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