Browse Source

Reimplemented search engine in editor.

Now search engines of editor and viewer use the identical algorithm.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Andrew Borodin 14 years ago
parent
commit
9a8ae90a49
6 changed files with 242 additions and 256 deletions
  1. 1 0
      src/editor/edit-impl.h
  2. 1 0
      src/editor/edit-widget.h
  3. 2 1
      src/editor/edit.c
  4. 88 133
      src/editor/editcmd.c
  5. 149 121
      src/editor/editcmd_dialogs.c
  6. 1 1
      src/editor/editcmd_dialogs.h

+ 1 - 0
src/editor/edit-impl.h

@@ -225,6 +225,7 @@ void edit_set_markers (WEdit * edit, long m1, long m2, int c1, int c2);
 void edit_push_markers (WEdit * edit);
 void edit_replace_cmd (WEdit * edit, int again);
 void edit_search_cmd (WEdit * edit, gboolean again);
+int edit_search_cmd_callback (const void *user_data, gsize char_offset);
 void edit_complete_word_cmd (WEdit * edit);
 void edit_get_match_keyword_cmd (WEdit * edit);
 int edit_save_block (WEdit * edit, const char *filename, long start, long finish);

+ 1 - 0
src/editor/edit-widget.h

@@ -55,6 +55,7 @@ struct WEdit
     mc_search_t *search;
     int replace_mode;
 
+    char *last_search_string;   /* String that have been searched */
     long search_start;          /* First character to start searching from */
     int found_len;              /* Length of found string or 0 if none was found */
     long found_start;           /* the found word from a search - start position */

+ 2 - 1
src/editor/edit.c

@@ -931,7 +931,6 @@ edit_init (WEdit * edit, int lines, int columns, const char *filename, long line
         }
 #endif /* ENABLE_NLS */
         edit = g_malloc0 (sizeof (WEdit));
-        edit->search = NULL;
         to_free = 1;
     }
     edit_purge_widget (edit);
@@ -1025,6 +1024,8 @@ edit_clean (WEdit * edit)
 
     mc_search_free (edit->search);
     edit->search = NULL;
+    g_free (edit->last_search_string);
+    edit->last_search_string = NULL;
 
     if (edit->converter != str_cnv_from_term)
         str_close_conv (edit->converter);

+ 88 - 133
src/editor/editcmd.c

@@ -83,46 +83,7 @@ int edit_confirm_save = 1;
 static int edit_save_cmd (WEdit * edit);
 static unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l);
 
-static void
-edit_search_cmd_search_create_bookmark (WEdit * edit)
-{
-    int found = 0, books = 0;
-    long l = 0, l_last = -1;
-    long q = 0;
-    gsize len = 0;
-
-    search_create_bookmark = FALSE;
-    book_mark_flush (edit, -1);
-
-    for (;;)
-    {
-        if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
-            break;
-        if (found == 0)
-            edit->search_start = edit->search->normal_offset;
-        found++;
-        l += edit_count_lines (edit, q, edit->search->normal_offset);
-        if (l != l_last)
-        {
-            book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
-            books++;
-        }
-        l_last = l;
-        q = edit->search->normal_offset + 1;
-    }
-
-    if (found == 0)
-    {
-        edit_error_dialog (_("Search"), _("Search string not found"));
-    }
-    else
-    {
-        edit_cursor_move (edit, edit->search_start - edit->curs1);
-        edit_scroll_screen_over_cursor (edit);
-    }
-}
-
-static int
+int
 edit_search_cmd_callback (const void *user_data, gsize char_offset)
 {
     return edit_get_byte ((WEdit *) user_data, (long) char_offset);
@@ -1901,112 +1862,47 @@ edit_replace_cmd (WEdit * edit, int again)
     g_free (input2);
 }
 
