Annotation of sbbs/sbbs3/getkey.cpp, revision 1.1.1.2

1.1       root        1: /* getkey.cpp */
                      2: 
                      3: /* Synchronet single-key console functions */
                      4: 
1.1.1.2 ! root        5: /* $Id: getkey.cpp,v 1.30 2004/10/21 08:13:27 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 2004 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 "telnet.h"    // TELNET_GA
1.1       root       40: 
                     41: /****************************************************************************/
                     42: /* Waits for remote or local user to hit a key. Inactivity timer is checked */
                     43: /* and hangs up if inactive for 4 minutes. Returns key hit, or uppercase of */
                     44: /* key hit if mode&K_UPPER or key out of KEY BUFFER. Does not print key.    */
                     45: /* Called from functions all over the place.                                */
                     46: /****************************************************************************/
                     47: char sbbs_t::getkey(long mode)
                     48: {
1.1.1.2 ! root       49:        char    ch,coldkey,c=0,spin=sbbs_random(5);
        !            50:        time_t  last_telnet_cmd=0;
1.1       root       51: 
1.1.1.2 ! root       52:        if(!online || !input_thread_running) {
        !            53:                YIELD();        // just in case someone is looping on getkey() when they shouldn't
1.1       root       54:                return(0);
1.1.1.2 ! root       55:        }
1.1       root       56:        sys_status&=~SS_ABORT;
                     57:        if((sys_status&SS_USERON || action==NODE_DFLT) && !(mode&K_GETSTR))
                     58:                mode|=(useron.misc&SPIN);
                     59:        lncntr=0;
                     60:        timeout=time(NULL);
                     61:        if(mode&K_SPIN)
                     62:                outchar(' ');
1.1.1.2 ! root       63: 
1.1       root       64:        do {
                     65:                if(sys_status&SS_ABORT) {
                     66:                        if(mode&K_SPIN) /* back space once if on spinning cursor */
                     67:                                bputs("\b \b");
1.1.1.2 ! root       68:                        return(0)1.1       root       69:                }
                     70: 
1.1.1.2 ! root       71:                if(mode&K_SPIN) {
        !            72:                        if(useron.misc&NO_EXASCII) {
        !            73:                                switch(c++) {
        !            74:                                        case 0:
        !            75:                                                outchar(BS);
        !            76:                                                outchar('|');
        !            77:                                                break;
        !            78:                                        case 1:
        !            79:                                                outchar(BS);
        !            80:                                                outchar('/');
        !            81:                                                break;
        !            82:                                        case 2:
        !            83:                                                outchar(BS);
        !            84:                                                outchar('-');
        !            85:                                                break;
        !            86:                                        case 3:
        !            87:                                                outchar(BS);
        !            88:                                                outchar('\\');
        !            89:                                                c=0;
        !            90:                                                break;
        !            91:                                }
        !            92:                        } else {
        !            93:                                switch(spin) {
        !            94:                                        case 0:
        !            95:                                                switch(c++) {
        !            96:                                                        case 0:
        !            97:                                                                outchar(BS);
        !            98:                                                                outchar('�');
        !            99:                                                                break;
        !           100:                                                        case 1:
        !           101:                                                                outchar(BS);
        !           102:                                                                outchar('/');
        !           103:                                                                break;
        !           104:                                                        case 2:
        !           105:                                                                outchar(BS);
        !           106:                                                                outchar('�');
        !           107:                                                                break;
        !           108:                                                        case 3:
        !           109:                                                                outchar(BS);
        !           110:                                                                outchar('\\');
        !           111:                                                                c=0;
        !           112:                                                                break;
        !           113:                                                }
        !           114:                                                break;
        !           115:                                        case 1:
        !           116:                                                switch(c++) {
        !           117:                                                        case 0:
        !           118:                                                                outchar(BS);
        !           119:                                                                outchar('�');
        !           120:                                                                break;
        !           121:                                                        case 1:
        !           122:                                                                outchar(BS);
        !           123:                                                                outchar('�');
        !           124:                                                                break;
        !           125:                                                        case 2:
        !           126:                                                                outchar(BS);
        !           127:                                                                outchar('�');
        !           128:                                                                break;
        !           129:                                                        case 3:
        !           130:                                                                outchar(BS);
        !           131:                                                                outchar('�');
        !           132:                                                                break;
        !           133:                                                        case 4:
        !           134:                                                                outchar(BS);
        !           135:                                                                outchar('�');
        !           136:                                                                break;
        !           137:                                                        case 5:
        !           138:                                                                outchar(BS);
        !           139:                                                                outchar('�');
        !           140:                                                                c=0;
        !           141:                                                                break;
        !           142:                                                }
        !           143:                                                break;
        !           144:                                        case 2:
        !           145:                                                switch(c++) {
        !           146:                                                        case 0:
        !           147:                                                                outchar(BS);
        !           148:                                                                outchar('-');
        !           149:                                                                break;
        !           150:                                                        case 1:
        !           151:                                                                outchar(BS);
        !           152:                                                                outchar('=');
        !           153:                                                                break;
        !           154:                                                        case 2:
        !           155:                                                                outchar(BS);
        !           156:                                                                outchar('�');
        !           157:                                                                break;
        !           158:                                                        case 3:
        !           159:                                                                outchar(BS);
        !           160:                                                                outchar('=');
        !           161:                                                                c=0;
        !           162:                                                                break;
        !           163:                                                }
        !           164:                                                break;
        !           165:                                        case 3:
        !           166:                                                switch(c++) {
        !           167:                                                        case 0:
        !           168:                                                                outchar(BS);
        !           169:                                                                outchar('�');
        !           170:                                                                break;
        !           171:                                                        case 1:
        !           172:                                                                outchar(BS);
        !           173:                                                                outchar('�');
        !           174:                                                                break;
        !           175:                                                        case 2:
        !           176:                                                                outchar(BS);
        !           177:                                                                outchar('�');
        !           178:                                                                break;
        !           179:                                                        case 3:
        !           180:                                                                outchar(BS);
        !           181:                                                                outchar('�');
        !           182:                                                                c=0;
        !           183:                                                                break;
        !           184:                                                }
        !           185:                                                break;
        !           186:                                        case 4:
        !           187:                                                switch(c++) {
        !           188:                                                        case 0:
        !           189:                                                                outchar(BS);
        !           190:                                                                outchar('�');
        !           191:                                                                break;
        !           192:                                                        case 1:
        !           193:                                                                outchar(BS);
        !           194:                                                                outchar('�');
        !           195:                                                                break;
        !           196:                                                        case 2:
        !           197:                                                                outchar(BS);
        !           198:                                                                outchar('�');
        !           199:                                                                break;
        !           200:                                                        case 3:
        !           201:                                                                outchar(BS);
        !           202:                                                                outchar('�');
        !           203:                                                                c=0;
        !           204:                                                                break;
        !           205:                                                }
        !           206:                                                break; 
        !           207:                                }
        !           208:                        }
        !           209:                }
        !           210:                ch=inkey(mode,mode&K_SPIN ? 250:1000);
1.1       root      211:                if(sys_status&SS_ABORT)
                    212:                        return(0);
                    213:                now=time(NULL);
                    214:                if(ch) {
                    215:                        if(mode&K_NUMBER && isprint(ch) && !isdigit(ch))
                    216:                                continue;
                    217:                        if(mode&K_ALPHA && isprint(ch) && !isalpha(ch))
                    218:                                continue;
                    219:                        if(mode&K_NOEXASC && ch&0x80)
                    220:                                continue;
                    221:                        if(mode&K_SPIN)
                    222:                                bputs("\b \b");
1.1.1.2 ! root      223:                        if(mode&K_COLD && ch>' ' && useron.misc&COLDKEYS) {
1.1       root      224:                                if(mode&K_UPPER)
                    225:                                        outchar(toupper(ch));
                    226:                                else
                    227:                                        outchar(ch);
1.1.1.2 ! root      228:                                while((coldkey=inkey(mode,1000))==0 && online && !(sys_status&SS_ABORT))
        !           229:                                        ;
1.1       root      230:                                bputs("\b \b");
1.1.1.2 ! root      231:                                if(coldkey==BS || coldkey==DEL)
1.1       root      232:                                        continue;
1.1.1.2 ! root      233:                                if(coldkey>' ')
        !           234:                                        ungetkey(coldkey); 
        !           235:                        }
1.1       root      236:                        if(mode&K_UPPER)
                    237:                                return(toupper(ch));
1.1.1.2 ! root      238:                        return(ch); 
        !           239:                }
1.1       root      240:                if(sys_status&SS_USERON && !(sys_status&SS_LCHAT)) gettimeleft();
                    241:                else if(online &&
                    242:                        ((cfg.node_dollars_per_call && now-answertime>SEC_BILLING)
                    243:                        || (now-answertime>SEC_LOGON && !(sys_status&SS_LCHAT)))) {
                    244:                        console&=~(CON_R_ECHOX|CON_L_ECHOX);
                    245:                        console|=(CON_R_ECHO|CON_L_ECHO);
                    246:                        bputs(text[TakenTooLongToLogon]);
1.1.1.2 ! root      247:                        hangup(); 
        !           248:                }
1.1       root      249:                if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn)
                    250:                        && !SYSOP && !(sys_status&SS_LCHAT)) {
                    251:                        timeleft_warn=5-(timeleft/60);
                    252:                        SAVELINE;
                    253:                        attr(LIGHTGRAY);
                    254:                        bprintf(text[OnlyXminutesLeft]
                    255:                                ,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr);
1.1.1.2 ! root      256:                        RESTORELINE; 
        !           257:                }
