2 Editor high level editing commands
4 Copyright (C) 1996-2024
5 Free Software Foundation, Inc.
9 Andrew Borodin <aborodin@vmail.ru>, 2012-2022
10 Ilia Maslakov <il.smind@gmail.com>, 2012
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 * \brief Source: editor high level editing commands
34 /* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
41 #include <sys/types.h>
47 #include "lib/global.h"
48 #include "lib/tty/tty.h"
49 #include "lib/tty/key.h" /* XCTRL */
50 #include "lib/strutil.h" /* utf string functions */
51 #include "lib/fileloc.h"
53 #include "lib/util.h" /* tilde_expand() */
54 #include "lib/vfs/vfs.h"
55 #include "lib/widget.h"
56 #include "lib/event.h" /* mc_event_raise() */
58 #include "lib/charsets.h"
61 #include "src/history.h"
62 #include "src/file_history.h" /* show_file_history() */
64 #include "src/selcodepage.h"
66 #include "src/util.h" /* check_for_default() */
68 #include "edit-impl.h"
69 #include "editwidget.h"
70 #include "editsearch.h"
73 /*** global variables ****************************************************************************/
75 /* search and replace: */
76 int search_create_bookmark
= FALSE
;
78 /*** file scope macro definitions ****************************************************************/
82 #define TEMP_BUF_LEN 1024
84 /*** file scope type declarations ****************************************************************/
86 /*** forward declarations (file scope functions) *************************************************/
88 /*** file scope variables ************************************************************************/
90 static unsigned long edit_save_mode_radio_id
, edit_save_mode_input_id
;
92 /* --------------------------------------------------------------------------------------------- */
93 /*** file scope functions ************************************************************************/
94 /* --------------------------------------------------------------------------------------------- */
97 edit_save_mode_callback (Widget
*w
, Widget
*sender
, widget_msg_t msg
, int parm
, void *data
)
101 case MSG_CHANGED_FOCUS
:
102 if (sender
!= NULL
&& sender
->id
== edit_save_mode_radio_id
)
106 ww
= widget_find_by_id (w
, edit_save_mode_input_id
);
107 widget_disable (ww
, RADIO (sender
)->sel
!= 2);
110 return MSG_NOT_HANDLED
;
113 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
117 /* --------------------------------------------------------------------------------------------- */
119 /* If 0 (quick save) then a) create/truncate <filename> file,
120 b) save to <filename>;
121 if 1 (safe save) then a) save to <tempnam>,
122 b) rename <tempnam> to <filename>;
123 if 2 (do backups) then a) save to <tempnam>,
124 b) rename <filename> to <filename.backup_ext>,
125 c) rename <tempnam> to <filename>. */
127 /* returns 0 on error, -1 on abort */
130 edit_save_file (WEdit
*edit
, const vfs_path_t
*filename_vpath
)
135 int this_save_mode
, rv
, fd
= -1;
136 vfs_path_t
*real_filename_vpath
;
137 vfs_path_t
*savename_vpath
= NULL
;
138 const char *start_filename
;
139 const vfs_path_element_t
*vpath_element
;
142 vpath_element
= vfs_path_get_by_index (filename_vpath
, 0);
143 if (vpath_element
== NULL
)
146 start_filename
= vpath_element
->path
;
147 if (*start_filename
== '\0')
150 if (!IS_PATH_SEP (*start_filename
) && edit
->dir_vpath
!= NULL
)
151 real_filename_vpath
= vfs_path_append_vpath_new (edit
->dir_vpath
, filename_vpath
, NULL
);
153 real_filename_vpath
= vfs_path_clone (filename_vpath
);
155 this_save_mode
= edit_options
.save_mode
;
156 if (this_save_mode
!= EDIT_QUICK_SAVE
)
158 if (!vfs_file_is_local (real_filename_vpath
))
159 /* The file does not exists yet, so no safe save or backup are necessary. */
160 this_save_mode
= EDIT_QUICK_SAVE
;
163 fd
= mc_open (real_filename_vpath
, O_RDONLY
| O_BINARY
);
165 /* The file does not exists yet, so no safe save or backup are necessary. */
166 this_save_mode
= EDIT_QUICK_SAVE
;
173 rv
= mc_stat (real_filename_vpath
, &sb
);
176 if (this_save_mode
== EDIT_QUICK_SAVE
&& !edit
->skip_detach_prompt
&& sb
.st_nlink
> 1)
178 rv
= edit_query_dialog3 (_("Warning"),
179 _("File has hard-links. Detach before saving?"),
180 _("&Yes"), _("&No"), _("&Cancel"));
184 this_save_mode
= EDIT_SAFE_SAVE
;
187 edit
->skip_detach_prompt
= 1;
190 vfs_path_free (real_filename_vpath
, TRUE
);
195 /* Prevent overwriting changes from other editor sessions. */
196 if (edit
->stat1
.st_mtime
!= 0 && edit
->stat1
.st_mtime
!= sb
.st_mtime
)
198 /* The default action is "Cancel". */
201 rv
= edit_query_dialog2 (_("Warning"),
202 _("The file has been modified in the meantime. Save anyway?"),
203 _("&Yes"), _("&Cancel"));
206 vfs_path_free (real_filename_vpath
, TRUE
);
212 if (this_save_mode
== EDIT_QUICK_SAVE
)
213 savename_vpath
= vfs_path_clone (real_filename_vpath
);
216 char *savedir
, *saveprefix
;
218 savedir
= vfs_path_tokens_get (real_filename_vpath
, 0, -1);
220 savedir
= g_strdup (".");
222 /* Token-related function never return leading slash, so we need add it manually */
223 saveprefix
= mc_build_filename (PATH_SEP_STR
, savedir
, "cooledit", (char *) NULL
);
225 fd
= mc_mkstemps (&savename_vpath
, saveprefix
, NULL
);
227 if (savename_vpath
== NULL
)
229 vfs_path_free (real_filename_vpath
, TRUE
);
233 * Close for now because mc_mkstemps use pure open system call
234 * to create temporary file and it needs to be reopened by
235 * VFS-aware mc_open().
240 (void) mc_chown (savename_vpath
, edit
->stat1
.st_uid
, edit
->stat1
.st_gid
);
241 (void) mc_chmod (savename_vpath
, edit
->stat1
.st_mode
);
243 (void) mc_fsetflags (savename_vpath
, edit
->attrs
);
245 fd
= mc_open (savename_vpath
, O_CREAT
| O_WRONLY
| O_TRUNC
| O_BINARY
, edit
->stat1
.st_mode
);
250 p
= edit_get_write_filter (savename_vpath
, real_filename_vpath
);
256 file
= (FILE *) popen (p
, "w");
260 filelen
= edit_write_stream (edit
, file
);
264 if (pclose (file
) != 0)
266 tmp
= g_strdup_printf (_("Error writing to pipe: %s"), p
);
267 edit_error_dialog (_("Error"), tmp
);
276 tmp
= g_strdup_printf (_("Cannot open pipe for writing: %s"), p
);
277 edit_error_dialog (_("Error"), get_sys_error (tmp
));
284 else if (edit
->lb
== LB_ASIS
)
285 { /* do not change line breaks */
286 filelen
= edit_buffer_write_file (&edit
->buffer
, fd
);
288 if (filelen
!= edit
->buffer
.size
)
294 if (mc_close (fd
) != 0)
297 /* Update the file information, especially the mtime. */
298 if (mc_stat (savename_vpath
, &edit
->stat1
) == -1)
302 { /* change line breaks */
304 const char *savename
;
308 savename
= vfs_path_get_last_path_str (savename_vpath
);
309 file
= (FILE *) fopen (savename
, "w");
312 filelen
= edit_write_stream (edit
, file
);
319 msg
= g_strdup_printf (_("Cannot open file for writing: %s"), savename
);
320 edit_error_dialog (_("Error"), msg
);
326 if (filelen
!= edit
->buffer
.size
)
329 if (this_save_mode
== EDIT_DO_BACKUP
)
331 char *tmp_store_filename
;
332 vfs_path_element_t
*last_vpath_element
;
333 vfs_path_t
*tmp_vpath
;
336 g_assert (edit_options
.backup_ext
!= NULL
);
338 /* add backup extension to the path */
339 tmp_vpath
= vfs_path_clone (real_filename_vpath
);
340 last_vpath_element
= (vfs_path_element_t
*) vfs_path_get_by_index (tmp_vpath
, -1);
341 tmp_store_filename
= last_vpath_element
->path
;
342 last_vpath_element
->path
=
343 g_strdup_printf ("%s%s", tmp_store_filename
, edit_options
.backup_ext
);
344 g_free (tmp_store_filename
);
346 ok
= (mc_rename (real_filename_vpath
, tmp_vpath
) != -1);
347 vfs_path_free (tmp_vpath
, TRUE
);
352 if (this_save_mode
!= EDIT_QUICK_SAVE
&& mc_rename (savename_vpath
, real_filename_vpath
) == -1)
355 vfs_path_free (real_filename_vpath
, TRUE
);
356 vfs_path_free (savename_vpath
, TRUE
);
359 /* FIXME: Is this safe ?
360 * if (this_save_mode != EDIT_QUICK_SAVE)
361 * mc_unlink (savename);
363 vfs_path_free (real_filename_vpath
, TRUE
);
364 vfs_path_free (savename_vpath
, TRUE
);
368 /* --------------------------------------------------------------------------------------------- */
371 edit_check_newline (const edit_buffer_t
*buf
)
373 return !(edit_options
.check_nl_at_eof
&& buf
->size
> 0
374 && edit_buffer_get_byte (buf
, buf
->size
- 1) != '\n'
375 && edit_query_dialog2 (_("Warning"),
376 _("The file you are saving does not end with a newline."),
377 _("C&ontinue"), _("&Cancel")) != 0);
380 /* --------------------------------------------------------------------------------------------- */
383 edit_get_save_file_as (WEdit
*edit
)
385 static LineBreaks cur_lb
= LB_ASIS
;
387 vfs_path_t
*ret_vpath
= NULL
;
389 const char *lb_names
[LB_NAMES
] = {
390 N_("&Do not change"),
391 N_("&Unix format (LF)"),
392 N_("&Windows/DOS format (CR LF)"),
393 N_("&Macintosh format (CR)")
396 quick_widget_t quick_widgets
[] = {
398 QUICK_LABELED_INPUT (N_("Enter file name:"), input_label_above
,
399 vfs_path_as_str (edit
->filename_vpath
), "save-as",
400 &filename_res
, NULL
, FALSE
, FALSE
, INPUT_COMPLETE_FILENAMES
),
401 QUICK_SEPARATOR (TRUE
),
402 QUICK_LABEL (N_("Change line breaks to:"), NULL
),
403 QUICK_RADIO (LB_NAMES
, lb_names
, (int *) &cur_lb
, NULL
),
404 QUICK_BUTTONS_OK_CANCEL
,
409 WRect r
= { -1, -1, 0, 64 };
411 quick_dialog_t qdlg
= {
412 r
, N_("Save As"), "[Save File As]",
413 quick_widgets
, NULL
, NULL
416 if (quick_dialog (&qdlg
) != B_CANCEL
)
421 fname
= tilde_expand (filename_res
);
422 g_free (filename_res
);
423 ret_vpath
= vfs_path_from_str (fname
);
430 /* --------------------------------------------------------------------------------------------- */
432 /** returns TRUE on success */
435 edit_save_cmd (WEdit
*edit
)
437 int res
, save_lock
= 0;
439 if (!edit
->locked
&& !edit
->delete_file
)
440 save_lock
= lock_file (edit
->filename_vpath
);
441 res
= edit_save_file (edit
, edit
->filename_vpath
);
443 /* Maintain modify (not save) lock on failure */
444 if ((res
> 0 && edit
->locked
) || save_lock
)
445 edit
->locked
= unlock_file (edit
->filename_vpath
);
447 /* On failure try 'save as', it does locking on its own */
449 return edit_save_as_cmd (edit
);
453 edit
->delete_file
= 0;
457 edit
->force
|= REDRAW_COMPLETELY
;
462 /* --------------------------------------------------------------------------------------------- */
465 edit_delete_column_of_text (WEdit
*edit
, off_t m1
, off_t m2
)
471 n
= edit_buffer_get_forward_offset (&edit
->buffer
, m1
, 0, m2
) + 1;
472 r
= edit_buffer_get_bol (&edit
->buffer
, m1
);
473 c
= (long) edit_move_forward3 (edit
, r
, 0, m1
);
474 r
= edit_buffer_get_bol (&edit
->buffer
, m2
);
475 d
= (long) edit_move_forward3 (edit
, r
, 0, m2
);
476 b
= MAX (MIN (c
, d
), MIN (edit
->column1
, edit
->column2
));
477 c
= MAX (c
, MAX (edit
->column1
, edit
->column2
));
483 r
= edit_buffer_get_current_bol (&edit
->buffer
);
484 p
= edit_move_forward3 (edit
, r
, b
, 0);
485 q
= edit_move_forward3 (edit
, r
, c
, 0);
488 edit_cursor_move (edit
, p
- edit
->buffer
.curs1
);
489 /* delete line between margins */
491 if (edit_buffer_get_current_byte (&edit
->buffer
) != '\n')
492 edit_delete (edit
, TRUE
);
494 /* move to next line except on the last delete */
497 r
= edit_buffer_get_forward_offset (&edit
->buffer
, edit
->buffer
.curs1
, 1, 0);
498 edit_cursor_move (edit
, r
- edit
->buffer
.curs1
);
503 /* --------------------------------------------------------------------------------------------- */
504 /** if success return TRUE */
507 edit_block_delete (WEdit
*edit
, off_t start_mark
, off_t end_mark
)
510 long curs_line
, c1
, c2
;
512 if (edit
->column_highlight
&& edit
->mark2
< 0)
513 edit_mark_cmd (edit
, FALSE
);
515 /* Warning message with a query to continue or cancel the operation */
516 if ((end_mark
- start_mark
) > max_undo
/ 2 &&
517 edit_query_dialog2 (_("Warning"),
518 ("Block is large, you may not be able to undo this action"),
519 _("C&ontinue"), _("&Cancel")) != 0)
522 c1
= MIN (edit
->column1
, edit
->column2
);
523 c2
= MAX (edit
->column1
, edit
->column2
);
527 edit_push_markers (edit
);
529 curs_line
= edit
->buffer
.curs_line
;
531 curs_pos
= edit
->curs_col
+ edit
->over_col
;
533 /* move cursor to start of selection */
534 edit_cursor_move (edit
, start_mark
- edit
->buffer
.curs1
);
535 edit_scroll_screen_over_cursor (edit
);
537 if (start_mark
< end_mark
)
539 if (edit
->column_highlight
)
545 edit_mark_cmd (edit
, FALSE
);
546 edit_delete_column_of_text (edit
, start_mark
, end_mark
);
547 /* move cursor to the saved position */
548 edit_move_to_line (edit
, curs_line
);
549 /* calculate line width and cursor position before cut */
550 b
= edit_buffer_get_current_bol (&edit
->buffer
);
551 e
= edit_buffer_get_current_eol (&edit
->buffer
);
552 line_width
= edit_move_forward3 (edit
, b
, 0, e
);
553 if (edit_options
.cursor_beyond_eol
&& curs_pos
> line_width
)
554 edit
->over_col
= curs_pos
- line_width
;
560 for (count
= start_mark
; count
< end_mark
; count
++)
561 edit_delete (edit
, TRUE
);
565 edit_set_markers (edit
, 0, 0, 0, 0);
566 edit
->force
|= REDRAW_PAGE
;
571 /* --------------------------------------------------------------------------------------------- */
572 /** Return a null terminated length of text. Result must be g_free'd */
574 static unsigned char *
575 edit_get_block (WEdit
*edit
, off_t start
, off_t finish
, off_t
*l
)
577 unsigned char *s
, *r
;
579 r
= s
= g_malloc0 (finish
- start
+ 1);
581 if (edit
->column_highlight
)
585 /* copy from buffer, excluding chars that are out of the column 'margins' */
586 for (; start
< finish
; start
++)
591 x
= edit_buffer_get_bol (&edit
->buffer
, start
);
592 x
= edit_move_forward3 (edit
, x
, 0, start
);
593 c
= edit_buffer_get_byte (&edit
->buffer
, start
);
594 if ((x
>= edit
->column1
&& x
< edit
->column2
)
595 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n')
606 for (; start
< finish
; start
++)
607 *s
++ = edit_buffer_get_byte (&edit
->buffer
, start
);
615 /* --------------------------------------------------------------------------------------------- */
616 /** copies a block to clipboard file */
619 edit_save_block_to_clip_file (WEdit
*edit
, off_t start
, off_t finish
)
624 tmp
= mc_config_get_full_path (EDIT_HOME_CLIP_FILE
);
625 ret
= edit_save_block (edit
, tmp
, start
, finish
);
631 /* --------------------------------------------------------------------------------------------- */
634 pipe_mail (const edit_buffer_t
*buf
, char *to
, char *subject
, char *cc
)
639 to
= name_quote (to
, FALSE
);
642 subject
= name_quote (subject
, FALSE
);
645 cc
= name_quote (cc
, FALSE
);
647 s
= g_strdup_printf ("mail -s %s %s", subject
, to
);
650 s
= g_strdup_printf ("mail -s %s -c %s %s", subject
, cc
, to
);
670 for (i
= 0; i
< buf
->size
; i
++)
671 if (fputc (edit_buffer_get_byte (buf
, i
), p
) < 0)
677 /* --------------------------------------------------------------------------------------------- */
680 edit_insert_column_of_text (WEdit
*edit
, unsigned char *data
, off_t size
, long width
,
681 off_t
*start_pos
, off_t
*end_pos
, long *col1
, long *col2
)
686 cursor
= edit
->buffer
.curs1
;
687 col
= edit_get_col (edit
);
689 for (i
= 0; i
< size
; i
++)
692 edit_insert (edit
, data
[i
]);
694 { /* fill in and move to next line */
698 if (edit_buffer_get_current_byte (&edit
->buffer
) != '\n')
700 for (l
= width
- (edit_get_col (edit
) - col
); l
> 0; l
-= space_width
)
701 edit_insert (edit
, ' ');
703 for (p
= edit
->buffer
.curs1
;; p
++)
705 if (p
== edit
->buffer
.size
)
707 edit_cursor_move (edit
, edit
->buffer
.size
- edit
->buffer
.curs1
);
708 edit_insert_ahead (edit
, '\n');
712 if (edit_buffer_get_byte (&edit
->buffer
, p
) == '\n')
718 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->buffer
.curs1
);
720 for (l
= col
- edit_get_col (edit
); l
>= space_width
; l
-= space_width
)
721 edit_insert (edit
, ' ');
728 *end_pos
= edit
->buffer
.curs1
;
729 edit_cursor_move (edit
, cursor
- edit
->buffer
.curs1
);
732 /* --------------------------------------------------------------------------------------------- */
734 * Callback for the iteration of objects in the 'editors' array.
735 * Toggle syntax highlighting in editor object.
737 * @param data probably WEdit object
738 * @param user_data unused
742 edit_syntax_onoff_cb (void *data
, void *user_data
)
746 if (edit_widget_is_editor (CONST_WIDGET (data
)))
748 WEdit
*edit
= EDIT (data
);
750 if (edit_options
.syntax_highlighting
)
751 edit_load_syntax (edit
, NULL
, edit
->syntax_type
);
752 edit
->force
|= REDRAW_PAGE
;
756 /* --------------------------------------------------------------------------------------------- */
759 editcmd_dialog_raw_key_query_cb (Widget
*w
, Widget
*sender
, widget_msg_t msg
, int parm
, void *data
)
761 WDialog
*h
= DIALOG (w
);
770 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
774 /* --------------------------------------------------------------------------------------------- */
775 /*** public functions ****************************************************************************/
776 /* --------------------------------------------------------------------------------------------- */
779 edit_refresh_cmd (void)
786 /* --------------------------------------------------------------------------------------------- */
788 * Toggle syntax highlighting in all editor windows.
790 * @param h root widget for all windows
794 edit_syntax_onoff_cmd (WDialog
*h
)
796 edit_options
.syntax_highlighting
= !edit_options
.syntax_highlighting
;
797 g_list_foreach (GROUP (h
)->widgets
, edit_syntax_onoff_cb
, NULL
);
798 widget_draw (WIDGET (h
));
801 /* --------------------------------------------------------------------------------------------- */
803 * Toggle tabs showing in all editor windows.
805 * @param h root widget for all windows
809 edit_show_tabs_tws_cmd (WDialog
*h
)
811 enable_show_tabs_tws
= !enable_show_tabs_tws
;
812 widget_draw (WIDGET (h
));
815 /* --------------------------------------------------------------------------------------------- */
817 * Toggle right margin showing in all editor windows.
819 * @param h root widget for all windows
823 edit_show_margin_cmd (WDialog
*h
)
825 edit_options
.show_right_margin
= !edit_options
.show_right_margin
;
826 widget_draw (WIDGET (h
));
829 /* --------------------------------------------------------------------------------------------- */
831 * Toggle line numbers showing in all editor windows.
833 * @param h root widget for all windows
837 edit_show_numbers_cmd (WDialog
*h
)
839 edit_options
.line_state
= !edit_options
.line_state
;
840 edit_options
.line_state_width
= edit_options
.line_state
? LINE_STATE_WIDTH
: 0;
841 widget_draw (WIDGET (h
));
844 /* --------------------------------------------------------------------------------------------- */
847 edit_save_mode_cmd (void)
849 char *str_result
= NULL
;
851 const char *str
[] = {
854 N_("&Do backups with following extension:")
860 for (i
= 0; i
< 3; i
++)
864 g_assert (edit_options
.backup_ext
!= NULL
);
867 quick_widget_t quick_widgets
[] = {
869 QUICK_RADIO (3, str
, &edit_options
.save_mode
, &edit_save_mode_radio_id
),
870 QUICK_INPUT (edit_options
.backup_ext
, "edit-backup-ext", &str_result
,
871 &edit_save_mode_input_id
, FALSE
, FALSE
, INPUT_COMPLETE_NONE
),
872 QUICK_SEPARATOR (TRUE
),
873 QUICK_CHECKBOX (N_("Check &POSIX new line"), &edit_options
.check_nl_at_eof
, NULL
),
874 QUICK_BUTTONS_OK_CANCEL
,
879 WRect r
= { -1, -1, 0, 38 };
881 quick_dialog_t qdlg
= {
882 r
, N_("Edit Save Mode"), "[Edit Save Mode]",
883 quick_widgets
, edit_save_mode_callback
, NULL
886 if (quick_dialog (&qdlg
) != B_CANCEL
)
888 g_free (edit_options
.backup_ext
);
889 edit_options
.backup_ext
= str_result
;
894 /* --------------------------------------------------------------------------------------------- */
897 edit_set_filename (WEdit
*edit
, const vfs_path_t
*name_vpath
)
899 vfs_path_free (edit
->filename_vpath
, TRUE
);
900 edit
->filename_vpath
= vfs_path_clone (name_vpath
);
902 if (edit
->dir_vpath
== NULL
)
903 edit
->dir_vpath
= vfs_path_clone (vfs_get_raw_current_dir ());
906 /* --------------------------------------------------------------------------------------------- */
907 /* Here we want to warn the users of overwriting an existing file,
908 but only if they have made a change to the filename */
909 /* returns TRUE on success */
911 edit_save_as_cmd (WEdit
*edit
)
913 /* This heads the 'Save As' dialog box */
914 vfs_path_t
*exp_vpath
;
916 gboolean different_filename
= FALSE
;
917 gboolean ret
= FALSE
;
919 if (!edit_check_newline (&edit
->buffer
))
922 exp_vpath
= edit_get_save_file_as (edit
);
923 edit_push_undo_action (edit
, KEY_PRESS
+ edit
->start_display
);
925 if (exp_vpath
!= NULL
&& vfs_path_len (exp_vpath
) != 0)
929 if (!vfs_path_equal (edit
->filename_vpath
, exp_vpath
))
934 if (mc_stat (exp_vpath
, &sb
) == 0 && !S_ISREG (sb
.st_mode
))
936 edit_error_dialog (_("Save as"),
938 ("Cannot save: destination is not a regular file")));
942 different_filename
= TRUE
;
943 file
= mc_open (exp_vpath
, O_RDONLY
| O_BINARY
);
946 edit
->stat1
.st_mode
|= S_IWUSR
;
949 /* the file exists */
951 /* Overwrite the current file or cancel the operation */
952 if (edit_query_dialog2
954 _("A file already exists with this name"), _("&Overwrite"), _("&Cancel")))
958 save_lock
= lock_file (exp_vpath
);
960 else if (!edit
->locked
&& !edit
->delete_file
)
961 /* filenames equal, check if already locked */
962 save_lock
= lock_file (exp_vpath
);
964 if (different_filename
)
965 /* Allow user to write into saved (under another name) file
966 * even if original file had r/o user permissions. */
967 edit
->stat1
.st_mode
|= S_IWUSR
;
969 rv
= edit_save_file (edit
, exp_vpath
);
973 /* Successful, so unlock both files */
974 if (different_filename
)
977 unlock_file (exp_vpath
);
979 edit
->locked
= unlock_file (edit
->filename_vpath
);
981 else if (edit
->locked
|| save_lock
)
982 edit
->locked
= unlock_file (edit
->filename_vpath
);
984 edit_set_filename (edit
, exp_vpath
);
985 if (edit
->lb
!= LB_ASIS
)
986 edit_reload (edit
, exp_vpath
);
988 edit
->delete_file
= 0;
989 if (different_filename
)
990 edit_load_syntax (edit
, NULL
, edit
->syntax_type
);
995 edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
999 /* Failed, so maintain modify (not save) lock */
1001 unlock_file (exp_vpath
);
1007 vfs_path_free (exp_vpath
, TRUE
);
1008 edit
->force
|= REDRAW_COMPLETELY
;
1012 /* --------------------------------------------------------------------------------------------- */
1013 /** returns TRUE on success */
1016 edit_save_confirm_cmd (WEdit
*edit
)
1018 if (edit
->filename_vpath
== NULL
)
1019 return edit_save_as_cmd (edit
);
1021 if (!edit_check_newline (&edit
->buffer
))
1024 if (edit_options
.confirm_save
)
1029 f
= g_strdup_printf (_("Confirm save file: \"%s\""),
1030 vfs_path_as_str (edit
->filename_vpath
));
1031 ok
= (edit_query_dialog2 (_("Save file"), f
, _("&Save"), _("&Cancel")) == 0);
1037 return edit_save_cmd (edit
);
1040 /* --------------------------------------------------------------------------------------------- */
1042 * Ask file to edit and load it.
1044 * @return TRUE on success or cancel of ask.
1048 edit_load_cmd (WDialog
*h
)
1051 gboolean ret
= TRUE
; /* possible cancel */
1053 exp
= input_expand_dialog (_("Load"), _("Enter file name:"),
1054 MC_HISTORY_EDIT_LOAD
, INPUT_LAST_TEXT
,
1055 INPUT_COMPLETE_FILENAMES
| INPUT_COMPLETE_CD
);
1057 if (exp
!= NULL
&& *exp
!= '\0')
1059 vfs_path_t
*exp_vpath
;
1062 exp_vpath
= vfs_path_from_str (exp
);
1063 edit_arg_init (&arg
, exp_vpath
, 0);
1064 ret
= edit_load_file_from_filename (h
, &arg
);
1065 vfs_path_free (exp_vpath
, TRUE
);
1073 /* --------------------------------------------------------------------------------------------- */
1077 * @param h screen the owner of editor window
1078 * @param vpath vfs file path
1079 * @param line line number
1081 * @return TRUE if file content was successfully loaded, FALSE otherwise
1085 edit_load_file_from_filename (WDialog
*h
, const edit_arg_t
*arg
)
1087 WRect r
= WIDGET (h
)->rect
;
1089 rect_grow (&r
, -1, 0);
1091 return edit_add_window (h
, &r
, arg
);
1094 /* --------------------------------------------------------------------------------------------- */
1096 * Show history od edited or viewed files and open selected file.
1098 * @return TRUE on success, FALSE otherwise.
1102 edit_load_file_from_history (WDialog
*h
)
1106 gboolean ret
= TRUE
; /* possible cancel */
1108 exp
= show_file_history (CONST_WIDGET (h
), &action
);
1109 if (exp
!= NULL
&& (action
== CK_Edit
|| action
== CK_Enter
))
1111 vfs_path_t
*exp_vpath
;
1114 exp_vpath
= vfs_path_from_str (exp
);
1115 edit_arg_init (&arg
, exp_vpath
, 0);
1116 ret
= edit_load_file_from_filename (h
, &arg
);
1117 vfs_path_free (exp_vpath
, TRUE
);
1125 /* --------------------------------------------------------------------------------------------- */
1127 * Load syntax file to edit.
1129 * @return TRUE on success
1133 edit_load_syntax_file (WDialog
*h
)
1135 vfs_path_t
*extdir_vpath
;
1138 gboolean ret
= FALSE
;
1140 if (geteuid () == 0)
1141 dir
= query_dialog (_("Syntax file edit"),
1142 _("Which syntax file you want to edit?"), D_NORMAL
, 2,
1143 _("&User"), _("&System wide"));
1146 vfs_path_build_filename (mc_global
.sysconfig_dir
, EDIT_SYNTAX_FILE
, (char *) NULL
);
1147 if (!exist_file (vfs_path_get_last_path_str (extdir_vpath
)))
1149 vfs_path_free (extdir_vpath
, TRUE
);
1151 vfs_path_build_filename (mc_global
.share_data_dir
, EDIT_SYNTAX_FILE
, (char *) NULL
);
1156 vfs_path_t
*user_syntax_file_vpath
;
1158 user_syntax_file_vpath
= mc_config_get_full_vpath (EDIT_SYNTAX_FILE
);
1159 check_for_default (extdir_vpath
, user_syntax_file_vpath
);
1160 edit_arg_init (&arg
, user_syntax_file_vpath
, 0);
1161 ret
= edit_load_file_from_filename (h
, &arg
);
1162 vfs_path_free (user_syntax_file_vpath
, TRUE
);
1166 edit_arg_init (&arg
, extdir_vpath
, 0);
1167 ret
= edit_load_file_from_filename (h
, &arg
);
1170 vfs_path_free (extdir_vpath
, TRUE
);
1175 /* --------------------------------------------------------------------------------------------- */
1177 * Load menu file to edit.
1179 * @return TRUE on success
1183 edit_load_menu_file (WDialog
*h
)
1185 vfs_path_t
*buffer_vpath
;
1186 vfs_path_t
*menufile_vpath
;
1192 dir
= query_dialog (_("Menu edit"),
1193 _("Which menu file do you want to edit?"), D_NORMAL
,
1194 geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System wide"));
1197 vfs_path_build_filename (mc_global
.sysconfig_dir
, EDIT_GLOBAL_MENU
, (char *) NULL
);
1198 if (!exist_file (vfs_path_get_last_path_str (menufile_vpath
)))
1200 vfs_path_free (menufile_vpath
, TRUE
);
1202 vfs_path_build_filename (mc_global
.share_data_dir
, EDIT_GLOBAL_MENU
, (char *) NULL
);
1208 buffer_vpath
= vfs_path_from_str (EDIT_LOCAL_MENU
);
1209 check_for_default (menufile_vpath
, buffer_vpath
);
1210 chmod (vfs_path_get_last_path_str (buffer_vpath
), 0600);
1214 buffer_vpath
= mc_config_get_full_vpath (EDIT_HOME_MENU
);
1215 check_for_default (menufile_vpath
, buffer_vpath
);
1220 vfs_path_build_filename (mc_global
.sysconfig_dir
, EDIT_GLOBAL_MENU
, (char *) NULL
);
1221 if (!exist_file (vfs_path_get_last_path_str (buffer_vpath
)))
1223 vfs_path_free (buffer_vpath
, TRUE
);
1225 vfs_path_build_filename (mc_global
.share_data_dir
, EDIT_GLOBAL_MENU
, (char *) NULL
);
1230 vfs_path_free (menufile_vpath
, TRUE
);
1234 edit_arg_init (&arg
, buffer_vpath
, 0);
1235 ret
= edit_load_file_from_filename (h
, &arg
);
1237 vfs_path_free (buffer_vpath
, TRUE
);
1238 vfs_path_free (menufile_vpath
, TRUE
);
1243 /* --------------------------------------------------------------------------------------------- */
1245 * Close window with opened file.
1247 * @return TRUE if file was closed.
1251 edit_close_cmd (WEdit
*edit
)
1255 ret
= (edit
!= NULL
) && edit_ok_to_exit (edit
);
1259 Widget
*w
= WIDGET (edit
);
1260 WGroup
*g
= w
->owner
;
1262 if (edit
->locked
!= 0)
1263 unlock_file (edit
->filename_vpath
);
1265 group_remove_widget (w
);
1268 if (edit_widget_is_editor (CONST_WIDGET (g
->current
->data
)))
1269 edit
= EDIT (g
->current
->data
);
1272 edit
= edit_find_editor (DIALOG (g
));
1274 widget_select (WIDGET (edit
));
1279 edit
->force
|= REDRAW_COMPLETELY
;
1284 /* --------------------------------------------------------------------------------------------- */
1287 edit_block_copy_cmd (WEdit
*edit
)
1289 off_t start_mark
, end_mark
, current
= edit
->buffer
.curs1
;
1290 off_t mark1
= 0, mark2
= 0;
1291 long c1
= 0, c2
= 0;
1293 unsigned char *copy_buf
;
1295 edit_update_curs_col (edit
);
1296 if (!eval_marks (edit
, &start_mark
, &end_mark
))
1299 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1301 /* all that gets pushed are deletes hence little space is used on the stack */
1303 edit_push_markers (edit
);
1305 if (edit
->column_highlight
)
1309 col_delta
= labs (edit
->column2
- edit
->column1
);
1310 edit_insert_column_of_text (edit
, copy_buf
, size
, col_delta
, &mark1
, &mark2
, &c1
, &c2
);
1314 int size_orig
= size
;
1317 edit_insert_ahead (edit
, copy_buf
[size
]);
1319 /* Place cursor at the end of text selection */
1320 if (edit_options
.cursor_after_inserted_block
)
1321 edit_cursor_move (edit
, size_orig
);
1325 edit_scroll_screen_over_cursor (edit
);
1327 if (edit
->column_highlight
)
1328 edit_set_markers (edit
, edit
->buffer
.curs1
, mark2
, c1
, c2
);
1329 else if (start_mark
< current
&& end_mark
> current
)
1330 edit_set_markers (edit
, start_mark
, end_mark
+ end_mark
- start_mark
, 0, 0);
1332 edit
->force
|= REDRAW_PAGE
;
1336 /* --------------------------------------------------------------------------------------------- */
1339 edit_block_move_cmd (WEdit
*edit
)
1342 unsigned char *copy_buf
= NULL
;
1343 off_t start_mark
, end_mark
;
1345 if (!eval_marks (edit
, &start_mark
, &end_mark
))
1348 if (!edit
->column_highlight
&& edit
->buffer
.curs1
> start_mark
&& edit
->buffer
.curs1
< end_mark
)
1351 if (edit
->mark2
< 0)
1352 edit_mark_cmd (edit
, FALSE
);
1353 edit_push_markers (edit
);
1355 if (edit
->column_highlight
)
1359 long c1
, c2
, b_width
;
1363 c1
= MIN (edit
->column1
, edit
->column2
);
1364 c2
= MAX (edit
->column1
, edit
->column2
);
1367 edit_update_curs_col (edit
);
1370 x2
= x
+ edit
->over_col
;
1372 /* do nothing when cursor inside first line of selected area */
1373 b1
= edit_buffer_get_eol (&edit
->buffer
, edit
->buffer
.curs1
);
1374 b2
= edit_buffer_get_eol (&edit
->buffer
, start_mark
);
1375 if (b1
== b2
&& x2
> c1
&& x2
<= c2
)
1378 if (edit
->buffer
.curs1
> start_mark
1379 && edit
->buffer
.curs1
< edit_buffer_get_eol (&edit
->buffer
, end_mark
))
1383 else if (x
> c1
&& x
<= c2
)
1386 /* save current selection into buffer */
1387 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1389 /* remove current selection */
1390 edit_block_delete_cmd (edit
);
1392 edit
->over_col
= MAX (0, edit
->over_col
- b_width
);
1393 /* calculate the cursor pos after delete block */
1394 b1
= edit_buffer_get_current_bol (&edit
->buffer
);
1395 current
= edit_move_forward3 (edit
, b1
, x
, 0);
1396 edit_cursor_move (edit
, current
- edit
->buffer
.curs1
);
1397 edit_scroll_screen_over_cursor (edit
);
1399 /* add TWS if need before block insertion */
1400 if (edit_options
.cursor_beyond_eol
&& edit
->over_col
> 0)
1401 edit_insert_over (edit
);
1403 edit_insert_column_of_text (edit
, copy_buf
, size
, b_width
, &mark1
, &mark2
, &c1
, &c2
);
1404 edit_set_markers (edit
, mark1
, mark2
, c1
, c2
);
1408 off_t count
, count_orig
;
1411 current
= edit
->buffer
.curs1
;
1412 copy_buf
= g_malloc0 (end_mark
- start_mark
);
1413 edit_cursor_move (edit
, start_mark
- edit
->buffer
.curs1
);
1414 edit_scroll_screen_over_cursor (edit
);
1416 for (count
= start_mark
; count
< end_mark
; count
++)
1417 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
, TRUE
);
1419 edit_scroll_screen_over_cursor (edit
);
1420 x
= current
> edit
->buffer
.curs1
? end_mark
- start_mark
: 0;
1421 edit_cursor_move (edit
, current
- edit
->buffer
.curs1
- x
);
1422 edit_scroll_screen_over_cursor (edit
);
1424 while (count
-- > start_mark
)
1425 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1427 edit_set_markers (edit
, edit
->buffer
.curs1
, edit
->buffer
.curs1
+ end_mark
- start_mark
, 0,
1430 /* Place cursor at the end of text selection */
1431 if (edit_options
.cursor_after_inserted_block
)
1432 edit_cursor_move (edit
, count_orig
- start_mark
);
1435 edit_scroll_screen_over_cursor (edit
);
1437 edit
->force
|= REDRAW_PAGE
;
1440 /* --------------------------------------------------------------------------------------------- */
1441 /** returns FALSE if canceelled by user */
1444 edit_block_delete_cmd (WEdit
*edit
)
1446 off_t start_mark
, end_mark
;
1448 if (eval_marks (edit
, &start_mark
, &end_mark
))
1449 return edit_block_delete (edit
, start_mark
, end_mark
);
1451 edit_delete_line (edit
);
1456 /* --------------------------------------------------------------------------------------------- */
1458 * Check if it's OK to close the file. If there are unsaved changes, ask user.
1460 * @return TRUE if it's OK to exit, FALSE to continue editing.
1464 edit_ok_to_exit (WEdit
*edit
)
1466 const char *fname
= N_("[NoName]");
1470 if (!edit
->modified
)
1473 if (edit
->filename_vpath
!= NULL
)
1474 fname
= vfs_path_as_str (edit
->filename_vpath
);
1480 if (!mc_global
.midnight_shutdown
)
1484 msg
= g_strdup_printf (_("File %s was modified.\nSave before close?"), fname
);
1485 act
= edit_query_dialog3 (_("Close file"), msg
, _("&Yes"), _("&No"), _("&Cancel"));
1489 msg
= g_strdup_printf (_("Midnight Commander is being shut down.\nSave modified file %s?"),
1491 act
= edit_query_dialog2 (_("Quit"), msg
, _("&Yes"), _("&No"));
1503 if (!mc_global
.midnight_shutdown
&& !edit_check_newline (&edit
->buffer
))
1505 edit_push_markers (edit
);
1506 edit_set_markers (edit
, 0, 0, 0, 0);
1507 if (!edit_save_cmd (edit
) || mc_global
.midnight_shutdown
)
1508 return mc_global
.midnight_shutdown
;
1513 case 2: /* Cancel quit */
1521 /* --------------------------------------------------------------------------------------------- */
1522 /** save block, returns TRUE on success */
1525 edit_save_block (WEdit
*edit
, const char *filename
, off_t start
, off_t finish
)
1531 vpath
= vfs_path_from_str (filename
);
1532 file
= mc_open (vpath
, O_CREAT
| O_WRONLY
| O_TRUNC
,
1533 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
| O_BINARY
);
1534 vfs_path_free (vpath
, TRUE
);
1538 if (edit
->column_highlight
)
1542 r
= mc_write (file
, VERTICAL_MAGIC
, sizeof (VERTICAL_MAGIC
));
1545 unsigned char *block
, *p
;
1547 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
1550 r
= mc_write (file
, p
, len
);
1564 len
= finish
- start
;
1565 buf
= g_malloc0 (TEMP_BUF_LEN
);
1566 while (start
!= finish
)
1570 end
= MIN (finish
, start
+ TEMP_BUF_LEN
);
1571 for (; i
< end
; i
++)
1572 buf
[i
- start
] = edit_buffer_get_byte (&edit
->buffer
, i
);
1573 len
-= mc_write (file
, (char *) buf
, end
- start
);
1583 /* --------------------------------------------------------------------------------------------- */
1586 edit_paste_from_history (WEdit
*edit
)
1589 edit_error_dialog (_("Error"), _("This function is not implemented"));
1592 /* --------------------------------------------------------------------------------------------- */
1595 edit_copy_to_X_buf_cmd (WEdit
*edit
)
1597 off_t start_mark
, end_mark
;
1599 if (!eval_marks (edit
, &start_mark
, &end_mark
))
1602 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
))
1604 edit_error_dialog (_("Copy to clipboard"), get_sys_error (_("Unable to save to file")));
1607 /* try use external clipboard utility */
1608 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_to_ext_clip", NULL
);
1610 if (edit_options
.drop_selection_on_copy
)
1611 edit_mark_cmd (edit
, TRUE
);
1616 /* --------------------------------------------------------------------------------------------- */
1619 edit_cut_to_X_buf_cmd (WEdit
*edit
)
1621 off_t start_mark
, end_mark
;
1623 if (!eval_marks (edit
, &start_mark
, &end_mark
))
1626 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
))
1628 edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
1631 /* try use external clipboard utility */
1632 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_to_ext_clip", NULL
);
1634 edit_block_delete_cmd (edit
);
1635 edit_mark_cmd (edit
, TRUE
);
1640 /* --------------------------------------------------------------------------------------------- */
1643 edit_paste_from_X_buf_cmd (WEdit
*edit
)
1648 /* try use external clipboard utility */
1649 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_from_ext_clip", NULL
);
1650 tmp
= mc_config_get_full_vpath (EDIT_HOME_CLIP_FILE
);
1651 ret
= (edit_insert_file (edit
, tmp
) >= 0);
1652 vfs_path_free (tmp
, TRUE
);
1657 /* --------------------------------------------------------------------------------------------- */
1659 * Ask user for the line and go to that line.
1660 * Negative numbers mean line from the end (i.e. -1 is the last line).
1664 edit_goto_cmd (WEdit
*edit
)
1666 static gboolean first_run
= TRUE
;
1672 f
= input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE
,
1673 first_run
? NULL
: INPUT_LAST_TEXT
, INPUT_COMPLETE_NONE
);
1674 if (f
== NULL
|| *f
== '\0')
1680 l
= strtol (f
, &error
, 0);
1688 l
= edit
->buffer
.lines
+ l
+ 2;
1690 edit_move_display (edit
, l
- WIDGET (edit
)->rect
.lines
/ 2 - 1);
1691 edit_move_to_line (edit
, l
- 1);
1692 edit
->force
|= REDRAW_COMPLETELY
;
1698 /* --------------------------------------------------------------------------------------------- */
1699 /** Return TRUE on success */
1702 edit_save_block_cmd (WEdit
*edit
)
1704 off_t start_mark
, end_mark
;
1706 gboolean ret
= FALSE
;
1708 if (!eval_marks (edit
, &start_mark
, &end_mark
))
1711 tmp
= mc_config_get_full_path (EDIT_HOME_CLIP_FILE
);
1713 input_expand_dialog (_("Save block"), _("Enter file name:"),
1714 MC_HISTORY_EDIT_SAVE_BLOCK
, tmp
, INPUT_COMPLETE_FILENAMES
);
1716 edit_push_undo_action (edit
, KEY_PRESS
+ edit
->start_display
);
1718 if (exp
!= NULL
&& *exp
!= '\0')
1720 if (edit_save_block (edit
, exp
, start_mark
, end_mark
))
1723 edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
1725 edit
->force
|= REDRAW_COMPLETELY
;
1733 /* --------------------------------------------------------------------------------------------- */
1735 /** returns TRUE on success */
1737 edit_insert_file_cmd (WEdit
*edit
)
1741 gboolean ret
= FALSE
;
1743 tmp
= mc_config_get_full_path (EDIT_HOME_CLIP_FILE
);
1744 exp
= input_expand_dialog (_("Insert file"), _("Enter file name:"),
1745 MC_HISTORY_EDIT_INSERT_FILE
, tmp
, INPUT_COMPLETE_FILENAMES
);
1748 edit_push_undo_action (edit
, KEY_PRESS
+ edit
->start_display
);
1750 if (exp
!= NULL
&& *exp
!= '\0')
1752 vfs_path_t
*exp_vpath
;
1754 exp_vpath
= vfs_path_from_str (exp
);
1755 ret
= (edit_insert_file (edit
, exp_vpath
) >= 0);
1756 vfs_path_free (exp_vpath
, TRUE
);
1759 edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
1764 edit
->force
|= REDRAW_COMPLETELY
;
1768 /* --------------------------------------------------------------------------------------------- */
1769 /** sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
1772 edit_sort_cmd (WEdit
*edit
)
1774 char *exp
, *tmp
, *tmp_edit_block_name
, *tmp_edit_temp_name
;
1775 off_t start_mark
, end_mark
;
1778 if (!eval_marks (edit
, &start_mark
, &end_mark
))
1780 edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
1784 tmp
= mc_config_get_full_path (EDIT_HOME_BLOCK_FILE
);
1785 edit_save_block (edit
, tmp
, start_mark
, end_mark
);
1788 exp
= input_dialog (_("Run sort"),
1789 _("Enter sort options (see sort(1) manpage) separated by whitespace:"),
1790 MC_HISTORY_EDIT_SORT
, INPUT_LAST_TEXT
, INPUT_COMPLETE_NONE
);
1795 tmp_edit_block_name
= mc_config_get_full_path (EDIT_HOME_BLOCK_FILE
);
1796 tmp_edit_temp_name
= mc_config_get_full_path (EDIT_HOME_TEMP_FILE
);
1798 g_strconcat (" sort ", exp
, " ", tmp_edit_block_name
,
1799 " > ", tmp_edit_temp_name
, (char *) NULL
);
1800 g_free (tmp_edit_temp_name
);
1801 g_free (tmp_edit_block_name
);
1808 if (e
== -1 || e
== 127)
1809 edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
1814 sprintf (q
, "%d ", e
);
1815 tmp
= g_strdup_printf (_("Sort returned non-zero: %s"), q
);
1816 edit_error_dialog (_("Sort"), tmp
);
1823 edit
->force
|= REDRAW_COMPLETELY
;
1825 if (!edit_block_delete_cmd (edit
))
1829 vfs_path_t
*tmp_vpath
;
1831 tmp_vpath
= mc_config_get_full_vpath (EDIT_HOME_TEMP_FILE
);
1832 edit_insert_file (edit
, tmp_vpath
);
1833 vfs_path_free (tmp_vpath
, TRUE
);
1839 /* --------------------------------------------------------------------------------------------- */
1841 * Ask user for a command, execute it and paste its output back to the
1846 edit_ext_cmd (WEdit
*edit
)
1848 char *exp
, *tmp
, *tmp_edit_temp_file
;
1852 input_dialog (_("Paste output of external command"),
1853 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD
, INPUT_LAST_TEXT
,
1854 INPUT_COMPLETE_FILENAMES
| INPUT_COMPLETE_VARIABLES
| INPUT_COMPLETE_USERNAMES
1855 | INPUT_COMPLETE_HOSTNAMES
| INPUT_COMPLETE_CD
| INPUT_COMPLETE_COMMANDS
|
1856 INPUT_COMPLETE_SHELL_ESC
);
1861 tmp_edit_temp_file
= mc_config_get_full_path (EDIT_HOME_TEMP_FILE
);
1862 tmp
= g_strconcat (exp
, " > ", tmp_edit_temp_file
, (char *) NULL
);
1863 g_free (tmp_edit_temp_file
);
1870 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
1874 edit
->force
|= REDRAW_COMPLETELY
;
1877 vfs_path_t
*tmp_vpath
;
1879 tmp_vpath
= mc_config_get_full_vpath (EDIT_HOME_TEMP_FILE
);
1880 edit_insert_file (edit
, tmp_vpath
);
1881 vfs_path_free (tmp_vpath
, TRUE
);
1887 /* --------------------------------------------------------------------------------------------- */
1888 /** if block is 1, a block must be highlighted and the shell command
1889 processes it. If block is 0 the shell command is a straight system
1890 command, that just produces some output which is to be inserted */
1893 edit_block_process_cmd (WEdit
*edit
, int macro_number
)
1896 char *macros_fname
= NULL
;
1898 fname
= g_strdup_printf ("%s.%i.sh", EDIT_HOME_MACRO_FILE
, macro_number
);
1899 macros_fname
= g_build_filename (mc_config_get_data_path (), fname
, (char *) NULL
);
1900 edit_user_menu (edit
, macros_fname
, 0);
1902 g_free (macros_fname
);
1903 edit
->force
|= REDRAW_COMPLETELY
;
1906 /* --------------------------------------------------------------------------------------------- */
1909 edit_mail_dialog (WEdit
*edit
)
1911 char *mail_to
, *mail_subject
, *mail_cc
;
1913 quick_widget_t quick_widgets
[] = {
1915 QUICK_LABEL (N_("mail -s <subject> -c <cc> <to>"), NULL
),
1916 QUICK_LABELED_INPUT (N_("To"), input_label_above
,
1917 INPUT_LAST_TEXT
, "mail-dlg-input-3",
1918 &mail_to
, NULL
, FALSE
, FALSE
, INPUT_COMPLETE_USERNAMES
),
1919 QUICK_LABELED_INPUT (N_("Subject"), input_label_above
,
1920 INPUT_LAST_TEXT
, "mail-dlg-input-2",
1921 &mail_subject
, NULL
, FALSE
, FALSE
, INPUT_COMPLETE_NONE
),
1922 QUICK_LABELED_INPUT (N_("Copies to"), input_label_above
,
1923 INPUT_LAST_TEXT
, "mail-dlg-input",
1924 &mail_cc
, NULL
, FALSE
, FALSE
, INPUT_COMPLETE_USERNAMES
),
1925 QUICK_BUTTONS_OK_CANCEL
,
1930 WRect r
= { -1, -1, 0, 50 };
1932 quick_dialog_t qdlg
= {
1933 r
, N_("Mail"), "[Input Line Keys]",
1934 quick_widgets
, NULL
, NULL
1937 if (quick_dialog (&qdlg
) != B_CANCEL
)
1939 pipe_mail (&edit
->buffer
, mail_to
, mail_subject
, mail_cc
);
1941 g_free (mail_subject
);
1946 /* --------------------------------------------------------------------------------------------- */
1950 edit_select_codepage_cmd (WEdit
*edit
)
1952 if (do_select_codepage ())
1953 edit_set_codeset (edit
);
1955 edit
->force
= REDRAW_PAGE
;
1956 widget_draw (WIDGET (edit
));
1960 /* --------------------------------------------------------------------------------------------- */
1963 edit_insert_literal_cmd (WEdit
*edit
)
1965 int char_for_insertion
;
1967 char_for_insertion
= editcmd_dialog_raw_key_query (_("Insert literal"),
1968 _("Press any key:"), FALSE
);
1969 edit_execute_key_command (edit
, -1, ascii_alpha_to_cntrl (char_for_insertion
));
1972 /* --------------------------------------------------------------------------------------------- */
1975 edit_load_forward_cmd (WEdit
*edit
)
1978 && edit_query_dialog2 (_("Warning"),
1979 _("Current text was modified without a file save.\n"
1980 "Continue discards these changes."), _("C&ontinue"),
1983 edit
->force
|= REDRAW_COMPLETELY
;
1987 if (edit_stack_iterator
+ 1 >= MAX_HISTORY_MOVETO
)
1990 if (edit_history_moveto
[edit_stack_iterator
+ 1].line_number
< 1)
1993 edit_stack_iterator
++;
1994 if (edit_history_moveto
[edit_stack_iterator
].file_vpath
!= NULL
)
1995 return edit_reload_line (edit
, &edit_history_moveto
[edit_stack_iterator
]);
2000 /* --------------------------------------------------------------------------------------------- */
2003 edit_load_back_cmd (WEdit
*edit
)
2006 && edit_query_dialog2 (_("Warning"),
2007 _("Current text was modified without a file save.\n"
2008 "Continue discards these changes."), _("C&ontinue"),
2011 edit
->force
|= REDRAW_COMPLETELY
;
2015 /* we are in the bottom of the stack, NO WAY! */
2016 if (edit_stack_iterator
== 0)
2019 edit_stack_iterator
--;
2020 if (edit_history_moveto
[edit_stack_iterator
].file_vpath
!= NULL
)
2021 return edit_reload_line (edit
, &edit_history_moveto
[edit_stack_iterator
]);
2026 /* --------------------------------------------------------------------------------------------- */
2028 /* gets a raw key from the keyboard. Passing cancel = 1 draws
2029 a cancel button thus allowing c-c etc. Alternatively, cancel = 0
2030 will return the next key pressed. ctrl-a (=B_CANCEL), ctrl-g, ctrl-c,
2031 and Esc are cannot returned */
2034 editcmd_dialog_raw_key_query (const char *heading
, const char *query
, gboolean cancel
)
2041 w
= str_term_width1 (heading
) + 6;
2042 wq
= str_term_width1 (query
);
2043 w
= MAX (w
, wq
+ 3 * 2 + 1 + 2);
2046 dlg_create (TRUE
, 0, 0, cancel
? 7 : 5, w
, WPOS_CENTER
| WPOS_TRYUP
, FALSE
, dialog_colors
,
2047 editcmd_dialog_raw_key_query_cb
, NULL
, NULL
, heading
);
2048 g
= GROUP (raw_dlg
);
2049 widget_want_tab (WIDGET (raw_dlg
), TRUE
);
2051 group_add_widget (g
, label_new (y
, 3, query
));
2052 group_add_widget (g
,
2053 input_new (y
++, 3 + wq
+ 1, input_colors
, w
- (6 + wq
+ 1), "", 0,
2054 INPUT_COMPLETE_NONE
));
2057 group_add_widget (g
, hline_new (y
++, -1, -1));
2058 /* Button w/o hotkey to allow use any key as raw or macro one */
2059 group_add_widget_autopos (g
, button_new (y
, 1, B_CANCEL
, NORMAL_BUTTON
, _("Cancel"), NULL
),
2060 WPOS_KEEP_TOP
| WPOS_CENTER_HORZ
, NULL
);
2063 w
= dlg_run (raw_dlg
);
2064 widget_destroy (WIDGET (raw_dlg
));
2066 return (cancel
&& (w
== ESC_CHAR
|| w
== B_CANCEL
)) ? 0 : w
;
2069 /* --------------------------------------------------------------------------------------------- */