This is usearch.c in view mode; [Download] [Up]
/* Search & Replace system */ #include "pw.h" #include "qw.h" #include "vs.h" #include "regex.h" #include "ublock.h" #include "uedit.h" #include "main.h" #include "undo.h" #include "usearch.h" int smode=0; /* Decremented to zero by execmd */ int csmode=0; /* Set for continued search mode */ B *findhist=0; /* Search string history */ B *replhist=0; /* Replacement string history */ SRCH *globalsrch=0; /* Most recent completed search data */ SRCHREC fsr={{&fsr,&fsr}}; /* 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 */ P *searchf(srch,p) SRCH *srch; P *p; { char *pattern=srch->pattern; P *start=pdup(p); P *end=pdup(p); int x; for(x=0;x!=sLEN(pattern) && pattern[x]!='\\';++x) if(srch->ignore) pattern[x]=toup(pattern[x]); while(srch->ignore?pifind(start,pattern,x):pfind(start,pattern,x)) { pset(end,start); pfwrd(end,(long)x); if(pmatch(srch->pieces,pattern+x,sLEN(pattern)-x,end,0,srch->ignore)) { 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)== MAXINT) break; } prm(start); prm(end); return 0; } /* 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 */ P *searchb(srch,p) SRCH *srch; P *p; { char *pattern=srch->pattern; P *start=pdup(p); P *end=pdup(p); int x; for(x=0;x!=sLEN(pattern) && pattern[x]!='\\';++x) if(srch->ignore) pattern[x]=toup(pattern[x]); while(pbkwd(start,1L) && (srch->ignore?prifind(start,pattern,x):prfind(start,pattern,x))) { pset(end,start); pfwrd(end,(long)x); if(pmatch(srch->pieces,pattern+x,sLEN(pattern)-x,end,0,srch->ignore)) { 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; } } prm(start); prm(end); return 0; } /* Make a search stucture */ SRCH *setmark(srch) SRCH *srch; { if(markv(1)) srch->valid=1; srch->markb=markb; if(srch->markb) srch->markb->owner= &srch->markb; markb=0; srch->markk=markk; if(srch->markk) srch->markk->owner= &srch->markk; markk=0; return srch; } SRCH *mksrch(pattern,replacement,ignore,backwards,repeat,replace,rest) char *pattern, *replacement; { SRCH *srch=(SRCH *)malloc(sizeof(SRCH)); int x; srch->pattern=pattern; srch->replacement=replacement; srch->ignore=ignore; srch->backwards=backwards; srch->repeat=repeat; srch->replace=replace; srch->rest=rest; srch->entire=0; srch->flg=0; srch->addr= -1; srch->markb=0; srch->markk=0; srch->valid=0; srch->restrict=0; izque(SRCHREC,link,&srch->recs); for(x=0;x!=26;++x) srch->pieces[x]=0; return srch; } /* Eliminate a search structure */ void rmsrch(srch) SRCH *srch; { int x; 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); } for(x=0;x!=26;++x) vsrm(srch->pieces[x]); frchn(&fsr,&srch->recs); vsrm(srch->pattern); vsrm(srch->replacement); vsrm(srch->entire); free(srch); updall(); } /* Insert a replacement string * p is advanced past the inserted text */ P *insert(srch,p,s,len) SRCH *srch; P *p; char *s; { int x; 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]=='\\') binsc(p,'\\'), pgetc(p); else if(s[1]=='n') binsc(p,'\n'), pgetc(p); else 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])); } 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'])); } else if(s[1]=='&' && srch->entire) { binsm(p,sv(srch->entire)); pfwrd(p,(long)sLEN(srch->entire)); } s+=2; len-=2; } else len=0; } return p; } /* Search system user interface */ /* Query for search string, search options, possible replacement string, * and execute first search */ char srchstr[]="Search"; /* Context sensitive help identifier */ static int pfabort(bw,srch) BW *bw; SRCH *srch; { if(srch) rmsrch(srch); return -1; } static int pfsave(bw,srch) 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=0; srch->markk=0; updall(); } return -1; } static int set_replace(bw,s,srch,notify) BW *bw; char *s; SRCH *srch; int *notify; { srch->replacement=s; return dopfnext(bw,srch,notify); } static int set_options(bw,s,srch,notify) BW *bw; char *s; SRCH *srch; int *notify; { int x; for(x=0;s[x];++x) switch(s[x]) { case 'r': case 'R': srch->replace=1; break; case 'b': case 'B': srch->backwards=1; break; case 'i': case 'I': srch->ignore=1; break; case 'k': case 'K': srch->restrict=1; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(srch->repeat== -1) srch->repeat=0; srch->repeat=srch->repeat*10+s[x]-'0'; break; } vsrm(s); if(srch->replace) { if(wmkpw(bw, "Replace with (^C to abort): ",&replhist,set_replace,srchstr,pfabort,utypebw,srch,notify)) return 0; else return -1; } else return dopfnext(bw,srch,notify); } static int set_pattern(bw,s,srch,notify) BW *bw; char *s; SRCH *srch; int *notify; { BW *pbw; vsrm(srch->pattern); srch->pattern=s; if(pbw=wmkpw(bw, "(I)gnore (R)eplace (B)ackwards Bloc(K) NNN (^C to abort): ", NULL,set_options,srchstr,pfabort,utypebw,srch,notify)) { char buf[10]; if(srch->ignore) binsc(pbw->cursor,'i'); if(srch->replace) binsc(pbw->cursor,'r'); if(srch->backwards) binsc(pbw->cursor,'b'); if(srch->repeat>=0) sprintf(buf,"%d",srch->repeat), binss(pbw->cursor,buf); pset(pbw->cursor,pbw->b->eof); pbw->cursor->xcol=piscol(pbw->cursor); srch->ignore=0; srch->replace=0; srch->backwards=0; srch->repeat= -1; return 0; } else { rmsrch(srch); return -1; } } static int dofirst(bw,back,repl) BW *bw; { SRCH *srch; if(smode && globalsrch) { globalsrch->backwards=back; globalsrch->replace=repl; return pfnext(bw); } if(bw->parent->huh==srchstr) { long byte; peol(bw->cursor); byte=bw->cursor->byte; pbol(bw->cursor); if(byte==bw->cursor->byte) prgetc(bw->cursor); return urtn(bw,MAXINT); } srch=setmark(mksrch(NULL,NULL,0,back,-1,repl,0)); srch->addr=bw->cursor->byte; if(wmkpw(bw,"Find (^C to abort): ",&findhist,set_pattern,srchstr,pfabort,utypebw,srch,NULL)) return 0; else { rmsrch(srch); return -1; } } int pffirst(bw) BW *bw; { return dofirst(bw,0,0); } int prfirst(bw) BW *bw; { return dofirst(bw,1,0); } int pqrepl(bw) BW *bw; { return dofirst(bw,0,1); } /* Execute next search */ static int doreplace(bw,srch) BW *bw; SRCH *srch; { P *q; if(bw->b->rdonly) { msgnw(bw,"Read only"); return -1; } if(markk) markk->end=1; if(srch->markk) srch->markk->end=1; q=pdup(bw->cursor); if(srch->backwards) { q=pfwrd(q,(long)sLEN(srch->entire)); bdel(bw->cursor,q); prm(q); } else { q=pbkwd(q,(long)sLEN(srch->entire)); bdel(q,bw->cursor); prm(q); } insert(srch,bw->cursor,sv(srch->replacement)); srch->addr=bw->cursor->byte; if(markk) markk->end=0; if(srch->markk) srch->markk->end=0; return 0; } static void visit(srch,bw,yn) SRCH *srch; BW *bw; { SRCHREC *r=(SRCHREC *)alitem(&fsr,sizeof(SRCHREC)); r->addr=bw->cursor->byte; r->yn=yn; enqueb(SRCHREC,link,&srch->recs,r); } static void goback(srch,bw) SRCH *srch; BW *bw; { SRCHREC *r=srch->recs.link.prev; if(r!=&srch->recs) { if(r->yn) uundo(bw); if(bw->cursor->byte!=r->addr) pgoto(bw->cursor,r->addr); demote(SRCHREC,link,&fsr,r); } } static int dopfrepl(bw,c,srch,notify) BW *bw; SRCH *srch; int *notify; { srch->addr=bw->cursor->byte; if(c=='N' || c=='n') return dopfnext(bw,srch,notify); else if(c=='Y' || c=='y' || c==' ') { srch->recs.link.prev->yn=1; if(doreplace(bw,srch)) { pfsave(bw,srch); return -1; } else return dopfnext(bw,srch,notify); } else if(c=='R' || c=='r') { if(doreplace(bw,srch)) return -1; srch->rest=1; return dopfnext(bw,srch,notify); } else if(c==8 || c==127 || c=='b' || c=='B') { goback(srch,bw); goback(srch,bw); return dopfnext(bw,srch,notify); } else if(c!=MAXINT) { if(notify) *notify=1; pfsave(bw,srch); nungetc(c); return 0; } if(mkqwnsr(bw,sc("Replace (Y)es (N)o (R)est (B)ackup (^C to abort)?"),dopfrepl,pfsave,srch,notify)) return 0; else return pfsave(bw,srch); } /* Test if found text is within region * return 0 if it is, * -1 if we should keep searching * 1 if we're done */ int restrict(bw,srch) BW *bw; SRCH *srch; { if(!srch->valid || !srch->restrict) return 0; bw->cursor->xcol=piscol(bw->cursor); if(srch->backwards) if(!square) { if(bw->cursor->byte<srch->markb->byte) return 1; else if(bw->cursor->byte+sLEN(srch->entire)>srch->markk->byte) return -1; } else { if(bw->cursor->line<srch->markb->line) return 1; else if(bw->cursor->line>srch->markk->line) return -1; else if(piscol(bw->cursor)+sLEN(srch->entire)>srch->markk->xcol || piscol(bw->cursor)<srch->markb->xcol) return -1; } else if(!square) { if(bw->cursor->byte>srch->markk->byte) return 1; else if(bw->cursor->byte-sLEN(srch->entire)<srch->markb->byte) return -1; } else { if(bw->cursor->line>srch->markk->line) return 1; if(bw->cursor->line<srch->markb->line) return -1; if(piscol(bw->cursor)>srch->markk->xcol || piscol(bw->cursor)-sLEN(srch->entire)<srch->markb->xcol) return -1; } return 0; } /* Possible results: * 0) Search or search & replace is finished. * 1) Search string was not found. * 2) Search string was found. */ static int fnext(bw,srch) BW *bw; SRCH *srch; { P *sta; next: if(srch->repeat!= -1) if(!srch->repeat) return 0; else --srch->repeat; again: if(srch->backwards) sta=searchb(srch,bw->cursor); else sta=searchf(srch,bw->cursor); if(!sta) { srch->repeat= -1; return 1; } else if(srch->rest || srch->repeat!= -1 && srch->replace) { if(srch->valid) switch(restrict(bw,srch)) { case -1: goto again; case 1: if(srch->addr>=0) pgoto(bw->cursor,srch->addr); return !srch->rest; } if(doreplace(bw,srch)) return 0; goto next; } else if(srch->repeat!= -1) { if(srch->valid) switch(restrict(bw,srch)) { case -1: goto again; case 1: if(srch->addr>=0) pgoto(bw->cursor,srch->addr); return 1; } srch->addr=bw->cursor->byte; goto next; } else return 2; } int dopfnext(bw,srch,notify) BW *bw; SRCH *srch; int *notify; { int orgmid=mid; /* Original mid status */ int ret=0; mid=1; /* Screen recenters mode during search */ if(csmode) smode=2; /* We have started a search mode */ if(srch->replace) visit(srch,bw,0); again: switch(fnext(bw,srch)) { case 0: break; case 1: bye: if(!srch->flg && !srch->rest) { if(srch->valid && srch->restrict) msgnw(bw,"Not found (search restricted to marked block)"); else msgnw(bw,"Not found"); ret= -1; } break; case 2: if(srch->valid) switch(restrict(bw,srch)) { case -1: goto again; case 1: if(srch->addr>=0) pgoto(bw->cursor,srch->addr); goto bye; } srch->addr=bw->cursor->byte; if(srch->replace) { if(square) bw->cursor->xcol=piscol(bw->cursor); if(srch->backwards) { pdupown(bw->cursor,&markb); markb->xcol=piscol(markb); pdupown(markb,&markk); pfwrd(markk,(long)sLEN(srch->entire)); markk->xcol=piscol(markk); } else { pdupown(bw->cursor,&markk); markk->xcol=piscol(markk); pdupown(bw->cursor,&markb); pbkwd(markb,(long)sLEN(srch->entire)); markb->xcol=piscol(markb); } srch->flg=1; if(dopfrepl(bw,MAXINT,srch,notify)) ret= -1; notify=0; srch=0; } break; } bw->cursor->xcol=piscol(bw->cursor); dofollows(); mid=orgmid; if(notify) *notify=1; if(srch) pfsave(bw,srch); else updall(); return ret; } int pfnext(bw) BW *bw; { if(!globalsrch) /* Query for search string if there isn't any */ return pffirst(bw); else { SRCH *srch=globalsrch; globalsrch=0; srch->addr=bw->cursor->byte; return dopfnext(bw,setmark(srch),NULL); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.