From 9a8ae90a49f90d705354963f019b3710b13e2902 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Wed, 17 Nov 2010 16:19:18 +0300 Subject: [PATCH] Reimplemented search engine in editor. Now search engines of editor and viewer use the identical algorithm. Signed-off-by: Andrew Borodin --- src/editor/edit-impl.h | 1 + src/editor/edit-widget.h | 1 + src/editor/edit.c | 3 +- src/editor/editcmd.c | 221 ++++++++++++++--------------------- src/editor/editcmd_dialogs.c | 270 ++++++++++++++++++++++++------------------- src/editor/editcmd_dialogs.h | 2 +- 6 files changed, 242 insertions(+), 256 deletions(-) diff --git a/src/editor/edit-impl.h b/src/editor/edit-impl.h index de018f3ac..1f41b25b1 100644 --- a/src/editor/edit-impl.h +++ b/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); diff --git a/src/editor/edit-widget.h b/src/editor/edit-widget.h index d51fa7b51..bef42bdc3 100644 --- a/src/editor/edit-widget.h +++ b/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 */ diff --git a/src/editor/edit.c b/src/editor/edit.c index 3c75f5527..5d776c74e 100644 --- a/src/editor/edit.c +++ b/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); diff --git a/src/editor/editcmd.c b/src/editor/editcmd.c index 84f59a26d..3f677129f 100644 --- a/src/editor/editcmd.c +++ b/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, diff --git a/src/editor/editcmd_dialogs.c b/src/editor/editcmd_dialogs.c index 9efb3ff1b..0a10a2b41 100644 --- a/src/editor/editcmd_dialogs.c +++ b/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); } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/editor/editcmd_dialogs.h b/src/editor/editcmd_dialogs.h index 6b880b7c0..d29fe2e54 100644 --- a/src/editor/editcmd_dialogs.h +++ b/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); -- 2.11.4.GIT