Don't adjust viewer parameters twice after search in the hex mode.
[midnight-commander.git] / src / viewer / search.c
blobed26ee6319f218c2a2070c6d117a2f6df3d2695e
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, 2013
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, 2013
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, off_t search_start, gsize * len)
80 off_t 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 (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 + (off_t) 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 == 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 (verbose)
140 dlg_run_done (*d);
141 dlg_destroy (*d);
142 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
143 tty_refresh ();
145 mcview_moveto_match (view);
148 /* --------------------------------------------------------------------------------------------- */
149 /*** public functions ****************************************************************************/
150 /* --------------------------------------------------------------------------------------------- */
152 mc_search_cbret_t
153 mcview_search_cmd_callback (const void *user_data, gsize char_offset, int *current_char)
155 mcview_t *view = (mcview_t *) user_data;
157 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
158 if (!view->text_nroff_mode)
160 mcview_get_byte (view, char_offset, current_char);
161 return MC_SEARCH_CB_OK;
164 if (view->search_numNeedSkipChar != 0)
166 view->search_numNeedSkipChar--;
167 return MC_SEARCH_CB_SKIP;
170 if (search_cb_char_curr_index == -1
171 || search_cb_char_curr_index >= view->search_nroff_seq->char_width)
173 if (search_cb_char_curr_index != -1)
174 mcview_nroff_seq_next (view->search_nroff_seq);
176 search_cb_char_curr_index = 0;
177 if (view->search_nroff_seq->char_width > 1)
178 g_unichar_to_utf8 (view->search_nroff_seq->current_char, search_cb_char_buffer);
179 else
180 search_cb_char_buffer[0] = (char) view->search_nroff_seq->current_char;
182 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
184 switch (view->search_nroff_seq->type)
186 case NROFF_TYPE_BOLD:
187 view->search_numNeedSkipChar = 1 + view->search_nroff_seq->char_width; /* real char width and 0x8 */
188 break;
189 case NROFF_TYPE_UNDERLINE:
190 view->search_numNeedSkipChar = 2; /* underline symbol and ox8 */
191 break;
192 default:
193 break;
196 return MC_SEARCH_CB_INVALID;
199 *current_char = search_cb_char_buffer[search_cb_char_curr_index];
200 search_cb_char_curr_index++;
202 return (*current_char != -1) ? MC_SEARCH_CB_OK : MC_SEARCH_CB_INVALID;
205 /* --------------------------------------------------------------------------------------------- */
207 mc_search_cbret_t
208 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
210 mcview_t *view = (mcview_t *) user_data;
212 if ((off_t) char_offset >= view->update_activate)
214 view->update_activate += view->update_steps;
215 if (verbose)
217 mcview_percent (view, char_offset);
218 tty_refresh ();
220 if (tty_got_interrupt ())
221 return MC_SEARCH_CB_ABORT;
223 /* may be in future return from this callback will change current position
224 * in searching block. Now this just constant return value.
226 return MC_SEARCH_CB_OK;
229 /* --------------------------------------------------------------------------------------------- */
231 void
232 mcview_do_search (mcview_t * view)
234 off_t search_start = 0;
235 gboolean isFound = FALSE;
236 gboolean need_search_again = TRUE;
238 WDialog *d = NULL;
240 size_t match_len;
242 if (verbose)
244 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
245 tty_refresh ();
248 /*for avoid infinite search loop we need to increase or decrease start offset of search */
250 if (view->search_start != 0)
252 if (!view->text_nroff_mode)
253 search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
254 else
256 if (mcview_search_options.backwards)
258 mcview_nroff_t *nroff;
259 nroff = mcview_nroff_seq_new_num (view, view->search_start);
260 if (mcview_nroff_seq_prev (nroff) != -1)
261 search_start =
262 -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
263 nroff->char_width + 1);
264 else
265 search_start = -2;
267 mcview_nroff_seq_free (&nroff);
269 else
271 search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
273 search_start += view->search_start;
277 if (mcview_search_options.backwards && (int) search_start < 0)
278 search_start = 0;
280 /* Compute the percent steps */
281 mcview_search_update_steps (view);
282 view->update_activate = 0;
284 tty_enable_interrupt_key ();
288 off_t growbufsize;
290 if (view->growbuf_in_use)
291 growbufsize = mcview_growbuf_filesize (view);
292 else
293 growbufsize = view->search->original_len;
295 if (mcview_find (view, search_start, &match_len))
297 mcview_search_show_result (view, &d, match_len);
298 need_search_again = FALSE;
299 isFound = TRUE;
300 break;
303 if (view->search->error_str == NULL)
304 break;
306 search_start = growbufsize - view->search->original_len;
307 if (search_start <= 0)
309 search_start = 0;
310 break;
313 while (mcview_may_still_grow (view));
315 if (view->search_start != 0 && !isFound && need_search_again
316 && !mcview_search_options.backwards)
318 int result;
320 mcview_update (view);
322 result =
323 query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
324 _("&No"));
326 if (result != 0)
327 isFound = TRUE;
328 else
329 search_start = 0;
332 if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
334 mcview_search_show_result (view, &d, match_len);
335 isFound = TRUE;
338 tty_disable_interrupt_key ();
340 if (verbose)
342 dlg_run_done (d);
343 dlg_destroy (d);
346 if (!isFound && view->search->error_str != NULL)
347 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
349 view->dirty++;
350 mcview_update (view);
353 /* --------------------------------------------------------------------------------------------- */