Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* getstr.cpp */
/* Synchronet string input routines */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
/****************************************************************************/
/* Waits for remote or local user to input a CR terminated string. 'length' */
/* is the maximum number of characters that getstr will allow the user to */
/* input into the string. 'mode' specifies upper case characters are echoed */
/* or wordwrap or if in message input (^A sequences allowed). ^W backspaces */
/* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */
/* ^N non-destructive BS, ^V center line. Valid keys are echoed. */
/****************************************************************************/
size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode)
{
size_t i,l,x,z; /* i=current position, l=length, j=printed chars */
/* x&z=misc */
char str1[256],str2[256];
uchar ch;
uchar ins=0,atr;
console&=~CON_UPARROW;
sys_status&=~SS_ABORT;
if(mode&K_LINE && useron.misc&ANSI && !(mode&K_NOECHO)) {
attr(cfg.color[clr_inputline]);
for(i=0;i<maxlen;i++)
outchar(SP);
bprintf("\x1b[%dD",maxlen); }
if(wordwrap[0]) {
strcpy(str1,wordwrap);
wordwrap[0]=0; }
else str1[0]=0;
if(mode&K_EDIT)
strcat(str1,strout);
else
strout[0]=0;
if(strlen(str1)>maxlen)
str1[maxlen]=0;
atr=curatr;
if(!(mode&K_NOECHO)) {
if(mode&K_AUTODEL && str1[0]) {
i=(cfg.color[clr_inputline]&0x77)<<4;
i|=(cfg.color[clr_inputline]&0x77)>>4;
attr(i); }
rputs(str1);
if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && useron.misc&ANSI)
bputs("\x1b[K"); /* destroy to eol */ }
i=l=strlen(str1);
if(mode&K_AUTODEL && str1[0] && !(mode&K_NOECHO)) {
ch=getkey(mode|K_GETSTR);
attr(atr);
for(i=0;i<l;i++)
bputs("\b \b");
i=l=0; }
else {
for(i=0;i<l;i++)
outchar(BS);
rputs(str1);
i=l; }
if(ch!=SP && ch!=TAB)
ungetkey(ch); }
while(!(sys_status&SS_ABORT) && (ch=getkey(mode|K_GETSTR))!=CR && online) {
if(!input_thread_running)
break;
if(sys_status&SS_ABORT)
break;
if(ch==LF && mode&K_MSG) /* Down-arrow same as CR */
break;
if(ch==TAB && (mode&K_TAB || !(mode&K_WRAP))) /* TAB same as CR */
break;
if(!i && mode&K_UPRLWR && (ch==SP || ch==TAB))
continue; /* ignore beginning white space if upper/lower */
if(mode&K_E71DETECT && (uchar)ch==(CR|0x80) && l>1) {
if(strstr(str1,"")) {
bputs("\r\n\r\nYou must set your terminal to NO PARITY, "
"8 DATA BITS, and 1 STOP BIT (N-8-1).\7\r\n");
return(0); } }
switch(ch) {
if(!(mode&K_MSG) || useron.rest&FLAG('A') || i>maxlen-3)
break;
if(ins) {
if(l<maxlen)
l++;
for(x=l;x>i;x--)
str1[x]=str1[x-1];
rprintf("%.*s",l-i,str1+i);
rprintf("\x1b[%dD",l-i);
if(i==maxlen-1)
ins=0; }
outchar(str1[i++]=1);
break;
case CTRL_B: /* Ctrl-B Beginning of Line */
if(useron.misc&ANSI && i && !(mode&K_NOECHO)) {
bprintf("\x1b[%dD",i);
i=0; }
break;
case CTRL_D: /* Ctrl-D Delete word right */
if(i<l) {
x=i;
while(x<l && str1[x]!=SP) {
outchar(SP);
x++; }
while(x<l && str1[x]==SP) {
outchar(SP);
x++; }
bprintf("\x1b[%dD",x-i); /* move cursor back */
z=i;
while(z<l-(x-i)) { /* move chars in string */
outchar(str1[z]=str1[z+(x-i)]);
z++; }
while(z<l) { /* write over extra chars */
outchar(SP);
z++; }
bprintf("\x1b[%dD",z-i);
l-=x-i; } /* l=new length */
break;
if(useron.misc&ANSI && i<l) {
bprintf("\x1b[%dC",l-i); /* move cursor to eol */
i=l; }
break;
case CTRL_F: /* Ctrl-F move cursor forewards */
if(i<l && (useron.misc&ANSI)) {
bputs("\x1b[C"); /* move cursor right one */
i++; }
break;
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
if(!(mode&K_MSG))
break;
if(useron.rest&FLAG('B')) {
if (i+6<maxlen) {
if(ins) {
for(x=l+6;x>i;x--)
str1[x]=str1[x-6];
if(l+5<maxlen)
l+=6;
if(i==maxlen-1)
ins=0; }
str1[i++]='(';
str1[i++]='b';
str1[i++]='e';
str1[i++]='e';
str1[i++]='p';
str1[i++]=')';
if(!(mode&K_NOECHO))
bputs("(beep)"); }
if(ins)
redrwstr(str1,i,l,0);
break; }
if(ins) {
if(l<maxlen)
l++;
for(x=l;x>i;x--)
str1[x]=str1[x-1];
if(i==maxlen-1)
ins=0; }
if(i<maxlen) {
str1[i++]=BEL;
outchar(BEL); }
if(!i)
break;
i--;
l--;
if(i!=l) { /* Deleting char in middle of line */
outchar(BS);
z=i;
while(z<l) { /* move the characters in the line */
outchar(str1[z]=str1[z+1]);
z++; }
outchar(SP); /* write over the last char */
bprintf("\x1b[%dD",(l-i)+1); }
else if(!(mode&K_NOECHO))
bputs("\b \b");
break;
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
if(!(i%TABSIZE)) {
if(ins) {
if(l<maxlen)
l++;
for(x=l;x>i;x--)
str1[x]=str1[x-1];
if(i==maxlen-1)
ins=0; }
str1[i++]=SP;
if(!(mode&K_NOECHO))
outchar(SP); }
while(i<maxlen && i%TABSIZE) {
if(ins) {
if(l<maxlen)
l++;
for(x=l;x>i;x--)
str1[x]=str1[x-1];
if(i==maxlen-1)
ins=0; }
str1[i++]=SP;
if(!(mode&K_NOECHO))
outchar(SP); }
if(ins && !(mode&K_NOECHO))
redrwstr(str1,i,l,0);
break;
case CTRL_L: /* Ctrl-L Center line (used to be Ctrl-V) */
str1[l]=0;
l=bstrlen(str1);
if(!l) break;
for(x=0;x<(maxlen-l)/2;x++)
str2[x]=SP;
str2[x]=0;
strcat(str2,str1);
strcpy(strout,str2);
l=strlen(strout);
if(mode&K_NOECHO)
return(l);
if(mode&K_MSG)
redrwstr(strout,i,l,K_MSG);
else {
while(i--)
bputs("\b");
bputs(strout);
if(mode&K_LINE)
attr(LIGHTGRAY); }
CRLF;
return(l);
if(i<l && (useron.misc&ANSI)) {
x=i;
while(str1[i]!=SP && i<l)
i++;
while(str1[i]==SP && i<l)
i++;
bprintf("\x1b[%dC",i-x); }
break;
if(!(mode&K_NOECHO))
redrwstr(str1,i,l,0);
break;
case CTRL_V: /* Ctrl-V Toggles Insert/Overwrite */
if(!(useron.misc&ANSI) || mode&K_NOECHO)
break;
if(ins) {
ins=0;
redrwstr(str1,i,l,0); }
else if(i<l) {
ins=1;
bprintf("\x1b[s\x1b[79C"); /* save pos */
z=curatr; /* and go to EOL */
attr(z|BLINK|HIGH);
outchar('');
attr(z);
bputs("\x1b[u"); } /* restore pos */
break;
case CTRL_W: /* Ctrl-W Delete word left */
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
if(i<l) {
x=i; /* x=original offset */
while(i && str1[i-1]==SP) {
outchar(BS);
i--; }
while(i && str1[i-1]!=SP) {
outchar(BS);
i--; }
z=i; /* i=z=new offset */
while(z<l-(x-i)) { /* move chars in string */
outchar(str1[z]=str1[z+(x-i)]);
z++; }
while(z<l) { /* write over extra chars */
outchar(SP);
z++; }
bprintf("\x1b[%dD",z-i); /* back to new x corridnant */
l-=x-i; } /* l=new length */
else {
while(i && str1[i-1]==SP) {
i--;
l--;
if(!(mode&K_NOECHO))
bputs("\b \b"); }
while(i && str1[i-1]!=SP) {
i--;
l--;
if(!(mode&K_NOECHO))
bputs("\b \b"); } }
break;
case CTRL_X: /* Ctrl-X Delete entire line */
if(mode&K_NOECHO)
l=0;
else {
while(i<l) {
outchar(SP);
i++; }
while(l) {
l--;
bputs("\b \b"); } }
i=0;
break;
case CTRL_Y: /* Ctrl-Y Delete to end of line */
if(useron.misc&ANSI && !(mode&K_NOECHO)) {
bputs("\x1b[K");
l=i; }
break;
case 28: /* Ctrl-\ Previous word */
if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
x=i;
while(str1[i-1]==SP && i)
i--;
while(str1[i-1]!=SP && i)
i--;
bprintf("\x1b[%dD",x-i); }
break;
case 29: /* Ctrl-]/Left Arrow Reverse Cursor Movement */
if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
bputs("\x1b[D"); /* move cursor left one */
i--; }
break;
case 30: /* Ctrl-^/Up Arrow */
if(!(mode&K_EDIT))
break;
if(i>l)
l=i;
str1[l]=0;
strcpy(strout,str1);
if((strip_invalid_attr(strout) || ins) && !(mode&K_NOECHO))
redrwstr(strout,i,l,K_MSG);
if(mode&K_LINE && !(mode&K_NOECHO))
attr(LIGHTGRAY);
console|=CON_UPARROW;
return(l);
case DEL: /* Ctrl-BkSpc (DEL) Delete current char */
if(i==l) { /* Backspace if end of line */
if(i) {
i--;
l--;
if(!(mode&K_NOECHO))
bputs("\b \b");
}
break;
}
l--;
z=i;
while(z<l) { /* move the characters in the line */
outchar(str1[z]=str1[z+1]);
z++; }
outchar(SP); /* write over the last char */
bprintf("\x1b[%dD",(l-i)+1);
break;
default:
if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) {
str1[i]=0;
if(ch==SP && !(mode&K_CHAT)) { /* don't wrap a space */
strcpy(strout,str1); /* as last char */
if(strip_invalid_attr(strout) && !(mode&K_NOECHO))
redrwstr(strout,i,l,K_MSG);
if(!(mode&K_NOECHO))
CRLF;
return(i); }
x=i-1;
z=1;
wordwrap[0]=ch;
while(str1[x]!=SP && x)
wordwrap[z++]=str1[x--];
if(x<(maxlen/2)) {
wordwrap[1]=0; /* only wrap one character */
strcpy(strout,str1);
if(strip_invalid_attr(strout) && !(mode&K_NOECHO))
redrwstr(strout,i,l,K_MSG);
if(!(mode&K_NOECHO))
CRLF;
return(i); }
wordwrap[z]=0;
if(!(mode&K_NOECHO))
while(z--) {
bputs("\b \b");
i--; }
strrev(wordwrap);
str1[x]=0;
strcpy(strout,str1);
if(strip_invalid_attr(strout) && !(mode&K_NOECHO))
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
redrwstr(strout,i,x,(char)mode);
if(!(mode&K_NOECHO))
CRLF;
return(x); }
if(i<maxlen && ch>=SP) {
if(mode&K_UPRLWR)
if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
|| str1[i-1]=='.' || str1[i-1]=='_')))
ch=toupper(ch);
else
ch=tolower(ch);
if(ins) {
if(l<maxlen) /* l<maxlen */
l++;
for(x=l;x>i;x--)
str1[x]=str1[x-1];
rprintf("%.*s",l-i,str1+i);
rprintf("\x1b[%dD",l-i);
if(i==maxlen-1) {
bputs(" \b\b");
ins=0; } }
str1[i++]=ch;
if(!(mode&K_NOECHO))
outchar(ch); } }
if(i>l)
l=i;
if(mode&K_CHAT && !l)
return(0); }
if(!online)
return(0);
if(i>l)
l=i;
str1[l]=0;
if(!(sys_status&SS_ABORT)) {
strcpy(strout,str1);
if((strip_invalid_attr(strout) || ins) && !(mode&K_NOECHO))
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
redrwstr(strout,i,l,K_MSG); }
else
l=0;
if(mode&K_LINE && !(mode&K_NOECHO)) attr(LIGHTGRAY);
if(!(mode&(K_NOCRLF|K_NOECHO))) {
outchar(CR);
if(!(mode&K_MSG && sys_status&SS_ABORT))
outchar(LF);
lncntr=0; }
return(l);
}
/****************************************************************************/
/* Hot keyed number input routine. */
/* Returns a valid number between 1 and max, 0 if no number entered, or -1 */
/* if the user hit 'Q' or ctrl-c */
/****************************************************************************/
long sbbs_t::getnum(ulong max)
{
uchar ch,n=0;
long i=0;
while(online) {
ch=getkey(K_UPPER);
if(ch>0x7f)
continue;
if(ch=='Q') {
outchar('Q');
if(useron.misc&COLDKEYS)
ch=getkey(K_UPPER);
if(ch==BS) {
bputs("\b \b");
continue; }
CRLF;
lncntr=0;
return(-1); }
else if(sys_status&SS_ABORT) {
CRLF;
lncntr=0;
return(-1); }
else if(ch==CR) {
CRLF;
lncntr=0;
return(i); }
else if(ch==BS && n) {
bputs("\b \b");
i/=10;
n--; }
else if(isdigit(ch) && (i*10UL)+(ch&0xf)<=max && (ch!='0' || n)) {
i*=10L;
n++;
i+=ch&0xf;
outchar(ch);
if(i*10UL>max && !(useron.misc&COLDKEYS)) {
CRLF;
lncntr=0;
return(i); } } }
return(0);
}