xref: /illumos-gate/usr/src/cmd/vi/port/ex_vadj.c (revision 55fea89d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
523a1cceaSRoger A. Faulkner  * Common Development and Distribution License (the "License").
623a1cceaSRoger A. Faulkner  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2123a1cceaSRoger A. Faulkner 
227c478bd9Sstevel@tonic-gate /*
2323a1cceaSRoger A. Faulkner  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "ex.h"
337c478bd9Sstevel@tonic-gate #include "ex_tune.h"
347c478bd9Sstevel@tonic-gate #include "ex_tty.h"
357c478bd9Sstevel@tonic-gate #include "ex_vis.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Routines to deal with management of logical versus physical
397c478bd9Sstevel@tonic-gate  * display, opening and redisplaying lines on the screen, and
407c478bd9Sstevel@tonic-gate  * use of intelligent terminal operations.  Routines to deal with
417c478bd9Sstevel@tonic-gate  * screen cleanup after a change.
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * Display a new line at physical line p, returning
467c478bd9Sstevel@tonic-gate  * the depth of the newly displayed line.  We may decide
477c478bd9Sstevel@tonic-gate  * to expand the window on an intelligent terminal if it is
487c478bd9Sstevel@tonic-gate  * less than a full screen by deleting a line above the top of the
497c478bd9Sstevel@tonic-gate  * window before doing an insert line to keep all the good text
507c478bd9Sstevel@tonic-gate  * on the screen in which case the line may actually end up
517c478bd9Sstevel@tonic-gate  * somewhere other than line p.
527c478bd9Sstevel@tonic-gate  */
53f6db9f27Scf void
vopen(line * tp,int p)54f6db9f27Scf vopen(line *tp, int p)
557c478bd9Sstevel@tonic-gate {
56f6db9f27Scf 	int cnt;
57f6db9f27Scf 	struct vlinfo *vp, *vpc;
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #ifdef ADEBUG
607c478bd9Sstevel@tonic-gate 	if (trace != NULL)
617c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vopen(%d, %d)\n", lineno(tp), p);
627c478bd9Sstevel@tonic-gate #endif
637c478bd9Sstevel@tonic-gate 	if (state != VISUAL) {
647c478bd9Sstevel@tonic-gate 		if (vcnt)
657c478bd9Sstevel@tonic-gate 			if (hold & HOLDROL)
667c478bd9Sstevel@tonic-gate 				vup1();
677c478bd9Sstevel@tonic-gate 			else
687c478bd9Sstevel@tonic-gate 				vclean();
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 		/*
717c478bd9Sstevel@tonic-gate 		 * Forget all that we once knew.
727c478bd9Sstevel@tonic-gate 		 */
737c478bd9Sstevel@tonic-gate 		vcnt = vcline = 0;
747c478bd9Sstevel@tonic-gate 		p = WBOT; LASTLINE = WBOT + 1;
757c478bd9Sstevel@tonic-gate 		state = bastate;
767c478bd9Sstevel@tonic-gate 		WTOP = basWTOP;
777c478bd9Sstevel@tonic-gate 		WLINES = basWLINES;
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 	vpc = &vlinfo[vcline];
807c478bd9Sstevel@tonic-gate 	for (vp = &vlinfo[vcnt]; vp >= vpc; vp--)
817c478bd9Sstevel@tonic-gate 		vlcopy(vp[1], vp[0]);
827c478bd9Sstevel@tonic-gate 	vcnt++;
837c478bd9Sstevel@tonic-gate 	if (Pline == numbline)
847c478bd9Sstevel@tonic-gate 		/*
857c478bd9Sstevel@tonic-gate 		 * Dirtying all the lines is rather inefficient
867c478bd9Sstevel@tonic-gate 		 * internally, but number mode is used rarely
877c478bd9Sstevel@tonic-gate 		 * and so it's not worth optimizing.
887c478bd9Sstevel@tonic-gate 		 */
897c478bd9Sstevel@tonic-gate 		vdirty(vcline+1, WECHO);
9023a1cceaSRoger A. Faulkner 	getaline(*tp);
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	/*
937c478bd9Sstevel@tonic-gate 	 * If we are opening at the top of the window, can try a window
947c478bd9Sstevel@tonic-gate 	 * expansion at the top.
957c478bd9Sstevel@tonic-gate 	 */
967c478bd9Sstevel@tonic-gate 	if (state == VISUAL && vcline == 0 && vcnt > 1 && p > ZERO) {
977c478bd9Sstevel@tonic-gate 		cnt = p + vdepth() - LINE(1);
987c478bd9Sstevel@tonic-gate 		if (cnt > 0) {
997c478bd9Sstevel@tonic-gate 			p -= cnt;
1007c478bd9Sstevel@tonic-gate 			if (p < ZERO)
1017c478bd9Sstevel@tonic-gate 				p = ZERO;
1027c478bd9Sstevel@tonic-gate 			WTOP = p;
1037c478bd9Sstevel@tonic-gate 			WLINES = WBOT - WTOP + 1;
1047c478bd9Sstevel@tonic-gate 		}
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 	vpc->vliny = p, vpc->vdepth = 0, vpc->vflags = 0;
1077c478bd9Sstevel@tonic-gate 	cnt = vreopen(p, lineno(tp), vcline);
1087c478bd9Sstevel@tonic-gate 	if (vcline + 1 == vcnt)
1097c478bd9Sstevel@tonic-gate 		LINE(vcnt) = LINE(vcline) + cnt;
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * Redisplay logical line l at physical line p with line number lineno.
1147c478bd9Sstevel@tonic-gate  */
115f6db9f27Scf int
vreopen(int p,int lineno,int l)116f6db9f27Scf vreopen(int p, int lineno, int l)
1177c478bd9Sstevel@tonic-gate {
118f6db9f27Scf 	int d;
119f6db9f27Scf 	struct vlinfo *vp = &vlinfo[l];
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	d = vp->vdepth;
1227c478bd9Sstevel@tonic-gate 	if (d == 0 || (vp->vflags & VDIRT))
1237c478bd9Sstevel@tonic-gate 		vp->vdepth = d = vdepth();
1247c478bd9Sstevel@tonic-gate 	vp->vliny = p, vp->vflags &= ~VDIRT;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	/*
1277c478bd9Sstevel@tonic-gate 	 * Try to win by making the screen larger rather than inserting
1287c478bd9Sstevel@tonic-gate 	 * a line and driving text off the bottom.
1297c478bd9Sstevel@tonic-gate 	 */
1307c478bd9Sstevel@tonic-gate 	p = vglitchup(l, 0);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/*
1337c478bd9Sstevel@tonic-gate 	 * BUG:	Should consider using clr_eol here to clear to end of line.
1347c478bd9Sstevel@tonic-gate 	 *	As it stands we always strike over the current text.
1357c478bd9Sstevel@tonic-gate 	 *	Since often the current text is the same as what
1367c478bd9Sstevel@tonic-gate 	 *	we are overstriking with, it tends not to show.
1377c478bd9Sstevel@tonic-gate 	 *	On the other hand if it is different and we end up
1387c478bd9Sstevel@tonic-gate 	 *	spacing out a lot of text, we could have won with
1397c478bd9Sstevel@tonic-gate 	 *	a clr_eol.  This is probably worthwhile at low speed
1407c478bd9Sstevel@tonic-gate 	 *	only however, since clearly computation will be
1417c478bd9Sstevel@tonic-gate 	 *	necessary to determine which way to go.
1427c478bd9Sstevel@tonic-gate 	 */
1437c478bd9Sstevel@tonic-gate 	vigoto(p, 0);
1447c478bd9Sstevel@tonic-gate 	pline(lineno);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (state == VISUAL && l == vcline && vp->vliny < 0) {
1477c478bd9Sstevel@tonic-gate 		vp->vliny = 0;
1487c478bd9Sstevel@tonic-gate 		vscrap();
149f6db9f27Scf 		return (d);
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	/*
1537c478bd9Sstevel@tonic-gate 	 * When we are typing part of a line for hardcopy open, don't
1547c478bd9Sstevel@tonic-gate 	 * want to type the '$' marking an end of line if in list mode.
1557c478bd9Sstevel@tonic-gate 	 */
1567c478bd9Sstevel@tonic-gate 	if (hold & HOLDDOL)
1577c478bd9Sstevel@tonic-gate 		return (d);
1587c478bd9Sstevel@tonic-gate 	if (Putchar == listchar)
1597c478bd9Sstevel@tonic-gate 		putchar('$');
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/*
1627c478bd9Sstevel@tonic-gate 	 * Optimization of cursor motion may prevent screen rollup if the
1637c478bd9Sstevel@tonic-gate 	 * line has blanks/tabs at the end unless we force the cursor to appear
1647c478bd9Sstevel@tonic-gate 	 * on the last line segment.
1657c478bd9Sstevel@tonic-gate 	 */
1667c478bd9Sstevel@tonic-gate 	if (vp->vliny + d - 1 > WBOT)
1677c478bd9Sstevel@tonic-gate 		vcsync();
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	/*
1707c478bd9Sstevel@tonic-gate 	 * Switch into hardcopy open mode if we are in one line (adm3)
1717c478bd9Sstevel@tonic-gate 	 * open mode and this line is now too long.  If in hardcopy
1727c478bd9Sstevel@tonic-gate 	 * open mode, then call sethard to move onto the next line
1737c478bd9Sstevel@tonic-gate 	 * with appropriate positioning.
1747c478bd9Sstevel@tonic-gate 	 */
1757c478bd9Sstevel@tonic-gate 	if (state == ONEOPEN) {
1767c478bd9Sstevel@tonic-gate 		WCOLS = OCOLUMNS;
1777c478bd9Sstevel@tonic-gate 		if (vdepth() > 1) {
1787c478bd9Sstevel@tonic-gate 			WCOLS = TUBECOLS;
1797c478bd9Sstevel@tonic-gate 			sethard();
1807c478bd9Sstevel@tonic-gate 		} else
1817c478bd9Sstevel@tonic-gate 			WCOLS = TUBECOLS;
1827c478bd9Sstevel@tonic-gate 	} else if (state == HARDOPEN)
1837c478bd9Sstevel@tonic-gate 		sethard();
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/*
1867c478bd9Sstevel@tonic-gate 	 * Unless we filled (completely) the last line we typed on,
1877c478bd9Sstevel@tonic-gate 	 * we have to clear to the end of the line
1887c478bd9Sstevel@tonic-gate 	 * in case stuff is left from before.
1897c478bd9Sstevel@tonic-gate 	 */
1907c478bd9Sstevel@tonic-gate 	if (vp->vliny + d > destline) {
1917c478bd9Sstevel@tonic-gate 		if (insert_null_glitch && destcol == WCOLS)
1927c478bd9Sstevel@tonic-gate 			vigoto(vp->vliny + d - 1, 0);
1937c478bd9Sstevel@tonic-gate 		vclreol();
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 	return (d);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate /*
1997c478bd9Sstevel@tonic-gate  * Real work for winning growing of window at top
2007c478bd9Sstevel@tonic-gate  * when inserting in the middle of a partially full
2017c478bd9Sstevel@tonic-gate  * screen on an intelligent terminal.  We have as argument
2027c478bd9Sstevel@tonic-gate  * the logical line number to be inserted after, and the offset
2037c478bd9Sstevel@tonic-gate  * from that line where the insert will go.
2047c478bd9Sstevel@tonic-gate  * We look at the picture of depths and positions, and if we can
2057c478bd9Sstevel@tonic-gate  * delete some (blank) lines from the top of the screen so that
2067c478bd9Sstevel@tonic-gate  * later inserts will not push stuff off the bottom.
2077c478bd9Sstevel@tonic-gate  */
208f6db9f27Scf int
vglitchup(int l,int o)209f6db9f27Scf vglitchup(int l, int o)
2107c478bd9Sstevel@tonic-gate {
211f6db9f27Scf 	struct vlinfo *vp = &vlinfo[l];
212f6db9f27Scf 	int need;
213f6db9f27Scf 	int p = vp->vliny;
2147c478bd9Sstevel@tonic-gate 	short oldhold, oldheldech;
2157c478bd9Sstevel@tonic-gate 	bool glitched = 0;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate  	if (l < vcnt - 1) {
2187c478bd9Sstevel@tonic-gate 		need = p + vp->vdepth - (vp+1)->vliny;
2197c478bd9Sstevel@tonic-gate 		if (need > 0) {
2207c478bd9Sstevel@tonic-gate 			if (state == VISUAL && WTOP - ZERO >= need && insert_line && delete_line) {
2217c478bd9Sstevel@tonic-gate 				glitched++;
2227c478bd9Sstevel@tonic-gate 				WTOP -= need;
2237c478bd9Sstevel@tonic-gate 				WLINES = WBOT - WTOP + 1;
2247c478bd9Sstevel@tonic-gate 				p -= need;
2257c478bd9Sstevel@tonic-gate 				if (p + o == WTOP) {
2267c478bd9Sstevel@tonic-gate 					vp->vliny = WTOP;
2277c478bd9Sstevel@tonic-gate 					return (WTOP + o);
2287c478bd9Sstevel@tonic-gate 				}
2297c478bd9Sstevel@tonic-gate 				vdellin(WTOP, need, -1);
2307c478bd9Sstevel@tonic-gate 				oldheldech = heldech;
2317c478bd9Sstevel@tonic-gate 				oldhold = hold;
2327c478bd9Sstevel@tonic-gate 				hold |= HOLDECH;
2337c478bd9Sstevel@tonic-gate 			}
2347c478bd9Sstevel@tonic-gate 			vinslin((vp+1)->vliny, need, l);
2357c478bd9Sstevel@tonic-gate 			if (glitched) {
2367c478bd9Sstevel@tonic-gate 				hold = oldhold;
2377c478bd9Sstevel@tonic-gate 				heldech = oldheldech;
2387c478bd9Sstevel@tonic-gate 			}
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 	} else
2417c478bd9Sstevel@tonic-gate 		vp[1].vliny = vp[0].vliny + vp->vdepth;
2427c478bd9Sstevel@tonic-gate 	return (p + o);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate  * Insert cnt blank lines before line p,
2477c478bd9Sstevel@tonic-gate  * logically and (if supported) physically.
2487c478bd9Sstevel@tonic-gate  */
249f6db9f27Scf void
vinslin(int p,int cnt,int l)250f6db9f27Scf vinslin(int p, int cnt, int l)
2517c478bd9Sstevel@tonic-gate {
252f6db9f27Scf 	int i;
2537c478bd9Sstevel@tonic-gate 	bool could = 1;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate #ifdef ADEBUG
2567c478bd9Sstevel@tonic-gate 	if (trace)
2577c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l);
2587c478bd9Sstevel@tonic-gate #endif
2597c478bd9Sstevel@tonic-gate 	if (p + cnt > WBOT && clr_eos) {
2607c478bd9Sstevel@tonic-gate 		/*
2617c478bd9Sstevel@tonic-gate 		 * Really quick -- clear to end of screen.
2627c478bd9Sstevel@tonic-gate 		 */
2637c478bd9Sstevel@tonic-gate 		cnt = WECHO + 1 - p;
2647c478bd9Sstevel@tonic-gate 		vgoto(p, 0), vputp(clr_eos, cnt);
2657c478bd9Sstevel@tonic-gate 		vclrech(1);
2667c478bd9Sstevel@tonic-gate 		vadjAL(p, cnt);
2677c478bd9Sstevel@tonic-gate 	} else if (scroll_reverse && p == WTOP && costSR < costAL) {
2687c478bd9Sstevel@tonic-gate 		/*
2697c478bd9Sstevel@tonic-gate 		 * Use reverse scroll mode of the terminal, at
2707c478bd9Sstevel@tonic-gate 		 * the top of the window.  Reverse linefeed works
2717c478bd9Sstevel@tonic-gate 		 * too, since we only use it from line WTOP.
2727c478bd9Sstevel@tonic-gate 		 */
2737c478bd9Sstevel@tonic-gate 		for (i = cnt; i > 0; i--) {
2747c478bd9Sstevel@tonic-gate 			vgoto(p, 0), vputp(scroll_reverse, 0);
2757c478bd9Sstevel@tonic-gate 			if (i > 1 && (hold & HOLDAT) == 0)
2767c478bd9Sstevel@tonic-gate 				putchar('@');
2777c478bd9Sstevel@tonic-gate 			/*
2787c478bd9Sstevel@tonic-gate 			 * If we are at the top of the screen, and the
2797c478bd9Sstevel@tonic-gate 			 * terminal retains display above, then we
2807c478bd9Sstevel@tonic-gate 			 * should try to clear to end of line.
2817c478bd9Sstevel@tonic-gate 			 * Have to use clr_eol since we don't remember what is
2827c478bd9Sstevel@tonic-gate 			 * actually on the line.
2837c478bd9Sstevel@tonic-gate 			 */
2847c478bd9Sstevel@tonic-gate 			if (clr_eol && (memory_above || p != 0))
2857c478bd9Sstevel@tonic-gate 				vputp(clr_eol, 1);
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 		vadjAL(p, cnt);
2887c478bd9Sstevel@tonic-gate 	} else if (insert_line) {
2897c478bd9Sstevel@tonic-gate 		/*
2907c478bd9Sstevel@tonic-gate 		 * Use insert line.
2917c478bd9Sstevel@tonic-gate 		 */
2927c478bd9Sstevel@tonic-gate 		vgoto(p, 0);
2937c478bd9Sstevel@tonic-gate 		if (parm_insert_line && (cnt>1 || *insert_line==0)) {
2947c478bd9Sstevel@tonic-gate 			/* insert cnt lines.  Should do @'s too. */
2957c478bd9Sstevel@tonic-gate 			vputp(tparm(parm_insert_line, cnt, p), WECHO+1-p);
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 		else if (change_scroll_region && *insert_line==0) {
2987c478bd9Sstevel@tonic-gate 			/* vt100 change scrolling region to fake insert_line */
2997c478bd9Sstevel@tonic-gate 			vputp(save_cursor, 1);
3007c478bd9Sstevel@tonic-gate 			vputp(tparm(change_scroll_region, p, lines-1), 1);
3017c478bd9Sstevel@tonic-gate 			vputp(restore_cursor, 1);	/* change_scroll_region homes stupid cursor */
3027c478bd9Sstevel@tonic-gate 			for (i=cnt; i>0; i--)
3037c478bd9Sstevel@tonic-gate 				vputp(scroll_reverse, 1);	/* should do @'s */
3047c478bd9Sstevel@tonic-gate 			vputp(tparm(change_scroll_region, 0, lines-1), 1);
3057c478bd9Sstevel@tonic-gate 			vputp(restore_cursor, 1);	/* Once again put it back */
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 		else {
3087c478bd9Sstevel@tonic-gate 			vputp(insert_line, WECHO + 1 - p);
3097c478bd9Sstevel@tonic-gate 			for (i = cnt - 1; i > 0; i--) {
3107c478bd9Sstevel@tonic-gate 				vgoto(outline+1, 0);
3117c478bd9Sstevel@tonic-gate 				vputp(insert_line, WECHO + 1 - outline);
3127c478bd9Sstevel@tonic-gate 				if ((hold & HOLDAT) == 0)
3137c478bd9Sstevel@tonic-gate 					putchar('@');
3147c478bd9Sstevel@tonic-gate 			}
3157c478bd9Sstevel@tonic-gate 		}
3167c478bd9Sstevel@tonic-gate 		vadjAL(p, cnt);
3177c478bd9Sstevel@tonic-gate 	} else
3187c478bd9Sstevel@tonic-gate 		could = 0;
3197c478bd9Sstevel@tonic-gate 	vopenup(cnt, could, l);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate /*
3237c478bd9Sstevel@tonic-gate  * Logically open up after line l, cnt of them.
3247c478bd9Sstevel@tonic-gate  * We need to know if it was done ``physically'' since in this
3257c478bd9Sstevel@tonic-gate  * case we accept what the hardware gives us.  If we have to do
3267c478bd9Sstevel@tonic-gate  * it ourselves (brute force) we will squish out @ lines in the process
3277c478bd9Sstevel@tonic-gate  * if this will save us work.
3287c478bd9Sstevel@tonic-gate  */
329f6db9f27Scf void
vopenup(int cnt,bool could,int l)330f6db9f27Scf vopenup(int cnt, bool could, int l)
3317c478bd9Sstevel@tonic-gate {
332f6db9f27Scf 	struct vlinfo *vc = &vlinfo[l + 1];
333f6db9f27Scf 	struct vlinfo *ve = &vlinfo[vcnt];
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate #ifdef ADEBUG
3367c478bd9Sstevel@tonic-gate 	if (trace)
3377c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l);
3387c478bd9Sstevel@tonic-gate #endif
3397c478bd9Sstevel@tonic-gate 	if (could)
3407c478bd9Sstevel@tonic-gate 		/*
3417c478bd9Sstevel@tonic-gate 		 * This will push @ lines down the screen,
3427c478bd9Sstevel@tonic-gate 		 * just as the hardware did.  Since the default
3437c478bd9Sstevel@tonic-gate 		 * for intelligent terminals is to never have @
3447c478bd9Sstevel@tonic-gate 		 * lines on the screen, this should never happen,
3457c478bd9Sstevel@tonic-gate 		 * and the code makes no special effort to be nice in this
3467c478bd9Sstevel@tonic-gate 		 * case, e.g. squishing out the @ lines by delete lines
3477c478bd9Sstevel@tonic-gate 		 * before doing append lines.
3487c478bd9Sstevel@tonic-gate 		 */
3497c478bd9Sstevel@tonic-gate 		for (; vc <= ve; vc++)
3507c478bd9Sstevel@tonic-gate 			vc->vliny += cnt;
3517c478bd9Sstevel@tonic-gate 	else {
3527c478bd9Sstevel@tonic-gate 		/*
3537c478bd9Sstevel@tonic-gate 		 * Will have to clean up brute force eventually,
3547c478bd9Sstevel@tonic-gate 		 * so push the line data around as little as possible.
3557c478bd9Sstevel@tonic-gate 		 */
3567c478bd9Sstevel@tonic-gate 		vc->vliny += cnt, vc->vflags |= VDIRT;
3577c478bd9Sstevel@tonic-gate 		while (vc < ve) {
358f6db9f27Scf 			int i = vc->vliny + vc->vdepth;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 			vc++;
3617c478bd9Sstevel@tonic-gate 			if (i <= vc->vliny)
3627c478bd9Sstevel@tonic-gate 				break;
3637c478bd9Sstevel@tonic-gate 			vc->vliny = i, vc->vflags |= VDIRT;
3647c478bd9Sstevel@tonic-gate 		}
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 	vscrap();
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate  * Adjust data structure internally to account for insertion of
3717c478bd9Sstevel@tonic-gate  * blank lines on the screen.
3727c478bd9Sstevel@tonic-gate  */
373f6db9f27Scf void
vadjAL(int p,int cnt)374f6db9f27Scf vadjAL(int p, int cnt)
3757c478bd9Sstevel@tonic-gate {
3767c478bd9Sstevel@tonic-gate 	wchar_t *tlines[TUBELINES];
377f6db9f27Scf 	int from, to;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate #ifdef ADEBUG
3807c478bd9Sstevel@tonic-gate 	if (trace)
3817c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt);
3827c478bd9Sstevel@tonic-gate #endif
3837c478bd9Sstevel@tonic-gate 	copy(tlines, vtube, sizeof vtube);	/*SASSIGN*/
3847c478bd9Sstevel@tonic-gate 	for (from = p, to = p + cnt; to <= WECHO; from++, to++)
3857c478bd9Sstevel@tonic-gate 		vtube[to] = tlines[from];
3867c478bd9Sstevel@tonic-gate 	for (to = p; from <= WECHO; from++, to++) {
3877c478bd9Sstevel@tonic-gate 		vtube[to] = tlines[from];
3887c478bd9Sstevel@tonic-gate 		vclrbyte(vtube[to], WCOLS);
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 	/*
3917c478bd9Sstevel@tonic-gate 	 * Have to clear the echo area since its contents aren't
3927c478bd9Sstevel@tonic-gate 	 * necessarily consistent with the rest of the display.
3937c478bd9Sstevel@tonic-gate 	 */
3947c478bd9Sstevel@tonic-gate 	vclrech(0);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate  * Roll the screen up logically and physically
3997c478bd9Sstevel@tonic-gate  * so that line dl is the bottom line on the screen.
4007c478bd9Sstevel@tonic-gate  */
401f6db9f27Scf void
vrollup(int dl)402f6db9f27Scf vrollup(int dl)
4037c478bd9Sstevel@tonic-gate {
404f6db9f27Scf 	int cnt;
405f6db9f27Scf 	int dc = destcol;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate #ifdef ADEBUG
4087c478bd9Sstevel@tonic-gate 	if (trace)
4097c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vrollup(%d)\n", dl);
4107c478bd9Sstevel@tonic-gate #endif
4117c478bd9Sstevel@tonic-gate 	cnt = dl - (splitw ? WECHO : WBOT);
4127c478bd9Sstevel@tonic-gate 	if (splitw && (state == VISUAL || state == CRTOPEN))
4137c478bd9Sstevel@tonic-gate 		holdupd = 1;
4147c478bd9Sstevel@tonic-gate 	vmoveitup(cnt, 1);
4157c478bd9Sstevel@tonic-gate 	vscroll(cnt);
4167c478bd9Sstevel@tonic-gate 	destline = dl - cnt, destcol = dc;
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate 
419f6db9f27Scf void
vup1(void)420f6db9f27Scf vup1(void)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	vrollup(WBOT + 1);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate  * Scroll the screen up cnt lines physically.
4287c478bd9Sstevel@tonic-gate  * If doclr is true, do a clear eol if the terminal
4297c478bd9Sstevel@tonic-gate  * has standout (to prevent it from scrolling up)
4307c478bd9Sstevel@tonic-gate  */
431f6db9f27Scf void
vmoveitup(int cnt,bool doclr)432f6db9f27Scf vmoveitup(int cnt, bool doclr)
4337c478bd9Sstevel@tonic-gate {
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	if (cnt == 0)
4367c478bd9Sstevel@tonic-gate 		return;
4377c478bd9Sstevel@tonic-gate #ifdef ADEBUG
4387c478bd9Sstevel@tonic-gate 	if (trace)
4397c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
4407c478bd9Sstevel@tonic-gate #endif
4417c478bd9Sstevel@tonic-gate 	if (doclr)
4427c478bd9Sstevel@tonic-gate 		vclrech(0);
4437c478bd9Sstevel@tonic-gate 	if (scroll_forward) {
4447c478bd9Sstevel@tonic-gate 		destline = WECHO;
4457c478bd9Sstevel@tonic-gate 		destcol = (NONL ? 0 : outcol % WCOLS);
4467c478bd9Sstevel@tonic-gate 		fgoto();
4477c478bd9Sstevel@tonic-gate 		while (cnt > 0)
4487c478bd9Sstevel@tonic-gate 			vputp(scroll_forward, 0), cnt--;
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 	else {
4517c478bd9Sstevel@tonic-gate 		destline = WECHO + cnt;
4527c478bd9Sstevel@tonic-gate 		destcol = (NONL ? 0 : outcol % WCOLS);
4537c478bd9Sstevel@tonic-gate 		fgoto();
4547c478bd9Sstevel@tonic-gate 		if (state == ONEOPEN || state == HARDOPEN) {
4557c478bd9Sstevel@tonic-gate 			outline = destline = 0;
4567c478bd9Sstevel@tonic-gate 			vclrbyte(vtube[0], WCOLS);
4577c478bd9Sstevel@tonic-gate 		}
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 	/* Get rid of line we just rolled up */
4607c478bd9Sstevel@tonic-gate 	if (doclr && memory_below && clr_eol)
4617c478bd9Sstevel@tonic-gate 		vclrech(0);
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /*
4657c478bd9Sstevel@tonic-gate  * Scroll the screen up cnt lines logically.
4667c478bd9Sstevel@tonic-gate  */
467f6db9f27Scf void
vscroll(int cnt)468f6db9f27Scf vscroll(int cnt)
4697c478bd9Sstevel@tonic-gate {
470f6db9f27Scf 	int from, to;
4717c478bd9Sstevel@tonic-gate 	wchar_t *tlines[TUBELINES];
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate #ifdef ADEBUG
4747c478bd9Sstevel@tonic-gate 	if (trace)
4757c478bd9Sstevel@tonic-gate 		fprintf(trace, "vscroll(%d)\n", cnt);
4767c478bd9Sstevel@tonic-gate #endif
4777c478bd9Sstevel@tonic-gate 	if (cnt < 0 || cnt > TUBELINES)
4787c478bd9Sstevel@tonic-gate 		error(gettext("Internal error: vscroll"));
4797c478bd9Sstevel@tonic-gate 	if (cnt == 0)
4807c478bd9Sstevel@tonic-gate 		return;
4817c478bd9Sstevel@tonic-gate 	copy(tlines, vtube, sizeof vtube);
4827c478bd9Sstevel@tonic-gate 	for (to = ZERO, from = ZERO + cnt; to <= WECHO - cnt; to++, from++)
4837c478bd9Sstevel@tonic-gate 		vtube[to] = tlines[from];
4847c478bd9Sstevel@tonic-gate 	for (from = ZERO; to <= WECHO; to++, from++) {
4857c478bd9Sstevel@tonic-gate 		vtube[to] = tlines[from];
4867c478bd9Sstevel@tonic-gate 		vclrbyte(vtube[to], WCOLS);
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 	for (from = 0; from <= vcnt; from++)
4897c478bd9Sstevel@tonic-gate 		LINE(from) -= cnt;
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate  * Discard logical lines due to physical wandering off the screen.
4947c478bd9Sstevel@tonic-gate  */
495f6db9f27Scf void
vscrap(void)496f6db9f27Scf vscrap(void)
4977c478bd9Sstevel@tonic-gate {
498f6db9f27Scf 	int i, j;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate #ifdef ADEBUG
5017c478bd9Sstevel@tonic-gate 	if (trace)
5027c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vscrap\n"), tvliny();
5037c478bd9Sstevel@tonic-gate #endif
5047c478bd9Sstevel@tonic-gate 	if (splitw)
5057c478bd9Sstevel@tonic-gate 		return;
5067c478bd9Sstevel@tonic-gate 	if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ZERO) {
5077c478bd9Sstevel@tonic-gate 		WTOP = LINE(0);
5087c478bd9Sstevel@tonic-gate 		WLINES = WBOT - WTOP + 1;
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 	for (j = 0; j < vcnt; j++)
5117c478bd9Sstevel@tonic-gate 		if (LINE(j) >= WTOP) {
5127c478bd9Sstevel@tonic-gate 			if (j == 0)
5137c478bd9Sstevel@tonic-gate 				break;
5147c478bd9Sstevel@tonic-gate 			/*
5157c478bd9Sstevel@tonic-gate 			 * Discard the first j physical lines off the top.
5167c478bd9Sstevel@tonic-gate 			 */
5177c478bd9Sstevel@tonic-gate 			vcnt -= j, vcline -= j;
5187c478bd9Sstevel@tonic-gate 			for (i = 0; i <= vcnt; i++)
5197c478bd9Sstevel@tonic-gate 				vlcopy(vlinfo[i], vlinfo[i + j]);
5207c478bd9Sstevel@tonic-gate 			break;
5217c478bd9Sstevel@tonic-gate 		}
5227c478bd9Sstevel@tonic-gate 	/*
5237c478bd9Sstevel@tonic-gate 	 * Discard lines off the bottom.
5247c478bd9Sstevel@tonic-gate 	 */
5257c478bd9Sstevel@tonic-gate 	if (vcnt) {
5267c478bd9Sstevel@tonic-gate 		for (j = 0; j <= vcnt; j++)
5277c478bd9Sstevel@tonic-gate 			if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) {
5287c478bd9Sstevel@tonic-gate 				vcnt = j;
5297c478bd9Sstevel@tonic-gate 				break;
5307c478bd9Sstevel@tonic-gate 			}
5317c478bd9Sstevel@tonic-gate 		if (vcnt == 0)
5327c478bd9Sstevel@tonic-gate 			LASTLINE = 0;
5337c478bd9Sstevel@tonic-gate 		else
5347c478bd9Sstevel@tonic-gate 			LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1);
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate #ifdef ADEBUG
5377c478bd9Sstevel@tonic-gate 	if (trace)
5387c478bd9Sstevel@tonic-gate 		tvliny();
5397c478bd9Sstevel@tonic-gate #endif
5407c478bd9Sstevel@tonic-gate 	/*
5417c478bd9Sstevel@tonic-gate 	 * May have no lines!
5427c478bd9Sstevel@tonic-gate 	 */
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  * Repaint the screen, with cursor at curs, aftern an arbitrary change.
5477c478bd9Sstevel@tonic-gate  * Handle notification on large changes.
5487c478bd9Sstevel@tonic-gate  */
549f6db9f27Scf void
vrepaint(unsigned char * curs)550f6db9f27Scf vrepaint(unsigned char *curs)
5517c478bd9Sstevel@tonic-gate {
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	wdot = NOLINE;
5547c478bd9Sstevel@tonic-gate 	/*
5557c478bd9Sstevel@tonic-gate 	 * In open want to notify first.
5567c478bd9Sstevel@tonic-gate 	 */
5577c478bd9Sstevel@tonic-gate 	noteit(0);
5587c478bd9Sstevel@tonic-gate 	vscrap();
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	/*
5617c478bd9Sstevel@tonic-gate 	 * Deal with a totally useless display.
5627c478bd9Sstevel@tonic-gate 	 */
5637c478bd9Sstevel@tonic-gate 	if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) {
564f6db9f27Scf 		line *odol = dol;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		vcnt = 0;
5677c478bd9Sstevel@tonic-gate 		if (holdupd)
5687c478bd9Sstevel@tonic-gate 			if (state == VISUAL)
5697c478bd9Sstevel@tonic-gate 				(void)peekkey();
5707c478bd9Sstevel@tonic-gate 			else
5717c478bd9Sstevel@tonic-gate 				vup1();
5727c478bd9Sstevel@tonic-gate 		holdupd = 0;
5737c478bd9Sstevel@tonic-gate 		if (odol == zero)
5747c478bd9Sstevel@tonic-gate 			fixzero();
5757c478bd9Sstevel@tonic-gate 		vcontext(dot, '.');
5767c478bd9Sstevel@tonic-gate 		noteit(1);
5777c478bd9Sstevel@tonic-gate 		if (noteit(1) == 0 && odol == zero) {
5787c478bd9Sstevel@tonic-gate 			CATCH
5797c478bd9Sstevel@tonic-gate 				error(gettext("No lines in buffer"));
5807c478bd9Sstevel@tonic-gate 			ENDCATCH
5817c478bd9Sstevel@tonic-gate 			linebuf[0] = 0;
5827c478bd9Sstevel@tonic-gate 			splitw = 0;
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 		vnline(curs);
5857c478bd9Sstevel@tonic-gate 		return;
5867c478bd9Sstevel@tonic-gate 	}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	/*
5897c478bd9Sstevel@tonic-gate 	 * Have some useful displayed text; refresh it.
5907c478bd9Sstevel@tonic-gate 	 */
5917c478bd9Sstevel@tonic-gate 	getDOT();
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/*
5947c478bd9Sstevel@tonic-gate 	 * This is for boundary conditions in open mode.
5957c478bd9Sstevel@tonic-gate 	 */
5967c478bd9Sstevel@tonic-gate 	if (FLAGS(0) & VDIRT)
5977c478bd9Sstevel@tonic-gate 		vsync(WTOP);
598*55fea89dSDan Cross 
5997c478bd9Sstevel@tonic-gate 	/*
6007c478bd9Sstevel@tonic-gate 	 * If the current line is after the last displayed line
6017c478bd9Sstevel@tonic-gate 	 * or the bottom of the screen, then special effort is needed
6027c478bd9Sstevel@tonic-gate 	 * to get it on the screen.  We first try a redraw at the
6037c478bd9Sstevel@tonic-gate 	 * last line on the screen, hoping it will fill in where @
6047c478bd9Sstevel@tonic-gate 	 * lines are now.  If this doesn't work, then roll it onto
6057c478bd9Sstevel@tonic-gate 	 * the screen.
6067c478bd9Sstevel@tonic-gate 	 */
6077c478bd9Sstevel@tonic-gate 	if (vcline >= vcnt || LINE(vcline) > WBOT) {
6087c478bd9Sstevel@tonic-gate 		short oldhold = hold;
6097c478bd9Sstevel@tonic-gate 		hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold;
6107c478bd9Sstevel@tonic-gate 		if (vcline >= vcnt) {
611f6db9f27Scf 			int i = vcline - vcnt + 1;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 			dot -= i;
6147c478bd9Sstevel@tonic-gate 			vcline -= i;
6157c478bd9Sstevel@tonic-gate 			vroll(i);
6167c478bd9Sstevel@tonic-gate 		} else
6177c478bd9Sstevel@tonic-gate 			vsyncCL();
6187c478bd9Sstevel@tonic-gate 	} else
6197c478bd9Sstevel@tonic-gate 		vsync(vcline > 0 ? LINE(vcline - 1) : WTOP);
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	/*
6227c478bd9Sstevel@tonic-gate 	 * Notification on large change for visual
6237c478bd9Sstevel@tonic-gate 	 * has to be done last or we may lose
6247c478bd9Sstevel@tonic-gate 	 * the echo area with redisplay.
6257c478bd9Sstevel@tonic-gate 	 */
6267c478bd9Sstevel@tonic-gate 	noteit(1);
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	/*
6297c478bd9Sstevel@tonic-gate 	 * Finally.  Move the cursor onto the current line.
6307c478bd9Sstevel@tonic-gate 	 */
6317c478bd9Sstevel@tonic-gate 	vnline(curs);
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate /*
6357c478bd9Sstevel@tonic-gate  * Fully cleanup the screen, leaving no @ lines except at end when
6367c478bd9Sstevel@tonic-gate  * line after last won't completely fit.  The routine vsync is
6377c478bd9Sstevel@tonic-gate  * more conservative and much less work on dumb terminals.
6387c478bd9Sstevel@tonic-gate  */
639f6db9f27Scf void
vredraw(int p)640f6db9f27Scf vredraw(int p)
6417c478bd9Sstevel@tonic-gate {
642f6db9f27Scf 	int l;
643f6db9f27Scf 	line *tp;
6447c478bd9Sstevel@tonic-gate 	unsigned char temp[LBSIZE];
6457c478bd9Sstevel@tonic-gate 	bool anydl = 0;
6467c478bd9Sstevel@tonic-gate 	short oldhold = hold;
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate #ifdef ADEBUG
6497c478bd9Sstevel@tonic-gate 	if (trace)
6507c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
6517c478bd9Sstevel@tonic-gate #endif
6527c478bd9Sstevel@tonic-gate 	if (holdupd) {
6537c478bd9Sstevel@tonic-gate 		holdupd = 3;
6547c478bd9Sstevel@tonic-gate 		return;
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 	if (state == HARDOPEN || splitw)
6577c478bd9Sstevel@tonic-gate 		return;
6587c478bd9Sstevel@tonic-gate 	if (p < 0 /* || p > WECHO */)
6597c478bd9Sstevel@tonic-gate 		error(gettext("Internal error: vredraw"));
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	/*
6627c478bd9Sstevel@tonic-gate 	 * Trim the ragged edges (lines which are off the screen but
6637c478bd9Sstevel@tonic-gate 	 * not yet logically discarded), save the current line, and
6647c478bd9Sstevel@tonic-gate 	 * search for first logical line affected by the redraw.
6657c478bd9Sstevel@tonic-gate 	 */
6667c478bd9Sstevel@tonic-gate 	vscrap();
6677c478bd9Sstevel@tonic-gate 	CP(temp, linebuf);
6687c478bd9Sstevel@tonic-gate 	l = 0;
6697c478bd9Sstevel@tonic-gate 	tp = dot - vcline;
6707c478bd9Sstevel@tonic-gate 	if (vcnt == 0)
6717c478bd9Sstevel@tonic-gate 		LINE(0) = WTOP;
6727c478bd9Sstevel@tonic-gate 	while (l < vcnt && LINE(l) < p)
6737c478bd9Sstevel@tonic-gate 		l++, tp++;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	/*
6767c478bd9Sstevel@tonic-gate 	 * We hold off echo area clearing during the redraw in deference
6777c478bd9Sstevel@tonic-gate 	 * to a final clear of the echo area at the end if appropriate.
6787c478bd9Sstevel@tonic-gate 	 */
6797c478bd9Sstevel@tonic-gate 	heldech = 0;
6807c478bd9Sstevel@tonic-gate 	hold |= HOLDECH;
6817c478bd9Sstevel@tonic-gate 	for (; l < vcnt && Peekkey != ATTN; l++) {
6827c478bd9Sstevel@tonic-gate 		if (l == vcline)
6837c478bd9Sstevel@tonic-gate 			strcLIN(temp);
6847c478bd9Sstevel@tonic-gate 		else
68523a1cceaSRoger A. Faulkner 			getaline(*tp);
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 		/*
6887c478bd9Sstevel@tonic-gate 		 * Delete junk between displayed lines.
6897c478bd9Sstevel@tonic-gate 		 */
6907c478bd9Sstevel@tonic-gate 		if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
6917c478bd9Sstevel@tonic-gate 			if (anydl == 0 && memory_below && clr_eos) {
6927c478bd9Sstevel@tonic-gate 				hold = oldhold;
6937c478bd9Sstevel@tonic-gate 				vclrech(0);
6947c478bd9Sstevel@tonic-gate 				anydl = 1;
6957c478bd9Sstevel@tonic-gate 				hold |= HOLDECH;
6967c478bd9Sstevel@tonic-gate 				heldech = 0;
6977c478bd9Sstevel@tonic-gate 			}
6987c478bd9Sstevel@tonic-gate 			vdellin(p, LINE(l) - p, l);
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		/*
7027c478bd9Sstevel@tonic-gate 		 * If line image is not know to be up to date, then
7037c478bd9Sstevel@tonic-gate 		 * redisplay it;  else just skip onward.
7047c478bd9Sstevel@tonic-gate 		 */
7057c478bd9Sstevel@tonic-gate 		LINE(l) = p;
7067c478bd9Sstevel@tonic-gate 		if (FLAGS(l) & VDIRT) {
7077c478bd9Sstevel@tonic-gate 			DEPTH(l) = vdepth();
7087c478bd9Sstevel@tonic-gate 			if (l != vcline && p + DEPTH(l) - 1 > WBOT) {
7097c478bd9Sstevel@tonic-gate 				vscrap();
7107c478bd9Sstevel@tonic-gate 				break;
7117c478bd9Sstevel@tonic-gate 			}
7127c478bd9Sstevel@tonic-gate 			FLAGS(l) &= ~VDIRT;
713f6db9f27Scf 			(void) vreopen(p, lineno(tp), l);
7147c478bd9Sstevel@tonic-gate 			p = LINE(l) + DEPTH(l);
7157c478bd9Sstevel@tonic-gate 		} else
7167c478bd9Sstevel@tonic-gate 			p += DEPTH(l);
7177c478bd9Sstevel@tonic-gate 		tp++;
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	/*
7217c478bd9Sstevel@tonic-gate 	 * That takes care of lines which were already partially displayed.
7227c478bd9Sstevel@tonic-gate 	 * Now try to fill the rest of the screen with text.
7237c478bd9Sstevel@tonic-gate 	 */
7247c478bd9Sstevel@tonic-gate 	if (state == VISUAL && p <= WBOT) {
7257c478bd9Sstevel@tonic-gate 		int ovcline = vcline;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 		vcline = l;
7287c478bd9Sstevel@tonic-gate 		for (; tp <= dol && Peekkey != ATTN; tp++) {
72923a1cceaSRoger A. Faulkner 			getaline(*tp);
7307c478bd9Sstevel@tonic-gate 			if (p + vdepth() - 1 > WBOT)
7317c478bd9Sstevel@tonic-gate 				break;
7327c478bd9Sstevel@tonic-gate 			vopen(tp, p);
7337c478bd9Sstevel@tonic-gate 			p += DEPTH(vcline);
7347c478bd9Sstevel@tonic-gate 			vcline++;
7357c478bd9Sstevel@tonic-gate 		}
7367c478bd9Sstevel@tonic-gate 		vcline = ovcline;
7377c478bd9Sstevel@tonic-gate 	}
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 	/*
7407c478bd9Sstevel@tonic-gate 	 * That's all the text we can get on.
7417c478bd9Sstevel@tonic-gate 	 * Now rest of lines (if any) get either a ~ if they
7427c478bd9Sstevel@tonic-gate 	 * are past end of file, or an @ if the next line won't fit.
7437c478bd9Sstevel@tonic-gate 	 */
744*55fea89dSDan Cross 	for (; p <= WBOT && Peekkey != ATTN; p++)
7457c478bd9Sstevel@tonic-gate 		vclrlin(p, tp);
7467c478bd9Sstevel@tonic-gate 	strcLIN(temp);
7477c478bd9Sstevel@tonic-gate 	hold = oldhold;
7487c478bd9Sstevel@tonic-gate 	if (heldech)
7497c478bd9Sstevel@tonic-gate 		vclrech(0);
7507c478bd9Sstevel@tonic-gate #ifdef ADEBUG
7517c478bd9Sstevel@tonic-gate 	if (trace)
7527c478bd9Sstevel@tonic-gate 		tvliny();
7537c478bd9Sstevel@tonic-gate #endif
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate /*
7577c478bd9Sstevel@tonic-gate  * Do the real work in deleting cnt lines starting at line p from
7587c478bd9Sstevel@tonic-gate  * the display.  First affected line is line l.
7597c478bd9Sstevel@tonic-gate  */
760f6db9f27Scf void
vdellin(int p,int cnt,int l)761f6db9f27Scf vdellin(int p, int cnt, int l)
7627c478bd9Sstevel@tonic-gate {
763f6db9f27Scf 	int i;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	if (cnt == 0)
7667c478bd9Sstevel@tonic-gate 		return;
7677c478bd9Sstevel@tonic-gate 	if (delete_line == NOSTR || cnt < 0) {
7687c478bd9Sstevel@tonic-gate 		/*
7697c478bd9Sstevel@tonic-gate 		 * Can't do it; just remember that line l is munged.
7707c478bd9Sstevel@tonic-gate 		 */
7717c478bd9Sstevel@tonic-gate 		FLAGS(l) |= VDIRT;
7727c478bd9Sstevel@tonic-gate 		return;
7737c478bd9Sstevel@tonic-gate 	}
7747c478bd9Sstevel@tonic-gate #ifdef ADEBUG
7757c478bd9Sstevel@tonic-gate 	if (trace)
7767c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
7777c478bd9Sstevel@tonic-gate #endif
7787c478bd9Sstevel@tonic-gate 	/*
7797c478bd9Sstevel@tonic-gate 	 * Send the deletes to the screen and then adjust logical
7807c478bd9Sstevel@tonic-gate 	 * and physical internal data structures.
7817c478bd9Sstevel@tonic-gate 	 */
7827c478bd9Sstevel@tonic-gate 	vgoto(p, 0);
7837c478bd9Sstevel@tonic-gate 	if (parm_delete_line && (cnt>1 || *delete_line==0)) {
7847c478bd9Sstevel@tonic-gate 		vputp(tparm(parm_delete_line, cnt, p), WECHO-p);
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 	else if (change_scroll_region && *delete_line==0) {
7877c478bd9Sstevel@tonic-gate 		/* vt100: fake delete_line by changing scrolling region */
7887c478bd9Sstevel@tonic-gate 		vputp(save_cursor, 1);	/* Save since change_scroll_region homes stupid cursor */
7897c478bd9Sstevel@tonic-gate 		vputp(tparm(change_scroll_region, p, lines-1), 1);
7907c478bd9Sstevel@tonic-gate 		vputp(tparm(cursor_address, lines-1, 0), 1);/* Go to lower left corner */
7917c478bd9Sstevel@tonic-gate 		for (i=0; i<cnt; i++)		/* .. and scroll cnt times */
792f6db9f27Scf 			(void) putch('\n');	/* should check NL too */
7937c478bd9Sstevel@tonic-gate 		vputp(tparm(change_scroll_region, 0, lines-1), 1);/* restore scrolling region */
7947c478bd9Sstevel@tonic-gate 		vputp(restore_cursor, 1);			/* put cursor back */
7957c478bd9Sstevel@tonic-gate 	}
7967c478bd9Sstevel@tonic-gate 	else {
7977c478bd9Sstevel@tonic-gate 		for (i = 0; i < cnt; i++)
7987c478bd9Sstevel@tonic-gate 			vputp(delete_line, WECHO - p);
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate 	vadjDL(p, cnt);
8017c478bd9Sstevel@tonic-gate 	vcloseup(l, cnt);
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate /*
8047c478bd9Sstevel@tonic-gate  * Adjust internal physical screen image to account for deleted lines.
8057c478bd9Sstevel@tonic-gate  */
806f6db9f27Scf void
vadjDL(int p,int cnt)807f6db9f27Scf vadjDL(int p, int cnt)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	wchar_t *tlines[TUBELINES];
810f6db9f27Scf 	int from, to;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate #ifdef ADEBUG
8137c478bd9Sstevel@tonic-gate 	if (trace)
8147c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt);
8157c478bd9Sstevel@tonic-gate #endif
8167c478bd9Sstevel@tonic-gate 	/*
8177c478bd9Sstevel@tonic-gate 	 * Would like to use structured assignment but early
8187c478bd9Sstevel@tonic-gate 	 * v7 compiler (released with phototypesetter for v6)
8197c478bd9Sstevel@tonic-gate 	 * can't hack it.
8207c478bd9Sstevel@tonic-gate 	 */
8217c478bd9Sstevel@tonic-gate 	copy(tlines, vtube, sizeof vtube);	/*SASSIGN*/
8227c478bd9Sstevel@tonic-gate 	for (from = p + cnt, to = p; from <= WECHO; from++, to++)
8237c478bd9Sstevel@tonic-gate 		vtube[to] = tlines[from];
8247c478bd9Sstevel@tonic-gate 	for (from = p; to <= WECHO; from++, to++) {
8257c478bd9Sstevel@tonic-gate 		vtube[to] = tlines[from];
8267c478bd9Sstevel@tonic-gate 		vclrbyte(vtube[to], WCOLS);
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate /*
8307c478bd9Sstevel@tonic-gate  * Sync the screen, like redraw but more lazy and willing to leave
8317c478bd9Sstevel@tonic-gate  * @ lines on the screen.  VsyncCL syncs starting at the current line.
8327c478bd9Sstevel@tonic-gate  * In any case, if the redraw option is set then all syncs map to redraws
8337c478bd9Sstevel@tonic-gate  * as if vsync didn't exist.
8347c478bd9Sstevel@tonic-gate  */
835f6db9f27Scf void
vsyncCL(void)836f6db9f27Scf vsyncCL(void)
8377c478bd9Sstevel@tonic-gate {
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	vsync(LINE(vcline));
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate 
842f6db9f27Scf void
vsync(int p)843f6db9f27Scf vsync(int p)
8447c478bd9Sstevel@tonic-gate {
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	if (value(vi_REDRAW))
8477c478bd9Sstevel@tonic-gate 		vredraw(p);
8487c478bd9Sstevel@tonic-gate 	else
8497c478bd9Sstevel@tonic-gate 		vsync1(p);
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate /*
8537c478bd9Sstevel@tonic-gate  * The guts of a sync.  Similar to redraw but
8547c478bd9Sstevel@tonic-gate  * just less ambitious.
8557c478bd9Sstevel@tonic-gate  */
856f6db9f27Scf void
vsync1(int p)857f6db9f27Scf vsync1(int p)
8587c478bd9Sstevel@tonic-gate {
859f6db9f27Scf 	int l;
8607c478bd9Sstevel@tonic-gate 	unsigned char temp[LBSIZE];
861f6db9f27Scf 	struct vlinfo *vp = &vlinfo[0];
8627c478bd9Sstevel@tonic-gate 	short oldhold = hold;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate #ifdef ADEBUG
8657c478bd9Sstevel@tonic-gate 	if (trace)
8667c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny();
8677c478bd9Sstevel@tonic-gate #endif
8687c478bd9Sstevel@tonic-gate 	if (holdupd) {
8697c478bd9Sstevel@tonic-gate 		if (holdupd < 3)
8707c478bd9Sstevel@tonic-gate 			holdupd = 2;
8717c478bd9Sstevel@tonic-gate 		return;
8727c478bd9Sstevel@tonic-gate 	}
8737c478bd9Sstevel@tonic-gate 	if (state == HARDOPEN || splitw)
8747c478bd9Sstevel@tonic-gate 		return;
8757c478bd9Sstevel@tonic-gate 	vscrap();
8767c478bd9Sstevel@tonic-gate 	CP(temp, linebuf);
8777c478bd9Sstevel@tonic-gate 	if (vcnt == 0)
8787c478bd9Sstevel@tonic-gate 		LINE(0) = WTOP;
8797c478bd9Sstevel@tonic-gate 	l = 0;
8807c478bd9Sstevel@tonic-gate 	while (l < vcnt && vp->vliny < p)
8817c478bd9Sstevel@tonic-gate 		l++, vp++;
8827c478bd9Sstevel@tonic-gate 	heldech = 0;
8837c478bd9Sstevel@tonic-gate 	hold |= HOLDECH;
8847c478bd9Sstevel@tonic-gate 	while (p <= WBOT && Peekkey != ATTN) {
8857c478bd9Sstevel@tonic-gate 		/*
8867c478bd9Sstevel@tonic-gate 		 * Want to put a line here if not in visual and first line
8877c478bd9Sstevel@tonic-gate 		 * or if there are lies left and this line starts before
8887c478bd9Sstevel@tonic-gate 		 * the current line, or if this line is piled under the
8897c478bd9Sstevel@tonic-gate 		 * next line (vreplace does this and we undo it).
8907c478bd9Sstevel@tonic-gate 		 */
8917c478bd9Sstevel@tonic-gate 		if (l == 0 && state != VISUAL ||
8927c478bd9Sstevel@tonic-gate 		    (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) {
8937c478bd9Sstevel@tonic-gate 			if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) {
8947c478bd9Sstevel@tonic-gate 				if (l == vcline)
8957c478bd9Sstevel@tonic-gate 					strcLIN(temp);
8967c478bd9Sstevel@tonic-gate 				else
89723a1cceaSRoger A. Faulkner 					getaline(dot[l - vcline]);
8987c478bd9Sstevel@tonic-gate 				/*
8997c478bd9Sstevel@tonic-gate 				 * Be careful that a long line doesn't cause the
9007c478bd9Sstevel@tonic-gate 				 * screen to shoot up.
9017c478bd9Sstevel@tonic-gate 				 */
9027c478bd9Sstevel@tonic-gate 				if (l != vcline && (vp->vflags & VDIRT)) {
9037c478bd9Sstevel@tonic-gate 					vp->vdepth = vdepth();
9047c478bd9Sstevel@tonic-gate 					vp->vflags &= ~VDIRT;
9057c478bd9Sstevel@tonic-gate 					if (p + vp->vdepth - 1 > WBOT)
9067c478bd9Sstevel@tonic-gate 						break;
9077c478bd9Sstevel@tonic-gate 				}
908f6db9f27Scf 				(void) vreopen(p, lineDOT() + (l - vcline), l);
9097c478bd9Sstevel@tonic-gate 			}
9107c478bd9Sstevel@tonic-gate 			p = vp->vliny + vp->vdepth;
9117c478bd9Sstevel@tonic-gate 			vp++;
9127c478bd9Sstevel@tonic-gate 			l++;
9137c478bd9Sstevel@tonic-gate 		} else
9147c478bd9Sstevel@tonic-gate 			/*
9157c478bd9Sstevel@tonic-gate 			 * A physical line between logical lines,
9167c478bd9Sstevel@tonic-gate 			 * so we settle for an @ at the beginning.
9177c478bd9Sstevel@tonic-gate 			 */
9187c478bd9Sstevel@tonic-gate 			vclrlin(p, dot + (l - vcline)), p++;
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 	strcLIN(temp);
9217c478bd9Sstevel@tonic-gate 	hold = oldhold;
9227c478bd9Sstevel@tonic-gate 	if (heldech)
9237c478bd9Sstevel@tonic-gate 		vclrech(0);
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate /*
927*55fea89dSDan Cross  * Subtract (logically) cnt physical lines from the
9287c478bd9Sstevel@tonic-gate  * displayed position of lines starting with line l.
9297c478bd9Sstevel@tonic-gate  */
930f6db9f27Scf void
vcloseup(int l,int cnt)931f6db9f27Scf vcloseup(int l, int cnt)
9327c478bd9Sstevel@tonic-gate {
933f6db9f27Scf 	int i;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate #ifdef ADEBUG
9367c478bd9Sstevel@tonic-gate 	if (trace)
9377c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt);
9387c478bd9Sstevel@tonic-gate #endif
9397c478bd9Sstevel@tonic-gate 	for (i = l + 1; i <= vcnt; i++)
9407c478bd9Sstevel@tonic-gate 		LINE(i) -= cnt;
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate /*
9447c478bd9Sstevel@tonic-gate  * Workhorse for rearranging line descriptors on changes.
9457c478bd9Sstevel@tonic-gate  * The idea here is that, starting with line l, cnt lines
9467c478bd9Sstevel@tonic-gate  * have been replaced with newcnt lines.  All of these may
9477c478bd9Sstevel@tonic-gate  * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
9487c478bd9Sstevel@tonic-gate  * since we may be called from an undo after the screen has
9497c478bd9Sstevel@tonic-gate  * moved a lot.  Thus we have to be careful.
9507c478bd9Sstevel@tonic-gate  *
9517c478bd9Sstevel@tonic-gate  * Many boundary conditions here.
9527c478bd9Sstevel@tonic-gate  */
953f6db9f27Scf void
vreplace(int l,int cnt,int newcnt)954f6db9f27Scf vreplace(int l, int cnt, int newcnt)
9557c478bd9Sstevel@tonic-gate {
956f6db9f27Scf 	int from, to, i;
9577c478bd9Sstevel@tonic-gate 	bool savenote = 0;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate #ifdef ADEBUG
9607c478bd9Sstevel@tonic-gate 	if (trace) {
9617c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
9627c478bd9Sstevel@tonic-gate 		tvliny();
9637c478bd9Sstevel@tonic-gate 	}
9647c478bd9Sstevel@tonic-gate #endif
9657c478bd9Sstevel@tonic-gate 	if (l >= vcnt)
9667c478bd9Sstevel@tonic-gate 		return;
9677c478bd9Sstevel@tonic-gate 	if (l < 0) {
9687c478bd9Sstevel@tonic-gate 		if (l + cnt < 0) {
9697c478bd9Sstevel@tonic-gate 			/*
9707c478bd9Sstevel@tonic-gate 			 * Nothing on the screen is relevant.
9717c478bd9Sstevel@tonic-gate 			 * Settle for redrawing from scratch (later).
9727c478bd9Sstevel@tonic-gate 			 */
9737c478bd9Sstevel@tonic-gate 			vcnt = 0;
9747c478bd9Sstevel@tonic-gate 			return;
9757c478bd9Sstevel@tonic-gate 		}
9767c478bd9Sstevel@tonic-gate 		/*
9777c478bd9Sstevel@tonic-gate 		 * Normalize l to top of screen; the add is
9787c478bd9Sstevel@tonic-gate 		 * really a subtract from cnt since l is negative.
9797c478bd9Sstevel@tonic-gate 		 */
9807c478bd9Sstevel@tonic-gate 		cnt += l;
9817c478bd9Sstevel@tonic-gate 		l = 0;
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 		/*
9847c478bd9Sstevel@tonic-gate 		 * Unseen lines were affected so notify (later).
9857c478bd9Sstevel@tonic-gate 		 */
9867c478bd9Sstevel@tonic-gate 		savenote++;
9877c478bd9Sstevel@tonic-gate 	}
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	/*
9907c478bd9Sstevel@tonic-gate 	 * These shouldn't happen
9917c478bd9Sstevel@tonic-gate 	 * but would cause great havoc.
9927c478bd9Sstevel@tonic-gate 	 */
9937c478bd9Sstevel@tonic-gate 	if (cnt < 0)
9947c478bd9Sstevel@tonic-gate 		cnt = 0;
9957c478bd9Sstevel@tonic-gate 	if (newcnt < 0)
9967c478bd9Sstevel@tonic-gate 		newcnt = 0;
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 	/*
9997c478bd9Sstevel@tonic-gate 	 * Surely worthy of note if more than report
10007c478bd9Sstevel@tonic-gate 	 * lines were changed.
10017c478bd9Sstevel@tonic-gate 	 */
10027c478bd9Sstevel@tonic-gate 	if (cnt > value(vi_REPORT) || newcnt > value(vi_REPORT))
10037c478bd9Sstevel@tonic-gate 		savenote++;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	/*
10067c478bd9Sstevel@tonic-gate 	 * Same number of lines affected as on screen, and we
10077c478bd9Sstevel@tonic-gate 	 * can insert and delete lines.  Thus we just type
10087c478bd9Sstevel@tonic-gate 	 * over them, since otherwise we will push them
10097c478bd9Sstevel@tonic-gate 	 * slowly off the screen, a clear lose.
10107c478bd9Sstevel@tonic-gate 	 */
10117c478bd9Sstevel@tonic-gate 	if (cnt == newcnt || vcnt - l == newcnt && insert_line && delete_line) {
10127c478bd9Sstevel@tonic-gate 		if (cnt > 1 && l + cnt > vcnt)
10137c478bd9Sstevel@tonic-gate 			savenote++;
10147c478bd9Sstevel@tonic-gate 		vdirty(l, newcnt);
10157c478bd9Sstevel@tonic-gate 	} else {
10167c478bd9Sstevel@tonic-gate 		/*
10177c478bd9Sstevel@tonic-gate 		 * Lines are going away, squish them out.
10187c478bd9Sstevel@tonic-gate 		 */
10197c478bd9Sstevel@tonic-gate 		if (cnt > 0) {
10207c478bd9Sstevel@tonic-gate 			/*
10217c478bd9Sstevel@tonic-gate 			 * If non-displayed lines went away,
10227c478bd9Sstevel@tonic-gate 			 * always notify.
10237c478bd9Sstevel@tonic-gate 			 */
10247c478bd9Sstevel@tonic-gate 			if (cnt > 1 && l + cnt > vcnt)
10257c478bd9Sstevel@tonic-gate 				savenote++;
10267c478bd9Sstevel@tonic-gate 			if (l + cnt >= vcnt)
10277c478bd9Sstevel@tonic-gate 				cnt = vcnt - l;
10287c478bd9Sstevel@tonic-gate 			else
10297c478bd9Sstevel@tonic-gate 				for (from = l + cnt, to = l; from <= vcnt; to++, from++)
10307c478bd9Sstevel@tonic-gate 					vlcopy(vlinfo[to], vlinfo[from]);
10317c478bd9Sstevel@tonic-gate 			vcnt -= cnt;
10327c478bd9Sstevel@tonic-gate 		}
10337c478bd9Sstevel@tonic-gate 		/*
10347c478bd9Sstevel@tonic-gate 		 * Open up space for new lines appearing.
10357c478bd9Sstevel@tonic-gate 		 * All new lines are piled in the same place,
10367c478bd9Sstevel@tonic-gate 		 * and will be unpiled by vredraw/vsync, which
10377c478bd9Sstevel@tonic-gate 		 * inserts lines in front as it unpiles.
10387c478bd9Sstevel@tonic-gate 		 */
10397c478bd9Sstevel@tonic-gate 		if (newcnt > 0) {
10407c478bd9Sstevel@tonic-gate 			/*
10417c478bd9Sstevel@tonic-gate 			 * Newlines are appearing which may not show,
10427c478bd9Sstevel@tonic-gate 			 * so notify (this is only approximately correct
10437c478bd9Sstevel@tonic-gate 			 * when long lines are present).
10447c478bd9Sstevel@tonic-gate 			 */
10457c478bd9Sstevel@tonic-gate 			if (newcnt > 1 && l + newcnt > vcnt + 1)
10467c478bd9Sstevel@tonic-gate 				savenote++;
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 			/*
10497c478bd9Sstevel@tonic-gate 			 * If there will be more lines than fit, then
10507c478bd9Sstevel@tonic-gate 			 * just throw way the rest of the stuff on the screen.
10517c478bd9Sstevel@tonic-gate 			 */
10527c478bd9Sstevel@tonic-gate 			if (l + newcnt > WBOT && insert_line && delete_line) {
10537c478bd9Sstevel@tonic-gate 				vcnt = l;
10547c478bd9Sstevel@tonic-gate 				goto skip;
10557c478bd9Sstevel@tonic-gate 			}
10567c478bd9Sstevel@tonic-gate 			from = vcnt, to = vcnt + newcnt;
10577c478bd9Sstevel@tonic-gate 			i = TUBELINES - to;
10587c478bd9Sstevel@tonic-gate 			if (i < 0)
10597c478bd9Sstevel@tonic-gate 				from += i, to += i;
10607c478bd9Sstevel@tonic-gate 			vcnt = to;
10617c478bd9Sstevel@tonic-gate 			for (; from >= l; from--, to--)
10627c478bd9Sstevel@tonic-gate 				vlcopy(vlinfo[to], vlinfo[from]);
10637c478bd9Sstevel@tonic-gate 			for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
10647c478bd9Sstevel@tonic-gate 				LINE(to) = LINE(from);
10657c478bd9Sstevel@tonic-gate 				DEPTH(to) = 0;
10667c478bd9Sstevel@tonic-gate 				FLAGS(to) = VDIRT;
10677c478bd9Sstevel@tonic-gate 			}
10687c478bd9Sstevel@tonic-gate 		}
10697c478bd9Sstevel@tonic-gate 	}
10707c478bd9Sstevel@tonic-gate skip:
10717c478bd9Sstevel@tonic-gate 	if (Pline == numbline && cnt != newcnt)
10727c478bd9Sstevel@tonic-gate 		/*
10737c478bd9Sstevel@tonic-gate 		 * When lines positions are shifted, the numbers
10747c478bd9Sstevel@tonic-gate 		 * will be wrong.
10757c478bd9Sstevel@tonic-gate 		 */
10767c478bd9Sstevel@tonic-gate 		vdirty(l, WECHO);
10777c478bd9Sstevel@tonic-gate 	if (!savenote)
10787c478bd9Sstevel@tonic-gate 		notecnt = 0;
10797c478bd9Sstevel@tonic-gate #ifdef ADEBUG
10807c478bd9Sstevel@tonic-gate 	if (trace)
10817c478bd9Sstevel@tonic-gate 		tvliny();
10827c478bd9Sstevel@tonic-gate #endif
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate /*
10867c478bd9Sstevel@tonic-gate  * Start harcopy open.
10877c478bd9Sstevel@tonic-gate  * Print an image of the line to the left of the cursor
10887c478bd9Sstevel@tonic-gate  * under the full print of the line and position the cursor.
10897c478bd9Sstevel@tonic-gate  * If we are in a scroll ^D within hardcopy open then all this
10907c478bd9Sstevel@tonic-gate  * is suppressed.
10917c478bd9Sstevel@tonic-gate  */
1092f6db9f27Scf void
sethard(void)1093f6db9f27Scf sethard(void)
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	if (state == VISUAL)
10977c478bd9Sstevel@tonic-gate 		return;
10987c478bd9Sstevel@tonic-gate 	rubble = 0;
10997c478bd9Sstevel@tonic-gate 	state = HARDOPEN;
11007c478bd9Sstevel@tonic-gate 	if (hold & HOLDROL)
11017c478bd9Sstevel@tonic-gate 		return;
11027c478bd9Sstevel@tonic-gate 	vup1();
11037c478bd9Sstevel@tonic-gate 	LINE(0) = WBOT;
11047c478bd9Sstevel@tonic-gate 	if (Pline == numbline)
1105f6db9f27Scf 		vgoto(WBOT, 0), viprintf("%6d  ", lineDOT());
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate /*
11097c478bd9Sstevel@tonic-gate  * Mark the lines starting at base for i lines
11107c478bd9Sstevel@tonic-gate  * as dirty so that they will be checked for correct
11117c478bd9Sstevel@tonic-gate  * display at next sync/redraw.
11127c478bd9Sstevel@tonic-gate  */
1113f6db9f27Scf void
vdirty(int base,int i)1114f6db9f27Scf vdirty(int base, int i)
11157c478bd9Sstevel@tonic-gate {
1116f6db9f27Scf 	int l;
1117*55fea89dSDan Cross 
11187c478bd9Sstevel@tonic-gate 	for (l = base; l < vcnt; l++) {
11197c478bd9Sstevel@tonic-gate 		if (--i < 0)
11207c478bd9Sstevel@tonic-gate 			return;
11217c478bd9Sstevel@tonic-gate 		FLAGS(l) |= VDIRT;
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate }
1124