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