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