This source file includes following definitions.
- mcview_search_status_update_cb
- mcview_search_update_steps
- mcview_find
- mcview_search_show_result
- mcview_search_init
- mcview_search_deinit
- mcview_search_cmd_callback
- mcview_search_update_cmd_callback
- mcview_do_search
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <config.h>
37
38 #include "lib/global.h"
39 #include "lib/strutil.h"
40 #ifdef HAVE_CHARSET
41 #include "lib/charsets.h"
42 #endif
43 #include "lib/widget.h"
44
45 #include "src/setup.h"
46
47 #include "internal.h"
48
49
50
51 mcview_search_options_t mcview_search_options = {
52 .type = MC_SEARCH_T_NORMAL,
53 .case_sens = FALSE,
54 .backwards = FALSE,
55 .whole_words = FALSE,
56 .all_codepages = FALSE
57 };
58
59
60
61
62
63 typedef struct
64 {
65 simple_status_msg_t status_msg;
66
67 gboolean first;
68 WView *view;
69 off_t offset;
70 } mcview_search_status_msg_t;
71
72
73
74
75
76 static int search_cb_char_curr_index = -1;
77 static char search_cb_char_buffer[6];
78
79
80
81
82
83 static int
84 mcview_search_status_update_cb (status_msg_t *sm)
85 {
86 simple_status_msg_t *ssm = SIMPLE_STATUS_MSG (sm);
87 mcview_search_status_msg_t *vsm = (mcview_search_status_msg_t *) sm;
88 Widget *wd = WIDGET (sm->dlg);
89 int percent = -1;
90
91 if (verbose)
92 percent = mcview_calc_percent (vsm->view, vsm->offset);
93
94 if (percent >= 0)
95 label_set_textv (ssm->label, _("Searching %s: %3d%%"), vsm->view->last_search_string,
96 percent);
97 else
98 label_set_textv (ssm->label, _("Searching %s"), vsm->view->last_search_string);
99
100 if (vsm->first)
101 {
102 Widget *lw = WIDGET (ssm->label);
103 WRect r;
104
105 r = wd->rect;
106 r.cols = MAX (r.cols, lw->rect.cols + 6);
107 widget_set_size_rect (wd, &r);
108 r = lw->rect;
109 r.x = wd->rect.x + (wd->rect.cols - r.cols) / 2;
110 widget_set_size_rect (lw, &r);
111 vsm->first = FALSE;
112 }
113
114 return status_msg_common_update (sm);
115 }
116
117
118
119 static void
120 mcview_search_update_steps (WView *view)
121 {
122 off_t filesize;
123
124 filesize = mcview_get_filesize (view);
125
126 if (filesize != 0)
127 view->update_steps = filesize / 100;
128 else
129 view->update_steps = 40000;
130
131
132 if (view->update_steps < 20000)
133 view->update_steps = 20000;
134
135
136 if (view->update_steps > 40000)
137 view->update_steps = 40000;
138 }
139
140
141
142 static gboolean
143 mcview_find (mcview_search_status_msg_t *ssm, off_t search_start, off_t search_end, gsize *len)
144 {
145 WView *view = ssm->view;
146
147 view->search_numNeedSkipChar = 0;
148 search_cb_char_curr_index = -1;
149
150 if (mcview_search_options.backwards)
151 {
152 search_end = mcview_get_filesize (view);
153 while (search_start >= 0)
154 {
155 gboolean ok;
156
157 view->search_nroff_seq->index = search_start;
158 mcview_nroff_seq_info (view->search_nroff_seq);
159
160 if (search_end > search_start + (off_t) view->search->original.str->len
161 && mc_search_is_fixed_search_str (view->search))
162 search_end = search_start + view->search->original.str->len;
163
164 ok = mc_search_run (view->search, (void *) ssm, search_start, search_end, len);
165 if (ok && view->search->normal_offset == search_start)
166 {
167 if (view->mode_flags.nroff)
168 view->search->normal_offset++;
169 return TRUE;
170 }
171
172
173
174 if (!ok && view->search->error != MC_SEARCH_E_NOTFOUND)
175 return FALSE;
176
177 search_start--;
178 }
179
180 mc_search_set_error (view->search, MC_SEARCH_E_NOTFOUND, "%s", _(STR_E_NOTFOUND));
181 return FALSE;
182 }
183 view->search_nroff_seq->index = search_start;
184 mcview_nroff_seq_info (view->search_nroff_seq);
185
186 return mc_search_run (view->search, (void *) ssm, search_start, search_end, len);
187 }
188
189
190
191 static void
192 mcview_search_show_result (WView *view, size_t match_len)
193 {
194 int nroff_len;
195
196 nroff_len =
197 view->mode_flags.nroff
198 ? mcview__get_nroff_real_len (view, view->search->start_buffer,
199 view->search->normal_offset - view->search->start_buffer) : 0;
200 view->search_start = view->search->normal_offset + nroff_len;
201
202 if (!view->mode_flags.hex)
203 view->search_start++;
204
205 nroff_len =
206 view->mode_flags.nroff ? mcview__get_nroff_real_len (view, view->search_start - 1,
207 match_len) : 0;
208 view->search_end = view->search_start + match_len + nroff_len;
209
210 mcview_moveto_match (view);
211 }
212
213
214
215
216
217 gboolean
218 mcview_search_init (WView *view)
219 {
220 #ifdef HAVE_CHARSET
221 view->search = mc_search_new (view->last_search_string, cp_source);
222 #else
223 view->search = mc_search_new (view->last_search_string, NULL);
224 #endif
225
226 view->search_nroff_seq = mcview_nroff_seq_new (view);
227
228 if (view->search == NULL)
229 return FALSE;
230
231 view->search->search_type = mcview_search_options.type;
232 #ifdef HAVE_CHARSET
233 view->search->is_all_charsets = mcview_search_options.all_codepages;
234 #endif
235 view->search->is_case_sensitive = mcview_search_options.case_sens;
236 view->search->whole_words = mcview_search_options.whole_words;
237 view->search->search_fn = mcview_search_cmd_callback;
238 view->search->update_fn = mcview_search_update_cmd_callback;
239
240 return TRUE;
241 }
242
243
244
245 void
246 mcview_search_deinit (WView *view)
247 {
248 mc_search_free (view->search);
249 g_free (view->last_search_string);
250 mcview_nroff_seq_free (&view->search_nroff_seq);
251 }
252
253
254
255 mc_search_cbret_t
256 mcview_search_cmd_callback (const void *user_data, gsize char_offset, int *current_char)
257 {
258 WView *view = ((const mcview_search_status_msg_t *) user_data)->view;
259
260
261 if (!view->mode_flags.nroff)
262 {
263 mcview_get_byte (view, char_offset, current_char);
264 return MC_SEARCH_CB_OK;
265 }
266
267 if (view->search_numNeedSkipChar != 0)
268 {
269 view->search_numNeedSkipChar--;
270 return MC_SEARCH_CB_SKIP;
271 }
272
273 if (search_cb_char_curr_index == -1
274 || search_cb_char_curr_index >= view->search_nroff_seq->char_length)
275 {
276 if (search_cb_char_curr_index != -1)
277 mcview_nroff_seq_next (view->search_nroff_seq);
278
279 search_cb_char_curr_index = 0;
280 if (view->search_nroff_seq->char_length > 1)
281 g_unichar_to_utf8 (view->search_nroff_seq->current_char, search_cb_char_buffer);
282 else
283 search_cb_char_buffer[0] = (char) view->search_nroff_seq->current_char;
284
285 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
286 {
287 switch (view->search_nroff_seq->type)
288 {
289 case NROFF_TYPE_BOLD:
290 view->search_numNeedSkipChar = 1 + view->search_nroff_seq->char_length;
291 break;
292 case NROFF_TYPE_UNDERLINE:
293 view->search_numNeedSkipChar = 2;
294 break;
295 default:
296 break;
297 }
298 }
299 return MC_SEARCH_CB_INVALID;
300 }
301
302 *current_char = search_cb_char_buffer[search_cb_char_curr_index];
303 search_cb_char_curr_index++;
304
305 return (*current_char != -1) ? MC_SEARCH_CB_OK : MC_SEARCH_CB_INVALID;
306 }
307
308
309
310 mc_search_cbret_t
311 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
312 {
313 status_msg_t *sm = STATUS_MSG (user_data);
314 mcview_search_status_msg_t *vsm = (mcview_search_status_msg_t *) user_data;
315 WView *view = vsm->view;
316 gboolean do_update = FALSE;
317 mc_search_cbret_t result = MC_SEARCH_CB_OK;
318
319 vsm->offset = (off_t) char_offset;
320
321 if (mcview_search_options.backwards)
322 {
323 if (vsm->offset <= view->update_activate)
324 {
325 view->update_activate -= view->update_steps;
326
327 do_update = TRUE;
328 }
329 }
330 else
331 {
332 if (vsm->offset >= view->update_activate)
333 {
334 view->update_activate += view->update_steps;
335
336 do_update = TRUE;
337 }
338 }
339
340 if (do_update && sm->update (sm) == B_CANCEL)
341 result = MC_SEARCH_CB_ABORT;
342
343
344
345 return result;
346 }
347
348
349
350 void
351 mcview_do_search (WView *view, off_t want_search_start)
352 {
353 mcview_search_status_msg_t vsm;
354
355 off_t search_start = 0;
356 off_t orig_search_start = view->search_start;
357 gboolean found = FALSE;
358
359 size_t match_len;
360
361 view->search_start = want_search_start;
362
363
364 if (view->search_start != 0)
365 {
366 if (!view->mode_flags.nroff)
367 search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
368 else
369 {
370 if (mcview_search_options.backwards)
371 {
372 mcview_nroff_t *nroff;
373
374 nroff = mcview_nroff_seq_new_num (view, view->search_start);
375 if (mcview_nroff_seq_prev (nroff) != -1)
376 search_start =
377 -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
378 nroff->char_length + 1);
379 else
380 search_start = -2;
381
382 mcview_nroff_seq_free (&nroff);
383 }
384 else
385 {
386 search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
387 }
388 search_start += view->search_start;
389 }
390 }
391
392 if (mcview_search_options.backwards && search_start < 0)
393 search_start = 0;
394
395
396 mcview_search_update_steps (view);
397
398 view->update_activate = search_start;
399
400 vsm.first = TRUE;
401 vsm.view = view;
402 vsm.offset = search_start;
403
404 status_msg_init (STATUS_MSG (&vsm), _("Search"), 1.0, simple_status_msg_init_cb,
405 mcview_search_status_update_cb, NULL);
406
407 do
408 {
409 off_t growbufsize;
410
411 if (view->growbuf_in_use)
412 growbufsize = mcview_growbuf_filesize (view);
413 else
414 growbufsize = view->search->original.str->len;
415
416 if (mcview_find (&vsm, search_start, mcview_get_filesize (view), &match_len))
417 {
418 mcview_search_show_result (view, match_len);
419 found = TRUE;
420 break;
421 }
422
423
424
425
426
427 if (view->search->error != MC_SEARCH_E_NOTFOUND)
428 break;
429
430 search_start = growbufsize - view->search->original.str->len;
431 }
432 while (search_start > 0 && mcview_may_still_grow (view));
433
434
435 if (view->growbuf_in_use && !found && view->search->error == MC_SEARCH_E_NOTFOUND
436 && !mcview_search_options.backwards
437 && mcview_find (&vsm, search_start, mcview_get_filesize (view), &match_len))
438 {
439 mcview_search_show_result (view, match_len);
440 found = TRUE;
441 }
442
443 status_msg_deinit (STATUS_MSG (&vsm));
444
445 if (orig_search_start != 0 && (!found && view->search->error == MC_SEARCH_E_NOTFOUND)
446 && !mcview_search_options.backwards)
447 {
448 view->search_start = orig_search_start;
449 mcview_update (view);
450
451 if (query_dialog
452 (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
453 _("&No")) != 0)
454 found = TRUE;
455 else
456 {
457
458 view->update_activate = 0;
459
460 vsm.first = TRUE;
461 vsm.view = view;
462 vsm.offset = 0;
463
464 status_msg_init (STATUS_MSG (&vsm), _("Search"), 1.0, simple_status_msg_init_cb,
465 mcview_search_status_update_cb, NULL);
466
467
468 if (mcview_find (&vsm, 0, orig_search_start, &match_len))
469 {
470 mcview_search_show_result (view, match_len);
471 found = TRUE;
472 }
473
474 status_msg_deinit (STATUS_MSG (&vsm));
475 }
476 }
477
478 if (!found)
479 {
480 view->search_start = orig_search_start;
481 mcview_update (view);
482
483 if (view->search->error == MC_SEARCH_E_NOTFOUND)
484 query_dialog (_("Search"), _(STR_E_NOTFOUND), D_NORMAL, 1, _("&Dismiss"));
485 else if (view->search->error_str != NULL)
486 query_dialog (_("Search"), view->search->error_str, D_NORMAL, 1, _("&Dismiss"));
487 }
488 view->dirty++;
489 }
490
491