Increase the size of the 'message' buffer, which is currently
[sgt/tweak] / actions.c
index c65c3e4..fb71b9f 100644 (file)
--- a/actions.c
+++ b/actions.c
@@ -1,10 +1,10 @@
+#include "tweak.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
-#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;