home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / jove / part07 / screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-03  |  17.1 KB  |  846 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  3.  * provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is *
  5.  * included in all the files.                                           *
  6.  ************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "io.h"
  10. #include "ctype.h"
  11. #include "termcap.h"
  12.  
  13. extern int    BufSize;
  14.  
  15. int    OkayAbort,
  16.     tabstop = 8;
  17.  
  18. int    (*TTins_line)(),
  19.     (*TTdel_line)();
  20.  
  21. struct scrimage
  22.     *DesiredScreen = 0,
  23.     *PhysScreen = 0;
  24.  
  25. struct screenline    *Screen = 0,    /* the screen (a bunch of screenline) */
  26.             *Savelines = 0,    /* another bunch (LI of them) */
  27.             *Curline = 0;    /* current line */
  28. char    *cursor,            /* offset into current Line */
  29.     *cursend;
  30.  
  31. int    CapCol,
  32.     CapLine,
  33.  
  34.     i_line,
  35.     i_col;
  36.  
  37. make_scr()
  38. {
  39.     register int    i;
  40.     register struct screenline    *ns;
  41.     register char    *nsp;
  42.  
  43. #ifdef RESHAPING
  44.     /* In case we are RESHAPING the window! */
  45.     if (DesiredScreen)
  46.         free((char *) DesiredScreen);
  47.     if (PhysScreen)
  48.         free((char *) PhysScreen);
  49.     if (Savelines)
  50.         free((char *) Savelines);
  51.     if (Screen) {
  52.         free(Screen->s_line);    /* free all the screen data */
  53.         free((char *) Screen);
  54.     }
  55. #endif RESHAPING
  56.  
  57.     DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
  58.     PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
  59.  
  60.     Savelines = (struct screenline *)
  61.             malloc((unsigned) LI * sizeof(struct screenline));
  62.     ns = Screen = (struct screenline *)
  63.             malloc((unsigned) LI * sizeof(struct screenline));
  64.  
  65.     nsp = (char *) malloc((unsigned)CO * LI);
  66.     if (nsp == 0) {
  67.         printf("\n\rCannot malloc screen!\n");
  68.         finish(1);
  69.     }
  70.  
  71.     for (i = 0; i < LI; i++) {
  72.         ns->s_line = nsp;
  73.         nsp += CO;
  74.         ns->s_length = nsp - 1;        /* End of Line */
  75.         ns++;
  76.     }
  77.     cl_scr(0);
  78. }
  79.  
  80. clrline(cp1, cp2)
  81. register char    *cp1,
  82.         *cp2;
  83. {
  84.     while (cp1 <= cp2)
  85.         *cp1++ = ' ';
  86. }
  87.  
  88. #define sputc(c)    ((*cursor != (char) (c)) ? dosputc(c) : (cursor++, i_col++))
  89. #define soutputc(c)    if (--n <= 0) break; else sputc(c)
  90.  
  91. cl_eol()
  92. {
  93.     if (cursor > cursend)
  94.         return;
  95.  
  96.     if (cursor < Curline->s_length) {
  97.         if (CE) {
  98.             Placur(i_line, i_col);
  99.             putpad(CE, 1);
  100.             clrline(cursor, Curline->s_length);
  101.         } else {
  102.         /* Ugh.  The slow way for dumb terminals. */
  103.             register char *savecp = cursor;
  104.  
  105.             while (cursor <= Curline->s_length)
  106.                 sputc(' ');
  107.             cursor = savecp;
  108.         }
  109.         Curline->s_length = cursor;
  110.     }
  111. }
  112.  
  113. cl_scr(doit)
  114. {
  115.     register int    i;
  116.     register struct screenline    *sp = Screen;
  117.  
  118.     for (i = 0; i < LI; i++, sp++) {
  119.         clrline(sp->s_line, sp->s_length);
  120.         sp->s_length = sp->s_line;
  121.         PhysScreen[i].s_id = 0;
  122.     }
  123.     if (doit) {
  124.         putpad(CL, LI);
  125.         CapCol = CapLine = 0;
  126.         UpdMesg++;
  127.     }
  128. }
  129.  
  130. #ifdef ID_CHAR
  131. extern int    IN_INSmode;
  132. #endif
  133.  
  134. /* Output one character (if necessary) at the current position */
  135.  
  136. dosputc(c)
  137. register char    c;
  138. {
  139.     if (*cursor != c) {
  140. #ifdef ID_CHAR
  141.         if (IN_INSmode)
  142.             INSmode(0);
  143. #endif
  144.         if (i_line != CapLine || i_col != CapCol)
  145.             Placur(i_line, i_col);
  146.         if (UL && (c & 0177) == '_' && (*cursor & 0177) != ' ')
  147.             putstr(" \b");        /* Erase so '_' looks right. */
  148.         *cursor++ = c;
  149.         putchar(c & 0177);
  150.         CapCol++;
  151.         i_col++;
  152.     } else {
  153.         cursor++;
  154.         i_col++;
  155.     }
  156. }
  157.  
  158. /* Write `line' at the current position of `cursor'.  Stop when we
  159.    reach the end of the screen.  Aborts if there is a character
  160.    waiting.  */
  161.  
  162. swrite(line, inversep, abortable)
  163. register char    *line;
  164. register int    abortable;
  165. {
  166.     register int    c;
  167.     int    col = i_col,
  168.         aborted = 0;
  169.     register int    n = cursend - cursor;
  170.     int    or_byte = inversep ? 0200 : 0,
  171.         thebyte;
  172.  
  173.     if (n <= 0)
  174.         return 1;
  175.  
  176.     OkayAbort = 0;
  177.     while (c = *line++) {
  178.         if (abortable && OkayAbort) {
  179.             OkayAbort = NO;
  180.             if (InputPending = charp()) {
  181.                 aborted = 1;
  182.                 break;
  183.             }
  184.         }
  185.         if (c == '\t') {
  186.             int    nchars;
  187.  
  188.             nchars = (tabstop - (col % tabstop));
  189.             col += nchars;
  190.  
  191.             thebyte = (' ' | or_byte);
  192.             while (nchars--)
  193.                 soutputc(thebyte);
  194.             if (n <= 0)
  195.                 break;
  196.         } else if (isctrl(c)) {
  197.             thebyte = ('^' | or_byte);
  198.             soutputc(thebyte);
  199.             thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
  200.             soutputc(thebyte);
  201.             col += 2;
  202.         } else {
  203.             thebyte = (c | or_byte);
  204.             soutputc(thebyte);
  205.             col++;
  206.         }
  207.     }
  208.     if (n <= 0) {
  209.         if ((*line == '\0') && (c != '\t') && !isctrl(c))
  210.             sputc(c|or_byte);
  211.         else
  212.             sputc('!'|or_byte);
  213.     }
  214.     if (cursor > Curline->s_length)
  215.         Curline->s_length = cursor;
  216.     return !aborted;
  217. }
  218.  
  219. /* This is for writing a buffer line to the screen.  This is to
  220.    minimize the amount of copying from one buffer to another buffer.
  221.    This gets the info directly from the disk buffers. */
  222.  
  223. BufSwrite(linenum)
  224. {
  225.     char    *bp;
  226.     register int    n = cursend - cursor,
  227.             col = 0,
  228.             c;
  229.     int    StartCol = DesiredScreen[linenum].s_offset,
  230.         visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
  231.         aborted = 0;
  232.  
  233.     bp = lcontents(DesiredScreen[linenum].s_lp);
  234.     if (*bp) for (;;) {
  235.         if (col >= StartCol) {
  236.             DesiredScreen[linenum].s_offset = col;
  237.             break;
  238.         }
  239.  
  240.         c = *bp++ & 0177;
  241.         if (c == '\t')
  242.             col += (tabstop - (col % tabstop));
  243.         else if (isctrl(c))
  244.             col += 2;
  245.         else
  246.             col++;
  247.     }
  248.  
  249.     OkayAbort = 0;
  250.     while (c = (*bp++ & 0177)) {
  251.         if (OkayAbort) {
  252.             OkayAbort = NO;
  253.             if (InputPending = charp()) {
  254.                 aborted = 1;
  255.                 break;
  256.             }
  257.         }
  258.         if (c == '\t') {
  259.             int    nchars = (tabstop - (col % tabstop));
  260.  
  261.             col += nchars;
  262.             if (visspace) {
  263.                 soutputc('>');
  264.                 nchars--;
  265.             }
  266.             while (--nchars >= 0)
  267.                 soutputc(' ');
  268.             if (n <= 0)
  269.                 break;
  270.         } else if (isctrl(c)) {
  271.             soutputc('^');
  272.             soutputc((c == '\177') ? '?' : c + '@');
  273.             col += 2;
  274.         } else {
  275.             if (c == ' ' && visspace)
  276.                 c = '_';
  277.             soutputc(c);
  278.             col++;
  279.         }
  280.     }
  281.     if (n <= 0) {
  282.         if ((*bp == '\0') && (c != '\t') && !isctrl(c))
  283.             sputc(c);
  284.         else
  285.             sputc('!');
  286.     }
  287.     if (cursor > Curline->s_length)
  288.         Curline->s_length = cursor;
  289.     return !aborted;        /* Didn't abort */
  290. }
  291.  
  292. i_set(nline, ncol)
  293. register int    nline,
  294.         ncol;
  295. {
  296.     Curline = &Screen[nline];
  297.     cursor = Curline->s_line + ncol;
  298.     cursend = &Curline->s_line[CO - 1];
  299.     i_line = nline;
  300.     i_col = ncol;
  301. }
  302.  
  303. /* Insert `num' lines a top, but leave all the lines BELOW `bottom'
  304.    alone (at least they won't look any different when we are done).
  305.    This changes the screen array AND does the physical changes. */
  306.  
  307. v_ins_line(num, top, bottom)
  308. {
  309.     register int    i;
  310.  
  311.     /* Save the screen pointers. */
  312.  
  313.     for(i = 0; i < num && top + i <= bottom; i++)
  314.         Savelines[i] = Screen[bottom - i];
  315.  
  316.     /* Num number of bottom lines will be lost.
  317.        Copy everything down num number of times. */
  318.  
  319.     for (i = bottom; i > top && i-num >= 0; i--)
  320.         Screen[i] = Screen[i - num];
  321.  
  322.     /* Restore the saved ones, making them blank. */
  323.  
  324.     for (i = 0; i < num; i++) {
  325.         Screen[top + i] = Savelines[i];
  326.         clrline(Screen[top + i].s_line, Screen[top + i].s_length);
  327.         Screen[top + i].s_length = Screen[top + i].s_line;
  328.     }
  329.  
  330.     (*TTins_line)(top, bottom, num);
  331. }
  332.  
  333. /* Delete `num' lines starting at `top' leaving the lines below `bottom'
  334.    alone.  This updates the internal image as well as the physical image.  */
  335.  
  336. v_del_line(num, top, bottom)
  337. {
  338.     register int    i,
  339.             bot;
  340.  
  341.     bot = bottom;
  342.  
  343.     /* Save the lost lines. */
  344.  
  345.     for (i = 0; i < num && top + i <= bottom; i++)
  346.         Savelines[i] = Screen[top + i];
  347.  
  348.     /* Copy everything up num number of lines. */
  349.  
  350.     for (i = top; num + i <= bottom; i++)
  351.         Screen[i] = Screen[i + num];
  352.  
  353.     /* Restore the lost ones, clearing them. */
  354.  
  355.     for (i = 0; i < num; i++) {
  356.         Screen[bottom - i] = Savelines[i];
  357.         clrline(Screen[bot].s_line, Screen[bot].s_length);
  358.         Screen[bot].s_length = Screen[bot].s_line;
  359.         bot--;
  360.     }
  361.  
  362.     (*TTdel_line)(top, bottom, num);
  363. }
  364.  
  365.  
  366. /* The cursor optimization happens here.  You may decide that this
  367.    is going too far with cursor optimization, or perhaps it should
  368.    limit the amount of checking to when the output speed is slow.
  369.    What ever turns you on ...   */
  370.  
  371. private struct cursaddr {
  372.     int    c_numchars,
  373.         (*c_proc)();
  374. };
  375.  
  376. private char    *Cmstr;
  377. private struct cursaddr    *HorMin,
  378.             *VertMin,
  379.             *DirectMin;
  380.  
  381. private ForMotion(),
  382.     ForTab(),
  383.     BackMotion(),
  384.     RetTab(),
  385.     DownMotion(),
  386.     UpMotion(),
  387.     GoDirect(),
  388.     HomeGo(),
  389.     BottomUp();
  390.     
  391.  
  392. private struct cursaddr    WarpHor[] = {
  393.     0,    ForMotion,
  394.     0,    ForTab,
  395.     0,    BackMotion,
  396.     0,    RetTab
  397. };
  398.  
  399. private struct cursaddr    WarpVert[] = {
  400.     0,    DownMotion,
  401.     0,    UpMotion
  402. };
  403.  
  404. private struct cursaddr    WarpDirect[] = {
  405.     0,    GoDirect,
  406.     0,    HomeGo,
  407.     0,    BottomUp
  408. };
  409.  
  410. #undef    FORWARD
  411. #define    FORWARD        0    /* Move forward */
  412. #define FORTAB        1    /* Forward using tabs */
  413. #undef    BACKWARD
  414. #define    BACKWARD    2    /* Move backward */
  415. #define RETFORWARD    3    /* Beginning of line and then tabs */
  416. #define NUMHOR        4
  417.  
  418. #define DOWN        0    /* Move down */
  419. #define UPMOVE        1    /* Move up */
  420. #define NUMVERT        2
  421.  
  422. #define DIRECT        0    /* Using CM */
  423. #define HOME        1    /* HOME    */
  424. #define LOWER        2    /* Lower Line */
  425. #define NUMDIRECT    3
  426.  
  427. #define    home()        Placur(0, 0)
  428. #define LowLine()    putpad(LL, 1), CapLine = ILI, CapCol = 0
  429. #define PrintHo()    putpad(HO, 1), CapLine = CapCol = 0
  430.  
  431. int    phystab = 8;
  432.  
  433. private
  434. GoDirect(line, col)
  435. register int    line,
  436.         col;
  437. {
  438.     putpad(Cmstr, 1);
  439.     CapLine = line;
  440.     CapCol = col;
  441. }
  442.  
  443. private
  444. RetTab(col)
  445. register int    col;
  446. {
  447.     putchar('\r');
  448.     CapCol = 0;
  449.     ForTab(col);
  450. }
  451.  
  452. private
  453. HomeGo(line, col)
  454. {
  455.     PrintHo();
  456.     DownMotion(line);
  457.     ForTab(col);
  458. }
  459.  
  460. private
  461. BottomUp(line, col)
  462. register int    line,
  463.         col;
  464. {
  465.     LowLine();
  466.     UpMotion(line);
  467.     ForTab(col);
  468. }
  469.  
  470. /* Tries to move forward using tabs (if possible).  It tabs to the
  471.    closest tabstop which means it may go past 'destcol' and backspace
  472.    to it. */
  473.  
  474. private
  475. ForTab(destcol)
  476. int    destcol;
  477. {
  478.     register int    tabgoal,
  479.             ntabs,
  480.             tabstp = phystab;
  481.  
  482.     if (TABS && (tabstp > 0)) {
  483.         tabgoal = destcol + (tabstp / 2);
  484.         tabgoal -= (tabgoal % tabstp);
  485.  
  486.         /* Don't tab to last place or else it is likely to screw up. */
  487.         if (tabgoal >= CO)
  488.             tabgoal -= tabstp;
  489.  
  490.         ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
  491.         while (--ntabs >= 0)
  492.             putchar('\t');
  493.         CapCol = tabgoal;
  494.     }
  495.     if (CapCol > destcol)
  496.         BackMotion(destcol);
  497.     else if (CapCol < destcol)
  498.         ForMotion(destcol);
  499. }
  500.  
  501. private
  502. ForMotion(destcol)
  503. register int    destcol;
  504. {
  505.     register int    nchars = destcol - CapCol;
  506.     register char    *cp = &Screen[CapLine].s_line[CapCol];
  507.  
  508.     while (--nchars >= 0)
  509.         putchar(*cp++ & 0177);
  510.     CapCol = destcol;
  511. }
  512.  
  513. private
  514. BackMotion(destcol)
  515. register int    destcol;
  516. {
  517.     register int    nchars = CapCol - destcol;
  518.  
  519.     if (BC)
  520.         while (--nchars >= 0)
  521.             putpad(BC, 1);
  522.     else
  523.         while (--nchars >= 0)
  524.             putchar('\b');
  525.     CapCol = destcol;
  526. }
  527.  
  528. private
  529. DownMotion(destline)
  530. register int    destline;
  531. {
  532.     register int    nlines = destline - CapLine;
  533.  
  534.     while (--nlines >= 0)
  535.         putchar('\n');
  536.     CapLine = destline;
  537. }
  538.  
  539. private
  540. UpMotion(destline)
  541. register int    destline;
  542. {
  543.     register int    nchars = CapLine - destline;
  544.  
  545.     while (--nchars >= 0)
  546.         putpad(UP, 1);
  547.     CapLine = destline;
  548. }
  549.  
  550. #ifdef ID_CHAR
  551. static int    EIlen;
  552. #endif
  553. extern int    IMlen;
  554.  
  555. InitCM()
  556. {
  557.     HOlen = HO ? strlen(HO) : 1000;
  558.     LLlen = LL ? strlen(LL) : 1000;
  559.     UPlen = UP ? strlen(UP) : 1000;
  560. #ifdef ID_CHAR
  561.     if (EI)
  562.         EIlen = strlen(EI);
  563. #endif
  564. }
  565.  
  566. Placur(line, col)
  567. {
  568.     int    dline,        /* Number of lines to move */
  569.         dcol;        /* Number of columns to move */
  570.     register int    best,
  571.             i;
  572.     register struct cursaddr    *cp;
  573.     int    xtracost = 0;    /* Misc addition to cost. */
  574.  
  575. #define CursMin(which,addrs,max) \
  576.     for (best = 0, cp = &addrs[1], i = 1; i < max; i++, cp++) \
  577.         if (cp->c_numchars < addrs[best].c_numchars) \
  578.             best = i; \
  579.     which = &addrs[best];
  580.  
  581.     if (line == CapLine && col == CapCol)
  582.         return;        /* We are already there. */
  583.  
  584.     dline = line - CapLine;
  585.     dcol = col - CapCol;
  586. #ifdef ID_CHAR
  587.     if (IN_INSmode && MI)
  588.         xtracost = EIlen + IMlen;
  589.     /* If we're already in insert mode, it is likely that we will
  590.        want to be in insert mode again, after the insert. */
  591. #endif
  592.  
  593.     /* Number of characters to move horizontally for each case.
  594.        1: Just move forward by typing the right character on the screen.
  595.        2: Print the correct number of back spaces.
  596.        3: Try tabbing to the correct place.
  597.        4: Try going to the beginning of the line, and then tab. */
  598.  
  599.     if (dcol == 1 || dcol == 0) {        /* Most common case. */
  600.         HorMin = &WarpHor[FORWARD];
  601.         HorMin->c_numchars = dcol + xtracost;
  602.     } else {
  603.         WarpHor[FORWARD].c_numchars = dcol >= 0 ? dcol + xtracost : 1000;
  604.         WarpHor[BACKWARD].c_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
  605.         WarpHor[FORTAB].c_numchars = dcol >= 0 && TABS ?
  606.                 ForNum(CapCol, col) + xtracost : 1000;
  607.         WarpHor[RETFORWARD].c_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
  608.  
  609.         /* Which is the shortest of the bunch */
  610.  
  611.         CursMin(HorMin, WarpHor, NUMHOR);
  612.     }
  613.  
  614.     /* Moving vertically is more simple. */
  615.  
  616.     WarpVert[DOWN].c_numchars = dline >= 0 ? dline : 1000;
  617.     WarpVert[UPMOVE].c_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
  618.  
  619.     /* Which of these is simpler */
  620.     CursMin(VertMin, WarpVert, NUMVERT);
  621.  
  622.     /* Homing first and lowering first are considered 
  623.        direct motions.
  624.        Homing first's total is the sum of the cost of homing
  625.        and the sum of tabbing (if possible) to the right. */
  626.     
  627.     if (VertMin->c_numchars + HorMin->c_numchars <= 3) {
  628.         DirectMin = &WarpDirect[DIRECT];    /* A dummy ... */
  629.         DirectMin->c_numchars = 100;
  630.     } else {
  631.         WarpDirect[DIRECT].c_numchars = CM ?
  632.                 strlen(Cmstr = tgoto(CM, col, line)) : 1000;
  633.         WarpDirect[HOME].c_numchars = HOlen + line +
  634.                 WarpHor[RETFORWARD].c_numchars;
  635.         WarpDirect[LOWER].c_numchars = LLlen + ((ILI - line) * UPlen) +
  636.                 WarpHor[RETFORWARD].c_numchars;
  637.         CursMin(DirectMin, WarpDirect, NUMDIRECT);
  638.     }
  639.  
  640.     if (HorMin->c_numchars + VertMin->c_numchars < DirectMin->c_numchars) {
  641.         if (line != CapLine)
  642.             (*VertMin->c_proc)(line);
  643.         if (col != CapCol) {
  644. #ifdef ID_CHAR
  645.             if (IN_INSmode)    /* We may use real characters ... */
  646.                 INSmode(0);
  647. #endif
  648.             (*HorMin->c_proc)(col);
  649.         }
  650.     } else {
  651. #ifdef ID_CHAR
  652.         if (IN_INSmode && !MI)
  653.             INSmode(0);
  654. #endif
  655.         (*DirectMin->c_proc)(line, col);
  656.     }
  657. }
  658.  
  659. #define abs(x)    ((x) >= 0 ? (x) : -(x))
  660.  
  661. ForNum(from, to)
  662. register int    from;
  663. {
  664.     register int    tabgoal,
  665.             tabstp = phystab;
  666.     int        numchars = 0;
  667.  
  668.     if (from >= to)
  669.         return from - to;
  670.     if (TABS && (tabstp > 0)) {
  671.         tabgoal = to + (tabstp / 2);
  672.         tabgoal -= (tabgoal % tabstp);
  673.         if (tabgoal >= CO)
  674.             tabgoal -= tabstp;
  675.         numchars = (tabgoal / tabstop) - (from / tabstp);
  676.         from = tabgoal;
  677.     }
  678.     return numchars + abs(from - to);
  679. }
  680.  
  681. #ifdef WIRED_TERMS
  682.  
  683. BGi_lines(top, bottom, num)
  684. {
  685.     printf("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
  686.     CapCol = CapLine = 0;
  687. }
  688.  
  689. SUNi_lines(top, bottom, num)
  690. {
  691.     Placur(bottom - num + 1, 0);
  692.     printf("\033[%dM", num);
  693.     Placur(top, 0);
  694.     printf("\033[%dL", num);
  695. }
  696.  
  697. C100i_lines(top, bottom, num)
  698. {
  699.     if (num <= 1) {
  700.         GENi_lines(top, bottom, num);
  701.         return;
  702.     }
  703.     printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
  704.     CapLine = CapCol = 0;
  705.     Placur(top, 0);
  706.     while (num--)
  707.         putpad(AL, ILI - CapLine);
  708.     printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
  709.     CapLine = CapCol = 0;
  710. }
  711.  
  712. #endif WIRED_TERMS
  713.  
  714. GENi_lines(top, bottom, num)
  715. {
  716.     register int    i;
  717.  
  718.     if (CS) {
  719.         putpad(tgoto(CS, bottom, top));
  720.         CapCol = CapLine = 0;
  721.         Placur(top, 0);
  722.         for (i = 0; i < num; i++)
  723.             putpad(SR, bottom - top);
  724.         putpad(tgoto(CS, ILI, 0));
  725.         CapCol = CapLine = 0;
  726.     } else {
  727.         Placur(bottom - num + 1, 0);
  728.         if (M_DL && (num > 1)) {
  729.             char    minibuf[16];
  730.  
  731.             sprintf(minibuf, M_DL, num);
  732.             putpad(minibuf, ILI - CapLine);
  733.         } else {
  734.             for (i = 0; i < num; i++)
  735.                 putpad(DL, ILI - CapLine);
  736.         }
  737.         Placur(top, 0);
  738.         if (M_AL && (num > 1)) {
  739.             char    minibuf[16];
  740.  
  741.             sprintf(minibuf, M_AL, num);
  742.             putpad(minibuf, ILI - CapLine);
  743.         } else {
  744.             for (i = 0; i < num; i++)
  745.                 putpad(AL, ILI - CapLine);
  746.         }
  747.     }
  748. }
  749.  
  750. #ifdef WIRED_TERMS
  751.  
  752. BGd_lines(top, bottom, num)
  753. {
  754.     printf("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
  755.     CapCol = CapLine = 0;
  756. }
  757.  
  758. SUNd_lines(top, bottom, num)
  759. {
  760.     Placur(top, 0);
  761.     printf("\033[%dM", num);
  762.     Placur(bottom + 1 - num, 0);
  763.     printf("\033[%dL", num);
  764. }
  765.  
  766. C100d_lines(top, bottom, num)
  767. {
  768.     if (num <= 1) {
  769.         GENd_lines(top, bottom, num);
  770.         return;
  771.     }
  772.     printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
  773.     CapLine = CapCol = 0;
  774.     Placur(top, 0);
  775.     while (num--)
  776.         putpad(DL, ILI - CapLine);
  777.     printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
  778.     CapLine = CapCol = 0;
  779. }
  780.  
  781. #endif WIRED_TERMS
  782.  
  783. GENd_lines(top, bottom, num)
  784. {
  785.     register int    i;
  786.  
  787.     if (CS) {
  788.         putpad(tgoto(CS, bottom, top));
  789.         CapCol = CapLine = 0;
  790.         Placur(bottom, 0);
  791.         for (i = 0; i < num; i++)
  792.             putpad(SF, bottom - top);
  793.         putpad(tgoto(CS, ILI, 0));
  794.         CapCol = CapLine = 0;
  795.     } else {
  796.         Placur(top, 0);
  797.         if (M_DL && (num > 1)) {
  798.             char    minibuf[16];
  799.  
  800.             sprintf(minibuf, M_DL, num);
  801.             putpad(minibuf, ILI - top);
  802.         } else {
  803.             for (i = 0; i < num; i++)
  804.                 putpad(DL, ILI - top);
  805.         }
  806.         Placur(bottom + 1 - num, 0);
  807.         if (M_AL && (num > 1)) {
  808.             char    minibuf[16];
  809.  
  810.             sprintf(minibuf, M_AL, num);
  811.             putpad(minibuf, ILI - CapLine);
  812.         } else {
  813.             for (i = 0; i < num; i++)
  814.                 putpad(AL, ILI - CapLine);
  815.         }
  816.     }
  817. }
  818.  
  819. struct ID_lookup {
  820.     char    *ID_name;
  821.     int    (*I_proc)();    /* proc to insert lines */
  822.     int    (*D_proc)();    /* proc to delete lines */
  823. } ID_trms[] = {
  824.     "generic",    GENi_lines,    GENd_lines,    /* This should stay here */
  825. #ifdef WIRED_TERMS
  826.     "sun",        SUNi_lines,    SUNd_lines,
  827.     "bg",        BGi_lines,    BGd_lines,
  828.     "c1",        C100i_lines,    C100d_lines,
  829. #endif WIRED_TERMS
  830.     0,        0,        0
  831. };
  832.  
  833. IDline_setup(tname)
  834. char    *tname;
  835. {
  836.     register struct ID_lookup    *idp;
  837.  
  838.     for (idp = &ID_trms[1]; idp->ID_name; idp++)
  839.         if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
  840.             break;
  841.     if (idp->ID_name == 0)
  842.         idp = &ID_trms[0];
  843.     TTins_line = idp->I_proc;
  844.     TTdel_line = idp->D_proc;
  845. }
  846.