This is search.c in view mode; [Download] [Up]
/* * Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu) * All Rights Reserved. */ #include <config.h> #include <stdio.h> #include <slang.h> #include <string.h> #include "buffer.h" #include "vfile.h" #include "search.h" #include "misc.h" #include "ins.h" #include "paste.h" #include "ledit.h" int Case_Sensitive = 0; static SLsearch_Type Search_Struct; int search(char *str, int dir, int n) { unsigned char *beg, *end, *p; Line *line; int key_len; unsigned int num = 0; if ((key_len = SLsearch_init (str, dir, Case_Sensitive, &Search_Struct)) <= 0) return 0; line = CLine; if (dir == 1) { beg = line->data + Point; end = line->data + line->len; do { if (NULL != (p = SLsearch (beg, end, &Search_Struct))) { CLine = line; LineNum += num; Point = (int) (p - line->data); return key_len; } line = line->next; num++; if (line == NULL) return 0; beg = line->data; end = line->data + line->len; } while (--n); } else if (dir == -1) { end = beg = line->data; if (Point) { int tmp = Point - 1 + key_len; if (tmp > line->len) tmp = line->len; end += tmp; } do { if (NULL != (p = SLsearch (beg, end, &Search_Struct))) { CLine = line; LineNum -= num; Point = (int) (p - line->data); return (key_len); } line = line->prev; num++; if (line == NULL) return(0); beg = line->data; end = line->data + line->len; } while (--n); } return(0); } int search_forward(char *s) { return search(s, 1, 0); } int search_backward(char *s) { return search(s, -1, 0); } int forward_search_line(char *s) { return search(s, 1, 1); } int backward_search_line(char *s) { return( search(s, -1, 1)); } #ifdef upcase #undef upcase #endif #define upcase(ch) (cs ? ch : UPPER_CASE(ch)) static int bol_search(char *str, int dir) { Line *tthis; int max, n, cs = Case_Sensitive; unsigned int num; unsigned char *s, ch1, ch2; max = strlen(str); if ((dir > 0) && Point) { num = 1; tthis = CLine->next; } else if ((dir < 0) && !Point) { tthis = CLine->prev; num = 1; } else { tthis = CLine; num = 0; } while (tthis != NULL) { if (max <= tthis->len) { s = tthis->data; for (n = 0; n < max; n++) { ch1 = upcase(s[n]); ch2 = upcase(str[n]); if (ch1 != ch2) break; } if (n == max) { Point = 0; CLine = tthis; if (dir > 0) LineNum += num; else LineNum -= num; return max; } } num++; if (dir > 0) tthis = tthis->next; else tthis = tthis->prev; } return(0); } int bol_fsearch(char *s) { return bol_search(s, 1); } int bol_bsearch(char *s) { return bol_search(s, -1); } static SLRegexp_Type reg; static int re_search_dir(unsigned char *pat, int dir) { int psave, skip, n, epos; unsigned char rbuf[512], *match; Line *l; reg.case_sensitive = Case_Sensitive; reg.buf = rbuf; reg.pat = pat; reg.buf_len = 512; if (SLang_regexp_compile(®)) { msg_error("Unable to compile pattern."); return(0); } if (reg.osearch) { if (reg.must_match_bol) { if (!bol_search((char *) pat, dir)) return (0); } else if (!search((char *) pat, dir, 0)) return (0); reg.beg_matches[0] = Point; n = strlen((char *) pat); reg.end_matches[0] = n; return n + 1; } if (reg.must_match_bol) { if (dir < 0) { if (Point == 0) { if (!backwchars(&Number_One)) return 0; } } else if (Point) { if (CLine->next == NULL) return (0); CLine = CLine->next; LineNum++; Point = 0; } } if (reg.must_match && (0 != reg.must_match_str[1])) skip = 0; else skip = 1; while (1) { psave = Point; if (!skip) { l = CLine; if (!search((char *) reg.must_match_str, dir, 0)) return (0); if (l != CLine) { if (dir < 0) eol(); else Point = 0; /* if ((dir == -1) && (!reg.must_match_bol)) eol(); else Point = 0; */ psave = Point; } } Point = psave; if (dir == 1) { match = SLang_regexp_match(CLine->data + Point, CLine->len - Point, ®); if (match != NULL) { /* adjust offsets */ reg.offset = Point; } } else if (NULL != (match = SLang_regexp_match(CLine->data, Point, /* was CLine->len */ ®))) { if (Point && (reg.beg_matches[0] >= Point)) match = NULL; else if (reg.must_match_bol == 0) { epos = Point - 1; /* found a match on line now find one closest to current point */ while (epos >= 0) { match = SLang_regexp_match(CLine->data + epos, Point - epos, /* was: CLine->len - epos, */ ®); if (match != NULL) break; epos--; } } } if (match != NULL) { Point = (int) (match - CLine->data); n = reg.end_matches[0]; return (n + 1); } if (dir > 0) { if (CLine->next == NULL) break; CLine = CLine->next; LineNum++; Point = 0; } else { if (CLine->prev == NULL) break; CLine = CLine->prev; LineNum--; eol (); } } return (0); } int re_search_forward(char *pat) { int n, p, len; Line *l; p = Point; n = LineNum; l = CLine; if (0 != (len = re_search_dir((unsigned char *) pat, 1))) return (len); Point = p; LineNum = n; CLine = l; return (0); } int re_search_backward(char *pat) { int n, p, len; Line *l; p = Point; n = LineNum; l = CLine; if (0 != (len = re_search_dir((unsigned char *) pat, -1))) return (len); Point = p; LineNum = n; CLine = l; return (0); } int replace_match(char *s, int *literal) { int n, nmax; char ch; unsigned char *p; if ((reg.pat == NULL) || (reg.beg_matches[0] == -1) || (reg.end_matches[0] + reg.beg_matches[0] + reg.offset >= CLine->len)) return 0; if (*literal) { Point = reg.beg_matches[0] + reg.offset; n = reg.end_matches[0]; generic_deln(&n); insert_string(s); return (1); } /* This is painful --- \& means whole expression, \x x = 1..9 means a sub expression */ /* must work with relative numbers since ins/del may do a realloc */ Point = reg.end_matches[0] + reg.offset + reg.beg_matches[0]; while ((ch = *s++) != 0) { if ((ch != '\\') || ((ch = *s++) == '\\')) { if (ch != '\n') ins(ch); /* Note that I should do a 'newline' call. However, as soon as * I do this, I lose the nth_match strings. Clearly, I need to * re-think this! */ continue; } if (ch == 0) break; if (ch == '&') ch = '0'; if ((ch >= '0') && (ch <= '9')) { nmax = ch - '0'; if ((n = reg.beg_matches[nmax]) == -1) continue; nmax = reg.end_matches[nmax] + reg.beg_matches[nmax]; } else continue; p = CLine->data + reg.offset; while (n < nmax) { ins((char) *(p + n)); n++; } } push_spot(); Point = reg.beg_matches[0] + reg.offset; n = reg.end_matches[0]; generic_deln(&n); pop_spot(); return (1); } static int push_string(char *b, int n) { char *s; s = (char *) SLMALLOC(n + 1); if (s == NULL) { SLang_Error = SL_MALLOC_ERROR; return (0); } if (n) MEMCPY(s, b, n); *(s + n) = 0; SLang_push_malloced_string (s); return (SLang_Error == 0); } void regexp_nth_match (int *np) { int b = 0, n = *np; if ((reg.pat == NULL) || (reg.beg_matches[0] == -1) || (reg.end_matches[0] + reg.beg_matches[0] + reg.offset >= CLine->len)) { SLang_Error = UNKNOWN_ERROR; return; } if ((n <= 0) || (n > 9)) n = 0; else { if ((b = reg.beg_matches[n]) == -1) n = 0; else { n = reg.end_matches[n]; } } b += reg.offset; push_string((char *) CLine->data + b, n); } int search_file(char *file, char *pat, int *np) { unsigned char rbuf[512], *buf; unsigned int n; VFILE *vp; int n_matches = 0, n_max = *np, key_len = 1; reg.case_sensitive = Case_Sensitive; reg.buf = rbuf; reg.pat = (unsigned char *) pat; reg.buf_len = 512; if (SLang_regexp_compile(®)) { msg_error("Unable to compile pattern."); return(0); } if (reg.osearch) { key_len = SLsearch_init ((char *) reg.pat, 1, reg.case_sensitive, &Search_Struct); } else if (reg.must_match) { key_len = SLsearch_init ((char *) reg.must_match_str, 1, reg.case_sensitive, &Search_Struct); } if (key_len <= 0) return 0; if (NULL == (vp = vopen(file, 0, VFILE_TEXT))) return(0); while (NULL != (buf = (unsigned char *) vgets(vp, &n))) { if (reg.must_match) { if (key_len > n) continue; if (NULL == SLsearch (buf, buf + n, &Search_Struct)) { continue; } if (reg.osearch) { goto match_found; } } if (!SLang_regexp_match(buf, (int) n, ®)) continue; match_found: n_matches++; n_max--; if (!push_string((char *) buf, n) || (n_max <= 0)) break; } vclose(vp); return(n_matches); } int insert_file_region (char *file, char *rbeg, char *rend) { VFILE *vp; unsigned int n; unsigned int len = (unsigned int) strlen (rbeg); int num = 0; unsigned char *buf; if (NULL == (vp = vopen(file, 0, VFILE_TEXT))) return (-1); while (NULL != (buf = (unsigned char *) vgets(vp, &n))) { if (n < len) continue; if (!strncmp ((char *) buf, rbeg, len)) { Suspend_Screen_Update = 1; quick_insert(buf, (int) n); num++; len = (unsigned int) strlen (rend); while(NULL != (buf = (unsigned char *) vgets(vp, &n))) { if ((n >= len) && !strncmp ((char *) buf, rend, len)) break; quick_insert(buf, (int) n); if (SLang_Error) break; num++; } break; } } vclose (vp); return num; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.