Ticket #2091: Superfluous "Search done, Continue from begining?" dialog
[midnight-commander.git] / src / viewer / search.c
blobfd1fd642b82be933530e3658da5c0933f5934820
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 Free Software Foundation, Inc.
8 Written by: 1994, 1995, 1998 Miguel de Icaza
9 1994, 1995 Janne Kukonlehto
10 1995 Jakub Jelinek
11 1996 Joseph M. Hinkle
12 1997 Norbert Warmuth
13 1998 Pavel Machek
14 2004 Roland Illig <roland.illig@gmx.de>
15 2005 Roland Illig <roland.illig@gmx.de>
16 2009 Slava Zanko <slavazanko@google.com>
17 2009 Andrew Borodin <aborodin@vmail.ru>
18 2009 Ilia Maslakov <il.smind@gmail.com>
20 This file is part of the Midnight Commander.
22 The Midnight Commander is free software; you can redistribute it
23 and/or modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be
28 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
35 MA 02110-1301, USA.
38 #include <config.h>
40 #include "lib/global.h"
41 #include "src/setup.h"
42 #include "src/wtools.h"
43 #include "lib/tty/tty.h"
44 #include "internal.h"
46 /*** global variables ****************************************************************************/
48 /*** file scope macro definitions ****************************************************************/
50 /*** file scope type declarations ****************************************************************/
52 /*** file scope variables ************************************************************************/
54 /*** file scope functions ************************************************************************/
57 /* --------------------------------------------------------------------------------------------- */
58 static void
59 mcview_search_update_steps (mcview_t * view)
61 off_t filesize = mcview_get_filesize (view);
62 if (filesize != 0)
63 view->update_steps = 40000;
64 else /* viewing a data stream, not a file */
65 view->update_steps = filesize / 100;
67 /* Do not update the percent display but every 20 ks */
68 if (view->update_steps < 20000)
69 view->update_steps = 20000;
72 /* --------------------------------------------------------------------------------------------- */
74 static gboolean
75 mcview_find (mcview_t * view, gsize search_start, gsize * len)
77 gsize search_end;
79 view->search_numNeedSkipChar = 0;
81 if (mcview_search_options.backwards)
83 search_end = mcview_get_filesize (view);
84 while ((int) search_start >= 0)
86 view->search_nroff_seq->index = search_start;
87 mcview_nroff_seq_info (view->search_nroff_seq);
89 if (search_end > search_start + view->search->original_len
90 && mc_search_is_fixed_search_str (view->search))
91 search_end = search_start + view->search->original_len;
93 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
94 && view->search->normal_offset == (off_t) search_start)
95 return TRUE;
97 search_start--;
99 view->search->error_str = g_strdup (_(" Search string not found "));
100 return FALSE;
102 view->search_nroff_seq->index = search_start;
103 mcview_nroff_seq_info (view->search_nroff_seq);
105 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
106 len);
109 /* --------------------------------------------------------------------------------------------- */
111 static void
112 mcview_search_show_result (mcview_t * view, Dlg_head ** d, size_t match_len)
115 view->search_start = view->search->normal_offset +
116 mcview__get_nroff_real_len (view,
117 view->search->start_buffer,
118 view->search->normal_offset - view->search->start_buffer);
120 if (!view->hex_mode)
121 view->search_start++;
123 view->search_end = view->search_start + match_len +
124 mcview__get_nroff_real_len (view, view->search_start - 1, match_len);
126 if (view->hex_mode)
128 view->hex_cursor = view->search_start;
129 view->hexedit_lownibble = FALSE;
130 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
131 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
134 if (verbose)
136 dlg_run_done (*d);
137 destroy_dlg (*d);
138 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
139 tty_refresh ();
141 mcview_moveto_match (view);
145 /* --------------------------------------------------------------------------------------------- */
147 /*** public functions ****************************************************************************/
149 /* --------------------------------------------------------------------------------------------- */
152 mcview_search_cmd_callback (const void *user_data, gsize char_offset)
154 int lc_byte;
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 if (!mcview_get_byte (view, char_offset, &lc_byte))
161 return MC_SEARCH_CB_INVALID;
163 return lc_byte;
166 if (view->search_numNeedSkipChar)
168 view->search_numNeedSkipChar--;
169 return MC_SEARCH_CB_SKIP;
172 lc_byte = view->search_nroff_seq->current_char;
174 if (lc_byte == -1)
175 return MC_SEARCH_CB_INVALID;
177 mcview_nroff_seq_next (view->search_nroff_seq);
179 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
180 view->search_numNeedSkipChar = 2;
182 return lc_byte;
185 /* --------------------------------------------------------------------------------------------- */
188 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
190 mcview_t *view = (mcview_t *) user_data;
192 if (char_offset >= (gsize) view->update_activate)
194 view->update_activate += view->update_steps;
195 if (verbose)
197 mcview_percent (view, char_offset);
198 tty_refresh ();
200 if (tty_got_interrupt ())
201 return MC_SEARCH_CB_ABORT;
203 /* may be in future return from this callback will change current position
204 * in searching block. Now this just constant return value.
206 return MC_SEARCH_CB_OK;
209 /* --------------------------------------------------------------------------------------------- */
211 void
212 mcview_do_search (mcview_t * view)
214 off_t search_start, growbufsize;
215 gboolean isFound = FALSE;
216 gboolean need_search_again = TRUE;
218 Dlg_head *d = NULL;
220 size_t match_len;
222 if (verbose)
224 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
225 tty_refresh ();
228 /*for avoid infinite search loop we need to increase or decrease start offset of search */
230 if (view->search_start)
232 search_start = (mcview_search_options.backwards) ? -2 : 2;
233 search_start = view->search_start + search_start +
234 mcview__get_nroff_real_len (view, view->search_start, 2) * search_start;
236 else
238 search_start = view->search_start;
241 if (mcview_search_options.backwards && (int) search_start < 0)
242 search_start = 0;
244 /* Compute the percent steps */
245 mcview_search_update_steps (view);
246 view->update_activate = 0;
248 tty_enable_interrupt_key ();
252 if (view->growbuf_in_use)
253 growbufsize = mcview_growbuf_filesize (view);
254 else
255 growbufsize = view->search->original_len;
257 if (!mcview_find (view, search_start, &match_len))
260 if (view->search->error_str == NULL)
261 break;
263 search_start = growbufsize - view->search->original_len;
264 if (search_start <= 0)
266 search_start = 0;
267 break;
270 continue;
273 mcview_search_show_result (view, &d, match_len);
274 need_search_again = FALSE;
275 isFound = TRUE;
276 break;
278 while (mcview_may_still_grow (view));
280 if (view->search_start != 0 && !isFound && need_search_again && !mcview_search_options.backwards)
282 int result;
283 mcview_update (view);
285 result =
286 query_dialog (_("Search done"), _("Continue from begining?"), D_NORMAL, 2, _("&Yes"),
287 _("&No"));
289 if (result != 0)
291 isFound = TRUE;
293 else
295 search_start = 0;
299 if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
301 mcview_search_show_result (view, &d, match_len);
302 isFound = TRUE;
305 if (!isFound)
307 if (view->search->error_str)
308 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
311 view->dirty++;
312 mcview_update (view);
314 tty_disable_interrupt_key ();
315 if (verbose)
317 dlg_run_done (d);
318 destroy_dlg (d);
323 /* --------------------------------------------------------------------------------------------- */