1.1       root      258: 
1.1.1.2 ! root      259:                if(!(startup->options&BBS_OPT_NO_TELNET_GA)
        !           260:                        && now!=last_telnet_cmd && now-timeout>=60 && !((now-timeout)%60)) {
        !           261:                        // Let's make sure the socket is up
        !           262:                        // Sending will trigger a socket d/c detection
        !           263:                        send_telnet_cmd(TELNET_GA,0);
        !           264:                        last_telnet_cmd=now;
        !           265:                }
        !           266:                        
        !           267:                if(online==ON_REMOTE && !(console&CON_NO_INACT)
        !           268:                        && now-timeout>=cfg.sec_warn) {                                         /* warning */
        !           269:                        if(sys_status&SS_USERON && cfg.sec_warn!=cfg.sec_hangup) {
1.1       root      270:                                SAVELINE;
1.1.1.2 ! root      271:                                bputs(text[AreYouThere]); 
        !           272:                        }
1.1       root      273:                        else
                    274:                                bputs("\7\7");
1.1.1.2 ! root      275:                        while(!inkey(K_NONE,100) && online && now-timeout>=cfg.sec_warn) {
1.1       root      276:                                now=time(NULL);
                    277:                                if(now-timeout>=cfg.sec_hangup) {
                    278:                                        if(online==ON_REMOTE) {
                    279:                                                console|=CON_R_ECHO;
1.1.1.2 ! root      280:                                                console&=~CON_R_ECHOX; 
        !           281:                                        }
1.1       root      282:                                        bputs(text[CallBackWhenYoureThere]);
                    283:                                        logline(nulstr,"Inactive");
                    284:                                        hangup();
1.1.1.2 ! root      285:                                        return(0)        !           286:                                }
        !           287:                        }
        !           288:                        if(sys_status&SS_USERON && cfg.sec_warn!=cfg.sec_hangup) {
1.1       root      289:                                bputs("\r\1n\1>");
1.1.1.2 ! root      290:                                RESTORELINE; 
        !           291:                        }
        !           292:                        timeout=now; 
        !           293:                }
        !           294: 
        !           295:        } while(online);
