summaryrefslogtreecommitdiff
path: root/move2.c
diff options
context:
space:
mode:
Diffstat (limited to 'move2.c')
-rw-r--r--move2.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/move2.c b/move2.c
new file mode 100644
index 0000000..c69dbb4
--- /dev/null
+++ b/move2.c
@@ -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;
+}
+