var FRAME_VIEWDATA = (1<<2); var VIEWDATA_LEFT = ascii(0x08); var VIEWDATA_RIGHT = ascii(0x09); var VIEWDATA_DOWN = ascii(0x0a); // \n var VIEWDATA_UP = ascii(0x0b); var VIEWDATA_CLS = ascii(0x0c); var VIEWDATA_CR = ascii(0x0d); // \r var VIEWDATA_CON = ascii(0x11); var VIEWDATA_COFF = ascii(0x14); var VIEWDATA_HOME = ascii(0x1e); var VIEWDATA_MOSIAC_RED = ascii(27)+ascii(0x51); var VIEWDATA_MOSIAC_GREEN = ascii(27)+ascii(0x52); var VIEWDATA_MOSIAC_YELLOW = ascii(27)+ascii(0x53); var VIEWDATA_MOSIAC_BLUE = ascii(27)+ascii(0x54); var VIEWDATA_MOSIAC_MAGENTA = ascii(27)+ascii(0x55); var VIEWDATA_MOSIAC_CYAN = ascii(27)+ascii(0x56); var VIEWDATA_MOSIAC_WHITE = ascii(27)+ascii(0x57); load('ansitex/load/frame-page.js'); // Our frame object function FrameViewdata() { PageFrame.apply(this,arguments); /* File Extension used for frames */ this.settings.ext = 'vtx'; /* Length of a frame */ this.settings.FRAME_LENGTH = 22; /* Width of a frame */ this.settings.FRAME_WIDTH = 40; /* Size of page owner (length) */ this.settings.FRAME_HEADER = 23; /* Size of page number (length with a-z) */ this.settings.FRAME_PAGENUM = 11; /* Size of cost (length without unit) */ this.settings.FRAME_COST = 3; this.settings.MSG_SENDORNOT = ascii(27)+'BKEY 1 TO SEND, 2 NOT TO SEND'; this.settings.MSG_LOGON = ascii(27)+'BKEY 1 TO LOGON, 2 TO RETURN'; this.settings.MSG_SENT = ascii(27)+'BMESSAGE SENT - KEY _ TO CONTINUE'; this.settings.MSG_NOTSENT = ascii(27)+'BMESSAGE NOT SENT - KEY _ TO CONTINUE'; this.settings.ERR_NO_PARENT = ascii(27)+'APARENT FRAME DOESNT EXIST'; this.settings.ERR_NOT_IMPLEMENTED = ascii(27)+'ANOT IMPLEMENTED YET?'; this.settings.ERR_ROUTE = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08'; this.settings.ERR_METHOD_NOT_EXIST = ascii(27)+'GMISTAKE?'+ascii(27)+'BTRY AGAIN OR TELL US ON *08'; this.settings.ACCESS_DENIED = ascii(27)+'AACCESS DENIED.'; this.settings.ALREADY_MEMBER = ascii(27)+'AALREADY MEMBER OF CUG' this.settings.INACTIVITY = ascii(27)+'AINACTIVITY ALERT, DISCONNECT PENDING...'; this.settings.INACTIVE = ascii(27)+'AINACTIVITY DISCONNECT'; this.settings.NOACTION = ascii(27)+'ANO ACTION PERFORMED'; this.settings.BASESTAR = ascii(27)+'B*'; this.settings.INVALID_CODE = ascii(27)+'AINVAID CODE, PLEASE TRY AGAIN *00'; this.settings.TOKEN_EMAIL = ascii(27)+'ATOKEN EMAILED TO YOU...'; this.settings.TOKEN_SENT = ascii(27)+'ATOKEN SENT, PLEASE ENTER TOKEN'; this.settings.INVALID_EMAIL = ascii(27)+'AINVAID EMAIL, PLEASE TRY AGAIN *00'; this.settings.INVALID_UID = ascii(27)+'AINVAID USER ID, PLEASE TRY AGAIN *00'; this.settings.CANNOT_SEND_TOKEN = ascii(27)+'ACANNOT SEND VALIDATION CODE, PLEASE TRY AGAIN *00'; this.settings.USER_EXISTS = ascii(27)+'AERROR USER EXISTS, PLEASE TRY AGAIN *00'; this.settings.USER_CREATE_ERROR = ascii(27)+'AERROR CREATING USER, PLEASE TRY AGAIN *00'; this.settings.LOGIN_ERROR = ascii(27)+'AERROR LOGGING IN, PLEASE TRY AGAIN *00'; this.settings.CANCEL_MSG = ascii(27)+'BPRESS 2 TO CANCEL'; this.settings.SYS_ERROR = ascii(27)+'ASYS ERR, TRY AGAIN OR TELL US ON *08'; this.settings.LOADING = VIEWDATA_MOSIAC_WHITE+'loading...'; var blp=0; // Length of data on the bottom line /** * Set the attribute at the current position */ this.attr=function(field) { //NOOP } /** * Turn off the cursor */ this.cursorOff=function() { write_raw(VIEWDATA_COFF); this.gotoxy(1,1); } this.cursorOn=function(x,y) { write_raw(VIEWDATA_CON); this.gotoxy(x,y); } // Field backspace, that leaves the field filler char this.fieldbs=function(char) { console.write(VIEWDATA_LEFT+char+VIEWDATA_LEFT); } this.gotoxy=function(x,y) { // @todo This could be optimised to go the shortest route write_raw(VIEWDATA_HOME); if (x>0) write_raw(VIEWDATA_RIGHT.repeat(x)); if (y>0) write_raw(VIEWDATA_DOWN.repeat(y)); } this.strlen=function(str) { return str.replace(/\x1b/g,'').length; }; // Render the frame to the user this.render=function(withHeader) { log(LOG_DEBUG,'- VIEWDATA FRAME'); owner = base64_decode(this.owner); header = VIEWDATA_DOWN; //log(LOG_DEBUG,' - FRAME User: ['+JSON.stringify(user)+']'); // Dont show the page number on system login page if (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1)) { log(LOG_DEBUG,' - Owner: ['+this.pageowner+'] ('+this.strlen(videotex(this.pageownerlogo))+')'); cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -'); header = videotex(this.pageownerlogo)+' '.repeat(this.settings.FRAME_HEADER-this.strlen(videotex(this.pageownerlogo)))+ (this.isAccessible ? ascii(27)+'G' : ascii(27)+'A')+this.page+' '.repeat(this.settings.FRAME_PAGENUM-this.page.length)+ ascii(27)+'B'+' '.repeat(this.settings.FRAME_COST-cost.toString().length+1)+cost; } //console.status |= CON_RAW_IN; write_raw(VIEWDATA_CLS); write_raw(header); return write_raw(videotex(base64_decode(this.content))); }; this.qrcode = function(qr) { // Render the body var qrcode = VIEWDATA_HOME+VIEWDATA_DOWN.repeat(5); var offset = this.settings.FRAME_WIDTH-Math.ceil(qr.size/2)-1; for (var x = -1; x < qr.size; x=x+3) { var line = VIEWDATA_RIGHT.repeat(offset ? offset-1 : 0)+VIEWDATA_MOSIAC_WHITE; for (var y = -1; y < qr.size; y=y+2) { var char = 0; //TL char |= ((x===-1) || (y===-1) || ! qr.getModule(x,y)) ? (1<<0) : (0<<0); //TR char |= ((x===-1) || (y === qr.size-1) || ! qr.getModule(x,y+1)) ? (1<<1) : (0<<1); //ML char |= ((y===-1) || ! qr.getModule(x+1,y)) ? (1<<2) : (0<<2); //MR char |= ((y === qr.size-1) || ! qr.getModule(x+1,y+1)) ? (1<<3) : (0<<3); //BL char |= ((x===qr.size-2) || (y===-1) || ! qr.getModule(x+2,y)) ? (1<<4) : (0<<4); //BR char |= ((x===qr.size-2) || (y === qr.size-1) || ! qr.getModule(x+2,y+1)) ? (1<<5) : (0<<5); char += 0x20; if (char > 0x3f) char += 0x20; line += ascii(char); } // Render the right column if (y%2) line += ascii(0x35); repeat_count = this.settings.FRAME_WIDTH-Math.ceil(qr.size/2)-offset-(offset ? 1 : 2)-(y%2 === 1 ? 0 : 1); qrcode += line+' '.repeat(repeat_count > 0 ? repeat_count : 0); // To fix some terminals where moving right from col 40 doesnt advance to col 1 on the next line qrcode +=VIEWDATA_LEFT+VIEWDATA_CR+VIEWDATA_DOWN; } log(LOG_DEBUG,'WIDTH:'+this.settings.FRAME_WIDTH); log(LOG_DEBUG,'QR :'+(Math.ceil(qr.size/2)+1)); log(LOG_DEBUG,'OFF :'+offset); log(LOG_DEBUG,'Y :'+(y%2 ? 0 : 1)); log(LOG_DEBUG,'X :'+(x%3 ? 0 : 1)); // Render the bottom if (x%3) { line = VIEWDATA_RIGHT.repeat(offset ? offset-1 : 0)+VIEWDATA_MOSIAC_WHITE; for (var y = 0; y < qr.size; y=y+2) { line += ascii(0x23); } // Render the right column if (y%2 === 0) { line += ascii(0x21); } qrcode += line+' '.repeat(repeat_count > 0 ? repeat_count : 0); } write_raw(qrcode); }; this.save=function() { file = system.mods_dir+'ansitex/text/'+this.page+'.tex'; w = new File(file); if (! w.open('w')) { log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+this.page); exit(1); } w.write(JSON.stringify(this)); w.close(); log(LOG_DEBUG,'Saved file: '+this.page+'.tex'); } /** * Send a message to the baseline. * * @param text * @param reposition */ this.sendBaseline=function(text,reposition) { var msg = this.getMessage(text); var x = this.strlen(msg); write_raw(VIEWDATA_HOME+VIEWDATA_UP+msg+ ((blp > x) ? (' '.repeat(blp-x)+(reposition ? VIEWDATA_HOME+VIEWDATA_UP+VIEWDATA_RIGHT.repeat(x) : '')) : '') ); blp = x; } this.clearBaseline=function(reposition) { msg = ''; write_raw(VIEWDATA_HOME+VIEWDATA_UP+msg+ ((blp > msg.length) ? (' '.repeat(blp-msg.length)+(reposition ? VIEWDATA_HOME+VIEWDATA_UP+VIEWDATA_RIGHT.repeat(msg.length) : '')) : '') ); blp = msg.length; } } function videotex(data) { var output = ''; //$output .= ($byte < 32) ? ESC.chr($byte+64) : chr($byte); for (var i = 0; i < data.length; i++) { output += (data.charCodeAt(i) < 32) ? "\x1b"+String.fromCharCode(data.charCodeAt(i)+64) : String.fromCharCode(data.charCodeAt(i)); } return output; } FrameViewdata.prototype = PageFrame.prototype; FrameViewdata.prototype.constructor = FrameViewdata;