1 /*
2 * This software is Copyright (c) 1989, 1990, 1991 by Patrick J. Wolfe.
3 *
4 * Permission is hereby granted to copy, distribute or otherwise
5 * use any part of this package as long as you do not try to make
6 * money from it or pretend that you wrote it. This copyright
7 * notice must be maintained in any copy made.
8 *
9 * Use of this software constitutes acceptance for use in an AS IS
10 * condition. There are NO warranties with regard to this software.
11 * In no event shall the author be liable for any damages whatsoever
12 * arising out of or in connection with the use or performance of this
13 * software. Any use of this software is at the user's own risk.
14 *
15 * If you make modifications to this software that you feel
16 * increases it usefulness for the rest of the community, please
17 * email the changes, enhancements, bug fixes as well as any and
18 * all ideas to me. This software is going to be maintained and
19 * enhanced as deemed necessary by the community.
20 *
21 * Patrick J. Wolfe
22 * uunet!uiucuxc!kailand!pwolfe
23 * pwolfe@kailand.kai.com
24 *
25 * Additions of Xenix,Sun,DOS,VMS,AIX and OS2 key handling
26 * made by Mark Hessling (M.Hessling@qut.edu.au)
27 *
28 */
29
30
31
32 #ifdef HAVE_CONFIG_H
33 # include <config.h>
34 #endif
35
36 #ifdef HAVE_ERRNO_H
37 # include <errno.h>
38 #endif
39
40 #if defined(USE_NCURSES)
41 # include <ncurses.h>
42 #else
43 # if defined(USE_EXTCURSES)
44 # include <cur00.h>
45 # else
46 # if defined(USE_XCURSES)
47 # include <curses.h>
48 # else
49 # include <curses.h>
50 # endif
51 # endif
52 #endif
53
54 /*
55 * Do special character handling if using ncurses, xcurses
56 */
57 #if !defined(PDCURSES) || defined(USE_XCURSES)
58 #include <getch.h>
59
60 #define NORMAL 100
61 #define ESCAPE 200
62 #define FKEY 300
63 #define BRACK 400
64
65 /***********************************************************************/
66 #ifdef HAVE_PROTO
67 # ifdef MSWIN
my_getch(WINDOW far * winptr)68 int my_getch (WINDOW far *winptr)
69 # else
70 int my_getch (WINDOW *winptr)
71 # endif
72 #else
73 int my_getch (winptr)
74 # ifdef MSWIN
75 WINDOW far *winptr;
76 # else
77 WINDOW *winptr;
78 # endif
79 #endif
80 /***********************************************************************/
81 {
82 int c=0,tmp_c=(-1);
83 short state = NORMAL;
84 short fkeycount = 0;
85
86 while (1)
87 {
88 #ifdef VMS1
89 c = keypress();
90 #else
91 c = wgetch( winptr );
92 # if defined(USE_NCURSES) && defined(EINTR) && defined(KEY_RESIZE)
93 if ( c == ERR )
94 {
95 if ( errno == EINTR )
96 c = KEY_RESIZE;
97 else
98 {
99 if ( errno == 0 )
100 c = wgetch( winptr );
101 }
102 }
103 # endif
104 #endif
105 switch (state)
106 {
107 case BRACK:
108 switch (c)
109 {
110 /* Linux f1 thru f5 are <esc>[[A <esc>[[B ... <esc>[[E */
111 case 'A': case 'B': case 'C': case 'D': case 'E':
112 return KEY_F1 + (c - 'A');
113 default:
114 state = NORMAL;
115 break;
116 }
117 break;
118
119 case FKEY:
120 switch (c)
121 {
122 /* numeric function keys */
123 case '0': case '1': case '2': case '3': case '4':
124 case '5': case '6': case '7': case '8': case '9':
125 fkeycount = (fkeycount * 10) + (c - '0');
126 break;
127
128 case '~':
129 switch (fkeycount)
130 {
131 /* Find, Insert Here, Remove, Select, Prev Screen, Next Screen */
132 case 1: return KEY_Find;
133 case 2: return KEY_InsertHere;
134 case 3: return KEY_Remove;
135 case 4: return KEY_Select;
136 case 5: return KEY_PrevScreen;
137 case 6: return KEY_NextScreen;
138
139 /* vt220 function keys F1 to F10 */
140 case 11: case 12: case 13: case 14: case 15:
141 return KEY_F(1) + (fkeycount - 11);
142 case 17: case 18: case 19: case 20: case 21:
143 return KEY_F(6) + (fkeycount - 17);
144
145 /* vt220 function keys F11 to F20 */
146 case 23: case 24:
147 return KEY_F(11) + (fkeycount - 23);
148 case 25: case 26:
149 return KEY_F(49) + (fkeycount - 25);
150 case 28: case 29:
151 return KEY_F(51) + (fkeycount - 28);
152 case 31: case 32: case 33: case 34:
153 return KEY_F(53) + (fkeycount - 31);
154
155 /* vt220 function keys - non-standard */
156 case 37: case 38: case 39: case 40: case 41:
157 case 42: case 43: case 44: case 45: case 46:
158 case 47: case 48: case 49: case 50: case 51:
159 case 52: case 53: case 54: case 55: case 56:
160 case 57: case 58: case 59: case 60:
161 return KEY_F(13) + (fkeycount - 37);
162
163 default:
164 state = NORMAL;
165 }
166 break;
167
168 case 0: return KEY_HOME;
169 case 'A': return KEY_UP;
170 case 'B': return KEY_DOWN;
171 case 'C': return KEY_RIGHT;
172 case 'D': return KEY_LEFT;
173 case 'M': return KEY_NUMENTER;
174 case 'Z': return KEY_BTAB;
175
176 /* Xenix default key mappings */
177 case 'H': return KEY_HOME;
178 case 'F': return KEY_END;
179 case 'L': return KEY_InsertHere;
180 case 'G': return KEY_NextScreen;
181 case 'I': return KEY_PrevScreen;
182
183 case 'N': return KEY_F2;
184 case 'O': return KEY_F3;
185 case 'T': return KEY_F8;
186 case 'U': return KEY_F9;
187 case 'V': return KEY_F10;
188 case 'W': return KEY_F11;
189 case 'X': return KEY_F12;
190
191 /* VT[12]00 PF keys */
192 case 'P': case 'Q': case 'R': case 'S':
193 return KEY_PF1 + (c - 'P');
194
195 case 'j':
196 return KEY_PadStar;
197 case 'k':
198 return KEY_PadPlus;
199 case 'l':
200 return KEY_PadComma;
201 case 'm':
202 return KEY_PadMinus;
203 case 'n':
204 return KEY_PadPeriod;
205 case 'o':
206 return KEY_PadSlash;
207 case 'p':
208 return KEY_Pad0;
209 case 'r':
210 return KEY_C2;
211 case 's':
212 return KEY_C3;
213 case 't':
214 return KEY_B1;
215 case 'u':
216 return KEY_B2;
217 case 'v':
218 return KEY_B3;
219 case 'w':
220 return KEY_A1;
221 case 'x':
222 return KEY_A2;
223 case 'y':
224 return KEY_A3;
225
226 /* Sun Keyboard Function Keys */
227 case 'z':
228 switch (fkeycount)
229 {
230 /* SUN F1-F12 */
231 case 224: case 225: case 226: case 227: case 228:
232 case 229: case 230: case 231: case 232: case 233:
233 case 234: case 235:
234 return KEY_F(1) + (fkeycount - 224);
235 /* SUN S-F1-S-F12 */
236 case 324: case 325: case 326: case 327: case 328:
237 case 329: case 330: case 331: case 332: case 333:
238 case 334: case 335:
239 return KEY_F(13) + (fkeycount - 324);
240 /* SUN C-F1-C-F12 */
241 case 424: case 425: case 426: case 427: case 428:
242 case 429: case 430: case 431: case 432: case 433:
243 case 434: case 435:
244 return KEY_F(25) + (fkeycount - 424);
245 case 192: return KEY_F(49); /* L1 */
246 case 193: return KEY_F(50); /* L2 */
247 case 195: return KEY_UNDO;
248 case 292: return KEY_F(57); /* S-L1 */
249 case 293: return KEY_F(58); /* S-L2 */
250 case 214: return KEY_HOME;
251 case 414: return CTL_HOME;
252 case 215: return KEY_UP;
253 case 415: return CTL_UP;
254 case 216: return KEY_PrevScreen;
255 case 416: return CTL_PGUP;
256 case 217: return KEY_LEFT;
257 case 417: return CTL_LEFT;
258 case 219: return KEY_RIGHT;
259 case 419: return CTL_RIGHT;
260 case 220: return KEY_END;
261 case 420: return CTL_END;
262 case 221: return KEY_DOWN;
263 case 421: return CTL_DOWN;
264 case 222: return KEY_NextScreen;
265 case 422: return CTL_PGDN;
266 case 1: return KEY_BTAB;
267 case 2: return KEY_InsertHere;
268 case 3: return KEY_HOME;
269 case 4: return KEY_END;
270 case 5: return KEY_PrevScreen;
271 case 6: return KEY_NextScreen;
272 case 423: return KEY_PadComma;
273 default:
274 state = NORMAL;
275 }
276 break;
277
278 /* IBM AIX ???????? */
279 case 'q':
280 switch (fkeycount)
281 {
282 case 0: /* VT100/200 keypad */
283 #if defined(USE_NCURSES)
284 return KEY_C1;
285 #else
286 return KEY_PadComma;
287 #endif
288 /* AIX F1-F12 */
289 case 1: case 2: case 3: case 4: case 5:
290 case 6: case 7: case 8: case 9: case 10:
291 case 11: case 12:
292 return KEY_F(1) + (fkeycount - 1);
293 /* AIX SF1-F12 */
294 case 13: case 14: case 15: case 16: case 17:
295 case 18: case 19: case 20: case 21: case 22:
296 case 23: case 24:
297 return KEY_F(13)+ (fkeycount - 13);
298 /* AIX CF1-F12 */
299 case 25: case 26: case 27: case 28: case 29:
300 case 30: case 31: case 32: case 33: case 34:
301 case 35: case 36:
302 return KEY_F(25)+ (fkeycount - 25);
303 case 150: return KEY_PrevScreen;
304 case 146: return KEY_END;
305 case 154: return KEY_NextScreen;
306 case 139: return KEY_InsertHere;
307 default:
308 state = NORMAL;
309 }
310 break;
311 case '[':
312 state = BRACK;
313 break;
314
315 default:
316 state = NORMAL;
317 }
318 break;
319
320 case ESCAPE:
321 switch (c)
322 {
323 case 'O': /* vt100 numeric keypad application codes */
324 case '?': /* vt52 numeric keypad application codes */
325 case '[':
326 state = FKEY;
327 fkeycount = 0;
328 break;
329 /* VT52 PF keys */
330 case 'P': case 'Q': case 'R': case 'S':
331 return KEY_PF1 + (c - 'P');
332
333 default:
334 state = NORMAL;
335 }
336 break;
337
338 default:
339 switch (c)
340 {
341 case KEY_ESC:
342 #if defined(HAVE_NODELAY) && defined(HAVE_UNGETCH)
343 /* this code allows the user to use the ESC key */
344 nodelay(winptr,TRUE);
345 tmp_c = wgetch(winptr);
346 nodelay(winptr,FALSE);
347 if (tmp_c == ERR)
348 return(c);
349 ungetch(tmp_c);
350 #endif
351 state = ESCAPE;
352 break;
353
354 case CSI:
355 state = FKEY;
356 fkeycount = 0;
357 break;
358
359 default:
360 return (c);
361 }
362 }
363 }
364 }
365 #endif
366
367 #ifdef VMS1
368 #include iodef
369 #include descrip
370 /***********************************************************************/
keypress()371 short keypress()
372 /***********************************************************************/
373 {
374 struct { long length; char *address; } logical_name;
375 struct { short status; short length; short remainder; } iosb;
376
377 static char kb[] = { "sys$input" };
378 static short chan;
379
380 static char key = 0;
381 short new_key;
382 static short first = 1;
383 short status;
384
385 key = 0;
386 logical_name.length = strlen (kb);
387 logical_name.address = kb;
388 status = sys$assign (&logical_name, &chan, 0, 0);
389 if (status != 1)
390 return(-1);
391 status = SYS$QIOW(0, chan, IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO
392 | IO$M_TIMED, &iosb, 0, 0, &key, 1,600, 0,0, 0, 0);
393 if (!key)
394 return (0);
395 new_key = (short)(key);
396 status = sys$dassgn (chan);
397 return (new_key);
398 }
399 #endif
400