-
-void
-edit_search_cmd (WEdit * edit, gboolean again)
+static void
+edit_do_search (WEdit * edit)
 {
-    char *search_string = NULL, *search_string_dup = NULL;
     gsize len = 0;
 
-    if (edit == NULL)
-        return;
-
-    if (edit->search != NULL)
-    {
-        search_string = g_strndup (edit->search->original, edit->search->original_len);
-        search_string_dup = search_string;
-    }
-    else
-    {
-        GList *history;
-        history = history_get (MC_HISTORY_SHARED_SEARCH);
-        if (history != NULL && history->data != NULL)
-        {
-            search_string_dup = search_string = (char *) g_strdup (history->data);
-            history = g_list_first (history);
-            g_list_foreach (history, (GFunc) g_free, NULL);
-            g_list_free (history);
-        }
+    if (edit->search == NULL)
         edit->search_start = edit->curs1;
-    }
 
-    if (!again)
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+
+    if (search_create_bookmark)
     {
-#ifdef HAVE_CHARSET
-        GString *tmp;
+        int found = 0, books = 0;
+        long l = 0, l_last = -1;
+        long q = 0;
 
-        if (search_string != NULL && *search_string != '\0')
-        {
-            tmp = str_convert_to_display (search_string);
-            if (tmp != NULL)
-            {
-                if (tmp->len == 0)
-                    g_string_free (tmp, TRUE);
-                else
-                {
-                    g_free (search_string);
-                    search_string = search_string_dup = g_string_free (tmp, FALSE);
-                }
-            }
-        }
-#endif /* HAVE_CHARSET */
-        editcmd_dialog_search_show (edit, &search_string);
-        g_free (search_string_dup);
-        search_string_dup = NULL;
-#ifdef HAVE_CHARSET
-        if (search_string != NULL && *search_string != '\0')
+        search_create_bookmark = FALSE;
+        book_mark_flush (edit, -1);
+
+        while (TRUE)
         {
-            tmp = str_convert_to_input (search_string);
-            if (tmp != NULL)
+            if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
+                break;
+            if (found == 0)
+                edit->search_start = edit->search->normal_offset;
+            found++;
+            l += edit_count_lines (edit, q, edit->search->normal_offset);
+            if (l != l_last)
             {
-                if (tmp->len == 0)
-                    g_string_free (tmp, TRUE);
-                else
-                {
-                    g_free (search_string);
-                    search_string = g_string_free (tmp, FALSE);
-                }
+                book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
+                books++;
             }
+            l_last = l;
+            q = edit->search->normal_offset + 1;
         }
-#endif /* HAVE_CHARSET */
-
-        edit_push_action (edit, KEY_PRESS + edit->start_display);
 
-        if (search_string == NULL)
-        {
-            edit->force |= REDRAW_COMPLETELY;
-            edit_scroll_screen_over_cursor (edit);
-            return;
-        }
-
-        if (edit->search != NULL)
-        {
-            mc_search_free (edit->search);
-            edit->search = NULL;
-        }
-    }
-
-    if (edit->search == NULL)
-    {
-        edit->search = mc_search_new (search_string, -1);
-        if (edit->search == NULL)
-        {
-            edit->search_start = edit->curs1;
-            g_free (search_string);
-            return;
-        }
-
-        edit->search->search_type = edit_search_options.type;
-        edit->search->is_all_charsets = edit_search_options.all_codepages;
-        edit->search->is_case_sensitive = edit_search_options.case_sens;
-        edit->search->whole_words = edit_search_options.whole_words;
-        edit->search->search_fn = edit_search_cmd_callback;
+        if (found == 0)
+            edit_error_dialog (_("Search"), _("Search string not found"));
+        else
+            edit_cursor_move (edit, edit->search_start - edit->curs1);
     }
-
-    g_free (search_string);
-
-    if (search_create_bookmark)
-        edit_search_cmd_search_create_bookmark (edit);
     else
     {
         if (edit->found_len != 0 && edit->search_start == edit->found_start + 1
@@ -2041,6 +1937,65 @@ edit_search_cmd (WEdit * edit, gboolean again)
     edit_scroll_screen_over_cursor (edit);
 }
 
+static void
+edit_search (WEdit *edit)
+{
+    if (editcmd_dialog_search_show (edit))
+        edit_do_search (edit);
+}
+
+void
+edit_search_cmd (WEdit * edit, gboolean again)
+{
+    if (edit == NULL)
+        return;
+
+    if (!again)
+        edit_search (edit);
+    else if (edit->last_search_string != NULL)
+        edit_do_search (edit);
+    else
+    {
+        /* find last search string in history */
+        GList *history;
+
+        history = history_get (MC_HISTORY_SHARED_SEARCH);
+        if (history != NULL && history->data != NULL)
+        {
+            edit->last_search_string = (char *) history->data;
+            history->data = NULL;
+            history = g_list_first (history);
+            g_list_foreach (history, (GFunc) g_free, NULL);
+            g_list_free (history);
+
+            edit->search = mc_search_new (edit->last_search_string, -1);
+            if (edit->search == NULL)
+            {
+                /* if not... then ask for an expression */
+                g_free (edit->last_search_string);
+                edit->last_search_string = NULL;
+                edit_search (edit);
+            }
+            else
+            {
+                edit->search->search_type = edit_search_options.type;
+                edit->search->is_all_charsets = edit_search_options.all_codepages;
+                edit->search->is_case_sensitive = edit_search_options.case_sens;
+                edit->search->whole_words = edit_search_options.whole_words;
+                edit->search->search_fn = edit_search_cmd_callback;
+                edit_do_search (edit);
+            }
+        }
+        else
+        {
+            /* if not... then ask for an expression */
+            g_free (edit->last_search_string);
+            edit->last_search_string = NULL;
+            edit_search (edit);
+        }
+    }
+}
+
 
 /*
  * Check if it's OK to close the editor.  If there are unsaved changes,

+ 149 - 121
src/editor/editcmd_dialogs.c

@@ -157,148 +157,176 @@ editcmd_dialog_replace_show (WEdit * edit, const char *search_default, const cha
 
 /* --------------------------------------------------------------------------------------------- */
 
-void
-editcmd_dialog_search_show (WEdit * edit, char **search_text)
+gboolean
+editcmd_dialog_search_show (WEdit * edit)
 {
-    (void) edit;
-
-    if (*search_text == NULL)
-        *search_text = INPUT_LAST_TEXT;
+    char *search_text;
 
-    {
-        size_t num_of_types;
-        gchar **list_of_types = mc_search_get_types_strings_array (&num_of_types);
-        int SEARCH_DLG_HEIGHT = SEARCH_DLG_MIN_HEIGHT + num_of_types - SEARCH_DLG_HEIGHT_SUPPLY;
-        size_t i;
+    size_t num_of_types;
+    gchar **list_of_types = mc_search_get_types_strings_array (&num_of_types);
+    int SEARCH_DLG_HEIGHT = SEARCH_DLG_MIN_HEIGHT + num_of_types - SEARCH_DLG_HEIGHT_SUPPLY;
+    size_t i;
 
-        int dialog_result;
+    int dialog_result;
 
-        QuickWidget quick_widgets[] = {
-            /* 0 */
-            QUICK_BUTTON (6, 10, 11, SEARCH_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
-            /* 1 */
-            QUICK_BUTTON (4, 10, 11, SEARCH_DLG_HEIGHT, N_("&Find all"), B_USER, NULL),
-            /* 2 */
-            QUICK_BUTTON (2, 10, 11, SEARCH_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
+    QuickWidget quick_widgets[] = {
+        /* 0 */
+        QUICK_BUTTON (6, 10, 11, SEARCH_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
+        /* 1 */
+        QUICK_BUTTON (4, 10, 11, SEARCH_DLG_HEIGHT, N_("&Find all"), B_USER, NULL),
+        /* 2 */
+        QUICK_BUTTON (2, 10, 11, SEARCH_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
 #ifdef HAVE_CHARSET
-            /* 3 */
-            QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 9, SEARCH_DLG_HEIGHT, N_("All charsets"),
-                            &edit_search_options.all_codepages),
+        /* 3 */
+        QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 9, SEARCH_DLG_HEIGHT, N_("All charsets"),
+                        &edit_search_options.all_codepages),
 #endif
-            /* 4 */
-            QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 8, SEARCH_DLG_HEIGHT, N_("&Whole words"),
-                            &edit_search_options.whole_words),
-            /* 5 */
-            QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 7, SEARCH_DLG_HEIGHT, N_("In se&lection"),
-                            &edit_search_options.only_in_selection),
-            /* 6 */
-            QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 6, SEARCH_DLG_HEIGHT, N_("&Backwards"),
-                            &edit_search_options.backwards),
-            /* 7 */
-            QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT, N_("Case &sensitive"),
-                            &edit_search_options.case_sens),
-            /* 8 */
-            QUICK_RADIO (3, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT,
-                         num_of_types, (const char **) list_of_types,
-                         (int *) &edit_search_options.type),
-            /* 9 */
-            QUICK_INPUT (3, SEARCH_DLG_WIDTH, 3, SEARCH_DLG_HEIGHT,
-                         *search_text, SEARCH_DLG_WIDTH - 6, 0,
-                         MC_HISTORY_SHARED_SEARCH, search_text),
-            /* 10 */
-            QUICK_LABEL (3, SEARCH_DLG_WIDTH, 2, SEARCH_DLG_HEIGHT, N_("Enter search string:")),
-            QUICK_END
-        };
+        /* 4 */
+        QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 8, SEARCH_DLG_HEIGHT, N_("&Whole words"),
+                        &edit_search_options.whole_words),
+        /* 5 */
+        QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 7, SEARCH_DLG_HEIGHT, N_("In se&lection"),
+                        &edit_search_options.only_in_selection),
+        /* 6 */
+        QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 6, SEARCH_DLG_HEIGHT, N_("&Backwards"),
+                        &edit_search_options.backwards),
+        /* 7 */
+        QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT, N_("Case &sensitive"),
+                        &edit_search_options.case_sens),
+        /* 8 */
+        QUICK_RADIO (3, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT,
+                     num_of_types, (const char **) list_of_types,
+                     (int *) &edit_search_options.type),
+        /* 9 */
+        QUICK_INPUT (3, SEARCH_DLG_WIDTH, 3, SEARCH_DLG_HEIGHT,
+                     INPUT_LAST_TEXT, SEARCH_DLG_WIDTH - 6, 0,
+                     MC_HISTORY_SHARED_SEARCH, &search_text),
+        /* 10 */
+        QUICK_LABEL (3, SEARCH_DLG_WIDTH, 2, SEARCH_DLG_HEIGHT, N_("Enter search string:")),
+        QUICK_END
+    };
 
 #ifdef HAVE_CHARSET
