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