Move common functions for ANSI/VIEWDATA frames to base file
This commit is contained in:
parent
5883b5ca9b
commit
8df5d1dcff
@ -1,578 +0,0 @@
|
||||
var FRAME_ANSI = (1<<1);
|
||||
|
||||
var ANSI_FRAME_LENGTH = 22; /* Length of a frame */
|
||||
var ANSI_FRAME_WIDTH = 80; /* Width of a frame */
|
||||
var ANSI_FRAME_HEADER = 56; /* Size of page owner (length) */
|
||||
var ANSI_FRAME_PAGENUM = 12; /* Size of page number (length with a-z) */
|
||||
var ANSI_FRAME_COST = 9; /* Size of cost (length without unit) */
|
||||
|
||||
var ANSI_MSG_SENDORNOT = '\1n\1h\1GKEY 1 TO SEND, 2 NOT TO SEND';
|
||||
var ANSI_MSG_LOGON = '\1n\1h\1GKEY 1 TO LOGON, 2 TO RETURN';
|
||||
var ANSI_MSG_SENT = '\1n\1h\1GMESSAGE SENT - KEY # TO CONTINUE';
|
||||
var ANSI_MSG_NOTSENT = '\1n\1h\1GMESSAGE NOT SENT - KEY # TO CONTINUE';
|
||||
var ANSI_ERR_NO_PARENT = '\1n\1h\1RPARENT FRAME DOESNT EXIST';
|
||||
var ANSI_ERR_NOT_IMPLEMENTED = '\1n\1h\1RNOT IMPLEMENTED YET?';
|
||||
var ANSI_ERR_ROUTE = '\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
|
||||
var ANSI_ERR_METHOD_NOT_EXIST = '\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
|
||||
var ANSI_ACCESS_DENIED = '\1n\1h\1RACCESS DENIED. MISTAKE? TRY AGAIN OR TELL US *08';
|
||||
var ANSI_ALREADY_MEMBER = '\1n\1h\1RALREADY MEMBER OF CUG'
|
||||
var ANSI_INACTIVITY = '\1n\1h\1RINACTIVITY ALERT, DISCONNECT PENDING...';
|
||||
var ANSI_INACTIVE = '\1n\1h\1RINACTIVITY DISCONNECT';
|
||||
var ANSI_NOACTION = '\1n\1h\1RNO ACTION PERFORMED';
|
||||
var ANSI_BASESTAR = '\1N\1G\1H*';
|
||||
var ANSI_INVALID_CODE = '\1n\1h\1RINVAID CODE, PLEASE TRY AGAIN *00';
|
||||
var ANSI_TOKEN_EMAIL = '\1n\1h\1RTOKEN EMAILED TO YOU...';
|
||||
var ANSI_TOKEN_SENT = '\1n\1h\1RTOKEN SENT, PLEASE ENTER TOKEN';
|
||||
var ANSI_INVALID_EMAIL = '\1n\1h\1RINVAID EMAIL, PLEASE TRY AGAIN *00';
|
||||
var ANSI_INVALID_UID = '\1n\1h\1RINVAID USER ID, PLEASE TRY AGAIN *00';
|
||||
var ANSI_CANNOT_SEND_TOKEN = '\1n\1h\1RCANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00';
|
||||
var ANSI_USER_EXISTS = '\1n\1h\1RERROR USER EXISTS, PLEASE TRY AGAIN *00';
|
||||
var ANSI_USER_CREATE_ERROR = '\1n\1h\1RERROR CREATING USER, PLEASE TRY AGAIN *00';
|
||||
var ANSI_LOGIN_ERROR = '\1n\1h\1RERROR LOGGING IN, PLEASE TRY AGAIN *00';
|
||||
var ANSI_CANCEL_MSG = '\1n\1h\1GPRESS 2 TO CANCEL';
|
||||
|
||||
// Our frame object
|
||||
function ANSIFrame() {
|
||||
this.version=1; // The version of this frame - in case we update functionality and we need to be
|
||||
// backwards compatible
|
||||
this.frame=null; // Frame Number [0-9]+
|
||||
this.index=null; // Frame Index [a-z]
|
||||
this.owner=0; // The Service Provider owning the frame.
|
||||
this.cost=0; // The cost to view the frame @TODO
|
||||
this.content=''; // The frame content, base64 encoded
|
||||
|
||||
// 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]
|
||||
|
||||
/**
|
||||
* 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');
|
||||
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(withHeader) {
|
||||
log(LOG_DEBUG,'- ANSI FRAME');
|
||||
owner = base64_decode(this.owner);
|
||||
|
||||
header = '\n\r';
|
||||
|
||||
//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+']');
|
||||
|
||||
cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -');
|
||||
|
||||
header = '\1n'+this.pageownerlogo+' '.repeat(ANSI_FRAME_HEADER-console.strlen(this.pageownerlogo))+'\1n '+
|
||||
(this.isAccessible ? '\1W' : '\1R')+'\1H'+this.page+' '.repeat(ANSI_FRAME_PAGENUM-this.page.length)+' '+
|
||||
'\1G\1H'+' '.repeat(ANSI_FRAME_COST-cost.toString().length+1)+cost+'\1n'+
|
||||
(console.screen_columns > 80 ? '\n\r' : '');
|
||||
}
|
||||
|
||||
console.clear();
|
||||
|
||||
return console.putmsg(header+this.parse(base64_decode(this.content)));
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Load a frame from disk (.tex file)
|
||||
this.load = function(filename) {
|
||||
log(LOG_DEBUG,'Loading ANSI frame from: '+filename);
|
||||
|
||||
f = new File(system.mods_dir+'ansitex/text/'+filename+'.tex');
|
||||
if (! f.exists || ! f.open('r')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var load = JSON.parse(f.read());
|
||||
|
||||
for (property in load) {
|
||||
this[property] = load[property];
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log(LOG_ERROR,'Frame error: '+error);
|
||||
|
||||
// Load our system error frame.
|
||||
this.load('998a');
|
||||
return null;
|
||||
}
|
||||
|
||||
log(LOG_DEBUG,'Loaded 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
|
||||
*/
|
||||
this.parse = function(text) {
|
||||
var c = 1; // column
|
||||
var r = 2; // row (row 1 is the header)
|
||||
var output = '';
|
||||
this.frame_fields = [];
|
||||
|
||||
// If there is no text return
|
||||
if (! text)
|
||||
return output;
|
||||
|
||||
// Default Attributes
|
||||
f = 39;
|
||||
b = 49;
|
||||
i = 0;
|
||||
|
||||
for(p=0;p<text.length;p++) {
|
||||
// Look for a special character until the end of the frame width
|
||||
cte = (r*ANSI_FRAME_WIDTH - ((r-1)*ANSI_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
|
||||
case 'X':
|
||||
//log(LOG_DEBUG,'PU ['+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-9]+)([;]?.+)?)\x1b\\/);
|
||||
//log(LOG_DEBUG,'PU ['+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 pu = matches[0].substr(0,matches[0].length-2).split(';');
|
||||
//log(LOG_DEBUG,'PU ['+r+'x'+c+'] ADVANCE: '+advance+', PU: '+pu);
|
||||
|
||||
chars = renderfield(pu[0],pu[1]);
|
||||
byte = '';
|
||||
|
||||
log(LOG_DEBUG,'PU Field found at ['+r+'x'+(c-1)+'], Field: '+pu[0]+', Length: '+pu[1]+', Attrs: '+JSON.stringify({i:i,f:f,b:b}));
|
||||
|
||||
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>ANSI_FRAME_WIDTH) {
|
||||
c = 1;
|
||||
r++;
|
||||
}
|
||||
|
||||
/*
|
||||
// @todo - If we are longer than ANSI_FRAME_LENGTH, move the output into the next frame.
|
||||
if (r>ANSI_FRAME_LENGTH) {
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
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)) == 0) {
|
||||
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) {
|
||||
eval('var msg = ANSI_'+text+';');
|
||||
console.pushxy();
|
||||
console.gotoxy(0,24);
|
||||
console.print(msg);
|
||||
console.cleartoeol();
|
||||
|
||||
if (! reposition) {
|
||||
console.popxy();
|
||||
}
|
||||
}
|
||||
|
||||
this.clearBaseline=function(reposition) {
|
||||
console.pushxy();
|
||||
console.gotoxy(0,24);
|
||||
console.print('');
|
||||
console.cleartoeol();
|
||||
|
||||
if (! reposition) {
|
||||
console.popxy();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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,'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(pageOwner(this.frame).logoans);
|
||||
}
|
||||
})
|
||||
}
|
@ -89,4 +89,7 @@ const HOME_FRAME_AUTH ={frame: 98,index: 'b'};
|
||||
/* Home page for initial connection */
|
||||
const HOME_FRAME_CONNECT ={frame: 980,index: 'a'};
|
||||
|
||||
/* Attributes saved/loaded from files */
|
||||
const SAVED_FRAME_ATTRS =['version','frame','index','owner','cost','content','isPublic','isAccessible','type','key'];
|
||||
|
||||
this;
|
||||
|
@ -30,8 +30,8 @@ function edit(fo) {
|
||||
const frame = new Frame(1,1,console.screen_columns,console.screen_rows,BG_BLACK|LIGHTGRAY);
|
||||
frame.gotoxy(1,1);
|
||||
|
||||
header = '\1n'+fo.pageownerlogo+' '.repeat(ANSI_FRAME_HEADER-console.strlen(fo.pageownerlogo))+'\1n '+
|
||||
'\1W\1H'+fo.page+' '.repeat(ANSI_FRAME_PAGENUM-fo.page.length)+' '+
|
||||
header = '\1n'+fo.pageownerlogo+' '.repeat(fo.FRAME_PAGENUM-console.strlen(fo.pageownerlogo))+'\1n '+
|
||||
'\1W\1H'+fo.page+' '.repeat(fo.FRAME_PAGENUM-fo.page.length)+' '+
|
||||
'\1G\1H'+' Edit';
|
||||
frame.putmsg(header);
|
||||
frame.open();
|
||||
@ -138,4 +138,4 @@ function edit(fo) {
|
||||
}
|
||||
}
|
||||
|
||||
this;
|
||||
this;
|
||||
|
195
load/frame-ansi.js
Normal file
195
load/frame-ansi.js
Normal file
@ -0,0 +1,195 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* 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');
|
||||
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(withHeader) {
|
||||
log(LOG_DEBUG,'- ANSI FRAME');
|
||||
owner = base64_decode(this.owner);
|
||||
|
||||
header = '\n\r';
|
||||
|
||||
//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+']');
|
||||
|
||||
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' : '');
|
||||
}
|
||||
|
||||
console.clear();
|
||||
|
||||
return console.putmsg(header+this.parse(base64_decode(this.content)));
|
||||
};
|
||||
|
||||
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)) == 0) {
|
||||
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;
|
475
load/frame-page.js
Normal file
475
load/frame-page.js
Normal file
@ -0,0 +1,475 @@
|
||||
// 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(pageOwner(this.frame).logoans);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
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]];
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log(LOG_ERROR,'Frame error: '+error);
|
||||
|
||||
// Load our system error frame.
|
||||
// @todo this should be a config item
|
||||
this.load('998a');
|
||||
return null;
|
||||
}
|
||||
|
||||
log(LOG_DEBUG,'Loaded frame: ['+this.frame+']['+this.index+'] ('+this.page+')');
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
PageFrame.prototype.parse = function(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
|
||||
case 'X':
|
||||
//log(LOG_DEBUG,'PU ['+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-9]+)([;]?.+)?)\x1b\\/);
|
||||
//log(LOG_DEBUG,'PU ['+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 pu = matches[0].substr(0,matches[0].length-2).split(';');
|
||||
//log(LOG_DEBUG,'PU ['+r+'x'+c+'] ADVANCE: '+advance+', PU: '+pu);
|
||||
|
||||
chars = renderfield(pu[0],pu[1]);
|
||||
byte = '';
|
||||
|
||||
log(LOG_DEBUG,'PU Field found at ['+r+'x'+(c-1)+'], Field: '+pu[0]+', Length: '+pu[1]+', Attrs: '+JSON.stringify({i:i,f:f,b:b}));
|
||||
|
||||
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;
|
||||
};
|
255
load/frame-viewdata.js
Normal file
255
load/frame-viewdata.js
Normal file
@ -0,0 +1,255 @@
|
||||
var FRAME_VIEWDATA = (1<<2);
|
||||
|
||||
var VIEWDATA_LEFT = ascii(0x08);
|
||||
var VIEWDATA_RIGHT = ascii(0x09);
|
||||
var VIEWDATA_DOWN = ascii(0x0a);
|
||||
var VIEWDATA_UP = ascii(0x0b);
|
||||
var VIEWDATA_CLS = ascii(0x0c);
|
||||
var VIEWDATA_CR = ascii(0x0d);
|
||||
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)+'ACCESS 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';
|
||||
|
||||
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;
|
@ -1,608 +0,0 @@
|
||||
var FRAME_VIEWDATA = (1<<2);
|
||||
|
||||
var VIEWDATA_FRAME_LENGTH = 22; /* Length of a frame */
|
||||
var VIEWDATA_FRAME_WIDTH = 40; /* Width of a frame */
|
||||
var VIEWDATA_FRAME_HEADER = 23; /* Size of page owner (length) */
|
||||
var VIEWDATA_FRAME_PAGENUM = 11; /* Size of page number (length with a-z) */
|
||||
var VIEWDATA_FRAME_COST = 3; /* Size of cost (length without unit) */
|
||||
|
||||
var VIEWDATA_LEFT = ascii(0x08);
|
||||
var VIEWDATA_RIGHT = ascii(0x09);
|
||||
var VIEWDATA_DOWN = ascii(0x0a);
|
||||
var VIEWDATA_UP = ascii(0x0b);
|
||||
var VIEWDATA_CLS = ascii(0x0c);
|
||||
var VIEWDATA_CR = ascii(0x0d);
|
||||
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);
|
||||
|
||||
var VIEWDATA_MSG_SENDORNOT = ascii(27)+'BKEY 1 TO SEND, 2 NOT TO SEND';
|
||||
var VIEWDATA_MSG_LOGON = ascii(27)+'BKEY 1 TO LOGON, 2 TO RETURN';
|
||||
var VIEWDATA_MSG_SENT = ascii(27)+'BMESSAGE SENT - KEY _ TO CONTINUE';
|
||||
var VIEWDATA_MSG_NOTSENT = ascii(27)+'BMESSAGE NOT SENT - KEY _ TO CONTINUE';
|
||||
var VIEWDATA_ERR_NO_PARENT = ascii(27)+'APARENT FRAME DOESNT EXIST';
|
||||
var VIEWDATA_ERR_NOT_IMPLEMENTED = ascii(27)+'ANOT IMPLEMENTED YET?';
|
||||
var VIEWDATA_ERR_ROUTE = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08';
|
||||
var VIEWDATA_ERR_METHOD_NOT_EXIST = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08';
|
||||
var VIEWDATA_ACCESS_DENIED = ascii(27)+'ACCESS DENIED.';
|
||||
var VIEWDATA_ALREADY_MEMBER = ascii(27)+'AALREADY MEMBER OF CUG'
|
||||
var VIEWDATA_INACTIVITY = ascii(27)+'AINACTIVITY ALERT, DISCONNECT PENDING...';
|
||||
var VIEWDATA_INACTIVE = ascii(27)+'AINACTIVITY DISCONNECT';
|
||||
var VIEWDATA_NOACTION = ascii(27)+'ANO ACTION PERFORMED';
|
||||
var VIEWDATA_BASESTAR = ascii(27)+'B*';
|
||||
var VIEWDATA_INVALID_CODE = ascii(27)+'AINVAID CODE, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_TOKEN_EMAIL = ascii(27)+'ATOKEN EMAILED TO YOU...';
|
||||
var VIEWDATA_TOKEN_SENT = ascii(27)+'ATOKEN SENT, PLEASE ENTER TOKEN';
|
||||
var VIEWDATA_INVALID_EMAIL = ascii(27)+'AINVAID EMAIL, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_INVALID_UID = ascii(27)+'AINVAID USER ID, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_CANNOT_SEND_TOKEN = ascii(27)+'ACANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_USER_EXISTS = ascii(27)+'AERROR USER EXISTS, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_USER_CREATE_ERROR = ascii(27)+'AERROR CREATING USER, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_LOGIN_ERROR = ascii(27)+'AERROR LOGGING IN, PLEASE TRY AGAIN *00';
|
||||
var VIEWDATA_CANCEL_MSG = ascii(27)+'BPRESS 2 TO CANCEL';
|
||||
|
||||
// Our frame object
|
||||
function VIEWDATAFrame() {
|
||||
this.version=1; // The version of this frame - in case we update functionality and we need to be
|
||||
// backwards compatible
|
||||
this.frame=null; // Frame Number [0-9]+
|
||||
this.index=null; // Frame Index [a-z]
|
||||
this.owner=0; // The Service Provider owning the frame.
|
||||
this.cost=0; // The cost to view the frame @TODO
|
||||
this.content=''; // The frame content, base64 encoded
|
||||
var blp=0; // Length of data on the bottom line
|
||||
|
||||
// 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]
|
||||
|
||||
/**
|
||||
* 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(VIEWDATA_FRAME_HEADER-this.strlen(videotex(this.pageownerlogo)))+
|
||||
(this.isAccessible ? ascii(27)+'G' : ascii(27)+'A')+this.page+' '.repeat(VIEWDATA_FRAME_PAGENUM-this.page.length)+
|
||||
ascii(27)+'B'+' '.repeat(VIEWDATA_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.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;
|
||||
}
|
||||
|
||||
// Load a frame from disk (.tex file)
|
||||
this.load = function(filename) {
|
||||
log(LOG_DEBUG,'Loading VIEWDATA frame from: '+filename);
|
||||
|
||||
f = new File(system.mods_dir+'ansitex/text/'+filename+'.vtx');
|
||||
if (! f.exists || ! f.open('r')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var load = JSON.parse(f.read());
|
||||
|
||||
for (property in load) {
|
||||
this[property] = load[property];
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log(LOG_ERROR,'Frame error: '+error);
|
||||
|
||||
// Load our system error frame.
|
||||
this.load('998a');
|
||||
return null;
|
||||
}
|
||||
|
||||
log(LOG_DEBUG,'Loaded 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
|
||||
*/
|
||||
this.parse = function(text) {
|
||||
var c = 1; // column
|
||||
var r = 2; // row (row 1 is the header)
|
||||
var output = '';
|
||||
this.frame_fields = [];
|
||||
|
||||
// If there is no text return
|
||||
if (! text)
|
||||
return output;
|
||||
|
||||
// Default Attributes
|
||||
f = 39;
|
||||
b = 49;
|
||||
i = 0;
|
||||
|
||||
for(p=0;p<text.length;p++) {
|
||||
// Look for a special character until the end of the frame width
|
||||
cte = (r*VIEWDATA_FRAME_WIDTH - ((r-1)*VIEWDATA_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;
|
||||
|
||||
// SOS
|
||||
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 \
|
||||
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 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>VIEWDATA_FRAME_WIDTH) {
|
||||
c = 1;
|
||||
r++;
|
||||
}
|
||||
|
||||
/*
|
||||
// @todo - If we are longer than FRAME_LENGTH, move the output into the next frame.
|
||||
if (r>FRAME_LENGTH) {
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
this.qrcode = function(qr) {
|
||||
// Render the body
|
||||
var qrcode = VIEWDATA_HOME+VIEWDATA_DOWN.repeat(5);
|
||||
var offset = VIEWDATA_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 = VIEWDATA_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:'+VIEWDATA_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) {
|
||||
eval('var msg = VIEWDATA_'+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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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,'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(pageOwner(this.frame).logovtx);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
20
main.js
20
main.js
@ -12,8 +12,8 @@ load('ansitex/load/funcs.js');
|
||||
|
||||
// Ansitex specific includes
|
||||
require('ansitex/load/defs.js','ACTION_EXIT');
|
||||
require('ansitex/load/ansiframe.js','FRAME_ANSI');
|
||||
require('ansitex/load/viewdataframe.js','FRAME_VIEWDATA');
|
||||
require('ansitex/load/frame-ansi.js','FRAME_ANSI');
|
||||
require('ansitex/load/frame-viewdata.js','FRAME_VIEWDATA');
|
||||
|
||||
// @todo Returning from chat should refresh the frame
|
||||
// @todo Suppress displays of telegrams
|
||||
@ -53,9 +53,9 @@ while(bbs.online) {
|
||||
|
||||
/**
|
||||
* Current Frame Object that is being displayed to the user
|
||||
* - VIEWDATAFrame - for viewdata frames
|
||||
* - ANSIFrame - for ANSItex frames
|
||||
* @type {ANSIFrame|VIEWDATAFrame}
|
||||
* - FrameViewdata - for viewdata frames
|
||||
* - FrameAnsi - for ANSItex frames
|
||||
* @type {FrameAnsi|FrameViewdata}
|
||||
*/
|
||||
var fo = null;
|
||||
|
||||
@ -834,7 +834,7 @@ while(bbs.online) {
|
||||
// If we are editing a specific frame, attempt to load it
|
||||
if (next_page) {
|
||||
var current = fo;
|
||||
fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame();
|
||||
fo = viewdata ? new FrameViewdata() : new FrameAnsi();
|
||||
fo.load(pageStr(next_page));
|
||||
|
||||
// If the frame doesnt exist, check that the parent frame exists in case we are creating a new one
|
||||
@ -843,7 +843,7 @@ while(bbs.online) {
|
||||
|
||||
// We can always create an 'a' frame
|
||||
if (next_page.index !== 'a') {
|
||||
fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame();
|
||||
fo = viewdata ? new FrameViewdata() : new FrameAnsi();
|
||||
fo.load(pageStr({frame: next_page.frame, index: String.fromCharCode(next_page.index.charCodeAt(0)-1)}));
|
||||
|
||||
log(LOG_DEBUG,'- ACTION_EDIT: check index: '+JSON.stringify(fo)+' ('+String.fromCharCode(next_page.index.charCodeAt(0)-1)+')');
|
||||
@ -857,7 +857,7 @@ while(bbs.online) {
|
||||
}
|
||||
|
||||
// New frame
|
||||
fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame();
|
||||
fo = viewdata ? new FrameViewdata() : new FrameAnsi();
|
||||
fo.frame = next_page.frame;
|
||||
fo.index = next_page.index;
|
||||
fo.cost = 0;
|
||||
@ -905,7 +905,7 @@ while(bbs.online) {
|
||||
|
||||
if (next_page !== null) {
|
||||
current = fo;
|
||||
fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame();
|
||||
fo = viewdata ? new FrameViewdata() : new FrameAnsi();
|
||||
fo.load(pageStr(next_page));
|
||||
|
||||
if (fo.page == null) {
|
||||
@ -913,7 +913,7 @@ while(bbs.online) {
|
||||
|
||||
// In case the frame doesnt exist
|
||||
if (fo == null)
|
||||
fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame();
|
||||
fo = viewdata ? new FrameViewdata() : new FrameAnsi();
|
||||
|
||||
// sendbaseline ERR_PAGE
|
||||
fo.sendBaseline('ERR_ROUTE',false);
|
||||
|
Loading…
Reference in New Issue
Block a user