home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / se / part05 / term.c
Encoding:
C/C++ Source or Header  |  1987-01-25  |  36.7 KB  |  2,069 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: term.c,v 1.7 86/11/12 11:37:30 arnold Exp $";
  3. #endif
  4.  
  5. /*
  6.  * $Log:    term.c,v $
  7.  * Revision 1.7  86/11/12  11:37:30  arnold
  8.  * Fixed winsize() to verify that cols and rows not 0 before assigning
  9.  * them to Nrows and Ncols.
  10.  * 
  11.  * Revision 1.6  86/10/14  11:10:36  arnold
  12.  * Reorganization of window handling stuff. Added (untested) code for sun.
  13.  * 
  14.  * Revision 1.5  86/10/07  14:50:48  arnold
  15.  * Changed setterm to set_term, to avoid Unix/PC shared library conflict.
  16.  * Fixed winsize() to set Nrows and Ncols on first call, as well.
  17.  * 
  18.  * Revision 1.4  86/09/19  12:15:28  arnold
  19.  * Fixes to BSD windowing for real 4.3, from BRL.
  20.  * 
  21.  * Revision 1.3  86/07/17  17:23:19  arnold
  22.  * Massive reorganization and cleaning up. Terminal initialization
  23.  * stuff moved here, and homogenized.
  24.  * 
  25.  * Revision 1.2  86/07/14  17:19:33  arnold
  26.  * Added code that notices whether or not the window we are runnng in has
  27.  * changed sizes. It definitely works on the Unix PC, and should work on
  28.  * BRL Unix and 4.3 BSD.
  29.  * 
  30.  * Revision 1.1  86/05/06  13:38:53  osadr
  31.  * Initial revision
  32.  * 
  33.  * 
  34.  */
  35.  
  36. /*
  37. ** term.c
  38. **
  39. ** provide terminal functions for se
  40. **
  41. ** If HARD_TERMS is *not* defined, which is the default, se will
  42. ** use the termlib library, which provides terminal independant operations.
  43. ** This makes se both smaller, and more flexible.
  44. **
  45. ** If HARD_TERMS is defined, then se will use the original code, which
  46. ** had terminal types hard-wired into the code.  This would be useful for
  47. ** a system which does not have the termlib library.
  48. **
  49. ** On System V systems, we have two possibilities.  Release 1 did not have
  50. ** the terminfo package, so we assume that if it is Release 1, someone will
  51. ** have ported the BSD termlib library.  If it is Release 2, then the new
  52. ** terminfo package is there, and we wil use it.
  53. **
  54. ** This file is large. It is organized as follows.
  55. **
  56. ** Routines that do not care whether or not HARD_TERMS is defined.
  57. ** Routines that are only if HARD_TERMS is NOT defined. These contain:
  58. **    BSD/termlib routines
  59. **    System V/terminfo routines
  60. **    Routines idenpendant of BSD/System V
  61. ** Routines that are only if HARD_TERMS is defined.
  62. ** Routines that have regular and conditonal code mixed.
  63. */
  64.  
  65. #include "se.h"
  66. #include "extern.h"
  67.  
  68. /* outc -- write a character to the terminal */
  69.  
  70. int outc (c)
  71. char c;
  72. {
  73.     twrite (1, &c, 1);
  74. }
  75.  
  76. #ifndef HARD_TERMS
  77. #if defined (BSD) || !defined (S5R2)
  78. /*
  79.  * code for using BSD termlib -- getting capabilities, and writing them out.
  80.  */
  81.  
  82. /* capabilities from termcap */
  83.  
  84. static int AM;        /* automatic margins, i.e. wraps at column 80 */
  85.  
  86. static char *VS;    /* visual start -- e.g. clear status line */
  87. static char *VE;    /* visual end -- e.g. restore status line */
  88. static char *TI;    /* terminal init -- whatever needed for screen ops */
  89. static char *TE;    /* terminal ops end */
  90. static char *CM;    /* cursor motion, used by tgoto() */
  91. static char *CE;    /* clear to end of line */
  92. static char *DL;    /* hardware delete line */
  93. static char *AL;    /* hardware add (insert) line */
  94. static char *CL;    /* clear screen */
  95.  
  96. extern char PC;        /* Pad character, usually '\0' */
  97.  
  98. static char *pcstr;
  99. extern char *tgoto (), *tgetstr ();    /* termlib routines */
  100.  
  101. static char caps[128];        /* space for decoded capability strings */
  102. static char *addr_caps;        /* address of caps for relocation */
  103.  
  104. #define TERMBUFSIZ    1024+1
  105. static char termbuf[TERMBUFSIZ];
  106.  
  107. /* getdescrip --- get descriptions out of termcap entry */
  108.  
  109. static getdescrip ()
  110. {
  111.     int i;
  112.     static struct _table {
  113.         char *name;
  114.         char **ptr_to_cap;
  115.         } table[] = {
  116.             "vs",    & VS,
  117.             "ve",    & VE,
  118.             "ti",    & TI,
  119.             "te",    & TE,
  120.             "cm",    & CM,
  121.             "ce",    & CE,
  122.             "dl",    & DL,
  123.             "al",    & AL,
  124.             "cl",    & CL,
  125.             "pc",    & pcstr,
  126.             NULL,    NULL
  127.             };
  128.  
  129.     AM = tgetflag ("am");        /* only boolean se needs */
  130.  
  131.     /* get string values */
  132.  
  133.     for (i = 0; table[i].name != NULL; i++)
  134.         *(table[i].ptr_to_cap) = tgetstr (table[i].name, & addr_caps);
  135. }
  136.  
  137. /* setcaps -- get the capabilities from termcap file into termbuf */
  138.  
  139. static setcaps (term)
  140. char *term;
  141. {
  142.     switch (tgetent (termbuf, term)) {
  143.     case -1:
  144.         error (NO, "se: couldn't open termcap file.");
  145.  
  146.     case 0:
  147.         error (NO, "se: no termcap entry for %s terminals.", term);
  148.  
  149.     case 1:
  150.         addr_caps = caps;
  151.         getdescrip ();        /* get terminal description */
  152.         Nrows = tgetnum ("li");
  153.         Ncols = tgetnum ("co");
  154.         break;
  155.  
  156.     default:
  157.         error (YES, "in setcaps: can't happen.\n");
  158.     }
  159.  
  160.     return (OK);
  161. }
  162.  
  163. #else
  164.  
  165. /* use the new terminfo package */
  166. /*
  167.  * Do NOT include <curses.h>, since it redefines
  168.  * USG, ERR, and OK, to values inconsistent with what
  169.  * we use.
  170.  */
  171.  
  172. /* fix a problem in /usr/include/term.h */
  173. #include <termio.h>
  174. typedef struct termio SGTTY;
  175.  
  176. #include <term.h>    /* should be all we really need */
  177.  
  178. #define AM    auto_right_margin
  179. #define TI    enter_ca_mode
  180. #define TE    exit_ca_mode
  181. #define VS    cursor_visible
  182. #define VE    cursor_normal
  183. #define CL    clear_screen
  184. #define CE    clr_eol
  185. #define DL    delete_line
  186. #define AL    insert_line
  187.  
  188. /* setcaps -- get the capabilities from the terminfo database */
  189.  
  190. static setcaps (term)
  191. char *term;
  192. {
  193.     int ret = 0;
  194.  
  195.     setupterm (term, 1, & ret);
  196.     if (ret != 1)
  197.         return (ERR);
  198.     Nrows = lines;
  199.     Ncols = columns;
  200.  
  201.     return (OK);
  202. }
  203. #endif
  204.  
  205. /* t_init -- put out terminal initialization string */
  206.  
  207. t_init ()
  208. {
  209.     if (VS)
  210.         tputs (VS, 1, outc);
  211.     if (TI)
  212.         tputs (TI, 1, outc);    /* terminal initializations */
  213. }
  214.  
  215. /* t_exit -- put out strings to turn off whatever modes we had turned on */
  216.  
  217. t_exit ()
  218. {
  219.     /* terminal exiting strings */
  220.     if (TE)
  221.         tputs (TE, 1, outc);
  222.     if (VE)
  223.         tputs (VE, 1, outc);
  224.     tflush ();    /* force it out */
  225. }
  226.  
  227. /* winsize --- get the size of the window from the windowing system */
  228. /*        also arrange to catch the windowing signal */
  229.  
  230. #include <signal.h>
  231.  
  232. #ifdef SIGWIND            /* UNIX PC */
  233. #include <sys/font.h>
  234. #include <sys/window.h>
  235. #define WINSIG        SIGWIND
  236. #define WINIOCTL    WIOCGETD
  237. #define WINSTRUCT    uwdata
  238. #define COLS        (w.uw_width / w.uw_hs)
  239. #define ROWS        (w.uw_height / w.uw_vs)
  240. #endif
  241.  
  242. #ifdef SIGWINCH            /* 4.3 BSD and/or Sun 3.x */
  243.  
  244. #define WINSIG        SIGWINCH
  245.  
  246. #ifdef sun
  247. #undef NEWLINE        /* shouldn't hurt; these are in sun include files */
  248. #undef TAB
  249. #include <sys/types.h>
  250. #include <sys/ioctl.h>
  251. #include <sys/tty.h>
  252. #define WINIOCTL TIOCGSIZE
  253. #define WINSTRUCT ttysize
  254. #define COLS w.ts_cols
  255. #define ROWS w.ts_lines
  256.  
  257. #else
  258.  
  259. #include <sys/ioctl.h>
  260. #define WINIOCTL    TIOCGWINSZ
  261. #define WINSTRUCT    winsize
  262. #define COLS w.ws_col
  263. #define ROWS w.ws_row
  264. #endif
  265. #endif
  266.  
  267. static struct WINSTRUCT w;
  268.  
  269. winsize ()
  270. {
  271. #if defined(SIGWIND) || defined(SIGWINCH)
  272.     static int first = 1;
  273.     static char savestatus[MAXCOLS];
  274.     int row, oldstatus = Nrows - 1;
  275.     int cols, rows;
  276.  
  277.     signal (WINSIG, winsize);
  278.  
  279.     if (ioctl (0, WINIOCTL, (char *) & w) != -1)
  280.     {
  281.         cols = COLS;
  282.         rows = ROWS;
  283.  
  284.         if (first)
  285.         {
  286.             first = 0;
  287.             if (cols && rows)
  288.             {
  289.                 Ncols = cols;
  290.                 Nrows = rows;
  291.             }
  292.             return;        /* don't redraw screen */
  293.         }
  294.         else if (Ncols == cols && Nrows == rows)
  295.         {
  296.             /* only position changed */
  297. #ifdef SIGWIND
  298.             remark ("window repositioned");
  299. #endif
  300.             return;
  301.         }
  302.         else
  303.         {
  304.             if (cols && rows)
  305.             {
  306.                 Ncols = cols;
  307.                 Nrows = rows;
  308.             }
  309.         }
  310.     }
  311.     else
  312.         return;
  313.  
  314.     move_ (Screen_image[oldstatus], savestatus, MAXCOLS);
  315.     clrscreen ();
  316.     Toprow = 0;
  317.     Botrow = Nrows - 3;
  318.     Cmdrow = Botrow + 1;
  319.     Sclen = -1;
  320.  
  321.     for (row = 0; row < Nrows; row++)
  322.         move_ (Blanks, Screen_image[row], MAXCOLS);
  323.         /* clear screen */
  324.  
  325.     First_affected = Topln;
  326.     adjust_window (Curln, Curln);
  327.     updscreen ();    /* reload from buffer */
  328.     loadstr (savestatus, Nrows - 1, 0, Ncols);
  329.     remark ("window size change");
  330.     tflush ();
  331. #endif
  332. }
  333.  
  334. #else
  335.  
  336. /* begin terminal dependant routines */
  337.  
  338. /* addspos --- position cursor to (row, col) on ADDS Consul 980 */
  339.  
  340. static addspos (row, col)
  341. int row, col;
  342. {
  343.     char coord;
  344.     int ntabs, where;
  345.  
  346.     if (Currow != row || col < Curcol - 7)
  347.     {
  348.         twrite (1, "\013", 1);    /* VT */
  349.         coord = '@' + row;
  350.         twrite (1, &coord, 1);
  351.         Currow = row;
  352.         Curcol = 0;
  353.     }
  354.  
  355.     if (col > Curcol + 2)
  356.     {
  357.         ntabs = (col + 2) / 5;    /* from beginning */
  358.         where = ntabs * 5;
  359.         ntabs -= Curcol / 5;    /* from Curcol */
  360.         if (ntabs + abs (where - col) <= 4)
  361.         {
  362.             for (; ntabs > 0; ntabs--)
  363.                 twrite (1, "\t", 1);
  364.             Curcol = where;
  365.         }
  366.     }
  367.  
  368.     if (col > Curcol + 4)
  369.     {
  370.         where = col - Curcol;
  371.         twrite (1, "\033\005", 2);    /* ESC ENQ */
  372.         coord = '0' + (where / 10);
  373.         twrite (1, &coord, 1);
  374.         coord = '0' + (where % 10);
  375.         twrite (1, &coord, 1);
  376.         Curcol = col;
  377.     }
  378.  
  379.     while (Curcol < col)
  380.     {
  381.         twrite (1, &Screen_image[Currow][Curcol], 1);
  382.         Curcol++;
  383.     }
  384.  
  385.     while (Curcol > col)
  386.     {
  387.         twrite (1, "\b", 1);
  388.         Curcol--;
  389.     }
  390. }
  391.  
  392. /* admpos --- position cursor to (row, col) on ADM-3A and ADM-31 terminals */
  393.  
  394. static admpos (row, col)
  395. int row, col;
  396. {
  397.     int dist;
  398.     char coord;
  399.  
  400.     dist = col - Curcol;
  401.     if (dist < 0)
  402.         dist = -dist;
  403.     if (row == Currow && dist < 4)  /* 4 chars for abs. position */
  404.     {
  405.         while (Curcol < col)
  406.         {
  407.             twrite (1, &Screen_image[Currow][Curcol], 1);
  408.             Curcol++;
  409.         }
  410.         while (Curcol > col)
  411.         {
  412.             twrite (1, "\b", 1);
  413.             Curcol--;
  414.         }
  415.     }
  416.     else
  417.     {
  418.         twrite (1, "\033=", 2);
  419.         coord = row + ' ';
  420.         twrite (1, &coord, 1);
  421.         coord = col + ' ';
  422.         twrite (1, &coord, 1);
  423.         Currow = row;
  424.         Curcol = col;
  425.     }
  426. }
  427.  
  428.  
  429.  
  430. /* ansipos --- position cursor on ANSI X something-or-other terminals */
  431.  
  432. static ansipos (row, col)
  433. register int row, col;
  434. {
  435.     register int dist;
  436.  
  437.     char absseq[20], relseq[50];
  438.     int absp = 0;
  439.     register int relp = 0;
  440.     register int trow, tcol;
  441.  
  442.     /*** Build relative positioning string--handle row first ***/
  443.     trow = Currow; 
  444.     tcol = Curcol;
  445.     if (row >= trow && row <= trow + 3)
  446.         for (; trow < row; trow++)
  447.             relseq[relp++] = '\012';
  448.     else if (row < trow && row >= trow - 1)
  449.         for (; trow > row; trow--)
  450.         { 
  451.             relseq[relp++] = '\033'; 
  452.             relseq[relp++] = 'M'; 
  453.         }
  454.     else if (row >= trow)
  455.     {
  456.         relseq[relp++] = '\033';
  457.         relseq[relp++] = '[';
  458.         dist = row - trow;
  459.         if (dist >= 10)
  460.             relseq[relp++] = '0' + dist / 10;
  461.         relseq[relp++] = '0' + dist % 10;
  462.         relseq[relp++] = 'B';
  463.         trow = row;
  464.     }
  465.     else /* row < trow */
  466.     {
  467.         relseq[relp++] = '\033';
  468.         relseq[relp++] = '[';
  469.         dist = trow - row;
  470.         if (dist >= 10)
  471.             relseq[relp++] = '0' + dist / 10;
  472.         relseq[relp++] = '0' + dist % 10;
  473.         relseq[relp++] = 'A';
  474.         trow = row;
  475.     }
  476.  
  477.     /*** Now do the column part of relative positioning ***/
  478.     if (col >= tcol - 2 && col <= tcol + 2)
  479.         ;       /* skip coarse positioning -- just do the fine stuff */
  480.     else
  481.     {
  482.         if (col <= 4)
  483.         {
  484.             relseq[relp++] = '\015';
  485.             tcol = 0;
  486.         }
  487.         dist = col - tcol;
  488.         if (col < 72 && dist > 2
  489.             && dist < 8 && (col + 1) % 8 <= 2)
  490.         {
  491.             relseq[relp++] = '\t';
  492.             tcol = ((tcol + 8) / 8) * 8;
  493.         }
  494.     }
  495.     dist = col - tcol;
  496.     if (dist < 0)
  497.         dist = -dist;
  498.     if (dist == 0)
  499.         ;
  500.     else if (dist < 4)  /* 4 chars for abs. position */
  501.     {
  502.         while (tcol < col)
  503.         {
  504.             relseq[relp++] = Screen_image[trow][tcol];
  505.             tcol++;
  506.         }
  507.         while (tcol > col)
  508.         {
  509.             relseq[relp++] = '\b';
  510.             tcol--;
  511.         }
  512.     }
  513.     else if (col >= tcol)
  514.     {
  515.         relseq[relp++] = '\033';
  516.         relseq[relp++] = '[';
  517.         if (dist >= 10)
  518.             relseq[relp++] = '0' + dist / 10;
  519.         relseq[relp++] = '0' + dist % 10;
  520.         relseq[relp++] = 'C';
  521.         tcol = col;
  522.     }
  523.     else /* if (col < tcol) */
  524.     {
  525.         relseq[relp++] = '\033';
  526.         relseq[relp++] = '[';
  527.         if (dist >= 10)
  528.             relseq[relp++] = '0' + dist / 10;
  529.         relseq[relp++] = '0' + dist % 10;
  530.         relseq[relp++] = 'D';
  531.         tcol = col;
  532.     }
  533.  
  534.     /*** If relative positioning will do it, forget absolute ***/
  535.     if (relp <= 5)
  536.         twrite (1, relseq, relp);
  537.     else
  538.     {
  539.         absseq[absp++] = '\033';
  540.         absseq[absp++] = '[';
  541.         if (row >= 9)
  542.             absseq[absp++] = '0' + (row + 1) / 10;
  543.         absseq[absp++] = '0' + (row + 1) % 10;
  544.         absseq[absp++] = ';';
  545.         if (col >= 9)
  546.             absseq[absp++] = '0' + (col + 1) / 10;
  547.         absseq[absp++] = '0' + (col + 1) % 10;
  548.         absseq[absp++] = 'H';
  549.         if (absp >= relp)
  550.             twrite (1, relseq, relp);
  551.         else
  552.             twrite (1, absseq, absp);
  553.     }
  554.     Curcol = col;
  555.     Currow = row;
  556. }
  557.  
  558.  
  559.  
  560. /* anppos --- position cursor on Allen & Paul model 1 */
  561.  
  562. static anppos (row, col)
  563. int row, col;
  564. {
  565.     char coord;
  566.  
  567.     if (row == Currow)      /* if close, just sneak right or left */
  568.     {
  569.         if (col == Curcol + 1)
  570.             twrite (1, "\t", 1);
  571.         else if (col == Curcol + 2)
  572.             twrite (1, "\t\t", 2);
  573.         else if (col == Curcol - 1)
  574.             twrite (1, "\b", 1);
  575.         else if (col == Curcol - 2)
  576.             twrite (1, "\b\b", 2);
  577.         else
  578.         {
  579.             twrite (1, "\033C", 2);
  580.             coord = col + ' ';
  581.             twrite (1, &coord, 1);
  582.         }
  583.     }
  584.  
  585.     else if (col == Curcol) /* if close, sneak up or down */
  586.     {
  587.         if (row == Currow + 1)
  588.             twrite (1, "\012", 1);
  589.         else if (row == Currow + 2)
  590.             twrite (1, "\012\012", 2);
  591.         else if (row == Currow - 1)
  592.             twrite (1, "\013", 1);
  593.         else if (row == Currow - 2)
  594.             twrite (1, "\013\013", 2);
  595.         else
  596.         {
  597.         /* because of bug in anp software, abs row pos is not working.
  598.          * the following code was replaced to compensate:
  599.          *
  600.          *          twrite (1, "\033R", 2);
  601.          *          coord = row + ' ';
  602.          *          twrite (1, &coord, 1);
  603.          */
  604.             twrite (1, "\033P", 2);
  605.             coord = row + ' ';
  606.             twrite (1, &coord, 1);
  607.             coord = col + ' ';
  608.             twrite (1, &coord, 1);
  609.         }
  610.     }
  611.     else    /* resort to absolute positioning */
  612.     {
  613.         twrite (1, "\033P", 2);
  614.         coord = row + ' ';
  615.         twrite (1, &coord, 1);
  616.         coord = col + ' ';
  617.         twrite (1, &coord, 1);
  618.     }
  619.  
  620.     Currow = row;
  621.     Curcol = col;
  622. }
  623.  
  624. /* b200coord --- transmit a coordinate for Beehive 200 cursor addressing */
  625.  
  626. static b200coord (coord)
  627. int coord;
  628. {
  629.     char acc;
  630.     int tens, units;
  631.  
  632.     tens = coord / 10;
  633.     units = coord - 10 * tens;
  634.     acc = units + 16 * tens;
  635.  
  636.     twrite (1, & acc, 1);
  637. }
  638.  
  639. /* beepos --- position cursor on Beehive terminal */
  640.  
  641. static beepos (row, col)
  642. int row, col;
  643. {
  644.     if (row == Currow + 1 && col == 0 && Term_type != SBEE)
  645.     {
  646.         twrite (1, "\r\n", 2);        /*  CR LF */
  647.         Curcol = 0;
  648.         Currow++;
  649.     }
  650.     else if (row == 0 && col == 0)        /* home cursor */
  651.     {
  652.         twrite (1, "\033H", 2);
  653.         Currow = Curcol = 0;
  654.     }
  655.     else if (row == Currow && col > Curcol && col <= Curcol + 4)
  656.         while (Curcol != col)
  657.         {
  658.             twrite (1, &Screen_image[Currow][Curcol], 1);
  659.             Curcol++;
  660.         }
  661.     else if (row == Currow && col < Curcol && col >= Curcol - 4)
  662.         while (Curcol != col)
  663.         {
  664.             twrite (1, "\b", 1);
  665.             Curcol--;
  666.         }
  667.     else        /* resort to absolute addressing */
  668.     {
  669.         twrite (1, "\033F", 2);
  670.         if (Term_type == BEE200 || Term_type == SOL)
  671.         {
  672.             b200coord (row);
  673.             b200coord (col);
  674.         }
  675.         else if (Term_type == BEE150)
  676.         {
  677.             char r, c;
  678.  
  679.             r = row + ' ';
  680.             c = col + ' ';
  681.             twrite (1, &r, 1);
  682.             twrite (1, &c, 1);
  683.         }
  684.         else        /* is superbee */
  685.         {
  686.             sbeecoord (col);
  687.             sbeecoord (row);
  688.         }
  689.  
  690.         Currow = row;
  691.         Curcol = col;
  692.     }
  693. }
  694.  
  695. /* cgpos --- position cursor on Chromatics CG */
  696.  
  697. static cgpos (row, col)
  698. int row, col;
  699. {
  700.     char i, j;
  701.  
  702.     if (row == Currow + 1 && col == 0)
  703.     {
  704.         twrite (1, "\r\n", 2);        /* CR LF */
  705.         Curcol = 0;
  706.         Currow++;
  707.     }
  708.     else if (row == 0 && col == 0)        /* home cursor */
  709.     {
  710.         twrite (1, "\034", 1);    /* FS */
  711.         Currow = Curcol = 0;
  712.     }
  713.     else if (row == Currow && col > Curcol && col <= Curcol + 7)
  714.         while (Curcol != col)
  715.         {
  716.             twrite (1, "\035", 1);    /* GS */
  717.             Curcol++;
  718.         }
  719.     else if (row == Currow && col < Curcol && col >= Curcol - 7)
  720.         while (Curcol != col)
  721.         {
  722.             twrite (1, "\b", 1);
  723.             Curcol--;
  724.         }
  725.     else
  726.     {
  727.         /* resort to absolute addressing */
  728.         twrite (1, "\001U", 2);        /* SOH U */
  729.         i = 511 - (10 * row);
  730.         j = 6 * col;
  731.         cgcoord (j);
  732.         cgcoord (i);
  733.         Currow = row;
  734.         Curcol = col;
  735.     }
  736.  
  737. }
  738.  
  739.  
  740. /* cgcoord --- output a decimal coordinate for Chromatics CG */
  741.  
  742. static cgcoord (i)
  743. int i;
  744. {
  745.     int units, tens, hundreds;
  746.     char coords[4];
  747.  
  748.     units = i % 10;
  749.     i /= 10;
  750.     tens = i % 10;
  751.     i /= 10;
  752.     hundreds = i % 10;
  753.  
  754.     coords[0] = hundreds + 16 + ' ';
  755.     coords[1] = tens + 16 + ' ';
  756.     coords[2] = units + 16 + ' ';
  757.     coords[3] = EOS;
  758.     twrite (1, coords, 3);
  759. }
  760.  
  761.  
  762.  
  763. /* gt40pos --- position cursor to (row, col) on DEC GT40 with Waugh software */
  764.  
  765. static gt40pos (row, col)
  766. int row, col;
  767. {
  768.     char coord;
  769.  
  770.     if (row != Currow && col != Curcol)    /* absolute positioning */
  771.     {
  772.         twrite (1, "\033", 1);
  773.         coord = row + ' ';
  774.         twrite (1, &coord, 1);
  775.         coord = col + ' ';
  776.         twrite (1, &coord, 1);
  777.         Currow = row;
  778.         Curcol = col;
  779.     }
  780.     else if (row != Currow)        /* col must = Curcol */
  781.     {                /* vertical positioning */
  782.         twrite (1, "\006", 1);    /* ACK */
  783.         coord = row + ' ';
  784.         twrite (1, &coord, 1);
  785.         Currow = row;
  786.     }
  787.     else if (abs (col - Curcol) < 2)
  788.         uhcm (col);
  789.     else
  790.     {
  791.         twrite (1, "\025", 1);    /* NACK */
  792.         coord = col + ' ';
  793.         twrite (1, &coord, 1);
  794.         Curcol = col;
  795.     }
  796. }
  797.  
  798.  
  799.  
  800. /* h19pos --- position cursor on Heath H19 (DEC VT52 compatible, supposedly) */
  801.  
  802. static h19pos (row, col)
  803. int row, col;
  804. {
  805.     int dist;
  806.     char coord;
  807.  
  808.     dist = col - Curcol;
  809.     if (dist < 0)
  810.         dist = -dist;
  811.     if (row == Currow && dist < 4)  /* 4 chars for abs. position */
  812.     {
  813.         while (Curcol < col)
  814.         {
  815.             twrite (1, &Screen_image[Currow][Curcol], 1);
  816.             Curcol++;
  817.         }
  818.         while (Curcol > col)
  819.         {
  820.             twrite (1, "\b", 1);
  821.             Curcol--;
  822.         }
  823.     }
  824.     else
  825.     {
  826.         twrite (1, "\033Y", 2);
  827.         coord = row + ' ';
  828.         twrite (1, &coord, 1);
  829.         coord = col + ' ';
  830.         twrite (1, &coord, 1);
  831.         Currow = row;
  832.         Curcol = col;
  833.     }
  834. }
  835.  
  836. /* hp21pos --- position cursor on HP 2621 terminal */
  837.  
  838. static hp21pos (row, col)
  839. int row, col;
  840. {
  841.     int units, tens;
  842.  
  843.     if (row == Currow && col == 0)
  844.     {
  845.         twrite (1, "\r\n", 2);        /* CR LF */
  846.         Curcol = 0;
  847.         Currow++;
  848.     }
  849.     else if (row == 0 && col == 0)        /* home cursor */
  850.     {
  851.         twrite (1, "\033H", 2);
  852.         Currow = Curcol = 0;
  853.     }
  854.     else if (row == Currow && col > Curcol && col <= Curcol + 4)
  855.         while (Curcol != col)
  856.         {
  857.             twrite (1, &Screen_image[Currow][Curcol], 1);
  858.             Curcol++;
  859.         }
  860.     else if (row == Currow && col < Curcol && col >= Curcol - 4)
  861.         while (Curcol != col)
  862.         {
  863.             twrite (1, "\b", 1);
  864.             Curcol--;
  865.         }
  866.     else if (2 * abs (Currow - row) + abs (Curcol - col) <= 7)
  867.     {
  868.         while (Currow < row)
  869.         {
  870.             twrite (1, "\033B", 2);
  871.             Currow++;
  872.         }
  873.         while (Currow > row)
  874.         {
  875.             twrite (1, "\033A", 2);
  876.             Currow--;
  877.         }
  878.         while (Curcol > col)
  879.         {
  880.             twrite (1, "\b", 1);
  881.             Curcol--;
  882.         }
  883.         while (Curcol < col)
  884.         {
  885.             twrite (1, & Screen_image[Currow][Curcol], 1);
  886.             Curcol++;
  887.         }
  888.     }
  889.     else
  890.     {
  891.         /* resort to absolute addressing */
  892.         char c;
  893.  
  894.         twrite (1, "\033&a", 3);
  895.         units = row % 10;
  896.         tens = row / 10;
  897.         if (tens != 0)
  898.         {
  899.             c = tens + '0';
  900.             twrite (1, &c, 1);
  901.         }
  902.         c = units + '0';
  903.         twrite (1, &c, 1);
  904.         twrite (1, "y", 1);
  905.         units = col % 10;
  906.         tens = col / 10;
  907.         if (tens != 0)
  908.         {
  909.             c = tens + '0';
  910.             twrite (1, &c, 1);
  911.         }
  912.         c = units + '0';
  913.         twrite (1, &c, 1);
  914.         twrite (1, "C", 1);
  915.         Currow = row;
  916.         Curcol = col;
  917.     }
  918. }
  919.  
  920.  
  921. /* hazpos --- position cursor on Hazeltine 1510 */
  922.  
  923. static hazpos (row, col)
  924. int row, col;
  925. {
  926.     int dist;
  927.     char c;
  928.  
  929.     dist = col - Curcol;
  930.     if (dist < 0)
  931.         dist = -dist;
  932.     if (row == Currow && dist < 4)  /* 4 chars for abs. position */
  933.     {
  934.         while (Curcol < col)
  935.         {
  936.             twrite (1, &Screen_image[Currow][Curcol], 1);
  937.             Curcol++;
  938.         }
  939.         while (Curcol > col)
  940.         {
  941.             twrite (1, "\b", 1);
  942.             Curcol--;
  943.         }
  944.     }
  945.     else
  946.     {
  947.         twrite (1, "\033\021", 2);
  948.         c = col;
  949.         twrite (1, &c, 1);
  950.         c = row;
  951.         twrite (1, &c, 1);
  952.         Currow = row;
  953.         Curcol = col;
  954.     }
  955. }
  956.  
  957.  
  958. /* ibmpos --- position cursor on IBM 3101 terminal */
  959.  
  960. static ibmpos (row, col)
  961. int row, col;
  962. {
  963.     int dist;
  964.     static char abspos[] = "\033\Y\0\0";
  965.  
  966.     dist = col - Curcol;
  967.     if (dist < 0)
  968.         dist = -dist;
  969.     
  970.     if (row == Currow && dist < 4)        /* 4 chars for abs pos */
  971.     {
  972.         while (Curcol < col)
  973.         {
  974.             twrite (1, & Screen_image[Currow][Curcol], 1);
  975.             Curcol++;
  976.         }
  977.         while (Curcol > col)
  978.         {
  979.             twrite (1, "\b", 1);
  980.             Curcol--;
  981.         }
  982.     }
  983.     else
  984.     {
  985.         abspos[2] = row + ' ';
  986.         abspos[3] = col + ' ';
  987.         twrite (1, abspos, 4);
  988.         Currow = row;
  989.         Curcol = col;
  990.     }
  991. }
  992.  
  993.  
  994.  
  995. /* iscpos --- position cursor on ISC 8001 color terminal */
  996.  
  997. static iscpos (row, col)
  998. int row, col;
  999. {
  1000.     char r, c;
  1001.  
  1002.     if (row == 0 && col == 0)
  1003.         twrite (1, "\b", 1);
  1004.     else
  1005.     {
  1006.         twrite (1, "\003", 1);        /* ETX */
  1007.         r = row;
  1008.         c = col;
  1009.         twrite (1, & r, 1);
  1010.         twrite (1, & c, 1);
  1011.     }
  1012.  
  1013.     Currow = row;
  1014.     Curcol = col;
  1015. }
  1016.  
  1017. /* netpos --- position cursor on Netron terminal */
  1018.  
  1019. static netpos (row, col)
  1020. int row, col;
  1021. {
  1022.     static char abspos[] = "\033=\0\0";
  1023.  
  1024.     abspos[2] = (char) row;
  1025.     abspos[3] = (char) col;
  1026.     twrite (1, abspos, 4);
  1027.     Currow = row;
  1028.     Curcol = col;
  1029. }
  1030.  
  1031. /* pepos --- position cursor on Perkin-Elmer 550 & 1100 terminals */
  1032.  
  1033. static pepos (row, col)
  1034. int row, col;
  1035. {
  1036.     char coord;
  1037.  
  1038.     /* get on correct row first */
  1039.     if (Currow == row)
  1040.         ;        /* already on correct row; nothing to do */
  1041.     else if (row == Currow - 1)
  1042.     {
  1043.         twrite (1, "\033A", 2);        /* cursor up */
  1044.         Currow--;
  1045.     }
  1046.     else if (row == Currow + 1)
  1047.     {
  1048.         twrite (1, "\033B", 2);        /* cursor down */
  1049.         Currow++;
  1050.     }
  1051.     else
  1052.     {
  1053.         /* vertical absolute positioning */
  1054.         twrite (1, "\033X", 2);
  1055.         coord = row + ' ';
  1056.         twrite (1, & coord, 1);
  1057.     }
  1058.  
  1059.     /* now perform horizontal motion */
  1060.     if (abs (col - Curcol) > 3)    /* do absolute horizontal position */
  1061.     {
  1062.         twrite (1, "\033Y", 2);
  1063.         coord = col + ' ';
  1064.         twrite (1, &coord, 1);
  1065.         Curcol = col;
  1066.     }
  1067.     else
  1068.         uhcm (col);
  1069. }
  1070.  
  1071. /* sbeecoord --- transmit a coordinate for Superbee terminal */
  1072.  
  1073. static sbeecoord (coord)
  1074. int coord;
  1075. {
  1076.     char r, c;
  1077.  
  1078.     r = (coord / 10) + ' ';
  1079.     c = (coord % 10) + ' ';
  1080.     twrite (1, & r, 1);
  1081.     twrite (1, & c, 1);
  1082. }
  1083.  
  1084. /* trspos --- position cursor on TRS80 Model 1 */
  1085.  
  1086. static trspos (row, col)
  1087. int row, col;
  1088. {
  1089.     while (Currow != row)
  1090.     {
  1091.         if (Currow > row)
  1092.         {
  1093.             twrite (1, "\033", 1);
  1094.             Currow--;
  1095.         }
  1096.         else
  1097.         {
  1098.             twrite (1, "\032", 1);        /* SUB */
  1099.             Currow++;
  1100.         }
  1101.     }
  1102.  
  1103.     if (Curcol != col)
  1104.     {
  1105.         if (col > Curcol)
  1106.             while (col > Curcol)
  1107.             {
  1108.                 twrite (1, "\031", 1);    /* EM */
  1109.                 Curcol++;
  1110.             }
  1111.         else if (col < Curcol / 2)
  1112.         {
  1113.             twrite (1, "\035", 1);    /* GS */
  1114.             Curcol = 0;
  1115.             while (Curcol < col)
  1116.             {
  1117.                 twrite (1, "\031", 1);    /* EM */
  1118.                 Curcol++;
  1119.             }
  1120.         }
  1121.         else
  1122.             while (col < Curcol)
  1123.             {
  1124.                 twrite (1, "\030", 1);    /* CAN */
  1125.                 Curcol--;
  1126.             }
  1127.     }
  1128. }
  1129.  
  1130.  
  1131.  
  1132. /* tvtpos --- position cursor on Allen's TV Typetwriter II */
  1133.  
  1134. static tvtpos (row, col)
  1135. int row, col;
  1136. {
  1137.     register int horirel, horiabs, vertrel, vertabs;
  1138.  
  1139.     horirel = col - Curcol;
  1140.     if (horirel < 0)
  1141.         horirel = -horirel;
  1142.  
  1143.     horiabs = col;
  1144.  
  1145.     if (row <= Currow)
  1146.         vertrel = Currow - row;
  1147.     else
  1148.         vertrel = Nrows - (row - Currow);
  1149.  
  1150.     if (row == 0)
  1151.         vertabs = 0;
  1152.     else
  1153.         vertabs = Nrows - row;
  1154.  
  1155.     if (1 + horiabs + vertabs <= horirel + vertrel)
  1156.     {
  1157.         twrite (1, "\014", 1);
  1158.         Currow = Curcol = 0;
  1159.     }
  1160.  
  1161.     while (Currow != row)
  1162.     {
  1163.         twrite (1, "\013", 1);
  1164.         Currow--;
  1165.         if (Currow < 0)
  1166.             Currow = Nrows - 1;
  1167.     }
  1168.  
  1169.     if (Curcol > col)
  1170.         for (; Curcol != col; Curcol--)
  1171.             twrite (1, "\b", 1);
  1172.     else
  1173.         for (; Curcol != col; Curcol++)
  1174.             twrite (1, "\t", 1);
  1175. }
  1176.  
  1177.  
  1178.  
  1179. /* regentpos --- position cursor on ADDS Regent 100 */
  1180.  
  1181. static regentpos (row, col)
  1182. int row, col;
  1183. {
  1184.     int dist;
  1185.     char coord;
  1186.  
  1187.     dist = col - Curcol;
  1188.     if (dist < 0)
  1189.         dist = -dist;
  1190.     
  1191.     if (dist > 4 || Currow != row)
  1192.     {
  1193.         twrite (1, "\033Y", 2);
  1194.         coord = ' ' + row;
  1195.         twrite (1, &coord, 1);
  1196.         coord = ' ' + col;
  1197.         twrite (1, &coord, 1);
  1198.         Currow = row;
  1199.         Curcol = col;
  1200.     }
  1201.     else
  1202.     {
  1203.         while (row < Currow)
  1204.         {
  1205.             twrite (1, "\032", 1);    /* SUB, cursor up */
  1206.             Currow--;
  1207.         }
  1208.         while (row > Currow)
  1209.         {
  1210.             twrite (1, "\n", 1);
  1211.             Currow++;
  1212.             Curcol = 1;
  1213.         }
  1214.         if (col > Curcol)
  1215.             while (col != Curcol)
  1216.             {
  1217.                 twrite (1, &Screen_image[Currow][Curcol], 1);
  1218.                 Curcol++;
  1219.             }
  1220.         else if ((Curcol - col) * 2 >= Ncols)
  1221.             while (col != Curcol)
  1222.             {
  1223.                 twrite (1, "\006", 1);    /* ACK, cursor right */
  1224.                 if (Curcol == Ncols)
  1225.                     Curcol = 1;
  1226.                 else
  1227.                     Curcol++;
  1228.             }
  1229.         else
  1230.             while (col != Curcol)
  1231.             {
  1232.                 twrite (1, "\b", 1);
  1233.                 Curcol--;
  1234.             }
  1235.     }
  1236. }
  1237.  
  1238.  
  1239.  
  1240. /* vipos --- position cursor on Visual 200 & 50 */
  1241.  
  1242. static vipos (row, col)
  1243. register int row, col;
  1244. {
  1245.     register int dist;
  1246.     register char coord;
  1247.  
  1248.     if (row == Currow + 1 && col < 3)
  1249.     {
  1250.         twrite (1, "\015\012", 2);
  1251.         Currow++;
  1252.         Curcol = 0;
  1253.     }
  1254.     dist = col - Curcol;
  1255.     if (Term_type == VI200 && row == Currow && col < 72 && dist > 2
  1256.         && dist < 8 && (col + 1) % 8 < 2)
  1257.     {
  1258.         twrite (1, "\t", 1);
  1259.         Curcol = ((Curcol + 7) / 8) * 8;
  1260.         dist = col - Curcol;
  1261.     }
  1262.     if (dist < 0)
  1263.         dist = -dist;
  1264.     if (row == Currow && dist < 4)  /* 4 chars for abs. position */
  1265.     {
  1266.         while (Curcol < col)
  1267.         {
  1268.             twrite (1, &Screen_image[Currow][Curcol], 1);
  1269.             Curcol++;
  1270.         }
  1271.         while (Curcol > col)
  1272.         {
  1273.             twrite (1, "\b", 1);
  1274.             Curcol--;
  1275.         }
  1276.     }
  1277.     else
  1278.     {
  1279.         twrite (1, "\033Y", 2);
  1280.         coord = row + ' ';
  1281.         twrite (1, &coord, 1);
  1282.         coord = col + ' ';
  1283.         twrite (1, &coord, 1);
  1284.         Currow = row;
  1285.         Curcol = col;
  1286.     }
  1287. }
  1288.  
  1289.  
  1290.  
  1291. /* vcpos --- position cursor Volker-Craig 4404 (ADM3A mode) */
  1292.  
  1293. static vcpos (row, col)
  1294. int row, col;
  1295. {
  1296.     int dist;
  1297.     char coord;
  1298.  
  1299.     dist = col - Curcol;
  1300.     if (dist < 0)
  1301.         dist = -dist;
  1302.     if (row == Currow && dist < 4)  /* 4 chars for abs. position */
  1303.     {
  1304.         while (Curcol < col)
  1305.         {
  1306.             twrite (1, &Screen_image[Currow][Curcol], 1);
  1307.             Curcol++;
  1308.         }
  1309.         while (Curcol > col)
  1310.         {
  1311.             twrite (1, "\b", 1);
  1312.             Curcol--;
  1313.         }
  1314.     }
  1315.     else
  1316.     {
  1317.         twrite (1, "\033=", 2);
  1318.         coord = row + ' ';
  1319.         twrite (1, &coord, 1);
  1320.         coord = col + ' ';
  1321.         twrite (1, &coord, 1);
  1322.         Currow = row;
  1323.         Curcol = col;
  1324.     }
  1325. }
  1326.  
  1327.  
  1328. /* espritpos --- position cursor on Hazeltine Esprit */
  1329.  
  1330. static espritpos (row, col)
  1331. int row, col;
  1332. {
  1333.     int dist;
  1334.     char c;
  1335.  
  1336.     dist = col - Curcol;
  1337.     if (dist < 0)
  1338.         dist = -dist;
  1339.     if (row == Currow && dist < 4)  /* 4 chars for abs. position */
  1340.     {
  1341.         while (Curcol < col)
  1342.         {
  1343.             twrite (1, &Screen_image[Currow][Curcol], 1);
  1344.             Curcol++;
  1345.         }
  1346.         while (Curcol > col)
  1347.         {
  1348.             twrite (1, "\b", 1);
  1349.             Curcol--;
  1350.         }
  1351.     }
  1352.     else
  1353.     {
  1354.         twrite (1, "\033\021", 2);
  1355.         c = col >= 32 ? col : col + '`';
  1356.         twrite (1, &c, 1);
  1357.         c = row >= 32 ? row : row + '`';
  1358.         twrite (1, &c, 1);
  1359.         Currow = row;
  1360.         Curcol = col;
  1361.     }
  1362. }
  1363.  
  1364. /* uhcm --- universal horizontal cursor motion */
  1365.  
  1366. static uhcm (col)
  1367. int col;
  1368. {
  1369.     while (Curcol < col)
  1370.     {
  1371.         twrite (1, &Screen_image[Currow][Curcol], 1);
  1372.         Curcol++;
  1373.     }
  1374.  
  1375.     while (Curcol > col)
  1376.     {
  1377.         twrite (1, "\b", 1);
  1378.         Curcol--;
  1379.     }
  1380. }
  1381.  
  1382.  
  1383. /* senddelay --- send NULs to delay n milliseconds */
  1384.  
  1385. senddelay (n)
  1386. int n;
  1387. {
  1388.     register int q;
  1389.  
  1390.     q = (long) n * Tspeed / 1000l;
  1391.     while (q > 0)
  1392.     {
  1393.         twrite (1, "\0\0\0\0\0\0\0\0\0\0", q > 10 ? 10 : q);
  1394.         q -= 10;
  1395.     }
  1396. }
  1397.  
  1398.  
  1399. /* decode_mnemonic --- decode a terminal type mnemonic */
  1400.  
  1401. static int decode_mnemonic (str)
  1402. char str[];
  1403. {
  1404.     int i;
  1405.     int strbsr ();
  1406.  
  1407.     static struct {
  1408.         char *s;
  1409.         int t;
  1410.     } stab[] = {
  1411.         "950",          TVI950,
  1412.         "adm31",        ADM31,  
  1413.         "adm3a",        ADM3A,  
  1414.         "anp",          ANP,    
  1415.         "b150",         BEE150,   
  1416.         "b200",         BEE200,   
  1417.         "cg",           CG,     
  1418.         "consul",       ADDS980,
  1419.         "esprit",       ESPRIT,
  1420.         "fox",          FOX,    
  1421.         "gt40",         GT40,   
  1422.         "h19",          H19,    
  1423.         "haz",          HAZ1510,
  1424.         "hp21",         HP21,   
  1425.         "hz1510",       HAZ1510,
  1426.         "ibm",          IBM,    
  1427.         "isc",          ISC8001,
  1428.         "netron",       NETRON, 
  1429.         "regent",       ADDS100,
  1430.         "regent40",     ADDS100,    /* kludge */
  1431.         "sbee",         SBEE,   
  1432.         "sol",          SOL,    
  1433.         "trs80",        TRS80,  
  1434.         "ts1",          TS1,
  1435.         "tvt",          TVT,    
  1436.         "vc4404",       VC4404,
  1437.         "vi200",        VI200,
  1438.         "vi300",    VI300,
  1439.         "vi50",         VI50,
  1440.     };
  1441.  
  1442.     i = strbsr ((char *)stab, sizeof (stab), sizeof (stab[0]), str);
  1443.     if (i == EOF)
  1444.         return (ERR);
  1445.     else
  1446.         return (stab[i].t);
  1447. }
  1448. #endif
  1449.  
  1450. /* terminal handling functions used throughout the editor */
  1451.  
  1452. /* send --- send a printable character, predict cursor position */
  1453.  
  1454. send (chr)
  1455. char chr;
  1456. {
  1457.     if (Currow == Nrows - 1 && Curcol == Ncols - 1)
  1458.         return;         /* anything in corner causes scroll... */
  1459.  
  1460. #ifndef HARD_TERMS
  1461.     outc (chr);
  1462. #else
  1463.     twrite (1, &chr, 1);
  1464. #endif
  1465.  
  1466.     if (Curcol == Ncols - 1)
  1467.     {
  1468. #ifndef HARD_TERMS
  1469.         if (AM)        /* terminal wraps when hits last column */
  1470. #else
  1471.         if (Term_type != TVT && Term_type != NETRON
  1472.             && Term_type != ESPRIT && Term_type != VI300)
  1473. #endif
  1474.         {
  1475.             Curcol = 0;
  1476.             Currow++;
  1477.         }
  1478.     }
  1479.     else        /* cursor not at extreme right */
  1480.         Curcol++;
  1481. }
  1482.  
  1483. /* clrscreen --- clear entire screen */
  1484.  
  1485. clrscreen ()
  1486. {
  1487.     Curcol = Currow = 0;
  1488.     /* clearing screen homes cursor to upper left corner */
  1489.     /* on all terminals */
  1490.  
  1491. #ifndef HARD_TERMS
  1492.     tputs (CL, 1, outc);
  1493. #else
  1494.     switch (Term_type) {
  1495.     case ADDS980:
  1496.     case ADDS100:
  1497.     case GT40:
  1498.     case CG:
  1499.     case ISC8001:
  1500.     case ANP:
  1501.     case NETRON:
  1502.         twrite (1, "\014", 1);
  1503.         break;
  1504.     case FOX:
  1505.         twrite (1, "\033K", 2);        /* clear display and all tabs */
  1506.         break;
  1507.     case TVT:
  1508.         twrite (1, "\014\017", 2);    /* home, erase to end of screen */
  1509.         break;
  1510.     case BEE150:
  1511.     case BEE200:
  1512.     case SBEE:
  1513.     case SOL:
  1514.     case H19:
  1515.         twrite (1, "\033E", 2);
  1516.         break;
  1517.     case HAZ1510:
  1518.     case ESPRIT:
  1519.         twrite (1, "\033\034", 2);
  1520.         break;
  1521.     case ADM3A:
  1522.     case VC4404:
  1523.     case TVI950:
  1524.         twrite (1, "\032", 1);
  1525.         break;
  1526.     case TS1:
  1527.         twrite (1, "\033*", 2);
  1528.         break;
  1529.     case ADM31:
  1530.         twrite (1, "\033+", 2);
  1531.         break;
  1532.     case IBM:
  1533.         twrite (1, "\033L", 2);
  1534.         break;
  1535.     case HP21:
  1536.         twrite (1, "\033H\033J", 4);    /* home cursor, erase to end of screen */
  1537.         break;
  1538.     case TRS80:
  1539.         twrite (1, "\034\037", 2);
  1540.         break;
  1541.     case VI200:
  1542.         twrite (1, "\033v", 2);
  1543.         break;
  1544.     case VI300:
  1545.         twrite (1, "\033[H\033[J", 6);
  1546.         /* home cursor, clear screen */
  1547.         break;
  1548.     case VI50:
  1549.         twrite (1, "\033v", 2);
  1550.         senddelay (30);
  1551.         break;
  1552.     }
  1553.  
  1554.     senddelay (20);
  1555. #endif
  1556. }
  1557.  
  1558.  
  1559. /* position_cursor --- position terminal's cursor to (row, col) */
  1560.  
  1561. position_cursor (row, col)
  1562. int row, col;
  1563. {
  1564.     if (row < Nrows && row >= 0        /* within vertical range? */
  1565.         && col < Ncols && col >= 0        /* within horizontal range? */
  1566.         && (row != Currow || col != Curcol))/* not already there? */
  1567. #ifndef HARD_TERMS
  1568.     {
  1569.         if (row == Currow && abs (Curcol - col) <= 4)
  1570.         {
  1571.             /* short motion in current line */
  1572.             if (Curcol < col)
  1573.                 for (; Curcol != col; Curcol++)
  1574.                     twrite (1, &Screen_image[Currow][Curcol], 1);
  1575.             else
  1576.                 for (; Curcol != col; Curcol--)
  1577.                     twrite (1, "\b", 1);
  1578.         }
  1579.         else
  1580.         {
  1581. #if defined (USG) && defined(S5R2)
  1582.             tputs (tparm (cursor_address, row, col), 1, outc);
  1583. #else
  1584.             tputs (tgoto (CM, col, row), 1, outc);
  1585. #endif
  1586.             Currow = row;
  1587.             Curcol = col;
  1588.         }
  1589.     }
  1590. #else
  1591.         switch (Term_type) {
  1592.         case ADDS980:
  1593.             addspos (row, col);
  1594.             break;
  1595.         case ADDS100:
  1596.             regentpos (row, col);
  1597.             break;
  1598.         case HP21:
  1599.             hp21pos (row, col);
  1600.             break;
  1601.         case FOX:
  1602.             pepos (row, col);
  1603.             break;
  1604.         case TVT:
  1605.             tvtpos (row, col);
  1606.             break;
  1607.         case GT40:
  1608.             gt40pos (row, col);
  1609.             break;
  1610.         case BEE150:
  1611.         case BEE200:
  1612.         case SBEE:
  1613.         case SOL:
  1614.             beepos (row, col);
  1615.             break;
  1616.         case VC4404:
  1617.             vcpos (row, col);
  1618.             break;
  1619.         case HAZ1510:
  1620.             hazpos (row, col);
  1621.             break;
  1622.         case ESPRIT:
  1623.             espritpos (row, col);
  1624.             break;
  1625.         case CG:
  1626.             cgpos (row, col);
  1627.             break;
  1628.         case ISC8001:
  1629.             iscpos (row, col);
  1630.             break;
  1631.         case ADM3A:
  1632.         case ADM31:
  1633.         case TS1:
  1634.         case TVI950:
  1635.             admpos (row, col);
  1636.             break;
  1637.         case IBM:
  1638.             ibmpos (row, col);
  1639.             break;
  1640.         case ANP:
  1641.             anppos (row, col);
  1642.             break;
  1643.         case NETRON:
  1644.             netpos (row, col);
  1645.             break;
  1646.         case H19:
  1647.             h19pos (row, col);
  1648.             break;
  1649.         case TRS80:
  1650.             trspos (row, col);
  1651.             break;
  1652.         case VI200:  
  1653.         case VI50:
  1654.             vipos (row, col);
  1655.             break;
  1656.         case VI300:
  1657.             ansipos (row, col);
  1658.             break;
  1659.         }
  1660. #endif
  1661. }
  1662.  
  1663.  
  1664. /* setscreen --- initialize screen and associated descriptive variables */
  1665.  
  1666. setscreen ()
  1667. {
  1668.     register int row, col;
  1669.  
  1670. #ifndef HARD_TERMS
  1671.     t_init ();    /* put out the 'ti' and 'vs' capabilities */
  1672. #endif
  1673.     clrscreen ();    /* clear physical screen, set cursor position */
  1674.  
  1675.     Toprow = 0;
  1676.     Botrow = Nrows - 3; /* 1 for 0-origin, 1 for status, 1 for cmd */
  1677.     Cmdrow = Botrow + 1;
  1678.     Topln = 1;
  1679.     Sclen = -1;         /* make sure we assume nothing on the screen */
  1680.  
  1681.     for (row = 0; row < Nrows; row++)    /* now clear virtual screen */
  1682.         for (col = 0; col < Ncols; col++)
  1683.             Screen_image[row][col] = ' ';
  1684.  
  1685.     for (col = 0; col < Ncols; col++)    /* and clear out status line */
  1686.         Msgalloc[col] = NOMSG;
  1687.  
  1688.     Insert_mode = NO;
  1689. }
  1690.  
  1691.  
  1692. /* inslines --- insert 'n' lines on the screen at 'row' */
  1693.  
  1694. inslines (row, n)
  1695. int row, n;
  1696. {
  1697.     register int i;
  1698.     int delay;
  1699.  
  1700.     position_cursor (row, 0);
  1701. #ifdef HARD_TERMS
  1702.     if (Term_type == VI300)
  1703.     {
  1704.         char pseq[10];
  1705.         register int pp = 0;
  1706.         pseq[pp++] = '\033';
  1707.         pseq[pp++] = '[';
  1708.         if (n >= 10)
  1709.             pseq[pp++] = '0' + n / 10;
  1710.         pseq[pp++] = '0' + n % 10;
  1711.         pseq[pp++] = 'L';
  1712.         twrite (1, pseq, pp);
  1713.         delay = 0;
  1714.     }
  1715.     else
  1716. #endif
  1717.         for (i = 0; i < n; i++)
  1718.         {
  1719. #ifndef HARD_TERMS
  1720.             tputs (AL, n, outc);
  1721.             tflush ();
  1722. #else
  1723.             switch (Term_type) {
  1724.             case VI200:
  1725.                 twrite (1, "\033L", 2);
  1726.                 delay = 0;
  1727.                 break;
  1728.             case VI50:
  1729.             case H19:
  1730.                 twrite (1, "\033L", 2);
  1731.                 delay = 32;
  1732.                 break;
  1733.             case ESPRIT:
  1734.                 twrite (1, "\033\032", 2);
  1735.                 delay = 32;
  1736.                 break;
  1737.             case TS1:
  1738.             case TVI950:
  1739.                 twrite (1, "\033E", 2);
  1740.                 delay = 0;
  1741.                 break;
  1742.             case ADDS100:
  1743.                 twrite (1, "\033M", 2);
  1744.                 delay = 96;
  1745.                 break;
  1746.             default:
  1747.                 error (YES, "in inslines: shouldn't happen");
  1748.             }
  1749.  
  1750.             if (delay != 0)
  1751.                 senddelay (delay);
  1752. #endif
  1753.         }
  1754.  
  1755.     for (i = Nrows - 1; i - n >= Currow; i--)
  1756.         move_ (Screen_image[i - n], Screen_image[i], Ncols);
  1757.  
  1758.     for (; i >= Currow; i--)
  1759.         move_ (Blanks, Screen_image[i], Ncols);
  1760. }
  1761.  
  1762.  
  1763. /* dellines --- delete 'n' lines beginning at 'row' */
  1764.  
  1765. dellines (row, n)
  1766. int row, n;
  1767. {
  1768.     register int i;
  1769.     int delay;
  1770.  
  1771.     position_cursor (row, 0);
  1772. #ifdef HARD_TERMS
  1773.     if (Term_type == VI300)
  1774.     {
  1775.         char pseq[10];
  1776.         register int pp = 0;
  1777.         pseq[pp++] = '\033';
  1778.         pseq[pp++] = '[';
  1779.         if (n >= 10)
  1780.             pseq[pp++] = '0' + n / 10;
  1781.         pseq[pp++] = '0' + n % 10;
  1782.         pseq[pp++] = 'M';
  1783.         twrite (1, pseq, pp);
  1784.         delay = 0;
  1785.     }
  1786.     else
  1787. #endif
  1788.         for (i = 0; i < n; i++)
  1789.         {
  1790. #ifndef HARD_TERMS
  1791.             tputs (DL, n, outc);
  1792.             tflush ();
  1793. #else
  1794.             switch (Term_type) {
  1795.             case VI200:
  1796.                 twrite (1, "\033M", 2);
  1797.                 delay = 0;
  1798.                 break;
  1799.             case VI50:
  1800.                 twrite (1, "\033M", 2);
  1801.                 delay = 32;
  1802.                 break;
  1803.             case H19:
  1804.                 twrite (1, "\033M", 2);
  1805.                 delay = 32;
  1806.                 break;
  1807.             case TS1:
  1808.             case TVI950:
  1809.                 twrite (1, "\033R", 2);
  1810.                 delay = 0;
  1811.                 break;
  1812.             case ESPRIT:
  1813.                 twrite (1, "\033\023", 2);
  1814.                 delay = 32;
  1815.                 break;
  1816.             case ADDS100:
  1817.                 twrite (1, "\033l", 2);
  1818.                 delay = 96;
  1819.                 break;
  1820.             default:
  1821.                 error (YES, "in dellines: shouldn't happen");
  1822.             }
  1823.  
  1824.             if (delay != 0)
  1825.                 senddelay (delay);
  1826. #endif
  1827.         }
  1828.  
  1829.     for (i = Currow; i + n < Nrows; i++)
  1830.         move_ (Screen_image[i + n], Screen_image[i], Ncols);
  1831.  
  1832.     for (; i < Nrows; i++)
  1833.         move_ (Blanks, Screen_image[i], Ncols);
  1834. }
  1835.  
  1836.  
  1837. /* hwinsdel --- return 1 if the terminal has hardware insert/delete */
  1838.  
  1839. int hwinsdel ()
  1840. {
  1841.     if (No_hardware == YES)
  1842.         return (NO);
  1843.  
  1844. #ifndef HARD_TERMS
  1845.     return (AL != NULL && DL != NULL);
  1846. #else
  1847.     switch (Term_type) {
  1848.     case VI300:
  1849.     case VI200:
  1850.     case VI50:
  1851.     case ESPRIT:
  1852.     case H19:
  1853.     case TS1:
  1854.     case TVI950:
  1855.     case ADDS100:
  1856.         return 1;
  1857.     }
  1858.     return 0;
  1859. #endif
  1860. }
  1861.  
  1862.  
  1863. /* clear_to_eol --- clear screen to end-of-line */
  1864.  
  1865. clear_to_eol (row, col)
  1866. int row, col;
  1867. {
  1868.     register int c, flag; 
  1869.     register int hardware = NO;
  1870.  
  1871. #ifdef HARD_TERMS
  1872.     switch (Term_type) {
  1873.     case BEE200:
  1874.     case BEE150:
  1875.     case FOX:
  1876.     case SBEE:
  1877.     case ADDS100:
  1878.     case HP21:
  1879.     case IBM:
  1880.     case ANP:
  1881.     case NETRON:
  1882.     case H19:
  1883.     case TS1:
  1884.     case TRS80:
  1885.     case ADM31:
  1886.     case VI200:
  1887.     case VI300:
  1888.     case VI50:
  1889.     case VC4404:
  1890.     case ESPRIT:
  1891.     case TVI950:
  1892.         hardware = YES;
  1893.         break;
  1894.     default:
  1895.         hardware = (Term_type == ADDS980 && row < Nrows - 1)
  1896.                 || (Term_type == TVT && row > 0);
  1897.     }
  1898. #else
  1899.     hardware = (CE != NULL);
  1900. #endif
  1901.  
  1902.     flag = NO;
  1903.  
  1904.     for (c = col; c < Ncols; c++)
  1905.         if (Screen_image[row][c] != ' ')
  1906.         {
  1907.             Screen_image[row][c] = ' ';
  1908.             if (hardware)
  1909.                 flag = YES;
  1910.             else
  1911.             {
  1912.                 position_cursor (row, c);
  1913.                 send (' ');
  1914.             }
  1915.         }
  1916.  
  1917.     if (flag == YES)
  1918.     {
  1919.         position_cursor (row, col);
  1920. #ifndef HARD_TERMS
  1921.         tputs (CE, 1, outc);
  1922. #else
  1923.         switch (Term_type) {
  1924.         case BEE200: 
  1925.         case BEE150:
  1926.         case SBEE:
  1927.         case ADDS100:
  1928.         case HP21:
  1929.         case H19:
  1930.         case VC4404:
  1931.         case TS1:
  1932.         case TVI950:
  1933.         case VI50:
  1934.             twrite (1, "\033K", 2);
  1935.             break;
  1936.         case FOX:
  1937.         case IBM:
  1938.             twrite (1, "\033I", 2);
  1939.             break;
  1940.         case ADDS980:
  1941.             twrite (1, "\n", 1);
  1942.             Currow++;
  1943.             Curcol = 0;
  1944.             break;
  1945.         case ANP:
  1946.             twrite (1, "\033L", 2);
  1947.             break;
  1948.         case NETRON:
  1949.             twrite (1, "\005", 1);
  1950.             break;
  1951.         case TRS80:
  1952.             twrite (1, "\036", 1);
  1953.             break;
  1954.         case ADM31:
  1955.             twrite (1, "\033T", 2);
  1956.             break;
  1957.         case VI200:
  1958.             twrite (1, "\033x", 2);
  1959.             break;
  1960.         case VI300:
  1961.             twrite (1, "\033[K", 3);
  1962.             break;
  1963.         case ESPRIT:
  1964.             twrite (1, "\033\017", 2);
  1965.             break;
  1966.         case TVT:
  1967.             twrite (1, "\013\012", 2);
  1968.             break;
  1969.         } /* end switch */
  1970. #endif
  1971.     } /* end if (flag == YES) */
  1972. }
  1973.  
  1974. /* set_term -- initialize terminal parameters and actual capabilities */
  1975.  
  1976. set_term (type)
  1977. char *type; 
  1978. {
  1979.     if (type == NULL)
  1980.         error (NO, "se: terminal type not available");
  1981.  
  1982.     if (type[0] == EOS)
  1983.         error (NO, "in set_term: can't happen.");
  1984.  
  1985.     Ncols = Nrows = -1;
  1986.  
  1987. #ifdef HARD_TERMS
  1988.     if ((Term_type = decode_mnemonic (type)) == ERR)
  1989.         error (NO, "se: could not find terminal in internal database");
  1990.  
  1991.     switch (Term_type) {
  1992.     case ADDS980: 
  1993.     case FOX: 
  1994.     case HAZ1510: 
  1995.     case ADDS100:
  1996.     case BEE150: 
  1997.     case ADM3A: 
  1998.     case IBM: 
  1999.     case HP21: 
  2000.     case H19:
  2001.     case ADM31: 
  2002.     case VI200: 
  2003.     case VC4404: 
  2004.     case ESPRIT: 
  2005.     case TS1:
  2006.     case TVI950: 
  2007.     case VI50: 
  2008.     case VI300:
  2009.         Nrows = 24;
  2010.         Ncols = 80;
  2011.         break;
  2012.     case ANP:
  2013.         Nrows = 24;
  2014.         Ncols = 96;
  2015.         break;
  2016.     case SOL: 
  2017.     case NETRON: 
  2018.     case TRS80:
  2019.         Nrows = 16;
  2020.         Ncols = 64;
  2021.         break;
  2022.     case TVT:
  2023.         Nrows = 16;
  2024.         Ncols = 63;
  2025.         break;
  2026.     case GT40:
  2027.         Nrows = 32;
  2028.         Ncols = 73;
  2029.         break;
  2030.     case CG:
  2031.         Nrows = 51;
  2032.         Ncols = 85;
  2033.         break;
  2034.     case ISC8001:
  2035.         Nrows = 48;
  2036.         Ncols = 80;
  2037.         break;
  2038.     case BEE200: 
  2039.     case SBEE:
  2040.         Nrows = 25;
  2041.         Ncols = 80;
  2042.         break;
  2043.     }
  2044. #else
  2045.     if (setcaps (type) == ERR)
  2046.         error (NO, "se: could not find terminal in system database");
  2047.  
  2048.  
  2049.     PC = pcstr ? pcstr[0] : EOS;
  2050.  
  2051.     if (*tgoto (CM, 0, 0) == 'O')    /* OOPS returned.. */
  2052.         error (NO, "se: terminal does not have cursor motion.");
  2053.  
  2054.     /*
  2055.      * first, get it from the library. then check the
  2056.      * windowing system, if there is one.
  2057.      */
  2058.     winsize ();
  2059. #endif
  2060.  
  2061.     if (Nrows == -1)
  2062.         error (NO, "se: could not determine number of rows");
  2063.  
  2064.     if (Ncols == -1)
  2065.         error (NO, "se: could not determine number of columns");
  2066.  
  2067.     return OK;
  2068. }
  2069.