xref: /dflybsd-src/contrib/nvi2/vi/v_z.c (revision 07bc39c2f4bbca56f12568e06d89da17f2eeb965)
1*e0b8e63eSJohn Marino /*-
2*e0b8e63eSJohn Marino  * Copyright (c) 1992, 1993, 1994
3*e0b8e63eSJohn Marino  *	The Regents of the University of California.  All rights reserved.
4*e0b8e63eSJohn Marino  * Copyright (c) 1992, 1993, 1994, 1995, 1996
5*e0b8e63eSJohn Marino  *	Keith Bostic.  All rights reserved.
6*e0b8e63eSJohn Marino  *
7*e0b8e63eSJohn Marino  * See the LICENSE file for redistribution information.
8*e0b8e63eSJohn Marino  */
9*e0b8e63eSJohn Marino 
10*e0b8e63eSJohn Marino #include "config.h"
11*e0b8e63eSJohn Marino 
12*e0b8e63eSJohn Marino #include <sys/types.h>
13*e0b8e63eSJohn Marino #include <sys/queue.h>
14*e0b8e63eSJohn Marino #include <sys/time.h>
15*e0b8e63eSJohn Marino 
16*e0b8e63eSJohn Marino #include <bitstring.h>
17*e0b8e63eSJohn Marino #include <limits.h>
18*e0b8e63eSJohn Marino #include <stdio.h>
19*e0b8e63eSJohn Marino 
20*e0b8e63eSJohn Marino #include "../common/common.h"
21*e0b8e63eSJohn Marino #include "vi.h"
22*e0b8e63eSJohn Marino 
23*e0b8e63eSJohn Marino /*
24*e0b8e63eSJohn Marino  * v_z -- [count]z[count][-.+^<CR>]
25*e0b8e63eSJohn Marino  *	Move the screen.
26*e0b8e63eSJohn Marino  *
27*e0b8e63eSJohn Marino  * PUBLIC: int v_z(SCR *, VICMD *);
28*e0b8e63eSJohn Marino  */
29*e0b8e63eSJohn Marino int
v_z(SCR * sp,VICMD * vp)30*e0b8e63eSJohn Marino v_z(SCR *sp, VICMD *vp)
31*e0b8e63eSJohn Marino {
32*e0b8e63eSJohn Marino 	recno_t lno;
33*e0b8e63eSJohn Marino 	e_key_t value;
34*e0b8e63eSJohn Marino 
35*e0b8e63eSJohn Marino 	/*
36*e0b8e63eSJohn Marino 	 * The first count is the line to use.  If the value doesn't
37*e0b8e63eSJohn Marino 	 * exist, use the last line.
38*e0b8e63eSJohn Marino 	 */
39*e0b8e63eSJohn Marino 	if (F_ISSET(vp, VC_C1SET)) {
40*e0b8e63eSJohn Marino 		lno = vp->count;
41*e0b8e63eSJohn Marino 		if (!db_exist(sp, lno) && db_last(sp, &lno))
42*e0b8e63eSJohn Marino 			return (1);
43*e0b8e63eSJohn Marino 	} else
44*e0b8e63eSJohn Marino 		lno = vp->m_start.lno;
45*e0b8e63eSJohn Marino 
46*e0b8e63eSJohn Marino 	/* Set default return cursor line. */
47*e0b8e63eSJohn Marino 	vp->m_final.lno = lno;
48*e0b8e63eSJohn Marino 	vp->m_final.cno = vp->m_start.cno;
49*e0b8e63eSJohn Marino 
50*e0b8e63eSJohn Marino 	/*
51*e0b8e63eSJohn Marino 	 * The second count is the displayed window size, i.e. the 'z' command
52*e0b8e63eSJohn Marino 	 * is another way to get artificially small windows.  Note, you can't
53*e0b8e63eSJohn Marino 	 * grow beyond the size of the window.
54*e0b8e63eSJohn Marino 	 *
55*e0b8e63eSJohn Marino 	 * !!!
56*e0b8e63eSJohn Marino 	 * A window size of 0 was historically allowed, and simply ignored.
57*e0b8e63eSJohn Marino 	 * This could be much more simply done by modifying the value of the
58*e0b8e63eSJohn Marino 	 * O_WINDOW option, but that's not how it worked historically.
59*e0b8e63eSJohn Marino 	 */
60*e0b8e63eSJohn Marino 	if (F_ISSET(vp, VC_C2SET) && vp->count2 != 0) {
61*e0b8e63eSJohn Marino 		if (vp->count2 > O_VAL(sp, O_WINDOW))
62*e0b8e63eSJohn Marino 			vp->count2 = O_VAL(sp, O_WINDOW);
63*e0b8e63eSJohn Marino 		if (vs_crel(sp, vp->count2))
64*e0b8e63eSJohn Marino 			return (1);
65*e0b8e63eSJohn Marino 	}
66*e0b8e63eSJohn Marino 
67*e0b8e63eSJohn Marino 	switch (vp->character) {
68*e0b8e63eSJohn Marino 	case '-':		/* Put the line at the bottom. */
69*e0b8e63eSJohn Marino 		if (vs_sm_fill(sp, lno, P_BOTTOM))
70*e0b8e63eSJohn Marino 			return (1);
71*e0b8e63eSJohn Marino 		break;
72*e0b8e63eSJohn Marino 	case '.':		/* Put the line in the middle. */
73*e0b8e63eSJohn Marino 		if (vs_sm_fill(sp, lno, P_MIDDLE))
74*e0b8e63eSJohn Marino 			return (1);
75*e0b8e63eSJohn Marino 		break;
76*e0b8e63eSJohn Marino 	case '+':
77*e0b8e63eSJohn Marino 		/*
78*e0b8e63eSJohn Marino 		 * If the user specified a line number, put that line at the
79*e0b8e63eSJohn Marino 		 * top and move the cursor to it.  Otherwise, scroll forward
80*e0b8e63eSJohn Marino 		 * a screen from the current screen.
81*e0b8e63eSJohn Marino 		 */
82*e0b8e63eSJohn Marino 		if (F_ISSET(vp, VC_C1SET)) {
83*e0b8e63eSJohn Marino 			if (vs_sm_fill(sp, lno, P_TOP))
84*e0b8e63eSJohn Marino 				return (1);
85*e0b8e63eSJohn Marino 			if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
86*e0b8e63eSJohn Marino 				return (1);
87*e0b8e63eSJohn Marino 		} else
88*e0b8e63eSJohn Marino 			if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_PLUS))
89*e0b8e63eSJohn Marino 				return (1);
90*e0b8e63eSJohn Marino 		break;
91*e0b8e63eSJohn Marino 	case '^':
92*e0b8e63eSJohn Marino 		/*
93*e0b8e63eSJohn Marino 		 * If the user specified a line number, put that line at the
94*e0b8e63eSJohn Marino 		 * bottom, move the cursor to it, and then display the screen
95*e0b8e63eSJohn Marino 		 * before that one.  Otherwise, scroll backward a screen from
96*e0b8e63eSJohn Marino 		 * the current screen.
97*e0b8e63eSJohn Marino 		 *
98*e0b8e63eSJohn Marino 		 * !!!
99*e0b8e63eSJohn Marino 		 * Note, we match the off-by-one characteristics of historic
100*e0b8e63eSJohn Marino 		 * vi, here.
101*e0b8e63eSJohn Marino 		 */
102*e0b8e63eSJohn Marino 		if (F_ISSET(vp, VC_C1SET)) {
103*e0b8e63eSJohn Marino 			if (vs_sm_fill(sp, lno, P_BOTTOM))
104*e0b8e63eSJohn Marino 				return (1);
105*e0b8e63eSJohn Marino 			if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
106*e0b8e63eSJohn Marino 				return (1);
107*e0b8e63eSJohn Marino 			if (vs_sm_fill(sp, vp->m_final.lno, P_BOTTOM))
108*e0b8e63eSJohn Marino 				return (1);
109*e0b8e63eSJohn Marino 		} else
110*e0b8e63eSJohn Marino 			if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_CARAT))
111*e0b8e63eSJohn Marino 				return (1);
112*e0b8e63eSJohn Marino 		break;
113*e0b8e63eSJohn Marino 	default:		/* Put the line at the top for <cr>. */
114*e0b8e63eSJohn Marino 		value = KEY_VAL(sp, vp->character);
115*e0b8e63eSJohn Marino 		if (value != K_CR && value != K_NL) {
116*e0b8e63eSJohn Marino 			v_emsg(sp, vp->kp->usage, VIM_USAGE);
117*e0b8e63eSJohn Marino 			return (1);
118*e0b8e63eSJohn Marino 		}
119*e0b8e63eSJohn Marino 		if (vs_sm_fill(sp, lno, P_TOP))
120*e0b8e63eSJohn Marino 			return (1);
121*e0b8e63eSJohn Marino 		break;
122*e0b8e63eSJohn Marino 	}
123*e0b8e63eSJohn Marino 	return (0);
124*e0b8e63eSJohn Marino }
125*e0b8e63eSJohn Marino 
126*e0b8e63eSJohn Marino /*
127*e0b8e63eSJohn Marino  * vs_crel --
128*e0b8e63eSJohn Marino  *	Change the relative size of the current screen.
129*e0b8e63eSJohn Marino  *
130*e0b8e63eSJohn Marino  * PUBLIC: int vs_crel(SCR *, long);
131*e0b8e63eSJohn Marino  */
132*e0b8e63eSJohn Marino int
vs_crel(SCR * sp,long int count)133*e0b8e63eSJohn Marino vs_crel(SCR *sp, long int count)
134*e0b8e63eSJohn Marino {
135*e0b8e63eSJohn Marino 	sp->t_minrows = sp->t_rows = count;
136*e0b8e63eSJohn Marino 	if (sp->t_rows > sp->rows - 1)
137*e0b8e63eSJohn Marino 		sp->t_minrows = sp->t_rows = sp->rows - 1;
138*e0b8e63eSJohn Marino 	TMAP = HMAP + (sp->t_rows - 1);
139*e0b8e63eSJohn Marino 	F_SET(sp, SC_SCR_REDRAW);
140*e0b8e63eSJohn Marino 	return (0);
141*e0b8e63eSJohn Marino }
142