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