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