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