(get_paragraph): fix of pointer difference.
[midnight-commander.git] / src / viewer / search.c
blobb1c0712c327065dd4cc62521b13d0b2e9f278b35
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 static int search_cb_char_curr_index = -1;
57 static char search_cb_char_buffer[6];
59 /*** file scope functions ************************************************************************/
60 /* --------------------------------------------------------------------------------------------- */
62 static void
63 mcview_search_update_steps (mcview_t * view)
65 off_t filesize = mcview_get_filesize (view);
66 if (filesize != 0)
67 view->update_steps = 40000;
68 else /* viewing a data stream, not a file */
69 view->update_steps = filesize / 100;
71 /* Do not update the percent display but every 20 ks */
72 if (view->update_steps < 20000)
73 view->update_steps = 20000;
76 /* --------------------------------------------------------------------------------------------- */
78 static gboolean
79 mcview_find (mcview_t * view, gsize search_start, gsize * len)
81 gsize search_end;
83 view->search_numNeedSkipChar = 0;
84 search_cb_char_curr_index = -1;
86 if (mcview_search_options.backwards)
88 search_end = mcview_get_filesize (view);
89 while ((int) search_start >= 0)
91 view->search_nroff_seq->index = search_start;
92 mcview_nroff_seq_info (view->search_nroff_seq);
94 if (search_end > search_start + view->search->original_len
95 && mc_search_is_fixed_search_str (view->search))
96 search_end = search_start + view->search->original_len;
98 if (mc_search_run (view->search, (void *) view, search_start, search_end, len)
99 && view->search->normal_offset == (off_t) search_start)
101 if (view->text_nroff_mode)
102 view->search->normal_offset++;
103 return TRUE;
106 search_start--;
108 view->search->error_str = g_strdup (_("Search string not found"));
109 return FALSE;
111 view->search_nroff_seq->index = search_start;
112 mcview_nroff_seq_info (view->search_nroff_seq);
114 return mc_search_run (view->search, (void *) view, search_start, mcview_get_filesize (view),
115 len);
118 /* --------------------------------------------------------------------------------------------- */
120 static void
121 mcview_search_show_result (mcview_t * view, Dlg_head ** d, size_t match_len)
123 int nroff_len;
125 nroff_len =
126 view->text_nroff_mode
127 ? mcview__get_nroff_real_len (view, view->search->start_buffer,
128 view->search->normal_offset - view->search->start_buffer) : 0;
129 view->search_start = view->search->normal_offset + nroff_len;
131 if (!view->hex_mode)
132 view->search_start++;
134 nroff_len =
135 view->text_nroff_mode ? mcview__get_nroff_real_len (view, view->search_start - 1,
136 match_len) : 0;
137 view->search_end = view->search_start + match_len + nroff_len;
139 if (view->hex_mode)
141 view->hex_cursor = view->search_start;
142 view->hexedit_lownibble = FALSE;
143 view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
144 view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
147 if (verbose)
149 dlg_run_done (*d);
150 destroy_dlg (*d);
151 *d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
152 tty_refresh ();
154 mcview_moveto_match (view);
158 /* --------------------------------------------------------------------------------------------- */
159 /*** public functions ****************************************************************************/
160 /* --------------------------------------------------------------------------------------------- */
163 mcview_search_cmd_callback (const void *user_data, gsize char_offset)
165 int lc_byte;
166 mcview_t *view = (mcview_t *) user_data;
168 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
169 if (!view->text_nroff_mode)
171 if (!mcview_get_byte (view, char_offset, &lc_byte))
172 return MC_SEARCH_CB_OK;
174 return lc_byte;
177 if (view->search_numNeedSkipChar != 0)
179 view->search_numNeedSkipChar--;
180 return MC_SEARCH_CB_SKIP;
183 if (search_cb_char_curr_index == -1
184 || search_cb_char_curr_index >= view->search_nroff_seq->char_width)
186 if (search_cb_char_curr_index != -1)
187 mcview_nroff_seq_next (view->search_nroff_seq);
189 search_cb_char_curr_index = 0;
190 if (view->search_nroff_seq->char_width > 1)
191 g_unichar_to_utf8 (view->search_nroff_seq->current_char, search_cb_char_buffer);
192 else
193 search_cb_char_buffer[0] = (char) view->search_nroff_seq->current_char;
195 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
197 switch (view->search_nroff_seq->type)
199 case NROFF_TYPE_BOLD:
200 view->search_numNeedSkipChar = 1 + view->search_nroff_seq->char_width; /* real char width and 0x8 */
201 break;
202 case NROFF_TYPE_UNDERLINE:
203 view->search_numNeedSkipChar = 2; /* underline symbol and ox8 */
204 break;
205 default:
206 break;
209 return MC_SEARCH_CB_INVALID;
212 lc_byte = search_cb_char_buffer[search_cb_char_curr_index];
213 search_cb_char_curr_index++;
214 return (lc_byte != -1) ? (unsigned char) lc_byte : MC_SEARCH_CB_INVALID;
218 /* --------------------------------------------------------------------------------------------- */
221 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
223 mcview_t *view = (mcview_t *) user_data;
225 if (char_offset >= (gsize) view->update_activate)
227 view->update_activate += view->update_steps;
228 if (verbose)
230 mcview_percent (view, char_offset);
231 tty_refresh ();
233 if (tty_got_interrupt ())
234 return MC_SEARCH_CB_ABORT;
236 /* may be in future return from this callback will change current position
237 * in searching block. Now this just constant return value.
239 return MC_SEARCH_CB_OK;
242 /* --------------------------------------------------------------------------------------------- */
244 void
245 mcview_do_search (mcview_t * view)
247 off_t search_start = 0;
248 gboolean isFound = FALSE;
249 gboolean need_search_again = TRUE;
251 Dlg_head *d = NULL;
253 size_t match_len;
255 if (verbose)
257 d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
258 tty_refresh ();
261 /*for avoid infinite search loop we need to increase or decrease start offset of search */
263 if (view->search_start != 0)
265 if (!view->text_nroff_mode)
266 search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
267 else
269 if (mcview_search_options.backwards)
271 mcview_nroff_t *nroff;
272 nroff = mcview_nroff_seq_new_num (view, view->search_start);
273 if (mcview_nroff_seq_prev (nroff) != -1)
274 search_start =
275 -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
276 nroff->char_width + 1);
277 else
278 search_start = -2;
280 mcview_nroff_seq_free (&nroff);
282 else
284 search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
286 search_start += view->search_start;
290 if (mcview_search_options.backwards && (int) search_start < 0)
291 search_start = 0;
293 /* Compute the percent steps */
294 mcview_search_update_steps (view);
295 view->update_activate = 0;
297 tty_enable_interrupt_key ();
301 off_t growbufsize;
303 if (view->growbuf_in_use)
304 growbufsize = mcview_growbuf_filesize (view);
305 else
306 growbufsize = view->search->original_len;
308 if (mcview_find (view, search_start, &match_len))
310 mcview_search_show_result (view, &d, match_len);
311 need_search_again = FALSE;
312 isFound = TRUE;
313 break;
316 if (view->search->error_str == NULL)
317 break;
319 search_start = growbufsize - view->search->original_len;
320 if (search_start <= 0)
322 search_start = 0;
323 break;
326 while (mcview_may_still_grow (view));
328 if (view->search_start != 0 && !isFound && need_search_again
329 && !mcview_search_options.backwards)
331 int result;
333 mcview_update (view);
335 result =
336 query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
337 _("&No"));
339 if (result != 0)
340 isFound = TRUE;
341 else
342 search_start = 0;
345 if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
347 mcview_search_show_result (view, &d, match_len);
348 isFound = TRUE;
351 if (!isFound && view->search->error_str != NULL)
352 message (D_NORMAL, _("Search"), "%s", view->search->error_str);
354 view->dirty++;
355 mcview_update (view);
357 tty_disable_interrupt_key ();
358 if (verbose)
360 dlg_run_done (d);
361 destroy_dlg (d);
365 /* --------------------------------------------------------------------------------------------- */