Sync with gnulib 2ab2617ee340ff35a9a4c713004fb302868d41b0
[midnight-commander.git] / src / diffviewer / search.c
blob40e10b4e342e18472bd8382cc56ee59bc4aa04a4
1 /*
2 Search functions for diffviewer.
4 Copyright (C) 2010, 2011
5 The Free Software Foundation, Inc.
7 Written by:
8 Slava Zanko <slavazanko@gmail.com>, 2010.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <config.h>
28 #include <stdio.h>
30 #include "lib/global.h"
31 #include "lib/strutil.h"
32 #include "lib/tty/key.h"
33 #include "lib/widget.h"
34 #ifdef HAVE_CHARSET
35 #include "lib/charsets.h"
36 #endif
38 #include "src/history.h"
40 #include "internal.h"
42 /*** global variables ****************************************************************************/
44 /*** file scope macro definitions ****************************************************************/
46 #define SEARCH_DLG_WIDTH 58
47 #define SEARCH_DLG_HEIGHT 13
49 /*** file scope type declarations ****************************************************************/
51 typedef struct mcdiffview_search_options_struct
53 mc_search_type_t type;
54 gboolean case_sens;
55 gboolean backwards;
56 gboolean whole_words;
57 gboolean all_codepages;
58 } mcdiffview_search_options_t;
60 /*** file scope variables ************************************************************************/
62 static mcdiffview_search_options_t mcdiffview_search_options = {
63 .type = MC_SEARCH_T_NORMAL,
64 .case_sens = FALSE,
65 .backwards = FALSE,
66 .whole_words = FALSE,
67 .all_codepages = FALSE,
70 /*** file scope functions ************************************************************************/
71 /* --------------------------------------------------------------------------------------------- */
73 #define DLG_BTN1_text N_("&Cancel")
74 #define DLG_BTN2_text N_("&OK")
76 static void
77 mcdiffview_dialog_fix_buttons_positions (QuickDialog * dlg)
79 size_t str_cancel_len, str_ok_len;
80 size_t first_start_position;
82 str_cancel_len = str_term_width1 (_(DLG_BTN1_text)) + 4;
83 str_ok_len = str_term_width1 (_(DLG_BTN2_text)) + 6;
85 first_start_position = (SEARCH_DLG_WIDTH - str_cancel_len - str_ok_len - 1) / 2;
86 dlg->widgets[1].relative_x = first_start_position;
87 dlg->widgets[0].relative_x = first_start_position + str_ok_len + 1;
90 /* --------------------------------------------------------------------------------------------- */
92 static gboolean
93 mcdiffview_dialog_search (WDiff * dview)
95 char *exp = NULL;
97 int qd_result;
99 size_t num_of_types;
100 gchar **list_of_types = mc_search_get_types_strings_array (&num_of_types);
102 QuickWidget search_widgets[] = {
103 /* 0 */
104 QUICK_BUTTON (3, SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT - 3, SEARCH_DLG_HEIGHT, DLG_BTN1_text,
105 B_CANCEL, NULL),
106 /* 1 */
107 QUICK_BUTTON (3, SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT - 3, SEARCH_DLG_HEIGHT, DLG_BTN2_text,
108 B_ENTER, NULL),
109 /* 2 */
110 #ifdef HAVE_CHARSET
111 QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 8, SEARCH_DLG_HEIGHT, N_("&All charsets"),
112 &mcdiffview_search_options.all_codepages),
113 #endif
115 QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 7, SEARCH_DLG_HEIGHT, N_("&Whole words"),
116 &mcdiffview_search_options.whole_words),
117 /* 3 */
118 QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 6, SEARCH_DLG_HEIGHT, N_("&Backwards"),
119 &mcdiffview_search_options.backwards),
120 /* 4 */
121 QUICK_CHECKBOX (33, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT, N_("Cas&e sensitive"),
122 &mcdiffview_search_options.case_sens),
123 /* 5 */
124 QUICK_RADIO (3, SEARCH_DLG_WIDTH, 5, SEARCH_DLG_HEIGHT,
125 num_of_types, (const char **) list_of_types,
126 (int *) &mcdiffview_search_options.type),
127 /* 6 */
128 QUICK_INPUT (3, SEARCH_DLG_WIDTH, 3, SEARCH_DLG_HEIGHT,
129 INPUT_LAST_TEXT, SEARCH_DLG_WIDTH - 6, 0,
130 MC_HISTORY_SHARED_SEARCH,
131 &exp),
132 /* 7 */
133 QUICK_LABEL (3, SEARCH_DLG_WIDTH, 2, SEARCH_DLG_HEIGHT, N_("Enter search string:")),
134 QUICK_END
137 QuickDialog search_input = {
138 SEARCH_DLG_WIDTH, SEARCH_DLG_HEIGHT, -1, -1,
139 N_("Search"), "[Input Line Keys]",
140 search_widgets, NULL, NULL, FALSE
143 mcdiffview_dialog_fix_buttons_positions (&search_input);
145 qd_result = quick_dialog (&search_input);
146 g_strfreev (list_of_types);
149 if ((qd_result == B_CANCEL) || (exp == NULL) || (exp[0] == '\0'))
151 g_free (exp);
152 return FALSE;
155 #ifdef HAVE_CHARSET
157 GString *tmp = str_convert_to_input (exp);
159 if (tmp)
161 g_free (exp);
162 exp = g_string_free (tmp, FALSE);
165 #endif
167 g_free (dview->search.last_string);
168 dview->search.last_string = exp;
170 return TRUE;
173 /* --------------------------------------------------------------------------------------------- */
175 static gboolean
176 mcdiffview_do_search_backward (WDiff * dview)
178 ssize_t ind;
179 DIFFLN *p;
181 if (dview->search.last_accessed_num_line < 0)
183 dview->search.last_accessed_num_line = -1;
184 return FALSE;
187 if ((size_t) dview->search.last_accessed_num_line >= dview->a[dview->ord]->len)
188 dview->search.last_accessed_num_line = (ssize_t) dview->a[dview->ord]->len;
190 for (ind = --dview->search.last_accessed_num_line; ind >= 0; ind--)
192 p = (DIFFLN *) & g_array_index (dview->a[dview->ord], DIFFLN, (size_t) ind);
193 if (p->u.len == 0)
194 continue;
196 if (mc_search_run (dview->search.handle, p->p, 0, p->u.len, NULL))
198 dview->skip_rows = dview->search.last_found_line =
199 dview->search.last_accessed_num_line = ind;
200 return TRUE;
203 return FALSE;
206 /* --------------------------------------------------------------------------------------------- */
209 static gboolean
210 mcdiffview_do_search_forward (WDiff * dview)
212 size_t ind;
213 DIFFLN *p;
215 if (dview->search.last_accessed_num_line < 0)
216 dview->search.last_accessed_num_line = -1;
217 else if ((size_t) dview->search.last_accessed_num_line >= dview->a[dview->ord]->len)
219 dview->search.last_accessed_num_line = (ssize_t) dview->a[dview->ord]->len;
220 return FALSE;
223 for (ind = (size_t)++ dview->search.last_accessed_num_line; ind < dview->a[dview->ord]->len;
224 ind++)
226 p = (DIFFLN *) & g_array_index (dview->a[dview->ord], DIFFLN, ind);
227 if (p->u.len == 0)
228 continue;
230 if (mc_search_run (dview->search.handle, p->p, 0, p->u.len, NULL))
232 dview->skip_rows = dview->search.last_found_line =
233 dview->search.last_accessed_num_line = (ssize_t) ind;
234 return TRUE;
237 return FALSE;
240 /* --------------------------------------------------------------------------------------------- */
242 static void
243 mcdiffview_do_search (WDiff * dview)
245 gboolean present_result = FALSE;
247 tty_enable_interrupt_key ();
249 if (mcdiffview_search_options.backwards)
251 present_result = mcdiffview_do_search_backward (dview);
253 else
255 present_result = mcdiffview_do_search_forward (dview);
258 tty_disable_interrupt_key ();
260 if (!present_result)
262 dview->search.last_found_line = -1;
263 error_dialog (_("Search"), _("Search string not found"));
267 /* --------------------------------------------------------------------------------------------- */
268 /*** public functions ****************************************************************************/
269 /* --------------------------------------------------------------------------------------------- */
271 void
272 dview_search_cmd (WDiff * dview)
274 if (dview->dsrc != DATA_SRC_MEM)
276 error_dialog (_("Search"), _("Search is disabled"));
277 return;
280 if (!mcdiffview_dialog_search (dview))
281 return;
283 mc_search_free (dview->search.handle);
284 dview->search.handle = mc_search_new (dview->search.last_string, -1);
286 if (dview->search.handle == NULL)
287 return;
289 dview->search.handle->search_type = mcdiffview_search_options.type;
290 dview->search.handle->is_all_charsets = mcdiffview_search_options.all_codepages;
291 dview->search.handle->is_case_sensitive = mcdiffview_search_options.case_sens;
292 dview->search.handle->whole_words = mcdiffview_search_options.whole_words;
294 mcdiffview_do_search (dview);
297 /* --------------------------------------------------------------------------------------------- */
299 void
300 dview_continue_search_cmd (WDiff * dview)
302 if (dview->dsrc != DATA_SRC_MEM)
303 error_dialog (_("Search"), _("Search is disabled"));
304 else if (dview->search.handle == NULL)
305 dview_search_cmd (dview);
306 else
307 mcdiffview_do_search (dview);
310 /* --------------------------------------------------------------------------------------------- */