-        size_t last_checkbox = 7;
+    size_t last_checkbox = 7;
 #else
-        size_t last_checkbox = 6;
+    size_t last_checkbox = 6;
 #endif
 
-        QuickDialog Quick_input = {
-            SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT, -1, -1, N_("Search"),
-            "[Input Line Keys]", quick_widgets, NULL, TRUE
-        };
+    QuickDialog Quick_input = {
+        SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT, -1, -1, N_("Search"),
+        "[Input Line Keys]", quick_widgets, NULL, TRUE
+    };
 
 #ifdef ENABLE_NLS
-        char **list_of_types_nls;
-
-        /* header title */
-        Quick_input.title = _(Quick_input.title);
-        /* buttons */
-        for (i = 0; i < 3; i++)
-            quick_widgets[i].u.button.text = _(quick_widgets[i].u.button.text);
-        /* checkboxes */
-        for (i = 3; i <= last_checkbox; i++)
-            quick_widgets[i].u.checkbox.text = _(quick_widgets[i].u.checkbox.text);
-        /* label */
-        quick_widgets[10].u.label.text = _(quick_widgets[10].u.label.text);
-
-        /* radiobuttons */
-        /* create copy of radio items to avoid memory leak */
-        list_of_types_nls = g_new0 (char *, num_of_types + 1);
-        for (i = 0; i < num_of_types; i++)
-            list_of_types_nls[i] = g_strdup (_(list_of_types[i]));
-        g_strfreev (list_of_types);
-        list_of_types = list_of_types_nls;
-        quick_widgets[last_checkbox + 1].u.radio.items = (const char **) list_of_types;
+    char **list_of_types_nls;
+
+    /* header title */
+    Quick_input.title = _(Quick_input.title);
+    /* buttons */
+    for (i = 0; i < 3; i++)
+        quick_widgets[i].u.button.text = _(quick_widgets[i].u.button.text);
+    /* checkboxes */
+    for (i = 3; i <= last_checkbox; i++)
+        quick_widgets[i].u.checkbox.text = _(quick_widgets[i].u.checkbox.text);
+    /* label */
+    quick_widgets[10].u.label.text = _(quick_widgets[10].u.label.text);
+
+    /* radiobuttons */
+    /* create copy of radio items to avoid memory leak */
+    list_of_types_nls = g_new0 (char *, num_of_types + 1);
+    for (i = 0; i < num_of_types; i++)
+        list_of_types_nls[i] = g_strdup (_(list_of_types[i]));
+    g_strfreev (list_of_types);
+    list_of_types = list_of_types_nls;
+    quick_widgets[last_checkbox + 1].u.radio.items = (const char **) list_of_types;
 #endif
 
