This source file includes following definitions.
- mcview_search_status_update_cb
- mcview_calculate_start_of_previous_line
- mcview_search_update_steps
- mcview_find
- mcview_search_show_result
- mcview_do_search
- mcview_search_init
- mcview_search_deinit
- mcview_search_cmd_callback
- mcview_search_update_cmd_callback
- mcview_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 inline off_t
120 mcview_calculate_start_of_previous_line (WView *view, const off_t current_pos)
121 {
122 const off_t bol = mcview_bol (view, current_pos, 0);
123
124
125 if (bol == 0)
126 return (-1);
127
128 return mcview_bol (view, bol - 1, 0);
129 }
130
131
132
133 static void
134 mcview_search_update_steps (WView *view)
135 {
136 off_t filesize;
137
138 filesize = mcview_get_filesize (view);
139
140 if (filesize != 0)
141 view->update_steps = filesize / 100;
142 else
143 view->update_steps = 40000;
144
145
146 if (view->update_steps < 20000)
147 view->update_steps = 20000;
148
149
150 if (view->update_steps > 40000)
151 view->update_steps = 40000;
152 }
153
154
155
156 static gboolean
157 mcview_find (mcview_search_status_msg_t *ssm, off_t search_start, off_t search_end, gsize *len)
158 {
159 WView *view = ssm->view;
160
161 view->search_numNeedSkipChar = 0;
162 search_cb_char_curr_index = -1;
163
164 if (mcview_search_options.backwards)
165 {
166 search_end = mcview_get_filesize (view);
167
168 if ((view->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
169 search_start = mcview_bol (view, search_start, 0);
170
171 while (search_start >= 0)
172 {
173 gboolean ok;
174
175 view->search_nroff_seq->index = search_start;
176 mcview_nroff_seq_info (view->search_nroff_seq);
177
178 if (search_end > search_start + (off_t) view->search->original.str->len
179 && mc_search_is_fixed_search_str (view->search))
180 search_end = search_start + view->search->original.str->len;
181
182 ok = mc_search_run (view->search, (void *) ssm, search_start, search_end, len);
183 if (ok && view->search->normal_offset == search_start)
184 {
185 if (view->mode_flags.nroff)
186 view->search->normal_offset++;
187 return TRUE;
188 }
189
190
191
192 if (!ok && view->search->error != MC_SEARCH_E_NOTFOUND)
193 return FALSE;
194
195 if ((view->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
196 search_start = mcview_calculate_start_of_previous_line (view, search_start);
197 else
198 search_start--;
199 }
200
201 mc_search_set_error (view->search, MC_SEARCH_E_NOTFOUND, "%s", _(STR_E_NOTFOUND));
202 return FALSE;
203 }
204
205 if ((view->search_line_type & MC_SEARCH_LINE_BEGIN) != 0 && search_start != 0)
206 search_start = mcview_eol (view, search_start);
207
208 view->search_nroff_seq->index = search_start;
209 mcview_nroff_seq_info (view->search_nroff_seq);
210
211 return mc_search_run (view->search, (void *) ssm, search_start, search_end, len);
212 }
213
214
215
216 static void
217 mcview_search_show_result (WView *view, size_t match_len)
218 {
219 int nroff_len;
220
221 nroff_len =
222 view->mode_flags.nroff
223 ? mcview__get_nroff_real_len (view, view->search->start_buffer,
224 view->search->normal_offset - view->search->start_buffer) : 0;
225 view->search_start = view->search->normal_offset + nroff_len;
226
227 if (!view->mode_flags.hex)
228 view->search_start++;
229
230 nroff_len =
231 view->mode_flags.nroff ? mcview__get_nroff_real_len (view, view->search_start - 1,
232 match_len) : 0;
233 view->search_end = view->search_start + match_len + nroff_len;
234
235 mcview_moveto_match (view);
236 }
237
238
239
240 static void
241 mcview_do_search (WView *view, off_t want_search_start)
242 {
243 mcview_search_status_msg_t vsm;
244
245 off_t search_start = 0;
246 off_t orig_search_start = view->search_start;
247 gboolean found = FALSE;
248
249 size_t match_len;
250
251 view->search_start = want_search_start;
252
253
254 if (view->search_start != 0)
255 {
256 if (!view->mode_flags.nroff)
257 search_start = view->search_start + (mcview_search_options.backwards ? -2 : 0);
258 else
259 {
260 if (mcview_search_options.backwards)
261 {
262 mcview_nroff_t *nroff;
263
264 nroff = mcview_nroff_seq_new_num (view, view->search_start);
265 if (mcview_nroff_seq_prev (nroff) != -1)
266 search_start =
267 -(mcview__get_nroff_real_len (view, nroff->index - 1, 2) +
268 nroff->char_length + 1);
269 else
270 search_start = -2;
271
272 mcview_nroff_seq_free (&nroff);
273 }
274 else
275 {
276 search_start = mcview__get_nroff_real_len (view, view->search_start + 1, 2);
277 }
278 search_start += view->search_start;
279 }
280 }
281
282 if (mcview_search_options.backwards && search_start < 0)
283 search_start = 0;
284
285
286 mcview_search_update_steps (view);
287
288 view->update_activate = search_start;
289
290 vsm.first = TRUE;
291 vsm.view = view;
292 vsm.offset = search_start;
293
294 status_msg_init (STATUS_MSG (&vsm), _("Search"), 1.0, simple_status_msg_init_cb,
295 mcview_search_status_update_cb, NULL);
296
297 do
298 {
299 off_t growbufsize;
300
301 if (view->growbuf_in_use)
302 growbufsize = mcview_growbuf_filesize (view);
303 else
304 growbufsize = view->search->original.str->len;
305
306 if (mcview_find (&vsm, search_start, mcview_get_filesize (view), &match_len))
307 {
308 mcview_search_show_result (view, match_len);
309 found = TRUE;
310 break;
311 }
312
313
314
315
316
317 if (view->search->error != MC_SEARCH_E_NOTFOUND)
318 break;
319
320 search_start = growbufsize - view->search->original.str->len;
321 }
322 while (search_start > 0 && mcview_may_still_grow (view));
323
324
325 if (view->growbuf_in_use && !found && view->search->error == MC_SEARCH_E_NOTFOUND
326 && !mcview_search_options.backwards
327 && mcview_find (&vsm, search_start, mcview_get_filesize (view), &match_len))
328 {
329 mcview_search_show_result (view, match_len);
330 found = TRUE;
331 }
332
333 status_msg_deinit (STATUS_MSG (&vsm));
334
335 if (orig_search_start != 0 && (!found && view->search->error == MC_SEARCH_E_NOTFOUND)
336 && !mcview_search_options.backwards)
337 {
338 view->search_start = orig_search_start;
339 mcview_update (view);
340
341 if (query_dialog
342 (_("Search done"), _("Continue from beginning?"), D_NORMAL, 2, _("&Yes"),
343 _("&No")) != 0)
344 found = TRUE;
345 else
346 {
347
348 view->update_activate = 0;
349
350 vsm.first = TRUE;
351 vsm.view = view;
352 vsm.offset = 0;
353
354 status_msg_init (STATUS_MSG (&vsm), _("Search"), 1.0, simple_status_msg_init_cb,
355 mcview_search_status_update_cb, NULL);
356
357
358 if (mcview_find (&vsm, 0, orig_search_start, &match_len))
359 {
360 mcview_search_show_result (view, match_len);
361 found = TRUE;
362 }
363
364 status_msg_deinit (STATUS_MSG (&vsm));
365 }
366 }
367
368 if (!found)
369 {
370 view->search_start = orig_search_start;
371 mcview_update (view);
372
373 if (view->search->error == MC_SEARCH_E_NOTFOUND)
374 query_dialog (_("Search"), _(STR_E_NOTFOUND), D_NORMAL, 1, _("&Dismiss"));
375 else if (view->search->error_str != NULL)
376 query_dialog (_("Search"), view->search->error_str, D_NORMAL, 1, _("&Dismiss"));
377 }
378
379 view->dirty++;
380 }
381
382
383
384
385
386 gboolean
387 mcview_search_init (WView *view)
388 {
389 #ifdef HAVE_CHARSET
390 view->search = mc_search_new (view->last_search_string, cp_source);
391 #else
392 view->search = mc_search_new (view->last_search_string, NULL);
393 #endif
394
395 view->search_nroff_seq = mcview_nroff_seq_new (view);
396
397 if (view->search == NULL)
398 return FALSE;
399
400 view->search->search_type = mcview_search_options.type;
401 #ifdef HAVE_CHARSET
402 view->search->is_all_charsets = mcview_search_options.all_codepages;
403 #endif
404 view->search->is_case_sensitive = mcview_search_options.case_sens;
405 view->search->whole_words = mcview_search_options.whole_words;
406 view->search->search_fn = mcview_search_cmd_callback;
407 view->search->update_fn = mcview_search_update_cmd_callback;
408
409 view->search_line_type = mc_search_get_line_type (view->search);
410
411 return TRUE;
412 }
413
414
415
416 void
417 mcview_search_deinit (WView *view)
418 {
419 mc_search_free (view->search);
420 g_free (view->last_search_string);
421 mcview_nroff_seq_free (&view->search_nroff_seq);
422 }
423
424
425
426 mc_search_cbret_t
427 mcview_search_cmd_callback (const void *user_data, gsize char_offset, int *current_char)
428 {
429 WView *view = ((const mcview_search_status_msg_t *) user_data)->view;
430
431
432 if (!view->mode_flags.nroff)
433 {
434 mcview_get_byte (view, char_offset, current_char);
435 return MC_SEARCH_CB_OK;
436 }
437
438 if (view->search_numNeedSkipChar != 0)
439 {
440 view->search_numNeedSkipChar--;
441 return MC_SEARCH_CB_SKIP;
442 }
443
444 if (search_cb_char_curr_index == -1
445 || search_cb_char_curr_index >= view->search_nroff_seq->char_length)
446 {
447 if (search_cb_char_curr_index != -1)
448 mcview_nroff_seq_next (view->search_nroff_seq);
449
450 search_cb_char_curr_index = 0;
451 if (view->search_nroff_seq->char_length > 1)
452 g_unichar_to_utf8 (view->search_nroff_seq->current_char, search_cb_char_buffer);
453 else
454 search_cb_char_buffer[0] = (char) view->search_nroff_seq->current_char;
455
456 if (view->search_nroff_seq->type != NROFF_TYPE_NONE)
457 {
458 switch (view->search_nroff_seq->type)
459 {
460 case NROFF_TYPE_BOLD:
461 view->search_numNeedSkipChar = 1 + view->search_nroff_seq->char_length;
462 break;
463 case NROFF_TYPE_UNDERLINE:
464 view->search_numNeedSkipChar = 2;
465 break;
466 default:
467 break;
468 }
469 }
470 return MC_SEARCH_CB_INVALID;
471 }
472
473 *current_char = search_cb_char_buffer[search_cb_char_curr_index];
474 search_cb_char_curr_index++;
475
476 return (*current_char != -1) ? MC_SEARCH_CB_OK : MC_SEARCH_CB_INVALID;
477 }
478
479
480
481 mc_search_cbret_t
482 mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
483 {
484 status_msg_t *sm = STATUS_MSG (user_data);
485 mcview_search_status_msg_t *vsm = (mcview_search_status_msg_t *) user_data;
486 WView *view = vsm->view;
487 gboolean do_update = FALSE;
488 mc_search_cbret_t result = MC_SEARCH_CB_OK;
489
490 vsm->offset = (off_t) char_offset;
491
492 if (mcview_search_options.backwards)
493 {
494 if (vsm->offset <= view->update_activate)
495 {
496 view->update_activate -= view->update_steps;
497
498 do_update = TRUE;
499 }
500 }
501 else
502 {
503 if (vsm->offset >= view->update_activate)
504 {
505 view->update_activate += view->update_steps;
506
507 do_update = TRUE;
508 }
509 }
510
511 if (do_update && sm->update (sm) == B_CANCEL)
512 result = MC_SEARCH_CB_ABORT;
513
514
515
516 return result;
517 }
518
519
520
521
522 void
523 mcview_search (WView *view, gboolean start_search)
524 {
525 off_t want_search_start = view->search_start;
526
527 if (start_search)
528 {
529 if (mcview_dialog_search (view))
530 {
531 if (view->mode_flags.hex)
532 want_search_start = view->hex_cursor;
533
534 mcview_do_search (view, want_search_start);
535 }
536 }
537 else
538 {
539 if (view->mode_flags.hex)
540 {
541 if (!mcview_search_options.backwards)
542 want_search_start = view->hex_cursor + 1;
543 else if (view->hex_cursor > 0)
544 want_search_start = view->hex_cursor - 1;
545 else
546 want_search_start = 0;
547 }
548
549 mcview_do_search (view, want_search_start);
550 }
551 }
552
553