1.1       root      296: 
                    297:        return(0);
                    298: }
                    299: 
                    300: 
                    301: /****************************************************************************/
                    302: /* Outputs a string highlighting characters preceeded by a tilde            */
                    303: /****************************************************************************/
                    304: void sbbs_t::mnemonics(char *str)
                    305: {
                    306:     char *ctrl_a_codes;
                    307:     long l;
                    308: 
                    309:        if(!strchr(str,'~')) {
                    310:                mnestr=str;
                    311:                bputs(str);
1.1.1.2 ! root      312:                return; 
        !           313:        }
1.1       root      314:        ctrl_a_codes=strchr(str,1);
                    315:        if(!ctrl_a_codes) {
1.1.1.2 ! root      316:                if(str[0]=='@' && str[strlen(str)-1]=='@' && !strchr(str,' ')) {
1.1       root      317:                        mnestr=str;
                    318:                        bputs(str);
1.1.1.2 ! root      319:                        return; 
        !           320:                }
        !           321:                attr(cfg.color[clr_mnelow]); 
        !           322:        }
1.1       root      323:        l=0L;
                    324:        while(str[l]) {
1.1.1.2 ! root      325:                if(str[l]=='~' && str[l+1]!=0) {
1.1       root      326:                        if(!(useron.misc&ANSI))
                    327:                                outchar('(');
                    328:                        l++;
                    329:                        if(!ctrl_a_codes)
                    330:                                attr(cfg.color[clr_mnehigh]);
                    331:                        outchar(str[l]);
                    332:                        l++;
                    333:                        if(!(useron.misc&ANSI))
                    334:                                outchar(')');
                    335:                        if(!ctrl_a_codes)
1.1.1.2 ! root      336:                                attr(cfg.color[clr_mnelow]); 
        !           337:                }
1.1       root      338:                else {
1.1.1.2 ! root      339:                        if(str[l]==CTRL_A           /* ctrl-a */
        !           340:                                && str[l+1]!=0) {               /* valid */
1.1       root      341:                                ctrl_a(str[++l]);       /* skip the ctrl-a */
1.1.1.2 ! root      342:                                l++;                    /* skip the attribute code */
        !           343:                        } else
        !           344:                                outchar(str[l++]); 
        !           345:                } 
        !           346:        }
1.1       root      347:        if(!ctrl_a_codes)
                    348:                attr(cfg.color[clr_mnecmd]);
                    349: }
                    350: 
                    351: /****************************************************************************/
                    352: /* Prompts user for Y or N (yes or no) and CR is interpreted as a Y         */
                    353: /* Returns 1 for Y or 0 for N                                               */
                    354: /* Called from quite a few places                                           */
                    355: /****************************************************************************/
                    356: bool sbbs_t::yesno(char *str)
                    357: {
                    358:     char ch;
                    359: 
                    360:        strcpy(question,str);
                    361:        SYNC;
                    362:        if(useron.misc&WIP) {
                    363:                strip_ctrl(question);
1.1.1.2 ! root      364:                menu("yesno"); 
        !           365:        }
1.1       root      366:        else
                    367:                bprintf(text[YesNoQuestion],str);
                    368:        while(online) {
                    369:                if(sys_status&SS_ABORT)
                    370:                        ch=text[YN][1];
                    371:                else
                    372:                        ch=getkey(K_UPPER|K_COLD);
                    373:                if(ch==text[YN][0] || ch==CR) {
                    374:                        if(bputs(text[Yes]))
                    375:                                CRLF;
                    376:                        lncntr=0;
1.1.1.2 ! root      377:                        return(true); 
        !           378:                }
1.1       root      379:                if(ch==text[YN][1]) {
                    380:                        if(bputs(text[No]))
                    381:                                CRLF;
                    382:                        lncntr=0;
1.1.1.2 ! root      383:                        return(false); 
        !           384:                } 
        !           385:        }
1.1       root      386:        return(true);
                    387: }
                    388: 
                    389: /****************************************************************************/
                    390: /* Prompts user for N or Y (no or yes) and CR is interpreted as a N         */
                    391: /* Returns 1 for N or 0 for Y                                               */
                    392: /* Called from quite a few places                                           */
                    393: /****************************************************************************/
                    394: bool sbbs_t::noyes(char *str)
                    395: {
                    396:     char ch;
                    397: 
                    398:        strcpy(question,str);
                    399:        SYNC;
                    400:        if(useron.misc&WIP) {
                    401:                strip_ctrl(question);
1.1.1.2 ! root      402:                menu("noyes"); 
        !           403:        }
1.1       root      404:        else
                    405:                bprintf(text[NoYesQuestion],str);
                    406:        while(online) {
                    407:                if(sys_status&SS_ABORT)
                    408:                        ch=text[YN][1];
                    409:                else
                    410:                        ch=getkey(K_UPPER|K_COLD);
                    411:                if(ch==text[YN][1] || ch==CR) {
                    412:                        if(bputs(text[No]))
                    413:                                CRLF;
                    414:                        lncntr=0;
1.1.1.2 ! root      415:                        return(true); 
        !           416:                }
1.1       root      417:                if(ch==text[YN][0]) {
                    418:                        if(bputs(text[Yes]))
                    419:                                CRLF;
                    420:                        lncntr=0;
1.1.1.2 ! root      421:                        return(false); 
        !           422:                } 
        !           423:        }
1.1       root      424:        return(true);
                    425: }
                    426: 
                    427: /****************************************************************************/
                    428: /* Waits for remote or local user to hit a key that is contained inside str.*/
                    429: /* 'str' should contain uppercase characters only. When a valid key is hit, */
                    430: /* it is echoed (upper case) and is the return value.                       */
                    431: /* Called from quite a few functions                                        */
                    432: /****************************************************************************/
                    433: long sbbs_t::getkeys(char *keys, ulong max)
                    434: {
                    435:        char    str[81];
1.1.1.2 ! root      436:        uchar   ch,n=0,c=0;
1.1       root      437:        ulong   i=0;
                    438: 
1.1.1.2 ! root      439:        SAFECOPY(str,keys);
1.1       root      440:        strupr(str);
                    441:        while(online) {
                    442:                ch=getkey(K_UPPER);
                    443:                if(max && ch>0x7f)  /* extended ascii chars are digits to isdigit() */
                    444:                        continue;
                    445:                if(sys_status&SS_ABORT) {   /* return -1 if Ctrl-C hit */
                    446:                        attr(LIGHTGRAY);
                    447:                        CRLF;
                    448:                        lncntr=0;
1.1.1.2 ! root      449:                        return(-1); 
        !           450:                }
1.1       root      451:                if(ch && !n && (strchr(str,ch))) {  /* return character if in string */
                    452:                        outchar(ch);
1.1.1.2 ! root      453:                        if(useron.misc&COLDKEYS && ch>' ') {
1.1       root      454:                                while(online && !(sys_status&SS_ABORT)) {
                    455:                                        c=getkey(0);
1.1.1.2 ! root      456:                                        if(c==CR || c==BS || c==DEL)
        !           457:                                                break; 
        !           458:                                }
1.1       root      459:                                if(sys_status&SS_ABORT) {
                    460:                                        CRLF;
1.1.1.2 ! root      461:                                        return(-1); 
        !           462:                                }
        !           463:                                if(c==BS || c==DEL) {
1.1       root      464:                                        bputs("\b \b");
1.1.1.2 ! root      465:                                        continue; 
        !           466:                                } 
        !           467:                        }
1.1       root      468:                        attr(LIGHTGRAY);
                    469:                        CRLF;
                    470:                        lncntr=0;
1.1.1.2 ! root      471:                        return(ch); 
        !           472:                }
1.1       root      473:                if(ch==CR && max) {             /* return 0 if no number */
                    474:                        attr(LIGHTGRAY);
                    475:                        CRLF;
                    476:                        lncntr=0;
                    477:                        if(n)
                    478:                                return(i|0x80000000L);           /* return number plus high bit */
1.1.1.2 ! root      479:                        return(0)        !           480:                }
        !           481:                if((ch==BS || ch==DEL) && n) {
1.1       root      482:                        bputs("\b \b");
                    483:                        i/=10;
1.1.1.2 ! root      484:                        n--; 
        !           485:                }
1.1       root      486:                else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
                    487:                        i*=10;
                    488:                        n++;
                    489:                        i+=ch&0xf;
                    490:                        outchar(ch);
                    491:                        if(i*10>max && !(useron.misc&COLDKEYS)) {
                    492:                                attr(LIGHTGRAY);
                    493:                                CRLF;
                    494:                                lncntr=0;
1.1.1.2 ! root      495:                                return(i|0x80000000L); 
        !           496:                        } 
        !           497:                } 
        !           498:        }
