home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / ex / ex_vadj.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  23KB  |  1,036 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include "ex.h"
  3. #include "ex_tty.h"
  4. #include "ex_vis.h"
  5.  
  6. /*
  7.  * Routines to deal with management of logical versus physical
  8.  * display, opening and redisplaying lines on the screen, and
  9.  * use of intelligent terminal operations.  Routines to deal with
  10.  * screen cleanup after a change.
  11.  */
  12.  
  13. /*
  14.  * Display a new line at physical line p, returning
  15.  * the depth of the newly displayed line.  We may decide
  16.  * to expand the window on an intelligent terminal if it is
  17.  * less than a full screen by deleting a line above the top of the
  18.  * window before doing an insert line to keep all the good text
  19.  * on the screen in which case the line may actually end up
  20.  * somewhere other than line p.
  21.  */
  22. vopen(tp, p)
  23.     line *tp;
  24.     int p;
  25. {
  26.     register int cnt;
  27.     register struct vlinfo *vp, *vpc;
  28.  
  29. #ifdef ADEBUG
  30.     if (trace != NULL)
  31.         tfixnl(), fprintf(trace, "vopen(%d, %d)\n", lineno(tp), p);
  32. #endif
  33.     if (state != VISUAL) {
  34.         if (vcnt)
  35.             if (hold & HOLDROL)
  36.                 vup1();
  37.             else
  38.                 vclean();
  39.  
  40.         /*
  41.          * Forget all that we once knew.
  42.          */
  43.         vcnt = vcline = 0;
  44.         p = WBOT; LASTLINE = WBOT + 1;
  45.         state = bastate;
  46.         WTOP = basWTOP;
  47.         WLINES = basWLINES;
  48.     }
  49.     vpc = &vlinfo[vcline];
  50.     for (vp = &vlinfo[vcnt]; vp >= vpc; vp--)
  51.         vlcopy(vp[1], vp[0]);
  52.     vcnt++;
  53.     if (Pline == numbline)
  54.         /*
  55.          * Dirtying all the lines is rather inefficient
  56.          * internally, but number mode is used rarely
  57.          * and so its not worth optimizing.
  58.          */
  59.         vdirty(vcline+1, WECHO);
  60.     getline(*tp);
  61.  
  62.     /*
  63.      * If we are opening at the top of the window, can try a window
  64.      * expansion at the top.
  65.      */
  66.     if (state == VISUAL && vcline == 0 && vcnt > 1 && p > ZERO) {
  67.         cnt = p + vdepth() - LINE(1);
  68.         if (cnt > 0) {
  69.             p -= cnt;
  70.             if (p < ZERO)
  71.                 p = ZERO;
  72.             WTOP = p;
  73.             WLINES = WBOT - WTOP + 1;
  74.         }
  75.     }
  76.     vpc->vliny = p, vpc->vdepth = 0, vpc->vflags = 0;
  77.     cnt = vreopen(p, lineno(tp), vcline);
  78.     if (vcline + 1 == vcnt)
  79.         LINE(vcnt) = LINE(vcline) + cnt;
  80. }
  81.  
  82. /*
  83.  * Redisplay logical line l at physical line p with line number lineno.
  84.  */
  85. vreopen(p, lineno, l)
  86.     int p, lineno, l;
  87. {
  88.     register int d;
  89.     register struct vlinfo *vp = &vlinfo[l];
  90.  
  91. #ifdef ADEBUG
  92.     if (trace)
  93.         tfixnl(), fprintf(trace, "vreopen(%d, %d, %d)\n", p, lineno, l);
  94. #endif
  95.     d = vp->vdepth;
  96.     if (d == 0 || (vp->vflags & VDIRT))
  97.         vp->vdepth = d = vdepth();
  98.     vp->vliny = p, vp->vflags &= ~VDIRT;
  99.  
  100.     /*
  101.      * Try to win by making the screen larger rather than inserting
  102.      * a line and driving text off the bottom.
  103.      */
  104.     p = vglitchup(l, 0);
  105.  
  106.     /*
  107.      * BUG:        Should consider using CE here to clear to end of line.
  108.      *        As it stands we always strike over the current text.
  109.      *        Since often the current text is the same as what
  110.      *        we are overstriking with, it tends not to show.
  111.      *        On the other hand if it is different and we end up
  112.      *        spacing out a lot of text, we could have won with
  113.      *        a CE.  This is probably worthwhile at low speed
  114.      *        only however, since clearly computation will be
  115.      *        necessary to determine which way to go.
  116.      */
  117.     vigoto(p, 0);
  118.     pline(lineno);
  119.  
  120.     /*
  121.      * When we are typing part of a line for hardcopy open, don't
  122.      * want to type the '$' marking an end of line if in list mode.
  123.      */
  124.     if (hold & HOLDDOL)
  125.         return (d);
  126.     if (Putchar == listchar)
  127.         putchar('$');
  128.  
  129.     /*
  130.      * Optimization of cursor motion may prevent screen rollup if the
  131.      * line has blanks/tabs at the end unless we force the cursor to appear
  132.      * on the last line segment.
  133.      */
  134.     if (vp->vliny + d - 1 > WBOT)
  135.         vcsync();
  136.  
  137.     /*
  138.      * Switch into hardcopy open mode if we are in one line (adm3)
  139.      * open mode and this line is now too long.  If in hardcopy
  140.      * open mode, then call sethard to move onto the next line
  141.      * with appropriate positioning.
  142.      */
  143.     if (state == ONEOPEN) {
  144.         WCOLS = OCOLUMNS;
  145.         if (vdepth() > 1) {
  146.             WCOLS = TUBECOLS;
  147.             sethard();
  148.         } else
  149.             WCOLS = TUBECOLS;
  150.     } else if (state == HARDOPEN)
  151.         sethard();
  152.  
  153.     /*
  154.      * Unless we filled (completely) the last line we typed on,
  155.      * we have to clear to the end of the line
  156.      * in case stuff is left from before.
  157.      */
  158.     if (vp->vliny + d > destline) {
  159.         if (IN && destcol == WCOLS)
  160.             vigoto(vp->vliny + d - 1, 0);
  161.         vclreol();
  162.     }
  163.     return (d);
  164. }
  165.  
  166. /*
  167.  * Real work for winning growing of window at top
  168.  * when inserting in the middle of a partially full
  169.  * screen on an intelligent terminal.  We have as argument
  170.  * the logical line number to be inserted after, and the offset
  171.  * from that line where the insert will go.
  172.  * We look at the picture of depths and positions, and if we can
  173.  * delete some (blank) lines from the top of the screen so that
  174.  * later inserts will not push stuff off the bottom.
  175.  */
  176. vglitchup(l, o)
  177.     int l, o;
  178. {
  179.     register struct vlinfo *vp = &vlinfo[l];
  180.     register int need;
  181.     register int p = vp->vliny;
  182.     short oldhold, oldheldech;
  183.     bool glitched = 0;
  184.  
  185.      if (l < vcnt - 1) {
  186.         need = p + vp->vdepth - (vp+1)->vliny;
  187.         if (need > 0) {
  188.             if (state == VISUAL && WTOP - ZERO >= need && AL && DL) {
  189.                 glitched++;
  190.                 WTOP -= need;
  191.                 WLINES = WBOT - WTOP + 1;
  192.                 p -= need;
  193.                 if (p == WTOP) {
  194.                     vp->vliny = WTOP;
  195.                     return (WTOP + o);
  196.                 }
  197.                 vdellin(WTOP, need, -1);
  198.                 oldheldech = heldech;
  199.                 oldhold = hold;
  200.                 hold |= HOLDECH;
  201.             }
  202.             vinslin((vp+1)->vliny, need, l);
  203.             if (glitched) {
  204.                 hold = oldhold;
  205.                 heldech = oldheldech;
  206.             }
  207.         }
  208.     } else
  209.         vp[1].vliny = vp[0].vliny + vp->vdepth;
  210.     return (p + o);
  211. }
  212.  
  213. /*
  214.  * Insert cnt blank lines before line p,
  215.  * logically and (if supported) physically.
  216.  */
  217. vinslin(p, cnt, l)
  218.     register int p, cnt;
  219.     int l;
  220. {
  221.     register int i;
  222.     bool could = 1;
  223.  
  224. #ifdef ADEBUG
  225.     if (trace)
  226.         tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l);
  227. #endif
  228.     if (p + cnt > WBOT && CD) {
  229.         /*
  230.          * Really quick -- clear to end of screen.
  231.          */
  232.         cnt = WECHO + 1 - p;
  233.         vgoto(p, 0), vputp(CD, cnt);
  234.         vclrech(1);
  235.         vadjAL(p, cnt);
  236.     } else if (AL) {
  237.         /*
  238.          * Use insert line.
  239.          */
  240.         vgoto(p, 0), vputp(AL, WECHO + 1 - p);
  241.         for (i = cnt - 1; i > 0; i--) {
  242.             vgoto(outline+1, 0), vputp(AL, WECHO + 1 - outline);
  243.             if ((hold & HOLDAT) == 0)
  244.                 putchar('@');
  245.         }
  246.         vadjAL(p, cnt);
  247.     } else if (SR && p == WTOP) {
  248.         /*
  249.          * Use reverse scroll mode of the terminal, at
  250.          * the top of the window.
  251.          */
  252.         for (i = cnt; i > 0; i--) {
  253.             vgoto(p, 0), vputp(SR, 0);
  254.             if (i > 1 && (hold & HOLDAT) == 0)
  255.                 putchar('@');
  256.             /*
  257.              * If we are at the top of the screen, and the
  258.              * terminal retains display above, then we
  259.              * should try to clear to end of line.
  260.              * Have to use CE since we don't remember what is
  261.              * actually on the line.
  262.              */
  263.             if (CE && (DA || p != 0))
  264.                 vputp(CE, 1);
  265.         }
  266.         vadjAL(p, cnt);
  267.     } else
  268.         could = 0;
  269.     vopenup(cnt, could, l);
  270. }
  271.  
  272. /*
  273.  * Logically open up after line l, cnt of them.
  274.  * We need to know if it was done ``physically'' since in this
  275.  * case we accept what the hardware gives us.  If we have to do
  276.  * it ourselves (brute force) we will squish out @ lines in the process
  277.  * if this will save us work.
  278.  */
  279. vopenup(cnt, could, l)
  280.     int cnt;
  281.     bool could;
  282. {
  283.     register struct vlinfo *vc = &vlinfo[l + 1];
  284.     register struct vlinfo *ve = &vlinfo[vcnt];
  285.  
  286. #ifdef ADEBUG
  287.     if (trace)
  288.         tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l);
  289. #endif
  290.     if (could)
  291.         /*
  292.          * This will push @ lines down the screen,
  293.          * just as the hardware did.  Since the default
  294.          * for intelligent terminals is to never have @
  295.          * lines on the screen, this should never happen,
  296.          * and the code makes no special effort to be nice in this
  297.          * case, e.g. squishing out the @ lines by delete lines
  298.          * before doing append lines.
  299.          */
  300.         for (; vc <= ve; vc++)
  301.             vc->vliny += cnt;
  302.     else {
  303.         /*
  304.          * Will have to clean up brute force eventually,
  305.          * so push the line data around as little as possible.
  306.          */
  307.         vc->vliny += cnt, vc->vflags |= VDIRT;
  308.         while (vc < ve) {
  309.             register int i = vc->vliny + vc->vdepth;
  310.  
  311.             vc++;
  312.             if (i <= vc->vliny)
  313.                 break;
  314.             vc->vliny = i, vc->vflags |= VDIRT;
  315.         }
  316.     }
  317.     vscrap();
  318. }
  319.  
  320. /*
  321.  * Adjust data structure internally to account for insertion of
  322.  * blank lines on the screen.
  323.  */
  324. vadjAL(p, cnt)
  325.     int p, cnt;
  326. {
  327.     char *tlines[TUBELINES];
  328.     register int from, to;
  329.  
  330. #ifdef ADEBUG
  331.     if (trace)
  332.         tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt);
  333. #endif
  334.     copy(tlines, vtube, sizeof vtube);    /*SASSIGN*/
  335.     for (from = p, to = p + cnt; to <= WECHO; from++, to++)
  336.         vtube[to] = tlines[from];
  337.     for (to = p; from <= WECHO; from++, to++) {
  338.         vtube[to] = tlines[from];
  339.         vclrbyte(vtube[to], WCOLS);
  340.     }
  341.     /*
  342.      * Have to clear the echo area since its contents aren't
  343.      * necessarily consistent with the rest of the display.
  344.      */
  345.     vclrech(0);
  346. }
  347.  
  348. /*
  349.  * Roll the screen up logically and physically
  350.  * so that line dl is the bottom line on the screen.
  351.  */
  352. vrollup(dl)
  353.     int dl;
  354. {
  355.     register int cnt;
  356.     register int dc = destcol;
  357.  
  358. #ifdef ADEBUG
  359.     if (trace)
  360.         tfixnl(), fprintf(trace, "vrollup(%d)\n", dl);
  361. #endif
  362.     cnt = dl - (splitw ? WECHO : WBOT);
  363.     if (splitw && (state == VISUAL || state == CRTOPEN))
  364.         holdupd = 1;
  365.     vscroll(cnt);
  366.     vmoveitup(cnt);
  367.     destline = dl - cnt, destcol = dc;
  368. }
  369.  
  370. vup1()
  371. {
  372.  
  373.     vrollup(WBOT + 1);
  374. }
  375.  
  376. /*
  377.  * Scroll the screen up cnt lines physically.
  378.  */
  379. vmoveitup(cnt)
  380.     register int cnt;
  381. {
  382.  
  383.     if (cnt == 0)
  384.         return;
  385. #ifdef ADEBUG
  386.     if (trace)
  387.         tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
  388. #endif
  389.     if (SF) {
  390.         while (cnt > 0)
  391.             vputp(SF, 0), cnt--;
  392.         return;
  393.     }
  394.     destline = WECHO + cnt;
  395.     destcol = (NONL ? 0 : outcol % WCOLS);
  396.     fgoto();
  397.     if (state == ONEOPEN || state == HARDOPEN) {
  398.         outline = destline = 0;
  399.         vclrbyte(vtube[0], WCOLS);
  400.     }
  401. }
  402.  
  403. /*
  404.  * Scroll the screen up cnt lines logically.
  405.  */
  406. vscroll(cnt)
  407.     register int cnt;
  408. {
  409.     register int from, to;
  410.     char *tlines[TUBELINES];
  411.  
  412. #ifdef ADEBUG
  413.     if (trace)
  414.         fprintf(trace, "vscroll(%d)\n", cnt);
  415. #endif
  416.     if (cnt < 0 || cnt > TUBELINES)
  417.         error("Internal error: vscroll");
  418.     if (cnt == 0)
  419.         return;
  420.     copy(tlines, vtube, sizeof vtube);
  421.     for (to = ZERO, from = ZERO + cnt; to <= WECHO - cnt; to++, from++)
  422.         vtube[to] = tlines[from];
  423.     for (from = ZERO; to <= WECHO; to++, from++) {
  424.         vtube[to] = tlines[from];
  425.         vclrbyte(vtube[to], WCOLS);
  426.     }
  427.     for (from = 0; from <= vcnt; from++)
  428.         LINE(from) -= cnt;
  429. }
  430.  
  431. /*
  432.  * Discard logical lines due to physical wandering off the screen.
  433.  */
  434. vscrap()
  435. {
  436.     register int i, j;
  437.  
  438. #ifdef ADEBUG
  439.     if (trace)
  440.         tfixnl(), fprintf(trace, "vscrap\n"), tvliny();
  441. #endif
  442.     if (splitw)
  443.         return;
  444.     if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ZERO) {
  445.         WTOP = LINE(0);
  446.         WLINES = WBOT - WTOP + 1;
  447.     }
  448.     for (j = 0; j < vcnt; j++)
  449.         if (LINE(j) >= WTOP) {
  450.             if (j == 0)
  451.                 break;
  452.             /*
  453.              * Discard the first j physical lines off the top.
  454.              */
  455.             vcnt -= j, vcline -= j;
  456.             for (i = 0; i <= vcnt; i++)
  457.                 vlcopy(vlinfo[i], vlinfo[i + j]);
  458.             break;
  459.         }
  460.     /*
  461.      * Discard lines off the bottom.
  462.      */
  463.     if (vcnt) {
  464.         for (j = 0; j <= vcnt; j++)
  465.             if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) {
  466.                 vcnt = j;
  467.                 break;
  468.             }
  469.         LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1);
  470.     }
  471. #ifdef ADEBUG
  472.     if (trace)
  473.         tvliny();
  474. #endif
  475.     /*
  476.      * May have no lines!
  477.      */
  478. }
  479.  
  480. /*
  481.  * Repaint the screen, with cursor at curs, aftern an arbitrary change.
  482.  * Handle notification on large changes.
  483.  */
  484. vrepaint(curs)
  485.     char *curs;
  486. {
  487.  
  488.     wdot = NOLINE;
  489.     /*
  490.      * In open want to notify first.
  491.      */
  492.     noteit(0);
  493.     vscrap();
  494.  
  495.     /*
  496.      * Deal with a totally useless display.
  497.      */
  498.     if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) {
  499.         register line *odol = dol;
  500.  
  501.         vcnt = 0;
  502.         if (holdupd)
  503.             if (state == VISUAL)
  504.                 ignore(peekkey());
  505.             else
  506.                 vup1();
  507.         holdupd = 0;
  508.         if (odol == zero)
  509.             fixzero();
  510.         vcontext(dot, '.');
  511.         noteit(1);
  512.         if (noteit(1) == 0 && odol == zero) {
  513.             CATCH
  514.                 error("No lines in buffer");
  515.             ENDCATCH
  516.             linebuf[0] = 0;
  517.             splitw = 0;
  518.         }
  519.         vnline(curs);
  520.         return;
  521.     }
  522.  
  523.     /*
  524.      * Have some useful displayed text; refresh it.
  525.      */
  526.     getDOT();
  527.  
  528.     /*
  529.      * This is for boundary conditions in open mode.
  530.      */
  531.     if (FLAGS(0) & VDIRT)
  532.         vsync(WTOP);
  533.     
  534.     /*
  535.      * If the current line is after the last displayed line
  536.      * or the bottom of the screen, then special effort is needed
  537.      * to get it on the screen.  We first try a redraw at the
  538.      * last line on the screen, hoping it will fill in where @
  539.      * lines are now.  If this doesn't work, then roll it onto
  540.      * the screen.
  541.      */
  542.     if (vcline == vcnt || LINE(vcline) > WBOT) {
  543.         short oldhold = hold;
  544.         hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold;
  545.         if (vcline == vcnt) 
  546.             vcline--, dot--, vroll(1);
  547.         else
  548.             vsyncCL();
  549.     } else
  550.         vsync(vcline > 0 ? LINE(vcline - 1) : WTOP);
  551.  
  552.     /*
  553.      * Notification on large change for visual
  554.      * has to be done last or we may lose
  555.      * the echo area with redisplay.
  556.      */
  557.     noteit(1);
  558.  
  559.     /*
  560.      * Finally.  Move the cursor onto the current line.
  561.      */
  562.     vnline(curs);
  563. }
  564.  
  565. /*
  566.  * Fully cleanup the screen, leaving no @ lines except at end when
  567.  * line after last won't completely fit.  The routine vsync is
  568.  * more conservative and much less work on dumb terminals.
  569.  */
  570. vredraw(p)
  571.     register int p;
  572. {
  573.     register int l;
  574.     register line *tp;
  575.     char temp[LBSIZE];
  576.     bool anydl = 0;
  577.     short oldhold = hold;
  578.  
  579. #ifdef ADEBUG
  580.     if (trace)
  581.         tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
  582. #endif
  583.     if (holdupd) {
  584.         holdupd = 3;
  585.         return;
  586.     }
  587.     if (state == HARDOPEN || splitw)
  588.         return;
  589.     if (p < 0 || p > WECHO)
  590.         error("Internal error: vredraw");
  591.  
  592.     /*
  593.      * Trim the ragged edges (lines which are off the screen but
  594.      * not yet logically discarded), save the current line, and
  595.      * search for first logical line affected by the redraw.
  596.      */
  597.     vscrap();
  598.     CP(temp, linebuf);
  599.     l = 0;
  600.     tp = dot - vcline;
  601.     if (vcnt == 0)
  602.         LINE(0) = WTOP;
  603.     while (l < vcnt && LINE(l) < p)
  604.         l++, tp++;
  605.  
  606.     /*
  607.      * We hold off echo area clearing during the redraw in deference
  608.      * to a final clear of the echo area at the end if appropriate.
  609.      */
  610.     heldech = 0;
  611.     hold |= HOLDECH;
  612.     for (; l < vcnt && Peekkey != ATTN; l++) {
  613.         if (l == vcline)
  614.             strcLIN(temp);
  615.         else
  616.             getline(*tp);
  617.  
  618.         /*
  619.          * Delete junk between displayed lines.
  620.          */
  621.         if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
  622.             if (anydl == 0 && DB && CD) {
  623.                 hold = oldhold;
  624.                 vclrech(0);
  625.                 anydl = 1;
  626.                 hold |= HOLDECH;
  627.                 heldech = 0;
  628.             }
  629.             vdellin(p, LINE(l) - p, l);
  630.         }
  631.  
  632.         /*
  633.          * If line image is not know to be up to date, then
  634.          * redisplay it;  else just skip onward.
  635.          */
  636.         LINE(l) = p;
  637.         if (FLAGS(l) & VDIRT) {
  638.             DEPTH(l) = vdepth();
  639.             FLAGS(l) &= ~VDIRT;
  640.             if (l != vcline && p + DEPTH(l) - 1 > WBOT)
  641.                 break;
  642.             vreopen(p, lineno(tp), l);
  643.             p = LINE(l) + DEPTH(l);
  644.         } else
  645.             p += DEPTH(l);
  646.         tp++;
  647.     }
  648.  
  649.     /*
  650.      * That takes care of lines which were already partially displayed.
  651.      * Now try to fill the rest of the screen with text.
  652.      */
  653.     if (state == VISUAL && p <= WBOT) {
  654.         int ovcline = vcline;
  655.  
  656.         vcline = l;
  657.         for (; tp <= dol && Peekkey != ATTN; tp++) {
  658.             getline(*tp);
  659.             if (p + vdepth() - 1 > WBOT)
  660.                 break;
  661.             vopen(tp, p);
  662.             p += DEPTH(vcline);
  663.             vcline++;
  664.         }
  665.         vcline = ovcline;
  666.     }
  667.  
  668.     /*
  669.      * Thats all the text we can get on.
  670.      * Now rest of lines (if any) get either a ~ if they
  671.      * are past end of file, or an @ if the next line won't fit.
  672.      */
  673.     for (; p <= WBOT && Peekkey != ATTN; p++)            
  674.         vclrlin(p, tp);
  675.     strcLIN(temp);
  676.     hold = oldhold;
  677.     if (heldech)
  678.         vclrech(0);
  679. #ifdef ADEBUG
  680.     if (trace)
  681.         tvliny();
  682. #endif
  683. }
  684.  
  685. /*
  686.  * Do the real work in deleting cnt lines starting at line p from
  687.  * the display.  First affected line is line l.
  688.  */
  689. vdellin(p, cnt, l)
  690.     int p, cnt, l;
  691. {
  692.     register int i;
  693.  
  694.     if (cnt == 0)
  695.         return;
  696.     if (DL == NOSTR || cnt < 0) {
  697.         /*
  698.          * Can't do it; just remember that line l is munged.
  699.          */
  700.         FLAGS(l) |= VDIRT;
  701.         return;
  702.     }
  703. #ifdef ADEBUG
  704.     if (trace)
  705.         tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
  706. #endif
  707.     /*
  708.      * Send the deletes to the screen and then adjust logical
  709.      * and physical internal data structures.
  710.      */
  711.     vgoto(p, 0);
  712.     for (i = 0; i < cnt; i++)
  713.         vputp(DL, WECHO - p);
  714.     vadjDL(p, cnt);
  715.     vcloseup(l, cnt);
  716. }
  717. /*
  718.  * Adjust internal physical screen image to account for deleted lines.
  719.  */
  720. vadjDL(p, cnt)
  721.     int p, cnt;
  722. {
  723.     char *tlines[TUBELINES];
  724.     register int from, to;
  725.  
  726. #ifdef ADEBUG
  727.     if (trace)
  728.         tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt);
  729. #endif
  730.     /*
  731.      * Would like to use structured assignment but early
  732.      * v7 compiler (released with phototypesetter for v6)
  733.      * can't hack it.
  734.      */
  735.     copy(tlines, vtube, sizeof vtube);    /*SASSIGN*/
  736.     for (from = p + cnt, to = p; from <= WECHO; from++, to++)
  737.         vtube[to] = tlines[from];
  738.     for (from = p; to <= WECHO; from++, to++) {
  739.         vtube[to] = tlines[from];
  740.         vclrbyte(vtube[to], WCOLS);
  741.     }
  742. }
  743. /*
  744.  * Sync the screen, like redraw but more lazy and willing to leave
  745.  * @ lines on the screen.  VsyncCL syncs starting at the current line.
  746.  * In any case, if the redraw option is set then all syncs map to redraws
  747.  * as if vsync didn't exist.
  748.  */
  749. vsyncCL()
  750. {
  751.  
  752.     vsync(LINE(vcline));
  753. }
  754.  
  755. vsync(p)
  756.     register int p;
  757. {
  758.  
  759.     if (value(REDRAW))
  760.         vredraw(p);
  761.     else
  762.         vsync1(p);
  763. }
  764.  
  765. /*
  766.  * The guts of a sync.  Similar to redraw but
  767.  * just less ambitous.
  768.  */
  769. vsync1(p)
  770.     register int p;
  771. {
  772.     register int l;
  773.     char temp[LBSIZE];
  774.     register struct vlinfo *vp = &vlinfo[0];
  775.     short oldhold = hold;
  776.  
  777. #ifdef ADEBUG
  778.     if (trace)
  779.         tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny();
  780. #endif
  781.     if (holdupd) {
  782.         if (holdupd < 3)
  783.             holdupd = 2;
  784.         return;
  785.     }
  786.     if (state == HARDOPEN || splitw)
  787.         return;
  788.     vscrap();
  789.     CP(temp, linebuf);
  790.     if (vcnt == 0)
  791.         LINE(0) = WTOP;
  792.     l = 0;
  793.     while (l < vcnt && vp->vliny < p)
  794.         l++, vp++;
  795.     heldech = 0;
  796.     hold |= HOLDECH;
  797.     while (p <= WBOT && Peekkey != ATTN) {
  798.         /*
  799.          * Want to put a line here if not in visual and first line
  800.          * or if there are lies left and this line starts before
  801.          * the current line, or if this line is piled under the
  802.          * next line (vreplace does this and we undo it).
  803.          */
  804.         if (l == 0 && state != VISUAL || (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) {
  805.             if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) {
  806.                 if (l == vcline)
  807.                     strcLIN(temp);
  808.                 else
  809.                     getline(dot[l - vcline]);
  810.                 /*
  811.                  * Be careful that a long line doesn't cause the
  812.                  * screen to shoot up.
  813.                  */
  814.                 if (l != vcline && (vp->vflags & VDIRT)) {
  815.                     vp->vdepth = vdepth();
  816.                     vp->vflags &= ~VDIRT;
  817.                     if (p + vp->vdepth - 1 > WBOT)
  818.                         break;
  819.                 }
  820.                 vreopen(p, lineDOT() + (l - vcline), l);
  821.             }
  822.             p = vp->vliny + vp->vdepth;
  823.             vp++;
  824.             l++;
  825.         } else
  826.             /*
  827.              * A physical line between logical lines,
  828.              * so we settle for an @ at the beginning.
  829.              */
  830.             vclrlin(p, dot + (l - vcline)), p++;
  831.     }
  832.     strcLIN(temp);
  833.     hold = oldhold;
  834.     if (heldech)
  835.         vclrech(0);
  836. }
  837.  
  838. /*
  839.  * Subtract (logically) cnt physical lines from the 
  840.  * displayed position of lines starting with line l.
  841.  */
  842. vcloseup(l, cnt)
  843.     int l;
  844.     register int cnt;
  845. {
  846.     register int i;
  847.  
  848. #ifdef ADEBUG
  849.     if (trace)
  850.         tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt);
  851. #endif
  852.     for (i = l + 1; i <= vcnt; i++)
  853.         LINE(i) -= cnt;
  854. }
  855.  
  856. /*
  857.  * Workhorse for rearranging line descriptors on changes.
  858.  * The idea here is that, starting with line l, cnt lines
  859.  * have been replaced with newcnt lines.  All of these may
  860.  * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
  861.  * since we may be called from an undo after the screen has
  862.  * moved a lot.  Thus we have to be careful.
  863.  *
  864.  * Many boundary conditions here.
  865.  */
  866. vreplace(l, cnt, newcnt)
  867.     int l, cnt, newcnt;
  868. {
  869.     register int from, to, i;
  870.     bool savenote = 0;
  871.  
  872. #ifdef ADEBUG
  873.     if (trace) {
  874.         tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
  875.         tvliny();
  876.     }
  877. #endif
  878.     if (l >= vcnt)
  879.         return;
  880.     if (l < 0) {
  881.         if (l + cnt < 0) {
  882.             /*
  883.              * Nothing on the screen is relevant.
  884.              * Settle for redrawing from scratch (later).
  885.              */
  886.             vcnt = 0;
  887.             return;
  888.         }
  889.         /*
  890.          * Normalize l to top of screen; the add is
  891.          * really a subtract from cnt since l is negative.
  892.          */
  893.         cnt += l;
  894.         l = 0;
  895.  
  896.         /*
  897.          * Unseen lines were affect so notify (later).
  898.          */
  899.         savenote++;
  900.     }
  901.  
  902.     /*
  903.      * These shouldn't happen
  904.      * but would cause great havoc.
  905.      */
  906.     if (cnt < 0)
  907.         cnt = 0;
  908.     if (newcnt < 0)
  909.         newcnt = 0;
  910.  
  911.     /*
  912.      * Surely worthy of note if more than report
  913.      * lines were changed.
  914.      */
  915.     if (cnt > value(REPORT) || newcnt > value(REPORT))
  916.         savenote++;
  917.  
  918.     /*
  919.      * Same number of lines affeted as on screen, and we
  920.      * can insert and delete lines.  Thus we just type
  921.      * over them, since otherwise we will push them
  922.      * slowly off the screen, a clear lose.
  923.      */
  924.     if (cnt == newcnt || vcnt - l == newcnt && AL && DL) {
  925.         if (cnt > 1 && l + cnt > vcnt)
  926.             savenote++;
  927.         vdirty(l, newcnt);
  928.     } else {
  929.         /*
  930.          * Lines are going away, squish them out.
  931.          */
  932.         if (cnt > 0) {
  933.             /*
  934.              * If non-displayed lines went away,
  935.              * always notify.
  936.              */
  937.             if (cnt > 1 && l + cnt > vcnt)
  938.                 savenote++;
  939.             if (l + cnt >= vcnt)
  940.                 cnt = vcnt - l;
  941.             else
  942.                 for (from = l + cnt, to = l; from <= vcnt; to++, from++)
  943.                     vlcopy(vlinfo[to], vlinfo[from]);
  944.             vcnt -= cnt;
  945.         }
  946.         /*
  947.          * Open up space for new lines appearing.
  948.          * All new lines are piled in the same place,
  949.          * and will be unpiled by vredraw/vsync, which
  950.          * inserts lines in front as it unpiles.
  951.          */
  952.         if (newcnt > 0) {
  953.             /*
  954.              * Newlines are appearing which may not show,
  955.              * so notify (this is only approximately correct
  956.              * when long lines are present).
  957.              */
  958.             if (newcnt > 1 && l + newcnt > vcnt + 1)
  959.                 savenote++;
  960.  
  961.             /*
  962.              * If there will be more lines than fit, then
  963.              * just throw way the rest of the stuff on the screen.
  964.              */
  965.             if (l + newcnt > WBOT && AL && DL) {
  966.                 vcnt = l;
  967.                 goto skip;
  968.             }
  969.             from = vcnt, to = vcnt + newcnt;
  970.             i = TUBELINES - to;
  971.             if (i < 0)
  972.                 from += i, to += i;
  973.             vcnt = to;
  974.             for (; from >= l; from--, to--)
  975.                 vlcopy(vlinfo[to], vlinfo[from]);
  976.             for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
  977.                 LINE(to) = LINE(from);
  978.                 DEPTH(to) = 0;
  979.                 FLAGS(to) = VDIRT;
  980.             }
  981.         }
  982.     }
  983. skip:
  984.     if (Pline == numbline && cnt != newcnt)
  985.         /*
  986.          * When lines positions are shifted, the numbers
  987.          * will be wrong.
  988.          */
  989.         vdirty(l, WECHO);
  990.     if (!savenote)
  991.         notecnt = 0;
  992. #ifdef ADEBUG
  993.     if (trace)
  994.         tvliny();
  995. #endif
  996. }
  997.  
  998. /*
  999.  * Start harcopy open.
  1000.  * Print an image of the line to the left of the cursor
  1001.  * under the full print of the line and position the cursor.
  1002.  * If we are in a scroll ^D within hardcopy open then all this
  1003.  * is suppressed.
  1004.  */
  1005. sethard()
  1006. {
  1007.  
  1008.     if (state == VISUAL)
  1009.         return;
  1010.     rubble = 0;
  1011.     state = HARDOPEN;
  1012.     if (hold & HOLDROL)
  1013.         return;
  1014.     vup1();
  1015.     LINE(0) = WBOT;
  1016.     if (Pline == numbline)
  1017.         vgoto(WBOT, 0), printf("%6d  ", lineDOT());
  1018. }
  1019.  
  1020. /*
  1021.  * Mark the lines starting at base for i lines
  1022.  * as dirty so that they will be checked for correct
  1023.  * display at next sync/redraw.
  1024.  */
  1025. vdirty(base, i)
  1026.     register int base, i;
  1027. {
  1028.     register int l;
  1029.     
  1030.     for (l = base; l < vcnt; l++) {
  1031.         if (--i < 0)
  1032.             return;
  1033.         FLAGS(l) |= VDIRT;
  1034.     }
  1035. }
  1036.