1 /* $NetBSD: v_left.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
13 #include <sys/cdefs.h>
16 static const char sccsid
[] = "Id: v_left.c,v 10.9 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32 ";
19 __RCSID("$NetBSD: v_left.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
22 #include <sys/types.h>
23 #include <sys/queue.h>
26 #include <bitstring.h>
30 #include "../common/common.h"
34 * v_left -- [count]^H, [count]h
35 * Move left by columns.
37 * PUBLIC: int v_left __P((SCR *, VICMD *));
40 v_left(SCR
*sp
, VICMD
*vp
)
46 * The ^H and h commands always failed in the first column.
48 if (vp
->m_start
.cno
== 0) {
53 /* Find the end of the range. */
54 cnt
= F_ISSET(vp
, VC_C1SET
) ? vp
->count
: 1;
55 if (vp
->m_start
.cno
> cnt
)
56 vp
->m_stop
.cno
= vp
->m_start
.cno
- cnt
;
61 * All commands move to the end of the range. Motion commands
62 * adjust the starting point to the character before the current
67 vp
->m_final
= vp
->m_stop
;
72 * v_cfirst -- [count]_
73 * Move to the first non-blank character in a line.
75 * PUBLIC: int v_cfirst __P((SCR *, VICMD *));
78 v_cfirst(SCR
*sp
, VICMD
*vp
)
84 * If the _ is a motion component, it makes the command a line motion
85 * e.g. "d_" deletes the line. It also means that the cursor doesn't
88 * The _ command never failed in the first column.
94 * Historically a specified count makes _ move down count - 1
95 * rows, so, "3_" is the same as "2j_".
97 cnt
= F_ISSET(vp
, VC_C1SET
) ? vp
->count
: 1;
100 return (v_down(sp
, vp
));
104 * Move to the first non-blank.
106 * Can't just use RCM_SET_FNB, in case _ is used as the motion
107 * component of another command.
110 if (nonblank(sp
, vp
->m_stop
.lno
, &vp
->m_stop
.cno
))
115 * The _ command has to fail if the file is empty and we're doing
116 * a delete. If deleting line 1, and 0 is the first nonblank,
119 if (vp
->m_stop
.lno
== 1 &&
120 vp
->m_stop
.cno
== 0 && ISCMD(vp
->rkp
, 'd')) {
121 if (db_last(sp
, &lno
))
130 * Delete and non-motion commands move to the end of the range,
131 * yank stays at the start. Ignore others.
134 ISMOTION(vp
) && ISCMD(vp
->rkp
, 'y') ? vp
->m_start
: vp
->m_stop
;
140 * Move to the first non-blank character in this line.
142 * PUBLIC: int v_first __P((SCR *, VICMD *));
145 v_first(SCR
*sp
, VICMD
*vp
)
149 * Yielding to none in our quest for compatibility with every
150 * historical blemish of vi, no matter how strange it might be,
151 * we permit the user to enter a count and then ignore it.
155 * Move to the first non-blank.
157 * Can't just use RCM_SET_FNB, in case ^ is used as the motion
158 * component of another command.
161 if (nonblank(sp
, vp
->m_stop
.lno
, &vp
->m_stop
.cno
))
166 * The ^ command succeeded if used as a command when the cursor was
167 * on the first non-blank in the line, but failed if used as a motion
168 * component in the same situation.
170 if (ISMOTION(vp
) && vp
->m_start
.cno
== vp
->m_stop
.cno
) {
176 * If moving right, non-motion commands move to the end of the range.
177 * Delete and yank stay at the start. Motion commands adjust the
178 * ending point to the character before the current ending charcter.
180 * If moving left, all commands move to the end of the range. Motion
181 * commands adjust the starting point to the character before the
182 * current starting character.
184 if (vp
->m_start
.cno
< vp
->m_stop
.cno
)
187 vp
->m_final
= vp
->m_start
;
189 vp
->m_final
= vp
->m_stop
;
193 vp
->m_final
= vp
->m_stop
;
200 * Move to column count or the first column on this line. If the
201 * requested column is past EOL, move to EOL. The nasty part is
202 * that we have to know character column widths to make this work.
204 * PUBLIC: int v_ncol __P((SCR *, VICMD *));
207 v_ncol(SCR
*sp
, VICMD
*vp
)
209 if (F_ISSET(vp
, VC_C1SET
) && vp
->count
> 1) {
212 vs_colpos(sp
, vp
->m_start
.lno
, (size_t)vp
->count
);
215 * The | command succeeded if used as a command and the cursor
216 * didn't move, but failed if used as a motion component in the
219 if (ISMOTION(vp
) && vp
->m_stop
.cno
== vp
->m_start
.cno
) {
226 * The | command succeeded if used as a command in column 0
227 * without a count, but failed if used as a motion component
228 * in the same situation.
230 if (ISMOTION(vp
) && vp
->m_start
.cno
== 0) {
238 * If moving right, non-motion commands move to the end of the range.
239 * Delete and yank stay at the start. Motion commands adjust the
240 * ending point to the character before the current ending charcter.
242 * If moving left, all commands move to the end of the range. Motion
243 * commands adjust the starting point to the character before the
244 * current starting character.
246 if (vp
->m_start
.cno
< vp
->m_stop
.cno
)
249 vp
->m_final
= vp
->m_start
;
251 vp
->m_final
= vp
->m_stop
;
255 vp
->m_final
= vp
->m_stop
;
262 * Move to the first column on this line.
264 * PUBLIC: int v_zero __P((SCR *, VICMD *));
267 v_zero(SCR
*sp
, VICMD
*vp
)
271 * The 0 command succeeded if used as a command in the first column
272 * but failed if used as a motion component in the same situation.
274 if (ISMOTION(vp
) && vp
->m_start
.cno
== 0) {
280 * All commands move to the end of the range. Motion commands
281 * adjust the starting point to the character before the current
287 vp
->m_final
= vp
->m_stop
;