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