From a63728c704b14d40a3229f66dbf0088fbe5d95af Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 21 Nov 2004 10:25:03 +0000 Subject: [PATCH] Implement reverse searching (via ^R, of course). git-svn-id: svn://svn.tartarus.org/sgt/tweak@4858 cda61777-01e9-0310-a592-d414129be87e --- actions.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- main.c | 6 ---- rcfile.c | 1 + search.c | 47 +++++++++++++++++------------- tweak.h | 10 +++++-- 5 files changed, 114 insertions(+), 48 deletions(-) diff --git a/actions.c b/actions.c index c65c3e4..3160e4a 100644 --- a/actions.c +++ b/actions.c @@ -31,6 +31,7 @@ static void act_susp (void); static void act_goto (void); static void act_togstat (void); static void act_search (void); +static void act_search_backwards (void); static void act_recentre (void); static void act_width (void); static void act_offset (void); @@ -38,6 +39,8 @@ static void act_offset (void); static void act_diagnostics (void); #endif +static Search *last_search = NULL; + keyact parse_action (char *name) { char *names[] = { "exit", "top-of-file", "page-up", "move-up", @@ -45,8 +48,8 @@ keyact parse_action (char *name) { "move-down", "page-down", "bottom-of-file", "toggle-insert", "change-mode", "delete-left", "delete-right", "mark-place", "cut", "copy", "paste", "suspend", "goto-position", - "toggle-status", "search", "save-file", "exit-and-save", - "screen-recentre", "new-width", "new-offset" + "toggle-status", "search", "search-back", "save-file", + "exit-and-save", "screen-recentre", "new-width", "new-offset" #ifdef TEST_BUFFER , "diagnostics" #endif @@ -56,8 +59,8 @@ keyact parse_action (char *name) { act_right, act_end, act_down, act_pgdn, act_bottom, act_togins, act_chmode, act_delete, act_delch, act_mark, act_cut, act_copy, act_paste, act_susp, act_goto, - act_togstat, act_search, act_save, act_exitsave, - act_recentre, act_width, act_offset + act_togstat, act_search, act_search_backwards, act_save, + act_exitsave, act_recentre, act_width, act_offset #ifdef TEST_BUFFER , act_diagnostics #endif @@ -526,35 +529,47 @@ static void act_togstat (void) { statfmt = decstatus; } -static void act_search (void) { +static int search_prompt(char *withdef, char *withoutdef) +{ char buffer[80]; - int len, posn, dfapos; - DFA dfa; - static unsigned char sblk[SEARCH_BLK]; - static char withdef[] = "Search for (default=last): "; - static char withoutdef[] = "Search for: "; + int len; - dfa = last_dfa(); - - if (!get_str(dfa ? withdef : withoutdef, buffer, TRUE)) - return; /* user break */ - if (!dfa && !*buffer) { + if (!get_str(last_search ? withdef : withoutdef, buffer, TRUE)) + return 0; /* user break */ + if (!last_search && !*buffer) { strcpy (message, "Search aborted."); - return; + return 0; } if (!*buffer) { - len = last_len(); + len = last_search->len; } else { len = parse_quoted (buffer); if (len == -1) { display_beep(); strcpy (message, "Invalid escape sequence in search string"); - return; + return 0; } - dfa = build_dfa (buffer, len); + if (last_search) + free_search(last_search); + last_search = build_search (buffer, len); } + return 1; +} + +static void act_search (void) { + int len, posn, dfapos; + DFA dfa; + static unsigned char sblk[SEARCH_BLK]; + static char withdef[] = "Search forward (default=last): "; + static char withoutdef[] = "Search forward: "; + + if (!search_prompt(withdef, withoutdef)) + return; + + dfa = last_search->forward; + len = last_search->len; dfapos = 0; for (posn = cur_pos+1; posn < file_size; posn++) { @@ -584,6 +599,51 @@ static void act_search (void) { strcpy (message, "Not found."); } +static void act_search_backwards (void) { + int len, posn, dfapos; + DFA dfa; + static unsigned char sblk[SEARCH_BLK]; + static char withdef[] = "Search backward (default=last): "; + static char withoutdef[] = "Search backward: "; + + if (!search_prompt(withdef, withoutdef)) + return; + + dfa = last_search->reverse; + len = last_search->len; + dfapos = 0; + + posn = cur_pos + len - 1; + if (posn >= file_size) + posn = file_size; + + for (; posn >= 0; posn--) { + unsigned char *q; + int size = SEARCH_BLK; + + if (size > posn) + size = posn; + buf_fetch_data (filedata, sblk, size, posn-size); + q = sblk + size; + while (size--) { + posn--; + dfapos = dfa[dfapos][*--q]; + if (dfapos == len) { + int new_top; + + cur_pos = posn; + edit_type = !!edit_type; + new_top = cur_pos - (scrlines-1) * width; + new_top = begline(new_top); + if (top_pos > new_top) + top_pos = new_top; + return; + } + } + } + strcpy (message, "Not found."); +} + static void act_recentre (void) { top_pos = cur_pos - (display_rows-2)/2 * width; if (top_pos < 0) diff --git a/main.c b/main.c index adae913..2e7d179 100644 --- a/main.c +++ b/main.c @@ -46,12 +46,6 @@ * an undo chain attached; so, in particular, the cut buffer * shouldn't be one. Sort that out. * - * - Reverse search. - * + need to construct a reverse DFA. - * + probably should construct both every time, so that you can - * search forward for a thing and then immediately change - * your mind and search backward for the same thing. - * * - In-place editing. * + this is an extra option when running in Fix mode. It * causes a change of semantics when saving: instead of diff --git a/rcfile.c b/rcfile.c index 146c8c2..6f5de8f 100644 --- a/rcfile.c +++ b/rcfile.c @@ -111,6 +111,7 @@ static char *default_rc[] = { "", "# Key bindings: additional movement keys", "bind search ^S", + "bind search-back ^R", "bind goto-position ^XG", "bind goto-position ^Xg", "bind screen-recentre ^L", diff --git a/search.c b/search.c index 9616f64..f99de2d 100644 --- a/search.c +++ b/search.c @@ -4,23 +4,16 @@ #include "tweak.h" -static DFA dfa = NULL; -static char *tmp = NULL; -static int dfa_size = 0, dfa_len = 0; - -DFA build_dfa (char *pattern, int len) { +static DFA build_dfa (char *pattern, int len) +{ int i, j, k, b; + char *tmp = malloc(len); + DFA dfa = malloc(len * sizeof(*dfa)); - if (dfa_size < len) { - dfa_size = len; - dfa = (dfa ? realloc(dfa, dfa_size * sizeof(*dfa)) : - malloc(dfa_size * sizeof(*dfa))); - if (!dfa) - return NULL; - tmp = (tmp ? realloc(tmp, dfa_size) : malloc(dfa_size)); - if (!tmp) - return NULL; - } + if (!dfa) + return NULL; + if (!tmp) + return NULL; memcpy (tmp, pattern, len); @@ -36,14 +29,28 @@ DFA build_dfa (char *pattern, int len) { } } } - dfa_len = len; + return dfa; } -DFA last_dfa (void) { - return dfa; +Search *build_search(char *pattern, int len) +{ + Search *ret = malloc(sizeof(Search)); + char *revpat = malloc(len); + int i; + + ret->len = len; + ret->forward = build_dfa(pattern, len); + for (i = 0; i < len; i++) + revpat[i] = pattern[len-1-i]; + ret->reverse = build_dfa(revpat, len); + + return ret; } -int last_len (void) { - return dfa_len; +void free_search(Search *s) +{ + free(s->forward); + free(s->reverse); + free(s); } diff --git a/tweak.h b/tweak.h index 2a8507a..f9ea9eb 100644 --- a/tweak.h +++ b/tweak.h @@ -34,6 +34,11 @@ #define NULL256 NULL64,NULL64,NULL64,NULL64 typedef int (*DFA)[256]; +typedef struct { + int len; + DFA forward, reverse; +} Search; + typedef void (*keyact) (void); typedef struct buffer buffer; @@ -65,9 +70,8 @@ extern keyact parse_action (char *); extern void proc_key (void); extern void bind_key (char *, int, keyact); -extern DFA build_dfa (char *, int); -extern DFA last_dfa (void); -extern int last_len (void); +extern Search *build_search (char *, int); +void free_search(Search *s); extern int get_str (char *, char *, int); extern int parse_quoted (char *); -- 2.11.0