source: trunk/third/nvi/vi/v_left.c @ 14302

Revision 14302, 6.4 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14301, which included commits to RCS files with non-trunk default branches.
Line 
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_left.c      10.7 (Berkeley) 3/6/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_left -- [count]^H, [count]h
29 *      Move left by columns.
30 *
31 * PUBLIC: int v_left __P((SCR *, VICMD *));
32 */
33int
34v_left(sp, vp)
35        SCR *sp;
36        VICMD *vp;
37{
38        recno_t cnt;
39
40        /*
41         * !!!
42         * The ^H and h commands always failed in the first column.
43         */
44        if (vp->m_start.cno == 0) {
45                v_sol(sp);
46                return (1);
47        }
48
49        /* Find the end of the range. */
50        cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
51        if (vp->m_start.cno > cnt)
52                vp->m_stop.cno = vp->m_start.cno - cnt;
53        else
54                vp->m_stop.cno = 0;
55
56        /*
57         * All commands move to the end of the range.  Motion commands
58         * adjust the starting point to the character before the current
59         * one.
60         */
61        if (ISMOTION(vp))
62                --vp->m_start.cno;
63        vp->m_final = vp->m_stop;
64        return (0);
65}
66
67/*
68 * v_cfirst -- [count]_
69 *      Move to the first non-blank character in a line.
70 *
71 * PUBLIC: int v_cfirst __P((SCR *, VICMD *));
72 */
73int
74v_cfirst(sp, vp)
75        SCR *sp;
76        VICMD *vp;
77{
78        recno_t cnt, lno;
79
80        /*
81         * !!!
82         * If the _ is a motion component, it makes the command a line motion
83         * e.g. "d_" deletes the line.  It also means that the cursor doesn't
84         * move.
85         *
86         * The _ command never failed in the first column.
87         */
88        if (ISMOTION(vp))
89                F_SET(vp, VM_LMODE);
90        /*
91         * !!!
92         * Historically a specified count makes _ move down count - 1
93         * rows, so, "3_" is the same as "2j_".
94         */
95        cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
96        if (cnt != 1) {
97                --vp->count;
98                return (v_down(sp, vp));
99        }
100
101        /*
102         * Move to the first non-blank.
103         *
104         * Can't just use RCM_SET_FNB, in case _ is used as the motion
105         * component of another command.
106         */
107        vp->m_stop.cno = 0;
108        if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
109                return (1);
110
111        /*
112         * !!!
113         * The _ command has to fail if the file is empty and we're doing
114         * a delete.  If deleting line 1, and 0 is the first nonblank,
115         * make the check.
116         */
117        if (vp->m_stop.lno == 1 &&
118            vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) {
119                if (db_last(sp, &lno))
120                        return (1);
121                if (lno == 0) {
122                        v_sol(sp);
123                        return (1);
124                }
125        }
126
127        /*
128         * Delete and non-motion commands move to the end of the range,
129         * yank stays at the start.  Ignore others.
130         */
131        vp->m_final =
132            ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop;
133        return (0);
134}
135
136/*
137 * v_first -- ^
138 *      Move to the first non-blank character in this line.
139 *
140 * PUBLIC: int v_first __P((SCR *, VICMD *));
141 */
142int
143v_first(sp, vp)
144        SCR *sp;
145        VICMD *vp;
146{
147        /*
148         * !!!
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.
152         */
153
154        /*
155         * Move to the first non-blank.
156         *
157         * Can't just use RCM_SET_FNB, in case ^ is used as the motion
158         * component of another command.
159         */
160        vp->m_stop.cno = 0;
161        if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
162                return (1);
163
164        /*
165         * !!!
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.
169         */
170        if (ISMOTION(vp) && vp->m_start.cno == vp->m_stop.cno) {
171                v_sol(sp);
172                return (1);
173        }
174
175        /*
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.
179         *
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.
183         */
184        if (vp->m_start.cno < vp->m_stop.cno)
185                if (ISMOTION(vp)) {
186                        --vp->m_stop.cno;
187                        vp->m_final = vp->m_start;
188                } else
189                        vp->m_final = vp->m_stop;
190        else {
191                if (ISMOTION(vp))
192                        --vp->m_start.cno;
193                vp->m_final = vp->m_stop;
194        }
195        return (0);
196}
197
198/*
199 * v_ncol -- [count]|
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.
203 *
204 * PUBLIC: int v_ncol __P((SCR *, VICMD *));
205 */
206int
207v_ncol(sp, vp)
208        SCR *sp;
209        VICMD *vp;
210{
211        if (F_ISSET(vp, VC_C1SET) && vp->count > 1) {
212                --vp->count;
213                vp->m_stop.cno =
214                    vs_colpos(sp, vp->m_start.lno, (size_t)vp->count);
215                /*
216                 * !!!
217                 * The | command succeeded if used as a command and the cursor
218                 * didn't move, but failed if used as a motion component in the
219                 * same situation.
220                 */
221                if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) {
222                        v_nomove(sp);
223                        return (1);
224                }
225        } else {
226                /*
227                 * !!!
228                 * The | command succeeded if used as a command in column 0
229                 * without a count, but failed if used as a motion component
230                 * in the same situation.
231                 */
232                if (ISMOTION(vp) && vp->m_start.cno == 0) {
233                        v_sol(sp);
234                        return (1);
235                }
236                vp->m_stop.cno = 0;
237        }
238
239        /*
240         * If moving right, non-motion commands move to the end of the range.
241         * Delete and yank stay at the start.  Motion commands adjust the
242         * ending point to the character before the current ending charcter.
243         *
244         * If moving left, all commands move to the end of the range.  Motion
245         * commands adjust the starting point to the character before the
246         * current starting character.
247         */
248        if (vp->m_start.cno < vp->m_stop.cno)
249                if (ISMOTION(vp)) {
250                        --vp->m_stop.cno;
251                        vp->m_final = vp->m_start;
252                } else
253                        vp->m_final = vp->m_stop;
254        else {
255                if (ISMOTION(vp))
256                        --vp->m_start.cno;
257                vp->m_final = vp->m_stop;
258        }
259        return (0);
260}
261
262/*
263 * v_zero -- 0
264 *      Move to the first column on this line.
265 *
266 * PUBLIC: int v_zero __P((SCR *, VICMD *));
267 */
268int
269v_zero(sp, vp)
270        SCR *sp;
271        VICMD *vp;
272{
273        /*
274         * !!!
275         * The 0 command succeeded if used as a command in the first column
276         * but failed if used as a motion component in the same situation.
277         */
278        if (ISMOTION(vp) && vp->m_start.cno == 0) {
279                v_sol(sp);
280                return (1);
281        }
282
283        /*
284         * All commands move to the end of the range.  Motion commands
285         * adjust the starting point to the character before the current
286         * one.
287         */
288        vp->m_stop.cno = 0;
289        if (ISMOTION(vp))
290                --vp->m_start.cno;
291        vp->m_final = vp->m_stop;
292        return (0);
293}
Note: See TracBrowser for help on using the repository browser.