home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / ELM23-2 / ELM23-2.ZIP / src / curses.c < prev    next >
C/C++ Source or Header  |  1996-10-07  |  21KB  |  974 lines

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