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