This source file includes following definitions.
- edit_dialog_search_show
- edit_search_get_current_end_line_char
- edit_calculate_start_of_next_line
- edit_calculate_end_of_previous_line
- edit_calculate_start_of_previous_line
- edit_calculate_start_of_current_line
- edit_search_fix_search_start_if_selection
- edit_find
- edit_replace_cmd__conv_to_display
- edit_replace_cmd__conv_to_input
- edit_search_show_error
- edit_do_search
- edit_search
- edit_search_init
- edit_search_deinit
- edit_search_cmd_callback
- edit_search_update_callback
- edit_search_status_update_cb
- edit_search_cmd
- edit_dialog_replace_show
- edit_dialog_replace_prompt_show
- edit_replace_cmd
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 #include <config.h>
27
28 #include <assert.h>
29
30 #include "lib/global.h"
31 #include "lib/search.h"
32 #include "lib/mcconfig.h"
33 #ifdef HAVE_CHARSET
34 #include "lib/charsets.h"
35 #endif
36 #include "lib/util.h"
37 #include "lib/widget.h"
38 #include "lib/skin.h"
39
40 #include "src/history.h"
41 #include "src/setup.h"
42
43 #include "edit-impl.h"
44 #include "editwidget.h"
45
46 #include "editsearch.h"
47
48
49
50 edit_search_options_t edit_search_options = {
51 .type = MC_SEARCH_T_NORMAL,
52 .case_sens = FALSE,
53 .backwards = FALSE,
54 .only_in_selection = FALSE,
55 .whole_words = FALSE,
56 .all_codepages = FALSE,
57 };
58
59
60
61
62
63
64
65 MC_MOCKABLE void edit_dialog_replace_show (WEdit *edit, const char *search_default,
66 const char *replace_default, char **search_text,
67 char **replace_text);
68
69 MC_MOCKABLE int edit_dialog_replace_prompt_show (WEdit *edit, char *from_text, char *to_text,
70 int xpos, int ypos);
71
72
73
74
75
76
77
78 static gboolean
79 edit_dialog_search_show (WEdit *edit)
80 {
81 char *search_text = NULL;
82 size_t num_of_types = 0;
83 gchar **list_of_types;
84 int dialog_result;
85
86 list_of_types = mc_search_get_types_strings_array (&num_of_types);
87
88 {
89 quick_widget_t quick_widgets[] = {
90
91 QUICK_LABELED_INPUT (N_ ("Enter search string:"), input_label_above, INPUT_LAST_TEXT,
92 MC_HISTORY_SHARED_SEARCH, &search_text, NULL, FALSE, FALSE,
93 INPUT_COMPLETE_NONE),
94 QUICK_SEPARATOR (TRUE),
95 QUICK_START_COLUMNS,
96 QUICK_RADIO (num_of_types, (const char **) list_of_types,
97 (int *) &edit_search_options.type, NULL),
98 QUICK_NEXT_COLUMN,
99 QUICK_CHECKBOX (N_ ("Cas&e sensitive"), &edit_search_options.case_sens, NULL),
100 QUICK_CHECKBOX (N_ ("&Backwards"), &edit_search_options.backwards, NULL),
101 QUICK_CHECKBOX (N_ ("In se&lection"), &edit_search_options.only_in_selection, NULL),
102 QUICK_CHECKBOX (N_ ("&Whole words"), &edit_search_options.whole_words, NULL),
103 #ifdef HAVE_CHARSET
104 QUICK_CHECKBOX (N_ ("&All charsets"), &edit_search_options.all_codepages, NULL),
105 #endif
106 QUICK_STOP_COLUMNS,
107 QUICK_START_BUTTONS (TRUE, TRUE),
108 QUICK_BUTTON (N_ ("&OK"), B_ENTER, NULL, NULL),
109 QUICK_BUTTON (N_ ("&Find all"), B_USER, NULL, NULL),
110 QUICK_BUTTON (N_ ("&Cancel"), B_CANCEL, NULL, NULL),
111 QUICK_END,
112
113 };
114
115 WRect r = { -1, -1, 0, 58 };
116
117 quick_dialog_t qdlg = {
118 .rect = r,
119 .title = N_ ("Search"),
120 .help = "[Input Line Keys]",
121 .widgets = quick_widgets,
122 .callback = NULL,
123 .mouse_callback = NULL,
124 };
125
126 dialog_result = quick_dialog (&qdlg);
127 }
128
129 g_strfreev (list_of_types);
130
131 if (dialog_result == B_CANCEL || search_text == NULL || search_text[0] == '\0')
132 {
133 g_free (search_text);
134 return FALSE;
135 }
136
137 if (dialog_result == B_USER)
138 search_create_bookmark = TRUE;
139
140 #ifdef HAVE_CHARSET
141 {
142 GString *tmp;
143
144 tmp = str_convert_to_input (search_text);
145 g_free (search_text);
146 if (tmp != NULL)
147 search_text = g_string_free (tmp, FALSE);
148 else
149 search_text = g_strdup ("");
150 }
151 #endif
152
153 edit_search_deinit (edit);
154 edit->last_search_string = search_text;
155
156 return edit_search_init (edit, edit->last_search_string);
157 }
158
159
160
161
162
163
164
165
166
167
168 static inline char
169 edit_search_get_current_end_line_char (const WEdit *edit)
170 {
171 switch (edit->lb)
172 {
173 case LB_MAC:
174 return '\r';
175 default:
176 return '\n';
177 }
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191 static off_t
192 edit_calculate_start_of_next_line (const edit_buffer_t *buf, off_t current_pos, off_t max_pos,
193 char end_string_symbol)
194 {
195 off_t i;
196
197 for (i = current_pos; i < max_pos; i++)
198 {
199 current_pos++;
200 if (edit_buffer_get_byte (buf, i) == end_string_symbol)
201 break;
202 }
203
204 return current_pos;
205 }
206
207
208
209
210
211
212
213
214
215
216
217 static off_t
218 edit_calculate_end_of_previous_line (const edit_buffer_t *buf, off_t current_pos,
219 char end_string_symbol)
220 {
221 off_t i;
222
223 for (i = current_pos - 1; i >= 0; i--)
224 if (edit_buffer_get_byte (buf, i) == end_string_symbol)
225 break;
226
227 return i;
228 }
229
230
231
232
233
234
235
236
237
238
239
240 static inline off_t
241 edit_calculate_start_of_previous_line (const edit_buffer_t *buf, off_t current_pos,
242 char end_string_symbol)
243 {
244 current_pos = edit_calculate_end_of_previous_line (buf, current_pos, end_string_symbol);
245 current_pos = edit_calculate_end_of_previous_line (buf, current_pos, end_string_symbol);
246
247 return (current_pos + 1);
248 }
249
250
251
252
253
254
255
256
257
258
259
260 static inline off_t
261 edit_calculate_start_of_current_line (const edit_buffer_t *buf, off_t current_pos,
262 char end_string_symbol)
263 {
264 current_pos = edit_calculate_end_of_previous_line (buf, current_pos, end_string_symbol);
265
266 return (current_pos + 1);
267 }
268
269
270
271
272
273
274
275
276 static void
277 edit_search_fix_search_start_if_selection (WEdit *edit)
278 {
279 off_t start_mark = 0;
280 off_t end_mark = 0;
281
282 if (!edit_search_options.only_in_selection)
283 return;
284
285 if (!eval_marks (edit, &start_mark, &end_mark))
286 return;
287
288 if (edit_search_options.backwards)
289 {
290 if (edit->search_start > end_mark || edit->search_start <= start_mark)
291 edit->search_start = end_mark;
292 }
293 else
294 {
295 if (edit->search_start < start_mark || edit->search_start >= end_mark)
296 edit->search_start = start_mark;
297 }
298 }
299
300
301
302 static gboolean
303 edit_find (edit_search_status_msg_t *esm, gsize *len)
304 {
305 WEdit *edit = esm->edit;
306 edit_buffer_t *buf = &edit->buffer;
307 off_t search_start = edit->search_start;
308 off_t search_end;
309 off_t start_mark = 0;
310 off_t end_mark = buf->size;
311 gboolean start_from_next_line = FALSE;
312 char end_string_symbol;
313
314 end_string_symbol = edit_search_get_current_end_line_char (edit);
315
316
317 if (edit_search_options.only_in_selection)
318 {
319 if (!eval_marks (edit, &start_mark, &end_mark))
320 {
321 mc_search_set_error (edit->search, MC_SEARCH_E_NOTFOUND, "%s", _ (STR_E_NOTFOUND));
322 return FALSE;
323 }
324
325
326 if (!edit_search_options.backwards && (edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0
327 && search_start != 0)
328 {
329 const off_t bol =
330 edit_calculate_start_of_current_line (buf, search_start, end_string_symbol);
331
332 if (search_start != bol)
333 {
334 start_mark = edit_calculate_start_of_next_line (buf, start_mark, buf->size,
335 end_string_symbol);
336 start_from_next_line = TRUE;
337 }
338 }
339
340 if ((edit->search_line_type & MC_SEARCH_LINE_END) != 0
341 && (end_mark - 1 != buf->size
342 || edit_buffer_get_byte (buf, end_mark) != end_string_symbol))
343 end_mark = edit_calculate_end_of_previous_line (buf, end_mark, end_string_symbol);
344
345 if (start_mark >= end_mark)
346 {
347 mc_search_set_error (edit->search, MC_SEARCH_E_NOTFOUND, "%s", _ (STR_E_NOTFOUND));
348 return FALSE;
349 }
350 }
351 else if (edit_search_options.backwards)
352 end_mark = MAX (1, buf->curs1) - 1;
353 else if ((edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
354 {
355
356 const off_t bol =
357 edit_calculate_start_of_current_line (buf, search_start, end_string_symbol);
358
359 start_from_next_line = search_start != bol;
360 }
361
362
363 if (edit_search_options.backwards)
364 {
365
366 search_end = end_mark;
367
368 if ((edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
369 search_start =
370 edit_calculate_start_of_current_line (buf, search_start, end_string_symbol);
371
372 while (search_start >= start_mark)
373 {
374 gboolean ok;
375
376 if (search_end > (off_t) (search_start + edit->search->original.str->len)
377 && mc_search_is_fixed_search_str (edit->search))
378 search_end = search_start + edit->search->original.str->len;
379
380 ok = mc_search_run (edit->search, (void *) esm, search_start, search_end, len);
381
382 if (ok && edit->search->normal_offset == search_start)
383 return TRUE;
384
385
386
387 if (!ok && edit->search->error != MC_SEARCH_E_NOTFOUND)
388 return FALSE;
389
390 if ((edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
391 search_start =
392 edit_calculate_start_of_previous_line (buf, search_start, end_string_symbol);
393 else
394 search_start--;
395 }
396
397 mc_search_set_error (edit->search, MC_SEARCH_E_NOTFOUND, "%s", _ (STR_E_NOTFOUND));
398 return FALSE;
399 }
400
401
402
403
404 if (end_mark == edit_calculate_start_of_current_line (buf, end_mark, end_string_symbol))
405 end_mark = edit_calculate_end_of_previous_line (buf, end_mark, end_string_symbol);
406
407 if (start_from_next_line)
408 search_start =
409 edit_calculate_start_of_next_line (buf, search_start, end_mark, end_string_symbol);
410
411 return mc_search_run (edit->search, (void *) esm, search_start, end_mark, len);
412 }
413
414
415
416 static char *
417 edit_replace_cmd__conv_to_display (const char *str)
418 {
419 #ifdef HAVE_CHARSET
420 GString *tmp;
421
422 tmp = str_convert_to_display (str);
423 if (tmp != NULL)
424 {
425 if (tmp->len != 0)
426 return g_string_free (tmp, FALSE);
427 g_string_free (tmp, TRUE);
428 }
429 #endif
430 return g_strdup (str);
431 }
432
433
434
435 static char *
436 edit_replace_cmd__conv_to_input (char *str)
437 {
438 #ifdef HAVE_CHARSET
439 GString *tmp;
440
441 tmp = str_convert_to_input (str);
442 if (tmp != NULL)
443 {
444 if (tmp->len != 0)
445 return g_string_free (tmp, FALSE);
446 g_string_free (tmp, TRUE);
447 }
448 #endif
449 return g_strdup (str);
450 }
451
452
453
454 static void
455 edit_search_show_error (const WEdit *edit, const char *title)
456 {
457 if (edit->search->error == MC_SEARCH_E_NOTFOUND)
458 message (D_NORMAL, title, "%s", _ (STR_E_NOTFOUND));
459 else if (edit->search->error_str != NULL)
460 message (D_NORMAL, title, "%s", edit->search->error_str);
461 }
462
463
464
465 static void
466 edit_do_search (WEdit *edit)
467 {
468 edit_search_status_msg_t esm;
469 gsize len = 0;
470
471
472 assert (edit->search != NULL);
473
474 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
475
476 esm.first = TRUE;
477 esm.edit = edit;
478 esm.offset = edit->search_start;
479
480 status_msg_init (STATUS_MSG (&esm), _ ("Search"), 1.0, simple_status_msg_init_cb,
481 edit_search_status_update_cb, NULL);
482
483 if (search_create_bookmark)
484 {
485 gboolean found = FALSE;
486 long l = 0, l_last = -1;
487 long q = 0;
488
489 search_create_bookmark = FALSE;
490 book_mark_flush (edit, -1);
491
492 while (mc_search_run (edit->search, (void *) &esm, q, edit->buffer.size, &len))
493 {
494 if (!found)
495 edit->search_start = edit->search->normal_offset;
496 found = TRUE;
497
498 l += edit_buffer_count_lines (&edit->buffer, q, edit->search->normal_offset);
499 if (l != l_last)
500 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
501 l_last = l;
502 q = edit->search->normal_offset + 1;
503 }
504
505 if (!found)
506 message (D_NORMAL, _ ("Search"), "%s", _ (STR_E_NOTFOUND));
507 else
508 edit_cursor_move (edit, edit->search_start - edit->buffer.curs1);
509 }
510 else
511 {
512 if (edit_search_options.backwards)
513 {
514 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1)
515 edit->search_start--;
516 }
517 else
518 {
519 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1)
520 edit->search_start++;
521 }
522
523 if (edit_find (&esm, &len))
524 {
525 edit->found_start = edit->search->normal_offset;
526 edit->found_len = len;
527
528 edit->over_col = 0;
529 edit_cursor_move (edit, edit->found_start - edit->buffer.curs1);
530 edit_scroll_screen_over_cursor (edit);
531
532 if (edit_search_options.backwards)
533 edit->search_start = edit->found_start - 1;
534 else
535 edit->search_start = edit->found_start + edit->found_len;
536 }
537 else
538 {
539 edit->search_start = edit->buffer.curs1;
540 edit_search_show_error (edit, _ ("Search"));
541 }
542 }
543
544 status_msg_deinit (STATUS_MSG (&esm));
545
546 edit->force |= REDRAW_COMPLETELY;
547 edit_scroll_screen_over_cursor (edit);
548 }
549
550
551
552 static void
553 edit_search (WEdit *edit)
554 {
555 if (edit_dialog_search_show (edit))
556 edit_do_search (edit);
557 }
558
559
560
561
562
563 gboolean
564 edit_search_init (WEdit *edit, const char *str)
565 {
566 #ifdef HAVE_CHARSET
567 edit->search = mc_search_new (str, cp_source);
568 #else
569 edit->search = mc_search_new (str, NULL);
570 #endif
571
572 if (edit->search == NULL)
573 return FALSE;
574
575 edit->search->search_type = edit_search_options.type;
576 #ifdef HAVE_CHARSET
577 edit->search->is_all_charsets = edit_search_options.all_codepages;
578 #endif
579 edit->search->is_case_sensitive = edit_search_options.case_sens;
580 edit->search->whole_words = edit_search_options.whole_words;
581 edit->search->search_fn = edit_search_cmd_callback;
582 edit->search->update_fn = edit_search_update_callback;
583
584 edit->search_line_type = mc_search_get_line_type (edit->search);
585
586 edit_search_fix_search_start_if_selection (edit);
587
588 return TRUE;
589 }
590
591
592
593 void
594 edit_search_deinit (WEdit *edit)
595 {
596 mc_search_free (edit->search);
597 g_free (edit->last_search_string);
598 }
599
600
601
602 mc_search_cbret_t
603 edit_search_cmd_callback (const void *user_data, off_t char_offset, int *current_char)
604 {
605 WEdit *edit = ((const edit_search_status_msg_t *) user_data)->edit;
606
607 *current_char = edit_buffer_get_byte (&edit->buffer, char_offset);
608
609 return MC_SEARCH_CB_OK;
610 }
611
612
613
614 mc_search_cbret_t
615 edit_search_update_callback (const void *user_data, off_t char_offset)
616 {
617 status_msg_t *sm = STATUS_MSG (user_data);
618
619 ((edit_search_status_msg_t *) sm)->offset = char_offset;
620
621 return (sm->update (sm) == B_CANCEL ? MC_SEARCH_CB_ABORT : MC_SEARCH_CB_OK);
622 }
623
624
625
626 int
627 edit_search_status_update_cb (status_msg_t *sm)
628 {
629 simple_status_msg_t *ssm = SIMPLE_STATUS_MSG (sm);
630 edit_search_status_msg_t *esm = (edit_search_status_msg_t *) sm;
631 Widget *wd = WIDGET (sm->dlg);
632
633 if (verbose)
634 label_set_textv (ssm->label, _ ("Searching %s: %3d%%"), esm->edit->last_search_string,
635 edit_buffer_calc_percent (&esm->edit->buffer, esm->offset));
636 else
637 label_set_textv (ssm->label, _ ("Searching %s"), esm->edit->last_search_string);
638
639 if (esm->first)
640 {
641 Widget *lw = WIDGET (ssm->label);
642 WRect r;
643
644 r = wd->rect;
645 r.cols = MAX (r.cols, lw->rect.cols + 6);
646 widget_set_size_rect (wd, &r);
647 r = lw->rect;
648 r.x = wd->rect.x + (wd->rect.cols - r.cols) / 2;
649 widget_set_size_rect (lw, &r);
650 esm->first = FALSE;
651 }
652
653 return status_msg_common_update (sm);
654 }
655
656
657
658 void
659 edit_search_cmd (WEdit *edit, gboolean again)
660 {
661 if (!again)
662 edit_search (edit);
663 else if (edit->last_search_string != NULL)
664 edit_do_search (edit);
665 else
666 {
667
668 char *s;
669
670 s = mc_config_history_get_recent_item (MC_HISTORY_SHARED_SEARCH);
671 if (s != NULL)
672 {
673 edit->last_search_string = s;
674
675 if (edit_search_init (edit, edit->last_search_string))
676 {
677 edit_do_search (edit);
678 return;
679 }
680
681
682 MC_PTR_FREE (edit->last_search_string);
683 }
684
685
686 edit_search (edit);
687 }
688 }
689
690
691
692 void
693 edit_dialog_replace_show (WEdit *edit, const char *search_default, const char *replace_default,
694 char **search_text, char **replace_text)
695 {
696 size_t num_of_types = 0;
697 gchar **list_of_types;
698
699 if ((search_default == NULL) || (*search_default == '\0'))
700 search_default = INPUT_LAST_TEXT;
701
702 list_of_types = mc_search_get_types_strings_array (&num_of_types);
703
704 {
705 quick_widget_t quick_widgets[] = {
706
707 QUICK_LABELED_INPUT (N_ ("Enter search string:"), input_label_above, search_default,
708 MC_HISTORY_SHARED_SEARCH, search_text, NULL, FALSE, FALSE,
709 INPUT_COMPLETE_NONE),
710 QUICK_LABELED_INPUT (N_ ("Enter replacement string:"), input_label_above,
711 replace_default, "replace", replace_text, NULL, FALSE, FALSE,
712 INPUT_COMPLETE_NONE),
713 QUICK_SEPARATOR (TRUE),
714 QUICK_START_COLUMNS,
715 QUICK_RADIO (num_of_types, (const char **) list_of_types,
716 (int *) &edit_search_options.type, NULL),
717 QUICK_NEXT_COLUMN,
718 QUICK_CHECKBOX (N_ ("Cas&e sensitive"), &edit_search_options.case_sens, NULL),
719 QUICK_CHECKBOX (N_ ("&Backwards"), &edit_search_options.backwards, NULL),
720 QUICK_CHECKBOX (N_ ("In se&lection"), &edit_search_options.only_in_selection, NULL),
721 QUICK_CHECKBOX (N_ ("&Whole words"), &edit_search_options.whole_words, NULL),
722 #ifdef HAVE_CHARSET
723 QUICK_CHECKBOX (N_ ("&All charsets"), &edit_search_options.all_codepages, NULL),
724 #endif
725 QUICK_STOP_COLUMNS,
726 QUICK_BUTTONS_OK_CANCEL,
727 QUICK_END,
728
729 };
730
731 WRect r = { -1, -1, 0, 58 };
732
733 quick_dialog_t qdlg = {
734 .rect = r,
735 .title = N_ ("Replace"),
736 .help = "[Input Line Keys]",
737 .widgets = quick_widgets,
738 .callback = NULL,
739 .mouse_callback = NULL,
740 };
741
742 if (quick_dialog (&qdlg) != B_CANCEL)
743 edit->replace_mode = 0;
744 else
745 {
746 *replace_text = NULL;
747 *search_text = NULL;
748 }
749 }
750
751 g_strfreev (list_of_types);
752 }
753
754
755
756 int
757 edit_dialog_replace_prompt_show (WEdit *edit, char *from_text, char *to_text, int xpos, int ypos)
758 {
759 Widget *w = WIDGET (edit);
760
761
762 int dlg_height = 10;
763 int dlg_width;
764
765 char tmp[BUF_MEDIUM];
766 char *repl_from, *repl_to;
767 int retval;
768
769 if (xpos == -1)
770 xpos = w->rect.x + edit_options.line_state_width + 1;
771 if (ypos == -1)
772 ypos = w->rect.y + w->rect.lines / 2;
773
774 if ((edit->curs_row >= ypos - 1) && (edit->curs_row <= ypos + dlg_height - 1))
775 ypos -= dlg_height;
776
777 dlg_width = WIDGET (w->owner)->rect.cols - xpos - 1;
778
779 g_snprintf (tmp, sizeof (tmp), "\"%s\"", from_text);
780 repl_from = g_strdup (str_trunc (tmp, dlg_width - 7));
781
782 g_snprintf (tmp, sizeof (tmp), "\"%s\"", to_text);
783 repl_to = g_strdup (str_trunc (tmp, dlg_width - 7));
784
785 {
786 quick_widget_t quick_widgets[] = {
787
788 QUICK_LABEL (repl_from, NULL),
789 QUICK_LABEL (N_ ("Replace with:"), NULL),
790 QUICK_LABEL (repl_to, NULL),
791 QUICK_START_BUTTONS (TRUE, TRUE),
792 QUICK_BUTTON (N_ ("&Replace"), B_ENTER, NULL, NULL),
793 QUICK_BUTTON (N_ ("A&ll"), B_REPLACE_ALL, NULL, NULL),
794 QUICK_BUTTON (N_ ("&Skip"), B_SKIP_REPLACE, NULL, NULL),
795 QUICK_BUTTON (N_ ("&Cancel"), B_CANCEL, NULL, NULL),
796 QUICK_END,
797
798 };
799
800 WRect r = { ypos, xpos, 0, -1 };
801
802 quick_dialog_t qdlg = {
803 .rect = r,
804 .title = N_ ("Confirm replace"),
805 .help = NULL,
806 .widgets = quick_widgets,
807 .callback = NULL,
808 .mouse_callback = NULL,
809 };
810
811 retval = quick_dialog (&qdlg);
812 }
813
814 g_free (repl_from);
815 g_free (repl_to);
816
817 return retval;
818 }
819
820
821
822
823 void
824 edit_replace_cmd (WEdit *edit, gboolean again)
825 {
826
827 static char *saved1 = NULL;
828 static char *saved2 = NULL;
829 char *input1 = NULL;
830 char *input2 = NULL;
831 GString *input2_str = NULL;
832 char *disp1 = NULL;
833 char *disp2 = NULL;
834 long times_replaced = 0;
835 gboolean once_found = FALSE;
836 edit_search_status_msg_t esm;
837
838 if (edit == NULL)
839 {
840 MC_PTR_FREE (saved1);
841 MC_PTR_FREE (saved2);
842 return;
843 }
844
845 edit->force |= REDRAW_COMPLETELY;
846
847 if (again && saved1 == NULL && saved2 == NULL)
848 again = FALSE;
849
850 if (again)
851 {
852 input1 = g_strdup (saved1 != NULL ? saved1 : "");
853 input2 = g_strdup (saved2 != NULL ? saved2 : "");
854 }
855 else
856 {
857 char *tmp_inp1, *tmp_inp2;
858
859 disp1 = edit_replace_cmd__conv_to_display (saved1 != NULL ? saved1 : "");
860 disp2 = edit_replace_cmd__conv_to_display (saved2 != NULL ? saved2 : "");
861
862 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
863
864 edit_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
865
866 g_free (disp1);
867 g_free (disp2);
868
869 if (input1 == NULL || *input1 == '\0')
870 {
871 edit->force = REDRAW_COMPLETELY;
872 goto cleanup;
873 }
874
875 tmp_inp1 = input1;
876 tmp_inp2 = input2;
877 input1 = edit_replace_cmd__conv_to_input (input1);
878 input2 = edit_replace_cmd__conv_to_input (input2);
879 g_free (tmp_inp1);
880 g_free (tmp_inp2);
881
882 g_free (saved1);
883 saved1 = g_strdup (input1);
884 g_free (saved2);
885 saved2 = g_strdup (input2);
886
887 mc_search_free (edit->search);
888 edit->search = NULL;
889 }
890
891 input2_str = g_string_new_take (input2);
892 input2 = NULL;
893
894 if (edit->search == NULL && !edit_search_init (edit, input1))
895 {
896 edit->search_start = edit->buffer.curs1;
897 goto cleanup;
898 }
899
900 if (edit_search_options.backwards)
901 {
902 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1)
903 edit->search_start--;
904 }
905 else
906 {
907 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1)
908 edit->search_start++;
909 }
910
911 esm.first = TRUE;
912 esm.edit = edit;
913 esm.offset = edit->search_start;
914
915 status_msg_init (STATUS_MSG (&esm), _ ("Search"), 1.0, simple_status_msg_init_cb,
916 edit_search_status_update_cb, NULL);
917
918 do
919 {
920 gsize len = 0;
921
922 if (!edit_find (&esm, &len))
923 {
924 if (!(edit->search->error == MC_SEARCH_E_OK
925 || (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
926 edit_search_show_error (edit, _ ("Search"));
927 break;
928 }
929
930 once_found = TRUE;
931
932 edit->search_start = edit->search->normal_offset;
933
934
935 if (edit->search_start >= 0 && edit->search_start < edit->buffer.size)
936 {
937 gsize i;
938 GString *repl_str;
939
940 edit->found_start = edit->search_start;
941 edit->found_len = len;
942
943 edit_cursor_move (edit, edit->found_start - edit->buffer.curs1);
944 edit_scroll_screen_over_cursor (edit);
945
946 if (edit->replace_mode == 0)
947 {
948 long l;
949 int prompt;
950
951 l = edit->curs_row - WIDGET (edit)->rect.lines / 3;
952 if (l > 0)
953 edit_scroll_downward (edit, l);
954 if (l < 0)
955 edit_scroll_upward (edit, -l);
956
957 edit_scroll_screen_over_cursor (edit);
958 edit->force |= REDRAW_PAGE;
959 edit_render_keypress (edit);
960
961
962 edit_push_key_press (edit);
963
964 disp1 = edit_replace_cmd__conv_to_display (saved1);
965 disp2 = edit_replace_cmd__conv_to_display (saved2);
966 prompt = edit_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
967 g_free (disp1);
968 g_free (disp2);
969
970 if (prompt == B_REPLACE_ALL)
971 edit->replace_mode = 1;
972 else if (prompt == B_SKIP_REPLACE)
973 {
974 if (edit_search_options.backwards)
975 edit->search_start--;
976 else
977 edit->search_start++;
978 continue;
979 }
980 else if (prompt == B_CANCEL)
981 {
982 edit->replace_mode = -1;
983 break;
984 }
985 }
986
987 repl_str = mc_search_prepare_replace_str (edit->search, input2_str);
988
989 if (edit->search->error != MC_SEARCH_E_OK)
990 {
991 edit_search_show_error (edit, _ ("Replace"));
992 if (repl_str != NULL)
993 g_string_free (repl_str, TRUE);
994 break;
995 }
996
997
998 for (i = 0; i < len; i++)
999 edit_delete (edit, TRUE);
1000
1001 for (i = 0; i < repl_str->len; i++)
1002 edit_insert (edit, repl_str->str[i]);
1003
1004 edit->found_len = repl_str->len;
1005 g_string_free (repl_str, TRUE);
1006 times_replaced++;
1007
1008
1009 if (edit_search_options.backwards)
1010 edit->search_start--;
1011 else
1012 {
1013 edit->search_start += edit->found_len + (len == 0 ? 1 : 0);
1014
1015 if (edit->search_start >= edit->buffer.size)
1016 break;
1017 }
1018
1019 edit_scroll_screen_over_cursor (edit);
1020 }
1021 else
1022 {
1023
1024 edit->search_start = edit->buffer.curs1;
1025 edit_update_curs_col (edit);
1026
1027 edit->force |= REDRAW_PAGE;
1028 edit_render_keypress (edit);
1029
1030 if (times_replaced == 0)
1031 query_dialog (_ ("Replace"), _ (STR_E_NOTFOUND), D_NORMAL, 1, _ ("&OK"));
1032 break;
1033 }
1034 }
1035 while (edit->replace_mode >= 0);
1036
1037 status_msg_deinit (STATUS_MSG (&esm));
1038 edit_scroll_screen_over_cursor (edit);
1039 edit->force |= REDRAW_COMPLETELY;
1040 edit_render_keypress (edit);
1041
1042 if (edit->replace_mode == 1 && times_replaced != 0)
1043 message (D_NORMAL, _ ("Replace"), _ ("%ld replacements made"), times_replaced);
1044
1045 cleanup:
1046 g_free (input1);
1047 g_free (input2);
1048 if (input2_str != NULL)
1049 g_string_free (input2_str, TRUE);
1050 }
1051
1052