961 lines
16 KiB
C
961 lines
16 KiB
C
/* move1.c */
|
|
|
|
/* Author:
|
|
* Steve Kirkendall
|
|
* 16820 SW Tallac Way
|
|
* Beaverton, OR 97006
|
|
* kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
|
|
*/
|
|
|
|
|
|
/* This file contains most movement functions */
|
|
|
|
#include <ctype.h>
|
|
#include "vi.h"
|
|
|
|
#ifndef isascii
|
|
# define isascii(c) !((c) & ~0x7f)
|
|
#endif
|
|
|
|
MARK moveup(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
DEFAULT(1);
|
|
|
|
/* if at top already, don't move */
|
|
if (markline(m) - cnt < 1)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
/* else move up one line */
|
|
m -= MARK_AT_LINE(cnt);
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK movedown(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
DEFAULT(1);
|
|
|
|
/* if at bottom already, don't move */
|
|
if (markline(m) + cnt > nlines)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
/* else move down one line */
|
|
m += MARK_AT_LINE(cnt);
|
|
|
|
/* adjust column number */
|
|
if (markidx(m) >= plen)
|
|
{
|
|
m = (m & ~(BLKSIZE - 1));
|
|
if (plen > 0)
|
|
{
|
|
m += plen - 1;
|
|
}
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK moveright(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
int idx; /* index of the new cursor position */
|
|
|
|
DEFAULT(1);
|
|
|
|
/* move to right, if that's OK */
|
|
pfetch(markline(m));
|
|
idx = markidx(m) + cnt;
|
|
if (idx < plen)
|
|
{
|
|
m += cnt;
|
|
}
|
|
else
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK moveleft(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
DEFAULT(1);
|
|
|
|
/* move to the left, if that's OK */
|
|
if (markidx(m) >= cnt)
|
|
{
|
|
m -= cnt;
|
|
}
|
|
else
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK movetoline(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric line number */
|
|
{
|
|
/* if no number specified, assume last line */
|
|
DEFAULT(nlines);
|
|
|
|
/* if invalid line number, don't move */
|
|
if (cnt > nlines)
|
|
{
|
|
msg("Line numbers range from 1 to %ld", nlines);
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
/* move to first character of the selected line */
|
|
m = MARK_AT_LINE(cnt);
|
|
return m;
|
|
}
|
|
|
|
MARK movetocol(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
char *text; /* text of the line */
|
|
int col; /* column number */
|
|
int idx; /* index into the line */
|
|
|
|
DEFAULT(1);
|
|
|
|
/* internally, columns are numbered 0..COLS-1, not 1..COLS */
|
|
cnt--;
|
|
|
|
/* if 0, that's easy */
|
|
if (cnt == 0)
|
|
{
|
|
m &= ~(BLKSIZE - 1);
|
|
return m;
|
|
}
|
|
|
|
/* find that column within the line */
|
|
pfetch(markline(m));
|
|
text = ptext;
|
|
for (col = idx = 0; col < cnt && *text; text++, idx++)
|
|
{
|
|
if (*text == '\t')
|
|
{
|
|
col += *o_tabstop;
|
|
col -= col % *o_tabstop;
|
|
}
|
|
else if (*text >= '\0' && *text < ' ' || *text == '\177')
|
|
{
|
|
col += 2;
|
|
}
|
|
#ifndef SET_NOCHARATTR
|
|
else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
|
|
{
|
|
text += 2; /* plus one more as part of for loop */
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
col++;
|
|
}
|
|
}
|
|
if (!*text)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
else
|
|
{
|
|
m = (m & ~(BLKSIZE - 1)) + idx;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
MARK movefront(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument (ignored) */
|
|
{
|
|
char *scan;
|
|
|
|
/* move to the first non-whitespace character */
|
|
pfetch(markline(m));
|
|
scan = ptext;
|
|
m &= ~(BLKSIZE - 1);
|
|
while (*scan == ' ' || *scan == '\t')
|
|
{
|
|
scan++;
|
|
m++;
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK moverear(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument (ignored) */
|
|
{
|
|
/* Try to move *EXTREMELY* far to the right. It is fervently hoped
|
|
* that other code will convert this to a more reasonable MARK before
|
|
* anything tries to actually use it. (See adjmove() in vi.c)
|
|
*/
|
|
return m | (BLKSIZE - 1);
|
|
}
|
|
|
|
MARK movefword(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register long l;
|
|
register char *text;
|
|
register int i;
|
|
|
|
DEFAULT(1);
|
|
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
|
{
|
|
i = *text++;
|
|
/* if we hit the end of the line, continue with next line */
|
|
if (!isascii(i) || isalnum(i) || i == '_')
|
|
{
|
|
/* include an alphanumeric word */
|
|
while (i && (!isascii(i) || isalnum(i) || i == '_'))
|
|
{
|
|
i = *text++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* include contiguous punctuation */
|
|
while (i && isascii(i) && !isalnum(i) && !isspace(i))
|
|
{
|
|
i = *text++;
|
|
}
|
|
}
|
|
|
|
/* include trailing whitespace */
|
|
while (!i || isascii(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++;
|
|
}
|
|
text--;
|
|
}
|
|
|
|
/* construct a MARK for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
|
|
MARK movebword(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register long l;
|
|
register 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 || isascii(*text) && 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 (!isascii(*text) || isalnum(*text) || *text == '_')
|
|
{
|
|
/* include an alphanumeric word */
|
|
while (text >= ptext && (!isascii(*text) || isalnum(*text) || *text == '_'))
|
|
{
|
|
text--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* include contiguous punctuation */
|
|
while (text >= ptext && isascii(*text) && !isalnum(*text) && !isspace(*text))
|
|
{
|
|
text--;
|
|
}
|
|
}
|
|
text++;
|
|
}
|
|
|
|
/* construct a MARK for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
MARK moveeword(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register long l;
|
|
register char *text;
|
|
register int i;
|
|
|
|
DEFAULT(1);
|
|
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
|
{
|
|
text++;
|
|
i = *text++;
|
|
|
|
/* include preceding whitespace */
|
|
while (!i || isascii(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 (!isascii(i) || isalnum(i) || i == '_')
|
|
{
|
|
/* include an alphanumeric word */
|
|
while (i && (!isascii(i) || isalnum(i) || i == '_'))
|
|
{
|
|
i = *text++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* include contiguous punctuation */
|
|
while (i && isascii(i) && !isalnum(i) && !isspace(i))
|
|
{
|
|
i = *text++;
|
|
}
|
|
}
|
|
text -= 2;
|
|
}
|
|
|
|
/* construct a MARK for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
MARK movefWord(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register long l;
|
|
register char *text;
|
|
register int i;
|
|
|
|
DEFAULT(1);
|
|
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
|
{
|
|
i = *text++;
|
|
/* if we hit the end of the line, continue with next line */
|
|
/* include contiguous non-space characters */
|
|
while (i && !isspace(i))
|
|
{
|
|
i = *text++;
|
|
}
|
|
|
|
/* include trailing whitespace */
|
|
while (!i || isascii(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++;
|
|
}
|
|
text--;
|
|
}
|
|
|
|
/* construct a MARK for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
|
|
MARK movebWord(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register long l;
|
|
register char *text;
|
|
|
|
DEFAULT(1);
|
|
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
|
{
|
|
text--;
|
|
|
|
/* include trailing whitespace */
|
|
while (text < ptext || isascii(*text) && isspace(*text))
|
|
{
|
|
/* did we hit the end of this line? */
|
|
if (text < ptext)
|
|
{
|
|
/* move to next line, if there is one */
|
|
l--;
|
|
if (l <= 0)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
pfetch(l);
|
|
text = ptext + plen - 1;
|
|
}
|
|
else
|
|
{
|
|
text--;
|
|
}
|
|
}
|
|
|
|
/* include contiguous non-whitespace */
|
|
while (text >= ptext && (!isascii(*text) || !isspace(*text)))
|
|
{
|
|
text--;
|
|
}
|
|
text++;
|
|
}
|
|
|
|
/* construct a MARK for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
MARK moveeWord(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register long l;
|
|
register char *text;
|
|
register int i;
|
|
|
|
DEFAULT(1);
|
|
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
while (cnt-- > 0) /* yes, ASSIGNMENT! */
|
|
{
|
|
text++;
|
|
i = *text++;
|
|
|
|
/* include preceding whitespace */
|
|
while (!i || isascii(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++;
|
|
}
|
|
|
|
/* include contiguous non-whitespace */
|
|
while (i && (!isascii(i) || !isspace(i)))
|
|
{
|
|
i = *text++;
|
|
}
|
|
text -= 2;
|
|
}
|
|
|
|
/* construct a MARK for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
MARK movefsentence(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register char *text;
|
|
register long l;
|
|
|
|
DEFAULT(1);
|
|
|
|
/* get the current line */
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
|
|
/* for each requested sentence... */
|
|
while (cnt-- > 0)
|
|
{
|
|
/* search forward for one of [.?!] followed by spaces or EOL */
|
|
do
|
|
{
|
|
/* wrap at end of line */
|
|
if (!text[0])
|
|
{
|
|
if (l >= nlines)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
l++;
|
|
pfetch(l);
|
|
text = ptext;
|
|
}
|
|
else
|
|
{
|
|
text++;
|
|
}
|
|
} while (text[0] != '.' && text[0] != '?' && text[0] != '!'
|
|
|| text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
|
|
}
|
|
|
|
/* construct a mark for this location */
|
|
m = buildmark(text);
|
|
|
|
/* move forward to the first word of the next sentence */
|
|
m = movefword(m, 1L);
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK movebsentence(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
register char *text; /* used to scan thru text */
|
|
register long l; /* current line number */
|
|
int flag; /* have we passed at least one word? */
|
|
|
|
DEFAULT(1);
|
|
|
|
/* get the current line */
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
|
|
/* for each requested sentence... */
|
|
flag = TRUE;
|
|
while (cnt-- > 0)
|
|
{
|
|
/* search backward for one of [.?!] followed by spaces or EOL */
|
|
do
|
|
{
|
|
/* wrap at beginning of line */
|
|
if (text == ptext)
|
|
{
|
|
do
|
|
{
|
|
if (l <= 1)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
l--;
|
|
pfetch(l);
|
|
} while (!*ptext);
|
|
text = ptext + plen - 1;
|
|
}
|
|
else
|
|
{
|
|
text--;
|
|
}
|
|
|
|
/* are we moving past a "word"? */
|
|
if (text[0] >= '0')
|
|
{
|
|
flag = FALSE;
|
|
}
|
|
} while (flag || text[0] != '.' && text[0] != '?' && text[0] != '!'
|
|
|| text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
|
|
}
|
|
|
|
/* construct a mark for this location */
|
|
m = buildmark(text);
|
|
|
|
/* move to the front of the following sentence */
|
|
m = movefword(m, 1L);
|
|
|
|
return m;
|
|
}
|
|
|
|
MARK movefparagraph(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
char *text;
|
|
char *pscn; /* used to scan thru value of "paragraphs" option */
|
|
long l;
|
|
|
|
DEFAULT(1);
|
|
|
|
for (l = markline(m); cnt > 0 && l++ < nlines; )
|
|
{
|
|
text = fetchline(l);
|
|
if (!*text)
|
|
{
|
|
cnt--;
|
|
}
|
|
else if (*text == '.')
|
|
{
|
|
for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
|
|
{
|
|
if (pscn[0] == text[1] && pscn[1] == text[2])
|
|
{
|
|
cnt--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (l <= nlines)
|
|
{
|
|
m = MARK_AT_LINE(l);
|
|
}
|
|
else
|
|
{
|
|
m = MARK_LAST;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
MARK movebparagraph(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
char *text;
|
|
char *pscn; /* used to scan thru value of "paragraph" option */
|
|
long l;
|
|
|
|
DEFAULT(1);
|
|
|
|
for (l = markline(m); cnt > 0 && l-- > 1; )
|
|
{
|
|
text = fetchline(l);
|
|
if (!*text)
|
|
{
|
|
cnt--;
|
|
}
|
|
else if (*text == '.')
|
|
{
|
|
for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
|
|
{
|
|
if (pscn[0] == text[1] && pscn[1] == text[2])
|
|
{
|
|
cnt--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (l >= 1)
|
|
{
|
|
m = MARK_AT_LINE(l);
|
|
}
|
|
else
|
|
{
|
|
m = MARK_FIRST;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
MARK movefsection(m, cnt, key)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* (ignored) */
|
|
int key; /* second key stroke - must be ']' */
|
|
{
|
|
char *text;
|
|
char *sscn; /* used to scan thru value of "sections" option */
|
|
long l;
|
|
|
|
/* make sure second key was ']' */
|
|
if (key != ']')
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
for (l = markline(m); l++ < nlines; )
|
|
{
|
|
text = fetchline(l);
|
|
if (*text == '{')
|
|
{
|
|
break;
|
|
}
|
|
if (*text == '.')
|
|
{
|
|
for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
|
|
{
|
|
if (sscn[0] == text[1] && sscn[1] == text[2])
|
|
{
|
|
goto BreakBreak;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
BreakBreak:
|
|
if (l <= nlines)
|
|
{
|
|
m = MARK_AT_LINE(l);
|
|
}
|
|
else
|
|
{
|
|
m = MARK_LAST;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
MARK movebsection(m, cnt, key)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* (ignored) */
|
|
int key; /* second key stroke - must be '[' */
|
|
{
|
|
char *text;
|
|
char *sscn; /* used to scan thru value of "sections" option */
|
|
long l;
|
|
|
|
/* make sure second key was '[' */
|
|
if (key != '[')
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
for (l = markline(m); l-- > 1; )
|
|
{
|
|
text = fetchline(l);
|
|
if (*text == '{')
|
|
{
|
|
break;
|
|
}
|
|
if (*text == '.')
|
|
{
|
|
for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
|
|
{
|
|
if (sscn[0] == text[1] && sscn[1] == text[2])
|
|
{
|
|
goto BreakBreak;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
BreakBreak:
|
|
if (l >= 1)
|
|
{
|
|
m = MARK_AT_LINE(l);
|
|
}
|
|
else
|
|
{
|
|
m = MARK_FIRST;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
|
|
MARK movematch(m, cnt)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* a numeric argument */
|
|
{
|
|
long l;
|
|
register char *text;
|
|
register char match;
|
|
register char nest;
|
|
register int count;
|
|
|
|
/* get the current line */
|
|
l = markline(m);
|
|
pfetch(l);
|
|
text = ptext + markidx(m);
|
|
|
|
/* search forward within line for one of "[](){}" */
|
|
for (match = '\0'; !match && *text; text++)
|
|
{
|
|
/* tricky way to recognize 'em in ASCII */
|
|
nest = *text;
|
|
if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
|
|
{
|
|
match = nest ^ ('[' ^ ']');
|
|
}
|
|
else if ((nest & 0xfe) == '(')
|
|
{
|
|
match = nest ^ ('(' ^ ')');
|
|
}
|
|
else
|
|
{
|
|
match = 0;
|
|
}
|
|
}
|
|
if (!match)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
text--;
|
|
|
|
/* search forward or backward for match */
|
|
if (match == '(' || match == '[' || match == '{')
|
|
{
|
|
/* search backward */
|
|
for (count = 1; count > 0; )
|
|
{
|
|
/* wrap at beginning of line */
|
|
if (text == ptext)
|
|
{
|
|
do
|
|
{
|
|
if (l <= 1L)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
l--;
|
|
pfetch(l);
|
|
} while (!*ptext);
|
|
text = ptext + plen - 1;
|
|
}
|
|
else
|
|
{
|
|
text--;
|
|
}
|
|
|
|
/* check the char */
|
|
if (*text == match)
|
|
count--;
|
|
else if (*text == nest)
|
|
count++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* search forward */
|
|
for (count = 1; count > 0; )
|
|
{
|
|
/* wrap at end of line */
|
|
if (!*text)
|
|
{
|
|
if (l >= nlines)
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
l++;
|
|
pfetch(l);
|
|
text = ptext;
|
|
}
|
|
else
|
|
{
|
|
text++;
|
|
}
|
|
|
|
/* check the char */
|
|
if (*text == match)
|
|
count--;
|
|
else if (*text == nest)
|
|
count++;
|
|
}
|
|
}
|
|
|
|
/* construct a mark for this place */
|
|
m = buildmark(text);
|
|
return m;
|
|
}
|
|
|
|
MARK movetomark(m, cnt, key)
|
|
MARK m; /* movement is relative to this mark */
|
|
long cnt; /* (ignored) */
|
|
int key; /* keystroke - the mark to move to */
|
|
{
|
|
/* mark '' is a special case */
|
|
if (key == '\'' || key == '`')
|
|
{
|
|
if (mark[26] == MARK_UNSET)
|
|
{
|
|
return MARK_FIRST;
|
|
}
|
|
else
|
|
{
|
|
return mark[26];
|
|
}
|
|
}
|
|
|
|
/* if not a valid mark number, don't move */
|
|
if (key < 'a' || key > 'z')
|
|
{
|
|
return MARK_UNSET;
|
|
}
|
|
|
|
/* return the selected mark -- may be MARK_UNSET */
|
|
if (!mark[key - 'a'])
|
|
{
|
|
msg("mark '%c is unset", key);
|
|
}
|
|
return mark[key - 'a'];
|
|
}
|
|
|