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