1 /* editor high level editing commands.
3 Copyright (C) 1996, 1997 the Free Software Foundation
5 Authors: 1996, 1997 Paul Sheer
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
30 #include "editcmddef.h"
33 #include <X11/Xatom.h>
39 /* search and replace: */
40 int replace_scanf
= 0;
41 int replace_regexp
= 0;
43 int replace_prompt
= 1;
44 int replace_whole
= 0;
46 int replace_backwards
= 0;
48 /* queries on a save */
50 int edit_confirm_save
= 1;
52 int edit_confirm_save
= 0;
55 #define NUM_REPL_ARGS 16
56 #define MAX_REPL_LEN 1024
60 static inline int my_lower_case (int c
)
65 char *strcasechr (const char *s
, int c
)
67 for (; my_lower_case ((int) *s
) != my_lower_case (c
); ++s
)
74 #include "../src/mad.h"
78 static void *memmove (void *dest
, const void *src
, size_t n
)
88 t
= (char *) dest
+ n
;
97 /* #define itoa MY_itoa <---- this line is now in edit.h */
106 } while ((i
= i
/ 10));
113 This joins strings end on end and allocates memory for the result.
114 The result is later automatically free'd and must not be free'd
117 char *catstrs (const char *first
,...)
119 static char *stacked
[16] =
120 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
129 len
= strlen (first
);
130 va_start (ap
, first
);
132 while ((data
= va_arg (ap
, char *)) != 0)
133 len
+= strlen (data
);
141 stacked
[i
] = malloc (len
);
143 va_start (ap
, first
);
144 strcpy (stacked
[i
], first
);
145 while ((data
= va_arg (ap
, char *)) != 0)
146 strcat (stacked
[i
], data
);
155 void edit_help_cmd (WEdit
* edit
)
157 char *hlpdir
= concat_dir_and_file (mc_home
, "mc.hlp");
158 interactive_display (hlpdir
, "[Internal File Editor]");
160 edit
->force
|= REDRAW_COMPLETELY
;
163 void edit_refresh_cmd (WEdit
* edit
)
171 edit_get_syntax_color (edit
, -1, &fg
, &bg
);
181 void edit_help_cmd (WEdit
* edit
)
185 void edit_refresh_cmd (WEdit
* edit
)
189 void CRefreshEditor (WEdit
* edit
)
191 edit_refresh_cmd (edit
);
198 /* three argument open */
199 int my_open (const char *pathname
, int flags
,...)
204 file
= open ((char *) pathname
, O_RDONLY
);
205 if (file
< 0 && (flags
& O_CREAT
)) { /* must it be created ? */
208 mode
= va_arg(ap
, mode_t
);
210 return creat ((char *) pathname
, mode
);
213 return open ((char *) pathname
, flags
);
220 /* "Oleg Yu. Repin" <repin@ssd.sscc.ru> added backup filenames
223 /* If 0 (quick save) then a) create/truncate <filename> file,
224 b) save to <filename>;
225 if 1 (safe save) then a) save to <tempnam>,
226 b) rename <tempnam> to <filename>;
227 if 2 (do backups) then a) save to <tempnam>,
228 b) rename <filename> to <filename.backup_ext>,
229 c) rename <tempnam> to <filename>. */
231 /* returns 0 on error */
232 int edit_save_file (WEdit
* edit
, const char *filename
)
237 char *savename
= (char *) filename
;
240 if ((file
= open (savename
, O_WRONLY
)) == -1) {
241 this_save_mode
= 0; /* the file does not exists yet, so no safe save or backup necessary */
244 this_save_mode
= option_save_mode
;
247 if (this_save_mode
> 0) {
248 char *savedir
= ".", *slashpos
= strrchr (filename
, '/');
250 savedir
= strdup (filename
);
253 savedir
[slashpos
- filename
+ 1] = '\0';
256 savename
= strdup (tempnam (savedir
, "cooledit"));
258 savename
= tempnam (savedir
, "cooledit");
265 if ((file
= open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| MY_O_TEXT
, edit
->stat
.st_mode
)) == -1) {
266 if (this_save_mode
> 0)
270 chown (savename
, edit
->stat
.st_uid
, edit
->stat
.st_gid
);
272 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
273 filelen
+= write (file
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
);
276 filelen
+= write (file
, (char *) edit
->buffers1
[buf
], edit
->curs1
& M_EDIT_BUF_SIZE
);
280 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
281 filelen
+= write (file
, (char *) edit
->buffers2
[buf
] + EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1, 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
));
284 filelen
+= write (file
, (char *) edit
->buffers2
[buf
], EDIT_BUF_SIZE
);
291 if (filelen
== edit
->last_byte
) {
292 if (this_save_mode
== 2) {
293 if (rename (filename
, catstrs (filename
, option_backup_ext
, 0)) == -1) { /* catstrs free's automatically */
298 if (this_save_mode
> 0) {
299 if (rename (savename
, filename
) == -1) {
307 if (this_save_mode
> 0)
315 I changed this from Oleg's original routine so
316 that option_backup_ext works with coolwidgets as well. This
317 does mean there is a memory leak - paul.
319 void menu_save_mode_cmd (void)
323 static char *str_result
;
324 static int save_mode_new
;
330 static QuickWidget widgets
[] =
332 {quick_button
, 18, DLG_X
, 7, DLG_Y
, "&Cancel", 0,
333 B_CANCEL
, 0, 0, XV_WLAY_DONTCARE
, "c"},
334 {quick_button
, 6, DLG_X
, 7, DLG_Y
, "&Ok", 0,
335 B_ENTER
, 0, 0, XV_WLAY_DONTCARE
, "o"},
336 {quick_input
, 23, DLG_X
, 5, DLG_Y
, 0, 9,
337 0, 0, &str_result
, XV_WLAY_DONTCARE
, "i"},
338 {quick_label
, 22, DLG_X
, 4, DLG_Y
, "Extension:", 0,
339 0, 0, 0, XV_WLAY_DONTCARE
, "savemext"},
340 {quick_radio
, 4, DLG_X
, 3, DLG_Y
, "", 3,
341 0, &save_mode_new
, str
, XV_WLAY_DONTCARE
, "t"},
343 static QuickDialog dialog
=
345 {DLG_X
, DLG_Y
, -1, -1, " Edit Save Mode ", "[Edit Save Mode]",
348 widgets
[2].text
= option_backup_ext
;
349 widgets
[4].value
= option_save_mode
;
350 if (quick_dialog (&dialog
) != B_ENTER
)
352 option_save_mode
= save_mode_new
;
353 option_backup_ext
= str_result
; /* this is a memory leak */
354 option_backup_ext_int
= 0;
355 str_result
[min (strlen (str_result
), sizeof (int))] = '\0';
356 memcpy ((char *) &option_backup_ext_int
, str_result
, strlen (option_backup_ext
));
363 void edit_split_filename (WEdit
* edit
, char *f
)
366 free (edit
->filename
);
367 edit
->filename
= strdup (f
);
370 edit
->dir
= strdup ("");
375 void edit_split_filename (WEdit
* edit
, char *longname
)
378 exp
= canonicalize_pathname (longname
); /* this ensures a full path */
380 free (edit
->filename
);
383 p
= strrchr (exp
, '/');
384 edit
->filename
= strdup (++p
);
386 edit
->dir
= strdup (exp
);
392 /* here we want to warn the user of overwriting an existing file, but only if they
393 have made a change to the filename */
394 /* returns 1 on success */
395 int edit_save_as_cmd (WEdit
* edit
)
397 /* This heads the 'Save As' dialog box */
398 char *exp
= edit_get_save_file (edit
->dir
, edit
->filename
, _(" Save As "));
399 int different_filename
= 0;
400 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
401 edit
->force
|= REDRAW_COMPLETELY
;
408 if (strcmp(catstrs (edit
->dir
, edit
->filename
, 0), exp
)) {
410 different_filename
= 1;
411 if ((file
= open ((char *) exp
, O_RDONLY
)) != -1) { /* the file exists */
413 if (edit_query_dialog2 (_(" Warning "),
414 _(" A file already exists with this name. "),
415 /* Push buttons to over-write the current file, or cancel the operation */
416 _("Overwrite"), _("Cancel")))
420 if (edit_save_file (edit
, exp
)) {
421 edit_split_filename (edit
, exp
);
425 edit
->delete_file
= 0;
427 if (different_filename
&& !edit
->explicit_syntax
)
428 edit_load_syntax (edit
, 0, 0);
432 edit_error_dialog (_(" Save as "), get_sys_error (_(" Error trying to save file. ")));
440 /* {{{ Macro stuff starts here */
443 int raw_callback (struct Dlg_head
*h
, int key
, int Msg
)
447 attrset (REVERSE_COLOR
);
449 draw_box (h
, 1, 1, h
->lines
- 2, h
->cols
- 2);
451 attrset (COLOR_HOT_NORMAL
);
464 /* gets a raw key from the keyboard. Passing cancel = 1 draws
465 a cancel button thus allowing c-c etc.. Alternatively, cancel = 0
466 will return the next key pressed */
467 int edit_raw_key_query (char *heading
, char *query
, int cancel
)
469 int w
= strlen (query
) + 7;
470 struct Dlg_head
*raw_dlg
= create_dlg (0, 0, 7, w
, dialog_colors
,
472 raw_callback
, "[Raw Key Query]",
474 DLG_CENTER
| DLG_TRYUP
);
475 x_set_dialog_title (raw_dlg
, heading
);
476 raw_dlg
->raw
= 1; /* to return even a tab key */
478 add_widget (raw_dlg
, button_new (4, w
/ 2 - 5, B_CANCEL
, NORMAL_BUTTON
, "Cancel", 0, 0, 0));
479 add_widget (raw_dlg
, label_new (3 - cancel
, 2, query
, 0));
480 add_widget (raw_dlg
, input_new (3 - cancel
, w
- 5, INPUT_COLOR
, 2, "", 0));
482 w
= raw_dlg
->ret_value
;
483 destroy_dlg (raw_dlg
);
485 if (w
== XCTRL ('g') || w
== XCTRL ('c') || w
== ESC_CHAR
|| w
== B_CANCEL
)
487 /* hence ctrl-a (=B_CANCEL), ctrl-g, ctrl-c, and Esc are cannot returned */
493 int edit_raw_key_query (char *heading
, char *query
, int cancel
)
495 return CKeySymMod (CRawkeyQuery (0, 0, 0, heading
, query
));
500 /* creates a macro file if it doesn't exist */
501 static FILE *edit_open_macro_file (const char *r
)
505 filename
= catstrs (home_dir
, MACRO_FILE
, 0);
506 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1)
509 return fopen (filename
, r
);
512 #define MAX_MACROS 1024
513 static int saved_macro
[MAX_MACROS
+ 1] =
515 static int saved_macros_loaded
= 0;
518 This is just to stop the macro file be loaded over and over for keys
519 that aren't defined to anything. On slow systems this could be annoying.
521 int macro_exists (int k
)
524 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
525 if (saved_macro
[i
] == k
)
530 /* returns 1 on error */
531 int edit_delete_macro (WEdit
* edit
, int k
)
533 struct macro macro
[MAX_MACRO_LENGTH
];
537 if (saved_macros_loaded
)
538 if ((j
= macro_exists (k
)) < 0)
540 g
= fopen (catstrs (home_dir
, TEMP_FILE
, 0), "w");
542 /* This heads the delete macro error dialog box */
543 edit_error_dialog (_(" Delete macro "),
544 /* 'Open' = load temp file */
545 get_sys_error (_(" Error trying to open temp file ")));
548 f
= edit_open_macro_file ("r");
550 /* This heads the delete macro error dialog box */
551 edit_error_dialog (_(" Delete macro "),
552 /* 'Open' = load temp file */
553 get_sys_error (_(" Error trying to open macro file ")));
558 n
= fscanf (f
, _("key '%d 0': "), &s
);
562 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
566 fprintf (g
, _("key '%d 0': "), s
);
567 for (i
= 0; i
< n
; i
++)
568 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
574 if (rename (catstrs (home_dir
, TEMP_FILE
, 0), catstrs (home_dir
, MACRO_FILE
, 0)) == -1) {
575 /* This heads the delete macro error dialog box */
576 edit_error_dialog (_(" Delete macro "),
577 get_sys_error (_(" Error trying to overwrite macro file ")));
580 if (saved_macros_loaded
)
581 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
585 /* returns 0 on error */
586 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
591 edit
->force
|= REDRAW_COMPLETELY
;
592 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
593 /* This heads the 'Macro' dialog box */
594 s
= edit_raw_key_query (_(" Macro "),
595 /* Input line for a single key press follows the ':' */
596 _(" Press the macro's new hotkey: "), 1);
598 if (edit_delete_macro (edit
, s
))
600 f
= edit_open_macro_file ("a+");
602 fprintf (f
, _("key '%d 0': "), s
);
603 for (i
= 0; i
< n
; i
++)
604 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
607 if (saved_macros_loaded
) {
608 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
613 /* This heads the 'Save Macro' dialog box */
614 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Error trying to open macro file ")));
619 void edit_delete_macro_cmd (WEdit
* edit
)
624 command
= CK_Macro (edit_raw_key_query (_(" Delete Macro "), _(" Press macro hotkey: "), 1));
626 /* This heads the 'Delete Macro' dialog box */
627 command
= CK_Macro (CKeySymMod (CRawkeyQuery (0, 0, 0, _(" Delete Macro "),
628 /* Input line for a single key press follows the ':' */
629 _(" Press macro hotkey: "))));
632 if (command
== CK_Macro (0))
635 edit_delete_macro (edit
, command
- 2000);
638 /* return 0 on error */
639 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
642 int s
, i
= 0, found
= 0;
644 if (saved_macros_loaded
)
645 if (macro_exists (k
) < 0)
648 if ((f
= edit_open_macro_file ("r"))) {
652 u
= fscanf (f
, _("key '%d 0': "), &s
);
655 if (!saved_macros_loaded
)
656 saved_macro
[i
++] = s
;
659 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
662 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
667 } while (!found
|| !saved_macros_loaded
);
668 if (!saved_macros_loaded
) {
670 saved_macros_loaded
= 1;
675 /* This heads the 'Load Macro' dialog box */
676 edit_error_dialog (_(" Load macro "),
677 get_sys_error (_(" Error trying to open macro file ")));
681 /* }}} Macro stuff starts here */
683 /* returns 1 on success */
684 int edit_save_confirm_cmd (WEdit
* edit
)
688 if (edit_confirm_save
) {
690 f
= catstrs (_(" Confirm save file? : "), edit
->filename
, " ", 0);
692 f
= catstrs (_(" Confirm save file? : "), edit
->dir
, edit
->filename
, " ", 0);
694 /* Buttons to 'Confirm save file' query */
695 if (edit_query_dialog2 (_(" Save file "), f
, _("Save"), _("Cancel")))
698 return edit_save_cmd (edit
);
702 /* returns 1 on success */
703 int edit_save_cmd (WEdit
* edit
)
705 edit
->force
|= REDRAW_COMPLETELY
;
706 if (!edit_save_file (edit
, catstrs (edit
->dir
, edit
->filename
, 0)))
707 return edit_save_as_cmd (edit
);
710 edit
->delete_file
= 0;
717 /* returns 1 on success */
718 int edit_new_cmd (WEdit
* edit
)
720 edit
->force
|= REDRAW_COMPLETELY
;
722 if (edit_query_dialog2 (_(" Warning "), _(" Current text was modified without a file save. \n Continue discards these changes. "), _("Continue"), _("Cancel")))
725 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
728 int edit_load_cmd (WEdit
* edit
)
731 edit
->force
|= REDRAW_COMPLETELY
;
734 if (edit_query_dialog2 (_(" Warning "), _(" Current text was modified without a file save. \n Continue discards these changes. "), _("Continue"), _("Cancel")))
737 exp
= edit_get_load_file (edit
->dir
, edit
->filename
, _(" Load "));
744 if ((file
= open ((char *) exp
, O_RDONLY
, MY_O_TEXT
)) != -1) {
746 edit_reload (edit
, exp
, 0, "", 0);
747 edit_split_filename (edit
, exp
);
753 /* Heads the 'Load' file dialog box */
754 edit_error_dialog (_(" Load "), get_sys_error (_(" Error trying to open file for reading ")));
762 if mark2 is -1 then marking is from mark1 to the cursor.
763 Otherwise its between the markers. This handles this.
764 Returns 1 if no text is marked.
766 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
768 if (edit
->mark1
!= edit
->mark2
) {
769 if (edit
->mark2
>= 0) {
770 *start_mark
= min (edit
->mark1
, edit
->mark2
);
771 *end_mark
= max (edit
->mark1
, edit
->mark2
);
773 *start_mark
= min (edit
->mark1
, edit
->curs1
);
774 *end_mark
= max (edit
->mark1
, edit
->curs1
);
775 edit
->column2
= edit
->curs_col
;
779 *start_mark
= *end_mark
= 0;
780 edit
->column2
= edit
->column1
= 0;
785 /*Block copy, move and delete commands */
787 void edit_block_copy_cmd (WEdit
* edit
)
789 long start_mark
, end_mark
, current
= edit
->curs1
;
793 if (eval_marks (edit
, &start_mark
, &end_mark
))
797 copy_buf
= malloc (end_mark
- start_mark
);
799 /* all that gets pushed are deletes hence little space is used on the stack */
801 edit_push_markers (edit
);
804 while (count
< end_mark
) {
805 copy_buf
[end_mark
- count
- 1] = edit_get_byte (edit
, count
);
808 while (count
-- > start_mark
) {
809 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
812 edit_scroll_screen_over_cursor (edit
);
814 if (start_mark
< current
&& end_mark
> current
)
815 edit_set_markers (edit
, start_mark
, end_mark
+ end_mark
- start_mark
, 0, 0);
817 edit
->force
|= REDRAW_PAGE
;
821 void edit_block_move_cmd (WEdit
* edit
)
826 long start_mark
, end_mark
;
828 if (eval_marks (edit
, &start_mark
, &end_mark
))
831 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
834 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
835 if (edit_query_dialog2 (_(" Warning "), _(" Block is large, you may not be able to undo this action. "), _("Continue"), _("Cancel")))
838 copy_buf
= malloc (end_mark
- start_mark
);
840 edit_push_markers (edit
);
842 current
= edit
->curs1
;
843 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
844 edit_scroll_screen_over_cursor (edit
);
847 while (count
< end_mark
) {
848 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
);
851 edit_scroll_screen_over_cursor (edit
);
853 edit_cursor_move (edit
, current
- edit
->curs1
854 - (((current
- edit
->curs1
) > 0) ? end_mark
- start_mark
: 0));
855 edit_scroll_screen_over_cursor (edit
);
857 while (count
-- > start_mark
) {
858 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
859 edit_set_markers (edit
, edit
->curs1
, edit
->curs1
+ end_mark
- start_mark
, 0, 0);
861 edit_scroll_screen_over_cursor (edit
);
864 edit
->force
|= REDRAW_PAGE
;
867 void edit_cursor_to_bol (WEdit
* edit
);
869 extern int column_highlighting
;
871 void edit_delete_column_of_text (WEdit
* edit
)
873 long p
, q
, r
, m1
, m2
;
876 eval_marks (edit
, &m1
, &m2
);
877 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
878 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
885 eval_marks (edit
, &m1
, &m2
);
886 r
= edit_bol (edit
, edit
->curs1
);
887 p
= edit_move_forward3 (edit
, r
, b
, 0);
888 q
= edit_move_forward3 (edit
, r
, c
, 0);
895 edit_cursor_move (edit
, p
- edit
->curs1
);
896 while (p
!= q
) { /* delete line between margins */
897 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
901 if (!fin
) /* next line */
902 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
906 /* returns 1 if canceelled by user */
907 int edit_block_delete_cmd (WEdit
* edit
)
910 long start_mark
, end_mark
;
912 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
913 start_mark
= edit_bol (edit
, edit
->curs1
);
914 end_mark
= edit_eol (edit
, edit
->curs1
) + 1;
916 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
917 /* Warning message with a query to continue or cancel the operation */
918 if (edit_query_dialog2 (_(" Warning "), _(" Block is large, you may not be able to undo this action. "), _(" Continue "), _(" Cancel ")))
921 edit_push_markers (edit
);
923 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
924 edit_scroll_screen_over_cursor (edit
);
927 if (start_mark
< end_mark
) {
928 if (column_highlighting
) {
929 edit_delete_column_of_text (edit
);
931 while (count
< end_mark
) {
937 edit_set_markers (edit
, 0, 0, 0, 0);
938 edit
->force
|= REDRAW_PAGE
;
946 #define INPUT_INDEX 9
947 #define SEARCH_DLG_HEIGHT 10
948 #define REPLACE_DLG_HEIGHT 15
949 #define B_REPLACE_ALL B_USER+1
950 #define B_SKIP_REPLACE B_USER+2
952 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
954 if (replace_prompt
) {
955 QuickWidget quick_widgets
[] =
957 /* NLS for hotkeys? */
958 {quick_button
, 14, 18, 3, 6, "&Cancel", 0, B_CANCEL
, 0,
959 0, XV_WLAY_DONTCARE
, NULL
},
960 {quick_button
, 9, 18, 3, 6, "Replace &all", 0, B_REPLACE_ALL
, 0,
961 0, XV_WLAY_DONTCARE
, NULL
},
962 {quick_button
, 6, 18, 3, 6, "&Skip", 0, B_SKIP_REPLACE
, 0,
963 0, XV_WLAY_DONTCARE
, NULL
},
964 {quick_button
, 2, 18, 3, 6, "&Replace", 0, B_ENTER
, 0,
965 0, XV_WLAY_DONTCARE
, NULL
},
966 {quick_label
, 2, 50, 2, 6, 0,
967 0, 0, 0, XV_WLAY_DONTCARE
, 0},
970 quick_widgets
[4].text
= catstrs (_(" Replace with: "), replace_text
, 0);
973 QuickDialog Quick_input
=
974 {66, 6, 0, 0, N_(" Replace "),
975 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
977 Quick_input
.widgets
= quick_widgets
;
979 Quick_input
.xpos
= xpos
;
980 Quick_input
.ypos
= ypos
;
981 return quick_dialog (&Quick_input
);
989 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
991 int treplace_scanf
= replace_scanf
;
992 int treplace_regexp
= replace_regexp
;
993 int treplace_all
= replace_all
;
994 int treplace_prompt
= replace_prompt
;
995 int treplace_backwards
= replace_backwards
;
996 int treplace_whole
= replace_whole
;
997 int treplace_case
= replace_case
;
1000 char *treplace_text
;
1002 QuickWidget quick_widgets
[] =
1004 {quick_button
, 6, 10, 12, REPLACE_DLG_HEIGHT
, "&Cancel", 0, B_CANCEL
, 0,
1005 0, XV_WLAY_DONTCARE
, NULL
},
1006 {quick_button
, 2, 10, 12, REPLACE_DLG_HEIGHT
, "&Ok", 0, B_ENTER
, 0,
1007 0, XV_WLAY_DONTCARE
, NULL
},
1008 {quick_checkbox
, 25, 50, 11, REPLACE_DLG_HEIGHT
, "Scanf &expression", 0, 0,
1009 0, 0, XV_WLAY_DONTCARE
, NULL
},
1010 {quick_checkbox
, 25, 50, 10, REPLACE_DLG_HEIGHT
, "Replace &all", 0, 0,
1011 0, 0, XV_WLAY_DONTCARE
, NULL
},
1012 {quick_checkbox
, 25, 50, 9, REPLACE_DLG_HEIGHT
, "Pr&ompt on replace", 0, 0,
1013 0, 0, XV_WLAY_DONTCARE
, NULL
},
1014 {quick_checkbox
, 4, 50, 11, REPLACE_DLG_HEIGHT
, "&Backwards", 0, 0,
1015 0, 0, XV_WLAY_DONTCARE
, NULL
},
1016 {quick_checkbox
, 4, 50, 10, REPLACE_DLG_HEIGHT
, "&Regular exprssn", 0, 0,
1017 0, 0, XV_WLAY_DONTCARE
, NULL
},
1018 {quick_checkbox
, 4, 50, 9, REPLACE_DLG_HEIGHT
, "&Whole words only", 0, 0,
1019 0, 0, XV_WLAY_DONTCARE
, NULL
},
1020 {quick_checkbox
, 4, 50, 8, REPLACE_DLG_HEIGHT
, "Case &sensitive", 0, 0,
1021 0, 0, XV_WLAY_DONTCARE
, NULL
},
1022 {quick_input
, 3, 50, 7, REPLACE_DLG_HEIGHT
, "", 44, 0, 0,
1023 0, XV_WLAY_BELOWCLOSE
, "edit-argord"},
1024 {quick_label
, 2, 50, 6, REPLACE_DLG_HEIGHT
, " Enter replacement argument order eg. 3,2,1,4 ", 0, 0,
1025 0, 0, XV_WLAY_DONTCARE
, 0},
1026 {quick_input
, 3, 50, 5, REPLACE_DLG_HEIGHT
, "", 44, 0, 0,
1027 0, XV_WLAY_BELOWCLOSE
, "edit-replace"},
1028 {quick_label
, 2, 50, 4, REPLACE_DLG_HEIGHT
, " Enter replacement string", 0, 0, 0,
1029 0, XV_WLAY_DONTCARE
, 0},
1030 {quick_input
, 3, 50, 3, REPLACE_DLG_HEIGHT
, "", 44, 0, 0,
1031 0, XV_WLAY_BELOWCLOSE
, "edit-search"},
1032 {quick_label
, 2, 50, 2, REPLACE_DLG_HEIGHT
, " Enter search string", 0, 0, 0,
1033 0, XV_WLAY_DONTCARE
, 0},
1036 quick_widgets
[2].result
= &treplace_scanf
;
1037 quick_widgets
[3].result
= &treplace_all
;
1038 quick_widgets
[4].result
= &treplace_prompt
;
1039 quick_widgets
[5].result
= &treplace_backwards
;
1040 quick_widgets
[6].result
= &treplace_regexp
;
1041 quick_widgets
[7].result
= &treplace_whole
;
1042 quick_widgets
[8].result
= &treplace_case
;
1043 quick_widgets
[9].str_result
= &targ_order
;
1044 quick_widgets
[9].text
= *arg_order
;
1045 quick_widgets
[11].str_result
= &treplace_text
;
1046 quick_widgets
[11].text
= *replace_text
;
1047 quick_widgets
[13].str_result
= &tsearch_text
;
1048 quick_widgets
[13].text
= *search_text
;
1050 QuickDialog Quick_input
=
1051 {50, REPLACE_DLG_HEIGHT
, -1, 0, N_(" Replace "),
1052 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1054 Quick_input
.widgets
= quick_widgets
;
1056 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
1057 *arg_order
= *(quick_widgets
[INPUT_INDEX
].str_result
);
1058 *replace_text
= *(quick_widgets
[INPUT_INDEX
+ 2].str_result
);
1059 *search_text
= *(quick_widgets
[INPUT_INDEX
+ 4].str_result
);
1060 replace_scanf
= treplace_scanf
;
1061 replace_backwards
= treplace_backwards
;
1062 replace_regexp
= treplace_regexp
;
1063 replace_all
= treplace_all
;
1064 replace_prompt
= treplace_prompt
;
1065 replace_whole
= treplace_whole
;
1066 replace_case
= treplace_case
;
1070 *replace_text
= NULL
;
1071 *search_text
= NULL
;
1078 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1080 int treplace_scanf
= replace_scanf
;
1081 int treplace_regexp
= replace_regexp
;
1082 int treplace_whole
= replace_whole
;
1083 int treplace_case
= replace_case
;
1084 int treplace_backwards
= replace_backwards
;
1087 QuickWidget quick_widgets
[] =
1089 {quick_button
, 6, 10, 7, SEARCH_DLG_HEIGHT
, "&Cancel", 0, B_CANCEL
, 0,
1090 0, XV_WLAY_DONTCARE
, NULL
},
1091 {quick_button
, 2, 10, 7, SEARCH_DLG_HEIGHT
, "&Ok", 0, B_ENTER
, 0,
1092 0, XV_WLAY_DONTCARE
, NULL
},
1093 {quick_checkbox
, 25, 50, 6, SEARCH_DLG_HEIGHT
, "Scanf &expression", 0, 0,
1094 0, 0, XV_WLAY_DONTCARE
, NULL
},
1095 {quick_checkbox
, 25, 50, 5, SEARCH_DLG_HEIGHT
, "&Backwards", 0, 0,
1096 0, 0, XV_WLAY_DONTCARE
, NULL
},
1097 {quick_checkbox
, 4, 50, 6, SEARCH_DLG_HEIGHT
, "&Regular exprssn", 0, 0,
1098 0, 0, XV_WLAY_DONTCARE
, NULL
},
1099 {quick_checkbox
, 4, 50, 5, SEARCH_DLG_HEIGHT
, "&Whole words only", 0, 0,
1100 0, 0, XV_WLAY_DONTCARE
, NULL
},
1101 {quick_checkbox
, 4, 50, 4, SEARCH_DLG_HEIGHT
, "Case &sensitive", 0, 0,
1102 0, 0, XV_WLAY_DONTCARE
, NULL
},
1103 {quick_input
, 3, 50, 3, SEARCH_DLG_HEIGHT
, "", 44, 0, 0,
1104 0, XV_WLAY_BELOWCLOSE
, "edit-search"},
1105 {quick_label
, 2, 50, 2, SEARCH_DLG_HEIGHT
, " Enter search string", 0, 0, 0,
1106 0, XV_WLAY_DONTCARE
, 0},
1109 quick_widgets
[2].result
= &treplace_scanf
;
1110 quick_widgets
[3].result
= &treplace_backwards
;
1111 quick_widgets
[4].result
= &treplace_regexp
;
1112 quick_widgets
[5].result
= &treplace_whole
;
1113 quick_widgets
[6].result
= &treplace_case
;
1114 quick_widgets
[7].str_result
= &tsearch_text
;
1115 quick_widgets
[7].text
= *search_text
;
1118 QuickDialog Quick_input
=
1119 {50, SEARCH_DLG_HEIGHT
, -1, 0, N_(" Search "),
1120 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
1122 Quick_input
.widgets
= quick_widgets
;
1124 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
1125 *search_text
= *(quick_widgets
[7].str_result
);
1126 replace_scanf
= treplace_scanf
;
1127 replace_backwards
= treplace_backwards
;
1128 replace_regexp
= treplace_regexp
;
1129 replace_whole
= treplace_whole
;
1130 replace_case
= treplace_case
;
1133 *search_text
= NULL
;
1143 #define B_SKIP_REPLACE 1
1144 #define B_REPLACE_ALL 2
1147 extern CWidget
*wedit
;
1149 void edit_search_replace_dialog (Window parent
, int x
, int y
, char **search_text
, char **replace_text
, char **arg_order
, char *heading
, int option
)
1155 int xh
, yh
, h
, xb
, ys
, yc
, yb
, yr
;
1161 win
= CDrawHeadedDialog ("replace", parent
, x
, y
, heading
);
1162 CGetHintPos (&xh
, &h
);
1165 CIdent ("replace")->position
= WINDOW_ALWAYS_RAISED
;
1166 /* An input line comes after the ':' */
1167 (CDrawText ("replace.t1", win
, xh
, h
, _(" Enter search text : ")))->hotkey
= 'E';
1169 CGetHintPos (0, &yh
);
1170 (m
= CDrawTextInput ("replace.sinp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 256, *search_text
))->hotkey
= 'E';
1173 CGetHintPos (0, &yh
);
1174 (CDrawText ("replace.t2", win
, xh
, yh
, _(" Enter replace text : ")))->hotkey
= 'n';
1175 CGetHintPos (0, &yh
);
1176 (CDrawTextInput ("replace.rinp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 256, *replace_text
))->hotkey
= 'n';
1177 CGetHintPos (0, &yh
);
1178 (CDrawText ("replace.t3", win
, xh
, yh
, _(" Enter argument order : ")))->hotkey
= 'o';
1179 CGetHintPos (0, &yh
);
1180 (CDrawTextInput ("replace.ainp", win
, xh
, yh
, 10, AUTO_HEIGHT
, 256, *arg_order
))->hotkey
= 'o';
1182 CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf format specifiers"));
1183 CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf format specifiers"));
1185 CGetHintPos (0, &yh
);
1187 /* The following are check boxes */
1188 CDrawSwitch ("replace.ww", win
, xh
, yh
, replace_whole
, _(" Whole words only "), 0);
1189 CGetHintPos (0, &yh
);
1190 CDrawSwitch ("replace.case", win
, xh
, yh
, replace_case
, _(" Case sensitive "), 0);
1192 CGetHintPos (0, &yh
);
1193 CDrawSwitch ("replace.reg", win
, xh
, yh
, replace_regexp
, _(" Regular expression "), 1);
1194 CSetToolHint ("replace.reg", _("See the regex man page for how to compose a regular expression"));
1195 CSetToolHint ("replace.reg.label", _("See the regex man page for how to compose a regular expression"));
1197 CGetHintPos (0, &yh
);
1198 CGetHintPos (&xb
, 0);
1200 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1201 CDrawSwitch ("replace.bkwd", win
, xh
, yh
, replace_backwards
, _(" Backwards "), 0);
1203 CSetToolHint ("replace.bkwd", _("Warning: Searching backward can be slow"));
1204 CSetToolHint ("replace.bkwd.label", _("Warning: Searching backward can be slow"));
1208 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
)
1217 CDrawSwitch ("replace.pr", win
, xb
, yr
, replace_prompt
, _(" Prompt on replace "), 0);
1219 CSetToolHint ("replace.pr", _("Ask before making each replacement"));
1220 CGetHintPos (0, &yr
);
1221 CDrawSwitch ("replace.all", win
, xb
, yr
, replace_all
, _(" Replace all "), 0);
1222 CGetHintPos (0, &yr
);
1224 CDrawSwitch ("replace.scanf", win
, xb
, yr
, replace_scanf
, _(" Scanf expression "), 1);
1226 CSetToolHint ("replace.scanf", _("Allows entering of a C format string, see the scanf man page"));
1228 get_hint_limits (&x
, &y
);
1229 CDrawPixmapButton ("replace.ok", win
, x
- WIDGET_SPACING
- TICK_BUTTON_WIDTH
, h
, PIXMAP_BUTTON_TICK
);
1231 CSetToolHint ("replace.ok", _("Begin search, Enter"));
1232 CDrawPixmapButton ("replace.cancel", win
, x
- WIDGET_SPACING
- TICK_BUTTON_WIDTH
, h
+ WIDGET_SPACING
+ TICK_BUTTON_WIDTH
, PIXMAP_BUTTON_CROSS
);
1234 CSetToolHint ("replace.cancel", _("Abort this dialog, Esc"));
1235 CSetSizeHintPos ("replace");
1236 CMapDialog ("replace");
1238 m
= CIdent ("replace");
1239 CSetWidgetSize ("replace.sinp", m
->width
- WIDGET_SPACING
* 3 - 4 - TICK_BUTTON_WIDTH
, (CIdent ("replace.sinp"))->height
);
1241 CSetWidgetSize ("replace.rinp", m
->width
- WIDGET_SPACING
* 3 - 4 - TICK_BUTTON_WIDTH
, (CIdent ("replace.rinp"))->height
);
1242 CSetWidgetSize ("replace.ainp", m
->width
- WIDGET_SPACING
* 3 - 4 - TICK_BUTTON_WIDTH
, (CIdent ("replace.ainp"))->height
);
1244 CFocus (CIdent ("replace.sinp"));
1247 CNextEvent (&xev
, &cev
);
1248 if (!CIdent ("replace")) {
1252 if (!strcmp (cev
.ident
, "replace.cancel") || cev
.command
== CK_Cancel
) {
1256 if (!strcmp (cev
.ident
, "replace.reg") || !strcmp (cev
.ident
, "replace.scanf")) {
1257 if (CIdent ("replace.reg")->keypressed
|| CIdent ("replace.scanf")->keypressed
) {
1258 if (!(CIdent ("replace.case")->keypressed
)) {
1259 CIdent ("replace.case")->keypressed
= 1;
1260 CExpose ("replace.case");
1264 if (!strcmp (cev
.ident
, "replace.ok") || cev
.command
== CK_Enter
) {
1266 replace_all
= CIdent ("replace.all")->keypressed
;
1267 replace_prompt
= CIdent ("replace.pr")->keypressed
;
1268 *replace_text
= strdup (CIdent ("replace.rinp")->text
);
1269 *arg_order
= strdup (CIdent ("replace.ainp")->text
);
1271 *search_text
= strdup (CIdent ("replace.sinp")->text
);
1272 replace_whole
= CIdent ("replace.ww")->keypressed
;
1273 replace_case
= CIdent ("replace.case")->keypressed
;
1274 replace_scanf
= CIdent ("replace.scanf")->keypressed
;
1275 replace_regexp
= CIdent ("replace.reg")->keypressed
;
1277 if (option
& SEARCH_DIALOG_OPTION_BACKWARDS
) {
1278 replace_backwards
= CIdent ("replace.bkwd")->keypressed
;
1280 replace_backwards
= 0;
1286 CDestroyWidget ("replace");
1292 void edit_search_dialog (WEdit
* edit
, char **search_text
)
1294 /* Heads the 'Search' dialog box */
1295 edit_search_replace_dialog (WIN_MESSAGES
, search_text
, 0, 0, _(" Search "), SEARCH_DIALOG_OPTION_BACKWARDS
);
1298 void edit_replace_dialog (WEdit
* edit
, char **search_text
, char **replace_text
, char **arg_order
)
1300 /* Heads the 'Replace' dialog box */
1301 edit_search_replace_dialog (WIN_MESSAGES
, search_text
, replace_text
, arg_order
, _(" Replace "), SEARCH_DIALOG_OPTION_BACKWARDS
);
1304 int edit_replace_prompt (WEdit
* edit
, char *replace_text
, int xpos
, int ypos
)
1306 if (replace_prompt
) {
1309 r
= p
= malloc (strlen (replace_text
) + NUM_REPL_ARGS
* 2);
1310 strcpy (p
, replace_text
);
1311 while ((p
= strchr (p
, '%'))) { /* convert "%" to "%%" so no convertion is attempted */
1312 memmove (p
+ 2, p
+ 1, strlen (p
) + 1);
1316 edit
->force
|= REDRAW_COMPLETELY
;
1317 q
= edit_query_dialog4 (_(" Replace "),
1318 /* This is for the confirm replace dialog box. The replaced string comes after the ':' */
1319 catstrs (_(" Replace with: "), r
, 0),
1320 /* Buttons for the confirm replace dialog box. */
1321 _("Replace"), _("Skip"), _("Replace all"), _("Cancel"));
1328 return B_SKIP_REPLACE
;
1330 return B_REPLACE_ALL
;
1342 long sargs
[NUM_REPL_ARGS
][256 / sizeof (long)];
1344 #define SCANF_ARGS sargs[0], sargs[1], sargs[2], sargs[3], \
1345 sargs[4], sargs[5], sargs[6], sargs[7], \
1346 sargs[8], sargs[9], sargs[10], sargs[11], \
1347 sargs[12], sargs[13], sargs[14], sargs[15]
1349 #define PRINTF_ARGS sargs[argord[0]], sargs[argord[1]], sargs[argord[2]], sargs[argord[3]], \
1350 sargs[argord[4]], sargs[argord[5]], sargs[argord[6]], sargs[argord[7]], \
1351 sargs[argord[8]], sargs[argord[9]], sargs[argord[10]], sargs[argord[11]], \
1352 sargs[argord[12]], sargs[argord[13]], sargs[argord[14]], sargs[argord[15]]
1354 /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
1355 /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
1356 int string_regexp_search (char *pattern
, char *string
, int len
, int match_type
, int match_bol
, int icase
, int *found_len
)
1359 regmatch_t pmatch
[1];
1360 static char *old_pattern
= NULL
;
1361 static int old_type
, old_icase
;
1363 if (!old_pattern
|| strcmp (old_pattern
, pattern
) || old_type
!= match_type
|| old_icase
!= icase
) {
1369 if (regcomp (&r
, pattern
, REG_EXTENDED
| (icase
? REG_ICASE
: 0))) {
1373 old_pattern
= strdup (pattern
);
1374 old_type
= match_type
;
1377 if (regexec (&r
, string
, 1, pmatch
, ((match_bol
|| match_type
!= match_normal
) ? 0 : REG_NOTBOL
)) != 0) {
1381 *found_len
= pmatch
[0].rm_eo
- pmatch
[0].rm_so
;
1382 return (pmatch
[0].rm_so
);
1385 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1386 (and the above) routines to work properly - paul */
1388 long edit_find_string (long start
, unsigned char *exp
, int *len
, long last_byte
, int (*get_byte
) (void *, long), void *data
, int once_only
)
1391 long l
= strlen ((char *) exp
), f
= 0;
1394 for (p
= 0; p
< l
; p
++) /* count conversions... */
1396 if (exp
[++p
] != '%') /* ...except for "%%" */
1399 if (replace_scanf
|| replace_regexp
) {
1402 unsigned char mbuf
[MAX_REPL_LEN
* 2 + 3];
1404 replace_scanf
= (!replace_regexp
); /* can't have both */
1408 if (replace_scanf
) {
1409 unsigned char e
[MAX_REPL_LEN
];
1410 if (n
>= NUM_REPL_ARGS
)
1414 for (p
= start
; p
< last_byte
&& p
< start
+ MAX_REPL_LEN
; p
++)
1415 buf
[p
- start
] = (*get_byte
) (data
, p
);
1417 for (p
= 0; exp
[p
] != 0; p
++)
1418 exp
[p
] = my_lower_case (exp
[p
]);
1419 for (p
= start
; p
< last_byte
&& p
< start
+ MAX_REPL_LEN
; p
++) {
1420 c
= (*get_byte
) (data
, p
);
1421 buf
[p
- start
] = my_lower_case (c
);
1425 buf
[(q
= p
- start
)] = 0;
1426 strcpy ((char *) e
, (char *) exp
);
1427 strcat ((char *) e
, "%n");
1431 *((int *) sargs
[n
]) = 0; /* --> here was the problem - now fixed: good */
1432 if (n
== sscanf ((char *) buf
, (char *) exp
, SCANF_ARGS
)) {
1433 if (*((int *) sargs
[n
])) {
1434 *len
= *((int *) sargs
[n
]);
1440 if (q
+ start
< last_byte
) {
1442 buf
[q
] = (*get_byte
) (data
, q
+ start
);
1444 c
= (*get_byte
) (data
, q
+ start
);
1445 buf
[q
] = my_lower_case (c
);
1451 buf
++; /* move the window along */
1452 if (buf
== mbuf
+ MAX_REPL_LEN
) { /* the window is about to go past the end of array, so... */
1453 memmove (mbuf
, buf
, strlen ((char *) buf
) + 1); /* reset it */
1458 } else { /* regexp matching */
1460 int found_start
, match_bol
, move_win
= 0;
1462 while (start
+ offset
< last_byte
) {
1463 match_bol
= (offset
== 0 || (*get_byte
) (data
, start
+ offset
- 1) == '\n');
1468 for (; p
< last_byte
&& q
< MAX_REPL_LEN
; p
++, q
++) {
1469 mbuf
[q
] = (*get_byte
) (data
, p
);
1470 if (mbuf
[q
] == '\n')
1479 found_start
= string_regexp_search ((char *) exp
, (char *) buf
, q
, match_normal
, match_bol
, !replace_case
, len
);
1481 if (found_start
<= -2) { /* regcomp/regexec error */
1485 else if (found_start
== -1) /* not found: try next line */
1487 else if (*len
== 0) { /* null pattern: try again at next character */
1494 return (start
+ offset
- q
+ found_start
);
1499 if (buf
[q
- 1] != '\n') { /* incomplete line: try to recover */
1500 buf
= mbuf
+ MAX_REPL_LEN
/ 2;
1501 q
= strlen ((char *) buf
);
1502 memmove (mbuf
, buf
, q
);
1511 *len
= strlen ((char *) exp
);
1513 for (p
= start
; p
<= last_byte
- l
; p
++) {
1514 if ((*get_byte
) (data
, p
) == (unsigned char)exp
[0]) { /* check if first char matches */
1515 for (f
= 0, q
= 0; q
< l
&& f
< 1; q
++)
1516 if ((*get_byte
) (data
, q
+ p
) != (unsigned char)exp
[q
])
1525 for (p
= 0; exp
[p
] != 0; p
++)
1526 exp
[p
] = my_lower_case (exp
[p
]);
1528 for (p
= start
; p
<= last_byte
- l
; p
++) {
1529 if (my_lower_case ((*get_byte
) (data
, p
)) == (unsigned char)exp
[0]) {
1530 for (f
= 0, q
= 0; q
< l
&& f
< 1; q
++)
1531 if (my_lower_case ((*get_byte
) (data
, q
+ p
)) != (unsigned char)exp
[q
])
1545 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
)
1546 { /*front end to find_string to check for
1551 while ((p
= edit_find_string (p
, exp
, len
, last_byte
, get_byte
, data
, once_only
)) >= 0) {
1552 if (replace_whole
) {
1553 /*If the bordering chars are not in option_whole_chars_search then word is whole */
1554 if (!strcasechr (option_whole_chars_search
, (*get_byte
) (data
, p
- 1))
1555 && !strcasechr (option_whole_chars_search
, (*get_byte
) (data
, p
+ *len
)))
1563 p
++; /*not a whole word so continue search. */
1568 long edit_find (long search_start
, unsigned char *exp
, int *len
, long last_byte
, int (*get_byte
) (void *, long), void *data
)
1571 if (replace_backwards
) {
1572 while (search_start
>= 0) {
1573 p
= edit_find_forwards (search_start
, exp
, len
, last_byte
, get_byte
, data
, 1);
1574 if (p
== search_start
)
1579 return edit_find_forwards (search_start
, exp
, len
, last_byte
, get_byte
, data
, 0);
1584 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1586 #define snprintf(v) { \
1591 sprintf(s,q1,v,&n); \
1595 /* this function uses the sprintf command to do a vprintf */
1596 /* it takes pointers to arguments instead of the arguments themselves */
1597 int sprintf_p (char *str
, const char *fmt
,...)
1601 char *q
, *p
, *s
= str
;
1606 p
= q
= (char *) fmt
;
1608 while ((p
= strchr (p
, '%'))) {
1609 n
= (int) ((unsigned long) p
- (unsigned long) q
);
1610 strncpy (s
, q
, n
); /* copy stuff between format specifiers */
1638 strcpy (p1
, itoa (*va_arg (ap
, int *))); /* replace field width with a number */
1641 while (is_digit (*p
))
1648 strcpy (p1
, itoa (*va_arg (ap
, int *))); /* replace precision with a number */
1651 while (is_digit (*p
))
1654 /* flags done, now get argument */
1656 snprintf (va_arg (ap
, char *));
1657 } else if (*p
== 'h') {
1658 if (strchr ("diouxX", *p
))
1659 snprintf (*va_arg (ap
, short *));
1660 } else if (*p
== 'l') {
1662 if (strchr ("diouxX", *p
))
1663 snprintf (*va_arg (ap
, long *));
1664 } else if (strchr ("cdiouxX", *p
)) {
1665 snprintf (*va_arg (ap
, int *));
1666 } else if (*p
== 'L') {
1668 if (strchr ("EefgG", *p
))
1669 snprintf (*va_arg (ap
, double *)); /* should be long double */
1670 } else if (strchr ("EefgG", *p
)) {
1671 snprintf (*va_arg (ap
, double *));
1672 } else if (strchr ("DOU", *p
)) {
1673 snprintf (*va_arg (ap
, long *));
1674 } else if (*p
== 'p') {
1675 snprintf (*va_arg (ap
, void **));
1680 sprintf (s
, q
); /* print trailing leftover */
1681 return (unsigned long) s
- (unsigned long) str
+ strlen (s
);
1684 static void regexp_error (WEdit
*edit
)
1686 /* "Error: Syntax error in regular expression, or scanf expression contained too many %'s */
1687 edit_error_dialog (_(" Error "), _(" Invalid regular expression, or scanf expression with to many conversions "));
1690 /* call with edit = 0 before shutdown to close memory leaks */
1691 void edit_replace_cmd (WEdit
* edit
, int again
)
1693 static char *old1
= NULL
;
1694 static char *old2
= NULL
;
1695 static char *old3
= NULL
;
1700 int replace_continue
;
1702 long times_replaced
= 0, last_search
;
1703 char fin_string
[32];
1704 int argord
[NUM_REPL_ARGS
];
1722 last_search
= edit
->last_byte
;
1724 edit
->force
|= REDRAW_COMPLETELY
;
1726 exp1
= old1
? old1
: exp1
;
1727 exp2
= old2
? old2
: exp2
;
1728 exp3
= old3
? old3
: exp3
;
1733 exp1
= strdup (old1
);
1734 exp2
= strdup (old2
);
1735 exp3
= strdup (old3
);
1737 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1738 edit_replace_dialog (edit
, &exp1
, &exp2
, &exp3
);
1741 if (!exp1
|| !*exp1
) {
1742 edit
->force
= REDRAW_COMPLETELY
;
1756 old1
= strdup (exp1
);
1757 old2
= strdup (exp2
);
1758 old3
= strdup (exp3
);
1763 while ((s
= strchr (exp3
, ' ')))
1764 memmove (s
, s
+ 1, strlen (s
));
1766 for (i
= 0; i
< NUM_REPL_ARGS
; i
++) {
1767 if ((unsigned long) s
!= 1 && s
< exp3
+ strlen (exp3
)) {
1768 if ((ord
= atoi (s
)))
1769 argord
[i
] = ord
- 1;
1772 s
= strchr (s
, ',') + 1;
1778 replace_continue
= replace_all
;
1780 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && replace_backwards
)
1781 edit
->search_start
--;
1783 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !replace_backwards
)
1784 edit
->search_start
++;
1789 new_start
= edit_find (edit
->search_start
, (unsigned char *) exp1
, &len
, last_search
,
1790 (int (*) (void *, long)) edit_get_byte
, (void *) edit
);
1791 if (new_start
== -3) {
1792 regexp_error (edit
);
1795 edit
->search_start
= new_start
;
1796 /*returns negative on not found or error in pattern */
1798 if (edit
->search_start
>= 0) {
1799 edit
->found_start
= edit
->search_start
;
1800 i
= edit
->found_len
= len
;
1802 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1803 edit_scroll_screen_over_cursor (edit
);
1807 if (replace_prompt
) {
1809 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
1811 edit_scroll_downward (edit
, l
);
1813 edit_scroll_upward (edit
, -l
);
1815 edit_scroll_screen_over_cursor (edit
);
1816 edit
->force
|= REDRAW_PAGE
;
1817 edit_render_keypress (edit
);
1819 /*so that undo stops at each query */
1820 edit_push_key_press (edit
);
1822 switch (edit_replace_prompt (edit
, exp2
, /*and prompt 2/3 down */
1823 edit
->num_widget_columns
/ 2 - 33, edit
->num_widget_lines
* 2 / 3)) {
1826 case B_SKIP_REPLACE
:
1831 replace_continue
= 1;
1835 replace_continue
= 0;
1839 if (replace_yes
) { /* delete then insert new */
1840 if (replace_scanf
) {
1841 char repl_str
[MAX_REPL_LEN
+ 2];
1842 if (sprintf_p (repl_str
, exp2
, PRINTF_ARGS
) >= 0) {
1846 while (repl_str
[++i
])
1847 edit_insert (edit
, repl_str
[i
]);
1849 edit_error_dialog (_(" Replace "),
1850 /* "Invalid regexp string or scanf string" */
1851 _(" Error in replacement format string. "));
1852 replace_continue
= 0;
1859 edit_insert (edit
, exp2
[i
]);
1861 edit
->found_len
= i
;
1863 /* so that we don't find the same string again */
1864 if (replace_backwards
) {
1865 last_search
= edit
->search_start
;
1866 edit
->search_start
--;
1868 edit
->search_start
+= i
;
1869 last_search
= edit
->last_byte
;
1871 edit_scroll_screen_over_cursor (edit
);
1873 edit
->search_start
= edit
->curs1
; /* try and find from right here for next search */
1874 edit_update_curs_col (edit
);
1876 edit
->force
|= REDRAW_PAGE
;
1877 edit_render_keypress (edit
);
1878 if (times_replaced
) {
1879 sprintf (fin_string
, _(" %ld replacements made. "), times_replaced
);
1880 edit_message_dialog (_(" Replace "), fin_string
);
1882 edit_message_dialog (_(" Replace "), _(" Search string not found. "));
1883 replace_continue
= 0;
1885 } while (replace_continue
);
1890 edit
->force
= REDRAW_COMPLETELY
;
1891 edit_scroll_screen_over_cursor (edit
);
1897 void edit_search_cmd (WEdit
* edit
, int again
)
1899 static char *old
= NULL
;
1910 exp
= old
? old
: exp
;
1911 if (again
) { /*ctrl-hotkey for search again. */
1916 edit_search_dialog (edit
, &exp
);
1917 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1927 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && replace_backwards
)
1928 edit
->search_start
--;
1930 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !replace_backwards
)
1931 edit
->search_start
++;
1933 edit
->search_start
= edit_find (edit
->search_start
, (unsigned char *) exp
, &len
, edit
->last_byte
,
1934 (int (*)(void *, long)) edit_get_byte
, (void *) edit
);
1936 if (edit
->search_start
>= 0) {
1937 edit
->found_start
= edit
->search_start
;
1938 edit
->found_len
= len
;
1940 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1941 edit_scroll_screen_over_cursor (edit
);
1942 if (replace_backwards
)
1943 edit
->search_start
--;
1945 edit
->search_start
++;
1946 } else if (edit
->search_start
== -3) {
1947 edit
->search_start
= edit
->curs1
;
1948 regexp_error (edit
);
1950 edit
->search_start
= edit
->curs1
;
1951 edit_error_dialog (_(" Search "), _(" Search string not found. "));
1956 edit
->force
|= REDRAW_COMPLETELY
;
1957 edit_scroll_screen_over_cursor (edit
);
1961 /* Real edit only */
1962 void edit_quit_cmd (WEdit
* edit
)
1964 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1966 edit
->force
|= REDRAW_COMPLETELY
;
1967 if (edit
->modified
) {
1969 switch (edit_query_dialog3 (_(" Quit "), _(" File was modified, Save with exit? "), _("Cancel quit"), _("&Yes"), _("&No"))) {
1971 /* Confirm 'Quit' dialog box */
1972 switch (edit_query_dialog3 (_(" Quit "),
1973 _(" Current text was modified without a file save. \n Save with exit? "), _(" &Cancel quit "), _(" &Yes "), _(" &No "))) {
1976 edit_push_markers (edit
);
1977 edit_set_markers (edit
, 0, 0, 0, 0);
1978 if (!edit_save_cmd (edit
))
1983 if (edit
->delete_file
)
1984 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
1993 else if (edit
->delete_file
)
1994 unlink (catstrs (edit
->dir
, edit
->filename
, 0));
1996 edit
->widget
.parent
->running
= 0;
2002 #define TEMP_BUF_LEN 1024
2004 extern int column_highlighting
;
2006 /* returns a null terminated length of text. Result must be free'd */
2007 unsigned char *edit_get_block (WEdit
* edit
, long start
, long finish
, int *l
)
2009 unsigned char *s
, *r
;
2010 r
= s
= malloc (finish
- start
+ 1);
2011 if (column_highlighting
) {
2013 while (start
< finish
) { /* copy from buffer, excluding chars that are out of the column 'margins' */
2015 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0, start
);
2016 c
= edit_get_byte (edit
, start
);
2017 if ((x
>= edit
->column1
&& x
< edit
->column2
)
2018 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
2025 *l
= finish
- start
;
2026 while (start
< finish
)
2027 *s
++ = edit_get_byte (edit
, start
++);
2033 /* save block, returns 1 on success */
2034 int edit_save_block (WEdit
* edit
, const char *filename
, long start
, long finish
)
2036 long i
= start
, end
, filelen
= finish
- start
;
2040 if ((file
= open ((char *) filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1)
2043 buf
= malloc (TEMP_BUF_LEN
);
2044 while (start
!= finish
) {
2045 end
= min (finish
, start
+ TEMP_BUF_LEN
);
2046 for (; i
< end
; i
++)
2047 buf
[i
- start
] = edit_get_byte (edit
, i
);
2048 filelen
-= write (file
, (char *) buf
, end
- start
);
2058 /* copies a block to clipboard file */
2059 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
2061 return edit_save_block (edit
, catstrs (home_dir
, CLIP_FILE
, 0), start
, finish
);
2066 void paste_text (WEdit
* edit
, unsigned char *data
, unsigned int nitems
)
2071 edit_insert_ahead (edit
, *data
--);
2073 edit
->force
|= REDRAW_COMPLETELY
;
2076 char *selection_get_line (void *data
, int line
)
2078 static unsigned char t
[1024];
2079 struct selection
*s
;
2081 s
= (struct selection
*) data
;
2082 line
= (current_selection
+ line
+ 1) % NUM_SELECTION_HISTORY
;
2084 unsigned char *p
= s
[line
].text
;
2086 for (j
= 0; j
< s
[line
].len
; j
++) {
2088 if ((c
< ' ' || (c
> '~' && c
< 160)) && c
!= '\t') {
2102 void edit_paste_from_history (WEdit
* edit
)
2106 edit_update_curs_col (edit
);
2107 edit_update_curs_row (edit
);
2109 c
= max (20, edit
->num_widget_columns
- 5);
2111 i
= CListboxDialog (WIN_MESSAGES
, c
, 10,
2112 0, NUM_SELECTION_HISTORY
- 10, NUM_SELECTION_HISTORY
- 1, NUM_SELECTION_HISTORY
,
2113 selection_get_line
, (void *) selection_history
);
2118 i
= (current_selection
+ i
+ 1) % NUM_SELECTION_HISTORY
;
2120 paste_text (edit
, selection_history
[i
].text
, selection_history
[i
].len
);
2121 edit
->force
|= REDRAW_COMPLETELY
;
2124 /* copies a block to the XWindows buffer */
2125 static int edit_XStore_block (WEdit
* edit
, long start
, long finish
)
2127 edit_get_selection (edit
);
2128 if (selection
.len
<= 512 * 1024) { /* we don't want to fill up the server */
2129 XStoreBytes (CDisplay
, (char *) selection
.text
, (int) selection
.len
);
2135 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
2137 long start_mark
, end_mark
;
2138 if (eval_marks (edit
, &start_mark
, &end_mark
))
2140 edit_XStore_block (edit
, start_mark
, end_mark
);
2141 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2142 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
2145 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, edit
->widget
->winid
, CurrentTime
);
2146 edit_mark_cmd (edit
, 1);
2150 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
2152 long start_mark
, end_mark
;
2153 if (eval_marks (edit
, &start_mark
, &end_mark
))
2155 edit_XStore_block (edit
, start_mark
, end_mark
);
2156 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2157 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2160 edit_block_delete_cmd (edit
);
2161 XSetSelectionOwner (CDisplay
, XA_PRIMARY
, edit
->widget
->winid
, CurrentTime
);
2162 edit_mark_cmd (edit
, 1);
2166 void selection_paste (WEdit
* edit
, Window win
, unsigned prop
, int delete);
2168 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
2171 paste_text (edit
, selection
.text
, selection
.len
);
2172 else if (!XGetSelectionOwner (CDisplay
, XA_PRIMARY
))
2173 selection_paste (edit
, CRoot
, XA_CUT_BUFFER0
, False
);
2175 XConvertSelection (CDisplay
, XA_PRIMARY
, XA_STRING
,
2176 XInternAtom (CDisplay
, "VT_SELECTION", False
),
2177 edit
->widget
->winid
, CurrentTime
);
2178 edit
->force
|= REDRAW_PAGE
;
2181 #else /* MIDNIGHT */
2183 void edit_paste_from_history (WEdit
*edit
)
2187 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
2189 long start_mark
, end_mark
;
2190 if (eval_marks (edit
, &start_mark
, &end_mark
))
2192 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2193 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
2196 edit_mark_cmd (edit
, 1);
2200 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
2202 long start_mark
, end_mark
;
2203 if (eval_marks (edit
, &start_mark
, &end_mark
))
2205 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
2206 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2209 edit_block_delete_cmd (edit
);
2210 edit_mark_cmd (edit
, 1);
2214 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
2216 edit_insert_file (edit
, catstrs (home_dir
, CLIP_FILE
, 0));
2219 #endif /* MIDMIGHT */
2221 void edit_goto_cmd (WEdit
*edit
)
2227 sprintf (s
, "%d", l
);
2228 f
= input_dialog (_(" Goto line "), _(" Enter line: "), l
? s
: "");
2230 f
= CInputDialog ("goto", WIN_MESSAGES
, 150, l
? itoa (l
) : "", _(" Goto line "), _(" Enter line: "));
2235 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
2236 edit_move_to_line (edit
, l
- 1);
2237 edit
->force
|= REDRAW_COMPLETELY
;
2243 /*returns 1 on success */
2244 int edit_save_block_cmd (WEdit
* edit
) {
2245 long start_mark
, end_mark
;
2247 if (eval_marks (edit
, &start_mark
, &end_mark
))
2250 exp
= edit_get_save_file (edit
->dir
, catstrs (home_dir
, CLIP_FILE
, 0), _(" Save Block "));
2252 edit
->force
|= REDRAW_COMPLETELY
;
2253 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2260 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
2262 edit
->force
|= REDRAW_COMPLETELY
;
2266 edit
->force
|= REDRAW_COMPLETELY
;
2267 edit_error_dialog (_(" Save Block "), get_sys_error (_(" Error trying to save file. ")));
2276 /* inserts a file at the cursor, returns 1 on success */
2277 int edit_insert_file (WEdit
* edit
, const char *filename
)
2279 int i
, file
, blocklen
;
2280 long current
= edit
->curs1
;
2283 if ((file
= open ((char *) filename
, O_RDONLY
)) == -1)
2285 buf
= malloc (TEMP_BUF_LEN
);
2286 while ((blocklen
= read (file
, (char *) buf
, TEMP_BUF_LEN
)) > 0) {
2287 for (i
= 0; i
< blocklen
; i
++)
2288 edit_insert (edit
, buf
[i
]);
2290 edit_cursor_move (edit
, current
- edit
->curs1
);
2299 /* returns 1 on success */
2300 int edit_insert_file_cmd (WEdit
* edit
) {
2301 char *exp
= edit_get_load_file (edit
->dir
, catstrs (home_dir
, CLIP_FILE
, 0), _(" Insert File "));
2302 edit
->force
|= REDRAW_COMPLETELY
;
2304 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2311 if (edit_insert_file (edit
, exp
)) {
2316 edit_error_dialog (_(" Insert file "), get_sys_error (_(" Error trying to insert file. ")));
2326 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2327 int edit_sort_cmd (WEdit
* edit
)
2329 static char *old
= 0;
2331 long start_mark
, end_mark
;
2334 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2335 /* Not essential to translate */
2336 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
2339 edit_save_block (edit
, catstrs (home_dir
, BLOCK_FILE
, 0), start_mark
, end_mark
);
2341 exp
= old
? old
: "";
2343 exp
= input_dialog (_(" Run Sort "),
2344 /* Not essential to translate */
2345 _(" Enter sort options (see manpage) separated by whitespace: "), "");
2353 e
= system (catstrs (" sort ", exp
, " ", home_dir
, BLOCK_FILE
, " > ", home_dir
, TEMP_FILE
, 0));
2355 if (e
== -1 || e
== 127) {
2356 edit_error_dialog (_(" Sort "),
2357 /* Not essential to translate */
2358 get_sys_error (_(" Error trying to execute sort command ")));
2361 sprintf (q
, "%d ", e
);
2362 edit_error_dialog (_(" Sort "),
2363 /* Not essential to translate */
2364 catstrs (_(" Sort returned non-zero: "), q
, 0));
2369 edit
->force
|= REDRAW_COMPLETELY
;
2371 if (edit_block_delete_cmd (edit
))
2373 edit_insert_file (edit
, catstrs (home_dir
, TEMP_FILE
, 0));
2377 /* if block is 1, a block must be highlighted and the shell command
2378 processes it. If block is 0 the shell command is a straight system
2379 command, that just produces some output which is to be inserted */
2380 void edit_block_process_cmd (WEdit
* edit
, const char *shell_cmd
, int block
)
2382 long start_mark
, end_mark
;
2384 char *f
= NULL
, *b
= NULL
;
2387 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2388 edit_error_dialog (_(" Process block "),
2389 /* Not essential to translate */
2390 _(" You must first highlight a block of text. "));
2393 edit_save_block (edit
, b
= catstrs (home_dir
, BLOCK_FILE
, 0), start_mark
, end_mark
);
2394 my_system (0, shell
, catstrs (home_dir
, shell_cmd
, 0));
2395 edit_refresh_cmd (edit
);
2397 my_system (0, shell
, shell_cmd
);
2398 edit_refresh_cmd (edit
);
2401 edit
->force
|= REDRAW_COMPLETELY
;
2403 f
= catstrs (home_dir
, ERROR_FILE
, 0);
2406 if (stat (f
, &s
) == 0) {
2407 if (!s
.st_size
) { /* no error messages */
2408 if (edit_block_delete_cmd (edit
))
2410 edit_insert_file (edit
, b
);
2413 edit_insert_file (edit
, f
);
2417 /* Not essential to translate */
2418 edit_error_dialog (_(" Process block "),
2419 /* Not essential to translate */
2420 get_sys_error (_(" Error trying to stat file ")));
2428 int edit_execute_cmd (WEdit
* edit
, int command
, int char_for_insertion
);
2430 /* prints at the cursor */
2431 /* returns the number of chars printed */
2432 int edit_print_string (WEdit
* e
, const char *s
)
2436 edit_execute_cmd (e
, -1, s
[i
++]);
2437 e
->force
|= REDRAW_COMPLETELY
;
2438 edit_update_screen (e
);
2442 int edit_printf (WEdit
* e
, const char *fmt
,...)
2448 sprintf (s
, fmt
, pa
);
2449 i
= edit_print_string (e
, s
);
2456 /* FIXME: does this function break NT_OS2 ? */
2458 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
2463 sprintf (s
, "mail -s \"%s\" -c \"%s\" \"%s\"", subject
, cc
, to
);
2470 for (i
= 0; i
< edit
->last_byte
; i
++)
2471 fputc (edit_get_byte (edit
, i
), p
);
2477 #define MAIL_DLG_HEIGHT 12
2479 void edit_mail_dialog (WEdit
* edit
)
2482 char *tmail_subject
;
2485 static char *mail_cc_last
= 0;
2486 static char *mail_subject_last
= 0;
2487 static char *mail_to_last
= 0;
2489 QuickDialog Quick_input
=
2490 {50, MAIL_DLG_HEIGHT
, -1, 0, N_(" Mail "),
2492 "[Input Line Keys]", "quick_input", 0};
2494 QuickWidget quick_widgets
[] =
2497 {quick_button
, 6, 10, 9, MAIL_DLG_HEIGHT
, "&Cancel", 0, B_CANCEL
, 0,
2498 0, XV_WLAY_DONTCARE
, NULL
},
2499 {quick_button
, 2, 10, 9, MAIL_DLG_HEIGHT
, "&Ok", 0, B_ENTER
, 0,
2500 0, XV_WLAY_DONTCARE
, NULL
},
2501 {quick_input
, 3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2502 0, XV_WLAY_BELOWCLOSE
, "mail-dlg-input"},
2503 {quick_label
, 2, 50, 7, MAIL_DLG_HEIGHT
, " Copies to", 0, 0, 0,
2504 0, XV_WLAY_DONTCARE
, 0},
2505 {quick_input
, 3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2506 0, XV_WLAY_BELOWCLOSE
, "mail-dlg-input-2"},
2507 {quick_label
, 2, 50, 5, MAIL_DLG_HEIGHT
, " Subject", 0, 0, 0,
2508 0, XV_WLAY_DONTCARE
, 0},
2509 {quick_input
, 3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2510 0, XV_WLAY_BELOWCLOSE
, "mail-dlg-input-3"},
2511 {quick_label
, 2, 50, 3, MAIL_DLG_HEIGHT
, " To", 0, 0, 0,
2512 0, XV_WLAY_DONTCARE
, 0},
2513 {quick_label
, 2, 50, 2, MAIL_DLG_HEIGHT
, " mail -s <subject> -c <cc> <to>", 0, 0, 0,
2514 0, XV_WLAY_DONTCARE
, 0},
2517 quick_widgets
[2].str_result
= &tmail_cc
;
2518 quick_widgets
[2].text
= mail_cc_last
? mail_cc_last
: "";
2519 quick_widgets
[4].str_result
= &tmail_subject
;
2520 quick_widgets
[4].text
= mail_subject_last
? mail_subject_last
: "";
2521 quick_widgets
[6].str_result
= &tmail_to
;
2522 quick_widgets
[6].text
= mail_to_last
? mail_to_last
: "";
2524 Quick_input
.widgets
= quick_widgets
;
2526 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
2528 free (mail_cc_last
);
2529 if (mail_subject_last
)
2530 free (mail_subject_last
);
2532 free (mail_to_last
);
2533 mail_cc_last
= *(quick_widgets
[2].str_result
);
2534 mail_subject_last
= *(quick_widgets
[4].str_result
);
2535 mail_to_last
= *(quick_widgets
[6].str_result
);
2536 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);