home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / nethack2.2 / part15 / unixtty.c < prev   
C/C++ Source or Header  |  1987-12-04  |  9KB  |  414 lines

  1. /*    SCCS Id: @(#)unixtty.c    2.1    87/11/09
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* tty.c - (Unix) version */
  4.  
  5. /* With thanks to the people who sent code for SYSV - hpscdi!jon,
  6.  * arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others.
  7.  */
  8.  
  9. #include    <stdio.h>
  10. #include    "extern.h"
  11. #include    "hack.h"
  12. #include    "func_tab.h"
  13.  
  14. #define    ON    1
  15. #define OFF    0
  16.  
  17. /*
  18.  * The distinctions here are not BSD - rest but rather USG - rest, as
  19.  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
  20.  */
  21. #ifdef BSD
  22. #define    V7
  23. #else
  24. #define USG
  25. #endif
  26.  
  27. /*
  28.  * Some systems may have getchar() return EOF for various reasons, and
  29.  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
  30.  */
  31. #ifndef BSD
  32. #define    NR_OF_EOFS    20
  33. #endif
  34.  
  35.  
  36. #ifdef USG
  37.  
  38. #include    <termio.h>
  39. #define termstruct    termio
  40. #define kill_sym    c_cc[VKILL]
  41. #define erase_sym    c_cc[VERASE]
  42. #define EXTABS        TAB3
  43. #define tabflgs        c_oflag
  44. #define echoflgs    c_lflag
  45. #define cbrkflgs    c_lflag
  46. #define CBRKMASK    ICANON
  47. #define CBRKON        ! /* reverse condition */
  48. #define OSPEED(x)    ((x).c_cflag & CBAUD)
  49. #define GTTY(x)        (ioctl(0, TCGETA, x))
  50. /* STTY now modified to run under Sys V R3.    - may have to be #ifdef'ed */
  51. #define STTY(x)        (ioctl(0, TCSETAW, x))    /* TCSETAF? TCSETAW? */
  52.  
  53. #else    /* V7 */
  54.  
  55. #include    <sgtty.h>
  56. #define termstruct    sgttyb
  57. #define    kill_sym    sg_kill
  58. #define    erase_sym    sg_erase
  59. #define EXTABS        XTABS
  60. #define tabflgs        sg_flags
  61. #define echoflgs    sg_flags
  62. #define cbrkflgs    sg_flags
  63. #define CBRKMASK    CBREAK
  64. #define CBRKON        /* empty */
  65. #define OSPEED(x)    (x).sg_ospeed
  66. #define GTTY(x)        (gtty(0, x))
  67. #define STTY(x)        (stty(0, x))
  68.  
  69. #endif
  70.  
  71. extern short ospeed;
  72. static char erase_char, kill_char;
  73. static boolean settty_needed = FALSE;
  74. struct termstruct inittyb, curttyb;
  75.  
  76. /*
  77.  * Get initial state of terminal, set ospeed (for termcap routines)
  78.  * and switch off tab expansion if necessary.
  79.  * Called by startup() in termcap.c and after returning from ! or ^Z
  80.  */
  81. gettty(){
  82.     if(GTTY(&inittyb) < 0)
  83.         perror("Hack (gettty)");
  84.     curttyb = inittyb;
  85.     ospeed = OSPEED(inittyb);
  86.     erase_char = inittyb.erase_sym;
  87.     kill_char = inittyb.kill_sym;
  88.     getioctls();
  89.  
  90.     /* do not expand tabs - they might be needed inside a cm sequence */
  91.     if(curttyb.tabflgs & EXTABS) {
  92.         curttyb.tabflgs &= ~EXTABS;
  93.         setctty();
  94.     }
  95.     settty_needed = TRUE;
  96. }
  97.  
  98. /* reset terminal to original state */
  99. settty(s) char *s; {
  100.     clear_screen();
  101.     end_screen();
  102.     if(s) printf(s);
  103.     (void) fflush(stdout);
  104.     if(STTY(&inittyb) < 0)
  105.         perror("Hack (settty)");
  106.     flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
  107.     flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
  108.     setioctls();
  109. }
  110.  
  111. setctty(){
  112.     if(STTY(&curttyb) < 0)
  113.         perror("Hack (setctty)");
  114. }
  115.  
  116.  
  117. setftty(){
  118. register int ef = 0;            /* desired value of flags & ECHO */
  119. register int cf = CBRKON(CBRKMASK);    /* desired value of flags & CBREAK */
  120. register int change = 0;
  121.     flags.cbreak = ON;
  122.     flags.echo = OFF;
  123.     /* Should use (ECHO|CRMOD) here instead of ECHO */
  124.     if((curttyb.echoflgs & ECHO) != ef){
  125.         curttyb.echoflgs &= ~ECHO;
  126. /*        curttyb.echoflgs |= ef;                    */
  127.         change++;
  128.     }
  129.     if((curttyb.cbrkflgs & CBRKMASK) != cf){
  130.         curttyb.cbrkflgs &= ~CBRKMASK;
  131.         curttyb.cbrkflgs |= cf;
  132. #ifdef USG
  133.         /* be satisfied with one character; no timeout */
  134.         curttyb.c_cc[VMIN] = 1;        /* was VEOF */
  135.         curttyb.c_cc[VTIME] = 0;    /* was VEOL */
  136. #endif
  137.         change++;
  138.     }
  139.     if(change){
  140.         setctty();
  141.     }
  142.     start_screen();
  143. }
  144.  
  145.  
  146. /* fatal error */
  147. /*VARARGS1*/
  148. error(s,x,y) char *s; {
  149.     if(settty_needed)
  150.         settty((char *) 0);
  151.     printf(s,x,y);
  152.     putchar('\n');
  153.     exit(1);
  154. }
  155.  
  156. /*
  157.  * Read a line closed with '\n' into the array char bufp[BUFSZ].
  158.  * (The '\n' is not stored. The string is closed with a '\0'.)
  159.  * Reading can be interrupted by an escape ('\033') - now the
  160.  * resulting string is "\033".
  161.  */
  162. getlin(bufp)
  163. register char *bufp;
  164. {
  165.     register char *obufp = bufp;
  166.     register int c;
  167.  
  168.     flags.toplin = 2;        /* nonempty, no --More-- required */
  169.     for(;;) {
  170.         (void) fflush(stdout);
  171.         if((c = getchar()) == EOF) {
  172.             *bufp = 0;
  173.             return;
  174.         }
  175.         if(c == '\033') {
  176.             *obufp = c;
  177.             obufp[1] = 0;
  178.             return;
  179.         }
  180.         if(c == erase_char || c == '\b') {
  181.             if(bufp != obufp) {
  182.                 bufp--;
  183.                 putstr("\b \b"); /* putsym converts \b */
  184.             } else    bell();
  185.         } else if(c == '\n') {
  186.             *bufp = 0;
  187.             return;
  188.         } else if(' ' <= c && c < '\177') {
  189.                 /* avoid isprint() - some people don't have it
  190.                    ' ' is not always a printing char */
  191.             *bufp = c;
  192.             bufp[1] = 0;
  193.             putstr(bufp);
  194.             if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  195.                 bufp++;
  196.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  197.                 /* this test last - @ might be the kill_char */
  198.             while(bufp != obufp) {
  199.                 bufp--;
  200.                 putstr("\b \b");
  201.             }
  202.         } else
  203.             bell();
  204.     }
  205. }
  206.  
  207. getret() {
  208.     cgetret("");
  209. }
  210.  
  211. cgetret(s)
  212. register char *s;
  213. {
  214.     putsym('\n');
  215.     if(flags.standout)
  216.         standoutbeg();
  217.     putstr("Hit ");
  218.     putstr(flags.cbreak ? "space" : "return");
  219.     putstr(" to continue: ");
  220.     if(flags.standout)
  221.         standoutend();
  222.     xwaitforspace(s);
  223. }
  224.  
  225. char morc;    /* tell the outside world what char he used */
  226.  
  227. xwaitforspace(s)
  228. register char *s;    /* chars allowed besides space or return */
  229. {
  230. register int c;
  231.  
  232.     morc = 0;
  233.  
  234.     while((c = readchar()) != '\n') {
  235.         if(flags.cbreak) {
  236.         if(c == ' ') break;
  237.         if(s && index(s,c)) {
  238.             morc = c;
  239.             break;
  240.         }
  241.         bell();
  242.         }
  243.     }
  244. }
  245.  
  246. static int last_multi;
  247.  
  248. char *
  249. parse()
  250. {
  251.     static char inline[COLNO];
  252.     register foo;
  253.  
  254.     multi = 0;
  255.     flags.move = 1;
  256.     if(!Invisible) curs_on_u(); else home();
  257.     while((foo = readchar()) >= '0' && foo <= '9') {
  258.         multi = 10*multi+foo-'0';
  259. #ifdef DGKMOD
  260.         if (multi < 0 || multi > LARGEST_INT)
  261.             multi = LARGEST_INT;
  262.         if (multi > 9) {
  263.             remember_topl();
  264.             home();
  265.             cl_end();
  266.             printf("Count: %d", multi);
  267.         }
  268. #endif
  269.         last_multi = multi;
  270.     }
  271. # ifdef REDO
  272.     if (foo == DOAGAIN || in_doagain)
  273.         multi = last_multi;
  274.     else {
  275.         savech(0);    /* reset input queue */
  276.         savech(foo);
  277.     }
  278. # endif
  279.     if(multi) {
  280.         multi--;
  281.         save_cm = inline;
  282.     }
  283.     inline[0] = foo;
  284.     inline[1] = 0;
  285.     if(foo == 'g' || foo == 'G'){
  286.         inline[1] = getchar();
  287. #ifdef QUEST
  288.         if(inline[1] == foo) inline[2] = getchar(); else
  289. #endif
  290.         inline[2] = 0;
  291.     }
  292.     if(foo == 'm' || foo == 'M'){
  293.         inline[1] = getchar();
  294.         inline[2] = 0;
  295.     }
  296.     clrlin();
  297.     return(inline);
  298. }
  299.  
  300. char
  301. readchar() {
  302.     register int sym;
  303.  
  304.     (void) fflush(stdout);
  305.     if((sym = getchar()) == EOF)
  306. #ifdef NR_OF_EOFS
  307.     { /*
  308.        * Some SYSV systems seem to return EOFs for various reasons
  309.        * (?like when one hits break or for interrupted systemcalls?),
  310.        * and we must see several before we quit.
  311.        */
  312.         register int cnt = NR_OF_EOFS;
  313.         while (cnt--) {
  314.             clearerr(stdin);    /* omit if clearerr is undefined */
  315.             if((sym = getchar()) != EOF) goto noteof;
  316.         }
  317.         end_of_input();
  318.          noteof:    ;
  319.     }
  320. #else
  321.         end_of_input();
  322. #endif /* NR_OF_EOFS /**/
  323.     if(flags.toplin == 1)
  324.         flags.toplin = 2;
  325.     return((char) sym);
  326. }
  327.  
  328. end_of_input()
  329. {
  330.     settty("End of input?\n");
  331.     clearlocks();
  332.     exit(0);
  333. }
  334.  
  335. #ifdef COM_COMPL
  336. /* Read in an extended command - doing command line completion for
  337.  * when enough character have been entered to make a unique command.
  338.  * This is just a modified getlin().   -jsb
  339.  */
  340. get_ext_cmd(bufp)
  341. register char *bufp;
  342. {
  343.     register char *obufp = bufp;
  344.     register int c;
  345.     int com_index, index;
  346.  
  347.     flags.toplin = 2;        /* nonempty, no --More-- required */
  348.  
  349.     for(;;) {
  350.         (void) fflush(stdout);
  351.         if((c = readchar()) == EOF) {
  352.             *bufp = 0;
  353.             return;
  354.         }
  355.         if(c == '\033') {
  356.             *obufp = c;
  357.             obufp[1] = 0;
  358.             return;
  359.         }
  360.         if(c == erase_char || c == '\b') {
  361.             if(bufp != obufp) {
  362.                 bufp--;
  363.                 putstr("\b \b"); /* putsym converts \b */
  364.             } else    bell();
  365.         } else if(c == '\n') {
  366.             *bufp = 0;
  367.             return;
  368.         } else if(' ' <= c && c < '\177') {
  369.                 /* avoid isprint() - some people don't have it
  370.                    ' ' is not always a printing char */
  371.             *bufp = c;
  372.             bufp[1] = 0;
  373.             index = 0;
  374.             com_index = -1;
  375.  
  376.             while(extcmdlist[index].ef_txt != (char *) 0){
  377.                 if(!strncmp(obufp, extcmdlist[index].ef_txt,
  378.                 strlen(obufp)))
  379.                     if(com_index == -1) /* No matches yet*/
  380.                         com_index = index;
  381.                     else /* More than 1 match */
  382.                         com_index = -2;
  383.                 index++;
  384.             }
  385.             if(com_index >= 0){
  386.                 strcpy(obufp,
  387.                 extcmdlist[com_index].ef_txt);
  388.                 /* finish print our string */
  389.                 putstr(bufp);
  390.                 bufp = obufp; /* reset it */
  391.                 if(strlen(obufp) < BUFSIZ-1 &&
  392.                  strlen(obufp) < COLNO)
  393.                     /* set bufp at the end of our
  394.                      * string
  395.                      */
  396.                     bufp += strlen(obufp);
  397.             } else {
  398.                 putstr(bufp);
  399.                 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  400.                     bufp++;
  401.             }
  402.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  403.                 /* this test last - @ might be the kill_char */
  404.             while(bufp != obufp) {
  405.                 bufp--;
  406.                 putstr("\b \b");
  407.             }
  408.         } else
  409.             bell();
  410.     }
  411.  
  412. }
  413. #endif COM_COMPL
  414.