home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HACKSRC.ZIP / TTY.C < prev    next >
C/C++ Source or Header  |  1985-10-16  |  7KB  |  336 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* tty.c - version 1.0.3 */
  3. /* With thanks to the people who sent code for SYSV - hpscdi!jon,
  4.    arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
  5.  
  6. #include <stdio.h>
  7. #include "hack.h"
  8.  
  9. #ifdef MSDOS
  10. static char erase_char, kill_char;
  11. static boolean settty_needed = FALSE;
  12. #else MSDOS
  13. /*
  14.  * The distinctions here are not BSD - rest but rather USG - rest, as
  15.  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
  16.  */
  17. #ifdef BSD
  18. #define    V7
  19. #else
  20. #define USG
  21. #endif BSD
  22.  
  23. /*
  24.  * Some systems may have getchar() return EOF for various reasons, and
  25.  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
  26.  */
  27. #ifndef BSD
  28. #define    NR_OF_EOFS    20
  29. #endif BSD
  30.  
  31.  
  32. #ifdef USG
  33.  
  34. #include    <termio.h>
  35. #define termstruct    termio
  36. #define kill_sym    c_cc[VKILL]
  37. #define erase_sym    c_cc[VERASE]
  38. #define EXTABS        TAB3
  39. #define tabflgs        c_oflag
  40. #define echoflgs    c_lflag
  41. #define cbrkflgs    c_lflag
  42. #define CBRKMASK    ICANON
  43. #define CBRKON        ! /* reverse condition */
  44. #define OSPEED(x)    ((x).c_cflag & CBAUD)
  45. #define GTTY(x)        (ioctl(0, TCGETA, x))
  46. #define STTY(x)        (ioctl(0, TCSETA, x))    /* TCSETAF? TCSETAW? */
  47.  
  48. #else    /* V7 */
  49.  
  50. #include    <sgtty.h>
  51. #define termstruct    sgttyb
  52. #define    kill_sym    sg_kill
  53. #define    erase_sym    sg_erase
  54. #define EXTABS        XTABS
  55. #define tabflgs        sg_flags
  56. #define echoflgs    sg_flags
  57. #define cbrkflgs    sg_flags
  58. #define CBRKMASK    CBREAK
  59. #define CBRKON        /* empty */
  60. #define OSPEED(x)    (x).sg_ospeed
  61. #define GTTY(x)        (gtty(0, x))
  62. #define STTY(x)        (stty(0, x))
  63.  
  64. #endif USG
  65.  
  66. extern short ospeed;
  67. static char erase_char, kill_char;
  68. static boolean settty_needed = FALSE;
  69. struct termstruct inittyb, curttyb;
  70. #endif MSDOS
  71.  
  72. /*
  73.  * Get initial state of terminal, set ospeed (for termcap routines)
  74.  * and switch off tab expansion if necessary.
  75.  * Called by startup() in termcap.c and after returning from ! or ^Z
  76.  */
  77. gettty(){
  78. #ifdef MSDOS
  79.     erase_char = '\b';
  80.     kill_char = 21;        /* cntl-U */
  81. #else
  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. #endif MSDOS
  96.     settty_needed = TRUE;
  97. }
  98.  
  99. /* reset terminal to original state */
  100. settty(s) char *s; {
  101.     end_screen();
  102.     clear_screen();
  103.     if(s) printf(s);
  104.     (void) fflush(stdout);
  105. #ifdef    MSDOS
  106.     flags.echo = ON;
  107.     flags.cbreak = OFF;
  108. #else
  109.     if(STTY(&inittyb) < 0)
  110.         perror("Hack (settty)");
  111.     flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
  112.     flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
  113.     setioctls();
  114. #endif MSDOS
  115. }
  116.  
  117. setctty(){
  118. #ifndef MSDOS
  119.     if(STTY(&curttyb) < 0)
  120.         perror("Hack (setctty)");
  121. #endif MSDOS
  122. }
  123.  
  124.  
  125. setftty(){
  126. #ifdef MSDOS
  127.     flags.cbreak = ON;
  128.     flags.echo = OFF;
  129. #else
  130. register int ef = 0;            /* desired value of flags & ECHO */
  131. register int cf = CBRKON(CBRKMASK);    /* desired value of flags & CBREAK */
  132. register int change = 0;
  133.     flags.cbreak = ON;
  134.     flags.echo = OFF;
  135.     /* Should use (ECHO|CRMOD) here instead of ECHO */
  136.     if((curttyb.echoflgs & ECHO) != ef){
  137.         curttyb.echoflgs &= ~ECHO;
  138. /*        curttyb.echoflgs |= ef;                    */
  139.         change++;
  140.     }
  141.     if((curttyb.cbrkflgs & CBRKMASK) != cf){
  142.         curttyb.cbrkflgs &= ~CBRKMASK;
  143.         curttyb.cbrkflgs |= cf;
  144. #ifdef USG
  145.         /* be satisfied with one character; no timeout */
  146.         curttyb.c_cc[VMIN] = 1;        /* was VEOF */
  147.         curttyb.c_cc[VTIME] = 0;    /* was VEOL */
  148. #endif USG
  149.         change++;
  150.     }
  151.     if(change){
  152.         setctty();
  153.     }
  154. #endif MSDOS
  155.     start_screen();
  156. }
  157.  
  158.  
  159. /* fatal error */
  160. /*VARARGS1*/
  161. error(s,x,y) char *s; {
  162.     if(settty_needed)
  163.         settty((char *) 0);
  164.     printf(s,x,y);
  165.     putchar('\n');
  166.     exit(1);
  167. }
  168.  
  169. /*
  170.  * Read a line closed with '\n' into the array char bufp[BUFSZ].
  171.  * (The '\n' is not stored. The string is closed with a '\0'.)
  172.  * Reading can be interrupted by an escape ('\033') - now the
  173.  * resulting string is "\033".
  174.  */
  175. getlin(bufp)
  176. register char *bufp;
  177. {
  178.     register char *obufp = bufp;
  179.     register int c;
  180.  
  181.     flags.toplin = 2;        /* nonempty, no --More-- required */
  182.     for(;;) {
  183.         (void) fflush(stdout);
  184.         if((c = getchar()) == EOF) {
  185.             *bufp = 0;
  186.             return;
  187.         }
  188.         if(c == '\033') {
  189.             *obufp = c;
  190.             obufp[1] = 0;
  191.             return;
  192.         }
  193.         if(c == erase_char || c == '\b') {
  194.             if(bufp != obufp) {
  195.                 bufp--;
  196.                 putstr("\b \b"); /* putsym converts \b */
  197.             } else    bell();
  198.         } else if(c == '\n') {
  199.             *bufp = 0;
  200.             return;
  201.         } else if(' ' <= c && c < '\177') {
  202.                 /* avoid isprint() - some people don't have it
  203.                    ' ' is not always a printing char */
  204.             *bufp = c;
  205.             bufp[1] = 0;
  206.             putstr(bufp);
  207.             if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  208.                 bufp++;
  209.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  210.                 /* this test last - @ might be the kill_char */
  211.             while(bufp != obufp) {
  212.                 bufp--;
  213.                 putstr("\b \b");
  214.             }
  215.         } else
  216.             bell();
  217.     }
  218. }
  219.  
  220. getret() {
  221.     cgetret("");
  222. }
  223.  
  224. cgetret(s)
  225. register char *s;
  226. {
  227.     putsym('\n');
  228.     if(flags.standout)
  229.         standoutbeg();
  230.     putstr("Hit ");
  231.     putstr(flags.cbreak ? "space" : "return");
  232.     putstr(" to continue: ");
  233.     if(flags.standout)
  234.         standoutend();
  235.     xwaitforspace(s);
  236. }
  237.  
  238. char morc;    /* tell the outside world what char he used */
  239.  
  240. xwaitforspace(s)
  241. register char *s;    /* chars allowed besides space or return */
  242. {
  243. register int c;
  244.  
  245.     morc = 0;
  246.     while((c = readchar()) != '\n') {
  247.         if(flags.cbreak) {
  248.         if(c == ' ') break;
  249.         if(s && index(s,c)) {
  250.             morc = c;
  251.             break;
  252.         }
  253.         bell();
  254.         }
  255.     }
  256. }
  257.  
  258. char *
  259. parse()
  260. {
  261.     static char inline[COLNO];
  262.     register foo;
  263.  
  264.     flags.move = 1;
  265.     if(!Invisible) curs_on_u(); else home();
  266. #ifdef DGK
  267.     /* provide feedback when the multi count gets large -dgk */
  268.     while((foo = readchar()) >= '0' && foo <= '9') {
  269.         multi = 10*multi+foo-'0';
  270.         if (multi >= 10) {
  271.             remember_topl();
  272.             home();
  273.             cl_end();
  274.             printf("count: %d", multi);
  275.         }
  276.     }
  277. #else
  278.     while((foo = readchar()) >= '0' && foo <= '9')
  279.         multi = 10*multi+foo-'0';
  280. #endif DGK
  281.     if(multi) {
  282.         multi--;
  283.         save_cm = inline;
  284.     }
  285.     inline[0] = foo;
  286.     inline[1] = 0;
  287.     if(foo == 'f' || foo == 'F'){
  288.         inline[1] = getchar();
  289. #ifdef QUEST
  290.         if(inline[1] == foo) inline[2] = getchar(); else
  291. #endif QUEST
  292.         inline[2] = 0;
  293.     }
  294.     if(foo == 'm' || foo == 'M'){
  295.         inline[1] = getchar();
  296.         inline[2] = 0;
  297.     }
  298.     clrlin();
  299.     return(inline);
  300. }
  301.  
  302. char
  303. readchar() {
  304.     register int sym;
  305.  
  306.     (void) fflush(stdout);
  307.     if((sym = getchar()) == EOF)
  308. #ifdef NR_OF_EOFS
  309.     { /*
  310.        * Some SYSV systems seem to return EOFs for various reasons
  311.        * (?like when one hits break or for interrupted systemcalls?),
  312.        * and we must see several before we quit.
  313.        */
  314.         register int cnt = NR_OF_EOFS;
  315.         while (cnt--) {
  316.             clearerr(stdin);    /* omit if clearerr is undefined */
  317.             if((sym = getchar()) != EOF) goto noteof;
  318.         }
  319.         end_of_input();
  320.          noteof:    ;
  321.     }
  322. #else
  323.         end_of_input();
  324. #endif NR_OF_EOFS
  325.     if(flags.toplin == 1)
  326.         flags.toplin = 2;
  327.     return((char) sym);
  328. }
  329.  
  330. end_of_input()
  331. {
  332.     settty("End of input?\n");
  333.     clearlocks();
  334.     exit(0);
  335. }
  336.