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 /* --------------------------------------------------------------------------------------------- */