1 /* editor high level editing commands.
3 Copyright (C) 1996, 1997 the Free Software Foundation
5 Authors: 1996, 1997 Paul Sheer
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 /* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
35 #include "editcmddef.h"
38 #include <X11/Xatom.h>
45 #include "../src/charsets.h"
50 /* search and replace: */
51 int replace_scanf
= 0;
52 int replace_regexp
= 0;
54 int replace_prompt
= 1;
55 int replace_whole
= 0;
57 int replace_backwards
= 0;
58 int search_create_bookmark
= 0;
60 /* queries on a save */
62 int edit_confirm_save
= 1;
64 int edit_confirm_save
= 0;
67 #define NUM_REPL_ARGS 64
68 #define MAX_REPL_LEN 1024
70 #if defined(MIDNIGHT) || defined(GTK)
72 static inline int my_lower_case (int c
)
74 return tolower(c
& 0xFF);
77 char *strcasechr (const unsigned char *s
, int c
)
79 for (c
= my_lower_case (c
); my_lower_case ((int) *s
) != c
; ++s
)
86 #include "../src/mad.h"
93 static void *memmove (void *dest
, const void *src
, size_t n
)
103 t
= (char *) dest
+ n
;
104 s
= (char *) src
+ n
;
112 /* #define itoa MY_itoa <---- this line is now in edit.h */
121 } while ((i
= i
/ 10));
128 This joins strings end on end and allocates memory for the result.
129 The result is later automatically free'd and must not be free'd
132 char *catstrs (const char *first
,...)
134 static char *stacked
[16] =
135 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
144 len
= strlen (first
);
145 va_start (ap
, first
);
147 while ((data
= va_arg (ap
, char *)) != 0)
148 len
+= strlen (data
);
156 stacked
[i
] = malloc (len
);
158 va_start (ap
, first
);
159 strcpy (stacked
[i
], first
);
160 while ((data
= va_arg (ap
, char *)) != 0)
161 strcat (stacked
[i
], data
);
170 void edit_help_cmd (WEdit
* edit
)
172 interactive_display (NULL
, "[Internal File Editor]");
173 edit
->force
|= REDRAW_COMPLETELY
;
176 void edit_refresh_cmd (WEdit
* edit
)
184 edit_get_syntax_color (edit
, -1, &fg
, &bg
);
187 #endif /* !HAVE_SLANG */
194 void edit_help_cmd (WEdit
* edit
)
198 void edit_refresh_cmd (WEdit
* edit
)
201 edit_get_syntax_color (edit
, -1, &fg
, &bg
);
202 edit
->force
|= REDRAW_COMPLETELY
;
205 void CRefreshEditor (WEdit
* edit
)
207 edit_refresh_cmd (edit
);
210 #endif /* MIDNIGHT */
215 /* three argument open */
216 int my_open (const char *pathname
, int flags
,...)
221 file
= open ((char *) pathname
, O_RDONLY
);
222 if (file
< 0 && (flags
& O_CREAT
)) { /* must it be created ? */
225 mode
= va_arg(ap
, mode_t
);
227 return creat ((char *) pathname
, mode
);
230 return open ((char *) pathname
, flags
);
236 #endif /* !MIDNIGHT */
238 /* "Oleg Yu. Repin" <repin@ssd.sscc.ru> added backup filenames
241 /* If 0 (quick save) then a) create/truncate <filename> file,
242 b) save to <filename>;
243 if 1 (safe save) then a) save to <tempnam>,
244 b) rename <tempnam> to <filename>;
245 if 2 (do backups) then a) save to <tempnam>,
246 b) rename <filename> to <filename.backup_ext>,
247 c) rename <tempnam> to <filename>. */
249 /* returns 0 on error */
250 int edit_save_file (WEdit
* edit
, const char *filename
)
255 int this_save_mode
, fd
;
262 savename
= (char *) strdup ((char *) filename
);
264 if (vfs_file_is_local (filename
)) {
265 if ((fd
= open (savename
, O_WRONLY
)) == -1) {
267 * The file does not exists yet, so no safe save or
268 * backup are necessary.
273 this_save_mode
= option_save_mode
;
277 * FIXME - rename is not impemented in VFS, so only
278 * quick save is possible.
283 if (this_save_mode
> 0) {
284 char *savedir
, *slashpos
, *saveprefix
;
285 savedir
= (char *) strdup (".");
286 slashpos
= strrchr (filename
, '/');
289 savedir
= (char *) strdup (filename
);
290 savedir
[slashpos
- filename
+ 1] = '\0';
294 saveprefix
= concat_dir_and_file (savedir
, "cooledit");
295 fd
= mc_mkstemps(&savename
, saveprefix
, NULL
);
301 * Close for now because it needs to be reopened by
302 * VFS-aware mc_open() and MY_O_TEXT should be used.
307 if ((fd
= open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| MY_O_TEXT
,
308 edit
->stat1
.st_mode
)) == -1)
311 chmod (savename
, edit
->stat1
.st_mode
);
312 chown (savename
, edit
->stat1
.st_uid
, edit
->stat1
.st_gid
);
315 if ((p
= (char *) edit_get_write_filter (savename
, filename
))) {
319 file
= (FILE *) popen (p
, "w");
322 filelen
= edit_write_stream (edit
, file
);
326 if (pclose (file
) != 0) {
327 edit_error_dialog (_ (" Error "), catstrs (_ (" Error writing to pipe: "), p
, " ", 0));
333 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open pipe for writing: "), p
, " ", 0)));
338 #ifdef CR_LF_TRANSLATION
339 } else { /* optimised save */
340 filelen
= edit_write_stream (edit
, f
);
347 filelen
= edit
->last_byte
;
348 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
349 if (write (fd
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
355 if (write (fd
, (char *) edit
->buffers1
[buf
], edit
->curs1
& M_EDIT_BUF_SIZE
) != (edit
->curs1
& M_EDIT_BUF_SIZE
)) {
357 } else if (edit
->curs2
) {
359 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
360 if (write (fd
, (char *) edit
->buffers2
[buf
] + EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1, 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) != 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) {
364 if (write (fd
, (char *) edit
->buffers2
[buf
], EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
374 #endif /* CR_LF_TRANSLATION */
377 if (filelen
!= edit
->last_byte
)
379 if (this_save_mode
== 2)
380 if (rename (filename
, catstrs (filename
, option_backup_ext
, 0)) == -1)
382 if (this_save_mode
> 0)
383 if (rename (savename
, filename
) == -1)
396 I changed this from Oleg's original routine so
397 that option_backup_ext works with coolwidgets as well. This
398 does mean there is a memory leak - paul.
400 void menu_save_mode_cmd (void)
404 static char *str_result
;
405 static int save_mode_new
;
410 N_("Do backups -->")};
411 static QuickWidget widgets
[] =
413 {quick_button
, 18, DLG_X
, 7, DLG_Y
, N_("&Cancel"), 0,
414 B_CANCEL
, 0, 0, "c"},
415 {quick_button
, 6, DLG_X
, 7, DLG_Y
, N_("&Ok"), 0,
417 {quick_input
, 23, DLG_X
, 5, DLG_Y
, 0, 9,
418 0, 0, &str_result
, "edit-backup-ext"},
419 {quick_label
, 22, DLG_X
, 4, DLG_Y
, N_("Extension:"), 0,
420 0, 0, 0, "savemext"},
421 {quick_radio
, 4, DLG_X
, 3, DLG_Y
, "", 3,
422 0, &save_mode_new
, str
, "t"},
424 static QuickDialog dialog
=
425 {DLG_X
, DLG_Y
, -1, -1, N_(" Edit Save Mode "), "[Edit Save Mode]",
427 static int i18n_flag
= 0;
435 /* Ok/Cancel buttons */
436 l1
= strlen (_(widgets
[0].text
)) + strlen (_(widgets
[1].text
)) + 5;
437 maxlen
= max (maxlen
, l1
);
439 for (i
= 0; i
< 3; i
++ ) {
441 maxlen
= max (maxlen
, strlen (str
[i
]) + 7);
445 dlg_x
= maxlen
+ strlen (_(widgets
[3].text
)) + 5 + 1;
446 widgets
[2].hotkey_pos
= strlen (_(widgets
[3].text
)); /* input field length */
447 dlg_x
= min (COLS
, dlg_x
);
451 widgets
[1].relative_x
= i
;
452 widgets
[0].relative_x
= i
+ strlen (_(widgets
[1].text
)) + i
+ 4;
454 widgets
[2].relative_x
= widgets
[3].relative_x
= maxlen
+ 2;
456 for (i
= 0; i
< sizeof (widgets
)/sizeof (widgets
[0]); i
++)
457 widgets
[i
].x_divisions
= dlg_x
;
460 widgets
[2].text
= option_backup_ext
;
461 widgets
[4].value
= option_save_mode
;
462 if (quick_dialog (&dialog
) != B_ENTER
)
464 option_save_mode
= save_mode_new
;
465 option_backup_ext
= str_result
; /* this is a memory leak */
466 option_backup_ext_int
= 0;
467 str_result
[min (strlen (str_result
), sizeof (int))] = '\0';
468 memcpy ((char *) &option_backup_ext_int
, str_result
, strlen (option_backup_ext
));
471 void edit_split_filename (WEdit
* edit
, const char *f
)
474 free (edit
->filename
);
475 edit
->filename
= (char *) strdup (f
);
478 edit
->dir
= (char *) strdup ("");
486 static char *edit_canonicalize_pathname (const char *p
)
493 cwd
= g_get_current_dir ();
494 t
= g_malloc (strlen (cwd
) + strlen (p
) + 2);
502 r
= q
= malloc (strlen (p
) + 2);
509 if (!strncmp (p
, "/./", 3) || !strcmp (p
, "/."))
511 else if (!strncmp (p
, "/../", 4) || !strcmp (p
, "/..")) {
514 q
= strrchr (r
, '/');
527 /* get rid of trailing / */
537 void edit_split_filename (WEdit
* edit
, const char *longname
)
541 exp
= edit_canonicalize_pathname (longname
);
543 exp
= pathdup (longname
); /* this ensures a full path */
546 free (edit
->filename
);
549 p
= strrchr (exp
, '/');
550 edit
->filename
= (char *) strdup (++p
);
552 edit
->dir
= (char *) strdup (exp
);
556 #endif /* ! MIDNIGHT */
558 /* here we want to warn the user of overwriting an existing file, but only if they
559 have made a change to the filename */
560 /* returns 1 on success */
561 int edit_save_as_cmd (WEdit
* edit
)
563 /* This heads the 'Save As' dialog box */
565 int different_filename
= 0;
567 exp
= edit_get_save_file (edit
->dir
, edit
->filename
, _(" Save As "));
568 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
573 edit
->force
|= REDRAW_COMPLETELY
;
576 if (strcmp(catstrs (edit
->dir
, edit
->filename
, 0), exp
)) {
578 different_filename
= 1;
579 if ((file
= open ((char *) exp
, O_RDONLY
)) != -1) { /* the file exists */
581 if (edit_query_dialog2 (_(" Warning "),
582 _(" A file already exists with this name. "),
583 /* Push buttons to over-write the current file, or cancel the operation */
584 _("Overwrite"), _("Cancel"))) {
585 edit
->force
|= REDRAW_COMPLETELY
;
590 if (edit_save_file (edit
, exp
)) {
591 edit_split_filename (edit
, exp
);
594 #if defined(MIDNIGHT) || defined(GTK)
595 edit
->delete_file
= 0;
597 if (different_filename
&& !edit
->explicit_syntax
)
598 edit_load_syntax (edit
, 0, 0);
599 edit
->force
|= REDRAW_COMPLETELY
;
603 edit_error_dialog (_(" Save as "), get_sys_error (_(" Error trying to save file. ")));
604 edit
->force
|= REDRAW_COMPLETELY
;
609 edit
->force
|= REDRAW_COMPLETELY
;
613 /* {{{ Macro stuff starts here */
616 int raw_callback (struct Dlg_head
*h
, int key
, int Msg
)
620 attrset (REVERSE_COLOR
);
622 draw_box (h
, 1, 1, h
->lines
- 2, h
->cols
- 2);
624 attrset (COLOR_HOT_NORMAL
);
637 /* gets a raw key from the keyboard. Passing cancel = 1 draws
638 a cancel button thus allowing c-c etc.. Alternatively, cancel = 0
639 will return the next key pressed */
640 int edit_raw_key_query (char *heading
, char *query
, int cancel
)
642 int w
= strlen (query
) + 7;
643 struct Dlg_head
*raw_dlg
= create_dlg (0, 0, 7, w
, dialog_colors
,
645 raw_callback
, "[Raw Key Query]",
647 DLG_CENTER
| DLG_TRYUP
);
648 x_set_dialog_title (raw_dlg
, heading
);
649 raw_dlg
->raw
= 1; /* to return even a tab key */
651 add_widget (raw_dlg
, button_new (4, w
/ 2 - 5, B_CANCEL
, NORMAL_BUTTON
, _("Cancel"), 0, 0, 0));
652 add_widget (raw_dlg
, label_new (3 - cancel
, 2, query
, 0));
653 add_widget (raw_dlg
, input_new (3 - cancel
, w
- 5, INPUT_COLOR
, 2, "", 0));
655 w
= raw_dlg
->ret_value
;
656 destroy_dlg (raw_dlg
);
658 if (w
== XCTRL ('g') || w
== XCTRL ('c') || w
== ESC_CHAR
|| w
== B_CANCEL
)
660 /* hence ctrl-a (=B_CANCEL), ctrl-g, ctrl-c, and Esc are cannot returned */
666 int edit_raw_key_query (char *heading
, char *query
, int cancel
)
672 return CKeySymMod (CRawkeyQuery (0, 0, 0, heading
, query
));
676 #endif /* MIDNIGHT */
678 /* creates a macro file if it doesn't exist */
679 static FILE *edit_open_macro_file (const char *r
)
683 filename
= catstrs (home_dir
, MACRO_FILE
, 0);
684 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1)
687 return fopen (filename
, r
);
690 #define MAX_MACROS 1024
691 static int saved_macro
[MAX_MACROS
+ 1] =
693 static int saved_macros_loaded
= 0;
696 This is just to stop the macro file be loaded over and over for keys
697 that aren't defined to anything. On slow systems this could be annoying.
699 int macro_exists (int k
)
702 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
703 if (saved_macro
[i
] == k
)
708 /* returns 1 on error */
709 int edit_delete_macro (WEdit
* edit
, int k
)
711 struct macro macro
[MAX_MACRO_LENGTH
];
715 if (saved_macros_loaded
)
716 if ((j
= macro_exists (k
)) < 0)
718 g
= fopen (catstrs (home_dir
, TEMP_FILE
, 0), "w");
720 /* This heads the delete macro error dialog box */
721 edit_error_dialog (_(" Delete macro "),
722 /* 'Open' = load temp file */
723 get_sys_error (_(" Error trying to open temp file ")));
726 f
= edit_open_macro_file ("r");
728 /* This heads the delete macro error dialog box */
729 edit_error_dialog (_(" Delete macro "),
730 /* 'Open' = load temp file */
731 get_sys_error (_(" Error trying to open macro file ")));
736 n
= fscanf (f
, ("key '%d 0': "), &s
);
740 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
744 fprintf (g
, ("key '%d 0': "), s
);
745 for (i
= 0; i
< n
; i
++)
746 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
752 if (rename (catstrs (home_dir
, TEMP_FILE
, 0), catstrs (home_dir
, MACRO_FILE
, 0)) == -1) {
753 /* This heads the delete macro error dialog box */
754 edit_error_dialog (_(" Delete macro "),
755 get_sys_error (_(" Error trying to overwrite macro file ")));
758 if (saved_macros_loaded
)
759 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
763 /* returns 0 on error */
764 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
769 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
770 /* This heads the 'Macro' dialog box */
771 s
= edit_raw_key_query (_(" Macro "),
772 /* Input line for a single key press follows the ':' */
773 _(" Press the macro's new hotkey: "), 1);
774 edit
->force
|= REDRAW_COMPLETELY
;
776 if (edit_delete_macro (edit
, s
))
778 f
= edit_open_macro_file ("a+");
780 fprintf (f
, ("key '%d 0': "), s
);
781 for (i
= 0; i
< n
; i
++)
782 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
785 if (saved_macros_loaded
) {
786 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
791 /* This heads the 'Save Macro' dialog box */
792 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Error trying to open macro file ")));
797 void edit_delete_macro_cmd (WEdit
* edit
)
802 command
= edit_raw_key_query (_ (" Delete Macro "),
803 _ (" Press macro hotkey: "), 1);
805 /* This heads the 'Delete Macro' dialog box */
810 command
= CKeySymMod (CRawkeyQuery (0, 0, 0, _ (" Delete Macro "),
811 /* Input line for a single key press follows the ':' */
812 _ (" Press macro hotkey: ")));
819 edit_delete_macro (edit
, command
);
822 /* return 0 on error */
823 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
826 int s
, i
= 0, found
= 0;
828 if (saved_macros_loaded
)
829 if (macro_exists (k
) < 0)
832 if ((f
= edit_open_macro_file ("r"))) {
836 u
= fscanf (f
, ("key '%d 0': "), &s
);
839 if (!saved_macros_loaded
)
840 saved_macro
[i
++] = s
;
843 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
846 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
851 } while (!found
|| !saved_macros_loaded
);
852 if (!saved_macros_loaded
) {
854 saved_macros_loaded
= 1;
859 /* This heads the 'Load Macro' dialog box */
860 edit_error_dialog (_(" Load macro "),
861 get_sys_error (_(" Error trying to open macro file ")));
865 /* }}} Macro stuff starts here */
867 /* returns 1 on success */
868 int edit_save_confirm_cmd (WEdit
* edit
)
872 if (edit_confirm_save
) {
874 f
= catstrs (_(" Confirm save file? : "), edit
->filename
, " ", 0);
876 f
= catstrs (_(" Confirm save file? : "), edit
->dir
, edit
->filename
, " ", 0);
878 /* Buttons to 'Confirm save file' query */
879 if (edit_query_dialog2 (_(" Save file "), f
, _("Save"), _("Cancel")))
882 return edit_save_cmd (edit
);
886 /* returns 1 on success */
887 int edit_save_cmd (WEdit
* edit
)
889 if (!edit_save_file (edit
, catstrs (edit
->dir
, edit
->filename
, 0)))
890 return edit_save_as_cmd (edit
);
891 edit
->force
|= REDRAW_COMPLETELY
;
893 #if defined(MIDNIGHT) || defined(GTK)
894 edit
->delete_file
= 0;
901 /* returns 1 on success */
902 int edit_new_cmd (WEdit
* edit
)
904 if (edit
->modified
) {
905 if (edit_query_dialog2 (_ (" Warning "), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("Continue"), _ ("Cancel"))) {
906 edit
->force
|= REDRAW_COMPLETELY
;
910 edit
->force
|= REDRAW_COMPLETELY
;
912 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
915 /* returns 1 on error */
916 int edit_load_file_from_filename (WEdit
* edit
, char *exp
)
918 if (!edit_reload (edit
, exp
, 0, "", 0))
920 edit_split_filename (edit
, exp
);
925 int edit_load_cmd (WEdit
* edit
)
929 if (edit
->modified
) {
930 if (edit_query_dialog2 (_ (" Warning "), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("Continue"), _ ("Cancel"))) {
931 edit
->force
|= REDRAW_COMPLETELY
;
936 exp
= edit_get_load_file (edit
->dir
, edit
->filename
, _ (" Load "));
940 edit_load_file_from_filename (edit
, exp
);
943 edit
->force
|= REDRAW_COMPLETELY
;
948 if mark2 is -1 then marking is from mark1 to the cursor.
949 Otherwise its between the markers. This handles this.
950 Returns 1 if no text is marked.
952 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
954 if (edit
->mark1
!= edit
->mark2
) {
955 if (edit
->mark2
>= 0) {
956 *start_mark
= min (edit
->mark1
, edit
->mark2
);
957 *end_mark
= max (edit
->mark1
, edit
->mark2
);
959 *start_mark
= min (edit
->mark1
, edit
->curs1
);
960 *end_mark
= max (edit
->mark1
, edit
->curs1
);
961 edit
->column2
= edit
->curs_col
;
965 *start_mark
= *end_mark
= 0;
966 edit
->column2
= edit
->column1
= 0;
971 /*Block copy, move and delete commands */
972 extern int column_highlighting
;
975 #define space_width 1
977 extern int space_width
;
980 void edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
)
984 cursor
= edit
->curs1
;
985 col
= edit_get_col (edit
);
986 for (i
= 0; i
< size
; i
++) {
987 if (data
[i
] == '\n') { /* fill in and move to next line */
990 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
991 l
= width
- (edit_get_col (edit
) - col
);
993 edit_insert (edit
, ' ');
997 for (p
= edit
->curs1
;; p
++) {
998 if (p
== edit
->last_byte
)
999 edit_insert_ahead (edit
, '\n');
1000 if (edit_get_byte (edit
, p
) == '\n') {
1005 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1006 l
= col
- edit_get_col (edit
);
1007 while (l
>= space_width
) {
1008 edit_insert (edit
, ' ');
1013 edit_insert (edit
, data
[i
]);
1015 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1019 void edit_block_copy_cmd (WEdit
* edit
)
1021 long start_mark
, end_mark
, current
= edit
->curs1
;
1023 unsigned char *copy_buf
;
1025 edit_update_curs_col (edit
);
1027 if (eval_marks (edit
, &start_mark
, &end_mark
))
1029 if (column_highlighting
)
1030 if ((x
>= edit
->column1
&& x
< edit
->column2
) || (x
> edit
->column2
&& x
<= edit
->column1
))
1033 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1035 /* all that gets pushed are deletes hence little space is used on the stack */
1037 edit_push_markers (edit
);
1039 if (column_highlighting
) {
1040 edit_insert_column_of_text (edit
, copy_buf
, size
, abs (edit
->column2
- edit
->column1
));
1043 edit_insert_ahead (edit
, copy_buf
[size
]);
1047 edit_scroll_screen_over_cursor (edit
);
1049 if (column_highlighting
) {
1050 edit_set_markers (edit
, 0, 0, 0, 0);
1051 edit_push_action (edit
, COLUMN_ON
);
1052 column_highlighting
= 0;
1053 } else if (start_mark
< current
&& end_mark
> current
)
1054 edit_set_markers (edit
, start_mark
, end_mark
+ end_mark
- start_mark
, 0, 0);
1056 edit
->force
|= REDRAW_PAGE
;
1060 void edit_block_move_cmd (WEdit
* edit
)
1064 unsigned char *copy_buf
;
1065 long start_mark
, end_mark
;
1069 if (eval_marks (edit
, &start_mark
, &end_mark
))
1071 if (column_highlighting
) {
1072 edit_update_curs_col (edit
);
1074 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1075 if ((x
> edit
->column1
&& x
< edit
->column2
) || (x
> edit
->column2
&& x
< edit
->column1
))
1077 } else if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1080 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1081 if (edit_query_dialog2 (_ (" Warning "), _ (" Block is large, you may not be able to undo this action. "), _ ("Continue"), _ ("Cancel")))
1084 edit_push_markers (edit
);
1085 current
= edit
->curs1
;
1086 if (column_highlighting
) {
1087 int size
, c1
, c2
, line
;
1088 line
= edit
->curs_line
;
1089 if (edit
->mark2
< 0)
1090 edit_mark_cmd (edit
, 0);
1091 c1
= min (edit
->column1
, edit
->column2
);
1092 c2
= max (edit
->column1
, edit
->column2
);
1093 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1095 edit_block_delete_cmd (edit
);
1098 edit_move_to_line (edit
, line
);
1099 edit_cursor_move (edit
, edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), x
, 0) - edit
->curs1
);
1100 edit_insert_column_of_text (edit
, copy_buf
, size
, c2
- c1
);
1102 line
= edit
->curs_line
;
1103 edit_update_curs_col (edit
);
1105 edit_block_delete_cmd (edit
);
1106 edit_move_to_line (edit
, line
);
1107 edit_cursor_move (edit
, edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), x
, 0) - edit
->curs1
);
1109 edit_set_markers (edit
, 0, 0, 0, 0);
1110 edit_push_action (edit
, COLUMN_ON
);
1111 column_highlighting
= 0;
1113 copy_buf
= malloc (end_mark
- start_mark
);
1114 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1115 edit_scroll_screen_over_cursor (edit
);
1117 while (count
< end_mark
) {
1118 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
);
1121 edit_scroll_screen_over_cursor (edit
);
1122 edit_cursor_move (edit
, current
- edit
->curs1
- (((current
- edit
->curs1
) > 0) ? end_mark
- start_mark
: 0));
1123 edit_scroll_screen_over_cursor (edit
);
1124 while (count
-- > start_mark
)
1125 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1126 edit_set_markers (edit
, edit
->curs1
, edit
->curs1
+ end_mark
- start_mark
, 0, 0);
1128 edit_scroll_screen_over_cursor (edit
);
1130 edit
->force
|= REDRAW_PAGE
;
1133 void edit_cursor_to_bol (WEdit
* edit
);
1135 void edit_delete_column_of_text (WEdit
* edit
)
1137 long p
, q
, r
, m1
, m2
;
1141 eval_marks (edit
, &m1
, &m2
);
1142 n
= edit_move_forward (edit
, m1
, 0, m2
) + 1;
1143 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
1144 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
1150 r
= edit_bol (edit
, edit
->curs1
);
1151 p
= edit_move_forward3 (edit
, r
, b
, 0);
1152 q
= edit_move_forward3 (edit
, r
, c
, 0);
1157 edit_cursor_move (edit
, p
- edit
->curs1
);
1158 while (q
> p
) { /* delete line between margins */
1159 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
1163 if (n
) /* move to next line except on the last delete */
1164 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
1168 /* if success return 0 */
1169 int edit_block_delete (WEdit
* edit
)
1172 long start_mark
, end_mark
;
1173 if (eval_marks (edit
, &start_mark
, &end_mark
))
1175 if (column_highlighting
&& edit
->mark2
< 0)
1176 edit_mark_cmd (edit
, 0);
1177 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1178 /* Warning message with a query to continue or cancel the operation */
1179 if (edit_query_dialog2 (_ (" Warning "), _ (" Block is large, you may not be able to undo this action. "), _ (" Continue "), _ (" Cancel ")))
1181 edit_push_markers (edit
);
1182 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1183 edit_scroll_screen_over_cursor (edit
);
1185 if (start_mark
< end_mark
) {
1186 if (column_highlighting
) {
1187 if (edit
->mark2
< 0)
1188 edit_mark_cmd (edit
, 0);
1189 edit_delete_column_of_text (edit
);
1191 while (count
< end_mark
) {
1197 edit_set_markers (edit
, 0, 0, 0, 0);
1198 edit
->force
|= REDRAW_PAGE
;
1202 /* returns 1 if canceelled by user */
1203 int edit_block_delete_cmd (WEdit
* edit
)
1205 long start_mark
, end_mark
;
1206 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1207 edit_delete_line (edit
);
1210 return edit_block_delete (edit
);
1216 #define INPUT_INDEX 9
1217 #define SEARCH_DLG_WIDTH 58
1218 #define SEARCH_DLG_HEIGHT 10
1219 #define REPLACE_DLG_WIDTH 58
1220 #define REPLACE_DLG_HEIGHT 15
1221 #define CONFIRM_DLG_WIDTH 79
1222 #define CONFIRM_DLG_HEIGTH 6
1223 #define B_REPLACE_ALL B_USER+1
1224 #define B_REPLACE_ONE B_USER+2
1225 #define B_SKIP_REPLACE B_USER+3
1227 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1229 QuickWidget quick_widgets
[] =
1231 {quick_button
, 63, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("&Cancel"),
1232 0, B_CANCEL
, 0, 0, NULL
},
1233 {quick_button
, 50, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("o&Ne"),
1234 0, B_REPLACE_ONE
, 0, 0, NULL
},
1235 {quick_button
, 37, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("al&L"),
1236 0, B_REPLACE_ALL
, 0, 0, NULL
},
1237 {quick_button
, 21, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("&Skip"),
1238 0, B_SKIP_REPLACE
, 0, 0, NULL
},
1239 {quick_button
, 4, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("&Replace"),
1240 0, B_ENTER
, 0, 0, NULL
},
1241 {quick_label
, 2, CONFIRM_DLG_WIDTH
, 2, CONFIRM_DLG_HEIGTH
, 0,
1245 #ifndef HAVE_CHARSET
1246 quick_widgets
[5].text
= catstrs (_ (" Replace with: "), replace_text
, 0);
1250 quick_widgets
[5].text
= catstrs (msg
= _(" Replace with: "), replace_text
, 0);
1253 convert_to_display (quick_widgets
[5].text
+ strlen (msg
));
1257 QuickDialog Quick_input
=
1258 {CONFIRM_DLG_WIDTH
, CONFIRM_DLG_HEIGTH
, 0, 0, N_ (" Confirm replace "),
1259 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1261 Quick_input
.widgets
= quick_widgets
;
1263 Quick_input
.xpos
= xpos
;
1265 /* Sometimes menu can hide replaced text. I don't like it */
1267 if ((edit
->curs_row
>= ypos
- 1) && (edit
->curs_row
<= ypos
+ CONFIRM_DLG_HEIGTH
- 1))
1268 ypos
-= CONFIRM_DLG_HEIGTH
;
1270 Quick_input
.ypos
= ypos
;
1271 return quick_dialog (&Quick_input
);
1275 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1277 int treplace_scanf
= replace_scanf
;
1278 int treplace_regexp
= replace_regexp
;
1279 int treplace_all
= replace_all
;
1280 int treplace_prompt
= replace_prompt
;
1281 int treplace_backwards
= replace_backwards
;
1282 int treplace_whole
= replace_whole
;
1283 int treplace_case
= replace_case
;
1286 char *treplace_text
;
1288 QuickWidget quick_widgets
[] =
1290 {quick_button
, 6, 10, 12, REPLACE_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
1292 {quick_button
, 2, 10, 12, REPLACE_DLG_HEIGHT
, N_("&Ok"), 0, B_ENTER
, 0,
1294 {quick_checkbox
, 33, REPLACE_DLG_WIDTH
, 11, REPLACE_DLG_HEIGHT
, N_("scanf &Expression"), 0, 0,
1296 {quick_checkbox
, 33, REPLACE_DLG_WIDTH
, 10, REPLACE_DLG_HEIGHT
, N_("replace &All"), 0, 0,
1298 {quick_checkbox
, 33, REPLACE_DLG_WIDTH
, 9, REPLACE_DLG_HEIGHT
, N_("pr&Ompt on replace"), 0, 0,
1300 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 11, REPLACE_DLG_HEIGHT
, N_("&Backwards"), 0, 0,
1302 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 10, REPLACE_DLG_HEIGHT
, N_("&Regular expression"), 0, 0,
1304 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 9, REPLACE_DLG_HEIGHT
, N_("&Whole words only"), 0, 0,
1306 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 8, REPLACE_DLG_HEIGHT
, N_("case &Sensitive"), 0, 0,
1308 {quick_input
, 3, REPLACE_DLG_WIDTH
, 7, REPLACE_DLG_HEIGHT
, "", 52, 0, 0,
1310 {quick_label
, 2, REPLACE_DLG_WIDTH
, 6, REPLACE_DLG_HEIGHT
, N_(" Enter replacement argument order eg. 3,2,1,4 "), 0, 0,
1312 {quick_input
, 3, REPLACE_DLG_WIDTH
, 5, REPLACE_DLG_HEIGHT
, "", 52, 0, 0,
1314 {quick_label
, 2, REPLACE_DLG_WIDTH
, 4, REPLACE_DLG_HEIGHT
, N_(" Enter replacement string:"), 0, 0, 0,
1316 {quick_input
, 3, REPLACE_DLG_WIDTH
, 3, REPLACE_DLG_HEIGHT
, "", 52, 0, 0,
1318 {quick_label
, 2, REPLACE_DLG_WIDTH
, 2, REPLACE_DLG_HEIGHT
, N_(" Enter search string:"), 0, 0, 0,
1322 quick_widgets
[2].result
= &treplace_scanf
;
1323 quick_widgets
[3].result
= &treplace_all
;
1324 quick_widgets
[4].result
= &treplace_prompt
;
1325 quick_widgets
[5].result
= &treplace_backwards
;
1326 quick_widgets
[6].result
= &treplace_regexp
;
1327 quick_widgets
[7].result
= &treplace_whole
;
1328 quick_widgets
[8].result
= &treplace_case
;
1329 quick_widgets
[9].str_result
= &targ_order
;
1330 quick_widgets
[9].text
= *arg_order
;
1331 quick_widgets
[11].str_result
= &treplace_text
;
1332 quick_widgets
[11].text
= *replace_text
;
1333 quick_widgets
[13].str_result
= &tsearch_text
;
1334 quick_widgets
[13].text
= *search_text
;
1336 QuickDialog Quick_input
=
1337 {REPLACE_DLG_WIDTH
, REPLACE_DLG_HEIGHT
, -1, 0, N_(" Replace "),
1338 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1340 Quick_input
.widgets
= quick_widgets
;
1342 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
1343 *arg_order
= *(quick_widgets
[INPUT_INDEX
].str_result
);
1344 *replace_text
= *(quick_widgets
[INPUT_INDEX
+ 2].str_result
);
1345 *search_text
= *(quick_widgets
[INPUT_INDEX
+ 4].str_result
);
1346 replace_scanf
= treplace_scanf
;
1347 replace_backwards
= treplace_backwards
;
1348 replace_regexp
= treplace_regexp
;
1349 replace_all
= treplace_all
;
1350 replace_prompt
= treplace_prompt
;
1351 replace_whole
= treplace_whole
;
1352 replace_case
= treplace_case
;
1356 *replace_text
= NULL
;
1357 *search_text
= NULL
;
1364 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1366 int treplace_scanf
= replace_scanf
;
1367 int treplace_regexp
= replace_regexp
;
1368 int treplace_whole
= replace_whole
;
1369 int treplace_case
= replace_case
;
1370 int treplace_backwards
= replace_backwards
;
1373 QuickWidget quick_widgets
[] =
1375 {quick_button
, 6, 10, 7, SEARCH_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
1377 {quick_button
, 2, 10, 7, SEARCH_DLG_HEIGHT
, N_("&Ok"), 0, B_ENTER
, 0,
1379 {quick_checkbox
, 33, SEARCH_DLG_WIDTH
, 6, SEARCH_DLG_HEIGHT
, N_("scanf &Expression"), 0, 0,
1381 {quick_checkbox
, 33, SEARCH_DLG_WIDTH
, 5, SEARCH_DLG_HEIGHT
, N_("&Backwards"), 0, 0,
1383 {quick_checkbox
, 4, SEARCH_DLG_WIDTH
, 6, SEARCH_DLG_HEIGHT
, N_("&Regular expression"), 0, 0,
1385 {quick_checkbox
, 4, SEARCH_DLG_WIDTH
, 5, SEARCH_DLG_HEIGHT
, N_("&Whole words only"), 0, 0,
1387 {quick_checkbox
, 4, SEARCH_DLG_WIDTH
, 4, SEARCH_DLG_HEIGHT
, N_("case &Sensitive"), 0, 0,
1389 {quick_input
, 3, SEARCH_DLG_WIDTH
, 3, SEARCH_DLG_HEIGHT
, "", 52, 0, 0,
1391 {quick_label
, 2, SEARCH_DLG_WIDTH
, 2, SEARCH_DLG_HEIGHT
, N_(" Enter search string:"), 0, 0, 0,
1395 quick_widgets
[2].result
= &treplace_scanf
;
1396 quick_widgets
[3].result
= &treplace_backwards
;
1397 quick_widgets
[4].result
= &treplace_regexp
;
1398 quick_widgets
[5].result
= &treplace_whole
;
1399 quick_widgets
[6].result
= &treplace_case
;
1400 quick_widgets
[7].str_result
= &tsearch_text
;
1401 quick_widgets
[7].text
= *search_text
;
1404 QuickDialog Quick_input
=
1405 {SEARCH_DLG_WIDTH
, SEARCH_DLG_HEIGHT
, -1, 0, N_(" Search "),
1406 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1408 Quick_input
.widgets
= quick_widgets
;
1410 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
1411 *search_text
= *(quick_widgets
[7].str_result
);
1412 replace_scanf
= treplace_scanf
;
1413 replace_backwards
= treplace_backwards
;
1414 replace_regexp
= treplace_regexp
;
1415 replace_whole
= treplace_whole
;
1416 replace_case
= treplace_case
;
1419 *search_text
= NULL
;
1431 #define B_SKIP_REPLACE 1
1432 #define B_REPLACE_ALL 2
1433 #define B_REPLACE_ONE 3
1436 extern CWidget
*wedit
;
1440 void edit_search_replace_dialog (Window parent
, int x
, int y
, char **search_text
, char **replace_text
, char **arg_order
, char *heading
, int option
)
1446 int xh
, yh
, h
, xb
, ys
, yc
, yb
, yr
;
1448 int text_input_width
;
1453 win
= CDrawHeadedDialog ("replace", parent
, x
, y
, heading
);
1454 CGetHintPos (&xh
, &h
);
1456 xh
+= NEXT_SPACING
;
1460 CIdent ("replace")->position
= WINDOW_ALWAYS_RAISED
;
1461 /* An input line comes after the ':' */
1462 (CDrawText ("replace.t1", win
, xh
, h
, _(" Enter search text : ")))->hotkey
= 'E';
1464 CGetHintPos (0, &yh
);
1465 (m
= CDrawTextInput ("replace.sinp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 8192, *search_text
))->hotkey
= 'E';
1468 CGetHintPos (0, &yh
);
1469 (CDrawText ("replace.t2", win
, xh
, yh
, _(" Enter replace text : ")))->hotkey
= 'n';
1470 CGetHintPos (0, &yh
);
1471 (CDrawTextInput ("replace.rinp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 8192, *replace_text
))->hotkey
= 'n';
1472 CSetToolHint ("replace.t2", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
1473 CSetToolHint ("replace.rinp", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
1474 CGetHintPos (0, &yh
);
1475 (CDrawText ("replace.t3", win
, xh
, yh
, _(" Enter argument (or substring) order : ")))->hotkey
= 'o';
1476 CGetHintPos (0, &yh
);
1477 (CDrawTextInput ("replace.ainp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 256, *arg_order
))->hotkey
= 'o';
1479 CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
1480 CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
1482 CGetHintPos (0, &yh
);
1484 /* The following are check boxes */
1485 CDrawSwitch ("replace.ww", win
, xh
, yh
, replace_whole
, _(" Whole words only "), 0);
1486 CGetHintPos (0, &yh
);
1487 CDrawSwitch ("replace.case", win
, xh
, yh
, replace_case
, _(" Case sensitive "), 0);
1489 CGetHintPos (0, &yh
);
1490 CDrawSwitch ("replace.reg", win
, xh
, yh
, replace_regexp
, _(" Regular expression "), 1);
1491 CSetToolHint ("replace.reg", _("See the regex man page for how\nto compose a regular expression"));
1492 CSetToolHint ("replace.reg.label", _("See the regex man page for how\nto compose a regular expression"));
1494 CGetHintPos (0, &yh
);
1495 CGetHintPos (&xb
, 0);
1497 xb
+= NEXT_SPACING
;
1499 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1500 CDrawSwitch ("replace.bkwd", win
, xh
, yh
, replace_backwards
, _(" Backwards "), 0);
1502 CSetToolHint ("replace.bkwd", _("Warning: Searching backward can be slow"));
1503 CSetToolHint ("replace.bkwd.label", _("Warning: Searching backward can be slow"));
1507 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
)
1510 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1511 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
)
1516 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
)
1524 CDrawSwitch ("replace.pr", win
, xb
, yr
, replace_prompt
, _(" Prompt on replace "), 0);
1526 CSetToolHint ("replace.pr", _("Ask before making each replacement"));
1527 CGetHintPos (0, &yr
);
1528 CDrawSwitch ("replace.all", win
, xb
, yr
, replace_all
, _(" Replace all "), 0);
1530 CSetToolHint ("replace.all", _("Replace repeatedly"));
1531 CGetHintPos (0, &yr
);
1533 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
) {
1534 CDrawSwitch ("replace.bkmk", win
, xb
, yr
, search_create_bookmark
, _(" Bookmarks "), 0);
1536 CSetToolHint ("replace.bkmk", _("Create bookmarks at all lines found"));
1537 CSetToolHint ("replace.bkmk.label", _("Create bookmarks at all lines found"));
1538 CGetHintPos (0, &yr
);
1540 CDrawSwitch ("replace.scanf", win
, xb
, yr
, replace_scanf
, _(" Scanf expression "), 1);
1542 CSetToolHint ("replace.scanf", _("Allows entering of a C format string,\nsee the scanf man page"));
1544 get_hint_limits (&x
, &y
);
1547 int btn_width
, x
, y
;
1548 CGetHintPos (&x
, &y
);
1550 y
+= NEXT_SPACING
* 2 ;
1551 x
+= NEXT_SPACING
* 2 ;
1552 CTextSize (&btn_width
, 0, " Cancel ");
1553 btn_width
+= 4 + BUTTON_RELIEF
* 2;
1554 x
-= (btn_width
+ NEXT_SPACING
) * 2 + NEXT_SPACING
;
1556 CDrawButton ("replace.ok", win
, x
+btn_width
+ NEXT_SPACING
* 2, y
, AUTO_WIDTH
, AUTO_HEIGHT
, " Ok ");
1557 CDrawButton ("replace.cancel", win
, x
, y
, AUTO_WIDTH
, AUTO_HEIGHT
, " Cancel ");
1558 CGetHintPos (0, &y
);
1559 x
+= (btn_width
+ NEXT_SPACING
) * 2 + NEXT_SPACING
;
1560 reset_hint_pos (x
, y
+ NEXT_SPACING
*2);
1563 CDrawPixmapButton ("replace.ok", win
, x
- WIDGET_SPACING
- TICK_BUTTON_WIDTH
, h
, PIXMAP_BUTTON_TICK
);
1564 CDrawPixmapButton ("replace.cancel", win
, x
- WIDGET_SPACING
- TICK_BUTTON_WIDTH
, h
+ WIDGET_SPACING
+ TICK_BUTTON_WIDTH
, PIXMAP_BUTTON_CROSS
);
1567 CSetToolHint ("replace.ok", _("Begin search, Enter"));
1568 CSetToolHint ("replace.cancel", _("Abort this dialog, Esc"));
1569 CSetSizeHintPos ("replace");
1570 CMapDialog ("replace");
1572 m
= CIdent ("replace");
1574 text_input_width
= m
->width
- WIDGET_SPACING
* 3 - 4 - NEXT_SPACING
*2 ;
1576 text_input_width
= m
->width
- WIDGET_SPACING
* 3 - 4 - TICK_BUTTON_WIDTH
;
1578 CSetWidgetSize ("replace.sinp", text_input_width
, (CIdent ("replace.sinp"))->height
);
1580 CSetWidgetSize ("replace.rinp", text_input_width
, (CIdent ("replace.rinp"))->height
);
1581 CSetWidgetSize ("replace.ainp", text_input_width
, (CIdent ("replace.ainp"))->height
);
1583 CFocus (CIdent ("replace.sinp"));
1586 CNextEvent (&xev
, &cev
);
1587 if (!CIdent ("replace")) {
1591 if (!strcmp (cev
.ident
, "replace.cancel") || cev
.command
== CK_Cancel
) {
1595 if (!strcmp (cev
.ident
, "replace.reg") || !strcmp (cev
.ident
, "replace.scanf")) {
1596 if (CIdent ("replace.reg")->keypressed
|| CIdent ("replace.scanf")->keypressed
) {
1597 if (!(CIdent ("replace.case")->keypressed
)) {
1598 CIdent ("replace.case")->keypressed
= 1;
1599 CExpose ("replace.case");
1603 if (!strcmp (cev
.ident
, "replace.ok") || cev
.command
== CK_Enter
) {
1605 replace_all
= CIdent ("replace.all")->keypressed
;
1606 replace_prompt
= CIdent ("replace.pr")->keypressed
;
1607 *replace_text
= (char *) strdup (CIdent ("replace.rinp")->text
);
1608 *arg_order
= (char *) strdup (CIdent ("replace.ainp")->text
);
1610 *search_text
= (char *) strdup (CIdent ("replace.sinp")->text
);
1611 replace_whole
= CIdent ("replace.ww")->keypressed
;
1612 replace_case
= CIdent ("replace.case")->keypressed
;
1613 replace_scanf
= CIdent ("replace.scanf")->keypressed
;
1614 replace_regexp
= CIdent ("replace.reg")->keypressed
;
1616 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1617 replace_backwards
= CIdent ("replace.bkwd")->keypressed
;
1619 replace_backwards
= 0;
1622 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
) {
1623 search_create_bookmark
= CIdent ("replace.bkmk")->keypressed
;
1625 search_create_bookmark
= 0;
1631 CDestroyWidget ("replace");
1635 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1637 /* Heads the 'Search' dialog box */
1638 edit_search_replace_dialog (WIN_MESSAGES
, search_text
, 0, 0, _(" Search "), SEARCH_DIALOG_OPTION_BACKWARDS
| SEARCH_DIALOG_OPTION_BOOKMARK
);
1641 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1643 /* Heads the 'Replace' dialog box */
1644 edit_search_replace_dialog (WIN_MESSAGES
, search_text
, replace_text
, arg_order
, _(" Replace "), SEARCH_DIALOG_OPTION_BACKWARDS
);
1649 #include <libgnomeui/gtkcauldron.h>
1650 #include <libgnomeui/gnome-stock.h>
1652 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1655 s
= gtk_dialog_cauldron (
1656 "Search", GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
,
1657 " ( (Enter search text)d | %Eogxf )xf / ( ( %Cd // %Cd // %Cd ) || ( %Cd // %Cd )xf )xf / ( %Bxfgrq || %Bxfgq )f",
1658 search_text
, "search",
1659 "&Whole word", &replace_whole
,
1660 "Case &sensitive", &replace_case
,
1661 "&Regular expression", &replace_regexp
,
1662 "&Backwards", &replace_backwards
,
1663 "Scanf &expression", &replace_scanf
,
1664 GNOME_STOCK_BUTTON_OK
,
1665 GNOME_STOCK_BUTTON_CANCEL
1667 if (s
== GTK_CAULDRON_ESCAPE
|| !s
|| s
== GNOME_STOCK_BUTTON_CANCEL
)
1672 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1675 s
= gtk_dialog_cauldron (
1676 "Search", GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
,
1677 " ( (Enter search text)d | %Eogxf )xf / ( (Enter replace text)d | %Egxf )xf / ( (Enter argument order)d | %Egxf )xf / ( ( %Cd // %Cd // %Cd // %Cd ) || ( %Cd // %Cd // %Cd )xf )xf / ( %Bxfgrq || %Bxfgq )f",
1678 search_text
, "search",
1679 replace_text
, "replace",
1680 arg_order
, "arg_order",
1681 "&Whole word", &replace_whole
,
1682 "Case &sensitive", &replace_case
,
1683 "&Regular expression", &replace_regexp
,
1684 "&Backwards", &replace_backwards
,
1685 "Pr&ompt on replace", &replace_prompt
,
1686 "Replace &all", &replace_all
,
1687 "Scanf &expression", &replace_scanf
,
1688 GNOME_STOCK_BUTTON_OK
,
1689 GNOME_STOCK_BUTTON_CANCEL
1691 if (s
== GTK_CAULDRON_ESCAPE
|| !s
|| s
== GNOME_STOCK_BUTTON_CANCEL
)
1700 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1703 s
= gtk_dialog_cauldron (
1704 "Replace", GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
,
1705 " ( (Replace with:)d %Ld )xf / ( %Bxfrq || %Bxfq || %Bxfq || %Bxfq || %Bxfgq )f",
1707 "Replace", "Skip", "Replace all", "Replace one",
1708 GNOME_STOCK_BUTTON_CANCEL
1710 if (s
== GTK_CAULDRON_ESCAPE
|| !s
|| s
== GNOME_STOCK_BUTTON_CANCEL
)
1712 if (!strcmp (s
, "Replace all"))
1713 return B_REPLACE_ALL
;
1714 if (!strcmp (s
, "Replace one"))
1715 return B_REPLACE_ONE
;
1716 if (!strcmp (s
, "Skip"))
1717 return B_SKIP_REPLACE
;
1718 if (!strcmp (s
, "Replace"))
1720 /* Shouldn't ever reach this point */
1726 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1730 B_CANCEL
, B_ENTER
, B_SKIP_REPLACE
, B_REPLACE_ALL
, B_REPLACE_ONE
, B_CANCEL
1732 q
= CQueryDialog (WIN_MESSAGES
+ (edit
->curs_line
< 8 ? edit
->num_widget_lines
/ 2 * FONT_PIX_PER_LINE
+ CYof (edit
->widget
) : 0),
1733 _ (" Replace "), catstrs (_ (" Replace with: "), replace_text
, 0), _ ("Replace"), _ ("Skip"), _ ("Replace all"), _ ("Replace one"), _ ("Cancel"), 0);
1734 edit
->force
|= REDRAW_COMPLETELY
;
1742 long sargs
[NUM_REPL_ARGS
][256 / sizeof (long)];
1744 #define SCANF_ARGS sargs[0], sargs[1], sargs[2], sargs[3], \
1745 sargs[4], sargs[5], sargs[6], sargs[7], \
1746 sargs[8], sargs[9], sargs[10], sargs[11], \
1747 sargs[12], sargs[13], sargs[14], sargs[15]
1749 #define PRINTF_ARGS sargs[argord[0]], sargs[argord[1]], sargs[argord[2]], sargs[argord[3]], \
1750 sargs[argord[4]], sargs[argord[5]], sargs[argord[6]], sargs[argord[7]], \
1751 sargs[argord[8]], sargs[argord[9]], sargs[argord[10]], sargs[argord[11]], \
1752 sargs[argord[12]], sargs[argord[13]], sargs[argord[14]], sargs[argord[15]]
1755 /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
1756 /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
1757 int string_regexp_search (char *pattern
, char *string
, int len
, int match_type
, int match_bol
, int icase
, int *found_len
, void *d
)
1760 static char *old_pattern
= NULL
;
1761 static int old_type
, old_icase
;
1763 static regmatch_t s
[1];
1765 pmatch
= (regmatch_t
*) d
;
1769 if (!old_pattern
|| strcmp (old_pattern
, pattern
) || old_type
!= match_type
|| old_icase
!= icase
) {
1775 if (regcomp (&r
, pattern
, REG_EXTENDED
| (icase
? REG_ICASE
: 0))) {
1779 old_pattern
= (char *) strdup (pattern
);
1780 old_type
= match_type
;
1783 if (regexec (&r
, string
, d
? NUM_REPL_ARGS
: 1, pmatch
, ((match_bol
|| match_type
!= match_normal
) ? 0 : REG_NOTBOL
)) != 0) {
1787 *found_len
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1788 return (pmatch
[0].rm_so
);
1791 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1792 (and the above) routines to work properly - paul */
1794 long edit_find_string (long start
, unsigned char *exp
, int *len
, long last_byte
, int (*get_byte
) (void *, long), void *data
, int once_only
, void *d
)
1797 long l
= strlen ((char *) exp
), f
= 0;
1800 for (p
= 0; p
< l
; p
++) /* count conversions... */
1802 if (exp
[++p
] != '%') /* ...except for "%%" */
1805 if (replace_scanf
|| replace_regexp
) {
1808 unsigned char mbuf
[MAX_REPL_LEN
* 2 + 3];
1810 replace_scanf
= (!replace_regexp
); /* can't have both */
1814 if (replace_scanf
) {
1815 unsigned char e
[MAX_REPL_LEN
];
1816 if (n
>= NUM_REPL_ARGS
)
1820 for (p
= start
; p
< last_byte
&& p
< start
+ MAX_REPL_LEN
; p
++)
1821 buf
[p
- start
] = (*get_byte
) (data
, p
);
1823 for (p
= 0; exp
[p
] != 0; p
++)
1824 exp
[p
] = my_lower_case (exp
[p
]);
1825 for (p
= start
; p
< last_byte
&& p
< start
+ MAX_REPL_LEN
; p
++) {
1826 c
= (*get_byte
) (data
, p
);
1827 buf
[p
- start
] = my_lower_case (c
);
1831 buf
[(q
= p
- start
)] = 0;
1832 strcpy ((char *) e
, (char *) exp
);
1833 strcat ((char *) e
, "%n");
1837 *((int *) sargs
[n
]) = 0; /* --> here was the problem - now fixed: good */
1838 if (n
== sscanf ((char *) buf
, (char *) exp
, SCANF_ARGS
)) {
1839 if (*((int *) sargs
[n
])) {
1840 *len
= *((int *) sargs
[n
]);
1846 if (q
+ start
< last_byte
) {
1848 buf
[q
] = (*get_byte
) (data
, q
+ start
);
1850 c
= (*get_byte
) (data
, q
+ start
);
1851 buf
[q
] = my_lower_case (c
);
1857 buf
++; /* move the window along */
1858 if (buf
== mbuf
+ MAX_REPL_LEN
) { /* the window is about to go past the end of array, so... */
1859 memmove (mbuf
, buf
, strlen ((char *) buf
) + 1); /* reset it */
1864 } else { /* regexp matching */
1866 int found_start
, match_bol
, move_win
= 0;
1868 while (start
+ offset
< last_byte
) {
1869 match_bol
= (offset
== 0 || (*get_byte
) (data
, start
+ offset
- 1) == '\n');
1874 for (; p
< last_byte
&& q
< MAX_REPL_LEN
; p
++, q
++) {
1875 mbuf
[q
] = (*get_byte
) (data
, p
);
1876 if (mbuf
[q
] == '\n')
1885 found_start
= string_regexp_search ((char *) exp
, (char *) buf
, q
, match_normal
, match_bol
, !replace_case
, len
, d
);
1887 if (found_start
<= -2) { /* regcomp/regexec error */
1891 else if (found_start
== -1) /* not found: try next line */
1893 else if (*len
== 0) { /* null pattern: try again at next character */
1900 return (start
+ offset
- q
+ found_start
);
1905 if (buf
[q
- 1] != '\n') { /* incomplete line: try to recover */
1906 buf
= mbuf
+ MAX_REPL_LEN
/ 2;
1907 q
= strlen ((char *) buf
);
1908 memmove (mbuf
, buf
, q
);
1917 *len
= strlen ((char *) exp
);
1919 for (p
= start
; p
<= last_byte
- l
; p
++) {
1920 if ((*get_byte
) (data
, p
) == (unsigned char)exp
[0]) { /* check if first char matches */
1921 for (f
= 0, q
= 0; q
< l
&& f
< 1; q
++)
1922 if ((*get_byte
) (data
, q
+ p
) != (unsigned char)exp
[q
])
1931 for (p
= 0; exp
[p
] != 0; p
++)
1932 exp
[p
] = my_lower_case (exp
[p
]);
1934 for (p
= start
; p
<= last_byte
- l
; p
++) {
1935 if (my_lower_case ((*get_byte
) (data
, p
)) == (unsigned char)exp
[0]) {
1936 for (f
= 0, q
= 0; q
< l
&& f
< 1; q
++)
1937 if (my_lower_case ((*get_byte
) (data
, q
+ p
)) != (unsigned char)exp
[q
])
1951 long edit_find_forwards (long search_start
, unsigned char *exp
, int *len
, long last_byte
, int (*get_byte
) (void *, long), void *data
, int once_only
, void *d
)
1952 { /*front end to find_string to check for
1957 while ((p
= edit_find_string (p
, exp
, len
, last_byte
, get_byte
, data
, once_only
, d
)) >= 0) {
1958 if (replace_whole
) {
1959 /*If the bordering chars are not in option_whole_chars_search then word is whole */
1960 if (!strcasechr (option_whole_chars_search
, (*get_byte
) (data
, p
- 1))
1961 && !strcasechr (option_whole_chars_search
, (*get_byte
) (data
, p
+ *len
)))
1969 p
++; /*not a whole word so continue search. */
1974 long edit_find (long search_start
, unsigned char *exp
, int *len
, long last_byte
, int (*get_byte
) (void *, long), void *data
, void *d
)
1977 if (replace_backwards
) {
1978 while (search_start
>= 0) {
1979 p
= edit_find_forwards (search_start
, exp
, len
, last_byte
, get_byte
, data
, 1, d
);
1980 if (p
== search_start
)
1985 return edit_find_forwards (search_start
, exp
, len
, last_byte
, get_byte
, data
, 0, d
);
1990 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1992 #define snprintf(v) { \
1997 sprintf(s,q1,v,&n); \
2001 /* this function uses the sprintf command to do a vprintf */
2002 /* it takes pointers to arguments instead of the arguments themselves */
2003 int sprintf_p (char *str
, const char *fmt
,...)
2007 char *q
, *p
, *s
= str
;
2012 p
= q
= (char *) fmt
;
2014 while ((p
= strchr (p
, '%'))) {
2015 n
= (int) ((unsigned long) p
- (unsigned long) q
);
2016 strncpy (s
, q
, n
); /* copy stuff between format specifiers */
2044 strcpy (p1
, itoa (*va_arg (ap
, int *))); /* replace field width with a number */
2047 while (is_digit (*p
))
2054 strcpy (p1
, itoa (*va_arg (ap
, int *))); /* replace precision with a number */
2057 while (is_digit (*p
))
2060 /* flags done, now get argument */
2062 snprintf (va_arg (ap
, char *));
2063 } else if (*p
== 'h') {
2064 if (strchr ("diouxX", *p
))
2065 snprintf (*va_arg (ap
, short *));
2066 } else if (*p
== 'l') {
2068 if (strchr ("diouxX", *p
))
2069 snprintf (*va_arg (ap
, long *));
2070 } else if (strchr ("cdiouxX", *p
)) {
2071 snprintf (*va_arg (ap
, int *));
2072 } else if (*p
== 'L') {
2074 if (strchr ("EefgG", *p
))
2075 snprintf (*va_arg (ap
, double *)); /* should be long double */
2076 } else if (strchr ("EefgG", *p
)) {
2077 snprintf (*va_arg (ap
, double *));
2078 } else if (strchr ("DOU", *p
)) {
2079 snprintf (*va_arg (ap
, long *));
2080 } else if (*p
== 'p') {
2081 snprintf (*va_arg (ap
, void **));
2086 sprintf (s
, q
); /* print trailing leftover */
2087 return (unsigned long) s
- (unsigned long) str
+ strlen (s
);
2090 static void regexp_error (WEdit
*edit
)
2092 /* "Error: Syntax error in regular expression, or scanf expression contained too many %'s */
2093 edit_error_dialog (_(" Error "), _(" Invalid regular expression, or scanf expression with to many conversions "));
2096 /* call with edit = 0 before shutdown to close memory leaks */
2097 void edit_replace_cmd (WEdit
* edit
, int again
)
2099 static regmatch_t pmatch
[NUM_REPL_ARGS
];
2100 static char *old1
= NULL
;
2101 static char *old2
= NULL
;
2102 static char *old3
= NULL
;
2107 int replace_continue
;
2108 int treplace_prompt
= 0;
2110 long times_replaced
= 0, last_search
;
2111 char fin_string
[64];
2112 int argord
[NUM_REPL_ARGS
];
2129 last_search
= edit
->last_byte
;
2131 edit
->force
|= REDRAW_COMPLETELY
;
2133 exp1
= old1
? old1
: exp1
;
2134 exp2
= old2
? old2
: exp2
;
2135 exp3
= old3
? old3
: exp3
;
2140 exp1
= (char *) strdup (old1
);
2141 exp2
= (char *) strdup (old2
);
2142 exp3
= (char *) strdup (old3
);
2144 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2148 convert_to_display (exp1
);
2150 convert_to_display (exp2
);
2153 edit_replace_dialog (edit
, &exp1
, &exp2
, &exp3
);
2157 convert_from_input (exp1
);
2159 convert_from_input (exp2
);
2162 treplace_prompt
= replace_prompt
;
2165 if (!exp1
|| !*exp1
) {
2166 edit
->force
= REDRAW_COMPLETELY
;
2180 old1
= (char *) strdup (exp1
);
2181 old2
= (char *) strdup (exp2
);
2182 old3
= (char *) strdup (exp3
);
2187 while ((s
= strchr (exp3
, ' ')))
2188 memmove (s
, s
+ 1, strlen (s
));
2190 for (i
= 0; i
< NUM_REPL_ARGS
; i
++) {
2191 if ((unsigned long) s
!= 1 && s
< exp3
+ strlen (exp3
)) {
2192 if ((ord
= atoi (s
)))
2193 argord
[i
] = ord
- 1;
2196 s
= strchr (s
, ',') + 1;
2202 replace_continue
= replace_all
;
2204 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && replace_backwards
)
2205 edit
->search_start
--;
2207 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !replace_backwards
)
2208 edit
->search_start
++;
2213 new_start
= edit_find (edit
->search_start
, (unsigned char *) exp1
, &len
, last_search
,
2214 (int (*)(void *, long)) edit_get_byte
, (void *) edit
, pmatch
);
2215 if (new_start
== -3) {
2216 regexp_error (edit
);
2219 edit
->search_start
= new_start
;
2220 /*returns negative on not found or error in pattern */
2222 if (edit
->search_start
>= 0) {
2223 edit
->found_start
= edit
->search_start
;
2224 i
= edit
->found_len
= len
;
2226 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
2227 edit_scroll_screen_over_cursor (edit
);
2231 if (treplace_prompt
) {
2233 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
2235 edit_scroll_downward (edit
, l
);
2237 edit_scroll_upward (edit
, -l
);
2239 edit_scroll_screen_over_cursor (edit
);
2240 edit
->force
|= REDRAW_PAGE
;
2241 edit_render_keypress (edit
);
2243 /*so that undo stops at each query */
2244 edit_push_key_press (edit
);
2246 switch (edit_replace_prompt (edit
, exp2
, /*and prompt 2/3 down */
2248 (edit
->num_widget_columns
- CONFIRM_DLG_WIDTH
)/2, edit
->num_widget_lines
* 2 / 3)) {
2250 edit
->num_widget_columns
/ 2 - 33, edit
->num_widget_lines
* 2 / 3)) {
2254 case B_SKIP_REPLACE
:
2258 treplace_prompt
= 0;
2259 replace_continue
= 1;
2262 replace_continue
= 0;
2266 replace_continue
= 0;
2270 if (replace_yes
) { /* delete then insert new */
2271 if (replace_scanf
|| replace_regexp
) {
2272 char repl_str
[MAX_REPL_LEN
+ 2];
2273 if (replace_regexp
) { /* we need to fill in sargs just like with scanf */
2275 for (k
= 1; k
< NUM_REPL_ARGS
&& pmatch
[k
].rm_eo
>= 0; k
++) {
2277 t
= (unsigned char *) &sargs
[k
- 1][0];
2278 for (j
= 0; j
< pmatch
[k
].rm_eo
- pmatch
[k
].rm_so
&& j
< 255; j
++, t
++)
2279 *t
= (unsigned char) edit_get_byte (edit
, edit
->search_start
- pmatch
[0].rm_so
+ pmatch
[k
].rm_so
+ j
);
2282 for (; k
<= NUM_REPL_ARGS
; k
++)
2283 sargs
[k
- 1][0] = 0;
2285 if (sprintf_p (repl_str
, exp2
, PRINTF_ARGS
) >= 0) {
2289 while (repl_str
[++i
])
2290 edit_insert (edit
, repl_str
[i
]);
2292 edit_error_dialog (_ (" Replace "),
2293 /* "Invalid regexp string or scanf string" */
2294 _ (" Error in replacement format string. "));
2295 replace_continue
= 0;
2302 edit_insert (edit
, exp2
[i
]);
2304 edit
->found_len
= i
;
2306 /* so that we don't find the same string again */
2307 if (replace_backwards
) {
2308 last_search
= edit
->search_start
;
2309 edit
->search_start
--;
2311 edit
->search_start
+= i
;
2312 last_search
= edit
->last_byte
;
2314 edit_scroll_screen_over_cursor (edit
);
2316 edit
->search_start
= edit
->curs1
; /* try and find from right here for next search */
2317 edit_update_curs_col (edit
);
2319 edit
->force
|= REDRAW_PAGE
;
2320 edit_render_keypress (edit
);
2321 if (times_replaced
) {
2322 sprintf (fin_string
, _ (" %ld replacements made. "), times_replaced
);
2323 edit_message_dialog (_ (" Replace "), fin_string
);
2325 edit_message_dialog (_ (" Replace "), _ (" Search string not found. "));
2326 replace_continue
= 0;
2328 } while (replace_continue
);
2333 edit
->force
= REDRAW_COMPLETELY
;
2334 edit_scroll_screen_over_cursor (edit
);
2340 void edit_search_cmd (WEdit
* edit
, int again
)
2342 static char *old
= NULL
;
2352 exp
= old
? old
: exp
;
2353 if (again
) { /*ctrl-hotkey for search again. */
2356 exp
= (char *) strdup (old
);
2361 convert_to_display (exp
);
2364 edit_search_dialog (edit
, &exp
);
2368 convert_from_input (exp
);
2371 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2379 old
= (char *) strdup (exp
);
2381 if (search_create_bookmark
) {
2382 int found
= 0, books
= 0;
2383 int l
= 0, l_last
= -1;
2386 p
= edit_find (q
, (unsigned char *) exp
, &len
, edit
->last_byte
,
2387 (int (*)(void *, long)) edit_get_byte
, (void *) edit
, 0);
2391 l
+= edit_count_lines (edit
, q
, p
);
2393 book_mark_insert (edit
, l
, BOOK_MARK_FOUND_COLOR
);
2400 char fin_string
[64];
2401 /* in response to number of bookmarks added because of string being found %d times */
2402 sprintf (fin_string
, _ (" %d finds made, %d bookmarks added "), found
, books
);
2403 edit_message_dialog (_ (" Search "), fin_string
);
2405 edit_error_dialog (_ (" Search "), _ (" Search string not found. "));
2409 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && replace_backwards
)
2410 edit
->search_start
--;
2412 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !replace_backwards
)
2413 edit
->search_start
++;
2415 edit
->search_start
= edit_find (edit
->search_start
, (unsigned char *) exp
, &len
, edit
->last_byte
,
2416 (int (*)(void *, long)) edit_get_byte
, (void *) edit
, 0);
2418 if (edit
->search_start
>= 0) {
2419 edit
->found_start
= edit
->search_start
;
2420 edit
->found_len
= len
;
2422 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
2423 edit_scroll_screen_over_cursor (edit
);
2424 if (replace_backwards
)
2425 edit
->search_start
--;
2427 edit
->search_start
++;
2428 } else if (edit
->search_start
== -3) {
2429 edit
->search_start
= edit
->curs1
;
2430 regexp_error (edit
);
2432 edit
->search_start
= edit
->curs1
;
2433 edit_error_dialog (_ (" Search "), _ (" Search string not found. "));
2439 edit
->force
|= REDRAW_COMPLETELY
;
2440 edit_scroll_screen_over_cursor (edit
);
2444 /* Real edit only */
2445 void edit_quit_cmd (WEdit
* edit
)
2447 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2454 edit
->force
|= REDRAW_COMPLETELY
;
2455 if (edit
->modified
) {
2458 r
= gtk_dialog_cauldron (_ (" Quit "), GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
, " [ ( %Lxf )xf ]xf / ( %Bgxfq || %Bgxfq || %Bgxfq ) ",
2459 _ (" Current text was modified without a file save. \n Save with exit? "), GNOME_STOCK_BUTTON_CANCEL
, GNOME_STOCK_BUTTON_YES
, GNOME_STOCK_BUTTON_NO
);
2460 if (r
== GNOME_STOCK_BUTTON_YES
) {
2461 edit_push_markers (edit
);
2462 edit_set_markers (edit
, 0, 0, 0, 0);
2463 if (!edit_save_cmd (edit
))
2465 } else if (r
== GNOME_STOCK_BUTTON_NO
) {
2466 if (edit
->delete_file
)
2467 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
2473 switch (edit_query_dialog3 (_ (" Quit "), _ (" File was modified, Save with exit? "), _ ("Cancel quit"), _ ("&Yes"), _ ("&No"))) {
2475 /* Confirm 'Quit' dialog box */
2476 switch (edit_query_dialog3 (_ (" Quit "),
2477 _ (" Current text was modified without a file save. \n Save with exit? "), _ (" &Cancel quit "), _ (" &Yes "), _ (" &No "))) {
2480 edit_push_markers (edit
);
2481 edit_set_markers (edit
, 0, 0, 0, 0);
2482 if (!edit_save_cmd (edit
))
2487 if (edit
->delete_file
)
2488 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
2497 #if defined(MIDNIGHT) || defined(GTK)
2498 else if (edit
->delete_file
)
2499 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
2502 dlg_stop (edit
->widget
.parent
);
2506 extern char *edit_one_file
;
2516 #define TEMP_BUF_LEN 1024
2518 /* returns a null terminated length of text. Result must be free'd */
2519 unsigned char *edit_get_block (WEdit
* edit
, long start
, long finish
, int *l
)
2521 unsigned char *s
, *r
;
2522 r
= s
= malloc (finish
- start
+ 1);
2523 if (column_highlighting
) {
2525 while (start
< finish
) { /* copy from buffer, excluding chars that are out of the column 'margins' */
2527 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0, start
);
2528 c
= edit_get_byte (edit
, start
);
2529 if ((x
>= edit
->column1
&& x
< edit
->column2
)
2530 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
2537 *l
= finish
- start
;
2538 while (start
< finish
)
2539 *s
++ = edit_get_byte (edit
, start
++);
2545 /* save block, returns 1 on success */
2546 int edit_save_block (WEdit
* edit
, const char *filename
, long start
, long finish
)
2550 if ((file
= open ((char *) filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1)
2553 if (column_highlighting
) {
2554 unsigned char *block
, *p
;
2556 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
2558 r
= write (file
, p
, len
);
2568 len
= finish
- start
;
2569 buf
= malloc (TEMP_BUF_LEN
);
2570 while (start
!= finish
) {
2571 end
= min (finish
, start
+ TEMP_BUF_LEN
);
2572 for (; i
< end
; i
++)
2573 buf
[i
- start
] = edit_get_byte (edit
, i
);
2574 len
-= write (file
, (char *) buf
, end
- start
);
2585 /* copies a block to clipboard file */
2586 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
2588 return edit_save_block (edit
, catstrs (home_dir
, CLIP_FILE
, 0), start
, finish
);
2593 void paste_text (WEdit
* edit
, unsigned char *data
, unsigned int nitems
)
2598 edit_insert_ahead (edit
, *data
--);
2600 edit
->force
|= REDRAW_COMPLETELY
;
2603 char *selection_get_line (void *data
, int line
)
2605 static unsigned char t
[1024];
2606 struct selection
*s
;
2608 s
= (struct selection
*) data
;
2609 line
= (current_selection
+ line
+ 1) % NUM_SELECTION_HISTORY
;
2611 unsigned char *p
= s
[line
].text
;
2613 for (j
= 0; j
< s
[line
].len
; j
++) {
2658 void edit_paste_from_history (WEdit
* edit
)
2662 edit_update_curs_col (edit
);
2663 edit_update_curs_row (edit
);
2665 c
= max (20, edit
->num_widget_columns
- 5);
2670 i
= gtk_edit_list_box_dialog (c
, 10,
2671 0, NUM_SELECTION_HISTORY
- 10, NUM_SELECTION_HISTORY
- 1, NUM_SELECTION_HISTORY
,
2672 selection_get_line
, (void *) selection_history
);
2677 i
= CListboxDialog (WIN_MESSAGES
, c
, 10,
2678 0, NUM_SELECTION_HISTORY
- 10, NUM_SELECTION_HISTORY
- 1, NUM_SELECTION_HISTORY
,
2679 selection_get_line
, (void *) selection_history
);
2685 i
= (current_selection
+ i
+ 1) % NUM_SELECTION_HISTORY
;
2687 paste_text (edit
, selection_history
[i
].text
, selection_history
[i
].len
);
2688 edit
->force
|= REDRAW_COMPLETELY
;
2691 /* copies a block to the XWindows buffer */
2692 static int edit_XStore_block (WEdit
* edit
, long start
, long finish
)
2694 edit_get_selection (edit
);
2695 if (selection
.len
<= 512 * 1024) { /* we don't want to fill up the server */
2696 XStoreBytes (CDisplay
, (char *) selection
.text
, (int) selection
.len
);
2702 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
2704 long start_mark
, end_mark
;
2705 if (eval_marks (edit
, &start_mark
, &end_mark
))
2707 edit_XStore_block (edit
, start_mark
, end_mark
);
2708 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2709 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
2713 gtk_selection_owner_set (GTK_WIDGET (edit
->widget
), GDK_SELECTION_PRIMARY
, GDK_CURRENT_TIME
);
2714 edit
->widget
->editable
.selection_start_pos
= start_mark
;
2715 edit
->widget
->editable
.selection_end_pos
= end_mark
;
2716 edit
->widget
->editable
.has_selection
= TRUE
;
2718 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, CWindowOf (edit
->widget
), CurrentTime
);
2720 edit_mark_cmd (edit
, 1);
2724 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
2726 long start_mark
, end_mark
;
2727 if (eval_marks (edit
, &start_mark
, &end_mark
))
2729 edit_XStore_block (edit
, start_mark
, end_mark
);
2730 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2731 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2734 edit_block_delete_cmd (edit
);
2736 gtk_selection_owner_set (GTK_WIDGET (edit
->widget
), GDK_SELECTION_PRIMARY
, GDK_CURRENT_TIME
);
2737 edit
->widget
->editable
.selection_start_pos
= start_mark
;
2738 edit
->widget
->editable
.selection_end_pos
= end_mark
;
2739 edit
->widget
->editable
.has_selection
= TRUE
;
2741 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, CWindowOf (edit
->widget
), CurrentTime
);
2743 edit_mark_cmd (edit
, 1);
2747 void selection_paste (WEdit
* edit
, Window win
, unsigned prop
, int delete);
2749 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
2752 paste_text (edit
, selection
.text
, selection
.len
);
2753 else if (!XGetSelectionOwner (CDisplay
, XA_PRIMARY
))
2758 selection_paste (edit
, CRoot
, XA_CUT_BUFFER0
, False
);
2762 gtk_selection_convert (GTK_WIDGET (edit
->widget
), GDK_SELECTION_PRIMARY
,
2763 gdk_atom_intern ("COMPOUND_TEXT", FALSE
), GDK_CURRENT_TIME
);
2765 XConvertSelection (CDisplay
, XA_PRIMARY
, XA_STRING
,
2766 XInternAtom (CDisplay
, "VT_SELECTION", False
),
2767 CWindowOf (edit
->widget
), CurrentTime
);
2769 edit
->force
|= REDRAW_PAGE
;
2772 #else /* MIDNIGHT */
2774 void edit_paste_from_history (WEdit
*edit
)
2778 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
2780 long start_mark
, end_mark
;
2781 if (eval_marks (edit
, &start_mark
, &end_mark
))
2783 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2784 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
2787 edit_mark_cmd (edit
, 1);
2791 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
2793 long start_mark
, end_mark
;
2794 if (eval_marks (edit
, &start_mark
, &end_mark
))
2796 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2797 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2800 edit_block_delete_cmd (edit
);
2801 edit_mark_cmd (edit
, 1);
2805 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
2807 edit_insert_file (edit
, catstrs (home_dir
, CLIP_FILE
, 0));
2810 #endif /* MIDNIGHT */
2812 void edit_goto_cmd (WEdit
*edit
)
2818 sprintf (s
, "%d", l
);
2819 f
= input_dialog (_(" Goto line "), _(" Enter line: "), l
? s
: "");
2823 f
= gtk_edit_dialog_input ("goto", 150, l
? itoa (l
) : "", _(" Goto line "), _(" Enter line: "));
2827 sprintf (s
, "%d", l
);
2828 f
= (char *) input_dialog (_(" Goto line "), _(" Enter line: "), l
? s
: "");
2831 f
= CInputDialog ("goto", WIN_MESSAGES
, 150, l
? itoa (l
) : "", _(" Goto line "), _(" Enter line: "));
2837 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
2838 edit_move_to_line (edit
, l
- 1);
2839 edit
->force
|= REDRAW_COMPLETELY
;
2845 /*returns 1 on success */
2846 int edit_save_block_cmd (WEdit
* edit
)
2848 long start_mark
, end_mark
;
2850 if (eval_marks (edit
, &start_mark
, &end_mark
))
2852 exp
= edit_get_save_file (edit
->dir
, catstrs (home_dir
, CLIP_FILE
, 0), _ (" Save Block "));
2853 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2859 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
2861 edit
->force
|= REDRAW_COMPLETELY
;
2865 edit_error_dialog (_ (" Save Block "), get_sys_error (_ (" Error trying to save file. ")));
2869 edit
->force
|= REDRAW_COMPLETELY
;
2874 /* returns 1 on success */
2875 int edit_insert_file_cmd (WEdit
* edit
)
2877 char *exp
= edit_get_load_file (edit
->dir
, catstrs (home_dir
, CLIP_FILE
, 0), _ (" Insert File "));
2878 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2884 if (edit_insert_file (edit
, exp
)) {
2886 edit
->force
|= REDRAW_COMPLETELY
;
2890 edit_error_dialog (_ (" Insert file "), get_sys_error (_ (" Error trying to insert file. ")));
2894 edit
->force
|= REDRAW_COMPLETELY
;
2900 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2901 int edit_sort_cmd (WEdit
* edit
)
2903 static char *old
= 0;
2905 long start_mark
, end_mark
;
2908 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2909 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
2912 edit_save_block (edit
, catstrs (home_dir
, BLOCK_FILE
, 0), start_mark
, end_mark
);
2914 exp
= old
? old
: "";
2916 exp
= input_dialog (_(" Run Sort "),
2917 _(" Enter sort options (see manpage) separated by whitespace: "), exp
);
2925 e
= system (catstrs (" sort ", exp
, " ", home_dir
, BLOCK_FILE
, " > ", home_dir
, TEMP_FILE
, 0));
2927 if (e
== -1 || e
== 127) {
2928 edit_error_dialog (_(" Sort "),
2929 get_sys_error (_(" Error trying to execute sort command ")));
2932 sprintf (q
, "%d ", e
);
2933 edit_error_dialog (_(" Sort "),
2934 catstrs (_(" Sort returned non-zero: "), q
, 0));
2939 edit
->force
|= REDRAW_COMPLETELY
;
2941 if (edit_block_delete_cmd (edit
))
2943 edit_insert_file (edit
, catstrs (home_dir
, TEMP_FILE
, 0));
2947 /* if block is 1, a block must be highlighted and the shell command
2948 processes it. If block is 0 the shell command is a straight system
2949 command, that just produces some output which is to be inserted */
2950 void edit_block_process_cmd (WEdit
* edit
, const char *shell_cmd
, int block
)
2952 long start_mark
, end_mark
;
2955 FILE *script_home
= NULL
;
2956 FILE *script_src
= NULL
;
2957 FILE *block_file
= NULL
;
2959 char *o
= catstrs (mc_home
, shell_cmd
, 0); /* original source script */
2960 char *h
= catstrs (home_dir
, EDIT_DIR
, shell_cmd
, 0); /* home script */
2961 char *b
= catstrs (home_dir
, BLOCK_FILE
, 0); /* block file */
2962 char *e
= catstrs (home_dir
, ERROR_FILE
, 0); /* error file */
2964 if (! (script_home
= fopen (h
, "r"))) {
2965 if (! (script_home
= fopen (h
, "w"))) {
2966 edit_error_dialog ("",
2967 get_sys_error (catstrs (_ ("Error create script:"), h
, 0)));
2970 if (! (script_src
= fopen (o
, "r"))) {
2971 fclose (script_home
); unlink (h
);
2972 edit_error_dialog ("",
2973 get_sys_error (catstrs (_ ("Error read script:"), o
, 0)));
2976 while (fgets(buf
, sizeof(buf
), script_src
))
2977 fputs (buf
, script_home
);
2978 if (fclose(script_home
)) {
2979 edit_error_dialog ("",
2980 get_sys_error (catstrs (_ ("Error close script:"), h
, 0)));
2984 edit_error_dialog ("",
2985 get_sys_error (catstrs (_ ("Script created:"), h
, 0)));
2990 if (block
) { /* for marked block run indent formatter */
2991 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2992 edit_error_dialog (_("Process block"),
2993 _(" You must first highlight a block of text. "));
2996 edit_save_block (edit
, b
, start_mark
, end_mark
);
2998 /* run your script */
2999 execute (catstrs (home_dir
, EDIT_DIR
, shell_cmd
, " ",
3000 edit
->filename
, " ", home_dir
, BLOCK_FILE
, " ",
3001 home_dir
, ERROR_FILE
, 0));
3003 } else { /* for missing marked block run ... */
3004 execute (catstrs (EDIT_DIR
, shell_cmd
));
3007 edit_refresh_cmd (edit
);
3008 edit
->force
|= REDRAW_COMPLETELY
;
3010 /* insert result block */
3012 if (stat (e
, &s
) == 0) {
3013 if (!s
.st_size
) { /* no error messages */
3014 if (edit_block_delete_cmd (edit
))
3016 edit_insert_file (edit
, b
);
3018 edit_insert_file (edit
, e
);
3021 edit_error_dialog ("",
3022 get_sys_error (catstrs (_ ("Error trying to stat file:"), e
, 0)));
3023 edit
->force
|= REDRAW_COMPLETELY
;
3025 if ((block_file
= fopen (b
, "w")))
3026 fclose (block_file
);
3032 #endif /* MIDNIGHT */
3034 int edit_execute_cmd (WEdit
* edit
, int command
, int char_for_insertion
);
3036 /* prints at the cursor */
3037 /* returns the number of chars printed */
3038 int edit_print_string (WEdit
* e
, const char *s
)
3042 edit_execute_cmd (e
, -1, (unsigned char) s
[i
++]);
3043 e
->force
|= REDRAW_COMPLETELY
;
3044 edit_update_screen (e
);
3048 int edit_printf (WEdit
* e
, const char *fmt
,...)
3054 sprintf (s
, fmt
, pa
);
3055 i
= edit_print_string (e
, s
);
3062 /* FIXME: does this function break NT_OS2 ? */
3064 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
3069 s
= g_strdup_printf ("mail -s \"%s\" -c \"%s\" \"%s\"", subject
, cc
, to
);
3078 for (i
= 0; i
< edit
->last_byte
; i
++)
3079 fputc (edit_get_byte (edit
, i
), p
);
3084 #define MAIL_DLG_HEIGHT 12
3086 void edit_mail_dialog (WEdit
* edit
)
3089 char *tmail_subject
;
3092 static char *mail_cc_last
= 0;
3093 static char *mail_subject_last
= 0;
3094 static char *mail_to_last
= 0;
3096 QuickDialog Quick_input
=
3097 {50, MAIL_DLG_HEIGHT
, -1, 0, N_(" Mail "),
3098 "[Input Line Keys]", "quick_input", 0};
3100 QuickWidget quick_widgets
[] =
3102 {quick_button
, 6, 10, 9, MAIL_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
3104 {quick_button
, 2, 10, 9, MAIL_DLG_HEIGHT
, N_("&Ok"), 0, B_ENTER
, 0,
3106 {quick_input
, 3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
3107 0, "mail-dlg-input"},
3108 {quick_label
, 2, 50, 7, MAIL_DLG_HEIGHT
, N_(" Copies to"), 0, 0, 0,
3110 {quick_input
, 3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
3111 0, "mail-dlg-input-2"},
3112 {quick_label
, 2, 50, 5, MAIL_DLG_HEIGHT
, N_(" Subject"), 0, 0, 0,
3114 {quick_input
, 3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
3115 0, "mail-dlg-input-3"},
3116 {quick_label
, 2, 50, 3, MAIL_DLG_HEIGHT
, N_(" To"), 0, 0, 0,
3118 {quick_label
, 2, 50, 2, MAIL_DLG_HEIGHT
, N_(" mail -s <subject> -c <cc> <to>"), 0, 0, 0,
3122 quick_widgets
[2].str_result
= &tmail_cc
;
3123 quick_widgets
[2].text
= mail_cc_last
? mail_cc_last
: "";
3124 quick_widgets
[4].str_result
= &tmail_subject
;
3125 quick_widgets
[4].text
= mail_subject_last
? mail_subject_last
: "";
3126 quick_widgets
[6].str_result
= &tmail_to
;
3127 quick_widgets
[6].text
= mail_to_last
? mail_to_last
: "";
3129 Quick_input
.widgets
= quick_widgets
;
3131 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
3133 free (mail_cc_last
);
3134 if (mail_subject_last
)
3135 free (mail_subject_last
);
3137 free (mail_to_last
);
3138 mail_cc_last
= *(quick_widgets
[2].str_result
);
3139 mail_subject_last
= *(quick_widgets
[4].str_result
);
3140 mail_to_last
= *(quick_widgets
[6].str_result
);
3141 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);
3145 #endif /* MIDNIGHT */