Annotation of sbbs/src/sbbs3/js_console.cpp, revision 1.1.1.2

1.1       root        1: /* js_console.cpp */
                      2: 
                      3: /* Synchronet JavaScript "Console" Object */
                      4: 
1.1.1.2 ! root        5: /* $Id: js_console.cpp,v 1.87 2009/07/19 02:45:18 rswindell Exp $ */
1.1       root        6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
1.1.1.2 ! root       11:  * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html         *
1.1       root       12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include "sbbs.h"
1.1.1.2 ! root       39: #include "js_request.h"
1.1       root       40: 
                     41: #ifdef JAVASCRIPT
                     42: 
                     43: /*****************************/
                     44: /* Console Object Properites */
                     45: /*****************************/
                     46: enum {
                     47:         CON_PROP_STATUS
                     48:        ,CON_PROP_LNCNTR 
1.1.1.2 ! root       49:        ,CON_PROP_COLUMN
1.1       root       50:        ,CON_PROP_ATTR
                     51:        ,CON_PROP_TOS
                     52:        ,CON_PROP_ROWS
                     53:        ,CON_PROP_COLUMNS
                     54:        ,CON_PROP_AUTOTERM
                     55:        ,CON_PROP_TERMINAL
                     56:        ,CON_PROP_WORDWRAP
                     57:        ,CON_PROP_QUESTION
1.1.1.2 ! root       58:        ,CON_PROP_INACTIV_WARN
        !            59:        ,CON_PROP_INACTIV_HANGUP
1.1       root       60:        ,CON_PROP_TIMEOUT                       /* User inactivity timeout reference */
1.1.1.2 ! root       61:        ,CON_PROP_TIMELEFT_WARN         /* low timeleft warning counter */
1.1       root       62:        ,CON_PROP_ABORTED
                     63:        ,CON_PROP_ABORTABLE
                     64:        ,CON_PROP_TELNET_MODE
                     65:        ,CON_PROP_GETSTR_OFFSET
                     66:        ,CON_PROP_CTRLKEY_PASSTHRU
                     67:        /* read only */
                     68:        ,CON_PROP_INBUF_LEVEL
                     69:        ,CON_PROP_INBUF_SPACE
                     70:        ,CON_PROP_OUTBUF_LEVEL
                     71:        ,CON_PROP_OUTBUF_SPACE
                     72: };
                     73: 
                     74: static JSBool js_console_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
                     75: {
                     76:        ulong           val;
                     77:     jsint       tiny;
                     78:        JSString*       js_str;
                     79:        sbbs_t*         sbbs;
                     80: 
                     81:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                     82:                return(JS_FALSE);
                     83: 
                     84:     tiny = JSVAL_TO_INT(id);
                     85: 
                     86:        switch(tiny) {
                     87:                case CON_PROP_STATUS:
                     88:                        val=sbbs->console;
                     89:                        break;
                     90:                case CON_PROP_LNCNTR:
                     91:                        val=sbbs->lncntr;
                     92:                        break;
1.1.1.2 ! root       93:                case CON_PROP_COLUMN:
        !            94:                        val=sbbs->column;
        !            95:                        break;
1.1       root       96:                case CON_PROP_ATTR:
                     97:                        val=sbbs->curatr;
                     98:                        break;
                     99:                case CON_PROP_TOS:
                    100:                        val=sbbs->tos;
                    101:                        break;
                    102:                case CON_PROP_ROWS:
                    103:                        val=sbbs->rows;
                    104:                        break;
                    105:                case CON_PROP_COLUMNS:
                    106:                        val=sbbs->cols;
                    107:                        break;
                    108:                case CON_PROP_AUTOTERM:
                    109:                        val=sbbs->autoterm;
                    110:                        break;
                    111:                case CON_PROP_TERMINAL:
                    112:                        if((js_str=JS_NewStringCopyZ(cx, sbbs->terminal))==NULL)
                    113:                                return(JS_FALSE);
                    114:                        *vp = STRING_TO_JSVAL(js_str);
                    115:                        return(JS_TRUE);
1.1.1.2 ! root      116: 
        !           117:                case CON_PROP_INACTIV_WARN:
        !           118:                        val=sbbs->cfg.sec_warn;
        !           119:                        break;
        !           120:                case CON_PROP_INACTIV_HANGUP:
        !           121:                        val=sbbs->cfg.sec_hangup;
        !           122:                        break;
1.1       root      123:                case CON_PROP_TIMEOUT:
                    124:                        val=sbbs->timeout;
                    125:                        break;
                    126:                case CON_PROP_TIMELEFT_WARN:
                    127:                        val=sbbs->timeleft_warn;
                    128:                        break;
                    129:                case CON_PROP_ABORTED:
                    130:                        *vp=BOOLEAN_TO_JSVAL(INT_TO_BOOL(sbbs->sys_status&SS_ABORT));
                    131:                        return(JS_TRUE);
                    132:                case CON_PROP_ABORTABLE:
                    133:                        *vp=BOOLEAN_TO_JSVAL(INT_TO_BOOL(sbbs->rio_abortable));
                    134:                        return(JS_TRUE);
                    135:                case CON_PROP_TELNET_MODE:
                    136:                        val=sbbs->telnet_mode;
                    137:                        break;
                    138:                case CON_PROP_GETSTR_OFFSET:
                    139:                        val=sbbs->getstr_offset;
                    140:                        break;
                    141:                case CON_PROP_WORDWRAP:
                    142:                        if((js_str=JS_NewStringCopyZ(cx, sbbs->wordwrap))==NULL)
                    143:                                return(JS_FALSE);
                    144:                        *vp = STRING_TO_JSVAL(js_str);
                    145:                        return(JS_TRUE);
                    146:                case CON_PROP_QUESTION:
                    147:                        if((js_str=JS_NewStringCopyZ(cx, sbbs->question))==NULL)
                    148:                                return(JS_FALSE);
                    149:                        *vp = STRING_TO_JSVAL(js_str);
                    150:                        return(JS_TRUE);
                    151:                case CON_PROP_CTRLKEY_PASSTHRU:
                    152:                        val=sbbs->cfg.ctrlkey_passthru;
                    153:                        break;
                    154:                case CON_PROP_INBUF_LEVEL:
                    155:                        val=RingBufFull(&sbbs->inbuf);
                    156:                        break;
                    157:                case CON_PROP_INBUF_SPACE:
                    158:                        val=RingBufFree(&sbbs->inbuf);
                    159:                        break;
                    160:                case CON_PROP_OUTBUF_LEVEL:
                    161:                        val=RingBufFull(&sbbs->outbuf);
                    162:                        break;
                    163:                case CON_PROP_OUTBUF_SPACE:
                    164:                        val=RingBufFree(&sbbs->outbuf);
                    165:                        break;
1.1.1.2 ! root      166: 
1.1       root      167:                default:
                    168:                        return(JS_TRUE);
                    169:        }
                    170: 
                    171:        *vp = INT_TO_JSVAL(val);
                    172: 
                    173:        return(JS_TRUE);
                    174: }
                    175: 
                    176: static JSBool js_console_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
                    177: {
                    178:        int32           val=0;
                    179:     jsint       tiny;
                    180:        sbbs_t*         sbbs;
                    181:        JSString*       str;
1.1.1.2 ! root      182:        jsrefcount      rc;
1.1       root      183: 
                    184:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    185:                return(JS_FALSE);
                    186: 
                    187:     tiny = JSVAL_TO_INT(id);
                    188: 
                    189:        if(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_BOOLEAN(*vp))
                    190:                JS_ValueToInt32(cx, *vp, &val);
                    191: 
                    192:        switch(tiny) {
                    193:                case CON_PROP_STATUS:
                    194:                        sbbs->console=val;
                    195:                        break;
                    196:                case CON_PROP_LNCNTR:
                    197:                        sbbs->lncntr=val;
                    198:                        break;
1.1.1.2 ! root      199:                case CON_PROP_COLUMN:
        !           200:                        sbbs->column=val;
        !           201:                        break;
1.1       root      202:                case CON_PROP_ATTR:
                    203:                        if(JSVAL_IS_STRING(*vp)) {
                    204:                                if((str=JS_ValueToString(cx, *vp))==NULL)
                    205:                                        break;
                    206:                                val=attrstr(JS_GetStringBytes(str));
                    207:                        }
1.1.1.2 ! root      208:                        rc=JS_SUSPENDREQUEST(cx);
1.1       root      209:                        sbbs->attr(val);
1.1.1.2 ! root      210:                        JS_RESUMEREQUEST(cx, rc);
1.1       root      211:                        break;
                    212:                case CON_PROP_TOS:
                    213:                        sbbs->tos=val;
                    214:                        break;
                    215:                case CON_PROP_ROWS:
                    216:                        sbbs->rows=val;
                    217:                        break;
                    218:                case CON_PROP_COLUMNS:
                    219:                        sbbs->cols=val;
                    220:                        break;
                    221:                case CON_PROP_AUTOTERM:
                    222:                        sbbs->autoterm=val;
                    223:                        break;
                    224:                case CON_PROP_TERMINAL:
                    225:                        if((str=JS_ValueToString(cx, *vp))==NULL)
                    226:                                break;
                    227:                        SAFECOPY(sbbs->terminal,JS_GetStringBytes(str));
                    228:                        break;
1.1.1.2 ! root      229:                case CON_PROP_INACTIV_WARN:
        !           230:                        sbbs->cfg.sec_warn = (uint16_t)val;
        !           231:                        break;
        !           232:                case CON_PROP_INACTIV_HANGUP:
        !           233:                        sbbs->cfg.sec_hangup = (uint16_t)val;
        !           234:                        break;
1.1       root      235:                case CON_PROP_TIMEOUT:
                    236:                        sbbs->timeout=val;
                    237:                        break;
                    238:                case CON_PROP_TIMELEFT_WARN:
                    239:                        sbbs->timeleft_warn=val;
                    240:                        break;
                    241:                case CON_PROP_ABORTED:
                    242:                        if(val)
                    243:                                sbbs->sys_status|=SS_ABORT;
                    244:                        else
                    245:                                sbbs->sys_status&=~SS_ABORT;
                    246:                        break;
                    247:                case CON_PROP_ABORTABLE:
                    248:                        sbbs->rio_abortable=val 
                    249:                                ? true:false; // This is a dumb bool conversion to make BC++ happy
                    250:                        break;
                    251:                case CON_PROP_TELNET_MODE:
                    252:                        sbbs->telnet_mode=val;
                    253:                        break;
                    254:                case CON_PROP_GETSTR_OFFSET:
                    255:                        sbbs->getstr_offset=val;
                    256:                        break;
                    257:                case CON_PROP_QUESTION:
                    258:                        if((str=JS_ValueToString(cx, *vp))==NULL)
                    259:                                break;
                    260:                        SAFECOPY(sbbs->question,JS_GetStringBytes(str));
                    261:                        break;
                    262:                case CON_PROP_CTRLKEY_PASSTHRU:
                    263:                        if(JSVAL_IS_STRING(*vp)) {
                    264:                                /* op can be 0 for replace, + for add, or - for remove */
                    265:                                int op=0;
                    266:                                char *s;
                    267:                                char ctrl;
                    268: 
                    269:                                if((str=JS_ValueToString(cx, *vp))==NULL)
                    270:                                        break;
                    271:                                val=sbbs->cfg.ctrlkey_passthru;
                    272:                                for(s=JS_GetStringBytes(str); *s; s++) {
                    273:                                        if(*s=='+')
                    274:                                                op=1;
                    275:                                        else if(*s=='-')
                    276:                                                op=2;
                    277:                                        else {
                    278:                                                if(!op) {
                    279:                                                        val=0;
                    280:                                                        op=1;
                    281:                                                }
                    282:                                                ctrl=toupper(*s);
                    283:                                                ctrl&=0x1f;                     /* Ensure it fits */
                    284:                                                switch(op) {
                    285:                                                        case 1:         /* Add to the set */
                    286:                                                                val |= 1<<ctrl;
                    287:                                                                break;
                    288:                                                        case 2:         /* Remove from the set */
                    289:                                                                val &= ~(1<<ctrl);
                    290:                                                                break;
                    291:                                                }
                    292:                                        }
                    293:                                }
                    294:                        }
                    295:                        sbbs->cfg.ctrlkey_passthru=val;
                    296:                        break;
1.1.1.2 ! root      297: 
1.1       root      298:                default:
                    299:                        return(JS_TRUE);
                    300:        }
                    301: 
                    302:        return(JS_TRUE);
                    303: }
                    304: 
                    305: #define CON_PROP_FLAGS JSPROP_ENUMERATE
                    306: 
                    307: static jsSyncPropertySpec js_console_properties[] = {
                    308: /*              name                           ,tinyid                                         ,flags                  ,ver    */
                    309: 
                    310:        {       "status"                        ,CON_PROP_STATUS                        ,CON_PROP_FLAGS ,310},
                    311:        {       "line_counter"          ,CON_PROP_LNCNTR                        ,CON_PROP_FLAGS ,310},
1.1.1.2 ! root      312:        {       "current_column"        ,CON_PROP_COLUMN                        ,CON_PROP_FLAGS ,315},
1.1       root      313:        {       "attributes"            ,CON_PROP_ATTR                          ,CON_PROP_FLAGS ,310},
                    314:        {       "top_of_screen"         ,CON_PROP_TOS                           ,CON_PROP_FLAGS ,310},
                    315:        {       "screen_rows"           ,CON_PROP_ROWS                          ,CON_PROP_FLAGS ,310},
                    316:        {       "screen_columns"        ,CON_PROP_COLUMNS                       ,CON_PROP_FLAGS ,311},
                    317:        {       "autoterm"                      ,CON_PROP_AUTOTERM                      ,CON_PROP_FLAGS ,310},
                    318:        {       "terminal"                      ,CON_PROP_TERMINAL                      ,CON_PROP_FLAGS ,311},
1.1.1.2 ! root      319:        {       "inactivity_warning",CON_PROP_INACTIV_WARN              ,CON_PROP_FLAGS, 31401},
        !           320:        {       "inactivity_hangup"     ,CON_PROP_INACTIV_HANGUP        ,CON_PROP_FLAGS, 31401},
1.1       root      321:        {       "timeout"                       ,CON_PROP_TIMEOUT                       ,CON_PROP_FLAGS ,310},
                    322:        {       "timeleft_warning"      ,CON_PROP_TIMELEFT_WARN         ,CON_PROP_FLAGS ,310},
                    323:        {       "aborted"                       ,CON_PROP_ABORTED                       ,CON_PROP_FLAGS ,310},
                    324:        {       "abortable"                     ,CON_PROP_ABORTABLE                     ,CON_PROP_FLAGS ,310},
                    325:        {       "telnet_mode"           ,CON_PROP_TELNET_MODE           ,CON_PROP_FLAGS ,310},
                    326:        {       "wordwrap"                      ,CON_PROP_WORDWRAP                      ,JSPROP_ENUMERATE|JSPROP_READONLY ,310},
                    327:        {       "question"                      ,CON_PROP_QUESTION                      ,CON_PROP_FLAGS ,310},
                    328:        {       "getstr_offset"         ,CON_PROP_GETSTR_OFFSET         ,CON_PROP_FLAGS ,311},
                    329:        {       "ctrlkey_passthru"      ,CON_PROP_CTRLKEY_PASSTHRU      ,CON_PROP_FLAGS ,310},
                    330:        {       "input_buffer_level",CON_PROP_INBUF_LEVEL               ,JSPROP_ENUMERATE|JSPROP_READONLY, 312},
                    331:        {       "input_buffer_space",CON_PROP_INBUF_SPACE               ,JSPROP_ENUMERATE|JSPROP_READONLY, 312},
                    332:        {       "output_buffer_level",CON_PROP_OUTBUF_LEVEL             ,JSPROP_ENUMERATE|JSPROP_READONLY, 312},
                    333:        {       "output_buffer_space",CON_PROP_OUTBUF_SPACE             ,JSPROP_ENUMERATE|JSPROP_READONLY, 312},
                    334:        {0}
                    335: };
                    336: 
                    337: #ifdef BUILD_JSDOCS
                    338: static char* con_prop_desc[] = {
                    339:         "status bitfield (see <tt>CON_*</tt> in <tt>sbbsdefs.js</tt> for bit definitions)"
1.1.1.2 ! root      340:        ,"current 0-based line counter (used for automatic screen pause)"
        !           341:        ,"current 0-based column counter (used to auto-increment <i>line_counter</i> when screen wraps)"
1.1       root      342:        ,"current display attributes (set with number or string value)"
1.1.1.2 ! root      343:        ,"set to <i>true</i> if the terminal cursor is already at the top of the screen"
        !           344:        ,"number of remote terminal screen rows (in lines)"
        !           345:        ,"number of remote terminal screen columns (in character cells)"
1.1       root      346:        ,"bitfield of automatically detected terminal settings "
                    347:                "(see <tt>USER_*</tt> in <tt>sbbsdefs.js</tt> for bit definitions)"
                    348:        ,"terminal type description (e.g. 'ANSI')"
1.1.1.2 ! root      349:        ,"number of seconds before displaying warning (Are you really there?) due to user/keyboard inactivity"
        !           350:        ,"number of seconds before disconnection due to user/keyboard inactivity"
        !           351:        ,"user/keyboard inactivity timeout reference value (time_t format)"
        !           352:        ,"number of low time-left (5 or fewer minutes remaining) warnings displayed to user"
1.1       root      353:        ,"input/output has been aborted"
1.1.1.2 ! root      354:        ,"remote output can be asynchronously aborted with Ctrl-C"
        !           355:        ,"current Telnet mode bitfield (see <tt>TELNET_MODE_*</tt> in <tt>sbbsdefs.js</tt> for bit definitions)"
1.1       root      356:        ,"word-wrap buffer (used by getstr) - <small>READ ONLY</small>"
                    357:        ,"current yes/no question (set by yesno and noyes)"
                    358:        ,"cursor position offset for use with <tt>getstr(K_USEOFFSET)</tt>"
                    359:        ,"control key pass-through bitmask, set bits represent control key combinations "
                    360:                "<i>not</i> handled by <tt>inkey()</tt> method "
                    361:                "This may optionally be specified as a string of characters. "
                    362:                "The format of this string is [+-][@-_]. If neither plus nor minus is "
                    363:                "the first character, the value will be replaced by one constructed "
                    364:                "from the string. A + indicates that characters following will be "
                    365:                "added to the set, and a - indicates they should be removed. "
                    366:                "ex: <tt>console.ctrlkey_passthru=\"-UP+AB\"</tt> will clear CTRL-U and "
                    367:                "CTRL-P and set CTRL-A and CTRL-B."
                    368:        ,"number of bytes currently in the input buffer (from the remote client) - <small>READ ONLY</small>"
                    369:        ,"number of bytes available in the input buffer - <small>READ ONLY</small>"
                    370:        ,"number of bytes currently in the output buffer (from the local server) - <small>READ ONLY</small>"
                    371:        ,"number of bytes available in the output buffer - <small>READ ONLY</small>"
                    372:        ,NULL
                    373: };
                    374: #endif
                    375: 
                    376: /**************************/
                    377: /* Console Object Methods */
                    378: /**************************/
                    379: 
                    380: static JSBool
                    381: js_inkey(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    382: {
                    383:        char            key[2];
                    384:        int32           mode=0;
                    385:        int32           timeout=0;
                    386:        sbbs_t*         sbbs;
                    387:     JSString*  js_str;
1.1.1.2 ! root      388:        jsrefcount      rc;
1.1       root      389: 
                    390:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    391:                return(JS_FALSE);
                    392: 
                    393:        if(argc)
                    394:                JS_ValueToInt32(cx,argv[0],&mode);
                    395:        if(argc>1)
                    396:                JS_ValueToInt32(cx,argv[1],&timeout);
1.1.1.2 ! root      397:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      398:        key[0]=sbbs->inkey(mode,timeout);
1.1.1.2 ! root      399:        JS_RESUMEREQUEST(cx, rc);
1.1       root      400:        key[1]=0;
                    401: 
                    402:        if((js_str = JS_NewStringCopyZ(cx, key))==NULL)
                    403:                return(JS_FALSE);
                    404: 
                    405:        *rval = STRING_TO_JSVAL(js_str);
                    406:     return(JS_TRUE);
                    407: }
                    408: 
                    409: static JSBool
                    410: js_getkey(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    411: {
                    412:        char            key[2];
                    413:        int32           mode=0;
                    414:        sbbs_t*         sbbs;
                    415:     JSString*  js_str;
1.1.1.2 ! root      416:        jsrefcount      rc;
1.1       root      417: 
                    418:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    419:                return(JS_FALSE);
                    420: 
                    421:        if(argc)
                    422:                JS_ValueToInt32(cx,argv[0],&mode);
1.1.1.2 ! root      423:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      424:        key[0]=sbbs->getkey(mode);
1.1.1.2 ! root      425:        JS_RESUMEREQUEST(cx, rc);
1.1       root      426:        key[1]=0;
                    427: 
                    428:        if((js_str = JS_NewStringCopyZ(cx, key))==NULL)
                    429:                return(JS_FALSE);
                    430: 
                    431:        *rval = STRING_TO_JSVAL(js_str);
                    432:     return(JS_TRUE);
                    433: }
                    434: 
                    435: static JSBool
                    436: js_handle_ctrlkey(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    437: {
                    438:        char            key;
                    439:        int32           mode=0;
                    440:        sbbs_t*         sbbs;
                    441:     JSString*  js_str;
1.1.1.2 ! root      442:        jsrefcount      rc;
1.1       root      443: 
                    444:        *rval = JSVAL_FALSE;
                    445: 
                    446:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    447:                return(JS_FALSE);
                    448: 
                    449:        if(JSVAL_IS_INT(argv[0]))
                    450:                key=(char)JSVAL_TO_INT(argv[0]);
                    451:        else {
                    452:                if((js_str=JS_ValueToString(cx, argv[0]))==NULL)
                    453:                        return(JS_FALSE);
                    454:                key=*JS_GetStringBytes(js_str);
                    455:        }
                    456: 
                    457:        if(argc>1)
                    458:                JS_ValueToInt32(cx, argv[1], &mode);
                    459: 
1.1.1.2 ! root      460:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      461:        *rval = BOOLEAN_TO_JSVAL(sbbs->handle_ctrlkey(key,mode)==0);
1.1.1.2 ! root      462:        JS_RESUMEREQUEST(cx, rc);
1.1       root      463:     return(JS_TRUE);
                    464: }
                    465: 
                    466: static JSBool
                    467: js_getstr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    468: {
                    469:        char            *p;
                    470:        long            mode=0;
                    471:        uintN           i;
                    472:        size_t          maxlen=0;
                    473:        sbbs_t*         sbbs;
                    474:     JSString*  js_str=NULL;
1.1.1.2 ! root      475:        jsrefcount      rc;
1.1       root      476: 
                    477:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    478:                return(JS_FALSE);
                    479: 
                    480:        for(i=0;i<argc;i++) {
                    481:                if(JSVAL_IS_NUMBER(argv[i])) {
                    482:                        if(!maxlen)
                    483:                                JS_ValueToInt32(cx,argv[i],(int32*)&maxlen);
                    484:                        else
                    485:                                JS_ValueToInt32(cx,argv[i],(int32*)&mode);
                    486:                        continue;
                    487:                }
                    488:                if(JSVAL_IS_STRING(argv[i])) {
                    489:                        js_str = JS_ValueToString(cx, argv[i]);
                    490:                        if (!js_str)
                    491:                            return(JS_FALSE);
                    492:                }
                    493:        }
                    494: 
                    495:        if(!maxlen) maxlen=128;
                    496: 
                    497:        if((p=(char *)calloc(1,maxlen+1))==NULL)
                    498:                return(JS_FALSE);
                    499: 
                    500:        if(js_str!=NULL)
                    501:                sprintf(p,"%.*s",(int)maxlen,JS_GetStringBytes(js_str));
                    502: 
1.1.1.2 ! root      503:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      504:        sbbs->getstr(p,maxlen,mode);
1.1.1.2 ! root      505:        JS_RESUMEREQUEST(cx, rc);
1.1       root      506: 
                    507:        js_str = JS_NewStringCopyZ(cx, p);
                    508: 
                    509:        free(p);
                    510: 
                    511:        if(js_str==NULL)
                    512:                return(JS_FALSE);
                    513: 
                    514:        *rval = STRING_TO_JSVAL(js_str);
                    515:     return(JS_TRUE);
                    516: }
                    517: 
                    518: static JSBool
                    519: js_getnum(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    520: {
                    521:        ulong           maxnum=~0;
1.1.1.2 ! root      522:        ulong           dflt=0;
1.1       root      523:        sbbs_t*         sbbs;
1.1.1.2 ! root      524:        jsrefcount      rc;
1.1       root      525: 
                    526:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    527:                return(JS_FALSE);
                    528: 
                    529:        if(argc && JSVAL_IS_NUMBER(argv[0]))
                    530:                JS_ValueToInt32(cx,argv[0],(int32*)&maxnum);
1.1.1.2 ! root      531:        if(argc>1 && JSVAL_IS_NUMBER(argv[1]))
        !           532:                JS_ValueToInt32(cx,argv[1],(int32*)&dflt);
1.1       root      533: 
1.1.1.2 ! root      534:        rc=JS_SUSPENDREQUEST(cx);
        !           535:        *rval = INT_TO_JSVAL(sbbs->getnum(maxnum,dflt));
        !           536:        JS_RESUMEREQUEST(cx, rc);
1.1       root      537:     return(JS_TRUE);
                    538: }
                    539: 
                    540: static JSBool
                    541: js_getkeys(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    542: {
                    543:        char            key[2];
                    544:        uintN           i;
                    545:        long            val;
                    546:        ulong           maxnum=~0;
                    547:        sbbs_t*         sbbs;
                    548:     JSString*  js_str=NULL;
1.1.1.2 ! root      549:        char*           cstr;
        !           550:        jsrefcount      rc;
1.1       root      551: 
                    552:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    553:                return(JS_FALSE);
                    554: 
                    555:        for(i=0;i<argc;i++) {
                    556:                if(JSVAL_IS_NUMBER(argv[i])) {
                    557:                        JS_ValueToInt32(cx,argv[i],(int32*)&maxnum);
                    558:                        continue;
                    559:                }
                    560:                if(JSVAL_IS_STRING(argv[i])) {
                    561:                        js_str = JS_ValueToString(cx, argv[i]);
                    562:                }
                    563:        }
                    564:        if(js_str==NULL)
                    565:                return(JS_FALSE);
                    566: 
1.1.1.2 ! root      567:        cstr=JS_GetStringBytes(js_str);
        !           568:        rc=JS_SUSPENDREQUEST(cx);
        !           569:        val=sbbs->getkeys(cstr,maxnum);
        !           570:        JS_RESUMEREQUEST(cx, rc);
1.1       root      571: 
                    572:        if(val==-1) {                   // abort
                    573:                *rval = INT_TO_JSVAL(0);
                    574:        } else if(val<0) {              // number
                    575:                val&=~0x80000000;
                    576:                *rval = INT_TO_JSVAL(val);
                    577:        } else {                                // key
                    578:                key[0]=(uchar)val;
                    579:                key[1]=0;
                    580:                if((js_str = JS_NewStringCopyZ(cx, key))==NULL)
                    581:                        return(JS_FALSE);
                    582:                *rval = STRING_TO_JSVAL(js_str);
                    583:        }
                    584: 
                    585:     return(JS_TRUE);
                    586: }
                    587: 
                    588: static JSBool
                    589: js_gettemplate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    590: {
                    591:        char            str[128];
                    592:        long            mode=0;
                    593:        uintN           i;
                    594:        sbbs_t*         sbbs;
                    595:     JSString*  js_str=NULL;
                    596:     JSString*  js_fmt=NULL;
1.1.1.2 ! root      597:        jsrefcount      rc;
        !           598:        char*           cstr;
1.1       root      599: 
                    600:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    601:                return(JS_FALSE);
                    602: 
                    603:        for(i=0;i<argc;i++) {
                    604:                if(JSVAL_IS_STRING(argv[i])) {
                    605:                        if(js_fmt==NULL)
                    606:                                js_fmt = JS_ValueToString(cx, argv[i]);
                    607:                        else
                    608:                                js_str = JS_ValueToString(cx, argv[i]);
                    609:                } else if(JSVAL_IS_NUMBER(argv[i]))
                    610:                        JS_ValueToInt32(cx,argv[i],(int32*)&mode);
                    611:        }
                    612: 
                    613:        if(js_fmt==NULL)
                    614:                return(JS_FALSE);
                    615: 
                    616:        if(js_str==NULL)
                    617:                str[0]=0;
                    618:        else
                    619:                SAFECOPY(str,JS_GetStringBytes(js_str));
                    620: 
1.1.1.2 ! root      621:        cstr=JS_GetStringBytes(js_fmt);
        !           622:        rc=JS_SUSPENDREQUEST(cx);
        !           623:        sbbs->gettmplt(str,cstr,mode);
        !           624:        JS_RESUMEREQUEST(cx, rc);
1.1       root      625: 
                    626:        if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
                    627:                return(JS_FALSE);
                    628: 
                    629:        *rval = STRING_TO_JSVAL(js_str);
                    630:     return(JS_TRUE);
                    631: }
                    632: 
                    633: static JSBool
                    634: js_ungetstr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    635: {
                    636:        char*           p;
                    637:        sbbs_t*         sbbs;
                    638:     JSString*  js_str;
1.1.1.2 ! root      639:        jsrefcount      rc;
1.1       root      640: 
                    641:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    642:                return(JS_FALSE);
                    643:        
                    644:        if((js_str=JS_ValueToString(cx, argv[0]))==NULL)
                    645:                return(JS_FALSE);
                    646: 
                    647:        p=JS_GetStringBytes(js_str);
                    648: 
1.1.1.2 ! root      649:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      650:        while(p && *p)
                    651:                sbbs->ungetkey(*(p++));
1.1.1.2 ! root      652:        JS_RESUMEREQUEST(cx, rc);
1.1       root      653:     return(JS_TRUE);
                    654: }
                    655: 
                    656: static JSBool
                    657: js_yesno(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    658: {
                    659:        sbbs_t*         sbbs;
                    660:     JSString*  js_str;
1.1.1.2 ! root      661:        char*           cstr;
        !           662:        jsrefcount      rc;
1.1       root      663: 
                    664:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    665:                return(JS_FALSE);
                    666:        
                    667:        if((js_str=JS_ValueToString(cx, argv[0]))==NULL)
                    668:                return(JS_FALSE);
                    669: 
1.1.1.2 ! root      670:        cstr=JS_GetStringBytes(js_str);
        !           671:        rc=JS_SUSPENDREQUEST(cx);
        !           672:        *rval = BOOLEAN_TO_JSVAL(sbbs->yesno(cstr));
        !           673:        JS_RESUMEREQUEST(cx, rc);
1.1       root      674:     return(JS_TRUE);
                    675: }
                    676: 
                    677: static JSBool
                    678: js_noyes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    679: {
                    680:        sbbs_t*         sbbs;
                    681:     JSString*  js_str;
1.1.1.2 ! root      682:        char*           cstr;
        !           683:        jsrefcount      rc;
1.1       root      684: 
                    685:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    686:                return(JS_FALSE);
                    687:        
                    688:        if((js_str=JS_ValueToString(cx, argv[0]))==NULL)
                    689:                return(JS_FALSE);
                    690: 
1.1.1.2 ! root      691:        cstr=JS_GetStringBytes(js_str);
        !           692:        rc=JS_SUSPENDREQUEST(cx);
        !           693:        *rval = BOOLEAN_TO_JSVAL(sbbs->noyes(cstr));
        !           694:        JS_RESUMEREQUEST(cx, rc);
1.1       root      695:     return(JS_TRUE);
                    696: }
                    697: 
                    698: static JSBool
                    699: js_mnemonics(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    700: {
                    701:        sbbs_t*         sbbs;
                    702:     JSString*  js_str;
1.1.1.2 ! root      703:        char*           cstr;
        !           704:        jsrefcount      rc;
1.1       root      705: 
                    706:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    707:                return(JS_FALSE);
                    708: 
                    709:        if((js_str=JS_ValueToString(cx, argv[0]))==NULL)
                    710:                return(JS_FALSE);
                    711:        
1.1.1.2 ! root      712:        cstr=JS_GetStringBytes(js_str);
        !           713:        rc=JS_SUSPENDREQUEST(cx);
        !           714:        sbbs->mnemonics(cstr);
        !           715:        JS_RESUMEREQUEST(cx, rc);
1.1       root      716:     return(JS_TRUE);
                    717: }
                    718: 
                    719: static void
                    720: js_set_attr(JSContext* cx, sbbs_t* sbbs, jsval val)
                    721: {
                    722:        int32           attr;
1.1.1.2 ! root      723:        jsrefcount      rc;
1.1       root      724: 
                    725:        if(JSVAL_IS_STRING(val))
                    726:                attr=attrstr(js_ValueToStringBytes(cx,val,NULL));
                    727:        else
                    728:                JS_ValueToInt32(cx, val, &attr);
                    729: 
1.1.1.2 ! root      730:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      731:        sbbs->attr(attr);
1.1.1.2 ! root      732:        JS_RESUMEREQUEST(cx, rc);
1.1       root      733: }
                    734: 
                    735: static JSBool
                    736: js_clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    737: {
                    738:        sbbs_t*         sbbs;
1.1.1.2 ! root      739:        jsrefcount      rc;
1.1       root      740: 
                    741:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    742:                return(JS_FALSE);
                    743: 
                    744:        if(argc)
                    745:                js_set_attr(cx, sbbs, argv[0]);
                    746: 
1.1.1.2 ! root      747:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      748:        sbbs->CLS;
1.1.1.2 ! root      749:        JS_RESUMEREQUEST(cx, rc);
1.1       root      750:     return(JS_TRUE);
                    751: }
                    752: 
                    753: static JSBool
                    754: js_clearline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    755: {
                    756:        sbbs_t*         sbbs;
1.1.1.2 ! root      757:        jsrefcount      rc;
1.1       root      758: 
                    759:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    760:                return(JS_FALSE);
                    761: 
                    762:        if(argc)
                    763:                js_set_attr(cx, sbbs, argv[0]);
                    764: 
1.1.1.2 ! root      765:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      766:        sbbs->clearline();
1.1.1.2 ! root      767:        JS_RESUMEREQUEST(cx, rc);
1.1       root      768:     return(JS_TRUE);
                    769: }
                    770: 
                    771: static JSBool
                    772: js_cleartoeol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    773: {
                    774:        sbbs_t*         sbbs;
1.1.1.2 ! root      775:        jsrefcount      rc;
1.1       root      776: 
                    777:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    778:                return(JS_FALSE);
                    779: 
                    780:        if(argc)
                    781:                js_set_attr(cx, sbbs, argv[0]);
                    782: 
1.1.1.2 ! root      783:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      784:        sbbs->cleartoeol();
1.1.1.2 ! root      785:        JS_RESUMEREQUEST(cx, rc);
1.1       root      786:     return(JS_TRUE);
                    787: }
                    788: 
                    789: static JSBool
                    790: js_crlf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    791: {
                    792:        sbbs_t*         sbbs;
1.1.1.2 ! root      793:        jsrefcount      rc;
        !           794:        int32           i;
        !           795:        int32           count=1;
1.1       root      796: 
                    797:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    798:                return(JS_FALSE);
                    799: 
1.1.1.2 ! root      800:        if(argc)
        !           801:                JS_ValueToInt32(cx, argv[0], &count);
        !           802: 
        !           803:        rc=JS_SUSPENDREQUEST(cx);
        !           804:        for(i=0;i<count;i++) {
        !           805:                sbbs->outchar(CR);
        !           806:                sbbs->outchar(LF);
        !           807:        }
        !           808:        JS_RESUMEREQUEST(cx, rc);
1.1       root      809:     return(JS_TRUE);
                    810: }
                    811: 
                    812: static JSBool
                    813: js_pause(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    814: {
                    815:        sbbs_t*         sbbs;
1.1.1.2 ! root      816:        jsrefcount      rc;
1.1       root      817: 
                    818:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    819:                return(JS_FALSE);
                    820: 
1.1.1.2 ! root      821:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      822:        sbbs->pause();
1.1.1.2 ! root      823:        JS_RESUMEREQUEST(cx, rc);
1.1       root      824:     return(JS_TRUE);
                    825: }
                    826: 
                    827: static JSBool
                    828: js_beep(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    829: {
                    830:        sbbs_t*         sbbs;
                    831:        int32           i;
                    832:        int32           count=1;
1.1.1.2 ! root      833:        jsrefcount      rc;
1.1       root      834: 
                    835:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    836:                return(JS_FALSE);
                    837: 
                    838:        if(argc)
                    839:                JS_ValueToInt32(cx, argv[0], &count);
1.1.1.2 ! root      840:        rc=JS_SUSPENDREQUEST(cx);
1.1       root      841:        for(i=0;i<count;i++)
                    842:                sbbs->outchar('\a');
1.1.1.2 ! root      843:        JS_RESUMEREQUEST(cx, rc);
1.1       root      844:        
                    845:     return(JS_TRUE);
                    846: }
                    847: 
                    848: static JSBool
                    849: js_print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    850: {
1.1.1.2 ! root      851:        uintN           i;
1.1       root      852:        sbbs_t*         sbbs;
1.1.1.2 ! root      853:        char*           cstr;
        !           854:        jsrefcount      rc;
1.1       root      855: 
                    856:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    857:                return(JS_FALSE);
                    858: 
1.1.1.2 ! root      859:     for (i = 0; i < argc; i++) {
        !           860:                if((cstr=js_ValueToStringBytes(cx, argv[i], NULL))==NULL)
        !           861:                    return(JS_FALSE);
        !           862:                rc=JS_SUSPENDREQUEST(cx);
        !           863:                sbbs->bputs(cstr);
        !           864:                JS_RESUMEREQUEST(cx, rc);
        !           865:        }
1.1       root      866: 
                    867:     return(JS_TRUE);
                    868: }
                    869: 
                    870: static JSBool
                    871: js_strlen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    872: {
                    873:     JSString*  str;
1.1.1.2 ! root      874:        char*           cstr;
        !           875:        jsrefcount      rc;
1.1       root      876: 
                    877:        if((str=JS_ValueToString(cx, argv[0]))==NULL)
                    878:                return(JS_FALSE);
                    879: 
1.1.1.2 ! root      880:        cstr=JS_GetStringBytes(str);
        !           881:        rc=JS_SUSPENDREQUEST(cx);
        !           882:        *rval = INT_TO_JSVAL(bstrlen(cstr));
        !           883:        JS_RESUMEREQUEST(cx, rc);
1.1       root      884:     return(JS_TRUE);
                    885: }
                    886: 
                    887: static JSBool
                    888: js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    889: {
                    890:        sbbs_t*         sbbs;
1.1.1.2 ! root      891:        uintN           i;
        !           892:        char*           str;
        !           893:        size_t          len;
        !           894:        jsrefcount      rc;
1.1       root      895: 
                    896:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    897:                return(JS_FALSE);
                    898: 
1.1.1.2 ! root      899:     for (i = 0; i < argc; i++) {
        !           900:                if((str=js_ValueToStringBytes(cx, argv[i], &len))==NULL)
        !           901:                    return(JS_FALSE);
        !           902:                rc=JS_SUSPENDREQUEST(cx);
        !           903:                sbbs->rputs(str, len);
        !           904:                JS_RESUMEREQUEST(cx, rc);
        !           905:        }
1.1       root      906: 
                    907:     return(JS_TRUE);
                    908: }
                    909: 
                    910: static JSBool
1.1.1.2 ! root      911: js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !           912: {
        !           913:        sbbs_t*         sbbs;
        !           914: 
        !           915:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
        !           916:                return(JS_FALSE);
        !           917: 
        !           918:        if(argc) {
        !           919:                if(!js_write(cx, obj, argc, argv, rval))
        !           920:                        return(JS_FALSE);
        !           921:        }
        !           922:        sbbs->rputs("\r\n");
        !           923:        return(JS_TRUE);
        !           924: }
        !           925: 
        !           926: static JSBool
1.1       root      927: js_putmsg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    928: {
                    929:        long            mode=0;
                    930:     JSString*  str;
                    931:        sbbs_t*         sbbs;
1.1.1.2 ! root      932:        char*           cstr;
        !           933:        jsrefcount      rc;
1.1       root      934: 
                    935:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    936:                return(JS_FALSE);
                    937: 
                    938:        str = JS_ValueToString(cx, argv[0]);
                    939:        if (!str)
                    940:                return(JS_FALSE);
                    941: 
                    942:        if(argc>1 && JSVAL_IS_NUMBER(argv[1]))
                    943:                JS_ValueToInt32(cx,argv[1],(int32*)&mode);
                    944: 
1.1.1.2 ! root      945:        cstr=JS_GetStringBytes(str);
        !           946:        rc=JS_SUSPENDREQUEST(cx);
        !           947:        sbbs->putmsg(cstr,mode);
        !           948:        JS_RESUMEREQUEST(cx, rc);
1.1       root      949:     return(JS_TRUE);
                    950: }
                    951: 
                    952: static JSBool
                    953: js_printfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    954: {
                    955:        long            mode=0;
                    956:     JSString*  str;
                    957:        sbbs_t*         sbbs;
1.1.1.2 ! root      958:        char*           cstr;
        !           959:        jsrefcount      rc;
1.1       root      960: 
                    961:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    962:                return(JS_FALSE);
                    963: 
                    964:        str = JS_ValueToString(cx, argv[0]);
                    965:        if (!str)
                    966:                return(JS_FALSE);
                    967: 
                    968:        if(argc>1 && JSVAL_IS_NUMBER(argv[1]))
                    969:                JS_ValueToInt32(cx,argv[1],(int32*)&mode);
                    970: 
1.1.1.2 ! root      971:        cstr=JS_GetStringBytes(str);
        !           972:        rc=JS_SUSPENDREQUEST(cx);
        !           973:        sbbs->printfile(cstr,mode);
        !           974:        JS_RESUMEREQUEST(cx, rc);
1.1       root      975:     return(JS_TRUE);
                    976: }
                    977: 
                    978: static JSBool
                    979: js_printtail(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    980: {
                    981:        int                     lines=0;
                    982:        long            mode=0;
                    983:        uintN           i;
                    984:        sbbs_t*         sbbs;
                    985:     JSString*  js_str=NULL;
1.1.1.2 ! root      986:        char*           cstr;
        !           987:        jsrefcount      rc;
1.1       root      988: 
                    989:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                    990:                return(JS_FALSE);
                    991: 
                    992:        for(i=0;i<argc;i++) {
                    993:                if(JSVAL_IS_NUMBER(argv[i])) {
                    994:                        if(!lines)
                    995:                                JS_ValueToInt32(cx,argv[i],(int32*)&lines);
                    996:                        else
                    997:                                JS_ValueToInt32(cx,argv[i],(int32*)&mode);
                    998:                } else if(JSVAL_IS_STRING(argv[i]))
                    999:                        js_str = JS_ValueToString(cx, argv[i]);
                   1000:        }
                   1001: 
                   1002:        if(js_str==NULL)
                   1003:                return(JS_FALSE);
                   1004: 
                   1005:        if(!lines) 
                   1006:                lines=5;
                   1007: 
1.1.1.2 ! root     1008:        cstr=JS_GetStringBytes(js_str);
        !          1009:        rc=JS_SUSPENDREQUEST(cx);
        !          1010:        sbbs->printtail(cstr,lines,mode);
        !          1011:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1012:     return(JS_TRUE);
                   1013: }
                   1014: 
                   1015: static JSBool
                   1016: js_editfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1017: {
                   1018:     JSString*  str;
                   1019:        sbbs_t*         sbbs;
1.1.1.2 ! root     1020:        char*           cstr;
        !          1021:        jsrefcount      rc;
1.1       root     1022: 
                   1023:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1024:                return(JS_FALSE);
                   1025: 
                   1026:        if((str=JS_ValueToString(cx, argv[0]))==NULL)
                   1027:                return(JS_FALSE);
                   1028: 
1.1.1.2 ! root     1029:        cstr=JS_GetStringBytes(str);
        !          1030:        rc=JS_SUSPENDREQUEST(cx);
        !          1031:        *rval = BOOLEAN_TO_JSVAL(sbbs->editfile(JS_GetStringBytes(str)));
        !          1032:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1033:     return(JS_TRUE);
                   1034: }
                   1035: 
                   1036: 
                   1037: static JSBool
                   1038: js_uselect(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1039: {
                   1040:        uintN           i;
                   1041:        int32           num=0;
                   1042:        char*           title=NULL;
                   1043:        char*           item=NULL;
                   1044:        char*           ar_str;
                   1045:        uchar*          ar=NULL;
                   1046:        sbbs_t*         sbbs;
                   1047:     JSString*  js_str;
1.1.1.2 ! root     1048:        jsrefcount      rc;
1.1       root     1049: 
                   1050:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1051:                return(JS_FALSE);
                   1052:        
                   1053:        if(!argc) {
                   1054:                *rval = INT_TO_JSVAL(sbbs->uselect(0,0,NULL,NULL,NULL));
                   1055:                return(JS_TRUE);
                   1056:        }
                   1057:        
                   1058:        for(i=0;i<argc;i++) {
                   1059:                if(JSVAL_IS_NUMBER(argv[i])) {
                   1060:                        JS_ValueToInt32(cx,argv[i],&num);
                   1061:                        continue;
                   1062:                }
                   1063:                if((js_str=JS_ValueToString(cx, argv[i]))==NULL)
                   1064:                        return(JS_FALSE);
                   1065: 
                   1066:                if(title==NULL) 
                   1067:                        title=JS_GetStringBytes(js_str);
                   1068:                else if(item==NULL)
                   1069:                        item=JS_GetStringBytes(js_str);
                   1070:                else {
                   1071:                        ar_str=JS_GetStringBytes(js_str);
                   1072:                        ar=arstr(NULL,ar_str,&sbbs->cfg);
                   1073:                }
                   1074:        }
                   1075: 
1.1.1.2 ! root     1076:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1077:        *rval = INT_TO_JSVAL(sbbs->uselect(1, num, title, item, ar));
1.1.1.2 ! root     1078:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1079:     return(JS_TRUE);
                   1080: }
                   1081: 
                   1082: static JSBool
                   1083: js_center(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1084: {
                   1085:     JSString*  str;
                   1086:        sbbs_t*         sbbs;
1.1.1.2 ! root     1087:        char*           cstr;
        !          1088:        jsrefcount      rc;
1.1       root     1089: 
                   1090:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1091:                return(JS_FALSE);
                   1092: 
                   1093:        str = JS_ValueToString(cx, argv[0]);
                   1094:        if (!str)
                   1095:                return(JS_FALSE);
                   1096: 
1.1.1.2 ! root     1097:        cstr=JS_GetStringBytes(str);
        !          1098:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1099:        sbbs->center(JS_GetStringBytes(str));
1.1.1.2 ! root     1100:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1101:     return(JS_TRUE);
                   1102: }
                   1103: 
                   1104: static JSBool
                   1105: js_saveline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1106: {
                   1107:        sbbs_t*         sbbs;
                   1108: 
                   1109:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1110:                return(JS_FALSE);
                   1111: 
1.1.1.2 ! root     1112:        if(sbbs->slcnt<SAVE_LINES) {
        !          1113:                sbbs->slatr[sbbs->slcnt]=sbbs->latr; 
        !          1114:                sbbs->slcuratr[sbbs->slcnt]=sbbs->curatr;
        !          1115:                sprintf(sbbs->slbuf[sbbs->slcnt],"%.*s",sbbs->lbuflen,sbbs->lbuf);
        !          1116:                sbbs->slcnt++;
        !          1117:                sbbs->lbuflen=0; 
        !          1118:        }
1.1       root     1119:     return(JS_TRUE);
                   1120: }
                   1121: 
                   1122: static JSBool
                   1123: js_restoreline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1124: {
                   1125:        sbbs_t*         sbbs;
1.1.1.2 ! root     1126:        jsrefcount      rc;
1.1       root     1127: 
                   1128:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1129:                return(JS_FALSE);
                   1130: 
1.1.1.2 ! root     1131:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1132:        sbbs->lbuflen=0; 
1.1.1.2 ! root     1133:        if(sbbs->slcnt)
        !          1134:                sbbs->slcnt--;
        !          1135:        sbbs->attr(sbbs->slatr[sbbs->slcnt]);
1.1       root     1136:        sbbs->rputs(sbbs->slbuf[sbbs->slcnt]); 
1.1.1.2 ! root     1137:        sbbs->curatr=sbbs->slcuratr[sbbs->slcnt];
        !          1138:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1139:     return(JS_TRUE);
                   1140: }
                   1141: 
                   1142: static JSBool
                   1143: js_ansi(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1144: {
                   1145:        int32           attr=0;
                   1146:        JSString*       js_str;
                   1147:        sbbs_t*         sbbs;
                   1148: 
                   1149:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1150:                return(JS_FALSE);
                   1151: 
                   1152:        if(argc)
                   1153:                JS_ValueToInt32(cx,argv[0],&attr);
1.1.1.2 ! root     1154:        if(argc>1) {
        !          1155:                int32   curattr=0;
        !          1156:                char    buf[16];
        !          1157: 
        !          1158:                JS_ValueToInt32(cx,argv[0],&curattr);
        !          1159:                if((js_str=JS_NewStringCopyZ(cx,sbbs->ansi(attr,curattr,buf)))==NULL)
        !          1160:                        return(JS_FALSE);
        !          1161:        } else {
        !          1162:                if((js_str=JS_NewStringCopyZ(cx,sbbs->ansi(attr)))==NULL)
        !          1163:                        return(JS_FALSE);
        !          1164:        }
1.1       root     1165: 
                   1166:        *rval = STRING_TO_JSVAL(js_str);
                   1167:     return(JS_TRUE);
                   1168: }
                   1169: 
                   1170: static JSBool
                   1171: js_pushxy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1172: {
                   1173:        sbbs_t*         sbbs;
1.1.1.2 ! root     1174:        jsrefcount      rc;
1.1       root     1175: 
                   1176:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1177:                return(JS_FALSE);
                   1178: 
1.1.1.2 ! root     1179:        rc=JS_SUSPENDREQUEST(cx);
        !          1180:        sbbs->ansi_save();
        !          1181:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1182:     return(JS_TRUE);
                   1183: }
                   1184: 
                   1185: static JSBool
                   1186: js_popxy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1187: {
                   1188:        sbbs_t*         sbbs;
1.1.1.2 ! root     1189:        jsrefcount      rc;
1.1       root     1190: 
                   1191:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1192:                return(JS_FALSE);
                   1193: 
1.1.1.2 ! root     1194:        rc=JS_SUSPENDREQUEST(cx);
        !          1195:        sbbs->ansi_restore();
        !          1196:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1197:     return(JS_TRUE);
                   1198: }
                   1199: 
                   1200: static JSBool
                   1201: js_gotoxy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1202: {
                   1203:        int32           x=1,y=1;
                   1204:        jsval           val;
                   1205:        sbbs_t*         sbbs;
1.1.1.2 ! root     1206:        jsrefcount      rc;
1.1       root     1207: 
                   1208:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1209:                return(JS_FALSE);
                   1210: 
                   1211:        if(JSVAL_IS_OBJECT(argv[0])) {
                   1212:                JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[0]),"x", &val);
                   1213:                JS_ValueToInt32(cx,val,&x);
                   1214:                JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[0]),"y", &val);
                   1215:                JS_ValueToInt32(cx,val,&y);
                   1216:        } else {
                   1217:                JS_ValueToInt32(cx,argv[0],&x);
                   1218:                JS_ValueToInt32(cx,argv[1],&y);
                   1219:        }
                   1220: 
1.1.1.2 ! root     1221:        rc=JS_SUSPENDREQUEST(cx);
        !          1222:        sbbs->ansi_gotoxy(x,y);
        !          1223:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1224:     return(JS_TRUE);
                   1225: }
                   1226: 
                   1227: 
                   1228: static JSBool
                   1229: js_getxy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1230: {
                   1231:        sbbs_t*         sbbs;
                   1232:        int                     x,y;
                   1233:        JSObject*       screen;
1.1.1.2 ! root     1234:        jsrefcount      rc;
1.1       root     1235: 
                   1236:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1237:                return(JS_FALSE);
                   1238:  
1.1.1.2 ! root     1239:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1240:        sbbs->ansi_getxy(&x,&y);
1.1.1.2 ! root     1241:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1242: 
                   1243:        if((screen=JS_NewObject(cx,NULL,NULL,obj))==NULL)
                   1244:                return(JS_TRUE);
                   1245: 
                   1246:        JS_DefineProperty(cx, screen, "x", INT_TO_JSVAL(x)
                   1247:                ,NULL,NULL,JSPROP_ENUMERATE);
                   1248:        JS_DefineProperty(cx, screen, "y", INT_TO_JSVAL(y)
                   1249:                ,NULL,NULL,JSPROP_ENUMERATE);
                   1250: 
                   1251:        *rval = OBJECT_TO_JSVAL(screen);
                   1252:     return(JS_TRUE);
                   1253: }
                   1254: 
                   1255: static JSBool
                   1256: js_cursor_home(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1257: {
                   1258:        sbbs_t*         sbbs;
1.1.1.2 ! root     1259:        jsrefcount      rc;
1.1       root     1260: 
                   1261:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1262:                return(JS_FALSE);
                   1263: 
1.1.1.2 ! root     1264:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1265:        sbbs->cursor_home();
1.1.1.2 ! root     1266:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1267:     return(JS_TRUE);
                   1268: }
                   1269: 
                   1270: static JSBool
                   1271: js_cursor_up(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1272: {
                   1273:        int32           val=1;
                   1274:        sbbs_t*         sbbs;
1.1.1.2 ! root     1275:        jsrefcount      rc;
1.1       root     1276: 
                   1277:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1278:                return(JS_FALSE);
                   1279: 
                   1280:        if(argc)
                   1281:                JS_ValueToInt32(cx,argv[0],&val);
1.1.1.2 ! root     1282:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1283:        sbbs->cursor_up(val);
1.1.1.2 ! root     1284:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1285:     return(JS_TRUE);
                   1286: }
                   1287: 
                   1288: static JSBool
                   1289: js_cursor_down(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1290: {
                   1291:        int32           val=1;
                   1292:        sbbs_t*         sbbs;
1.1.1.2 ! root     1293:        jsrefcount      rc;
1.1       root     1294: 
                   1295:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1296:                return(JS_FALSE);
                   1297: 
                   1298:        if(argc)
                   1299:                JS_ValueToInt32(cx,argv[0],&val);
1.1.1.2 ! root     1300:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1301:        sbbs->cursor_down(val);
1.1.1.2 ! root     1302:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1303:     return(JS_TRUE);
                   1304: }
                   1305: 
                   1306: static JSBool
                   1307: js_cursor_right(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1308: {
                   1309:        int32           val=1;
                   1310:        sbbs_t*         sbbs;
1.1.1.2 ! root     1311:        jsrefcount      rc;
1.1       root     1312: 
                   1313:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1314:                return(JS_FALSE);
                   1315: 
                   1316:        if(argc)
                   1317:                JS_ValueToInt32(cx,argv[0],&val);
1.1.1.2 ! root     1318:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1319:        sbbs->cursor_right(val);
1.1.1.2 ! root     1320:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1321:     return(JS_TRUE);
                   1322: }
                   1323: 
                   1324: static JSBool
                   1325: js_cursor_left(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1326: {
                   1327:        int32           val=1;
                   1328:        sbbs_t*         sbbs;
1.1.1.2 ! root     1329:        jsrefcount      rc;
1.1       root     1330: 
                   1331:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1332:                return(JS_FALSE);
                   1333: 
                   1334:        if(argc)
                   1335:                JS_ValueToInt32(cx,argv[0],&val);
1.1.1.2 ! root     1336:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1337:        sbbs->cursor_left(val);
1.1.1.2 ! root     1338:        JS_RESUMEREQUEST(cx, rc);
        !          1339:     return(JS_TRUE);
        !          1340: }
        !          1341: 
        !          1342: static JSBool
        !          1343: js_backspace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !          1344: {
        !          1345:        sbbs_t*         sbbs;
        !          1346:        jsrefcount      rc;
        !          1347: 
        !          1348:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
        !          1349:                return(JS_FALSE);
        !          1350: 
        !          1351:        rc=JS_SUSPENDREQUEST(cx);
        !          1352:        sbbs->backspace();
        !          1353:        JS_RESUMEREQUEST(cx, rc);
        !          1354:     return(JS_TRUE);
        !          1355: }
        !          1356: 
        !          1357: static JSBool
        !          1358: js_clearkeybuf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        !          1359: {
        !          1360:        sbbs_t*         sbbs;
        !          1361: 
        !          1362:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
        !          1363:                return(JS_FALSE);
        !          1364: 
        !          1365:        sbbs->keybufbot=sbbs->keybuftop=0;
1.1       root     1366:     return(JS_TRUE);
                   1367: }
                   1368: 
                   1369: static JSBool
                   1370: js_getlines(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1371: {
                   1372:        sbbs_t*         sbbs;
1.1.1.2 ! root     1373:        jsrefcount      rc;
1.1       root     1374: 
                   1375:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1376:                return(JS_FALSE);
                   1377: 
1.1.1.2 ! root     1378:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1379:        sbbs->ansi_getlines();
1.1.1.2 ! root     1380:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1381:     return(JS_TRUE);
                   1382: }
                   1383: 
                   1384: static JSBool
                   1385: js_lock_input(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1386: {
                   1387:        sbbs_t*         sbbs;
                   1388:        JSBool          lock=TRUE;
1.1.1.2 ! root     1389:        jsrefcount      rc;
1.1       root     1390: 
                   1391:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1392:                return(JS_FALSE);
                   1393: 
                   1394:        if(argc)
                   1395:                JS_ValueToBoolean(cx, argv[0], &lock);
                   1396: 
1.1.1.2 ! root     1397:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1398:        if(lock) {
                   1399:                pthread_mutex_lock(&sbbs->input_thread_mutex);
                   1400:                sbbs->input_thread_mutex_locked=true;
                   1401:        } else if(sbbs->input_thread_mutex_locked) {
                   1402:                pthread_mutex_unlock(&sbbs->input_thread_mutex);
                   1403:                sbbs->input_thread_mutex_locked=false;
                   1404:        }
1.1.1.2 ! root     1405:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1406: 
                   1407:     return(JS_TRUE);
                   1408: }
                   1409: 
                   1410: static JSBool
                   1411: js_telnet_cmd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1412: {
                   1413:        sbbs_t*         sbbs;
                   1414:        int32           cmd,opt=0;
1.1.1.2 ! root     1415:        jsrefcount      rc;
1.1       root     1416: 
                   1417:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1418:                return(JS_FALSE);
                   1419: 
                   1420:        JS_ValueToInt32(cx,argv[0],&cmd);
                   1421:        if(argc>1)
                   1422:                JS_ValueToInt32(cx,argv[1],&opt);
                   1423: 
1.1.1.2 ! root     1424:        rc=JS_SUSPENDREQUEST(cx);
1.1       root     1425:        sbbs->send_telnet_cmd((uchar)cmd,(uchar)opt);
1.1.1.2 ! root     1426:        JS_RESUMEREQUEST(cx, rc);
1.1       root     1427: 
                   1428:     return(JS_TRUE);
                   1429: }
                   1430: 
                   1431: static JSBool
                   1432: js_term_supports(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                   1433: {
                   1434:        sbbs_t*         sbbs;
                   1435:        int32           flags;
1.1.1.2 ! root     1436:        jsrefcount      rc;
1.1       root     1437: 
                   1438:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1439:                return(JS_FALSE);
                   1440: 
                   1441:        if(argc) {
                   1442:                if(!JS_ValueToInt32(cx,argv[0],&flags))
                   1443:                        return(JS_FALSE);
1.1.1.2 ! root     1444:                rc=JS_SUSPENDREQUEST(cx);
1.1       root     1445:                *rval = BOOLEAN_TO_JSVAL(sbbs->term_supports(flags));
1.1.1.2 ! root     1446:                JS_RESUMEREQUEST(cx, rc);
        !          1447:        } else {
        !          1448:                rc=JS_SUSPENDREQUEST(cx);
        !          1449:                flags=sbbs->term_supports();
        !          1450:                JS_RESUMEREQUEST(cx, rc);
        !          1451:                JS_NewNumberValue(cx,flags,rval);
        !          1452:        }
1.1       root     1453: 
                   1454:     return(JS_TRUE);
                   1455: }
                   1456: 
                   1457: static jsSyncMethodSpec js_console_functions[] = {
                   1458:        {"inkey",                       js_inkey,                       0, JSTYPE_STRING,       JSDOCSTR("[mode=<tt>K_NONE</tt>] [,timeout=<tt>0</tt>]")
                   1459:        ,JSDOCSTR("get a single key with optional <i>timeout</i> in milliseconds (defaults to 0, for no wait), "
                   1460:                "see <tt>K_*</tt> in <tt>sbbsdefs.js</tt> for <i>mode</i> bits")
                   1461:        ,311
                   1462:        },              
                   1463:        {"getkey",                      js_getkey,                      0, JSTYPE_STRING,       JSDOCSTR("[mode=<tt>K_NONE</tt>]")
                   1464:        ,JSDOCSTR("get a single key, with wait, "
                   1465:                "see <tt>K_*</tt> in <tt>sbbsdefs.js</tt> for <i>mode</i> bits")
                   1466:        ,310
                   1467:        },              
                   1468:        {"getstr",                      js_getstr,                      0, JSTYPE_STRING,       JSDOCSTR("[string] [,maxlen=<tt>128</tt>] [,mode=<tt>K_NONE</tt>]")
                   1469:        ,JSDOCSTR("get a text string from the user, "
                   1470:                "see <tt>K_*</tt> in <tt>sbbsdefs.js</tt> for <i>mode</i> bits")
                   1471:        ,310
                   1472:        },              
1.1.1.2 ! root     1473:        {"getnum",                      js_getnum,                      0, JSTYPE_NUMBER,       JSDOCSTR("[maxnum[, default]]")
        !          1474:        ,JSDOCSTR("get a number between 1 and <i>maxnum</i> from the user with a default value of <i>default</i>")
1.1       root     1475:        ,310
                   1476:        },              
                   1477:        {"getkeys",                     js_getkeys,                     1, JSTYPE_NUMBER,       JSDOCSTR("string keys [,maxnum]")
                   1478:        ,JSDOCSTR("get one key from of a list of valid command <i>keys</i>, "
                   1479:                "or a number between 1 and <i>maxnum</i>")
                   1480:        ,310
                   1481:        },              
                   1482:        {"gettemplate",         js_gettemplate,         1, JSTYPE_STRING,       JSDOCSTR("format [,string] [,mode=<tt>0</tt>]")
                   1483:        ,JSDOCSTR("get a string based on template")
                   1484:        ,310
                   1485:        },              
                   1486:        {"ungetstr",            js_ungetstr,            1, JSTYPE_VOID,         JSDOCSTR("")
                   1487:        ,JSDOCSTR("put a string in the keyboard buffer")
                   1488:        ,310
                   1489:        },              
                   1490:        {"yesno",                       js_yesno,                       1, JSTYPE_BOOLEAN,      JSDOCSTR("question")
1.1.1.2 ! root     1491:        ,JSDOCSTR("YES/no question - returns <i>true</i> if yes is selected")
1.1       root     1492:        ,310
                   1493:        },              
                   1494:        {"noyes",                       js_noyes,                       1, JSTYPE_BOOLEAN,      JSDOCSTR("question")
1.1.1.2 ! root     1495:        ,JSDOCSTR("NO/yes question - returns <i>true</i> if no is selected")
1.1       root     1496:        ,310
                   1497:        },              
                   1498:        {"mnemonics",           js_mnemonics,           1, JSTYPE_VOID,         JSDOCSTR("text")
                   1499:        ,JSDOCSTR("print a mnemonics string, command keys highlighted with tilde (~) characters")
                   1500:        ,310
                   1501:        },              
                   1502:        {"clear",           js_clear,                   0, JSTYPE_VOID,         JSDOCSTR("[attribute]")
                   1503:        ,JSDOCSTR("clear screen and home cursor, "
                   1504:                "optionally (in v3.13b+) setting current attribute first")
                   1505:        ,310
                   1506:        },
                   1507:        {"home",            js_cursor_home,             0, JSTYPE_VOID,         JSDOCSTR("")
                   1508:        ,JSDOCSTR("send cursor to home position (x,y:1,1)")
                   1509:        ,311
                   1510:        },
                   1511:        {"clearline",       js_clearline,               0, JSTYPE_VOID,         JSDOCSTR("[attribute]")
                   1512:        ,JSDOCSTR("clear current line, "
                   1513:                "optionally (in v3.13b+) setting current attribute first")
                   1514:        ,310
                   1515:        },              
                   1516:        {"cleartoeol",      js_cleartoeol,              0, JSTYPE_VOID,         JSDOCSTR("[attribute]")
                   1517:        ,JSDOCSTR("clear to end-of-line (ANSI), "
                   1518:                "optionally (in v3.13b+) setting current attribute first")
                   1519:        ,311
                   1520:        },              
1.1.1.2 ! root     1521:        {"crlf",            js_crlf,                    0, JSTYPE_VOID,         JSDOCSTR("[count=<tt>1</tt>]")
        !          1522:        ,JSDOCSTR("output <i>count</i> number of carriage-return/line-feed pairs (new-lines)")
1.1       root     1523:        ,310
                   1524:        },              
                   1525:        {"pause",                       js_pause,                       0, JSTYPE_VOID,         JSDOCSTR("")
                   1526:        ,JSDOCSTR("display pause prompt and wait for key hit")
                   1527:        ,310
                   1528:        },
                   1529:        {"beep",                        js_beep,                        1, JSTYPE_VOID,         JSDOCSTR("[count=<tt>1</tt>]")
1.1.1.2 ! root     1530:        ,JSDOCSTR("beep for <i>count</i> number of times (default count is 1)")
1.1       root     1531:        ,311
                   1532:        },
1.1.1.2 ! root     1533:        {"print",                       js_print,                       1, JSTYPE_VOID,         JSDOCSTR("value [,value]")
        !          1534:        ,JSDOCSTR("display one or more values as strings (supports Ctrl-A codes, Telnet-escaping, auto-screen pausing, etc.)")
1.1       root     1535:        ,310
                   1536:        },              
1.1.1.2 ! root     1537:        {"write",                       js_write,                       1, JSTYPE_VOID,         JSDOCSTR("value [,value]")
        !          1538:        ,JSDOCSTR("display one or more values as raw strings (may include NULs)")
1.1       root     1539:        ,310
                   1540:        },              
1.1.1.2 ! root     1541:        {"writeln",                     js_writeln,                     1, JSTYPE_VOID,         JSDOCSTR("value [,value]")
        !          1542:        ,JSDOCSTR("display one or more values as raw strings followed by a single carriage-return/line-feed pair (new-line)")
        !          1543:        ,315
        !          1544:        },              
1.1       root     1545:        {"putmsg",                      js_putmsg,                      1, JSTYPE_VOID,         JSDOCSTR("text [,mode=<tt>P_NONE</tt>]")
                   1546:        ,JSDOCSTR("display message text (Ctrl-A codes, @-codes, pipe codes, etc), "
                   1547:                "see <tt>P_*</tt> in <tt>sbbsdefs.js</tt> for <i>mode</i> bits")
                   1548:        ,310
                   1549:        },              
                   1550:        {"center",                      js_center,                      1, JSTYPE_VOID,         JSDOCSTR("text")
                   1551:        ,JSDOCSTR("display a string centered on the screen")
                   1552:        ,310
                   1553:        },
                   1554:        {"strlen",                      js_strlen,                      1, JSTYPE_NUMBER,       JSDOCSTR("text")
                   1555:        ,JSDOCSTR("returns the number of characters in text, excluding Ctrl-A codes")
                   1556:        ,310
                   1557:        },
                   1558:        {"printfile",           js_printfile,           1, JSTYPE_VOID,         JSDOCSTR("filename [,mode=<tt>P_NONE</tt>]")
                   1559:        ,JSDOCSTR("print a message text file with optional mode")
                   1560:        ,310
                   1561:        },              
                   1562:        {"printtail",           js_printtail,           2, JSTYPE_VOID,         JSDOCSTR("filename, lines [,mode=<tt>P_NONE</tt>]")
                   1563:        ,JSDOCSTR("print last x lines of file with optional mode")
                   1564:        ,310
                   1565:        },              
1.1.1.2 ! root     1566:        {"editfile",            js_editfile,            1, JSTYPE_BOOLEAN,              JSDOCSTR("filename")
1.1       root     1567:        ,JSDOCSTR("edit/create a text file using the user's preferred message editor")
                   1568:        ,310
                   1569:        },              
                   1570:        {"uselect",                     js_uselect,                     0, JSTYPE_NUMBER,       JSDOCSTR("[number, title, item] [,ars]")
                   1571:        ,JSDOCSTR("user selection menu, call for each item, then with no args to display select menu")
                   1572:        ,312
                   1573:        },              
                   1574:        {"saveline",            js_saveline,            0, JSTYPE_VOID,         JSDOCSTR("")
                   1575:        ,JSDOCSTR("save last output line")
                   1576:        ,310
                   1577:        },              
                   1578:        {"restoreline",         js_restoreline,         0, JSTYPE_VOID,         JSDOCSTR("")
                   1579:        ,JSDOCSTR("restore last output line")
                   1580:        ,310
                   1581:        },              
1.1.1.2 ! root     1582:        {"ansi",                        js_ansi,                        1, JSTYPE_STRING,       JSDOCSTR("attribute [,current_attribute]")
        !          1583:        ,JSDOCSTR("returns ANSI sequence required to generate specified terminal <i>attribute</i> "
        !          1584:        "(e.g. <tt>YELLOW|HIGH|BG_BLUE</tt>), "
        !          1585:        "if <i>current_attribute</i> is specified, an optimized ANSI sequence may be returned")
1.1       root     1586:        ,310
                   1587:        },              
                   1588:        {"ansi_save",           js_pushxy,                      0, JSTYPE_ALIAS },
                   1589:        {"ansi_pushxy",         js_pushxy,                      0, JSTYPE_ALIAS },
                   1590:        {"pushxy",                      js_pushxy,                      0, JSTYPE_VOID,         JSDOCSTR("")
                   1591:        ,JSDOCSTR("save current cursor position (AKA ansi_save)")
                   1592:        ,311
                   1593:        },
                   1594:        {"ansi_restore",        js_popxy,                       0, JSTYPE_ALIAS },
                   1595:        {"ansi_popxy",          js_popxy,                       0, JSTYPE_ALIAS },
                   1596:        {"popxy",                       js_popxy,                       0, JSTYPE_VOID,         JSDOCSTR("")
                   1597:        ,JSDOCSTR("restore saved cursor position (AKA ansi_restore)")
                   1598:        ,311
                   1599:        },
                   1600:        {"ansi_gotoxy",         js_gotoxy,                      1, JSTYPE_ALIAS },
                   1601:        {"gotoxy",                      js_gotoxy,                      1, JSTYPE_VOID,         JSDOCSTR("[x,y] or [object { x,y }]")
                   1602:        ,JSDOCSTR("move cursor to a specific screen coordinate (ANSI), "
                   1603:        "arguments can be separate x and y cooridinates or an object with x and y properites "
                   1604:        "(like that returned from <tt>console.getxy()</tt>)")
                   1605:        ,311
                   1606:        },
                   1607:        {"ansi_up",                     js_cursor_up,           0, JSTYPE_ALIAS },
                   1608:        {"up",                          js_cursor_up,           0, JSTYPE_VOID,         JSDOCSTR("[rows=<tt>1</tt>]")
                   1609:        ,JSDOCSTR("move cursor up one or more rows (ANSI)")
                   1610:        ,311
                   1611:        },
                   1612:        {"ansi_down",           js_cursor_down,         0, JSTYPE_ALIAS },
                   1613:        {"down",                        js_cursor_down,         0, JSTYPE_VOID,         JSDOCSTR("[rows=<tt>1</tt>]")
                   1614:        ,JSDOCSTR("move cursor down one or more rows (ANSI)")
                   1615:        ,311
                   1616:        },
                   1617:        {"ansi_right",          js_cursor_right,        0, JSTYPE_ALIAS },
                   1618:        {"right",                       js_cursor_right,        0, JSTYPE_VOID,         JSDOCSTR("[columns=<tt>1</tt>]")
                   1619:        ,JSDOCSTR("move cursor right one or more columns (ANSI)")
                   1620:        ,311
                   1621:        },
                   1622:        {"ansi_left",           js_cursor_left,         0, JSTYPE_ALIAS },
                   1623:        {"left",                        js_cursor_left,         0, JSTYPE_VOID,         JSDOCSTR("[columns=<tt>1</tt>]")
                   1624:        ,JSDOCSTR("move cursor left one or more columns (ANSI)")
                   1625:        ,311
                   1626:        },
                   1627:        {"ansi_getlines",       js_getlines,            0, JSTYPE_ALIAS },
1.1.1.2 ! root     1628:        {"getlines",            js_getlines,            0, JSTYPE_ALIAS },
        !          1629:        {"getdimensions",       js_getlines,            0, JSTYPE_VOID,         JSDOCSTR("")
        !          1630:        ,JSDOCSTR("query the number of rows and columns on the remote terminal (ANSI)")
1.1       root     1631:        ,311
                   1632:        },
                   1633:        {"ansi_getxy",          js_getxy,                       0, JSTYPE_ALIAS },
                   1634:        {"getxy",                       js_getxy,                       0, JSTYPE_OBJECT,       JSDOCSTR("")
1.1.1.2 ! root     1635:        ,JSDOCSTR("query the current cursor position on the remote terminal (ANSI) "
        !          1636:                "and returns the coordinates as an object (with x and y properties)")
1.1       root     1637:        ,311
                   1638:        },
                   1639:        {"lock_input",          js_lock_input,          1, JSTYPE_VOID,         JSDOCSTR("[lock=<tt>true</tt>]")
                   1640:        ,JSDOCSTR("lock the user input thread (allowing direct client socket access)")
                   1641:        ,310
                   1642:        },
                   1643:        {"telnet_cmd",          js_telnet_cmd,          2, JSTYPE_VOID,         JSDOCSTR("command [,option=<tt>0</tt>]")
                   1644:        ,JSDOCSTR("send Telnet command (with optional command option) to remote client")
                   1645:        ,310
                   1646:        },
                   1647:        {"handle_ctrlkey",      js_handle_ctrlkey,      1, JSTYPE_BOOLEAN,      JSDOCSTR("key [,mode=<tt>K_NONE</tt>]")
                   1648:        ,JSDOCSTR("call internal control key handler for specified control key, returns <tt>true</tt> if handled")
                   1649:        ,311
                   1650:        },
                   1651:        {"term_supports",       js_term_supports,       1, JSTYPE_BOOLEAN,      JSDOCSTR("[terminal_flags]")
                   1652:        ,JSDOCSTR("either returns <i>bool</i>, indicating whether or not the current user/client "
                   1653:                "supports all the specified <i>terminal_flags</i>, or returns the current user/client's "
                   1654:                "<i>terminal_flags</i> (numeric bit-field) if no <i>terminal_flags</i> were specified")
                   1655:        ,314
                   1656:        },
1.1.1.2 ! root     1657:        {"backspace",           js_backspace,           0, JSTYPE_VOID,         JSDOCSTR("")
        !          1658:        ,JSDOCSTR("send a destructive backspace sequence")
        !          1659:        ,315
        !          1660:        },
        !          1661:        {"clearkeybuffer",      js_clearkeybuf,         0, JSTYPE_VOID,         JSDOCSTR("")
        !          1662:        ,JSDOCSTR("clear keyboard input buffer")
        !          1663:        ,315
        !          1664:        },
1.1       root     1665:        {0}
                   1666: };
                   1667: 
                   1668: 
1.1.1.2 ! root     1669: static JSBool js_console_resolve(JSContext *cx, JSObject *obj, jsval id)
        !          1670: {
        !          1671:        char*                   name=NULL;
        !          1672: 
        !          1673:        if(id != JSVAL_NULL)
        !          1674:                name=JS_GetStringBytes(JSVAL_TO_STRING(id));
        !          1675: 
        !          1676:        return(js_SyncResolve(cx, obj, name, js_console_properties, js_console_functions, NULL, 0));
        !          1677: }
        !          1678: 
        !          1679: static JSBool js_console_enumerate(JSContext *cx, JSObject *obj)
        !          1680: {
        !          1681:        return(js_console_resolve(cx, obj, JSVAL_NULL));
        !          1682: }
        !          1683: 
1.1       root     1684: static JSClass js_console_class = {
                   1685:      "Console"                         /* name                 */
                   1686:     ,0                                         /* flags                */
                   1687:        ,JS_PropertyStub                /* addProperty  */
                   1688:        ,JS_PropertyStub                /* delProperty  */
                   1689:        ,js_console_get                 /* getProperty  */
                   1690:        ,js_console_set                 /* setProperty  */
1.1.1.2 ! root     1691:        ,js_console_enumerate   /* enumerate    */
        !          1692:        ,js_console_resolve             /* resolve              */
1.1       root     1693:        ,JS_ConvertStub                 /* convert              */
                   1694:        ,JS_FinalizeStub                /* finalize             */
                   1695: };
                   1696: 
                   1697: JSObject* js_CreateConsoleObject(JSContext* cx, JSObject* parent)
                   1698: {
                   1699:        JSObject*       obj;
                   1700:        sbbs_t*         sbbs;
                   1701: 
                   1702:        if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
                   1703:                return(NULL);
                   1704: 
                   1705:        if((obj=JS_DefineObject(cx, parent, "console", &js_console_class, NULL
                   1706:                ,JSPROP_ENUMERATE|JSPROP_READONLY))==NULL)
                   1707:                return(NULL);
                   1708: 
                   1709:        /* Create an array of pre-defined colors */
                   1710: 
                   1711:        JSObject* color_list;
                   1712: 
                   1713:        if((color_list=JS_NewArrayObject(cx,0,NULL))==NULL)
                   1714:                return(NULL);
                   1715: 
                   1716:        if(!JS_DefineProperty(cx, obj, "color_list", OBJECT_TO_JSVAL(color_list)
                   1717:                ,NULL, NULL, 0))
                   1718:                return(NULL);
                   1719: 
                   1720:        for(uint i=0;i<sbbs->cfg.total_colors;i++) {
                   1721: 
                   1722:                jsval val=INT_TO_JSVAL(sbbs->cfg.color[i]);
                   1723:                if(!JS_SetElement(cx, color_list, i, &val))
                   1724:                        return(NULL);
1.1.1.2 ! root     1725:        }
1.1       root     1726: 
                   1727: #ifdef BUILD_JSDOCS
1.1.1.2 ! root     1728:        js_DescribeSyncObject(cx,obj,"Controls the remote terminal",310);
1.1       root     1729:        js_CreateArrayOfStrings(cx, obj, "_property_desc_list", con_prop_desc, JSPROP_READONLY);
                   1730: #endif
                   1731: 
                   1732:        return(obj);
                   1733: }
                   1734: 
                   1735: #endif /* JAVSCRIPT */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.