home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / curses.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-11  |  20.0 KB  |  952 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: curses.c,v 5.10 1993/04/12 03:57:45 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.10 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: curses.c,v $
  17.  * Revision 5.10  1993/04/12  03:57:45  syd
  18.  * Give up and add an Ultrix specific patch. There is a bug in Ispell under
  19.  * ultrix.  The problem is that when ispell returns, the terminal is no
  20.  * longer in raw mode. (Ispell isn't restoring the terminal parameters)
  21.  * From: Scott Ames <scott@cwis.unomaha.edu>
  22.  *
  23.  * Revision 5.9  1993/02/03  19:06:31  syd
  24.  * Remove extra strchr/strcat/strcpy et al declarations
  25.  * From: Syd
  26.  *
  27.  * Revision 5.8  1992/12/11  01:45:04  syd
  28.  * remove sys/types.h include, it is now included by defs.h
  29.  * and this routine includes defs.h or indirectly includes defs.h
  30.  * From: Syd
  31.  *
  32.  * Revision 5.7  1992/11/07  20:45:39  syd
  33.  * add no tite flag on options that should not use ti/te
  34.  * Hack by Syd
  35.  *
  36.  * Revision 5.6  1992/10/27  15:46:35  syd
  37.  * Suns dont like ioctl on top of termios
  38.  * From: syd
  39.  *
  40.  * Revision 5.5  1992/10/27  01:52:16  syd
  41.  * Always include <sys/ioctl.h> in curses.c When calling ioctl()
  42.  *
  43.  * Remove declaration of getegid() from leavembox.c & lock.c
  44.  * They aren't even used there.
  45.  * From: tom@osf.org
  46.  *
  47.  * Revision 5.4  1992/10/24  13:35:39  syd
  48.  * changes found by using codecenter on Elm 2.4.3
  49.  * From: Graham Hudspith <gwh@inmos.co.uk>
  50.  *
  51.  * Revision 5.3  1992/10/17  22:58:57  syd
  52.  * patch to make elm use (or in my case, not use) termcap/terminfo ti/te.
  53.  * From: Graham Hudspith <gwh@inmos.co.uk>
  54.  *
  55.  * Revision 5.2  1992/10/11  01:02:05  syd
  56.  * Add AIX to those who dont define window size in termios.h
  57.  * From: Syd via note from Tom Kovar
  58.  *
  59.  * Revision 5.1  1992/10/03  22:58:40  syd
  60.  * Initial checkin as of 2.4 Release at PL0
  61.  *
  62.  *
  63.  ******************************************************************************/
  64.  
  65. /**  This library gives programs the ability to easily access the
  66.      termcap information and write screen oriented and raw input
  67.      programs.  The routines can be called as needed, except that
  68.      to use the cursor / screen routines there must be a call to
  69.      InitScreen() first.  The 'Raw' input routine can be used
  70.      independently, however.
  71.  
  72. **/
  73.  
  74. /** NOTE THE ADDITION OF: the #ifndef ELM stuff around routines that
  75.     we don't use.  This is for code size and compile time speed...
  76. **/
  77.  
  78. #include "headers.h"
  79.  
  80. #ifdef TERMIOS
  81. # include <termios.h>
  82. # ifndef sun
  83. #  include <sys/ioctl.h>    /* for TIOCGWINSZ */
  84. # endif
  85. #else
  86. # ifdef TERMIO
  87. #  include <termio.h>
  88. # else
  89. #  include <sgtty.h>
  90. # endif
  91. #endif
  92.  
  93. #include <ctype.h>
  94.  
  95. #ifdef PTEM
  96. #  include <sys/stream.h>
  97. #  include <sys/ptem.h>
  98. #endif
  99.  
  100. #ifdef BSD
  101. #undef tolower
  102. #endif
  103.  
  104. #define TTYIN    0
  105.  
  106. #ifdef SHORTNAMES
  107. # define _clearinverse    _clrinv
  108. # define _cleartoeoln    _clrtoeoln
  109. # define _cleartoeos    _clr2eos
  110. # define _transmit_off    xmit_off
  111. # define _transmit_on    xmit_on
  112. #endif
  113.  
  114. #ifdef TERMIOS
  115. struct termios _raw_tty,
  116.            _original_tty;
  117. #define    ttgetattr(fd,where)    tcgetattr((fd),(where))
  118. #define    ttsetattr(fd,where)    tcsetattr((fd),TCSADRAIN,(where))
  119. #else    /*TERMIOS*/
  120. # ifdef TERMIO
  121. struct termio _raw_tty, 
  122.               _original_tty;
  123. #define    ttgetattr(fd,where)    ioctl((fd),TCGETA,(where))
  124. #define    ttsetattr(fd,where)    ioctl((fd),TCSETAW,(where))
  125. # else
  126. struct sgttyb _raw_tty,
  127.           _original_tty;
  128. #define    ttgetattr(fd,where)    ioctl((fd),TIOCGETP,(where))
  129. #define    ttsetattr(fd,where)    ioctl((fd),TIOCSETP,(where))
  130. # endif    /*TERMIO*/
  131. #endif    /*TERMIOS*/
  132.  
  133. static int _inraw = 0;                  /* are we IN rawmode?    */
  134.  
  135. #define DEFAULT_LINES_ON_TERMINAL    24
  136. #define DEFAULT_COLUMNS_ON_TERMINAL    80
  137.  
  138. static int _memory_locked = 0;        /* are we IN memlock??   */
  139. static int _line  = -1,            /* initialize to "trash" */
  140.            _col   = -1;
  141.  
  142. static int _intransmit;            /* are we transmitting keys? */
  143.  
  144. static
  145. char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
  146.      *_setbold, *_clearbold, *_setunderline, *_clearunderline, 
  147.      *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
  148.      *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off,
  149.      *_set_memlock, *_clear_memlock, *_start_termcap, *_end_termcap;
  150.  
  151. static int _lines, _columns, _automargin, _eatnewlineglitch;
  152. int tabspacing;
  153.  
  154. static char _terminal[1024];              /* Storage for terminal entry */
  155. static char _capabilities[1024];           /* String for cursor motion */
  156.  
  157. static char *ptr = _capabilities;    /* for buffering         */
  158.  
  159. int    outchar();            /* char output for tputs */
  160. char  *tgetstr(),                    /* Get termcap capability */
  161.       *tgoto();                /* and the goto stuff    */
  162.  
  163. InitScreen()
  164. {
  165.     /* Set up all this fun stuff: returns zero if all okay, or;
  166.         -1 indicating no terminal name associated with this shell,
  167.         -2..-n  No termcap for this terminal type known
  168.    */
  169.  
  170.     int  tgetent(),      /* get termcap entry */
  171.          err;
  172.     char termname[40];
  173.     char *termenv;
  174.     
  175.     if ((termenv = getenv("TERM")) == NULL) return(-1);
  176.  
  177.     if (strcpy(termname, termenv) == NULL)
  178.         return(-1);
  179.  
  180.     if ((err = tgetent(_terminal, termname)) != 1)
  181.         return(err-2);
  182.  
  183.     _line  =  0;        /* where are we right now?? */
  184.     _col   =  0;        /* assume zero, zero...     */
  185.  
  186.     /* load in all those pesky values */
  187.     _clearscreen       = tgetstr("cl", &ptr);
  188.     _moveto            = tgetstr("cm", &ptr);
  189.     _up                = tgetstr("up", &ptr);
  190.     _down              = tgetstr("do", &ptr);
  191.     _right             = tgetstr("nd", &ptr);
  192.     _left              = tgetstr("bc", &ptr);
  193.     _setbold           = tgetstr("so", &ptr);
  194.     _clearbold         = tgetstr("se", &ptr);
  195.     _setunderline      = tgetstr("us", &ptr);
  196.     _clearunderline    = tgetstr("ue", &ptr);
  197.     _setinverse        = tgetstr("so", &ptr);
  198.     _clearinverse      = tgetstr("se", &ptr);
  199.     _sethalfbright     = tgetstr("hs", &ptr);
  200.     _clearhalfbright   = tgetstr("he", &ptr);
  201.     _cleartoeoln       = tgetstr("ce", &ptr);
  202.     _cleartoeos        = tgetstr("cd", &ptr);
  203.     _lines                 = tgetnum("li");
  204.     _columns       = tgetnum("co");
  205.     tabspacing       = ((tabspacing=tgetnum("it"))==-1 ? 8 : tabspacing);
  206.     _automargin       = tgetflag("am");
  207.     _eatnewlineglitch   = tgetflag("xn");
  208.     _transmit_on       = tgetstr("ks", &ptr);
  209.     _transmit_off      = tgetstr("ke", &ptr);
  210.     _set_memlock       = tgetstr("ml", &ptr);
  211.     _clear_memlock       = tgetstr("mu", &ptr);
  212.     _start_termcap       = tgetstr("ti", &ptr);
  213.     _end_termcap       = tgetstr("te", &ptr);
  214.  
  215.  
  216.     if (!_left) {
  217.         _left = "\b";
  218.     }
  219.  
  220.     return(0);
  221. }
  222.  
  223. char *return_value_of(termcap_label)
  224. char *termcap_label;
  225. {
  226.     /** This will return the string kept by termcap for the 
  227.         specified capability. Modified to ensure that if 
  228.         tgetstr returns a pointer to a transient address    
  229.         that we won't bomb out with a later segmentation
  230.         fault (thanks to Dave@Infopro for this one!)
  231.  
  232.         Tweaked to remove padding sequences.
  233.      **/
  234.  
  235.     static char escape_sequence[20];
  236.     register int i=0,j=0;
  237.     char buffer[20];
  238.     char *myptr, *tgetstr();             /* Get termcap capability */
  239.  
  240.     if (strlen(termcap_label) < 2)
  241.       return(NULL);
  242.  
  243.     if (termcap_label[0] == 's' && termcap_label[1] == 'o')
  244.       {
  245.       if (_setinverse)
  246.         strcpy(escape_sequence, _setinverse);
  247.       else
  248.         return( (char *) NULL );
  249.       }
  250.     else if (termcap_label[0] == 's' && termcap_label[1] == 'e')
  251.       {
  252.       if (_clearinverse)
  253.         strcpy(escape_sequence, _clearinverse);
  254.       else
  255.         return( (char *) NULL );
  256.       }
  257.     else if ((myptr = tgetstr(termcap_label, &ptr)) == NULL)
  258.       return( (char *) NULL );
  259.     else
  260.       strcpy(escape_sequence, myptr);
  261.  
  262.     if (chloc(escape_sequence, '$') != -1) {
  263.       while (escape_sequence[i] != '\0') {
  264.         while (escape_sequence[i] != '$' && escape_sequence[i] != '\0')
  265.           buffer[j++] = escape_sequence[i++];
  266.         if (escape_sequence[i] == '$') {
  267.           while (escape_sequence[i] != '>') i++;
  268.           i++;
  269.         }
  270.       }
  271.       buffer[j] = '\0';
  272.       strcpy(escape_sequence, buffer);
  273.     }
  274.  
  275.     return( (char *) escape_sequence);
  276. }
  277.  
  278. transmit_functions(newstate)
  279. int newstate;
  280. {
  281.     /** turn function key transmission to ON | OFF **/
  282.  
  283.     if (newstate != _intransmit) {
  284.         _intransmit = ! _intransmit;
  285.         if (newstate == ON)
  286.           tputs(_transmit_on, 1, outchar);
  287.         else 
  288.           tputs(_transmit_off, 1, outchar);
  289.         fflush(stdout);      /* clear the output buffer */
  290.     }
  291. }
  292.  
  293. /****** now into the 'meat' of the routines...the cursor stuff ******/
  294.  
  295. ScreenSize(lines, columns)
  296. int *lines, *columns;
  297. {
  298.     /** returns the number of lines and columns on the display. **/
  299.  
  300. #ifdef TIOCGWINSZ
  301.     struct winsize w;
  302.  
  303.     if (ioctl(1,TIOCGWINSZ,&w) != -1) {
  304.         if (w.ws_row > 0)
  305.             _lines = w.ws_row;
  306.         if (w.ws_col > 0)
  307.             _columns = w.ws_col;
  308.     }
  309. #endif
  310.  
  311.     if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  312.     if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  313.  
  314.     *lines = _lines - 1;        /* assume index from zero */
  315.     *columns = _columns;
  316. }
  317.  
  318. SetXYLocation(x,y)
  319. int x,y;
  320. {
  321.     /* declare where the cursor is on the screen - useful after using
  322.      * a function that moves cursor in predictable fasion but doesn't
  323.      * set the static x and y variables used in this source file -
  324.      * e.g. getpass().
  325.      */
  326.  
  327.     _line = x;
  328.     _col = y;
  329. }
  330.  
  331. GetXYLocation(x,y)
  332. int *x,*y;
  333. {
  334.     /* return the current cursor location on the screen */
  335.  
  336.     *x = _line;
  337.     *y = _col;
  338. }
  339.  
  340. ClearScreen()
  341. {
  342.     /* clear the screen: returns -1 if not capable */
  343.  
  344.     _line = 0;    /* clear leaves us at top... */
  345.     _col  = 0;
  346.  
  347.     if (!_clearscreen)
  348.         return(-1);
  349.  
  350.     tputs(_clearscreen, 1, outchar);
  351.     fflush(stdout);      /* clear the output buffer */
  352.     return(0);
  353. }
  354.  
  355. static
  356. CursorUp(n)
  357. int n;
  358. {
  359.     /** move the cursor up 'n' lines **/
  360.     /** Calling function must check that _up is not null before calling **/
  361.  
  362.     _line = (_line-n > 0? _line - n: 0);    /* up 'n' lines... */
  363.  
  364.     while (n-- > 0)
  365.         tputs(_up, 1, outchar);
  366.  
  367.     fflush(stdout);
  368.     return(0);
  369. }
  370.  
  371.  
  372. static
  373. CursorDown(n)
  374. int n;
  375. {
  376.     /** move the cursor down 'n' lines **/
  377.     /** Caller must check that _down is not null before calling **/
  378.  
  379.     _line = (_line+n <= LINES? _line + n: LINES);    /* down 'n' lines... */
  380.  
  381.     while (n-- > 0)
  382.         tputs(_down, 1, outchar);
  383.  
  384.     fflush(stdout);
  385.     return(0);
  386. }
  387.  
  388.  
  389. static
  390. CursorLeft(n)
  391. int n;
  392. {
  393.     /** move the cursor 'n' characters to the left **/
  394.     /** Caller must check that _left is not null before calling **/
  395.  
  396.     _col = (_col - n> 0? _col - n: 0);    /* left 'n' chars... */
  397.  
  398.     while (n-- > 0)
  399.         tputs(_left, 1, outchar);
  400.  
  401.     fflush(stdout);
  402.     return(0);
  403. }
  404.  
  405.  
  406. static
  407. CursorRight(n)
  408. int n;
  409. {
  410.     /** move the cursor 'n' characters to the right (nondestructive) **/
  411.     /** Caller must check that _right is not null before calling **/
  412.  
  413.     _col = (_col+n < COLUMNS? _col + n: COLUMNS);    /* right 'n' chars... */
  414.  
  415.     while (n-- > 0)
  416.         tputs(_right, 1, outchar);
  417.  
  418.     fflush(stdout);
  419.     return(0);
  420. }
  421.  
  422. static
  423. moveabsolute(col, row)
  424. {
  425.  
  426.     char *stuff, *tgoto();
  427.  
  428.     stuff = tgoto(_moveto, col, row);
  429.     tputs(stuff, 1, outchar);
  430.     fflush(stdout);
  431. }
  432.  
  433. MoveCursor(row, col)
  434. int row, col;
  435. {
  436.     /** move cursor to the specified row column on the screen.
  437.             0,0 is the top left! **/
  438.  
  439.     int scrollafter = 0;
  440.  
  441.     /* we don't want to change "rows" or we'll mangle scrolling... */
  442.  
  443.     if (col < 0)
  444.       col = 0;
  445.     if (col >= COLUMNS)
  446.       col = COLUMNS - 1;
  447.     if (row < 0)
  448.       row = 0;
  449.     if (row > LINES) {
  450.       if (col == 0)
  451.         scrollafter = row - LINES;
  452.       row = LINES;
  453.     }
  454.  
  455.     if (!_moveto)
  456.         return(-1);
  457.  
  458.     if (row == _line) {
  459.       if (col == _col)
  460.         return(0);                /* already there! */
  461.  
  462.       else if (abs(col - _col) < 5) {    /* within 5 spaces... */
  463.         if (col > _col && _right)
  464.           CursorRight(col - _col);
  465.         else if (col < _col &&  _left)
  466.           CursorLeft(_col - col);
  467.         else
  468.           moveabsolute(col, row);
  469.           }
  470.       else         /* move along to the new x,y loc */
  471.         moveabsolute(col, row);
  472.     }
  473.     else if (_line == row-1 && col == 0) {
  474.       if (_col != 0)
  475.         putchar('\r');
  476.       putchar('\n');
  477.       fflush(stdout);
  478.     }
  479.     else if (col == _col && abs(row - _line) < 5) {
  480.       if (row < _line && _up)
  481.         CursorUp(_line - row);
  482.       else if (row > _line && _down)
  483.         CursorDown(row - _line);
  484.       else
  485.         moveabsolute(col, row);
  486.     }
  487.     else 
  488.       moveabsolute(col, row);
  489.  
  490.     _line = row;    /* to ensure we're really there... */
  491.     _col  = col;
  492.  
  493.     if (scrollafter) {
  494.       putchar('\r');
  495.       while (scrollafter--)
  496.         putchar('\n');
  497.     }
  498.  
  499.     return(0);
  500. }
  501.  
  502. CarriageReturn()
  503. {
  504.     /** move the cursor to the beginning of the current line **/
  505.     Writechar('\r');
  506. }
  507.  
  508. NewLine()
  509. {
  510.     /** move the cursor to the beginning of the next line **/
  511.  
  512.     Writechar('\r');
  513.     Writechar('\n');
  514. }
  515.  
  516. StartBold()
  517. {
  518.     /** start boldface/standout mode **/
  519.  
  520.     if (!_setbold)
  521.         return(-1);
  522.  
  523.     tputs(_setbold, 1, outchar);
  524.     fflush(stdout);
  525.     return(0);
  526. }
  527.  
  528.  
  529. EndBold()
  530. {
  531.     /** compliment of startbold **/
  532.  
  533.     if (!_clearbold)
  534.         return(-1);
  535.  
  536.     tputs(_clearbold, 1, outchar);
  537.     fflush(stdout);
  538.     return(0);
  539. }
  540.  
  541. #ifndef ELM
  542.  
  543. StartUnderline()
  544. {
  545.     /** start underline mode **/
  546.  
  547.     if (!_setunderline)
  548.         return(-1);
  549.  
  550.     tputs(_setunderline, 1, outchar);
  551.     fflush(stdout);
  552.     return(0);
  553. }
  554.  
  555.  
  556. EndUnderline()
  557. {
  558.     /** the compliment of start underline mode **/
  559.  
  560.     if (!_clearunderline)
  561.         return(-1);
  562.  
  563.     tputs(_clearunderline, 1, outchar);
  564.     fflush(stdout);
  565.     return(0);
  566. }
  567.  
  568.  
  569. StartHalfbright()
  570. {
  571.     /** start half intensity mode **/
  572.  
  573.     if (!_sethalfbright)
  574.         return(-1);
  575.  
  576.     tputs(_sethalfbright, 1, outchar);
  577.     fflush(stdout);
  578.     return(0);
  579. }
  580.  
  581. EndHalfbright()
  582. {
  583.     /** compliment of starthalfbright **/
  584.  
  585.     if (!_clearhalfbright)
  586.         return(-1);
  587.  
  588.     tputs(_clearhalfbright, 1, outchar);
  589.     fflush(stdout);
  590.     return(0);
  591. }
  592.  
  593. StartInverse()
  594. {
  595.     /** set inverse video mode **/
  596.  
  597.     if (!_setinverse)
  598.         return(-1);
  599.  
  600.     tputs(_setinverse, 1, outchar);
  601.     fflush(stdout);
  602.     return(0);
  603. }
  604.  
  605.  
  606. EndInverse()
  607. {
  608.     /** compliment of startinverse **/
  609.  
  610.     if (!_clearinverse)
  611.         return(-1);
  612.  
  613.     tputs(_clearinverse, 1, outchar);
  614.     fflush(stdout);
  615.     return(0);
  616. }
  617.  
  618. int
  619. HasMemlock()
  620. {
  621.     /** returns TRUE iff memory locking is available (a terminal
  622.         feature that allows a specified portion of the screen to
  623.         be "locked" & not cleared/scrolled... **/
  624.  
  625.     return ( _set_memlock && _clear_memlock );
  626. }
  627.  
  628. static int _old_LINES;
  629.  
  630. int
  631. StartMemlock()
  632. {
  633.     /** mark the current line as the "last" line of the portion to 
  634.         be memory locked (always relative to the top line of the
  635.         screen) Note that this will alter LINES so that it knows
  636.         the top is locked.  This means that (plus) the program 
  637.         will scroll nicely but (minus) End memlock MUST be called
  638.         whenever we leave the locked-memory part of the program! **/
  639.  
  640.     if (! _set_memlock)
  641.       return(-1);
  642.  
  643.     if (! _memory_locked) {
  644.  
  645.       _old_LINES = LINES;
  646.       LINES -= _line;        /* we can't use this for scrolling */
  647.  
  648.       tputs(_set_memlock, 1, outchar);
  649.       fflush(stdout);
  650.       _memory_locked = TRUE;
  651.     }
  652.  
  653.     return(0);
  654. }
  655.  
  656. int
  657. EndMemlock()
  658. {
  659.     /** Clear the locked memory condition...  **/
  660.  
  661.     if (! _set_memlock)
  662.       return(-1);
  663.  
  664.     if (_memory_locked) {
  665.       LINES = _old_LINES;        /* back to old setting */
  666.   
  667.       tputs(_clear_memlock, 1, outchar);
  668.       fflush(stdout);
  669.       _memory_locked = FALSE;
  670.     }
  671.     return(0);
  672. }
  673.  
  674. #endif /* ndef ELM */
  675.  
  676. Writechar(ch)
  677. register int ch;
  678. {
  679.     /** write a character to the current screen location. **/
  680.  
  681.     static int wrappedlastchar = 0;
  682.     int justwrapped, nt;
  683.  
  684.     ch &= 0xFF;
  685.     justwrapped = 0;
  686.  
  687.     /* if return, just go to left column. */
  688.     if(ch == '\r') {
  689.       if (wrappedlastchar)
  690.         justwrapped = 1;                /* preserve wrap flag */
  691.       else {
  692.         putchar('\r');
  693.         _col = 0;
  694.       }
  695.     }
  696.  
  697.     /* if newline and terminal just did a newline without our asking,
  698.      * do nothing, else output a newline and increment the line count */
  699.     else if (ch == '\n') {
  700.       if (!wrappedlastchar) {
  701.         putchar('\n');
  702.         if (_line < LINES)
  703.           ++_line;
  704.       }
  705.     }
  706.  
  707.     /* if backspace, move back  one space  if not already in column 0 */
  708.     else if (ch == BACKSPACE) {
  709.       if(_col != 0) {
  710.         tputs(_left, 1, outchar);
  711.         _col--;
  712.       } /* else BACKSPACE does nothing */
  713.     }
  714.  
  715.     /* if bell, ring the bell but don't advance the column */
  716.     else if (ch == '\007') {
  717.       putchar(ch);
  718.     }
  719.  
  720.     /* if a tab, output it */
  721.     else if (ch == '\t') {
  722.       putchar(ch);
  723.       if((nt=next_tab(_col+1)) > prev_tab(COLUMNS))
  724.         _col = COLUMNS-1;
  725.       else
  726.         _col = nt-1;
  727.     }
  728.  
  729.     else {
  730.       /* if some kind of non-printable character change to a '?' */
  731. #ifdef ASCII_CTYPE
  732.       if(!isascii(ch) || !isprint(ch))
  733. #else
  734.       if(!isprint(ch))
  735. #endif
  736.         ch = '?';
  737.  
  738.       /* if we only have one column left, simulate automargins if
  739.        * the terminal doesn't have them */
  740.       if (_col == COLUMNS - 1) {
  741.         putchar(ch);
  742.         if (!_automargin || _eatnewlineglitch) {
  743.           putchar('\r');
  744.           putchar('\n');
  745.         }
  746.         if (_line < LINES)
  747.           ++_line;
  748.         _col = 0;
  749.         justwrapped = 1;
  750.       }
  751.  
  752.       /* if we are here this means we have no interference from the
  753.        * right margin - just output the character and increment the
  754.        * column position. */
  755.       else {
  756.         putchar(ch);
  757.         _col++;
  758.       }
  759.     }
  760.  
  761.     wrappedlastchar = justwrapped;
  762.  
  763.     return(0);
  764. }
  765.  
  766. /*VARARGS2*/
  767.  
  768. Write_to_screen(line, argcount, arg1, arg2, arg3)
  769. char *line;
  770. int   argcount; 
  771. char *arg1, *arg2, *arg3;
  772. {
  773.     /** This routine writes to the screen at the current location.
  774.           when done, it increments lines & columns accordingly by
  775.         looking for "\n" sequences... **/
  776.  
  777.     switch (argcount) {
  778.     case 0 :
  779.         PutLine0(_line, _col, line);
  780.         break;
  781.     case 1 :
  782.         PutLine1(_line, _col, line, arg1);
  783.         break;
  784.     case 2 :
  785.         PutLine2(_line, _col, line, arg1, arg2);
  786.         break;
  787.     case 3 :
  788.         PutLine3(_line, _col, line, arg1, arg2, arg3);
  789.         break;
  790.     }
  791. }
  792.  
  793. PutLine0(x, y, line)
  794. int x,y;
  795. register char *line;
  796. {
  797.     /** Write a zero argument line at location x,y **/
  798.  
  799.     MoveCursor(x,y);
  800.     while(*line)
  801.       Writechar(*line++);
  802.     fflush(stdout);
  803. }
  804.  
  805. /*VARARGS2*/
  806. PutLine1(x,y, line, arg1)
  807. int x,y;
  808. char *line;
  809. char *arg1;
  810. {
  811.     /** write line at location x,y - one argument... **/
  812.  
  813.     char buffer[VERY_LONG_STRING];
  814.  
  815.     sprintf(buffer, line, arg1);
  816.  
  817.     PutLine0(x, y, buffer);
  818.         fflush(stdout);
  819. }
  820.  
  821. /*VARARGS2*/
  822. PutLine2(x,y, line, arg1, arg2)
  823. int x,y;
  824. char *line;
  825. char *arg1, *arg2;
  826. {
  827.     /** write line at location x,y - one argument... **/
  828.  
  829.     char buffer[VERY_LONG_STRING];
  830.  
  831.     MCsprintf(buffer, line, arg1, arg2);
  832.  
  833.     PutLine0(x, y, buffer);
  834.         fflush(stdout);
  835. }
  836.  
  837. /*VARARGS2*/
  838. PutLine3(x,y, line, arg1, arg2, arg3)
  839. int x,y;
  840. char *line;
  841. char *arg1, *arg2, *arg3;
  842. {
  843.     /** write line at location x,y - one argument... **/
  844.  
  845.     char buffer[VERY_LONG_STRING];
  846.  
  847.     MCsprintf(buffer, line, arg1, arg2, arg3);
  848.  
  849.     PutLine0(x, y, buffer);
  850.         fflush(stdout);
  851. }
  852.  
  853. CleartoEOLN()
  854. {
  855.     /** clear to end of line **/
  856.  
  857.     if (!_cleartoeoln)
  858.         return(-1);
  859.  
  860.     tputs(_cleartoeoln, 1, outchar);
  861.     fflush(stdout);  /* clear the output buffer */
  862.     return(0);
  863. }
  864.  
  865. CleartoEOS()
  866. {
  867.     /** clear to end of screen **/
  868.  
  869.     if (!_cleartoeos)
  870.         return(-1);
  871.  
  872.     tputs(_cleartoeos, 1, outchar);
  873.     fflush(stdout);  /* clear the output buffer */
  874.     return(0);
  875. }
  876.  
  877.  
  878. RawState()
  879. {
  880.     /** returns either 1 or 0, for ON or OFF **/
  881.  
  882.     return( _inraw );
  883. }
  884.  
  885. #ifdef ultrix
  886. force_raw()
  887. {
  888.     _inraw = 0;
  889.     Raw(ON);
  890. }
  891. #endif
  892.  
  893. Raw(state)
  894. int state;
  895. {
  896.     int do_tite = (state & NO_TITE) == 0;
  897.  
  898.     state = state & ~NO_TITE;
  899.  
  900.     /** state is either ON or OFF, as indicated by call **/
  901.  
  902.     if (state == OFF && _inraw) {
  903.       if (use_tite && _end_termcap && do_tite) {
  904.         tputs(_end_termcap, 1, outchar);
  905.         fflush(stdout);
  906.       }
  907.       (void) ttsetattr(TTYIN,&_original_tty);
  908.       _inraw = 0;
  909.     }
  910.     else if (state == ON && ! _inraw) {
  911.  
  912.       (void) ttgetattr(TTYIN, &_original_tty);
  913.       (void) ttgetattr(TTYIN, &_raw_tty);    /** again! **/
  914.  
  915. #if !defined(TERMIO) && !defined(TERMIOS)
  916.       _raw_tty.sg_flags &= ~(ECHO);    /* echo off */
  917.       _raw_tty.sg_flags |= CBREAK;    /* raw on    */
  918. #else
  919.       _raw_tty.c_lflag &= ~(ICANON | ECHO);    /* noecho raw mode        */
  920.  
  921.       _raw_tty.c_cc[VMIN] = '\01';    /* minimum # of chars to queue    */
  922.       _raw_tty.c_cc[VTIME] = '\0';    /* minimum time to wait for input */
  923.  
  924. #endif
  925.       (void) ttsetattr(TTYIN, &_raw_tty);
  926.       if (use_tite && _start_termcap && do_tite)
  927.         tputs(_start_termcap, 1, outchar);
  928.       _inraw = 1;
  929.     }
  930. }
  931.  
  932. int
  933. ReadCh()
  934. {
  935.     /** read a character with Raw mode set! **/
  936.  
  937.     register int result;
  938.     char ch;
  939.     result = read(0, &ch, 1);
  940.         return((result <= 0 ) ? EOF : ch);
  941. }
  942.  
  943. outchar(c)
  944. char c;
  945. {
  946.     /** output the given character.  From tputs... **/
  947.     /** Note: this CANNOT be a macro!              **/
  948.  
  949.     putc(c, stdout);
  950. }
  951.  
  952.