diff options
Diffstat (limited to 'tree/src/vi/ex-070224/ex_vadj.c')
| -rw-r--r-- | tree/src/vi/ex-070224/ex_vadj.c | 1171 |
1 files changed, 0 insertions, 1171 deletions
diff --git a/tree/src/vi/ex-070224/ex_vadj.c b/tree/src/vi/ex-070224/ex_vadj.c deleted file mode 100644 index c579ee7..0000000 --- a/tree/src/vi/ex-070224/ex_vadj.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * This code contains changes by - * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved. - * - * Conditions 1, 2, and 4 and the no-warranty notice below apply - * to these changes. - * - * - * Copyright (c) 1980, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * Redistributions of source code and documentation must retain the - * above copyright notice, this list of conditions and the following - * disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed or owned by Caldera - * International, Inc. - * Neither the name of Caldera International, Inc. nor the names of - * other contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA - * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE - * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef lint -#ifdef DOSCCS -static char sccsid[] = "@(#)ex_vadj.c 1.16 (gritter) 8/6/05"; -#endif -#endif - -/* from ex_vadj.c 7.9 (Berkeley) 6/7/85 */ - -#include "ex.h" -#include "ex_tty.h" -#include "ex_vis.h" - -/* - * Routines to deal with management of logical versus physical - * display, opening and redisplaying lines on the screen, and - * use of intelligent terminal operations. Routines to deal with - * screen cleanup after a change. - */ - -/* - * Display a new line at physical line p, returning - * the depth of the newly displayed line. We may decide - * to expand the window on an intelligent terminal if it is - * less than a full screen by deleting a line above the top of the - * window before doing an insert line to keep all the good text - * on the screen in which case the line may actually end up - * somewhere other than line p. - */ -void -vopen(line *tp, int p) -{ - register int cnt; - register struct vlinfo *vp, *vpc; - -#ifdef ADEBUG - if (trace != NULL) - tfixnl(), fprintf(trace, "vopen(%d, %d)\n", lineno(tp), p); -#endif - if (state != VISUAL) { - if (vcnt) - if (hold & HOLDROL) - vup1(); - else - vclean(); - - /* - * Forget all that we once knew. - */ - vcnt = vcline = 0; - p = WBOT; LASTLINE = WBOT + 1; - state = bastate; - WTOP = basWTOP; - WLINES = basWLINES; - } - vpc = &vlinfo[vcline]; - for (vp = &vlinfo[vcnt]; vp >= vpc; vp--) - vlcopy(vp[1], vp[0]); - vcnt++; - if (Pline == numbline) - /* - * Dirtying all the lines is rather inefficient - * internally, but number mode is used rarely - * and so its not worth optimizing. - */ - vdirty(vcline+1, WECHO); - getline(*tp); - - /* - * If we are opening at the top of the window, can try a window - * expansion at the top. - */ - if (state == VISUAL && vcline == 0 && vcnt > 1 && p > ZERO) { - cnt = p + vdepth() - LINE(1); - if (cnt > 0) { - p -= cnt; - if (p < ZERO) - p = ZERO; - WTOP = p; - WLINES = WBOT - WTOP + 1; - } - } - vpc->vliny = p, vpc->vdepth = 0, vpc->vflags = 0; - cnt = vreopen(p, lineno(tp), vcline); - if (vcline + 1 == vcnt) - LINE(vcnt) = LINE(vcline) + cnt; -} - -/* - * Redisplay logical line l at physical line p with line number lineno. - */ -int -vreopen(int p, int lineno, int l) -{ - register int d; - register struct vlinfo *vp = &vlinfo[l]; - - if (p < 0) - error("Line too long to fit on screen"); - d = vp->vdepth; - if (d == 0 || (vp->vflags & VDIRT)) - vp->vdepth = d = vdepth(); - vp->vliny = p, vp->vflags &= ~VDIRT; - - /* - * Try to win by making the screen larger rather than inserting - * a line and driving text off the bottom. - */ - p = vglitchup(l, 0); - - /* - * BUG: Should consider using CE here to clear to end of line. - * As it stands we always strike over the current text. - * Since often the current text is the same as what - * we are overstriking with, it tends not to show. - * On the other hand if it is different and we end up - * spacing out a lot of text, we could have won with - * a CE. This is probably worthwhile at low speed - * only however, since clearly computation will be - * necessary to determine which way to go. - */ - vigoto(p, 0); - if (pline(lineno, WCOLS*WLINES) == 1) - vp->vflags |= VLONG; - - /* - * When we are typing part of a line for hardcopy open, don't - * want to type the '$' marking an end of line if in list mode. - */ - if (hold & HOLDDOL) - return (d); - if (Putchar == listchar) - putchar('$'); - - /* - * Optimization of cursor motion may prevent screen rollup if the - * line has blanks/tabs at the end unless we force the cursor to appear - * on the last line segment. - */ - if (vp->vliny + d - 1 > WBOT) - vcsync(); - - /* - * Switch into hardcopy open mode if we are in one line (adm3) - * open mode and this line is now too long. If in hardcopy - * open mode, then call sethard to move onto the next line - * with appropriate positioning. - */ - if (state == ONEOPEN) { - WCOLS = OCOLUMNS; - if (vdepth() > 1) { - WCOLS = TUBECOLS; - sethard(); - } else - WCOLS = TUBECOLS; - } else if (state == HARDOPEN) - sethard(); - - /* - * Unless we filled (completely) the last line we typed on, - * we have to clear to the end of the line - * in case stuff is left from before. - */ - if (vp->vliny + d > destline) { - if (IN && destcol == WCOLS) - vigoto(vp->vliny + d - 1, 0); - vclreol(); - } - return (d); -} - -/* - * Real work for winning growing of window at top - * when inserting in the middle of a partially full - * screen on an intelligent terminal. We have as argument - * the logical line number to be inserted after, and the offset - * from that line where the insert will go. - * We look at the picture of depths and positions, and if we can - * delete some (blank) lines from the top of the screen so that - * later inserts will not push stuff off the bottom. - */ -int -vglitchup(int l, int o) -{ - register struct vlinfo *vp = &vlinfo[l]; - register int need; - register int p = vp->vliny; - short oldhold = 0, oldheldech = 0; - bool glitched = 0; - - if (l < vcnt - 1) { - need = p + vp->vdepth - (vp+1)->vliny; - if (need > 0) { - if (state == VISUAL && WTOP - ZERO >= need && AL && DL) { - glitched++; - WTOP -= need; - WLINES = WBOT - WTOP + 1; - p -= need; - if (p + o == WTOP) { - vp->vliny = WTOP; - return (WTOP + o); - } - vdellin(WTOP, need, -1); - oldheldech = heldech; - oldhold = hold; - hold |= HOLDECH; - } - vinslin((vp+1)->vliny, need, l); - if (glitched) { - hold = oldhold; - heldech = oldheldech; - } - } - } else - vp[1].vliny = vp[0].vliny + vp->vdepth; - return (p + o); -} - -/* - * Insert cnt blank lines before line p, - * logically and (if supported) physically. - */ -void -vinslin(register int p, register int cnt, int l) -{ - register int i; - bool could = 1; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l); -#endif - if (p + cnt > WBOT && CD) { - /* - * Really quick -- clear to end of screen. - */ - cnt = WECHO + 1 - p; - vgoto(p, 0), vputp(CD, cnt); - vclrech(1); - vadjAL(p, cnt); - } else if (SR && p == WTOP && costSR < costAL) { - /* - * Use reverse scroll mode of the terminal, at - * the top of the window. Reverse linefeed works - * too, since we only use it from line WTOP. - */ - for (i = cnt; i > 0; i--) { - vgoto(p, 0), vputp(SR, 0); - if (i > 1 && (hold & HOLDAT) == 0) - putchar('@'); - /* - * If we are at the top of the screen, and the - * terminal retains display above, then we - * should try to clear to end of line. - * Have to use CE since we don't remember what is - * actually on the line. - */ - if (CE && (DA || p != 0)) - vputp(CE, 1); - } - vadjAL(p, cnt); - } else if (AL) { - /* - * Use insert line. - */ - vgoto(p, 0); - if (AL_PARM && (cnt>1 || *AL==0)) { - /* insert cnt lines. Should do @'s too. */ - vputp(tgoto(AL_PARM, p, cnt), WECHO+1-p); - } - else if (xCS && *AL==0) { - /* vt100 change scrolling region to fake AL */ - vputp(SC, 1); - vputp(tgoto(xCS, TLINES-1,p), 1); - vputp(RC, 1); /* xCS homes stupid cursor */ - for (i=cnt; i>0; i--) - vputp(SR, 1); /* should do @'s */ - vputp(tgoto(xCS, TLINES-1,0), 1); - vputp(RC, 1); /* Once again put it back */ - } - else { - vputp(AL, WECHO + 1 - p); - for (i = cnt - 1; i > 0; i--) { - vgoto(outline+1, 0); - vputp(AL, WECHO + 1 - outline); - if ((hold & HOLDAT) == 0) - putchar('@'); - } - } - vadjAL(p, cnt); - } else - could = 0; - vopenup(cnt, could, l); -} - -/* - * Logically open up after line l, cnt of them. - * We need to know if it was done ``physically'' since in this - * case we accept what the hardware gives us. If we have to do - * it ourselves (brute force) we will squish out @ lines in the process - * if this will save us work. - */ -void -vopenup(int cnt, int could, int l) -{ - register struct vlinfo *vc = &vlinfo[l + 1]; - register struct vlinfo *ve = &vlinfo[vcnt]; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l); -#endif - if (could) - /* - * This will push @ lines down the screen, - * just as the hardware did. Since the default - * for intelligent terminals is to never have @ - * lines on the screen, this should never happen, - * and the code makes no special effort to be nice in this - * case, e.g. squishing out the @ lines by delete lines - * before doing append lines. - */ - for (; vc <= ve; vc++) - vc->vliny += cnt; - else { - /* - * Will have to clean up brute force eventually, - * so push the line data around as little as possible. - */ - vc->vliny += cnt, vc->vflags |= VDIRT; - while (vc < ve) { - register int i = vc->vliny + vc->vdepth; - - vc++; - if (i <= vc->vliny) - break; - vc->vliny = i, vc->vflags |= VDIRT; - } - } - vscrap(); -} - -/* - * Adjust data structure internally to account for insertion of - * blank lines on the screen. - */ -void -vadjAL(int p, int cnt) -{ - cell **tlines = smalloc(TUBELINES * sizeof *tlines); - register int from, to; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt); -#endif - copy(tlines, vtube, TUBELINES * sizeof *tlines); /*SASSIGN*/ - for (from = p, to = p + cnt; to <= WECHO; from++, to++) - vtube[to] = tlines[from]; - for (to = p; from <= WECHO; from++, to++) { - vtube[to] = tlines[from]; - vclrcell(vtube[to], WCOLS); - } - /* - * Have to clear the echo area since its contents aren't - * necessarily consistent with the rest of the display. - */ - vclrech(0); - free(tlines); -} - -/* - * Roll the screen up logically and physically - * so that line dl is the bottom line on the screen. - */ -void -vrollup(int dl) -{ - register int cnt; - register int dc = destcol; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vrollup(%d)\n", dl); -#endif - cnt = dl - (splitw ? WECHO : WBOT); - if (splitw && (state == VISUAL || state == CRTOPEN)) - holdupd = 1; - vmoveitup(cnt, 1); - vscroll(cnt); - destline = dl - cnt, destcol = dc; -} - -void -vup1(void) -{ - - vrollup(WBOT + 1); -} - -/* - * Scroll the screen up cnt lines physically. - * If doclr is true, do a clear eol if the terminal - * has standout (to prevent it from scrolling up) - */ -void -vmoveitup(register int cnt, int doclr) -{ - - if (cnt == 0) - return; -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt); -#endif - if (doclr && (SO || SE)) - vclrech(0); - if (SF) { - destline = WECHO; - destcol = (NONL ? 0 : outcol % WCOLS); - fgoto(); - while (cnt > 0) - vputp(SF, 0), cnt--; - return; - } - destline = WECHO + cnt; - destcol = (NONL ? 0 : outcol % WCOLS); - fgoto(); - if (state == ONEOPEN || state == HARDOPEN) { - outline = destline = 0; - vclrcell(vtube[0], WCOLS); - } -} - -/* - * Scroll the screen up cnt lines logically. - */ -void -vscroll(register int cnt) -{ - register int from, to; - cell **tlines; - -#ifdef ADEBUG - if (trace) - fprintf(trace, "vscroll(%d)\n", cnt); -#endif - if (cnt < 0 || cnt > TUBELINES) - error(catgets(catd, 1, 219, "Internal error: vscroll")); - if (cnt == 0) - return; - tlines = smalloc(TUBELINES * sizeof *tlines); - copy(tlines, vtube, TUBELINES * sizeof *tlines); - for (to = ZERO, from = ZERO + cnt; to <= WECHO - cnt; to++, from++) - vtube[to] = tlines[from]; - for (from = ZERO; to <= WECHO; to++, from++) { - vtube[to] = tlines[from]; - vclrcell(vtube[to], WCOLS); - } - for (from = 0; from <= vcnt; from++) - LINE(from) -= cnt; - free(tlines); -} - -/* - * Discard logical lines due to physical wandering off the screen. - */ -void -vscrap(void) -{ - register int i, j; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vscrap\n"), tvliny(); -#endif - if (splitw) - return; - if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ZERO) { - WTOP = LINE(0); - WLINES = WBOT - WTOP + 1; - } - for (j = 0; j < vcnt; j++) - if (LINE(j) >= WTOP) { - if (j == 0) - break; - /* - * Discard the first j physical lines off the top. - */ - vcnt -= j, vcline -= j; - for (i = 0; i <= vcnt; i++) - vlcopy(vlinfo[i], vlinfo[i + j]); - break; - } - /* - * Discard lines off the bottom. - */ - if (vcnt) { - for (j = 0; j <= vcnt; j++) - if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) { - vcnt = j; - break; - } - LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1); - } -#ifdef ADEBUG - if (trace) - tvliny(); -#endif - /* - * May have no lines! - */ -} - -/* - * Repaint the screen, with cursor at curs, aftern an arbitrary change. - * Handle notification on large changes. - */ -void -vrepaint(char *curs) -{ - - wdot = NOLINE; - /* - * In open want to notify first. - */ - noteit(0); - vscrap(); - - /* - * Deal with a totally useless display. - */ - if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) { - register line *odol = dol; - - vcnt = 0; - if (holdupd) - if (state == VISUAL) - ignore(peekkey()); - else - vup1(); - holdupd = 0; - if (odol == zero) - fixzero(); - vcontext(dot, '.'); - noteit(1); - if (noteit(1) == 0 && odol == zero) { - CATCH - error(catgets(catd, 1, 220, - "No lines in buffer")); - ENDCATCH - linebuf[0] = 0; - splitw = 0; - } - vnline(curs); - return; - } - - /* - * Have some useful displayed text; refresh it. - */ - getDOT(); - - /* - * This is for boundary conditions in open mode. - */ - if (FLAGS(0) & VDIRT) - vsync(WTOP); - - /* - * If the current line is after the last displayed line - * or the bottom of the screen, then special effort is needed - * to get it on the screen. We first try a redraw at the - * last line on the screen, hoping it will fill in where @ - * lines are now. If this doesn't work, then roll it onto - * the screen. - */ - if (vcline >= vcnt || LINE(vcline) > WBOT) { - short oldhold = hold; - hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold; - if (vcline >= vcnt) { - register int i = vcline - vcnt + 1; - - dot -= i; - vcline -= i; - vroll(i); - } else - vsyncCL(); - } else - vsync(vcline > 0 ? LINE(vcline - 1) : WTOP); - - /* - * Notification on large change for visual - * has to be done last or we may lose - * the echo area with redisplay. - */ - noteit(1); - - /* - * Finally. Move the cursor onto the current line. - */ - vnline(curs); -} - -/* - * Fully cleanup the screen, leaving no @ lines except at end when - * line after last won't completely fit. The routine vsync is - * more conservative and much less work on dumb terminals. - */ -void -vredraw(register int p) -{ - register int l; - register line *tp; - char *temp; - bool anydl = 0; - short oldhold = hold; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny(); -#endif - if (holdupd) { - holdupd = 3; - return; - } - if (state == HARDOPEN || splitw) - return; - if (p < 0 /* || p > WECHO */) - error(catgets(catd, 1, 221, "Internal error: vredraw")); - - temp = smalloc(LBSIZE); - /* - * Trim the ragged edges (lines which are off the screen but - * not yet logically discarded), save the current line, and - * search for first logical line affected by the redraw. - */ - vscrap(); - CP(temp, linebuf); - l = 0; - tp = dot - vcline; - if (vcnt == 0) - LINE(0) = WTOP; - while (l < vcnt && LINE(l) < p) - l++, tp++; - - /* - * We hold off echo area clearing during the redraw in deference - * to a final clear of the echo area at the end if appropriate. - */ - heldech = 0; - hold |= HOLDECH; - for (; l < vcnt && Peekkey != ATTN; l++) { - if (l == vcline) - strcLIN(temp); - else - getline(*tp); - - /* - * Delete junk between displayed lines. - */ - if (LINE(l) != LINE(l + 1) && LINE(l) != p) { - if (anydl == 0 && DB && CD) { - hold = oldhold; - vclrech(0); - anydl = 1; - hold |= HOLDECH; - heldech = 0; - } - vdellin(p, LINE(l) - p, l); - } - - /* - * If line image is not know to be up to date, then - * redisplay it; else just skip onward. - */ - LINE(l) = p; - if (FLAGS(l) & VDIRT) { - DEPTH(l) = vdepth(); - if (l != vcline && p + DEPTH(l) - 1 > WBOT) { - vscrap(); - break; - } - FLAGS(l) &= ~VDIRT; - vreopen(p, lineno(tp), l); - p = LINE(l) + DEPTH(l); - } else - p += DEPTH(l); - tp++; - } - - /* - * That takes care of lines which were already partially displayed. - * Now try to fill the rest of the screen with text. - */ - if (state == VISUAL && p <= WBOT) { - int ovcline = vcline; - - vcline = l; - for (; tp <= dol && Peekkey != ATTN; tp++) { - getline(*tp); - if (p + vdepth() - 1 > WBOT) - break; - vopen(tp, p); - p += DEPTH(vcline); - vcline++; - } - vcline = ovcline; - } - - /* - * Thats all the text we can get on. - * Now rest of lines (if any) get either a ~ if they - * are past end of file, or an @ if the next line won't fit. - */ - for (; p <= WBOT && Peekkey != ATTN; p++) - vclrlin(p, tp); - strcLIN(temp); - hold = oldhold; - if (heldech) - vclrech(0); -#ifdef ADEBUG - if (trace) - tvliny(); -#endif - free(temp); -} - -/* - * Do the real work in deleting cnt lines starting at line p from - * the display. First affected line is line l. - */ -void -vdellin(int p, int cnt, int l) -{ - register int i; - - if (cnt == 0) - return; - if (DL == NOSTR || cnt < 0) { - /* - * Can't do it; just remember that line l is munged. - */ - FLAGS(l) |= VDIRT; - return; - } -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l); -#endif - /* - * Send the deletes to the screen and then adjust logical - * and physical internal data structures. - */ - vgoto(p, 0); - if (DL_PARM && (cnt>1 || *DL==0)) { - vputp(tgoto(DL_PARM, p, cnt), WECHO-p); - } - else if (xCS && *DL==0) { - /* vt100: fake DL by changing scrolling region */ - vputp(SC, 1); /* Save since xCS homes stupid cursor */ - vputp(tgoto(xCS, TLINES-1, p), 1); - vputp(tgoto(CM, 0, TLINES-1), 1);/* Go to lower left corner */ - for (i=0; i<cnt; i++) /* .. and scroll cnt times */ - putch('\n'); /* should check NL too */ - vputp(tgoto(xCS, TLINES-1, 0), 1);/* restore scrolling region */ - vputp(RC, 1); /* put cursor back */ - } - else { - for (i = 0; i < cnt; i++) - vputp(DL, WECHO - p); - } - vadjDL(p, cnt); - vcloseup(l, cnt); -} -/* - * Adjust internal physical screen image to account for deleted lines. - */ -void -vadjDL(int p, int cnt) -{ - cell **tlines = smalloc(TUBELINES * sizeof *tlines); - register int from, to; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt); -#endif - /* - * Would like to use structured assignment but early - * v7 compiler (released with phototypesetter for v6) - * can't hack it. - */ - copy(tlines, vtube, TUBELINES * sizeof *tlines); /*SASSIGN*/ - for (from = p + cnt, to = p; from <= WECHO; from++, to++) - vtube[to] = tlines[from]; - for (from = p; to <= WECHO; from++, to++) { - vtube[to] = tlines[from]; - vclrcell(vtube[to], WCOLS); - } - free(tlines); -} -/* - * Sync the screen, like redraw but more lazy and willing to leave - * @ lines on the screen. VsyncCL syncs starting at the current line. - * In any case, if the redraw option is set then all syncs map to redraws - * as if vsync didn't exist. - */ -void -vsyncCL(void) -{ - - vsync(LINE(vcline)); -} - -void -vsync(register int p) -{ - - if (value(REDRAW)) - vredraw(p); - else - vsync1(p); -} - -/* - * The guts of a sync. Similar to redraw but - * just less ambitous. - */ -void -vsync1(register int p) -{ - register int l; - char *temp; - register struct vlinfo *vp = &vlinfo[0]; - short oldhold = hold; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny(); -#endif - if (holdupd) { - if (holdupd < 3) - holdupd = 2; - return; - } - if (state == HARDOPEN || splitw) - return; - temp = smalloc(LBSIZE); - vscrap(); - CP(temp, linebuf); - if (vcnt == 0) - LINE(0) = WTOP; - l = 0; - while (l < vcnt && vp->vliny < p) - l++, vp++; - heldech = 0; - hold |= HOLDECH; - while (p <= WBOT && Peekkey != ATTN) { - /* - * Want to put a line here if not in visual and first line - * or if there are lies left and this line starts before - * the current line, or if this line is piled under the - * next line (vreplace does this and we undo it). - */ - if (l == 0 && state != VISUAL || - (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) { - if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) { - if (l == vcline) - strcLIN(temp); - else - getline(dot[l - vcline]); - /* - * Be careful that a long line doesn't cause the - * screen to shoot up. - */ - if (l != vcline && (vp->vflags & VDIRT)) { - vp->vdepth = vdepth(); - vp->vflags &= ~VDIRT; - if (p + vp->vdepth - 1 > WBOT) - break; - } - vreopen(p, lineDOT() + (l - vcline), l); - } - p = vp->vliny + vp->vdepth; - vp++; - l++; - } else - /* - * A physical line between logical lines, - * so we settle for an @ at the beginning. - */ - vclrlin(p, dot + (l - vcline)), p++; - } - strcLIN(temp); - hold = oldhold; - if (heldech) - vclrech(0); - free(temp); -} - -/* - * Subtract (logically) cnt physical lines from the - * displayed position of lines starting with line l. - */ -void -vcloseup(int l, register int cnt) -{ - register int i; - -#ifdef ADEBUG - if (trace) - tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt); -#endif - for (i = l + 1; i <= vcnt; i++) - LINE(i) -= cnt; -} - -/* - * Workhorse for rearranging line descriptors on changes. - * The idea here is that, starting with line l, cnt lines - * have been replaced with newcnt lines. All of these may - * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0, - * since we may be called from an undo after the screen has - * moved a lot. Thus we have to be careful. - * - * Many boundary conditions here. - */ -void -vreplace(int l, int cnt, int newcnt) -{ - register int from, to, i; - bool savenote = 0; - -#ifdef ADEBUG - if (trace) { - tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt); - tvliny(); - } -#endif - if (l >= vcnt) - return; - if (l < 0) { - if (l + cnt < 0) { - /* - * Nothing on the screen is relevant. - * Settle for redrawing from scratch (later). - */ - vcnt = 0; - return; - } - /* - * Normalize l to top of screen; the add is - * really a subtract from cnt since l is negative. - */ - cnt += l; - l = 0; - - /* - * Unseen lines were affect so notify (later). - */ - savenote++; - } - - /* - * These shouldn't happen - * but would cause great havoc. - */ - if (cnt < 0) - cnt = 0; - if (newcnt < 0) - newcnt = 0; - - /* - * Surely worthy of note if more than report - * lines were changed. - */ - if (cnt > value(REPORT) || newcnt > value(REPORT)) - savenote++; - - /* - * Same number of lines affeted as on screen, and we - * can insert and delete lines. Thus we just type - * over them, since otherwise we will push them - * slowly off the screen, a clear lose. - */ - if (cnt == newcnt || vcnt - l == newcnt && AL && DL) { - if (cnt > 1 && l + cnt > vcnt) - savenote++; - vdirty(l, newcnt); - } else { - /* - * Lines are going away, squish them out. - */ - if (cnt > 0) { - /* - * If non-displayed lines went away, - * always notify. - */ - if (cnt > 1 && l + cnt > vcnt) - savenote++; - if (l + cnt >= vcnt) - cnt = vcnt - l; - else - for (from = l + cnt, to = l; from <= vcnt; to++, from++) - vlcopy(vlinfo[to], vlinfo[from]); - vcnt -= cnt; - } - /* - * Open up space for new lines appearing. - * All new lines are piled in the same place, - * and will be unpiled by vredraw/vsync, which - * inserts lines in front as it unpiles. - */ - if (newcnt > 0) { - /* - * Newlines are appearing which may not show, - * so notify (this is only approximately correct - * when long lines are present). - */ - if (newcnt > 1 && l + newcnt > vcnt + 1) - savenote++; - - /* - * If there will be more lines than fit, then - * just throw way the rest of the stuff on the screen. - */ - if (l + newcnt > WBOT && AL && DL) { - vcnt = l; - goto skip; - } - from = vcnt, to = vcnt + newcnt; - i = TUBELINES - to; - if (i < 0) - from += i, to += i; - vcnt = to; - for (; from >= l; from--, to--) - vlcopy(vlinfo[to], vlinfo[from]); - for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) { - LINE(to) = LINE(from); - DEPTH(to) = 0; - FLAGS(to) = VDIRT; - } - } - } -skip: - if (Pline == numbline && cnt != newcnt) - /* - * When lines positions are shifted, the numbers - * will be wrong. - */ - vdirty(l, WECHO); - if (!savenote) - notecnt = 0; -#ifdef ADEBUG - if (trace) - tvliny(); -#endif -} - -/* - * Start harcopy open. - * Print an image of the line to the left of the cursor - * under the full print of the line and position the cursor. - * If we are in a scroll ^D within hardcopy open then all this - * is suppressed. - */ -void -sethard(void) -{ - - if (state == VISUAL) - return; - rubble = 0; - state = HARDOPEN; - if (hold & HOLDROL) - return; - vup1(); - LINE(0) = WBOT; - if (Pline == numbline) - vgoto(WBOT, 0), printf("%6d ", lineDOT()); -} - -/* - * Mark the lines starting at base for i lines - * as dirty so that they will be checked for correct - * display at next sync/redraw. - */ -void -vdirty(register int base, register int i) -{ - register int l; - - for (l = base; l < vcnt; l++) { - if (--i < 0) - return; - FLAGS(l) |= VDIRT; - } -} |
