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