1.1       root      499:        return(-1);
                    500: }
                    501: 
                    502: /****************************************************************************/
                    503: /* Prints PAUSE message and waits for a key stoke                           */
                    504: /****************************************************************************/
                    505: void sbbs_t::pause()
                    506: {
                    507:        char    ch;
                    508:        uchar   tempattrs=curatr; /* was lclatr(-1) */
                    509:     int                i,j;
                    510:        long    l=K_UPPER;
                    511: 
                    512:        RIOSYNC(0);
                    513:        if(sys_status&SS_ABORT)
                    514:                return;
                    515:        lncntr=0;
                    516:        if(online==ON_REMOTE)
                    517:                rioctl(IOFI);
                    518:        bputs(text[Pause]);
                    519:        j=bstrlen(text[Pause]);
1.1.1.2 ! root      520:        if(sys_status&SS_USERON && !(useron.misc&(WIP|NOPAUSESPIN))
1.1       root      521:                && !(cfg.node_misc&NM_NOPAUSESPIN))
                    522:                l|=K_SPIN;
                    523:        ch=getkey(l);
                    524:        if(ch==text[YN][1] || ch=='Q')
                    525:                sys_status|=SS_ABORT;
                    526:        else if(ch==LF) // down arrow == display one more line
                    527:                lncntr=rows-2;
                    528:        if(text[Pause][0]!='@')
                    529:                for(i=0;i<j;i++)
                    530:                        bputs("\b \b");
                    531:        getnodedat(cfg.node_num,&thisnode,0);
                    532:        nodesync();
                    533:        attr(tempattrs);
                    534: }
                    535: 
                    536: /****************************************************************************/
                    537: /* Puts a character into the input buffer                                   */
                    538: /****************************************************************************/
                    539: void sbbs_t::ungetkey(char ch)
                    540: {
                    541: 
                    542:        keybuf[keybuftop++]=ch;
                    543:        if(keybuftop==KEY_BUFSIZE)
                    544:                keybuftop=0;
                    545: }

unix.superglobalmegacorp.com

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