x86_64: Cleanup of code for master
[midnight-commander.git] / src / viewer / search.c
blob50faf9abc7c3d9d816f0b22b2a51d4e887dbf686
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) {
82 search_end = mcview_get_filesize (view);
83 while ((int) search_start >= 0) {
84 view->search_nroff_seq->index = search_start;
85 mcview_nroff_seq_info (view->search_nroff_seq);
87 if (search_end > search_start + view->search->original_len
88 && mc_search_is_fixed_search_str (view->search))
89 search_end = search_start + view->search->original_len;
91 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
92 && view->search->normal_offset == (off_t) search_start)
93 return TRUE;
95 search_start--;
97 view->search->error_str = g_strdup (_(" Search string not found "));
98 return FALSE;
100 view->search_nroff_seq->index = search_start;
101 mcview_nroff_seq_info (view->search_nroff_seq);
103 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
104 len);
107 /* --------------------------------------------------------------------------------------------- */
109 static void
110 mcview_search_show_result(mcview_t * view, Dlg_head **d, size_t match_len)
113 view->search_start = view->search->normal_offset +
114 mcview__get_nroff_real_len (view,
115 view->search->start_buffer,
116 view->search->normal_offset -
117 view->search->start_buffer);
119 if (!view->hex_mode)
120 view->search_start++;
122 view->search_end = view->search_start + match_len +
123 mcview__get_nroff_real_len (view, view->search_start - 1, match_len);
125 if (view->hex_mode) {
126 view->hex_cursor = view->search_start;
127 view->hexedit_lownibble = FALSE;
128 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
129 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
132 if (verbose) {
133 dlg_run_done (*d);
134 destroy_dlg (*d);
135 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
136 tty_refresh ();
138 mcview_moveto_match (view);
142 /* --------------------------------------------------------------------------------------------- */
144 /*** public functions ****************************************************************************/
146 /* --------------------------------------------------------------------------------------------- */
149 mcview_search_cmd_callback (const void *user_data, gsize char_offset)
151 int lc_byte;
152 mcview_t *view = (mcview_t *) user_data;
154 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
155 if (!view->text_nroff_mode) {
156 if (! mcview_get_byte (view, char_offset, &lc_byte))
157 return MC_SEARCH_CB_INVALID;
159 return lc_byte;
162 if (view->search_numNeedSkipChar) {
163 view->search_numNeedSkipChar--;
164 return MC_SEARCH_CB_SKIP;
167 lc_byte = view->search_nroff_seq->current_char;
169 if (lc_byte == -1)
170 return MC_SEARCH_CB_INVALID;
172 mcview_nroff_seq_next (view->search_nroff_seq);
174 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
175 view->search_numNeedSkipChar = 2;
177 return lc_byte;
180 /* --------------------------------------------------------------------------------------------- */
183 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
185 mcview_t *view = (mcview_t *) user_data;
187 if (char_offset >= (gsize) view->update_activate) {
188 view->update_activate += view->update_steps;
189 if (verbose) {
190 mcview_percent (view, char_offset);
191 tty_refresh ();
193 if (tty_got_interrupt ())
194 return MC_SEARCH_CB_ABORT;
196 /* may be in future return from this callback will change current position
197 * in searching block. Now this just constant return value.
199 return MC_SEARCH_CB_OK;
202 /* --------------------------------------------------------------------------------------------- */
204 void
205 mcview_do_search (mcview_t * view)
207 off_t search_start, growbufsize;
208 gboolean isFound = FALSE;
209 gboolean need_search_again = TRUE;
211 Dlg_head *d = NULL;
213 size_t match_len;
215 if (verbose) {
216 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
217 tty_refresh ();
220 /*for avoid infinite search loop we need to increase or decrease start offset of search */
222 if (view->search_start) {
223 search_start = (mcview_search_options.backwards) ? -2 : 2;
224 search_start = view->search_start + search_start +
225 mcview__get_nroff_real_len (view, view->search_start, 2) * search_start;
226 } else {
227 search_start = view->search_start;
230 if (mcview_search_options.backwards && (int) search_start < 0)
231 search_start = 0;
233 /* Compute the percent steps */
234 mcview_search_update_steps (view);
235 view->update_activate = 0;
237 tty_enable_interrupt_key ();
239 do {
240 if (view->growbuf_in_use)
241 growbufsize = mcview_growbuf_filesize (view);
242 else
243 growbufsize = view->search->original_len;
245 if (! mcview_find (view, search_start, &match_len)) {
247 if (view->search->error_str == NULL)
248 break;
250 search_start = growbufsize - view->search->original_len;
251 if ( search_start <= 0 ) {
252 search_start = 0;
253 break;
256 continue;
259 mcview_search_show_result(view, &d, match_len);
260 need_search_again = FALSE;
261 isFound = TRUE;
262 break;
263 } while (mcview_may_still_grow (view));
265 if (!isFound && need_search_again && !mcview_search_options.backwards) {
266 int result;
267 mcview_update (view);
269 result =
270 query_dialog (_("Search done"), _("Continue from begining?"), D_NORMAL, 2, _("&Yes"), _("&No"));
272 if (result != 0) {
273 isFound=TRUE;
274 } else {
275 search_start = 0;
279 if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len)) {
280 mcview_search_show_result(view, &d, match_len);
281 isFound = TRUE;
284 if (!isFound) {
285 if (view->search->error_str)
286 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
289 view->dirty++;
290 mcview_update (view);
292 tty_disable_interrupt_key ();
293 if (verbose) {
294 dlg_run_done (d);
295 destroy_dlg (d);
300 /* --------------------------------------------------------------------------------------------- */