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.
7 * See the LICENSE file for redistribution information.
12 #include <sys/types.h>
13 #include <sys/queue.h>
16 #include <bitstring.h>
21 #include "../common/common.h"
25 * There are two types of "words". Bigwords are easy -- groups of anything
26 * delimited by whitespace. Normal words are trickier. They are either a
27 * group of characters, numbers and underscores, or a group of anything but,
28 * delimited by whitespace. When for a word, if you're in whitespace, it's
29 * easy, just remove the whitespace and go to the beginning or end of the
30 * word. Otherwise, figure out if the next character is in a different group.
31 * If it is, go to the beginning or end of that group, otherwise, go to the
32 * beginning or end of the current group. The historic version of vi didn't
33 * get this right, so, for example, there were cases where "4e" was not the
34 * same as "eeee" -- in particular, single character words, and commands that
35 * began in whitespace were almost always handled incorrectly. To get it right
36 * you have to resolve the cursor after each search so that the look-ahead to
37 * figure out what type of "word" the cursor is in will be correct.
39 * Empty lines, and lines that consist of only white-space characters count
40 * as a single word, and the beginning and end of the file counts as an
41 * infinite number of words.
43 * Movements associated with commands are different than movement commands.
44 * For example, in "abc def", with the cursor on the 'a', "cw" is from
45 * 'a' to 'c', while "w" is from 'a' to 'd'. In general, trailing white
46 * space is discarded from the change movement. Another example is that,
47 * in the same string, a "cw" on any white space character replaces that
48 * single character, and nothing else. Ain't nothin' in here that's easy.
50 * One historic note -- in the original vi, the 'w', 'W' and 'B' commands
51 * would treat groups of empty lines as individual words, i.e. the command
52 * would move the cursor to each new empty line. The 'e' and 'E' commands
53 * would treat groups of empty lines as a single word, i.e. the first use
54 * would move past the group of lines. The 'b' command would just beep at
55 * you, or, if you did it from the start of the line as part of a motion
56 * command, go absolutely nuts. If the lines contained only white-space
57 * characters, the 'w' and 'W' commands would just beep at you, and the 'B',
58 * 'b', 'E' and 'e' commands would treat the group as a single word, and
59 * the 'B' and 'b' commands will treat the lines as individual words. This
60 * implementation treats all of these cases as a single white-space word.
63 enum which {BIGWORD, LITTLEWORD};
65 static int bword(SCR *, VICMD *, enum which);
66 static int eword(SCR *, VICMD *, enum which);
67 static int fword(SCR *, VICMD *, enum which);
71 * Move forward a bigword at a time.
73 * PUBLIC: int v_wordW(SCR *, VICMD *);
76 v_wordW(SCR *sp, VICMD *vp)
78 return (fword(sp, vp, BIGWORD));
83 * Move forward a word at a time.
85 * PUBLIC: int v_wordw(SCR *, VICMD *);
88 v_wordw(SCR *sp, VICMD *vp)
90 return (fword(sp, vp, LITTLEWORD));
95 * Move forward by words.
98 fword(SCR *sp, VICMD *vp, enum which type)
100 enum { INWORD, NOTWORD } state;
104 cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
105 cs.cs_lno = vp->m_start.lno;
106 cs.cs_cno = vp->m_start.cno;
107 if (cs_init(sp, &cs))
112 * If the count is 1, and it's a change command, we're done.
113 * Else, move to the first non-white-space character, which
114 * counts as a single word move. If it's a motion command,
115 * don't move off the end of the line.
117 if (cs.cs_flags == CS_EMP || (cs.cs_flags == 0 && ISBLANK(cs.cs_ch))) {
118 if (ISMOTION(vp) && cs.cs_flags != CS_EMP && cnt == 1) {
119 if (ISCMD(vp->rkp, 'c'))
121 if (ISCMD(vp->rkp, 'd') || ISCMD(vp->rkp, 'y')) {
122 if (cs_fspace(sp, &cs))
127 if (cs_fblank(sp, &cs))
133 * Cyclically move to the next word -- this involves skipping
134 * over word characters and then any trailing non-word characters.
135 * Note, for the 'w' command, the definition of a word keeps
141 if (cs_next(sp, &cs))
143 if (cs.cs_flags == CS_EOF)
145 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
149 * If a motion command and we're at the end of the
150 * last word, we're done. Delete and yank eat any
151 * trailing blanks, but we don't move off the end
152 * of the line regardless.
154 if (cnt == 0 && ISMOTION(vp)) {
155 if ((ISCMD(vp->rkp, 'd') ||
156 ISCMD(vp->rkp, 'y')) &&
162 /* Eat whitespace characters. */
163 if (cs_fblank(sp, &cs))
165 if (cs.cs_flags == CS_EOF)
170 state = cs.cs_flags == 0 &&
171 inword(cs.cs_ch) ? INWORD : NOTWORD;
173 if (cs_next(sp, &cs))
175 if (cs.cs_flags == CS_EOF)
177 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
179 if (state == INWORD) {
180 if (!inword(cs.cs_ch))
183 if (inword(cs.cs_ch))
186 /* See comment above. */
187 if (cnt == 0 && ISMOTION(vp)) {
188 if ((ISCMD(vp->rkp, 'd') ||
189 ISCMD(vp->rkp, 'y')) &&
195 /* Eat whitespace characters. */
196 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
197 if (cs_fblank(sp, &cs))
199 if (cs.cs_flags == CS_EOF)
204 * If we didn't move, we must be at EOF.
207 * That's okay for motion commands, however.
209 ret: if (!ISMOTION(vp) &&
210 cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
211 v_eof(sp, &vp->m_start);
215 /* Adjust the end of the range for motion commands. */
216 vp->m_stop.lno = cs.cs_lno;
217 vp->m_stop.cno = cs.cs_cno;
218 if (ISMOTION(vp) && cs.cs_flags == 0)
222 * Non-motion commands move to the end of the range. Delete
223 * and yank stay at the start, ignore others.
225 vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
230 * v_wordE -- [count]E
231 * Move forward to the end of the bigword.
233 * PUBLIC: int v_wordE(SCR *, VICMD *);
236 v_wordE(SCR *sp, VICMD *vp)
238 return (eword(sp, vp, BIGWORD));
242 * v_worde -- [count]e
243 * Move forward to the end of the word.
245 * PUBLIC: int v_worde(SCR *, VICMD *);
248 v_worde(SCR *sp, VICMD *vp)
250 return (eword(sp, vp, LITTLEWORD));
255 * Move forward to the end of the word.
258 eword(SCR *sp, VICMD *vp, enum which type)
260 enum { INWORD, NOTWORD } state;
264 cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
265 cs.cs_lno = vp->m_start.lno;
266 cs.cs_cno = vp->m_start.cno;
267 if (cs_init(sp, &cs))
272 * If in whitespace, or the next character is whitespace, move past
273 * it. (This doesn't count as a word move.) Stay at the character
274 * past the current one, it sets word "state" for the 'e' command.
276 if (cs.cs_flags == 0 && !ISBLANK(cs.cs_ch)) {
277 if (cs_next(sp, &cs))
279 if (cs.cs_flags == 0 && !ISBLANK(cs.cs_ch))
282 if (cs_fblank(sp, &cs))
286 * Cyclically move to the next word -- this involves skipping
287 * over word characters and then any trailing non-word characters.
288 * Note, for the 'e' command, the definition of a word keeps
291 start: if (type == BIGWORD)
294 if (cs_next(sp, &cs))
296 if (cs.cs_flags == CS_EOF)
298 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
302 * When we reach the start of the word after the last
303 * word, we're done. If we changed state, back up one
304 * to the end of the previous word.
307 if (cs.cs_flags == 0 && cs_prev(sp, &cs))
312 /* Eat whitespace characters. */
313 if (cs_fblank(sp, &cs))
315 if (cs.cs_flags == CS_EOF)
320 state = cs.cs_flags == 0 &&
321 inword(cs.cs_ch) ? INWORD : NOTWORD;
323 if (cs_next(sp, &cs))
325 if (cs.cs_flags == CS_EOF)
327 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
329 if (state == INWORD) {
330 if (!inword(cs.cs_ch))
333 if (inword(cs.cs_ch))
336 /* See comment above. */
338 if (cs.cs_flags == 0 && cs_prev(sp, &cs))
343 /* Eat whitespace characters. */
344 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
345 if (cs_fblank(sp, &cs))
347 if (cs.cs_flags == CS_EOF)
352 * If we didn't move, we must be at EOF.
355 * That's okay for motion commands, however.
357 ret: if (!ISMOTION(vp) &&
358 cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
359 v_eof(sp, &vp->m_start);
363 /* Set the end of the range for motion commands. */
364 vp->m_stop.lno = cs.cs_lno;
365 vp->m_stop.cno = cs.cs_cno;
368 * Non-motion commands move to the end of the range.
369 * Delete and yank stay at the start, ignore others.
371 vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
376 * v_WordB -- [count]B
377 * Move backward a bigword at a time.
379 * PUBLIC: int v_wordB(SCR *, VICMD *);
382 v_wordB(SCR *sp, VICMD *vp)
384 return (bword(sp, vp, BIGWORD));
388 * v_wordb -- [count]b
389 * Move backward a word at a time.
391 * PUBLIC: int v_wordb(SCR *, VICMD *);
394 v_wordb(SCR *sp, VICMD *vp)
396 return (bword(sp, vp, LITTLEWORD));
401 * Move backward by words.
404 bword(SCR *sp, VICMD *vp, enum which type)
406 enum { INWORD, NOTWORD } state;
410 cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
411 cs.cs_lno = vp->m_start.lno;
412 cs.cs_cno = vp->m_start.cno;
413 if (cs_init(sp, &cs))
418 * If in whitespace, or the previous character is whitespace, move
419 * past it. (This doesn't count as a word move.) Stay at the
420 * character before the current one, it sets word "state" for the
423 if (cs.cs_flags == 0 && !ISBLANK(cs.cs_ch)) {
424 if (cs_prev(sp, &cs))
426 if (cs.cs_flags == 0 && !ISBLANK(cs.cs_ch))
429 if (cs_bblank(sp, &cs))
433 * Cyclically move to the beginning of the previous word -- this
434 * involves skipping over word characters and then any trailing
435 * non-word characters. Note, for the 'b' command, the definition
436 * of a word keeps switching.
438 start: if (type == BIGWORD)
441 if (cs_prev(sp, &cs))
443 if (cs.cs_flags == CS_SOF)
445 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
449 * When we reach the end of the word before the last
450 * word, we're done. If we changed state, move forward
451 * one to the end of the next word.
454 if (cs.cs_flags == 0 && cs_next(sp, &cs))
459 /* Eat whitespace characters. */
460 if (cs_bblank(sp, &cs))
462 if (cs.cs_flags == CS_SOF)
467 state = cs.cs_flags == 0 &&
468 inword(cs.cs_ch) ? INWORD : NOTWORD;
470 if (cs_prev(sp, &cs))
472 if (cs.cs_flags == CS_SOF)
474 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
476 if (state == INWORD) {
477 if (!inword(cs.cs_ch))
480 if (inword(cs.cs_ch))
483 /* See comment above. */
485 if (cs.cs_flags == 0 && cs_next(sp, &cs))
490 /* Eat whitespace characters. */
491 if (cs.cs_flags != 0 || ISBLANK(cs.cs_ch))
492 if (cs_bblank(sp, &cs))
494 if (cs.cs_flags == CS_SOF)
498 /* If we didn't move, we must be at SOF. */
499 ret: if (cs.cs_lno == vp->m_start.lno && cs.cs_cno == vp->m_start.cno) {
500 v_sof(sp, &vp->m_start);
504 /* Set the end of the range for motion commands. */
505 vp->m_stop.lno = cs.cs_lno;
506 vp->m_stop.cno = cs.cs_cno;
509 * All commands move to the end of the range. Motion commands
510 * adjust the starting point to the character before the current
514 * The historic vi didn't get this right -- the `yb' command yanked
515 * the right stuff and even updated the cursor value, but the cursor
516 * was not actually updated on the screen.
518 vp->m_final = vp->m_stop;