1 /* editor high level editing commands
3 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007 Free Software Foundation, Inc.
6 Authors: 1996, 1997 Paul Sheer
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 * \brief Source: editor high level editing commands
31 /* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
40 #include <sys/types.h>
47 #include "../src/global.h"
48 #include "../src/history.h"
50 #include "edit-impl.h"
52 #include "editcmddef.h"
53 #include "edit-widget.h"
54 #include "editcmd_dialogs.h"
55 #include "../edit/etags.h"
56 #include "../src/panel.h"
58 #include "../src/tty.h" /* LINES */
59 #include "../src/widget.h" /* listbox_new() */
60 #include "../src/layout.h" /* clr_scr() */
61 #include "../src/main.h" /* mc_home source_codepage */
62 #include "../src/help.h" /* interactive_display() */
63 #include "../src/key.h" /* XCTRL */
64 #include "../src/wtools.h" /* message() */
65 #include "../src/charsets.h"
66 #include "../src/selcodepage.h"
67 #include "../src/strutil.h" /* utf string functions */
71 /* search and replace: */
72 static int search_create_bookmark
= 0;
73 /* static int search_in_all_charsets = 0; */
75 /* queries on a save */
76 int edit_confirm_save
= 1;
78 static int edit_save_cmd (WEdit
*edit
);
79 static unsigned char *edit_get_block (WEdit
*edit
, long start
,
83 edit_search_cmd_search_create_bookmark(WEdit
* edit
)
85 int found
= 0, books
= 0;
86 int l
= 0, l_last
= -1;
91 if (!mc_search_run(edit
->search
, (void *) edit
, q
, edit
->last_byte
, &len
))
95 l
+= edit_count_lines (edit
, q
, edit
->search
->normal_offset
);
97 book_mark_insert (edit
, l
, BOOK_MARK_FOUND_COLOR
);
101 q
= edit
->search
->normal_offset
+ 1;
105 /* in response to number of bookmarks added because of string being found %d times */
106 message (D_NORMAL
, _("Search"), _(" %d items found, %d bookmarks added "), found
, books
);
108 edit_error_dialog (_ ("Search"), _ (" Search string not found "));
113 edit_search_cmd_callback(const void *user_data
, gsize char_offset
)
115 return edit_get_byte ((WEdit
* )user_data
, (long) char_offset
);
118 void edit_help_cmd (WEdit
* edit
)
120 interactive_display (NULL
, "[Internal File Editor]");
121 edit
->force
|= REDRAW_COMPLETELY
;
124 void edit_refresh_cmd (WEdit
* edit
)
132 edit_get_syntax_color (edit
, -1, &color
);
135 #endif /* !HAVE_SLANG */
140 /* If 0 (quick save) then a) create/truncate <filename> file,
141 b) save to <filename>;
142 if 1 (safe save) then a) save to <tempnam>,
143 b) rename <tempnam> to <filename>;
144 if 2 (do backups) then a) save to <tempnam>,
145 b) rename <filename> to <filename.backup_ext>,
146 c) rename <tempnam> to <filename>. */
148 /* returns 0 on error, -1 on abort */
150 edit_save_file (WEdit
*edit
, const char *filename
)
156 gchar
*real_filename
;
157 int this_save_mode
, fd
= -1;
164 if (*filename
!= PATH_SEP
&& edit
->dir
) {
165 real_filename
= concat_dir_and_file (edit
->dir
, filename
);
167 real_filename
= g_strdup(filename
);
170 this_save_mode
= option_save_mode
;
171 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
172 if (!vfs_file_is_local (real_filename
) ||
173 (fd
= mc_open (real_filename
, O_RDONLY
| O_BINARY
)) == -1) {
175 * The file does not exists yet, so no safe save or
176 * backup are necessary.
178 this_save_mode
= EDIT_QUICK_SAVE
;
184 if (this_save_mode
== EDIT_QUICK_SAVE
&&
185 !edit
->skip_detach_prompt
) {
189 rv
= mc_stat (real_filename
, &sb
);
190 if (rv
== 0 && sb
.st_nlink
> 1) {
191 rv
= edit_query_dialog3 (_("Warning"),
192 _(" File has hard-links. Detach before saving? "),
193 _("&Yes"), _("&No"), _("&Cancel"));
196 this_save_mode
= EDIT_SAFE_SAVE
;
199 edit
->skip_detach_prompt
= 1;
202 g_free(real_filename
);
207 /* Prevent overwriting changes from other editor sessions. */
208 if (rv
== 0 && edit
->stat1
.st_mtime
!= 0 && edit
->stat1
.st_mtime
!= sb
.st_mtime
) {
210 /* The default action is "Cancel". */
213 rv
= edit_query_dialog2 (
215 _("The file has been modified in the meantime. Save anyway?"),
219 g_free(real_filename
);
225 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
226 char *savedir
, *saveprefix
;
227 const char *slashpos
;
228 slashpos
= strrchr (real_filename
, PATH_SEP
);
230 savedir
= g_strdup (real_filename
);
231 savedir
[slashpos
- real_filename
+ 1] = '\0';
233 savedir
= g_strdup (".");
234 saveprefix
= concat_dir_and_file (savedir
, "cooledit");
236 fd
= mc_mkstemps (&savename
, saveprefix
, NULL
);
239 g_free(real_filename
);
243 * Close for now because mc_mkstemps use pure open system call
244 * to create temporary file and it needs to be reopened by
245 * VFS-aware mc_open().
249 savename
= g_strdup (real_filename
);
251 mc_chown (savename
, edit
->stat1
.st_uid
, edit
->stat1
.st_gid
);
252 mc_chmod (savename
, edit
->stat1
.st_mode
);
255 mc_open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| O_BINARY
,
256 edit
->stat1
.st_mode
)) == -1)
260 if ((p
= edit_get_write_filter (savename
, real_filename
))) {
264 file
= (FILE *) popen (p
, "w");
267 filelen
= edit_write_stream (edit
, file
);
271 if (pclose (file
) != 0) {
272 tmp
= g_strconcat (_(" Error writing to pipe: "),
273 p
, " ", (char *) NULL
);
274 edit_error_dialog (_("Error"), tmp
);
281 tmp
= g_strconcat (_(" Cannot open pipe for writing: "),
282 p
, " ", (char *) NULL
);
284 edit_error_dialog (_("Error"),
285 get_sys_error (tmp
));
294 filelen
= edit
->last_byte
;
295 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
296 if (mc_write (fd
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
)
304 (fd
, (char *) edit
->buffers1
[buf
],
305 edit
->curs1
& M_EDIT_BUF_SIZE
) !=
306 (edit
->curs1
& M_EDIT_BUF_SIZE
)) {
308 } else if (edit
->curs2
) {
310 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
313 (char *) edit
->buffers2
[buf
] + EDIT_BUF_SIZE
-
314 (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1,
315 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) !=
316 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) {
321 (fd
, (char *) edit
->buffers2
[buf
],
322 EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
333 /* Update the file information, especially the mtime. */
334 if (mc_stat (savename
, &edit
->stat1
) == -1)
338 if (filelen
!= edit
->last_byte
)
341 if (this_save_mode
== EDIT_DO_BACKUP
) {
342 assert (option_backup_ext
!= NULL
);
343 tmp
= g_strconcat (real_filename
, option_backup_ext
,(char *) NULL
);
344 if (mc_rename (real_filename
, tmp
) == -1){
350 if (this_save_mode
!= EDIT_QUICK_SAVE
)
351 if (mc_rename (savename
, real_filename
) == -1)
354 g_free(real_filename
);
357 /* FIXME: Is this safe ?
358 * if (this_save_mode != EDIT_QUICK_SAVE)
359 * mc_unlink (savename);
361 g_free(real_filename
);
366 void menu_save_mode_cmd (void)
370 static char *str_result
;
371 static int save_mode_new
;
372 static const char *str
[] =
376 N_("Do backups -->")};
378 static QuickWidget widgets
[] =
380 {quick_button
, 18, DLG_X
, 7, DLG_Y
, N_("&Cancel"), 0,
381 B_CANCEL
, 0, 0, NULL
, NULL
, NULL
},
382 {quick_button
, 6, DLG_X
, 7, DLG_Y
, N_("&OK"), 0,
383 B_ENTER
, 0, 0, NULL
, NULL
, NULL
},
384 {quick_input
, 23, DLG_X
, 5, DLG_Y
, 0, 9,
385 0, 0, &str_result
, "edit-backup-ext", NULL
, NULL
},
386 {quick_label
, 22, DLG_X
, 4, DLG_Y
, N_("Extension:"), 0,
387 0, 0, 0, NULL
, NULL
, NULL
},
388 {quick_radio
, 4, DLG_X
, 3, DLG_Y
, "", 3,
389 0, &save_mode_new
, (char **) str
, NULL
, NULL
, NULL
},
391 static QuickDialog dialog
=
392 {DLG_X
, DLG_Y
, -1, -1, N_(" Edit Save Mode "), "[Edit Save Mode]",
394 static int i18n_flag
= 0;
402 /* OK/Cancel buttons */
403 l1
= str_term_width1 (_(widgets
[0].text
)) + str_term_width1 (_(widgets
[1].text
)) + 5;
404 maxlen
= max (maxlen
, l1
);
406 for (i
= 0; i
< 3; i
++ ) {
408 maxlen
= max (maxlen
, (size_t) str_term_width1 (str
[i
]) + 7);
412 dlg_x
= maxlen
+ str_term_width1 (_(widgets
[3].text
)) + 5 + 1;
413 widgets
[2].hotkey_pos
= str_term_width1 (_(widgets
[3].text
)); /* input field length */
414 dlg_x
= min (COLS
, dlg_x
);
418 widgets
[1].relative_x
= i
;
419 widgets
[0].relative_x
= i
+ str_term_width1 (_(widgets
[1].text
)) + i
+ 4;
421 widgets
[2].relative_x
= widgets
[3].relative_x
= maxlen
+ 2;
423 for (i
= 0; i
< sizeof (widgets
)/sizeof (widgets
[0]); i
++)
424 widgets
[i
].x_divisions
= dlg_x
;
427 assert (option_backup_ext
!= NULL
);
428 widgets
[2].text
= option_backup_ext
;
429 widgets
[4].value
= option_save_mode
;
430 if (quick_dialog (&dialog
) != B_ENTER
)
432 option_save_mode
= save_mode_new
;
434 g_free (option_backup_ext
);
435 option_backup_ext
= str_result
;
440 edit_set_filename (WEdit
*edit
, const char *f
)
442 g_free (edit
->filename
);
445 edit
->filename
= g_strdup (f
);
446 if (edit
->dir
== NULL
&& *f
!= PATH_SEP
)
448 edit
->dir
= g_strdup (vfs_get_current_dir ());
450 edit
->dir
= g_get_current_dir ();
454 /* Here we want to warn the users of overwriting an existing file,
455 but only if they have made a change to the filename */
456 /* returns 1 on success */
458 edit_save_as_cmd (WEdit
*edit
)
460 /* This heads the 'Save As' dialog box */
463 int different_filename
= 0;
465 exp
= input_expand_dialog (
466 _(" Save As "), _(" Enter file name: "),MC_HISTORY_EDIT_SAVE_AS
, edit
->filename
);
467 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
472 edit
->force
|= REDRAW_COMPLETELY
;
476 if (strcmp (edit
->filename
, exp
)) {
478 different_filename
= 1;
479 if ((file
= mc_open (exp
, O_RDONLY
| O_BINARY
)) != -1) {
480 /* the file exists */
482 /* Overwrite the current file or cancel the operation */
483 if (edit_query_dialog2
485 _(" A file already exists with this name. "),
486 _("&Overwrite"), _("&Cancel"))) {
487 edit
->force
|= REDRAW_COMPLETELY
;
492 save_lock
= edit_lock_file (exp
);
494 /* filenames equal, check if already locked */
495 if (!edit
->locked
&& !edit
->delete_file
)
496 save_lock
= edit_lock_file (exp
);
499 rv
= edit_save_file (edit
, exp
);
502 /* Succesful, so unlock both files */
503 if (different_filename
) {
505 edit_unlock_file (exp
);
507 edit
->locked
= edit_unlock_file (edit
->filename
);
509 if (edit
->locked
|| save_lock
)
510 edit
->locked
= edit_unlock_file (edit
->filename
);
513 edit_set_filename (edit
, exp
);
516 edit
->delete_file
= 0;
517 if (different_filename
)
518 edit_load_syntax (edit
, NULL
, option_syntax_type
);
519 edit
->force
|= REDRAW_COMPLETELY
;
522 edit_error_dialog (_(" Save As "),
524 (" Cannot save file. ")));
527 /* Failed, so maintain modify (not save) lock */
529 edit_unlock_file (exp
);
531 edit
->force
|= REDRAW_COMPLETELY
;
536 edit
->force
|= REDRAW_COMPLETELY
;
540 /* {{{ Macro stuff starts here */
542 /* creates a macro file if it doesn't exist */
543 static FILE *edit_open_macro_file (const char *r
)
548 filename
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
549 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1){
554 fd
= fopen (filename
, r
);
559 #define MAX_MACROS 1024
560 static int saved_macro
[MAX_MACROS
+ 1];
561 static int saved_macros_loaded
= 0;
564 This is just to stop the macro file be loaded over and over for keys
565 that aren't defined to anything. On slow systems this could be annoying.
571 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
572 if (saved_macro
[i
] == k
)
577 /* returns 1 on error */
579 edit_delete_macro (WEdit
* edit
, int k
)
582 struct macro macro
[MAX_MACRO_LENGTH
];
588 if (saved_macros_loaded
)
589 if ((j
= macro_exists (k
)) < 0)
591 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
592 g
= fopen (tmp
, "w");
595 edit_error_dialog (_(" Delete macro "),
596 get_sys_error (_(" Cannot open temp file ")));
599 f
= edit_open_macro_file ("r");
601 edit_error_dialog (_(" Delete macro "),
602 get_sys_error (_(" Cannot open macro file ")));
607 n
= fscanf (f
, ("key '%d 0': "), &s
);
611 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
615 fprintf (g
, ("key '%d 0': "), s
);
616 for (i
= 0; i
< n
; i
++)
617 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
623 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
624 tmp2
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
625 if (rename ( tmp
, tmp2
) == -1) {
626 edit_error_dialog (_(" Delete macro "),
627 get_sys_error (_(" Cannot overwrite macro file ")));
635 if (saved_macros_loaded
)
636 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
640 /* returns 0 on error */
641 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
646 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
647 s
= editcmd_dialog_raw_key_query (_(" Save macro "),
648 _(" Press the macro's new hotkey: "), 1);
649 edit
->force
|= REDRAW_COMPLETELY
;
651 if (edit_delete_macro (edit
, s
))
653 f
= edit_open_macro_file ("a+");
655 fprintf (f
, ("key '%d 0': "), s
);
656 for (i
= 0; i
< n
; i
++)
657 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
660 if (saved_macros_loaded
) {
661 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
666 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Cannot open macro file ")));
671 void edit_delete_macro_cmd (WEdit
* edit
)
675 command
= editcmd_dialog_raw_key_query (_ (" Delete macro "),
676 _ (" Press macro hotkey: "), 1);
681 edit_delete_macro (edit
, command
);
684 /* return 0 on error */
685 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
688 int s
, i
= 0, found
= 0;
692 if (saved_macros_loaded
)
693 if (macro_exists (k
) < 0)
696 if ((f
= edit_open_macro_file ("r"))) {
700 u
= fscanf (f
, ("key '%d 0': "), &s
);
703 if (!saved_macros_loaded
)
704 saved_macro
[i
++] = s
;
707 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
710 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
715 } while (!found
|| !saved_macros_loaded
);
716 if (!saved_macros_loaded
) {
718 saved_macros_loaded
= 1;
723 edit_error_dialog (_(" Load macro "),
724 get_sys_error (_(" Cannot open macro file ")));
728 /* }}} Macro stuff starts here */
730 /* returns 1 on success */
731 int edit_save_confirm_cmd (WEdit
* edit
)
735 if (edit_confirm_save
) {
736 f
= g_strconcat (_(" Confirm save file? : "), edit
->filename
, " ", NULL
);
737 if (edit_query_dialog2 (_(" Save file "), f
, _("&Save"), _("&Cancel"))){
743 return edit_save_cmd (edit
);
747 /* returns 1 on success */
749 edit_save_cmd (WEdit
*edit
)
751 int res
, save_lock
= 0;
753 if (!edit
->locked
&& !edit
->delete_file
)
754 save_lock
= edit_lock_file (edit
->filename
);
755 res
= edit_save_file (edit
, edit
->filename
);
757 /* Maintain modify (not save) lock on failure */
758 if ((res
> 0 && edit
->locked
) || save_lock
)
759 edit
->locked
= edit_unlock_file (edit
->filename
);
761 /* On failure try 'save as', it does locking on its own */
763 return edit_save_as_cmd (edit
);
764 edit
->force
|= REDRAW_COMPLETELY
;
766 edit
->delete_file
= 0;
774 /* returns 1 on success */
775 int edit_new_cmd (WEdit
* edit
)
777 if (edit
->modified
) {
778 if (edit_query_dialog2 (_ ("Warning"), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("C&ontinue"), _ ("&Cancel"))) {
779 edit
->force
|= REDRAW_COMPLETELY
;
783 edit
->force
|= REDRAW_COMPLETELY
;
785 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
788 /* returns 1 on error */
790 edit_load_file_from_filename (WEdit
* edit
, char *exp
)
792 int prev_locked
= edit
->locked
;
793 char *prev_filename
= g_strdup (edit
->filename
);
795 if (!edit_reload (edit
, exp
)) {
796 g_free (prev_filename
);
801 edit_unlock_file (prev_filename
);
802 g_free (prev_filename
);
807 edit_load_syntax_file (WEdit
* edit
)
812 if (geteuid () == 0) {
813 dir
= query_dialog (_("Syntax file edit"),
814 _(" Which syntax file you want to edit? "), D_NORMAL
, 2,
815 _("&User"), _("&System Wide"));
818 extdir
= concat_dir_and_file (mc_home
, "syntax" PATH_SEP_STR
"Syntax");
819 if (!exist_file(extdir
)) {
821 extdir
= concat_dir_and_file (mc_home_alt
, "syntax" PATH_SEP_STR
"Syntax");
827 buffer
= concat_dir_and_file (home_dir
, EDIT_SYNTAX_FILE
);
828 check_for_default (extdir
, buffer
);
829 edit_load_file_from_filename (edit
, buffer
);
832 edit_load_file_from_filename (edit
, extdir
);
838 edit_load_menu_file (WEdit
* edit
)
846 _(" Which menu file do you want to edit? "), D_NORMAL
,
847 geteuid() ? 2 : 3, _("&Local"), _("&User"), _("&System Wide")
850 menufile
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
852 if (!exist_file (menufile
)) {
854 menufile
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
859 buffer
= g_strdup (EDIT_LOCAL_MENU
);
860 check_for_default (menufile
, buffer
);
861 chmod (buffer
, 0600);
865 buffer
= concat_dir_and_file (home_dir
, EDIT_HOME_MENU
);
866 check_for_default (menufile
, buffer
);
870 buffer
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
871 if (!exist_file (buffer
)) {
873 buffer
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
882 edit_load_file_from_filename (edit
, buffer
);
889 edit_load_cmd (WEdit
*edit
, edit_current_file_t what
)
894 && (edit_query_dialog2
896 _(" Current text was modified without a file save. \n"
897 " Continue discards these changes. "),
898 _("C&ontinue"), _("&Cancel")) == 1)) {
899 edit
->force
|= REDRAW_COMPLETELY
;
904 case EDIT_FILE_COMMON
:
905 exp
= input_expand_dialog (_(" Load "), _(" Enter file name: "),
906 MC_HISTORY_EDIT_LOAD
, edit
->filename
);
910 edit_load_file_from_filename (edit
, exp
);
915 case EDIT_FILE_SYNTAX
:
916 edit_load_syntax_file (edit
);
920 edit_load_menu_file (edit
);
927 edit
->force
|= REDRAW_COMPLETELY
;
932 if mark2 is -1 then marking is from mark1 to the cursor.
933 Otherwise its between the markers. This handles this.
934 Returns 1 if no text is marked.
936 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
938 if (edit
->mark1
!= edit
->mark2
) {
939 if (edit
->mark2
>= 0) {
940 *start_mark
= min (edit
->mark1
, edit
->mark2
);
941 *end_mark
= max (edit
->mark1
, edit
->mark2
);
943 *start_mark
= min (edit
->mark1
, edit
->curs1
);
944 *end_mark
= max (edit
->mark1
, edit
->curs1
);
945 edit
->column2
= edit
->curs_col
;
949 *start_mark
= *end_mark
= 0;
950 edit
->column2
= edit
->column1
= 0;
955 #define space_width 1
958 edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
)
962 cursor
= edit
->curs1
;
963 col
= edit_get_col (edit
);
964 for (i
= 0; i
< size
; i
++) {
965 if (data
[i
] == '\n') { /* fill in and move to next line */
968 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
969 l
= width
- (edit_get_col (edit
) - col
);
971 edit_insert (edit
, ' ');
975 for (p
= edit
->curs1
;; p
++) {
976 if (p
== edit
->last_byte
) {
977 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
978 edit_insert_ahead (edit
, '\n');
982 if (edit_get_byte (edit
, p
) == '\n') {
987 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
988 l
= col
- edit_get_col (edit
);
989 while (l
>= space_width
) {
990 edit_insert (edit
, ' ');
995 edit_insert (edit
, data
[i
]);
997 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1002 edit_block_copy_cmd (WEdit
*edit
)
1004 long start_mark
, end_mark
, current
= edit
->curs1
;
1006 unsigned char *copy_buf
;
1008 edit_update_curs_col (edit
);
1009 if (eval_marks (edit
, &start_mark
, &end_mark
))
1012 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1014 /* all that gets pushed are deletes hence little space is used on the stack */
1016 edit_push_markers (edit
);
1018 if (column_highlighting
) {
1019 edit_insert_column_of_text (edit
, copy_buf
, size
,
1020 abs (edit
->column2
- edit
->column1
));
1023 edit_insert_ahead (edit
, copy_buf
[size
]);
1027 edit_scroll_screen_over_cursor (edit
);
1029 if (column_highlighting
) {
1030 edit_set_markers (edit
, 0, 0, 0, 0);
1031 edit_push_action (edit
, COLUMN_ON
);
1032 column_highlighting
= 0;
1033 } else if (start_mark
< current
&& end_mark
> current
)
1034 edit_set_markers (edit
, start_mark
,
1035 end_mark
+ end_mark
- start_mark
, 0, 0);
1037 edit
->force
|= REDRAW_PAGE
;
1042 edit_block_move_cmd (WEdit
*edit
)
1046 unsigned char *copy_buf
;
1047 long start_mark
, end_mark
;
1051 if (eval_marks (edit
, &start_mark
, &end_mark
))
1053 if (column_highlighting
) {
1054 edit_update_curs_col (edit
);
1056 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1057 if ((x
> edit
->column1
&& x
< edit
->column2
)
1058 || (x
> edit
->column2
&& x
< edit
->column1
))
1060 } else if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1063 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1064 if (edit_query_dialog2
1067 (" Block is large, you may not be able to undo this action. "),
1068 _("C&ontinue"), _("&Cancel")))
1071 edit_push_markers (edit
);
1072 current
= edit
->curs1
;
1073 if (column_highlighting
) {
1074 int size
, c1
, c2
, line
;
1075 line
= edit
->curs_line
;
1076 if (edit
->mark2
< 0)
1077 edit_mark_cmd (edit
, 0);
1078 c1
= min (edit
->column1
, edit
->column2
);
1079 c2
= max (edit
->column1
, edit
->column2
);
1080 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1082 edit_block_delete_cmd (edit
);
1085 edit_move_to_line (edit
, line
);
1086 edit_cursor_move (edit
,
1087 edit_move_forward3 (edit
,
1088 edit_bol (edit
, edit
->curs1
),
1089 x
, 0) - edit
->curs1
);
1090 edit_insert_column_of_text (edit
, copy_buf
, size
, c2
- c1
);
1092 line
= edit
->curs_line
;
1093 edit_update_curs_col (edit
);
1095 edit_block_delete_cmd (edit
);
1096 edit_move_to_line (edit
, line
);
1097 edit_cursor_move (edit
,
1098 edit_move_forward3 (edit
,
1101 x
, 0) - edit
->curs1
);
1103 edit_set_markers (edit
, 0, 0, 0, 0);
1104 edit_push_action (edit
, COLUMN_ON
);
1105 column_highlighting
= 0;
1107 copy_buf
= g_malloc (end_mark
- start_mark
);
1108 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1109 edit_scroll_screen_over_cursor (edit
);
1111 while (count
< end_mark
) {
1112 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
, 1);
1115 edit_scroll_screen_over_cursor (edit
);
1116 edit_cursor_move (edit
,
1117 current
- edit
->curs1
-
1118 (((current
- edit
->curs1
) >
1119 0) ? end_mark
- start_mark
: 0));
1120 edit_scroll_screen_over_cursor (edit
);
1121 while (count
-- > start_mark
)
1122 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1123 edit_set_markers (edit
, edit
->curs1
,
1124 edit
->curs1
+ end_mark
- start_mark
, 0, 0);
1126 edit_scroll_screen_over_cursor (edit
);
1128 edit
->force
|= REDRAW_PAGE
;
1132 edit_delete_column_of_text (WEdit
* edit
)
1134 long p
, q
, r
, m1
, m2
;
1138 eval_marks (edit
, &m1
, &m2
);
1139 n
= edit_move_forward (edit
, m1
, 0, m2
) + 1;
1140 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
1141 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
1147 r
= edit_bol (edit
, edit
->curs1
);
1148 p
= edit_move_forward3 (edit
, r
, b
, 0);
1149 q
= edit_move_forward3 (edit
, r
, c
, 0);
1154 edit_cursor_move (edit
, p
- edit
->curs1
);
1155 while (q
> p
) { /* delete line between margins */
1156 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
1157 edit_delete (edit
, 1);
1160 if (n
) /* move to next line except on the last delete */
1161 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
1165 /* if success return 0 */
1167 edit_block_delete (WEdit
*edit
)
1170 long start_mark
, end_mark
;
1171 if (eval_marks (edit
, &start_mark
, &end_mark
))
1173 if (column_highlighting
&& edit
->mark2
< 0)
1174 edit_mark_cmd (edit
, 0);
1175 if ((end_mark
- start_mark
) > option_max_undo
/ 2) {
1176 /* Warning message with a query to continue or cancel the operation */
1177 if (edit_query_dialog2
1180 (" Block is large, you may not be able to undo this action. "),
1181 _("C&ontinue"), _("&Cancel"))) {
1185 edit_push_markers (edit
);
1186 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1187 edit_scroll_screen_over_cursor (edit
);
1189 if (start_mark
< end_mark
) {
1190 if (column_highlighting
) {
1191 if (edit
->mark2
< 0)
1192 edit_mark_cmd (edit
, 0);
1193 edit_delete_column_of_text (edit
);
1195 while (count
< end_mark
) {
1196 edit_delete (edit
, 1);
1201 edit_set_markers (edit
, 0, 0, 0, 0);
1202 edit
->force
|= REDRAW_PAGE
;
1206 /* returns 1 if canceelled by user */
1207 int edit_block_delete_cmd (WEdit
* edit
)
1209 long start_mark
, end_mark
;
1210 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1211 edit_delete_line (edit
);
1214 return edit_block_delete (edit
);
1217 #define INPUT_INDEX 9
1220 editcmd_find (WEdit
*edit
, gsize
*len
)
1222 gsize search_start
= edit
->search_start
;
1225 if (edit
->replace_backwards
) {
1226 search_end
= edit
->curs1
-1;
1227 while ((int) search_start
>= 0) {
1228 if (search_end
- search_start
> edit
->search
->original_len
&& mc_search_is_fixed_search_str(edit
->search
))
1229 search_end
= search_start
+ edit
->search
->original_len
+1;
1230 if ( mc_search_run(edit
->search
, (void *) edit
, search_start
, search_end
, len
))
1236 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1238 return mc_search_run(edit
->search
, (void *) edit
, edit
->search_start
, edit
->last_byte
, len
);
1244 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1245 (and the above) routines to work properly - paul */
1247 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1250 edit_replace_cmd__conv_to_display(char *str
)
1254 tmp
= str_convert_to_display (str
);
1256 if (tmp
&& tmp
->len
){
1260 g_string_free (tmp
, FALSE
);
1263 return g_strdup(str
);
1268 edit_replace_cmd__conv_to_input(char *str
)
1272 tmp
= str_convert_to_input (str
);
1274 if (tmp
&& tmp
->len
){
1278 g_string_free (tmp
, FALSE
);
1281 return g_strdup(str
);
1284 /* call with edit = 0 before shutdown to close memory leaks */
1286 edit_replace_cmd (WEdit
*edit
, int again
)
1288 /* 1 = search string, 2 = replace with */
1289 static char *saved1
= NULL
; /* saved default[123] */
1290 static char *saved2
= NULL
;
1291 char *input1
= NULL
; /* user input from the dialog */
1292 char *input2
= NULL
;
1293 char *str_for_prompt_dialog
= NULL
;
1295 long times_replaced
= 0, last_search
;
1296 gboolean once_found
= FALSE
;
1299 g_free (saved1
), saved1
= NULL
;
1300 g_free (saved2
), saved2
= NULL
;
1304 last_search
= edit
->last_byte
;
1306 edit
->force
|= REDRAW_COMPLETELY
;
1308 if (again
&& !saved1
&& !saved2
)
1312 input1
= g_strdup (saved1
? saved1
: "");
1313 input2
= g_strdup (saved2
? saved2
: "");
1315 char *disp1
= edit_replace_cmd__conv_to_display(g_strdup (saved1
? saved1
: ""));
1316 char *disp2
= edit_replace_cmd__conv_to_display(g_strdup (saved2
? saved2
: ""));
1318 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1320 editcmd_dialog_replace_show (edit
, disp1
, disp2
, &input1
, &input2
);
1325 str_for_prompt_dialog
= g_strdup(input2
);
1327 if (input1
== NULL
|| *input1
== '\0') {
1328 edit
->force
= REDRAW_COMPLETELY
;
1332 input1
= edit_replace_cmd__conv_to_input(input1
);
1333 input2
= edit_replace_cmd__conv_to_input(input2
);
1335 g_free (saved1
), saved1
= g_strdup (input1
);
1336 g_free (saved2
), saved2
= g_strdup (input2
);
1340 mc_search_free(edit
->search
);
1341 edit
->search
= NULL
;
1347 edit
->search
= mc_search_new(input1
, -1);
1348 if (edit
->search
== NULL
)
1350 edit
->search_start
= edit
->curs1
;
1353 edit
->search
->search_type
= edit
->search_type
;
1354 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1355 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1356 edit
->search
->search_fn
= edit_search_cmd_callback
;
1359 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1
1360 && edit
->replace_backwards
)
1361 edit
->search_start
--;
1363 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1
1364 && !edit
->replace_backwards
)
1365 edit
->search_start
++;
1371 if (! editcmd_find(edit
, &len
))
1373 if (!(edit
->search
->error
== MC_SEARCH_E_OK
|| (once_found
&& edit
->search
->error
== MC_SEARCH_E_NOTFOUND
)))
1375 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1380 new_start
= edit
->search
->normal_offset
;
1382 edit
->search_start
= new_start
= edit
->search
->normal_offset
;
1383 /*returns negative on not found or error in pattern */
1385 if (edit
->search_start
>= 0) {
1388 edit
->found_start
= edit
->search_start
;
1389 i
= edit
->found_len
= len
;
1391 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1392 edit_scroll_screen_over_cursor (edit
);
1396 if (edit
->replace_mode
==0) {
1398 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
1400 edit_scroll_downward (edit
, l
);
1402 edit_scroll_upward (edit
, -l
);
1404 edit_scroll_screen_over_cursor (edit
);
1405 edit
->force
|= REDRAW_PAGE
;
1406 edit_render_keypress (edit
);
1408 /*so that undo stops at each query */
1409 edit_push_key_press (edit
);
1411 switch (editcmd_dialog_replace_prompt_show (edit
, str_for_prompt_dialog
, /* and prompt 2/3 down */
1416 case B_SKIP_REPLACE
:
1420 edit
->replace_mode
=1;
1429 if (replace_yes
) { /* delete then insert new */
1430 GString
*repl_str
, *tmp_str
;
1431 tmp_str
= g_string_new(input2
);
1433 repl_str
= mc_search_prepare_replace_str (edit
->search
, tmp_str
);
1434 g_string_free(tmp_str
, TRUE
);
1435 if (edit
->search
->error
!= MC_SEARCH_E_OK
)
1437 edit_error_dialog (_ ("Replace"), edit
->search
->error_str
);
1442 edit_delete (edit
, 1);
1444 while (++i
< repl_str
->len
)
1445 edit_insert (edit
, repl_str
->str
[i
]);
1447 g_string_free(repl_str
, TRUE
);
1448 edit
->found_len
= i
;
1450 /* so that we don't find the same string again */
1451 if (edit
->replace_backwards
) {
1452 last_search
= edit
->search_start
;
1453 edit
->search_start
--;
1455 edit
->search_start
+= i
;
1456 last_search
= edit
->last_byte
;
1458 edit_scroll_screen_over_cursor (edit
);
1460 const char *msg
= _(" Replace ");
1461 /* try and find from right here for next search */
1462 edit
->search_start
= edit
->curs1
;
1463 edit_update_curs_col (edit
);
1465 edit
->force
|= REDRAW_PAGE
;
1466 edit_render_keypress (edit
);
1467 if (times_replaced
) {
1468 message (D_NORMAL
, msg
, _(" %ld replacements made. "),
1471 query_dialog (msg
, _(" Search string not found "),
1472 D_NORMAL
, 1, _("&OK"));
1473 edit
->replace_mode
= -1;
1475 } while (edit
->replace_mode
>0);
1477 edit
->force
= REDRAW_COMPLETELY
;
1478 edit_scroll_screen_over_cursor (edit
);
1480 g_free (str_for_prompt_dialog
);
1486 void edit_search_cmd (WEdit
* edit
, int again
)
1488 char *search_string
= NULL
, *search_string_dup
= NULL
;
1495 if (edit
->search
!= NULL
)
1496 search_string_dup
= search_string
= g_strndup(edit
->search
->original
, edit
->search
->original_len
);
1502 if (search_string
&& *search_string
)
1504 tmp
= str_convert_to_display (search_string
);
1506 g_free(search_string_dup
);
1507 search_string_dup
= NULL
;
1509 if (tmp
&& tmp
->len
)
1510 search_string
= search_string_dup
= tmp
->str
;
1511 g_string_free (tmp
, FALSE
);
1513 #endif /* HAVE_CHARSET */
1514 editcmd_dialog_search_show (edit
, &search_string
);
1516 if (search_string
&& *search_string
)
1518 tmp
= str_convert_to_input (search_string
);
1519 if (tmp
&& tmp
->len
)
1520 search_string
= tmp
->str
;
1522 g_string_free (tmp
, FALSE
);
1524 if (search_string_dup
)
1525 g_free(search_string_dup
);
1527 #endif /* HAVE_CHARSET */
1529 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1533 edit
->force
|= REDRAW_COMPLETELY
;
1534 edit_scroll_screen_over_cursor (edit
);
1540 mc_search_free(edit
->search
);
1541 edit
->search
= NULL
;
1547 edit
->search
= mc_search_new(search_string
, -1);
1548 if (edit
->search
== NULL
)
1550 edit
->search_start
= edit
->curs1
;
1553 edit
->search
->search_type
= edit
->search_type
;
1554 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1555 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1556 edit
->search
->search_fn
= edit_search_cmd_callback
;
1559 if (search_create_bookmark
)
1561 edit_search_cmd_search_create_bookmark(edit
);
1565 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && edit
->replace_backwards
)
1566 edit
->search_start
--;
1568 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !edit
->replace_backwards
)
1569 edit
->search_start
++;
1572 if (editcmd_find(edit
, &len
))
1574 edit
->found_start
= edit
->search_start
= edit
->search
->normal_offset
;
1575 edit
->found_len
= len
;
1577 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1578 edit_scroll_screen_over_cursor (edit
);
1579 if (edit
->replace_backwards
)
1580 edit
->search_start
--;
1582 edit
->search_start
++;
1586 edit
->search_start
= edit
->curs1
;
1587 if (edit
->search
->error_str
)
1588 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1592 edit
->force
|= REDRAW_COMPLETELY
;
1593 edit_scroll_screen_over_cursor (edit
);
1598 * Check if it's OK to close the editor. If there are unsaved changes,
1599 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
1602 edit_ok_to_exit (WEdit
*edit
)
1604 if (!edit
->modified
)
1607 switch (edit_query_dialog3
1608 (_("Quit"), _(" File was modified, Save with exit? "),
1609 _("&Cancel quit"), _("&Yes"), _("&No"))) {
1611 edit_push_markers (edit
);
1612 edit_set_markers (edit
, 0, 0, 0, 0);
1613 if (!edit_save_cmd (edit
))
1627 #define TEMP_BUF_LEN 1024
1629 /* Return a null terminated length of text. Result must be g_free'd */
1630 static unsigned char *
1631 edit_get_block (WEdit
*edit
, long start
, long finish
, int *l
)
1633 unsigned char *s
, *r
;
1634 r
= s
= g_malloc (finish
- start
+ 1);
1635 if (column_highlighting
) {
1637 /* copy from buffer, excluding chars that are out of the column 'margins' */
1638 while (start
< finish
) {
1640 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0,
1642 c
= edit_get_byte (edit
, start
);
1643 if ((x
>= edit
->column1
&& x
< edit
->column2
)
1644 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
1651 *l
= finish
- start
;
1652 while (start
< finish
)
1653 *s
++ = edit_get_byte (edit
, start
++);
1659 /* save block, returns 1 on success */
1661 edit_save_block (WEdit
* edit
, const char *filename
, long start
,
1667 mc_open (filename
, O_CREAT
| O_WRONLY
| O_TRUNC
,
1668 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
| O_BINARY
)) == -1)
1671 if (column_highlighting
) {
1672 unsigned char *block
, *p
;
1674 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
1676 r
= mc_write (file
, p
, len
);
1686 len
= finish
- start
;
1687 buf
= g_malloc (TEMP_BUF_LEN
);
1688 while (start
!= finish
) {
1689 end
= min (finish
, start
+ TEMP_BUF_LEN
);
1690 for (; i
< end
; i
++)
1691 buf
[i
- start
] = edit_get_byte (edit
, i
);
1692 len
-= mc_write (file
, (char *) buf
, end
- start
);
1703 /* copies a block to clipboard file */
1704 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
1708 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1709 ret
= edit_save_block (edit
, tmp
, start
, finish
);
1715 void edit_paste_from_history (WEdit
*edit
)
1718 edit_error_dialog (_(" Error "), _(" This function is not implemented. "));
1721 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
1723 long start_mark
, end_mark
;
1724 if (eval_marks (edit
, &start_mark
, &end_mark
))
1726 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1727 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
1730 edit_mark_cmd (edit
, 1);
1734 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
1736 long start_mark
, end_mark
;
1737 if (eval_marks (edit
, &start_mark
, &end_mark
))
1739 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1740 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
1743 edit_block_delete_cmd (edit
);
1744 edit_mark_cmd (edit
, 1);
1748 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
1751 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1752 edit_insert_file (edit
, tmp
);
1758 * Ask user for the line and go to that line.
1759 * Negative numbers mean line from the end (i.e. -1 is the last line).
1762 edit_goto_cmd (WEdit
*edit
)
1765 static long line
= 0; /* line as typed, saved as default */
1770 g_snprintf (s
, sizeof (s
), "%ld", line
);
1771 f
= input_dialog (_(" Goto line "), _(" Enter line: "), MC_HISTORY_EDIT_GOTO_LINE
,
1781 l
= strtol (f
, &error
, 0);
1789 l
= edit
->total_lines
+ l
+ 2;
1790 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
1791 edit_move_to_line (edit
, l
- 1);
1792 edit
->force
|= REDRAW_COMPLETELY
;
1797 /* Return 1 on success */
1799 edit_save_block_cmd (WEdit
*edit
)
1801 long start_mark
, end_mark
;
1804 if (eval_marks (edit
, &start_mark
, &end_mark
))
1807 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1809 input_expand_dialog (_(" Save Block "), _(" Enter file name: "),
1810 MC_HISTORY_EDIT_SAVE_BLOCK
,
1813 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1819 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
1821 edit
->force
|= REDRAW_COMPLETELY
;
1825 edit_error_dialog (_(" Save Block "),
1827 (" Cannot save file. ")));
1831 edit
->force
|= REDRAW_COMPLETELY
;
1836 /* returns 1 on success */
1838 edit_insert_file_cmd (WEdit
*edit
)
1843 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1844 exp
= input_expand_dialog (_(" Insert File "), _(" Enter file name: "),
1845 MC_HISTORY_EDIT_INSERT_FILE
,
1848 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1854 if (edit_insert_file (edit
, exp
)) {
1856 edit
->force
|= REDRAW_COMPLETELY
;
1860 edit_error_dialog (_(" Insert File "),
1862 (" Cannot insert file. ")));
1866 edit
->force
|= REDRAW_COMPLETELY
;
1870 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
1871 int edit_sort_cmd (WEdit
* edit
)
1873 static char *old
= 0;
1875 long start_mark
, end_mark
;
1878 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1879 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
1883 tmp
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
);
1884 edit_save_block (edit
, tmp
, start_mark
, end_mark
);
1887 exp
= input_dialog (_(" Run Sort "),
1888 _(" Enter sort options (see manpage) separated by whitespace: "),
1889 MC_HISTORY_EDIT_SORT
, (old
!= NULL
) ? old
: "");
1895 tmp
= g_strconcat (" sort ", exp
, " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
, " > ",
1896 home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
1900 if (e
== -1 || e
== 127) {
1901 edit_error_dialog (_(" Sort "),
1902 get_sys_error (_(" Cannot execute sort command ")));
1905 sprintf (q
, "%d ", e
);
1906 tmp
= g_strconcat (_(" Sort returned non-zero: "), q
, (char *) NULL
);
1907 edit_error_dialog (_(" Sort "), tmp
);
1913 edit
->force
|= REDRAW_COMPLETELY
;
1915 if (edit_block_delete_cmd (edit
))
1917 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
1918 edit_insert_file (edit
, tmp
);
1924 * Ask user for a command, execute it and paste its output back to the
1928 edit_ext_cmd (WEdit
*edit
)
1934 input_dialog (_("Paste output of external command"),
1935 _("Enter shell command(s):"),
1936 MC_HISTORY_EDIT_PASTE_EXTCMD
, NULL
);
1941 tmp
= g_strconcat (exp
, " > ", home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
1947 edit_error_dialog (_("External command"),
1948 get_sys_error (_("Cannot execute command")));
1952 edit
->force
|= REDRAW_COMPLETELY
;
1953 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
1954 edit_insert_file (edit
, tmp
);
1959 /* if block is 1, a block must be highlighted and the shell command
1960 processes it. If block is 0 the shell command is a straight system
1961 command, that just produces some output which is to be inserted */
1963 edit_block_process_cmd (WEdit
*edit
, const char *shell_cmd
, int block
)
1965 long start_mark
, end_mark
;
1967 FILE *script_home
= NULL
;
1968 FILE *script_src
= NULL
;
1969 FILE *block_file
= NULL
;
1970 gchar
*o
, *h
, *b
, *tmp
;
1971 char *quoted_name
= NULL
;
1973 o
= g_strconcat (mc_home
, shell_cmd
, (char *) NULL
); /* original source script */
1974 h
= g_strconcat (home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, (char *) NULL
); /* home script */
1975 b
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
); /* block file */
1977 if (!(script_home
= fopen (h
, "r"))) {
1978 if (!(script_home
= fopen (h
, "w"))) {
1979 tmp
= g_strconcat (_("Error creating script:"), h
, (char *) NULL
);
1980 edit_error_dialog ("", get_sys_error (tmp
));
1982 goto edit_block_process_cmd__EXIT
;
1984 if (!(script_src
= fopen (o
, "r"))) {
1985 o
= g_strconcat (mc_home_alt
, shell_cmd
, (char *) NULL
);
1986 if (!(script_src
= fopen (o
, "r"))) {
1987 fclose (script_home
);
1989 tmp
= g_strconcat (_("Error reading script:"), o
, (char *) NULL
);
1990 edit_error_dialog ("", get_sys_error (tmp
));
1992 goto edit_block_process_cmd__EXIT
;
1995 while (fgets (buf
, sizeof (buf
), script_src
))
1996 fputs (buf
, script_home
);
1997 if (fclose (script_home
)) {
1998 tmp
= g_strconcat (_("Error closing script:"), h
, (char *) NULL
);
1999 edit_error_dialog ("", get_sys_error (tmp
));
2001 goto edit_block_process_cmd__EXIT
;
2004 tmp
= g_strconcat (_("Script created:"), h
, (char *) NULL
);
2005 edit_error_dialog ("", get_sys_error (tmp
));
2011 if (block
) { /* for marked block run indent formatter */
2012 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2013 edit_error_dialog (_("Process block"),
2015 (" You must first highlight a block of text. "));
2016 goto edit_block_process_cmd__EXIT
;
2018 edit_save_block (edit
, b
, start_mark
, end_mark
);
2019 quoted_name
= name_quote (edit
->filename
, 0);
2022 * Initial space is to avoid polluting bash history.
2024 * $1 - name of the edited file (to check its extension etc).
2025 * $2 - file containing the current block.
2026 * $3 - file where error messages should be put
2027 * (for compatibility with old scripts).
2029 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ", quoted_name
,
2030 " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
" /dev/null", (char *) NULL
);
2035 * No block selected, just execute the command for the file.
2037 * $1 - name of the edited file.
2039 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ",
2040 quoted_name
, (char *) NULL
);
2044 g_free (quoted_name
);
2045 close_error_pipe (D_NORMAL
, NULL
);
2047 edit_refresh_cmd (edit
);
2048 edit
->force
|= REDRAW_COMPLETELY
;
2050 /* insert result block */
2052 if (edit_block_delete_cmd (edit
))
2053 goto edit_block_process_cmd__EXIT
;
2054 edit_insert_file (edit
, b
);
2055 if ((block_file
= fopen (b
, "w")))
2056 fclose (block_file
);
2057 goto edit_block_process_cmd__EXIT
;
2059 edit_block_process_cmd__EXIT
:
2066 /* prints at the cursor */
2067 /* returns the number of chars printed */
2068 int edit_print_string (WEdit
* e
, const char *s
)
2072 edit_execute_cmd (e
, -1, (unsigned char) s
[i
++]);
2073 e
->force
|= REDRAW_COMPLETELY
;
2074 edit_update_screen (e
);
2079 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
2084 to
= name_quote (to
, 0);
2085 subject
= name_quote (subject
, 0);
2086 cc
= name_quote (cc
, 0);
2087 s
= g_strconcat ("mail -s ", subject
, *cc
? " -c " : "" , cc
, " ", to
, (char *) NULL
);
2099 for (i
= 0; i
< edit
->last_byte
; i
++)
2100 fputc (edit_get_byte (edit
, i
), p
);
2105 #define MAIL_DLG_HEIGHT 12
2107 void edit_mail_dialog (WEdit
* edit
)
2110 char *tmail_subject
;
2113 static char *mail_cc_last
= 0;
2114 static char *mail_subject_last
= 0;
2115 static char *mail_to_last
= 0;
2117 QuickDialog Quick_input
=
2118 {50, MAIL_DLG_HEIGHT
, -1, 0, N_(" Mail "),
2119 "[Input Line Keys]", 0, 0};
2121 QuickWidget quick_widgets
[] =
2123 {quick_button
, 6, 10, 9, MAIL_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
2124 0, NULL
, NULL
, NULL
},
2125 {quick_button
, 2, 10, 9, MAIL_DLG_HEIGHT
, N_("&OK"), 0, B_ENTER
, 0,
2126 0, NULL
, NULL
, NULL
},
2127 {quick_input
, 3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2128 0, "mail-dlg-input", NULL
, NULL
},
2129 {quick_label
, 2, 50, 7, MAIL_DLG_HEIGHT
, N_(" Copies to"), 0, 0, 0,
2131 {quick_input
, 3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2132 0, "mail-dlg-input-2", NULL
, NULL
},
2133 {quick_label
, 2, 50, 5, MAIL_DLG_HEIGHT
, N_(" Subject"), 0, 0, 0,
2135 {quick_input
, 3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2136 0, "mail-dlg-input-3", NULL
, NULL
},
2137 {quick_label
, 2, 50, 3, MAIL_DLG_HEIGHT
, N_(" To"), 0, 0, 0,
2139 {quick_label
, 2, 50, 2, MAIL_DLG_HEIGHT
, N_(" mail -s <subject> -c <cc> <to>"), 0, 0, 0,
2143 quick_widgets
[2].str_result
= &tmail_cc
;
2144 quick_widgets
[2].text
= mail_cc_last
? mail_cc_last
: "";
2145 quick_widgets
[4].str_result
= &tmail_subject
;
2146 quick_widgets
[4].text
= mail_subject_last
? mail_subject_last
: "";
2147 quick_widgets
[6].str_result
= &tmail_to
;
2148 quick_widgets
[6].text
= mail_to_last
? mail_to_last
: "";
2150 Quick_input
.widgets
= quick_widgets
;
2152 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
2153 g_free (mail_cc_last
);
2154 g_free (mail_subject_last
);
2155 g_free (mail_to_last
);
2156 mail_cc_last
= tmail_cc
;
2157 mail_subject_last
= tmail_subject
;
2158 mail_to_last
= tmail_to
;
2159 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);
2164 /*******************/
2165 /* Word Completion */
2166 /*******************/
2169 /* find first character of current word */
2170 static int edit_find_word_start (WEdit
*edit
, long *word_start
, int *word_len
)
2174 /* return if at begin of file */
2175 if (edit
->curs1
<= 0)
2178 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- 1);
2179 /* return if not at end or in word */
2180 if (isspace (c
) || !(isalnum (c
) || c
== '_'))
2183 /* search start of word to be completed */
2185 /* return if at begin of file */
2186 if (edit
->curs1
- i
< 0)
2190 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- i
);
2192 if (!(isalnum (c
) || c
== '_')) {
2193 /* return if word starts with digit */
2197 *word_start
= edit
->curs1
- (i
- 1); /* start found */
2207 /* (re)set search parameters to the given values */
2208 static void edit_set_search_parameters (WEdit
*edit
, int replace_mode
, int rb
, int rc
)
2210 edit
->replace_mode
= replace_mode
;
2211 edit
->replace_backwards
= rb
;
2212 edit
->replace_case
= rc
;
2216 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2218 /* collect the possible completions */
2220 edit_collect_completions (WEdit
*edit
, long start
, int word_len
,
2221 char *match_expr
, struct selection
*compl,
2224 int len
= 0, max_len
= 0, i
, skip
;
2225 unsigned char *bufpos
;
2228 /* collect max MAX_WORD_COMPLETIONS completions */
2229 while (*num
< MAX_WORD_COMPLETIONS
) {
2230 /* get next match */
2233 edit_find (start - 1, (unsigned char *) match_expr, &len,
2234 edit->last_byte, edit_get_byte_ptr, (void *) edit, 0);
2241 /* add matched completion if not yet added */
2244 buffers1
[start
>> S_EDIT_BUF_SIZE
][start
& M_EDIT_BUF_SIZE
];
2246 for (i
= 0; i
< *num
; i
++) {
2248 ((char *) &compl[i
].text
[word_len
],
2249 (char *) &bufpos
[word_len
], max (len
,
2253 break; /* skip it, already added */
2259 compl[*num
].text
= g_malloc (len
+ 1);
2260 compl[*num
].len
= len
;
2261 for (i
= 0; i
< len
; i
++)
2262 compl[*num
].text
[i
] = *(bufpos
+ i
);
2263 compl[*num
].text
[i
] = '\0';
2266 /* note the maximal length needed for the completion dialog */
2274 * Complete current word using regular expression search
2275 * backwards beginning at the current cursor position.
2278 edit_complete_word_cmd (WEdit
*edit
)
2280 int word_len
= 0, i
, num_compl
= 0, max_len
;
2281 long word_start
= 0;
2282 unsigned char *bufpos
;
2284 struct selection
compl[MAX_WORD_COMPLETIONS
]; /* completions */
2286 /* don't want to disturb another search */
2287 int old_replace_mode
= edit
->replace_mode
;
2288 int old_rb
= edit
->replace_backwards
;
2289 int old_rc
= edit
->replace_case
;
2291 /* search start of word to be completed */
2292 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2295 /* prepare match expression */
2296 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2297 [word_start
& M_EDIT_BUF_SIZE
];
2299 match_expr
= g_strdup_printf ("%.*s[a-zA-Z_0-9]+", word_len
, bufpos
);
2300 /* init search: backward, regexp, whole word, case sensitive */
2301 edit_set_search_parameters (edit
, 0, 1, 1);
2303 /* collect the possible completions */
2304 /* start search from curs1 down to begin of file */
2306 edit_collect_completions (edit
, word_start
, word_len
, match_expr
,
2307 (struct selection
*) &compl, &num_compl
);
2309 if (num_compl
> 0) {
2310 /* insert completed word if there is only one match */
2311 if (num_compl
== 1) {
2312 for (i
= word_len
; i
< compl[0].len
; i
++)
2313 edit_insert (edit
, *(compl[0].text
+ i
));
2315 /* more than one possible completion => ask the user */
2317 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2318 /* !!! pressed again the selection dialog pops up, but that !!! */
2319 /* !!! seems to require a further internal state !!! */
2322 /* let the user select the preferred completion */
2323 editcmd_dialog_completion_show (edit
, max_len
, word_len
,
2324 (struct selection
*) &compl,
2329 g_free (match_expr
);
2330 /* release memory before return */
2331 for (i
= 0; i
< num_compl
; i
++)
2332 g_free (compl[i
].text
);
2334 /* restore search parameters */
2335 edit_set_search_parameters (edit
, old_replace_mode
, old_rb
, old_rc
);
2339 edit_select_codepage_cmd (WEdit
*edit
)
2342 if (do_select_codepage ()) {
2345 cp_id
= get_codepage_id (source_codepage
>= 0 ?
2346 source_codepage
: display_codepage
);
2349 edit
->utf8
= str_isutf8 (cp_id
);
2352 edit
->force
= REDRAW_COMPLETELY
;
2353 edit_refresh_cmd (edit
);
2358 edit_insert_literal_cmd (WEdit
*edit
)
2360 int char_for_insertion
=
2361 editcmd_dialog_raw_key_query (_(" Insert Literal "),
2362 _(" Press any key: "), 0);
2363 edit_execute_key_command (edit
, -1,
2364 ascii_alpha_to_cntrl (char_for_insertion
));
2368 edit_execute_macro_cmd (WEdit
*edit
)
2371 CK_Macro (editcmd_dialog_raw_key_query
2372 (_(" Execute Macro "), _(" Press macro hotkey: "),
2374 if (command
== CK_Macro (0))
2375 command
= CK_Insert_Char
;
2377 edit_execute_key_command (edit
, command
, -1);
2381 edit_begin_end_macro_cmd(WEdit
*edit
)
2385 /* edit is a pointer to the widget */
2389 0 ? CK_Begin_Record_Macro
: CK_End_Record_Macro
;
2390 edit_execute_key_command (edit
, command
, -1);
2395 edit_load_forward_cmd (WEdit
*edit
)
2397 if (edit
->modified
) {
2398 if (edit_query_dialog2
2400 _(" Current text was modified without a file save. \n"
2401 " Continue discards these changes. "), _("C&ontinue"),
2403 edit
->force
|= REDRAW_COMPLETELY
;
2407 if ( edit_stack_iterator
+ 1 < MAX_HISTORY_MOVETO
) {
2408 if ( edit_history_moveto
[edit_stack_iterator
+ 1].line
< 1 ) {
2411 edit_stack_iterator
++;
2412 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2413 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2414 edit_history_moveto
[edit_stack_iterator
].line
);
2425 edit_load_back_cmd (WEdit
*edit
)
2427 if (edit
->modified
) {
2428 if (edit_query_dialog2
2430 _(" Current text was modified without a file save. \n"
2431 " Continue discards these changes. "), _("C&ontinue"),
2433 edit
->force
|= REDRAW_COMPLETELY
;
2437 if ( edit_stack_iterator
> 0 ) {
2438 edit_stack_iterator
--;
2439 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2440 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2441 edit_history_moveto
[edit_stack_iterator
].line
);
2452 edit_get_match_keyword_cmd (WEdit
*edit
)
2458 long word_start
= 0;
2459 unsigned char *bufpos
;
2463 char *tagfile
= NULL
;
2465 etags_hash_t def_hash
[MAX_DEFINITIONS
];
2467 for ( i
= 0; i
< MAX_DEFINITIONS
; i
++) {
2468 def_hash
[i
].filename
= NULL
;
2471 /* search start of word to be completed */
2472 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2475 /* prepare match expression */
2476 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2477 [word_start
& M_EDIT_BUF_SIZE
];
2478 match_expr
= g_strdup_printf ("%.*s", word_len
, bufpos
);
2480 ptr
= g_get_current_dir ();
2481 path
= g_strconcat (ptr
, G_DIR_SEPARATOR_S
, (char *) NULL
);
2484 /* Recursive search file 'TAGS' in parent dirs */
2486 ptr
= g_path_get_dirname (path
);
2487 g_free(path
); path
= ptr
;
2489 tagfile
= g_build_filename (path
, TAGS_NAME
, (char *) NULL
);
2490 if ( exist_file (tagfile
) )
2492 } while (strcmp( path
, G_DIR_SEPARATOR_S
) != 0);
2495 num_def
= etags_set_definition_hash(tagfile
, path
, match_expr
, (etags_hash_t
*) &def_hash
);
2500 max_len
= MAX_WIDTH_DEF_DIALOG
;
2502 if ( num_def
> 0 ) {
2503 editcmd_dialog_select_definition_show (edit
, match_expr
, max_len
, word_len
,
2504 (etags_hash_t
*) &def_hash
,
2507 g_free (match_expr
);
2511 edit_move_block_to_right (WEdit
* edit
)
2513 long start_mark
, end_mark
;
2514 long cur_bol
, start_bol
;
2516 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2519 start_bol
= edit_bol (edit
, start_mark
);
2520 cur_bol
= edit_bol (edit
, end_mark
- 1);
2522 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2523 if ( option_fill_tabs_with_spaces
) {
2524 if ( option_fake_half_tabs
) {
2525 insert_spaces_tab (edit
, 1);
2527 insert_spaces_tab (edit
, 0);
2530 edit_insert (edit
, '\t');
2532 edit_cursor_move (edit
, edit_bol (edit
, cur_bol
) - edit
->curs1
);
2533 if ( cur_bol
== 0 ) {
2536 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2537 } while (cur_bol
>= start_bol
) ;
2538 edit
->force
|= REDRAW_PAGE
;
2542 edit_move_block_to_left (WEdit
* edit
)
2544 long start_mark
, end_mark
;
2545 long cur_bol
, start_bol
;
2546 int i
, del_tab_width
;
2549 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2552 start_bol
= edit_bol (edit
, start_mark
);
2553 cur_bol
= edit_bol (edit
, end_mark
- 1);
2555 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2556 if (option_fake_half_tabs
) {
2557 del_tab_width
= HALF_TAB_SIZE
;
2559 del_tab_width
= option_tab_spacing
;
2561 next_char
= edit_get_byte (edit
, edit
->curs1
);
2562 if ( next_char
== '\t' ) {
2563 edit_delete (edit
, 1);
2564 } else if ( next_char
== ' ' ) {
2565 for (i
= 1; i
<= del_tab_width
; i
++) {
2566 if ( next_char
== ' ' ) {
2567 edit_delete (edit
, 1);
2569 next_char
= edit_get_byte (edit
, edit
->curs1
);
2572 if ( cur_bol
== 0 ) {
2575 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2576 } while (cur_bol
>= start_bol
) ;
2577 edit
->force
|= REDRAW_PAGE
;