|
|
1.1 ! root 1: /* getkey.cpp */ ! 2: ! 3: /* Synchronet single-key console functions */ ! 4: ! 5: /* $Id: getkey.cpp,v 1.37 2006/08/23 01:45:05 rswindell Exp $ */ ! 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: * * ! 11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * ! 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" ! 39: #include "telnet.h" // TELNET_GA ! 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: { ! 49: char ch,coldkey,c=0,spin=sbbs_random(5); ! 50: time_t last_telnet_cmd=0; ! 51: ! 52: if(!online || !input_thread_running) { ! 53: YIELD(); // just in case someone is looping on getkey() when they shouldn't ! 54: return(0); ! 55: } ! 56: sys_status&=~SS_ABORT; ! 57: if((sys_status&SS_USERON || action==NODE_DFLT) && !(mode&(K_GETSTR|K_NOSPIN))) ! 58: mode|=(useron.misc&SPIN); ! 59: lncntr=0; ! 60: timeout=time(NULL); ! 61: if(mode&K_SPIN) ! 62: outchar(' '); ! 63: ! 64: do { ! 65: if(sys_status&SS_ABORT) { ! 66: if(mode&K_SPIN) /* back space once if on spinning cursor */ ! 67: backspace(); ! 68: return(0); ! 69: } ! 70: ! 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); ! 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: backspace(); ! 223: if(mode&K_COLD && ch>' ' && useron.misc&COLDKEYS) { ! 224: if(mode&K_UPPER) ! 225: outchar(toupper(ch)); ! 226: else ! 227: outchar(ch); ! 228: while((coldkey=inkey(mode,1000))==0 && online && !(sys_status&SS_ABORT)) ! 229: ; ! 230: backspace(); ! 231: if(coldkey==BS || coldkey==DEL) ! 232: continue; ! 233: if(coldkey>' ') ! 234: ungetkey(coldkey); ! 235: } ! 236: if(mode&K_UPPER) ! 237: return(toupper(ch)); ! 238: return(ch); ! 239: } ! 240: if(sys_status&SS_USERON && !(sys_status&SS_LCHAT)) gettimeleft(); ! 241: else if(online && now-answertime>SEC_LOGON && !(sys_status&SS_LCHAT)) { ! 242: console&=~(CON_R_ECHOX|CON_L_ECHOX); ! 243: console|=(CON_R_ECHO|CON_L_ECHO); ! 244: bputs(text[TakenTooLongToLogon]); ! 245: hangup(); ! 246: } ! 247: if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn) ! 248: && !SYSOP && !(sys_status&SS_LCHAT)) { ! 249: timeleft_warn=5-(timeleft/60); ! 250: SAVELINE; ! 251: attr(LIGHTGRAY); ! 252: bprintf(text[OnlyXminutesLeft] ! 253: ,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr); ! 254: RESTORELINE; ! 255: } ! 256: ! 257: if(!(startup->options&BBS_OPT_NO_TELNET_GA) ! 258: && now!=last_telnet_cmd && now-timeout>=60 && !((now-timeout)%60)) { ! 259: // Let's make sure the socket is up ! 260: // Sending will trigger a socket d/c detection ! 261: send_telnet_cmd(TELNET_GA,0); ! 262: last_telnet_cmd=now; ! 263: } ! 264: ! 265: if(online==ON_REMOTE && !(console&CON_NO_INACT) ! 266: && now-timeout>=cfg.sec_warn) { /* warning */ ! 267: if(sys_status&SS_USERON && cfg.sec_warn!=cfg.sec_hangup) { ! 268: SAVELINE; ! 269: bputs(text[AreYouThere]); ! 270: } ! 271: else ! 272: bputs("\7\7"); ! 273: while(!inkey(K_NONE,100) && online && now-timeout>=cfg.sec_warn) { ! 274: now=time(NULL); ! 275: if(now-timeout>=cfg.sec_hangup) { ! 276: if(online==ON_REMOTE) { ! 277: console|=CON_R_ECHO; ! 278: console&=~CON_R_ECHOX; ! 279: } ! 280: bputs(text[CallBackWhenYoureThere]); ! 281: logline(nulstr,"Inactive"); ! 282: hangup(); ! 283: return(0); ! 284: } ! 285: } ! 286: if(sys_status&SS_USERON && cfg.sec_warn!=cfg.sec_hangup) { ! 287: bputs("\r\1n\1>"); ! 288: RESTORELINE; ! 289: } ! 290: timeout=now; ! 291: } ! 292: ! 293: } while(online); ! 294: ! 295: return(0); ! 296: } ! 297: ! 298: ! 299: /****************************************************************************/ ! 300: /* Outputs a string highlighting characters preceeded by a tilde */ ! 301: /****************************************************************************/ ! 302: void sbbs_t::mnemonics(char *str) ! 303: { ! 304: char *ctrl_a_codes; ! 305: long l; ! 306: ! 307: if(!strchr(str,'~')) { ! 308: mnestr=str; ! 309: bputs(str); ! 310: return; ! 311: } ! 312: ctrl_a_codes=strchr(str,1); ! 313: if(!ctrl_a_codes) { ! 314: if(str[0]=='@' && str[strlen(str)-1]=='@' && !strchr(str,' ')) { ! 315: mnestr=str; ! 316: bputs(str); ! 317: return; ! 318: } ! 319: attr(cfg.color[clr_mnelow]); ! 320: } ! 321: l=0L; ! 322: while(str[l]) { ! 323: if(str[l]=='~' && str[l+1]!=0) { ! 324: if(!term_supports(ANSI)) ! 325: outchar('('); ! 326: l++; ! 327: if(!ctrl_a_codes) ! 328: attr(cfg.color[clr_mnehigh]); ! 329: outchar(str[l]); ! 330: l++; ! 331: if(!term_supports(ANSI)) ! 332: outchar(')'); ! 333: if(!ctrl_a_codes) ! 334: attr(cfg.color[clr_mnelow]); ! 335: } ! 336: else { ! 337: if(str[l]==CTRL_A /* ctrl-a */ ! 338: && str[l+1]!=0) { /* valid */ ! 339: ctrl_a(str[++l]); /* skip the ctrl-a */ ! 340: l++; /* skip the attribute code */ ! 341: } else ! 342: outchar(str[l++]); ! 343: } ! 344: } ! 345: if(!ctrl_a_codes) ! 346: attr(cfg.color[clr_mnecmd]); ! 347: } ! 348: ! 349: /****************************************************************************/ ! 350: /* Prompts user for Y or N (yes or no) and CR is interpreted as a Y */ ! 351: /* Returns 1 for Y or 0 for N */ ! 352: /* Called from quite a few places */ ! 353: /****************************************************************************/ ! 354: bool sbbs_t::yesno(char *str) ! 355: { ! 356: char ch; ! 357: ! 358: strcpy(question,str); ! 359: SYNC; ! 360: if(useron.misc&WIP) { ! 361: strip_ctrl(question); ! 362: menu("yesno"); ! 363: } ! 364: else ! 365: bprintf(text[YesNoQuestion],str); ! 366: while(online) { ! 367: if(sys_status&SS_ABORT) ! 368: ch=text[YN][1]; ! 369: else ! 370: ch=getkey(K_UPPER|K_COLD); ! 371: if(ch==text[YN][0] || ch==CR) { ! 372: if(bputs(text[Yes])) ! 373: CRLF; ! 374: lncntr=0; ! 375: return(true); ! 376: } ! 377: if(ch==text[YN][1]) { ! 378: if(bputs(text[No])) ! 379: CRLF; ! 380: lncntr=0; ! 381: return(false); ! 382: } ! 383: } ! 384: return(true); ! 385: } ! 386: ! 387: /****************************************************************************/ ! 388: /* Prompts user for N or Y (no or yes) and CR is interpreted as a N */ ! 389: /* Returns 1 for N or 0 for Y */ ! 390: /* Called from quite a few places */ ! 391: /****************************************************************************/ ! 392: bool sbbs_t::noyes(char *str) ! 393: { ! 394: char ch; ! 395: ! 396: strcpy(question,str); ! 397: SYNC; ! 398: if(useron.misc&WIP) { ! 399: strip_ctrl(question); ! 400: menu("noyes"); ! 401: } ! 402: else ! 403: bprintf(text[NoYesQuestion],str); ! 404: while(online) { ! 405: if(sys_status&SS_ABORT) ! 406: ch=text[YN][1]; ! 407: else ! 408: ch=getkey(K_UPPER|K_COLD); ! 409: if(ch==text[YN][1] || ch==CR) { ! 410: if(bputs(text[No])) ! 411: CRLF; ! 412: lncntr=0; ! 413: return(true); ! 414: } ! 415: if(ch==text[YN][0]) { ! 416: if(bputs(text[Yes])) ! 417: CRLF; ! 418: lncntr=0; ! 419: return(false); ! 420: } ! 421: } ! 422: return(true); ! 423: } ! 424: ! 425: /****************************************************************************/ ! 426: /* Waits for remote or local user to hit a key that is contained inside str.*/ ! 427: /* 'str' should contain uppercase characters only. When a valid key is hit, */ ! 428: /* it is echoed (upper case) and is the return value. */ ! 429: /* Called from quite a few functions */ ! 430: /****************************************************************************/ ! 431: long sbbs_t::getkeys(char *keys, ulong max) ! 432: { ! 433: char str[81]; ! 434: uchar ch,n=0,c=0; ! 435: ulong i=0; ! 436: ! 437: SAFECOPY(str,keys); ! 438: strupr(str); ! 439: while(online) { ! 440: ch=getkey(K_UPPER); ! 441: if(max && ch>0x7f) /* extended ascii chars are digits to isdigit() */ ! 442: continue; ! 443: if(sys_status&SS_ABORT) { /* return -1 if Ctrl-C hit */ ! 444: attr(LIGHTGRAY); ! 445: CRLF; ! 446: lncntr=0; ! 447: return(-1); ! 448: } ! 449: if(ch && !n && (strchr(str,ch))) { /* return character if in string */ ! 450: outchar(ch); ! 451: if(useron.misc&COLDKEYS && ch>' ') { ! 452: while(online && !(sys_status&SS_ABORT)) { ! 453: c=getkey(0); ! 454: if(c==CR || c==BS || c==DEL) ! 455: break; ! 456: } ! 457: if(sys_status&SS_ABORT) { ! 458: CRLF; ! 459: return(-1); ! 460: } ! 461: if(c==BS || c==DEL) { ! 462: backspace(); ! 463: continue; ! 464: } ! 465: } ! 466: attr(LIGHTGRAY); ! 467: CRLF; ! 468: lncntr=0; ! 469: return(ch); ! 470: } ! 471: if(ch==CR && max) { /* return 0 if no number */ ! 472: attr(LIGHTGRAY); ! 473: CRLF; ! 474: lncntr=0; ! 475: if(n) ! 476: return(i|0x80000000L); /* return number plus high bit */ ! 477: return(0); ! 478: } ! 479: if((ch==BS || ch==DEL) && n) { ! 480: backspace(); ! 481: i/=10; ! 482: n--; ! 483: } ! 484: else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) { ! 485: i*=10; ! 486: n++; ! 487: i+=ch&0xf; ! 488: outchar(ch); ! 489: if(i*10>max && !(useron.misc&COLDKEYS)) { ! 490: attr(LIGHTGRAY); ! 491: CRLF; ! 492: lncntr=0; ! 493: return(i|0x80000000L); ! 494: } ! 495: } ! 496: } ! 497: return(-1); ! 498: } ! 499: ! 500: /****************************************************************************/ ! 501: /* Prints PAUSE message and waits for a key stoke */ ! 502: /****************************************************************************/ ! 503: void sbbs_t::pause() ! 504: { ! 505: char ch; ! 506: uchar tempattrs=curatr; /* was lclatr(-1) */ ! 507: int i,j; ! 508: long l=K_UPPER; ! 509: ! 510: if(sys_status&SS_ABORT) ! 511: return; ! 512: lncntr=0; ! 513: if(online==ON_REMOTE) ! 514: rioctl(IOFI); ! 515: bputs(text[Pause]); ! 516: j=bstrlen(text[Pause]); ! 517: if(sys_status&SS_USERON && !(useron.misc&(WIP|NOPAUSESPIN)) ! 518: && !(cfg.node_misc&NM_NOPAUSESPIN)) ! 519: l|=K_SPIN; ! 520: ch=getkey(l); ! 521: if(ch==text[YN][1] || ch=='Q') ! 522: sys_status|=SS_ABORT; ! 523: else if(ch==LF) // down arrow == display one more line ! 524: lncntr=rows-2; ! 525: if(text[Pause][0]!='@') ! 526: for(i=0;i<j;i++) ! 527: backspace(); ! 528: getnodedat(cfg.node_num,&thisnode,0); ! 529: nodesync(); ! 530: attr(tempattrs); ! 531: } ! 532: ! 533: /****************************************************************************/ ! 534: /* Puts a character into the input buffer */ ! 535: /****************************************************************************/ ! 536: void sbbs_t::ungetkey(char ch) ! 537: { ! 538: #if 0 /* this way breaks ansi_getxy() */ ! 539: RingBufWrite(&inbuf,(uchar*)&ch,sizeof(uchar)); ! 540: #else ! 541: keybuf[keybuftop++]=ch; ! 542: if(keybuftop==KEY_BUFSIZE) ! 543: keybuftop=0; ! 544: #endif ! 545: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.