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
7
The Free Software Foundation, Inc.
10
Miguel de Icaza, 1994, 1995, 1998
11
Janne Kukonlehto, 1994, 1995
13
Joseph M. Hinkle, 1996
16
Roland Illig <roland.illig@gmx.de>, 2004, 2005
17
Slava Zanko <slavazanko@google.com>, 2009
18
Andrew Borodin <aborodin@vmail.ru>, 2009
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/>.
39
#include "lib/global.h"
40
#include "lib/tty/tty.h"
41
#include "lib/widget.h"
43
#include "src/setup.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
/* --------------------------------------------------------------------------------------------- */
62
mcview_search_update_steps (mcview_t * view)
64
off_t filesize = mcview_get_filesize (view);
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
/* --------------------------------------------------------------------------------------------- */
78
mcview_find (mcview_t * view, gsize search_start, gsize * len)
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 ((int) 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 + 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 == (off_t) search_start)
100
if (view->text_nroff_mode)
101
view->search->normal_offset++;
107
view->search->error_str = g_strdup (_("Search string not found"));
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),
117
/* --------------------------------------------------------------------------------------------- */
120
mcview_search_show_result (mcview_t * view, Dlg_head ** d, size_t match_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;
131
view->search_start++;
134
view->text_nroff_mode ? mcview__get_nroff_real_len (view, view->search_start - 1,
136
view->search_end = view->search_start + match_len + nroff_len;
140
view->hex_cursor = view->search_start;
141
view->hexedit_lownibble = FALSE;
142
view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
143
view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
150
*d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
153
mcview_moveto_match (view);
157
/* --------------------------------------------------------------------------------------------- */
158
/*** public functions ****************************************************************************/
159
/* --------------------------------------------------------------------------------------------- */
162
mcview_search_cmd_callback (const void *user_data, gsize char_offset)
165
mcview_t *view = (mcview_t *) user_data;
167
/* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
168
if (!view->text_nroff_mode)
170
if (!mcview_get_byte (view, char_offset, &lc_byte))
171
return MC_SEARCH_CB_OK;
176
if (view->search_numNeedSkipChar != 0)
178
view->search_numNeedSkipChar--;
179
return MC_SEARCH_CB_SKIP;
182
if (search_cb_char_curr_index == -1
183
|| search_cb_char_curr_index >= view->search_nroff_seq->char_width)
185
if (search_cb_char_curr_index != -1)
186
mcview_nroff_seq_next (view->search_nroff_seq);
188
search_cb_char_curr_index = 0;
189
if (view->search_nroff_seq->char_width > 1)
190
g_unichar_to_utf8 (view->search_nroff_seq->current_char, search_cb_char_buffer);
192
search_cb_char_buffer[0] = (char) view->search_nroff_seq->current_char;
194
if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
196
switch (view->search_nroff_seq->type)
198
case NROFF_TYPE_BOLD:
199
view->search_numNeedSkipChar = 1 + view->search_nroff_seq->char_width; /* real char width and 0x8 */
201
case NROFF_TYPE_UNDERLINE:
202
view->search_numNeedSkipChar = 2; /* underline symbol and ox8 */
208
return MC_SEARCH_CB_INVALID;
211
lc_byte = search_cb_char_buffer[search_cb_char_curr_index];
212
search_cb_char_curr_index++;
213
return (lc_byte != -1) ? (unsigned char) lc_byte : MC_SEARCH_CB_INVALID;
217
/* --------------------------------------------------------------------------------------------- */
220
mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
222
mcview_t *view = (mcview_t *) user_data;
224
if (char_offset >= (gsize) view->update_activate)
226
view->update_activate += view->update_steps;
229
mcview_percent (view, char_offset);
232
if (tty_got_interrupt ())
233
return MC_SEARCH_CB_ABORT;
235
/* may be in future return from this callback will change current position
236
* in searching block. Now this just constant return value.
238
return MC_SEARCH_CB_OK;
241
/* --------------------------------------------------------------------------------------------- */
244
mcview_do_search (mcview_t * view)
246
off_t search_start = 0;
247
gboolean isFound = FALSE;
248
gboolean need_search_again = TRUE;
256
d = create_message (D_NORMAL, _("Search"), _("Searching %s"), view->last_search_string);
260
/*for avoid infinite search loop we need to increase or decrease start offset of search */
262
if (view->search_start != 0)
264
if (!view->text_nroff_mode)
265
search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
268
if (mcview_search_options.backwards)
270
mcview_nroff_t *nroff;
271
nroff = mcview_nroff_seq_new_num (view, view->search_start);
272
if (mcview_nroff_seq_prev (nroff) != -1)
274
-(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
275
nroff->char_width + 1);
279
mcview_nroff_seq_free (&nroff);
283
search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
285
search_start += view->search_start;
289
if (mcview_search_options.backwards && (int) search_start < 0)
292
/* Compute the percent steps */
293
mcview_search_update_steps (view);
294
view->update_activate = 0;
296
tty_enable_interrupt_key ();
302
if (view->growbuf_in_use)
303
growbufsize = mcview_growbuf_filesize (view);
305
growbufsize = view->search->original_len;
307
if (mcview_find (view, search_start, &match_len))
309
mcview_search_show_result (view, &d, match_len);
310
need_search_again = FALSE;
315
if (view->search->error_str == NULL)
318
search_start = growbufsize - view->search->original_len;
319
if (search_start <= 0)
325
while (mcview_may_still_grow (view));
327
if (view->search_start != 0 && !isFound && need_search_again
328
&& !mcview_search_options.backwards)
332
mcview_update (view);
335
query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
344
if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len))
346
mcview_search_show_result (view, &d, match_len);
350
tty_disable_interrupt_key ();
358
if (!isFound && view->search->error_str != NULL)
359
message (D_NORMAL, _("Search"), "%s", view->search->error_str);
362
mcview_update (view);
365
/* --------------------------------------------------------------------------------------------- */