Compatibility with old-but-newer-than-C89 compilers.
[rogue-pphs.git] / mdport.c
1 /*
2 mdport.c - Machine Dependent Code for Porting Unix/Curses games
3
4 Copyright (C) 2005 Nicholas J. Kisseberth
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name(s) of the author(s) nor the names of other contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31
32 #if defined(_WIN32)
33 #include <Windows.h>
34 #include <Lmcons.h>
35 #include <process.h>
36 #include <shlobj.h>
37 #include <sys/types.h>
38 #include <io.h>
39 #include <conio.h>
40 #undef MOUSE_MOVED
41 #elif defined(__DJGPP__)
42 #include <process.h>
43 #else
44 #include <pwd.h>
45 #include <sys/utsname.h>
46 #include <unistd.h>
47 #include <utmpx.h>
48 #endif
49
50 #ifdef __INTERIX
51 char *strdup(const char *s);
52 #endif
53
54 #include <stdlib.h>
55 #include <string.h>
56
57 #if defined(_WIN32) && !defined(__MINGW32__)
58 #define PATH_MAX MAX_PATH
59 #endif
60
61 #include <curses.h>
62 #if !defined(DJGPP)
63 #include <term.h>
64 #endif
65
66 #include <stdio.h>
67 #include <fcntl.h>
68 #include <limits.h>
69 #include <sys/stat.h>
70 #include <signal.h>
71
72 #define MOD_MOVE(c) (toupper(c) )
73
74 void
75 md_init()
76 {
77 #ifdef __INTERIX
78 char *term;
79
80 term = getenv("TERM");
81
82 if (term == NULL)
83 setenv("TERM","interix",1);
84 #endif
85 #if defined(__DJGPP__) || defined(_WIN32)
86 _fmode = _O_BINARY;
87 #endif
88 }
89
90 int
91 md_hasclreol()
92 {
93 #ifdef CE
94 return((CE != NULL) && (*CE != 0));
95 #elif defined (clr_eol)
96 return((clr_eol != NULL) && (*clr_eol != 0));
97 #elif !defined(__PDCURSES__)
98 return(clr_eol != NULL);
99 #else
100 return(TRUE);
101 #endif
102 }
103
104 void
105 md_putchar(int c)
106 {
107 putchar(c);
108 }
109
110 static int md_standout_mode = 0;
111
112 void
113 md_raw_standout()
114 {
115 #ifdef _WIN32
116 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
117 HANDLE hStdout;
118 int fgattr,bgattr;
119
120 if (md_standout_mode == 0)
121 {
122 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
123 GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
124 fgattr = (csbiInfo.wAttributes & 0xF);
125 bgattr = (csbiInfo.wAttributes & 0xF0);
126 SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
127 md_standout_mode = 1;
128 }
129 #elif defined(SO)
130 tputs(SO,0,md_putchar);
131 fflush(stdout);
132 #endif
133 }
134
135 void
136 md_raw_standend()
137 {
138 #ifdef _WIN32
139 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
140 HANDLE hStdout;
141 int fgattr,bgattr;
142
143 if (md_standout_mode == 1)
144 {
145 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
146 GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
147 fgattr = (csbiInfo.wAttributes & 0xF);
148 bgattr = (csbiInfo.wAttributes & 0xF0);
149 SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
150 md_standout_mode = 0;
151 }
152 #elif defined(SE)
153 tputs(SE,0,md_putchar);
154 fflush(stdout);
155 #endif
156 }
157
158 int
159 md_unlink_open_file(char *file, int inf)
160 {
161 #ifdef _WIN32
162 _close(inf);
163 _chmod(file, 0600);
164 return( _unlink(file) );
165 #else
166 return(unlink(file));
167 #endif
168 }
169
170 int
171 md_unlink(char *file)
172 {
173 #ifdef _WIN32
174 _chmod(file, 0600);
175 return( _unlink(file) );
176 #else
177 return(unlink(file));
178 #endif
179 }
180
181 int
182 md_creat(char *file, int mode)
183 {
184 int fd;
185 #ifdef _WIN32
186 mode = _S_IREAD | _S_IWRITE;
187 fd = _open(file,O_CREAT | O_EXCL | O_WRONLY, mode);
188 #else
189 fd = open(file,O_CREAT | O_EXCL | O_WRONLY, mode);
190 #endif
191
192 return(fd);
193 }
194
195
196 void
197 md_normaluser()
198 {
199 #ifndef _WIN32
200 setuid(getuid());
201 setgid(getgid());
202 #endif
203 }
204
205 int
206 md_getuid()
207 {
208 #ifndef _WIN32
209 return( getuid() );
210 #else
211 return(42);
212 #endif
213 }
214
215 char *
216 md_getusername(int uid)
217 {
218 static char login[80];
219 char *l = NULL;
220 #ifdef _WIN32
221 LPSTR mybuffer;
222 DWORD size = UNLEN + 1;
223 TCHAR buffer[UNLEN + 1];
224
225 mybuffer = buffer;
226 if (uid != md_getuid())
227 strcpy(mybuffer, "someone");
228 else
229 GetUserName(mybuffer,&size);
230 l = mybuffer;
231 #endif
232 #if !defined(_WIN32) && !defined(DJGPP)
233 struct passwd *pw;
234
235 pw = getpwuid(getuid());
236
237 l = pw->pw_name;
238 #endif
239
240 if ((l == NULL) || (*l == '\0'))
241 if ( (l = getenv("USERNAME")) == NULL )
242 if ( (l = getenv("LOGNAME")) == NULL )
243 if ( (l = getenv("USER")) == NULL )
244 l = "nobody";
245
246 strncpy(login,l,80);
247 login[79] = 0;
248
249 return(login);
250 }
251
252 char *
253 md_gethomedir()
254 {
255 static char homedir[PATH_MAX];
256 char *h = NULL;
257 size_t len;
258 #if defined(_WIN32)
259 TCHAR szPath[PATH_MAX];
260 #endif
261 #if defined(_WIN32) || defined(DJGPP)
262 char slash = '\\';
263 #else
264 char slash = '/';
265 struct passwd *pw;
266 pw = getpwuid(getuid());
267
268 h = pw->pw_dir;
269
270 if (strcmp(h,"/") == 0)
271 h = NULL;
272 #endif
273 homedir[0] = 0;
274 #ifdef _WIN32
275 if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath)))
276 h = szPath;
277 #endif
278
279 if ( (h == NULL) || (*h == '\0') )
280 if ( (h = getenv("HOME")) == NULL )
281 h = "";
282
283 strncpy(homedir,h,PATH_MAX-1);
284 len = strlen(homedir);
285
286 if ((len > 0) && (homedir[len-1] == slash))
287 homedir[len-1] = 0;
288
289 return(homedir);
290 }
291
292 void
293 md_sleep(int s)
294 {
295 #ifdef _WIN32
296 Sleep(s);
297 #else
298 sleep(s);
299 #endif
300 }
301
302 char *
303 md_getshell()
304 {
305 static char shell[PATH_MAX];
306 char *s = NULL;
307 #ifdef _WIN32
308 char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
309 #elif defined(__DJGPP__)
310 char *def = "C:\\COMMAND.COM";
311 #else
312 char *def = "/bin/sh";
313 struct passwd *pw;
314 pw = getpwuid(getuid());
315 s = pw->pw_shell;
316 #endif
317 if ((s == NULL) || (*s == '\0'))
318 if ( (s = getenv("COMSPEC")) == NULL)
319 if ( (s = getenv("SHELL")) == NULL)
320 if ( (s = getenv("SystemRoot")) == NULL)
321 s = def;
322
323 strncpy(shell,s,PATH_MAX);
324 shell[PATH_MAX-1] = 0;
325
326 return(shell);
327 }
328
329 int
330 md_shellescape()
331 {
332 #if (!defined(_WIN32) && !defined(__DJGPP__))
333 int ret_status;
334 int pid;
335 void (*myquit)(int);
336 void (*myend)(int);
337 #endif
338 char *sh;
339
340 sh = md_getshell();
341
342 #if defined(_WIN32)
343 return((int)_spawnl(_P_WAIT,sh,"shell",NULL,0));
344 #elif defined(__DJGPP__)
345 return ( spawnl(P_WAIT,sh,"shell",NULL,0) );
346 #else
347 while((pid = fork()) < 0)
348 sleep(1);
349
350 if (pid == 0) /* Shell Process */
351 {
352 /*
353 * Set back to original user, just in case
354 */
355 setuid(getuid());
356 setgid(getgid());
357 execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", (char *)0);
358 perror("No shelly");
359 _exit(-1);
360 }
361 else /* Application */
362 {
363 myend = signal(SIGINT, SIG_IGN);
364 #ifdef SIGQUIT
365 myquit = signal(SIGQUIT, SIG_IGN);
366 #endif
367 while (wait(&ret_status) != pid)
368 continue;
369
370 signal(SIGINT, myquit);
371 #ifdef SIGQUIT
372 signal(SIGQUIT, myend);
373 #endif
374 }
375
376 return(ret_status);
377 #endif
378 }
379
380 int
381 directory_exists(char *dirname)
382 {
383 struct stat sb;
384
385 if (stat(dirname, &sb) == 0) /* path exists */
386 return (sb.st_mode & S_IFDIR);
387
388 return(0);
389 }
390
391 char *
392 md_getroguedir()
393 {
394 static char path[1024];
395 char *end,*home;
396
397 if ( (home = getenv("ROGUEHOME")) != NULL)
398 {
399 if (*home)
400 {
401 strncpy(path, home, PATH_MAX - 20);
402
403 end = &path[strlen(path)-1];
404
405 while( (end >= path) && ((*end == '/') || (*end == '\\')))
406 *end-- = '\0';
407
408 if (directory_exists(path))
409 return(path);
410 }
411 }
412
413 if (directory_exists("/var/games/roguelike"))
414 return("/var/games/roguelike");
415 if (directory_exists("/var/lib/roguelike"))
416 return("/var/lib/roguelike");
417 if (directory_exists("/var/roguelike"))
418 return("/var/roguelike");
419 if (directory_exists("/usr/games/lib"))
420 return("/usr/games/lib");
421 if (directory_exists("/games/roguelik"))
422 return("/games/roguelik");
423 if (directory_exists(md_gethomedir()))
424 return(md_gethomedir());
425 return("");
426 }
427
428 char *
429 md_getrealname(int uid)
430 {
431 static char uidstr[20];
432 #if !defined(_WIN32) && !defined(DJGPP)
433 struct passwd *pp;
434
435 if ((pp = getpwuid(uid)) == NULL)
436 {
437 sprintf(uidstr,"%d", uid);
438 return(uidstr);
439 }
440 else
441 return(pp->pw_name);
442 #else
443 sprintf(uidstr,"%d", uid);
444 return(uidstr);
445 #endif
446 }
447
448 extern char *xcrypt(char *key, char *salt);
449
450 char *
451 md_crypt(char *key, char *salt)
452 {
453 return( xcrypt(key,salt) );
454 }
455
456 char *
457 md_getpass(char *prompt)
458 {
459 #ifdef _WIN32
460 static char password_buffer[9];
461 char *p = password_buffer;
462 int c, count = 0;
463 int max_length = 9;
464
465 fflush(stdout);
466 /* If we can't prompt, abort */
467 if (fputs(prompt, stderr) < 0)
468 {
469 *p = '\0';
470 return NULL;
471 }
472
473 for(;;)
474 {
475 /* Get a character with no echo */
476 c = _getch();
477
478 /* Exit on interrupt (^c or ^break) */
479 if (c == '\003' || c == 0x100)
480 exit(1);
481
482 /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
483 if (c == '\r' || c == '\n' || c == '\004' || c == '\032')
484 break;
485
486 /* Back up on backspace */
487 if (c == '\b')
488 {
489 if (count)
490 count--;
491 else if (p > password_buffer)
492 p--;
493 continue;
494 }
495
496 /* Ignore DOS extended characters */
497 if ((c & 0xff) != c)
498 continue;
499
500 /* Add to password if it isn't full */
501 if (p < password_buffer + max_length - 1)
502 *p++ = c;
503 else
504 count++;
505 }
506 *p = '\0';
507
508 fputc('\n', stderr);
509
510 return password_buffer;
511 #else
512 return( (char *) getpass(prompt) );
513 #endif
514 }
515
516
517 int md_endian = 0x01020304;
518
519 unsigned long int
520 md_ntohl(unsigned long int x)
521 {
522 #ifdef _WIN32
523 if ( *((char *)&md_endian) == 0x01 )
524 return(x);
525 else
526 return( ((x & 0x000000ffU) << 24) |
527 ((x & 0x0000ff00U) << 8) |
528 ((x & 0x00ff0000U) >> 8) |
529 ((x & 0xff000000U) >> 24) );
530 #else
531 return( ntohl(x) );
532 #endif
533 }
534
535 unsigned long int
536 md_htonl(unsigned long int x)
537 {
538 #ifdef _WIN32
539 if ( *((char *)&md_endian) == 0x01 )
540 return(x);
541 else
542 return( ((x & 0x000000ffU) << 24) |
543 ((x & 0x0000ff00U) << 8) |
544 ((x & 0x00ff0000U) >> 8) |
545 ((x & 0xff000000U) >> 24) );
546 #else
547 return( htonl(x) );
548 #endif
549 }
550
551 int
552 md_ucount()
553 {
554 #ifdef __DJGPP__
555 return(1);
556 #elif defined(_WIN32)
557 return(1);
558 #else
559 struct utmpx *up=NULL;
560 int count=0;
561
562 setutxent();
563 do
564 {
565 up = getutxent();
566 if (up && up->ut_type == USER_PROCESS)
567 count++;
568 } while(up != NULL);
569
570 endutxent();
571
572 return(count);
573 #endif
574 }
575
576 int
577 md_getloadavg(double *avg)
578 {
579 #if defined(__GLIBC__) || defined(_BSD)
580 if (getloadavg(avg, 3) == -1)
581 #endif
582 {
583 avg[0] = avg[1] = avg[2] = 0.0;
584 return -1;
585 }
586 }
587
588 long
589 md_random()
590 {
591 #ifdef _WIN32
592 return(rand());
593 #else
594 return( random() );
595 #endif
596 }
597
598 void
599 md_srandom(unsigned x)
600 {
601 #ifdef _WIN32
602 srand(x);
603 #else
604 srandom(x);
605 #endif
606 }
607
608 int
609 md_rand()
610 {
611 #ifdef _WIN32
612 return(rand());
613 #else
614 return(lrand48() & 0x7fffffff);
615 #endif
616 }
617
618 void
619 md_srand(int seed)
620 {
621 #ifdef _WIN32
622 srand(seed);
623 #else
624 srand48(seed);
625 #endif
626 }
627
628 char *
629 md_strdup(const char *s)
630 {
631 #ifdef _WIN32
632 return( _strdup(s) );
633 #else
634 return(strdup(s));
635 #endif
636 }
637
638 long
639 md_memused()
640 {
641 #ifdef _WIN32
642 MEMORYSTATUS stat;
643
644 GlobalMemoryStatus(&stat);
645
646 return((long)stat.dwTotalPageFile);
647 #else
648 return( (long)sbrk(0) );
649 #endif
650 }
651
652 char *
653 md_gethostname()
654 {
655 static char nodename[80];
656 char *n = NULL;
657 #if !defined(_WIN32) && !defined(__DJGPP__)
658 struct utsname ourname;
659
660 if (uname(&ourname) == 0)
661 n = ourname.nodename;
662 #endif
663 if ((n == NULL) || (*n == '\0'))
664 if ( (n = getenv("COMPUTERNAME")) == NULL)
665 if ( (n = getenv("HOSTNAME")) == NULL)
666 n = "localhost";
667
668 strncpy(nodename, n, 80);
669 nodename[79] = 0;
670
671 return(nodename);
672 }
673
674 int
675 md_erasechar()
676 {
677 #ifdef BSD
678 return(_tty.sg_erase); /* process erase character */
679 #elif defined(USG5_0)
680 return(_tty.c_cc[VERASE]); /* process erase character */
681 #else /* USG5_2 .... curses */
682 return( erasechar() ); /* process erase character */
683 #endif
684 }
685
686 int
687 md_killchar()
688 {
689 #ifdef BSD
690 return(_tty.sg_kill);
691 #elif defined(USG5_0)
692 return(_tty.c_cc[VKILL]);
693 #else /* USG5_2 ..... curses */
694 return( killchar() );
695 #endif
696 }
697
698 /*
699 * unctrl:
700 * Print a readable version of a certain character
701 */
702
703 char *
704 md_unctrl(char ch)
705 {
706 #if USG5_0
707 extern char *_unctrl[]; /* Defined in curses library */
708
709 return _unctrl[ch&0177];
710 #else
711 return( unctrl(ch) );
712 #endif
713 }
714
715 void
716 md_flushinp()
717 {
718 #ifdef BSD
719 ioctl(0, TIOCFLUSH);
720 #elif defined(USG5_0)
721 ioctl(_tty_ch,TCFLSH,0)
722 #else /* USG5_2.... curses */
723 flushinp();
724 #endif
725 }
726
727 /*
728 Cursor/Keypad Support
729
730 Sadly Cursor/Keypad support is less straightforward than it should be.
731
732 The various terminal emulators/consoles choose to differentiate the
733 cursor and keypad keys (with modifiers) in different ways (if at all!).
734 Furthermore they use different code set sequences for each key only
735 a subset of which the various curses libraries recognize. Partly due
736 to incomplete termcap/terminfo entries and partly due to inherent
737 limitations of those terminal capability databases.
738
739 I give curses first crack at decoding the sequences. If it fails to decode
740 it we check for common ESC-prefixed sequences.
741
742 All cursor/keypad results are translated into standard rogue movement
743 commands.
744
745 Unmodified keys are translated to walk commands: hjklyubn
746 Modified (shift,control,alt) are translated to run commands: HJKLYUBN
747
748 Console and supported (differentiated) keys
749 Interix: Cursor Keys, Keypad, Ctl-Keypad
750 Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys
751 MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad
752 Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
753 DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
754
755 Interix Console (raw, ncurses)
756 ==============================
757 normal shift ctrl alt
758 ESC [D, ESC F^, ESC [D, ESC [D /# Left #/
759 ESC [C, ESC F$, ESC [C, ESC [C /# Right #/
760 ESC [A, ESC F-, local win, ESC [A /# Up #/
761 ESC [B, ESC F+, local win, ESC [B /# Down #/
762 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
763 ESC [S, local win, ESC [S, ESC [S /# Page Up #/
764 ESC [T, local win, ESC [T, ESC [T /# Page Down #/
765 ESC [U, ESC [U, ESC [U, ESC [U /# End #/
766 ESC [D, ESC F^, ESC [D, O /# Keypad Left #/
767 ESC [C, ESC F$, ESC [C, O /# Keypad Right #/
768 ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/
769 ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/
770 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
771 ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/
772 ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/
773 ESC [U, ESC [U, ESC [-21, O /# Keypad End #/
774 nothing, nothing, nothing, O /# Kaypad 5 #/
775
776 Interix Console (term=interix, ncurses)
777 ==============================
778 KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/
779 KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/
780 KEY_UP, 0x146, local win, KEY_UP /# Up #/
781 KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/
782 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
783 KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/
784 KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/
785 KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/
786 KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/
787 KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/
788 KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/
789 KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/
790 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
791 KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/
792 KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/
793 KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/
794 nothing, nothing, nothing, O /# Keypad 5 #/
795
796 Cygwin Console (raw, ncurses)
797 ==============================
798 normal shift ctrl alt
799 ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/
800 ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/
801 ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/
802 ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/
803 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/
804 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/
805 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/
806 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/
807 ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/
808 ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/
809 ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/
810 ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/
811 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/
812 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/
813 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/
814 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/
815 ESC [-71, nothing, nothing, O /# Keypad 5 #/
816
817 Cygwin Console (term=cygwin, ncurses)
818 ==============================
819 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/
820 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/
821 KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/
822 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/
823 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/
824 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/
825 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/
826 KEY_END, KEY_END, KEY_END, ESC-360 /# End #/
827 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/
828 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/
829 KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/
830 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/
831 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/
832 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/
833 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/
834 KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/
835 ESC [G, nothing, nothing, O /# Keypad 5 #/
836
837 MSYS Console (raw, ncurses)
838 ==============================
839 normal shift ctrl alt
840 ESC OD, ESC [d, ESC Od nothing /# Left #/
841 ESC OE, ESC [e, ESC Oe, nothing /# Right #/
842 ESC OA, ESC [a, ESC Oa, nothing /# Up #/
843 ESC OB, ESC [b, ESC Ob, nothing /# Down #/
844 ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/
845 ESC [5~, local window, ESC [5^, nothing /# Page Up #/
846 ESC [6~, local window, ESC [6^, nothing /# Page Down #/
847 ESC [8~, ESC [8$, ESC [8^, nothing /# End #/
848 ESC OD, ESC [d, ESC Od O /# Keypad Left #/
849 ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/
850 ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/
851 ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/
852 ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/
853 ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/
854 ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/
855 ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/
856 11, 11, 11, O /# Keypad 5 #/
857
858 MSYS Console (term=rxvt, ncurses)
859 ==============================
860 normal shift ctrl alt
861 KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/
862 KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/
863 KEY_UP, 518, 519, nothing /# Up #/
864 KEY_DOWN, 511, 512, nothing /# Down #/
865 KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/
866 KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/
867 KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/
868 KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/
869 KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/
870 KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/
871 KEY_UP, 518, 519, O /# Keypad Up #/
872 KEY_DOWN, 511, 512, O /# Keypad Down #/
873 KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/
874 KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/
875 KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/
876 KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/
877 11, 11, 11, O /# Keypad 5 #/
878
879 Win32 Console (raw, pdcurses)
880 DJGPP Console (raw, pdcurses)
881 ==============================
882 normal shift ctrl alt
883 260, 391, 443, 493 /# Left #/
884 261, 400, 444, 492 /# Right #/
885 259, 547, 480, 490 /# Up #/
886 258, 548, 481, 491 /# Down #/
887 262, 388, 447, 524 /# Home #/
888 339, 396, 445, 526 /# Page Up #/
889 338, 394, 446, 520 /# Page Down #/
890 358, 384, 448, 518 /# End #/
891 452, 52('4'), 511, 521 /# Keypad Left #/
892 454, 54('6'), 513, 523 /# Keypad Right #/
893 450, 56('8'), 515, 525 /# Keypad Up #/
894 456, 50('2'), 509, 519 /# Keypad Down #/
895 449, 55('7'), 514, 524 /# Keypad Home #/
896 451, 57('9'), 516, 526 /# Keypad PgUp #/
897 457, 51('3'), 510, 520 /# Keypad PgDn #/
898 455, 49('1'), 508, 518 /# Keypad End #/
899 453, 53('5'), 512, 522 /# Keypad 5 #/
900
901 Win32 Console (pdcurses, MSVC/MingW32)
902 DJGPP Console (pdcurses)
903 ==============================
904 normal shift ctrl alt
905 KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/
906 KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/
907 KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/
908 KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/
909 KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/
910 KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/
911 KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/
912 KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/
913 KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/
914 KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/
915 KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/
916 KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/
917 KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/
918 KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/
919 KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/
920 KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/
921 KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/
922
923 Windows Telnet (raw)
924 ==============================
925 normal shift ctrl alt
926 ESC [D, ESC [D, ESC [D, ESC [D /# Left #/
927 ESC [C, ESC [C, ESC [C, ESC [C /# Right #/
928 ESC [A, ESC [A, ESC [A, ESC [A /# Up #/
929 ESC [B, ESC [B, ESC [B, ESC [B /# Down #/
930 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
931 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/
932 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/
933 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
934 ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/
935 ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/
936 ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/
937 ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/
938 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
939 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/
940 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/
941 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/
942 nothing, nothing, nothing, nothing /# Keypad 5 #/
943
944 Windows Telnet (term=xterm)
945 ==============================
946 normal shift ctrl alt
947 KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/
948 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/
949 KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/
950 KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/
951 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
952 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/
953 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/
954 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
955 KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/
956 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/
957 KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/
958 KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/
959 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
960 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/
961 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/
962 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
963 ESC [-71, nothing, nothing, O /# Keypad 5 #/
964
965 PuTTY
966 ==============================
967 normal shift ctrl alt
968 ESC [D, ESC [D, ESC OD, ESC [D /# Left #/
969 ESC [C, ESC [C, ESC OC, ESC [C /# Right #/
970 ESC [A, ESC [A, ESC OA, ESC [A /# Up #/
971 ESC [B, ESC [B, ESC OB, ESC [B /# Down #/
972 ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/
973 ESC [5~, local win, local win, ESC [5~ /# Page Up #/
974 ESC [6~, local win, local win, ESC [6~ /# Page Down #/
975 ESC [4~, ESC [4~, local win, ESC [4~ /# End #/
976 ESC [D, ESC [D, ESC [D, O /# Keypad Left #/
977 ESC [C, ESC [C, ESC [C, O /# Keypad Right #/
978 ESC [A, ESC [A, ESC [A, O /# Keypad Up #/
979 ESC [B, ESC [B, ESC [B, O /# Keypad Down #/
980 ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/
981 ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/
982 ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/
983 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
984 nothing, nothing, nothing, O /# Keypad 5 #/
985
986 PuTTY
987 ==============================
988 normal shift ctrl alt
989 KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/
990 KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/
991 KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/
992 KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/
993 ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/
994 KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/
995 KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/
996 ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/
997 ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/
998 ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/
999 ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/
1000 ESC Or, ESC Or, ESC Or, O /# Keypad Down #/
1001 ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/
1002 ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/
1003 ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/
1004 ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/
1005 ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/
1006 */
1007
1008 #define M_NORMAL 0
1009 #define M_ESC 1
1010 #define M_KEYPAD 2
1011 #define M_TRAIL 3
1012
1013 int
1014 md_readchar(WINDOW *win)
1015 {
1016 int ch = 0;
1017 int lastch = 0;
1018 int mode = M_NORMAL;
1019 int mode2 = M_NORMAL;
1020
1021 for(;;)
1022 {
1023 ch = wgetch(win);
1024
1025 if (ch == ERR) /* timed out waiting for valid sequence */
1026 { /* flush input so far and start over */
1027 mode = M_NORMAL;
1028 nocbreak();
1029 raw();
1030 ch = 27;
1031 break;
1032 }
1033
1034 if (mode == M_TRAIL)
1035 {
1036 if (ch == '^') /* msys console : 7,5,6,8: modified*/
1037 ch = MOD_MOVE( toupper(lastch) );
1038
1039 if (ch == '~') /* cygwin console: 1,5,6,4: normal */
1040 ch = tolower(lastch); /* windows telnet: 1,5,6,4: normal */
1041 /* msys console : 7,5,6,8: normal */
1042
1043 if (mode2 == M_ESC) /* cygwin console: 1,5,6,4: modified*/
1044 ch = MOD_MOVE( toupper(ch) );
1045
1046 break;
1047 }
1048
1049 if (mode == M_ESC)
1050 {
1051 if (ch == 27)
1052 {
1053 mode2 = M_ESC;
1054 continue;
1055 }
1056
1057 if ((ch == 'F') || (ch == 'O') || (ch == '['))
1058 {
1059 mode = M_KEYPAD;
1060 continue;
1061 }
1062
1063
1064 switch(ch)
1065 {
1066 /* Cygwin Console */
1067 /* PuTTY */
1068 case KEY_LEFT : ch = MOD_MOVE('H'); break;
1069 case KEY_RIGHT: ch = MOD_MOVE('L'); break;
1070 case KEY_UP : ch = MOD_MOVE('K'); break;
1071 case KEY_DOWN : ch = MOD_MOVE('J'); break;
1072 case KEY_HOME : ch = MOD_MOVE('Y'); break;
1073 case KEY_PPAGE: ch = MOD_MOVE('U'); break;
1074 case KEY_NPAGE: ch = MOD_MOVE('N'); break;
1075 case KEY_END : ch = MOD_MOVE('B'); break;
1076
1077 default: break;
1078 }
1079
1080 break;
1081 }
1082
1083 if (mode == M_KEYPAD)
1084 {
1085 switch(ch)
1086 {
1087 /* ESC F - Interix Console codes */
1088 case '^': ch = MOD_MOVE('H'); break; /* Shift-Left */
1089 case '$': ch = MOD_MOVE('L'); break; /* Shift-Right */
1090
1091 /* ESC [ - Interix Console codes */
1092 case 'H': ch = 'y'; break; /* Home */
1093 case 1: ch = MOD_MOVE('K'); break; /* Ctl-Keypad Up */
1094 case 2: ch = MOD_MOVE('J'); break; /* Ctl-Keypad Down */
1095 case 3: ch = MOD_MOVE('L'); break; /* Ctl-Keypad Right */
1096 case 4: ch = MOD_MOVE('H'); break; /* Ctl-Keypad Left */
1097 case 263: ch = MOD_MOVE('Y'); break; /* Ctl-Keypad Home */
1098 case 19: ch = MOD_MOVE('U'); break; /* Ctl-Keypad PgUp */
1099 case 20: ch = MOD_MOVE('N'); break; /* Ctl-Keypad PgDn */
1100 case 21: ch = MOD_MOVE('B'); break; /* Ctl-Keypad End */
1101
1102 /* ESC [ - Cygwin Console codes */
1103 case 'G': ch = '.'; break; /* Keypad 5 */
1104 case '7': lastch = 'Y'; mode=M_TRAIL; break; /* Ctl-Home */
1105 case '5': lastch = 'U'; mode=M_TRAIL; break; /* Ctl-PgUp */
1106 case '6': lastch = 'N'; mode=M_TRAIL; break; /* Ctl-PgDn */
1107
1108 /* ESC [ - Win32 Telnet, PuTTY */
1109 case '1': lastch = 'y'; mode=M_TRAIL; break; /* Home */
1110 case '4': lastch = 'b'; mode=M_TRAIL; break; /* End */
1111
1112 /* ESC O - PuTTY */
1113 case 'D': ch = MOD_MOVE('H'); break;
1114 case 'C': ch = MOD_MOVE('L'); break;
1115 case 'A': ch = MOD_MOVE('K'); break;
1116 case 'B': ch = MOD_MOVE('J'); break;
1117 case 't': ch = 'h'; break;
1118 case 'v': ch = 'l'; break;
1119 case 'x': ch = 'k'; break;
1120 case 'r': ch = 'j'; break;
1121 case 'w': ch = 'y'; break;
1122 case 'y': ch = 'u'; break;
1123 case 's': ch = 'n'; break;
1124 case 'q': ch = 'b'; break;
1125 case 'u': ch = '.'; break;
1126 }
1127
1128 if (mode != M_KEYPAD)
1129 continue;
1130 }
1131
1132 if (ch == 27)
1133 {
1134 halfdelay(1);
1135 mode = M_ESC;
1136 continue;
1137 }
1138
1139 switch(ch)
1140 {
1141 case KEY_LEFT : ch = 'h'; break;
1142 case KEY_DOWN : ch = 'j'; break;
1143 case KEY_UP : ch = 'k'; break;
1144 case KEY_RIGHT : ch = 'l'; break;
1145 case KEY_HOME : ch = 'y'; break;
1146 case KEY_PPAGE : ch = 'u'; break;
1147 case KEY_END : ch = 'b'; break;
1148 #ifdef KEY_LL
1149 case KEY_LL : ch = 'b'; break;
1150 #endif
1151 case KEY_NPAGE : ch = 'n'; break;
1152
1153 #ifdef KEY_B1
1154 case KEY_B1 : ch = 'h'; break;
1155 case KEY_C2 : ch = 'j'; break;
1156 case KEY_A2 : ch = 'k'; break;
1157 case KEY_B3 : ch = 'l'; break;
1158 #endif
1159 case KEY_A1 : ch = 'y'; break;
1160 case KEY_A3 : ch = 'u'; break;
1161 case KEY_C1 : ch = 'b'; break;
1162 case KEY_C3 : ch = 'n'; break;
1163 /* next should be '.', but for problem with putty/linux */
1164 case KEY_B2 : ch = 'u'; break;
1165
1166 #ifdef KEY_SLEFT
1167 case KEY_SRIGHT : ch = MOD_MOVE('L'); break;
1168 case KEY_SLEFT : ch = MOD_MOVE('H'); break;
1169 #ifdef KEY_SUP
1170 case KEY_SUP : ch = MOD_MOVE('K'); break;
1171 case KEY_SDOWN : ch = MOD_MOVE('J'); break;
1172 #endif
1173 case KEY_SHOME : ch = MOD_MOVE('Y'); break;
1174 case KEY_SPREVIOUS:ch = MOD_MOVE('U'); break;
1175 case KEY_SEND : ch = MOD_MOVE('B'); break;
1176 case KEY_SNEXT : ch = MOD_MOVE('N'); break;
1177 #endif
1178 case 0x146 : ch = MOD_MOVE('K'); break; /* Shift-Up */
1179 case 0x145 : ch = MOD_MOVE('J'); break; /* Shift-Down */
1180
1181 #ifdef CTL_RIGHT
1182 case CTL_RIGHT : ch = MOD_MOVE('L'); break;
1183 case CTL_LEFT : ch = MOD_MOVE('H'); break;
1184 case CTL_UP : ch = MOD_MOVE('K'); break;
1185 case CTL_DOWN : ch = MOD_MOVE('J'); break;
1186 case CTL_HOME : ch = MOD_MOVE('Y'); break;
1187 case CTL_PGUP : ch = MOD_MOVE('U'); break;
1188 case CTL_END : ch = MOD_MOVE('B'); break;
1189 case CTL_PGDN : ch = MOD_MOVE('N'); break;
1190 #endif
1191 #ifdef KEY_EOL
1192 case KEY_EOL : ch = MOD_MOVE('B'); break;
1193 #endif
1194
1195 #ifndef CTL_PAD1
1196 /* MSYS rxvt console */
1197 case 511 : ch = MOD_MOVE('J'); break; /* Shift Dn */
1198 case 512 : ch = MOD_MOVE('J'); break; /* Ctl Down */
1199 case 514 : ch = MOD_MOVE('H'); break; /* Ctl Left */
1200 case 516 : ch = MOD_MOVE('L'); break; /* Ctl Right*/
1201 case 518 : ch = MOD_MOVE('K'); break; /* Shift Up */
1202 case 519 : ch = MOD_MOVE('K'); break; /* Ctl Up */
1203 #endif
1204
1205 #ifdef CTL_PAD1
1206 case CTL_PAD1 : ch = MOD_MOVE('B'); break;
1207 case CTL_PAD2 : ch = MOD_MOVE('J'); break;
1208 case CTL_PAD3 : ch = MOD_MOVE('N'); break;
1209 case CTL_PAD4 : ch = MOD_MOVE('H'); break;
1210 case CTL_PAD5 : ch = '.'; break;
1211 case CTL_PAD6 : ch = MOD_MOVE('L'); break;
1212 case CTL_PAD7 : ch = MOD_MOVE('Y'); break;
1213 case CTL_PAD8 : ch = MOD_MOVE('K'); break;
1214 case CTL_PAD9 : ch = MOD_MOVE('U'); break;
1215 #endif
1216
1217 #ifdef ALT_RIGHT
1218 case ALT_RIGHT : ch = MOD_MOVE('L'); break;
1219 case ALT_LEFT : ch = MOD_MOVE('H'); break;
1220 case ALT_DOWN : ch = MOD_MOVE('J'); break;
1221 case ALT_HOME : ch = MOD_MOVE('Y'); break;
1222 case ALT_PGUP : ch = MOD_MOVE('U'); break;
1223 case ALT_END : ch = MOD_MOVE('B'); break;
1224 case ALT_PGDN : ch = MOD_MOVE('N'); break;
1225 #endif
1226
1227 #ifdef ALT_PAD1
1228 case ALT_PAD1 : ch = MOD_MOVE('B'); break;
1229 case ALT_PAD2 : ch = MOD_MOVE('J'); break;
1230 case ALT_PAD3 : ch = MOD_MOVE('N'); break;
1231 case ALT_PAD4 : ch = MOD_MOVE('H'); break;
1232 case ALT_PAD5 : ch = '.'; break;
1233 case ALT_PAD6 : ch = MOD_MOVE('L'); break;
1234 case ALT_PAD7 : ch = MOD_MOVE('Y'); break;
1235 case ALT_PAD8 : ch = MOD_MOVE('K'); break;
1236 case ALT_PAD9 : ch = MOD_MOVE('U'); break;
1237 #endif
1238 }
1239
1240 break;
1241 }
1242
1243 nocbreak(); /* disable halfdelay mode if on */
1244 raw();
1245
1246 return(ch & 0x7F);
1247 }