Work in progress with new page.js
This commit is contained in:
parent
ef4453b77b
commit
1c80c3951a
@ -20,21 +20,21 @@ auth_post=/api/sqrl
|
|||||||
|
|
||||||
[prefix]
|
[prefix]
|
||||||
key=0@videotex
|
key=0@videotex
|
||||||
logoans=AWgBUkEBR04BQlMBWUkBbgE3AWt0ZXgBbg==
|
logoans=G1swbRtbMTszMW1BG1szMm1OG1szNG1TG1szM21JG1swOzMwOzQ3bXRleA==
|
||||||
logovtx=AUECTgNTBEkHdGV4
|
logovtx=AUECTgNTBEkHdGV4
|
||||||
user=1
|
user=1
|
||||||
|
|
||||||
; System frames are owned by this key
|
; System frames are owned by this key
|
||||||
[prefix:9]
|
[prefix:9]
|
||||||
key=0@videotex
|
key=0@videotex
|
||||||
logoans=AWgBUkEBR04BQlMBWUkBbgE3AWt0ZXgBbg==
|
logoans=G1swbRtbMTszMW1BG1szMm1OG1szNG1TG1szM21JG1swOzMwOzQ3bXRleA==
|
||||||
logovtx=AUECTgNTBEkHdGV4
|
logovtx=AUECTgNTBEkHdGV4
|
||||||
user=1
|
user=1
|
||||||
|
|
||||||
; Ansitex Help Pages
|
; ANSItex Help Pages
|
||||||
[prefix:516]
|
[prefix:516]
|
||||||
key=516@videotex
|
key=516@videotex
|
||||||
logoans=AWgBUkEBR04BQlMBWUkBbgE3AWt0ZXgBbg==
|
logoans=G1swbRtbMTszMW1BG1szMm1OG1szNG1TG1szM21JG1swOzMwOzQ3bXRleA==
|
||||||
logovtx=AUECTgNTBEkHdGV4
|
logovtx=AUECTgNTBEkHdGV4
|
||||||
user=1
|
user=1
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
load('smbdefs.js');
|
load('smbdefs.js');
|
||||||
|
|
||||||
// Ansitex specific includes
|
// ANSItex specific includes
|
||||||
load('ansitex/load/defs.js');
|
load('ansitex/load/defs.js');
|
||||||
load('ansitex/load/funcs.js');
|
load('ansitex/load/funcs.js');
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ require('key_defs.js','KEY_ESC');
|
|||||||
ansi = load({},'ansiterm_lib.js');
|
ansi = load({},'ansiterm_lib.js');
|
||||||
load('ansitex/load/funcs.js');
|
load('ansitex/load/funcs.js');
|
||||||
|
|
||||||
// Ansitex specific includes
|
// ANSItex specific includes
|
||||||
require('ansitex/load/defs.js','ACTION_EXIT');
|
require('ansitex/load/defs.js','ACTION_EXIT');
|
||||||
require('ansitex/load/frame-ansi.js','FRAME_ANSI');
|
require('ansitex/load/frame-ansi.js','FRAME_ANSI');
|
||||||
require('ansitex/load/frame-viewdata.js','FRAME_VIEWDATA');
|
require('ansitex/load/frame-viewdata.js','FRAME_VIEWDATA');
|
||||||
|
@ -38,7 +38,7 @@ function register() {
|
|||||||
this.handle=function(read) {
|
this.handle=function(read) {
|
||||||
// Dont allow existing users to re-register
|
// Dont allow existing users to re-register
|
||||||
if (user.number) {
|
if (user.number) {
|
||||||
fo.sendBaseline('ALREADY_MEMBER',false);
|
fo.baselineSend('ALREADY_MEMBER',false);
|
||||||
return read === '*' ? read : '';
|
return read === '*' ? read : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,33 +48,33 @@ function register() {
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(LOG_DEBUG,'- Field '+cf.fname+'('+JSON.stringify(cf)+')');
|
log(LOG_DEBUG,'- Field '+cf.name+'('+JSON.stringify(cf)+')');
|
||||||
|
|
||||||
if ((cf.fname === 'TOKEN') && (read === '#' || read === "\r")) {
|
if ((cf.name === 'TOKEN') && (read === '#' || read === "\r")) {
|
||||||
if (cf.fvalue === code) {
|
if (cf.value === code) {
|
||||||
complete = true;
|
complete = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fo.sendBaseline('INVALID_CODE',false);
|
fo.baselineSend('INVALID_CODE',false);
|
||||||
fo.cursorOn(cf.c+cf.fvalue.length,cf.r);
|
fo.cursorOn(cf.c+cf.value.length,cf.r);
|
||||||
fo.attr(cf.attribute);
|
fo.attr(cf.attribute);
|
||||||
read = '';
|
read = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log(LOG_DEBUG,'- Field Value ['+cf.fvalue+'] ('+code+')');
|
log(LOG_DEBUG,'- Field Value ['+cf.value+'] ('+code+')');
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we got an email
|
// Make sure we got an email
|
||||||
this.prefield=function() {
|
this.prefield=function() {
|
||||||
log(LOG_DEBUG,'- prefield: Field '+cf.fname+'('+JSON.stringify(cf)+')');
|
log(LOG_DEBUG,'- prefield: Field '+cf.name+'('+JSON.stringify(cf)+')');
|
||||||
|
|
||||||
if (cf.fname === 'TOKEN') {
|
if (cf.name === 'TOKEN') {
|
||||||
if (! code.length) {
|
if (! code.length) {
|
||||||
log(LOG_DEBUG,' - BASELINE '+cf.fname+'('+JSON.stringify(cf)+')');
|
log(LOG_DEBUG,' - BASELINE '+cf.name+'('+JSON.stringify(cf)+')');
|
||||||
fo.sendBaseline('TOKEN_EMAIL',false);
|
fo.baselineSend('TOKEN_EMAIL',false);
|
||||||
|
|
||||||
var email = fo.fieldValue('EMAIL');
|
var email = fo.fieldValue('EMAIL');
|
||||||
var uid = fo.fieldValue('UID');
|
var uid = fo.fieldValue('UID');
|
||||||
@ -85,13 +85,13 @@ function register() {
|
|||||||
// Validate Email hasnt been used
|
// Validate Email hasnt been used
|
||||||
// Validate USER_ID hasnt been used
|
// Validate USER_ID hasnt been used
|
||||||
if ((email.indexOf('@') === -1) || ! EMAIL_REGEX.test(email) || (system.matchuserdata(U_NETMAIL,email) !== 0)) {
|
if ((email.indexOf('@') === -1) || ! EMAIL_REGEX.test(email) || (system.matchuserdata(U_NETMAIL,email) !== 0)) {
|
||||||
fo.sendBaseline('INVALID_EMAIL',false);
|
fo.baselineSend('INVALID_EMAIL',false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! system.check_name(uid)) {
|
if (! system.check_name(uid)) {
|
||||||
log(LOG_DEBUG,' - Cannot use user_id: ('+uid+')');
|
log(LOG_DEBUG,' - Cannot use user_id: ('+uid+')');
|
||||||
fo.sendBaseline('INVALID_UID',false);
|
fo.baselineSend('INVALID_UID',false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ function register() {
|
|||||||
if (hdrs.to_net_type !== NET_NONE) {
|
if (hdrs.to_net_type !== NET_NONE) {
|
||||||
hdrs.to_net_addr = email;
|
hdrs.to_net_addr = email;
|
||||||
} else {
|
} else {
|
||||||
fo.sendBaseline('CANNOT_SEND_TOKEN',false);
|
fo.baselineSend('CANNOT_SEND_TOKEN',false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hdrs.from=system.name;
|
hdrs.from=system.name;
|
||||||
@ -137,7 +137,7 @@ function register() {
|
|||||||
msgbase.close();
|
msgbase.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
fo.sendBaseline('TOKEN_SENT',false);
|
fo.baselineSend('TOKEN_SENT',false);
|
||||||
log(LOG_DEBUG,'SENT EMAIL TOKEN ('+code+') ['+JSON.stringify(hdrs)+']');
|
log(LOG_DEBUG,'SENT EMAIL TOKEN ('+code+') ['+JSON.stringify(hdrs)+']');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ function register() {
|
|||||||
var newuser = system.new_user(fo.fieldValue('UID'));
|
var newuser = system.new_user(fo.fieldValue('UID'));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
fo.sendBaseline('USER_EXISTS',false);
|
fo.baselineSend('USER_EXISTS',false);
|
||||||
log(LOG_ERROR,"New user couldn't be created (user created while signing up)");
|
log(LOG_ERROR,"New user couldn't be created (user created while signing up)");
|
||||||
log(LOG_ERROR,JSON.stringify(e));
|
log(LOG_ERROR,JSON.stringify(e));
|
||||||
processed = true;
|
processed = true;
|
||||||
@ -157,7 +157,7 @@ function register() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof newuser === 'number') {
|
if (typeof newuser === 'number') {
|
||||||
fo.sendBaseline('USER_CREATE_ERROR',false);
|
fo.baselineSend('USER_CREATE_ERROR',false);
|
||||||
log(LOG_ERROR,"New user couldn't be created (error code "+newuser+")");
|
log(LOG_ERROR,"New user couldn't be created (error code "+newuser+")");
|
||||||
processed = true;
|
processed = true;
|
||||||
return this.isComplete;
|
return this.isComplete;
|
||||||
@ -172,7 +172,7 @@ function register() {
|
|||||||
user.location = fo.fieldValue('CITY')+', '+fo.fieldValue('COUNTRY');
|
user.location = fo.fieldValue('CITY')+', '+fo.fieldValue('COUNTRY');
|
||||||
user.zipcode = fo.fieldValue('PCODE');
|
user.zipcode = fo.fieldValue('PCODE');
|
||||||
user.netmail = fo.fieldValue('EMAIL');
|
user.netmail = fo.fieldValue('EMAIL');
|
||||||
user.comment = 'ANSITEX registered user';
|
user.comment = 'ANSItex registered user';
|
||||||
bbs.user_sync();
|
bbs.user_sync();
|
||||||
bbs.logon();
|
bbs.logon();
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ function register() {
|
|||||||
return this.isComplete;
|
return this.isComplete;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fo.sendBaseline('LOGIN_ERROR',false);
|
fo.baselineSend('LOGIN_ERROR',false);
|
||||||
log(LOG_INFO,"bbs.login() failed");
|
log(LOG_INFO,"bbs.login() failed");
|
||||||
user.comment = 'Initial login failed!';
|
user.comment = 'Initial login failed!';
|
||||||
newuser.settings |= USER_DELETED;
|
newuser.settings |= USER_DELETED;
|
||||||
|
@ -43,7 +43,7 @@ function sqrllogin() {
|
|||||||
var subframe = new Frame((viewdata ? fo.settings.FRAME_WIDTH : fo.settings.FRAME_WIDTH-qr.size-2),2,(viewdata ? qr.size/2 : qr.size+2),22,BG_BLACK|LIGHTGRAY);
|
var subframe = new Frame((viewdata ? fo.settings.FRAME_WIDTH : fo.settings.FRAME_WIDTH-qr.size-2),2,(viewdata ? qr.size/2 : qr.size+2),22,BG_BLACK|LIGHTGRAY);
|
||||||
fo.qrcode(qr,subframe);
|
fo.qrcode(qr,subframe);
|
||||||
|
|
||||||
fo.sendBaseline('CANCEL_MSG',false);
|
fo.baselineSend('CANCEL_MSG',false);
|
||||||
|
|
||||||
// Loop and see if the user has logged in
|
// Loop and see if the user has logged in
|
||||||
var nut = http.body.substr(http.body.indexOf('nut='),68);
|
var nut = http.body.substr(http.body.indexOf('nut='),68);
|
||||||
@ -127,7 +127,7 @@ function sqrllogin() {
|
|||||||
user.zipcode = '000';
|
user.zipcode = '000';
|
||||||
user.netmail = username+'@'+system.inet_addr;
|
user.netmail = username+'@'+system.inet_addr;
|
||||||
|
|
||||||
user.comment = 'ANSITEX registered user - with SQRL';
|
user.comment = 'ANSItex registered user - with SQRL';
|
||||||
bbs.user_sync();
|
bbs.user_sync();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -96,7 +96,7 @@ const HOME_FRAME_CONNECT ={frame: 980,index: 'a'};
|
|||||||
const FRAME_SYSTEM_ERROR ={frame: 998,index: 'a'};
|
const FRAME_SYSTEM_ERROR ={frame: 998,index: 'a'};
|
||||||
|
|
||||||
/* Attributes saved/loaded from files */
|
/* Attributes saved/loaded from files */
|
||||||
const SAVED_FRAME_ATTRS =['version','frame','frame_fields','index','owner','cost','content','isPublic','isAccessible','type','key'];
|
const SAVED_FRAME_ATTRS =['content','version','frame','input_fields','index','owner','cost','isPublic','isAccessible','type','key','date'];
|
||||||
|
|
||||||
/* The page that has our echomail area reading template */
|
/* The page that has our echomail area reading template */
|
||||||
var MAIL_TEMPLATE_FRAME ='199a';
|
var MAIL_TEMPLATE_FRAME ='199a';
|
||||||
@ -107,4 +107,7 @@ var MAIL_TEMPLATE_AREA_SUMMARY ='198a';
|
|||||||
// The maximum size of embedded dynamic fields in frames
|
// The maximum size of embedded dynamic fields in frames
|
||||||
var DYNAMIC_FIELD_SIZE_MAX =50;
|
var DYNAMIC_FIELD_SIZE_MAX =50;
|
||||||
|
|
||||||
|
/** ESCAPE CODES **/
|
||||||
|
const ESC = '\x1b';
|
||||||
|
|
||||||
this;
|
this;
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
var FRAME_ANSI = (1<<1);
|
|
||||||
|
|
||||||
load('ansitex/load/frame-page.js');
|
|
||||||
|
|
||||||
// Our frame object
|
|
||||||
function FrameAnsi() {
|
|
||||||
PageFrame.apply(this,arguments);
|
|
||||||
|
|
||||||
/* File Extension used for frames */
|
|
||||||
this.settings.ext = 'tex';
|
|
||||||
|
|
||||||
/* Length of a frame */
|
|
||||||
this.settings.FRAME_LENGTH = 22;
|
|
||||||
/* Width of a frame */
|
|
||||||
this.settings.FRAME_WIDTH = 80;
|
|
||||||
/* Size of page owner (length) */
|
|
||||||
this.settings.FRAME_HEADER = 56;
|
|
||||||
/* Size of page number (length with a-z) */
|
|
||||||
this.settings.FRAME_PAGENUM = 12;
|
|
||||||
/* Size of cost (length without unit) */
|
|
||||||
this.settings.FRAME_COST = 9;
|
|
||||||
|
|
||||||
this.settings.MSG_SENDORNOT = '\1n\1h\1GKEY 1 TO SEND, 2 NOT TO SEND';
|
|
||||||
this.settings.MSG_LOGON = '\1n\1h\1GKEY 1 TO LOGON, 2 TO RETURN';
|
|
||||||
this.settings.MSG_SENT = '\1n\1h\1GMESSAGE SENT - KEY # TO CONTINUE';
|
|
||||||
this.settings.MSG_NOTSENT = '\1n\1h\1GMESSAGE NOT SENT - KEY # TO CONTINUE';
|
|
||||||
this.settings.ERR_NO_PARENT = '\1n\1h\1RPARENT FRAME DOESNT EXIST';
|
|
||||||
this.settings.ERR_NOT_IMPLEMENTED = '\1n\1h\1RNOT IMPLEMENTED YET?';
|
|
||||||
this.settings.ERR_ROUTE = '\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
|
|
||||||
this.settings.ERR_METHOD_NOT_EXIST = '\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
|
|
||||||
this.settings.ACCESS_DENIED = '\1n\1h\1RACCESS DENIED. MISTAKE? TRY AGAIN OR TELL US *08';
|
|
||||||
this.settings.ALREADY_MEMBER = '\1n\1h\1RALREADY MEMBER OF CUG'
|
|
||||||
this.settings.INACTIVITY = '\1n\1h\1RINACTIVITY ALERT, DISCONNECT PENDING...';
|
|
||||||
this.settings.INACTIVE = '\1n\1h\1RINACTIVITY DISCONNECT';
|
|
||||||
this.settings.NOACTION = '\1n\1h\1RNO ACTION PERFORMED';
|
|
||||||
this.settings.BASESTAR = '\1N\1G\1H*';
|
|
||||||
this.settings.INVALID_CODE = '\1n\1h\1RINVAID CODE, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.TOKEN_EMAIL = '\1n\1h\1RTOKEN EMAILED TO YOU...';
|
|
||||||
this.settings.TOKEN_SENT = '\1n\1h\1RTOKEN SENT, PLEASE ENTER TOKEN';
|
|
||||||
this.settings.INVALID_EMAIL = '\1n\1h\1RINVAID EMAIL, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.INVALID_UID = '\1n\1h\1RINVAID USER ID, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.CANNOT_SEND_TOKEN = '\1n\1h\1RCANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.USER_EXISTS = '\1n\1h\1RERROR USER EXISTS, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.USER_CREATE_ERROR = '\1n\1h\1RERROR CREATING USER, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.LOGIN_ERROR = '\1n\1h\1RERROR LOGGING IN, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.CANCEL_MSG = '\1n\1h\1GPRESS 2 TO CANCEL';
|
|
||||||
this.settings.SYS_ERROR = '\1n\1h\1RSYSTEM ERROR DETECTED - TRY AGAIN OR TELL US *08';
|
|
||||||
this.settings.LOADING = '\1n\1h\1Kloading...';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the attribute at the current position
|
|
||||||
*/
|
|
||||||
this.attr=function(field) {
|
|
||||||
console.write(ascii(27)+'['+field.i+';'+field.f+';'+field.b+'m');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn off the cursor
|
|
||||||
*/
|
|
||||||
this.cursorOff=function() {
|
|
||||||
ansi.send('ext_mode','clear','cursor');
|
|
||||||
this.gotoxy(0,24);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cursorOn=function(x,y) {
|
|
||||||
ansi.send('ext_mode','set','cursor');
|
|
||||||
if (x && y)
|
|
||||||
this.gotoxy(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field backspace, that leaves the field filler char
|
|
||||||
this.fieldbs=function(char) {
|
|
||||||
console.write(ascii(27)+'[D'+char+ascii(27)+'[D');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.gotoxy=function(x,y) {
|
|
||||||
console.gotoxy(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the frame to the user
|
|
||||||
this.render=function(context,withoutHeader) {
|
|
||||||
log(LOG_DEBUG,'- ANSI FRAME');
|
|
||||||
owner = base64_decode(this.owner);
|
|
||||||
|
|
||||||
const frame = new Frame(1,1,this.settings.FRAME_WIDTH,this.settings.FRAME_LENGTH+2,LIGHTGRAY);
|
|
||||||
frame.open();
|
|
||||||
|
|
||||||
// Dont show the page number on system login page
|
|
||||||
if ((! withoutHeader) && (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1))) {
|
|
||||||
log(LOG_DEBUG,' - Owner: ['+this.pageowner+']');
|
|
||||||
|
|
||||||
cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -');
|
|
||||||
|
|
||||||
header = '\1n'+this.pageownerlogo+' '.repeat(this.settings.FRAME_HEADER-console.strlen(this.pageownerlogo))+'\1n '+
|
|
||||||
(this.isAccessible ? '\1W' : '\1R')+'\1H'+this.page+' '.repeat(this.settings.FRAME_PAGENUM-this.page.length)+' '+
|
|
||||||
'\1G\1H'+' '.repeat(this.settings.FRAME_COST-cost.toString().length+1)+cost+'\1n'+
|
|
||||||
(console.screen_columns > 80 ? '\n\r' : '');
|
|
||||||
|
|
||||||
frame.putmsg(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
contentgraphic = new Graphic(this.settings.FRAME_WIDTH);
|
|
||||||
contentgraphic.auto_extend = true;
|
|
||||||
contentgraphic.atcodes = false;
|
|
||||||
contentgraphic.ANSI = this.parse(base64_decode(this.content),context);
|
|
||||||
|
|
||||||
var contentframe = new Frame(1,2,this.settings.FRAME_WIDTH,this.settings.FRAME_LENGTH,LIGHTGRAY,frame);
|
|
||||||
contentframe.open();
|
|
||||||
contentframe.lf_strict = false;
|
|
||||||
contentframe.atcodes = false;
|
|
||||||
contentframe.word_wrap = false
|
|
||||||
|
|
||||||
contentframe.putmsg(contentgraphic.MSG)
|
|
||||||
contentframe.scrollTo(0,0);
|
|
||||||
|
|
||||||
frame.cycle();
|
|
||||||
|
|
||||||
return contentframe;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.qrcode=function(qr,subframe) {
|
|
||||||
// SMALL Image
|
|
||||||
var full = ascii(0xdb);
|
|
||||||
var top = ascii(0xdf);
|
|
||||||
var bot = ascii(0xdc);
|
|
||||||
var blank = ' ';
|
|
||||||
|
|
||||||
var qrcode = '';
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Render the top line
|
|
||||||
var line = ascii(27)+'[1;37m'+bot;
|
|
||||||
for (var y = 0; y < qr.size; y++) {
|
|
||||||
line += bot;
|
|
||||||
}
|
|
||||||
qrcode += line+bot+bot+ascii(27)+'[0m'+"\r\n";
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Render the body
|
|
||||||
for (var x = -1; x < qr.size; x=x+2) {
|
|
||||||
line = ascii(27)+'[1;37m'+full;
|
|
||||||
|
|
||||||
for (var y = 0; y < qr.size; y++) {
|
|
||||||
// Top is white
|
|
||||||
if (! ((x===-1)? 0 : qr.getModule(x, y))) {
|
|
||||||
line += (qr.getModule(x+1, y)) ? top : full;
|
|
||||||
|
|
||||||
// Top is black
|
|
||||||
} else {
|
|
||||||
line += (qr.getModule(x+1, y)) ? blank : bot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qrcode += line+full+ascii(27)+'[0m'+"\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the bottom
|
|
||||||
line = ascii(27)+'[1;37m'+top;
|
|
||||||
for (var y = 0; y < qr.size; y++) {
|
|
||||||
line += top;
|
|
||||||
}
|
|
||||||
qrcode += line+top+ascii(27)+'[0m'+"\r\n";
|
|
||||||
|
|
||||||
ans2bin(fo.parse(qrcode),subframe);
|
|
||||||
subframe.open();
|
|
||||||
subframe.cycle();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.save=function() {
|
|
||||||
file = system.mods_dir+'ansitex/text/'+this.page+'.tex';
|
|
||||||
w = new File(file);
|
|
||||||
if (! w.open('w')) {
|
|
||||||
log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+this.page);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
w.write(JSON.stringify(this));
|
|
||||||
w.close();
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'Saved file: '+this.page+'.tex');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message to the baseline.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* @param reposition
|
|
||||||
*/
|
|
||||||
this.sendBaseline=function(text,reposition) {
|
|
||||||
console.pushxy();
|
|
||||||
console.gotoxy(0,24);
|
|
||||||
console.print(this.getMessage(text));
|
|
||||||
console.cleartoeol();
|
|
||||||
|
|
||||||
if (! reposition) {
|
|
||||||
console.popxy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clearBaseline=function(reposition) {
|
|
||||||
console.pushxy();
|
|
||||||
console.gotoxy(0,24);
|
|
||||||
console.print('');
|
|
||||||
console.cleartoeol();
|
|
||||||
|
|
||||||
if (! reposition) {
|
|
||||||
console.popxy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameAnsi.prototype = PageFrame.prototype;
|
|
||||||
FrameAnsi.prototype.constructor = FrameAnsi;
|
|
@ -1,603 +0,0 @@
|
|||||||
// Our frame object
|
|
||||||
function PageFrame() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* Frame type settings */
|
|
||||||
this.settings = {};
|
|
||||||
|
|
||||||
/* Frame Version */
|
|
||||||
this.version = 1;
|
|
||||||
|
|
||||||
/* Frame Number [0-9] */
|
|
||||||
this.frame = null;
|
|
||||||
|
|
||||||
/* Frame Index [a-z] */
|
|
||||||
this.index = null;
|
|
||||||
|
|
||||||
/* The Service Provider owning the frame. */
|
|
||||||
this.owner = 0;
|
|
||||||
|
|
||||||
/* The cost to view the frame @todo to implement */
|
|
||||||
this.cost = 0;
|
|
||||||
|
|
||||||
/* The frame content, base64 encoded */
|
|
||||||
this.content = '';
|
|
||||||
|
|
||||||
// Frame's owned by the system where:
|
|
||||||
// isPublic is FALSE - the user must be logged in to view it
|
|
||||||
// isPublic is TRUE - can be viewed by non-logged in users
|
|
||||||
|
|
||||||
// Frame's owned by Service Providers where:
|
|
||||||
// isPublic is FALSE - can only be viewed if a user is
|
|
||||||
// a member of the Service Providers CUG
|
|
||||||
// isPublic is TRUE - can be viewed by users (if logged in)
|
|
||||||
|
|
||||||
this.isPublic = false; // Is this frame accessible to non CUG users
|
|
||||||
// If FALSE user must be a member of the CUG to view the frame
|
|
||||||
// All users, including unauthenticated, are members of 'system' (owner = 0)
|
|
||||||
this.isAccessible = false; // Is this frame available to be accessed
|
|
||||||
// If FALSE, only the SP can view/edit the frame
|
|
||||||
|
|
||||||
this.type = FRAME_TYPE_INFO; // The frame type - see FRAME_TYPES above
|
|
||||||
this.key = [null,null,null,null,null,null,null,null,null,null]; // Key actions [0-9]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if this frame is accessible to the current user
|
|
||||||
*/
|
|
||||||
Object.defineProperty(this,'accessible',{
|
|
||||||
get: function() {
|
|
||||||
log(LOG_DEBUG,'- Checking if user can access frame: '+this.page);
|
|
||||||
log(LOG_DEBUG,' - User: '+JSON.stringify(user.number));
|
|
||||||
log(LOG_DEBUG,' - Frame Owner: '+JSON.stringify(this.owner)+', System Frame: '+(this.pageowner === SYSTEM_OWNER));
|
|
||||||
|
|
||||||
// user.number 0 is unidentified user.
|
|
||||||
if (user.number) {
|
|
||||||
return (
|
|
||||||
(this.isAccessible && this.pageowner === SYSTEM_OWNER && ! this.isPublic) ||
|
|
||||||
(this.isAccessible && this.isPublic) ||
|
|
||||||
(this.isAccessible && ! this.isPublic && this.isMember) ||
|
|
||||||
(pageEditor(this.frame))
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return (this.isAccessible && this.pageowner === SYSTEM_OWNER && this.isPublic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the frames fields
|
|
||||||
*/
|
|
||||||
Object.defineProperty(this,'fields', {
|
|
||||||
get: function() {
|
|
||||||
return this.frame_fields;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the user is already a member of the CUG
|
|
||||||
*/
|
|
||||||
Object.defineProperty(this,'isMember',{
|
|
||||||
get: function() {
|
|
||||||
log(LOG_DEBUG,'- Checking if user is a member of frame: '+this.page);
|
|
||||||
|
|
||||||
if (user.number) {
|
|
||||||
return (
|
|
||||||
(this.pageowner === SYSTEM_OWNER)
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the page number
|
|
||||||
*/
|
|
||||||
Object.defineProperty(this,'page', {
|
|
||||||
get: function() {
|
|
||||||
if (this.frame === null || this.index === null) return null;
|
|
||||||
return this.frame.toString()+this.index;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this,'pageowner', {
|
|
||||||
get: function() {
|
|
||||||
return pageOwner(this.frame).prefix;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.defineProperty(this,'pageownerlogo', {
|
|
||||||
get: function() {
|
|
||||||
return base64_decode(this.settings.ext === 'tex' ? pageOwner(this.frame).logoans : pageOwner(this.frame).logovtx);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable pulling out submitted value by its name
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @returns {null|string|*}
|
|
||||||
*/
|
|
||||||
PageFrame.prototype.fieldValue = function(key) {
|
|
||||||
for each (var k in this.frame_fields) {
|
|
||||||
log(LOG_DEBUG,' - k:'+JSON.stringify(k));
|
|
||||||
|
|
||||||
if (k.fname === key) {
|
|
||||||
return k.fvalue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the message for a index
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
* @returns {string|*}
|
|
||||||
*/
|
|
||||||
PageFrame.prototype.getMessage = function(index) {
|
|
||||||
eval('var msg = this.settings.'+index);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a frame
|
|
||||||
*
|
|
||||||
* @param filename
|
|
||||||
* @returns {null}
|
|
||||||
*/
|
|
||||||
PageFrame.prototype.load = function(filename) {
|
|
||||||
log(LOG_DEBUG,'Loading FRAME from: '+filename+'.'+this.settings.ext);
|
|
||||||
this.sendBaseline('LOADING');
|
|
||||||
|
|
||||||
f = new File(system.mods_dir+'ansitex/text/'+filename+'.'+this.settings.ext);
|
|
||||||
if (! f.exists || ! f.open('r')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var load = JSON.parse(f.read());
|
|
||||||
|
|
||||||
for (property in SAVED_FRAME_ATTRS) {
|
|
||||||
this[SAVED_FRAME_ATTRS[property]] = load[SAVED_FRAME_ATTRS[property]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the page doesnt match the filename, throw an error
|
|
||||||
if (this.page !== filename)
|
|
||||||
throw 'Frame doesnt match filename';
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
log(LOG_ERROR,'Frame error: '+error);
|
|
||||||
|
|
||||||
// Load our system error frame.
|
|
||||||
this.load(pageStr(FRAME_SYSTEM_ERROR));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'Loaded frame: ['+this.frame+']['+this.index+'] ('+this.page+')');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a message frame
|
|
||||||
*
|
|
||||||
* @param page
|
|
||||||
*/
|
|
||||||
PageFrame.prototype.loadMessage = function(page) {
|
|
||||||
this.frame = ''+page;
|
|
||||||
this.index = 'a';
|
|
||||||
this.owner = 1;
|
|
||||||
this.isPublic = true;
|
|
||||||
this.isAccessible = true;
|
|
||||||
// @todo Keys should map to next/previous/send, etc as indicated in the template frame.
|
|
||||||
this.key = [this.frame.substr(0,7)+'1',null,null,null,null,null,null,null,null,null];
|
|
||||||
// @todo validate that FRAME_TYPE_MESSAGE is a message template
|
|
||||||
this.type = FRAME_TYPE_MESSAGE;
|
|
||||||
|
|
||||||
// Load our message
|
|
||||||
var ma = new MsgAreas()
|
|
||||||
var area = ma.getArea(this.frame);
|
|
||||||
var msg = ma.getMessage(this.frame);
|
|
||||||
var msg_header;
|
|
||||||
|
|
||||||
if (! msg)
|
|
||||||
return undefined;
|
|
||||||
|
|
||||||
// @todo Search 1zzzzEE..., 1zzzz...
|
|
||||||
var to = viewdata ? new FrameViewdata() : new FrameAnsi();
|
|
||||||
to.load(MAIL_TEMPLATE_FRAME);
|
|
||||||
// @todo Check that this is a frame of type "m" and report error if not
|
|
||||||
// @todo Take the cost from the template
|
|
||||||
this.cost = 5;
|
|
||||||
|
|
||||||
if (! to) {
|
|
||||||
log(LOG_ERROR,'Echomail template missing :['+MAIL_TEMPLATE_FRAME+'] ?');
|
|
||||||
msg_header = 'TO: '+msg.to.substr(0,72)+"\n\r";
|
|
||||||
msg_header += 'FROM: '+msg.from.substr(0,72)+"\n\r";
|
|
||||||
msg_header += 'DATE: '+msg.date.substr(0,72)+"\n\r";
|
|
||||||
msg_header += 'SUBJECT: '+msg.subject.substr(0,72)+"\n\r";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// @todo change this to use atcode()
|
|
||||||
msg_header = base64_decode(to.content).replace(/@(.*)@/g,
|
|
||||||
function (str, code, offset, s) {
|
|
||||||
var length = code.split(':')[1];
|
|
||||||
switch(code.split(':')[0]) {
|
|
||||||
case 'DATE': return msg.date.substr(0,length);
|
|
||||||
case 'TO': return msg.to.substr(0,length);
|
|
||||||
case 'FROM': return msg.from.substr(0,length);
|
|
||||||
case 'SUBJECT': return msg.subject.substr(0,length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//log(LOG_DEBUG,'Loaded message: '+msg_header+msg.content);
|
|
||||||
this.content = base64_encode(msg_header+msg.content);
|
|
||||||
|
|
||||||
// Update the user's pointers
|
|
||||||
var stats = ma.getUserStats(this.frame);
|
|
||||||
|
|
||||||
// if this message is to the user, and the msg number > scan_ptr and it is the next message on the user's new mail list
|
|
||||||
var newmsgs = area.newMsgsToMe();
|
|
||||||
var next;
|
|
||||||
log(LOG_DEBUG,'User has: '+newmsgs.length-1+' msgs to read to ME');
|
|
||||||
if (newmsgs.length) {
|
|
||||||
next = newmsgs[1];
|
|
||||||
//log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags);
|
|
||||||
|
|
||||||
if (next && (next.tags === msg.tags)) {
|
|
||||||
log(LOG_DEBUG,'- Updating scan_ptr to: '+next.number);
|
|
||||||
stats.scan_ptr = next.number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last message
|
|
||||||
next = newmsgs[0];
|
|
||||||
if (next !== undefined) {
|
|
||||||
log(LOG_DEBUG,'- LAST TO ME is: '+next.tags);
|
|
||||||
this.key[1] = area.page(next.tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next new message
|
|
||||||
next = newmsgs[2];
|
|
||||||
if (next !== undefined) {
|
|
||||||
log(LOG_DEBUG,'- NEXT TO ME is: '+next.tags);
|
|
||||||
this.key[2] = area.page(next.tags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this message is the next message, update last_read
|
|
||||||
newmsgs = area.newMsgs();
|
|
||||||
log(LOG_DEBUG,'User has: '+newmsgs.length+' msgs to read');
|
|
||||||
if (newmsgs.length) {
|
|
||||||
next = newmsgs[0];
|
|
||||||
log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags);
|
|
||||||
|
|
||||||
if (next.tags === msg.tags) {
|
|
||||||
log(LOG_DEBUG,'- Updating last_read to: '+next.number);
|
|
||||||
stats.last_read = next.number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Previous Message
|
|
||||||
x = area.MessagePrev(this.frame);
|
|
||||||
if (x)
|
|
||||||
this.key[4] = area.page(x.tags);
|
|
||||||
|
|
||||||
// Next Message
|
|
||||||
x = area.MessageNext(this.frame);
|
|
||||||
if (x)
|
|
||||||
this.key[6] = area.page(x.tags);
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'Built frame: ['+this.frame+']['+this.index+'] ('+this.page+')');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the page text, and return the frame as 2 arrays:
|
|
||||||
* + First array is all the characters and the position on the frame
|
|
||||||
* + Second array is the array of the control codes that changes the color of the character
|
|
||||||
*
|
|
||||||
* The purpose of this function is to convert any special char sequences there are interpreted directly by Ansitex
|
|
||||||
* Currently they are:
|
|
||||||
* + ESC _ <value>[;value] ESC \
|
|
||||||
*
|
|
||||||
* Additionally, for response frames, if the cursor is moved to a field, its to determine what attributes (eg: color)
|
|
||||||
* should apply for that field.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* @param context
|
|
||||||
*/
|
|
||||||
PageFrame.prototype.parse = function(text,context) {
|
|
||||||
log(LOG_DEBUG,'Parsing Frame ...');
|
|
||||||
|
|
||||||
if (this.type === FRAME_TYPE_MESSAGE) {
|
|
||||||
log(LOG_DEBUG,'- Not parsing message frame');
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Column
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
var c = 1;
|
|
||||||
/** Row - row 1 is the header
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
var r = 2;
|
|
||||||
/**
|
|
||||||
* The output to send to the screen
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
var output = '';
|
|
||||||
/**
|
|
||||||
* Fields within the frame
|
|
||||||
* @type {{
|
|
||||||
* ftype: fieldtype,
|
|
||||||
* flength: fieldlen,
|
|
||||||
* fchar: fieldchar,
|
|
||||||
* fname: field,
|
|
||||||
* r: r,
|
|
||||||
* c: c,
|
|
||||||
* attribute: {i:i,f:f,b:b},
|
|
||||||
* fvalue: '',
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
this.frame_fields = [];
|
|
||||||
|
|
||||||
// If there is no text return
|
|
||||||
if (! text)
|
|
||||||
return output;
|
|
||||||
|
|
||||||
// Default Attributes
|
|
||||||
// @note - this has no affect for viewdata frames
|
|
||||||
/* Foreground */
|
|
||||||
var f = 39;
|
|
||||||
/* Background */
|
|
||||||
var b = 49;
|
|
||||||
/* Intensity */
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
for(var p=0;p<text.length;p++) {
|
|
||||||
// Look for a special character until the end of the frame width
|
|
||||||
cte = (r*this.settings.FRAME_WIDTH - ((r-1)*this.settings.FRAME_WIDTH+c));
|
|
||||||
match = text.substr(p,cte).match(/[\r\n\x1b]/);
|
|
||||||
//log(LOG_DEBUG,'SPECIAL CHAR ['+r+'x'+c+'] ['+p+'-'+cte+'] for: '+match);
|
|
||||||
|
|
||||||
if (match === null || match.index) {
|
|
||||||
advance = match ? match.index : cte;
|
|
||||||
//log(LOG_DEBUG,'INCLUDE: '+text.substr(p,advance));
|
|
||||||
|
|
||||||
output += text.substr(p,advance);
|
|
||||||
p += advance;
|
|
||||||
c += advance;
|
|
||||||
advance = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the frame is not big enough, fill it with spaces.
|
|
||||||
byte = text.charAt(p);
|
|
||||||
advance = 0;
|
|
||||||
|
|
||||||
switch (byte) {
|
|
||||||
// Carriage Return
|
|
||||||
case "\r":
|
|
||||||
// log(LOG_DEBUG,'CR');
|
|
||||||
c=1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// New line
|
|
||||||
case "\n":
|
|
||||||
// log(LOG_DEBUG,'LF');
|
|
||||||
r++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ESC
|
|
||||||
case KEY_ESC:
|
|
||||||
advance = 1;
|
|
||||||
// Is the next byte something we know about
|
|
||||||
nextbyte = text.charAt(p+advance);
|
|
||||||
//log(LOG_DEBUG,'ESC ['+r+'x'+c+'] NEXT: '+nextbyte);
|
|
||||||
|
|
||||||
switch (nextbyte) {
|
|
||||||
// CSI
|
|
||||||
case '[':
|
|
||||||
advance++;
|
|
||||||
chars = '';
|
|
||||||
|
|
||||||
// Find our end CSI param in the next 50 chars
|
|
||||||
matches = text.substr(p+advance,50).match(/([0-9]+[;]?)+([a-zA-Z])/);
|
|
||||||
//log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', STRING: '+text.substr(p+advance,50));
|
|
||||||
|
|
||||||
if (! matches) {
|
|
||||||
chars += nextbyte;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
advance += matches[0].length-1;
|
|
||||||
chars += nextbyte+matches[0];
|
|
||||||
//log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', CHARS: '+chars+', CHARSLEN: '+chars.length);
|
|
||||||
|
|
||||||
switch (matches[2]) {
|
|
||||||
// Color CSIs
|
|
||||||
case 'm':
|
|
||||||
//log(LOG_DEBUG,'CSI m ['+r+'x'+c+'] MATCHES: '+matches[0]+', LENGTH : '+matches[0].length);
|
|
||||||
|
|
||||||
csi = matches[0].substr(0,matches[0].length-1).split(';');
|
|
||||||
var num = null;
|
|
||||||
for (num in csi) {
|
|
||||||
//log(LOG_DEBUG,'CSI m ['+r+'x'+c+'] NUM: '+num+', CSI: '+csi[num]);
|
|
||||||
// Intensity
|
|
||||||
if (csi[num] >= 0 && csi[num] <= 8) {
|
|
||||||
i = csi[num];
|
|
||||||
f = 39;
|
|
||||||
b = 49;
|
|
||||||
|
|
||||||
// Forground Color
|
|
||||||
} else if (csi[num] >= 30 && csi[num] <= 39) {
|
|
||||||
f = csi[num];
|
|
||||||
|
|
||||||
// Background Color
|
|
||||||
} else if (csi[num] >= 40 && csi[num] <= 49) {
|
|
||||||
b = num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Advance characters
|
|
||||||
case 'C':
|
|
||||||
//log(LOG_DEBUG,'CSI C ['+r+'x'+c+'] CHARS: '+matches[1]);
|
|
||||||
c += parseInt(matches[1]); // Advance our position
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log(LOG_DEBUG,'? CSI: '+matches[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ' ':
|
|
||||||
log(LOG_DEBUG,'LOOSE ESC? ['+r+'x'+c+'] '+advance);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// X - dynamic fields, terminated with ESC
|
|
||||||
// Dynamic fields are defined with ESC X FIELD;LENGTH;PAD ESC \
|
|
||||||
// @note FIELD & LENGTH are required
|
|
||||||
// @note Dynamic field is can only be DYNAMIC_FIELD_SIZE_MAX chars in size
|
|
||||||
case 'X':
|
|
||||||
//log(LOG_DEBUG,'DF ['+r+'x'+c+'] '+advance);
|
|
||||||
advance++;
|
|
||||||
|
|
||||||
// Find our end ST param in the next DYNAMIC_FIELD_SIZE_MAX chars
|
|
||||||
matches = text.substr(p+advance,DYNAMIC_FIELD_SIZE_MAX).match(/(([a-zA-Z._:^;]+[0-9]?;-?[0-9^;]+)([;]?[^;]+)?)\x1b\\/);
|
|
||||||
//log(LOG_DEBUG,'- DF ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+JSON.stringify(matches)+', LENGTH: '+(matches ? matches[0].length : 0)+', STRING: '+text.substr(p+advance,50));
|
|
||||||
|
|
||||||
if (! matches) {
|
|
||||||
chars += nextbyte;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
advance += matches[0].length-1;
|
|
||||||
|
|
||||||
var df = matches[0].substr(0,matches[0].length-2).split(';');
|
|
||||||
//log(LOG_DEBUG,'- DF ['+r+'x'+c+'] ADVANCE: '+advance+', DF: '+df);
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'- DF found at ['+r+'x'+(c-1)+'], Field: '+df[0]+', Length: '+df[1]+', Attrs: '+JSON.stringify({i:i,f:f,b:b}));
|
|
||||||
chars = atcode(df[0],df[1],df[2],context);
|
|
||||||
byte = '';
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// _ - has our fields that take input
|
|
||||||
case '_':
|
|
||||||
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] '+advance);
|
|
||||||
advance++;
|
|
||||||
|
|
||||||
// Find our end ST param in the next 50 chars
|
|
||||||
matches = text.substr(p+advance,50).match(/(([A-Z]+;[0-9a-z]+)([;]?.+)?)\x1b\\/);
|
|
||||||
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', LENGTH: '+matches[0].length+', STRING: '+text.substr(p+advance,50));
|
|
||||||
|
|
||||||
if (! matches) {
|
|
||||||
chars += nextbyte;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
advance += matches[0].length-1;
|
|
||||||
|
|
||||||
// The last 2 chars of matches[0] are the ESC \
|
|
||||||
var sos = matches[0].substr(0,matches[0].length-2).split(';');
|
|
||||||
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] ADVANCE: '+advance+', SOS: '+sos);
|
|
||||||
|
|
||||||
var num = null;
|
|
||||||
var field = null;
|
|
||||||
var fieldlen = null;
|
|
||||||
for (num in sos) {
|
|
||||||
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM: '+num+', SOS: '+sos[num]);
|
|
||||||
|
|
||||||
switch (num) {
|
|
||||||
// First value is the field name
|
|
||||||
case '0':
|
|
||||||
field = sos[num];
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Second value is the length/type of the field
|
|
||||||
case '1':
|
|
||||||
x = sos[num].match(/([0-9]+)([a-z])/);
|
|
||||||
if (! x) {
|
|
||||||
log(LOG_ERROR,'SOS FAILED PARSING FIELD LENGTH/TYPE. ['+r+'x'+c+'] '+sos[num]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM CHARS: '+x[1]+', TYPE: '+x[2]);
|
|
||||||
fieldlen = x[1];
|
|
||||||
fieldtype = x[2];
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Third field is the char to to use
|
|
||||||
case '2':
|
|
||||||
fieldchar = sos[num];
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log(LOG_ERROR,'IGNORING ADDITIONAL SOS FIELDS. ['+r+'x'+c+'] '+sos[num]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldlen) {
|
|
||||||
chars = fieldchar.repeat(fieldlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte = '';
|
|
||||||
|
|
||||||
this.frame_fields.push({
|
|
||||||
ftype: fieldtype,
|
|
||||||
flength: fieldlen,
|
|
||||||
fchar: fieldchar,
|
|
||||||
fname: field,
|
|
||||||
r: r,
|
|
||||||
c: c,
|
|
||||||
attribute: {i:i,f:f,b:b},
|
|
||||||
fvalue: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'SOS Field found at ['+r+'x'+(c-1)+'], Type: '+fieldtype+', Length: '+fieldlen+', Attrs: '+JSON.stringify({i:i,f:f,b:b}));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log(LOG_DEBUG,'DEFAULT ['+r+'x'+c+'] '+advance);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
|
|
||||||
output += byte;
|
|
||||||
|
|
||||||
if (advance) {
|
|
||||||
//log(LOG_DEBUG,'ADVANCE P ['+r+'x'+c+'] '+advance+', NEXT CHAR: '+text.charAt(p+advance)+' ('+text.charCodeAt(p+advance)+')');
|
|
||||||
output += chars;
|
|
||||||
p += advance;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c>this.settings.FRAME_WIDTH) {
|
|
||||||
c = 1;
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// @todo - If we are longer than FRAME_LENGTH, move the output into the next frame.
|
|
||||||
if (r>this.settings.FRAME_LENGTH) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
};
|
|
@ -1,257 +0,0 @@
|
|||||||
var FRAME_VIEWDATA = (1<<2);
|
|
||||||
|
|
||||||
var VIEWDATA_LEFT = ascii(0x08);
|
|
||||||
var VIEWDATA_RIGHT = ascii(0x09);
|
|
||||||
var VIEWDATA_DOWN = ascii(0x0a); // \n
|
|
||||||
var VIEWDATA_UP = ascii(0x0b);
|
|
||||||
var VIEWDATA_CLS = ascii(0x0c);
|
|
||||||
var VIEWDATA_CR = ascii(0x0d); // \r
|
|
||||||
var VIEWDATA_CON = ascii(0x11);
|
|
||||||
var VIEWDATA_COFF = ascii(0x14);
|
|
||||||
var VIEWDATA_HOME = ascii(0x1e);
|
|
||||||
var VIEWDATA_MOSIAC_RED = ascii(27)+ascii(0x51);
|
|
||||||
var VIEWDATA_MOSIAC_GREEN = ascii(27)+ascii(0x52);
|
|
||||||
var VIEWDATA_MOSIAC_YELLOW = ascii(27)+ascii(0x53);
|
|
||||||
var VIEWDATA_MOSIAC_BLUE = ascii(27)+ascii(0x54);
|
|
||||||
var VIEWDATA_MOSIAC_MAGENTA = ascii(27)+ascii(0x55);
|
|
||||||
var VIEWDATA_MOSIAC_CYAN = ascii(27)+ascii(0x56);
|
|
||||||
var VIEWDATA_MOSIAC_WHITE = ascii(27)+ascii(0x57);
|
|
||||||
|
|
||||||
load('ansitex/load/frame-page.js');
|
|
||||||
|
|
||||||
// Our frame object
|
|
||||||
function FrameViewdata() {
|
|
||||||
PageFrame.apply(this,arguments);
|
|
||||||
|
|
||||||
/* File Extension used for frames */
|
|
||||||
this.settings.ext = 'vtx';
|
|
||||||
|
|
||||||
/* Length of a frame */
|
|
||||||
this.settings.FRAME_LENGTH = 22;
|
|
||||||
/* Width of a frame */
|
|
||||||
this.settings.FRAME_WIDTH = 40;
|
|
||||||
/* Size of page owner (length) */
|
|
||||||
this.settings.FRAME_HEADER = 23;
|
|
||||||
/* Size of page number (length with a-z) */
|
|
||||||
this.settings.FRAME_PAGENUM = 11;
|
|
||||||
/* Size of cost (length without unit) */
|
|
||||||
this.settings.FRAME_COST = 3;
|
|
||||||
|
|
||||||
this.settings.MSG_SENDORNOT = ascii(27)+'BKEY 1 TO SEND, 2 NOT TO SEND';
|
|
||||||
this.settings.MSG_LOGON = ascii(27)+'BKEY 1 TO LOGON, 2 TO RETURN';
|
|
||||||
this.settings.MSG_SENT = ascii(27)+'BMESSAGE SENT - KEY _ TO CONTINUE';
|
|
||||||
this.settings.MSG_NOTSENT = ascii(27)+'BMESSAGE NOT SENT - KEY _ TO CONTINUE';
|
|
||||||
this.settings.ERR_NO_PARENT = ascii(27)+'APARENT FRAME DOESNT EXIST';
|
|
||||||
this.settings.ERR_NOT_IMPLEMENTED = ascii(27)+'ANOT IMPLEMENTED YET?';
|
|
||||||
this.settings.ERR_ROUTE = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08';
|
|
||||||
this.settings.ERR_METHOD_NOT_EXIST = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08';
|
|
||||||
this.settings.ACCESS_DENIED = ascii(27)+'AACCESS DENIED.';
|
|
||||||
this.settings.ALREADY_MEMBER = ascii(27)+'AALREADY MEMBER OF CUG'
|
|
||||||
this.settings.INACTIVITY = ascii(27)+'AINACTIVITY ALERT, DISCONNECT PENDING...';
|
|
||||||
this.settings.INACTIVE = ascii(27)+'AINACTIVITY DISCONNECT';
|
|
||||||
this.settings.NOACTION = ascii(27)+'ANO ACTION PERFORMED';
|
|
||||||
this.settings.BASESTAR = ascii(27)+'B*';
|
|
||||||
this.settings.INVALID_CODE = ascii(27)+'AINVAID CODE, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.TOKEN_EMAIL = ascii(27)+'ATOKEN EMAILED TO YOU...';
|
|
||||||
this.settings.TOKEN_SENT = ascii(27)+'ATOKEN SENT, PLEASE ENTER TOKEN';
|
|
||||||
this.settings.INVALID_EMAIL = ascii(27)+'AINVAID EMAIL, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.INVALID_UID = ascii(27)+'AINVAID USER ID, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.CANNOT_SEND_TOKEN = ascii(27)+'ACANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.USER_EXISTS = ascii(27)+'AERROR USER EXISTS, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.USER_CREATE_ERROR = ascii(27)+'AERROR CREATING USER, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.LOGIN_ERROR = ascii(27)+'AERROR LOGGING IN, PLEASE TRY AGAIN *00';
|
|
||||||
this.settings.CANCEL_MSG = ascii(27)+'BPRESS 2 TO CANCEL';
|
|
||||||
this.settings.SYS_ERROR = ascii(27)+'ASYS ERR, TRY AGAIN OR TELL US ON *08';
|
|
||||||
this.settings.LOADING = VIEWDATA_MOSIAC_WHITE+'loading...';
|
|
||||||
|
|
||||||
var blp=0; // Length of data on the bottom line
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the attribute at the current position
|
|
||||||
*/
|
|
||||||
this.attr=function(field) {
|
|
||||||
//NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn off the cursor
|
|
||||||
*/
|
|
||||||
this.cursorOff=function() {
|
|
||||||
write_raw(VIEWDATA_COFF);
|
|
||||||
this.gotoxy(1,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cursorOn=function(x,y) {
|
|
||||||
write_raw(VIEWDATA_CON);
|
|
||||||
this.gotoxy(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field backspace, that leaves the field filler char
|
|
||||||
this.fieldbs=function(char) {
|
|
||||||
console.write(VIEWDATA_LEFT+char+VIEWDATA_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.gotoxy=function(x,y) {
|
|
||||||
// @todo This could be optimised to go the shortest route
|
|
||||||
write_raw(VIEWDATA_HOME);
|
|
||||||
if (x>0)
|
|
||||||
write_raw(VIEWDATA_RIGHT.repeat(x));
|
|
||||||
if (y>0)
|
|
||||||
write_raw(VIEWDATA_DOWN.repeat(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.strlen=function(str) {
|
|
||||||
return str.replace(/\x1b/g,'').length;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Render the frame to the user
|
|
||||||
this.render=function(withHeader) {
|
|
||||||
log(LOG_DEBUG,'- VIEWDATA FRAME');
|
|
||||||
owner = base64_decode(this.owner);
|
|
||||||
|
|
||||||
header = VIEWDATA_DOWN;
|
|
||||||
|
|
||||||
//log(LOG_DEBUG,' - FRAME User: ['+JSON.stringify(user)+']');
|
|
||||||
|
|
||||||
// Dont show the page number on system login page
|
|
||||||
if (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1)) {
|
|
||||||
log(LOG_DEBUG,' - Owner: ['+this.pageowner+'] ('+this.strlen(videotex(this.pageownerlogo))+')');
|
|
||||||
|
|
||||||
cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -');
|
|
||||||
|
|
||||||
header = videotex(this.pageownerlogo)+' '.repeat(this.settings.FRAME_HEADER-this.strlen(videotex(this.pageownerlogo)))+
|
|
||||||
(this.isAccessible ? ascii(27)+'G' : ascii(27)+'A')+this.page+' '.repeat(this.settings.FRAME_PAGENUM-this.page.length)+
|
|
||||||
ascii(27)+'B'+' '.repeat(this.settings.FRAME_COST-cost.toString().length+1)+cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.status |= CON_RAW_IN;
|
|
||||||
write_raw(VIEWDATA_CLS);
|
|
||||||
write_raw(header);
|
|
||||||
return write_raw(videotex(base64_decode(this.content)));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.qrcode = function(qr) {
|
|
||||||
// Render the body
|
|
||||||
var qrcode = VIEWDATA_HOME+VIEWDATA_DOWN.repeat(5);
|
|
||||||
var offset = this.settings.FRAME_WIDTH-Math.ceil(qr.size/2)-1;
|
|
||||||
|
|
||||||
for (var x = -1; x < qr.size; x=x+3) {
|
|
||||||
var line = VIEWDATA_RIGHT.repeat(offset ? offset-1 : 0)+VIEWDATA_MOSIAC_WHITE;
|
|
||||||
|
|
||||||
for (var y = -1; y < qr.size; y=y+2) {
|
|
||||||
var char = 0;
|
|
||||||
|
|
||||||
//TL
|
|
||||||
char |= ((x===-1) || (y===-1) || ! qr.getModule(x,y)) ? (1<<0) : (0<<0);
|
|
||||||
//TR
|
|
||||||
char |= ((x===-1) || (y === qr.size-1) || ! qr.getModule(x,y+1)) ? (1<<1) : (0<<1);
|
|
||||||
//ML
|
|
||||||
char |= ((y===-1) || ! qr.getModule(x+1,y)) ? (1<<2) : (0<<2);
|
|
||||||
//MR
|
|
||||||
char |= ((y === qr.size-1) || ! qr.getModule(x+1,y+1)) ? (1<<3) : (0<<3);
|
|
||||||
//BL
|
|
||||||
char |= ((x===qr.size-2) || (y===-1) || ! qr.getModule(x+2,y)) ? (1<<4) : (0<<4);
|
|
||||||
//BR
|
|
||||||
char |= ((x===qr.size-2) || (y === qr.size-1) || ! qr.getModule(x+2,y+1)) ? (1<<5) : (0<<5);
|
|
||||||
|
|
||||||
char += 0x20;
|
|
||||||
if (char > 0x3f)
|
|
||||||
char += 0x20;
|
|
||||||
|
|
||||||
line += ascii(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the right column
|
|
||||||
if (y%2)
|
|
||||||
line += ascii(0x35);
|
|
||||||
|
|
||||||
repeat_count = this.settings.FRAME_WIDTH-Math.ceil(qr.size/2)-offset-(offset ? 1 : 2)-(y%2 === 1 ? 0 : 1);
|
|
||||||
|
|
||||||
qrcode += line+' '.repeat(repeat_count > 0 ? repeat_count : 0);
|
|
||||||
|
|
||||||
// To fix some terminals where moving right from col 40 doesnt advance to col 1 on the next line
|
|
||||||
qrcode +=VIEWDATA_LEFT+VIEWDATA_CR+VIEWDATA_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'WIDTH:'+this.settings.FRAME_WIDTH);
|
|
||||||
log(LOG_DEBUG,'QR :'+(Math.ceil(qr.size/2)+1));
|
|
||||||
log(LOG_DEBUG,'OFF :'+offset);
|
|
||||||
log(LOG_DEBUG,'Y :'+(y%2 ? 0 : 1));
|
|
||||||
log(LOG_DEBUG,'X :'+(x%3 ? 0 : 1));
|
|
||||||
|
|
||||||
// Render the bottom
|
|
||||||
if (x%3) {
|
|
||||||
line = VIEWDATA_RIGHT.repeat(offset ? offset-1 : 0)+VIEWDATA_MOSIAC_WHITE;
|
|
||||||
|
|
||||||
for (var y = 0; y < qr.size; y=y+2) {
|
|
||||||
line += ascii(0x23);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the right column
|
|
||||||
if (y%2 === 0) {
|
|
||||||
line += ascii(0x21);
|
|
||||||
}
|
|
||||||
|
|
||||||
qrcode += line+' '.repeat(repeat_count > 0 ? repeat_count : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_raw(qrcode);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.save=function() {
|
|
||||||
file = system.mods_dir+'ansitex/text/'+this.page+'.tex';
|
|
||||||
w = new File(file);
|
|
||||||
if (! w.open('w')) {
|
|
||||||
log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+this.page);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
w.write(JSON.stringify(this));
|
|
||||||
w.close();
|
|
||||||
|
|
||||||
log(LOG_DEBUG,'Saved file: '+this.page+'.tex');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message to the baseline.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* @param reposition
|
|
||||||
*/
|
|
||||||
this.sendBaseline=function(text,reposition) {
|
|
||||||
var msg = this.getMessage(text);
|
|
||||||
var x = this.strlen(msg);
|
|
||||||
|
|
||||||
write_raw(VIEWDATA_HOME+VIEWDATA_UP+msg+
|
|
||||||
((blp > x)
|
|
||||||
? (' '.repeat(blp-x)+(reposition ? VIEWDATA_HOME+VIEWDATA_UP+VIEWDATA_RIGHT.repeat(x) : ''))
|
|
||||||
: '')
|
|
||||||
);
|
|
||||||
|
|
||||||
blp = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clearBaseline=function(reposition) {
|
|
||||||
msg = '';
|
|
||||||
|
|
||||||
write_raw(VIEWDATA_HOME+VIEWDATA_UP+msg+
|
|
||||||
((blp > msg.length)
|
|
||||||
? (' '.repeat(blp-msg.length)+(reposition ? VIEWDATA_HOME+VIEWDATA_UP+VIEWDATA_RIGHT.repeat(msg.length) : ''))
|
|
||||||
: '')
|
|
||||||
);
|
|
||||||
|
|
||||||
blp = msg.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function videotex(data) {
|
|
||||||
var output = '';
|
|
||||||
//$output .= ($byte < 32) ? ESC.chr($byte+64) : chr($byte);
|
|
||||||
for (var i = 0; i < data.length; i++) {
|
|
||||||
output += (data.charCodeAt(i) < 32) ? "\x1b"+String.fromCharCode(data.charCodeAt(i)+64) : String.fromCharCode(data.charCodeAt(i));
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameViewdata.prototype = PageFrame.prototype;
|
|
||||||
FrameViewdata.prototype.constructor = FrameViewdata;
|
|
@ -104,8 +104,16 @@ function ans2bin(ansi,frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic Field Processing
|
/**
|
||||||
// @note bbs.atcodes() cannot process modifiers, so this function is a replacement.
|
* Dynamic Field Processing
|
||||||
|
*
|
||||||
|
* @param field field we want to get a value for
|
||||||
|
* @param length length to fill this field
|
||||||
|
* @param pad the padding character if field is less than length
|
||||||
|
* @param context a context value to determine the value from
|
||||||
|
* @returns {string|*|null}
|
||||||
|
* @note bbs.atcodes() cannot process modifiers, so this function is a replacement.
|
||||||
|
*/
|
||||||
function atcode(field,length,pad,context) {
|
function atcode(field,length,pad,context) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -299,7 +307,7 @@ function atcode(field,length,pad,context) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result = bbs.atcode(field);
|
result = (typeof bbs === 'undefined') ? '*'.repeat(Math.abs(length)) : bbs.atcode(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result === null) || (typeof result === 'undefined'))
|
if ((result === null) || (typeof result === 'undefined'))
|
||||||
@ -379,7 +387,7 @@ function getNodeID() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (matches.length === 0) ? '-' : padright(matches[0],3,'0')+padright(matches[1],3,'0')+padright(bbs.node_num,2,'0');
|
return (matches.length === 0) ? '-' : padright(matches[0],3,'0')+padright(matches[1],3,'0')+padright((typeof bbs === 'undefined') ? 0 : bbs.node_num,2,'0');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPageOwners() {
|
function getPageOwners() {
|
||||||
|
1098
load/page.js
Normal file
1098
load/page.js
Normal file
File diff suppressed because it is too large
Load Diff
666
load/session-ansitex.js
Normal file
666
load/session-ansitex.js
Normal file
@ -0,0 +1,666 @@
|
|||||||
|
var SESSION_ANSITEX = (1<<1);
|
||||||
|
var SESSION_EXT = 'tex';
|
||||||
|
|
||||||
|
var ANSI_FRAME_WIDTH = 80;
|
||||||
|
var ANSI_FRAME_HEIGHT = 22;
|
||||||
|
var ANSI_FRAME_PROVIDER_LENGTH = 55;
|
||||||
|
var ANSI_FRAME_PAGE_LENGTH = 13;
|
||||||
|
var ANSI_FRAME_COST_LENGTH = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function converts ANSI text into an array of attributes
|
||||||
|
*
|
||||||
|
* We include the attribute for every character, so that if a window is placed on top of this window, the edges
|
||||||
|
* render correctly.
|
||||||
|
*
|
||||||
|
* @param contents - Our ANSI content to convert
|
||||||
|
* @param width - The width before wrapping to the next line
|
||||||
|
* @param yoffset - fields offset as discovered
|
||||||
|
* @param xoffset - fields offset as discovered
|
||||||
|
* @param debug - Enable debug mode
|
||||||
|
*/
|
||||||
|
function anstoattrs(contents,width,yoffset,xoffset,debug) {
|
||||||
|
if (debug)
|
||||||
|
writeln('DEBUG active: '+debug);
|
||||||
|
|
||||||
|
lines = (''+contents).split(/\r\n/);
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var bg = BG_BLACK;
|
||||||
|
var fg = LIGHTGRAY;
|
||||||
|
var attr = fg + bg + i;
|
||||||
|
|
||||||
|
var y = 0;
|
||||||
|
// Saving cursor positions
|
||||||
|
var saved = {};
|
||||||
|
|
||||||
|
var frame = {
|
||||||
|
content: [],
|
||||||
|
dynamic_fields: [],
|
||||||
|
input_fields: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// @todo temp hack, rework ansi variable - perhaps have a function that converts an attribute back into an ANSI sequence
|
||||||
|
var ansi = { i: 0, f: 37, b: 40 };
|
||||||
|
|
||||||
|
while (lines.length > 0) {
|
||||||
|
var x = 0;
|
||||||
|
var line = lines.shift();
|
||||||
|
|
||||||
|
if ((debug !== undefined) && (y > debug)) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
log(LOG_DEBUG,'y:'+y);
|
||||||
|
log(LOG_DEBUG,'line:'+line);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (line.length > 0) {
|
||||||
|
/* parse an attribute sequence*/
|
||||||
|
var m = line.match(/^\x1b\[((\d+)(;?(\d+))*)+m/);
|
||||||
|
if (m !== null) {
|
||||||
|
line = line.substr(m.shift().length);
|
||||||
|
m = m.shift().split(';').sort(function(a,b) { return Number(a) < Number(b) ? -1 : 1; });
|
||||||
|
|
||||||
|
if ((debug !== undefined) && debug === y) {
|
||||||
|
//writeln();
|
||||||
|
log(LOG_DEBUG,'m:'+JSON.stringify(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
if (Number(m[0]) === 0) {
|
||||||
|
bg = BG_BLACK;
|
||||||
|
fg = LIGHTGRAY;
|
||||||
|
i = 0;
|
||||||
|
ansi = { i:0, b:37, f:40};
|
||||||
|
m.shift();
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
log(LOG_DEBUG,' - RESET');
|
||||||
|
}
|
||||||
|
|
||||||
|
// High Intensity
|
||||||
|
if (Number(m[0]) === 1) {
|
||||||
|
i += (((i === 0) || (i === BLINK)) ? HIGH : 0);
|
||||||
|
m.shift();
|
||||||
|
ansi.i = 1;
|
||||||
|
|
||||||
|
if (debug && (debug === y))
|
||||||
|
writeln('fg:'+fg+', bg:'+bg+' i:'+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blink
|
||||||
|
if (Number(m[0]) === 5) {
|
||||||
|
i += (((i === 0) || (i === HIGH)) ? BLINK : 0);
|
||||||
|
m.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Foreground
|
||||||
|
if ((Number(m[0]) >= 30) && (Number(m[0]) <= 37)) {
|
||||||
|
ansi.f = Number(m[0]);
|
||||||
|
|
||||||
|
switch(Number(m.shift())) {
|
||||||
|
case 30:
|
||||||
|
fg = BLACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 31:
|
||||||
|
fg = RED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
fg = GREEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 33:
|
||||||
|
fg = BROWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 34:
|
||||||
|
fg = BLUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 35:
|
||||||
|
fg = MAGENTA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 36:
|
||||||
|
fg = CYAN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 37:
|
||||||
|
fg = LIGHTGRAY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Background
|
||||||
|
if ((Number(m[0]) >= 40) && (Number(m[0]) <= 47)) {
|
||||||
|
ansi.b = Number(m[0]);
|
||||||
|
|
||||||
|
switch (Number(m.shift())) {
|
||||||
|
case 40:
|
||||||
|
bg = BG_BLACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 41:
|
||||||
|
bg = BG_RED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 42:
|
||||||
|
bg = BG_GREEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 43:
|
||||||
|
bg = BG_BROWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 44:
|
||||||
|
bg = BG_BLUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 45:
|
||||||
|
bg = BG_MAGENTA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 46:
|
||||||
|
bg = BG_CYAN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 47:
|
||||||
|
bg = BG_LIGHTGRAY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
log(LOG_DEBUG,'fg:'+fg+', bg:'+bg+' i:'+i);
|
||||||
|
log(LOG_DEBUG,'ansi:'+JSON.stringify(ansi));
|
||||||
|
}
|
||||||
|
|
||||||
|
attr = bg + fg + i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
log(LOG_DEBUG,'= Current attr:'+attr);
|
||||||
|
|
||||||
|
/* parse absolute character position */
|
||||||
|
var m = line.match(/^\x1b\[(\d*);?(\d*)[Hf]/);
|
||||||
|
if (m !== null) {
|
||||||
|
line = line.substr(m.shift().length);
|
||||||
|
|
||||||
|
if (m.length === 0) {
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(m[0])
|
||||||
|
y = Number(m.shift())-1;
|
||||||
|
|
||||||
|
if(m[0])
|
||||||
|
x = Number(m.shift())-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ignore a bullshit sequence */
|
||||||
|
var n = line.match(/^\x1b\[\?7h/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse an up positional sequence */
|
||||||
|
var n = line.match(/^\x1b\[(\d*)A/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
|
||||||
|
var chars = n.shift();
|
||||||
|
|
||||||
|
y -= (chars < 1) ? 0 : Number(chars);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a down positional sequence */
|
||||||
|
var n = line.match(/^\x1b\[(\d*)B/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
|
||||||
|
var chars = n.shift();
|
||||||
|
|
||||||
|
y += (chars < 1) ? 0 : Number(chars);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a forward positional sequence */
|
||||||
|
var n = line.match(/^\x1b\[(\d*)C/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
|
||||||
|
var chars = n.shift();
|
||||||
|
|
||||||
|
x += (chars < 1) ? 0 : Number(chars);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a backward positional sequence */
|
||||||
|
var n = line.match(/^\x1b\[(\d*)D/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
|
||||||
|
var chars = n.shift()
|
||||||
|
|
||||||
|
x -= (chars < 1) ? 0 : Number(chars);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a clear screen sequence */
|
||||||
|
var n = line.match(/^\x1b\[2J/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse save cursor sequence */
|
||||||
|
var n = line.match(/^\x1b\[s/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
saved.x = x;
|
||||||
|
saved.y = y;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse restore cursor sequence */
|
||||||
|
var n = line.match(/^\x1b\[u/);
|
||||||
|
if (n !== null) {
|
||||||
|
line = line.substr(n.shift().length);
|
||||||
|
x = saved.x;
|
||||||
|
y = saved.y;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse an input field */
|
||||||
|
// Input field 'FIELD;valueTYPE;input char'
|
||||||
|
// @todo remove the trailing ESC \ to end the field, just use a control code ^B \x02 (Start of Text) and ^C \x03
|
||||||
|
var m = line.match(/^\x1b_(([A-Z]+;[0-9a-z]+)([;]?.+)?)\x1b\\/);
|
||||||
|
if (m !== null) {
|
||||||
|
log(LOG_DEBUG,'Got input field: '+JSON.stringify(m));
|
||||||
|
log(LOG_DEBUG,'ansi:'+JSON.stringify(ansi));
|
||||||
|
// full string that matched
|
||||||
|
match = m.shift();
|
||||||
|
|
||||||
|
// thus, the rest of the line
|
||||||
|
line = line.substr(match.length);
|
||||||
|
//writeln('rest of line:'+JSON.stringify(line));
|
||||||
|
|
||||||
|
// We are interested in our field match
|
||||||
|
var sos = m.shift().split(';');
|
||||||
|
//writeln('sos:'+JSON.stringify(sos));
|
||||||
|
|
||||||
|
for (var num in sos) {
|
||||||
|
switch (num) {
|
||||||
|
// First value is the field name
|
||||||
|
case '0':
|
||||||
|
field = sos[num];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Second value is the length/type of the field, nnX nn=size in chars, T=type (lower case)
|
||||||
|
case '1':
|
||||||
|
var c = sos[num].match(/([0-9]+)([a-z])/);
|
||||||
|
if (! c) {
|
||||||
|
log(LOG_ERROR,'SOS FAILED PARSING FIELD LENGTH/TYPE. ['+r+'x'+c+'] '+sos[num]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM CHARS: '+x[1]+', TYPE: '+x[2]);
|
||||||
|
fieldlen = c[1];
|
||||||
|
fieldtype = c[2];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Third field is the char to to use
|
||||||
|
case '2':
|
||||||
|
fieldchar = sos[num];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(LOG_ERROR,'IGNORING ADDITIONAL SOS FIELDS. ['+r+'x'+c+'] '+sos[num]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are padding our field with a char, we need to add that back to line
|
||||||
|
// @todo validate if this goes beyond our width (and if scrolling not enabled)
|
||||||
|
if (fieldlen)
|
||||||
|
line = fieldchar.repeat(fieldlen)+line;
|
||||||
|
|
||||||
|
frame.input_fields.push({
|
||||||
|
type: fieldtype,
|
||||||
|
length: Number(fieldlen),
|
||||||
|
char: fieldchar,
|
||||||
|
name: field,
|
||||||
|
attribute: JSON.parse(JSON.stringify(ansi)),
|
||||||
|
x: Number(x+(xoffset !== undefined ? xoffset : 0)),
|
||||||
|
y: Number(y+(yoffset !== undefined ? yoffset : 0)),
|
||||||
|
value: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'input_field:'+JSON.stringify(frame.input_fields.last));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse dynamic value field */
|
||||||
|
// @todo remove the trailing ESC \ to end the field, just use a control code ie: ^E \x05 (Enquiry) or ^Z \x26 (Substitute)
|
||||||
|
var m = line.match(/^\x1bX(([a-zA-Z._:^;]+[0-9]?;-?[0-9^;]+)([;]?[^;]+)?)\x1b\\/);
|
||||||
|
if (m !== null) {
|
||||||
|
// full string that matched
|
||||||
|
match = m.shift();
|
||||||
|
|
||||||
|
// thus, the rest of the line
|
||||||
|
line = line.substr(match.length);
|
||||||
|
//writeln('rest of line:'+JSON.stringify(line));
|
||||||
|
|
||||||
|
// We are interested in our field match
|
||||||
|
var df = m.shift().split(';');
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'- DF found at ['+x+'x'+y+'], Field: '+df[0]+', Length: '+df[1]+', Pad:'+df[2]);
|
||||||
|
// If we are padding our field with a char, we need to add that back to line
|
||||||
|
// @todo validate if this goes beyond our width (and if scrolling not enabled)
|
||||||
|
line = (df[2] ? df[2] : '_').repeat(Math.abs(df[1]))+line;
|
||||||
|
|
||||||
|
frame.dynamic_fields.push({
|
||||||
|
name: df[0],
|
||||||
|
length: df[1],
|
||||||
|
pad: df[2],
|
||||||
|
x: x+(xoffset !== undefined ? xoffset : 0),
|
||||||
|
y: y+(yoffset !== undefined ? yoffset : 0),
|
||||||
|
value: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set character and attribute */
|
||||||
|
var ch = line[0];
|
||||||
|
line = line.substr(1);
|
||||||
|
|
||||||
|
if (debug && debug === y) {
|
||||||
|
log(LOG_DEBUG,'Got char: '+ch);
|
||||||
|
//write(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate position */
|
||||||
|
if (y < 0)
|
||||||
|
y = 0;
|
||||||
|
if (x < 0)
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
if (x >= width) {
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set character and attribute */
|
||||||
|
if (! frame.content[y+1])
|
||||||
|
frame.content[y+1]=[];
|
||||||
|
|
||||||
|
if (attr === null)
|
||||||
|
throw new Error('Attribute is null?');
|
||||||
|
|
||||||
|
frame.content[y+1][x+1] = new Char(ch,attr);
|
||||||
|
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got a BG_BLACK|LIGHTGRAY ESC [0m, but not character, we include it as it resets any background that was going on
|
||||||
|
if ((attr === BG_BLACK|LIGHTGRAY) && frame.content[y+1] && (frame.content[y+1][x].__properties__.attr !== attr))
|
||||||
|
frame.content[y+1][x+1] = new Char(undefined,attr);
|
||||||
|
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
load('ansitex/load/session.js');
|
||||||
|
|
||||||
|
// Our frame object
|
||||||
|
function SessionAnsitex() {
|
||||||
|
Session.apply(this,arguments);
|
||||||
|
|
||||||
|
/* File Extension used for frames */
|
||||||
|
this.settings.ext = 'tex';
|
||||||
|
|
||||||
|
/* Length of a frame */
|
||||||
|
this.settings.FRAME_LENGTH = 22;
|
||||||
|
/* Width of a frame */
|
||||||
|
this.settings.FRAME_WIDTH = 80;
|
||||||
|
/* Size of page owner (length) */
|
||||||
|
this.settings.FRAME_HEADER = 56;
|
||||||
|
/* Size of page number (length with a-z) */
|
||||||
|
this.settings.FRAME_PAGENUM = 12;
|
||||||
|
/* Size of cost (length without unit) */
|
||||||
|
this.settings.FRAME_COST = 9;
|
||||||
|
|
||||||
|
this.settings.MSG_SENDORNOT = '\1n\1h\1GKEY 1 TO SEND, 2 NOT TO SEND';
|
||||||
|
this.settings.MSG_LOGON = '\1n\1h\1GKEY 1 TO LOGON, 2 TO RETURN';
|
||||||
|
this.settings.MSG_SENT = '\1n\1h\1GMESSAGE SENT - KEY # TO CONTINUE';
|
||||||
|
this.settings.MSG_NOTSENT = '\1n\1h\1GMESSAGE NOT SENT - KEY # TO CONTINUE';
|
||||||
|
this.settings.ERR_NO_PARENT = '\1n\1h\1RPARENT FRAME DOESNT EXIST';
|
||||||
|
this.settings.ERR_NOT_IMPLEMENTED = '\1n\1h\1RNOT IMPLEMENTED YET?';
|
||||||
|
this.settings.ERR_ROUTE = '\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
|
||||||
|
this.settings.ERR_METHOD_NOT_EXIST = '\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
|
||||||
|
this.settings.ACCESS_DENIED = '\1n\1h\1RACCESS DENIED. MISTAKE? TRY AGAIN OR TELL US *08';
|
||||||
|
this.settings.ALREADY_MEMBER = '\1n\1h\1RALREADY MEMBER OF CUG'
|
||||||
|
this.settings.INACTIVITY = '\1n\1h\1RINACTIVITY ALERT, DISCONNECT PENDING...';
|
||||||
|
this.settings.INACTIVE = '\1n\1h\1RINACTIVITY DISCONNECT';
|
||||||
|
this.settings.NOACTION = '\1n\1h\1RNO ACTION PERFORMED';
|
||||||
|
this.settings.BASESTAR = '\1N\1G\1H*';
|
||||||
|
this.settings.INVALID_CODE = '\1n\1h\1RINVAID CODE, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.TOKEN_EMAIL = '\1n\1h\1RTOKEN EMAILED TO YOU...';
|
||||||
|
this.settings.TOKEN_SENT = '\1n\1h\1RTOKEN SENT, PLEASE ENTER TOKEN';
|
||||||
|
this.settings.INVALID_EMAIL = '\1n\1h\1RINVAID EMAIL, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.INVALID_UID = '\1n\1h\1RINVAID USER ID, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.CANNOT_SEND_TOKEN = '\1n\1h\1RCANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.USER_EXISTS = '\1n\1h\1RERROR USER EXISTS, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.USER_CREATE_ERROR = '\1n\1h\1RERROR CREATING USER, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.LOGIN_ERROR = '\1n\1h\1RERROR LOGGING IN, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.CANCEL_MSG = '\1n\1h\1GPRESS 2 TO CANCEL';
|
||||||
|
this.settings.SYS_ERROR = '\1n\1h\1RSYSTEM ERROR DETECTED - TRY AGAIN OR TELL US *08';
|
||||||
|
this.settings.LOADING = '\1n\1h\1Kloading...';
|
||||||
|
this.settings.PROCESSING = '\1n\1h\1Kprocessing...';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the attribute at the current position
|
||||||
|
*/
|
||||||
|
this.attr = function(field) {
|
||||||
|
write('\x1b['+field.i+';'+field.f+';'+field.b+'m');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.baselineClear = function(reposition) {
|
||||||
|
this.cursorSave();
|
||||||
|
this.gotoxy(0,24);
|
||||||
|
this.cleareol();
|
||||||
|
|
||||||
|
if (! reposition)
|
||||||
|
this.cursorRestore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the baseline.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* @param reposition
|
||||||
|
*/
|
||||||
|
this.baselineSend = function(text,reposition) {
|
||||||
|
this.cursorSave();
|
||||||
|
this.gotoxy(0,24);
|
||||||
|
write(this.getMessage(text));
|
||||||
|
this.cleareol();
|
||||||
|
|
||||||
|
if (! reposition)
|
||||||
|
this.cursorRestore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn off the cursor
|
||||||
|
*/
|
||||||
|
this.cursorOff = function() {
|
||||||
|
write('\x1b[?25l');
|
||||||
|
write('\x1b[24;0H');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on cursor
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
*/
|
||||||
|
this.cursorOn = function(x,y) {
|
||||||
|
write('\x1b[?25h');
|
||||||
|
|
||||||
|
if (x && y)
|
||||||
|
this.gotoxy(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cursorRestore = function() {
|
||||||
|
write('\x1b[u');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cursorSave = function() {
|
||||||
|
write('\x1b[s');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cleareol = function() {
|
||||||
|
write('\x1b[0K');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field backspace, that leaves the field filler char
|
||||||
|
this.fieldbs = function(char) {
|
||||||
|
write('\x1b[D'+char+'\x1b[D');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position the cursor in a specific location
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
*/
|
||||||
|
this.gotoxy = function(x,y) {
|
||||||
|
write('\x1b['+y+';'+x+'H');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Render the frame to the user
|
||||||
|
this.render=function(context,withoutHeader) {
|
||||||
|
log(LOG_DEBUG,'- ANSI FRAME');
|
||||||
|
owner = base64_decode(this.owner);
|
||||||
|
|
||||||
|
const frame = new Frame(1,1,this.settings.FRAME_WIDTH,this.settings.FRAME_LENGTH+2,LIGHTGRAY);
|
||||||
|
frame.open();
|
||||||
|
|
||||||
|
// Dont show the page number on system login page
|
||||||
|
if ((! withoutHeader) && (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1))) {
|
||||||
|
log(LOG_DEBUG,' - Owner: ['+this.pageowner+']');
|
||||||
|
|
||||||
|
cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -');
|
||||||
|
|
||||||
|
header = '\1n'+this.pageownerlogo+' '.repeat(this.settings.FRAME_HEADER-console.strlen(this.pageownerlogo))+'\1n '+
|
||||||
|
(this.isAccessible ? '\1W' : '\1R')+'\1H'+this.page+' '.repeat(this.settings.FRAME_PAGENUM-this.page.length)+' '+
|
||||||
|
'\1G\1H'+' '.repeat(this.settings.FRAME_COST-cost.toString().length+1)+cost+'\1n'+
|
||||||
|
(console.screen_columns > 80 ? '\n\r' : '');
|
||||||
|
|
||||||
|
frame.putmsg(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
contentgraphic = new Graphic(this.settings.FRAME_WIDTH);
|
||||||
|
contentgraphic.auto_extend = true;
|
||||||
|
contentgraphic.atcodes = false;
|
||||||
|
contentgraphic.ANSI = this.parse(base64_decode(this.content),context);
|
||||||
|
|
||||||
|
var contentframe = new Frame(1,2,this.settings.FRAME_WIDTH,this.settings.FRAME_LENGTH,LIGHTGRAY,frame);
|
||||||
|
contentframe.open();
|
||||||
|
contentframe.lf_strict = false;
|
||||||
|
contentframe.atcodes = false;
|
||||||
|
contentframe.word_wrap = false
|
||||||
|
|
||||||
|
contentframe.putmsg(contentgraphic.MSG)
|
||||||
|
contentframe.scrollTo(0,0);
|
||||||
|
|
||||||
|
frame.cycle();
|
||||||
|
|
||||||
|
return contentframe;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.qrcode=function(qr,subframe) {
|
||||||
|
// SMALL Image
|
||||||
|
var full = ascii(0xdb);
|
||||||
|
var top = ascii(0xdf);
|
||||||
|
var bot = ascii(0xdc);
|
||||||
|
var blank = ' ';
|
||||||
|
|
||||||
|
var qrcode = '';
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Render the top line
|
||||||
|
var line = ascii(27)+'[1;37m'+bot;
|
||||||
|
for (var y = 0; y < qr.size; y++) {
|
||||||
|
line += bot;
|
||||||
|
}
|
||||||
|
qrcode += line+bot+bot+ascii(27)+'[0m'+"\r\n";
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Render the body
|
||||||
|
for (var x = -1; x < qr.size; x=x+2) {
|
||||||
|
line = ascii(27)+'[1;37m'+full;
|
||||||
|
|
||||||
|
for (var y = 0; y < qr.size; y++) {
|
||||||
|
// Top is white
|
||||||
|
if (! ((x===-1)? 0 : qr.getModule(x, y))) {
|
||||||
|
line += (qr.getModule(x+1, y)) ? top : full;
|
||||||
|
|
||||||
|
// Top is black
|
||||||
|
} else {
|
||||||
|
line += (qr.getModule(x+1, y)) ? blank : bot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qrcode += line+full+ascii(27)+'[0m'+"\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the bottom
|
||||||
|
line = ascii(27)+'[1;37m'+top;
|
||||||
|
for (var y = 0; y < qr.size; y++) {
|
||||||
|
line += top;
|
||||||
|
}
|
||||||
|
qrcode += line+top+ascii(27)+'[0m'+"\r\n";
|
||||||
|
|
||||||
|
ans2bin(fo.parse(qrcode),subframe);
|
||||||
|
subframe.open();
|
||||||
|
subframe.cycle();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
this.save=function() {
|
||||||
|
file = system.mods_dir+'ansitex/text/'+this.page+'.tex';
|
||||||
|
w = new File(file);
|
||||||
|
if (! w.open('w')) {
|
||||||
|
log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+this.page);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.write(JSON.stringify(this));
|
||||||
|
w.close();
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'Saved file: '+this.page+'.tex');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionAnsitex.prototype = Session.prototype;
|
||||||
|
SessionAnsitex.prototype.constructor = SessionAnsitex;
|
691
load/session-viewdata.js
Normal file
691
load/session-viewdata.js
Normal file
@ -0,0 +1,691 @@
|
|||||||
|
var SESSION_VIEWDATA = (1<<2);
|
||||||
|
var SESSION_EXT = 'vtx';
|
||||||
|
|
||||||
|
var VIEWDATA_FRAME_WIDTH = 40;
|
||||||
|
var VIEWDATA_FRAME_HEIGHT = 22;
|
||||||
|
var VIEWDATA_FRAME_PROVIDER_LENGTH = 23;
|
||||||
|
var VIEWDATA_FRAME_PAGE_LENGTH = 11;
|
||||||
|
var VIEWDATA_FRAME_COST_LENGTH = 6;
|
||||||
|
|
||||||
|
var VIEWDATA_LEFT = '\x08';
|
||||||
|
var VIEWDATA_RIGHT = '\x09';
|
||||||
|
var VIEWDATA_DOWN = '\x0a'; // \n
|
||||||
|
var VIEWDATA_UP = '\x0b';
|
||||||
|
var VIEWDATA_CLS = '\x0c';
|
||||||
|
var VIEWDATA_CR = '\x0d'; // \r
|
||||||
|
var VIEWDATA_CON = '\x11';
|
||||||
|
var VIEWDATA_COFF = '\x14';
|
||||||
|
var VIEWDATA_HOME = '\x1e';
|
||||||
|
|
||||||
|
var VIEWDATA_BLINK = '\x48';
|
||||||
|
var VIEWDATA_STEADY = '\x49';
|
||||||
|
var VIEWDATA_NORMAL = '\x4c';
|
||||||
|
var VIEWDATA_DOUBLE = '\x4d';
|
||||||
|
var VIEWDATA_CONCEAL = '\x58';
|
||||||
|
var VIEWDATA_BLOCKS = '\x59';
|
||||||
|
var VIEWDATA_SEPARATED = '\x5a';
|
||||||
|
var VIEWDATA_BLACKBACK = '\x5c';
|
||||||
|
var VIEWDATA_NEWBACK = '\x5d';
|
||||||
|
var VIEWDATA_HOLD = '\x5e';
|
||||||
|
var VIEWDATA_REVEAL = '\x5f';
|
||||||
|
|
||||||
|
var VIEWDATA_RED = '\x41';
|
||||||
|
var VIEWDATA_GREEN = '\x42';
|
||||||
|
var VIEWDATA_YELLOW = '\x43'; // C
|
||||||
|
var VIEWDATA_BLUE = '\x44';
|
||||||
|
var VIEWDATA_MAGENTA = '\x45';
|
||||||
|
var VIEWDATA_CYAN = '\x46';
|
||||||
|
var VIEWDATA_WHITE = '\x47';
|
||||||
|
|
||||||
|
var VIEWDATA_MOSIAC_RED = '\x51';
|
||||||
|
var VIEWDATA_MOSIAC_GREEN = '\x52';
|
||||||
|
var VIEWDATA_MOSIAC_YELLOW = '\x53';
|
||||||
|
var VIEWDATA_MOSIAC_BLUE = '\x54';
|
||||||
|
var VIEWDATA_MOSIAC_MAGENTA = '\x55';
|
||||||
|
var VIEWDATA_MOSIAC_CYAN = '\x56';
|
||||||
|
var VIEWDATA_MOSIAC_WHITE = '\x57'; // W
|
||||||
|
|
||||||
|
/* BINARY DUMP LEVEL 1 ATTRIBUTES */
|
||||||
|
var VIEWDATA_BIN_RED = '\x01';
|
||||||
|
var VIEWDATA_BIN_GREEN = '\x02';
|
||||||
|
var VIEWDATA_BIN_YELLOW = '\x03';
|
||||||
|
var VIEWDATA_BIN_BLUE = '\x04';
|
||||||
|
var VIEWDATA_BIN_MAGENTA = '\x05';
|
||||||
|
var VIEWDATA_BIN_CYAN = '\x06';
|
||||||
|
var VIEWDATA_BIN_WHITE = '\x07';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewData characters are 7bit (0x00-0x7f)
|
||||||
|
*
|
||||||
|
* Chars 0x00-0x1f are control characters (display attributes) and are sent to the terminal with 0x1b
|
||||||
|
* + 0x00-0x07 are foreground colors
|
||||||
|
* + 0x08-0x09 flash/steady
|
||||||
|
* + 0x0a-0x0b end/start box (?) *
|
||||||
|
* + 0x0c-0x0d normal/double height
|
||||||
|
* + 0x0e-0x0f double width (?) *
|
||||||
|
* + 0x10-0x17 are foreground graphics (mosiac) colors
|
||||||
|
* + 0x18/0x1f conceal/reveal
|
||||||
|
* + 0x19-0x1a solid/seperated graphics
|
||||||
|
* + 0x1b unused
|
||||||
|
* + 0x1c-1x1d Black/New Background (new background converts color foreground to background)
|
||||||
|
* + 0x1e-0x1f graphics hold/release (enables changing color and repeats previous graphics char)
|
||||||
|
* Chars 0x20-0x7f are normal printed ASCII chars
|
||||||
|
* Chars 0x20-0x3f & 0x60-0x7f when activated with a MOSIAC color sends a 2x3 pixel character
|
||||||
|
*
|
||||||
|
* We can map these into cga_defs with the following amendments:
|
||||||
|
* 0x00-0x0f = foreground/background colors (4 bits) (8 foreground/8 background colors)
|
||||||
|
* 0x10 - mosiac (bit 4)
|
||||||
|
* 0x20 - conceal (bit 5)
|
||||||
|
* 0x40 - seperated graphics (bit 6)
|
||||||
|
* 0x80 - flash (bit 7)
|
||||||
|
* 0x100 - double height (bit 8)
|
||||||
|
* 0x200 - hold (bit 9)
|
||||||
|
* 0x400 - new background (bits 10/11)
|
||||||
|
* 0x800 - black background (bits 10/11)
|
||||||
|
* 0xc00 - unused (bits 10/11)
|
||||||
|
* bits (12-15) unused
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
var MOSIAC = 0x10;
|
||||||
|
|
||||||
|
// Toggles
|
||||||
|
var CONCEAL = 0x20;
|
||||||
|
var REVEAL = 0x2000; // @temp Turns off Conceal
|
||||||
|
|
||||||
|
var SEPARATED = 0x40;
|
||||||
|
var BLOCKS = 0x4000; // @temp Turns off Separated
|
||||||
|
|
||||||
|
var STEADY = 0x8000; // @temp (turn off flash)
|
||||||
|
|
||||||
|
var DOUBLE = 0x100;
|
||||||
|
var NORMAL = 0x1000; // @temp Turns off Double Height
|
||||||
|
|
||||||
|
var HOLD = 0x200;
|
||||||
|
var RELEASE = 0x20000; // @temp turns off Hold
|
||||||
|
|
||||||
|
var NEWBACK = 0x400;
|
||||||
|
var BLACKBACK = 0x800;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function converts ANSI text into an array of attributes
|
||||||
|
*
|
||||||
|
* @param contents - Our ANSI content to convert
|
||||||
|
* @param width - The width before wrapping to the next line
|
||||||
|
* @param yoffset - fields offset as discovered
|
||||||
|
* @param xoffset - fields offset as discovered
|
||||||
|
* @param debug - Enable debug mode
|
||||||
|
*/
|
||||||
|
function bintoattrs(contents,width,yoffset,xoffset,debug) {
|
||||||
|
if (debug)
|
||||||
|
writeln('DEBUG active: '+debug);
|
||||||
|
|
||||||
|
lines = (''+contents).split(/\r\n/);
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var bg = BG_BLACK;
|
||||||
|
var fg = LIGHTGRAY;
|
||||||
|
var attr = fg + bg + i;
|
||||||
|
|
||||||
|
// Attribute state on a new line
|
||||||
|
var new_line = attr;
|
||||||
|
|
||||||
|
var y = 0;
|
||||||
|
|
||||||
|
var frame = {
|
||||||
|
content: [],
|
||||||
|
dynamic_fields: [],
|
||||||
|
input_fields: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// @todo temp hack, rework ansi variable - perhaps have a function that converts an attribute back into an ANSI sequence
|
||||||
|
var ansi = { i: 0, f: 37, b: 40 };
|
||||||
|
|
||||||
|
while (lines.length > 0) {
|
||||||
|
var x = 0;
|
||||||
|
var line = lines.shift();
|
||||||
|
|
||||||
|
if ((debug !== undefined) && (y > debug)) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
log(LOG_DEBUG,'y:'+y);
|
||||||
|
log(LOG_DEBUG,'line:'+line);
|
||||||
|
write('y:'+y+', line:'+line);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (line.length > 0) {
|
||||||
|
if (x >= width) {
|
||||||
|
x = 0;
|
||||||
|
// Each new line, we reset the attrs
|
||||||
|
attr = new_line;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
//writeln('next ch:'+line[0].charCodeAt(0));
|
||||||
|
|
||||||
|
/* parse control codes */
|
||||||
|
var m = line.match(/^([\x00-\x1f])/);
|
||||||
|
if (m !== null) {
|
||||||
|
line = line.substr(m[0].length);
|
||||||
|
attr = 0;
|
||||||
|
|
||||||
|
match = m.shift().charCodeAt(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
writeln('- match:'+match);
|
||||||
|
|
||||||
|
writeln('- match 0x0f:'+(match & 0x0f));
|
||||||
|
if (match & 0x10) {
|
||||||
|
writeln(' - got mosiac');
|
||||||
|
attr += MOSIAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
//if (match < 0x0f) {
|
||||||
|
//switch(match & 0x07) {
|
||||||
|
switch(match) {
|
||||||
|
case 0x00:
|
||||||
|
attr += BLACK;
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
attr += RED;
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
attr += GREEN;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
attr += YELLOW;
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
attr += BLUE;
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
attr += MAGENTA;
|
||||||
|
break;
|
||||||
|
case 0x06:
|
||||||
|
attr += CYAN;
|
||||||
|
break;
|
||||||
|
case 0x07:
|
||||||
|
attr += LIGHTGRAY;
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
attr = BLINK;
|
||||||
|
break;
|
||||||
|
case 0x09:
|
||||||
|
attr = STEADY;
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case 0x0a:
|
||||||
|
//attr = ENDBOX; // End Box (Unused?)
|
||||||
|
break;
|
||||||
|
case 0x0b:
|
||||||
|
//attr = STARTBOX; // Start Box (Unused?)
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case 0x0c:
|
||||||
|
//attr &= ~DOUBLE;
|
||||||
|
attr = NORMAL;
|
||||||
|
break;
|
||||||
|
case 0x0d:
|
||||||
|
attr = DOUBLE;
|
||||||
|
break;
|
||||||
|
case 0x0e:
|
||||||
|
attr = NORMAL; // @todo Double Width (Unused)?
|
||||||
|
break;
|
||||||
|
case 0x0f:
|
||||||
|
attr = NORMAL; // @todo Double Width (Unused?)
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
attr = MOSIAC|BLACK;
|
||||||
|
break;
|
||||||
|
case 0x11:
|
||||||
|
attr += MOSIAC|RED;
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
attr += MOSIAC|GREEN;
|
||||||
|
break;
|
||||||
|
case 0x13:
|
||||||
|
attr += MOSIAC|YELLOW;
|
||||||
|
break;
|
||||||
|
case 0x14:
|
||||||
|
attr += MOSIAC|BLUE;
|
||||||
|
break;
|
||||||
|
case 0x15:
|
||||||
|
attr += MOSIAC|MAGENTA;
|
||||||
|
break;
|
||||||
|
case 0x16:
|
||||||
|
attr += MOSIAC|CYAN;
|
||||||
|
break;
|
||||||
|
case 0x17:
|
||||||
|
attr += MOSIAC|LIGHTGRAY;
|
||||||
|
break;
|
||||||
|
case 0x18:
|
||||||
|
attr = CONCEAL;
|
||||||
|
break;
|
||||||
|
case 0x19:
|
||||||
|
attr = BLOCKS;
|
||||||
|
break;
|
||||||
|
case 0x1a:
|
||||||
|
attr = SEPARATED;
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case 0x1b:
|
||||||
|
//attr = NORMAL; // CSI
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case 0x1c:
|
||||||
|
attr = BLACKBACK; // Black Background
|
||||||
|
break;
|
||||||
|
case 0x1d:
|
||||||
|
attr = NEWBACK; // New Background
|
||||||
|
break;
|
||||||
|
case 0x1e:
|
||||||
|
attr = HOLD; // Mosiac Hold
|
||||||
|
break;
|
||||||
|
case 0x1f:
|
||||||
|
attr = RELEASE; // Mosiac Release
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Catch all for other codes
|
||||||
|
default:
|
||||||
|
attr = 0xff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
writeln(' - got control code:'+attr+'['+y+','+x+'] - length:'+attr.length);
|
||||||
|
|
||||||
|
store(x++,y,null,attr);
|
||||||
|
attr = undefined;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse an input field */
|
||||||
|
// Input field 'FIELD;valueTYPE;input char'
|
||||||
|
// @todo remove the trailing ESC \ to end the field, just use a control code ^B \x02 (Start of Text) and ^C \x03
|
||||||
|
var m = line.match(/^\x1b_(([A-Z]+;[0-9a-z]+)([;]?.+)?)\x1b\\/);
|
||||||
|
if (m !== null) {
|
||||||
|
log(LOG_DEBUG,'Got input field: '+JSON.stringify(m));
|
||||||
|
log(LOG_DEBUG,'ansi:'+JSON.stringify(ansi));
|
||||||
|
// full string that matched
|
||||||
|
match = m.shift();
|
||||||
|
|
||||||
|
// thus, the rest of the line
|
||||||
|
line = line.substr(match.length);
|
||||||
|
//writeln('rest of line:'+JSON.stringify(line));
|
||||||
|
|
||||||
|
// We are interested in our field match
|
||||||
|
var sos = m.shift().split(';');
|
||||||
|
//writeln('sos:'+JSON.stringify(sos));
|
||||||
|
|
||||||
|
for (var num in sos) {
|
||||||
|
switch (num) {
|
||||||
|
// First value is the field name
|
||||||
|
case '0':
|
||||||
|
field = sos[num];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Second value is the length/type of the field, nnX nn=size in chars, T=type (lower case)
|
||||||
|
case '1':
|
||||||
|
var c = sos[num].match(/([0-9]+)([a-z])/);
|
||||||
|
if (! c) {
|
||||||
|
log(LOG_ERROR,'SOS FAILED PARSING FIELD LENGTH/TYPE. ['+r+'x'+c+'] '+sos[num]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM CHARS: '+x[1]+', TYPE: '+x[2]);
|
||||||
|
fieldlen = c[1];
|
||||||
|
fieldtype = c[2];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Third field is the char to to use
|
||||||
|
case '2':
|
||||||
|
fieldchar = sos[num];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(LOG_ERROR,'IGNORING ADDITIONAL SOS FIELDS. ['+r+'x'+c+'] '+sos[num]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are padding our field with a char, we need to add that back to line
|
||||||
|
// @todo validate if this goes beyond our width (and if scrolling not enabled)
|
||||||
|
if (fieldlen)
|
||||||
|
line = fieldchar.repeat(fieldlen)+line;
|
||||||
|
|
||||||
|
frame.input_fields.push({
|
||||||
|
type: fieldtype,
|
||||||
|
length: Number(fieldlen),
|
||||||
|
char: fieldchar,
|
||||||
|
name: field,
|
||||||
|
attribute: JSON.parse(JSON.stringify(ansi)),
|
||||||
|
x: Number(x+(xoffset !== undefined ? xoffset : 0)),
|
||||||
|
y: Number(y+(yoffset !== undefined ? yoffset : 0)),
|
||||||
|
value: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'input_field:'+JSON.stringify(frame.input_fields.last));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse dynamic value field */
|
||||||
|
// @todo remove the trailing ESC \ to end the field, just use a control code ie: ^E \x05 (Enquiry) or ^Z \x26 (Substitute)
|
||||||
|
var m = line.match(/^\x1bX(([a-zA-Z._:^;]+[0-9]?;-?[0-9^;]+)([;]?[^;]+)?)\x1b\\/);
|
||||||
|
if (m !== null) {
|
||||||
|
// full string that matched
|
||||||
|
match = m.shift();
|
||||||
|
|
||||||
|
// thus, the rest of the line
|
||||||
|
line = line.substr(match.length);
|
||||||
|
//writeln('rest of line:'+JSON.stringify(line));
|
||||||
|
|
||||||
|
// We are interested in our field match
|
||||||
|
var df = m.shift().split(';');
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'- DF found at ['+x+'x'+y+'], Field: '+df[0]+', Length: '+df[1]+', Pad:'+df[2]);
|
||||||
|
// If we are padding our field with a char, we need to add that back to line
|
||||||
|
// @todo validate if this goes beyond our width (and if scrolling not enabled)
|
||||||
|
line = (df[2] ? df[2] : '_').repeat(Math.abs(df[1]))+line;
|
||||||
|
|
||||||
|
frame.dynamic_fields.push({
|
||||||
|
name: df[0],
|
||||||
|
length: df[1],
|
||||||
|
pad: df[2],
|
||||||
|
x: x+(xoffset !== undefined ? xoffset : 0),
|
||||||
|
y: y+(yoffset !== undefined ? yoffset : 0),
|
||||||
|
value: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set character and attribute */
|
||||||
|
var ch = line[0];
|
||||||
|
line = line.substr(1);
|
||||||
|
|
||||||
|
if (debug && (debug === y)) {
|
||||||
|
writeln('y:'+y+', x:'+x+', ch:'+ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate position */
|
||||||
|
if (y < 0)
|
||||||
|
y = 0;
|
||||||
|
if (x < 0)
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
store(x,y,ch,undefined);
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each new line, we reset the attrs
|
||||||
|
attr = undefined;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
|
||||||
|
function store(x,y,ch,attr) {
|
||||||
|
/* set character and attribute */
|
||||||
|
if (! frame.content[y+1])
|
||||||
|
frame.content[y+1]=[];
|
||||||
|
|
||||||
|
frame.content[y+1][x+1] = new Char(ch,attr,SESSION_EXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load('ansitex/load/session.js');
|
||||||
|
|
||||||
|
// Our frame object
|
||||||
|
function SessionViewdata() {
|
||||||
|
Session.apply(this,arguments);
|
||||||
|
|
||||||
|
/* File Extension used for frames */
|
||||||
|
this.settings.ext = 'vtx';
|
||||||
|
|
||||||
|
/* Length of a frame */
|
||||||
|
this.settings.FRAME_LENGTH = 22;
|
||||||
|
/* Width of a frame */
|
||||||
|
this.settings.FRAME_WIDTH = 40;
|
||||||
|
/* Size of page owner (length) */
|
||||||
|
this.settings.FRAME_HEADER = 23;
|
||||||
|
/* Size of page number (length with a-z) */
|
||||||
|
this.settings.FRAME_PAGENUM = 11;
|
||||||
|
/* Size of cost (length without unit) */
|
||||||
|
this.settings.FRAME_COST = 3;
|
||||||
|
|
||||||
|
this.settings.MSG_SENDORNOT = ascii(27)+'BKEY 1 TO SEND, 2 NOT TO SEND';
|
||||||
|
this.settings.MSG_LOGON = ascii(27)+'BKEY 1 TO LOGON, 2 TO RETURN';
|
||||||
|
this.settings.MSG_SENT = ascii(27)+'BMESSAGE SENT - KEY _ TO CONTINUE';
|
||||||
|
this.settings.MSG_NOTSENT = ascii(27)+'BMESSAGE NOT SENT - KEY _ TO CONTINUE';
|
||||||
|
this.settings.ERR_NO_PARENT = ascii(27)+'APARENT FRAME DOESNT EXIST';
|
||||||
|
this.settings.ERR_NOT_IMPLEMENTED = ascii(27)+'ANOT IMPLEMENTED YET?';
|
||||||
|
this.settings.ERR_ROUTE = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08';
|
||||||
|
this.settings.ERR_METHOD_NOT_EXIST = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08';
|
||||||
|
this.settings.ACCESS_DENIED = ascii(27)+'AACCESS DENIED.';
|
||||||
|
this.settings.ALREADY_MEMBER = ascii(27)+'AALREADY MEMBER OF CUG'
|
||||||
|
this.settings.INACTIVITY = ascii(27)+'AINACTIVITY ALERT, DISCONNECT PENDING...';
|
||||||
|
this.settings.INACTIVE = ascii(27)+'AINACTIVITY DISCONNECT';
|
||||||
|
this.settings.NOACTION = ascii(27)+'ANO ACTION PERFORMED';
|
||||||
|
this.settings.BASESTAR = ascii(27)+'B*';
|
||||||
|
this.settings.INVALID_CODE = ascii(27)+'AINVAID CODE, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.TOKEN_EMAIL = ascii(27)+'ATOKEN EMAILED TO YOU...';
|
||||||
|
this.settings.TOKEN_SENT = ascii(27)+'ATOKEN SENT, PLEASE ENTER TOKEN';
|
||||||
|
this.settings.INVALID_EMAIL = ascii(27)+'AINVAID EMAIL, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.INVALID_UID = ascii(27)+'AINVAID USER ID, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.CANNOT_SEND_TOKEN = ascii(27)+'ACANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.USER_EXISTS = ascii(27)+'AERROR USER EXISTS, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.USER_CREATE_ERROR = ascii(27)+'AERROR CREATING USER, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.LOGIN_ERROR = ascii(27)+'AERROR LOGGING IN, PLEASE TRY AGAIN *00';
|
||||||
|
this.settings.CANCEL_MSG = ascii(27)+'BPRESS 2 TO CANCEL';
|
||||||
|
this.settings.SYS_ERROR = ascii(27)+'ASYS ERR, TRY AGAIN OR TELL US ON *08';
|
||||||
|
this.settings.LOADING = ascii(27)+'Cloading...';
|
||||||
|
this.settings.PROCESSING = ESC+VIEWDATA_YELLOW+'processing...';
|
||||||
|
|
||||||
|
var blp = 0; // Length of data on the bottom line
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the attribute at the current position
|
||||||
|
*/
|
||||||
|
this.attr = function(field) {
|
||||||
|
//NOOP - the terminal takes care of this
|
||||||
|
}
|
||||||
|
|
||||||
|
this.baselineClear = function(reposition) {
|
||||||
|
msg = '';
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'- Clear Bottom Line ['+blp+'] - reposition ['+reposition+']');
|
||||||
|
|
||||||
|
write_raw(VIEWDATA_HOME+VIEWDATA_UP+msg+
|
||||||
|
((blp > msg.length)
|
||||||
|
? (' '.repeat(blp-msg.length)+(reposition ? VIEWDATA_HOME+VIEWDATA_UP+VIEWDATA_RIGHT.repeat(msg.length) : ''))
|
||||||
|
: '')
|
||||||
|
);
|
||||||
|
|
||||||
|
blp = msg.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the baseline.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* @param reposition
|
||||||
|
*/
|
||||||
|
this.baselineSend = function(text,reposition) {
|
||||||
|
var msg = this.getMessage(text);
|
||||||
|
var x = this.strlen(msg);
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'- Bottom Line ['+msg+'] ('+x+') - reposition ['+reposition+'] BLP:'+blp);
|
||||||
|
|
||||||
|
write_raw(VIEWDATA_HOME+VIEWDATA_UP+msg+
|
||||||
|
((blp > x)
|
||||||
|
? (' '.repeat(blp-x)+(reposition ? VIEWDATA_HOME+VIEWDATA_UP+VIEWDATA_RIGHT.repeat(x) : ''))
|
||||||
|
: '')
|
||||||
|
);
|
||||||
|
|
||||||
|
blp = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn off the cursor
|
||||||
|
*/
|
||||||
|
this.cursorOff = function() {
|
||||||
|
write_raw(VIEWDATA_COFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on cursor
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
*/
|
||||||
|
this.cursorOn = function(x,y) {
|
||||||
|
write_raw(VIEWDATA_CON);
|
||||||
|
|
||||||
|
if (x && y)
|
||||||
|
this.gotoxy(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field backspace, that leaves the field filler char
|
||||||
|
this.fieldbs = function(char) {
|
||||||
|
log(LOG_DEBUG,'- Field backspace with char:'+char);
|
||||||
|
write_raw(VIEWDATA_LEFT+char+VIEWDATA_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gotoxy = function(x,y) {
|
||||||
|
log(LOG_DEBUG,'- Moving cursor to y:'+y+', x:'+x);
|
||||||
|
|
||||||
|
// @todo This could be optimised to go the shortest route
|
||||||
|
write_raw(VIEWDATA_HOME);
|
||||||
|
|
||||||
|
if (x > 0)
|
||||||
|
write_raw(VIEWDATA_RIGHT.repeat(x));
|
||||||
|
|
||||||
|
if (y > 0)
|
||||||
|
write_raw(VIEWDATA_DOWN.repeat(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.strlen = function(str) {
|
||||||
|
return str.replace(/\x1b/g,'').length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Render the frame to the user
|
||||||
|
this.render=function(withHeader) {
|
||||||
|
log(LOG_DEBUG,'- VIEWDATA FRAME');
|
||||||
|
owner = base64_decode(this.owner);
|
||||||
|
|
||||||
|
header = VIEWDATA_DOWN;
|
||||||
|
|
||||||
|
//log(LOG_DEBUG,' - FRAME User: ['+JSON.stringify(user)+']');
|
||||||
|
|
||||||
|
// Dont show the page number on system login page
|
||||||
|
if (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1)) {
|
||||||
|
log(LOG_DEBUG,' - Owner: ['+this.pageowner+'] ('+this.strlen(videotex(this.pageownerlogo))+')');
|
||||||
|
|
||||||
|
cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -');
|
||||||
|
|
||||||
|
header = videotex(this.pageownerlogo)+' '.repeat(this.settings.FRAME_HEADER-this.strlen(videotex(this.pageownerlogo)))+
|
||||||
|
(this.isAccessible ? ascii(27)+'G' : ascii(27)+'A')+this.page+' '.repeat(this.settings.FRAME_PAGENUM-this.page.length)+
|
||||||
|
ascii(27)+'B'+' '.repeat(this.settings.FRAME_COST-cost.toString().length+1)+cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.status |= CON_RAW_IN;
|
||||||
|
write_raw(VIEWDATA_CLS);
|
||||||
|
write_raw(header);
|
||||||
|
return write_raw(videotex(base64_decode(this.content)));
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.qrcode = function(qr) {
|
||||||
|
// Render the body
|
||||||
|
var qrcode = VIEWDATA_HOME+VIEWDATA_DOWN.repeat(5);
|
||||||
|
var offset = this.settings.FRAME_WIDTH-Math.ceil(qr.size/2)-1;
|
||||||
|
|
||||||
|
for (var x = -1; x < qr.size; x=x+3) {
|
||||||
|
var line = VIEWDATA_RIGHT.repeat(offset ? offset-1 : 0)+ESC+VIEWDATA_MOSIAC_WHITE;
|
||||||
|
|
||||||
|
for (var y = -1; y < qr.size; y=y+2) {
|
||||||
|
var char = 0;
|
||||||
|
|
||||||
|
//TL
|
||||||
|
char |= ((x===-1) || (y===-1) || ! qr.getModule(x,y)) ? (1<<0) : (0<<0);
|
||||||
|
//TR
|
||||||
|
char |= ((x===-1) || (y === qr.size-1) || ! qr.getModule(x,y+1)) ? (1<<1) : (0<<1);
|
||||||
|
//ML
|
||||||
|
char |= ((y===-1) || ! qr.getModule(x+1,y)) ? (1<<2) : (0<<2);
|
||||||
|
//MR
|
||||||
|
char |= ((y === qr.size-1) || ! qr.getModule(x+1,y+1)) ? (1<<3) : (0<<3);
|
||||||
|
//BL
|
||||||
|
char |= ((x===qr.size-2) || (y===-1) || ! qr.getModule(x+2,y)) ? (1<<4) : (0<<4);
|
||||||
|
//BR
|
||||||
|
char |= ((x===qr.size-2) || (y === qr.size-1) || ! qr.getModule(x+2,y+1)) ? (1<<5) : (0<<5);
|
||||||
|
|
||||||
|
char += 0x20;
|
||||||
|
if (char > 0x3f)
|
||||||
|
char += 0x20;
|
||||||
|
|
||||||
|
line += ascii(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the right column
|
||||||
|
if (y%2)
|
||||||
|
line += '\x35';
|
||||||
|
|
||||||
|
repeat_count = this.settings.FRAME_WIDTH-Math.ceil(qr.size/2)-offset-(offset ? 1 : 2)-(y%2 === 1 ? 0 : 1);
|
||||||
|
|
||||||
|
qrcode += line+' '.repeat(repeat_count > 0 ? repeat_count : 0);
|
||||||
|
|
||||||
|
// To fix some terminals where moving right from col 40 doesnt advance to col 1 on the next line
|
||||||
|
qrcode +=VIEWDATA_LEFT+VIEWDATA_CR+VIEWDATA_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'WIDTH:'+this.settings.FRAME_WIDTH);
|
||||||
|
log(LOG_DEBUG,'QR :'+(Math.ceil(qr.size/2)+1));
|
||||||
|
log(LOG_DEBUG,'OFF :'+offset);
|
||||||
|
log(LOG_DEBUG,'Y :'+(y%2 ? 0 : 1));
|
||||||
|
log(LOG_DEBUG,'X :'+(x%3 ? 0 : 1));
|
||||||
|
|
||||||
|
// Render the bottom
|
||||||
|
if (x%3) {
|
||||||
|
line = VIEWDATA_RIGHT.repeat(offset ? offset-1 : 0)+ESC+VIEWDATA_MOSIAC_WHITE;
|
||||||
|
|
||||||
|
for (var y = 0; y < qr.size; y=y+2) {
|
||||||
|
line += '\x23';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the right column
|
||||||
|
if (y%2 === 0) {
|
||||||
|
line += '\x21';
|
||||||
|
}
|
||||||
|
|
||||||
|
qrcode += line+' '.repeat(repeat_count > 0 ? repeat_count : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_raw(qrcode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
this.save=function() {
|
||||||
|
file = system.mods_dir+'ansitex/text/'+this.page+'.tex';
|
||||||
|
w = new File(file);
|
||||||
|
if (! w.open('w')) {
|
||||||
|
log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+this.page);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.write(JSON.stringify(this));
|
||||||
|
w.close();
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'Saved file: '+this.page+'.tex');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
function videotex(data) {
|
||||||
|
var output = '';
|
||||||
|
//$output .= ($byte < 32) ? ESC.chr($byte+64) : chr($byte);
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
output += (data.charCodeAt(i) < 32) ? "\x1b"+String.fromCharCode(data.charCodeAt(i)+64) : String.fromCharCode(data.charCodeAt(i));
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionViewdata.prototype = Session.prototype;
|
||||||
|
SessionViewdata.prototype.constructor = SessionViewdata;
|
252
load/session.js
Normal file
252
load/session.js
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/**
|
||||||
|
* This handles session specific aspects of each frame type, eg: sending to the baseline, clearing, accepting
|
||||||
|
* input, moving around the frame (and windows within one if any)
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function Session() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Our page object
|
||||||
|
this.page = undefined;
|
||||||
|
|
||||||
|
/* Frame type settings */
|
||||||
|
this.settings = {};
|
||||||
|
|
||||||
|
/* Frame Version */
|
||||||
|
this.version = 1;
|
||||||
|
|
||||||
|
/* Frame Number [0-9] */
|
||||||
|
this.frame = null;
|
||||||
|
|
||||||
|
/* Frame Index [a-z] */
|
||||||
|
this.index = null;
|
||||||
|
|
||||||
|
/* The Service Provider owning the frame. */
|
||||||
|
this.owner = 0;
|
||||||
|
|
||||||
|
/* The cost to view the frame @todo to implement */
|
||||||
|
this.cost = 0;
|
||||||
|
|
||||||
|
/* The frame content, base64 encoded */
|
||||||
|
this.content = '';
|
||||||
|
|
||||||
|
// Frame's owned by the system where:
|
||||||
|
// isPublic is FALSE - the user must be logged in to view it
|
||||||
|
// isPublic is TRUE - can be viewed by non-logged in users
|
||||||
|
|
||||||
|
// Frame's owned by Service Providers where:
|
||||||
|
// isPublic is FALSE - can only be viewed if a user is
|
||||||
|
// a member of the Service Providers CUG
|
||||||
|
// isPublic is TRUE - can be viewed by users (if logged in)
|
||||||
|
|
||||||
|
this.isPublic = false; // Is this frame accessible to non CUG users
|
||||||
|
// If FALSE user must be a member of the CUG to view the frame
|
||||||
|
// All users, including unauthenticated, are members of 'system' (owner = 0)
|
||||||
|
this.isAccessible = false; // Is this frame available to be accessed
|
||||||
|
// If FALSE, only the SP can view/edit the frame
|
||||||
|
|
||||||
|
this.type = FRAME_TYPE_INFO; // The frame type - see FRAME_TYPES above
|
||||||
|
this.key = [null,null,null,null,null,null,null,null,null,null]; // Key actions [0-9]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the frames fields
|
||||||
|
*/
|
||||||
|
Object.defineProperty(this,'fields', {
|
||||||
|
get: function() {
|
||||||
|
return this.frame_fields;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user is already a member of the CUG
|
||||||
|
*/
|
||||||
|
Object.defineProperty(this,'isMember',{
|
||||||
|
get: function() {
|
||||||
|
log(LOG_DEBUG,'- Checking if user is a member of frame: '+this.page);
|
||||||
|
|
||||||
|
if (user.number) {
|
||||||
|
return (
|
||||||
|
(this.pageowner === SYSTEM_OWNER)
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.defineProperty(this,'pageownerlogo', {
|
||||||
|
get: function() {
|
||||||
|
return base64_decode(this.settings.ext === 'tex' ? pageOwner(this.frame).logoans : pageOwner(this.frame).logovtx);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable pulling out submitted value by its name
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @returns {null|string|*}
|
||||||
|
*/
|
||||||
|
this.fieldValue = function(key) {
|
||||||
|
for each (var k in this.frame_fields) {
|
||||||
|
log(LOG_DEBUG,' - k:'+JSON.stringify(k));
|
||||||
|
|
||||||
|
if (k.fname === key) {
|
||||||
|
return k.fvalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get = function(page) {
|
||||||
|
if (!(page instanceof PageObject))
|
||||||
|
throw new Error('page must be a PageObject');
|
||||||
|
|
||||||
|
switch (this.settings.ext) {
|
||||||
|
case 'tex':
|
||||||
|
case 'vtx':
|
||||||
|
this.page = new Page(this.settings.ext);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(this.settings.ext+' has not been implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.baselineSend('LOADING');
|
||||||
|
this.page.get(page,this.settings.ext);
|
||||||
|
this.baselineClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a message frame
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
*/
|
||||||
|
this.loadMessage = function(page) {
|
||||||
|
this.frame = ''+page;
|
||||||
|
this.index = 'a';
|
||||||
|
this.owner = 1;
|
||||||
|
this.isPublic = true;
|
||||||
|
this.isAccessible = true;
|
||||||
|
// @todo Keys should map to next/previous/send, etc as indicated in the template frame.
|
||||||
|
this.key = [this.frame.substr(0,7)+'1',null,null,null,null,null,null,null,null,null];
|
||||||
|
// @todo validate that FRAME_TYPE_MESSAGE is a message template
|
||||||
|
this.type = FRAME_TYPE_MESSAGE;
|
||||||
|
|
||||||
|
// Load our message
|
||||||
|
var ma = new MsgAreas()
|
||||||
|
var area = ma.getArea(this.frame);
|
||||||
|
var msg = ma.getMessage(this.frame);
|
||||||
|
var msg_header;
|
||||||
|
|
||||||
|
if (! msg)
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
// @todo Search 1zzzzEE..., 1zzzz...
|
||||||
|
var to = viewdata ? new FrameViewdata() : new FrameAnsi();
|
||||||
|
to.load(MAIL_TEMPLATE_FRAME);
|
||||||
|
// @todo Check that this is a frame of type "m" and report error if not
|
||||||
|
// @todo Take the cost from the template
|
||||||
|
this.cost = 5;
|
||||||
|
|
||||||
|
if (! to) {
|
||||||
|
log(LOG_ERROR,'Echomail template missing :['+MAIL_TEMPLATE_FRAME+'] ?');
|
||||||
|
msg_header = 'TO: '+msg.to.substr(0,72)+"\n\r";
|
||||||
|
msg_header += 'FROM: '+msg.from.substr(0,72)+"\n\r";
|
||||||
|
msg_header += 'DATE: '+msg.date.substr(0,72)+"\n\r";
|
||||||
|
msg_header += 'SUBJECT: '+msg.subject.substr(0,72)+"\n\r";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// @todo change this to use atcode()
|
||||||
|
msg_header = base64_decode(to.content).replace(/@(.*)@/g,
|
||||||
|
function (str, code, offset, s) {
|
||||||
|
var length = code.split(':')[1];
|
||||||
|
switch(code.split(':')[0]) {
|
||||||
|
case 'DATE': return msg.date.substr(0,length);
|
||||||
|
case 'TO': return msg.to.substr(0,length);
|
||||||
|
case 'FROM': return msg.from.substr(0,length);
|
||||||
|
case 'SUBJECT': return msg.subject.substr(0,length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//log(LOG_DEBUG,'Loaded message: '+msg_header+msg.content);
|
||||||
|
this.content = base64_encode(msg_header+msg.content);
|
||||||
|
|
||||||
|
// Update the user's pointers
|
||||||
|
var stats = ma.getUserStats(this.frame);
|
||||||
|
|
||||||
|
// if this message is to the user, and the msg number > scan_ptr and it is the next message on the user's new mail list
|
||||||
|
var newmsgs = area.newMsgsToMe();
|
||||||
|
var next;
|
||||||
|
log(LOG_DEBUG,'User has: '+newmsgs.length-1+' msgs to read to ME');
|
||||||
|
if (newmsgs.length) {
|
||||||
|
next = newmsgs[1];
|
||||||
|
//log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags);
|
||||||
|
|
||||||
|
if (next && (next.tags === msg.tags)) {
|
||||||
|
log(LOG_DEBUG,'- Updating scan_ptr to: '+next.number);
|
||||||
|
stats.scan_ptr = next.number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last message
|
||||||
|
next = newmsgs[0];
|
||||||
|
if (next !== undefined) {
|
||||||
|
log(LOG_DEBUG,'- LAST TO ME is: '+next.tags);
|
||||||
|
this.key[1] = area.page(next.tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next new message
|
||||||
|
next = newmsgs[2];
|
||||||
|
if (next !== undefined) {
|
||||||
|
log(LOG_DEBUG,'- NEXT TO ME is: '+next.tags);
|
||||||
|
this.key[2] = area.page(next.tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this message is the next message, update last_read
|
||||||
|
newmsgs = area.newMsgs();
|
||||||
|
log(LOG_DEBUG,'User has: '+newmsgs.length+' msgs to read');
|
||||||
|
if (newmsgs.length) {
|
||||||
|
next = newmsgs[0];
|
||||||
|
log(LOG_DEBUG,'- NEXT is: '+next.tags+', this is: '+msg.tags);
|
||||||
|
|
||||||
|
if (next.tags === msg.tags) {
|
||||||
|
log(LOG_DEBUG,'- Updating last_read to: '+next.number);
|
||||||
|
stats.last_read = next.number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Previous Message
|
||||||
|
x = area.MessagePrev(this.frame);
|
||||||
|
if (x)
|
||||||
|
this.key[4] = area.page(x.tags);
|
||||||
|
|
||||||
|
// Next Message
|
||||||
|
x = area.MessageNext(this.frame);
|
||||||
|
if (x)
|
||||||
|
this.key[6] = area.page(x.tags);
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'Built frame: ['+this.frame+']['+this.index+'] ('+this.page+')');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the page
|
||||||
|
this.render = function() {
|
||||||
|
this.gotoxy(0,0);
|
||||||
|
write(so.page.display().join(''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the message for a index
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @returns {string|*}
|
||||||
|
*/
|
||||||
|
Session.prototype.getMessage = function(index) {
|
||||||
|
eval('var msg = this.settings.'+index);
|
||||||
|
return msg;
|
||||||
|
}
|
991
load/windows.js
Normal file
991
load/windows.js
Normal file
@ -0,0 +1,991 @@
|
|||||||
|
/**
|
||||||
|
* Windows are elements of a Page object
|
||||||
|
*
|
||||||
|
* @param x - (int) starting x of it's parent [1..]
|
||||||
|
* @param y - (int) starting y of it's parent [1..]
|
||||||
|
* @param width - (int) full width of the window (text content will be smaller if there are scroll bars/boarder)
|
||||||
|
* @param height - (int) full height of the window (text content will be smaller if there are scroll bars/boarder)
|
||||||
|
* @param name - (string) internal name for the window (useful for debugging)
|
||||||
|
* @param parent - (object) parent of this window
|
||||||
|
* @param debug - (int) debug mode, which fills the window with debug content
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* Pages have the following attributes:
|
||||||
|
* - bx/by - (int) right/bottom most boundary of the window representing the start + width/height of the window
|
||||||
|
* - child - (array) children in this window
|
||||||
|
* - height - (int) Window's height
|
||||||
|
* - name - (string) Windows name (useful for internal debugging)
|
||||||
|
* - parent - (object) Parent that this window belongs to
|
||||||
|
* - x/y - (int) start position of the window
|
||||||
|
* - visible - (bool) whether this window is visible
|
||||||
|
* - width - (int) Window's width
|
||||||
|
* - z - (int) Window's depth indicator
|
||||||
|
*
|
||||||
|
* Windows have the following public functions
|
||||||
|
* - build - Compile the frame for rendering
|
||||||
|
* - debug - Useful for debugging with properties of this Window
|
||||||
|
* - draw - Draw a part of this Window
|
||||||
|
* - drawline - Draw a y line for this Window
|
||||||
|
* - visibleChildren - Children that will be included when this window is rendered
|
||||||
|
*/
|
||||||
|
function Window(x,y,width,height,name,parent,debug) {
|
||||||
|
this.__properties__ = {
|
||||||
|
x: undefined, // X offset of parent that the canvas starts [1..width]
|
||||||
|
y: undefined, // Y offset of parent that the canvas starts [1..height]
|
||||||
|
z: 0, // Window top-bottom position, higher z is shown [0..]
|
||||||
|
ox: 0, // When canvas width > width, this is the offset we display [0..]
|
||||||
|
oy: 0, // When canvas height > height, this is the offset we display [0..]
|
||||||
|
width: undefined, // Display Width + (1 char if scrollbars = true)
|
||||||
|
height: undefined, // Display Height
|
||||||
|
canvaswidth: undefined, // Width of Canvas (default display width)
|
||||||
|
canvasheight: undefined, // Height of Canvas (default display height)
|
||||||
|
content: [], // Window content - starting at 0,0 = 1,1
|
||||||
|
visible: true, // Is this window visible
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
this.__settings__ = {
|
||||||
|
checkbounds: true, // Can this frame move outside of the parent
|
||||||
|
v_scroll: true, // Can the content scroll vertically (takes up 1 line) [AUTO DETERMINE IF canvas > width]
|
||||||
|
h_scroll: false, // Can the content scroll horizontally (takes up 1 char) [AUTO DETERMINE IF canvas > height]
|
||||||
|
delay: 0, // Delay while rendering
|
||||||
|
word_wrap: false, // Word wrap content
|
||||||
|
pageable: false, // Overflowed content is rendered with the next page
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.__relations__ = {
|
||||||
|
parent: undefined,
|
||||||
|
child: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
this.__position__ = {
|
||||||
|
cursor: undefined,
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Validation to implement:
|
||||||
|
+ X BOUNDARY
|
||||||
|
- x cannot be < parent.x if checkbounds is true [when moving window]
|
||||||
|
- x+width(-1 if h_scroll is true) cannot be greater than parent.width if checkbounds is true
|
||||||
|
- v_scroll must be true for canvaswidth > width
|
||||||
|
- when scrolling ox cannot be > width-x
|
||||||
|
- when layout.pageable is true, next page will only have windows included that have a y in the range
|
||||||
|
ie: if height is 44 (window is 22), next page is 23-44 and will only include children where y=23-44
|
||||||
|
+ Y BOUNDARY
|
||||||
|
- y cannot be < parent.y if checkbounds is true [when moving window]
|
||||||
|
- y+height(-1 if v_scroll is true) cannot be greater than parent.height if checkbounds is true
|
||||||
|
- h_scroll must be true for canvasheight > height
|
||||||
|
- when scrolling oy cannot be > height-y
|
||||||
|
- when layout.pageable is true, children height cannot be greater than parent.height - y.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function init(x,y,width,height,name,parent,debug) {
|
||||||
|
if (parent instanceof Window) {
|
||||||
|
this.z = parent.__relations__.child.length+1;
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
parent.child = this;
|
||||||
|
|
||||||
|
// Check that our height/widths is not outside of our parent
|
||||||
|
if ((this.x < 1) || (width > this.parent.width))
|
||||||
|
throw new Error('Window: '+name+' width ['+width+'] is beyond our parent\'s width ['+this.parent.width+'].');
|
||||||
|
if ((x > this.parent.bx) || (x+width-1 > this.parent.bx))
|
||||||
|
throw new Error('Window: '+name+' start x ['+x+'] and width ['+width+'] is beyond our parent\'s end x ['+this.parent.bx+'].');
|
||||||
|
|
||||||
|
if ((this.y < 1) || (height > this.parent.height))
|
||||||
|
throw new Error('Window: '+name+' height ['+height+'] is beyond our parent\'s height ['+this.parent.height+'].');
|
||||||
|
if ((y > this.parent.by) || (y+height-1 > this.parent.by))
|
||||||
|
throw new Error('Window: '+name+' start y ['+y+'] and height ['+height+'] is beyond our parent\'s end y ['+this.parent.by+'].');
|
||||||
|
|
||||||
|
} else if (parent instanceof Page) {
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error('INVALID Parent Type: '+parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.__properties__.width = this.__properties__.canvaswidth = width;
|
||||||
|
this.__properties__.height = this.__properties__.canvasheight = height;
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
this.__properties__.canvaswidth = width*2;
|
||||||
|
this.__properties__.canvasheight = height*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill with data
|
||||||
|
for(var y=1;y<=this.__properties__.canvasheight;y++) {
|
||||||
|
for(var x=1;x<=this.__properties__.canvaswidth;x++) {
|
||||||
|
if (this.__properties__.content[y] == undefined)
|
||||||
|
this.__properties__.content[y] = [];
|
||||||
|
|
||||||
|
this.__properties__.content[y][x] = debug
|
||||||
|
? new Char((x > this.width) || (y > this.height) ? this.name[0].toUpperCase() : this.name[0].toLowerCase(),undefined)
|
||||||
|
: new Char(undefined,undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init.apply(this,arguments);
|
||||||
|
|
||||||
|
// Windows boundary (right most width) of parent [1..]
|
||||||
|
Window.prototype.__defineGetter__('bx',function() {
|
||||||
|
return this.x+this.width-1;
|
||||||
|
});
|
||||||
|
// Windows boundary (bottom most height) of parent [1..]
|
||||||
|
Window.prototype.__defineGetter__('by',function() {
|
||||||
|
return this.y+this.height-1;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Can this window be moved outside of the parents visible area
|
||||||
|
Window.prototype.__defineGetter__('checkbounds',function() {
|
||||||
|
return this.__settings__.checkbounds;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('checkbounds',function(bool) {
|
||||||
|
this.__settings__.checkbounds = bool;
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Management of children objects, in highest z order
|
||||||
|
Window.prototype.__defineGetter__('child',function() {
|
||||||
|
// Return the children sorted in z order lowest to highest
|
||||||
|
return this.__relations__.child.sort(function(a,b) { return (a.z < b.z) ? -1 : ((b.z < a.z) ? 1 : 0); });
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('child',function(obj) {
|
||||||
|
if(obj instanceof Window) {
|
||||||
|
this.__relations__.child.push(obj);
|
||||||
|
|
||||||
|
} else
|
||||||
|
throw new Error('child not an instance of Window()');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Window name
|
||||||
|
Window.prototype.__defineGetter__('name',function() {
|
||||||
|
return this.__properties__.name;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('name',function(string) {
|
||||||
|
if (this.__properties__.name)
|
||||||
|
throw new Error('name already DEFINED');
|
||||||
|
|
||||||
|
return this.__properties__.name = string;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Parent window object
|
||||||
|
Window.prototype.__defineGetter__('parent',function() {
|
||||||
|
return this.__relations__.parent;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('parent',function(obj) {
|
||||||
|
if (this.__relations__.parent)
|
||||||
|
throw new Error('parent already DEFINED');
|
||||||
|
|
||||||
|
return this.__relations__.parent = obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Window's display height
|
||||||
|
Window.prototype.__defineGetter__('height',function() {
|
||||||
|
return this.__properties__.height;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('height',function(int) {
|
||||||
|
if (this.__properties__.height)
|
||||||
|
throw new Error('height already DEFINED');
|
||||||
|
|
||||||
|
this.__properties__.height = int;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Window's display width
|
||||||
|
Window.prototype.__defineGetter__('width',function() {
|
||||||
|
return this.__properties__.width;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('width',function(int) {
|
||||||
|
if (this.__properties__.width)
|
||||||
|
throw new Error('width already DEFINED');
|
||||||
|
|
||||||
|
this.__properties__.width = int;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Window's start position on it's parent (width)
|
||||||
|
Window.prototype.__defineGetter__('x',function() {
|
||||||
|
return this.__properties__.x;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('x',function(int) {
|
||||||
|
if (this.__properties__.x)
|
||||||
|
throw new Error('x already DEFINED');
|
||||||
|
|
||||||
|
this.__properties__.x = int;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Window's start position on it's parent (height)
|
||||||
|
Window.prototype.__defineGetter__('y',function() {
|
||||||
|
return this.__properties__.y;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineSetter__('y',function(int) {
|
||||||
|
if (this.__properties__.y)
|
||||||
|
throw new Error('y already DEFINED');
|
||||||
|
|
||||||
|
this.__properties__.y = int;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Is the current window visible
|
||||||
|
Window.prototype.__defineGetter__('visible',function() {
|
||||||
|
return this.__properties__.visible;
|
||||||
|
});
|
||||||
|
|
||||||
|
// What position is this window (highest is visible)
|
||||||
|
Window.prototype.__defineSetter__('z',function(int) {
|
||||||
|
if (this.__properties__.z)
|
||||||
|
throw new Error('z already DEFINED');
|
||||||
|
|
||||||
|
this.__properties__.z = int;
|
||||||
|
});
|
||||||
|
Window.prototype.__defineGetter__('z',function() {
|
||||||
|
return this.__properties__.z;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build this window, returning an array of Char that will be rendered by Page
|
||||||
|
*
|
||||||
|
* @param xoffset - (int) This windows x position for its parent
|
||||||
|
* @param yoffset - (int) This windows y position for its parent
|
||||||
|
* @param debug - (int) debug mode, which fills the window with debug content
|
||||||
|
* @returns {*[]}
|
||||||
|
*/
|
||||||
|
Window.prototype.build = function(xoffset,yoffset,debug) {
|
||||||
|
var display = [];
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
writeln('********* ['+this.name+'] *********');
|
||||||
|
writeln('name :'+this.name);
|
||||||
|
writeln('xoff :'+xoffset);
|
||||||
|
writeln('yoff :'+yoffset);
|
||||||
|
writeln('x :'+this.x);
|
||||||
|
writeln('bx :'+this.bx)
|
||||||
|
writeln('ox :'+this.__properties__.ox);
|
||||||
|
writeln('y :'+this.y);
|
||||||
|
writeln('by :'+this.by)
|
||||||
|
writeln('oy :'+this.__properties__.oy);
|
||||||
|
writeln('lines :'+this.__properties__.content.length);
|
||||||
|
writeln('content:'+JSON.stringify(Object.keys(this.__properties__.content).join(',')));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
writeln('-------------');
|
||||||
|
|
||||||
|
for (y=1;y<=this.height;y++) {
|
||||||
|
if (debug)
|
||||||
|
write(padright(y,2,0)+':');
|
||||||
|
|
||||||
|
var sy = this.y-1+y+yoffset-1;
|
||||||
|
|
||||||
|
for (x=1;x<=this.width;x++) {
|
||||||
|
if (debug)
|
||||||
|
writeln('- Checking :'+this.name+', y:'+(y+this.__properties__.oy)+', x:'+(x+this.__properties__.ox));
|
||||||
|
|
||||||
|
var sx = this.x-1+x+xoffset-1;
|
||||||
|
if (display[sy] === undefined)
|
||||||
|
display[sy] = [];
|
||||||
|
|
||||||
|
if ((this.__properties__.content[y+this.__properties__.oy] !== undefined) && (this.__properties__.content[y+this.__properties__.oy][x+this.__properties__.ox] !== undefined)) {
|
||||||
|
display[sy][sx] = this.__properties__.content[y+this.__properties__.oy][x+this.__properties__.ox];
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
writeln('- storing in y:'+(sy)+', x:'+(sx)+', ch:'+display[sy][sx].ch);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//display[sy][sx] = new Char(null,BG_BLACK|LIGHTGRAY);
|
||||||
|
display[sy][sx] = new Char();
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
writeln('- nothing for y:'+(sy)+', x:'+(sx)+', ch:'+display[sy][sx].ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
writeln('Window:'+this.name+', has ['+this.child.filter(function(child) { return child.visible; }).length+'] children');
|
||||||
|
this.child.forEach(function(child) {
|
||||||
|
writeln(' - child:'+child.name+', visible:'+child.visible);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the array with our values
|
||||||
|
var that = this;
|
||||||
|
this.child.filter(function(child) { return child.visible; }).forEach(function(child) {
|
||||||
|
if (debug) {
|
||||||
|
writeln('=========== ['+child.name+'] =============');
|
||||||
|
writeln('xoff :'+xoffset);
|
||||||
|
writeln('yoff :'+yoffset);
|
||||||
|
writeln('this.x :'+that.x);
|
||||||
|
writeln('this.y :'+that.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw = child.build(that.x+xoffset-1,that.y+yoffset-1,debug);
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
writeln('draw y:'+JSON.stringify(Object.keys(draw).join(',')));
|
||||||
|
writeln('draw 1:'+JSON.stringify(Object.keys(draw[1]).join(',')));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var y in draw)
|
||||||
|
for (var x in draw[y]) {
|
||||||
|
if (display[y] === undefined)
|
||||||
|
display[y] = [];
|
||||||
|
|
||||||
|
display[y][x] = draw[y][x];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
writeln('draw 1:'+JSON.stringify(Object.keys(draw[1]).join(',')));
|
||||||
|
writeln('=========== END ['+child.name+'] =============')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
writeln('this.name:'+this.name);
|
||||||
|
writeln('this.y:'+this.y);
|
||||||
|
writeln('display now:'+Object.keys(display[this.y]).join(','));
|
||||||
|
writeln('********* END ['+this.name+'] *********');
|
||||||
|
}
|
||||||
|
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window.prototype.debug = function(text) {
|
||||||
|
return '- '+text+': '+this.name+'('+this.x+'->'+(this.bx)+') width:'+this.width+' ['+this.y+'=>'+this.by+'] with z:'+this.z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render this window
|
||||||
|
*
|
||||||
|
* @param start - (int) Starting x position
|
||||||
|
* @param end - (int) Ending x position
|
||||||
|
* @param y - (int) Line to render
|
||||||
|
* @param color - (bool) Whether to include color
|
||||||
|
* @returns {{x: number, content: string}}
|
||||||
|
*/
|
||||||
|
Window.prototype.draw = function(start,end,y,color) {
|
||||||
|
var content = '';
|
||||||
|
|
||||||
|
for (x=start;x<=end;x++) {
|
||||||
|
var rx = this.__properties__.ox+x;
|
||||||
|
var ry = this.__properties__.oy+y;
|
||||||
|
|
||||||
|
// Check if we have an attribute to draw
|
||||||
|
if (! (ry in this.__properties__.content) || ! (rx in this.__properties__.content[ry])) {
|
||||||
|
content += ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color === undefined || color === true) {
|
||||||
|
// Only write a new attribute if it has changed
|
||||||
|
if ((this.last === undefined) || (this.last !== this.__properties__.content[ry][rx].attr)) {
|
||||||
|
this.last = this.__properties__.content[ry][rx].attr;
|
||||||
|
|
||||||
|
content += (this.last === null ? BG_BLACK|LIGHTGRAY : this.last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
content += (this.__properties__.content[ry][rx].ch !== null ? this.__properties__.content[ry][rx].ch : ' ');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
writeln(e);
|
||||||
|
writeln('---');
|
||||||
|
writeln('x:'+(x-this.x));
|
||||||
|
writeln('y:'+(y-this.y));
|
||||||
|
writeln('ox:'+this.__properties__.ox);
|
||||||
|
writeln('oy:'+this.__properties__.oy);
|
||||||
|
writeln('rx:'+rx);
|
||||||
|
writeln('ry:'+ry);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { content: content, x: end - start + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DRAW a line for this Window
|
||||||
|
*
|
||||||
|
* @param startx - the start position to render this window [1..]
|
||||||
|
* @param endx - the stop position to stop rendinering this window [1..]
|
||||||
|
* @param y - the current windows line number [1..]
|
||||||
|
* @param color - output color
|
||||||
|
* @param debug - turn on debugging
|
||||||
|
*
|
||||||
|
* Other Attributes:
|
||||||
|
* @param x - Our current X position
|
||||||
|
*
|
||||||
|
* When rendering, for each children on a y axis, the one with a character in x and the highest z wins.
|
||||||
|
*
|
||||||
|
* = Thus, if there is only 1 child on a y line, we render that child.width, with optional padding on the left/right.
|
||||||
|
*
|
||||||
|
* = If there are more children:
|
||||||
|
* + build an array of each childs x starting position sorted by z (asc).
|
||||||
|
* + if we need, we pad until the first child to rendered
|
||||||
|
* + after the child is rendered, we pad on the right if it didnt render to window.width
|
||||||
|
*
|
||||||
|
* + we render the a.x -> a.bx, unless there are other children with a higher z and it's x < a.bx
|
||||||
|
* + "x" keeps track of where we are
|
||||||
|
* + repeat until all children are processed, repeating from the begining again if necessary where children with a lower z have a wider width
|
||||||
|
*/
|
||||||
|
Window.prototype.drawline = function(startx,endx,y,color,debug) {
|
||||||
|
// Some sanity checking
|
||||||
|
if (startx < 1)
|
||||||
|
throw new Error('Nope, startx < 1:'+startx);
|
||||||
|
if (endx < startx)
|
||||||
|
throw new Error('Nope, endx:'+endx+' < startx:'+startx);
|
||||||
|
if (y < 1)
|
||||||
|
throw new Error('Nope, y < 1:'+y);
|
||||||
|
|
||||||
|
// Advance x if required
|
||||||
|
var x = startx;
|
||||||
|
|
||||||
|
// Get any of our children
|
||||||
|
var children = this.visibleChildren();
|
||||||
|
|
||||||
|
// Find children with something on this line.
|
||||||
|
var that = this;
|
||||||
|
var kids = children.filter(function(child) {
|
||||||
|
return (y-that.y+1 >= child.y) && (y-that.y+1 <= child.by) && (child.x < endx) && (child.bx > startx);
|
||||||
|
});
|
||||||
|
|
||||||
|
var draw;
|
||||||
|
var content = '';
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln()
|
||||||
|
writeln('********* drawline for ['+this.name+'] ***********');
|
||||||
|
writeln('* chars :'+startx+'->'+endx);
|
||||||
|
writeln('* line :'+y);
|
||||||
|
writeln('* parents start line :'+(this.parent.y !== undefined ? this.parent.y : '-no parent-'));
|
||||||
|
writeln(this.debug('drawline'));
|
||||||
|
|
||||||
|
writeln('* we have children :'+children.length);
|
||||||
|
|
||||||
|
children.forEach(function(child) {
|
||||||
|
if (y > debug) writeln(child.debug('CHILD'));
|
||||||
|
})
|
||||||
|
|
||||||
|
writeln('* relevant :'+kids.length);
|
||||||
|
kids.forEach(function(child) {
|
||||||
|
writeln(child.debug('KID'));
|
||||||
|
})
|
||||||
|
|
||||||
|
writeln('*************************************'+'*'.repeat(this.name.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
var child = null;
|
||||||
|
|
||||||
|
// Only 1 child, so we render the line with it
|
||||||
|
if (kids.length === 1) {
|
||||||
|
child = kids.pop();
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln(': Only 1 child :'+child.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.x > x) {
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln(': Padding until :'+x+'->'+(endx < child.x-1 ? endx : child.x-1)+' on:'+(y-this.y+1)+' with:'+this.name);
|
||||||
|
writeln(': Padded :'+((endx < child.x-1 ? endx : child.x-1)-x));
|
||||||
|
}
|
||||||
|
|
||||||
|
draw = this.draw(x,endx < child.x-1 ? endx : child.x-1,y-this.y+1,color);
|
||||||
|
content += draw.content;
|
||||||
|
x += draw.x;
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln(child.debug('THIS'));
|
||||||
|
writeln(': x :'+x);
|
||||||
|
writeln(': endx :'+endx);
|
||||||
|
writeln(': size of child :'+(child.bx-child.x+1));
|
||||||
|
writeln(': draw :'+(x-child.x+1)+'->'+((endx-startx+1 < child.width ? endx : child.bx)-child.x+1)+' on:'+(y-this.y+1))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < endx) {
|
||||||
|
draw = child.drawline(x-child.x+1,(endx < child.bx ? endx : child.bx)-child.x+1,y-this.y+1,color,(debug !== false ? debug-this.y+1 : debug));
|
||||||
|
content += draw.content;
|
||||||
|
x += draw.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) writeln();
|
||||||
|
|
||||||
|
} else if (kids.length !== 0) {
|
||||||
|
if (debug !== false && (y > debug)) writeln('| multiple children :'+kids.length);
|
||||||
|
|
||||||
|
// Sort the kids in x start order
|
||||||
|
kids = kids.sort(function(a,b) {
|
||||||
|
return (a.x < b.x) ? -1 : ((b.x < a.x) ? 1 : 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debug !== false)
|
||||||
|
kids.forEach(function(child) {
|
||||||
|
if (y > debug) writeln(child.debug('SORT'));
|
||||||
|
})
|
||||||
|
|
||||||
|
var c = 0; // Our kids index
|
||||||
|
var C = null; // If we need to come back and reprocess the list
|
||||||
|
|
||||||
|
while (c < kids.length) {
|
||||||
|
child = kids[c++];
|
||||||
|
var drawendx = endx;
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('| -------------- ['+child.name+'] -----------');
|
||||||
|
writeln('| x :'+x);
|
||||||
|
writeln('| child.x :'+child.x);
|
||||||
|
writeln('| child.bx:'+child.bx);
|
||||||
|
writeln('| startx :'+startx);
|
||||||
|
writeln(child.debug('CHILD'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this child cannot be rendered, skip it (because it is underneath another window)
|
||||||
|
if (x > child.bx) {
|
||||||
|
if (debug !== false && (y > debug)) writeln('| skipping:'+child.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad the beginning of this child
|
||||||
|
if (child.x > x) {
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('| Padding :'+x+'->'+(child.x-1)+' for: '+this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw = this.draw(x,child.x-1,y-this.y+1,color);
|
||||||
|
content += draw.content;
|
||||||
|
x += draw.x;
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// If this child cannot be rendered, skip it
|
||||||
|
if (x < child.x) {
|
||||||
|
if (debug !== false && (y > debug)) writeln('| skipping:'+child.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (kids[c] !== undefined) {
|
||||||
|
if (debug !== false && (y > debug)) writeln(kids[c].debug('AFTER'));
|
||||||
|
|
||||||
|
// If the next child has a higher z and the same x skip this one
|
||||||
|
if ((kids[c].x === x) && (kids[c].z > child.z)) {
|
||||||
|
if (debug !== false && (y > debug)) writeln('|- Skipping:'+child.name);
|
||||||
|
C = kids[c].x;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) writeln('| FILTERING: x le:'+x+' bx lt:'+(child.bx)+' and z gt:'+child.z);
|
||||||
|
var nextkid = kids.filter(function(kid) {
|
||||||
|
if (debug !== false && (y > debug)) writeln('| - EVAL: '+kid.name+': x:'+(kid.x)+' bx:'+(kid.bx)+' and z:'+kid.z);
|
||||||
|
return ((kid.bx > x+startx-1)) && (kid.x < child.bx) && (kid.z > child.z);
|
||||||
|
});
|
||||||
|
if (debug !== false && (y > debug)) writeln('| Got next children: '+nextkid.length);
|
||||||
|
|
||||||
|
if (debug !== false)
|
||||||
|
nextkid.forEach(function(child) {
|
||||||
|
if (y > debug) writeln(child.debug('NEXT'));
|
||||||
|
})
|
||||||
|
|
||||||
|
// If a next child who starts before we finish and has a higher z, we'll stop at that next child
|
||||||
|
if (nextkid.length) {
|
||||||
|
// If nextkid should already be showing, we'll skip to it
|
||||||
|
if (x > nextkid[0].x) {
|
||||||
|
C = nextkid[0].bx;
|
||||||
|
if (debug !== false && (y > debug)) writeln('| NEXTKID should have started, skipping to it:'+nextkid[0].x+' (C:'+C+')');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawendx = (endx-child.x+1 < nextkid[0].x-1 ? endx : nextkid[0].x-1);
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('| x :'+x);
|
||||||
|
writeln('| startx :'+startx);
|
||||||
|
writeln('| childx :'+child.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln(nextkid[0].debug('NEXTKID'));
|
||||||
|
writeln('| draw partial width of me:'+child.name+', drawendx:'+drawendx+' because nextkid starts:'+nextkid[0].name+' at:'+nextkid[0].x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If I need to continue after next kid, we'll come back
|
||||||
|
if ((! C) && (nextkid[0].bx < child.bx)) {
|
||||||
|
C = nextkid[0].bx;
|
||||||
|
if (debug !== false && (y > debug)) writeln('| coming back to:'+child.name+' at:'+C);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If C is set, we need to push it out.
|
||||||
|
if (C)
|
||||||
|
C = drawendx;
|
||||||
|
|
||||||
|
// No next children
|
||||||
|
} else {
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('| x :'+x);
|
||||||
|
writeln('| startx :'+startx);
|
||||||
|
writeln('| endx :'+endx);
|
||||||
|
writeln('| child :'+child.name);
|
||||||
|
writeln('| childx :'+child.x);
|
||||||
|
writeln('| childbx:'+child.bx);
|
||||||
|
writeln('| calcsta:'+(endx-child.x+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
drawendx = (endx-child.x+1 < child.bx ? x+child.width : child.bx);
|
||||||
|
if (debug !== false && (y > debug)) writeln('| draw full width of me:'+child.name+', from:'+(x-child.x+1)+' until:'+drawendx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No other children
|
||||||
|
} else {
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('| No other child');
|
||||||
|
writeln(child.debug('DRAW'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// If there is a gap, we'll need to pad it.
|
||||||
|
if (x < child.x) {
|
||||||
|
write(':'.repeat(xx=child.x-x));
|
||||||
|
x += xx;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
drawendx = (endx-child.x+1 < child.width ? endx : child.bx);
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('| will render:'+child.name+', from:'+(x-child.x+1)+'->'+(drawendx-child.x+1)+' on:'+(y-this.y+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < endx) {
|
||||||
|
draw = child.drawline(x-child.x+1,(x < endx ? drawendx : child.bx)-child.x+1,y-this.y+1,color,(debug !== false ? debug-this.y+1 : debug));
|
||||||
|
content += draw.content;
|
||||||
|
x += draw.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln();
|
||||||
|
writeln('| C :'+C);
|
||||||
|
writeln('| x :'+x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C && (x > C)) {
|
||||||
|
c = 0;
|
||||||
|
C = null;
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) writeln('! Resetting c back');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln('= x :'+x);
|
||||||
|
writeln('= startx :'+startx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad the beginning of this child
|
||||||
|
if (x < startx) {
|
||||||
|
if (debug !== false && (y > debug)) writeln('! Padding until:'+this.x);
|
||||||
|
write(' '.repeat(xx=this.x-startx));
|
||||||
|
x += xx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render our item
|
||||||
|
if (debug !== false && (y > debug)) writeln('= drawing:'+this.name+' ('+x+'->'+endx+')');
|
||||||
|
draw = this.draw(x,endx,y-this.y+1,color);
|
||||||
|
content += draw.content;
|
||||||
|
x += draw.x;
|
||||||
|
|
||||||
|
if (debug !== false && (y > debug)) {
|
||||||
|
writeln();
|
||||||
|
writeln('- DONE, x now :'+x+' (endx:'+endx+') for:'+this.name);
|
||||||
|
writeln('- DREW :'+(x-startx));
|
||||||
|
writeln('************** end for ['+this.name+'] ***********');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug !== false && y > debug+1) exit();
|
||||||
|
|
||||||
|
return { content: content, x: endx-startx+1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the visible children (child should have sort by z)
|
||||||
|
Window.prototype.visibleChildren = function() {
|
||||||
|
return this.child.filter(function(child) {
|
||||||
|
return child.visible;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each character in a window
|
||||||
|
*
|
||||||
|
* @todo Need to add a Viewdata implementation
|
||||||
|
* @param ch
|
||||||
|
* @param attr
|
||||||
|
* @param ext - tex = ANSItex, vtx = ViewDasta
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function Char(ch,attr) {
|
||||||
|
this.__properties__ = {
|
||||||
|
attr: attr, // - Attributes for the character (ie: color)
|
||||||
|
ch: ch, // - Character to be shown
|
||||||
|
//changed: false, // - Has this ch or attr been changed?
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the color codes required to draw the current character
|
||||||
|
*
|
||||||
|
* @todo Implement Viewdata
|
||||||
|
* @param last - last rendered char
|
||||||
|
* @param ext - service we are rendering for
|
||||||
|
* @param debug - debug mode
|
||||||
|
* @returns {string|undefined}
|
||||||
|
*/
|
||||||
|
Char.prototype.attr = function(last,ext,debug) {
|
||||||
|
// If our attr is undefined, we'll return
|
||||||
|
if (this.__properties__.attr === undefined)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// @todo This condition appears to fail?
|
||||||
|
if (this.__properties__.attr === null)
|
||||||
|
throw new Error('Attributes shouldnt be null');
|
||||||
|
|
||||||
|
var ansi = [];
|
||||||
|
var c;
|
||||||
|
var l;
|
||||||
|
var r = '';
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
writeln();
|
||||||
|
writeln('- last:'+last+', this:'+this.__properties__.attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ext) {
|
||||||
|
case 'tex':
|
||||||
|
if (debug) {
|
||||||
|
writeln(' - this BG_BLACK:'+(this.__properties__.attr & BG_BLACK));
|
||||||
|
writeln(' - last BG_BLACK:'+(last & BG_BLACK));
|
||||||
|
|
||||||
|
writeln(' - this HIGH:'+(this.__properties__.attr & HIGH));
|
||||||
|
writeln(' - last HIGH:'+(last & HIGH));
|
||||||
|
|
||||||
|
writeln(' - this BLINK:'+(this.__properties__.attr & BLINK));
|
||||||
|
writeln(' - last BLINK:'+(last & BLINK));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(((this.__properties__.attr & BG_BLACK) !== (last & BG_BLACK))
|
||||||
|
|| ((this.__properties__.attr & HIGH) !== (last & HIGH))
|
||||||
|
|| ((this.__properties__.attr & BLINK) !== (last & BLINK))))
|
||||||
|
{
|
||||||
|
ansi.push('0');
|
||||||
|
last = BG_BLACK|LIGHTGRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.__properties__.attr & HIGH) && ((this.__properties__.attr & HIGH) !== (last & HIGH))) {
|
||||||
|
ansi.push('1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.__properties__.attr & BLINK) && ((this.__properties__.attr & BLINK) !== (last & BLINK))) {
|
||||||
|
ansi.push('5');
|
||||||
|
}
|
||||||
|
|
||||||
|
c = (this.__properties__.attr & 0x07);
|
||||||
|
l = (last & 0x07);
|
||||||
|
|
||||||
|
// Foreground
|
||||||
|
switch (c) {
|
||||||
|
case BLACK:
|
||||||
|
r = 30;
|
||||||
|
break;
|
||||||
|
case RED:
|
||||||
|
r = 31;
|
||||||
|
break;
|
||||||
|
case GREEN:
|
||||||
|
r = 32;
|
||||||
|
break;
|
||||||
|
case BROWN:
|
||||||
|
r = 33;
|
||||||
|
break;
|
||||||
|
case BLUE:
|
||||||
|
r = 34;
|
||||||
|
break;
|
||||||
|
case MAGENTA:
|
||||||
|
r = 35;
|
||||||
|
break;
|
||||||
|
case CYAN:
|
||||||
|
r = 36;
|
||||||
|
break;
|
||||||
|
case LIGHTGRAY:
|
||||||
|
r = 37;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//writeln('r:'+r+', l:'+l+', c:'+c);
|
||||||
|
if (r && (c !== l))
|
||||||
|
ansi.push(r);
|
||||||
|
|
||||||
|
// Background
|
||||||
|
if (this.__properties__.attr & 0x70) {
|
||||||
|
c = (this.__properties__.attr & 0x70);
|
||||||
|
l = (last & 0x70);
|
||||||
|
|
||||||
|
switch (this.__properties__.attr & 0x70) {
|
||||||
|
case BG_BLACK:
|
||||||
|
r = 40;
|
||||||
|
break;
|
||||||
|
case BG_RED:
|
||||||
|
r = 41;
|
||||||
|
break;
|
||||||
|
case BG_GREEN:
|
||||||
|
r = 42;
|
||||||
|
break;
|
||||||
|
case BG_BROWN:
|
||||||
|
r = 43;
|
||||||
|
break;
|
||||||
|
case BG_BLUE:
|
||||||
|
r = 44;
|
||||||
|
break;
|
||||||
|
case BG_MAGENTA:
|
||||||
|
r = 45;
|
||||||
|
break;
|
||||||
|
case BG_CYAN:
|
||||||
|
r = 46;
|
||||||
|
break;
|
||||||
|
case BG_LIGHTGRAY:
|
||||||
|
r = 47
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r && (c !== l))
|
||||||
|
ansi.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false && debug)
|
||||||
|
writeln(' - ansi:'+ansi);
|
||||||
|
|
||||||
|
return ansi.length ? (debug ? '': '\x1b')+'['+ansi.join(';')+'m' : undefined;
|
||||||
|
|
||||||
|
case 'vtx':
|
||||||
|
log(LOG_DEBUG,'+ last:'+last+', attr ('+this.__properties__.attr+')');
|
||||||
|
switch (this.__properties__.attr) {
|
||||||
|
// \x08
|
||||||
|
case BLINK:
|
||||||
|
r = VIEWDATA_BLINK;
|
||||||
|
break;
|
||||||
|
// \x09
|
||||||
|
case STEADY:
|
||||||
|
r = VIEWDATA_STEADY;
|
||||||
|
break;
|
||||||
|
// \x0c
|
||||||
|
case NORMAL:
|
||||||
|
r = VIEWDATA_NORMAL;
|
||||||
|
break;
|
||||||
|
// \x0d
|
||||||
|
case DOUBLE:
|
||||||
|
r = VIEWDATA_DOUBLE;
|
||||||
|
break;
|
||||||
|
// \x18
|
||||||
|
case CONCEAL:
|
||||||
|
r = VIEWDATA_CONCEAL;
|
||||||
|
break;
|
||||||
|
// \x19
|
||||||
|
case BLOCKS:
|
||||||
|
r = VIEWDATA_BLOCKS;
|
||||||
|
break;
|
||||||
|
// \x1a
|
||||||
|
case SEPARATED:
|
||||||
|
r = VIEWDATA_SEPARATED;
|
||||||
|
break;
|
||||||
|
// \x1c
|
||||||
|
case BLACKBACK:
|
||||||
|
r = VIEWDATA_BLACKBACK;
|
||||||
|
break;
|
||||||
|
// \x1d
|
||||||
|
case NEWBACK:
|
||||||
|
r = VIEWDATA_NEWBACK;
|
||||||
|
break;
|
||||||
|
// \x1e
|
||||||
|
case HOLD:
|
||||||
|
r = VIEWDATA_HOLD;
|
||||||
|
break;
|
||||||
|
// \x1f
|
||||||
|
case RELEASE:
|
||||||
|
r = VIEWDATA_REVEAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Not handled
|
||||||
|
// \x0a-b,\x0e-f,\x1b
|
||||||
|
case 0xff00:
|
||||||
|
return '?';
|
||||||
|
|
||||||
|
default:
|
||||||
|
var mosiac = (this.__properties__.attr & MOSIAC);
|
||||||
|
c = (this.__properties__.attr & 0x07);
|
||||||
|
|
||||||
|
// Color control \x00-\x07, \x10-\x17
|
||||||
|
switch (c) {
|
||||||
|
case BLACK:
|
||||||
|
r = VIEWDATA_BLACKBACK;
|
||||||
|
break;
|
||||||
|
case RED:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_RED : VIEWDATA_RED;
|
||||||
|
break;
|
||||||
|
case GREEN:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_GREEN : VIEWDATA_GREEN;
|
||||||
|
break;
|
||||||
|
case BROWN:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_YELLOW : VIEWDATA_YELLOW;
|
||||||
|
break;
|
||||||
|
case BLUE:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_BLUE : VIEWDATA_BLUE;
|
||||||
|
break;
|
||||||
|
case MAGENTA:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_MAGENTA : VIEWDATA_MAGENTA;
|
||||||
|
break;
|
||||||
|
case CYAN:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_CYAN : VIEWDATA_CYAN;
|
||||||
|
break;
|
||||||
|
case LIGHTGRAY:
|
||||||
|
r = mosiac ? VIEWDATA_MOSIAC_WHITE : VIEWDATA_WHITE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(LOG_DEBUG,'Not a color?:'+c);
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'= result:'+r.charCodeAt(0)+', ('+r+')');
|
||||||
|
return ESC+r;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(this.__properties__.type+': has not been implemented');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Char.prototype.__defineGetter__('ch',function() {
|
||||||
|
return this.__properties__.ch;
|
||||||
|
});
|
||||||
|
Char.prototype.__defineSetter__('ch',function(char) {
|
||||||
|
if (typeof char !== 'string')
|
||||||
|
throw new Error('ch is not a string')
|
||||||
|
|
||||||
|
if (char.length !== 1)
|
||||||
|
throw new Error('ch can only be 1 character');
|
||||||
|
|
||||||
|
this.__properties__.ch = char;
|
||||||
|
})
|
||||||
|
}
|
2
save.js
2
save.js
@ -1,4 +1,4 @@
|
|||||||
// Ansitex specific includes
|
// ANSItex specific includes
|
||||||
load('ansitex/load/defs.js');
|
load('ansitex/load/defs.js');
|
||||||
load('ansitex/load/funcs.js');
|
load('ansitex/load/funcs.js');
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
{"version":1,"frame":981,"index":"a","owner":9,"cost":0,"content":"ICARLGwSfGwUfCwTLBc3a38jMzdrIzUgICAgICACMDAwMTAwMDEwMSAgEX9rEn9qFC98E38XNWhvIDw9JCw1ByAgICAgICAgICAgICAgICAgIBEvLhIvKhQsLxMvF3VwenBxdXpwNSAgICAgICAgICAgICAgICAgICAgVmlkZW90ZXggICAgICAgICAgICAgICAgICAgIA1SZWdpc3RlciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICACKiogB3RvIGNsZWFyIGlucHV0ICAgICAgICAgICAgICAgICAgICAgAiowMAd0byBzdGFydCBhZ2FpbiAgICAgICBVc2UCXwd0byBFbnRlciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICABRW1haWwgICAgOgcuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgAVVzZXIgSUQgIDoHLi4uLi4uLi4uLi4uLi4uICAgICAgICAgICAgIAFQYXNzd29yZCA6By4uLi4uLi4uLi4uLi4uLiAgICAgICAgICAgICABRnVsbCBOYW1lOgcuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgAUNpdHkgICAgIDoHLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLiAgIAFDb3VudHJ5ICA6By4uLiAgICAgICAgICAgICAgICAgICAgICAgICABUG9zdCBDb2RlOgcuLi4uLi4uLi4uICAgICAgICAgICAgICAgICAgAVRva2VuICAgIDoHLi4uLi4uICAgICAgICAgICAgICAgICAgICAgIBoXODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZ2lzdGVyaW5nIGFuZCB1c2luZyB0aGlzIHN5c3RlbSwgeW91ICBhZ3JlZSB0byBhYmlkZSBieSB0aGUgc3lzdGVtIHJ1bGVzLiBTZWUCKjk4OF8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA==","isPublic":1,"isAccessible":1,"type":"r","key":[980,"register",null,null,null,null,null,null,null,null],"frame_fields":[{"ftype":"t","flength":25,"fchar":".","fname":"EMAIL","r":9,"c":12,"attribute":{},"fvalue":""},{"ftype":"t","flength":15,"fchar":".","fname":"UID","r":10,"c":12,"attribute":{},"fvalue":""},{"ftype":"p","flength":15,"fchar":".","fname":"PASS","r":11,"c":12,"attribute":{},"fvalue":""},{"ftype":"t","flength":25,"fchar":".","fname":"FULLNAME","r":12,"c":12,"attribute":{},"fvalue":""},{"ftype":"t","flength":25,"fchar":".","fname":"CITY","r":13,"c":12,"attribute":{},"fvalue":""},{"ftype":"t","flength":3,"fchar":".","fname":"COUNTRY","r":14,"c":12,"attribute":{},"fvalue":""},{"ftype":"t","flength":10,"fchar":".","fname":"PCODE","r":15,"c":12,"attribute":{},"fvalue":""},{"ftype":"t","flength":10,"fchar":".","fname":"TOKEN","r":16,"c":12,"attribute":{},"fvalue":""}],"date":"2020-07-08T05:17:35.174Z"}
|
{"version":1,"frame":981,"index":"a","owner":9,"cost":0,"content":"ICARLGwSfGwUfCwTLBc3a38jMzdrIzUgICAgICACMDAwMTAwMDEwMSAgEX9rEn9qFC98E38XNWhvIDw9JCw1ByAgICAgICAgICAgICAgICAgIBEvLhIvKhQsLxMvF3VwenBxdXpwNSAgICAgICAgICAgICAgICAgICAgVmlkZW90ZXggICAgICAgICAgICAgICAgICAgIA1SZWdpc3RlciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICACKiogB3RvIGNsZWFyIGlucHV0ICAgICAgICAgICAgICAgICAgICAgAiowMAd0byBzdGFydCBhZ2FpbiAgICAgICBVc2UCXwd0byBFbnRlciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICABRW1haWwgICAgOgcuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgAVVzZXIgSUQgIDoHLi4uLi4uLi4uLi4uLi4uICAgICAgICAgICAgIAFQYXNzd29yZCA6By4uLi4uLi4uLi4uLi4uLiAgICAgICAgICAgICABRnVsbCBOYW1lOgcuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgAUNpdHkgICAgIDoHLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLiAgIAFDb3VudHJ5ICA6By4uLiAgICAgICAgICAgICAgICAgICAgICAgICABUG9zdCBDb2RlOgcuLi4uLi4uLi4uICAgICAgICAgICAgICAgICAgAVRva2VuICAgIDoHLi4uLi4uICAgICAgICAgICAgICAgICAgICAgIBoXODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZ2lzdGVyaW5nIGFuZCB1c2luZyB0aGlzIHN5c3RlbSwgeW91ICBhZ3JlZSB0byBhYmlkZSBieSB0aGUgc3lzdGVtIHJ1bGVzLiBTZWUCKjk4OF8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA==","isPublic":1,"isAccessible":1,"type":"r","key":[980,"register",null,null,null,null,null,null,null,null],"input_fields":[{"type":"t","length":25,"char":".","name":"EMAIL","y":9,"x":12,"attribute":{},"value":""},{"type":"t","length":15,"char":".","name":"UID","y":10,"x":12,"attribute":{},"value":""},{"type":"p","length":15,"char":".","name":"PASS","y":11,"x":12,"attribute":{},"value":""},{"type":"t","length":25,"char":".","name":"FULLNAME","y":12,"x":12,"attribute":{},"value":""},{"type":"t","length":25,"char":".","name":"CITY","y":13,"x":12,"attribute":{},"value":""},{"type":"t","length":3,"char":".","name":"COUNTRY","y":14,"x":12,"attribute":{},"value":""},{"type":"t","length":10,"char":".","name":"PCODE","y":15,"x":12,"attribute":{},"value":""},{"type":"t","length":10,"char":".","name":"TOKEN","y":16,"x":12,"attribute":{},"value":""}],"date":"2020-07-08T05:17:35.174Z"}
|
||||||
|
@ -1 +1 @@
|
|||||||
{"version":1,"frame":98,"index":"a","owner":9,"cost":0,"content":"ICARLGwSfGwUfCwTLBc3a38jMzdrIzUgICAgICACMDAwMTAwMDEwMSAgEX9rEn9qFC98E38XNWhvIDw9JCw1ByAgICAgICAgICAgICAgICAgIBEvLhIvKhQsLxMvF3VwenBxdXpwNSAgICAgICAgICAgICAgICAgICAgVmlkZW90ZXggICAgICAgICAgICAgICAgICAgICANU2lnbiBJbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgAVVzZXIHLi4uLi4uLi4uLi4uLi4uICAgICAgICAgICAgICAgICAgIAFQYXNzBy4uLi4uLi4uLi4uLi4uLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbnRlcgJORVcHdG8gcmVnaXN0ZXIgbmV3IGFjY291bnQgICAgICAgUHJlc3MCKioHdG8gY2xlYXIgeW91ciBpbnB1dCAgICAgICAgICAgIFByZXNzAiowMAd0byBzdGFydCBhZ2FpbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA==","isPublic":1,"isAccessible":1,"type":"l","key":[null,"login",null,null,null,null,null,null,null,null],"frame_fields": [{"ftype":"t","flength":15,"fchar":".","fname":"USER","r":10,"c":15,"attribute":{},"fvalue":""},{"ftype":"p","flength":15,"fchar":".","fname":"PASS","r":11,"c":15,"attribute":{},"fvalue":""}],"date":"2020-07-08T05:17:35.174Z"}
|
{"version":1,"frame":98,"index":"a","owner":9,"cost":0,"content":"ICARLGwSfGwUfCwTLBc3a38jMzdrIzUgICAgICACMDAwMTAwMDEwMSAgEX9rEn9qFC98E38XNWhvIDw9JCw1ByAgICAgICAgICAgICAgICAgIBEvLhIvKhQsLxMvF3VwenBxdXpwNSAgICAgICAgICAgICAgICAgICAgVmlkZW90ZXggICAgICAgICAgICAgICAgICAgICANU2lnbiBJbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgAVVzZXIHLi4uLi4uLi4uLi4uLi4uICAgICAgICAgICAgICAgICAgIAFQYXNzBy4uLi4uLi4uLi4uLi4uLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbnRlcgJORVcHdG8gcmVnaXN0ZXIgbmV3IGFjY291bnQgICAgICAgUHJlc3MCKioHdG8gY2xlYXIgeW91ciBpbnB1dCAgICAgICAgICAgIFByZXNzAiowMAd0byBzdGFydCBhZ2FpbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA==","isPublic":1,"isAccessible":1,"type":"l","key":[null,"login",null,null,null,null,null,null,null,null],"input_fields": [{"type":"t","length":15,"char":".","name":"USER","y":10,"x":15,"attribute":{},"value":""},{"type":"p","length":15,"char":".","name":"PASS","y":11,"x":15,"attribute":{},"value":""}],"date":"2020-07-08T05:17:35.174Z"}
|
||||||
|
Loading…
Reference in New Issue
Block a user