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