[9] | 1 | /* move2.c */
|
---|
| 2 |
|
---|
| 3 | /* Author:
|
---|
| 4 | * Steve Kirkendall
|
---|
| 5 | * 14407 SW Teal Blvd. #C
|
---|
| 6 | * Beaverton, OR 97005
|
---|
| 7 | * kirkenda@cs.pdx.edu
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 |
|
---|
| 11 | /* This function contains the movement functions that perform RE searching */
|
---|
| 12 |
|
---|
| 13 | #include "config.h"
|
---|
| 14 | #include "vi.h"
|
---|
| 15 | #include "regexp.h"
|
---|
| 16 |
|
---|
| 17 | extern long atol();
|
---|
| 18 |
|
---|
| 19 | static regexp *re; /* compiled version of the pattern to search for */
|
---|
| 20 | static prevsf; /* boolean: previous search direction was forward? */
|
---|
| 21 |
|
---|
| 22 | #ifndef NO_EXTENSIONS
|
---|
| 23 | /*ARGSUSED*/
|
---|
| 24 | MARK m_wsrch(word, m, cnt)
|
---|
| 25 | char *word; /* the word to search for */
|
---|
| 26 | MARK m; /* the starting point */
|
---|
| 27 | int cnt; /* ignored */
|
---|
| 28 | {
|
---|
| 29 | char buffer[30];
|
---|
| 30 |
|
---|
| 31 | /* wrap \< and \> around the word */
|
---|
| 32 | strcpy(buffer, "/\\<");
|
---|
| 33 | strcat(buffer, word);
|
---|
| 34 | strcat(buffer, "\\>");
|
---|
| 35 |
|
---|
| 36 | /* show the searched-for word on the bottom line */
|
---|
| 37 | move(LINES - 1, 0);
|
---|
| 38 | qaddstr(buffer);
|
---|
| 39 | clrtoeol();
|
---|
| 40 | refresh();
|
---|
| 41 |
|
---|
| 42 | /* search for the word */
|
---|
| 43 | return m_fsrch(m, buffer);
|
---|
| 44 | }
|
---|
| 45 | #endif
|
---|
| 46 |
|
---|
| 47 | MARK m_nsrch(m)
|
---|
| 48 | MARK m; /* where to start searching */
|
---|
| 49 | {
|
---|
| 50 | if (prevsf)
|
---|
| 51 | {
|
---|
| 52 | m = m_fsrch(m, (char *)0);
|
---|
| 53 | prevsf = TRUE;
|
---|
| 54 | }
|
---|
| 55 | else
|
---|
| 56 | {
|
---|
| 57 | m = m_bsrch(m, (char *)0);
|
---|
| 58 | prevsf = FALSE;
|
---|
| 59 | }
|
---|
| 60 | return m;
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | MARK m_Nsrch(m)
|
---|
| 64 | MARK m; /* where to start searching */
|
---|
| 65 | {
|
---|
| 66 | if (prevsf)
|
---|
| 67 | {
|
---|
| 68 | m = m_bsrch(m, (char *)0);
|
---|
| 69 | prevsf = TRUE;
|
---|
| 70 | }
|
---|
| 71 | else
|
---|
| 72 | {
|
---|
| 73 | m = m_fsrch(m, (char *)0);
|
---|
| 74 | prevsf = FALSE;
|
---|
| 75 | }
|
---|
| 76 | return m;
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | MARK m_fsrch(m, ptrn)
|
---|
| 80 | MARK m; /* where to start searching */
|
---|
| 81 | char *ptrn; /* pattern to search for */
|
---|
| 82 | {
|
---|
| 83 | long l; /* line# of line to be searched */
|
---|
| 84 | char *line; /* text of line to be searched */
|
---|
| 85 | int wrapped;/* boolean: has our search wrapped yet? */
|
---|
| 86 | int pos; /* where we are in the line */
|
---|
| 87 | #ifndef CRUNCH
|
---|
| 88 | long delta = INFINITY;/* line offset, for things like "/foo/+1" */
|
---|
| 89 | #endif
|
---|
| 90 |
|
---|
| 91 | /* remember: "previous search was forward" */
|
---|
| 92 | prevsf = TRUE;
|
---|
| 93 |
|
---|
| 94 | if (ptrn && *ptrn)
|
---|
| 95 | {
|
---|
| 96 | /* locate the closing '/', if any */
|
---|
| 97 | line = parseptrn(ptrn);
|
---|
| 98 | #ifndef CRUNCH
|
---|
| 99 | if (*line)
|
---|
| 100 | {
|
---|
| 101 | delta = atol(line);
|
---|
| 102 | }
|
---|
| 103 | #endif
|
---|
| 104 | ptrn++;
|
---|
| 105 |
|
---|
| 106 | /* free the previous pattern */
|
---|
| 107 | if (re) free(re);
|
---|
| 108 |
|
---|
| 109 | /* compile the pattern */
|
---|
| 110 | re = regcomp(ptrn);
|
---|
| 111 | if (!re)
|
---|
| 112 | {
|
---|
| 113 | return MARK_UNSET;
|
---|
| 114 | }
|
---|
| 115 | }
|
---|
| 116 | else if (!re)
|
---|
| 117 | {
|
---|
| 118 | msg("No previous expression");
|
---|
| 119 | return MARK_UNSET;
|
---|
| 120 | }
|
---|
| 121 |
|
---|
| 122 | /* search forward for the pattern */
|
---|
| 123 | pos = markidx(m) + 1;
|
---|
| 124 | pfetch(markline(m));
|
---|
| 125 | if (pos >= plen)
|
---|
| 126 | {
|
---|
| 127 | pos = 0;
|
---|
| 128 | m = (m | (BLKSIZE - 1)) + 1;
|
---|
| 129 | }
|
---|
| 130 | wrapped = FALSE;
|
---|
| 131 | for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
|
---|
| 132 | {
|
---|
| 133 | /* wrap search */
|
---|
| 134 | if (l > nlines)
|
---|
| 135 | {
|
---|
| 136 | /* if we wrapped once already, then the search failed */
|
---|
| 137 | if (wrapped)
|
---|
| 138 | {
|
---|
| 139 | break;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | /* else maybe we should wrap now? */
|
---|
| 143 | if (*o_wrapscan)
|
---|
| 144 | {
|
---|
| 145 | l = 0;
|
---|
| 146 | wrapped = TRUE;
|
---|
| 147 | continue;
|
---|
| 148 | }
|
---|
| 149 | else
|
---|
| 150 | {
|
---|
| 151 | break;
|
---|
| 152 | }
|
---|
| 153 | }
|
---|
| 154 |
|
---|
| 155 | /* get this line */
|
---|
| 156 | line = fetchline(l);
|
---|
| 157 |
|
---|
| 158 | /* check this line */
|
---|
| 159 | if (regexec(re, &line[pos], (pos == 0)))
|
---|
| 160 | {
|
---|
| 161 | /* match! */
|
---|
| 162 | if (wrapped && *o_warn)
|
---|
| 163 | msg("(wrapped)");
|
---|
| 164 | #ifndef CRUNCH
|
---|
| 165 | if (delta != INFINITY)
|
---|
| 166 | {
|
---|
| 167 | l += delta;
|
---|
| 168 | if (l < 1 || l > nlines)
|
---|
| 169 | {
|
---|
| 170 | msg("search offset too big");
|
---|
| 171 | return MARK_UNSET;
|
---|
| 172 | }
|
---|
| 173 | force_flags = LNMD|INCL;
|
---|
| 174 | return MARK_AT_LINE(l);
|
---|
| 175 | }
|
---|
| 176 | #endif
|
---|
| 177 | return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
|
---|
| 178 | }
|
---|
| 179 | pos = 0;
|
---|
| 180 | }
|
---|
| 181 |
|
---|
| 182 | /* not found */
|
---|
| 183 | msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
|
---|
| 184 | return MARK_UNSET;
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 | MARK m_bsrch(m, ptrn)
|
---|
| 188 | MARK m; /* where to start searching */
|
---|
| 189 | char *ptrn; /* pattern to search for */
|
---|
| 190 | {
|
---|
| 191 | long l; /* line# of line to be searched */
|
---|
| 192 | char *line; /* text of line to be searched */
|
---|
| 193 | int wrapped;/* boolean: has our search wrapped yet? */
|
---|
| 194 | int pos; /* last acceptable idx for a match on this line */
|
---|
| 195 | int last; /* remembered idx of the last acceptable match on this line */
|
---|
| 196 | int try; /* an idx at which we strat searching for another match */
|
---|
| 197 | #ifndef CRUNCH
|
---|
| 198 | long delta = INFINITY;/* line offset, for things like "/foo/+1" */
|
---|
| 199 | #endif
|
---|
| 200 |
|
---|
| 201 | /* remember: "previous search was not forward" */
|
---|
| 202 | prevsf = FALSE;
|
---|
| 203 |
|
---|
| 204 | if (ptrn && *ptrn)
|
---|
| 205 | {
|
---|
| 206 | /* locate the closing '?', if any */
|
---|
| 207 | line = parseptrn(ptrn);
|
---|
| 208 | #ifndef CRUNCH
|
---|
| 209 | if (*line)
|
---|
| 210 | {
|
---|
| 211 | delta = atol(line);
|
---|
| 212 | }
|
---|
| 213 | #endif
|
---|
| 214 | ptrn++;
|
---|
| 215 |
|
---|
| 216 | /* free the previous pattern, if any */
|
---|
| 217 | if (re) free(re);
|
---|
| 218 |
|
---|
| 219 | /* compile the pattern */
|
---|
| 220 | re = regcomp(ptrn);
|
---|
| 221 | if (!re)
|
---|
| 222 | {
|
---|
| 223 | return MARK_UNSET;
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
| 226 | else if (!re)
|
---|
| 227 | {
|
---|
| 228 | msg("No previous expression");
|
---|
| 229 | return MARK_UNSET;
|
---|
| 230 | }
|
---|
| 231 |
|
---|
| 232 | /* search backward for the pattern */
|
---|
| 233 | pos = markidx(m);
|
---|
| 234 | wrapped = FALSE;
|
---|
| 235 | for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
|
---|
| 236 | {
|
---|
| 237 | /* wrap search */
|
---|
| 238 | if (l < 1)
|
---|
| 239 | {
|
---|
| 240 | if (*o_wrapscan)
|
---|
| 241 | {
|
---|
| 242 | l = nlines + 1;
|
---|
| 243 | wrapped = TRUE;
|
---|
| 244 | continue;
|
---|
| 245 | }
|
---|
| 246 | else
|
---|
| 247 | {
|
---|
| 248 | break;
|
---|
| 249 | }
|
---|
| 250 | }
|
---|
| 251 |
|
---|
| 252 | /* get this line */
|
---|
| 253 | line = fetchline(l);
|
---|
| 254 |
|
---|
| 255 | /* check this line */
|
---|
| 256 | if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
|
---|
| 257 | {
|
---|
| 258 | /* match! now find the last acceptable one in this line */
|
---|
| 259 | do
|
---|
| 260 | {
|
---|
| 261 | last = (int)(re->startp[0] - line);
|
---|
| 262 | try = (int)(re->endp[0] - line);
|
---|
| 263 | } while (try > 0
|
---|
| 264 | && regexec(re, &line[try], FALSE)
|
---|
| 265 | && (int)(re->startp[0] - line) < pos);
|
---|
| 266 |
|
---|
| 267 | if (wrapped && *o_warn)
|
---|
| 268 | msg("(wrapped)");
|
---|
| 269 | #ifndef CRUNCH
|
---|
| 270 | if (delta != INFINITY)
|
---|
| 271 | {
|
---|
| 272 | l += delta;
|
---|
| 273 | if (l < 1 || l > nlines)
|
---|
| 274 | {
|
---|
| 275 | msg("search offset too big");
|
---|
| 276 | return MARK_UNSET;
|
---|
| 277 | }
|
---|
| 278 | force_flags = LNMD|INCL;
|
---|
| 279 | return MARK_AT_LINE(l);
|
---|
| 280 | }
|
---|
| 281 | #endif
|
---|
| 282 | return MARK_AT_LINE(l) + last;
|
---|
| 283 | }
|
---|
| 284 | pos = BLKSIZE;
|
---|
| 285 | }
|
---|
| 286 |
|
---|
| 287 | /* not found */
|
---|
| 288 | msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
|
---|
| 289 | return MARK_UNSET;
|
---|
| 290 | }
|
---|
| 291 |
|
---|