comparison rogue3/mdport.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children 9a2c0c60c386
comparison
equal deleted inserted replaced
-1:000000000000 0:527e2150eaf0
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 #include <stdlib.h>
33 #include <string.h>
34
35 #if defined(_WIN32)
36 #include <Windows.h>
37 #include <io.h>
38 #include <sys/locking.h>
39 #include <Lmcons.h>
40 #include <conio.h>
41 #pragma warning( disable: 4201 )
42 #include <shlobj.h>
43 #pragma warning( default: 4201 )
44 #include <Shlwapi.h>
45 #undef MOUSE_MOVED
46 #endif
47
48 #include <curses.h>
49
50 #include "mdport.h"
51
52 #if defined(HAVE_SYS_TYPES)
53 #include <sys/types.h>
54 #endif
55
56 #if defined(HAVE_PROCESS_H)
57 #include <process.h>
58 #endif
59
60 #if defined(HAVE_PWD_H)
61 #include <pwd.h>
62 #endif
63
64 #if defined(HAVE_SYS_UTSNAME)
65 #include <sys/utsname.h>
66 #endif
67
68 #if defined(HAVE_ARPA_INET_H)
69 #include <arpa/inet.h> /* Solaris 2.8 required this for htonl() and ntohl() */
70 #endif
71
72 #if defined(HAVE_TERMIOS_H)
73 #include <termios.h>
74 #endif
75
76 #if defined(HAVE_UNISTD_H)
77 #ifndef __USE_GNU
78 #define __USE_GNU
79 #include <unistd.h>
80 #undef __USE_GNU
81 #else
82 #include <unistd.h>
83 #endif
84 #endif
85
86 #if defined(HAVE_TERM_H)
87 #include <term.h>
88 #elif defined(HAVE_NCURSES_TERM_H)
89 #include <ncurses/term.h>
90 #endif
91
92 #if defined(HAVE_WORKING_FORK)
93 #include <sys/wait.h>
94 #endif
95
96 #ifdef HAVE_UTMPX_H
97 #include <utmpx.h>
98 #endif
99
100 #ifdef HAVE_ERRNO_H
101 #include <errno.h>
102 #endif
103
104 #include <ctype.h>
105 #include <fcntl.h>
106 #include <limits.h>
107 #include <sys/stat.h>
108 #include <signal.h>
109
110 #define NOOP(x) (x += 0)
111
112 static int pass_ctrl_keypad = 1;
113
114 void
115 md_init(int options)
116 {
117 #if defined(__INTERIX)
118 char *term;
119
120 term = getenv("TERM");
121
122 if (term == NULL)
123 setenv("TERM","interix");
124 #elif defined(__DJGPP__)
125 _fmode = _O_BINARY;
126 #elif defined(_WIN32)
127 _fmode = _O_BINARY;
128 #endif
129
130 #if defined(HAVE_ESCDELAY) || defined(NCURSES_VERSION)
131 ESCDELAY=64;
132 #endif
133
134 #if defined(DUMP)
135 md_onsignal_default();
136 #else
137 md_onsignal_exit();
138 #endif
139
140 if (options & MD_STRIP_CTRL_KEYPAD)
141 pass_ctrl_keypad = 0;
142 else
143 pass_ctrl_keypad = 1;
144 }
145
146 void
147 md_onsignal_default(void)
148 {
149 #ifdef SIGHUP
150 signal(SIGHUP, SIG_DFL);
151 #endif
152 #ifdef SIGQUIT
153 signal(SIGQUIT, SIG_DFL);
154 #endif
155 #ifdef SIGILL
156 signal(SIGILL, SIG_DFL);
157 #endif
158 #ifdef SIGTRAP
159 signal(SIGTRAP, SIG_DFL);
160 #endif
161 #ifdef SIGIOT
162 signal(SIGIOT, SIG_DFL);
163 #endif
164 #ifdef SIGEMT
165 signal(SIGEMT, SIG_DFL);
166 #endif
167 #ifdef SIGFPE
168 signal(SIGFPE, SIG_DFL);
169 #endif
170 #ifdef SIGBUS
171 signal(SIGBUS, SIG_DFL);
172 #endif
173 #ifdef SIGSEGV
174 signal(SIGSEGV, SIG_DFL);
175 #endif
176 #ifdef SIGSYS
177 signal(SIGSYS, SIG_DFL);
178 #endif
179 #ifdef SIGTERM
180 signal(SIGTERM, SIG_DFL);
181 #endif
182 }
183
184 void
185 md_onsignal_exit(void)
186 {
187 #ifdef SIGHUP
188 signal(SIGHUP, SIG_DFL);
189 #endif
190 #ifdef SIGQUIT
191 signal(SIGQUIT, exit);
192 #endif
193 #ifdef SIGILL
194 signal(SIGILL, exit);
195 #endif
196 #ifdef SIGTRAP
197 signal(SIGTRAP, exit);
198 #endif
199 #ifdef SIGIOT
200 signal(SIGIOT, exit);
201 #endif
202 #ifdef SIGEMT
203 signal(SIGEMT, exit);
204 #endif
205 #ifdef SIGFPE
206 signal(SIGFPE, exit);
207 #endif
208 #ifdef SIGBUS
209 signal(SIGBUS, exit);
210 #endif
211 #ifdef SIGSEGV
212 signal(SIGSEGV, exit);
213 #endif
214 #ifdef SIGSYS
215 signal(SIGSYS, exit);
216 #endif
217 #ifdef SIGTERM
218 signal(SIGTERM, exit);
219 #endif
220 }
221
222 extern void auto_save(int sig);
223 extern void endit(int sig);
224 extern void quit(int sig);
225
226 void
227 md_onsignal_autosave(void)
228 {
229
230 #ifdef SIGHUP
231 signal(SIGHUP, auto_save);
232 #endif
233 #ifdef SIGQUIT
234 signal(SIGQUIT, endit);
235 #endif
236 #ifdef SIGILL
237 signal(SIGILL, auto_save);
238 #endif
239 #ifdef SIGTRAP
240 signal(SIGTRAP, auto_save);
241 #endif
242 #ifdef SIGIOT
243 signal(SIGIOT, auto_save);
244 #endif
245 #ifdef SIGEMT
246 signal(SIGEMT, auto_save);
247 #endif
248 #ifdef SIGFPE
249 signal(SIGFPE, auto_save);
250 #endif
251 #ifdef SIGBUS
252 signal(SIGBUS, auto_save);
253 #endif
254 #ifdef SIGSEGV
255 signal(SIGSEGV, auto_save);
256 #endif
257 #ifdef SIGSYS
258 signal(SIGSYS, auto_save);
259 #endif
260 #ifdef SIGTERM
261 signal(SIGTERM, auto_save);
262 #endif
263 #ifdef SIGINT
264 signal(SIGINT, quit);
265 #endif
266 }
267
268 int
269 md_hasclreol(void)
270 {
271 #if defined(clr_eol)
272 #ifdef NCURSES_VERSION
273 if (cur_term == NULL)
274 return(0);
275 if (cur_term->type.Strings == NULL)
276 return(0);
277 #endif
278 return((clr_eol != NULL) && (*clr_eol != 0));
279 #elif defined(__PDCURSES__)
280 return(TRUE);
281 #else
282 return((CE != NULL) && (*CE != 0));
283 #endif
284 }
285
286 void
287 md_putchar(int c)
288 {
289 putchar(c);
290 }
291
292 #ifdef _WIN32
293 static int md_standout_mode = 0;
294 #endif
295
296 void
297 md_raw_standout(void)
298 {
299 #ifdef _WIN32
300 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
301 HANDLE hStdout;
302 WORD fgattr,bgattr;
303
304 if (md_standout_mode == 0)
305 {
306 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
307 GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
308 fgattr = (csbiInfo.wAttributes & 0xF);
309 bgattr = (csbiInfo.wAttributes & 0xF0);
310 SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
311 md_standout_mode = 1;
312 }
313 #elif defined(SO)
314 tputs(SO,0,md_putchar);
315 fflush(stdout);
316 #endif
317 }
318
319 void
320 md_raw_standend(void)
321 {
322 #ifdef _WIN32
323 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
324 HANDLE hStdout;
325 WORD fgattr,bgattr;
326
327 if (md_standout_mode == 1)
328 {
329 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
330 GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
331 fgattr = (csbiInfo.wAttributes & 0xF);
332 bgattr = (csbiInfo.wAttributes & 0xF0);
333 SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
334 md_standout_mode = 0;
335 }
336 #elif defined(SE)
337 tputs(SE,0,md_putchar);
338 fflush(stdout);
339 #endif
340 }
341
342 int
343 md_unlink_open_file(const char *file, FILE *inf)
344 {
345 #ifdef _WIN32
346 fclose(inf);
347 (void) _chmod(file, 0600);
348 return( _unlink(file) );
349 #else
350 return(unlink(file));
351 #endif
352 }
353
354 int
355 md_unlink(char *file)
356 {
357 #ifdef _WIN32
358 (void) _chmod(file, 0600);
359 return( _unlink(file) );
360 #else
361 return(unlink(file));
362 #endif
363 }
364
365 int
366 md_chmod(const char *filename, int mode)
367 {
368 #ifdef _WIN32
369 return( _chmod(filename, mode) );
370 #else
371 return( chmod(filename, mode) );
372 #endif
373 }
374
375 void
376 md_normaluser(void)
377 {
378 #if defined(HAVE_GETGID) && defined(HAVE_GETUID)
379 gid_t realgid = getgid();
380 uid_t realuid = getuid();
381
382 #if defined(HAVE_SETRESGID)
383 if (setresgid(-1, realgid, realgid) != 0) {
384 #elif defined (HAVE_SETREGID)
385 if (setregid(realgid, realgid) != 0) {
386 #elif defined (HAVE_SETGID)
387 if (setgid(realgid) != 0) {
388 #else
389 if (0) {
390 #endif
391 perror("Could not drop setgid privileges. Aborting.");
392 exit(1);
393 }
394
395 #if defined(HAVE_SETRESUID)
396 if (setresuid(-1, realuid, realuid) != 0) {
397 #elif defined(HAVE_SETREUID)
398 if (setreuid(realuid, realuid) != 0) {
399 #elif defined(HAVE_SETUID)
400 if (setuid(realuid) != 0) {
401 #else
402 if (0) {
403 #endif
404 perror("Could not drop setuid privileges. Aborting.");
405 exit(1);
406 }
407 #endif
408 }
409
410 uid_t
411 md_getuid(void)
412 {
413 #ifdef HAVE_GETUID
414 return( getuid() );
415 #else
416 return(42);
417 #endif
418 }
419
420 pid_t
421 md_getpid(void)
422 {
423 #ifdef _WIN32
424 return( _getpid() );
425 #else
426 return( getpid() );
427 #endif
428 }
429
430 char *
431 md_getusername(void)
432 {
433 static char login[80];
434 char *l = NULL;
435 #ifdef _WIN32
436 LPSTR mybuffer;
437 DWORD size = UNLEN + 1;
438 TCHAR buffer[UNLEN + 1];
439
440 mybuffer = buffer;
441 GetUserName(mybuffer,&size);
442 l = mybuffer;
443 #elif defined(HAVE_GETPWUID)&& !defined(__DJGPP__)
444 struct passwd *pw;
445
446 pw = getpwuid(getuid());
447
448 l = pw->pw_name;
449 #endif
450
451 if ((l == NULL) || (*l == '\0'))
452 if ( (l = getenv("USERNAME")) == NULL )
453 if ( (l = getenv("LOGNAME")) == NULL )
454 if ( (l = getenv("USER")) == NULL )
455 l = "nobody";
456
457 strncpy(login,l,80);
458 login[79] = 0;
459
460 return(login);
461 }
462
463 char *
464 md_gethomedir(void)
465 {
466 static char homedir[PATH_MAX];
467 char *h = NULL;
468 size_t len;
469 #if defined(_WIN32)
470 TCHAR szPath[PATH_MAX];
471 #endif
472 #if defined(_WIN32) || defined(DJGPP)
473 char slash = '\\';
474 #else
475 char slash = '/';
476 struct passwd *pw;
477 pw = getpwuid(getuid());
478
479 h = pw->pw_dir;
480
481 if (strcmp(h,"/") == 0)
482 h = NULL;
483 #endif
484 homedir[0] = 0;
485 #ifdef _WIN32
486 if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath)))
487 h = szPath;
488 #endif
489
490 if ( (h == NULL) || (*h == '\0') )
491 {
492 if ( (h = getenv("HOME")) == NULL )
493 {
494 if ( (h = getenv("HOMEDRIVE")) == NULL)
495 h = "";
496 else
497 {
498 strncpy(homedir,h,PATH_MAX-1);
499 homedir[PATH_MAX-1] = 0;
500
501 if ( (h = getenv("HOMEPATH")) == NULL)
502 h = "";
503 }
504 }
505 }
506
507
508 len = strlen(homedir);
509 strncat(homedir,h,PATH_MAX-len-1);
510 len = strlen(homedir);
511
512 if ((len > 0) && (homedir[len-1] != slash)) {
513 homedir[len] = slash;
514 homedir[len+1] = 0;
515 }
516
517 return(homedir);
518 }
519
520 void
521 md_sleep(int s)
522 {
523 #ifdef _WIN32
524 Sleep(s);
525 #else
526 sleep(s);
527 #endif
528 }
529
530 char *
531 md_getshell(void)
532 {
533 static char shell[PATH_MAX];
534 char *s = NULL;
535 #ifdef _WIN32
536 char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
537 #elif defined(__DJGPP__)
538 char *def = "C:\\COMMAND.COM";
539 #else
540 char *def = "/bin/sh";
541 struct passwd *pw;
542 pw = getpwuid(getuid());
543 s = pw->pw_shell;
544 #endif
545 if ((s == NULL) || (*s == '\0'))
546 if ( (s = getenv("COMSPEC")) == NULL)
547 if ( (s = getenv("SHELL")) == NULL)
548 if ( (s = getenv("SystemRoot")) == NULL)
549 s = def;
550
551 strncpy(shell,s,PATH_MAX);
552 shell[PATH_MAX-1] = 0;
553
554 return(shell);
555 }
556
557 int
558 md_shellescape(void)
559 {
560 #if defined(HAVE_WORKING_FORK)
561 int ret_status;
562 int pid;
563 void (*myquit)(int);
564 void (*myend)(int);
565 char *sh;
566
567 sh = md_getshell();
568
569 while((pid = fork()) < 0)
570 sleep(1);
571
572 if (pid == 0) /* Shell Process */
573 {
574 /*
575 * Set back to original user, just in case
576 */
577 md_normaluser();
578 execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", NULL);
579 perror("No shelly");
580 _exit(-1);
581 }
582 else /* Application */
583 {
584 myend = signal(SIGINT, SIG_IGN);
585 #ifdef SIGQUIT
586 myquit = signal(SIGQUIT, SIG_IGN);
587 #endif
588 while (wait(&ret_status) != pid)
589 continue;
590
591 signal(SIGINT, myquit);
592 #ifdef SIGQUIT
593 signal(SIGQUIT, myend);
594 #endif
595 }
596 return(ret_status);
597 #elif defined(HAVE__SPAWNL)
598 return((int)_spawnl(_P_WAIT,md_getshell(),"shell",NULL,0));
599 #elif defined(HAVE_SPAWNL)
600 return ( spawnl(P_WAIT,md_getshell(),"shell",NULL,0) );
601 #else
602 return(0);
603 #endif
604 }
605
606 int
607 directory_exists(char *dirname)
608 {
609 struct stat sb;
610
611 if (stat(dirname, &sb) == 0) /* path exists */
612 return (sb.st_mode & S_IFDIR);
613
614 return(0);
615 }
616
617 char *
618 md_getrealname(uid_t uid)
619 {
620 static char uidstr[20];
621 #if !defined(_WIN32) && !defined(DJGPP)
622 struct passwd *pp;
623
624 if ((pp = getpwuid(uid)) == NULL)
625 {
626 sprintf(uidstr,"%d", uid);
627 return(uidstr);
628 }
629 else
630 return(pp->pw_name);
631 #else
632 sprintf(uidstr,"%d", uid);
633 return(uidstr);
634 #endif
635 }
636
637 char *
638 md_getpass(char *prompt)
639 {
640 #ifndef HAVE_GETPASS
641 static char password_buffer[9];
642 char *p = password_buffer;
643 int c, count = 0;
644 int max_length = 9;
645
646 fflush(stdout);
647 /* If we can't prompt, abort */
648 if (fputs(prompt, stderr) < 0)
649 {
650 *p = '\0';
651 return NULL;
652 }
653
654 for(;;)
655 {
656 /* Get a character with no echo */
657 c = _getch();
658
659 /* Exit on interrupt (^c or ^break) */
660 if (c == '\003' || c == 0x100)
661 exit(1);
662
663 /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
664 if (c == '\r' || c == '\n' || c == '\004' || c == '\032')
665 break;
666
667 /* Back up on backspace */
668 if (c == '\b')
669 {
670 if (count)
671 count--;
672 else if (p > password_buffer)
673 p--;
674 continue;
675 }
676
677 /* Ignore DOS extended characters */
678 if ((c & 0xff) != c)
679 continue;
680
681 /* Add to password if it isn't full */
682 if (p < password_buffer + max_length - 1)
683 *p++ = (char) c;
684 else
685 count++;
686 }
687 *p = '\0';
688
689 fputc('\n', stderr);
690
691 return password_buffer;
692 #else
693 return( getpass(prompt) );
694 #endif
695 }
696
697 int
698 md_erasechar(void)
699 {
700 #ifdef HAVE_ERASECHAR
701 return( erasechar() ); /* process erase character */
702 #elif defined(VERASE)
703 return(_tty.c_cc[VERASE]); /* process erase character */
704 #else
705 return(_tty.sg_erase); /* process erase character */
706 #endif
707 }
708
709 int
710 md_killchar(void)
711 {
712 #ifdef HAVE_KILLCHAR
713 return( killchar() );
714 #elif defined(VKILL)
715 return(_tty.c_cc[VKILL]);
716 #else
717 return(_tty.sg_kill);
718 #endif
719 }
720
721 int
722 md_dsuspchar(void)
723 {
724 #if defined(VDSUSP) /* POSIX has priority */
725 struct termios attr;
726 tcgetattr(STDIN_FILENO, &attr);
727 return( attr.c_cc[VDSUSP] );
728 #elif defined(TIOCGLTC)
729 struct ltchars ltc;
730 ioctl(1, TIOCGLTC, &ltc);
731 return(ltc.t_dsuspc);
732 #elif defined(_POSIX_VDISABLE)
733 return(_POSIX_VDISABLE);
734 #else
735 return(0);
736 #endif
737 }
738
739 int
740 md_setdsuspchar(int c)
741 {
742 #if defined(VDSUSP) /* POSIX has priority */
743 struct termios attr;
744 tcgetattr(STDIN_FILENO, &attr);
745 attr.c_cc[VDSUSP] = c;
746 tcgetattr(STDIN_FILENO, &attr);
747 #elif defined(TIOCSLTC)
748 struct ltchars ltc;
749 ioctl(1, TIOCGLTC, &ltc);
750 ltc.t_dsuspc = c;
751 ioctl(1, TIOCSLTC, &ltc);
752 #else
753 NOOP(c);
754 #endif
755 return(0);
756 }
757
758 int
759 md_suspchar(void)
760 {
761 #if defined(VSUSP) /* POSIX has priority */
762 struct termios attr;
763 tcgetattr(STDIN_FILENO, &attr);
764 return( attr.c_cc[VSUSP] );
765 #elif defined(TIOCGLTC)
766 struct ltchars ltc;
767 ioctl(1, TIOCGLTC, &ltc);
768 return(ltc.t_suspc);
769 #elif defined(_POSIX_VDISABLE)
770 return(_POSIX_VDISABLE);
771 #else
772 return(0);
773 #endif
774 }
775
776 int
777 md_setsuspchar(int c)
778 {
779 #if defined(VSUSP) /* POSIX has priority */
780 struct termios attr;
781 tcgetattr(STDIN_FILENO, &attr);
782 attr.c_cc[VSUSP] = c;
783 tcgetattr(STDIN_FILENO, &attr);
784 #elif defined(TIOCSLTC)
785 struct ltchars ltc;
786 ioctl(1, TIOCGLTC, &ltc);
787 ltc.t_suspc = c;
788 ioctl(1, TIOCSLTC, &ltc);
789 #else
790 NOOP(c);
791 #endif
792
793 return(0);
794 }
795
796 /*
797 Cursor/Keypad Support
798
799 Sadly Cursor/Keypad support is less straightforward than it should be.
800
801 The various terminal emulators/consoles choose to differentiate the
802 cursor and keypad keys (with modifiers) in different ways (if at all!).
803 Furthermore they use different code set sequences for each key only
804 a subset of which the various curses libraries recognize. Partly due
805 to incomplete termcap/terminfo entries and partly due to inherent
806 limitations of those terminal capability databases.
807
808 I give curses first crack at decoding the sequences. If it fails to decode
809 it we check for common ESC-prefixed sequences.
810
811 All cursor/keypad results are translated into standard rogue movement
812 commands.
813
814 Unmodified keys are translated to walk commands: hjklyubn
815 Modified (shift,control,alt) are translated to run commands: HJKLYUBN
816
817 Console and supported (differentiated) keys
818 Interix: Cursor Keys, Keypad, Ctl-Keypad
819 Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys
820 MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad
821 Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
822 DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
823
824 Interix Console (raw, ncurses)
825 ==============================
826 normal shift ctrl alt
827 ESC [D, ESC F^, ESC [D, ESC [D /# Left #/
828 ESC [C, ESC F$, ESC [C, ESC [C /# Right #/
829 ESC [A, ESC F-, local win, ESC [A /# Up #/
830 ESC [B, ESC F+, local win, ESC [B /# Down #/
831 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
832 ESC [S, local win, ESC [S, ESC [S /# Page Up #/
833 ESC [T, local win, ESC [T, ESC [T /# Page Down #/
834 ESC [U, ESC [U, ESC [U, ESC [U /# End #/
835 ESC [D, ESC F^, ESC [D, O /# Keypad Left #/
836 ESC [C, ESC F$, ESC [C, O /# Keypad Right #/
837 ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/
838 ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/
839 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
840 ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/
841 ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/
842 ESC [U, ESC [U, ESC [-21, O /# Keypad End #/
843 nothing, nothing, nothing, O /# Kaypad 5 #/
844
845 Interix Console (term=interix, ncurses)
846 ==============================
847 KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/
848 KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/
849 KEY_UP, 0x146, local win, KEY_UP /# Up #/
850 KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/
851 ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
852 KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/
853 KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/
854 KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/
855 KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/
856 KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/
857 KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/
858 KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/
859 ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
860 KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/
861 KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/
862 KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/
863 nothing, nothing, nothing, O /# Keypad 5 #/
864
865 Cygwin Console (raw, ncurses)
866 ==============================
867 normal shift ctrl alt
868 ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/
869 ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/
870 ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/
871 ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/
872 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/
873 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/
874 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/
875 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/
876 ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/
877 ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/
878 ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/
879 ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/
880 ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/
881 ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/
882 ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/
883 ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/
884 ESC [-71, nothing, nothing, O /# Keypad 5 #/
885
886 Cygwin Console (term=cygwin, ncurses)
887 ==============================
888 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/
889 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/
890 KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/
891 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/
892 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/
893 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/
894 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/
895 KEY_END, KEY_END, KEY_END, ESC-360 /# End #/
896 KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/
897 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/
898 KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/
899 KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/
900 KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/
901 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/
902 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/
903 KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/
904 ESC [G, nothing, nothing, O /# Keypad 5 #/
905
906 MSYS Console (raw, ncurses)
907 ==============================
908 normal shift ctrl alt
909 ESC OD, ESC [d, ESC Od nothing /# Left #/
910 ESC OE, ESC [e, ESC Oe, nothing /# Right #/
911 ESC OA, ESC [a, ESC Oa, nothing /# Up #/
912 ESC OB, ESC [b, ESC Ob, nothing /# Down #/
913 ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/
914 ESC [5~, local window, ESC [5^, nothing /# Page Up #/
915 ESC [6~, local window, ESC [6^, nothing /# Page Down #/
916 ESC [8~, ESC [8$, ESC [8^, nothing /# End #/
917 ESC OD, ESC [d, ESC Od O /# Keypad Left #/
918 ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/
919 ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/
920 ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/
921 ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/
922 ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/
923 ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/
924 ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/
925 11, 11, 11, O /# Keypad 5 #/
926
927 MSYS Console (term=rxvt, ncurses)
928 ==============================
929 normal shift ctrl alt
930 KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/
931 KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/
932 KEY_UP, 518, 519, nothing /# Up #/
933 KEY_DOWN, 511, 512, nothing /# Down #/
934 KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/
935 KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/
936 KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/
937 KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/
938 KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/
939 KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/
940 KEY_UP, 518, 519, O /# Keypad Up #/
941 KEY_DOWN, 511, 512, O /# Keypad Down #/
942 KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/
943 KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/
944 KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/
945 KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/
946 11, 11, 11, O /# Keypad 5 #/
947
948 Win32 Console (raw, pdcurses)
949 DJGPP Console (raw, pdcurses)
950 ==============================
951 normal shift ctrl alt
952 260, 391, 443, 493 /# Left #/
953 261, 400, 444, 492 /# Right #/
954 259, 547, 480, 490 /# Up #/
955 258, 548, 481, 491 /# Down #/
956 262, 388, 447, 524 /# Home #/
957 339, 396, 445, 526 /# Page Up #/
958 338, 394, 446, 520 /# Page Down #/
959 358, 384, 448, 518 /# End #/
960 452, 52('4'), 511, 521 /# Keypad Left #/
961 454, 54('6'), 513, 523 /# Keypad Right #/
962 450, 56('8'), 515, 525 /# Keypad Up #/
963 456, 50('2'), 509, 519 /# Keypad Down #/
964 449, 55('7'), 514, 524 /# Keypad Home #/
965 451, 57('9'), 516, 526 /# Keypad PgUp #/
966 457, 51('3'), 510, 520 /# Keypad PgDn #/
967 455, 49('1'), 508, 518 /# Keypad End #/
968 453, 53('5'), 512, 522 /# Keypad 5 #/
969
970 Win32 Console (pdcurses, MSVC/MingW32)
971 DJGPP Console (pdcurses)
972 ==============================
973 normal shift ctrl alt
974 KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/
975 KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/
976 KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/
977 KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/
978 KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/
979 KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/
980 KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/
981 KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/
982 KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/
983 KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/
984 KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/
985 KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/
986 KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/
987 KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/
988 KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/
989 KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/
990 KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/
991
992 Windows Telnet (raw)
993 ==============================
994 normal shift ctrl alt
995 ESC [D, ESC [D, ESC [D, ESC [D /# Left #/
996 ESC [C, ESC [C, ESC [C, ESC [C /# Right #/
997 ESC [A, ESC [A, ESC [A, ESC [A /# Up #/
998 ESC [B, ESC [B, ESC [B, ESC [B /# Down #/
999 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
1000 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/
1001 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/
1002 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
1003 ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/
1004 ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/
1005 ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/
1006 ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/
1007 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
1008 ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/
1009 ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/
1010 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/
1011 nothing, nothing, nothing, nothing /# Keypad 5 #/
1012
1013 Windows Telnet (term=xterm)
1014 ==============================
1015 normal shift ctrl alt
1016 KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/
1017 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/
1018 KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/
1019 KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/
1020 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
1021 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/
1022 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/
1023 ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
1024 KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/
1025 KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/
1026 KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/
1027 KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/
1028 ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
1029 KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/
1030 KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/
1031 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
1032 ESC [-71, nothing, nothing, O /# Keypad 5 #/
1033
1034 PuTTY
1035 ==============================
1036 normal shift ctrl alt
1037 ESC [D, ESC [D, ESC OD, ESC [D /# Left #/
1038 ESC [C, ESC [C, ESC OC, ESC [C /# Right #/
1039 ESC [A, ESC [A, ESC OA, ESC [A /# Up #/
1040 ESC [B, ESC [B, ESC OB, ESC [B /# Down #/
1041 ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/
1042 ESC [5~, local win, local win, ESC [5~ /# Page Up #/
1043 ESC [6~, local win, local win, ESC [6~ /# Page Down #/
1044 ESC [4~, ESC [4~, local win, ESC [4~ /# End #/
1045 ESC [D, ESC [D, ESC [D, O /# Keypad Left #/
1046 ESC [C, ESC [C, ESC [C, O /# Keypad Right #/
1047 ESC [A, ESC [A, ESC [A, O /# Keypad Up #/
1048 ESC [B, ESC [B, ESC [B, O /# Keypad Down #/
1049 ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/
1050 ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/
1051 ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/
1052 ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
1053 nothing, nothing, nothing, O /# Keypad 5 #/
1054
1055 PuTTY
1056 ==============================
1057 normal shift ctrl alt
1058 KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/
1059 KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/
1060 KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/
1061 KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/
1062 ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/
1063 KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/
1064 KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/
1065 ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/
1066 ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/
1067 ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/
1068 ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/
1069 ESC Or, ESC Or, ESC Or, O /# Keypad Down #/
1070 ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/
1071 ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/
1072 ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/
1073 ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/
1074 ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/
1075 */
1076
1077 #define M_NORMAL 0
1078 #define M_ESC 1
1079 #define M_KEYPAD 2
1080 #define M_TRAIL 3
1081
1082 #ifndef CTRL
1083 #define CTRL(ch) (ch & 0x1F)
1084 #endif
1085
1086 int undo[5];
1087 int uindex = -1;
1088
1089 int
1090 reread()
1091 {
1092 int redo;
1093
1094 if (uindex < 0)
1095 return 0;
1096
1097 redo = undo[0];
1098 undo[0] = undo[1];
1099 undo[1] = undo[2];
1100 undo[2] = undo[3];
1101 undo[3] = undo[4];
1102 uindex--;
1103 return redo;
1104 }
1105
1106 void
1107 unread(int c)
1108 {
1109 if (uindex >= 4)
1110 abort();
1111
1112 undo[++uindex] = c;
1113 }
1114
1115 int
1116 md_readchar(WINDOW *win)
1117 {
1118 int ch = 0;
1119 int lastch = 0;
1120 int wch = 0;
1121 int mode = M_NORMAL;
1122 int mode2 = M_NORMAL;
1123 int nodelayf = 0;
1124 int count = 0;
1125
1126 for(;;)
1127 {
1128 if (mode == M_NORMAL && uindex >= 0)
1129 {
1130 wch = ch = reread();
1131 break;
1132 }
1133
1134 wch = ch = wgetch(win);
1135
1136 if (ch == ERR) /* timed out or error */
1137 {
1138 if (nodelayf) /* likely timed out, switch to */
1139 { /* normal mode and block on */
1140 mode = M_NORMAL; /* next read */
1141 nodelayf = 0;
1142 nodelay(win,0);
1143 }
1144 else if (count > 10) /* after 10 errors assume */
1145 auto_save(0); /* input stream is broken and */
1146 else /* auto save and exit */
1147 count++;
1148
1149 continue;
1150 }
1151
1152 count = 0; /* reset input error count */
1153
1154 if (mode == M_TRAIL)
1155 {
1156 if (ch == '^') /* msys console : 7,5,6,8: modified*/
1157 ch = CTRL( toupper(lastch) );
1158 else if (ch == '~') /* cygwin console: 1,5,6,4: normal */
1159 ch = tolower(lastch); /* windows telnet: 1,5,6,4: normal */
1160 /* msys console : 7,5,6,8: normal */
1161 else if (mode2 == M_ESC) /* cygwin console: 1,5,6,4: modified*/
1162 ch = CTRL( toupper(ch) );
1163 else
1164 {
1165 mode = M_NORMAL;
1166 unread(ch);
1167 continue;
1168 }
1169
1170 break;
1171 }
1172
1173 if (mode == M_ESC)
1174 {
1175 if (ch == 27)
1176 {
1177 mode2 = M_ESC;
1178 unread(ch);
1179 continue;
1180 }
1181
1182 if ((ch == 'F') || (ch == 'O') || (ch == '['))
1183 {
1184 mode = M_KEYPAD;
1185 unread(ch);
1186 continue;
1187 }
1188
1189
1190 switch(ch)
1191 {
1192 /* Cygwin Console */
1193 /* PuTTY */
1194 case KEY_LEFT : ch = CTRL('H'); break;
1195 case KEY_RIGHT: ch = CTRL('L'); break;
1196 case KEY_UP : ch = CTRL('K'); break;
1197 case KEY_DOWN : ch = CTRL('J'); break;
1198 case KEY_HOME : ch = CTRL('Y'); break;
1199 case KEY_PPAGE: ch = CTRL('U'); break;
1200 case KEY_NPAGE: ch = CTRL('N'); break;
1201 case KEY_END : ch = CTRL('B'); break;
1202
1203 default: mode = M_NORMAL;
1204 mode2 = M_NORMAL;
1205 unread(ch);
1206 continue;}
1207
1208 break;
1209 }
1210
1211 if (mode == M_KEYPAD)
1212 {
1213 switch(ch)
1214 {
1215 /* ESC F - Interix Console codes */
1216 case '^': ch = CTRL('H'); break; /* Shift-Left */
1217 case '$': ch = CTRL('L'); break; /* Shift-Right */
1218
1219 /* ESC [ - Interix Console codes */
1220 case 'H': ch = 'y'; break; /* Home */
1221 case 1: ch = CTRL('K'); break; /* Ctl-Keypad Up */
1222 case 2: ch = CTRL('J'); break; /* Ctl-Keypad Down */
1223 case 3: ch = CTRL('L'); break; /* Ctl-Keypad Right */
1224 case 4: ch = CTRL('H'); break; /* Ctl-Keypad Left */
1225 case 263: ch = CTRL('Y'); break; /* Ctl-Keypad Home */
1226 case 19: ch = CTRL('U'); break; /* Ctl-Keypad PgUp */
1227 case 20: ch = CTRL('N'); break; /* Ctl-Keypad PgDn */
1228 case 21: ch = CTRL('B'); break; /* Ctl-Keypad End */
1229
1230 /* ESC [ - Cygwin Console codes */
1231 case 'G': ch = '.'; break; /* Keypad 5 */
1232 case '7': lastch = 'Y'; mode=M_TRAIL; break; /* Ctl-Home */
1233 case '5': lastch = 'U'; mode=M_TRAIL; break; /* Ctl-PgUp */
1234 case '6': lastch = 'N'; mode=M_TRAIL; break; /* Ctl-PgDn */
1235
1236 /* ESC [ - Win32 Telnet, PuTTY */
1237 case '1': lastch = 'y'; mode=M_TRAIL; break; /* Home */
1238 case '4': lastch = 'b'; mode=M_TRAIL; break; /* End */
1239
1240 /* ESC O - PuTTY */
1241 case 'D': ch = CTRL('H'); break;
1242 case 'C': ch = CTRL('L'); break;
1243 case 'A': ch = CTRL('K'); break;
1244 case 'B': ch = CTRL('J'); break;
1245 case 't': ch = 'h'; break;
1246 case 'v': ch = 'l'; break;
1247 case 'x': ch = 'k'; break;
1248 case 'r': ch = 'j'; break;
1249 case 'w': ch = 'y'; break;
1250 case 'y': ch = 'u'; break;
1251 case 's': ch = 'n'; break;
1252 case 'q': ch = 'b'; break;
1253 case 'u': ch = '.'; break;
1254 }
1255
1256 if (mode != M_KEYPAD)
1257 {
1258 unread(ch);
1259 continue;
1260 }
1261 }
1262
1263 if (ch == 27)
1264 {
1265 nodelay(win,1);
1266 mode = M_ESC;
1267 nodelayf = 1;
1268 unread(ch);
1269 continue;
1270 }
1271
1272 switch(ch)
1273 {
1274 case KEY_LEFT : ch = 'h'; break;
1275 case KEY_DOWN : ch = 'j'; break;
1276 case KEY_UP : ch = 'k'; break;
1277 case KEY_RIGHT : ch = 'l'; break;
1278 case KEY_HOME : ch = 'y'; break;
1279 case KEY_PPAGE : ch = 'u'; break;
1280 case KEY_END : ch = 'b'; break;
1281 #ifdef KEY_LL
1282 case KEY_LL : ch = 'b'; break;
1283 #endif
1284 case KEY_NPAGE : ch = 'n'; break;
1285
1286 #ifdef KEY_B1
1287 case KEY_B1 : ch = 'h'; break;
1288 case KEY_C2 : ch = 'j'; break;
1289 case KEY_A2 : ch = 'k'; break;
1290 case KEY_B3 : ch = 'l'; break;
1291 #endif
1292 case KEY_A1 : ch = 'y'; break;
1293 case KEY_A3 : ch = 'u'; break;
1294 case KEY_C1 : ch = 'b'; break;
1295 case KEY_C3 : ch = 'n'; break;
1296 /* next should be '.', but for problem with putty/linux */
1297 case KEY_B2 : ch = 'u'; break;
1298
1299 #ifdef KEY_SLEFT
1300 case KEY_SRIGHT : ch = CTRL('L'); break;
1301 case KEY_SLEFT : ch = CTRL('H'); break;
1302 #ifdef KEY_SUP
1303 case KEY_SUP : ch = CTRL('K'); break;
1304 case KEY_SDOWN : ch = CTRL('J'); break;
1305 #endif
1306 case KEY_SHOME : ch = CTRL('Y'); break;
1307 case KEY_SPREVIOUS:ch = CTRL('U'); break;
1308 case KEY_SEND : ch = CTRL('B'); break;
1309 case KEY_SNEXT : ch = CTRL('N'); break;
1310 #endif
1311 case 0x146 : ch = CTRL('K'); break; /* Shift-Up */
1312 case 0x145 : ch = CTRL('J'); break; /* Shift-Down */
1313
1314 #ifdef CTL_RIGHT
1315 case CTL_RIGHT : ch = CTRL('L'); break;
1316 case CTL_LEFT : ch = CTRL('H'); break;
1317 case CTL_UP : ch = CTRL('K'); break;
1318 case CTL_DOWN : ch = CTRL('J'); break;
1319 case CTL_HOME : ch = CTRL('Y'); break;
1320 case CTL_PGUP : ch = CTRL('U'); break;
1321 case CTL_END : ch = CTRL('B'); break;
1322 case CTL_PGDN : ch = CTRL('N'); break;
1323 #endif
1324 #ifdef KEY_EOL
1325 case KEY_EOL : ch = CTRL('B'); break;
1326 #endif
1327
1328 #ifndef CTL_PAD1
1329 /* MSYS rxvt console */
1330 case 511 : ch = CTRL('J'); break; /* Shift Dn */
1331 case 512 : ch = CTRL('J'); break; /* Ctl Down */
1332 case 514 : ch = CTRL('H'); break; /* Ctl Left */
1333 case 516 : ch = CTRL('L'); break; /* Ctl Right*/
1334 case 518 : ch = CTRL('K'); break; /* Shift Up */
1335 case 519 : ch = CTRL('K'); break; /* Ctl Up */
1336 #endif
1337
1338 #ifdef CTL_PAD1
1339 case CTL_PAD1 : ch = CTRL('B'); break;
1340 case CTL_PAD2 : ch = CTRL('J'); break;
1341 case CTL_PAD3 : ch = CTRL('N'); break;
1342 case CTL_PAD4 : ch = CTRL('H'); break;
1343 case CTL_PAD5 : ch = '.'; break;
1344 case CTL_PAD6 : ch = CTRL('L'); break;
1345 case CTL_PAD7 : ch = CTRL('Y'); break;
1346 case CTL_PAD8 : ch = CTRL('K'); break;
1347 case CTL_PAD9 : ch = CTRL('U'); break;
1348 #endif
1349
1350 #ifdef ALT_RIGHT
1351 case ALT_RIGHT : ch = CTRL('L'); break;
1352 case ALT_LEFT : ch = CTRL('H'); break;
1353 case ALT_DOWN : ch = CTRL('J'); break;
1354 case ALT_HOME : ch = CTRL('Y'); break;
1355 case ALT_PGUP : ch = CTRL('U'); break;
1356 case ALT_END : ch = CTRL('B'); break;
1357 case ALT_PGDN : ch = CTRL('N'); break;
1358 #endif
1359
1360 #ifdef ALT_PAD1
1361 case ALT_PAD1 : ch = CTRL('B'); break;
1362 case ALT_PAD2 : ch = CTRL('J'); break;
1363 case ALT_PAD3 : ch = CTRL('N'); break;
1364 case ALT_PAD4 : ch = CTRL('H'); break;
1365 case ALT_PAD5 : ch = '.'; break;
1366 case ALT_PAD6 : ch = CTRL('L'); break;
1367 case ALT_PAD7 : ch = CTRL('Y'); break;
1368 case ALT_PAD8 : ch = CTRL('K'); break;
1369 case ALT_PAD9 : ch = CTRL('U'); break;
1370 #endif
1371 #ifdef KEY_BACKSPACE /* NCURSES in Keypad mode sends this for Ctrl-H */
1372 case KEY_BACKSPACE: ch = CTRL('H'); break;
1373 #endif
1374 }
1375
1376 break;
1377 }
1378
1379
1380 if (nodelayf)
1381 nodelay(win,0);
1382
1383 uindex = -1;
1384
1385 if (!pass_ctrl_keypad && (ch != wch))
1386 switch(ch)
1387 {
1388 case CTRL('H'):
1389 case CTRL('L'):
1390 case CTRL('K'):
1391 case CTRL('J'):
1392 case CTRL('Y'):
1393 case CTRL('U'):
1394 case CTRL('N'):
1395 case CTRL('B'):
1396 return(ch + 0x40);
1397 }
1398
1399 return(ch & 0x7F);
1400 }
1401
1402 #if defined(LOADAV) && defined(HAVE_NLIST_H) && defined(HAVE_NLIST)
1403 /*
1404 * loadav:
1405 * Looking up load average in core (for system where the loadav()
1406 * system call isn't defined
1407 */
1408
1409 #include <nlist.h>
1410
1411 struct nlist avenrun = {
1412 "_avenrun"
1413 };
1414
1415 int
1416 md_loadav(double *avg)
1417 {
1418 int kmem;
1419
1420 if ((kmem = open("/dev/kmem", 0)) < 0)
1421 goto bad;
1422 nlist(NAMELIST, &avenrun);
1423 if (avenrun.n_type == 0)
1424 {
1425 close(kmem);
1426 bad:
1427 avg[0] = 0.0;
1428 avg[1] = 0.0;
1429 avg[2] = 0.0;
1430 return -1;
1431 }
1432
1433 lseek(kmem, avenrun.n_value, 0);
1434 read(kmem, (char *) avg, 3 * sizeof (double));
1435 close(kmem);
1436 return 0;
1437 }
1438 #else
1439 int
1440 md_loadav(double *avg)
1441 {
1442 #if defined(HAVE_LOADAV)
1443 loadav(avg);
1444 return(0);
1445 #elif defined(HAVE_GETLOADAVG)
1446 int ret;
1447 ret = getloadavg(avg,3);
1448 return (ret == 3) ? 0 : -1;
1449 #else
1450 avg[0] = avg[1] = avg[2] = 0;
1451 return(-1);
1452 #endif
1453 }
1454 #endif
1455
1456 #ifndef NSIG
1457 #define NSIG 32
1458 #endif
1459
1460 void
1461 md_ignoreallsignals(void)
1462 {
1463 int i;
1464
1465 for (i = 0; i < NSIG; i++)
1466 signal(i, SIG_IGN);
1467 }
1468
1469 void
1470 md_tstphold(void)
1471 {
1472 #ifdef SIGTSTP
1473 /*
1474 * If a process can be suspended, this code wouldn't work
1475 */
1476 # ifdef SIG_HOLD
1477 signal(SIGTSTP, SIG_HOLD);
1478 # else
1479 signal(SIGTSTP, SIG_IGN);
1480 # endif
1481 #endif
1482 }
1483
1484 void
1485 md_tstpresume(void (*tstp)(int))
1486 {
1487 #ifdef SIGTSTP
1488 signal(SIGTSTP, tstp);
1489 #endif
1490 }
1491
1492 void
1493 md_tstpsignal(void)
1494 {
1495 #ifdef SIGTSTP
1496 kill(0, SIGTSTP); /* send actual signal and suspend process */
1497 #endif
1498 }
1499
1500 #if defined(CHECKTIME)
1501 void
1502 md_start_checkout_timer(int time)
1503 {
1504 int checkout();
1505
1506 #if defined(HAVE_ALARM) && defined(SIGALRM)
1507 signal(SIGALRM, checkout);
1508 alarm(time);
1509 #endif
1510 }
1511
1512 void
1513 md_stop_checkout_timer(void)
1514 {
1515 #if defined(SIGALRM)
1516 signal(SIGALRM, SIG_IGN);
1517 #endif
1518 }
1519 #endif
1520
1521 long
1522 md_memused()
1523 {
1524 #ifdef _WIN32
1525 MEMORYSTATUS stat;
1526
1527 GlobalMemoryStatus(&stat);
1528
1529 return((long)stat.dwTotalPageFile);
1530 #else
1531 return( (long)sbrk(0) );
1532 #endif
1533 }
1534
1535 int
1536 md_ucount()
1537 {
1538 #if defined(HAVE_UTMPX_H)
1539 struct utmpx *up=NULL;
1540 int count=0;
1541
1542 setutxent();
1543 do
1544 {
1545 up = getutxent();
1546 if (up && up->ut_type == USER_PROCESS)
1547 count++;
1548 } while(up != NULL);
1549
1550 endutxent();
1551
1552 return(count);
1553 #else
1554 return(1)
1555 #endif
1556 }
1557
1558 int
1559 md_lockfile(FILE *fp)
1560 {
1561 int fd;
1562 int ret;
1563
1564 fflush(fp);
1565 rewind(fp);
1566
1567 #ifdef _WIN32
1568 fd = _fileno(fp);
1569 ret = _locking(fd,_LK_LOCK,1);
1570 #else
1571 fd = fileno(fp);
1572
1573 while((ret = lockf(fd, F_LOCK, 1)) == -1)
1574 if (errno != EINTR)
1575 break;
1576 #endif
1577
1578 return ret;
1579 }
1580
1581 int
1582 md_unlockfile(FILE *fp)
1583 {
1584 int fd;
1585 int ret;
1586
1587 fflush(fp);
1588 rewind(fp);
1589
1590
1591 #ifdef _WIN32
1592 fd = _fileno(fp);
1593 ret = _locking(fd,_LK_UNLCK,1);
1594 #else
1595 fd = fileno(fp);
1596
1597 while( (ret = lockf(fd, F_ULOCK, 1)) == -1)
1598 if (errno != EINTR)
1599 break;
1600 #endif
1601
1602 return ret;
1603 }