diff options
Diffstat (limited to 'move2.c')
-rw-r--r-- | move2.c | 238 |
1 files changed, 238 insertions, 0 deletions
@@ -0,0 +1,238 @@ +/* move2.c */ + +/* Author: + * Steve Kirkendall + * 14407 SW Teal Blvd. #C + * Beaverton, OR 97005 + * kirkenda@cs.pdx.edu + */ + + +/* This function contains the movement functions that perform RE searching */ + +#include "config.h" +#include "vi.h" +#include "regexp.h" + +extern long atol(); + +static regexp *re; /* compiled version of the pattern to search for */ +static prevsf; /* boolean: previous search direction was forward? */ + +MARK m_nsrch(m) + MARK m; /* where to start searching */ +{ + if (prevsf) + { + m = m_fsrch(m, (char *)0); + prevsf = TRUE; + } + else + { + m = m_bsrch(m, (char *)0); + prevsf = FALSE; + } + return m; +} + +MARK m_Nsrch(m) + MARK m; /* where to start searching */ +{ + if (prevsf) + { + m = m_bsrch(m, (char *)0); + prevsf = TRUE; + } + else + { + m = m_fsrch(m, (char *)0); + prevsf = FALSE; + } + return m; +} + +MARK m_fsrch(m, ptrn) + MARK m; /* where to start searching */ + char *ptrn; /* pattern to search for */ +{ + long l; /* line# of line to be searched */ + char *line; /* text of line to be searched */ + int wrapped;/* boolean: has our search wrapped yet? */ + int pos; /* where we are in the line */ + long delta; /* line offset, for things like "/foo/+1" */ + + /* remember: "previous search was forward" */ + prevsf = TRUE; + + delta = 0L; + if (ptrn && *ptrn) + { + /* locate the closing '/', if any */ + line = parseptrn(ptrn); + if (*line) + { + delta = atol(line); + } + ptrn++; + + /* free the previous pattern */ + if (re) free(re); + + /* compile the pattern */ + re = regcomp(ptrn); + if (!re) + { + return MARK_UNSET; + } + } + else if (!re) + { + msg("No previous expression"); + return MARK_UNSET; + } + + /* search forward for the pattern */ + pos = markidx(m) + 1; + pfetch(markline(m)); + if (pos >= plen) + { + pos = 0; + m = (m | (BLKSIZE - 1)) + 1; + } + wrapped = FALSE; + for (l = markline(m); l != markline(m) + 1 || !wrapped; l++) + { + /* wrap search */ + if (l > nlines) + { + /* if we wrapped once already, then the search failed */ + if (wrapped) + { + break; + } + + /* else maybe we should wrap now? */ + if (*o_wrapscan) + { + l = 0; + wrapped = TRUE; + continue; + } + else + { + break; + } + } + + /* get this line */ + line = fetchline(l); + + /* check this line */ + if (regexec(re, &line[pos], (pos == 0))) + { + /* match! */ + if (wrapped && *o_warn) + msg("(wrapped)"); + if (delta != 0L) + { + l += delta; + if (l < 1 || l > nlines) + { + msg("search offset too big"); + return MARK_UNSET; + } + return m_front(MARK_AT_LINE(l), 0L); + } + return MARK_AT_LINE(l) + (int)(re->startp[0] - line); + } + pos = 0; + } + + /* not found */ + msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE"); + return MARK_UNSET; +} + +MARK m_bsrch(m, ptrn) + MARK m; /* where to start searching */ + char *ptrn; /* pattern to search for */ +{ + long l; /* line# of line to be searched */ + char *line; /* text of line to be searched */ + int wrapped;/* boolean: has our search wrapped yet? */ + int pos; /* last acceptable idx for a match on this line */ + int last; /* remembered idx of the last acceptable match on this line */ + int try; /* an idx at which we strat searching for another match */ + + /* remember: "previous search was not forward" */ + prevsf = FALSE; + + if (ptrn && *ptrn) + { + /* locate the closing '?', if any */ + line = parseptrn(ptrn); + ptrn++; + + /* free the previous pattern, if any */ + if (re) free(re); + + /* compile the pattern */ + re = regcomp(ptrn); + if (!re) + { + return MARK_UNSET; + } + } + else if (!re) + { + msg("No previous expression"); + return MARK_UNSET; + } + + /* search backward for the pattern */ + pos = markidx(m); + wrapped = FALSE; + for (l = markline(m); l != markline(m) - 1 || !wrapped; l--) + { + /* wrap search */ + if (l < 1) + { + if (*o_wrapscan) + { + l = nlines + 1; + wrapped = TRUE; + continue; + } + else + { + break; + } + } + + /* get this line */ + line = fetchline(l); + + /* check this line */ + if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos) + { + /* match! now find the last acceptable one in this line */ + do + { + last = (int)(re->startp[0] - line); + try = (int)(re->endp[0] - line); + } while (try > 0 + && regexec(re, &line[try], FALSE) + && (int)(re->startp[0] - line) < pos); + + if (wrapped && *o_warn) + msg("(wrapped)"); + return MARK_AT_LINE(l) + last; + } + pos = BLKSIZE; + } + + /* not found */ + msg(*o_wrapscan ? "Not found" : "Hit top without finding RE"); + return MARK_UNSET; +} + |