-        /* calculate widget coordinates */
+    /* calculate widget coordinates */
+    {
+        int len = 0;
+        int dlg_width;
+        gchar **radio = list_of_types;
+        int b0_len, b1_len, b2_len;
+        const int button_gap = 2;
+
+        /* length of radiobuttons */
+        while (*radio != NULL)
         {
-            int len = 0;
-            int dlg_width;
-            gchar **radio = list_of_types;
-            int b0_len, b1_len, b2_len;
-            const int button_gap = 2;
-
-            /* length of radiobuttons */
-            while (*radio != NULL)
-            {
-                len = max (len, str_term_width1 (*radio));
-                radio++;
-            }
-            /* length of checkboxes */
-            for (i = 3; i <= last_checkbox; i++)
-                len = max (len, str_term_width1 (quick_widgets[i].u.checkbox.text) + 4);
-
-            /* preliminary dialog width */
-            dlg_width = max (len * 2, str_term_width1 (Quick_input.title)) + 4;
-
-            /* length of buttons */
-            b0_len = str_term_width1 (quick_widgets[0].u.button.text) + 3;
-            b1_len = str_term_width1 (quick_widgets[1].u.button.text) + 3;
-            b2_len = str_term_width1 (quick_widgets[2].u.button.text) + 5;      /* default button */
-            len = b0_len + b1_len + b2_len + button_gap * 2;
-
-            /* dialog width */
-            Quick_input.xlen = max (SEARCH_DLG_WIDTH, max (dlg_width, len + 6));
-
-            /* correct widget coordinates */
-            for (i = 0; i < sizeof (quick_widgets) / sizeof (quick_widgets[0]); i++)
-                quick_widgets[i].x_divisions = Quick_input.xlen;
-
-            /* checkbox positions */
-            for (i = 3; i <= last_checkbox; i++)
-                quick_widgets[i].relative_x = Quick_input.xlen / 2 + 2;
-            /* input length */
-            quick_widgets[last_checkbox + 2].u.input.len = Quick_input.xlen - 6;
-            /* button positions */
-            quick_widgets[2].relative_x = Quick_input.xlen / 2 - len / 2;
-            quick_widgets[1].relative_x = quick_widgets[2].relative_x + b2_len + button_gap;
-            quick_widgets[0].relative_x = quick_widgets[1].relative_x + b1_len + button_gap;
+            len = max (len, str_term_width1 (*radio));
+            radio++;
         }
+        /* length of checkboxes */
+        for (i = 3; i <= last_checkbox; i++)
+            len = max (len, str_term_width1 (quick_widgets[i].u.checkbox.text) + 4);
 
-        dialog_result = quick_dialog (&Quick_input);
+        /* preliminary dialog width */
+        dlg_width = max (len * 2, str_term_width1 (Quick_input.title)) + 4;
 
-        g_strfreev (list_of_types);
+        /* length of buttons */
+        b0_len = str_term_width1 (quick_widgets[0].u.button.text) + 3;
+        b1_len = str_term_width1 (quick_widgets[1].u.button.text) + 3;
+        b2_len = str_term_width1 (quick_widgets[2].u.button.text) + 5;      /* default button */
+        len = b0_len + b1_len + b2_len + button_gap * 2;
 
-        if (dialog_result == B_CANCEL)
-            *search_text = NULL;
-        else if (dialog_result == B_USER)
-            search_create_bookmark = TRUE;
+        /* dialog width */
+        Quick_input.xlen = max (SEARCH_DLG_WIDTH, max (dlg_width, len + 6));
+
+        /* correct widget coordinates */
+        for (i = 0; i < sizeof (quick_widgets) / sizeof (quick_widgets[0]); i++)
+            quick_widgets[i].x_divisions = Quick_input.xlen;
+
+        /* checkbox positions */
+        for (i = 3; i <= last_checkbox; i++)
+            quick_widgets[i].relative_x = Quick_input.xlen / 2 + 2;
+        /* input length */
+        quick_widgets[last_checkbox + 2].u.input.len = Quick_input.xlen - 6;
+        /* button positions */
+        quick_widgets[2].relative_x = Quick_input.xlen / 2 - len / 2;
+        quick_widgets[1].relative_x = quick_widgets[2].relative_x + b2_len + button_gap;
+        quick_widgets[0].relative_x = quick_widgets[1].relative_x + b1_len + button_gap;
+    }
+
+    dialog_result = quick_dialog (&Quick_input);
+
+    g_strfreev (list_of_types);
+
+    if ((dialog_result == B_CANCEL) || (search_text == NULL) || (search_text[0] == '\0'))
+    {
+        g_free (search_text);
+        return FALSE;
     }
