Rename Dlg_head to WDialog.
[midnight-commander.git] / src / viewer / search.c
blobb1cde90fd9078e9a3621a89b9148502748ad1443
1 /*
2 Internal file viewer for the Midnight Commander
3 Function for search data
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009, 2011
7 The Free Software Foundation, Inc.
9 Written by:
10 Miguel de Icaza, 1994, 1995, 1998
11 Janne Kukonlehto, 1994, 1995
12 Jakub Jelinek, 1995
13 Joseph M. Hinkle, 1996
14 Norbert Warmuth, 1997
15 Pavel Machek, 1998
16 Roland Illig <roland.illig@gmx.de>, 2004, 2005
17 Slava Zanko <slavazanko@google.com>, 2009
18 Andrew Borodin <aborodin@vmail.ru>, 2009
19 Ilia Maslakov <il.smind@gmail.com>, 2009
21 This file is part of the Midnight Commander.
23 The Midnight Commander is free software: you can redistribute it
24 and/or modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation, either version 3 of the License,
26 or (at your option) any later version.
28 The Midnight Commander is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program. If not, see <http://www.gnu.org/licenses/>.
37 #include <config.h>
39 #include "lib/global.h"
40 #include "lib/tty/tty.h"
41 #include "lib/widget.h"
43 #include "src/setup.h"
45 #include "internal.h"
47 /*** global variables ****************************************************************************/
49 /*** file scope macro definitions ****************************************************************/
51 /*** file scope type declarations ****************************************************************/
53 /*** file scope variables ************************************************************************/
55 static int search_cb_char_curr_index = -1;
56 static char search_cb_char_buffer[6];
58 /*** file scope functions ************************************************************************/
59 /* --------------------------------------------------------------------------------------------- */
61 static void
62 mcview_search_update_steps (mcview_t * view)
64 off_t filesize = mcview_get_filesize (view);
65 if (filesize != 0)
66 view->update_steps = 40000;
67 else /* viewing a data stream, not a file */
68 view->update_steps = filesize / 100;
70 /* Do not update the percent display but every 20 ks */
71 if (view->update_steps < 20000)
72 view->update_steps = 20000;
75 /* --------------------------------------------------------------------------------------------- */
77 static gboolean
78 mcview_find (mcview_t * view, gsize search_start, gsize * len)
80 gsize search_end;
82 view->search_numNeedSkipChar = 0;
83 search_cb_char_curr_index = -1;
85 if (mcview_search_options.backwards)
87 search_end = mcview_get_filesize (view);
88 while ((int) search_start >= 0)
90 view->search_nroff_seq->index = search_start;
91 mcview_nroff_seq_info (view->search_nroff_seq);
93 if (search_end > search_start + view->search->original_len
94 && mc_search_is_fixed_search_str (view->search))
95 search_end = search_start + view->search->original_len;
97 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
98 && view->search->normal_offset == (off_t) search_start)
100 if (view->text_nroff_mode)
101 view->search->normal_offset++;
102 return TRUE;
105 search_start--;
107 view->search->error_str = g_strdup (_("Search string not found"));
108 return FALSE;
110 view->search_nroff_seq->index = search_start;
111 mcview_nroff_seq_info (view->search_nroff_seq);
113 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
114 len);
117 /* --------------------------------------------------------------------------------------------- */
119 static void
120 mcview_search_show_result (mcview_t * view, WDialog ** d, size_t match_len)
122 int nroff_len;
124 nroff_len =
125 view->text_nroff_mode
126 ? mcview__get_nroff_real_len (view, view->search->start_buffer,
127 view->search->normal_offset - view->search->start_buffer) : 0;
128 view->search_start = view->search->normal_offset + nroff_len;
130 if (!view->hex_mode)
131 view->search_start++;
133 nroff_len =
134 view->text_nroff_mode ? mcview__get_nroff_real_len (view, view->search_start - 1,
135 match_len) : 0;
136 view->search_end = view->search_start + match_len + nroff_len;
138 if (view->hex_mode)
140 view->hex_cursor = view->search_start;
141 view->hexedit_lownibble = FALSE;
142 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
143 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
146 if (verbose)
148 dlg_run_done (*d);
149 destroy_dlg (*d);
150 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
151 tty_refresh ();
153 mcview_moveto_match (view);
157 /* --------------------------------------------------------------------------------------------- */
158 /*** public functions ****************************************************************************/
159 /* --------------------------------------------------------------------------------------------- */
161 mc_search_cbret_t
162 mcview_search_cmd_callback (const void *user_data, gsize char_offset, int *current_char)
164 mcview_t *view = (mcview_t *) user_data;
166 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
167 if (!view->text_nroff_mode)
169 mcview_get_byte (view, char_offset, current_char);
170 return MC_SEARCH_CB_OK;
173 if (view->search_numNeedSkipChar != 0)
175 view->search_numNeedSkipChar--;
176 return MC_SEARCH_CB_SKIP;
179 if (search_cb_char_curr_index == -1
180 || search_cb_char_curr_index >= view->search_nroff_seq->char_width)
182 if (search_cb_char_curr_index != -1)
183 mcview_nroff_seq_next (view->search_nroff_seq);
185 search_cb_char_curr_index = 0;
186 if (view->search_nroff_seq->char_width > 1)
187 g_unichar_to_utf8 (view->search_nroff_seq->current_char, search_cb_char_buffer);
188 else
189 search_cb_char_buffer[0] = (char) view->search_nroff_seq->current_char;
191 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
193 switch (view->search_nroff_seq->type)
195 case NROFF_TYPE_BOLD:
196 view->search_numNeedSkipChar = 1 + view->search_nroff_seq->char_width; /* real char width and 0x8 */
197 break;
198 case NROFF_TYPE_UNDERLINE:
199 view->search_numNeedSkipChar = 2; /* underline symbol and ox8 */
200 break;
201 default:
202 break;
205 return MC_SEARCH_CB_INVALID;
208 *current_char = search_cb_char_buffer[search_cb_char_curr_index];
209 search_cb_char_curr_index++;
211 return (*current_char != -1) ? MC_SEARCH_CB_OK : MC_SEARCH_CB_INVALID;
214 /* --------------------------------------------------------------------------------------------- */
217 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
219 mcview_t *view = (mcview_t *) user_data;
221 if (char_offset >= (gsize) view->update_activate)
223 view->update_activate += view->update_steps;
224 if (verbose)
226 mcview_percent (view, char_offset);
227 tty_refresh ();
229 if (tty_got_interrupt ())
230 return MC_SEARCH_CB_ABORT;
232 /* may be in future return from this callback will change current position
233 * in searching block. Now this just constant return value.
235 return MC_SEARCH_CB_OK;
238 /* --------------------------------------------------------------------------------------------- */
240 void
241 mcview_do_search (mcview_t * view)
243 off_t search_start = 0;
244 gboolean isFound = FALSE;
245 gboolean need_search_again = TRUE;
247 WDialog *d = NULL;
249 size_t match_len;
251 if (verbose)
253 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
254 tty_refresh ();
257 /*for avoid infinite search loop we need to increase or decrease start offset of search */
259 if (view->search_start != 0)
261 if (!view->text_nroff_mode)
262 search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
263 else
265 if (mcview_search_options.backwards)
267 mcview_nroff_t *nroff;
268 nroff = mcview_nroff_seq_new_num (view, view->search_start);
269 if (mcview_nroff_seq_prev (nroff) != -1)
270 search_start =
271 -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
272 nroff->char_width + 1);
273 else
274 search_start = -2;
276 mcview_nroff_seq_free (&nroff);
278 else
280 search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
282 search_start += view->search_start;
286 if (mcview_search_options.backwards && (int) search_start < 0)
287 search_start = 0;
289 /* Compute the percent steps */
290 mcview_search_update_steps (view);
291 view->update_activate = 0;
293 tty_enable_interrupt_key ();
297 off_t growbufsize;
299 if (view->growbuf_in_use)
300 growbufsize = mcview_growbuf_filesize (view);
301 else
302 growbufsize = view->search->original_len;
304 if (mcview_find (view, search_start, &match_len))
306 mcview_search_show_result (view, &d, match_len);
307 need_search_again = FALSE;
308 isFound = TRUE;
309 break;
312 if (view->search->error_str == NULL)
313 break;
315 search_start = growbufsize - view->search->original_len;
316 if (search_start <= 0)
318 search_start = 0;
319 break;
322 while (mcview_may_still_grow (view));
324 if (view->search_start != 0 && !isFound && need_search_again
325 && !mcview_search_options.backwards)
327 int result;
329 mcview_update (view);
331 result =
332 query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
333 _("&No"));
335 if (result != 0)
336 isFound = TRUE;
337 else
338 search_start = 0;
341 if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
343 mcview_search_show_result (view, &d, match_len);
344 isFound = TRUE;
347 tty_disable_interrupt_key ();
349 if (verbose)
351 dlg_run_done (d);
352 destroy_dlg (d);
355 if (!isFound && view->search->error_str != NULL)
356 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
358 view->dirty++;
359 mcview_update (view);
362 /* --------------------------------------------------------------------------------------------- */