created parse() for response frames with fields
This commit is contained in:
parent
225d17308c
commit
019279fcca
261
load/defs.js
261
load/defs.js
@ -43,30 +43,51 @@ function Frame() {
|
|||||||
this.type = FRAME_TYPE_INFO;
|
this.type = FRAME_TYPE_INFO;
|
||||||
this.key=[ null,null,null,null,null,null,null,null,null,null ];
|
this.key=[ null,null,null,null,null,null,null,null,null,null ];
|
||||||
|
|
||||||
|
// Initialise frame array
|
||||||
|
this.frame_data = {};
|
||||||
|
this.frame_content = {};
|
||||||
|
for(x=0;x<FRAME_LENGTH;x++)
|
||||||
|
{
|
||||||
|
this.frame_data[x] = {};
|
||||||
|
this.frame_content[x] = {};
|
||||||
|
}
|
||||||
|
this.frame_fields = [];
|
||||||
|
|
||||||
this.raw=function() {
|
this.raw=function() {
|
||||||
return base64_decode(this.content).replace(/(\r\n|\n|\r)/gm,'');
|
return base64_decode(this.content).replace(/(\r\n|\n|\r)/gm,'');
|
||||||
}
|
};
|
||||||
|
|
||||||
this.render=function(withHeader) {
|
this.render=function(withHeader) {
|
||||||
owner = base64_decode(this.owner);
|
owner = base64_decode(this.owner);
|
||||||
|
|
||||||
header = '\n\r';
|
header = '\n\r';
|
||||||
|
|
||||||
if (this.type != FRAME_TYPE_LOGIN)
|
if (this.type != FRAME_TYPE_LOGIN) {
|
||||||
header = '\1n'+owner+' '.repeat(FRAME_HEADER-console.strlen(owner))+'\1n '+
|
header = '\1n'+owner+' '.repeat(FRAME_HEADER-console.strlen(owner))+'\1n '+
|
||||||
'\1W\1H'+this.page+' '.repeat(FRAME_PAGENUM-this.page.length)+' '+
|
'\1W\1H'+this.page+' '.repeat(FRAME_PAGENUM-this.page.length)+' '+
|
||||||
'\1G\1H'+' '.repeat(FRAME_COST-this.cost.toString().length)+this.cost+FRAME_COSTUNIT+
|
'\1G\1H'+' '.repeat(FRAME_COST-this.cost.toString().length)+this.cost+FRAME_COSTUNIT+
|
||||||
(console.screen_columns > 80 ? '\n\r' : '');
|
(console.screen_columns > 80 ? '\n\r' : '');
|
||||||
|
|
||||||
return header + base64_decode(this.content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((this.type == FRAME_TYPE_LOGIN) || (this.type == FRAME_TYPE_RESPONSE)) {
|
||||||
|
return header+this.parse(this.content);
|
||||||
|
} else {
|
||||||
|
return header+this.content;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Object.defineProperty(this,'page', {
|
Object.defineProperty(this,'page', {
|
||||||
get: function() {
|
get: function() {
|
||||||
if (this.frame == null || this.index == null) return null;
|
if (this.frame == null || this.index == null) return null;
|
||||||
return this.frame+this.index;
|
return this.frame+this.index;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(this,'fields', {
|
||||||
|
get: function() {
|
||||||
|
return this.frame_fields;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a frame from disk (.tex file)
|
// Load a frame from disk (.tex file)
|
||||||
@ -85,10 +106,240 @@ Frame.prototype.load = function(filename) {
|
|||||||
this[property] = load[property];
|
this[property] = load[property];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.content = base64_decode(this.content);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log(LOG_ERROR,'Frame error: '+error);
|
log(LOG_ERROR,'Frame error: '+error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(LOG_DEBUG,'Loaded frame: ['+this.frame+']['+this.index+'] ('+this.page+')');
|
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.
|
||||||
|
*
|
||||||
|
* @todo This function could be advanced by looking for the next KEY_ESC char, instead of progressing 1 char at a time
|
||||||
|
* @param text
|
||||||
|
*/
|
||||||
|
Frame.prototype.parse = function(text) {
|
||||||
|
var c = 1; // column
|
||||||
|
var r = 1; // row
|
||||||
|
var output = '';
|
||||||
|
|
||||||
|
// Default Attributes
|
||||||
|
f = 39;
|
||||||
|
b = 49;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for(p=0;p<text.length;p++) {
|
||||||
|
// 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.substring(p+advance,p+advance+50).match(/([0-9]+[;]?)+([a-zA-Z])/);
|
||||||
|
log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', STRING: '+text.substring(p+advance,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:
|
||||||
|
dump('? 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.substring(p+advance,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.substring(p+advance,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 ADITIONAL SOS FIELDS. ['+r+'x'+c+'] '+sos[num]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldlen) {
|
||||||
|
chars = fieldchar.repeat(fieldlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte = '';
|
||||||
|
|
||||||
|
this.frame_fields.push({
|
||||||
|
'type': fieldtype,
|
||||||
|
'length': fieldlen,
|
||||||
|
'r': r,
|
||||||
|
'c': c,
|
||||||
|
});
|
||||||
|
|
||||||
|
log(LOG_DEBUG,'SOS Field found at ['+r+'x'+(c-1)+'], Type: '+fieldtype+', Length: '+fieldlen);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(LOG_DEBUG,'DEFAULT ['+r+'x'+c+'] '+advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.frame_data[r][c] = {i:i,f:f,b:b};
|
||||||
|
this.frame_content[r][c] = byte;
|
||||||
|
log(LOG_DEBUG,'ADD OUTPUT ['+r+'x'+c+'] for: '+byte);
|
||||||
|
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>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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
if (false && r > 3) {
|
||||||
|
console.write(output);
|
||||||
|
bbs.hangup();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
// String repeat.
|
||||||
if (!String.prototype.repeat) {
|
if (!String.prototype.repeat) {
|
||||||
String.prototype.repeat = function(count) {
|
String.prototype.repeat = function(count) {
|
||||||
'use strict';
|
'use strict';
|
||||||
@ -51,8 +52,7 @@ function cursorOff() {
|
|||||||
* @param code
|
* @param code
|
||||||
* @returns {number | string|boolean}
|
* @returns {number | string|boolean}
|
||||||
*/
|
*/
|
||||||
function findMsgBase(code)
|
function findMsgBase(code) {
|
||||||
{
|
|
||||||
if (! code)
|
if (! code)
|
||||||
code = "tex_data";
|
code = "tex_data";
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user