2 Internal file viewer for the Midnight Commander
3 Function for search data
5 Copyright (C) 1994-2016
6 Free Software Foundation, Inc.
9 Miguel de Icaza, 1994, 1995, 1998
10 Janne Kukonlehto, 1994, 1995
12 Joseph M. Hinkle, 1996
15 Roland Illig <roland.illig@gmx.de>, 2004, 2005
16 Slava Zanko <slavazanko@google.com>, 2009
17 Andrew Borodin <aborodin@vmail.ru>, 2009, 2013
18 Ilia Maslakov <il.smind@gmail.com>, 2009
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 3 of the License,
25 or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU 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, see <http://www.gnu.org/licenses/>.
38 #include "lib/global.h"
39 #include "lib/strutil.h"
40 #include "lib/widget.h"
42 #include "src/setup.h"
46 /*** global variables ****************************************************************************/
48 /*** file scope macro definitions ****************************************************************/
50 /*** file scope type declarations ****************************************************************/
54 simple_status_msg_t status_msg
; /* base class */
59 } mcview_search_status_msg_t
;
61 /*** file scope variables ************************************************************************/
63 static int search_cb_char_curr_index
= -1;
64 static char search_cb_char_buffer
[6];
66 /* --------------------------------------------------------------------------------------------- */
67 /*** file scope functions ************************************************************************/
68 /* --------------------------------------------------------------------------------------------- */
71 mcview_search_status_update_cb (status_msg_t
* sm
)
73 simple_status_msg_t
*ssm
= SIMPLE_STATUS_MSG (sm
);
74 mcview_search_status_msg_t
*vsm
= (mcview_search_status_msg_t
*) sm
;
75 Widget
*wd
= WIDGET (sm
->dlg
);
79 percent
= mcview_calc_percent (vsm
->view
, vsm
->offset
);
82 label_set_textv (ssm
->label
, _("Searching %s: %3d%%"), vsm
->view
->last_search_string
,
85 label_set_textv (ssm
->label
, _("Searching %s"), vsm
->view
->last_search_string
);
90 Widget
*lw
= WIDGET (ssm
->label
);
92 wd_width
= max (wd
->cols
, lw
->cols
+ 6);
93 widget_set_size (wd
, wd
->y
, wd
->x
, wd
->lines
, wd_width
);
94 widget_set_size (lw
, lw
->y
, wd
->x
+ (wd
->cols
- lw
->cols
) / 2, lw
->lines
, lw
->cols
);
98 return status_msg_common_update (sm
);
101 /* --------------------------------------------------------------------------------------------- */
104 mcview_search_update_steps (WView
* view
)
106 off_t filesize
= mcview_get_filesize (view
);
108 view
->update_steps
= 40000;
109 else /* viewing a data stream, not a file */
110 view
->update_steps
= filesize
/ 100;
112 /* Do not update the percent display but every 20 ks */
113 if (view
->update_steps
< 20000)
114 view
->update_steps
= 20000;
117 /* --------------------------------------------------------------------------------------------- */
120 mcview_find (mcview_search_status_msg_t
* ssm
, off_t search_start
, off_t search_end
, gsize
* len
)
122 WView
*view
= ssm
->view
;
124 view
->search_numNeedSkipChar
= 0;
125 search_cb_char_curr_index
= -1;
127 if (mcview_search_options
.backwards
)
129 search_end
= mcview_get_filesize (view
);
130 while (search_start
>= 0)
132 view
->search_nroff_seq
->index
= search_start
;
133 mcview_nroff_seq_info (view
->search_nroff_seq
);
135 if (search_end
> search_start
+ (off_t
) view
->search
->original_len
136 && mc_search_is_fixed_search_str (view
->search
))
137 search_end
= search_start
+ view
->search
->original_len
;
139 if (mc_search_run (view
->search
, (void *) ssm
, search_start
, search_end
, len
)
140 && view
->search
->normal_offset
== search_start
)
142 if (view
->text_nroff_mode
)
143 view
->search
->normal_offset
++;
149 view
->search
->error_str
= g_strdup (_(STR_E_NOTFOUND
));
152 view
->search_nroff_seq
->index
= search_start
;
153 mcview_nroff_seq_info (view
->search_nroff_seq
);
155 return mc_search_run (view
->search
, (void *) ssm
, search_start
, search_end
, len
);
158 /* --------------------------------------------------------------------------------------------- */
161 mcview_search_show_result (WView
* view
, size_t match_len
)
166 view
->text_nroff_mode
167 ? mcview__get_nroff_real_len (view
, view
->search
->start_buffer
,
168 view
->search
->normal_offset
- view
->search
->start_buffer
) : 0;
169 view
->search_start
= view
->search
->normal_offset
+ nroff_len
;
172 view
->search_start
++;
175 view
->text_nroff_mode
? mcview__get_nroff_real_len (view
, view
->search_start
- 1,
177 view
->search_end
= view
->search_start
+ match_len
+ nroff_len
;
179 mcview_moveto_match (view
);
182 /* --------------------------------------------------------------------------------------------- */
183 /*** public functions ****************************************************************************/
184 /* --------------------------------------------------------------------------------------------- */
187 mcview_search_cmd_callback (const void *user_data
, gsize char_offset
, int *current_char
)
189 WView
*view
= ((const mcview_search_status_msg_t
*) user_data
)->view
;
191 /* view_read_continue (view, &view->search_onechar_info); *//* AB:FIXME */
192 if (!view
->text_nroff_mode
)
194 mcview_get_byte (view
, char_offset
, current_char
);
195 return MC_SEARCH_CB_OK
;
198 if (view
->search_numNeedSkipChar
!= 0)
200 view
->search_numNeedSkipChar
--;
201 return MC_SEARCH_CB_SKIP
;
204 if (search_cb_char_curr_index
== -1
205 || search_cb_char_curr_index
>= view
->search_nroff_seq
->char_length
)
207 if (search_cb_char_curr_index
!= -1)
208 mcview_nroff_seq_next (view
->search_nroff_seq
);
210 search_cb_char_curr_index
= 0;
211 if (view
->search_nroff_seq
->char_length
> 1)
212 g_unichar_to_utf8 (view
->search_nroff_seq
->current_char
, search_cb_char_buffer
);
214 search_cb_char_buffer
[0] = (char) view
->search_nroff_seq
->current_char
;
216 if (view
->search_nroff_seq
->type
!= NROFF_TYPE_NONE
)
218 switch (view
->search_nroff_seq
->type
)
220 case NROFF_TYPE_BOLD
:
221 view
->search_numNeedSkipChar
= 1 + view
->search_nroff_seq
->char_length
; /* real char length and 0x8 */
223 case NROFF_TYPE_UNDERLINE
:
224 view
->search_numNeedSkipChar
= 2; /* underline symbol and ox8 */
230 return MC_SEARCH_CB_INVALID
;
233 *current_char
= search_cb_char_buffer
[search_cb_char_curr_index
];
234 search_cb_char_curr_index
++;
236 return (*current_char
!= -1) ? MC_SEARCH_CB_OK
: MC_SEARCH_CB_INVALID
;
239 /* --------------------------------------------------------------------------------------------- */
242 mcview_search_update_cmd_callback (const void *user_data
, gsize char_offset
)
244 status_msg_t
*sm
= STATUS_MSG (user_data
);
245 mcview_search_status_msg_t
*vsm
= (mcview_search_status_msg_t
*) user_data
;
246 mc_search_cbret_t result
= MC_SEARCH_CB_OK
;
248 vsm
->offset
= (off_t
) char_offset
;
249 if (vsm
->offset
>= vsm
->view
->update_activate
)
251 vsm
->view
->update_activate
+= vsm
->view
->update_steps
;
253 if (sm
->update (sm
) == B_CANCEL
)
254 result
= MC_SEARCH_CB_ABORT
;
257 /* may be in future return from this callback will change current position in searching block. */
262 /* --------------------------------------------------------------------------------------------- */
265 mcview_do_search (WView
* view
, off_t want_search_start
)
267 mcview_search_status_msg_t vsm
;
269 off_t search_start
= 0;
270 off_t orig_search_start
= view
->search_start
;
271 gboolean found
= FALSE
;
275 view
->search_start
= want_search_start
;
276 /* for avoid infinite search loop we need to increase or decrease start offset of search */
278 if (view
->search_start
!= 0)
280 if (!view
->text_nroff_mode
)
281 search_start
= view
->search_start
+ (mcview_search_options
.backwards
? -2 : 0);
284 if (mcview_search_options
.backwards
)
286 mcview_nroff_t
*nroff
;
288 nroff
= mcview_nroff_seq_new_num (view
, view
->search_start
);
289 if (mcview_nroff_seq_prev (nroff
) != -1)
291 -(mcview__get_nroff_real_len (view
, nroff
->index
- 1, 2) +
292 nroff
->char_length
+ 1);
296 mcview_nroff_seq_free (&nroff
);
300 search_start
= mcview__get_nroff_real_len (view
, view
->search_start
+ 1, 2);
302 search_start
+= view
->search_start
;
306 if (mcview_search_options
.backwards
&& search_start
< 0)
309 /* Compute the percent steps */
310 mcview_search_update_steps (view
);
312 view
->update_activate
= search_start
;
316 vsm
.offset
= search_start
;
318 status_msg_init (STATUS_MSG (&vsm
), _("Search"), 1.0, simple_status_msg_init_cb
,
319 mcview_search_status_update_cb
, NULL
);
325 if (view
->growbuf_in_use
)
326 growbufsize
= mcview_growbuf_filesize (view
);
328 growbufsize
= view
->search
->original_len
;
330 if (mcview_find (&vsm
, search_start
, mcview_get_filesize (view
), &match_len
))
332 mcview_search_show_result (view
, match_len
);
337 if (view
->search
->error_str
== NULL
)
340 search_start
= growbufsize
- view
->search
->original_len
;
342 while (search_start
> 0 && mcview_may_still_grow (view
));
344 status_msg_deinit (STATUS_MSG (&vsm
));
346 if (orig_search_start
!= 0 && !found
&& !mcview_search_options
.backwards
)
348 view
->search_start
= orig_search_start
;
349 mcview_update (view
);
352 (_("Search done"), _("Continue from beginning?"), D_NORMAL
, 2, _("&Yes"),
357 /* continue search from beginning */
358 view
->update_activate
= 0;
364 status_msg_init (STATUS_MSG (&vsm
), _("Search"), 1.0, simple_status_msg_init_cb
,
365 mcview_search_status_update_cb
, NULL
);
367 /* search from file begin up to initial search start position */
368 if (mcview_find (&vsm
, 0, orig_search_start
, &match_len
))
370 mcview_search_show_result (view
, match_len
);
374 status_msg_deinit (STATUS_MSG (&vsm
));
378 if (!found
&& view
->search
->error_str
!= NULL
)
380 view
->search_start
= orig_search_start
;
381 mcview_update (view
);
382 query_dialog (_("Search"), view
->search
->error_str
, D_NORMAL
, 1, _("&Dismiss"));
387 /* --------------------------------------------------------------------------------------------- */