+
+    if (dialog_result == B_USER)
+        search_create_bookmark = TRUE;
+
+#ifdef HAVE_CHARSET
+    {
+        GString *tmp;
+
+        tmp = str_convert_to_input (search_text);
+        if (tmp != NULL)
+        {
+            g_free (search_text);
+            search_text = g_string_free (tmp, FALSE);
+        }
+    }
+#endif
+
+    g_free (edit->last_search_string);
+    edit->last_search_string = search_text;
+    mc_search_free (edit->search);
+
+    edit->search = mc_search_new (edit->last_search_string, -1);
+    if (edit->search != NULL)
+    {
+        edit->search->search_type = edit_search_options.type;
+        edit->search->is_all_charsets = edit_search_options.all_codepages;
+        edit->search->is_case_sensitive = edit_search_options.case_sens;
+        edit->search->whole_words = edit_search_options.whole_words;
+        edit->search->search_fn = edit_search_cmd_callback;
+    }
+
+    return (edit->search != NULL);
 }
 
 /* --------------------------------------------------------------------------------------------- */

+ 1 - 1
src/editor/editcmd_dialogs.h

@@ -26,7 +26,7 @@ struct selection {
 
 void editcmd_dialog_replace_show (WEdit *, const char *, const char *, char **, char **);
 
-void editcmd_dialog_search_show (WEdit *, char **);
+gboolean editcmd_dialog_search_show (WEdit *edit);
 
 int editcmd_dialog_raw_key_query (const char *, const char *, int);