X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/tweak/blobdiff_plain/6e182d98f1e2191523a4a0b8532a73819d6dca8d..HEAD:/actions.c diff --git a/actions.c b/actions.c index c65c3e4..fb71b9f 100644 --- a/actions.c +++ b/actions.c @@ -1,10 +1,10 @@ +#include "tweak.h" + #include #include #include #include -#include "tweak.h" - static void act_exit (void); static void act_save (void); static void act_exitsave (void); @@ -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 @@ -70,8 +73,8 @@ keyact parse_action (char *name) { return NULL; } -static int begline(int x) { - int y = x + width-offset; +static fileoffset_t begline(fileoffset_t x) { + fileoffset_t y = x + width-offset; y -= (y % width); y -= width-offset; if (y < 0) @@ -79,8 +82,8 @@ static int begline(int x) { return y; } -static int endline(int x) { - int y = x + width-offset; +static fileoffset_t endline(fileoffset_t x) { + fileoffset_t y = x + width-offset; y -= (y % width); y += width-1; y -= width-offset; @@ -206,7 +209,7 @@ static void act_left(void) { } static void act_right(void) { - int new_top; + fileoffset_t new_top; if (edit_type == 1) { if (cur_pos < file_size) @@ -227,7 +230,7 @@ static void act_right(void) { } static void act_end(void) { - int new_top; + fileoffset_t new_top; cur_pos = endline(cur_pos); edit_type = !!edit_type; @@ -242,7 +245,7 @@ static void act_end(void) { } static void act_down(void) { - int new_top; + fileoffset_t new_top; cur_pos += width; if (cur_pos >= file_size) { @@ -258,7 +261,7 @@ static void act_down(void) { } static void act_pgdn(void) { - int new_top; + fileoffset_t new_top; cur_pos += (scrlines-1) * width; if (cur_pos >= file_size) { @@ -274,7 +277,7 @@ static void act_pgdn(void) { } static void act_bottom (void) { - int new_top; + fileoffset_t new_top; cur_pos = file_size; edit_type = !!edit_type; @@ -404,7 +407,7 @@ static void act_mark (void) { } static void act_cut (void) { - long marktop, marksize; + fileoffset_t marktop, marksize; if (!marking || mark_point==cur_pos) { display_beep(); @@ -437,7 +440,7 @@ static void act_cut (void) { } static void act_copy (void) { - int marktop, marksize; + fileoffset_t marktop, marksize; if (!marking) { display_beep(); @@ -457,8 +460,10 @@ static void act_copy (void) { } static void act_paste (void) { - int cutsize, new_top; + fileoffset_t cutsize, new_top; + if (!cutbuffer) + return; cutsize = buf_length (cutbuffer); if (!insert_mode) { if (cur_pos + cutsize > file_size) { @@ -488,7 +493,7 @@ static void act_susp (void) { static void act_goto (void) { char buffer[80]; - long position, new_top; + fileoffset_t position, new_top; int error; if (!get_str("Enter position to go to: ", buffer, FALSE)) @@ -526,35 +531,48 @@ 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: "; - - dfa = last_dfa(); + int len; - 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; + fileoffset_t 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++) { @@ -569,7 +587,7 @@ static void act_search (void) { posn++; dfapos = dfa[dfapos][*q++]; if (dfapos == len) { - int new_top; + fileoffset_t new_top; cur_pos = posn - len; edit_type = !!edit_type; @@ -584,6 +602,52 @@ static void act_search (void) { strcpy (message, "Not found."); } +static void act_search_backwards (void) { + int len; + fileoffset_t 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) { + fileoffset_t 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) @@ -594,11 +658,11 @@ static void act_recentre (void) { static void act_width (void) { char buffer[80]; char prompt[80]; - long w; - long new_top; + fileoffset_t w; + fileoffset_t new_top; int error; - sprintf (prompt, "Enter screen width in bytes (now %d): ", width); + sprintf (prompt, "Enter screen width in bytes (now %"OFF"d): ", width); if (!get_str (prompt, buffer, FALSE)) return; w = parse_num (buffer, &error); @@ -620,11 +684,11 @@ static void act_width (void) { static void act_offset (void) { char buffer[80]; char prompt[80]; - long o; - long new_top; + fileoffset_t o; + fileoffset_t new_top; int error; - sprintf (prompt, "Enter start-of-file offset in bytes (now %d): ", + sprintf (prompt, "Enter start-of-file offset in bytes (now %"OFF"d): ", realoffset); if (!get_str (prompt, buffer, FALSE)) return;