|
|
1.1 ! root 1: /* con_out.cpp */ ! 2: ! 3: /* Synchronet console output routines */ ! 4: ! 5: /* $Id: con_out.cpp,v 1.3 2000/11/14 02:16:57 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 2000 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: ! 39: /**********************************************************************/ ! 40: /* Functions that pertain to console i/o - color, strings, chars etc. */ ! 41: /* Called from functions everywhere */ ! 42: /**********************************************************************/ ! 43: ! 44: #include "sbbs.h" ! 45: ! 46: /***************************************************/ ! 47: /* Seven bit table for EXASCII to ASCII conversion */ ! 48: /***************************************************/ ! 49: const char *sbtbl="CUeaaaaceeeiiiAAEaAooouuyOUcLYRfaiounNao?--24!<>" ! 50: "###||||++||++++++--|-+||++--|-+----++++++++##[]#" ! 51: "abrpEout*ono%0ENE+><rj%=o..+n2* "; ! 52: ! 53: /****************************************************************************/ ! 54: /* Outputs a NULL terminated string locally and remotely (if applicable) */ ! 55: /* Handles ctrl-a characters */ ! 56: /****************************************************************************/ ! 57: int sbbs_t::bputs(char *str) ! 58: { ! 59: int i; ! 60: ulong l=0; ! 61: ! 62: while(str[l]) { ! 63: if(str[l]==1) { /* ctrl-a */ ! 64: ctrl_a(str[++l]); /* skip the ctrl-a */ ! 65: l++; /* skip the attribute code */ ! 66: continue; } ! 67: if(str[l]=='@') { /* '@' */ ! 68: if(str==mnestr /* Mnemonic string or */ ! 69: || (str>=text[0] /* Straight out of TEXT.DAT */ ! 70: && str<=text[TOTAL_TEXT-1])) { ! 71: i=atcodes(str+l); /* return 0 if not valid @ code */ ! 72: l+=i; /* i is length of code string */ ! 73: if(i) /* if valid string, go to top */ ! 74: continue; } ! 75: for(i=0;i<TOTAL_TEXT;i++) ! 76: if(str==text[i]) ! 77: break; ! 78: if(i<TOTAL_TEXT) { /* Replacement text */ ! 79: i=atcodes(str+l); ! 80: l+=i; ! 81: if(i) ! 82: continue; } } ! 83: outchar(str[l++]); } ! 84: return(l); ! 85: } ! 86: ! 87: /****************************************************************************/ ! 88: /* Outputs a NULL terminated string locally and remotely (if applicable) */ ! 89: /* Does not expand ctrl-a characters (raw) */ ! 90: /* Max length of str is 64 kbytes */ ! 91: /****************************************************************************/ ! 92: int sbbs_t::rputs(char *str) ! 93: { ! 94: ulong l=0; ! 95: ! 96: while(str[l]) ! 97: outchar(str[l++]); ! 98: return(l); ! 99: } ! 100: ! 101: /****************************************************************************/ ! 102: /* Performs printf() using bbs bputs function */ ! 103: /****************************************************************************/ ! 104: int sbbs_t::bprintf(char *fmt, ...) ! 105: { ! 106: va_list argptr; ! 107: char sbuf[1024]; ! 108: ! 109: if(!strchr(fmt,'%')) ! 110: return(bputs(fmt)); ! 111: va_start(argptr,fmt); ! 112: vsprintf(sbuf,fmt,argptr); ! 113: va_end(argptr); ! 114: return(bputs(sbuf)); ! 115: } ! 116: ! 117: /****************************************************************************/ ! 118: /* Performs printf() using bbs rputs function */ ! 119: /****************************************************************************/ ! 120: int sbbs_t::rprintf(char *fmt, ...) ! 121: { ! 122: va_list argptr; ! 123: char sbuf[1024]; ! 124: ! 125: va_start(argptr,fmt); ! 126: vsprintf(sbuf,fmt,argptr); ! 127: va_end(argptr); ! 128: return(rputs(sbuf)); ! 129: } ! 130: ! 131: /****************************************************************************/ ! 132: /* Outputs character locally and remotely (if applicable), preforming echo */ ! 133: /* translations (X's and r0dent emulation) if applicable. */ ! 134: /****************************************************************************/ ! 135: void sbbs_t::outchar(char ch) ! 136: { ! 137: int i; ! 138: ! 139: if(console&CON_ECHO_OFF) ! 140: return; ! 141: if(ch==ESC) ! 142: outchar_esc=1; ! 143: else if(outchar_esc==1) { ! 144: if(ch=='[') ! 145: outchar_esc++; ! 146: else ! 147: outchar_esc=0; } ! 148: else ! 149: outchar_esc=0; ! 150: if(useron.misc&NO_EXASCII && ch&0x80) ! 151: ch=sbtbl[(uchar)ch^0x80]; /* seven bit table */ ! 152: if(ch==FF && lncntr>1 && !tos) { ! 153: lncntr=0; ! 154: CRLF; ! 155: pause(); ! 156: while(lncntr && online && !(sys_status&SS_ABORT)) ! 157: pause(); } ! 158: if(sys_status&SS_CAP /* Writes to Capture File */ ! 159: && (sys_status&SS_ANSCAP || (ch!=ESC /* && !lclaes() */))) ! 160: fwrite(&ch,1,1,capfile); ! 161: ! 162: #if 0 ! 163: if(console&CON_L_ECHO) { ! 164: if(console&CON_L_ECHOX && (uchar)ch>=SP) ! 165: putch('X'); ! 166: else if(cfg.node_misc&NM_NOBEEP && ch==BEL); /* Do nothing if beep */ ! 167: else if(ch==BEL) { ! 168: sbbs_beep(2000,110); ! 169: nosound(); } ! 170: else putch(ch); } ! 171: #endif ! 172: ! 173: if(online==ON_REMOTE && console&CON_R_ECHO) { ! 174: if(console&CON_R_ECHOX && (uchar)ch>=SP) ! 175: ch='X'; ! 176: if(ch==FF && useron.misc&ANSI) { ! 177: putcom("\x1b[2J\x1b[H"); /* clear screen, home cursor */ ! 178: } ! 179: else { ! 180: i=0; ! 181: while(outcom(ch)&TXBOF && i<1440) { /* 3 minute pause delay */ ! 182: if(!online) ! 183: break; ! 184: i++; ! 185: if(sys_status&SS_SYSPAGE) ! 186: sbbs_beep(i,80); ! 187: else ! 188: mswait(80); } ! 189: if(i==1440) { /* timeout - beep flush outbuf */ ! 190: i=rioctl(TXBC); ! 191: lprintf("timeout(outchar) %04X %04X\r\n",i,rioctl(IOFO)); ! 192: outcom(BEL); ! 193: rioctl(IOCS|PAUSE); } } } ! 194: if(ch==LF) { ! 195: lncntr++; ! 196: lbuflen=0; ! 197: tos=0; ! 198: } else if(ch==FF) { ! 199: lncntr=0; ! 200: lbuflen=0; ! 201: tos=1; ! 202: } else { ! 203: if(!lbuflen) ! 204: latr=curatr; ! 205: if(lbuflen<LINE_BUFSIZE) ! 206: lbuf[lbuflen++]=ch; } ! 207: ! 208: if(lncntr==rows-1 && ((useron.misc&UPAUSE && !(sys_status&SS_PAUSEOFF)) ! 209: || sys_status&SS_PAUSEON)) { ! 210: lncntr=0; ! 211: pause(); } ! 212: ! 213: } ! 214: ! 215: void sbbs_t::center(char *instr) ! 216: { ! 217: char str[256]; ! 218: int i,j; ! 219: ! 220: sprintf(str,"%.*s",sizeof(str)-1,instr); ! 221: truncsp(str); ! 222: j=bstrlen(str); ! 223: for(i=0;i<(80-j)/2;i++) ! 224: outchar(SP); ! 225: bputs(str); ! 226: CRLF; ! 227: } ! 228: ! 229: ! 230: /****************************************************************************/ ! 231: /* performs the correct attribute modifications for the Ctrl-A code */ ! 232: /****************************************************************************/ ! 233: void sbbs_t::ctrl_a(char x) ! 234: { ! 235: int i; ! 236: char tmp1[128],atr=curatr; ! 237: struct tm * tm; ! 238: ! 239: if(x && (uchar)x<ESC) { /* Ctrl-A through Ctrl-Z for users with MF only */ ! 240: if(!(useron.flags1&FLAG(x+64))) ! 241: console^=(CON_ECHO_OFF); ! 242: return; } ! 243: if((uchar)x>=0x7f) { ! 244: if(useron.misc&ANSI) ! 245: bprintf("\x1b[%uC",(uchar)x-0x7f); ! 246: else ! 247: for(i=0;i<(uchar)x-0x7f;i++) ! 248: outchar(SP); ! 249: return; } ! 250: switch(toupper(x)) { ! 251: case '!': /* level 10 or higher */ ! 252: if(useron.level<10) ! 253: console^=CON_ECHO_OFF; ! 254: break; ! 255: case '@': /* level 20 or higher */ ! 256: if(useron.level<20) ! 257: console^=CON_ECHO_OFF; ! 258: break; ! 259: case '#': /* level 30 or higher */ ! 260: if(useron.level<30) ! 261: console^=CON_ECHO_OFF; ! 262: break; ! 263: case '$': /* level 40 or higher */ ! 264: if(useron.level<40) ! 265: console^=CON_ECHO_OFF; ! 266: break; ! 267: case '%': /* level 50 or higher */ ! 268: if(useron.level<50) ! 269: console^=CON_ECHO_OFF; ! 270: break; ! 271: case '^': /* level 60 or higher */ ! 272: if(useron.level<60) ! 273: console^=CON_ECHO_OFF; ! 274: break; ! 275: case '&': /* level 70 or higher */ ! 276: if(useron.level<70) ! 277: console^=CON_ECHO_OFF; ! 278: break; ! 279: case '*': /* level 80 or higher */ ! 280: if(useron.level<80) ! 281: console^=CON_ECHO_OFF; ! 282: break; ! 283: case '(': /* level 90 or higher */ ! 284: if(useron.level<90) ! 285: console^=CON_ECHO_OFF; ! 286: break; ! 287: case ')': /* turn echo back on */ ! 288: console&=~CON_ECHO_OFF; ! 289: break; ! 290: case '-': /* turn off all attributes if */ ! 291: if(atr&(HIGH|BLINK|(LIGHTGRAY<<4))) /* high intensity, blink or */ ! 292: attr(LIGHTGRAY); /* background bits are set */ ! 293: break; ! 294: case '_': /* turn off all attributes if */ ! 295: if(atr&(BLINK|(LIGHTGRAY<<4))) /* blink or background is set */ ! 296: attr(LIGHTGRAY); ! 297: break; ! 298: case 'P': /* Pause */ ! 299: pause(); ! 300: break; ! 301: case 'Q': /* Pause reset */ ! 302: lncntr=0; ! 303: break; ! 304: case 'T': /* Time */ ! 305: now=time(NULL); ! 306: tm=gmtime(&now); ! 307: if(tm!=NULL) ! 308: bprintf("%02d:%02d %s" ! 309: ,tm->tm_hour==0 ? 12 ! 310: : tm->tm_hour>12 ? tm->tm_hour-12 ! 311: : tm->tm_hour, tm->tm_min, tm->tm_hour>11 ? "pm":"am"); ! 312: break; ! 313: case 'D': /* Date */ ! 314: now=time(NULL); ! 315: bputs(unixtodstr(&cfg,now,tmp1)); ! 316: break; ! 317: case ',': /* Delay 1/10 sec */ ! 318: mswait(100); ! 319: break; ! 320: case ';': /* Delay 1/2 sec */ ! 321: mswait(500); ! 322: break; ! 323: case '.': /* Delay 2 secs */ ! 324: mswait(2000); ! 325: break; ! 326: case 'S': /* Synchronize */ ! 327: ASYNC; ! 328: break; ! 329: case 'L': /* CLS (form feed) */ ! 330: CLS; ! 331: break; ! 332: case '>': /* CLREOL */ ! 333: if(useron.misc&ANSI) ! 334: bputs("\x1b[K"); ! 335: #if 0 ! 336: else { ! 337: i=j=lclwx(); /* commented out */ ! 338: while(i++<79) ! 339: outchar(SP); ! 340: while(j++<79) ! 341: outchar(BS); } ! 342: #endif ! 343: break; ! 344: case '<': /* Non-destructive backspace */ ! 345: outchar(BS); ! 346: break; ! 347: case '[': /* Carriage return */ ! 348: outchar(CR); ! 349: break; ! 350: case ']': /* Line feed */ ! 351: outchar(LF); ! 352: break; ! 353: case 'A': /* Ctrl-A */ ! 354: outchar(1); ! 355: break; ! 356: case 'H': /* High intensity */ ! 357: atr|=HIGH; ! 358: attr(atr); ! 359: break; ! 360: case 'I': /* Blink */ ! 361: atr|=BLINK; ! 362: attr(atr); ! 363: break; ! 364: case 'N': /* Normal */ ! 365: attr(LIGHTGRAY); ! 366: break; ! 367: case 'R': ! 368: atr=(atr&0xf8)|RED; ! 369: attr(atr); ! 370: break; ! 371: case 'G': ! 372: atr=(atr&0xf8)|GREEN; ! 373: attr(atr); ! 374: break; ! 375: case 'B': ! 376: atr=(atr&0xf8)|BLUE; ! 377: attr(atr); ! 378: break; ! 379: case 'W': /* White */ ! 380: atr=(atr&0xf8)|LIGHTGRAY; ! 381: attr(atr); ! 382: break; ! 383: case 'C': ! 384: atr=(atr&0xf8)|CYAN; ! 385: attr(atr); ! 386: break; ! 387: case 'M': ! 388: atr=(atr&0xf8)|MAGENTA; ! 389: attr(atr); ! 390: break; ! 391: case 'Y': /* Yellow */ ! 392: atr=(atr&0xf8)|BROWN; ! 393: attr(atr); ! 394: break; ! 395: case 'K': /* Black */ ! 396: atr=(atr&0xf8)|BLACK; ! 397: attr(atr); ! 398: break; ! 399: case '0': /* Black Background */ ! 400: atr=(atr&0x8f)|(uchar)(BLACK<<4); ! 401: attr(atr); ! 402: break; ! 403: case '1': /* Red Background */ ! 404: atr=(atr&0x8f)|(uchar)(RED<<4); ! 405: attr(atr); ! 406: break; ! 407: case '2': /* Green Background */ ! 408: atr=(atr&0x8f)|(uchar)(GREEN<<4); ! 409: attr(atr); ! 410: break; ! 411: case '3': /* Yellow Background */ ! 412: atr=(atr&0x8f)|(uchar)(BROWN<<4); ! 413: attr(atr); ! 414: break; ! 415: case '4': /* Blue Background */ ! 416: atr=(atr&0x8f)|(uchar)(BLUE<<4); ! 417: attr(atr); ! 418: break; ! 419: case '5': /* Magenta Background */ ! 420: atr=(atr&0x8f)|(uchar)(MAGENTA<<4); ! 421: attr(atr); ! 422: break; ! 423: case '6': /* Cyan Background */ ! 424: atr=(atr&0x8f)|(uchar)(CYAN<<4); ! 425: attr(atr); ! 426: break; ! 427: case '7': /* White Background */ ! 428: atr=(atr&0x8f)|(uchar)(LIGHTGRAY<<4); ! 429: attr(atr); ! 430: break; } ! 431: } ! 432: ! 433: /***************************************************************************/ ! 434: /* Changes local and remote text attributes accounting for monochrome */ ! 435: /***************************************************************************/ ! 436: /****************************************************************************/ ! 437: /* Sends ansi codes to change remote ansi terminal's colors */ ! 438: /* Only sends necessary codes - tracks remote terminal's current attributes */ ! 439: /* through the 'curatr' variable */ ! 440: /****************************************************************************/ ! 441: void sbbs_t::attr(int atr) ! 442: { ! 443: ! 444: if(!(useron.misc&ANSI)) ! 445: return; ! 446: if(!(useron.misc&COLOR)) { /* eliminate colors if user doesn't have them */ ! 447: if(atr&LIGHTGRAY) /* if any foreground bits set, set all */ ! 448: atr|=LIGHTGRAY; ! 449: if(atr&(LIGHTGRAY<<4)) /* if any background bits set, set all */ ! 450: atr|=(LIGHTGRAY<<4); ! 451: if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4)) ! 452: atr&=~LIGHTGRAY; /* if background is solid, foreground is black */ ! 453: if(!atr) ! 454: atr|=LIGHTGRAY; } /* don't allow black on black */ ! 455: if(curatr==atr) /* text hasn't changed. don't send codes */ ! 456: return; ! 457: ! 458: if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK) ! 459: || atr==LIGHTGRAY) { ! 460: bputs("\x1b[0m"); ! 461: curatr=LIGHTGRAY; } ! 462: ! 463: if(atr==LIGHTGRAY) /* no attributes */ ! 464: return; ! 465: ! 466: if(atr&BLINK) { /* special attributes */ ! 467: if(!(curatr&BLINK)) ! 468: bputs(ansi(BLINK)); } ! 469: if(atr&HIGH) { ! 470: if(!(curatr&HIGH)) ! 471: bputs(ansi(HIGH)); } ! 472: ! 473: if((atr&0x7)==BLACK) { /* foreground colors */ ! 474: if((curatr&0x7)!=BLACK) ! 475: bputs(ansi(BLACK)); } ! 476: else if((atr&0x7)==RED) { ! 477: if((curatr&0x7)!=RED) ! 478: bputs(ansi(RED)); } ! 479: else if((atr&0x7)==GREEN) { ! 480: if((curatr&0x7)!=GREEN) ! 481: bputs(ansi(GREEN)); } ! 482: else if((atr&0x7)==BROWN) { ! 483: if((curatr&0x7)!=BROWN) ! 484: bputs(ansi(BROWN)); } ! 485: else if((atr&0x7)==BLUE) { ! 486: if((curatr&0x7)!=BLUE) ! 487: bputs(ansi(BLUE)); } ! 488: else if((atr&0x7)==MAGENTA) { ! 489: if((curatr&0x7)!=MAGENTA) ! 490: bputs(ansi(MAGENTA)); } ! 491: else if((atr&0x7)==CYAN) { ! 492: if((curatr&0x7)!=CYAN) ! 493: bputs(ansi(CYAN)); } ! 494: else if((atr&0x7)==LIGHTGRAY) { ! 495: if((curatr&0x7)!=LIGHTGRAY) ! 496: bputs(ansi(LIGHTGRAY)); } ! 497: ! 498: if((atr&0x70)==(BLACK<<4)) { /* background colors */ ! 499: if((curatr&0x70)!=(BLACK<<4)) ! 500: bputs("\x1b[40m"); } ! 501: else if((atr&0x70)==(RED<<4)) { ! 502: if((curatr&0x70)!=(RED<<4)) ! 503: bputs(ansi(RED<<4)); } ! 504: else if((atr&0x70)==(GREEN<<4)) { ! 505: if((curatr&0x70)!=(GREEN<<4)) ! 506: bputs(ansi(GREEN<<4)); } ! 507: else if((atr&0x70)==(BROWN<<4)) { ! 508: if((curatr&0x70)!=(BROWN<<4)) ! 509: bputs(ansi(BROWN<<4)); } ! 510: else if((atr&0x70)==(BLUE<<4)) { ! 511: if((curatr&0x70)!=(BLUE<<4)) ! 512: bputs(ansi(BLUE<<4)); } ! 513: else if((atr&0x70)==(MAGENTA<<4)) { ! 514: if((curatr&0x70)!=(MAGENTA<<4)) ! 515: bputs(ansi(MAGENTA<<4)); } ! 516: else if((atr&0x70)==(CYAN<<4)) { ! 517: if((curatr&0x70)!=(CYAN<<4)) ! 518: bputs(ansi(CYAN<<4)); } ! 519: else if((atr&0x70)==(LIGHTGRAY<<4)) { ! 520: if((curatr&0x70)!=(LIGHTGRAY<<4)) ! 521: bputs(ansi(LIGHTGRAY<<4)); } ! 522: ! 523: curatr=atr; ! 524: } ! 525: ! 526: /****************************************************************************/ ! 527: /* Checks to see if user has hit Pause or Abort. Returns 1 if user aborted. */ ! 528: /* If the user hit Pause, waits for a key to be hit. */ ! 529: /* Emulates remote XON/XOFF flow control on local console */ ! 530: /* Preserves SS_ABORT flag state, if already set. */ ! 531: /* Called from various listing procedures that wish to check for abort */ ! 532: /****************************************************************************/ ! 533: bool sbbs_t::msgabort() ! 534: { ! 535: if(sys_status&SS_SYSPAGE) { ! 536: sbbs_beep(sbbs_random(800),1); ! 537: } ! 538: ! 539: checkline(); ! 540: if(sys_status&SS_ABORT) ! 541: return(true); ! 542: #if 0 // no longer necessary ! 543: if(online==ON_REMOTE && rioctl(IOSTATE)&ABORT) { ! 544: rioctl(IOCS|ABORT); ! 545: sys_status|=SS_ABORT; ! 546: return(true); } ! 547: #endif ! 548: if(!online) ! 549: return(true); ! 550: return(false); ! 551: } ! 552: ! 553:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.