|
|
1.1 root 1: /* inkey.cpp */
2:
3: /* Synchronet single key input function (no wait) */
4:
1.1.1.2 ! root 5: /* $Id: inkey.cpp,v 1.44 2011/09/10 01:45:21 rswindell Exp $ */
1.1 root 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: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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: #define LAST_STAT_LINE 16
41:
42: #define nosound()
43:
1.1.1.2 ! root 44: int kbincom(sbbs_t* sbbs, unsigned long timeout)
! 45: {
! 46: int ch;
! 47:
! 48: if(sbbs->keybuftop!=sbbs->keybufbot) {
! 49: ch=sbbs->keybuf[sbbs->keybufbot++];
! 50: if(sbbs->keybufbot==KEY_BUFSIZE)
! 51: sbbs->keybufbot=0;
! 52: } else
! 53: ch=sbbs->incom(timeout);
! 54:
! 55: return ch;
! 56: }
! 57:
1.1 root 58: /****************************************************************************/
59: /* Returns character if a key has been hit remotely and responds */
60: /* Called from functions getkey, msgabort and main_sec */
61: /****************************************************************************/
62: char sbbs_t::inkey(long mode, unsigned long timeout)
63: {
64: uchar ch=0;
65:
1.1.1.2 ! root 66: ch=kbincom(this,timeout);
1.1 root 67:
68: if(ch==0) {
69: // moved here from getkey() on AUG-29-2001
70: if(sys_status&SS_SYSPAGE)
71: sbbs_beep(sbbs_random(800),100);
72: #if 0
73: if(!(mode&K_GETSTR) || mode&K_LOWPRIO || cfg.node_misc&NM_LOWPRIO)
74: YIELD();
75: #endif
76: return(0);
77: }
78:
79: if(cfg.node_misc&NM_7BITONLY
80: && (!(sys_status&SS_USERON) || useron.misc&NO_EXASCII))
81: ch&=0x7f;
82:
1.1.1.2 ! root 83: this->timeout=time(NULL);
1.1 root 84:
85: /* Is this a control key */
86: if(ch<' ') {
87: if(cfg.ctrlkey_passthru&(1<<ch)) /* flagged as passthru? */
88: return(ch); /* do not handle here */
89: return(handle_ctrlkey(ch,mode));
90: }
91:
92: if(mode&K_UPPER)
93: ch=toupper(ch);
94:
95: return(ch);
96: }
97:
98: char sbbs_t::handle_ctrlkey(char ch, long mode)
99: {
100: char str[512];
101: char tmp[512];
102: uint i,j;
103:
104: if(ch==CTRL_C) { /* Ctrl-C Abort */
105: sys_status|=SS_ABORT;
106: if(mode&K_SPIN) /* back space once if on spinning cursor */
107: backspace();
108: return(0);
109: }
110: if(ch==CTRL_Z && !(mode&K_MSG)
111: && action!=NODE_PCHT) { /* Ctrl-Z toggle raw input mode */
112: if(hotkey_inside>1) /* only allow so much recursion */
113: return(0);
114: hotkey_inside++;
115: if(mode&K_SPIN)
116: bputs("\b ");
117: SAVELINE;
118: attr(LIGHTGRAY);
119: CRLF;
120: bputs(text[RawMsgInputModeIsNow]);
121: if(console&CON_RAW_IN)
122: bputs(text[OFF]);
123: else
124: bputs(text[ON]);
125: console^=CON_RAW_IN;
126: CRLF;
127: CRLF;
128: RESTORELINE;
129: lncntr=0;
130: hotkey_inside--;
131: if(action!=NODE_MAIN && action!=NODE_XFER)
132: return(CTRL_Z);
133: return(0);
134: }
135:
136: if(console&CON_RAW_IN) /* ignore ctrl-key commands if in raw mode */
137: return(ch);
138:
139: #if 0 /* experimental removal to fix Tracker1's pause module problem with down-arrow */
140: if(ch==LF) /* ignore LF's if not in raw mode */
141: return(0);
142: #endif
143:
144: /* Global hot key event */
1.1.1.2 ! root 145: if(sys_status&SS_USERON) {
! 146: for(i=0;i<cfg.total_hotkeys;i++)
! 147: if(cfg.hotkey[i]->key==ch)
! 148: break;
! 149: if(i<cfg.total_hotkeys) {
! 150: if(hotkey_inside>1) /* only allow so much recursion */
! 151: return(0);
! 152: hotkey_inside++;
! 153: if(mode&K_SPIN)
! 154: bputs("\b ");
! 155: if(!(sys_status&SS_SPLITP)) {
! 156: SAVELINE;
! 157: attr(LIGHTGRAY);
! 158: CRLF;
! 159: }
! 160: if(cfg.hotkey[i]->cmd[0]=='?')
! 161: js_execfile(cmdstr(cfg.hotkey[i]->cmd+1,nulstr,nulstr,NULL), /* startup_dir: */NULL, /* scope: */js_glob);
! 162: else
! 163: external(cmdstr(cfg.hotkey[i]->cmd,nulstr,nulstr,NULL),0);
! 164: if(!(sys_status&SS_SPLITP)) {
! 165: CRLF;
! 166: RESTORELINE;
! 167: }
! 168: lncntr=0;
! 169: hotkey_inside--;
1.1 root 170: return(0);
171: }
172: }
173:
174: switch(ch) {
175: case CTRL_O: /* Ctrl-O toggles pause temporarily */
176: useron.misc^=UPAUSE;
177: return(0);
178: case CTRL_P: /* Ctrl-P Private node-node comm */
179: if(!(sys_status&SS_USERON))
180: return(0); /* keep from being recursive */
181: if(hotkey_inside>1) /* only allow so much recursion */
182: return(0);
183: hotkey_inside++;
184: if(mode&K_SPIN)
185: bputs("\b ");
186: if(!(sys_status&SS_SPLITP)) {
187: SAVELINE;
188: attr(LIGHTGRAY);
189: CRLF;
190: }
191: nodesync(); /* read any waiting messages */
192: nodemsg(); /* send a message */
193: SYNC;
194: if(!(sys_status&SS_SPLITP)) {
195: CRLF;
196: RESTORELINE;
197: }
198: lncntr=0;
199: hotkey_inside--;
200: return(0);
201:
202: case CTRL_U: /* Ctrl-U Users online */
203: /* needs recursion checking */
204: if(!(sys_status&SS_USERON))
205: return(0);
206: if(hotkey_inside>1) /* only allow so much recursion */
207: return(0);
208: hotkey_inside++;
209: if(mode&K_SPIN)
210: bputs("\b ");
211: if(!(sys_status&SS_SPLITP)) {
212: SAVELINE;
213: attr(LIGHTGRAY);
214: CRLF;
215: }
216: whos_online(true); /* list users */
217: ASYNC;
218: if(!(sys_status&SS_SPLITP)) {
219: CRLF;
220: RESTORELINE;
221: }
222: lncntr=0;
223: hotkey_inside--;
224: return(0);
225: case CTRL_T: /* Ctrl-T Time information */
226: if(sys_status&SS_SPLITP)
227: return(ch);
228: if(!(sys_status&SS_USERON))
229: return(0);
230: if(hotkey_inside>1) /* only allow so much recursion */
231: return(0);
232: hotkey_inside++;
233: if(mode&K_SPIN)
234: bputs("\b ");
235: SAVELINE;
236: attr(LIGHTGRAY);
237: now=time(NULL);
1.1.1.2 ! root 238: bprintf(text[TiLogon],timestr(logontime));
! 239: bprintf(text[TiNow],timestr(now));
1.1 root 240: bprintf(text[TiTimeon]
241: ,sectostr(now-logontime,tmp));
242: bprintf(text[TiTimeLeft]
243: ,sectostr(timeleft,tmp));
244: SYNC;
245: RESTORELINE;
246: lncntr=0;
247: hotkey_inside--;
248: return(0);
249: case CTRL_K: /* Ctrl-k Control key menu */
250: if(sys_status&SS_SPLITP)
251: return(ch);
252: if(!(sys_status&SS_USERON))
253: return(0);
254: if(hotkey_inside>1) /* only allow so much recursion */
255: return(0);
256: hotkey_inside++;
257: if(mode&K_SPIN)
258: bputs("\b ");
259: SAVELINE;
260: attr(LIGHTGRAY);
261: lncntr=0;
262: bputs(text[ControlKeyMenu]);
263: ASYNC;
264: RESTORELINE;
265: lncntr=0;
266: hotkey_inside--;
267: return(0);
268: case ESC:
1.1.1.2 ! root 269: i=kbincom(this, (mode&K_GETSTR) ? 3000:1000);
1.1 root 270: if(i==NOINP) // timed-out waiting for '['
271: return(ESC);
272: ch=i;
273: if(ch!='[') {
274: ungetkey(ch);
275: return(ESC);
276: }
277: i=j=0;
278: autoterm|=ANSI; /* <ESC>[x means they have ANSI */
279: if(sys_status&SS_USERON && useron.misc&AUTOTERM && !(useron.misc&ANSI)
280: && useron.number) {
281: useron.misc|=ANSI;
282: putuserrec(&cfg,useron.number,U_MISC,8,ultoa(useron.misc,str,16));
283: }
284: while(i<10 && j<30) { /* up to 3 seconds */
1.1.1.2 ! root 285: ch=kbincom(this, 100);
1.1 root 286: if(ch==(NOINP&0xff)) {
287: j++;
288: continue;
289: }
290: if(ch!=';' && !isdigit(ch) && ch!='R') { /* other ANSI */
291: switch(ch) {
292: case 'A':
293: return(0x1e); /* ctrl-^ (up arrow) */
294: case 'B':
295: return(LF); /* ctrl-j (dn arrow) */
296: case 'C':
297: return(CTRL_F); /* ctrl-f (rt arrow) */
298: case 'D':
299: return(0x1d); /* ctrl-] (lf arrow) */
300: case 'H': /* ANSI: home cursor */
301: return(CTRL_B); /* ctrl-b (beg line) */
302: case 'F': /* Xterm: cursor preceding line */
303: case 'K': /* ANSI: clear-to-end-of-line */
304: return(CTRL_E); /* ctrl-e (end line) */
1.1.1.2 ! root 305: case '@': /* ANSI/ECMA-048 INSERT */
! 306: return(CTRL_V);
! 307: case '~': /* VT-220 (XP telnet.exe) */
! 308: switch(atoi(str)) {
! 309: case 1:
! 310: return(CTRL_B);
! 311: case 2:
! 312: return(CTRL_V);
! 313: case 3:
! 314: return(DEL);
! 315: case 4:
! 316: return(CTRL_E);
! 317: }
! 318: break;
1.1 root 319: }
320: ungetkey('[');
321: for(j=0;j<i;j++)
322: ungetkey(str[j]);
323: ungetkey(ch);
324: return(ESC);
325: }
326: if(ch=='R') { /* cursor position report */
1.1.1.2 ! root 327: if(mode&K_ANSI_CPR && i && !(useron.rows)) { /* auto-detect rows */
! 328: int x,y;
1.1 root 329: str[i]=0;
1.1.1.2 ! root 330: if(sscanf(str,"%u;%u",&y,&x)==2) {
! 331: lprintf(LOG_DEBUG,"Node %d received ANSI cursor position report: %ux%u"
! 332: ,cfg.node_num, x, y);
! 333: /* Sanity check the coordinates in the response: */
! 334: if(x>=40 && x<=255) cols=x;
! 335: if(y>=10 && y<=255) rows=y;
! 336: }
1.1 root 337: }
338: return(0);
339: }
340: str[i++]=ch;
341: }
342:
343: ungetkey('[');
344: for(j=0;j<i;j++)
345: ungetkey(str[j]);
346: return(ESC);
347: }
348: return(ch);
349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.