|
|
1.1 ! root 1: /* getstr.cpp */ ! 2: ! 3: /* Synchronet string input routines */ ! 4: ! 5: /* $Id: getstr.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: #include "sbbs.h" ! 39: ! 40: /****************************************************************************/ ! 41: /* Waits for remote or local user to input a CR terminated string. 'length' */ ! 42: /* is the maximum number of characters that getstr will allow the user to */ ! 43: /* input into the string. 'mode' specifies upper case characters are echoed */ ! 44: /* or wordwrap or if in message input (^A sequences allowed). ^W backspaces */ ! 45: /* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */ ! 46: /* ^N non-destructive BS, ^V center line. Valid keys are echoed. */ ! 47: /****************************************************************************/ ! 48: size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode) ! 49: { ! 50: size_t i,l,x,z; /* i=current position, l=length, j=printed chars */ ! 51: /* x&z=misc */ ! 52: char str1[256],str2[256]; ! 53: uchar ch; ! 54: uchar ins=0,atr; ! 55: ! 56: console&=~CON_UPARROW; ! 57: sys_status&=~SS_ABORT; ! 58: if(mode&K_LINE && useron.misc&ANSI && !(mode&K_NOECHO)) { ! 59: attr(cfg.color[clr_inputline]); ! 60: for(i=0;i<maxlen;i++) ! 61: outchar(SP); ! 62: bprintf("\x1b[%dD",maxlen); } ! 63: if(wordwrap[0]) { ! 64: strcpy(str1,wordwrap); ! 65: wordwrap[0]=0; } ! 66: else str1[0]=0; ! 67: if(mode&K_EDIT) ! 68: strcat(str1,strout); ! 69: else ! 70: strout[0]=0; ! 71: if(strlen(str1)>maxlen) ! 72: str1[maxlen]=0; ! 73: atr=curatr; ! 74: if(!(mode&K_NOECHO)) { ! 75: if(mode&K_AUTODEL && str1[0]) { ! 76: i=(cfg.color[clr_inputline]&0x77)<<4; ! 77: i|=(cfg.color[clr_inputline]&0x77)>>4; ! 78: attr(i); } ! 79: rputs(str1); ! 80: if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && useron.misc&ANSI) ! 81: bputs("\x1b[K"); /* destroy to eol */ } ! 82: ! 83: i=l=strlen(str1); ! 84: if(mode&K_AUTODEL && str1[0] && !(mode&K_NOECHO)) { ! 85: ch=getkey(mode|K_GETSTR); ! 86: attr(atr); ! 87: if(isprint(ch) || ch==DEL) { ! 88: for(i=0;i<l;i++) ! 89: bputs("\b \b"); ! 90: i=l=0; } ! 91: else { ! 92: for(i=0;i<l;i++) ! 93: outchar(BS); ! 94: rputs(str1); ! 95: i=l; } ! 96: if(ch!=SP && ch!=TAB) ! 97: ungetkey(ch); } ! 98: ! 99: while(!(sys_status&SS_ABORT) && (ch=getkey(mode|K_GETSTR))!=CR && online) { ! 100: if(sys_status&SS_ABORT) ! 101: break; ! 102: if(ch==LF && mode&K_MSG) /* Down-arrow same as CR */ ! 103: break; ! 104: if(ch==TAB && (mode&K_TAB || !(mode&K_WRAP))) /* TAB same as CR */ ! 105: break; ! 106: if(!i && mode&K_UPRLWR && (ch==SP || ch==TAB)) ! 107: continue; /* ignore beginning white space if upper/lower */ ! 108: if(mode&K_E71DETECT && (uchar)ch==(CR|0x80) && l>1) { ! 109: if(strstr(str1,"��")) { ! 110: bputs("\r\n\r\nYou must set your terminal to NO PARITY, " ! 111: "8 DATA BITS, and 1 STOP BIT (N-8-1).\7\r\n"); ! 112: return(0); } } ! 113: switch(ch) { ! 114: case 1: /* Ctrl-A for ANSI */ ! 115: if(!(mode&K_MSG) || useron.rest&FLAG('A') || i>maxlen-3) ! 116: break; ! 117: if(ins) { ! 118: if(l<maxlen) ! 119: l++; ! 120: for(x=l;x>i;x--) ! 121: str1[x]=str1[x-1]; ! 122: rprintf("%.*s",l-i,str1+i); ! 123: rprintf("\x1b[%dD",l-i); ! 124: if(i==maxlen-1) ! 125: ins=0; } ! 126: outchar(str1[i++]=1); ! 127: break; ! 128: case 2: /* Ctrl-B Beginning of Line */ ! 129: if(useron.misc&ANSI && i && !(mode&K_NOECHO)) { ! 130: bprintf("\x1b[%dD",i); ! 131: i=0; } ! 132: break; ! 133: case 4: /* Ctrl-D Delete word right */ ! 134: if(i<l) { ! 135: x=i; ! 136: while(x<l && str1[x]!=SP) { ! 137: outchar(SP); ! 138: x++; } ! 139: while(x<l && str1[x]==SP) { ! 140: outchar(SP); ! 141: x++; } ! 142: bprintf("\x1b[%dD",x-i); /* move cursor back */ ! 143: z=i; ! 144: while(z<l-(x-i)) { /* move chars in string */ ! 145: outchar(str1[z]=str1[z+(x-i)]); ! 146: z++; } ! 147: while(z<l) { /* write over extra chars */ ! 148: outchar(SP); ! 149: z++; } ! 150: bprintf("\x1b[%dD",z-i); ! 151: l-=x-i; } /* l=new length */ ! 152: break; ! 153: case 5: /* Ctrl-E End of line */ ! 154: if(useron.misc&ANSI && i<l) { ! 155: bprintf("\x1b[%dC",l-i); /* move cursor to eol */ ! 156: i=l; } ! 157: break; ! 158: case 6: /* Ctrl-F move cursor forewards */ ! 159: if(i<l && (useron.misc&ANSI)) { ! 160: bputs("\x1b[C"); /* move cursor right one */ ! 161: i++; } ! 162: break; ! 163: case 7: /* Ctrl-G */ ! 164: if(!(mode&K_MSG)) ! 165: break; ! 166: if(useron.rest&FLAG('B')) { ! 167: if (i+6<maxlen) { ! 168: if(ins) { ! 169: for(x=l+6;x>i;x--) ! 170: str1[x]=str1[x-6]; ! 171: if(l+5<maxlen) ! 172: l+=6; ! 173: if(i==maxlen-1) ! 174: ins=0; } ! 175: str1[i++]='('; ! 176: str1[i++]='b'; ! 177: str1[i++]='e'; ! 178: str1[i++]='e'; ! 179: str1[i++]='p'; ! 180: str1[i++]=')'; ! 181: if(!(mode&K_NOECHO)) ! 182: bputs("(beep)"); } ! 183: if(ins) ! 184: redrwstr(str1,i,l,0); ! 185: break; } ! 186: if(ins) { ! 187: if(l<maxlen) ! 188: l++; ! 189: for(x=l;x>i;x--) ! 190: str1[x]=str1[x-1]; ! 191: if(i==maxlen-1) ! 192: ins=0; } ! 193: if(i<maxlen) { ! 194: str1[i++]=BEL; ! 195: if(!(mode&K_NOECHO)) ! 196: outchar(BEL); } ! 197: break; ! 198: case 8: /* Ctrl-H/Backspace */ ! 199: if(!i) ! 200: break; ! 201: i--; ! 202: l--; ! 203: if(i!=l) { /* Deleting char in middle of line */ ! 204: outchar(BS); ! 205: z=i; ! 206: while(z<l) { /* move the characters in the line */ ! 207: outchar(str1[z]=str1[z+1]); ! 208: z++; } ! 209: outchar(SP); /* write over the last char */ ! 210: bprintf("\x1b[%dD",(l-i)+1); } ! 211: else if(!(mode&K_NOECHO)) ! 212: bputs("\b \b"); ! 213: break; ! 214: case 9: /* Ctrl-I/TAB */ ! 215: if(!(i%TABSIZE)) { ! 216: if(ins) { ! 217: if(l<maxlen) ! 218: l++; ! 219: for(x=l;x>i;x--) ! 220: str1[x]=str1[x-1]; ! 221: if(i==maxlen-1) ! 222: ins=0; } ! 223: str1[i++]=SP; ! 224: if(!(mode&K_NOECHO)) ! 225: outchar(SP); } ! 226: while(i<maxlen && i%TABSIZE) { ! 227: if(ins) { ! 228: if(l<maxlen) ! 229: l++; ! 230: for(x=l;x>i;x--) ! 231: str1[x]=str1[x-1]; ! 232: if(i==maxlen-1) ! 233: ins=0; } ! 234: str1[i++]=SP; ! 235: if(!(mode&K_NOECHO)) ! 236: outchar(SP); } ! 237: if(ins && !(mode&K_NOECHO)) ! 238: redrwstr(str1,i,l,0); ! 239: break; ! 240: ! 241: case 12: /* Ctrl-L Center line (used to be Ctrl-V) */ ! 242: str1[l]=0; ! 243: l=bstrlen(str1); ! 244: if(!l) break; ! 245: for(x=0;x<(maxlen-l)/2;x++) ! 246: str2[x]=SP; ! 247: str2[x]=0; ! 248: strcat(str2,str1); ! 249: strcpy(strout,str2); ! 250: l=strlen(strout); ! 251: if(mode&K_NOECHO) ! 252: return(l); ! 253: if(mode&K_MSG) ! 254: redrwstr(strout,i,l,K_MSG); ! 255: else { ! 256: while(i--) ! 257: bputs("\b"); ! 258: bputs(strout); ! 259: if(mode&K_LINE) ! 260: attr(LIGHTGRAY); } ! 261: CRLF; ! 262: return(l); ! 263: ! 264: case 14: /* Ctrl-N Next word */ ! 265: if(i<l && (useron.misc&ANSI)) { ! 266: x=i; ! 267: while(str1[i]!=SP && i<l) ! 268: i++; ! 269: while(str1[i]==SP && i<l) ! 270: i++; ! 271: bprintf("\x1b[%dC",i-x); } ! 272: break; ! 273: case 18: /* Ctrl-R Redraw Line */ ! 274: if(!(mode&K_NOECHO)) ! 275: redrwstr(str1,i,l,0); ! 276: break; ! 277: case 22: /* Ctrl-V Toggles Insert/Overwrite */ ! 278: if(!(useron.misc&ANSI) || mode&K_NOECHO) ! 279: break; ! 280: if(ins) { ! 281: ins=0; ! 282: redrwstr(str1,i,l,0); } ! 283: else if(i<l) { ! 284: ins=1; ! 285: bprintf("\x1b[s\x1b[79C"); /* save pos */ ! 286: z=curatr; /* and go to EOL */ ! 287: attr(z|BLINK|HIGH); ! 288: outchar('�'); ! 289: attr(z); ! 290: bputs("\x1b[u"); } /* restore pos */ ! 291: break; ! 292: case 23: /* Ctrl-W Delete word left */ ! 293: if(i<l) { ! 294: x=i; /* x=original offset */ ! 295: while(i && str1[i-1]==SP) { ! 296: outchar(BS); ! 297: i--; } ! 298: while(i && str1[i-1]!=SP) { ! 299: outchar(BS); ! 300: i--; } ! 301: z=i; /* i=z=new offset */ ! 302: while(z<l-(x-i)) { /* move chars in string */ ! 303: outchar(str1[z]=str1[z+(x-i)]); ! 304: z++; } ! 305: while(z<l) { /* write over extra chars */ ! 306: outchar(SP); ! 307: z++; } ! 308: bprintf("\x1b[%dD",z-i); /* back to new x corridnant */ ! 309: l-=x-i; } /* l=new length */ ! 310: else { ! 311: while(i && str1[i-1]==SP) { ! 312: i--; ! 313: l--; ! 314: if(!(mode&K_NOECHO)) ! 315: bputs("\b \b"); } ! 316: while(i && str1[i-1]!=SP) { ! 317: i--; ! 318: l--; ! 319: if(!(mode&K_NOECHO)) ! 320: bputs("\b \b"); } } ! 321: break; ! 322: case 24: /* Ctrl-X Delete entire line */ ! 323: if(mode&K_NOECHO) ! 324: l=0; ! 325: else { ! 326: while(i<l) { ! 327: outchar(SP); ! 328: i++; } ! 329: while(l) { ! 330: l--; ! 331: bputs("\b \b"); } } ! 332: i=0; ! 333: break; ! 334: case 25: /* Ctrl-Y Delete to end of line */ ! 335: if(useron.misc&ANSI && !(mode&K_NOECHO)) { ! 336: bputs("\x1b[K"); ! 337: l=i; } ! 338: break; ! 339: case 28: /* Ctrl-\ Previous word */ ! 340: if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) { ! 341: x=i; ! 342: while(str1[i-1]==SP && i) ! 343: i--; ! 344: while(str1[i-1]!=SP && i) ! 345: i--; ! 346: bprintf("\x1b[%dD",x-i); } ! 347: break; ! 348: case 29: /* Ctrl-]/Left Arrow Reverse Cursor Movement */ ! 349: if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) { ! 350: bputs("\x1b[D"); /* move cursor left one */ ! 351: i--; } ! 352: break; ! 353: case 30: /* Ctrl-^/Up Arrow */ ! 354: if(!(mode&K_EDIT)) ! 355: break; ! 356: if(i>l) ! 357: l=i; ! 358: str1[l]=0; ! 359: strcpy(strout,str1); ! 360: if((stripattr(strout) || ins) && !(mode&K_NOECHO)) ! 361: redrwstr(strout,i,l,K_MSG); ! 362: if(mode&K_LINE && !(mode&K_NOECHO)) ! 363: attr(LIGHTGRAY); ! 364: console|=CON_UPARROW; ! 365: return(l); ! 366: case DEL: /* Ctrl-BkSpc (DEL) Delete current char */ ! 367: if(i==l) { /* Backspace if end of line */ ! 368: if(i) { ! 369: i--; ! 370: l--; ! 371: if(!(mode&K_NOECHO)) ! 372: bputs("\b \b"); ! 373: } ! 374: break; ! 375: } ! 376: l--; ! 377: z=i; ! 378: while(z<l) { /* move the characters in the line */ ! 379: outchar(str1[z]=str1[z+1]); ! 380: z++; } ! 381: outchar(SP); /* write over the last char */ ! 382: bprintf("\x1b[%dD",(l-i)+1); ! 383: break; ! 384: default: ! 385: if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) { ! 386: str1[i]=0; ! 387: if(ch==SP && !(mode&K_CHAT)) { /* don't wrap a space */ ! 388: strcpy(strout,str1); /* as last char */ ! 389: if(stripattr(strout) && !(mode&K_NOECHO)) ! 390: redrwstr(strout,i,l,K_MSG); ! 391: if(!(mode&K_NOECHO)) ! 392: CRLF; ! 393: return(i); } ! 394: x=i-1; ! 395: z=1; ! 396: wordwrap[0]=ch; ! 397: while(str1[x]!=SP && x) ! 398: wordwrap[z++]=str1[x--]; ! 399: if(x<(maxlen/2)) { ! 400: wordwrap[1]=0; /* only wrap one character */ ! 401: strcpy(strout,str1); ! 402: if(stripattr(strout) && !(mode&K_NOECHO)) ! 403: redrwstr(strout,i,l,K_MSG); ! 404: if(!(mode&K_NOECHO)) ! 405: CRLF; ! 406: return(i); } ! 407: wordwrap[z]=0; ! 408: if(!(mode&K_NOECHO)) ! 409: while(z--) { ! 410: bputs("\b \b"); ! 411: i--; } ! 412: strrev(wordwrap); ! 413: str1[x]=0; ! 414: strcpy(strout,str1); ! 415: if(stripattr(strout) && !(mode&K_NOECHO)) ! 416: redrwstr(strout,i,x,(char)mode); ! 417: if(!(mode&K_NOECHO)) ! 418: CRLF; ! 419: return(x); } ! 420: if(i<maxlen && ch>=SP) { ! 421: if(mode&K_UPRLWR) ! 422: if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-' ! 423: || str1[i-1]=='.' || str1[i-1]=='_'))) ! 424: ch=toupper(ch); ! 425: else ! 426: ch=tolower(ch); ! 427: if(ins) { ! 428: if(l<maxlen) /* l<maxlen */ ! 429: l++; ! 430: for(x=l;x>i;x--) ! 431: str1[x]=str1[x-1]; ! 432: rprintf("%.*s",l-i,str1+i); ! 433: rprintf("\x1b[%dD",l-i); ! 434: if(i==maxlen-1) { ! 435: bputs(" \b\b"); ! 436: ins=0; } } ! 437: str1[i++]=ch; ! 438: if(!(mode&K_NOECHO)) ! 439: outchar(ch); } } ! 440: if(i>l) ! 441: l=i; ! 442: if(mode&K_CHAT && !l) ! 443: return(0); } ! 444: if(!online) ! 445: return(0); ! 446: if(i>l) ! 447: l=i; ! 448: str1[l]=0; ! 449: if(!(sys_status&SS_ABORT)) { ! 450: strcpy(strout,str1); ! 451: if((stripattr(strout) || ins) && !(mode&K_NOECHO)) ! 452: redrwstr(strout,i,l,K_MSG); } ! 453: else ! 454: l=0; ! 455: if(mode&K_LINE && !(mode&K_NOECHO)) attr(LIGHTGRAY); ! 456: if(!(mode&(K_NOCRLF|K_NOECHO))) { ! 457: outchar(CR); ! 458: if(!(mode&K_MSG && sys_status&SS_ABORT)) ! 459: outchar(LF); ! 460: lncntr=0; } ! 461: return(l); ! 462: } ! 463: ! 464: /****************************************************************************/ ! 465: /* Hot keyed number input routine. */ ! 466: /* Returns a valid number between 1 and max, 0 if no number entered, or -1 */ ! 467: /* if the user hit 'Q' or ctrl-c */ ! 468: /****************************************************************************/ ! 469: long sbbs_t::getnum(ulong max) ! 470: { ! 471: uchar ch,n=0; ! 472: long i=0; ! 473: ! 474: while(online) { ! 475: ch=getkey(K_UPPER); ! 476: if(ch>0x7f) ! 477: continue; ! 478: if(ch=='Q') { ! 479: outchar('Q'); ! 480: if(useron.misc&COLDKEYS) ! 481: ch=getkey(K_UPPER); ! 482: if(ch==BS) { ! 483: bputs("\b \b"); ! 484: continue; } ! 485: CRLF; ! 486: lncntr=0; ! 487: return(-1); } ! 488: else if(sys_status&SS_ABORT) { ! 489: CRLF; ! 490: lncntr=0; ! 491: return(-1); } ! 492: else if(ch==CR) { ! 493: CRLF; ! 494: lncntr=0; ! 495: return(i); } ! 496: else if(ch==BS && n) { ! 497: bputs("\b \b"); ! 498: i/=10; ! 499: n--; } ! 500: else if(isdigit(ch) && (i*10UL)+(ch&0xf)<=max && (ch!='0' || n)) { ! 501: i*=10L; ! 502: n++; ! 503: i+=ch&0xf; ! 504: outchar(ch); ! 505: if(i*10UL>max && !(useron.misc&COLDKEYS)) { ! 506: CRLF; ! 507: lncntr=0; ! 508: return(i); } } } ! 509: return(0); ! 510: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.