home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume9 / teco / part02 / te_chario.c next >
Encoding:
C/C++ Source or Header  |  1987-03-11  |  8.8 KB  |  310 lines

  1. /* TECO for Ultrix   Copyright 1986 Matt Fichtenbaum                        */
  2. /* This program and its components belong to GenRad Inc, Concord MA 01742    */
  3. /* They may be copied if this copyright notice is included                    */
  4.  
  5. /* te_chario.c   character I/O routines   10/9/86 */
  6. #include <errno.h>
  7. #include "te_defs.h"
  8.  
  9. #include <fcntl.h>
  10. #ifndef DEBUG
  11. #include <signal.h>
  12. extern int int_handler();
  13. extern int stp_handler();
  14. extern int hup_handler();
  15. #define SIGINTMASK 2
  16. #endif
  17.  
  18. int lf_sw;                                    /* nonzero: make up a LF following an entered CR */
  19. int ttyflags;                                /* flags for (stdin) file descriptor */
  20. struct tchars tc_orig, tc_new, tc_noint;    /* original, new, disabled intrpt tty special chars */
  21. struct ltchars lc_orig, lc_new;                /* original and new local special chars */
  22. struct sgttyb tty_orig, tty_new;            /* original and new tty flags */
  23. int tty_local;                                /* original tty local mode flags */
  24. int lnoflsh = LNOFLSH;                        /* bit to force "no flush on interrupt */
  25.  
  26. #ifndef DEBUG
  27. struct sigvec intsigstruc = { int_handler, 0, 0 } ;        /* info structure for ^C interrupt        */
  28. struct sigvec stpsigstruc = { stp_handler, 0, 0 } ;        /* info structure for "stop" signal        */
  29. struct sigvec hupsigstruc = { hup_handler, 0, 0 } ;        /* info structure for "hangup" signal    */
  30. struct sigvec nosigstr = { SIG_DFL, 0, 0 };                /* default structure for signal            */
  31. #endif
  32.  
  33. int inp_noterm;                /* nonzero if standard input is not a terminal */
  34. int out_noterm;                /* nonzero if standard output is not a terminal */
  35. /* set tty (stdin) mode.  TECO mode is CBREAK, no ECHO, sep CR & LF                */
  36. /* operation; normal mode is none of the above.  TTY_OFF and TTY_ON do this        */
  37. /* absolutely; TTY_SUSP and TTY_RESUME use saved signal status.                    */
  38.  
  39. setup_tty(arg)
  40.     int arg;
  41.     {
  42.     extern int errno;
  43.     int ioerr;
  44.     struct sgttyb tmpbuf;
  45.  
  46. /* initial processing: set tty mode */
  47.  
  48.     if (arg == TTY_ON)
  49.         {
  50.         ioerr = ioctl(fileno(stdin), TIOCGETP, &tty_orig);    /* get std input characteristics */
  51.         inp_noterm = (ioerr && (errno == ENOTTY));            /* nonzero if input not a terminal */
  52.         ioerr = ioctl(fileno(stdout), TIOCGETP, &tmpbuf);    /* get std output characteristics */
  53.         out_noterm = (ioerr && (errno == ENOTTY));            /* nonzero if output not a terminal */
  54.         ioctl(fileno(stdout), TIOCLGET, &tty_local);        /* get current "local mode flags" word */
  55.  
  56.         ttybuf = tty_new = tty_orig;                        /* make a copy of tty control structure */
  57.         tty_new.sg_flags = (tty_new.sg_flags & ~ECHO & ~CRMOD) | CBREAK;    /* turn on teco modes */
  58.  
  59.         ioctl(fileno(stdin), TIOCGETC, &tc_orig);        /* read current tchars */
  60.         tc_new = tc_orig;                                /* make local copy */
  61.         tc_new.t_quitc = tc_new.t_brkc = -1;            /* disable "quit" and "delimiter" chars */
  62.         tc_noint = tc_new;
  63.         tc_noint.t_intrc = -1;                            /* disable the interrupt char in this one */
  64.  
  65.         ioctl(fileno(stdin), TIOCGLTC, &lc_orig);        /* read current ltchars */
  66.         lc_new = lc_orig;                                /* make local copy */
  67.         lc_new.t_rprntc = lc_new.t_werasc = lc_new.t_lnextc = -1;    /* disable "reprint," "word erase," "lit next" */
  68.         }
  69.  
  70.     if ((arg == TTY_ON) || (arg == TTY_RESUME))
  71.         {
  72.         ioctl(fileno(stdin), TIOCSETP, &tty_new);        /* set flags for teco */
  73.         ioctl(fileno(stdin), TIOCSETC, &tc_new);        /* update both */
  74.         ioctl(fileno(stdin), TIOCSLTC, &lc_new);
  75.         ioctl(fileno(stdout), TIOCLBIS, &lnoflsh);        /* disable "interrupt => flush buffers" */
  76. #ifndef DEBUG
  77.         sigvec(SIGTSTP, &stpsigstruc, 0);                /* set up to trap "stop" signal */
  78.         sigvec(SIGINT, &intsigstruc, 0);                /* and "interrupt" signal */
  79.         sigvec(SIGHUP, &hupsigstruc, 0);                /* and "hangup" signal */
  80. #endif
  81.         }
  82.     else
  83.         {
  84.         ioctl(fileno(stdin), TIOCSETP, &tty_orig);        /* set flags back to original */
  85.         ioctl(fileno(stdin), TIOCSETC, &tc_orig);        /* put both back to orig states */
  86.         ioctl(fileno(stdin), TIOCSLTC, &lc_orig);
  87.         ioctl(fileno(stdout), TIOCLSET, &tty_local);    /* restore local mode flags to original states */
  88. #ifndef DEBUG
  89.         sigvec(SIGTSTP, &nosigstr, 0);                    /* restore default signal handling */
  90.         sigvec(SIGINT, &nosigstr, 0);
  91.         sigvec(SIGHUP, &nosigstr, 0);
  92. #endif
  93.         }
  94.     }
  95. /* routines to handle keyboard input */
  96.  
  97. /* routine to get a character without waiting, used by ^T when ET & 64 is set    */
  98. /* if lf_sw is nonzero, return the LF; else use the FNDELAY fcntl to inquire of the input */
  99.  
  100. int gettty_nowait()
  101.     {
  102.     int c;
  103.  
  104.     if (lf_sw)
  105.         {
  106.         lf_sw = 0;
  107.         return(LF);            /* LF to be sent: return it */
  108.         }
  109.     fcntl(fileno(stdin), F_SETFL, ttyflags | FNDELAY);        /* set to "no delay" mode */
  110.     while (!(c = getchar()));                    /* read character, or -1, skip nulls */
  111.     fcntl(fileno(stdin), F_SETFL, ttyflags);                /* reset to normal mode */
  112.     if (c == CR) ++lf_sw;                        /* CR: set switch to make up a LF */
  113.     return(c);
  114.     }
  115.  
  116.  
  117.  
  118. /* normal routine to get a character */
  119.  
  120. int in_read = 0;        /* flag for "read busy" (used by interrupt handler) */
  121.  
  122. char gettty()
  123.     {
  124.     int c;
  125.  
  126.     if (lf_sw)
  127.         {
  128.         lf_sw = 0;
  129.         return(LF);        /* if switch set, make up a line feed */
  130.         }
  131.     ++in_read;                            /* set "read busy" switch */
  132.     while(!(c = getchar()));                /* get character; skip nulls */
  133.     in_read = 0;                        /* clear switch */
  134.     if (c == CR) ++lf_sw;                    /* CR: set switch to make up a LF */
  135.     if (c == EOF) ERROR(E_EFI);                /* end-of-file from standard input */
  136.     return( (char) c & 0177);                /* and return the 7-bit char */
  137.     }
  138.  
  139. #ifndef DEBUG
  140.  
  141. /* routine to handle interrupt signal */
  142.  
  143. int_handler()
  144.     {
  145.  
  146.     if (exitflag <= 0)                        /* if executing commands */
  147.         {
  148.         if (et_val & ET_CTRLC) et_val &= ~ET_CTRLC;        /* if "trap ^C" set, clear it and ignore */
  149.         else exitflag = -2;                                /* else set flag to stop execution */
  150.         }
  151.     if (in_read)                            /* if interrupt happened in "getchar" pass a ^C to input */
  152.         {
  153.         in_read = 0;                                    /* clear "read" switch */
  154.         ioctl(fileno(stdin), TIOCSETC, &tc_noint);        /* disable interrupt char */
  155.         qio_char(CTL (C));                                /* send a ^C to input stream */
  156.         ioctl(fileno(stdin), TIOCSETC, &tc_new);        /* reenable interrupt char */
  157.         }
  158.     }
  159. #endif
  160. /* routine to disable (1), enable (0) ^C interrupt, used to block interrupts during display update */
  161.  
  162. int old_mask;                /* storage for previous signal mask */
  163. #define INT_MASK 2
  164.  
  165. block_inter(func)
  166.     int func;
  167.     {
  168. #ifndef DEBUG
  169.     if (func) old_mask = sigblock(INT_MASK);            /* if arg nonzero, block interrupt */
  170.     else sigsetmask(old_mask);                            /* otherwise restore old signal mask */
  171. #endif
  172.     }
  173.  
  174.  
  175.  
  176. #ifndef DEBUG
  177. /* routine to handle "stop" signal (^Y) */
  178.  
  179. stp_handler()
  180.     {
  181.     window(WIN_SUSP);                /* restore screen */
  182.     setup_tty(TTY_SUSP);            /* put tty back to normal */
  183.     sigvec(SIGTSTP, &nosigstr, 0);     /* put default action back */
  184.     sigsetmask(0);                    /* unblock "suspend" signal */
  185.     kill(0, SIGTSTP);                /* suspend this process */
  186.  
  187. /* ----- process gets suspended here ----- */
  188.  
  189.     sigvec(SIGTSTP, &stpsigstruc, 0);    /* restore local handling of "stop" signal */
  190.     setup_tty(TTY_RESUME);                /* restore tty */
  191.     buff_mod = 0;                        /* set whole screen modified */
  192.     if (win_data[7])            /* redraw window */
  193.         {
  194.         window(WIN_RESUME);        /* re-enable window */
  195.         window(WIN_REDRAW);        /* force complete redraw */
  196.         window(WIN_REFR);        /* and refresh */
  197.         }
  198.     qio_char('\0');                /* wake up the input
  199.     if (exitflag) retype_cmdstr('*');    /* if not executing, prompt again and echo command string so far */
  200.     }
  201. #endif
  202.  
  203.  
  204.  
  205. /* simulate a character's having been typed on the keyboard */
  206.  
  207. qio_char(c)
  208.     char c;
  209.     {
  210.     ioctl(fileno(stdin), TIOCSTI, &c);                /* send char to input stream */
  211.     }
  212. /* routine to handle "hangup" signal */
  213. #ifndef DEBUG
  214.  
  215. hup_handler()
  216.     {
  217.     if (!exitflag) exitflag = -3;                    /* if executing, set flag to terminate */
  218.     else
  219.         {
  220.         panic();                                    /* dump buffer and close output files */
  221.         exit(1);
  222.         }
  223.     }
  224. #endif
  225.  
  226.  
  227.  
  228. /* type a crlf */
  229.  
  230. crlf()
  231.     {
  232.     type_char(CR);
  233.     type_char(LF);
  234.     }
  235.  
  236.  
  237.  
  238. /* reset ^O status */
  239.  
  240. int lflusho = LFLUSHO;
  241. int lfo;
  242.  
  243. reset_ctlo()
  244.     {
  245.     ioctl(fileno(stdin), TIOCLGET, &lfo);        /* read flags */
  246.     if (lfo & LFLUSHO)                            /* if ^O was set */
  247.         {
  248.         ioctl(fileno(stdin), TIOCLBIC, &lflusho);    /* reset ^O */
  249.         crlf();                                        /* type a crlf */
  250.         }
  251.     }
  252. /* routine to type one character */
  253.  
  254. type_char(c)
  255.     char c;
  256.     {
  257.  
  258.     if ((char_count >= WN_width) && (c != CR) && !(spec_chars[c] & A_L))    /* spacing char beyond end of line */
  259.         {
  260.         if (et_val & ET_TRUNC) return;        /* truncate output to line width */
  261.         else crlf();                        /* otherwise do automatic new line (note recursive call to type_char) */
  262.         }
  263.  
  264.     if ((c & 0140) == 0)                /* control char? */
  265.         {
  266.         switch (c & 0177)
  267.             {
  268.             case CR:
  269.                 putchar(c);
  270.                 char_count = 0;
  271.                 break;
  272.  
  273.             case LF:
  274.                 putchar(c);
  275. /*                scroll_dly();            /* filler chars in case VT-100 scrolls */
  276.                 break;
  277.  
  278.             case ESC:
  279.                 if ((et_val & ET_IMAGE) && !exitflag) putchar(c);
  280.                 else
  281.                     {
  282.                     putchar('$');
  283.                     char_count++;
  284.                     }
  285.                 break;
  286.  
  287.             case TAB:
  288.                 if ((et_val & ET_IMAGE) && !exitflag) putchar(c);
  289.                 else for (type_char(' '); (char_count & tabmask) != 0; type_char(' '));
  290.                 break;
  291.  
  292.             default:
  293.                 if ((et_val & ET_IMAGE) && !exitflag) putchar(c);
  294.                 else
  295.                     {
  296.                     putchar('^');
  297.                     putchar(c + 'A'-1);
  298.                     char_count += 2;
  299.                     }
  300.                 break;
  301.             }
  302.         }
  303.     else
  304.         {
  305.         putchar(c);
  306.         char_count++;
  307.         }
  308.     }
  309.  
  310.