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