/* move5.c */ /* Author: * Steve Kirkendall * 14407 SW Teal Blvd. #C * Beaverton, OR 97005 * kirkenda@cs.pdx.edu */ /* This file contains the word-oriented movement functions */ #include "config.h" #include "ctype.h" #include "vi.h" MARK m_fword(m, cnt, cmd, prevkey) MARK m; /* movement is relative to this mark */ long cnt; /* a numeric argument */ int cmd; /* either 'w' or 'W' */ int prevkey;/* previous command... if 'c' then exclude whitespace */ { REG long l; REG char *text; REG int i; DEFAULT(1); l = markline(m); pfetch(l); text = ptext + markidx(m); #ifndef CRUNCH /* As a special case, "cw" or "cW" on whitespace without a count * treats the single whitespace character under the cursor as a word. */ if (cnt == 1L && prevkey == 'c' && isspace(*text)) { return m + 1L; } #endif while (cnt-- > 0) /* yes, ASSIGNMENT! */ { i = *text++; if (cmd == 'W') { /* include any non-whitespace */ while (i && !isspace(i)) { i = *text++; } } else if (isalnum(i) || i == '_') { /* include an alphanumeric word */ while (i && isalnum(i)) { i = *text++; } } else { /* include contiguous punctuation */ while (i && !isalnum(i) && !isspace(i)) { i = *text++; } } /* if not part of "cw" or "cW" command... */ if (prevkey != 'c' || cnt > 0) { /* include trailing whitespace */ while (!i || isspace(i)) { /* did we hit the end of this line? */ if (!i) { /* "dw" shouldn't delete newline after word */ if (prevkey && cnt == 0) { break; } /* move to next line, if there is one */ l++; if (l > nlines) { return MARK_UNSET; } pfetch(l); text = ptext; } i = *text++; } } text--; } /* if argument to operator, then back off 1 char since "w" and "W" * include the last char in the affected text. */ if (prevkey) { text--; } /* construct a MARK for this place */ m = buildmark(text); return m; } MARK m_bword(m, cnt, cmd) MARK m; /* movement is relative to this mark */ long cnt; /* a numeric argument */ int cmd; /* either 'b' or 'B' */ { REG long l; REG char *text; DEFAULT(1); l = markline(m); pfetch(l); text = ptext + markidx(m); while (cnt-- > 0) /* yes, ASSIGNMENT! */ { text--; /* include preceding whitespace */ while (text < ptext || isspace(*text)) { /* did we hit the end of this line? */ if (text < ptext) { /* move to preceding line, if there is one */ l--; if (l <= 0) { return MARK_UNSET; } pfetch(l); text = ptext + plen - 1; } else { text--; } } if (cmd == 'B') { /* include any non-whitespace */ while (text >= ptext && !isspace(*text)) { text--; } } else if (isalnum(*text) || *text == '_') { /* include an alphanumeric word */ while (text >= ptext && isalnum(*text)) { text--; } } else { /* include contiguous punctuation */ while (text >= ptext && !isalnum(*text) && !isspace(*text)) { text--; } } text++; } /* construct a MARK for this place */ m = buildmark(text); return m; } MARK m_eword(m, cnt, cmd) MARK m; /* movement is relative to this mark */ long cnt; /* a numeric argument */ int cmd; /* either 'e' or 'E' */ { REG long l; REG char *text; REG int i; DEFAULT(1); l = markline(m); pfetch(l); text = ptext + markidx(m); while (cnt-- > 0) /* yes, ASSIGNMENT! */ { if (*text) text++; i = *text++; /* include preceding whitespace */ while (!i || isspace(i)) { /* did we hit the end of this line? */ if (!i) { /* move to next line, if there is one */ l++; if (l > nlines) { return MARK_UNSET; } pfetch(l); text = ptext; } i = *text++; } if (cmd == 'E') { /* include any non-whitespace */ while (i && !isspace(i)) { i = *text++; } } else if (isalnum(i) || i == '_') { /* include an alphanumeric word */ while (i && isalnum(i)) { i = *text++; } } else { /* include contiguous punctuation */ while (i && !isalnum(i) && !isspace(i)) { i = *text++; } } text -= 2; } /* construct a MARK for this place */ m = buildmark(text); return m; }