📄 usearch.c
字号:
/* * Search & Replace system * Copyright * (C) 1992 Joseph H. Allen * * This file is part of JOE (Joe's Own Editor) */#include "types.h"int wrap = 0; /* Allow wrap */int smode = 0; /* Decremented to zero by execmd */int csmode = 0; /* Set for continued search mode */int icase = 0; /* Set to force case insensitive search */int pico = 0; /* Pico search prompting */B *findhist = NULL; /* Search string history */B *replhist = NULL; /* Replacement string history */SRCH *globalsrch = NULL; /* Most recent completed search data */SRCHREC fsr = { {&fsr, &fsr} };/* Completion stuff: should go somewhere else */unsigned char **word_list;#define MAX_WORD_SIZE 64unsigned char **get_word_list(B *b,int ignore){ unsigned char buf[MAX_WORD_SIZE]; unsigned char *s; unsigned char **list = 0; HASH *h; HENTRY *t; P *p; int c; int idx; int start = 0; h = htmk(1024); p = pdup(b->bof, USTR "get_word_list"); idx = 0; while ((c=pgetc(p))!=NO_MORE_DATA) if (idx) { if (joe_isalnum_(b->o.charmap, c)) { if (idx!=MAX_WORD_SIZE) buf[idx++] = c; } else { if (idx!=MAX_WORD_SIZE && start!=ignore) { buf[idx] = 0; if (!htfind(h,buf)) { s = vsncpy(NULL,0,buf,idx); htadd(h, s, s); } } idx = 0; } } else { start=p->byte-1; if (joe_isalpha_(b->o.charmap, c)) buf[idx++] = c; } prm(p); for (idx = 0;idx != h->len;++idx) for (t = h->tab[idx];t;t=t->next) list = vaadd(list, t->name); if (list) vasort(list,sLEN(list)); htrm(h); return list;}void fcmplt_ins(BW *bw, unsigned char *line){ P *p = pdup(bw->cursor, USTR "fcmplt_ins"); int c; if (!piseol(bw->cursor)) { int c = brch(bw->cursor); if (joe_isalnum_(bw->b->o.charmap,c)) return; } /* Move p to beginning of word */ p = pdup(bw->cursor, USTR "fcmplt_ins"); do c = prgetc(p); while (joe_isalnum_(bw->b->o.charmap,c)); if (c!=NO_MORE_DATA) pgetc(p); if (bw->cursor->byte!=p->byte && bw->cursor->byte-p->byte<64) { /* Insert single match */ bdel(p,bw->cursor); binsm(bw->cursor,sv(line)); pfwrd(bw->cursor,sLEN(line)); bw->cursor->xcol = piscol(bw->cursor); prm(p); } else { prm(p); }}int fcmplt_abrt(BW *bw, int x, unsigned char *line){ if (line) { fcmplt_ins(bw, line); vsrm(line); } return -1;}int fcmplt_rtn(MENU *m, int x, unsigned char *line){ fcmplt_ins(m->parent->win->object, m->list[x]); vsrm(line); m->object = NULL; wabort(m->parent); return 0;}int ufinish(BW *bw){ unsigned char *line; unsigned char *line1; unsigned char **lst; P *p; int c; MENU *m; /* Make sure we're not in a word */ if (!piseol(bw->cursor)) { int c = brch(bw->cursor); if (joe_isalnum_(bw->b->o.charmap,c)) return -1; } /* Move p to beginning of word */ p = pdup(bw->cursor, USTR "ufinish"); do c = prgetc(p); while (joe_isalnum_(bw->b->o.charmap,c)); if (c!=NO_MORE_DATA) pgetc(p); if (bw->cursor->byte!=p->byte && bw->cursor->byte-p->byte<64) { line = brvs(p, bw->cursor->byte-p->byte); /* We have a word */ /* Get word list */ if (word_list) varm(word_list); word_list = get_word_list(bw->b, p->byte); if (!word_list) { vsrm(line); prm(p); return -1; } line1 = vsncpy(NULL,0,sv(line)); line1 = vsadd(line1,'*'); lst = regsub(word_list, aLEN(word_list), line1); vsrm(line1); if (!lst) { ttputc(7); vsrm(line); return -1; } m = mkmenu(bw->parent, bw->parent, lst, fcmplt_rtn, fcmplt_abrt, NULL, 0, line, NULL); if (!m) { varm(lst); vsrm(line); return -1; } /* Possible match list is now in lst */ if (aLEN(lst) == 1) return fcmplt_rtn(m, 0, line); else if (smode) return 0; else { unsigned char *com = mcomplete(m); vsrm(m->object); m->object = com; wabort(m->parent); smode = 2; ttputc(7); return 0; } } else { prm(p); return -1; }}static int srch_cmplt(BW *bw){ if (word_list) varm(word_list); word_list = get_word_list(((BW *)bw->parent->win->object)->b, -1); if (!word_list) { ttputc(7); return 0; } return simple_cmplt(bw,word_list);}/* Search forward. bw, pattern and ignore must be set The first possible string we can find is the one beginning under p Returns p if we found a string: The found string is placed in entire/pieces p is placed right after the found string Return 0 if we did not find the string: p is left in its orignal spot*/static P *searchf(BW *bw,SRCH *srch, P *p){ unsigned char *pattern; P *start; P *end; int x; pattern = srch->pattern; start = pdup(p, USTR "searchf"); end = pdup(p, USTR "searchf"); try_again: for (x = 0; x != sLEN(pattern) && pattern[x] != '\\' && (pattern[x]<128 || !p->b->o.charmap->type); ++x) if (srch->ignore) pattern[x] = joe_tolower(p->b->o.charmap,pattern[x]); wrapped: while (srch->ignore ? pifind(start, pattern, x) : pfind(start, pattern, x)) { pset(end, start); pfwrd(end, (long) x); if (srch->wrap_flag && start->byte>=srch->wrap_p->byte) break; if (pmatch(srch->pieces, pattern + x, sLEN(pattern) - x, end, 0, srch->ignore)) { if (end->byte == srch->last_repl) { /* Stuck? */ pattern = srch->pattern; pset(start, p); if (pgetc(start) == NO_MORE_DATA) break; pset(end, start); goto try_again; } else { srch->entire = vstrunc(srch->entire, (int) (end->byte - start->byte)); brmem(start, srch->entire, (int) (end->byte - start->byte)); pset(p, end); prm(start); prm(end); return p; } } if (pgetc(start) == NO_MORE_DATA) break; } if (srch->allow_wrap && !srch->wrap_flag && srch->wrap_p) { msgnw(bw->parent, joe_gettext(_("Wrapped"))); srch->wrap_flag = 1; p_goto_bof(start); goto wrapped; } prm(start); prm(end); return NULL;}/* Search backwards. bw, pattern and ignore must be set The first possible string we can find is the one beginning one position to the left of p. Returns 1 if we found a string: The found string is placed in entire p is placed at the beginning of the string Return 0 if we did not find the string: p is left in its orignal spot*/static P *searchb(BW *bw,SRCH *srch, P *p){ unsigned char *pattern = srch->pattern; P *start; P *end; int x; start = pdup(p, USTR "searchb"); end = pdup(p, USTR "searchb"); try_again: for (x = 0; x != sLEN(pattern) && pattern[x] != '\\' && (pattern[x]<128 || !p->b->o.charmap->type); ++x) if (srch->ignore) pattern[x] = joe_tolower(p->b->o.charmap,pattern[x]); wrapped: while (pbkwd(start, 1L) && (srch->ignore ? prifind(start, pattern, x) : prfind(start, pattern, x))) { pset(end, start); pfwrd(end, (long) x); if (srch->wrap_flag && start->byte<srch->wrap_p->byte) break; if (pmatch(srch->pieces, pattern + x, sLEN(pattern) - x, end, 0, srch->ignore)) { if (start->byte == srch->last_repl) { /* Stuck? */ pattern = srch->pattern; pset(start, p); if (prgetc(start) == NO_MORE_DATA) break; pset(end, start); goto try_again; } else { srch->entire = vstrunc(srch->entire, (int) (end->byte - start->byte)); brmem(start, srch->entire, (int) (end->byte - start->byte)); pset(p, start); prm(start); prm(end); return p; } } } if (srch->allow_wrap && !srch->wrap_flag && srch->wrap_p) { msgnw(bw->parent, joe_gettext(_("Wrapped"))); srch->wrap_flag = 1; p_goto_eof(start); goto wrapped; } prm(start); prm(end); return NULL;}/* Make a search stucture */static SRCH *setmark(SRCH *srch){ if (markv(0)) srch->valid = 1; srch->markb = markb; if (srch->markb) srch->markb->owner = &srch->markb; markb = NULL; srch->markk = markk; if (srch->markk) srch->markk->owner = &srch->markk; markk = NULL; return srch;}SRCH *mksrch(unsigned char *pattern, unsigned char *replacement, int ignore, int backwards, int repeat, int replace, int rest, int all){ SRCH *srch = (SRCH *) joe_malloc(sizeof(SRCH)); int x; srch->first = NULL; srch->current = NULL; srch->all = all; srch->pattern = pattern; srch->replacement = replacement; srch->ignore = ignore; srch->backwards = backwards; srch->repeat = repeat; srch->replace = replace; srch->rest = rest; srch->entire = NULL; srch->flg = 0; srch->addr = -1; srch->last_repl = -1; srch->markb = NULL; srch->markk = NULL; srch->wrap_p = NULL; srch->allow_wrap = wrap; srch->wrap_flag = 0; srch->valid = 0; srch->block_restrict = 0; izque(SRCHREC, link, &srch->recs); for (x = 0; x != 26; ++x) srch->pieces[x] = NULL; return srch;}/* Eliminate a search structure */void rmsrch(SRCH *srch){ int x; prm(markb); prm(markk); prm(srch->wrap_p); if (srch->markb) { markb = srch->markb; markb->owner = &markb; markb->xcol = piscol(markb); } if (srch->markk) { markk = srch->markk; markk->owner = &markk; markk->xcol = piscol(markk); } for (x = 0; x != 26; ++x) vsrm(srch->pieces[x]); frchn(&fsr, &srch->recs); vsrm(srch->pattern); vsrm(srch->replacement); vsrm(srch->entire); joe_free(srch); updall();}/* Insert a replacement string * p is advanced past the inserted text */static P *insert(SRCH *srch, P *p, unsigned char *s, int len){ int x; long starting = p->byte; while (len) { for (x = 0; x != len && s[x] != '\\'; ++x) ; if (x) { binsm(p, s, x); pfwrd(p, (long) x); len -= x; s += x; } else if (len >= 2) { if (((s[1] >= 'a' && s[1] <= 'z') || (s[1] >= 'A' && s[1] <= 'Z')) && srch->pieces[(s[1] & 0x1f) - 1]) { binsm(p, sv(srch->pieces[(s[1] & 0x1f) - 1])); pfwrd(p, (long) sLEN(srch->pieces[(s[1] & 0x1f) - 1])); s += 2; len -= 2; } else if (s[1] >= '0' && s[1] <= '9' && srch->pieces[s[1] - '0']) { binsm(p, sv(srch->pieces[s[1] - '0'])); pfwrd(p, (long) sLEN(srch->pieces[s[1] - '0'])); s += 2; len -= 2; } else if (s[1] == '&' && srch->entire) { binsm(p, sv(srch->entire)); pfwrd(p, (long) sLEN(srch->entire)); s += 2; len -= 2; } else { unsigned char *a=(unsigned char *)s+x; int l=len-x; binsc(p,escape(p->b->o.charmap->type,&a,&l)); pgetc(p); len -= a - (unsigned char *)s; s = a; } } else len = 0; } if (srch->backwards) pbkwd (p, p->byte - starting); return p;}/* Search system user interface *//* Query for search string, search options, possible replacement string, * and execute first search */unsigned char srchstr[] = "Search"; /* Context sensitive help identifier */unsigned char srchopt[] = "SearchOptions";static int pfabort(BW *bw, SRCH *srch){ if (srch) rmsrch(srch); return -1;}static int pfsave(BW *bw, SRCH *srch){ if (srch) { if (globalsrch) rmsrch(globalsrch); globalsrch = srch; srch->rest = 0; srch->repeat = -1; srch->flg = 0; prm(markb); prm(markk); if (srch->markb) { markb = srch->markb; markb->owner = &markb; markb->xcol = piscol(markb); } if (srch->markk) { markk = srch->markk; markk->owner = &markk; markk->xcol = piscol(markk); } srch->markb = NULL; srch->markk = NULL; updall(); } return -1;}static int set_replace(BW *bw, unsigned char *s, SRCH *srch, int *notify){ if (sLEN(s) || !globalsrch || !pico) srch->replacement = s; else { /* Use previous string: this prevents replace with empty string */ /* vsrm(s); srch->replacement = vsdup(globalsrch->replacement); */ srch->replacement = s; } return dopfnext(bw, setmark(srch), notify);}/* Option characters */unsigned char *all_key = (unsigned char *) _("|all files|aA");unsigned char *list_key = (unsigned char *) _("|error list files|eE");unsigned char *replace_key = (unsigned char *) _("|search and replace|rR");unsigned char *backwards_key = (unsigned char *) _("|backwards|bB");unsigned char *ignore_key = (unsigned char *) _("|ignore case|iI");unsigned char *block_key = (unsigned char *) _("|restrict to highlighted block|kK");unsigned char *noignore_key = (unsigned char *) _("|don't ignore case|sS");unsigned char *wrap_key = (unsigned char *) _("|wrap|wW");unsigned char *nowrap_key = (unsigned char *) _("|don't wrap|nN");/* Get next character from string and advance it, locale dependent */int fwrd_c(unsigned char **s){ if (locale_map->type) return utf8_decode_fwrd(s, NULL); else { int c = **s; *s = *s + 1; return c; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -