home *** CD-ROM | disk | FTP | other *** search
- /* move1.c */
-
- /* Author:
- * Steve Kirkendall
- * 14407 SW Teal Blvd. #C
- * Beaverton, OR 97005
- * kirkenda@cs.pdx.edu
- */
-
-
- /* This file contains most movement functions */
-
- #include "config.h"
- #include <ctype.h>
- #include "vi.h"
-
- #ifndef isascii
- # define isascii(c) !((c) & ~0x7f)
- #endif
-
- MARK m_updnto(m, cnt, cmd)
- MARK m; /* movement is relative to this mark */
- long cnt; /* a numeric argument */
- {
- DEFAULT(cmd == 'G' ? nlines : 1L);
-
- /* move up or down 'cnt' lines */
- switch (cmd)
- {
- case ('P'&0x1f):
- case '-':
- case 'k':
- m -= MARK_AT_LINE(cnt);
- break;
-
- case 'G':
- if (cnt < 1L || cnt > nlines)
- {
- msg("Only %ld lines", nlines);
- return MARK_UNSET;
- }
- m = MARK_AT_LINE(cnt);
- break;
-
- default:
- m += MARK_AT_LINE(cnt);
- }
-
- /* if that left us screwed up, then fail */
- if (m < MARK_FIRST || markline(m) > nlines)
- {
- return MARK_UNSET;
- }
-
- return m;
- }
-
- /*ARGSUSED*/
- MARK m_right(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;
- }
-
- /*ARGSUSED*/
- MARK m_left(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;
- }
-
- /*ARGSUSED*/
- MARK m_tocol(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' && !*o_list)
- {
- col += *o_tabstop;
- col -= col % *o_tabstop;
- }
- else if (UCHAR(*text) < ' ' || *text == '\177')
- {
- col += 2;
- }
- #ifndef NO_CHARATTR
- 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;
- }
-
- /*ARGSUSED*/
- MARK m_front(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;
- }
-
- /*ARGSUSED*/
- MARK m_rear(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);
- }
-
- #ifndef NO_SENTENCE
- /*ARGSUSED*/
- MARK m_fsentence(m, cnt)
- MARK m; /* movement is relative to this mark */
- long cnt; /* a numeric argument */
- {
- REG char *text;
- REG 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 = m_fword(m, 1L);
-
- return m;
- }
-
- /*ARGSUSED*/
- MARK m_bsentence(m, cnt)
- MARK m; /* movement is relative to this mark */
- long cnt; /* a numeric argument */
- {
- REG char *text; /* used to scan thru text */
- REG 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 = m_fword(m, 1L);
-
- return m;
- }
- #endif
-
- /*ARGSUSED*/
- MARK m_fparagraph(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--;
- }
- #ifndef NO_SENTENCE
- else if (*text == '.')
- {
- for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
- {
- if (pscn[0] == text[1] && pscn[1] == text[2])
- {
- cnt--;
- break;
- }
- }
- }
- #endif
- }
- if (l <= nlines)
- {
- m = MARK_AT_LINE(l);
- }
- else
- {
- m = MARK_LAST;
- }
- return m;
- }
-
- /*ARGSUSED*/
- MARK m_bparagraph(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--;
- }
- #ifndef NO_SENTENCE
- else if (*text == '.')
- {
- for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
- {
- if (pscn[0] == text[1] && pscn[1] == text[2])
- {
- cnt--;
- break;
- }
- }
- }
- #endif
- }
- if (l >= 1)
- {
- m = MARK_AT_LINE(l);
- }
- else
- {
- m = MARK_FIRST;
- }
- return m;
- }
-
- /*ARGSUSED*/
- MARK m_fsection(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;
- }
- #ifndef NO_SENTENCE
- else if (*text == '.')
- {
- for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
- {
- if (sscn[0] == text[1] && sscn[1] == text[2])
- {
- goto BreakBreak;
- }
- }
- }
- #endif
- }
- BreakBreak:
- if (l <= nlines)
- {
- m = MARK_AT_LINE(l);
- }
- else
- {
- m = MARK_LAST;
- }
- return m;
- }
-
- /*ARGSUSED*/
- MARK m_bsection(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;
- }
- #ifndef NO_SENTENCE
- else if (*text == '.')
- {
- for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
- {
- if (sscn[0] == text[1] && sscn[1] == text[2])
- {
- goto BreakBreak;
- }
- }
- }
- #endif
- }
- BreakBreak:
- if (l >= 1)
- {
- m = MARK_AT_LINE(l);
- }
- else
- {
- m = MARK_FIRST;
- }
- return m;
- }
-
-
- /*ARGSUSED*/
- MARK m_match(m, cnt)
- MARK m; /* movement is relative to this mark */
- long cnt; /* a numeric argument (ignored) */
- {
- long l;
- REG char *text;
- REG char match;
- REG char nest;
- REG 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;
- }
-
- /*ARGSUSED*/
- MARK m_tomark(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'];
- }
-
-