static char rcsid[] = "$Id: search.c,v 1.1 1992/09/05 01:13:32 mike Exp $"; /* $Log: search.c,v $ * Revision 1.1 1992/09/05 01:13:32 mike * Initial revision * */ /* * * SEARCH.C: search and replace stuff * * The functions in this file implement commands that search in the forward * and backward directions. Query replace is also done here. Regular * expression stuff is in regexp.c * * Revision history: * * ? Steve Wilhite, 1-Dec-85 - massive cleanup on code. * Craig Durland, March 86: more cleanup and reorganization */ /* Copyright 1990, 1991, 1992 Craig Durland * Distributed under the terms of the GNU General Public License. * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include "me2.h" static int lookfor(), submatch(); int case_fold = TRUE; /* * Search forward beginning at dot, for the string. If found, reset the dot * to be just after the match string, and [perhaps] repaint the display. * Returns: TRUE if found, else FALSE. */ search_forward(pattern) char *pattern; { return lookfor(pattern); } /* Search the current buffer for pattern. Start at the dot and search * towards the end of the buffer. * Returns: * TRUE: Found a match for pattern. Dot is after the last matched * character. * FALSE: No match found. Dot not moved. */ static int lookfor(pattern) char *pattern; { unsigned char c; register Line *clp; register int cbo; clp = the_dot->line; cbo = the_dot->offset; /* start at cursor */ if (clp == BUFFER_LAST_LINE(curbp)) return FALSE; /* ??? needed? */ while (TRUE) { if (cbo >= llength(clp)) /* at end of line */ { if ((clp = lforw(clp)) == BUFFER_LAST_LINE(curbp)) return FALSE; cbo = 0; c = '\n'; } else c = lgetc(clp,cbo++); if (ceq(c,*pattern) && submatch(clp,cbo,pattern+1)) return TRUE; } /* never gets here */ } /* point to next char to be matched */ static int submatch(tlp,tbo,pattern) Line *tlp; int tbo; char *pattern; { unsigned char c; while (*pattern != '\0') { if (tlp == BUFFER_LAST_LINE(curbp)) return FALSE; if (tbo >= llength(tlp)) { tlp = lforw(tlp); tbo = 0; c = '\n'; } else c = lgetc(tlp, tbo++); if (!ceq(c,*pattern++)) return FALSE; } the_dot->line = tlp; the_dot->offset = tbo; dot_moved(); return TRUE; } /* * Reverse search. Search, starting at dot and proceeding toward the front * of the buffer for pattern. If found, dot is left pointing at the first * character of the pattern [the last character that was matched]. * Returns: TRUE if found, else FALSE. */ search_reverse(pattern) char *pattern; { register Line *clp, *dlp; register int cbo, dbo; unsigned char c; clp = dlp = the_dot->line; cbo = dbo = the_dot->offset; /* for (; n>0; n--)*/ while (TRUE) { if (cbo == 0) /* at start of line, goto end of previous line */ { clp = lback(clp); if (clp == BUFFER_LAST_LINE(curbp)) return FALSE; cbo = llength(clp) +1; } if (--cbo == llength(clp)) c = '\n'; else c = lgetc(clp,cbo); if (ceq(c,*pattern) && submatch(dlp,dbo,pattern +1)) { the_dot->line = clp; the_dot->offset = cbo; break; } dlp = clp; dbo = cbo; } return TRUE; } /* Search/Replace. * Returns: * TRUE : Did at least one replace. * FALSE: No replacements * ABORT: Something bad happened. */ search_replace(search_for,replace_with) char *search_for, *replace_with; { int match_len, got_a_match; set_mark(THE_MARK); /* save excursion */ match_len = strlen(search_for); got_a_match = FALSE; while (TRUE) { if (!lookfor(search_for)) break; /* no more matches */ /* got a match, replace it */ got_a_match = TRUE; if (!replace_occ(match_len,replace_with)) return ABORT; } /* while */ /* restore excursion & set mark at end of replace */ swap_marks(THE_DOT,THE_MARK); return got_a_match; } #if 0 /* old code that might be interesting */ search_replace(pattern,replace_with) char *pattern, *replace_with; { return qr(lookfor,pattern,replace_with,FALSE); } /* A helper routines to actually perform the search and replace. * Returns: TRUE if everything went as expected, ABORT if something bad * happened. */ qr(search, search_pattern,replace_pattern, regexp) int (*search)(), regexp; char *search_pattern, *replace_pattern; { extern char *eopat[], *bopat[]; char line[260]; int s, match_len; set_mark(THE_MARK); /* save excursion */ if (!regexp) match_len = strlen(search_pattern); while (TRUE) { /* Note: relookfor() has no params */ if ((s = (*search)(search_pattern)) == ABORT) return ABORT; if (s == FALSE) break; /* got a match, replace it */ /* repl_cnt++;*/ if (regexp) { if (!re_subs(replace_pattern,line)) { mlwrite("Invalid replace string"); return ABORT; } s = replace_occ(eopat[0]-bopat[0],line); } else s = replace_occ(match_len,replace_pattern); if (!s) return ABORT; /* something bad happened */ } /* while */ /* restore excursion & set mark at end of replace */ swap_marks(THE_DOT,THE_MARK); /* ??? return false if nothing replaced? how about return the replace count? */ return TRUE; } #endif /* * This routine is called by the Search/Replace routines. * This routine backs up the dot, deletes the old string and replaces it * with the new string. * After replacement cursor points to end of new string. * Don't save deleted text in the cut buffer. * Returns: * TRUE: text replaced * FALSE: memory problems. */ replace_occ(old_length,new_str) int old_length; char *new_str; { if (!delete_characters(-old_length, FALSE)) return FALSE; return insert_text(new_str,strlen(new_str)); }