Split file src/keybind.[ch] to lib/keybind.[ch] and src/keybind-defaults.[ch].
[midnight-commander.git] / src / viewer / search.c
blob0503e2300025025e43579a84bf57781b5ab03b32
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 "lib/tty/tty.h"
42 #include "lib/widget.h"
44 #include "src/setup.h"
46 #include "internal.h"
48 /*** global variables ****************************************************************************/
50 /*** file scope macro definitions ****************************************************************/
52 /*** file scope type declarations ****************************************************************/
54 /*** file scope variables ************************************************************************/
56 /*** file scope functions ************************************************************************/
57 /* --------------------------------------------------------------------------------------------- */
59 static void
60 mcview_search_update_steps (mcview_t * view)
62 off_t filesize = mcview_get_filesize (view);
63 if (filesize != 0)
64 view->update_steps = 40000;
65 else /* viewing a data stream, not a file */
66 view->update_steps = filesize / 100;
68 /* Do not update the percent display but every 20 ks */
69 if (view->update_steps < 20000)
70 view->update_steps = 20000;
73 /* --------------------------------------------------------------------------------------------- */
75 static gboolean
76 mcview_find (mcview_t * view, gsize search_start, gsize * len)
78 gsize search_end;
80 view->search_numNeedSkipChar = 0;
82 if (mcview_search_options.backwards)
84 search_end = mcview_get_filesize (view);
85 while ((int) search_start >= 0)
87 view->search_nroff_seq->index = search_start;
88 mcview_nroff_seq_info (view->search_nroff_seq);
90 if (search_end > search_start + view->search->original_len
91 && mc_search_is_fixed_search_str (view->search))
92 search_end = search_start + view->search->original_len;
94 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
95 && view->search->normal_offset == (off_t) search_start)
96 return TRUE;
98 search_start--;
100 view->search->error_str = g_strdup (_("Search string not found"));
101 return FALSE;
103 view->search_nroff_seq->index = search_start;
104 mcview_nroff_seq_info (view->search_nroff_seq);
106 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
107 len);
110 /* --------------------------------------------------------------------------------------------- */
112 static void
113 mcview_search_show_result (mcview_t * view, Dlg_head ** d, size_t match_len)
116 view->search_start = view->search->normal_offset +
117 mcview__get_nroff_real_len (view,
118 view->search->start_buffer,
119 view->search->normal_offset - view->search->start_buffer);
121 if (!view->hex_mode)
122 view->search_start++;
124 view->search_end = view->search_start + match_len +
125 mcview__get_nroff_real_len (view, view->search_start - 1, match_len);
127 if (view->hex_mode)
129 view->hex_cursor = view->search_start;
130 view->hexedit_lownibble = FALSE;
131 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
132 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
135 if (verbose)
137 dlg_run_done (*d);
138 destroy_dlg (*d);
139 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
140 tty_refresh ();
142 mcview_moveto_match (view);
146 /* --------------------------------------------------------------------------------------------- */
147 /*** public functions ****************************************************************************/
148 /* --------------------------------------------------------------------------------------------- */
151 mcview_search_cmd_callback (const void *user_data, gsize char_offset)
153 int lc_byte;
154 mcview_t *view = (mcview_t *) user_data;
156 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
157 if (!view->text_nroff_mode)
159 if (!mcview_get_byte (view, char_offset, &lc_byte))
160 return MC_SEARCH_CB_INVALID;
162 return lc_byte;
165 if (view->search_numNeedSkipChar)
167 view->search_numNeedSkipChar--;
168 return MC_SEARCH_CB_SKIP;
171 lc_byte = view->search_nroff_seq->current_char;
173 if (lc_byte == -1)
174 return MC_SEARCH_CB_INVALID;
176 mcview_nroff_seq_next (view->search_nroff_seq);
178 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
179 view->search_numNeedSkipChar = 2;
181 return lc_byte;
184 /* --------------------------------------------------------------------------------------------- */
187 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
189 mcview_t *view = (mcview_t *) user_data;
191 if (char_offset >= (gsize) view->update_activate)
193 view->update_activate += view->update_steps;
194 if (verbose)
196 mcview_percent (view, char_offset);
197 tty_refresh ();
199 if (tty_got_interrupt ())
200 return MC_SEARCH_CB_ABORT;
202 /* may be in future return from this callback will change current position
203 * in searching block. Now this just constant return value.
205 return MC_SEARCH_CB_OK;
208 /* --------------------------------------------------------------------------------------------- */
210 void
211 mcview_do_search (mcview_t * view)
213 off_t search_start, growbufsize;
214 gboolean isFound = FALSE;
215 gboolean need_search_again = TRUE;
217 Dlg_head *d = NULL;
219 size_t match_len;
221 if (verbose)
223 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
224 tty_refresh ();
227 /*for avoid infinite search loop we need to increase or decrease start offset of search */
229 if (view->search_start)
231 search_start = (mcview_search_options.backwards) ? -2 : 2;
232 search_start = view->search_start + search_start +
233 mcview__get_nroff_real_len (view, view->search_start, 2) * search_start;
235 else
237 search_start = view->search_start;
240 if (mcview_search_options.backwards && (int) search_start < 0)
241 search_start = 0;
243 /* Compute the percent steps */
244 mcview_search_update_steps (view);
245 view->update_activate = 0;
247 tty_enable_interrupt_key ();
251 if (view->growbuf_in_use)
252 growbufsize = mcview_growbuf_filesize (view);
253 else
254 growbufsize = view->search->original_len;
256 if (!mcview_find (view, search_start, &match_len))
259 if (view->search->error_str == NULL)
260 break;
262 search_start = growbufsize - view->search->original_len;
263 if (search_start <= 0)
265 search_start = 0;
266 break;
269 continue;
272 mcview_search_show_result (view, &d, match_len);
273 need_search_again = FALSE;
274 isFound = TRUE;
275 break;
277 while (mcview_may_still_grow (view));
279 if (view->search_start != 0 && !isFound && need_search_again
280 && !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 /* --------------------------------------------------------------------------------------------- */