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
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,
40 #include "lib/global.h"
41 #include "lib/tty/tty.h"
42 #include "lib/widget.h"
44 #include "src/setup.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 /* --------------------------------------------------------------------------------------------- */
63 mcview_search_update_steps (mcview_t
* view
)
65 off_t filesize
= mcview_get_filesize (view
);
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 /* --------------------------------------------------------------------------------------------- */
79 mcview_find (mcview_t
* view
, gsize search_start
, gsize
* len
)
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
)
104 view
->search
->error_str
= g_strdup (_("Search string not found"));
107 view
->search_nroff_seq
->index
= search_start
;
108 mcview_nroff_seq_info (view
->search_nroff_seq
);
110 return mc_search_run (view
->search
, (void *) view
, search_start
, mcview_get_filesize (view
),
114 /* --------------------------------------------------------------------------------------------- */
117 mcview_search_show_result (mcview_t
* view
, Dlg_head
** d
, size_t match_len
)
120 view
->search_start
= view
->search
->normal_offset
+
121 mcview__get_nroff_real_len (view
,
122 view
->search
->start_buffer
,
123 view
->search
->normal_offset
- view
->search
->start_buffer
);
126 view
->search_start
++;
128 view
->search_end
= view
->search_start
+ match_len
+
129 mcview__get_nroff_real_len (view
, view
->search_start
- 1, match_len
);
133 view
->hex_cursor
= view
->search_start
;
134 view
->hexedit_lownibble
= FALSE
;
135 view
->dpy_start
= view
->search_start
- view
->search_start
% view
->bytes_per_line
;
136 view
->dpy_end
= view
->search_end
- view
->search_end
% view
->bytes_per_line
;
143 *d
= create_message (D_NORMAL
, _("Search"), _("Seeking to search result"));
146 mcview_moveto_match (view
);
150 /* --------------------------------------------------------------------------------------------- */
151 /*** public functions ****************************************************************************/
152 /* --------------------------------------------------------------------------------------------- */
155 mcview_search_cmd_callback (const void *user_data
, gsize char_offset
)
158 mcview_t
*view
= (mcview_t
*) user_data
;
160 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
161 if (!view
->text_nroff_mode
)
163 if (!mcview_get_byte (view
, char_offset
, &lc_byte
))
164 return MC_SEARCH_CB_INVALID
;
169 if (view
->search_numNeedSkipChar
)
171 view
->search_numNeedSkipChar
--;
172 return MC_SEARCH_CB_SKIP
;
175 if (search_cb_char_curr_index
== -1)
177 search_cb_char_curr_index
= 0;
178 if (view
->search_nroff_seq
->char_width
> 1)
179 g_unichar_to_utf8 (view
->search_nroff_seq
->current_char
, search_cb_char_buffer
);
181 search_cb_char_buffer
[0] = (char) view
->search_nroff_seq
->current_char
;
184 if (search_cb_char_curr_index
< view
->search_nroff_seq
->char_width
)
186 lc_byte
= search_cb_char_buffer
[search_cb_char_curr_index
];
187 search_cb_char_curr_index
++;
189 return (lc_byte
!= -1) ? lc_byte
: MC_SEARCH_CB_INVALID
;
192 mcview_nroff_seq_next (view
->search_nroff_seq
);
193 search_cb_char_curr_index
= 0;
194 if (view
->search_nroff_seq
->char_width
> 1)
195 g_unichar_to_utf8 (view
->search_nroff_seq
->current_char
, search_cb_char_buffer
);
197 search_cb_char_buffer
[0] = (char) view
->search_nroff_seq
->current_char
;
199 if (view
->search_nroff_seq
->type
!= NROFF_TYPE_NONE
)
200 view
->search_numNeedSkipChar
= 1 + view
->search_nroff_seq
->char_width
;
202 return MC_SEARCH_CB_SKIP
;
205 /* --------------------------------------------------------------------------------------------- */
208 mcview_search_update_cmd_callback (const void *user_data
, gsize char_offset
)
210 mcview_t
*view
= (mcview_t
*) user_data
;
212 if (char_offset
>= (gsize
) view
->update_activate
)
214 view
->update_activate
+= view
->update_steps
;
217 mcview_percent (view
, char_offset
);
220 if (tty_got_interrupt ())
221 return MC_SEARCH_CB_ABORT
;
223 /* may be in future return from this callback will change current position
224 * in searching block. Now this just constant return value.
226 return MC_SEARCH_CB_OK
;
229 /* --------------------------------------------------------------------------------------------- */
232 mcview_do_search (mcview_t
* view
)
234 off_t search_start
= 0;
235 gboolean isFound
= FALSE
;
236 gboolean need_search_again
= TRUE
;
244 d
= create_message (D_NORMAL
, _("Search"), _("Searching %s"), view
->last_search_string
);
248 /*for avoid infinite search loop we need to increase or decrease start offset of search */
250 if (view
->search_start
!= 0)
252 int nroff_real_len
= mcview__get_nroff_real_len (view
, view
->search_start
+ 1, 2);
253 search_start
= mcview_search_options
.backwards
? -2 : nroff_real_len
!= 0 ? 2 : 0;
254 search_start
+= view
->search_start
+ nroff_real_len
* search_start
;
257 if (mcview_search_options
.backwards
&& (int) search_start
< 0)
260 /* Compute the percent steps */
261 mcview_search_update_steps (view
);
262 view
->update_activate
= 0;
264 tty_enable_interrupt_key ();
270 if (view
->growbuf_in_use
)
271 growbufsize
= mcview_growbuf_filesize (view
);
273 growbufsize
= view
->search
->original_len
;
275 if (mcview_find (view
, search_start
, &match_len
))
277 mcview_search_show_result (view
, &d
, match_len
);
278 need_search_again
= FALSE
;
283 if (view
->search
->error_str
== NULL
)
286 search_start
= growbufsize
- view
->search
->original_len
;
287 if (search_start
<= 0)
293 while (mcview_may_still_grow (view
));
295 if (view
->search_start
!= 0 && !isFound
&& need_search_again
296 && !mcview_search_options
.backwards
)
300 mcview_update (view
);
303 query_dialog (_("Search done"), _("Continue from beginning?"), D_NORMAL
, 2, _("&Yes"),
312 if (!isFound
&& view
->search
->error_str
!= NULL
&& mcview_find (view
, search_start
, &match_len
))
314 mcview_search_show_result (view
, &d
, match_len
);
318 if (!isFound
&& view
->search
->error_str
!= NULL
)
319 message (D_NORMAL
, _("Search"), "%s", view
->search
->error_str
);
322 mcview_update (view
);
324 tty_disable_interrupt_key ();
332 /* --------------------------------------------------------------------------------------------- */