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