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 (N_ ("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 (N_ ("Cas&e sensitive"), &edit_search_options.case_sens, NULL),
98 QUICK_CHECKBOX (N_ ("&Backwards"), &edit_search_options.backwards, NULL),
99 QUICK_CHECKBOX (N_ ("In se&lection"), &edit_search_options.only_in_selection, NULL),
100 QUICK_CHECKBOX (N_ ("&Whole words"), &edit_search_options.whole_words, NULL),
101 QUICK_CHECKBOX (N_ ("&All charsets"), &edit_search_options.all_codepages, NULL),
102 QUICK_STOP_COLUMNS,
103 QUICK_START_BUTTONS (TRUE, TRUE),
104 QUICK_BUTTON (N_ ("&OK"), B_ENTER, NULL, NULL),
105 QUICK_BUTTON (N_ ("&Find all"), B_USER, NULL, NULL),
106 QUICK_BUTTON (N_ ("&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 = N_ ("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 if (search_start >= end_mark)
323 {
324 mc_search_set_error (edit->search, MC_SEARCH_E_NOTFOUND, "%s", _ (STR_E_NOTFOUND));
325 return FALSE;
326 }
327 }
328 else if (edit_search_options.backwards)
329 end_mark = MAX (1, buf->curs1) - 1;
330 else if ((edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
331 {
332
333 const off_t bol =
334 edit_calculate_start_of_current_line (buf, search_start, end_string_symbol);
335
336 start_from_next_line = search_start != bol;
337 }
338
339
340 if (edit_search_options.backwards)
341 {
342
343
344 off_t search_end = end_mark;
345
346 if ((edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
347 search_start =
348 edit_calculate_start_of_current_line (buf, search_start, end_string_symbol);
349
350 while (search_start >= start_mark)
351 {
352 gboolean ok;
353
354 if (search_end > (off_t) (search_start + edit->search->original.str->len)
355 && mc_search_is_fixed_search_str (edit->search))
356 search_end = search_start + edit->search->original.str->len;
357
358 ok = mc_search_run (edit->search, (void *) esm, search_start, search_end, len);
359
360 if (ok && edit->search->normal_offset == search_start)
361 return TRUE;
362
363
364
365 if (!ok && edit->search->error != MC_SEARCH_E_NOTFOUND)
366 return FALSE;
367
368 if ((edit->search_line_type & MC_SEARCH_LINE_BEGIN) != 0)
369 search_start =
370 edit_calculate_start_of_previous_line (buf, search_start, end_string_symbol);
371 else
372 search_start--;
373 }
374
375 mc_search_set_error (edit->search, MC_SEARCH_E_NOTFOUND, "%s", _ (STR_E_NOTFOUND));
376 return FALSE;
377 }
378
379
380
381
382 if (end_mark == edit_calculate_start_of_current_line (buf, end_mark, end_string_symbol))
383 {
384 end_mark = edit_calculate_end_of_previous_line (buf, end_mark, end_string_symbol);
385
386
387 if (edit->mark2 >= 0 && edit->mark2 != edit->mark1)
388 {
389 if (edit->mark2 > edit->mark1)
390 edit->mark2 = end_mark;
391 else
392 edit->mark1 = end_mark;
393 }
394 }
395
396 if (start_from_next_line)
397 search_start =
398 edit_calculate_start_of_next_line (buf, search_start, end_mark, end_string_symbol);
399
400 if (search_start >= end_mark)
401 {
402 mc_search_set_error (edit->search, MC_SEARCH_E_NOTFOUND, "%s", _ (STR_E_NOTFOUND));
403 return FALSE;
404 }
405
406 return mc_search_run (edit->search, (void *) esm, search_start, end_mark, len);
407 }
408
409
410
411 static char *
412 edit_replace_cmd__conv_to_display (const char *str)
413 {
414 GString *tmp;
415
416 tmp = str_convert_to_display (str);
417 if (tmp != NULL)
418 {
419 if (tmp->len != 0)
420 return g_string_free (tmp, FALSE);
421 g_string_free (tmp, TRUE);
422 }
423
424 return g_strdup (str);
425 }
426
427
428
429 static char *
430 edit_replace_cmd__conv_to_input (char *str)
431 {
432 GString *tmp;
433
434 tmp = str_convert_to_input (str);
435 if (tmp != NULL)
436 {
437 if (tmp->len != 0)
438 return g_string_free (tmp, FALSE);
439 g_string_free (tmp, TRUE);
440 }
441
442 return g_strdup (str);
443 }
444
445
446
447 static void
448 edit_search_show_error (const WEdit *edit, const char *title)
449 {
450 if (edit->search->error == MC_SEARCH_E_NOTFOUND)
451 message (D_NORMAL, title, "%s", _ (STR_E_NOTFOUND));
452 else if (edit->search->error_str != NULL)
453 message (D_NORMAL, title, "%s", edit->search->error_str);
454 }
455
456
457
458 static void
459 edit_do_search (WEdit *edit)
460 {
461 edit_search_status_msg_t esm;
462 gsize len = 0;
463
464
465 assert (edit->search != NULL);
466
467 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
468
469 esm.first = TRUE;
470 esm.edit = edit;
471 esm.offset = edit->search_start;
472
473 status_msg_init (STATUS_MSG (&esm), _ ("Search"), 1.0, simple_status_msg_init_cb,
474 edit_search_status_update_cb, NULL);
475
476 if (search_create_bookmark)
477 {
478 gboolean found = FALSE;
479 long l = 0, l_last = -1;
480 long q = 0;
481
482 search_create_bookmark = FALSE;
483 book_mark_flush (edit, -1);
484
485 while (mc_search_run (edit->search, (void *) &esm, q, edit->buffer.size, &len))
486 {
487 if (!found)
488 edit->search_start = edit->search->normal_offset;
489 found = TRUE;
490
491 l += edit_buffer_count_lines (&edit->buffer, q, edit->search->normal_offset);
492 if (l != l_last)
493 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
494 l_last = l;
495 q = edit->search->normal_offset + 1;
496 }
497
498 if (!found)
499 message (D_NORMAL, _ ("Search"), "%s", _ (STR_E_NOTFOUND));
500 else
501 edit_cursor_move (edit, edit->search_start - edit->buffer.curs1);
502 }
503 else
504 {
505 if (edit_search_options.backwards)
506 {
507 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1)
508 edit->search_start--;
509 }
510 else
511 {
512 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1)
513 edit->search_start++;
514 }
515
516 if (edit_find (&esm, &len))
517 {
518 edit->found_start = edit->search->normal_offset;
519 edit->found_len = len;
520
521 edit->over_col = 0;
522 edit_cursor_move (edit, edit->found_start - edit->buffer.curs1);
523 edit_scroll_screen_over_cursor (edit);
524
525 if (edit_search_options.backwards)
526 edit->search_start = edit->found_start - 1;
527 else
528 edit->search_start = edit->found_start + edit->found_len;
529 }
530 else
531 {
532 edit->search_start = edit->buffer.curs1;
533 edit_search_show_error (edit, _ ("Search"));
534 }
535 }
536
537 status_msg_deinit (STATUS_MSG (&esm));
538
539 edit->force |= REDRAW_COMPLETELY;
540 edit_scroll_screen_over_cursor (edit);
541 }
542
543
544
545 static void
546 edit_search (WEdit *edit)
547 {
548 if (edit_dialog_search_show (edit))
549 edit_do_search (edit);
550 }
551
552
553
554
555
556 gboolean
557 edit_search_init (WEdit *edit, const char *str)
558 {
559 edit->search = mc_search_new (str, cp_source);
560
561 if (edit->search == NULL)
562 return FALSE;
563
564 edit->search->search_type = edit_search_options.type;
565 edit->search->is_all_charsets = edit_search_options.all_codepages;
566 edit->search->is_case_sensitive = edit_search_options.case_sens;
567 edit->search->whole_words = edit_search_options.whole_words;
568 edit->search->search_fn = edit_search_cmd_callback;
569 edit->search->update_fn = edit_search_update_callback;
570
571 edit->search_line_type = mc_search_get_line_type (edit->search);
572
573 edit_search_fix_search_start_if_selection (edit);
574
575 return TRUE;
576 }
577
578
579
580 void
581 edit_search_deinit (WEdit *edit)
582 {
583 mc_search_free (edit->search);
584 g_free (edit->last_search_string);
585 }
586
587
588
589 mc_search_cbret_t
590 edit_search_cmd_callback (const void *user_data, off_t char_offset, int *current_char)
591 {
592 WEdit *edit = ((const edit_search_status_msg_t *) user_data)->edit;
593
594 *current_char = edit_buffer_get_byte (&edit->buffer, char_offset);
595
596 return MC_SEARCH_CB_OK;
597 }
598
599
600
601 mc_search_cbret_t
602 edit_search_update_callback (const void *user_data, off_t char_offset)
603 {
604 status_msg_t *sm = STATUS_MSG (user_data);
605
606 ((edit_search_status_msg_t *) sm)->offset = char_offset;
607
608 return (sm->update (sm) == B_CANCEL ? MC_SEARCH_CB_ABORT : MC_SEARCH_CB_OK);
609 }
610
611
612
613 int
614 edit_search_status_update_cb (status_msg_t *sm)
615 {
616 simple_status_msg_t *ssm = SIMPLE_STATUS_MSG (sm);
617 edit_search_status_msg_t *esm = (edit_search_status_msg_t *) sm;
618 Widget *wd = WIDGET (sm->dlg);
619
620 if (verbose)
621 label_set_textv (ssm->label, _ ("Searching %s: %3d%%"), esm->edit->last_search_string,
622 edit_buffer_calc_percent (&esm->edit->buffer, esm->offset));
623 else
624 label_set_textv (ssm->label, _ ("Searching %s"), esm->edit->last_search_string);
625
626 if (esm->first)
627 {
628 Widget *lw = WIDGET (ssm->label);
629 WRect r;
630
631 r = wd->rect;
632 r.cols = MAX (r.cols, lw->rect.cols + 6);
633 widget_set_size_rect (wd, &r);
634 r = lw->rect;
635 r.x = wd->rect.x + (wd->rect.cols - r.cols) / 2;
636 widget_set_size_rect (lw, &r);
637 esm->first = FALSE;
638 }
639
640 return status_msg_common_update (sm);
641 }
642
643
644
645 void
646 edit_search_cmd (WEdit *edit, gboolean again)
647 {
648 if (!again)
649 edit_search (edit);
650 else if (edit->last_search_string != NULL)
651 edit_do_search (edit);
652 else
653 {
654
655 char *s;
656
657 s = mc_config_history_get_recent_item (MC_HISTORY_SHARED_SEARCH);
658 if (s != NULL)
659 {
660 edit->last_search_string = s;
661
662 if (edit_search_init (edit, edit->last_search_string))
663 {
664 edit_do_search (edit);
665 return;
666 }
667
668
669 MC_PTR_FREE (edit->last_search_string);
670 }
671
672
673 edit_search (edit);
674 }
675 }
676
677
678
679 void
680 edit_dialog_replace_show (WEdit *edit, const char *search_default, const char *replace_default,
681 char **search_text, char **replace_text)
682 {
683 size_t num_of_types = 0;
684 gchar **list_of_types;
685
686 if ((search_default == NULL) || (*search_default == '\0'))
687 search_default = INPUT_LAST_TEXT;
688
689 list_of_types = mc_search_get_types_strings_array (&num_of_types);
690
691 {
692 quick_widget_t quick_widgets[] = {
693
694 QUICK_LABELED_INPUT (N_ ("Enter search string:"), input_label_above, search_default,
695 MC_HISTORY_SHARED_SEARCH, search_text, NULL, FALSE, FALSE,
696 INPUT_COMPLETE_NONE),
697 QUICK_LABELED_INPUT (N_ ("Enter replacement string:"), input_label_above,
698 replace_default, "replace", replace_text, NULL, FALSE, FALSE,
699 INPUT_COMPLETE_NONE),
700 QUICK_SEPARATOR (TRUE),
701 QUICK_START_COLUMNS,
702 QUICK_RADIO (num_of_types, (const char **) list_of_types,
703 (int *) &edit_search_options.type, NULL),
704 QUICK_NEXT_COLUMN,
705 QUICK_CHECKBOX (N_ ("Cas&e sensitive"), &edit_search_options.case_sens, NULL),
706 QUICK_CHECKBOX (N_ ("&Backwards"), &edit_search_options.backwards, NULL),
707 QUICK_CHECKBOX (N_ ("In se&lection"), &edit_search_options.only_in_selection, NULL),
708 QUICK_CHECKBOX (N_ ("&Whole words"), &edit_search_options.whole_words, NULL),
709 QUICK_CHECKBOX (N_ ("&All charsets"), &edit_search_options.all_codepages, NULL),
710 QUICK_STOP_COLUMNS,
711 QUICK_BUTTONS_OK_CANCEL,
712 QUICK_END,
713
714 };
715
716 WRect r = { -1, -1, 0, 58 };
717
718 quick_dialog_t qdlg = {
719 .rect = r,
720 .title = N_ ("Replace"),
721 .help = "[Input Line Keys]",
722 .widgets = quick_widgets,
723 .callback = NULL,
724 .mouse_callback = NULL,
725 };
726
727 if (quick_dialog (&qdlg) != B_CANCEL)
728 edit->replace_mode = 0;
729 else
730 {
731 *replace_text = NULL;
732 *search_text = NULL;
733 }
734 }
735
736 g_strfreev (list_of_types);
737 }
738
739
740
741 int
742 edit_dialog_replace_prompt_show (WEdit *edit, char *from_text, char *to_text, int xpos, int ypos)
743 {
744 Widget *w = WIDGET (edit);
745
746
747 int dlg_height = 10;
748 int dlg_width;
749
750 char tmp[BUF_MEDIUM];
751 char *repl_from, *repl_to;
752 int retval;
753
754 if (xpos == -1)
755 xpos = w->rect.x + edit_options.line_state_width + 1;
756 if (ypos == -1)
757 ypos = w->rect.y + w->rect.lines / 2;
758
759 if ((edit->curs_row >= ypos - 1) && (edit->curs_row <= ypos + dlg_height - 1))
760 ypos -= dlg_height;
761
762 dlg_width = WIDGET (w->owner)->rect.cols - xpos - 1;
763
764 g_snprintf (tmp, sizeof (tmp), "\"%s\"", from_text);
765 repl_from = g_strdup (str_trunc (tmp, dlg_width - 7));
766
767 g_snprintf (tmp, sizeof (tmp), "\"%s\"", to_text);
768 repl_to = g_strdup (str_trunc (tmp, dlg_width - 7));
769
770 {
771 quick_widget_t quick_widgets[] = {
772
773 QUICK_LABEL (repl_from, NULL),
774 QUICK_LABEL (N_ ("Replace with:"), NULL),
775 QUICK_LABEL (repl_to, NULL),
776 QUICK_START_BUTTONS (TRUE, TRUE),
777 QUICK_BUTTON (N_ ("&Replace"), B_ENTER, NULL, NULL),
778 QUICK_BUTTON (N_ ("A&ll"), B_REPLACE_ALL, NULL, NULL),
779 QUICK_BUTTON (N_ ("&Skip"), B_SKIP_REPLACE, NULL, NULL),
780 QUICK_BUTTON (N_ ("&Cancel"), B_CANCEL, NULL, NULL),
781 QUICK_END,
782
783 };
784
785 WRect r = { ypos, xpos, 0, -1 };
786
787 quick_dialog_t qdlg = {
788 .rect = r,
789 .title = N_ ("Confirm replace"),
790 .help = NULL,
791 .widgets = quick_widgets,
792 .callback = NULL,
793 .mouse_callback = NULL,
794 };
795
796 retval = quick_dialog (&qdlg);
797 }
798
799 g_free (repl_from);
800 g_free (repl_to);
801
802 return retval;
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_search_options.backwards)
886 {
887 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1)
888 edit->search_start--;
889 }
890 else
891 {
892 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1)
893 edit->search_start++;
894 }
895
896 esm.first = TRUE;
897 esm.edit = edit;
898 esm.offset = edit->search_start;
899
900 status_msg_init (STATUS_MSG (&esm), _ ("Search"), 1.0, simple_status_msg_init_cb,
901 edit_search_status_update_cb, NULL);
902
903 do
904 {
905 gsize len = 0;
906
907 if (!edit_find (&esm, &len))
908 {
909 if (!(edit->search->error == MC_SEARCH_E_OK
910 || (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
911 edit_search_show_error (edit, _ ("Search"));
912 break;
913 }
914
915 once_found = TRUE;
916
917 edit->search_start = edit->search->normal_offset;
918
919
920 if (edit->search_start >= 0 && edit->search_start < edit->buffer.size)
921 {
922 gsize i;
923 GString *repl_str;
924
925 edit->found_start = edit->search_start;
926 edit->found_len = len;
927
928 edit_cursor_move (edit, edit->found_start - edit->buffer.curs1);
929 edit_scroll_screen_over_cursor (edit);
930
931 if (edit->replace_mode == 0)
932 {
933 long l;
934 int prompt;
935
936 l = edit->curs_row - WIDGET (edit)->rect.lines / 3;
937 if (l > 0)
938 edit_scroll_downward (edit, l);
939 if (l < 0)
940 edit_scroll_upward (edit, -l);
941
942 edit_scroll_screen_over_cursor (edit);
943 edit->force |= REDRAW_PAGE;
944 edit_render_keypress (edit);
945
946
947 edit_push_key_press (edit);
948
949 disp1 = edit_replace_cmd__conv_to_display (saved1);
950 disp2 = edit_replace_cmd__conv_to_display (saved2);
951 prompt = edit_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
952 g_free (disp1);
953 g_free (disp2);
954
955 if (prompt == B_REPLACE_ALL)
956 edit->replace_mode = 1;
957 else if (prompt == B_SKIP_REPLACE)
958 {
959 if (edit_search_options.backwards)
960 edit->search_start--;
961 else
962 edit->search_start++;
963 continue;
964 }
965 else if (prompt == B_CANCEL)
966 {
967 edit->replace_mode = -1;
968 break;
969 }
970 }
971
972 repl_str = mc_search_prepare_replace_str (edit->search, input2_str);
973
974 if (edit->search->error != MC_SEARCH_E_OK)
975 {
976 edit_search_show_error (edit, _ ("Replace"));
977 if (repl_str != NULL)
978 g_string_free (repl_str, TRUE);
979 break;
980 }
981
982
983 for (i = 0; i < len; i++)
984 edit_delete (edit, TRUE);
985
986 for (i = 0; i < repl_str->len; i++)
987 edit_insert (edit, repl_str->str[i]);
988
989 edit->found_len = repl_str->len;
990 g_string_free (repl_str, TRUE);
991 times_replaced++;
992
993
994 if (edit_search_options.backwards)
995 edit->search_start--;
996 else
997 {
998 edit->search_start += edit->found_len + (len == 0 ? 1 : 0);
999
1000 if (edit->search_start >= edit->buffer.size)
1001 break;
1002 }
1003
1004 edit_scroll_screen_over_cursor (edit);
1005 }
1006 else
1007 {
1008
1009 edit->search_start = edit->buffer.curs1;
1010 edit_update_curs_col (edit);
1011
1012 edit->force |= REDRAW_PAGE;
1013 edit_render_keypress (edit);
1014
1015 if (times_replaced == 0)
1016 query_dialog (_ ("Replace"), _ (STR_E_NOTFOUND), D_NORMAL, 1, _ ("&OK"));
1017 break;
1018 }
1019 }
1020 while (edit->replace_mode >= 0);
1021
1022 status_msg_deinit (STATUS_MSG (&esm));
1023 edit_scroll_screen_over_cursor (edit);
1024 edit->force |= REDRAW_COMPLETELY;
1025 edit_render_keypress (edit);
1026
1027 if (edit->replace_mode == 1 && times_replaced != 0)
1028 message (D_NORMAL, _ ("Replace"), _ ("%ld replacements made"), times_replaced);
1029
1030 cleanup:
1031 g_free (input1);
1032 g_free (input2);
1033 if (input2_str != NULL)
1034 g_string_free (input2_str, TRUE);
1035 }
1036
1037