We only use __properties__ in setters and getters, in all other cases we set/access variables via magic methods

This commit is contained in:
Deon George 2023-12-22 10:25:32 +11:00
parent 1c80c3951a
commit 9513f8d144
3 changed files with 231 additions and 146 deletions

View File

@ -10,9 +10,9 @@
- Line 2..23 - Content (Scrollable) - Line 2..23 - Content (Scrollable)
- Line 24 - Status/Command Input (Fixed) - Line 24 - Status/Command Input (Fixed)
= When scrolling is disabled, and the canvas is greater than the window, then "nextpage" returns the next frame = @todo When scrolling is disabled, and the canvas is greater than the window, then "nextpage" returns the next frame
= Pageable windows cannot have children, only "CONTENT" is paged = Pageable windows cannot have children [b-z frames], only "CONTENT" is paged
= Pageable windows are pagable when scrolling is false and window canvas.height > window.height and canvas.width = window.width = @todo Pageable windows are pagable when scrolling is false and window canvas.height > window.height and canvas.width = window.width
+ Window - size W x H, where W/H can be larger than the Screen + Window - size W x H, where W/H can be larger than the Screen
- Window holds all the content to be shown - Window holds all the content to be shown
@ -75,7 +75,10 @@
--:____.____|____.____|____.____|____.____|____.____|____.____|____.____|____.____| --:____.____|____.____|____.____|____.____|____.____|____.____|____.____|____.____|
*/ */
load('ansitex/load/windows.js'); load('ansitex/load/windows.js'); // Our supporting window class
require('sbbsdefs.js','SS_USERON'); // Need for our ANSI colors eg: BG_*
require('ansitex/load/msgbases.js','MAX_PAGE_NUM'); // To read/write to message bases
require('ansitex/load/session-ansitex.js','SESSION_ANSITEX'); // @todo Only load this if it is an ANSI page we are loading
/** /**
* This object represents a full page that interacts with the user * This object represents a full page that interacts with the user
@ -102,13 +105,12 @@ load('ansitex/load/windows.js');
* Pages have the following public functions * Pages have the following public functions
* - build - Compile the frame for rendering * - build - Compile the frame for rendering
* - display - Display the compiled frame * - display - Display the compiled frame
* - load - Load a frame from a file source * - import - Load a frame from a file source
* - save - Save the frame to the msgbase
* - load - Load the frame from the msgbase
*/ */
function Page(service,debug) { function Page(service,debug) {
this.__properties__ = { this.__window__ = {
type: undefined, // Viewdata or ANSItex frame
name: new PageObject,
layout: undefined, // Window - Full page content layout: undefined, // Window - Full page content
header: undefined, // Window - Page Title header: undefined, // Window - Page Title
@ -116,7 +118,12 @@ function Page(service,debug) {
pagenum: undefined, // Our page number (*) pagenum: undefined, // Our page number (*)
cost: undefined, // Page cost (*) cost: undefined, // Page cost (*)
content: undefined, // Window - Page Content body: undefined, // Window - Page body
};
this.__properties__ = {
type: undefined, // Viewdata or ANSItex frame
name: new PageObject,
input_fields: [], // Array of our input fields input_fields: [], // Array of our input fields
dynamic_fields: [], // Array of our dynamic fields dynamic_fields: [], // Array of our dynamic fields
@ -130,7 +137,7 @@ function Page(service,debug) {
}; };
this.__compiled__ = { this.__compiled__ = {
build: undefined, build: undefined, // Our page compiled content
}; };
/* /*
@ -151,25 +158,25 @@ function Page(service,debug) {
switch (service) { switch (service) {
case 'tex': case 'tex':
this.__properties__.layout = new Window(1,1,ANSI_FRAME_WIDTH,ANSI_FRAME_HEIGHT+1,'LAYOUT',this,debug); this.__window__.layout = new Window(1,1,ANSI_FRAME_WIDTH,ANSI_FRAME_HEIGHT+1,'LAYOUT',this,debug);
this.__properties__.content = new Window(1,2,ANSI_FRAME_WIDTH,ANSI_FRAME_HEIGHT,'CONTENT',this.__properties__.layout,debug); this.__window__.body = new Window(1,2,ANSI_FRAME_WIDTH,ANSI_FRAME_HEIGHT,'CONTENT',this.__window__.layout,debug);
this.__properties__.header = new Window(1,1,ANSI_FRAME_WIDTH,1,'HEADER',this.__properties__.layout,debug); this.__window__.header = new Window(1,1,ANSI_FRAME_WIDTH,1,'HEADER',this.__window__.layout,debug);
this.__properties__.provider = new Window(1,1,ANSI_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__properties__.header,debug); this.__window__.provider = new Window(1,1,ANSI_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__window__.header,debug);
this.__properties__.pagenum = new Window(57,1,ANSI_FRAME_PAGE_LENGTH,1,'#',this.__properties__.header,debug); this.__window__.pagenum = new Window(57,1,ANSI_FRAME_PAGE_LENGTH,1,'#',this.__window__.header,debug);
this.__properties__.cost = new Window(71,1,ANSI_FRAME_COST_LENGTH,1,'$',this.__properties__.header,debug); this.__window__.cost = new Window(71,1,ANSI_FRAME_COST_LENGTH,1,'$',this.__window__.header,debug);
break; break;
case 'vtx': case 'vtx':
// @todo VTX hasnt been worked on at all - need at last a viewdata2attrs function // @todo VTX hasnt been worked on at all - need at last a viewdata2attrs function
this.__properties__.layout = new Window(1,1,VIEWDATA_FRAME_WIDTH,VIEWDATA_FRAME_HEIGHT+1,'LAYOUT',this,debug); this.__window__.layout = new Window(1,1,VIEWDATA_FRAME_WIDTH,VIEWDATA_FRAME_HEIGHT+1,'LAYOUT',this,debug);
this.__properties__.content = new Window(1,2,VIEWDATA_FRAME_WIDTH,VIEWDATA_FRAME_HEIGHT,'CONTENT',this.__properties__.layout,debug) this.__window__.body = new Window(1,2,VIEWDATA_FRAME_WIDTH,VIEWDATA_FRAME_HEIGHT,'CONTENT',this.__window__.layout,debug)
this.__properties__.header = new Window(1,1,VIEWDATA_FRAME_WIDTH,1,'HEADER',this.__properties__.layout,debug); this.__window__.header = new Window(1,1,VIEWDATA_FRAME_WIDTH,1,'HEADER',this.__window__.layout,debug);
this.__properties__.provider = new Window(1,1,VIEWDATA_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__properties__.header,debug); this.__window__.provider = new Window(1,1,VIEWDATA_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__window__.header,debug);
this.__properties__.pagenum = new Window(24,1,VIEWDATA_FRAME_PAGE_LENGTH,1,'#',this.__properties__.header,debug); this.__window__.pagenum = new Window(24,1,VIEWDATA_FRAME_PAGE_LENGTH,1,'#',this.__window__.header,debug);
this.__properties__.cost = new Window(35,1,VIEWDATA_FRAME_COST_LENGTH,1,'$',this.__properties__.header,debug); this.__window__.cost = new Window(35,1,VIEWDATA_FRAME_COST_LENGTH,1,'$',this.__window__.header,debug);
break; break;
@ -180,8 +187,6 @@ function Page(service,debug) {
this.service = service; this.service = service;
} }
init.apply(this,arguments);
// @todo change this to Object.defineProperty() - see session.js // @todo change this to Object.defineProperty() - see session.js
/** /**
* Determine if this frame is accessible to the current user * Determine if this frame is accessible to the current user
@ -197,7 +202,7 @@ function Page(service,debug) {
(this.__properties__.isAccessible && this.pageowner === SYSTEM_OWNER && ! this.__properties__.isPublic) || (this.__properties__.isAccessible && this.pageowner === SYSTEM_OWNER && ! this.__properties__.isPublic) ||
(this.__properties__.isAccessible && this.__properties__.isPublic) || (this.__properties__.isAccessible && this.__properties__.isPublic) ||
(this.__properties__.isAccessible && ! this.__properties__.isPublic && this.isMember) || (this.__properties__.isAccessible && ! this.__properties__.isPublic && this.isMember) ||
(pageEditor(this.frame)) (pageEditor(this.name.frame))
); );
} else { } else {
@ -209,12 +214,12 @@ function Page(service,debug) {
if (typeof int !== 'number') if (typeof int !== 'number')
throw new Error('Cost must be a number'); throw new Error('Cost must be a number');
switch (this.service) { switch (this.__properties__.service) {
case 'tex': case 'tex':
if ((''+int).length > ANSI_FRAME_COST_LENGTH-1) if ((''+int).length > ANSI_FRAME_COST_LENGTH-1)
throw new Error('Cost too large'); throw new Error('Cost too large');
this.__properties__.cost.__properties__.content = anstoattrs(ESC+'[1;32m'+padright(int,ANSI_FRAME_COST_LENGTH-1,' ')+'c').content; this.__window__.cost.__properties__.content = anstoattrs(ESC+'[1;32m'+padright(int,ANSI_FRAME_COST_LENGTH-1,' ')+'c').content;
break; break;
@ -222,30 +227,36 @@ function Page(service,debug) {
if ((''+int).length > VIEWDATA_FRAME_COST_LENGTH-2) if ((''+int).length > VIEWDATA_FRAME_COST_LENGTH-2)
throw new Error('Cost too large'); throw new Error('Cost too large');
this.__properties__.cost.__properties__.content = bintoattrs(VIEWDATA_BIN_GREEN+padright(int,VIEWDATA_FRAME_COST_LENGTH-2,' ')+'c').content; this.__window__.cost.__properties__.content = bintoattrs(VIEWDATA_BIN_GREEN+padright(int,VIEWDATA_FRAME_COST_LENGTH-2,' ')+'c').content;
break; break;
default: default:
throw new Error(this.service+' type not implemented'); throw new Error(this.__properties__.service+' type not implemented');
} }
}); });
Page.prototype.__defineGetter__('dimensions',function() { Page.prototype.__defineGetter__('dimensions',function() {
return this.width+' X '+this.height; return this.__properties__.width+' X '+this.__properties__.height;
}); });
Page.prototype.__defineGetter__('dynamic_fields',function() { Page.prototype.__defineGetter__('dynamic_fields',function() {
return this.__properties__.dynamic_fields; return this.__properties__.dynamic_fields;
}); });
Page.prototype.__defineSetter__('dynamic_fields',function(array) {
this.__properties__.dynamic_fields = array;
});
Page.prototype.__defineGetter__('height',function() { Page.prototype.__defineGetter__('height',function() {
return Number(this.__properties__.layout.height); return Number(this.__window__.layout.height);
}); });
Page.prototype.__defineGetter__('input_fields',function() { Page.prototype.__defineGetter__('input_fields',function() {
return this.__properties__.input_fields; return this.__properties__.input_fields;
}); });
Page.prototype.__defineSetter__('input_fields',function(array) {
this.__properties__.input_fields = array;
});
Page.prototype.__defineSetter__('isAccessible',function(bool) { Page.prototype.__defineSetter__('isAccessible',function(bool) {
if ((typeof bool !== 'boolean') && (typeof bool !== 'number')) if ((typeof bool !== 'boolean') && (typeof bool !== 'number'))
@ -270,25 +281,25 @@ function Page(service,debug) {
this.__properties__.name = object; this.__properties__.name = object;
switch (this.service) { switch (this.__properties__.service) {
case 'tex': case 'tex':
if ((''+this.name.frame).length > ANSI_FRAME_PAGE_LENGTH-1) if ((''+this.__properties__.name.frame).length > ANSI_FRAME_PAGE_LENGTH-1)
throw new Error('Pagenum too large'); throw new Error('Pagenum too large');
this.__properties__.pagenum.__properties__.content = anstoattrs(ESC+'[1;37m'+this.name.name).content; this.__window__.pagenum.__properties__.content = anstoattrs(ESC+'[1;37m'+this.__properties__.name.name).content;
break; break;
case 'vtx': case 'vtx':
if ((''+this.name.frame).length > VIEWDATA_FRAME_PAGE_LENGTH-2) if ((''+this.__properties__.name.frame).length > VIEWDATA_FRAME_PAGE_LENGTH-2)
throw new Error('Pagenum too large'); throw new Error('Pagenum too large');
this.__properties__.pagenum.__properties__.content = bintoattrs(VIEWDATA_BIN_WHITE+this.name.name).content; this.__window__.pagenum.__properties__.content = bintoattrs(VIEWDATA_BIN_WHITE+this.__properties__.name.name).content;
break; break;
default: default:
throw new Error(this.service+' type not implemented'); throw new Error(this.__properties__.service+' type not implemented');
} }
}); });
@ -300,15 +311,15 @@ function Page(service,debug) {
* Determine who the owner of a page is * Determine who the owner of a page is
*/ */
Page.prototype.__defineGetter__('pageowner',function() { Page.prototype.__defineGetter__('pageowner',function() {
log(LOG_DEBUG,'Getting page owner for:'+this.__properties__.name.__properties__.frame); log(LOG_DEBUG,'Getting page owner for:'+this.__properties__.name.frame);
return pageOwner(this.__properties__.name.__properties__.frame).prefix; return pageOwner(this.__properties__.name.frame).prefix;
}); });
Page.prototype.__defineSetter__('provider',function(ansi) { Page.prototype.__defineSetter__('provider',function(ansi) {
var provider; var provider;
switch (this.service) { switch (this.__properties__.service) {
case 'tex': case 'tex':
provider = anstoattrs(ansi+ESC+'[0m').content; provider = anstoattrs(ansi+ESC+'[0m').content;
@ -326,10 +337,10 @@ function Page(service,debug) {
break; break;
default: default:
throw new Error(this.service+' not implemented'); throw new Error(this.__properties__.service+' not implemented');
} }
this.__properties__.provider.__properties__.content = provider; this.__window__.provider.__properties__.content = provider;
}); });
Page.prototype.__defineGetter__('service',function() { Page.prototype.__defineGetter__('service',function() {
@ -349,11 +360,11 @@ function Page(service,debug) {
if (typeof bool !== 'boolean') if (typeof bool !== 'boolean')
throw new Error('showHeader expected a true/false'); throw new Error('showHeader expected a true/false');
this.__properties__.header.__properties__.visible = bool; this.__window__.header.visible = bool;
}); });
Page.prototype.__defineGetter__('width',function() { Page.prototype.__defineGetter__('width',function() {
return Number(this.__properties__.layout.width); return Number(this.__window__.layout.width);
}); });
/** /**
@ -366,7 +377,7 @@ function Page(service,debug) {
throw new Error('Refusing to build without force.'); throw new Error('Refusing to build without force.');
this.build_system_fields(); this.build_system_fields();
this.__compiled__.build = this.__properties__.layout.build(1,1,false); this.__compiled__.build = this.__window__.layout.build(1,1,false);
// Add our dynamic values // Add our dynamic values
var fields = this.dynamic_fields.filter(function(item) { return item.value !== undefined; }); var fields = this.dynamic_fields.filter(function(item) { return item.value !== undefined; });
@ -484,25 +495,25 @@ function Page(service,debug) {
// The current char value // The current char value
var char = (display[y] !== undefined && display[y][x] !== undefined) ? display[y][x] : undefined; var char = (display[y] !== undefined && display[y][x] !== undefined) ? display[y][x] : undefined;
if (debug) if (debug)
log(LOG_DEBUG,' - CHAR : '+(char !== undefined ? char.__properties__.ch : 'undefined')+', ATTR:'+(char !== undefined ? char.__properties__.attr : 'undefined')+', LAST:'+last); log(LOG_DEBUG,' - CHAR : '+(char !== undefined ? char.ch : 'undefined')+', ATTR:'+(char !== undefined ? char.attr : 'undefined')+', LAST:'+last);
if (debug) { if (debug) {
writeln(); writeln();
writeln('-------- ['+x+'] ------'); writeln('-------- ['+x+'] ------');
writeln('y:'+y+',x:'+x+', attr:'+(char !== undefined ? char.__properties__.attr : 'undefined')); writeln('y:'+y+',x:'+x+', attr:'+(char !== undefined ? char.attr : 'undefined'));
} }
if ((color === undefined) || color) { if ((color === undefined) || color) {
// Only write a new attribute if it has changed (and not Videotex) // Only write a new attribute if it has changed (and not Videotex)
if ((this.service === 'vtx') || (last === undefined) || (last !== char.__properties__.attr)) { if ((this.service === 'vtx') || (last === undefined) || (last !== char.attr)) {
// The current attribute for this character // The current attribute for this character
attr = (char === undefined) ? undefined : char.attr(last,this.service,debug); attr = (char === undefined) ? undefined : char.attribute(last,this.service,debug);
switch (this.service) { switch (this.service) {
case 'tex': case 'tex':
// If the attribute is null, we'll write our default attribute // If the attribute is null, we'll write our default attribute
if (attr === null) if (attr === null)
line += this.__defaults__.attr line += this.attr
else else
line += (attr !== undefined) ? attr : ''; line += (attr !== undefined) ? attr : '';
@ -525,13 +536,13 @@ function Page(service,debug) {
// For no-color output and ViewData, we'll render a character // For no-color output and ViewData, we'll render a character
} else { } else {
if ((this.service === 'vtx') && char.__properties__.attr) if ((this.service === 'vtx') && char.attr)
line += '^'; line += '^';
} }
if (char.ch !== undefined) { if (char.ch !== undefined) {
if (debug) if (debug)
log(LOG_DEBUG,' = SEND CHAR :'+char.ch+', attr:'+char.__properties__.attr+', last:'+last); log(LOG_DEBUG,' = SEND CHAR :'+char.ch+', attr:'+char.attr+', last:'+last);
line += (char.ch !== null) ? char.ch : ''; line += (char.ch !== null) ? char.ch : '';
@ -541,7 +552,7 @@ function Page(service,debug) {
line += ' '; line += ' ';
} }
last = (char.__properties__.attr === undefined) ? undefined : char.__properties__.attr; last = (char.attr === undefined) ? undefined : char.attr;
} }
result.push(line); result.push(line);
@ -611,36 +622,36 @@ function Page(service,debug) {
} }
write('['); write('[');
if (display[y][x].__properties__.attr === undefined) { if (display[y][x].attr === undefined) {
// NOOP // NOOP
} else if (display[y][x].__properties__.attr === null) { } else if (display[y][x].attr === null) {
// NOOP // NOOP
} else { } else {
try { try {
write((last === display[y][x].__properties__.attr) ? '' : display[y][x].__properties__.attr); write((last === display[y][x].attr) ? '' : display[y][x].attr);
} catch (e) { } catch (e) {
writeln(); writeln();
writeln('error:'+e); writeln('error:'+e);
writeln(' y:'+y); writeln(' y:'+y);
writeln(' x:'+x); writeln(' x:'+x);
writeln(JSON.stringify(display[y][x].__properties__.attr)); writeln(JSON.stringify(display[y][x].attr));
exit(1); exit(1);
} }
} }
write(':'); write(':');
if (display[y][x].__properties__.ch === undefined) { if (display[y][x].ch === undefined) {
// NOOP - No window filled a character at this location // NOOP - No window filled a character at this location
write((display[y][x].__properties__.attr === undefined) ? '--' : ''); write((display[y][x].attr === undefined) ? '--' : '');
} else if (display[y][x].__properties__.ch === null) { } else if (display[y][x].ch === null) {
// NOOP // NOOP
} else { } else {
write('_'+display[y][x].__properties__.ch); write('_'+display[y][x].ch);
} }
write(']'); write(']');
last = display[y][x].__properties__.attr; last = display[y][x].attr;
xx++; xx++;
} }
@ -661,9 +672,9 @@ function Page(service,debug) {
var xx = 1; var xx = 1;
for (var x in display[y]) { for (var x in display[y]) {
var attr = display[y][x].__properties__.attr; var attr = display[y][x].attr;
writeln('X:'+(xx++)+'|'+attr+':'+display[y][x].__properties__.ch+'|'+display[y][x].attr(last,this.service,debug)); writeln('X:'+(xx++)+'|'+attr+':'+display[y][x].ch+'|'+display[y][x].attribute(last,this.service,debug));
// Only write a new attribute if it has changed // Only write a new attribute if it has changed
if ((this.last === undefined) || (this.last !== attr)) { if ((this.last === undefined) || (this.last !== attr)) {
@ -750,7 +761,7 @@ function Page(service,debug) {
if (!(page instanceof PageObject)) if (!(page instanceof PageObject))
throw new Error('page must be a PageObject'); throw new Error('page must be a PageObject');
return this.load(system.mods_dir+'ansitex/text/'+page.name+'.'+ext); return this.import(system.mods_dir+'ansitex/text/'+page.name+'.'+ext);
} }
/** /**
@ -772,18 +783,20 @@ function Page(service,debug) {
/** /**
* Load a frame from a file * Load a frame from a file
* *
* @param filename - Name of file to load page from * @param filename - Name of file to load page from (SBBS default dir is CTRL, so relative to it)
* @param width - Width to build window (not required for ANS) * @param width - Width to build window (not required for ANS)
* @param height - Height to build window (not required for ANS) * @param height - Height to build window (not required for ANS)
* @returns {boolean} * @returns {boolean}
* @todo Dont allow load() to load a Viewdata frame for an ANSItex session and visa-versa. * @todo Dont allow load() to load a Viewdata frame for an ANSItex session and visa-versa.
*/ */
this.load = function(filename,width,height) { this.import = function(filename,width,height) {
log(LOG_DEBUG,'Loading frame: ['+filename+']'); log(LOG_DEBUG,' - Importing frame: ['+filename+']');
var f = new File(filename); var f = new File(filename);
if (! f.exists || ! f.open('rb',true)) if (! f.exists || ! f.open('rb',true)) {
log(LOG_ERROR,' ? File doesnt exist: ['+filename+']');
return null; return null;
}
var contents = f.read(); var contents = f.read();
f.close(); f.close();
@ -856,12 +869,12 @@ function Page(service,debug) {
switch (ext) { switch (ext) {
// ANSI files // ANSI files
case 'ans': case 'ans':
var page = anstoattrs(contents,this.width,this.__properties__.content.y,this.__properties__.content.x); var page = anstoattrs(contents,this.width,this.__window__.body.y,this.__window__.body.x);
this.__properties__.content.__properties__.content = page.content; this.__window__.body.__properties__.content = page.content;
this.__properties__.dynamic_fields = page.dynamic_fields; this.dynamic_fields = page.dynamic_fields;
// Our fields are sorted in x descending order // Our fields are sorted in x descending order
this.__properties__.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; }); this.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; });
break; break;
@ -879,16 +892,16 @@ function Page(service,debug) {
log(LOG_INFO,'- Parsing content'); log(LOG_INFO,'- Parsing content');
//log(LOG_ERROR,'Frame content: '+JSON.stringify(base64_decode(load[SAVED_FRAME_ATTRS[property]]))); //log(LOG_ERROR,'Frame content: '+JSON.stringify(base64_decode(load[SAVED_FRAME_ATTRS[property]])));
if (ext === 'tex') if (ext === 'tex')
var page = anstoattrs(base64_decode(load[SAVED_FRAME_ATTRS[property]]).replace("\x0a\x0d\x0a\x0d","\x0a\x0d"),this.width,this.__properties__.content.y,this.__properties__.content.x); var page = anstoattrs(base64_decode(load[SAVED_FRAME_ATTRS[property]]).replace("\x0a\x0d\x0a\x0d","\x0a\x0d"),this.width,this.__window__.body.y,this.__window__.body.x);
else if (ext == 'vtx') else if (ext === 'vtx')
var page = bintoattrs(base64_decode(load[SAVED_FRAME_ATTRS[property]]),this.width,this.__properties__.content.y,this.__properties__.content.x); var page = bintoattrs(base64_decode(load[SAVED_FRAME_ATTRS[property]]),this.width,this.__window__.body.y,this.__window__.body.x);
//log(LOG_ERROR,'Frame content: '+JSON.stringify(page)); //log(LOG_ERROR,'Frame content: '+JSON.stringify(page));
this.__properties__.content.__properties__.content = page.content; this.__window__.body.__properties__.content = page.content;
this.__properties__.dynamic_fields = page.dynamic_fields; this.dynamic_fields = page.dynamic_fields;
// Our fields are sorted in x descending order // Our fields are sorted in x descending order
if (page.input_fields.length) if (page.input_fields.length)
this.__properties__.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; }); this.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; });
log(LOG_INFO,'- Parsing content complete'); log(LOG_INFO,'- Parsing content complete');
break; break;
@ -898,16 +911,16 @@ function Page(service,debug) {
break; break;
case 'frame': case 'frame':
this.__properties__.name.frame = ''+load[SAVED_FRAME_ATTRS[property]]; this.name.frame = ''+load[SAVED_FRAME_ATTRS[property]];
break; break;
case 'input_fields': case 'input_fields':
if (load[SAVED_FRAME_ATTRS[property]]) if (load[SAVED_FRAME_ATTRS[property]])
this.__properties__.input_fields = load[SAVED_FRAME_ATTRS[property]]; this.input_fields = load[SAVED_FRAME_ATTRS[property]];
break; break;
case 'index': case 'index':
this.__properties__.name.index = load[SAVED_FRAME_ATTRS[property]]; this.name.index = load[SAVED_FRAME_ATTRS[property]];
break; break;
case 'version': case 'version':
@ -945,12 +958,12 @@ function Page(service,debug) {
// ViewData files // ViewData files
case 'bin': case 'bin':
var page = bintoattrs(contents,this.width,this.__properties__.content.y,this.__properties__.content.x,debug); var page = bintoattrs(contents,this.width,this.__window__.body.y,this.__window__.body.x,debug);
this.__properties__.content.__properties__.content = page.content; this.__window__.body.__properties__.content = page.content;
this.__properties__.dynamic_fields = page.dynamic_fields; this.dynamic_fields = page.dynamic_fields;
// Our fields are sorted in x descending order // Our fields are sorted in x descending order
this.__properties__.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; }); this.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; });
break; break;
@ -982,13 +995,13 @@ function Page(service,debug) {
switch (this.service) { switch (this.service) {
case 'tex': case 'tex':
this.__properties__.pagenum.__properties__.content = anstoattrs(ESC+'[1;37m'+this.name.name).content; this.__window__.pagenum.__properties__.content = anstoattrs(ESC+'[1;37m'+this.name.name).content;
this.provider = base64_decode(po.logoans); this.provider = base64_decode(po.logoans);
break; break;
case 'vtx': case 'vtx':
this.__properties__.pagenum.__properties__.content = bintoattrs(VIEWDATA_BIN_WHITE+this.name.name).content; this.__window__.pagenum.__properties__.content = bintoattrs(VIEWDATA_BIN_WHITE+this.name.name).content;
this.provider = base64_decode(po.logovtx); this.provider = base64_decode(po.logovtx);
break; break;
@ -1027,7 +1040,7 @@ function Page(service,debug) {
// Line intro // Line intro
write('\x1b[0m'); write('\x1b[0m');
line = this.__properties__.layout.drawline(1,this.width,y,false); line = this.__window__.layout.drawline(1,this.width,y,false);
write(line.content); write(line.content);
write('\x1b[0m'); write('\x1b[0m');
@ -1035,6 +1048,8 @@ function Page(service,debug) {
writeln(); writeln();
} }
} }
init.apply(this,arguments);
} }
function PageObject(frame,index) { function PageObject(frame,index) {
@ -1046,11 +1061,13 @@ function PageObject(frame,index) {
function init(frame,index) { function init(frame,index) {
if (typeof frame === 'object') { if (typeof frame === 'object') {
this.__properties__.frame = frame.frame; this.__properties__.frame = frame.frame;
this.__properties__.index = frame.index; this.index = frame.index;
} else { } else {
this.__properties__.frame = frame; this.__properties__.frame = frame;
this.__properties__.index = index;
if (index)
this.index = index;
} }
} }
@ -1081,16 +1098,16 @@ function PageObject(frame,index) {
}); });
PageObject.prototype.__defineGetter__('name',function() { PageObject.prototype.__defineGetter__('name',function() {
return (this.__properties__.frame && this.__properties__.index) ? this.frame+this.index : null; return (this.frame && this.index) ? this.frame+this.index : null;
}); });
PageObject.prototype.__defineGetter__('next',function() { PageObject.prototype.__defineGetter__('next',function() {
var next = undefined; var next = undefined;
if (this.__properties__.index !== 'z') { if (this.index !== 'z') {
log(LOG_DEBUG,'page_next: Current page:'+this.__properties__.frame+', current index:'+this.__properties__.index); log(LOG_DEBUG,'page_next: Current page:'+this.frame+', current index:'+this.index);
next = new PageObject(this.__properties__.frame,String.fromCharCode(this.__properties__.index.charCodeAt(0)+1)); next = new PageObject(this.frame,String.fromCharCode(this.index.charCodeAt(0)+1));
} }
return next; return next;

View File

@ -110,36 +110,34 @@ function Window(x,y,width,height,name,parent,debug) {
this.name = name; this.name = name;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.__properties__.width = this.__properties__.canvaswidth = width; this.width = this.canvaswidth = width;
this.__properties__.height = this.__properties__.canvasheight = height; this.height = this.canvasheight = height;
if (debug) { if (debug) {
this.__properties__.canvaswidth = width*2; this.canvaswidth = width*2;
this.__properties__.canvasheight = height*2; this.canvasheight = height*2;
} }
// Fill with data // Fill with data
for(var y=1;y<=this.__properties__.canvasheight;y++) { for(var y=1;y<=this.canvasheight;y++) {
for(var x=1;x<=this.__properties__.canvaswidth;x++) { for(var x=1;x<=this.canvaswidth;x++) {
if (this.__properties__.content[y] == undefined) if (this.content[y] === undefined)
this.__properties__.content[y] = []; this.content[y] = [];
this.__properties__.content[y][x] = debug this.content[y][x] = debug
? new Char((x > this.width) || (y > this.height) ? this.name[0].toUpperCase() : this.name[0].toLowerCase(),undefined) ? new Char((x > this.width) || (y > this.height) ? this.name[0].toUpperCase() : this.name[0].toLowerCase(),undefined)
: new Char(undefined,undefined); : new Char(undefined,undefined);
} }
} }
} }
init.apply(this,arguments);
// Windows boundary (right most width) of parent [1..] // Windows boundary (right most width) of parent [1..]
Window.prototype.__defineGetter__('bx',function() { Window.prototype.__defineGetter__('bx',function() {
return this.x+this.width-1; return this.__properties__.x+this.__properties__.width-1;
}); });
// Windows boundary (bottom most height) of parent [1..] // Windows boundary (bottom most height) of parent [1..]
Window.prototype.__defineGetter__('by',function() { Window.prototype.__defineGetter__('by',function() {
return this.y+this.height-1; return this.__properties__.y+this.__properties__.height-1;
}); });
/* /*
@ -155,7 +153,7 @@ function Window(x,y,width,height,name,parent,debug) {
// Management of children objects, in highest z order // Management of children objects, in highest z order
Window.prototype.__defineGetter__('child',function() { Window.prototype.__defineGetter__('child',function() {
// Return the children sorted in z order lowest to highest // 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); }); return this.__relations__.child.sort(function(a,b) { return (a.__properties__.z < b.__properties__.z) ? -1 : ((b.__properties__.z < a.__properties__.z) ? 1 : 0); });
}); });
Window.prototype.__defineSetter__('child',function(obj) { Window.prototype.__defineSetter__('child',function(obj) {
if(obj instanceof Window) { if(obj instanceof Window) {
@ -165,6 +163,39 @@ function Window(x,y,width,height,name,parent,debug) {
throw new Error('child not an instance of Window()'); throw new Error('child not an instance of Window()');
}); });
// Window content
Window.prototype.__defineGetter__('content',function() {
return this.__properties__.content;
});
Window.prototype.__defineSetter__('content',function(string) {
if (this.__properties__.content)
throw new Error('content already DEFINED');
return this.__properties__.content = string;
});
// Window canvas height
Window.prototype.__defineGetter__('canvasheight',function() {
return this.__properties__.canvasheight;
});
Window.prototype.__defineSetter__('canvasheight',function(int) {
if (this.__properties__.canvasheight)
throw new Error('canvasheight already DEFINED');
return this.__properties__.canvasheight = int;
});
// Window canvas width
Window.prototype.__defineGetter__('canvaswidth',function() {
return this.__properties__.canvaswidth;
});
Window.prototype.__defineSetter__('canvaswidth',function(int) {
if (this.__properties__.canvaswidth)
throw new Error('canvaswidth already DEFINED');
return this.__properties__.canvaswidth = int;
});
// Window name // Window name
Window.prototype.__defineGetter__('name',function() { Window.prototype.__defineGetter__('name',function() {
return this.__properties__.name; return this.__properties__.name;
@ -176,6 +207,26 @@ function Window(x,y,width,height,name,parent,debug) {
return this.__properties__.name = string; return this.__properties__.name = string;
}); });
Window.prototype.__defineGetter__('ox',function() {
return this.__properties__.ox;
});
Window.prototype.__defineSetter__('ox',function(int) {
if (this.__properties__.ox)
throw new Error('ox already DEFINED');
this.__properties__.ox = int;
});
Window.prototype.__defineGetter__('oy',function() {
return this.__properties__.oy;
});
Window.prototype.__defineSetter__('oy',function(int) {
if (this.__properties__.oy)
throw new Error('oy already DEFINED');
this.__properties__.oy = int;
});
// Parent window object // Parent window object
Window.prototype.__defineGetter__('parent',function() { Window.prototype.__defineGetter__('parent',function() {
return this.__relations__.parent; return this.__relations__.parent;
@ -235,6 +286,12 @@ function Window(x,y,width,height,name,parent,debug) {
Window.prototype.__defineGetter__('visible',function() { Window.prototype.__defineGetter__('visible',function() {
return this.__properties__.visible; return this.__properties__.visible;
}); });
Window.prototype.__defineSetter__('visible',function(bool) {
if (typeof bool !== 'boolean')
throw new Error('visible expected a true/false');
this.__properties__.visible = bool;
});
// What position is this window (highest is visible) // What position is this window (highest is visible)
Window.prototype.__defineSetter__('z',function(int) { Window.prototype.__defineSetter__('z',function(int) {
@ -265,12 +322,12 @@ function Window(x,y,width,height,name,parent,debug) {
writeln('yoff :'+yoffset); writeln('yoff :'+yoffset);
writeln('x :'+this.x); writeln('x :'+this.x);
writeln('bx :'+this.bx) writeln('bx :'+this.bx)
writeln('ox :'+this.__properties__.ox); writeln('ox :'+this.ox);
writeln('y :'+this.y); writeln('y :'+this.y);
writeln('by :'+this.by) writeln('by :'+this.by)
writeln('oy :'+this.__properties__.oy); writeln('oy :'+this.oy);
writeln('lines :'+this.__properties__.content.length); writeln('lines :'+this.content.length);
writeln('content:'+JSON.stringify(Object.keys(this.__properties__.content).join(','))); writeln('content:'+JSON.stringify(Object.keys(this.content).join(',')));
} }
if (debug) if (debug)
@ -284,14 +341,14 @@ function Window(x,y,width,height,name,parent,debug) {
for (x=1;x<=this.width;x++) { for (x=1;x<=this.width;x++) {
if (debug) if (debug)
writeln('- Checking :'+this.name+', y:'+(y+this.__properties__.oy)+', x:'+(x+this.__properties__.ox)); writeln('- Checking :'+this.name+', y:'+(y+this.oy)+', x:'+(x+this.ox));
var sx = this.x-1+x+xoffset-1; var sx = this.x-1+x+xoffset-1;
if (display[sy] === undefined) if (display[sy] === undefined)
display[sy] = []; display[sy] = [];
if ((this.__properties__.content[y+this.__properties__.oy] !== undefined) && (this.__properties__.content[y+this.__properties__.oy][x+this.__properties__.ox] !== undefined)) { if ((this.content[y+this.oy] !== undefined) && (this.content[y+this.oy][x+this.ox] !== undefined)) {
display[sy][sx] = this.__properties__.content[y+this.__properties__.oy][x+this.__properties__.ox]; display[sy][sx] = this.content[y+this.oy][x+this.ox];
if (debug) if (debug)
writeln('- storing in y:'+(sy)+', x:'+(sx)+', ch:'+display[sy][sx].ch); writeln('- storing in y:'+(sy)+', x:'+(sx)+', ch:'+display[sy][sx].ch);
@ -375,34 +432,34 @@ function Window(x,y,width,height,name,parent,debug) {
var content = ''; var content = '';
for (x=start;x<=end;x++) { for (x=start;x<=end;x++) {
var rx = this.__properties__.ox+x; var rx = this.ox+x;
var ry = this.__properties__.oy+y; var ry = this.oy+y;
// Check if we have an attribute to draw // Check if we have an attribute to draw
if (! (ry in this.__properties__.content) || ! (rx in this.__properties__.content[ry])) { if (! (ry in this.content) || ! (rx in this.content[ry])) {
content += ' '; content += ' ';
continue; continue;
} }
if (color === undefined || color === true) { if (color === undefined || color === true) {
// Only write a new attribute if it has changed // Only write a new attribute if it has changed
if ((this.last === undefined) || (this.last !== this.__properties__.content[ry][rx].attr)) { if ((this.last === undefined) || (this.last !== this.content[ry][rx].attr)) {
this.last = this.__properties__.content[ry][rx].attr; this.last = this.content[ry][rx].attr;
content += (this.last === null ? BG_BLACK|LIGHTGRAY : this.last); content += (this.last === null ? BG_BLACK|LIGHTGRAY : this.last);
} }
} }
try { try {
content += (this.__properties__.content[ry][rx].ch !== null ? this.__properties__.content[ry][rx].ch : ' '); content += (this.content[ry][rx].ch !== null ? this.content[ry][rx].ch : ' ');
} catch (e) { } catch (e) {
writeln(e); writeln(e);
writeln('---'); writeln('---');
writeln('x:'+(x-this.x)); writeln('x:'+(x-this.x));
writeln('y:'+(y-this.y)); writeln('y:'+(y-this.y));
writeln('ox:'+this.__properties__.ox); writeln('ox:'+this.ox);
writeln('oy:'+this.__properties__.oy); writeln('oy:'+this.oy);
writeln('rx:'+rx); writeln('rx:'+rx);
writeln('ry:'+ry); writeln('ry:'+ry);
exit(); exit();
@ -726,6 +783,8 @@ function Window(x,y,width,height,name,parent,debug) {
return child.visible; return child.visible;
}); });
} }
init.apply(this,arguments);
} }
/** /**
@ -753,13 +812,13 @@ function Char(ch,attr) {
* @param debug - debug mode * @param debug - debug mode
* @returns {string|undefined} * @returns {string|undefined}
*/ */
Char.prototype.attr = function(last,ext,debug) { Char.prototype.attribute = function(last,ext,debug) {
// If our attr is undefined, we'll return // If our attr is undefined, we'll return
if (this.__properties__.attr === undefined) if (this.attr === undefined)
return; return;
// @todo This condition appears to fail? // @todo This condition appears to fail?
if (this.__properties__.attr === null) if (this.attr === null)
throw new Error('Attributes shouldnt be null'); throw new Error('Attributes shouldnt be null');
var ansi = []; var ansi = [];
@ -769,40 +828,40 @@ function Char(ch,attr) {
if (debug) { if (debug) {
writeln(); writeln();
writeln('- last:'+last+', this:'+this.__properties__.attr); writeln('- last:'+last+', this:'+this.attr);
} }
switch (ext) { switch (ext) {
case 'tex': case 'tex':
if (debug) { if (debug) {
writeln(' - this BG_BLACK:'+(this.__properties__.attr & BG_BLACK)); writeln(' - this BG_BLACK:'+(this.attr & BG_BLACK));
writeln(' - last BG_BLACK:'+(last & BG_BLACK)); writeln(' - last BG_BLACK:'+(last & BG_BLACK));
writeln(' - this HIGH:'+(this.__properties__.attr & HIGH)); writeln(' - this HIGH:'+(this.attr & HIGH));
writeln(' - last HIGH:'+(last & HIGH)); writeln(' - last HIGH:'+(last & HIGH));
writeln(' - this BLINK:'+(this.__properties__.attr & BLINK)); writeln(' - this BLINK:'+(this.attr & BLINK));
writeln(' - last BLINK:'+(last & BLINK)); writeln(' - last BLINK:'+(last & BLINK));
} }
if ( if (
(((this.__properties__.attr & BG_BLACK) !== (last & BG_BLACK)) (((this.attr & BG_BLACK) !== (last & BG_BLACK))
|| ((this.__properties__.attr & HIGH) !== (last & HIGH)) || ((this.attr & HIGH) !== (last & HIGH))
|| ((this.__properties__.attr & BLINK) !== (last & BLINK)))) || ((this.attr & BLINK) !== (last & BLINK))))
{ {
ansi.push('0'); ansi.push('0');
last = BG_BLACK|LIGHTGRAY; last = BG_BLACK|LIGHTGRAY;
} }
if ((this.__properties__.attr & HIGH) && ((this.__properties__.attr & HIGH) !== (last & HIGH))) { if ((this.attr & HIGH) && ((this.attr & HIGH) !== (last & HIGH))) {
ansi.push('1'); ansi.push('1');
} }
if ((this.__properties__.attr & BLINK) && ((this.__properties__.attr & BLINK) !== (last & BLINK))) { if ((this.attr & BLINK) && ((this.attr & BLINK) !== (last & BLINK))) {
ansi.push('5'); ansi.push('5');
} }
c = (this.__properties__.attr & 0x07); c = (this.attr & 0x07);
l = (last & 0x07); l = (last & 0x07);
// Foreground // Foreground
@ -838,11 +897,11 @@ function Char(ch,attr) {
ansi.push(r); ansi.push(r);
// Background // Background
if (this.__properties__.attr & 0x70) { if (this.attr & 0x70) {
c = (this.__properties__.attr & 0x70); c = (this.attr & 0x70);
l = (last & 0x70); l = (last & 0x70);
switch (this.__properties__.attr & 0x70) { switch (this.attr & 0x70) {
case BG_BLACK: case BG_BLACK:
r = 40; r = 40;
break; break;
@ -879,8 +938,8 @@ function Char(ch,attr) {
return ansi.length ? (debug ? '': '\x1b')+'['+ansi.join(';')+'m' : undefined; return ansi.length ? (debug ? '': '\x1b')+'['+ansi.join(';')+'m' : undefined;
case 'vtx': case 'vtx':
log(LOG_DEBUG,'+ last:'+last+', attr ('+this.__properties__.attr+')'); log(LOG_DEBUG,'+ last:'+last+', attr ('+this.attr+')');
switch (this.__properties__.attr) { switch (this.attr) {
// \x08 // \x08
case BLINK: case BLINK:
r = VIEWDATA_BLINK; r = VIEWDATA_BLINK;
@ -932,8 +991,8 @@ function Char(ch,attr) {
return '?'; return '?';
default: default:
var mosiac = (this.__properties__.attr & MOSIAC); var mosiac = (this.attr & MOSIAC);
c = (this.__properties__.attr & 0x07); c = (this.attr & 0x07);
// Color control \x00-\x07, \x10-\x17 // Color control \x00-\x07, \x10-\x17
switch (c) { switch (c) {
@ -972,10 +1031,14 @@ function Char(ch,attr) {
return ESC+r; return ESC+r;
default: default:
throw new Error(this.__properties__.type+': has not been implemented'); throw new Error(ext+': has not been implemented');
} }
}; };
Char.prototype.__defineGetter__('attr',function() {
return this.__properties__.attr;
});
Char.prototype.__defineGetter__('ch',function() { Char.prototype.__defineGetter__('ch',function() {
return this.__properties__.ch; return this.__properties__.ch;
}); });

View File

@ -51,6 +51,11 @@ switch (client.socket.local_port) {
require('ansitex/load/session-ansitex.js','SESSION_ANSITEX'); require('ansitex/load/session-ansitex.js','SESSION_ANSITEX');
} }
// @todo Suppress "Read your mail now" at login
// @todo Update message loading to process mystic color codes - this todo shouldnt be here, but placed here so I would see it and move it
// @todo Add "time ago" for messages, as an easier visual of how old it is.
bbs.node_settings &= ~(NM_LOGON_P); // Dont always ask for a password.
/** /**
* This is our main event loop - where we interact with the user. * This is our main event loop - where we interact with the user.
* This loop takes care of first connect (unauthenticated users), or after authentication (main shell). * This loop takes care of first connect (unauthenticated users), or after authentication (main shell).