#include "ded.h" #include "match.h" #include "signal.h" #include "str.h" /* for strlength() */ /************************************************************************ * * * copyright Richard Bornat 1981 * * * ************************************************************************/ char *cachesetup(), *cacheshuffle(), *cachebuf(); /* variables to help in fast matching */ int auxempty; int one_line; matchinterrupt() { signal(SIGINT, ttyinterrupt); ttyzonk(); dlogout(1); /* search aborted */ abandon("!! search abandoned by ^C !!"); } abandon(str) /* abandon match or substitution */ char *str; { i_display(ab_line); /* ab_line, _col are set in comm.c and change.c */ in_c.row=ab_line-topl; in_c.col=ab_col; tdiag(str); } /************************************************************************ * * * this procedure is only called from comm.c - it is certain that * * sline, scol are within the range tline, bline. * * * ************************************************************************/ find(direction, sline, scol, tline, bline) register int direction; register int sline, scol; /* start line, start column */ int tline, bline; /* Top line, Bottom line of range to be searched */ { int s2line, s2col; if (direction==FORWARD) { if (x_find(direction, sline, scol+1, bline, ncols, bline, ncols)) return(true); else { s2line=tline; s2col=MARGIN; } } else { if (x_find(direction, sline, scol-1, tline, MARGIN, bline, ncols)) return(true); else { s2line=bline; s2col=ncols; } } return (x_find(direction, s2line, s2col, sline, scol, bline, ncols)); } /************************************************************************ * * * this procedure is only called from find (above) and change * * (change.c). It is certain that sline/col, fline/col and * * tline/col are reasonable - i.e. that both sline/col and * * fline/col are before tline/col and that sline/col are either * * before (FORWARD) or after (BACKWARD) fline/col. * * * * If any of these assertions should be untrue, funny things * * might occur - or at least long irrelevant searches. * * * * Note that matches are done relative to the screen margin - * * hence the cache routines return a pointer to the line after * * the margin. * * * ************************************************************************/ x_find(direction, sline, scol, /* initial position of head */ fline, fcol, /* final position of head */ tline, tcol) /* max position of tail */ int direction; int sline, scol, fline, fcol, tline, tcol; { char *buf; register char *bufp; register char fre, fc; int result=false; /* set limit on tail of search */ mt_line=tline; mt_col=tcol; /* all matching is done relative to the screen margin */ scol -= MARGIN; /* read first line, setting pointer to initial character */ bufp = scol + (buf = cachesetup(sline)); /* find first symbol of regular expression */ fre = RE[0]; fc = RE[1]; /* if ^C is typed during a search, abort it and leave the * command routine. */ if (NORMAL_INPUT) signal(SIGINT, matchinterrupt); else /* see whether the match was aborted */ if (ttyin()!=2) tdiag("(search aborted)"); /* check that buffer is okay - * length test allows for the fact that you may point to the * newline 'character' */ { int maxscol = strlength(buf); if (direction==FORWARD ? scol>maxscol : scol<0) goto changeline; else if (scol>maxscol) bufp=buf+maxscol; } do /* loop to read a line */ { if (direction==FORWARD) do { if (fre == p_BOL && bufp!=buf) break; else if (fre == p_EOL) bufp = buf+strlength(buf); else if (fre == p_CHAR) while (*bufp!=fc) if (*bufp++==0) goto changeline; if ( (ms_linefline || (bufp-buf+MARGIN)>=fcol) && match(RE, ms_line, bufp, BEGLINE)) goto found; } while (bufp-- > buf); /* end of backward loop */ changeline: if (ms_line==fline) goto notfound; else { /* read a new line */ buf = cacheshuffle(direction); /* set the pointer */ if (direction==FORWARD) bufp = buf; else bufp = buf+strlength(buf); } } while (true); found: result = true; ms_col = bufp-buf+MARGIN; mf_line = g_fline; mf_col = g_bufp-cachebuf(mf_line)+MARGIN; notfound: if (NORMAL_INPUT) { signal(SIGINT, ttyinterrupt); dlogout(2); /* search completed */ } return(result); } /**************************************************************** * three procedures to help the matcher in multi-line matches. * * * * Because of the restriction on matches that they all fit on * * the screen, we can get away with a small buffer * ****************************************************************/ struct CACHE { int empty; char *cbuf; }; struct CACHE *cache; int firsttime = true; char *cachesetup(sline) int sline; { if (firsttime) { firsttime = false; #ifdef DBUG if (dbug('z')) /* make sure there is enough room in ded */ { cache_init(); editerror( "[cachesetup] space left is %d words\n(curr_break %8, local address %8)", ((char *)&sline)-curr_break, curr_break, &sline); } #endif } one_line = auxempty = true; ms_line=sline; return(cachebuf(sline)); } extern char *my_alloc(); cache_init() { register int i; /* set up the space on first entry */ if (auxscreen==(char **)0) auxscreen = newscreen(); if (cache==(struct CACHE *)0) cache = (struct CACHE *) my_alloc(NINROWS*sizeof(*cache)); for (i=0; i=NINROWS) editerror("sline (%d) out of range (ms_line %d) in cachebuf", sline, ms_line); if (one_line) cache_init(); if (cache[i].empty) { getline(sline,cache[i].cbuf); cache[i].empty = false; } return(cache[i].cbuf+MARGIN); } char *cacheshuffle(direction) int direction; { register int i; register char *buf; auxempty = true; if (direction==FORWARD) { ms_line++; if (!one_line) { buf = cache[0].cbuf; for (i=1; i0; i--) { cache[i].empty = cache[i-1].empty; cache[i].cbuf = cache[i-1].cbuf; } cache[0].empty = true; cache[0].cbuf = buf; } } if (!one_line && cache[0].empty) one_line=true; return(cachebuf(ms_line)); }