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>
46 /* search and replace: */
47 int replace_scanf
= 0;
48 int replace_regexp
= 0;
50 int replace_prompt
= 1;
51 int replace_whole
= 0;
53 int replace_backwards
= 0;
54 int search_create_bookmark
= 0;
56 /* queries on a save */
58 int edit_confirm_save
= 1;
60 int edit_confirm_save
= 0;
63 #define NUM_REPL_ARGS 64
64 #define MAX_REPL_LEN 1024
66 #if defined(MIDNIGHT) || defined(GTK)
68 static inline int my_lower_case (int c
)
70 return tolower(c
& 0xFF);
73 char *strcasechr (const unsigned char *s
, int c
)
75 for (c
= my_lower_case (c
); my_lower_case ((int) *s
) != c
; ++s
)
82 #include "../src/mad.h"
89 static void *memmove (void *dest
, const void *src
, size_t n
)
99 t
= (char *) dest
+ n
;
100 s
= (char *) src
+ n
;
108 /* #define itoa MY_itoa <---- this line is now in edit.h */
117 } while ((i
= i
/ 10));
124 This joins strings end on end and allocates memory for the result.
125 The result is later automatically free'd and must not be free'd
128 char *catstrs (const char *first
,...)
130 static char *stacked
[16] =
131 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
140 len
= strlen (first
);
141 va_start (ap
, first
);
143 while ((data
= va_arg (ap
, char *)) != 0)
144 len
+= strlen (data
);
152 stacked
[i
] = malloc (len
);
154 va_start (ap
, first
);
155 strcpy (stacked
[i
], first
);
156 while ((data
= va_arg (ap
, char *)) != 0)
157 strcat (stacked
[i
], data
);
166 void edit_help_cmd (WEdit
* edit
)
168 char *hlpdir
= concat_dir_and_file (mc_home
, _("mc.hlp"));
169 interactive_display (hlpdir
, "[Internal File Editor]");
171 edit
->force
|= REDRAW_COMPLETELY
;
174 void edit_refresh_cmd (WEdit
* edit
)
182 edit_get_syntax_color (edit
, -1, &fg
, &bg
);
185 #endif /* !HAVE_SLANG */
192 void edit_help_cmd (WEdit
* edit
)
196 void edit_refresh_cmd (WEdit
* edit
)
199 edit_get_syntax_color (edit
, -1, &fg
, &bg
);
200 edit
->force
|= REDRAW_COMPLETELY
;
203 void CRefreshEditor (WEdit
* edit
)
205 edit_refresh_cmd (edit
);
208 #endif /* MIDNIGHT */
213 /* three argument open */
214 int my_open (const char *pathname
, int flags
,...)
219 file
= open ((char *) pathname
, O_RDONLY
);
220 if (file
< 0 && (flags
& O_CREAT
)) { /* must it be created ? */
223 mode
= va_arg(ap
, mode_t
);
225 return creat ((char *) pathname
, mode
);
228 return open ((char *) pathname
, flags
);
234 #endif /* !MIDNIGHT */
236 /* "Oleg Yu. Repin" <repin@ssd.sscc.ru> added backup filenames
239 /* If 0 (quick save) then a) create/truncate <filename> file,
240 b) save to <filename>;
241 if 1 (safe save) then a) save to <tempnam>,
242 b) rename <tempnam> to <filename>;
243 if 2 (do backups) then a) save to <tempnam>,
244 b) rename <filename> to <filename.backup_ext>,
245 c) rename <tempnam> to <filename>. */
247 /* returns 0 on error */
248 int edit_save_file (WEdit
* edit
, const char *filename
)
253 int this_save_mode
, fd
;
260 savename
= (char *) strdup ((char *) filename
);
262 if ((fd
= open (savename
, O_WRONLY
)) == -1) {
263 this_save_mode
= 0; /* the file does not exists yet, so no safe save or backup necessary */
266 this_save_mode
= option_save_mode
;
269 if (this_save_mode
> 0) {
270 char *savedir
, *slashpos
;
271 savedir
= (char *) strdup (".");
272 slashpos
= strrchr (filename
, '/');
275 savedir
= (char *) strdup (filename
);
276 savedir
[slashpos
- filename
+ 1] = '\0';
280 savename
= (char *) tempnam (savedir
, "cooledit");
286 if ((fd
= open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| MY_O_TEXT
, edit
->stat
.st_mode
)) == -1)
289 chmod (savename
, edit
->stat
.st_mode
);
290 chown (savename
, edit
->stat
.st_uid
, edit
->stat
.st_gid
);
293 if ((p
= (char *) edit_get_write_filter (savename
, filename
))) {
297 file
= (FILE *) popen (p
, "w");
300 filelen
= edit_write_stream (edit
, file
);
304 if (pclose (file
) != 0) {
305 edit_error_dialog (_ (" Error "), catstrs (_ (" Error writing to pipe: "), p
, " ", 0));
311 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open pipe for writing: "), p
, " ", 0)));
316 #ifdef CR_LF_TRANSLATION
317 } else { /* optimised save */
318 filelen
= edit_write_stream (edit
, f
);
325 filelen
= edit
->last_byte
;
326 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
327 if (write (fd
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
333 if (write (fd
, (char *) edit
->buffers1
[buf
], edit
->curs1
& M_EDIT_BUF_SIZE
) != (edit
->curs1
& M_EDIT_BUF_SIZE
)) {
335 } else if (edit
->curs2
) {
337 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
338 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
)) {
342 if (write (fd
, (char *) edit
->buffers2
[buf
], EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
352 #endif /* CR_LF_TRANSLATION */
355 if (filelen
!= edit
->last_byte
)
357 if (this_save_mode
== 2)
358 if (rename (filename
, catstrs (filename
, option_backup_ext
, 0)) == -1)
360 if (this_save_mode
> 0)
361 if (rename (savename
, filename
) == -1)
374 I changed this from Oleg's original routine so
375 that option_backup_ext works with coolwidgets as well. This
376 does mean there is a memory leak - paul.
378 void menu_save_mode_cmd (void)
382 static char *str_result
;
383 static int save_mode_new
;
388 N_("Do backups -->")};
389 static QuickWidget widgets
[] =
391 {quick_button
, 18, DLG_X
, 7, DLG_Y
, N_("&Cancel"), 0,
392 B_CANCEL
, 0, 0, "c"},
393 {quick_button
, 6, DLG_X
, 7, DLG_Y
, N_("&Ok"), 0,
395 {quick_input
, 23, DLG_X
, 5, DLG_Y
, 0, 9,
396 0, 0, &str_result
, "i"},
397 {quick_label
, 22, DLG_X
, 4, DLG_Y
, N_("Extension:"), 0,
398 0, 0, 0, "savemext"},
399 {quick_radio
, 4, DLG_X
, 3, DLG_Y
, "", 3,
400 0, &save_mode_new
, str
, "t"},
402 static QuickDialog dialog
=
403 {DLG_X
, DLG_Y
, -1, -1, N_(" Edit Save Mode "), "[Edit Save Mode]",
405 static int i18n_flag
= 0;
410 for (i
= 0; i
< 3; i
++ )
415 widgets
[2].text
= option_backup_ext
;
416 widgets
[4].value
= option_save_mode
;
417 if (quick_dialog (&dialog
) != B_ENTER
)
419 option_save_mode
= save_mode_new
;
420 option_backup_ext
= str_result
; /* this is a memory leak */
421 option_backup_ext_int
= 0;
422 str_result
[min (strlen (str_result
), sizeof (int))] = '\0';
423 memcpy ((char *) &option_backup_ext_int
, str_result
, strlen (option_backup_ext
));
426 void edit_split_filename (WEdit
* edit
, const char *f
)
429 free (edit
->filename
);
430 edit
->filename
= (char *) strdup (f
);
433 edit
->dir
= (char *) strdup ("");
440 static char cwd
[1040];
442 static char *canonicalize_pathname (const char *p
)
448 if (strlen (cwd
) == 0) {
450 getcwd (cwd
, MAX_PATH_LEN
);
455 t
= malloc (strlen (cwd
) + strlen (p
) + 2);
461 r
= q
= malloc (strlen (p
) + 2);
468 if (!strncmp (p
, "/./", 3) || !strcmp (p
, "/."))
470 else if (!strncmp (p
, "/../", 4) || !strcmp (p
, "/..")) {
473 q
= strrchr (r
, '/');
487 /* get rid of trailing / */
497 void edit_split_filename (WEdit
* edit
, const char *longname
)
501 exp
= canonicalize_pathname (longname
);
503 exp
= pathdup (longname
); /* this ensures a full path */
506 free (edit
->filename
);
509 p
= strrchr (exp
, '/');
510 edit
->filename
= (char *) strdup (++p
);
512 edit
->dir
= (char *) strdup (exp
);
516 #endif /* ! MIDNIGHT */
518 /* here we want to warn the user of overwriting an existing file, but only if they
519 have made a change to the filename */
520 /* returns 1 on success */
521 int edit_save_as_cmd (WEdit
* edit
)
523 /* This heads the 'Save As' dialog box */
525 int different_filename
= 0;
527 exp
= edit_get_save_file (edit
->dir
, edit
->filename
, _(" Save As "));
528 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
533 edit
->force
|= REDRAW_COMPLETELY
;
536 if (strcmp(catstrs (edit
->dir
, edit
->filename
, 0), exp
)) {
538 different_filename
= 1;
539 if ((file
= open ((char *) exp
, O_RDONLY
)) != -1) { /* the file exists */
541 if (edit_query_dialog2 (_(" Warning "),
542 _(" A file already exists with this name. "),
543 /* Push buttons to over-write the current file, or cancel the operation */
544 _("Overwrite"), _("Cancel"))) {
545 edit
->force
|= REDRAW_COMPLETELY
;
550 if (edit_save_file (edit
, exp
)) {
551 edit_split_filename (edit
, exp
);
554 #if defined(MIDNIGHT) || defined(GTK)
555 edit
->delete_file
= 0;
557 if (different_filename
&& !edit
->explicit_syntax
)
558 edit_load_syntax (edit
, 0, 0);
559 edit
->force
|= REDRAW_COMPLETELY
;
563 edit_error_dialog (_(" Save as "), get_sys_error (_(" Error trying to save file. ")));
564 edit
->force
|= REDRAW_COMPLETELY
;
569 edit
->force
|= REDRAW_COMPLETELY
;
573 /* {{{ Macro stuff starts here */
576 int raw_callback (struct Dlg_head
*h
, int key
, int Msg
)
580 attrset (REVERSE_COLOR
);
582 draw_box (h
, 1, 1, h
->lines
- 2, h
->cols
- 2);
584 attrset (COLOR_HOT_NORMAL
);
597 /* gets a raw key from the keyboard. Passing cancel = 1 draws
598 a cancel button thus allowing c-c etc.. Alternatively, cancel = 0
599 will return the next key pressed */
600 int edit_raw_key_query (char *heading
, char *query
, int cancel
)
602 int w
= strlen (query
) + 7;
603 struct Dlg_head
*raw_dlg
= create_dlg (0, 0, 7, w
, dialog_colors
,
605 raw_callback
, "[Raw Key Query]",
607 DLG_CENTER
| DLG_TRYUP
);
608 x_set_dialog_title (raw_dlg
, heading
);
609 raw_dlg
->raw
= 1; /* to return even a tab key */
611 add_widget (raw_dlg
, button_new (4, w
/ 2 - 5, B_CANCEL
, NORMAL_BUTTON
, _("Cancel"), 0, 0, 0));
612 add_widget (raw_dlg
, label_new (3 - cancel
, 2, query
, 0));
613 add_widget (raw_dlg
, input_new (3 - cancel
, w
- 5, INPUT_COLOR
, 2, "", 0));
615 w
= raw_dlg
->ret_value
;
616 destroy_dlg (raw_dlg
);
618 if (w
== XCTRL ('g') || w
== XCTRL ('c') || w
== ESC_CHAR
|| w
== B_CANCEL
)
620 /* hence ctrl-a (=B_CANCEL), ctrl-g, ctrl-c, and Esc are cannot returned */
626 int edit_raw_key_query (char *heading
, char *query
, int cancel
)
632 return CKeySymMod (CRawkeyQuery (0, 0, 0, heading
, query
));
636 #endif /* MIDNIGHT */
638 /* creates a macro file if it doesn't exist */
639 static FILE *edit_open_macro_file (const char *r
)
643 filename
= catstrs (home_dir
, MACRO_FILE
, 0);
644 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1)
647 return fopen (filename
, r
);
650 #define MAX_MACROS 1024
651 static int saved_macro
[MAX_MACROS
+ 1] =
653 static int saved_macros_loaded
= 0;
656 This is just to stop the macro file be loaded over and over for keys
657 that aren't defined to anything. On slow systems this could be annoying.
659 int macro_exists (int k
)
662 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
663 if (saved_macro
[i
] == k
)
668 /* returns 1 on error */
669 int edit_delete_macro (WEdit
* edit
, int k
)
671 struct macro macro
[MAX_MACRO_LENGTH
];
675 if (saved_macros_loaded
)
676 if ((j
= macro_exists (k
)) < 0)
678 g
= fopen (catstrs (home_dir
, TEMP_FILE
, 0), "w");
680 /* This heads the delete macro error dialog box */
681 edit_error_dialog (_(" Delete macro "),
682 /* 'Open' = load temp file */
683 get_sys_error (_(" Error trying to open temp file ")));
686 f
= edit_open_macro_file ("r");
688 /* This heads the delete macro error dialog box */
689 edit_error_dialog (_(" Delete macro "),
690 /* 'Open' = load temp file */
691 get_sys_error (_(" Error trying to open macro file ")));
696 n
= fscanf (f
, ("key '%d 0': "), &s
);
700 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
704 fprintf (g
, ("key '%d 0': "), s
);
705 for (i
= 0; i
< n
; i
++)
706 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
712 if (rename (catstrs (home_dir
, TEMP_FILE
, 0), catstrs (home_dir
, MACRO_FILE
, 0)) == -1) {
713 /* This heads the delete macro error dialog box */
714 edit_error_dialog (_(" Delete macro "),
715 get_sys_error (_(" Error trying to overwrite macro file ")));
718 if (saved_macros_loaded
)
719 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
723 /* returns 0 on error */
724 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
729 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
730 /* This heads the 'Macro' dialog box */
731 s
= edit_raw_key_query (_(" Macro "),
732 /* Input line for a single key press follows the ':' */
733 _(" Press the macro's new hotkey: "), 1);
734 edit
->force
|= REDRAW_COMPLETELY
;
736 if (edit_delete_macro (edit
, s
))
738 f
= edit_open_macro_file ("a+");
740 fprintf (f
, ("key '%d 0': "), s
);
741 for (i
= 0; i
< n
; i
++)
742 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
745 if (saved_macros_loaded
) {
746 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
751 /* This heads the 'Save Macro' dialog box */
752 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Error trying to open macro file ")));
757 void edit_delete_macro_cmd (WEdit
* edit
)
762 command
= edit_raw_key_query (_ (" Delete Macro "),
763 _ (" Press macro hotkey: "), 1);
765 /* This heads the 'Delete Macro' dialog box */
770 command
= CKeySymMod (CRawkeyQuery (0, 0, 0, _ (" Delete Macro "),
771 /* Input line for a single key press follows the ':' */
772 _ (" Press macro hotkey: ")));
779 edit_delete_macro (edit
, command
);
782 /* return 0 on error */
783 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
786 int s
, i
= 0, found
= 0;
788 if (saved_macros_loaded
)
789 if (macro_exists (k
) < 0)
792 if ((f
= edit_open_macro_file ("r"))) {
796 u
= fscanf (f
, ("key '%d 0': "), &s
);
799 if (!saved_macros_loaded
)
800 saved_macro
[i
++] = s
;
803 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
806 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
811 } while (!found
|| !saved_macros_loaded
);
812 if (!saved_macros_loaded
) {
814 saved_macros_loaded
= 1;
819 /* This heads the 'Load Macro' dialog box */
820 edit_error_dialog (_(" Load macro "),
821 get_sys_error (_(" Error trying to open macro file ")));
825 /* }}} Macro stuff starts here */
827 /* returns 1 on success */
828 int edit_save_confirm_cmd (WEdit
* edit
)
832 if (edit_confirm_save
) {
834 f
= catstrs (_(" Confirm save file? : "), edit
->filename
, " ", 0);
836 f
= catstrs (_(" Confirm save file? : "), edit
->dir
, edit
->filename
, " ", 0);
838 /* Buttons to 'Confirm save file' query */
839 if (edit_query_dialog2 (_(" Save file "), f
, _("Save"), _("Cancel")))
842 return edit_save_cmd (edit
);
846 /* returns 1 on success */
847 int edit_save_cmd (WEdit
* edit
)
849 if (!edit_save_file (edit
, catstrs (edit
->dir
, edit
->filename
, 0)))
850 return edit_save_as_cmd (edit
);
851 edit
->force
|= REDRAW_COMPLETELY
;
853 #if defined(MIDNIGHT) || defined(GTK)
854 edit
->delete_file
= 0;
861 /* returns 1 on success */
862 int edit_new_cmd (WEdit
* edit
)
864 if (edit
->modified
) {
865 if (edit_query_dialog2 (_ (" Warning "), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("Continue"), _ ("Cancel"))) {
866 edit
->force
|= REDRAW_COMPLETELY
;
870 edit
->force
|= REDRAW_COMPLETELY
;
872 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
875 /* returns 1 on error */
876 int edit_load_file_from_filename (WEdit
* edit
, char *exp
)
878 if (!edit_reload (edit
, exp
, 0, "", 0))
880 edit_split_filename (edit
, exp
);
885 int edit_load_cmd (WEdit
* edit
)
889 if (edit
->modified
) {
890 if (edit_query_dialog2 (_ (" Warning "), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("Continue"), _ ("Cancel"))) {
891 edit
->force
|= REDRAW_COMPLETELY
;
896 exp
= edit_get_load_file (edit
->dir
, edit
->filename
, _ (" Load "));
900 edit_load_file_from_filename (edit
, exp
);
903 edit
->force
|= REDRAW_COMPLETELY
;
908 if mark2 is -1 then marking is from mark1 to the cursor.
909 Otherwise its between the markers. This handles this.
910 Returns 1 if no text is marked.
912 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
914 if (edit
->mark1
!= edit
->mark2
) {
915 if (edit
->mark2
>= 0) {
916 *start_mark
= min (edit
->mark1
, edit
->mark2
);
917 *end_mark
= max (edit
->mark1
, edit
->mark2
);
919 *start_mark
= min (edit
->mark1
, edit
->curs1
);
920 *end_mark
= max (edit
->mark1
, edit
->curs1
);
921 edit
->column2
= edit
->curs_col
;
925 *start_mark
= *end_mark
= 0;
926 edit
->column2
= edit
->column1
= 0;
931 /*Block copy, move and delete commands */
932 extern int column_highlighting
;
935 #define space_width 1
937 extern int space_width
;
940 void edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
)
944 cursor
= edit
->curs1
;
945 col
= edit_get_col (edit
);
946 for (i
= 0; i
< size
; i
++) {
947 if (data
[i
] == '\n') { /* fill in and move to next line */
950 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
951 l
= width
- (edit_get_col (edit
) - col
);
953 edit_insert (edit
, ' ');
957 for (p
= edit
->curs1
;; p
++) {
958 if (p
== edit
->last_byte
)
959 edit_insert_ahead (edit
, '\n');
960 if (edit_get_byte (edit
, p
) == '\n') {
965 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
966 l
= col
- edit_get_col (edit
);
967 while (l
>= space_width
) {
968 edit_insert (edit
, ' ');
973 edit_insert (edit
, data
[i
]);
975 edit_cursor_move (edit
, cursor
- edit
->curs1
);
979 void edit_block_copy_cmd (WEdit
* edit
)
981 long start_mark
, end_mark
, current
= edit
->curs1
;
983 unsigned char *copy_buf
;
985 edit_update_curs_col (edit
);
987 if (eval_marks (edit
, &start_mark
, &end_mark
))
989 if (column_highlighting
)
990 if ((x
>= edit
->column1
&& x
< edit
->column2
) || (x
> edit
->column2
&& x
<= edit
->column1
))
993 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
995 /* all that gets pushed are deletes hence little space is used on the stack */
997 edit_push_markers (edit
);
999 if (column_highlighting
) {
1000 edit_insert_column_of_text (edit
, copy_buf
, size
, abs (edit
->column2
- edit
->column1
));
1003 edit_insert_ahead (edit
, copy_buf
[size
]);
1007 edit_scroll_screen_over_cursor (edit
);
1009 if (column_highlighting
) {
1010 edit_set_markers (edit
, 0, 0, 0, 0);
1011 edit_push_action (edit
, COLUMN_ON
);
1012 column_highlighting
= 0;
1013 } else if (start_mark
< current
&& end_mark
> current
)
1014 edit_set_markers (edit
, start_mark
, end_mark
+ end_mark
- start_mark
, 0, 0);
1016 edit
->force
|= REDRAW_PAGE
;
1020 void edit_block_move_cmd (WEdit
* edit
)
1024 unsigned char *copy_buf
;
1025 long start_mark
, end_mark
;
1029 if (eval_marks (edit
, &start_mark
, &end_mark
))
1031 if (column_highlighting
) {
1032 edit_update_curs_col (edit
);
1034 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1035 if ((x
> edit
->column1
&& x
< edit
->column2
) || (x
> edit
->column2
&& x
< edit
->column1
))
1037 } else if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1040 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1041 if (edit_query_dialog2 (_ (" Warning "), _ (" Block is large, you may not be able to undo this action. "), _ ("Continue"), _ ("Cancel")))
1044 edit_push_markers (edit
);
1045 current
= edit
->curs1
;
1046 if (column_highlighting
) {
1047 int size
, c1
, c2
, line
;
1048 line
= edit
->curs_line
;
1049 if (edit
->mark2
< 0)
1050 edit_mark_cmd (edit
, 0);
1051 c1
= min (edit
->column1
, edit
->column2
);
1052 c2
= max (edit
->column1
, edit
->column2
);
1053 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1055 edit_block_delete_cmd (edit
);
1058 edit_move_to_line (edit
, line
);
1059 edit_cursor_move (edit
, edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), x
, 0) - edit
->curs1
);
1060 edit_insert_column_of_text (edit
, copy_buf
, size
, c2
- c1
);
1062 line
= edit
->curs_line
;
1063 edit_update_curs_col (edit
);
1065 edit_block_delete_cmd (edit
);
1066 edit_move_to_line (edit
, line
);
1067 edit_cursor_move (edit
, edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), x
, 0) - edit
->curs1
);
1069 edit_set_markers (edit
, 0, 0, 0, 0);
1070 edit_push_action (edit
, COLUMN_ON
);
1071 column_highlighting
= 0;
1073 copy_buf
= malloc (end_mark
- start_mark
);
1074 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1075 edit_scroll_screen_over_cursor (edit
);
1077 while (count
< end_mark
) {
1078 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
);
1081 edit_scroll_screen_over_cursor (edit
);
1082 edit_cursor_move (edit
, current
- edit
->curs1
- (((current
- edit
->curs1
) > 0) ? end_mark
- start_mark
: 0));
1083 edit_scroll_screen_over_cursor (edit
);
1084 while (count
-- > start_mark
)
1085 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1086 edit_set_markers (edit
, edit
->curs1
, edit
->curs1
+ end_mark
- start_mark
, 0, 0);
1088 edit_scroll_screen_over_cursor (edit
);
1090 edit
->force
|= REDRAW_PAGE
;
1093 void edit_cursor_to_bol (WEdit
* edit
);
1095 void edit_delete_column_of_text (WEdit
* edit
)
1097 long p
, q
, r
, m1
, m2
;
1101 eval_marks (edit
, &m1
, &m2
);
1102 n
= edit_move_forward (edit
, m1
, 0, m2
) + 1;
1103 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
1104 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
1110 r
= edit_bol (edit
, edit
->curs1
);
1111 p
= edit_move_forward3 (edit
, r
, b
, 0);
1112 q
= edit_move_forward3 (edit
, r
, c
, 0);
1117 edit_cursor_move (edit
, p
- edit
->curs1
);
1118 while (q
> p
) { /* delete line between margins */
1119 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
1123 if (n
) /* move to next line except on the last delete */
1124 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
1128 /* if success return 0 */
1129 int edit_block_delete (WEdit
* edit
)
1132 long start_mark
, end_mark
;
1133 if (eval_marks (edit
, &start_mark
, &end_mark
))
1135 if (column_highlighting
&& edit
->mark2
< 0)
1136 edit_mark_cmd (edit
, 0);
1137 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1138 /* Warning message with a query to continue or cancel the operation */
1139 if (edit_query_dialog2 (_ (" Warning "), _ (" Block is large, you may not be able to undo this action. "), _ (" Continue "), _ (" Cancel ")))
1141 edit_push_markers (edit
);
1142 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1143 edit_scroll_screen_over_cursor (edit
);
1145 if (start_mark
< end_mark
) {
1146 if (column_highlighting
) {
1147 if (edit
->mark2
< 0)
1148 edit_mark_cmd (edit
, 0);
1149 edit_delete_column_of_text (edit
);
1151 while (count
< end_mark
) {
1157 edit_set_markers (edit
, 0, 0, 0, 0);
1158 edit
->force
|= REDRAW_PAGE
;
1162 /* returns 1 if canceelled by user */
1163 int edit_block_delete_cmd (WEdit
* edit
)
1165 long start_mark
, end_mark
;
1166 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1167 edit_delete_line (edit
);
1170 return edit_block_delete (edit
);
1176 #define INPUT_INDEX 9
1177 #define SEARCH_DLG_WIDTH 58
1178 #define SEARCH_DLG_HEIGHT 10
1179 #define REPLACE_DLG_WIDTH 58
1180 #define REPLACE_DLG_HEIGHT 15
1181 #define CONFIRM_DLG_WIDTH 79
1182 #define CONFIRM_DLG_HEIGTH 6
1183 #define B_REPLACE_ALL B_USER+1
1184 #define B_REPLACE_ONE B_USER+2
1185 #define B_SKIP_REPLACE B_USER+3
1187 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1189 QuickWidget quick_widgets
[] =
1191 {quick_button
, 63, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("&Cancel"),
1192 0, B_CANCEL
, 0, 0, NULL
},
1193 {quick_button
, 50, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("o&Ne"),
1194 0, B_REPLACE_ONE
, 0, 0, NULL
},
1195 {quick_button
, 37, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("al&L"),
1196 0, B_REPLACE_ALL
, 0, 0, NULL
},
1197 {quick_button
, 21, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("&Skip"),
1198 0, B_SKIP_REPLACE
, 0, 0, NULL
},
1199 {quick_button
, 4, CONFIRM_DLG_WIDTH
, 3, CONFIRM_DLG_HEIGTH
, N_ ("&Replace"),
1200 0, B_ENTER
, 0, 0, NULL
},
1201 {quick_label
, 2, CONFIRM_DLG_WIDTH
, 2, CONFIRM_DLG_HEIGTH
, 0,
1205 quick_widgets
[5].text
= catstrs (_ (" Replace with: "), replace_text
, 0);
1208 QuickDialog Quick_input
=
1209 {CONFIRM_DLG_WIDTH
, CONFIRM_DLG_HEIGTH
, 0, 0, N_ (" Confirm replace "),
1210 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1212 Quick_input
.widgets
= quick_widgets
;
1214 Quick_input
.xpos
= xpos
;
1216 /* Sometimes menu can hide replaced text. I don't like it */
1218 if ((edit
->curs_row
>= ypos
) && (edit
->curs_row
<= ypos
+ CONFIRM_DLG_HEIGTH
))
1219 ypos
-= CONFIRM_DLG_HEIGTH
;
1221 Quick_input
.ypos
= ypos
;
1222 return quick_dialog (&Quick_input
);
1226 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1228 int treplace_scanf
= replace_scanf
;
1229 int treplace_regexp
= replace_regexp
;
1230 int treplace_all
= replace_all
;
1231 int treplace_prompt
= replace_prompt
;
1232 int treplace_backwards
= replace_backwards
;
1233 int treplace_whole
= replace_whole
;
1234 int treplace_case
= replace_case
;
1237 char *treplace_text
;
1239 QuickWidget quick_widgets
[] =
1241 {quick_button
, 6, 10, 12, REPLACE_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
1243 {quick_button
, 2, 10, 12, REPLACE_DLG_HEIGHT
, N_("&Ok"), 0, B_ENTER
, 0,
1245 {quick_checkbox
, 33, REPLACE_DLG_WIDTH
, 11, REPLACE_DLG_HEIGHT
, N_("scanf &Expression"), 0, 0,
1247 {quick_checkbox
, 33, REPLACE_DLG_WIDTH
, 10, REPLACE_DLG_HEIGHT
, N_("replace &All"), 0, 0,
1249 {quick_checkbox
, 33, REPLACE_DLG_WIDTH
, 9, REPLACE_DLG_HEIGHT
, N_("pr&Ompt on replace"), 0, 0,
1251 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 11, REPLACE_DLG_HEIGHT
, N_("&Backwards"), 0, 0,
1253 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 10, REPLACE_DLG_HEIGHT
, N_("&Regular expression"), 0, 0,
1255 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 9, REPLACE_DLG_HEIGHT
, N_("&Whole words only"), 0, 0,
1257 {quick_checkbox
, 4, REPLACE_DLG_WIDTH
, 8, REPLACE_DLG_HEIGHT
, N_("case &Sensitive"), 0, 0,
1259 {quick_input
, 3, REPLACE_DLG_WIDTH
, 7, REPLACE_DLG_HEIGHT
, "", 52, 0, 0,
1261 {quick_label
, 2, REPLACE_DLG_WIDTH
, 6, REPLACE_DLG_HEIGHT
, N_(" Enter replacement argument order eg. 3,2,1,4 "), 0, 0,
1263 {quick_input
, 3, REPLACE_DLG_WIDTH
, 5, REPLACE_DLG_HEIGHT
, "", 52, 0, 0,
1265 {quick_label
, 2, REPLACE_DLG_WIDTH
, 4, REPLACE_DLG_HEIGHT
, N_(" Enter replacement string:"), 0, 0, 0,
1267 {quick_input
, 3, REPLACE_DLG_WIDTH
, 3, REPLACE_DLG_HEIGHT
, "", 52, 0, 0,
1269 {quick_label
, 2, REPLACE_DLG_WIDTH
, 2, REPLACE_DLG_HEIGHT
, N_(" Enter search string:"), 0, 0, 0,
1273 quick_widgets
[2].result
= &treplace_scanf
;
1274 quick_widgets
[3].result
= &treplace_all
;
1275 quick_widgets
[4].result
= &treplace_prompt
;
1276 quick_widgets
[5].result
= &treplace_backwards
;
1277 quick_widgets
[6].result
= &treplace_regexp
;
1278 quick_widgets
[7].result
= &treplace_whole
;
1279 quick_widgets
[8].result
= &treplace_case
;
1280 quick_widgets
[9].str_result
= &targ_order
;
1281 quick_widgets
[9].text
= *arg_order
;
1282 quick_widgets
[11].str_result
= &treplace_text
;
1283 quick_widgets
[11].text
= *replace_text
;
1284 quick_widgets
[13].str_result
= &tsearch_text
;
1285 quick_widgets
[13].text
= *search_text
;
1287 QuickDialog Quick_input
=
1288 {REPLACE_DLG_WIDTH
, REPLACE_DLG_HEIGHT
, -1, 0, N_(" Replace "),
1289 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1291 Quick_input
.widgets
= quick_widgets
;
1293 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
1294 *arg_order
= *(quick_widgets
[INPUT_INDEX
].str_result
);
1295 *replace_text
= *(quick_widgets
[INPUT_INDEX
+ 2].str_result
);
1296 *search_text
= *(quick_widgets
[INPUT_INDEX
+ 4].str_result
);
1297 replace_scanf
= treplace_scanf
;
1298 replace_backwards
= treplace_backwards
;
1299 replace_regexp
= treplace_regexp
;
1300 replace_all
= treplace_all
;
1301 replace_prompt
= treplace_prompt
;
1302 replace_whole
= treplace_whole
;
1303 replace_case
= treplace_case
;
1307 *replace_text
= NULL
;
1308 *search_text
= NULL
;
1315 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1317 int treplace_scanf
= replace_scanf
;
1318 int treplace_regexp
= replace_regexp
;
1319 int treplace_whole
= replace_whole
;
1320 int treplace_case
= replace_case
;
1321 int treplace_backwards
= replace_backwards
;
1324 QuickWidget quick_widgets
[] =
1326 {quick_button
, 6, 10, 7, SEARCH_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
1328 {quick_button
, 2, 10, 7, SEARCH_DLG_HEIGHT
, N_("&Ok"), 0, B_ENTER
, 0,
1330 {quick_checkbox
, 33, SEARCH_DLG_WIDTH
, 6, SEARCH_DLG_HEIGHT
, N_("scanf &Expression"), 0, 0,
1332 {quick_checkbox
, 33, SEARCH_DLG_WIDTH
, 5, SEARCH_DLG_HEIGHT
, N_("&Backwards"), 0, 0,
1334 {quick_checkbox
, 4, SEARCH_DLG_WIDTH
, 6, SEARCH_DLG_HEIGHT
, N_("&Regular expression"), 0, 0,
1336 {quick_checkbox
, 4, SEARCH_DLG_WIDTH
, 5, SEARCH_DLG_HEIGHT
, N_("&Whole words only"), 0, 0,
1338 {quick_checkbox
, 4, SEARCH_DLG_WIDTH
, 4, SEARCH_DLG_HEIGHT
, N_("case &Sensitive"), 0, 0,
1340 {quick_input
, 3, SEARCH_DLG_WIDTH
, 3, SEARCH_DLG_HEIGHT
, "", 52, 0, 0,
1342 {quick_label
, 2, SEARCH_DLG_WIDTH
, 2, SEARCH_DLG_HEIGHT
, N_(" Enter search string:"), 0, 0, 0,
1346 quick_widgets
[2].result
= &treplace_scanf
;
1347 quick_widgets
[3].result
= &treplace_backwards
;
1348 quick_widgets
[4].result
= &treplace_regexp
;
1349 quick_widgets
[5].result
= &treplace_whole
;
1350 quick_widgets
[6].result
= &treplace_case
;
1351 quick_widgets
[7].str_result
= &tsearch_text
;
1352 quick_widgets
[7].text
= *search_text
;
1355 QuickDialog Quick_input
=
1356 {SEARCH_DLG_WIDTH
, SEARCH_DLG_HEIGHT
, -1, 0, N_(" Search "),
1357 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1359 Quick_input
.widgets
= quick_widgets
;
1361 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
1362 *search_text
= *(quick_widgets
[7].str_result
);
1363 replace_scanf
= treplace_scanf
;
1364 replace_backwards
= treplace_backwards
;
1365 replace_regexp
= treplace_regexp
;
1366 replace_whole
= treplace_whole
;
1367 replace_case
= treplace_case
;
1370 *search_text
= NULL
;
1379 #define B_SKIP_REPLACE 1
1380 #define B_REPLACE_ALL 2
1381 #define B_REPLACE_ONE 3
1384 extern CWidget
*wedit
;
1388 void edit_search_replace_dialog (Window parent
, int x
, int y
, char **search_text
, char **replace_text
, char **arg_order
, char *heading
, int option
)
1394 int xh
, yh
, h
, xb
, ys
, yc
, yb
, yr
;
1396 int text_input_width
;
1401 win
= CDrawHeadedDialog ("replace", parent
, x
, y
, heading
);
1402 CGetHintPos (&xh
, &h
);
1404 xh
+= NEXT_SPACING
;
1408 CIdent ("replace")->position
= WINDOW_ALWAYS_RAISED
;
1409 /* An input line comes after the ':' */
1410 (CDrawText ("replace.t1", win
, xh
, h
, _(" Enter search text : ")))->hotkey
= 'E';
1412 CGetHintPos (0, &yh
);
1413 (m
= CDrawTextInput ("replace.sinp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 8192, *search_text
))->hotkey
= 'E';
1416 CGetHintPos (0, &yh
);
1417 (CDrawText ("replace.t2", win
, xh
, yh
, _(" Enter replace text : ")))->hotkey
= 'n';
1418 CGetHintPos (0, &yh
);
1419 (CDrawTextInput ("replace.rinp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 8192, *replace_text
))->hotkey
= 'n';
1420 CSetToolHint ("replace.t2", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
1421 CSetToolHint ("replace.rinp", _("You can enter regexp substrings with %s\n(not \\1, \\2 like sed) then use \"Enter...order\""));
1422 CGetHintPos (0, &yh
);
1423 (CDrawText ("replace.t3", win
, xh
, yh
, _(" Enter argument (or substring) order : ")))->hotkey
= 'o';
1424 CGetHintPos (0, &yh
);
1425 (CDrawTextInput ("replace.ainp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 256, *arg_order
))->hotkey
= 'o';
1427 CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
1428 CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf\nformat specifiers or regexp substrings, eg 3,1,2"));
1430 CGetHintPos (0, &yh
);
1432 /* The following are check boxes */
1433 CDrawSwitch ("replace.ww", win
, xh
, yh
, replace_whole
, _(" Whole words only "), 0);
1434 CGetHintPos (0, &yh
);
1435 CDrawSwitch ("replace.case", win
, xh
, yh
, replace_case
, _(" Case sensitive "), 0);
1437 CGetHintPos (0, &yh
);
1438 CDrawSwitch ("replace.reg", win
, xh
, yh
, replace_regexp
, _(" Regular expression "), 1);
1439 CSetToolHint ("replace.reg", _("See the regex man page for how\nto compose a regular expression"));
1440 CSetToolHint ("replace.reg.label", _("See the regex man page for how\nto compose a regular expression"));
1442 CGetHintPos (0, &yh
);
1443 CGetHintPos (&xb
, 0);
1445 xb
+= NEXT_SPACING
;
1447 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1448 CDrawSwitch ("replace.bkwd", win
, xh
, yh
, replace_backwards
, _(" Backwards "), 0);
1450 CSetToolHint ("replace.bkwd", _("Warning: Searching backward can be slow"));
1451 CSetToolHint ("replace.bkwd.label", _("Warning: Searching backward can be slow"));
1455 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
)
1458 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1459 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
)
1464 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
)
1472 CDrawSwitch ("replace.pr", win
, xb
, yr
, replace_prompt
, _(" Prompt on replace "), 0);
1474 CSetToolHint ("replace.pr", _("Ask before making each replacement"));
1475 CGetHintPos (0, &yr
);
1476 CDrawSwitch ("replace.all", win
, xb
, yr
, replace_all
, _(" Replace all "), 0);
1478 CSetToolHint ("replace.all", _("Replace repeatedly"));
1479 CGetHintPos (0, &yr
);
1481 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
) {
1482 CDrawSwitch ("replace.bkmk", win
, xb
, yr
, search_create_bookmark
, _(" Bookmarks "), 0);
1484 CSetToolHint ("replace.bkmk", _("Create bookmarks at all lines found"));
1485 CSetToolHint ("replace.bkmk.label", _("Create bookmarks at all lines found"));
1486 CGetHintPos (0, &yr
);
1488 CDrawSwitch ("replace.scanf", win
, xb
, yr
, replace_scanf
, _(" Scanf expression "), 1);
1490 CSetToolHint ("replace.scanf", _("Allows entering of a C format string,\nsee the scanf man page"));
1492 get_hint_limits (&x
, &y
);
1495 int btn_width
, x
, y
;
1496 CGetHintPos (&x
, &y
);
1498 y
+= NEXT_SPACING
* 2 ;
1499 x
+= NEXT_SPACING
* 2 ;
1500 CTextSize (&btn_width
, 0, " Cancel ");
1501 btn_width
+= 4 + BUTTON_RELIEF
* 2;
1502 x
-= (btn_width
+ NEXT_SPACING
) * 2 + NEXT_SPACING
;
1504 CDrawButton ("replace.ok", win
, x
+btn_width
+ NEXT_SPACING
* 2, y
, AUTO_WIDTH
, AUTO_HEIGHT
, " Ok ");
1505 CDrawButton ("replace.cancel", win
, x
, y
, AUTO_WIDTH
, AUTO_HEIGHT
, " Cancel ");
1506 CGetHintPos (0, &y
);
1507 x
+= (btn_width
+ NEXT_SPACING
) * 2 + NEXT_SPACING
;
1508 reset_hint_pos (x
, y
+ NEXT_SPACING
*2);
1511 CDrawPixmapButton ("replace.ok", win
, x
- WIDGET_SPACING
- TICK_BUTTON_WIDTH
, h
, PIXMAP_BUTTON_TICK
);
1512 CDrawPixmapButton ("replace.cancel", win
, x
- WIDGET_SPACING
- TICK_BUTTON_WIDTH
, h
+ WIDGET_SPACING
+ TICK_BUTTON_WIDTH
, PIXMAP_BUTTON_CROSS
);
1515 CSetToolHint ("replace.ok", _("Begin search, Enter"));
1516 CSetToolHint ("replace.cancel", _("Abort this dialog, Esc"));
1517 CSetSizeHintPos ("replace");
1518 CMapDialog ("replace");
1520 m
= CIdent ("replace");
1522 text_input_width
= m
->width
- WIDGET_SPACING
* 3 - 4 - NEXT_SPACING
*2 ;
1524 text_input_width
= m
->width
- WIDGET_SPACING
* 3 - 4 - TICK_BUTTON_WIDTH
;
1526 CSetWidgetSize ("replace.sinp", text_input_width
, (CIdent ("replace.sinp"))->height
);
1528 CSetWidgetSize ("replace.rinp", text_input_width
, (CIdent ("replace.rinp"))->height
);
1529 CSetWidgetSize ("replace.ainp", text_input_width
, (CIdent ("replace.ainp"))->height
);
1531 CFocus (CIdent ("replace.sinp"));
1534 CNextEvent (&xev
, &cev
);
1535 if (!CIdent ("replace")) {
1539 if (!strcmp (cev
.ident
, "replace.cancel") || cev
.command
== CK_Cancel
) {
1543 if (!strcmp (cev
.ident
, "replace.reg") || !strcmp (cev
.ident
, "replace.scanf")) {
1544 if (CIdent ("replace.reg")->keypressed
|| CIdent ("replace.scanf")->keypressed
) {
1545 if (!(CIdent ("replace.case")->keypressed
)) {
1546 CIdent ("replace.case")->keypressed
= 1;
1547 CExpose ("replace.case");
1551 if (!strcmp (cev
.ident
, "replace.ok") || cev
.command
== CK_Enter
) {
1553 replace_all
= CIdent ("replace.all")->keypressed
;
1554 replace_prompt
= CIdent ("replace.pr")->keypressed
;
1555 *replace_text
= (char *) strdup (CIdent ("replace.rinp")->text
);
1556 *arg_order
= (char *) strdup (CIdent ("replace.ainp")->text
);
1558 *search_text
= (char *) strdup (CIdent ("replace.sinp")->text
);
1559 replace_whole
= CIdent ("replace.ww")->keypressed
;
1560 replace_case
= CIdent ("replace.case")->keypressed
;
1561 replace_scanf
= CIdent ("replace.scanf")->keypressed
;
1562 replace_regexp
= CIdent ("replace.reg")->keypressed
;
1564 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1565 replace_backwards
= CIdent ("replace.bkwd")->keypressed
;
1567 replace_backwards
= 0;
1570 if (option
& SEARCH_DIALOG_OPTION_BOOKMARK
) {
1571 search_create_bookmark
= CIdent ("replace.bkmk")->keypressed
;
1573 search_create_bookmark
= 0;
1579 CDestroyWidget ("replace");
1583 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1585 /* Heads the 'Search' dialog box */
1586 edit_search_replace_dialog (WIN_MESSAGES
, search_text
, 0, 0, _(" Search "), SEARCH_DIALOG_OPTION_BACKWARDS
| SEARCH_DIALOG_OPTION_BOOKMARK
);
1589 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1591 /* Heads the 'Replace' dialog box */
1592 edit_search_replace_dialog (WIN_MESSAGES
, search_text
, replace_text
, arg_order
, _(" Replace "), SEARCH_DIALOG_OPTION_BACKWARDS
);
1597 #include <libgnomeui/gtkcauldron.h>
1598 #include <libgnomeui/gnome-stock.h>
1600 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1603 s
= gtk_dialog_cauldron (
1604 "Search", GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
,
1605 " ( (Enter search text)d | %Eogxf )xf / ( ( %Cd // %Cd // %Cd ) || ( %Cd // %Cd )xf )xf / ( %Bxfgrq || %Bxfgq )f",
1606 search_text
, "search",
1607 "&Whole word", &replace_whole
,
1608 "Case &sensitive", &replace_case
,
1609 "&Regular expression", &replace_regexp
,
1610 "&Backwards", &replace_backwards
,
1611 "Scanf &expression", &replace_scanf
,
1612 GNOME_STOCK_BUTTON_OK
,
1613 GNOME_STOCK_BUTTON_CANCEL
1615 if (s
== GTK_CAULDRON_ESCAPE
|| !s
|| s
== GNOME_STOCK_BUTTON_CANCEL
)
1620 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1623 s
= gtk_dialog_cauldron (
1624 "Search", GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
,
1625 " ( (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",
1626 search_text
, "search",
1627 replace_text
, "replace",
1628 arg_order
, "arg_order",
1629 "&Whole word", &replace_whole
,
1630 "Case &sensitive", &replace_case
,
1631 "&Regular expression", &replace_regexp
,
1632 "&Backwards", &replace_backwards
,
1633 "Pr&ompt on replace", &replace_prompt
,
1634 "Replace &all", &replace_all
,
1635 "Scanf &expression", &replace_scanf
,
1636 GNOME_STOCK_BUTTON_OK
,
1637 GNOME_STOCK_BUTTON_CANCEL
1639 if (s
== GTK_CAULDRON_ESCAPE
|| !s
|| s
== GNOME_STOCK_BUTTON_CANCEL
)
1648 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1651 s
= gtk_dialog_cauldron (
1652 "Replace", GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
,
1653 " ( (Replace with:)d %Ld )xf / ( %Bxfrq || %Bxfq || %Bxfq || %Bxfq || %Bxfgq )f",
1655 "Replace", "Skip", "Replace all", "Replace one",
1656 GNOME_STOCK_BUTTON_CANCEL
1658 if (s
== GTK_CAULDRON_ESCAPE
|| !s
|| s
== GNOME_STOCK_BUTTON_CANCEL
)
1660 if (!strcmp (s
, "Replace all"))
1661 return B_REPLACE_ALL
;
1662 if (!strcmp (s
, "Replace one"))
1663 return B_REPLACE_ONE
;
1664 if (!strcmp (s
, "Skip"))
1665 return B_SKIP_REPLACE
;
1666 if (!strcmp (s
, "Replace"))
1668 /* Shouldn't ever reach this point */
1674 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1678 B_CANCEL
, B_ENTER
, B_SKIP_REPLACE
, B_REPLACE_ALL
, B_REPLACE_ONE
, B_CANCEL
1680 q
= CQueryDialog (WIN_MESSAGES
+ (edit
->curs_line
< 8 ? edit
->num_widget_lines
/ 2 * FONT_PIX_PER_LINE
+ CYof (edit
->widget
) : 0),
1681 _ (" Replace "), catstrs (_ (" Replace with: "), replace_text
, 0), _ ("Replace"), _ ("Skip"), _ ("Replace all"), _ ("Replace one"), _ ("Cancel"), 0);
1682 edit
->force
|= REDRAW_COMPLETELY
;
1690 long sargs
[NUM_REPL_ARGS
][256 / sizeof (long)];
1692 #define SCANF_ARGS sargs[0], sargs[1], sargs[2], sargs[3], \
1693 sargs[4], sargs[5], sargs[6], sargs[7], \
1694 sargs[8], sargs[9], sargs[10], sargs[11], \
1695 sargs[12], sargs[13], sargs[14], sargs[15]
1697 #define PRINTF_ARGS sargs[argord[0]], sargs[argord[1]], sargs[argord[2]], sargs[argord[3]], \
1698 sargs[argord[4]], sargs[argord[5]], sargs[argord[6]], sargs[argord[7]], \
1699 sargs[argord[8]], sargs[argord[9]], sargs[argord[10]], sargs[argord[11]], \
1700 sargs[argord[12]], sargs[argord[13]], sargs[argord[14]], sargs[argord[15]]
1703 /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
1704 /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
1705 int string_regexp_search (char *pattern
, char *string
, int len
, int match_type
, int match_bol
, int icase
, int *found_len
, void *d
)
1708 static char *old_pattern
= NULL
;
1709 static int old_type
, old_icase
;
1711 static regmatch_t s
[1];
1713 pmatch
= (regmatch_t
*) d
;
1717 if (!old_pattern
|| strcmp (old_pattern
, pattern
) || old_type
!= match_type
|| old_icase
!= icase
) {
1723 if (regcomp (&r
, pattern
, REG_EXTENDED
| (icase
? REG_ICASE
: 0))) {
1727 old_pattern
= (char *) strdup (pattern
);
1728 old_type
= match_type
;
1731 if (regexec (&r
, string
, d
? NUM_REPL_ARGS
: 1, pmatch
, ((match_bol
|| match_type
!= match_normal
) ? 0 : REG_NOTBOL
)) != 0) {
1735 *found_len
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1736 return (pmatch
[0].rm_so
);
1739 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1740 (and the above) routines to work properly - paul */
1742 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
)
1745 long l
= strlen ((char *) exp
), f
= 0;
1748 for (p
= 0; p
< l
; p
++) /* count conversions... */
1750 if (exp
[++p
] != '%') /* ...except for "%%" */
1753 if (replace_scanf
|| replace_regexp
) {
1756 unsigned char mbuf
[MAX_REPL_LEN
* 2 + 3];
1758 replace_scanf
= (!replace_regexp
); /* can't have both */
1762 if (replace_scanf
) {
1763 unsigned char e
[MAX_REPL_LEN
];
1764 if (n
>= NUM_REPL_ARGS
)
1768 for (p
= start
; p
< last_byte
&& p
< start
+ MAX_REPL_LEN
; p
++)
1769 buf
[p
- start
] = (*get_byte
) (data
, p
);
1771 for (p
= 0; exp
[p
] != 0; p
++)
1772 exp
[p
] = my_lower_case (exp
[p
]);
1773 for (p
= start
; p
< last_byte
&& p
< start
+ MAX_REPL_LEN
; p
++) {
1774 c
= (*get_byte
) (data
, p
);
1775 buf
[p
- start
] = my_lower_case (c
);
1779 buf
[(q
= p
- start
)] = 0;
1780 strcpy ((char *) e
, (char *) exp
);
1781 strcat ((char *) e
, "%n");
1785 *((int *) sargs
[n
]) = 0; /* --> here was the problem - now fixed: good */
1786 if (n
== sscanf ((char *) buf
, (char *) exp
, SCANF_ARGS
)) {
1787 if (*((int *) sargs
[n
])) {
1788 *len
= *((int *) sargs
[n
]);
1794 if (q
+ start
< last_byte
) {
1796 buf
[q
] = (*get_byte
) (data
, q
+ start
);
1798 c
= (*get_byte
) (data
, q
+ start
);
1799 buf
[q
] = my_lower_case (c
);
1805 buf
++; /* move the window along */
1806 if (buf
== mbuf
+ MAX_REPL_LEN
) { /* the window is about to go past the end of array, so... */
1807 memmove (mbuf
, buf
, strlen ((char *) buf
) + 1); /* reset it */
1812 } else { /* regexp matching */
1814 int found_start
, match_bol
, move_win
= 0;
1816 while (start
+ offset
< last_byte
) {
1817 match_bol
= (offset
== 0 || (*get_byte
) (data
, start
+ offset
- 1) == '\n');
1822 for (; p
< last_byte
&& q
< MAX_REPL_LEN
; p
++, q
++) {
1823 mbuf
[q
] = (*get_byte
) (data
, p
);
1824 if (mbuf
[q
] == '\n')
1833 found_start
= string_regexp_search ((char *) exp
, (char *) buf
, q
, match_normal
, match_bol
, !replace_case
, len
, d
);
1835 if (found_start
<= -2) { /* regcomp/regexec error */
1839 else if (found_start
== -1) /* not found: try next line */
1841 else if (*len
== 0) { /* null pattern: try again at next character */
1848 return (start
+ offset
- q
+ found_start
);
1853 if (buf
[q
- 1] != '\n') { /* incomplete line: try to recover */
1854 buf
= mbuf
+ MAX_REPL_LEN
/ 2;
1855 q
= strlen ((char *) buf
);
1856 memmove (mbuf
, buf
, q
);
1865 *len
= strlen ((char *) exp
);
1867 for (p
= start
; p
<= last_byte
- l
; p
++) {
1868 if ((*get_byte
) (data
, p
) == (unsigned char)exp
[0]) { /* check if first char matches */
1869 for (f
= 0, q
= 0; q
< l
&& f
< 1; q
++)
1870 if ((*get_byte
) (data
, q
+ p
) != (unsigned char)exp
[q
])
1879 for (p
= 0; exp
[p
] != 0; p
++)
1880 exp
[p
] = my_lower_case (exp
[p
]);
1882 for (p
= start
; p
<= last_byte
- l
; p
++) {
1883 if (my_lower_case ((*get_byte
) (data
, p
)) == (unsigned char)exp
[0]) {
1884 for (f
= 0, q
= 0; q
< l
&& f
< 1; q
++)
1885 if (my_lower_case ((*get_byte
) (data
, q
+ p
)) != (unsigned char)exp
[q
])
1899 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
)
1900 { /*front end to find_string to check for
1905 while ((p
= edit_find_string (p
, exp
, len
, last_byte
, get_byte
, data
, once_only
, d
)) >= 0) {
1906 if (replace_whole
) {
1907 /*If the bordering chars are not in option_whole_chars_search then word is whole */
1908 if (!strcasechr (option_whole_chars_search
, (*get_byte
) (data
, p
- 1))
1909 && !strcasechr (option_whole_chars_search
, (*get_byte
) (data
, p
+ *len
)))
1917 p
++; /*not a whole word so continue search. */
1922 long edit_find (long search_start
, unsigned char *exp
, int *len
, long last_byte
, int (*get_byte
) (void *, long), void *data
, void *d
)
1925 if (replace_backwards
) {
1926 while (search_start
>= 0) {
1927 p
= edit_find_forwards (search_start
, exp
, len
, last_byte
, get_byte
, data
, 1, d
);
1928 if (p
== search_start
)
1933 return edit_find_forwards (search_start
, exp
, len
, last_byte
, get_byte
, data
, 0, d
);
1938 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1940 #define snprintf(v) { \
1945 sprintf(s,q1,v,&n); \
1949 /* this function uses the sprintf command to do a vprintf */
1950 /* it takes pointers to arguments instead of the arguments themselves */
1951 int sprintf_p (char *str
, const char *fmt
,...)
1955 char *q
, *p
, *s
= str
;
1960 p
= q
= (char *) fmt
;
1962 while ((p
= strchr (p
, '%'))) {
1963 n
= (int) ((unsigned long) p
- (unsigned long) q
);
1964 strncpy (s
, q
, n
); /* copy stuff between format specifiers */
1992 strcpy (p1
, itoa (*va_arg (ap
, int *))); /* replace field width with a number */
1995 while (is_digit (*p
))
2002 strcpy (p1
, itoa (*va_arg (ap
, int *))); /* replace precision with a number */
2005 while (is_digit (*p
))
2008 /* flags done, now get argument */
2010 snprintf (va_arg (ap
, char *));
2011 } else if (*p
== 'h') {
2012 if (strchr ("diouxX", *p
))
2013 snprintf (*va_arg (ap
, short *));
2014 } else if (*p
== 'l') {
2016 if (strchr ("diouxX", *p
))
2017 snprintf (*va_arg (ap
, long *));
2018 } else if (strchr ("cdiouxX", *p
)) {
2019 snprintf (*va_arg (ap
, int *));
2020 } else if (*p
== 'L') {
2022 if (strchr ("EefgG", *p
))
2023 snprintf (*va_arg (ap
, double *)); /* should be long double */
2024 } else if (strchr ("EefgG", *p
)) {
2025 snprintf (*va_arg (ap
, double *));
2026 } else if (strchr ("DOU", *p
)) {
2027 snprintf (*va_arg (ap
, long *));
2028 } else if (*p
== 'p') {
2029 snprintf (*va_arg (ap
, void **));
2034 sprintf (s
, q
); /* print trailing leftover */
2035 return (unsigned long) s
- (unsigned long) str
+ strlen (s
);
2038 static void regexp_error (WEdit
*edit
)
2040 /* "Error: Syntax error in regular expression, or scanf expression contained too many %'s */
2041 edit_error_dialog (_(" Error "), _(" Invalid regular expression, or scanf expression with to many conversions "));
2044 /* call with edit = 0 before shutdown to close memory leaks */
2045 void edit_replace_cmd (WEdit
* edit
, int again
)
2047 static regmatch_t pmatch
[NUM_REPL_ARGS
];
2048 static char *old1
= NULL
;
2049 static char *old2
= NULL
;
2050 static char *old3
= NULL
;
2055 int replace_continue
;
2056 int treplace_prompt
= 0;
2058 long times_replaced
= 0, last_search
;
2059 char fin_string
[64];
2060 int argord
[NUM_REPL_ARGS
];
2077 last_search
= edit
->last_byte
;
2079 edit
->force
|= REDRAW_COMPLETELY
;
2081 exp1
= old1
? old1
: exp1
;
2082 exp2
= old2
? old2
: exp2
;
2083 exp3
= old3
? old3
: exp3
;
2088 exp1
= (char *) strdup (old1
);
2089 exp2
= (char *) strdup (old2
);
2090 exp3
= (char *) strdup (old3
);
2092 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2093 edit_replace_dialog (edit
, &exp1
, &exp2
, &exp3
);
2094 treplace_prompt
= replace_prompt
;
2097 if (!exp1
|| !*exp1
) {
2098 edit
->force
= REDRAW_COMPLETELY
;
2112 old1
= (char *) strdup (exp1
);
2113 old2
= (char *) strdup (exp2
);
2114 old3
= (char *) strdup (exp3
);
2119 while ((s
= strchr (exp3
, ' ')))
2120 memmove (s
, s
+ 1, strlen (s
));
2122 for (i
= 0; i
< NUM_REPL_ARGS
; i
++) {
2123 if ((unsigned long) s
!= 1 && s
< exp3
+ strlen (exp3
)) {
2124 if ((ord
= atoi (s
)))
2125 argord
[i
] = ord
- 1;
2128 s
= strchr (s
, ',') + 1;
2134 replace_continue
= replace_all
;
2136 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && replace_backwards
)
2137 edit
->search_start
--;
2139 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !replace_backwards
)
2140 edit
->search_start
++;
2145 new_start
= edit_find (edit
->search_start
, (unsigned char *) exp1
, &len
, last_search
,
2146 (int (*)(void *, long)) edit_get_byte
, (void *) edit
, pmatch
);
2147 if (new_start
== -3) {
2148 regexp_error (edit
);
2151 edit
->search_start
= new_start
;
2152 /*returns negative on not found or error in pattern */
2154 if (edit
->search_start
>= 0) {
2155 edit
->found_start
= edit
->search_start
;
2156 i
= edit
->found_len
= len
;
2158 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
2159 edit_scroll_screen_over_cursor (edit
);
2163 if (treplace_prompt
) {
2165 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
2167 edit_scroll_downward (edit
, l
);
2169 edit_scroll_upward (edit
, -l
);
2171 edit_scroll_screen_over_cursor (edit
);
2172 edit
->force
|= REDRAW_PAGE
;
2173 edit_render_keypress (edit
);
2175 /*so that undo stops at each query */
2176 edit_push_key_press (edit
);
2178 switch (edit_replace_prompt (edit
, exp2
, /*and prompt 2/3 down */
2180 (edit
->num_widget_columns
- CONFIRM_DLG_WIDTH
)/2, edit
->num_widget_lines
* 2 / 3)) {
2182 edit
->num_widget_columns
/ 2 - 33, edit
->num_widget_lines
* 2 / 3)) {
2186 case B_SKIP_REPLACE
:
2190 treplace_prompt
= 0;
2191 replace_continue
= 1;
2194 replace_continue
= 0;
2198 replace_continue
= 0;
2202 if (replace_yes
) { /* delete then insert new */
2203 if (replace_scanf
|| replace_regexp
) {
2204 char repl_str
[MAX_REPL_LEN
+ 2];
2205 if (replace_regexp
) { /* we need to fill in sargs just like with scanf */
2207 for (k
= 1; k
< NUM_REPL_ARGS
&& pmatch
[k
].rm_eo
>= 0; k
++) {
2209 t
= (unsigned char *) &sargs
[k
- 1][0];
2210 for (j
= 0; j
< pmatch
[k
].rm_eo
- pmatch
[k
].rm_so
&& j
< 255; j
++, t
++)
2211 *t
= (unsigned char) edit_get_byte (edit
, edit
->search_start
- pmatch
[0].rm_so
+ pmatch
[k
].rm_so
+ j
);
2214 for (; k
<= NUM_REPL_ARGS
; k
++)
2215 sargs
[k
- 1][0] = 0;
2217 if (sprintf_p (repl_str
, exp2
, PRINTF_ARGS
) >= 0) {
2221 while (repl_str
[++i
])
2222 edit_insert (edit
, repl_str
[i
]);
2224 edit_error_dialog (_ (" Replace "),
2225 /* "Invalid regexp string or scanf string" */
2226 _ (" Error in replacement format string. "));
2227 replace_continue
= 0;
2234 edit_insert (edit
, exp2
[i
]);
2236 edit
->found_len
= i
;
2238 /* so that we don't find the same string again */
2239 if (replace_backwards
) {
2240 last_search
= edit
->search_start
;
2241 edit
->search_start
--;
2243 edit
->search_start
+= i
;
2244 last_search
= edit
->last_byte
;
2246 edit_scroll_screen_over_cursor (edit
);
2248 edit
->search_start
= edit
->curs1
; /* try and find from right here for next search */
2249 edit_update_curs_col (edit
);
2251 edit
->force
|= REDRAW_PAGE
;
2252 edit_render_keypress (edit
);
2253 if (times_replaced
) {
2254 sprintf (fin_string
, _ (" %ld replacements made. "), times_replaced
);
2255 edit_message_dialog (_ (" Replace "), fin_string
);
2257 edit_message_dialog (_ (" Replace "), _ (" Search string not found. "));
2258 replace_continue
= 0;
2260 } while (replace_continue
);
2265 edit
->force
= REDRAW_COMPLETELY
;
2266 edit_scroll_screen_over_cursor (edit
);
2272 void edit_search_cmd (WEdit
* edit
, int again
)
2274 static char *old
= NULL
;
2284 exp
= old
? old
: exp
;
2285 if (again
) { /*ctrl-hotkey for search again. */
2288 exp
= (char *) strdup (old
);
2290 edit_search_dialog (edit
, &exp
);
2291 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2299 old
= (char *) strdup (exp
);
2301 if (search_create_bookmark
) {
2302 int found
= 0, books
= 0;
2303 int l
= 0, l_last
= -1;
2306 p
= edit_find (q
, (unsigned char *) exp
, &len
, edit
->last_byte
,
2307 (int (*)(void *, long)) edit_get_byte
, (void *) edit
, 0);
2311 l
+= edit_count_lines (edit
, q
, p
);
2313 book_mark_insert (edit
, l
, BOOK_MARK_FOUND_COLOR
);
2320 char fin_string
[64];
2321 /* in response to number of bookmarks added because of string being found %d times */
2322 sprintf (fin_string
, _ (" %d finds made, %d bookmarks added "), found
, books
);
2323 edit_message_dialog (_ (" Search "), fin_string
);
2325 edit_error_dialog (_ (" Search "), _ (" Search string not found. "));
2329 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && replace_backwards
)
2330 edit
->search_start
--;
2332 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !replace_backwards
)
2333 edit
->search_start
++;
2335 edit
->search_start
= edit_find (edit
->search_start
, (unsigned char *) exp
, &len
, edit
->last_byte
,
2336 (int (*)(void *, long)) edit_get_byte
, (void *) edit
, 0);
2338 if (edit
->search_start
>= 0) {
2339 edit
->found_start
= edit
->search_start
;
2340 edit
->found_len
= len
;
2342 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
2343 edit_scroll_screen_over_cursor (edit
);
2344 if (replace_backwards
)
2345 edit
->search_start
--;
2347 edit
->search_start
++;
2348 } else if (edit
->search_start
== -3) {
2349 edit
->search_start
= edit
->curs1
;
2350 regexp_error (edit
);
2352 edit
->search_start
= edit
->curs1
;
2353 edit_error_dialog (_ (" Search "), _ (" Search string not found. "));
2359 edit
->force
|= REDRAW_COMPLETELY
;
2360 edit_scroll_screen_over_cursor (edit
);
2364 /* Real edit only */
2365 void edit_quit_cmd (WEdit
* edit
)
2367 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2374 edit
->force
|= REDRAW_COMPLETELY
;
2375 if (edit
->modified
) {
2378 r
= gtk_dialog_cauldron (_ (" Quit "), GTK_CAULDRON_TOPLEVEL
| GTK_CAULDRON_GRAB
, " [ ( %Lxf )xf ]xf / ( %Bgxfq || %Bgxfq || %Bgxfq ) ",
2379 _ (" Current text was modified without a file save. \n Save with exit? "), GNOME_STOCK_BUTTON_CANCEL
, GNOME_STOCK_BUTTON_YES
, GNOME_STOCK_BUTTON_NO
);
2380 if (!strcmp (r
, GNOME_STOCK_BUTTON_YES
)) {
2381 edit_push_markers (edit
);
2382 edit_set_markers (edit
, 0, 0, 0, 0);
2383 if (!edit_save_cmd (edit
))
2385 } else if (!strcmp (r
, GNOME_STOCK_BUTTON_NO
)) {
2386 if (edit
->delete_file
)
2387 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
2393 switch (edit_query_dialog3 (_ (" Quit "), _ (" File was modified, Save with exit? "), _ ("Cancel quit"), _ ("&Yes"), _ ("&No"))) {
2395 /* Confirm 'Quit' dialog box */
2396 switch (edit_query_dialog3 (_ (" Quit "),
2397 _ (" Current text was modified without a file save. \n Save with exit? "), _ (" &Cancel quit "), _ (" &Yes "), _ (" &No "))) {
2400 edit_push_markers (edit
);
2401 edit_set_markers (edit
, 0, 0, 0, 0);
2402 if (!edit_save_cmd (edit
))
2407 if (edit
->delete_file
)
2408 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
2417 #if defined(MIDNIGHT) || defined(GTK)
2418 else if (edit
->delete_file
)
2419 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
2422 dlg_stop (edit
->widget
.parent
);
2426 extern char *edit_one_file
;
2436 #define TEMP_BUF_LEN 1024
2438 /* returns a null terminated length of text. Result must be free'd */
2439 unsigned char *edit_get_block (WEdit
* edit
, long start
, long finish
, int *l
)
2441 unsigned char *s
, *r
;
2442 r
= s
= malloc (finish
- start
+ 1);
2443 if (column_highlighting
) {
2445 while (start
< finish
) { /* copy from buffer, excluding chars that are out of the column 'margins' */
2447 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0, start
);
2448 c
= edit_get_byte (edit
, start
);
2449 if ((x
>= edit
->column1
&& x
< edit
->column2
)
2450 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
2457 *l
= finish
- start
;
2458 while (start
< finish
)
2459 *s
++ = edit_get_byte (edit
, start
++);
2465 /* save block, returns 1 on success */
2466 int edit_save_block (WEdit
* edit
, const char *filename
, long start
, long finish
)
2470 if ((file
= open ((char *) filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1)
2473 if (column_highlighting
) {
2474 unsigned char *block
, *p
;
2476 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
2478 r
= write (file
, p
, len
);
2488 len
= finish
- start
;
2489 buf
= malloc (TEMP_BUF_LEN
);
2490 while (start
!= finish
) {
2491 end
= min (finish
, start
+ TEMP_BUF_LEN
);
2492 for (; i
< end
; i
++)
2493 buf
[i
- start
] = edit_get_byte (edit
, i
);
2494 len
-= write (file
, (char *) buf
, end
- start
);
2505 /* copies a block to clipboard file */
2506 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
2508 return edit_save_block (edit
, catstrs (home_dir
, CLIP_FILE
, 0), start
, finish
);
2513 void paste_text (WEdit
* edit
, unsigned char *data
, unsigned int nitems
)
2518 edit_insert_ahead (edit
, *data
--);
2520 edit
->force
|= REDRAW_COMPLETELY
;
2523 char *selection_get_line (void *data
, int line
)
2525 static unsigned char t
[1024];
2526 struct selection
*s
;
2528 s
= (struct selection
*) data
;
2529 line
= (current_selection
+ line
+ 1) % NUM_SELECTION_HISTORY
;
2531 unsigned char *p
= s
[line
].text
;
2533 for (j
= 0; j
< s
[line
].len
; j
++) {
2578 void edit_paste_from_history (WEdit
* edit
)
2582 edit_update_curs_col (edit
);
2583 edit_update_curs_row (edit
);
2585 c
= max (20, edit
->num_widget_columns
- 5);
2590 i
= gtk_edit_list_box_dialog (c
, 10,
2591 0, NUM_SELECTION_HISTORY
- 10, NUM_SELECTION_HISTORY
- 1, NUM_SELECTION_HISTORY
,
2592 selection_get_line
, (void *) selection_history
);
2597 i
= CListboxDialog (WIN_MESSAGES
, c
, 10,
2598 0, NUM_SELECTION_HISTORY
- 10, NUM_SELECTION_HISTORY
- 1, NUM_SELECTION_HISTORY
,
2599 selection_get_line
, (void *) selection_history
);
2605 i
= (current_selection
+ i
+ 1) % NUM_SELECTION_HISTORY
;
2607 paste_text (edit
, selection_history
[i
].text
, selection_history
[i
].len
);
2608 edit
->force
|= REDRAW_COMPLETELY
;
2611 /* copies a block to the XWindows buffer */
2612 static int edit_XStore_block (WEdit
* edit
, long start
, long finish
)
2614 edit_get_selection (edit
);
2615 if (selection
.len
<= 512 * 1024) { /* we don't want to fill up the server */
2616 XStoreBytes (CDisplay
, (char *) selection
.text
, (int) selection
.len
);
2622 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
2624 long start_mark
, end_mark
;
2625 if (eval_marks (edit
, &start_mark
, &end_mark
))
2627 edit_XStore_block (edit
, start_mark
, end_mark
);
2628 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2629 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
2633 gtk_selection_owner_set (GTK_WIDGET (edit
->widget
), GDK_SELECTION_PRIMARY
, GDK_CURRENT_TIME
);
2634 edit
->widget
->editable
.selection_start_pos
= start_mark
;
2635 edit
->widget
->editable
.selection_end_pos
= end_mark
;
2636 edit
->widget
->editable
.has_selection
= TRUE
;
2638 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, CWindowOf (edit
->widget
), CurrentTime
);
2640 edit_mark_cmd (edit
, 1);
2644 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
2646 long start_mark
, end_mark
;
2647 if (eval_marks (edit
, &start_mark
, &end_mark
))
2649 edit_XStore_block (edit
, start_mark
, end_mark
);
2650 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2651 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2654 edit_block_delete_cmd (edit
);
2656 gtk_selection_owner_set (GTK_WIDGET (edit
->widget
), GDK_SELECTION_PRIMARY
, GDK_CURRENT_TIME
);
2657 edit
->widget
->editable
.selection_start_pos
= start_mark
;
2658 edit
->widget
->editable
.selection_end_pos
= end_mark
;
2659 edit
->widget
->editable
.has_selection
= TRUE
;
2661 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, CWindowOf (edit
->widget
), CurrentTime
);
2663 edit_mark_cmd (edit
, 1);
2667 void selection_paste (WEdit
* edit
, Window win
, unsigned prop
, int delete);
2669 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
2672 paste_text (edit
, selection
.text
, selection
.len
);
2673 else if (!XGetSelectionOwner (CDisplay
, XA_PRIMARY
))
2678 selection_paste (edit
, CRoot
, XA_CUT_BUFFER0
, False
);
2682 gtk_selection_convert (GTK_WIDGET (edit
->widget
), GDK_SELECTION_PRIMARY
,
2683 gdk_atom_intern ("COMPOUND_TEXT", FALSE
), GDK_CURRENT_TIME
);
2685 XConvertSelection (CDisplay
, XA_PRIMARY
, XA_STRING
,
2686 XInternAtom (CDisplay
, "VT_SELECTION", False
),
2687 CWindowOf (edit
->widget
), CurrentTime
);
2689 edit
->force
|= REDRAW_PAGE
;
2692 #else /* MIDNIGHT */
2694 void edit_paste_from_history (WEdit
*edit
)
2698 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
2700 long start_mark
, end_mark
;
2701 if (eval_marks (edit
, &start_mark
, &end_mark
))
2703 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2704 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
2707 edit_mark_cmd (edit
, 1);
2711 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
2713 long start_mark
, end_mark
;
2714 if (eval_marks (edit
, &start_mark
, &end_mark
))
2716 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2717 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2720 edit_block_delete_cmd (edit
);
2721 edit_mark_cmd (edit
, 1);
2725 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
2727 edit_insert_file (edit
, catstrs (home_dir
, CLIP_FILE
, 0));
2730 #endif /* MIDMIGHT */
2732 void edit_goto_cmd (WEdit
*edit
)
2738 sprintf (s
, "%d", l
);
2739 f
= input_dialog (_(" Goto line "), _(" Enter line: "), l
? s
: "");
2743 f
= gtk_edit_dialog_input ("goto", 150, l
? itoa (l
) : "", _(" Goto line "), _(" Enter line: "));
2747 sprintf (s
, "%d", l
);
2748 f
= (char *) input_dialog (_(" Goto line "), _(" Enter line: "), l
? s
: "");
2751 f
= CInputDialog ("goto", WIN_MESSAGES
, 150, l
? itoa (l
) : "", _(" Goto line "), _(" Enter line: "));
2757 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
2758 edit_move_to_line (edit
, l
- 1);
2759 edit
->force
|= REDRAW_COMPLETELY
;
2765 /*returns 1 on success */
2766 int edit_save_block_cmd (WEdit
* edit
)
2768 long start_mark
, end_mark
;
2770 if (eval_marks (edit
, &start_mark
, &end_mark
))
2772 exp
= edit_get_save_file (edit
->dir
, catstrs (home_dir
, CLIP_FILE
, 0), _ (" Save Block "));
2773 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2779 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
2781 edit
->force
|= REDRAW_COMPLETELY
;
2785 edit_error_dialog (_ (" Save Block "), get_sys_error (_ (" Error trying to save file. ")));
2789 edit
->force
|= REDRAW_COMPLETELY
;
2794 /* returns 1 on success */
2795 int edit_insert_file_cmd (WEdit
* edit
)
2797 char *exp
= edit_get_load_file (edit
->dir
, catstrs (home_dir
, CLIP_FILE
, 0), _ (" Insert File "));
2798 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2804 if (edit_insert_file (edit
, exp
)) {
2806 edit
->force
|= REDRAW_COMPLETELY
;
2810 edit_error_dialog (_ (" Insert file "), get_sys_error (_ (" Error trying to insert file. ")));
2814 edit
->force
|= REDRAW_COMPLETELY
;
2820 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2821 int edit_sort_cmd (WEdit
* edit
)
2823 static char *old
= 0;
2825 long start_mark
, end_mark
;
2828 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2829 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
2832 edit_save_block (edit
, catstrs (home_dir
, BLOCK_FILE
, 0), start_mark
, end_mark
);
2834 exp
= old
? old
: "";
2836 exp
= input_dialog (_(" Run Sort "),
2837 _(" Enter sort options (see manpage) separated by whitespace: "), exp
);
2845 e
= system (catstrs (" sort ", exp
, " ", home_dir
, BLOCK_FILE
, " > ", home_dir
, TEMP_FILE
, 0));
2847 if (e
== -1 || e
== 127) {
2848 edit_error_dialog (_(" Sort "),
2849 get_sys_error (_(" Error trying to execute sort command ")));
2852 sprintf (q
, "%d ", e
);
2853 edit_error_dialog (_(" Sort "),
2854 catstrs (_(" Sort returned non-zero: "), q
, 0));
2859 edit
->force
|= REDRAW_COMPLETELY
;
2861 if (edit_block_delete_cmd (edit
))
2863 edit_insert_file (edit
, catstrs (home_dir
, TEMP_FILE
, 0));
2867 /* if block is 1, a block must be highlighted and the shell command
2868 processes it. If block is 0 the shell command is a straight system
2869 command, that just produces some output which is to be inserted */
2870 void edit_block_process_cmd (WEdit
* edit
, const char *shell_cmd
, int block
)
2872 long start_mark
, end_mark
;
2875 FILE *script_home
= NULL
;
2876 FILE *script_src
= NULL
;
2877 FILE *block_file
= NULL
;
2879 char *o
= catstrs (mc_home
, shell_cmd
, 0); /* original source script */
2880 char *h
= catstrs (home_dir
, EDIT_DIR
, shell_cmd
, 0); /* home script */
2881 char *b
= catstrs (home_dir
, BLOCK_FILE
, 0); /* block file */
2882 char *e
= catstrs (home_dir
, ERROR_FILE
, 0); /* error file */
2884 if (! (script_home
= fopen (h
, "r"))) {
2885 if (! (script_home
= fopen (h
, "w"))) {
2886 edit_error_dialog ("",
2887 get_sys_error (catstrs (_ ("Error create script:"), h
, 0)));
2890 if (! (script_src
= fopen (o
, "r"))) {
2891 fclose (script_home
); unlink (h
);
2892 edit_error_dialog ("",
2893 get_sys_error (catstrs (_ ("Error read script:"), o
, 0)));
2896 while (fgets(buf
, sizeof(buf
), script_src
))
2897 fputs (buf
, script_home
);
2898 if (fclose(script_home
)) {
2899 edit_error_dialog ("",
2900 get_sys_error (catstrs (_ ("Error close script:"), h
, 0)));
2904 edit_error_dialog ("",
2905 get_sys_error (catstrs (_ ("Script created:"), h
, 0)));
2910 if (block
) { /* for marked block run indent formatter */
2911 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2912 edit_error_dialog (_("Process block"),
2913 _(" You must first highlight a block of text. "));
2916 edit_save_block (edit
, b
, start_mark
, end_mark
);
2918 /* run your script */
2919 my_system (EXECUTE_AS_SHELL
, shell
,
2920 catstrs (home_dir
, EDIT_DIR
, shell_cmd
, " ",
2921 edit
->filename
, " ", home_dir
, BLOCK_FILE
, " ",
2922 home_dir
, ERROR_FILE
, 0));
2924 } else { /* for missing marked block run ... */
2925 my_system (0, shell
, catstrs (EDIT_DIR
, shell_cmd
));
2928 edit_refresh_cmd (edit
);
2929 edit
->force
|= REDRAW_COMPLETELY
;
2931 /* insert result block */
2933 if (stat (e
, &s
) == 0) {
2934 if (!s
.st_size
) { /* no error messages */
2935 if (edit_block_delete_cmd (edit
))
2937 edit_insert_file (edit
, b
);
2939 edit_insert_file (edit
, e
);
2942 edit_error_dialog ("",
2943 get_sys_error (catstrs (_ ("Error trying to stat file:"), e
, 0)));
2944 edit
->force
|= REDRAW_COMPLETELY
;
2946 if ((block_file
= fopen (b
, "w")))
2947 fclose (block_file
);
2953 #endif /* MIDNIGHT */
2955 int edit_execute_cmd (WEdit
* edit
, int command
, int char_for_insertion
);
2957 /* prints at the cursor */
2958 /* returns the number of chars printed */
2959 int edit_print_string (WEdit
* e
, const char *s
)
2963 edit_execute_cmd (e
, -1, (unsigned char) s
[i
++]);
2964 e
->force
|= REDRAW_COMPLETELY
;
2965 edit_update_screen (e
);
2969 int edit_printf (WEdit
* e
, const char *fmt
,...)
2975 sprintf (s
, fmt
, pa
);
2976 i
= edit_print_string (e
, s
);
2983 /* FIXME: does this function break NT_OS2 ? */
2985 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
2990 s
= g_strdup_printf ("mail -s \"%s\" -c \"%s\" \"%s\"", subject
, cc
, to
);
2999 for (i
= 0; i
< edit
->last_byte
; i
++)
3000 fputc (edit_get_byte (edit
, i
), p
);
3005 #define MAIL_DLG_HEIGHT 12
3007 void edit_mail_dialog (WEdit
* edit
)
3010 char *tmail_subject
;
3013 static char *mail_cc_last
= 0;
3014 static char *mail_subject_last
= 0;
3015 static char *mail_to_last
= 0;
3017 QuickDialog Quick_input
=
3018 {50, MAIL_DLG_HEIGHT
, -1, 0, N_(" Mail "),
3019 "[Input Line Keys]", "quick_input", 0};
3021 QuickWidget quick_widgets
[] =
3023 {quick_button
, 6, 10, 9, MAIL_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
3025 {quick_button
, 2, 10, 9, MAIL_DLG_HEIGHT
, N_("&Ok"), 0, B_ENTER
, 0,
3027 {quick_input
, 3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
3028 0, "mail-dlg-input"},
3029 {quick_label
, 2, 50, 7, MAIL_DLG_HEIGHT
, N_(" Copies to"), 0, 0, 0,
3031 {quick_input
, 3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
3032 0, "mail-dlg-input-2"},
3033 {quick_label
, 2, 50, 5, MAIL_DLG_HEIGHT
, N_(" Subject"), 0, 0, 0,
3035 {quick_input
, 3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
3036 0, "mail-dlg-input-3"},
3037 {quick_label
, 2, 50, 3, MAIL_DLG_HEIGHT
, N_(" To"), 0, 0, 0,
3039 {quick_label
, 2, 50, 2, MAIL_DLG_HEIGHT
, N_(" mail -s <subject> -c <cc> <to>"), 0, 0, 0,
3043 quick_widgets
[2].str_result
= &tmail_cc
;
3044 quick_widgets
[2].text
= mail_cc_last
? mail_cc_last
: "";
3045 quick_widgets
[4].str_result
= &tmail_subject
;
3046 quick_widgets
[4].text
= mail_subject_last
? mail_subject_last
: "";
3047 quick_widgets
[6].str_result
= &tmail_to
;
3048 quick_widgets
[6].text
= mail_to_last
? mail_to_last
: "";
3050 Quick_input
.widgets
= quick_widgets
;
3052 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
3054 free (mail_cc_last
);
3055 if (mail_subject_last
)
3056 free (mail_subject_last
);
3058 free (mail_to_last
);
3059 mail_cc_last
= *(quick_widgets
[2].str_result
);
3060 mail_subject_last
= *(quick_widgets
[4].str_result
);
3061 mail_to_last
= *(quick_widgets
[6].str_result
);
3062 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);
3066 #endif /* MIDNIGHT */