257 lines
4.2 KiB
C
257 lines
4.2 KiB
C
|
/* 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;
|
||
|
}
|