home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / editor / j414src.arc / SCREEN.C < prev    next >
C/C++ Source or Header  |  1989-10-10  |  25KB  |  1,159 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is 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 "fp.h"
  10. #include "ctype.h"
  11. #include "termcap.h"
  12. #include "disp.h"
  13.  
  14. int    AbortCnt,
  15.     CanScroll = 0,
  16.     tabstop = 8;
  17.  
  18. #if !(defined(IBMPC) || defined(MAC))
  19. private void
  20.     (*TTins_line) proto((int, int, int)),
  21.     (*TTdel_line) proto((int, int, int));
  22. #endif /* (defined(IBMPC) || defined(MAC)) */
  23.  
  24. struct scrimage
  25.     *DesiredScreen = 0,
  26.     *PhysScreen = 0;
  27.  
  28. struct screenline    *Screen = 0,    /* the screen (a bunch of screenline) */
  29.             *Curline = 0;    /* current line */
  30.  
  31. private struct screenline   *Savelines = 0;    /* another bunch (LI of them) */
  32.  
  33.  
  34. private char    *cursor;            /* offset into current Line */
  35.  
  36. char    *cursend;
  37.  
  38. int    CapCol,
  39.     CapLine,
  40.  
  41.     i_line,
  42.     i_col;
  43.  
  44. #ifdef IBMPC
  45. extern unsigned char    CHPL;
  46. extern void        near normfun(),
  47.             near scr_win(),
  48.             near clr_page(),
  49.             near clr_eoln();
  50.  
  51. #endif
  52.  
  53. void
  54. make_scr()
  55. {
  56.     register int    i;
  57.     register struct screenline    *ns;
  58.     register char    *nsp;
  59.  
  60. #ifdef RESHAPING
  61.     /* In case we are RESHAPING the window! */
  62.     if (DesiredScreen)
  63.         free((char *) DesiredScreen);
  64.     if (PhysScreen)
  65.         free((char *) PhysScreen);
  66.     if (Savelines)
  67.         free((char *) Savelines);
  68.     if (Screen) {
  69.         free(Screen->s_line);    /* free all the screen data */
  70.         free((char *) Screen);
  71.     }
  72. #endif /* RESHAPING */
  73.  
  74.     DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
  75.     PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
  76.  
  77.     Savelines = (struct screenline *)
  78.             malloc((unsigned) LI * sizeof(struct screenline));
  79.     ns = Screen = (struct screenline *)
  80.             malloc((unsigned) LI * sizeof(struct screenline));
  81.  
  82.     nsp = (char *) malloc((unsigned)CO * LI);
  83.     if (nsp == 0) {
  84.         writef("\n\rCannot malloc screen!\n");
  85.         finish(1);
  86.     }
  87.  
  88.     for (i = 0; i < LI; i++) {
  89.         ns->s_line = nsp;
  90.         nsp += CO;
  91.         ns->s_length = nsp - 1;        /* End of Line */
  92.         ns += 1;
  93.     }
  94.     cl_scr(0);
  95. }
  96.  
  97. void
  98. clrline(cp1, cp2)
  99. register char    *cp1,
  100.         *cp2;
  101. {
  102.     while (cp1 <= cp2)
  103.         *cp1++ = ' ';
  104. }
  105.  
  106. #if !(defined(IBMPC) || defined(MAC))
  107. # define sputc(c)    ((*cursor != (char) (c)) ? dosputc((c)) : (cursor++, i_col++))
  108. #endif /* (defined(IBMPC) || defined(MAC)) */
  109.  
  110. #ifdef IBMPC
  111. int force = 0;
  112. # define sputc(c)    dosputc((c))
  113. #endif /* IBMPC */
  114.  
  115. #ifdef MAC
  116. # define sputc(c)    bufputc((c))    /* line buffered for mac display */
  117. #endif /* MAC */
  118.  
  119. #define soutputc(c)    { if (--n <= 0) break; else sputc((c)); }
  120.  
  121. void
  122. cl_eol()
  123. {
  124.     if (cursor > cursend)
  125.         return;
  126.  
  127.     if (cursor < Curline->s_length) {
  128. #if !(defined(IBMPC) || defined(MAC))
  129.         if (CE) {
  130. #endif /* (defined(IBMPC) || defined(MAC)) */
  131.             Placur(i_line, i_col);
  132. #ifdef TERMCAP
  133.             putpad(CE, 1);
  134. #else
  135.         clr_eoln();
  136. #endif /* TERMCAP */
  137.             clrline(cursor, Curline->s_length);
  138. #if !(defined(IBMPC) || defined(MAC))
  139.         } else {
  140.         /* Ugh.  The slow way for dumb terminals. */
  141.             register char *savecp = cursor;
  142.  
  143.             while (cursor <= Curline->s_length)
  144.                 sputc(' ');
  145.             cursor = savecp;
  146.         }
  147. #endif /* (defined(IBMPC) || defined(MAC)) */
  148.         Curline->s_length = cursor;
  149.     }
  150. }
  151.  
  152. void
  153. cl_scr(doit)
  154. int doit;
  155. {
  156.     register int    i;
  157.     register struct screenline    *sp = Screen;
  158.  
  159.     for (i = 0; i < LI; i++, sp++) {
  160.         clrline(sp->s_line, sp->s_length);
  161.         sp->s_length = sp->s_line;
  162.         PhysScreen[i].s_id = 0;
  163.     }
  164.     if (doit) {
  165. #ifdef TERMCAP
  166.         putpad(CL, LI);
  167. #else
  168.         clr_page();
  169. #endif /* TERMCAP */
  170.         CapCol = CapLine = 0;
  171.         UpdMesg = YES;
  172.     }
  173. }
  174.  
  175. /* Output one character (if necessary) at the current position */
  176.  
  177. #ifndef MAC
  178. int        /* only for lints sake */
  179. dosputc(c)
  180. register int    c;
  181. {
  182. #ifndef IBMPC
  183.     if (*cursor != c) {
  184. # ifdef ID_CHAR
  185.         if (IN_INSmode)
  186.             INSmode(0);
  187. # endif
  188. #else /* IBMPC */
  189.     if ((force) || (*cursor != c)) {
  190. #endif /* IBMPC */
  191.         if (i_line != CapLine || i_col != CapCol)
  192.             Placur(i_line, i_col);
  193. #ifndef IBMPC
  194.         if (UL && (c & CHARMASK) == '_' && (*cursor & CHARMASK) != ' ')
  195.             putstr(" \b");        /* Erase so '_' looks right. */
  196. #endif /* IBMPC */
  197.         *cursor++ = c;
  198. #ifndef IBMPC
  199.         jputchar(c & CHARMASK);
  200. #else /* IBMPC */
  201.         normfun((char) c);
  202. #endif /* IBMPC */
  203.         AbortCnt -= 1;
  204.         CapCol += 1;
  205.         i_col += 1;
  206.     } else {
  207.         cursor += 1;
  208.         i_col += 1;
  209.     }
  210.     return 0;   /* useless result */
  211. }
  212. #else /* MAC */
  213.  
  214. /* Character output to bit-mapped screen is very expensive. It makes
  215.    much more sense to write the entire line at once. So, we print all
  216.    the characters, whether already there or not, once the line is
  217.    complete.  */
  218.  
  219. #define BUFFLUSH (char) 0
  220. #define BUFSTART (char) 1
  221.  
  222. bufputc(c)
  223. register char c;
  224. {
  225.     static char buf[256];
  226.     static int len = 0;
  227.  
  228.     if(c == BUFSTART) {
  229. /*        if (i_line != CapLine || i_col != CapCol)*/
  230.             NPlacur(i_line, i_col);
  231.         len = 0;
  232.         return;
  233.     }
  234.     if(c == BUFFLUSH) {
  235.         buf[0] = (unsigned char) len;
  236.         writechr(buf);
  237.         len = 0;
  238.     }
  239.     else {
  240.         if(len > 255) return;
  241.         *cursor++ = c;
  242.         if(c == '0') buf[++len] = 0xAF;    /* slashed zero */
  243.         else buf[++len] = c;
  244.         CapCol++;
  245.         i_col++;
  246.     }
  247.     return;
  248. }
  249. #endif /* MAC */
  250.  
  251. /* Write `line' at the current position of `cursor'.  Stop when we
  252.    reach the end of the screen.  Aborts if there is a character
  253.    waiting.  */
  254.  
  255. #ifdef MAC        /* This was getting too complicated with ifdefs ... */
  256. int
  257. swrite(line, inversep, abortable)
  258. register char    *line;
  259. register int    abortable;
  260. {
  261.     register int    c;
  262.     int    col = i_col,
  263.         aborted = 0;
  264.     register int    n = cursend - cursor;
  265.  
  266.     if (n <= 0)
  267.         return 1;
  268.     sputc(BUFSTART);    /* Okay, because no interruption possible */
  269.  
  270.     while (c = *line++) {
  271.         if (abortable && AbortCnt < 0) {
  272.             AbortCnt = BufSize;
  273.             if (InputPending = charp()) {
  274.                 aborted = 1;
  275.                 break;
  276.             }
  277.         }
  278.         if (c == '\t') {
  279.             int    nchars;
  280.  
  281.             nchars = (tabstop - (col % tabstop));
  282.             col += nchars;
  283.  
  284.             while (nchars--)
  285.                 soutputc(' ');
  286.             if (n <= 0)
  287.                 break;
  288.         } else if (isctrl(c)) {
  289.             soutputc('^');
  290.             c = ((c == '\177') ? '?' : c + '@');
  291.             soutputc(c);
  292.             col += 2;
  293.         } else {
  294.             soutputc(c);
  295.             col += 1;
  296.         }
  297.     }
  298.     if (n <= 0) {
  299.         if ((*line == '\0') && (c != '\t') && !isctrl(c))
  300.             sputc(c);
  301.             sputc('!');
  302.     }
  303.     if (cursor > Curline->s_length)
  304.         Curline->s_length = cursor;
  305.     sputc(BUFFLUSH);
  306.     return !aborted;
  307. }
  308.  
  309. #else /* MAC */
  310.  
  311. int
  312. swrite(line, inversep, abortable)
  313. register char    *line;
  314. int    inversep;
  315. register int    abortable;
  316. {
  317.     register int    c;
  318.     int    col = i_col,
  319.         aborted = 0;
  320.     register int    n = cursend - cursor;
  321. #ifndef IBMPC
  322.     int    or_byte = inversep ? 0200 : 0,
  323.         thebyte;
  324. #else
  325.     int    thebyte;
  326. #endif /* IBMPC */
  327.  
  328. #ifdef IBMPC
  329.     force = inversep? 1: 0;  /* to force a redraw of the modeline */
  330. #endif /* IBMPC */
  331.  
  332.     if (n <= 0)
  333.         return 1;
  334.     while ((c = *line++) != '\0') {
  335.         if (abortable && AbortCnt < 0) {
  336.             AbortCnt = BufSize;
  337.             if ((InputPending = charp()) != '\0') {
  338.                 aborted = 1;
  339.                 break;
  340.             }
  341.         }
  342.         if (c == '\t') {
  343.             int    nchars;
  344.  
  345.             nchars = (tabstop - (col % tabstop));
  346.             col += nchars;
  347.  
  348. #ifndef IBMPC
  349.             thebyte = (' ' | or_byte);
  350. #endif /* IBMPC */
  351.             while (nchars--)
  352. #ifndef IBMPC
  353.                 soutputc(thebyte);
  354. #else /* IBMPC */
  355.                 soutputc(' ');
  356. #endif /* IBMPC */
  357.             if (n <= 0)
  358.                 break;
  359.         } else if (isctrl(c)) {
  360. #ifndef IBMPC
  361.             thebyte = ('^' | or_byte);
  362.             soutputc(thebyte);
  363.             thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
  364.             soutputc(thebyte);
  365. #else /* IBMPC */
  366.             soutputc('^');
  367.             c = ((c == '\177') ? '?' : c + '@');
  368.             soutputc(c);
  369. #endif /* IBMPC */
  370.             col += 2;
  371. #ifdef TERMCAP
  372.         } else if (HZ && c == '~') {
  373.             thebyte = ('`' | or_byte);
  374.             soutputc(thebyte);
  375.             col += 1;
  376. #endif
  377.         } else {
  378. #ifndef IBMPC
  379.             thebyte = (c | or_byte);
  380.             soutputc(thebyte);
  381. #else /* IBMPC */
  382.             if (c == 255) c = 1;
  383.             if (c == ' ' && inversep) c = 255;
  384.             soutputc(c);
  385. #endif /* IBMPC */
  386.             col += 1;
  387.         }
  388.     }
  389.     if (n <= 0) {
  390.         if ((*line == '\0') && (c != '\t') && !isctrl(c))
  391. #ifndef IBMPC
  392.             sputc(c|or_byte);
  393. #else /* IBMPC */
  394.             sputc(c);
  395. #endif /* IBMPC */
  396.         else
  397. #ifndef IBMPC
  398.             sputc('!'|or_byte);
  399. #else /* IBMPC */
  400.             sputc('!');
  401. #endif /* IBMPC */
  402.     }
  403.     if (cursor > Curline->s_length)
  404.         Curline->s_length = cursor;
  405. #ifdef IBMPC
  406.     force = 0;
  407. #endif
  408.     return !aborted;
  409. }
  410. #endif /* MAC */
  411.  
  412. /* This is for writing a buffer line to the screen.  This is to
  413.    minimize the amount of copying from one buffer to another buffer.
  414.    This gets the info directly from the disk buffers. */
  415.  
  416. int
  417. BufSwrite(linenum)
  418. int linenum;
  419. {
  420.     register int    n = cursend - cursor,
  421.             col = 0,
  422.             c = -1;
  423.     register char    *bp;
  424.     int    StartCol = DesiredScreen[linenum].s_offset,
  425.         visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
  426.         aborted = 0;
  427.  
  428.     bp = lcontents(DesiredScreen[linenum].s_lp);
  429.     if (*bp) for (;;) {
  430.         if (col >= StartCol) {
  431.             DesiredScreen[linenum].s_offset = col;
  432.             break;
  433.         }
  434.  
  435.         c = *bp++ & CHARMASK;
  436.         if (c == '\0')
  437.             break;
  438.         if (c == '\t')
  439.             col += (tabstop - (col % tabstop));
  440.         else if (isctrl(c))
  441.             col += 2;
  442.         else
  443.             col += 1;
  444.     }
  445. #ifdef MAC
  446.     sputc(BUFSTART);    /* Okay because we can't be interrupted */
  447. #endif
  448.  
  449.     if (c != '\0') while ((c = *bp++) != '\0') {
  450.         if (AbortCnt < 0) {
  451.             AbortCnt = BufSize;
  452.             if ((InputPending = charp()) != '\0') {
  453.                 aborted = 1;
  454.                 break;
  455.             }
  456.         }
  457.         if (c == '\t') {
  458.             int    nchars = (tabstop - (col % tabstop));
  459.  
  460.             col += nchars;
  461.             if (visspace) {
  462.                 soutputc('>');
  463.                 nchars -= 1;
  464.             }
  465.             while (--nchars >= 0)
  466.                 soutputc(' ');
  467.             if (n <= 0)
  468.                 break;
  469.         } else if (isctrl(c)) {
  470.             soutputc('^');
  471.             soutputc((c == '\177') ? '?' : c + '@');
  472.             col += 2;
  473. #ifdef TERMCAP
  474.         } else if (HZ && c == '~') {
  475.             soutputc('`');
  476.             col += 1;
  477. #endif
  478.         } else {
  479.             if (c == ' ' && visspace)
  480.                 c = '_';
  481. #ifdef IBMPC
  482.             if (c == 255)
  483.                c = 1;
  484. #endif /* IBMPC */
  485.             soutputc(c);
  486.             col += 1;
  487.         }
  488.     }
  489.     if (n <= 0) {
  490.         if ((*bp == '\0') && (c != '\t') && !isctrl(c))
  491.             sputc(c);
  492.         else
  493.             sputc('!');
  494.     }
  495.     if (cursor > Curline->s_length)
  496.         Curline->s_length = cursor;
  497. #ifdef MAC
  498.     sputc(BUFFLUSH);
  499. #endif
  500.     return !aborted;        /* Didn't abort */
  501. }
  502.  
  503. void
  504. i_set(nline, ncol)
  505. register int    nline,
  506.         ncol;
  507. {
  508.     Curline = &Screen[nline];
  509.     cursor = Curline->s_line + ncol;
  510.     cursend = &Curline->s_line[CO - 1];
  511.     i_line = nline;
  512.     i_col = ncol;
  513. }
  514.  
  515. #if !(defined(MAC) || defined(IBMPC))
  516. void
  517. SO_on()
  518. {
  519.     /* If there are magic cookies, then WHERE the SO string is
  520.        printed decides where the SO actually starts on the screen.
  521.        So it's important to make sure the cursor is positioned there
  522.        anyway.  I think this is right. */
  523.     if (SG != 0) {
  524.         Placur(i_line, i_col);
  525.         i_col += SG;
  526.         CapCol += SG;
  527.     }
  528.     putpad(SO, 1);
  529. }
  530.  
  531. void
  532. SO_off()
  533. {
  534.     /* see comment in SO_on() */
  535.     if (SG != 0) {
  536.         Placur(i_line, i_col);
  537.         i_col += SG;
  538.         CapCol += SG;
  539.     }
  540.     putpad(SE, 1);
  541. }
  542. #endif
  543.  
  544. /* Insert `num' lines a top, but leave all the lines BELOW `bottom'
  545.    alone (at least they won't look any different when we are done).
  546.    This changes the screen array AND does the physical changes. */
  547.  
  548. void
  549. v_ins_line(num, top, bottom)
  550. int num,
  551.     top,
  552.     bottom;
  553. {
  554.     register int    i;
  555.  
  556.     /* Save the screen pointers. */
  557.  
  558.     for(i = 0; i < num && top + i <= bottom; i++)
  559.         Savelines[i] = Screen[bottom - i];
  560.  
  561.     /* Num number of bottom lines will be lost.
  562.        Copy everything down num number of times. */
  563.  
  564.     for (i = bottom; i > top && i-num >= 0; i--)
  565.         Screen[i] = Screen[i - num];
  566.  
  567.     /* Restore the saved ones, making them blank. */
  568.  
  569.     for (i = 0; i < num; i++) {
  570.         Screen[top + i] = Savelines[i];
  571.         clrline(Screen[top + i].s_line, Screen[top + i].s_length);
  572.         Screen[top + i].s_length = Screen[top + i].s_line;
  573.     }
  574.  
  575. #if !(defined(IBMPC) || defined(MAC))
  576.     (*TTins_line)(top, bottom, num);
  577. #endif
  578.  
  579. #ifdef MAC
  580.     i_lines(top, bottom, num);
  581. #endif
  582.  
  583. #ifdef IBMPC
  584.     scr_win((int) -num, (unsigned char) top, 0, (unsigned char) bottom, CHPL-1);
  585. #endif
  586. }
  587.  
  588. /* Delete `num' lines starting at `top' leaving the lines below `bottom'
  589.    alone.  This updates the internal image as well as the physical image.  */
  590.  
  591. void
  592. v_del_line(num, top, bottom)
  593. int num,
  594.     top,
  595.     bottom;
  596. {
  597.     register int    i,
  598.             bot;
  599.  
  600.     bot = bottom;
  601.  
  602.     /* Save the lost lines. */
  603.  
  604.     for (i = 0; i < num && top + i <= bottom; i++)
  605.         Savelines[i] = Screen[top + i];
  606.  
  607.     /* Copy everything up num number of lines. */
  608.  
  609.     for (i = top; num + i <= bottom; i++)
  610.         Screen[i] = Screen[i + num];
  611.  
  612.     /* Restore the lost ones, clearing them. */
  613.  
  614.     for (i = 0; i < num; i++) {
  615.         Screen[bottom - i] = Savelines[i];
  616.         clrline(Screen[bot].s_line, Screen[bot].s_length);
  617.         Screen[bot].s_length = Screen[bot].s_line;
  618.         bot -= 1;
  619.     }
  620.  
  621. #if !(defined(IBMPC) || defined(MAC))
  622.     (*TTdel_line)(top, bottom, num);
  623. #endif
  624.  
  625. #ifdef MAC
  626.     d_lines(top, bottom, num);
  627. #endif
  628.  
  629. #ifdef IBMPC
  630.     scr_win(num, (unsigned char) top, 0, (unsigned char) bottom, CHPL-1);
  631. #endif
  632.  
  633. }
  634.  
  635. #if !(defined(MAC) || defined(IBMPC))    /* remainder of this file */
  636.  
  637. /* The cursor optimization happens here.  You may decide that this
  638.    is going too far with cursor optimization, or perhaps it should
  639.    limit the amount of checking to when the output speed is slow.
  640.    What ever turns you on ...   */
  641.  
  642. struct cursaddr {
  643.     int    cm_numchars;
  644.     void    (*cm_proc) ();
  645. };
  646.  
  647. private char    *Cmstr;
  648. private struct cursaddr    *HorMin,
  649.             *VertMin,
  650.             *DirectMin;
  651.  
  652. private void
  653.     GENi_lines proto((int, int, int)),
  654.     GENd_lines proto((int, int, int)),
  655.     ForMotion proto((int)),
  656.     ForTab proto((int)),
  657.     BackMotion proto((int)),
  658.     RetTab proto((int)),
  659.     DownMotion proto((int)),
  660.     UpMotion proto((int)),
  661.     GoDirect proto((int, int)),
  662.     HomeGo proto((int, int)),
  663.     BottomUp proto((int, int));
  664.  
  665.  
  666. private struct cursaddr    WarpHor[] = {
  667.     0,    ForMotion,
  668.     0,    ForTab,
  669.     0,    BackMotion,
  670.     0,    RetTab
  671. };
  672.  
  673. private struct cursaddr    WarpVert[] = {
  674.     0,    DownMotion,
  675.     0,    UpMotion
  676. };
  677.  
  678. private struct cursaddr    WarpDirect[] = {
  679.     0,    GoDirect,
  680.     0,    HomeGo,
  681.     0,    BottomUp
  682. };
  683.  
  684. #undef    FORWARD
  685. #define    FORWARD        0    /* Move forward */
  686. #define FORTAB        1    /* Forward using tabs */
  687. #undef    BACKWARD
  688. #define    BACKWARD    2    /* Move backward */
  689. #define RETFORWARD    3    /* Beginning of line and then tabs */
  690. #define NUMHOR        4
  691.  
  692. #define DOWN        0    /* Move down */
  693. #define UPMOVE        1    /* Move up */
  694. #define NUMVERT        2
  695.  
  696. #define DIRECT        0    /* Using CM */
  697. #define HOME        1    /* HOME    */
  698. #define LOWER        2    /* Lower Line */
  699. #define NUMDIRECT    3
  700.  
  701. #define    home()        Placur(0, 0)
  702. #define LowLine()    { putpad(LL, 1); CapLine = ILI; CapCol = 0; }
  703. #define PrintHo()    { putpad(HO, 1); CapLine = CapCol = 0; }
  704.  
  705. int    phystab = 8;
  706.  
  707. private void
  708. GoDirect(line, col)
  709. register int    line,
  710.         col;
  711. {
  712.     putpad(Cmstr, 1);
  713.     CapLine = line;
  714.     CapCol = col;
  715. }
  716.  
  717. private void
  718. RetTab(col)
  719. register int    col;
  720. {
  721.     jputchar('\r');
  722.     CapCol = 0;
  723.     ForTab(col);
  724. }
  725.  
  726. private void
  727. HomeGo(line, col)
  728. int line,
  729.     col;
  730. {
  731.     PrintHo();
  732.     DownMotion(line);
  733.     ForTab(col);
  734. }
  735.  
  736. private void
  737. BottomUp(line, col)
  738. register int    line,
  739.         col;
  740. {
  741.     LowLine();
  742.     UpMotion(line);
  743.     ForTab(col);
  744. }
  745.  
  746. /* Tries to move forward using tabs (if possible).  It tabs to the
  747.    closest tabstop which means it may go past 'destcol' and backspace
  748.    to it. */
  749.  
  750. private void
  751. ForTab(destcol)
  752. int    destcol;
  753. {
  754.     register int    tabgoal,
  755.             ntabs,
  756.             tabstp = phystab;
  757.  
  758.     if (TABS && (tabstp > 0)) {
  759.         tabgoal = destcol + (tabstp / 2);
  760.         tabgoal -= (tabgoal % tabstp);
  761.  
  762.         /* Don't tab to last place or else it is likely to screw up. */
  763.         if (tabgoal >= CO)
  764.             tabgoal -= tabstp;
  765.  
  766.         ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
  767.         while (--ntabs >= 0)
  768.             jputchar('\t');
  769.         CapCol = tabgoal;
  770.     }
  771.     if (CapCol > destcol)
  772.         BackMotion(destcol);
  773.     else if (CapCol < destcol)
  774.         ForMotion(destcol);
  775. }
  776.  
  777. private void
  778. ForMotion(destcol)
  779. register int    destcol;
  780. {
  781.     register int    nchars = destcol - CapCol;
  782.     register char    *cp = &Screen[CapLine].s_line[CapCol];
  783.  
  784.     while (--nchars >= 0)
  785.         jputchar(*cp++ & CHARMASK);
  786.     CapCol = destcol;
  787. }
  788.  
  789. private void
  790. BackMotion(destcol)
  791. register int    destcol;
  792. {
  793.     register int    nchars = CapCol - destcol;
  794.  
  795.     if (BC)
  796.         while (--nchars >= 0)
  797.             putpad(BC, 1);
  798.     else
  799.         while (--nchars >= 0)
  800.             jputchar('\b');
  801.     CapCol = destcol;
  802. }
  803.  
  804. private void
  805. DownMotion(destline)
  806. register int    destline;
  807. {
  808.     register int    nlines = destline - CapLine;
  809.  
  810.     while (--nlines >= 0)
  811.         putpad(DO, 1);
  812.     CapLine = destline;
  813. }
  814.  
  815. private void
  816. UpMotion(destline)
  817. register int    destline;
  818. {
  819.     register int    nchars = CapLine - destline;
  820.  
  821.     while (--nchars >= 0)
  822.         putpad(UP, 1);
  823.     CapLine = destline;
  824. }
  825.  
  826. #ifdef ID_CHAR
  827. static int    EIlen;
  828. #endif
  829.  
  830. #ifndef IBMPC
  831.  
  832. void
  833. InitCM()
  834. {
  835.     HOlen = HO ? strlen(HO) : 1000;
  836.     LLlen = LL ? strlen(LL) : 1000;
  837.     UPlen = UP ? strlen(UP) : 1000;
  838. #ifdef ID_CHAR
  839.     if (EI)
  840.         EIlen = strlen(EI);
  841. #endif
  842. }
  843.  
  844. private int ForNum proto((int from, int to));
  845.  
  846. void
  847. Placur(line, col)
  848. int line,
  849.     col;
  850. {
  851.     int    dline,        /* Number of lines to move */
  852.         dcol;        /* Number of columns to move */
  853.     register int    best,
  854.             i;
  855.     register struct cursaddr    *cp;
  856.     int    xtracost = 0;    /* Misc addition to cost. */
  857.  
  858. #define CursMin(which,addrs,max)    { \
  859.     for (best = 0, cp = &(addrs)[1], i = 1; i < (max); i++, cp++) \
  860.         if (cp->cm_numchars < (addrs)[best].cm_numchars) \
  861.             best = i; \
  862.     (which) = &(addrs)[best]; \
  863. }
  864.  
  865.     if (line == CapLine && col == CapCol)
  866.         return;        /* We are already there. */
  867.  
  868.     dline = line - CapLine;
  869.     dcol = col - CapCol;
  870. #ifdef ID_CHAR
  871.     if (IN_INSmode && MI)
  872.         xtracost = EIlen + IMlen;
  873.     /* If we're already in insert mode, it is likely that we will
  874.        want to be in insert mode again, after the insert. */
  875. #endif
  876.  
  877.     /* Number of characters to move horizontally for each case.
  878.        1: Just move forward by typing the right character on the screen.
  879.        2: Print the correct number of back spaces.
  880.        3: Try tabbing to the correct place.
  881.        4: Try going to the beginning of the line, and then tab. */
  882.  
  883.     if (dcol == 1 || dcol == 0) {        /* Most common case. */
  884.         HorMin = &WarpHor[FORWARD];
  885.         HorMin->cm_numchars = dcol + xtracost;
  886.     } else {
  887.         WarpHor[FORWARD].cm_numchars = dcol >= 0 ? dcol + xtracost : 1000;
  888.         WarpHor[BACKWARD].cm_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
  889.         WarpHor[FORTAB].cm_numchars = dcol >= 0 && TABS ?
  890.                 ForNum(CapCol, col) + xtracost : 1000;
  891.         WarpHor[RETFORWARD].cm_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
  892.  
  893.         /* Which is the shortest of the bunch */
  894.  
  895.         CursMin(HorMin, WarpHor, NUMHOR);
  896.     }
  897.  
  898.     /* Moving vertically is more simple. */
  899.  
  900.     WarpVert[DOWN].cm_numchars = dline >= 0 ? dline : 1000;
  901.     WarpVert[UPMOVE].cm_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
  902.  
  903.     /* Which of these is simpler */
  904.     CursMin(VertMin, WarpVert, NUMVERT);
  905.  
  906.     /* Homing first and lowering first are considered
  907.        direct motions.
  908.        Homing first's total is the sum of the cost of homing
  909.        and the sum of tabbing (if possible) to the right. */
  910.  
  911.     if (VertMin->cm_numchars + HorMin->cm_numchars <= 3) {
  912.         DirectMin = &WarpDirect[DIRECT];    /* A dummy ... */
  913.         DirectMin->cm_numchars = 100;
  914.     } else {
  915.         WarpDirect[DIRECT].cm_numchars = CM ?
  916.                 strlen(Cmstr = tgoto(CM, col, line)) : 1000;
  917.         WarpDirect[HOME].cm_numchars = HOlen + line +
  918.                 WarpHor[RETFORWARD].cm_numchars;
  919.         WarpDirect[LOWER].cm_numchars = LLlen + ((ILI - line) * UPlen) +
  920.                 WarpHor[RETFORWARD].cm_numchars;
  921.         CursMin(DirectMin, WarpDirect, NUMDIRECT);
  922.     }
  923.  
  924.     if (HorMin->cm_numchars + VertMin->cm_numchars < DirectMin->cm_numchars) {
  925.         if (line != CapLine)
  926.             (*VertMin->cm_proc)(line);
  927.         if (col != CapCol) {
  928. #ifdef ID_CHAR
  929.             if (IN_INSmode)    /* We may use real characters ... */
  930.                 INSmode(0);
  931. #endif
  932.             (*HorMin->cm_proc)(col);
  933.         }
  934.     } else {
  935. #ifdef ID_CHAR
  936.         if (IN_INSmode && !MI)
  937.             INSmode(0);
  938. #endif
  939.         (*DirectMin->cm_proc)(line, col);
  940.     }
  941. }
  942.  
  943. #endif /* IBMPC */
  944.  
  945. #define abs(x)    ((x) >= 0 ? (x) : -(x))
  946.  
  947. private int
  948. ForNum(from, to)
  949. register int    from;
  950. int to;
  951. {
  952.     register int    tabgoal,
  953.             tabstp = phystab;
  954.     int        numchars = 0;
  955.  
  956.     if (from >= to)
  957.         return from - to;
  958.     if (TABS && (tabstp > 0)) {
  959.         tabgoal = to + (tabstp / 2);
  960.         tabgoal -= (tabgoal % tabstp);
  961.         if (tabgoal >= CO)
  962.             tabgoal -= tabstp;
  963.         numchars = (tabgoal / tabstop) - (from / tabstp);
  964.         from = tabgoal;
  965.     }
  966.     return numchars + abs(from - to);
  967. }
  968.  
  969. #ifdef WIRED_TERMS
  970.  
  971. private void
  972. BGi_lines(top, bottom, num)
  973. int top,
  974.     bottom,
  975.     num;
  976. {
  977.     writef("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
  978.     CapCol = CapLine = 0;
  979. }
  980.  
  981. private void
  982. SUNi_lines(top, bottom, num)
  983. int top,
  984.     bottom,
  985.     num;
  986. {
  987.     Placur(bottom - num + 1, 0);
  988.     writef("\033[%dM", num);
  989.     Placur(top, 0);
  990.     writef("\033[%dL", num);
  991. }
  992.  
  993. private void
  994. C100i_lines(top, bottom, num)
  995. int top,
  996.     bottom,
  997.     num;
  998. {
  999.     if (num <= 1) {
  1000.         GENi_lines(top, bottom, num);
  1001.         return;
  1002.     }
  1003.     writef("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
  1004.     CapLine = CapCol = 0;
  1005.     Placur(top, 0);
  1006.     while (num--)
  1007.         putpad(AL, ILI - CapLine);
  1008.     writef("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
  1009.     CapLine = CapCol = 0;
  1010. }
  1011.  
  1012. #endif /* WIRED_TERMS */
  1013.  
  1014. private void
  1015. GENi_lines(top, bottom, num)
  1016. int top,
  1017.     bottom,
  1018.     num;
  1019. {
  1020.     register int    i;
  1021.  
  1022.     if (CS) {
  1023.         putpad(tgoto(CS, bottom, top), 1);
  1024.         CapCol = CapLine = 0;
  1025.         Placur(top, 0);
  1026.         for (i = 0; i < num; i++)
  1027.             putpad(SR, bottom - top);
  1028.         putpad(tgoto(CS, ILI, 0), 1);
  1029.         CapCol = CapLine = 0;
  1030.     } else {
  1031.         Placur(bottom - num + 1, 0);
  1032.         if (M_DL && (num > 1)) {
  1033.             putargpad(M_DL, num, ILI - CapLine);
  1034.         } else {
  1035.             for (i = 0; i < num; i++)
  1036.                 putpad(DL, ILI - CapLine);
  1037.         }
  1038.         Placur(top, 0);
  1039.         if (M_AL && (num > 1)) {
  1040.             putargpad(M_AL, num, ILI - CapLine);
  1041.         } else {
  1042.             for (i = 0; i < num; i++)
  1043.                 putpad(AL, ILI - CapLine);
  1044.         }
  1045.     }
  1046. }
  1047.  
  1048. #ifdef WIRED_TERMS
  1049.  
  1050. private void
  1051. BGd_lines(top, bottom, num)
  1052. int top,
  1053.     bottom,
  1054.     num;
  1055. {
  1056.     writef("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
  1057.     CapCol = CapLine = 0;
  1058. }
  1059.  
  1060. private void
  1061. SUNd_lines(top, bottom, num)
  1062. int top,
  1063.     bottom,
  1064.     num;
  1065. {
  1066.     Placur(top, 0);
  1067.     writef("\033[%dM", num);
  1068.     Placur(bottom + 1 - num, 0);
  1069.     writef("\033[%dL", num);
  1070. }
  1071.  
  1072. private void
  1073. C100d_lines(top, bottom, num)
  1074. int top,
  1075.     bottom,
  1076.     num;
  1077. {
  1078.     if (num <= 1) {
  1079.         GENd_lines(top, bottom, num);
  1080.         return;
  1081.     }
  1082.     writef("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
  1083.     CapLine = CapCol = 0;
  1084.     Placur(top, 0);
  1085.     while (num--)
  1086.         putpad(DL, ILI - CapLine);
  1087.     writef("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
  1088.     CapLine = CapCol = 0;
  1089. }
  1090.  
  1091. #endif /* WIRED_TERMS */
  1092.  
  1093. private void
  1094. GENd_lines(top, bottom, num)
  1095. int top,
  1096.     bottom,
  1097.     num;
  1098. {
  1099.     register int    i;
  1100.  
  1101.     if (CS) {
  1102.         putpad(tgoto(CS, bottom, top), 1);
  1103.         CapCol = CapLine = 0;
  1104.         Placur(bottom, 0);
  1105.         for (i = 0; i < num; i++)
  1106.             putpad(SF, bottom - top);
  1107.         putpad(tgoto(CS, ILI, 0), 1);
  1108.         CapCol = CapLine = 0;
  1109.     } else {
  1110.         Placur(top, 0);
  1111.         if (M_DL && (num > 1)) {
  1112.             putargpad(M_DL, num, ILI - top);
  1113.         } else {
  1114.             for (i = 0; i < num; i++)
  1115.                 putpad(DL, ILI - top);
  1116.         }
  1117.         Placur(bottom + 1 - num, 0);
  1118.         if (M_AL && (num > 1)) {
  1119.             putargpad(M_AL, num, ILI - CapLine);
  1120.         } else {
  1121.             for (i = 0; i < num; i++)
  1122.                 putpad(AL, ILI - CapLine);
  1123.         }
  1124.     }
  1125. }
  1126.  
  1127. private const struct ID_lookup {
  1128.     char    *ID_name;
  1129.     void    (*I_proc) proto((int, int, int));    /* proc to insert lines */
  1130.     void    (*D_proc) proto((int, int, int));    /* proc to delete lines */
  1131. } ID_trms[] = {
  1132.     "generic",    GENi_lines,    GENd_lines,    /* This should stay here */
  1133. #ifdef WIRED_TERMS
  1134.     "sun",        SUNi_lines,    SUNd_lines,
  1135.     "bg",        BGi_lines,    BGd_lines,
  1136.     "c1",        C100i_lines,    C100d_lines,
  1137. #endif /* WIRED_TERMS */
  1138.     0,        0,        0
  1139. };
  1140.  
  1141. void
  1142. IDline_setup(tname)
  1143. char    *tname;
  1144. {
  1145.     register const struct ID_lookup    *idp;
  1146.  
  1147.     for (idp = &ID_trms[1]; idp->ID_name; idp++)
  1148.         if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
  1149.             break;
  1150.     if (idp->ID_name == 0)
  1151.         idp = &ID_trms[0];
  1152. #ifndef IBMPC
  1153.     TTins_line = idp->I_proc;
  1154.     TTdel_line = idp->D_proc;
  1155. #endif
  1156. }
  1157.  
  1158. #endif /* MAC */
  1159.