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 24 - Status/Command Input (Fixed)
= 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 are pagable when scrolling is false and window canvas.height > window.height and canvas.width = window.width
= @todo When scrolling is disabled, and the canvas is greater than the window, then "nextpage" returns the next frame
= Pageable windows cannot have children [b-z frames], only "CONTENT" is paged
= @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 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
@ -102,13 +105,12 @@ load('ansitex/load/windows.js');
* Pages have the following public functions
* - build - Compile the frame for rendering
* - 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) {
this.__properties__ = {
type: undefined, // Viewdata or ANSItex frame
name: new PageObject,
this.__window__ = {
layout: undefined, // Window - Full page content
header: undefined, // Window - Page Title
@ -116,7 +118,12 @@ function Page(service,debug) {
pagenum: undefined, // Our page number (*)
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
dynamic_fields: [], // Array of our dynamic fields
@ -130,7 +137,7 @@ function Page(service,debug) {
};
this.__compiled__ = {
build: undefined,
build: undefined, // Our page compiled content
};
/*
@ -151,25 +158,25 @@ function Page(service,debug) {
switch (service) {
case 'tex':
this.__properties__.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__.layout = new Window(1,1,ANSI_FRAME_WIDTH,ANSI_FRAME_HEIGHT+1,'LAYOUT',this,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.__properties__.provider = new Window(1,1,ANSI_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__properties__.header,debug);
this.__properties__.pagenum = new Window(57,1,ANSI_FRAME_PAGE_LENGTH,1,'#',this.__properties__.header,debug);
this.__properties__.cost = new Window(71,1,ANSI_FRAME_COST_LENGTH,1,'$',this.__properties__.header,debug);
this.__window__.header = new Window(1,1,ANSI_FRAME_WIDTH,1,'HEADER',this.__window__.layout,debug);
this.__window__.provider = new Window(1,1,ANSI_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__window__.header,debug);
this.__window__.pagenum = new Window(57,1,ANSI_FRAME_PAGE_LENGTH,1,'#',this.__window__.header,debug);
this.__window__.cost = new Window(71,1,ANSI_FRAME_COST_LENGTH,1,'$',this.__window__.header,debug);
break;
case 'vtx':
// @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.__properties__.content = new Window(1,2,VIEWDATA_FRAME_WIDTH,VIEWDATA_FRAME_HEIGHT,'CONTENT',this.__properties__.layout,debug)
this.__window__.layout = new Window(1,1,VIEWDATA_FRAME_WIDTH,VIEWDATA_FRAME_HEIGHT+1,'LAYOUT',this,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.__properties__.provider = new Window(1,1,VIEWDATA_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__properties__.header,debug);
this.__properties__.pagenum = new Window(24,1,VIEWDATA_FRAME_PAGE_LENGTH,1,'#',this.__properties__.header,debug);
this.__properties__.cost = new Window(35,1,VIEWDATA_FRAME_COST_LENGTH,1,'$',this.__properties__.header,debug);
this.__window__.header = new Window(1,1,VIEWDATA_FRAME_WIDTH,1,'HEADER',this.__window__.layout,debug);
this.__window__.provider = new Window(1,1,VIEWDATA_FRAME_PROVIDER_LENGTH,1,'PROVIDER',this.__window__.header,debug);
this.__window__.pagenum = new Window(24,1,VIEWDATA_FRAME_PAGE_LENGTH,1,'#',this.__window__.header,debug);
this.__window__.cost = new Window(35,1,VIEWDATA_FRAME_COST_LENGTH,1,'$',this.__window__.header,debug);
break;
@ -180,8 +187,6 @@ function Page(service,debug) {
this.service = service;
}
init.apply(this,arguments);
// @todo change this to Object.defineProperty() - see session.js
/**
* 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.__properties__.isPublic) ||
(this.__properties__.isAccessible && ! this.__properties__.isPublic && this.isMember) ||
(pageEditor(this.frame))
(pageEditor(this.name.frame))
);
} else {
@ -209,12 +214,12 @@ function Page(service,debug) {
if (typeof int !== 'number')
throw new Error('Cost must be a number');
switch (this.service) {
switch (this.__properties__.service) {
case 'tex':
if ((''+int).length > ANSI_FRAME_COST_LENGTH-1)
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;
@ -222,30 +227,36 @@ function Page(service,debug) {
if ((''+int).length > VIEWDATA_FRAME_COST_LENGTH-2)
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;
default:
throw new Error(this.service+' type not implemented');
throw new Error(this.__properties__.service+' type not implemented');
}
});
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() {
return this.__properties__.dynamic_fields;
});
Page.prototype.__defineSetter__('dynamic_fields',function(array) {
this.__properties__.dynamic_fields = array;
});
Page.prototype.__defineGetter__('height',function() {
return Number(this.__properties__.layout.height);
return Number(this.__window__.layout.height);
});
Page.prototype.__defineGetter__('input_fields',function() {
return this.__properties__.input_fields;
});
Page.prototype.__defineSetter__('input_fields',function(array) {
this.__properties__.input_fields = array;
});
Page.prototype.__defineSetter__('isAccessible',function(bool) {
if ((typeof bool !== 'boolean') && (typeof bool !== 'number'))
@ -270,25 +281,25 @@ function Page(service,debug) {
this.__properties__.name = object;
switch (this.service) {
switch (this.__properties__.service) {
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');
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;
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');
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;
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
*/
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) {
var provider;
switch (this.service) {
switch (this.__properties__.service) {
case 'tex':
provider = anstoattrs(ansi+ESC+'[0m').content;
@ -326,10 +337,10 @@ function Page(service,debug) {
break;
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() {
@ -349,11 +360,11 @@ function Page(service,debug) {
if (typeof bool !== 'boolean')
throw new Error('showHeader expected a true/false');
this.__properties__.header.__properties__.visible = bool;
this.__window__.header.visible = bool;
});
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.');
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
var fields = this.dynamic_fields.filter(function(item) { return item.value !== undefined; });
@ -484,25 +495,25 @@ function Page(service,debug) {
// The current char value
var char = (display[y] !== undefined && display[y][x] !== undefined) ? display[y][x] : undefined;
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) {
writeln();
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) {
// 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
attr = (char === undefined) ? undefined : char.attr(last,this.service,debug);
attr = (char === undefined) ? undefined : char.attribute(last,this.service,debug);
switch (this.service) {
case 'tex':
// If the attribute is null, we'll write our default attribute
if (attr === null)
line += this.__defaults__.attr
line += this.attr
else
line += (attr !== undefined) ? attr : '';
@ -525,13 +536,13 @@ function Page(service,debug) {
// For no-color output and ViewData, we'll render a character
} else {
if ((this.service === 'vtx') && char.__properties__.attr)
if ((this.service === 'vtx') && char.attr)
line += '^';
}
if (char.ch !== undefined) {
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 : '';
@ -541,7 +552,7 @@ function Page(service,debug) {
line += ' ';
}
last = (char.__properties__.attr === undefined) ? undefined : char.__properties__.attr;
last = (char.attr === undefined) ? undefined : char.attr;
}
result.push(line);
@ -611,36 +622,36 @@ function Page(service,debug) {
}
write('[');
if (display[y][x].__properties__.attr === undefined) {
if (display[y][x].attr === undefined) {
// NOOP
} else if (display[y][x].__properties__.attr === null) {
} else if (display[y][x].attr === null) {
// NOOP
} else {
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) {
writeln();
writeln('error:'+e);
writeln(' y:'+y);
writeln(' x:'+x);
writeln(JSON.stringify(display[y][x].__properties__.attr));
writeln(JSON.stringify(display[y][x].attr));
exit(1);
}
}
write(':');
if (display[y][x].__properties__.ch === undefined) {
if (display[y][x].ch === undefined) {
// NOOP - No window filled a character at this location
write((display[y][x].__properties__.attr === undefined) ? '--' : '');
} else if (display[y][x].__properties__.ch === null) {
write((display[y][x].attr === undefined) ? '--' : '');
} else if (display[y][x].ch === null) {
// NOOP
} else {
write('_'+display[y][x].__properties__.ch);
write('_'+display[y][x].ch);
}
write(']');
last = display[y][x].__properties__.attr;
last = display[y][x].attr;
xx++;
}
@ -661,9 +672,9 @@ function Page(service,debug) {
var xx = 1;
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
if ((this.last === undefined) || (this.last !== attr)) {
@ -750,7 +761,7 @@ function Page(service,debug) {
if (!(page instanceof 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
*
* @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 height - Height to build window (not required for ANS)
* @returns {boolean}
* @todo Dont allow load() to load a Viewdata frame for an ANSItex session and visa-versa.
*/
this.load = function(filename,width,height) {
log(LOG_DEBUG,'Loading frame: ['+filename+']');
this.import = function(filename,width,height) {
log(LOG_DEBUG,' - Importing frame: ['+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;
}
var contents = f.read();
f.close();
@ -856,12 +869,12 @@ function Page(service,debug) {
switch (ext) {
// ANSI files
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.__properties__.dynamic_fields = page.dynamic_fields;
this.__window__.body.__properties__.content = page.content;
this.dynamic_fields = page.dynamic_fields;
// 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;
@ -879,16 +892,16 @@ function Page(service,debug) {
log(LOG_INFO,'- Parsing content');
//log(LOG_ERROR,'Frame content: '+JSON.stringify(base64_decode(load[SAVED_FRAME_ATTRS[property]])));
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);
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 = 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')
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));
this.__properties__.content.__properties__.content = page.content;
this.__properties__.dynamic_fields = page.dynamic_fields;
this.__window__.body.__properties__.content = page.content;
this.dynamic_fields = page.dynamic_fields;
// Our fields are sorted in x descending order
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');
break;
@ -898,16 +911,16 @@ function Page(service,debug) {
break;
case 'frame':
this.__properties__.name.frame = ''+load[SAVED_FRAME_ATTRS[property]];
this.name.frame = ''+load[SAVED_FRAME_ATTRS[property]];
break;
case 'input_fields':
if (load[SAVED_FRAME_ATTRS[property]])
this.__properties__.input_fields = load[SAVED_FRAME_ATTRS[property]];
this.input_fields = load[SAVED_FRAME_ATTRS[property]];
break;
case 'index':
this.__properties__.name.index = load[SAVED_FRAME_ATTRS[property]];
this.name.index = load[SAVED_FRAME_ATTRS[property]];
break;
case 'version':
@ -945,12 +958,12 @@ function Page(service,debug) {
// ViewData files
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.__properties__.dynamic_fields = page.dynamic_fields;
this.__window__.body.__properties__.content = page.content;
this.dynamic_fields = page.dynamic_fields;
// 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;
@ -982,13 +995,13 @@ function Page(service,debug) {
switch (this.service) {
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);
break;
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);
break;
@ -1027,7 +1040,7 @@ function Page(service,debug) {
// Line intro
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('\x1b[0m');
@ -1035,6 +1048,8 @@ function Page(service,debug) {
writeln();
}
}
init.apply(this,arguments);
}
function PageObject(frame,index) {
@ -1046,11 +1061,13 @@ function PageObject(frame,index) {
function init(frame,index) {
if (typeof frame === 'object') {
this.__properties__.frame = frame.frame;
this.__properties__.index = frame.index;
this.index = frame.index;
} else {
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() {
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() {
var next = undefined;
if (this.__properties__.index !== 'z') {
log(LOG_DEBUG,'page_next: Current page:'+this.__properties__.frame+', current index:'+this.__properties__.index);
if (this.index !== 'z') {
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;

View File

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

View File

@ -51,6 +51,11 @@ switch (client.socket.local_port) {
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 loop takes care of first connect (unauthenticated users), or after authentication (main shell).