xref: /illumos-gate/usr/src/cmd/vi/port/ex_vwind.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 
22f6db9f27Scf /*
2323a1cceaSRoger A. Faulkner  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24f6db9f27Scf  */
25f6db9f27Scf 
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 */
31f6db9f27Scf 
327c478bd9Sstevel@tonic-gate #include "ex.h"
337c478bd9Sstevel@tonic-gate #include "ex_tty.h"
347c478bd9Sstevel@tonic-gate #include "ex_vis.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * Routines to adjust the window, showing specified lines
387c478bd9Sstevel@tonic-gate  * in certain positions on the screen, and scrolling in both
397c478bd9Sstevel@tonic-gate  * directions.  Code here is very dependent on mode (open versus visual).
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * Move in a nonlocal way to line addr.
447c478bd9Sstevel@tonic-gate  * If it isn't on screen put it in specified context.
457c478bd9Sstevel@tonic-gate  * New position for cursor is curs.
467c478bd9Sstevel@tonic-gate  * Like most routines here, we vsave().
477c478bd9Sstevel@tonic-gate  */
48f6db9f27Scf void
vmoveto(addr,curs,context)497c478bd9Sstevel@tonic-gate vmoveto(addr, curs, context)
50f6db9f27Scf 	line *addr;
517c478bd9Sstevel@tonic-gate 	unsigned char *curs;
527c478bd9Sstevel@tonic-gate 	unsigned char context;
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	markit(addr);
567c478bd9Sstevel@tonic-gate 	vsave();
577c478bd9Sstevel@tonic-gate 	vjumpto(addr, curs, context);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * Vjumpto is like vmoveto, but doesn't mark previous
627c478bd9Sstevel@tonic-gate  * context or save linebuf as current line.
637c478bd9Sstevel@tonic-gate  */
64f6db9f27Scf void
vjumpto(line * addr,unsigned char * curs,unsigned char context)65f6db9f27Scf vjumpto(line *addr, unsigned char *curs, unsigned char context)
667c478bd9Sstevel@tonic-gate {
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	noteit(0);
697c478bd9Sstevel@tonic-gate 	if (context != 0)
707c478bd9Sstevel@tonic-gate 		vcontext(addr, context);
717c478bd9Sstevel@tonic-gate 	else
727c478bd9Sstevel@tonic-gate 		vshow(addr, NOLINE);
737c478bd9Sstevel@tonic-gate 	noteit(1);
747c478bd9Sstevel@tonic-gate 	vnline(curs);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate  * Go up or down cnt (negative is up) to new position curs.
797c478bd9Sstevel@tonic-gate  */
80f6db9f27Scf void
vupdown(int cnt,unsigned char * curs)81f6db9f27Scf vupdown(int cnt, unsigned char *curs)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (cnt > 0)
857c478bd9Sstevel@tonic-gate 		vdown(cnt, 0, 0);
867c478bd9Sstevel@tonic-gate 	else if (cnt < 0)
877c478bd9Sstevel@tonic-gate 		vup(-cnt, 0, 0);
887c478bd9Sstevel@tonic-gate 	if (vcnt == 0)
897c478bd9Sstevel@tonic-gate 		vrepaint(curs);
907c478bd9Sstevel@tonic-gate 	else
917c478bd9Sstevel@tonic-gate 		vnline(curs);
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * Go up cnt lines, afterwards preferring to be ind
967c478bd9Sstevel@tonic-gate  * logical lines from the top of the screen.
977c478bd9Sstevel@tonic-gate  * If scroll, then we MUST use a scroll.
987c478bd9Sstevel@tonic-gate  * Otherwise clear and redraw if motion is far.
997c478bd9Sstevel@tonic-gate  */
100f6db9f27Scf void
vup(int cnt,int ind,bool scroll)101f6db9f27Scf vup(int cnt, int ind, bool scroll)
1027c478bd9Sstevel@tonic-gate {
103f6db9f27Scf 	int i, tot;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	if (dot == one) {
106f6db9f27Scf 		(void) beep();
1077c478bd9Sstevel@tonic-gate 		return;
1087c478bd9Sstevel@tonic-gate 	}
1097c478bd9Sstevel@tonic-gate 	vsave();
1107c478bd9Sstevel@tonic-gate 	i = lineDOT() - 1;
1117c478bd9Sstevel@tonic-gate 	if (cnt > i) {
1127c478bd9Sstevel@tonic-gate 		ind -= cnt - i;
1137c478bd9Sstevel@tonic-gate 		if (ind < 0)
1147c478bd9Sstevel@tonic-gate 			ind = 0;
1157c478bd9Sstevel@tonic-gate 		cnt = i;
1167c478bd9Sstevel@tonic-gate 	}
1177c478bd9Sstevel@tonic-gate 	if (!scroll && cnt <= vcline) {
1187c478bd9Sstevel@tonic-gate 		vshow(dot - cnt, NOLINE);
1197c478bd9Sstevel@tonic-gate 		return;
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 	cnt -= vcline, dot -= vcline, vcline = 0;
1227c478bd9Sstevel@tonic-gate 	if (hold & HOLDWIG)
1237c478bd9Sstevel@tonic-gate 		goto contxt;
1247c478bd9Sstevel@tonic-gate 	if (state == VISUAL && !insert_line && !scroll_reverse &&
1257c478bd9Sstevel@tonic-gate 	    cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
1267c478bd9Sstevel@tonic-gate 		goto okr;
1277c478bd9Sstevel@tonic-gate 	tot = WECHO - WTOP;
1287c478bd9Sstevel@tonic-gate 	if (state != VISUAL || (!insert_line && !scroll_reverse) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
1297c478bd9Sstevel@tonic-gate 		if (ind > basWLINES / 2)
1307c478bd9Sstevel@tonic-gate 			ind = basWLINES / 3;
1317c478bd9Sstevel@tonic-gate contxt:
1327c478bd9Sstevel@tonic-gate 		vcontext(dot + ind - cnt, '.');
1337c478bd9Sstevel@tonic-gate 		return;
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate okr:
1367c478bd9Sstevel@tonic-gate 	vrollR(cnt);
1377c478bd9Sstevel@tonic-gate 	if (scroll) {
1387c478bd9Sstevel@tonic-gate 		vcline += ind, dot += ind;
1397c478bd9Sstevel@tonic-gate 		if (vcline >= vcnt)
1407c478bd9Sstevel@tonic-gate 			dot -= vcline - vcnt + 1, vcline = vcnt - 1;
1417c478bd9Sstevel@tonic-gate 		getDOT();
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate /*
1467c478bd9Sstevel@tonic-gate  * Like vup, but scrolling down.
1477c478bd9Sstevel@tonic-gate  */
148f6db9f27Scf void
vdown(int cnt,int ind,bool scroll)149f6db9f27Scf vdown(int cnt, int ind, bool scroll)
1507c478bd9Sstevel@tonic-gate {
151f6db9f27Scf 	int i, tot;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	if (dot == dol) {
154f6db9f27Scf 		(void) beep();
1557c478bd9Sstevel@tonic-gate 		return;
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 	vsave();
1587c478bd9Sstevel@tonic-gate 	i = dol - dot;
1597c478bd9Sstevel@tonic-gate 	if (cnt > i) {
1607c478bd9Sstevel@tonic-gate 		ind -= cnt - i;
1617c478bd9Sstevel@tonic-gate 		if (ind < 0)
1627c478bd9Sstevel@tonic-gate 			ind = 0;
1637c478bd9Sstevel@tonic-gate 		cnt = i;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	i = vcnt - vcline - 1;
1667c478bd9Sstevel@tonic-gate 	if (!scroll && cnt <= i) {
1677c478bd9Sstevel@tonic-gate 		vshow(dot + cnt, NOLINE);
1687c478bd9Sstevel@tonic-gate 		return;
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 	cnt -= i, dot += i, vcline += i;
1717c478bd9Sstevel@tonic-gate 	if (hold & HOLDWIG)
1727c478bd9Sstevel@tonic-gate 		goto dcontxt;
1737c478bd9Sstevel@tonic-gate 	if (!scroll) {
1747c478bd9Sstevel@tonic-gate 		tot = WECHO - WTOP;
1757c478bd9Sstevel@tonic-gate 		if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
1767c478bd9Sstevel@tonic-gate dcontxt:
1777c478bd9Sstevel@tonic-gate 			vcontext(dot + cnt, '.');
1787c478bd9Sstevel@tonic-gate 			return;
1797c478bd9Sstevel@tonic-gate 		}
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate 	if (cnt > 0)
1827c478bd9Sstevel@tonic-gate 		vroll(cnt);
1837c478bd9Sstevel@tonic-gate 	if (state == VISUAL && scroll) {
1847c478bd9Sstevel@tonic-gate 		vcline -= ind, dot -= ind;
1857c478bd9Sstevel@tonic-gate 		if (vcline < 0)
1867c478bd9Sstevel@tonic-gate 			dot -= vcline, vcline = 0;
1877c478bd9Sstevel@tonic-gate 		getDOT();
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * Show line addr in context where on the screen.
1937c478bd9Sstevel@tonic-gate  * Work here is in determining new top line implied by
1947c478bd9Sstevel@tonic-gate  * this placement of line addr, since we always draw from the top.
1957c478bd9Sstevel@tonic-gate  */
196f6db9f27Scf void
vcontext(line * addr,unsigned char where)197f6db9f27Scf vcontext(line *addr, unsigned char where)
1987c478bd9Sstevel@tonic-gate {
199f6db9f27Scf 	line *top;
2007c478bd9Sstevel@tonic-gate 
20123a1cceaSRoger A. Faulkner 	getaline(*addr);
2027c478bd9Sstevel@tonic-gate 	if (state != VISUAL)
2037c478bd9Sstevel@tonic-gate 		top = addr;
2047c478bd9Sstevel@tonic-gate 	else switch (where) {
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	case '^':
2077c478bd9Sstevel@tonic-gate 		addr = vback(addr, basWLINES - vdepth());
20823a1cceaSRoger A. Faulkner 		getaline(*addr);
2099097ca5cSToomas Soome 		/* FALLTHROUGH */
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	case '-':
2127c478bd9Sstevel@tonic-gate 		top = vback(addr, basWLINES - vdepth());
21323a1cceaSRoger A. Faulkner 		getaline(*addr);
2147c478bd9Sstevel@tonic-gate 		break;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	case '.':
2177c478bd9Sstevel@tonic-gate 		top = vback(addr, basWLINES / 2 - vdepth());
21823a1cceaSRoger A. Faulkner 		getaline(*addr);
2197c478bd9Sstevel@tonic-gate 		break;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	default:
2227c478bd9Sstevel@tonic-gate 		top = addr;
2237c478bd9Sstevel@tonic-gate 		break;
2247c478bd9Sstevel@tonic-gate 	}
2257c478bd9Sstevel@tonic-gate 	if (state == ONEOPEN && LINE(0) == WBOT)
2267c478bd9Sstevel@tonic-gate 		vup1();
2277c478bd9Sstevel@tonic-gate 	vcnt = vcline = 0;
2287c478bd9Sstevel@tonic-gate 	vclean();
2297c478bd9Sstevel@tonic-gate 	if (state == CRTOPEN)
2307c478bd9Sstevel@tonic-gate 		vup1();
2317c478bd9Sstevel@tonic-gate 	vshow(addr, top);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate  * Get a clean line.  If we are in a hard open
2367c478bd9Sstevel@tonic-gate  * we may be able to reuse the line we are on
2377c478bd9Sstevel@tonic-gate  * if it is blank.  This is a real win.
2387c478bd9Sstevel@tonic-gate  */
239f6db9f27Scf void
vclean(void)240f6db9f27Scf vclean(void)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	if (state != VISUAL && state != CRTOPEN) {
2447c478bd9Sstevel@tonic-gate 		destcol = 0;
2457c478bd9Sstevel@tonic-gate 		if (!ateopr())
2467c478bd9Sstevel@tonic-gate 			vup1();
2477c478bd9Sstevel@tonic-gate 		vcnt = 0;
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * Show line addr with the specified top line on the screen.
2537c478bd9Sstevel@tonic-gate  * Top may be 0; in this case have vcontext compute the top
2547c478bd9Sstevel@tonic-gate  * (and call us recursively).  Eventually, we clear the screen
2557c478bd9Sstevel@tonic-gate  * (or its open mode equivalent) and redraw.
2567c478bd9Sstevel@tonic-gate  */
257f6db9f27Scf void
vshow(line * addr,line * top)258f6db9f27Scf vshow(line *addr, line *top)
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate #ifndef CBREAK
261f6db9f27Scf 	bool fried = 0;
2627c478bd9Sstevel@tonic-gate #endif
263f6db9f27Scf 	int cnt = addr - dot;
264f6db9f27Scf 	int i = vcline + cnt;
2657c478bd9Sstevel@tonic-gate 	short oldhold = hold;
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
2687c478bd9Sstevel@tonic-gate 		dot = addr;
2697c478bd9Sstevel@tonic-gate 		getDOT();
2707c478bd9Sstevel@tonic-gate 		vcline = i;
2717c478bd9Sstevel@tonic-gate 		return;
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 	if (state != VISUAL) {
2747c478bd9Sstevel@tonic-gate 		dot = addr;
2757c478bd9Sstevel@tonic-gate 		vopen(dot, WBOT);
2767c478bd9Sstevel@tonic-gate 		return;
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 	if (top == 0) {
2797c478bd9Sstevel@tonic-gate 		vcontext(addr, '.');
2807c478bd9Sstevel@tonic-gate 		return;
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 	dot = top;
2837c478bd9Sstevel@tonic-gate #ifndef CBREAK
2847c478bd9Sstevel@tonic-gate 	if (vcookit(2))
2857c478bd9Sstevel@tonic-gate 		fried++, vcook();
2867c478bd9Sstevel@tonic-gate #endif
2877c478bd9Sstevel@tonic-gate 	oldhold = hold;
2887c478bd9Sstevel@tonic-gate 	hold |= HOLDAT;
2897c478bd9Sstevel@tonic-gate 	vclear();
2907c478bd9Sstevel@tonic-gate 	vreset(0);
2917c478bd9Sstevel@tonic-gate 	vredraw(WTOP);
2927c478bd9Sstevel@tonic-gate 	/* error if vcline >= vcnt ! */
2937c478bd9Sstevel@tonic-gate 	vcline = addr - top;
2947c478bd9Sstevel@tonic-gate 	dot = addr;
2957c478bd9Sstevel@tonic-gate 	getDOT();
2967c478bd9Sstevel@tonic-gate 	hold = oldhold;
2977c478bd9Sstevel@tonic-gate 	vsync(LASTLINE);
2987c478bd9Sstevel@tonic-gate #ifndef CBREAK
2997c478bd9Sstevel@tonic-gate 	if (fried)
3007c478bd9Sstevel@tonic-gate 		flusho(), vraw();
3017c478bd9Sstevel@tonic-gate #endif
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate  * reset the state.
3067c478bd9Sstevel@tonic-gate  * If inecho then leave us at the beginning of the echo
3077c478bd9Sstevel@tonic-gate  * area;  we are called this way in the middle of a :e escape
3087c478bd9Sstevel@tonic-gate  * from visual, e.g.
3097c478bd9Sstevel@tonic-gate  */
310f6db9f27Scf void
vreset(bool inecho)311f6db9f27Scf vreset(bool inecho)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	vcnt = vcline = 0;
3157c478bd9Sstevel@tonic-gate 	WTOP = basWTOP;
3167c478bd9Sstevel@tonic-gate 	WLINES = basWLINES;
3177c478bd9Sstevel@tonic-gate 	if (inecho)
3187c478bd9Sstevel@tonic-gate 		splitw = 1, vgoto(WECHO, 0);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate  * Starting from which line preceding tp uses almost (but not more
3237c478bd9Sstevel@tonic-gate  * than) cnt physical lines?
3247c478bd9Sstevel@tonic-gate  */
3257c478bd9Sstevel@tonic-gate line *
vback(tp,cnt)3267c478bd9Sstevel@tonic-gate vback(tp, cnt)
327f6db9f27Scf 	int cnt;
328f6db9f27Scf 	line *tp;
3297c478bd9Sstevel@tonic-gate {
330f6db9f27Scf 	int d;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	if (cnt > 0)
3337c478bd9Sstevel@tonic-gate 		for (; tp > one; tp--) {
33423a1cceaSRoger A. Faulkner 			getaline(tp[-1]);
3357c478bd9Sstevel@tonic-gate 			d = vdepth();
3367c478bd9Sstevel@tonic-gate 			if (d > cnt)
3377c478bd9Sstevel@tonic-gate 				break;
3387c478bd9Sstevel@tonic-gate 			cnt -= d;
3397c478bd9Sstevel@tonic-gate 		}
3407c478bd9Sstevel@tonic-gate 	return (tp);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate /*
3447c478bd9Sstevel@tonic-gate  * How much scrolling will it take to roll cnt lines starting at tp?
3457c478bd9Sstevel@tonic-gate  */
346f6db9f27Scf int
vfit(line * tp,int cnt)347f6db9f27Scf vfit(line *tp, int cnt)
3487c478bd9Sstevel@tonic-gate {
349f6db9f27Scf 	int j;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	j = 0;
3527c478bd9Sstevel@tonic-gate 	while (cnt > 0) {
3537c478bd9Sstevel@tonic-gate 		cnt--;
35423a1cceaSRoger A. Faulkner 		getaline(tp[cnt]);
3557c478bd9Sstevel@tonic-gate 		j += vdepth();
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 	if (tp > dot)
3587c478bd9Sstevel@tonic-gate 		j -= WBOT - LASTLINE;
3597c478bd9Sstevel@tonic-gate 	return (j);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate  * Roll cnt lines onto the screen.
3647c478bd9Sstevel@tonic-gate  */
365f6db9f27Scf void
vroll(int cnt)366f6db9f27Scf vroll(int cnt)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate #ifndef CBREAK
369f6db9f27Scf 	bool fried = 0;
3707c478bd9Sstevel@tonic-gate #endif
3717c478bd9Sstevel@tonic-gate 	short oldhold = hold;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate #ifdef ADEBUG
3747c478bd9Sstevel@tonic-gate 	if (trace)
3757c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
3767c478bd9Sstevel@tonic-gate #endif
3777c478bd9Sstevel@tonic-gate 	if (state != VISUAL)
3787c478bd9Sstevel@tonic-gate 		hold |= HOLDAT|HOLDROL;
3797c478bd9Sstevel@tonic-gate 	if (WBOT == WECHO) {
3807c478bd9Sstevel@tonic-gate 		vcnt = 0;
3817c478bd9Sstevel@tonic-gate 		if (state == ONEOPEN)
3827c478bd9Sstevel@tonic-gate 			vup1();
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate #ifndef CBREAK
3857c478bd9Sstevel@tonic-gate 	if (vcookit(cnt))
3867c478bd9Sstevel@tonic-gate 		fried++, vcook();
3877c478bd9Sstevel@tonic-gate #endif
3887c478bd9Sstevel@tonic-gate 	for (; cnt > 0 && Peekkey != ATTN; cnt--) {
3897c478bd9Sstevel@tonic-gate 		dot++, vcline++;
3907c478bd9Sstevel@tonic-gate 		vopen(dot, LASTLINE);
3917c478bd9Sstevel@tonic-gate 		vscrap();
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 	hold = oldhold;
3947c478bd9Sstevel@tonic-gate 	if (state == HARDOPEN)
3957c478bd9Sstevel@tonic-gate 		sethard();
3967c478bd9Sstevel@tonic-gate 	vsyncCL();
3977c478bd9Sstevel@tonic-gate #ifndef CBREAK
3987c478bd9Sstevel@tonic-gate 	if (fried)
3997c478bd9Sstevel@tonic-gate 		flusho(), vraw();
4007c478bd9Sstevel@tonic-gate #endif
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate /*
4047c478bd9Sstevel@tonic-gate  * Roll backwards (scroll up).
4057c478bd9Sstevel@tonic-gate  */
406f6db9f27Scf void
vrollR(int cnt)407f6db9f27Scf vrollR(int cnt)
4087c478bd9Sstevel@tonic-gate {
409f6db9f27Scf 	bool fried = 0;
4107c478bd9Sstevel@tonic-gate 	short oldhold = hold;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate #ifdef ADEBUG
4137c478bd9Sstevel@tonic-gate 	if (trace)
4147c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
4157c478bd9Sstevel@tonic-gate #endif
4167c478bd9Sstevel@tonic-gate #ifndef CBREAK
4177c478bd9Sstevel@tonic-gate 	if (vcookit(cnt))
4187c478bd9Sstevel@tonic-gate 		fried++, vcook();
4197c478bd9Sstevel@tonic-gate #endif
4207c478bd9Sstevel@tonic-gate 	if (WBOT == WECHO)
4217c478bd9Sstevel@tonic-gate 		vcnt = 0;
4227c478bd9Sstevel@tonic-gate 	heldech = 0;
4237c478bd9Sstevel@tonic-gate 	hold |= HOLDAT|HOLDECH;
4247c478bd9Sstevel@tonic-gate 	for (; cnt > 0 && Peekkey != ATTN; cnt--) {
4257c478bd9Sstevel@tonic-gate 		dot--;
4267c478bd9Sstevel@tonic-gate 		vopen(dot, WTOP);
4277c478bd9Sstevel@tonic-gate 		vscrap();
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 	hold = oldhold;
4307c478bd9Sstevel@tonic-gate 	if (heldech)
4317c478bd9Sstevel@tonic-gate 		vclrech(0);
4327c478bd9Sstevel@tonic-gate 	vsync(LINE(vcnt-1));
4337c478bd9Sstevel@tonic-gate #ifndef CBREAK
4347c478bd9Sstevel@tonic-gate 	if (fried)
4357c478bd9Sstevel@tonic-gate 		flusho(), vraw();
4367c478bd9Sstevel@tonic-gate #endif
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate  * Go into cooked mode (allow interrupts) during
4417c478bd9Sstevel@tonic-gate  * a scroll if we are at less than 1200 baud and not
4427c478bd9Sstevel@tonic-gate  * a 'vi' command, of if we are in a 'vi' command and the
4437c478bd9Sstevel@tonic-gate  * scroll is more than 2 full screens.
4447c478bd9Sstevel@tonic-gate  *
4457c478bd9Sstevel@tonic-gate  * BUG:		An interrupt during a scroll in this way
4467c478bd9Sstevel@tonic-gate  *		dumps to command mode.
4477c478bd9Sstevel@tonic-gate  */
448f6db9f27Scf int
vcookit(int cnt)449f6db9f27Scf vcookit(int cnt)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	return (cnt > 1 && (ospeed < B1200 && !initev || cnt > lines * 2));
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate  * Determine displayed depth of current line.
4577c478bd9Sstevel@tonic-gate  */
458f6db9f27Scf int
vdepth(void)459f6db9f27Scf vdepth(void)
4607c478bd9Sstevel@tonic-gate {
461f6db9f27Scf 	int d;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + insert_null_glitch) / WCOLS;
4647c478bd9Sstevel@tonic-gate #ifdef ADEBUG
4657c478bd9Sstevel@tonic-gate 	if (trace)
4667c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
4677c478bd9Sstevel@tonic-gate #endif
4687c478bd9Sstevel@tonic-gate 	return (d == 0 ? 1 : d);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate /*
4727c478bd9Sstevel@tonic-gate  * Move onto a new line, with cursor at position curs.
4737c478bd9Sstevel@tonic-gate  */
474f6db9f27Scf void
vnline(unsigned char * curs)475f6db9f27Scf vnline(unsigned char *curs)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate 	unsigned char *owcursor;
4787c478bd9Sstevel@tonic-gate 	int j;
4797c478bd9Sstevel@tonic-gate 	if (curs) {
4807c478bd9Sstevel@tonic-gate 		if(curs >= strend(linebuf)) {
4817c478bd9Sstevel@tonic-gate 			if(!*linebuf)
4827c478bd9Sstevel@tonic-gate 				wcursor = linebuf;
4837c478bd9Sstevel@tonic-gate 			else {
4847c478bd9Sstevel@tonic-gate 				wcursor = strend(linebuf);
4857c478bd9Sstevel@tonic-gate 				wcursor = lastchr(linebuf, wcursor);
4867c478bd9Sstevel@tonic-gate 			}
4877c478bd9Sstevel@tonic-gate 		} else {
4887c478bd9Sstevel@tonic-gate 			owcursor = wcursor = curs;
4897c478bd9Sstevel@tonic-gate 			j = wcursor - linebuf;
4907c478bd9Sstevel@tonic-gate 			for(wcursor = linebuf; wcursor - linebuf < j; ) {
4917c478bd9Sstevel@tonic-gate 				owcursor = wcursor;
4927c478bd9Sstevel@tonic-gate 				wcursor = nextchr(wcursor);
4937c478bd9Sstevel@tonic-gate 			}
4947c478bd9Sstevel@tonic-gate 			if(wcursor - linebuf > j)
4957c478bd9Sstevel@tonic-gate 				wcursor = owcursor;
4967c478bd9Sstevel@tonic-gate 		}
497*55fea89dSDan Cross 
4987c478bd9Sstevel@tonic-gate 	} else if (vmoving)
4997c478bd9Sstevel@tonic-gate 		wcursor = vfindcol(vmovcol);
5007c478bd9Sstevel@tonic-gate 	else
5017c478bd9Sstevel@tonic-gate 		wcursor = vskipwh(linebuf);
5027c478bd9Sstevel@tonic-gate 	cursor = linebuf;
503f6db9f27Scf 	(void) vmove();
5047c478bd9Sstevel@tonic-gate }
505