diff --git a/exec/load/chateng.js b/exec/load/chateng.js index 11376f0632fc9808181fd5563cfe2e0384fb5c96..2d910f3bd7f7a33b14da0cf9ead9330ffca099d9 100644 --- a/exec/load/chateng.js +++ b/exec/load/chateng.js @@ -38,200 +38,194 @@ function Chat(key,engine) { while(1) { - if(engine.stream) - { - var packet=engine.stream.receive(); - if(packet<0) exit(); - else if(!packet==0 && (packet.room==engine.room || packet.scope==global_scope)) + engine.receive(); + key=console.inkey(K_NOCRLF|K_NOSPIN|K_NOECHO,5); + if(key) { + engine.processKey(key); + switch(key.toUpperCase()) { - engine.processData(packet.data); + case '\x1b': + engine.exit(); + return false; + default: + key=""; + break; } } - key=console.inkey(K_NOCRLF|K_NOSPIN|K_NOECHO,5); - if(key) engine.processKey(key); - switch(key.toUpperCase()) - { - case '\x1b': - return false; - default: - key=""; - break; - } } } } //*************MAIN ENGINE************* load("commclient.js"); load("scrollbar.js"); +load("graphic.js"); +load("str_cmds.js"); load("nodedefs.js"); +bbs.sys_status |= SS_PAUSEOFF; +oldpass=console.ctrl_key_passthru; -function ChatEngine(root,stream) +function ChatEngine(root) { - const local_color= "\1n\1g"; - const remote_color= "\1n\1c"; - const alert_color= "\1n\1r\1h"; - const notice_color= "\1n\1k\1h"; - const input_color= "\1n\1y"; - const private_color= "\1n\1y"; - const global_color= "\1n\1m"; + const flag_normal= "#"; + const flag_global= "!"; + const flag_private= "%"; + const flag_alert= 2; + const flag_notice= 1; + const flag_message= 0; - var root_dir= (root?root:system.exec_dir); - var scope= normal_scope; - var messages= []; - - this.stream= stream?stream:new ServiceConnection("chat"); - this.buffer= ""; - this.room; - this.fullscreen; - this.columns; - this.rows; - this.x; - this.y; - this.boxed; - this.lined; - this.input_line; - this.scrollbar; + const local_color= "\1n\1g"; + const remote_color= "\1n\1c"; + const alert_color= "\1r\1h"; + const notice_color= "\1n\1y"; + const input_color= "\1n"; + const private_color= "\1y\1h"; + const global_color= "\1n\1m"; + //TODO: the only time this will be used is for storing chat history + //maybe give ALL chat history files their own home, independent of the parent script + var root_dir=(root?root:js.exec_dir); + var stream=new ServiceConnection("chat"); + var scope=flag_normal; + var window=false; + var message=new Object(); + var fullscreen=true; + var scrollbar=false; + var background="\0010"; + var ignore=[]; + this.buffer=""; + this.room="main"; + this.columns=console.screen_columns; + this.rows=console.screen_rows; + this.x=1; + this.y=1; + this.input_line; // USEFUL METHODS - this.init=function(room,input_line,columns,rows,posx,posy,lined,boxed,userlist) //NOTE: DESTROYS BUFFER AND MESSAGE LIST + this.init=function(room,c,r,x,y,bg,ix,iy,iw) //NOTE: DESTROYS BUFFER AND MESSAGE LIST { - //DEFAULT SETTINGS - this.columns=columns?columns: 79; //chat window width - this.rows=rows?rows: 24; //chat window height - this.x=posx?posx: 1; //top left corner x - this.y=posy?posy: 1; //top left corner y - this.lined=lined?lined: false; //frame chat window? (boolean) - this.boxed=boxed?boxed: false; //frame chat window? (boolean) - this.room=room?room: "default"; //room name (for lobby style interface) - this.userlist=userlist?userlist: false; //separate user list window (boolean) - + if(x) this.x=x; //top left corner x + if(y) this.y=y; //top left corner y + if(room) this.room=room; //room name (for lobby style interface) + if(bg) background=bg; this.buffer=""; - messages=[]; - - if(input_line) - { - this.input_line=new InputLine(this.x,this.y+this.rows+1,this.columns,BG_BLACK); - this.fullscreen=false; - this.scrollbar=new Scrollbar(this.x+this.columns,this.y,this.rows,"vertical","\1k"); - } - else this.fullscreen=true; - this.drawLines(); - this.drawBox(); - this.getNotices(); - this.entryMessage(); - - if(!this.stream) - { - log("unable to connect to service..."); + if(c && r) { + fullscreen=false; + this.columns=c; + this.rows=r; + if(this.columns>=console.screen_columns) this.columns=console.screen_columns-1; + scrollbar=new Scrollbar(this.x+this.columns,this.y,this.rows,"vertical","\1k\1h"); + } + if(ix && iy) { + this.input_line=new InputLine(ix,iy,iw?iw:this.columns,bg); + fullscreen=false; + } else if(ix || iy) { + log("invalid input line parameters",LOG_WARNING); return false; } + if(!fullscreen) { + console.ctrlkey_passthru="+ACGKLOPQRTUVWXYZ_"; + bbs.sys_status|=SS_MOFF; + window=new Graphic(this.columns,this.rows,undefined,undefined,true); + } + this.entryMessage(); return true; } + this.exit=function() + { + this.exitMessage(); + stream.close(); + console.ctrlkey_passthru=oldpass; + bbs.sys_status&=~SS_MOFF; + bbs.sys_status&=~SS_PAUSEOFF; + console.attributes=ANSI_NORMAL; + } + this.exitMessage=function() + { + if(user.compare_ars("QUIET")) return false; + var message=user.alias + " disconnected"; + this.send(message,flag_notice); + } this.entryMessage=function() { - var message=user.alias + " has entered the room"; - var data= - { - "scope":scope, - "system":system.qwk_id, - "message":message - }; - var packet= - { - "scope":scope, - "room":this.room, - "type":"chat", - "data":data - }; - this.stream.send(packet); + if(user.compare_ars("QUIET")) return false; + var message=user.alias + " connected"; + this.send(message,flag_notice); } - this.resize=function(x,y,columns,rows) //NOTE: DOES NOT DESTROY BUFFER OR MESSAGE LIST + this.resize=function(x,y,c,r,ix,iy,iw) //NOTE: DOES NOT DESTROY BUFFER OR MESSAGE LIST { - if(this.lined) clearLine(this.columns+2,this.x-1,this.y-1); this.clearChatWindow(); if(x) this.x=x; if(y) this.y=y; - if(columns) this.columns=columns; - if(rows) this.rows=rows; - if(this.input_line) - { - this.input_line.x=this.x; - this.input_line.y=this.y+this.rows+1; + if(c) this.columns=columns; + if(r) this.rows=rows; + if(ix && iy) { + if(!this.input_line) { + this.input_line=new InputLine(ix,iy,iw?iw:this.columns,background); + } else { + this.input_line.x=ix; + this.input_line.y=iy; + this.input_line.width=iw?iw:this.columns; + } + } else { + if(this.input_line) { + this.input_line.x=this.x; + this.input_line.y=this.y+this.rows+1; + this.input_line.width=this.columns; + } + } + if(this.input_line) { + scrollbar=new Scrollbar(this.x+this.columns-1,this.y,this.rows,"vertical",DARKGRAY); } this.redraw(); - this.scrollbar=new Scrollbar(this.x+this.columns,this.y,this.rows,"vertical",this.scrollbar.color); + } + this.ignoreUser=function(alias) + { + if(ignore[alias]==true) ignore[alias]=false; + else ignore[alias]==true; } this.findUser=function(id) { - //return this.stream.findUser(id); + //return stream.findUser(id); } this.clearChatWindow=function() //CLEARS THE ENTIRE CHAT WINDOW { clearBlock(this.x,this.y,this.columns,this.rows); } - this.displayInfo=function(array) //DISPLAYS A TEMPORARY MESSAGE IN THE CHAT WINDOW (NOT STORED) + this.list=function(array,color) //DISPLAYS A TEMPORARY MESSAGE IN THE CHAT WINDOW (NOT STORED) { - this.clearChatWindow(); - var newarray=[]; - for(var l=0;l<array.length;l++) - { - var newlines=this.concat(array[l]); - for(var n=0;n<newlines.length;n++) - { - newarray.push(newlines[n]); - } - } - for(item=0;item<newarray.length;item++) - { - console.gotoxy(this.x,this.y+item); - console.putmsg(newarray[item],P_SAVEATR); - } + for(var i=0;i<array.length;i++) this.display(array[i],color); } this.notice=function(msg) { - this.display(notice_color + msg); + this.display(msg,notice_color); } - this.getNotices=function() + this.alert=function(msg) { - var msgs=stream.getNotices(); - if(!msgs) return false; - stream.notices=[]; - for(var m=0;m<msgs.length;m++) - { - this.notice(msgs[m]); - } - } - this.alert=function(msg) //DISPLAYS A MESSAGE ON THE INPUT LINE (OR CURRENT LINE IN FULLSCREEN MODE) - { - if(this.input_line) - { - this.input_line.clear(); - console.gotoxy(this.input_line.x,this.input_line.y); - } - console.putmsg(alert_color + msg); + this.display(msg,alert_color); } this.redraw=function() { this.clearChatWindow(); - this.drawLines(); - this.drawBox(); this.display(); - this.input_line.clear(); - this.bufferKey(); + this.printBuffer(); } - this.send=function(message) + this.send=function(txt,level,scope,source,target) { - if(!message.length) return false; - var packet=this.packageData(message); - if(!this.stream.send(packet)) - { - this.notice("message could not be sent.."); + if(!level) level=flag_message; + if(!scope) scope=flag_normal; + var packet=new Message(txt,level,scope,source,target); + if(!stream.send(packet)) { + this.alert("message not sent."); + } + } + this.receive=function() + { + var packet=stream.receive(); + if(packet && packet.message) { + this.processData(packet); } - scope=normal_scope; - //this.storeHistory(data.message); } //INTERNAL METHODS @@ -243,7 +237,6 @@ function ChatEngine(root,stream) case '\x00': /* CTRL-@ (NULL) */ case '\x03': /* CTRL-C (Center Line) */ case '\x04': /* CTRL-D (Quick find in SyncEdit)*/ - case '\x09': /* CTRL-I TAB... ToDo expand to spaces */ case '\x0b': /* CTRL-K */ case '\x0c': /* CTRL-L (Insert Line) */ case '\x0e': /* CTRL-N */ @@ -265,255 +258,283 @@ function ChatEngine(root,stream) case '\x1b': /* ESC (This should parse extra ANSI sequences) */ case KEY_LEFT: case KEY_RIGHT: - case '\x02': /* CTRL-B KEY_HOME */ - case '\x05': /* CTRL-E KEY_END */ + break; case KEY_UP: case KEY_DOWN: + case '\x02': /* CTRL-B KEY_HOME */ + case '\x05': /* CTRL-E KEY_END */ + this.showHistory(key); break; case '\b': this.backSpace(); break; case '\r': case '\n': - if(console.strlen(removeSpaces(this.buffer))) - { - this.send(this.buffer); - } - this.resetInput(); + this.submitMessage(); break; - case '!': - if(console.strlen(removeSpaces(this.buffer)) || scope==global_scope) - { - this.bufferKey(key); - } - else - { - scope=global_scope; + case '\x09': /* CTRL-I TAB */ + if(message.scope==flag_global) message.scope=flag_normal; + else message.scope=flag_global; + this.printBuffer(); + break; + case ';': + this.bufferKey(key); + if(this.buffer.length==1 && fullscreen && user.compare_ars("SYSOP")) { + this.getStringCommand() + this.resetInput(); + break; } break; case '@': - if(!user.compare_ars("SYSOP") && !(bbs.sys_status&SS_TMPSYSOP)) - break; + if(!user.compare_ars("SYSOP") && !(bbs.sys_status&SS_TMPSYSOP)) break; default: - if(key) this.bufferKey(key); + this.bufferKey(key); break; } return true; } - this.drawLines=function() + this.getStringCommand=function() { - if(!this.lined) return; - drawLine(this.input_line.x-1,this.input_line.y-1,this.columns+2,"\1k\1h"); - if(this.y>1) drawLine(this.x-1,this.y-1,this.columns+2); - if(this.input_line.y<24) drawLine(this.input_line.x-1,this.input_line.y+1,this.columns+2,"\1k\1h"); + var cmd=console.getstr(); + if(cmd.length>0) { + str_cmds(cmd); + return true; + } else return false; } - this.drawBox=function() + this.submitMessage=function() { - if(!this.boxed) return; - console.gotoxy(this.x-1,this.y-1); - console.putmsg("\1n\1h\xDA"); - drawLine(false,false,this.columns-(8+this.room.length),"\1n\1h"); - console.putmsg("\1n\1h\xB4\1nCHAT\1h: \1n" + this.room + "\1h\xC3\xBF"); - for(line = 0; line<this.rows; line++) - { - console.gotoxy(this.x-1,this.y+line); - printf("\1n\1h\xB3%*s\xB3",this.columns,""); + if(strlen(this.buffer)>0) { + this.send(this.buffer,message.level,message.scope,message.source,message.target); + switch(message.scope) + { + case flag_global: + this.display(this.buffer,global_color,user.alias); + break; + case flag_private: + this.display(this.buffer,private_color,user.alias,message.target); + break; + case flag_normal: + default: + this.display(this.buffer,local_color,user.alias); + break; + } } - console.gotoxy(this.input_line.x-1,this.input_line.y-1); - console.putmsg("\1n\1h\xC3"); - drawLine(false,false,this.columns-7,"\1n\1h"); - console.putmsg("\1n\1h\xB4\1nINPUT\1h\xC3\xB4"); - console.gotoxy(this.input_line.x-1,this.input_line.y); - printf("\1n\1h\xB3%*s\xB3",this.columns,""); - console.gotoxy(this.input_line.x-1,this.input_line.y+1); - console.putmsg("\1n\1h\xC0"); - drawLine(false,false,this.columns,"\1n\1h"); - var spot=console.getxy(); - if(!(spot.y==console.screen_rows && spot.x==console.screen_columns)) console.putmsg("\1n\1h\xD9"); + this.resetInput(); } this.backSpace=function() { - if(this.buffer.length>0) - { - write(console.ansi(ANSI_NORMAL)); - this.buffer=this.buffer.substring(0,this.buffer.length-1); - if(this.fullscreen) - { + if(this.buffer.length>0) { + if(fullscreen) { console.left(); console.cleartoeol(); + this.buffer=this.buffer.substr(0,this.buffer.length-1); + } else if(this.buffer.length<=this.input_line.width) { + this.getInputPosition(); + console.left(); + console.putmsg(" ",P_SAVEATR); + this.buffer=this.buffer.substr(0,this.buffer.length-1); + } else { + this.buffer=this.buffer.substr(0,this.buffer.length-1); + this.printBuffer(); } - this.bufferKey(); + return true; + } else { + return false; } } - this.bufferKey=function(key) //ADD A KEY TO THE USER INPUT BUFFER + this.getInputPosition=function() { - if(!this.fullscreen) - { - var offset=key?1:0; - if(this.buffer.length+offset>this.columns) - { - var overrun=(this.buffer.length+offset-this.columns); + console.gotoxy(this.input_line.x+this.buffer.length,this.input_line.y); + } + this.printBuffer=function() + { + if(!this.buffer.length) return false; + var color=""; + switch(message.scope) { + case flag_global: + color=background + global_color; + break; + case flag_private: + color=background + private_color; + break; + case flag_normal: + default: + color=background + input_color; + break; + } + if(fullscreen) { + console.putmsg(color,P_SAVEATR); + console.write("\r" + this.buffer); + console.cleartoeol(); + } else { + console.gotoxy(this.input_line); + console.putmsg(color,P_SAVEATR); + if(this.buffer.length>this.input_line.width) { + var overrun=(this.buffer.length-this.columns); var truncated=this.buffer.substr(overrun); var disp=truncated; if(disp.indexOf('@')>=0) disp=disp.replace(/@/g,"?"); - console.gotoxy(this.input_line.x,this.input_line.y); - console.putmsg(input_color + disp,P_SAVEATR); - } - else if(!key) - { - console.gotoxy(this.input_line.x,this.input_line.y); - var disp=this.buffer; - if(disp.indexOf('@')>=0) disp=disp.replace(/@/g,"?"); - console.putmsg(input_color + disp,P_SAVEATR); - } - else - { - offset=this.buffer.length; - console.gotoxy(this.input_line.x+offset,this.input_line.y); + console.write(disp); + } else { + console.write(this.buffer); } } - if(key) - { - this.buffer+=key; - if(key=="@") key="?"; - console.putmsg(input_color + key,P_SAVEATR); - } - if(!this.fullscreen && this.buffer.length<this.columns) clearLine(this.columns-this.buffer.length); } - this.display=function(text,color,username) + this.bufferKey=function(key) //ADD A KEY TO THE USER INPUT BUFFER { - var col=color?color:""; - //FOR FULLSCREEN MODE WITH NO INPUT LINE, DISPLAY MESSAGE IN FULL AND RETURN - if(this.fullscreen) - { - if(!text) return; - if(username) console.putmsg("\r" + col + username + ": " + text + "\r\n",P_SAVEATR); - else console.putmsg("\r" + col + text + "\r\n",P_SAVEATR); - if(this.buffer.length) console.putmsg(local_color+this.buffer,P_SAVEATR); + if(!key) return false; + var color=""; + switch(message.scope) { + case flag_global: + color=background + global_color; + break; + case flag_private: + color=background + private_color; + break; + case flag_normal: + default: + color=background + input_color; + break; } - else - { - //FOR ALL OTHER MODES, STORE MESSAGES IN AN ARRAY AND HANDLE WRAPPING - var output=[]; - if(text) - { - if(username) - { - messages.push(col + username+ "\1h: " + col + text); - } - else messages.push(col + text); - } - for(msg in messages) - { - var array=this.concat(messages[msg]); - for(item in array) - { - output.push(array[item]); - } + if(!fullscreen) { + if(this.buffer.length>=this.input_line.width) { + this.buffer+=key; + this.printBuffer(); + return; + } else { + this.getInputPosition(); } - if(output.length>this.rows && this.scrollbar) - { - this.scrollbar.draw(1,1); //SHOW SCROLLBAR AT BOTTOM LIMIT - this.history_index=0; - while(output.length>this.rows) output.shift(); - } - console.gotoxy(this.x,this.y); - for(line in output) + } + this.buffer+=key; + console.putmsg(color,P_SAVEATR); + console.write(key); + } + this.showHistory=function(key) //ACTIVATE MESSAGE HISTORY SCROLLBACK + { + if(!fullscreen && window.length>window.height) { + switch(key) { - //TODO: FIX SINGLE LINE MODE... NOT FUNCTIONAL - if(this.rows==1) console.gotoxy(this.x,this.y); - - else console.gotoxy(this.x,this.y+parseInt(line,10)); - var display=output[line]; - if(user.compare_ars("SYSOP")) - { - if(display.indexOf('@')>=0) display=display.replace(/@/g,"?"); - } - console.putmsg(display,P_SAVEATR); - var length=console.strlen(strip_ctrl(output[line])); - if(length<this.columns) clearLine(this.columns-length); + case '\x02': /* CTRL-B KEY_HOME */ + window.home(); + break; + case '\x05': /* CTRL-E KEY_END */ + window.end(); + break; + case KEY_DOWN: + window.scroll(1); + break; + case KEY_UP: + window.scroll(-1); + break; } + window.draw(this.x,this.y); + scrollbar.draw(window.index,window.length,window.height); } } - this.concat=function(text) //WRAP AND CONCATENATE NEW MESSAGE DATA + this.display=function(text,color,source,target) { - var newarray=[]; - if(console.strlen(text)<=this.columns) newarray.push(text); - else - { - var array=word_wrap(text,this.columns,text.length,false); - array=array.split(/[\r\n$]+/); - for(item in array) - { - if(array[item]!=="") newarray.push(removeSpaces(array[item])); - } + var msg; + if(source) { + msg="\r" + color + source + "\1h: " + color + text + "\r\n"; + } else { + msg="\r" + color + text + "\r\n"; + } + if(fullscreen) { + console.putmsg(msg,P_SAVEATR); + this.printBuffer(); + } else { + window.putmsg(false,false,msg,undefined,true); + window.draw(this.x,this.y); + if(window.length>window.height) scrollbar.draw(window.index,window.length,window.height); + } - return newarray; } this.processData=function(data) { - var intensity=""; - if(data.name==user.alias) intensity="\1h"; + if(ignore[data.source]==true) return false; switch(data.scope) { - case normal_scope: - if(data.name) this.display(data.message,remote_color + intensity,data.name); - else this.display(data.message,alert_color); - break; - case priv_scope: - this.display(data.message,private_color + intensity,data.name); - break; - case global_scope: - this.display(data.message,global_color + intensity,data.name); - break; - default: - log("message scope unknown"); - break; + case flag_private: + if(data.target==user.alias) this.display(data.message,private_color + "\1h",data.source); + break; + case flag_global: + this.display(data.message,global_color + "\1h",data.source); + break; + case flag_normal: + default: + if(!data.source) { + switch(data.level) + { + case flag_alert: + this.display(data.message,alert_color); + break; + case flag_notice: + default: + this.display(data.message,notice_color); + break; + } + } else if(data.source==user.alias) { + this.display(data.message,local_color,data.source); + } else this.display(data.message,remote_color,source); + break; } } - this.packageData=function(message) - { - var data= - { - "scope":scope, - "system":system.qwk_id, - "name":user.alias, - "message":message - }; - var packet= - { - "scope":scope, - "room":this.room, - "type":"chat", - "data":data - }; - this.processData(data); - return packet; - } this.resetInput=function() { - if(!this.fullscreen) this.input_line.clear(); - else - { + if(!fullscreen) this.input_line.clear(); + else { console.left(this.buffer.length); console.cleartoeol(); } this.buffer=""; - scope=normal_scope; + message=new Message(); } } +function Message(txt,level,scope,source,target) +{ + this.txt=txt; + this.level=level; + this.scope=scope; + this.source=source; + this.target=target; +} function InputLine(x,y,width,bg) { this.x=x; this.y=y; this.width=width; this.bg=bg; + this.position; + this.window; + this.buffer=""; - this.clear=function(bg) + this.clear=function(bg) { clearLine(this.width,this.x,this.y,bg?bg:this.bg); + console.gotoxy(this); + } + this.init=function(x,y,w,bg,window) + { + this.x=x; + this.y=y; + this.width=w; + this.bg=bg; + if(window) { + this.window=new Window(x,y,w,3); + this.window.init("\1nINPUT"); + this.x+=1; + this.y+=1; + this.width-=2; + } + } + this.draw=function() + { + if(this.window) { + this.window.draw(); + } + console.gotoxy(this.x,this.y); + console.write(printPadded(this.color + this.buffer,this.width)); } } -