]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/nvi/vi/v_left.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / nvi / vi / v_left.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 #ifndef lint
13 static const char sccsid[] = "$Id: v_left.c,v 10.9 2001/06/25 15:19:32 skimo Exp $";
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_left -- [count]^H, [count]h
29  *      Move left by columns.
30  *
31  * PUBLIC: int v_left __P((SCR *, VICMD *));
32  */
33 int
34 v_left(SCR *sp, VICMD *vp)
35 {
36         recno_t cnt;
37
38         /*
39          * !!!
40          * The ^H and h commands always failed in the first column.
41          */
42         if (vp->m_start.cno == 0) {
43                 v_sol(sp);
44                 return (1);
45         }
46
47         /* Find the end of the range. */
48         cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
49         if (vp->m_start.cno > cnt)
50                 vp->m_stop.cno = vp->m_start.cno - cnt;
51         else
52                 vp->m_stop.cno = 0;
53
54         /*
55          * All commands move to the end of the range.  Motion commands
56          * adjust the starting point to the character before the current
57          * one.
58          */
59         if (ISMOTION(vp))
60                 --vp->m_start.cno;
61         vp->m_final = vp->m_stop;
62         return (0);
63 }
64
65 /*
66  * v_cfirst -- [count]_
67  *      Move to the first non-blank character in a line.
68  *
69  * PUBLIC: int v_cfirst __P((SCR *, VICMD *));
70  */
71 int
72 v_cfirst(SCR *sp, VICMD *vp)
73 {
74         recno_t cnt, lno;
75
76         /*
77          * !!!
78          * If the _ is a motion component, it makes the command a line motion
79          * e.g. "d_" deletes the line.  It also means that the cursor doesn't
80          * move.
81          *
82          * The _ command never failed in the first column.
83          */
84         if (ISMOTION(vp))
85                 F_SET(vp, VM_LMODE);
86         /*
87          * !!!
88          * Historically a specified count makes _ move down count - 1
89          * rows, so, "3_" is the same as "2j_".
90          */
91         cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
92         if (cnt != 1) {
93                 --vp->count;
94                 return (v_down(sp, vp));
95         }
96
97         /*
98          * Move to the first non-blank.
99          *
100          * Can't just use RCM_SET_FNB, in case _ is used as the motion
101          * component of another command.
102          */
103         vp->m_stop.cno = 0;
104         if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
105                 return (1);
106
107         /*
108          * !!!
109          * The _ command has to fail if the file is empty and we're doing
110          * a delete.  If deleting line 1, and 0 is the first nonblank,
111          * make the check.
112          */
113         if (vp->m_stop.lno == 1 &&
114             vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) {
115                 if (db_last(sp, &lno))
116                         return (1);
117                 if (lno == 0) {
118                         v_sol(sp);
119                         return (1);
120                 }
121         }
122
123         /*
124          * Delete and non-motion commands move to the end of the range,
125          * yank stays at the start.  Ignore others.
126          */
127         vp->m_final =
128             ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop;
129         return (0);
130 }
131
132 /*
133  * v_first -- ^
134  *      Move to the first non-blank character in this line.
135  *
136  * PUBLIC: int v_first __P((SCR *, VICMD *));
137  */
138 int
139 v_first(SCR *sp, VICMD *vp)
140 {
141         /*
142          * !!!
143          * Yielding to none in our quest for compatibility with every
144          * historical blemish of vi, no matter how strange it might be,
145          * we permit the user to enter a count and then ignore it.
146          */
147
148         /*
149          * Move to the first non-blank.
150          *
151          * Can't just use RCM_SET_FNB, in case ^ is used as the motion
152          * component of another command.
153          */
154         vp->m_stop.cno = 0;
155         if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
156                 return (1);
157
158         /*
159          * !!!
160          * The ^ command succeeded if used as a command when the cursor was
161          * on the first non-blank in the line, but failed if used as a motion
162          * component in the same situation.
163          */
164         if (ISMOTION(vp) && vp->m_start.cno == vp->m_stop.cno) {
165                 v_sol(sp);
166                 return (1);
167         }
168
169         /*
170          * If moving right, non-motion commands move to the end of the range.
171          * Delete and yank stay at the start.  Motion commands adjust the
172          * ending point to the character before the current ending charcter.
173          *
174          * If moving left, all commands move to the end of the range.  Motion
175          * commands adjust the starting point to the character before the
176          * current starting character.
177          */
178         if (vp->m_start.cno < vp->m_stop.cno)
179                 if (ISMOTION(vp)) {
180                         --vp->m_stop.cno;
181                         vp->m_final = vp->m_start;
182                 } else
183                         vp->m_final = vp->m_stop;
184         else {
185                 if (ISMOTION(vp))
186                         --vp->m_start.cno;
187                 vp->m_final = vp->m_stop;
188         }
189         return (0);
190 }
191
192 /*
193  * v_ncol -- [count]|
194  *      Move to column count or the first column on this line.  If the
195  *      requested column is past EOL, move to EOL.  The nasty part is
196  *      that we have to know character column widths to make this work.
197  *
198  * PUBLIC: int v_ncol __P((SCR *, VICMD *));
199  */
200 int
201 v_ncol(SCR *sp, VICMD *vp)
202 {
203         if (F_ISSET(vp, VC_C1SET) && vp->count > 1) {
204                 --vp->count;
205                 vp->m_stop.cno =
206                     vs_colpos(sp, vp->m_start.lno, (size_t)vp->count);
207                 /*
208                  * !!!
209                  * The | command succeeded if used as a command and the cursor
210                  * didn't move, but failed if used as a motion component in the
211                  * same situation.
212                  */
213                 if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) {
214                         v_nomove(sp);
215                         return (1);
216                 }
217         } else {
218                 /*
219                  * !!!
220                  * The | command succeeded if used as a command in column 0
221                  * without a count, but failed if used as a motion component
222                  * in the same situation.
223                  */
224                 if (ISMOTION(vp) && vp->m_start.cno == 0) {
225                         v_sol(sp);
226                         return (1);
227                 }
228                 vp->m_stop.cno = 0;
229         }
230
231         /*
232          * If moving right, non-motion commands move to the end of the range.
233          * Delete and yank stay at the start.  Motion commands adjust the
234          * ending point to the character before the current ending charcter.
235          *
236          * If moving left, all commands move to the end of the range.  Motion
237          * commands adjust the starting point to the character before the
238          * current starting character.
239          */
240         if (vp->m_start.cno < vp->m_stop.cno)
241                 if (ISMOTION(vp)) {
242                         --vp->m_stop.cno;
243                         vp->m_final = vp->m_start;
244                 } else
245                         vp->m_final = vp->m_stop;
246         else {
247                 if (ISMOTION(vp))
248                         --vp->m_start.cno;
249                 vp->m_final = vp->m_stop;
250         }
251         return (0);
252 }
253
254 /*
255  * v_zero -- 0
256  *      Move to the first column on this line.
257  *
258  * PUBLIC: int v_zero __P((SCR *, VICMD *));
259  */
260 int
261 v_zero(SCR *sp, VICMD *vp)
262 {
263         /*
264          * !!!
265          * The 0 command succeeded if used as a command in the first column
266          * but failed if used as a motion component in the same situation.
267          */
268         if (ISMOTION(vp) && vp->m_start.cno == 0) {
269                 v_sol(sp);
270                 return (1);
271         }
272
273         /*
274          * All commands move to the end of the range.  Motion commands
275          * adjust the starting point to the character before the current
276          * one.
277          */
278         vp->m_stop.cno = 0;
279         if (ISMOTION(vp))
280                 --vp->m_start.cno;
281         vp->m_final = vp->m_stop;
282         return (0);
283 }