]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/nvi/vi/v_z.c
Update nvi to 2.2.0
[FreeBSD/FreeBSD.git] / contrib / nvi / vi / v_z.c
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
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
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 }