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>
48 #include "../src/global.h"
50 #include "../src/tty/tty.h"
51 #include "../src/tty/key.h" /* XCTRL */
53 #include "../src/history.h"
54 #include "../src/widget.h" /* listbox_new() */
55 #include "../src/layout.h" /* clr_scr() */
56 #include "../src/main.h" /* mc_home source_codepage */
57 #include "../src/help.h" /* interactive_display() */
58 #include "../src/wtools.h" /* message() */
59 #include "../src/charsets.h"
60 #include "../src/selcodepage.h"
61 #include "../src/strutil.h" /* utf string functions */
62 #include "../src/mcconfig/mcconfig.h"
63 #include "../src/skin/skin.h" /* mc_skin_color_get */
65 #include "../edit/edit-impl.h"
66 #include "../edit/edit.h"
67 #include "../edit/editlock.h"
68 #include "../src/cmddef.h"
69 #include "../edit/edit-widget.h"
70 #include "../edit/editcmd_dialogs.h"
71 #include "../edit/etags.h"
75 /* search and replace: */
76 int search_create_bookmark
= 0;
77 /* static int search_in_all_charsets = 0; */
79 /* queries on a save */
80 int edit_confirm_save
= 1;
82 static int edit_save_cmd (WEdit
*edit
);
83 static unsigned char *edit_get_block (WEdit
*edit
, long start
,
87 edit_search_cmd_search_create_bookmark(WEdit
* edit
)
89 int found
= 0, books
= 0;
90 int l
= 0, l_last
= -1;
94 search_create_bookmark
= 0;
95 book_mark_flush (edit
, -1);
98 if (!mc_search_run(edit
->search
, (void *) edit
, q
, edit
->last_byte
, &len
))
101 edit
->search_start
= edit
->search
->normal_offset
;
103 l
+= edit_count_lines (edit
, q
, edit
->search
->normal_offset
);
105 book_mark_insert (edit
, l
, BOOK_MARK_FOUND_COLOR
);
109 q
= edit
->search
->normal_offset
+ 1;
113 edit_error_dialog (_ ("Search"), _ (" Search string not found "));
115 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
116 edit_scroll_screen_over_cursor (edit
);
121 edit_search_cmd_callback(const void *user_data
, gsize char_offset
)
123 return edit_get_byte ((WEdit
* )user_data
, (long) char_offset
);
126 void edit_help_cmd (WEdit
* edit
)
128 interactive_display (NULL
, "[Internal File Editor]");
129 edit
->force
|= REDRAW_COMPLETELY
;
133 edit_refresh_cmd (WEdit
* edit
)
138 edit_get_syntax_color (edit
, -1, &color
);
144 #endif /* !HAVE_SLANG */
148 /* If 0 (quick save) then a) create/truncate <filename> file,
149 b) save to <filename>;
150 if 1 (safe save) then a) save to <tempnam>,
151 b) rename <tempnam> to <filename>;
152 if 2 (do backups) then a) save to <tempnam>,
153 b) rename <filename> to <filename.backup_ext>,
154 c) rename <tempnam> to <filename>. */
156 /* returns 0 on error, -1 on abort */
158 edit_save_file (WEdit
*edit
, const char *filename
)
164 gchar
*real_filename
;
165 int this_save_mode
, fd
= -1;
172 if (*filename
!= PATH_SEP
&& edit
->dir
) {
173 real_filename
= concat_dir_and_file (edit
->dir
, filename
);
175 real_filename
= g_strdup(filename
);
178 this_save_mode
= option_save_mode
;
179 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
180 if (!vfs_file_is_local (real_filename
) ||
181 (fd
= mc_open (real_filename
, O_RDONLY
| O_BINARY
)) == -1) {
183 * The file does not exists yet, so no safe save or
184 * backup are necessary.
186 this_save_mode
= EDIT_QUICK_SAVE
;
192 if (this_save_mode
== EDIT_QUICK_SAVE
&&
193 !edit
->skip_detach_prompt
) {
197 rv
= mc_stat (real_filename
, &sb
);
198 if (rv
== 0 && sb
.st_nlink
> 1) {
199 rv
= edit_query_dialog3 (_("Warning"),
200 _(" File has hard-links. Detach before saving? "),
201 _("&Yes"), _("&No"), _("&Cancel"));
204 this_save_mode
= EDIT_SAFE_SAVE
;
207 edit
->skip_detach_prompt
= 1;
210 g_free(real_filename
);
215 /* Prevent overwriting changes from other editor sessions. */
216 if (rv
== 0 && edit
->stat1
.st_mtime
!= 0 && edit
->stat1
.st_mtime
!= sb
.st_mtime
) {
218 /* The default action is "Cancel". */
221 rv
= edit_query_dialog2 (
223 _("The file has been modified in the meantime. Save anyway?"),
227 g_free(real_filename
);
233 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
234 char *savedir
, *saveprefix
;
235 const char *slashpos
;
236 slashpos
= strrchr (real_filename
, PATH_SEP
);
238 savedir
= g_strdup (real_filename
);
239 savedir
[slashpos
- real_filename
+ 1] = '\0';
241 savedir
= g_strdup (".");
242 saveprefix
= concat_dir_and_file (savedir
, "cooledit");
244 fd
= mc_mkstemps (&savename
, saveprefix
, NULL
);
247 g_free(real_filename
);
251 * Close for now because mc_mkstemps use pure open system call
252 * to create temporary file and it needs to be reopened by
253 * VFS-aware mc_open().
257 savename
= g_strdup (real_filename
);
259 mc_chown (savename
, edit
->stat1
.st_uid
, edit
->stat1
.st_gid
);
260 mc_chmod (savename
, edit
->stat1
.st_mode
);
263 mc_open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| O_BINARY
,
264 edit
->stat1
.st_mode
)) == -1)
268 if ((p
= edit_get_write_filter (savename
, real_filename
))) {
272 file
= (FILE *) popen (p
, "w");
275 filelen
= edit_write_stream (edit
, file
);
279 if (pclose (file
) != 0) {
280 tmp
= g_strconcat (_(" Error writing to pipe: "),
281 p
, " ", (char *) NULL
);
282 edit_error_dialog (_("Error"), tmp
);
289 tmp
= g_strconcat (_(" Cannot open pipe for writing: "),
290 p
, " ", (char *) NULL
);
292 edit_error_dialog (_("Error"),
293 get_sys_error (tmp
));
299 } else if (edit
->lb
== LB_ASIS
) { /* do not change line breaks */
302 filelen
= edit
->last_byte
;
303 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
304 if (mc_write (fd
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
)
312 (fd
, (char *) edit
->buffers1
[buf
],
313 edit
->curs1
& M_EDIT_BUF_SIZE
) !=
314 (edit
->curs1
& M_EDIT_BUF_SIZE
)) {
316 } else if (edit
->curs2
) {
318 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
321 (char *) edit
->buffers2
[buf
] + EDIT_BUF_SIZE
-
322 (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1,
323 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) !=
324 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) {
329 (fd
, (char *) edit
->buffers2
[buf
],
330 EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
341 /* Update the file information, especially the mtime. */
342 if (mc_stat (savename
, &edit
->stat1
) == -1)
344 } else { /* change line breaks */
349 file
= (FILE *) fopen (savename
, "w");
352 filelen
= edit_write_stream (edit
, file
);
357 msg
= g_strdup_printf (_(" Cannot open file for writing: %s "), savename
);
358 edit_error_dialog (_("Error"), msg
);
364 if (filelen
!= edit
->last_byte
)
367 if (this_save_mode
== EDIT_DO_BACKUP
) {
368 assert (option_backup_ext
!= NULL
);
369 tmp
= g_strconcat (real_filename
, option_backup_ext
,(char *) NULL
);
370 if (mc_rename (real_filename
, tmp
) == -1){
376 if (this_save_mode
!= EDIT_QUICK_SAVE
)
377 if (mc_rename (savename
, real_filename
) == -1)
380 g_free(real_filename
);
383 /* FIXME: Is this safe ?
384 * if (this_save_mode != EDIT_QUICK_SAVE)
385 * mc_unlink (savename);
387 g_free(real_filename
);
393 menu_save_mode_cmd (void)
396 const int DLG_X
= 38;
397 const int DLG_Y
= 13;
405 N_("&Do backups with following extension:")
408 QuickWidget widgets
[] =
411 QUICK_BUTTON (18, DLG_X
, DLG_Y
- 3, DLG_Y
, N_("&Cancel"), B_CANCEL
, NULL
),
413 QUICK_BUTTON ( 6, DLG_X
, DLG_Y
- 3, DLG_Y
, N_("&OK"), B_ENTER
, NULL
),
415 QUICK_CHECKBOX ( 4, DLG_X
, 8, DLG_Y
, N_("Check &POSIX new line"), &option_check_nl_at_eof
),
417 QUICK_INPUT ( 8, DLG_X
, 6, DLG_Y
, option_backup_ext
, 9, 0, "edit-backup-ext", &str_result
),
419 QUICK_RADIO ( 4, DLG_X
, 3, DLG_Y
, 3, str
, &option_save_mode
),
425 DLG_X
, DLG_Y
, -1, -1, N_(" Edit Save Mode "),
426 "[Edit Save Mode]", widgets
, FALSE
431 size_t w0
, w1
, b_len
, w3
;
433 assert (option_backup_ext
!= NULL
);
435 /* OK/Cancel buttons */
436 w0
= str_term_width1 (_(widgets
[0].u
.button
.text
)) + 3;
437 w1
= str_term_width1 (_(widgets
[1].u
.button
.text
)) + 5; /* default button */
440 maxlen
= max (b_len
, (size_t) str_term_width1 (_(dialog
.title
)) + 2);
443 for (i
= 0; i
< 3; i
++) {
447 w3
= max (w3
, (size_t) str_term_width1 (str
[i
]));
450 maxlen
= max (maxlen
, w3
+ 4);
452 dialog
.xlen
= min ((size_t) COLS
, maxlen
+ 8);
454 widgets
[3].u
.input
.len
= w3
;
455 widgets
[1].relative_x
= (dialog
.xlen
- b_len
)/2;
456 widgets
[0].relative_x
= widgets
[1].relative_x
+ w0
+ 2;
458 for (i
= 0; i
< sizeof (widgets
)/sizeof (widgets
[0]); i
++)
459 widgets
[i
].x_divisions
= dialog
.xlen
;
461 if (quick_dialog (&dialog
) != B_CANCEL
) {
462 g_free (option_backup_ext
);
463 option_backup_ext
= str_result
;
468 edit_set_filename (WEdit
*edit
, const char *f
)
470 g_free (edit
->filename
);
473 edit
->filename
= g_strdup (f
);
474 if (edit
->dir
== NULL
&& *f
!= PATH_SEP
)
476 edit
->dir
= g_strdup (vfs_get_current_dir ());
478 edit
->dir
= g_get_current_dir ();
483 edit_check_newline (WEdit
*edit
)
485 return !(option_check_nl_at_eof
&& edit
->last_byte
> 0
486 && edit_get_byte (edit
, edit
->last_byte
- 1) != '\n'
487 && edit_query_dialog2 (_("Warning"),
488 _("The file you are saving is not finished with a newline"),
489 _("C&ontinue"), _("&Cancel")));
493 edit_get_save_file_as (WEdit
*edit
)
496 #define DLG_HEIGHT 14
498 static LineBreaks cur_lb
= LB_ASIS
;
500 char *filename
= edit
->filename
;
502 const char *lb_names
[LB_NAMES
] =
504 N_("&Do not change"),
505 N_("&Unix format (LF)"),
506 N_("&Windows/DOS format (CR LF)"),
507 N_("&Macintosh format (CR)")
510 QuickWidget quick_widgets
[] =
512 QUICK_BUTTON (6, 10, DLG_HEIGHT
- 3, DLG_HEIGHT
, N_("&Cancel"), B_CANCEL
, NULL
),
513 QUICK_BUTTON (2, 10, DLG_HEIGHT
- 3, DLG_HEIGHT
, N_("&OK"), B_ENTER
, NULL
),
514 QUICK_RADIO (5, DLG_WIDTH
, DLG_HEIGHT
- 8, DLG_HEIGHT
, LB_NAMES
, lb_names
, (int *) &cur_lb
),
515 QUICK_LABEL (3, DLG_WIDTH
, DLG_HEIGHT
- 9, DLG_HEIGHT
, N_("Change line breaks to:")),
516 QUICK_INPUT (3, DLG_WIDTH
, DLG_HEIGHT
- 11, DLG_HEIGHT
, filename
, DLG_WIDTH
- 6, 0, "save-as", &filename
),
517 QUICK_LABEL (2, DLG_WIDTH
, DLG_HEIGHT
- 12, DLG_HEIGHT
, N_(" Enter file name: ")),
521 QuickDialog Quick_options
=
523 DLG_WIDTH
, DLG_HEIGHT
, -1, -1,
524 N_(" Save As "), "[Save File As]",
528 if (quick_dialog (&Quick_options
) != B_CANCEL
) {
539 /* Here we want to warn the users of overwriting an existing file,
540 but only if they have made a change to the filename */
541 /* returns 1 on success */
543 edit_save_as_cmd (WEdit
*edit
)
545 /* This heads the 'Save As' dialog box */
548 int different_filename
= 0;
550 if (!edit_check_newline (edit
))
553 exp
= edit_get_save_file_as (edit
);
554 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
559 edit
->force
|= REDRAW_COMPLETELY
;
563 if (strcmp (edit
->filename
, exp
)) {
565 different_filename
= 1;
566 if ((file
= mc_open (exp
, O_RDONLY
| O_BINARY
)) != -1) {
567 /* the file exists */
569 /* Overwrite the current file or cancel the operation */
570 if (edit_query_dialog2
572 _(" A file already exists with this name. "),
573 _("&Overwrite"), _("&Cancel"))) {
574 edit
->force
|= REDRAW_COMPLETELY
;
579 edit
->stat1
.st_mode
|= S_IWUSR
;
581 save_lock
= edit_lock_file (exp
);
583 /* filenames equal, check if already locked */
584 if (!edit
->locked
&& !edit
->delete_file
)
585 save_lock
= edit_lock_file (exp
);
588 if (different_filename
)
591 * Allow user to write into saved (under another name) file
592 * even if original file had r/o user permissions.
594 edit
->stat1
.st_mode
|= S_IWRITE
;
597 rv
= edit_save_file (edit
, exp
);
600 /* Succesful, so unlock both files */
601 if (different_filename
) {
603 edit_unlock_file (exp
);
605 edit
->locked
= edit_unlock_file (edit
->filename
);
607 if (edit
->locked
|| save_lock
)
608 edit
->locked
= edit_unlock_file (edit
->filename
);
611 edit_set_filename (edit
, exp
);
612 if (edit
->lb
!= LB_ASIS
)
613 edit_reload(edit
, exp
);
616 edit
->delete_file
= 0;
617 if (different_filename
)
618 edit_load_syntax (edit
, NULL
, option_syntax_type
);
619 edit
->force
|= REDRAW_COMPLETELY
;
622 edit_error_dialog (_(" Save As "),
624 (" Cannot save file. ")));
627 /* Failed, so maintain modify (not save) lock */
629 edit_unlock_file (exp
);
631 edit
->force
|= REDRAW_COMPLETELY
;
636 edit
->force
|= REDRAW_COMPLETELY
;
640 /* {{{ Macro stuff starts here */
642 /* creates a macro file if it doesn't exist */
643 static FILE *edit_open_macro_file (const char *r
)
648 filename
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
649 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1){
654 fd
= fopen (filename
, r
);
659 #define MAX_MACROS 1024
660 static int saved_macro
[MAX_MACROS
+ 1];
661 static int saved_macros_loaded
= 0;
664 This is just to stop the macro file be loaded over and over for keys
665 that aren't defined to anything. On slow systems this could be annoying.
671 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
672 if (saved_macro
[i
] == k
)
677 /* returns 1 on error */
679 edit_delete_macro (WEdit
* edit
, int k
)
682 struct macro macro
[MAX_MACRO_LENGTH
];
688 if (saved_macros_loaded
)
689 if ((j
= macro_exists (k
)) < 0)
691 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
692 g
= fopen (tmp
, "w");
695 edit_error_dialog (_(" Delete macro "),
696 get_sys_error (_(" Cannot open temp file ")));
699 f
= edit_open_macro_file ("r");
701 edit_error_dialog (_(" Delete macro "),
702 get_sys_error (_(" Cannot open macro file ")));
707 n
= fscanf (f
, ("key '%d 0': "), &s
);
711 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
715 fprintf (g
, ("key '%d 0': "), s
);
716 for (i
= 0; i
< n
; i
++)
717 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
723 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
724 tmp2
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
725 if (rename ( tmp
, tmp2
) == -1) {
726 edit_error_dialog (_(" Delete macro "),
727 get_sys_error (_(" Cannot overwrite macro file ")));
735 if (saved_macros_loaded
)
736 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
740 /* returns 0 on error */
741 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
746 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
747 s
= editcmd_dialog_raw_key_query (_(" Save macro "),
748 _(" Press the macro's new hotkey: "), 1);
749 edit
->force
|= REDRAW_COMPLETELY
;
751 if (edit_delete_macro (edit
, s
))
753 f
= edit_open_macro_file ("a+");
755 fprintf (f
, ("key '%d 0': "), s
);
756 for (i
= 0; i
< n
; i
++)
757 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
760 if (saved_macros_loaded
) {
761 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
766 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Cannot open macro file ")));
771 void edit_delete_macro_cmd (WEdit
* edit
)
775 command
= editcmd_dialog_raw_key_query (_ (" Delete macro "),
776 _ (" Press macro hotkey: "), 1);
781 edit_delete_macro (edit
, command
);
784 /* return 0 on error */
785 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
788 int s
, i
= 0, found
= 0;
792 if (saved_macros_loaded
)
793 if (macro_exists (k
) < 0)
796 if ((f
= edit_open_macro_file ("r"))) {
800 u
= fscanf (f
, ("key '%d 0': "), &s
);
803 if (!saved_macros_loaded
)
804 saved_macro
[i
++] = s
;
807 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
810 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
815 } while (!found
|| !saved_macros_loaded
);
816 if (!saved_macros_loaded
) {
818 saved_macros_loaded
= 1;
823 edit_error_dialog (_(" Load macro "),
824 get_sys_error (_(" Cannot open macro file ")));
828 /* }}} Macro stuff starts here */
830 /* returns 1 on success */
831 int edit_save_confirm_cmd (WEdit
* edit
)
835 if (!edit_check_newline (edit
))
838 if (edit_confirm_save
) {
839 f
= g_strconcat (_(" Confirm save file? : "), edit
->filename
, " ", NULL
);
840 if (edit_query_dialog2 (_(" Save file "), f
, _("&Save"), _("&Cancel"))){
846 return edit_save_cmd (edit
);
850 /* returns 1 on success */
852 edit_save_cmd (WEdit
*edit
)
854 int res
, save_lock
= 0;
856 if (!edit
->locked
&& !edit
->delete_file
)
857 save_lock
= edit_lock_file (edit
->filename
);
858 res
= edit_save_file (edit
, edit
->filename
);
860 /* Maintain modify (not save) lock on failure */
861 if ((res
> 0 && edit
->locked
) || save_lock
)
862 edit
->locked
= edit_unlock_file (edit
->filename
);
864 /* On failure try 'save as', it does locking on its own */
866 return edit_save_as_cmd (edit
);
867 edit
->force
|= REDRAW_COMPLETELY
;
869 edit
->delete_file
= 0;
877 /* returns 1 on success */
878 int edit_new_cmd (WEdit
* edit
)
880 if (edit
->modified
) {
881 if (edit_query_dialog2 (_ ("Warning"), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("C&ontinue"), _ ("&Cancel"))) {
882 edit
->force
|= REDRAW_COMPLETELY
;
886 edit
->force
|= REDRAW_COMPLETELY
;
888 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
891 /* returns 1 on error */
893 edit_load_file_from_filename (WEdit
* edit
, char *exp
)
895 int prev_locked
= edit
->locked
;
896 char *prev_filename
= g_strdup (edit
->filename
);
898 if (!edit_reload (edit
, exp
)) {
899 g_free (prev_filename
);
904 edit_unlock_file (prev_filename
);
905 g_free (prev_filename
);
910 edit_load_syntax_file (WEdit
* edit
)
915 if (geteuid () == 0) {
916 dir
= query_dialog (_("Syntax file edit"),
917 _(" Which syntax file you want to edit? "), D_NORMAL
, 2,
918 _("&User"), _("&System Wide"));
921 extdir
= concat_dir_and_file (mc_home
, "syntax" PATH_SEP_STR
"Syntax");
922 if (!exist_file(extdir
)) {
924 extdir
= concat_dir_and_file (mc_home_alt
, "syntax" PATH_SEP_STR
"Syntax");
930 buffer
= concat_dir_and_file (home_dir
, EDIT_SYNTAX_FILE
);
931 check_for_default (extdir
, buffer
);
932 edit_load_file_from_filename (edit
, buffer
);
935 edit_load_file_from_filename (edit
, extdir
);
941 edit_load_menu_file (WEdit
* edit
)
949 _(" Which menu file do you want to edit? "), D_NORMAL
,
950 geteuid() ? 2 : 3, _("&Local"), _("&User"), _("&System Wide")
953 menufile
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
955 if (!exist_file (menufile
)) {
957 menufile
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
962 buffer
= g_strdup (EDIT_LOCAL_MENU
);
963 check_for_default (menufile
, buffer
);
964 chmod (buffer
, 0600);
968 buffer
= concat_dir_and_file (home_dir
, EDIT_HOME_MENU
);
969 check_for_default (menufile
, buffer
);
973 buffer
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
974 if (!exist_file (buffer
)) {
976 buffer
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
985 edit_load_file_from_filename (edit
, buffer
);
992 edit_load_cmd (WEdit
*edit
, edit_current_file_t what
)
997 && (edit_query_dialog2
999 _(" Current text was modified without a file save. \n"
1000 " Continue discards these changes. "),
1001 _("C&ontinue"), _("&Cancel")) == 1)) {
1002 edit
->force
|= REDRAW_COMPLETELY
;
1007 case EDIT_FILE_COMMON
:
1008 exp
= input_expand_dialog (_(" Load "), _(" Enter file name: "),
1009 MC_HISTORY_EDIT_LOAD
, edit
->filename
);
1013 edit_load_file_from_filename (edit
, exp
);
1018 case EDIT_FILE_SYNTAX
:
1019 edit_load_syntax_file (edit
);
1022 case EDIT_FILE_MENU
:
1023 edit_load_menu_file (edit
);
1030 edit
->force
|= REDRAW_COMPLETELY
;
1035 if mark2 is -1 then marking is from mark1 to the cursor.
1036 Otherwise its between the markers. This handles this.
1037 Returns 1 if no text is marked.
1039 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
1041 if (edit
->mark1
!= edit
->mark2
) {
1042 if (edit
->mark2
>= 0) {
1043 *start_mark
= min (edit
->mark1
, edit
->mark2
);
1044 *end_mark
= max (edit
->mark1
, edit
->mark2
);
1047 *start_mark
= min (edit
->mark1
, edit
->curs1
);
1048 *end_mark
= max (edit
->mark1
, edit
->curs1
);
1049 if (column_highlighting
) {
1050 diff
= (*start_mark
- edit_bol (edit
, *start_mark
)) -
1051 (*end_mark
- edit_bol (edit
, *end_mark
));
1053 *start_mark
-= diff
;
1057 edit
->column2
= edit
->curs_col
+ edit
->over_col
;
1061 *start_mark
= *end_mark
= 0;
1062 edit
->column2
= edit
->column1
= 0;
1067 #define space_width 1
1070 edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
)
1074 cursor
= edit
->curs1
;
1075 col
= edit_get_col (edit
);
1076 for (i
= 0; i
< size
; i
++) {
1077 if (data
[i
] == '\n') { /* fill in and move to next line */
1080 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
1081 l
= width
- (edit_get_col (edit
) - col
);
1083 edit_insert (edit
, ' ');
1087 for (p
= edit
->curs1
;; p
++) {
1088 if (p
== edit
->last_byte
) {
1089 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
1090 edit_insert_ahead (edit
, '\n');
1094 if (edit_get_byte (edit
, p
) == '\n') {
1099 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1100 l
= col
- edit_get_col (edit
);
1101 while (l
>= space_width
) {
1102 edit_insert (edit
, ' ');
1107 edit_insert (edit
, data
[i
]);
1109 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1112 #define TEMP_BUF_LEN 1024
1115 edit_insert_column_of_text_from_file (WEdit
* edit
, int file
)
1119 int blocklen
= -1, width
;
1120 unsigned char *data
;
1121 cursor
= edit
->curs1
;
1122 col
= edit_get_col (edit
);
1123 data
= g_malloc (TEMP_BUF_LEN
);
1124 while ((blocklen
= mc_read (file
, (char *) data
, TEMP_BUF_LEN
)) > 0) {
1125 for (width
= 0; width
< blocklen
; width
++) {
1126 if (data
[width
] == '\n')
1129 for (i
= 0; i
< blocklen
; i
++) {
1130 if (data
[i
] == '\n') { /* fill in and move to next line */
1133 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
1134 l
= width
- (edit_get_col (edit
) - col
);
1136 edit_insert (edit
, ' ');
1140 for (p
= edit
->curs1
;; p
++) {
1141 if (p
== edit
->last_byte
) {
1142 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
1143 edit_insert_ahead (edit
, '\n');
1147 if (edit_get_byte (edit
, p
) == '\n') {
1152 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1153 l
= col
- edit_get_col (edit
);
1154 while (l
>= space_width
) {
1155 edit_insert (edit
, ' ');
1160 edit_insert (edit
, data
[i
]);
1163 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1165 edit
->force
|= REDRAW_PAGE
;
1170 edit_block_copy_cmd (WEdit
*edit
)
1172 long start_mark
, end_mark
, current
= edit
->curs1
;
1174 unsigned char *copy_buf
;
1176 edit_update_curs_col (edit
);
1177 if (eval_marks (edit
, &start_mark
, &end_mark
))
1180 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1182 /* all that gets pushed are deletes hence little space is used on the stack */
1184 edit_push_markers (edit
);
1186 if (column_highlighting
) {
1187 edit_insert_column_of_text (edit
, copy_buf
, size
,
1188 abs (edit
->column2
- edit
->column1
));
1191 edit_insert_ahead (edit
, copy_buf
[size
]);
1195 edit_scroll_screen_over_cursor (edit
);
1197 if (column_highlighting
) {
1198 edit_set_markers (edit
, 0, 0, 0, 0);
1199 edit_push_action (edit
, COLUMN_ON
);
1200 column_highlighting
= 0;
1201 } else if (start_mark
< current
&& end_mark
> current
)
1202 edit_set_markers (edit
, start_mark
,
1203 end_mark
+ end_mark
- start_mark
, 0, 0);
1205 edit
->force
|= REDRAW_PAGE
;
1210 edit_block_move_cmd (WEdit
*edit
)
1214 unsigned char *copy_buf
;
1215 long start_mark
, end_mark
;
1219 if (eval_marks (edit
, &start_mark
, &end_mark
))
1221 if (column_highlighting
) {
1222 edit_update_curs_col (edit
);
1224 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1225 if ((x
> edit
->column1
&& x
< edit
->column2
)
1226 || (x
> edit
->column2
&& x
< edit
->column1
))
1228 } else if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1231 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1232 if (edit_query_dialog2
1235 (" Block is large, you may not be able to undo this action. "),
1236 _("C&ontinue"), _("&Cancel")))
1239 edit_push_markers (edit
);
1240 current
= edit
->curs1
;
1241 if (column_highlighting
) {
1242 int size
, c1
, c2
, line
;
1243 line
= edit
->curs_line
;
1244 if (edit
->mark2
< 0)
1245 edit_mark_cmd (edit
, 0);
1246 c1
= min (edit
->column1
, edit
->column2
);
1247 c2
= max (edit
->column1
, edit
->column2
);
1248 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1250 edit_block_delete_cmd (edit
);
1253 edit_move_to_line (edit
, line
);
1254 edit_cursor_move (edit
,
1255 edit_move_forward3 (edit
,
1256 edit_bol (edit
, edit
->curs1
),
1257 x
, 0) - edit
->curs1
);
1258 edit_insert_column_of_text (edit
, copy_buf
, size
, c2
- c1
);
1260 line
= edit
->curs_line
;
1261 edit_update_curs_col (edit
);
1263 edit_block_delete_cmd (edit
);
1264 edit_move_to_line (edit
, line
);
1265 edit_cursor_move (edit
,
1266 edit_move_forward3 (edit
,
1269 x
, 0) - edit
->curs1
);
1271 edit_set_markers (edit
, 0, 0, 0, 0);
1272 edit_push_action (edit
, COLUMN_ON
);
1273 column_highlighting
= 0;
1275 copy_buf
= g_malloc (end_mark
- start_mark
);
1276 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1277 edit_scroll_screen_over_cursor (edit
);
1279 while (count
< end_mark
) {
1280 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
, 1);
1283 edit_scroll_screen_over_cursor (edit
);
1284 edit_cursor_move (edit
,
1285 current
- edit
->curs1
-
1286 (((current
- edit
->curs1
) >
1287 0) ? end_mark
- start_mark
: 0));
1288 edit_scroll_screen_over_cursor (edit
);
1289 while (count
-- > start_mark
)
1290 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1291 edit_set_markers (edit
, edit
->curs1
,
1292 edit
->curs1
+ end_mark
- start_mark
, 0, 0);
1294 edit_scroll_screen_over_cursor (edit
);
1296 edit
->force
|= REDRAW_PAGE
;
1300 edit_delete_column_of_text (WEdit
* edit
)
1302 long p
, q
, r
, m1
, m2
;
1306 eval_marks (edit
, &m1
, &m2
);
1307 n
= edit_move_forward (edit
, m1
, 0, m2
) + 1;
1308 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
1309 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
1311 b
= max(min (c
, d
), min (edit
->column1
, edit
->column2
));
1312 c
= max (c
, d
+ edit
->over_col
);
1315 r
= edit_bol (edit
, edit
->curs1
);
1316 p
= edit_move_forward3 (edit
, r
, b
, 0);
1317 q
= edit_move_forward3 (edit
, r
, c
, 0);
1322 edit_cursor_move (edit
, p
- edit
->curs1
);
1323 while (q
> p
) { /* delete line between margins */
1324 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
1325 edit_delete (edit
, 1);
1328 if (n
) /* move to next line except on the last delete */
1329 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
1333 /* if success return 0 */
1335 edit_block_delete (WEdit
*edit
)
1338 long start_mark
, end_mark
;
1339 if (eval_marks (edit
, &start_mark
, &end_mark
))
1341 if (column_highlighting
&& edit
->mark2
< 0)
1342 edit_mark_cmd (edit
, 0);
1343 if ((end_mark
- start_mark
) > option_max_undo
/ 2) {
1344 /* Warning message with a query to continue or cancel the operation */
1345 if (edit_query_dialog2
1348 (" Block is large, you may not be able to undo this action. "),
1349 _("C&ontinue"), _("&Cancel"))) {
1353 edit_push_markers (edit
);
1354 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1355 edit_scroll_screen_over_cursor (edit
);
1357 if (start_mark
< end_mark
) {
1358 if (column_highlighting
) {
1359 if (edit
->mark2
< 0)
1360 edit_mark_cmd (edit
, 0);
1361 edit_delete_column_of_text (edit
);
1363 while (count
< end_mark
) {
1364 edit_delete (edit
, 1);
1369 edit_set_markers (edit
, 0, 0, 0, 0);
1370 edit
->force
|= REDRAW_PAGE
;
1374 /* returns 1 if canceelled by user */
1375 int edit_block_delete_cmd (WEdit
* edit
)
1377 long start_mark
, end_mark
;
1378 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1379 edit_delete_line (edit
);
1382 return edit_block_delete (edit
);
1385 #define INPUT_INDEX 9
1388 editcmd_find (WEdit
*edit
, gsize
*len
)
1390 off_t search_start
= edit
->search_start
;
1392 long start_mark
= 0;
1393 long end_mark
= edit
->last_byte
;
1396 if (edit
->only_in_selection
) {
1397 mark_res
= eval_marks(edit
, &start_mark
, &end_mark
);
1398 if (mark_res
!= 0) {
1399 edit
->search
->error
= MC_SEARCH_E_NOTFOUND
;
1400 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1403 if (edit
->replace_backwards
) {
1404 if (search_start
> end_mark
|| search_start
<= start_mark
) {
1405 search_start
= end_mark
;
1408 if (search_start
< start_mark
|| search_start
>= end_mark
) {
1409 search_start
= start_mark
;
1413 if (edit
->replace_backwards
)
1414 end_mark
= max(1, edit
->curs1
) - 1;
1416 if (edit
->replace_backwards
) {
1417 search_end
= end_mark
;
1418 while ((int) search_start
>= start_mark
) {
1419 if (search_end
> search_start
+ edit
->search
->original_len
1420 && mc_search_is_fixed_search_str(edit
->search
)) {
1421 search_end
= search_start
+ edit
->search
->original_len
;
1423 if (mc_search_run(edit
->search
, (void *) edit
, search_start
, search_end
, len
)
1424 && edit
->search
->normal_offset
== search_start
) {
1429 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1431 return mc_search_run(edit
->search
, (void *) edit
, search_start
, end_mark
, len
);
1437 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1438 (and the above) routines to work properly - paul */
1440 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1443 edit_replace_cmd__conv_to_display(char *str
)
1447 tmp
= str_convert_to_display (str
);
1449 if (tmp
&& tmp
->len
){
1453 g_string_free (tmp
, FALSE
);
1456 return g_strdup(str
);
1461 edit_replace_cmd__conv_to_input(char *str
)
1465 tmp
= str_convert_to_input (str
);
1467 if (tmp
&& tmp
->len
){
1471 g_string_free (tmp
, FALSE
);
1474 return g_strdup(str
);
1477 /* call with edit = 0 before shutdown to close memory leaks */
1479 edit_replace_cmd (WEdit
*edit
, int again
)
1481 /* 1 = search string, 2 = replace with */
1482 static char *saved1
= NULL
; /* saved default[123] */
1483 static char *saved2
= NULL
;
1484 char *input1
= NULL
; /* user input from the dialog */
1485 char *input2
= NULL
;
1487 long times_replaced
= 0, last_search
;
1488 gboolean once_found
= FALSE
;
1491 g_free (saved1
), saved1
= NULL
;
1492 g_free (saved2
), saved2
= NULL
;
1496 last_search
= edit
->last_byte
;
1498 edit
->force
|= REDRAW_COMPLETELY
;
1500 if (again
&& !saved1
&& !saved2
)
1504 input1
= g_strdup (saved1
? saved1
: "");
1505 input2
= g_strdup (saved2
? saved2
: "");
1507 char *disp1
= edit_replace_cmd__conv_to_display(g_strdup (saved1
? saved1
: ""));
1508 char *disp2
= edit_replace_cmd__conv_to_display(g_strdup (saved2
? saved2
: ""));
1510 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1512 editcmd_dialog_replace_show (edit
, disp1
, disp2
, &input1
, &input2
);
1517 if (input1
== NULL
|| *input1
== '\0') {
1518 edit
->force
= REDRAW_COMPLETELY
;
1522 input1
= edit_replace_cmd__conv_to_input(input1
);
1523 input2
= edit_replace_cmd__conv_to_input(input2
);
1525 g_free (saved1
), saved1
= g_strdup (input1
);
1526 g_free (saved2
), saved2
= g_strdup (input2
);
1529 mc_search_free(edit
->search
);
1530 edit
->search
= NULL
;
1534 if (!edit
->search
) {
1535 edit
->search
= mc_search_new(input1
, -1);
1536 if (edit
->search
== NULL
) {
1537 edit
->search_start
= edit
->curs1
;
1540 edit
->search
->search_type
= edit
->search_type
;
1541 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1542 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1543 edit
->search
->whole_words
= edit
->whole_words
;
1544 edit
->search
->search_fn
= edit_search_cmd_callback
;
1547 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1
1548 && edit
->replace_backwards
)
1549 edit
->search_start
--;
1551 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1
1552 && !edit
->replace_backwards
)
1553 edit
->search_start
++;
1559 if (! editcmd_find(edit
, &len
)) {
1560 if (!(edit
->search
->error
== MC_SEARCH_E_OK
||
1561 (once_found
&& edit
->search
->error
== MC_SEARCH_E_NOTFOUND
))) {
1562 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1567 new_start
= edit
->search
->normal_offset
;
1569 edit
->search_start
= new_start
= edit
->search
->normal_offset
;
1570 /*returns negative on not found or error in pattern */
1572 if (edit
->search_start
>= 0) {
1575 edit
->found_start
= edit
->search_start
;
1576 i
= edit
->found_len
= len
;
1578 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1579 edit_scroll_screen_over_cursor (edit
);
1583 if (edit
->replace_mode
== 0) {
1585 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
1587 edit_scroll_downward (edit
, l
);
1589 edit_scroll_upward (edit
, -l
);
1591 edit_scroll_screen_over_cursor (edit
);
1592 edit
->force
|= REDRAW_PAGE
;
1593 edit_render_keypress (edit
);
1595 /*so that undo stops at each query */
1596 edit_push_key_press (edit
);
1597 /* and prompt 2/3 down */
1598 switch (editcmd_dialog_replace_prompt_show (edit
, input1
, input2
, -1, -1)) {
1602 case B_SKIP_REPLACE
:
1606 edit
->replace_mode
=1;
1610 edit
->replace_mode
= -1;
1614 if (replace_yes
) { /* delete then insert new */
1615 GString
*repl_str
, *tmp_str
;
1616 tmp_str
= g_string_new(input2
);
1618 repl_str
= mc_search_prepare_replace_str (edit
->search
, tmp_str
);
1619 g_string_free(tmp_str
, TRUE
);
1620 if (edit
->search
->error
!= MC_SEARCH_E_OK
)
1622 edit_error_dialog (_ ("Replace"), edit
->search
->error_str
);
1627 edit_delete (edit
, 1);
1629 while (++i
< repl_str
->len
)
1630 edit_insert (edit
, repl_str
->str
[i
]);
1632 g_string_free(repl_str
, TRUE
);
1633 edit
->found_len
= i
;
1635 /* so that we don't find the same string again */
1636 if (edit
->replace_backwards
) {
1637 last_search
= edit
->search_start
;
1638 edit
->search_start
--;
1640 edit
->search_start
+= i
;
1641 last_search
= edit
->last_byte
;
1643 edit_scroll_screen_over_cursor (edit
);
1645 const char *msg
= _(" Replace ");
1646 /* try and find from right here for next search */
1647 edit
->search_start
= edit
->curs1
;
1648 edit_update_curs_col (edit
);
1650 edit
->force
|= REDRAW_PAGE
;
1651 edit_render_keypress (edit
);
1652 if (times_replaced
) {
1653 message (D_NORMAL
, msg
, _(" %ld replacements made. "),
1656 query_dialog (msg
, _(" Search string not found "),
1657 D_NORMAL
, 1, _("&OK"));
1658 edit
->replace_mode
= -1;
1660 } while (edit
->replace_mode
>= 0);
1662 edit
->force
= REDRAW_COMPLETELY
;
1663 edit_scroll_screen_over_cursor (edit
);
1670 void edit_search_cmd (WEdit
* edit
, int again
)
1672 char *search_string
= NULL
, *search_string_dup
= NULL
;
1679 if (edit
->search
!= NULL
) {
1680 search_string
= g_strndup(edit
->search
->original
, edit
->search
->original_len
);
1681 search_string_dup
= search_string
;
1684 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
1685 if (history
!= NULL
&& history
->data
!= NULL
) {
1686 search_string_dup
= search_string
= (char *) g_strdup(history
->data
);
1687 history
= g_list_first (history
);
1688 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
1689 g_list_free (history
);
1691 edit
->search_start
= edit
->curs1
;
1697 if (search_string
&& *search_string
) {
1698 tmp
= str_convert_to_display (search_string
);
1700 g_free(search_string_dup
);
1701 search_string_dup
= NULL
;
1703 if (tmp
&& tmp
->len
)
1704 search_string
= search_string_dup
= tmp
->str
;
1705 g_string_free (tmp
, FALSE
);
1707 #endif /* HAVE_CHARSET */
1708 editcmd_dialog_search_show (edit
, &search_string
);
1710 if (search_string
&& *search_string
) {
1711 tmp
= str_convert_to_input (search_string
);
1712 if (tmp
&& tmp
->len
)
1713 search_string
= tmp
->str
;
1715 g_string_free (tmp
, FALSE
);
1717 if (search_string_dup
)
1718 g_free(search_string_dup
);
1720 #endif /* HAVE_CHARSET */
1722 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1724 if (!search_string
) {
1725 edit
->force
|= REDRAW_COMPLETELY
;
1726 edit_scroll_screen_over_cursor (edit
);
1731 mc_search_free(edit
->search
);
1732 edit
->search
= NULL
;
1736 if (!edit
->search
) {
1737 edit
->search
= mc_search_new(search_string
, -1);
1738 if (edit
->search
== NULL
) {
1739 edit
->search_start
= edit
->curs1
;
1742 edit
->search
->search_type
= edit
->search_type
;
1743 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1744 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1745 edit
->search
->whole_words
= edit
->whole_words
;
1746 edit
->search
->search_fn
= edit_search_cmd_callback
;
1749 if (search_create_bookmark
) {
1750 edit_search_cmd_search_create_bookmark(edit
);
1752 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && edit
->replace_backwards
)
1753 edit
->search_start
--;
1755 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !edit
->replace_backwards
)
1756 edit
->search_start
++;
1759 if (editcmd_find(edit
, &len
)) {
1760 edit
->found_start
= edit
->search_start
= edit
->search
->normal_offset
;
1761 edit
->found_len
= len
;
1763 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1764 edit_scroll_screen_over_cursor (edit
);
1765 if (edit
->replace_backwards
)
1766 edit
->search_start
--;
1768 edit
->search_start
++;
1770 edit
->search_start
= edit
->curs1
;
1771 if (edit
->search
->error_str
)
1772 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1776 edit
->force
|= REDRAW_COMPLETELY
;
1777 edit_scroll_screen_over_cursor (edit
);
1782 * Check if it's OK to close the editor. If there are unsaved changes,
1783 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
1786 edit_ok_to_exit (WEdit
*edit
)
1788 if (!edit
->modified
)
1791 if (!edit_check_newline (edit
))
1794 switch (edit_query_dialog3
1795 (_("Quit"), _(" File was modified, Save with exit? "),
1796 _("&Cancel quit"), _("&Yes"), _("&No"))) {
1798 edit_push_markers (edit
);
1799 edit_set_markers (edit
, 0, 0, 0, 0);
1800 if (!edit_save_cmd (edit
))
1813 /* Return a null terminated length of text. Result must be g_free'd */
1814 static unsigned char *
1815 edit_get_block (WEdit
*edit
, long start
, long finish
, int *l
)
1817 unsigned char *s
, *r
;
1818 r
= s
= g_malloc (finish
- start
+ 1);
1819 if (column_highlighting
) {
1821 /* copy from buffer, excluding chars that are out of the column 'margins' */
1822 while (start
< finish
) {
1824 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0,
1826 c
= edit_get_byte (edit
, start
);
1827 if ((x
>= edit
->column1
&& x
< edit
->column2
)
1828 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
1835 *l
= finish
- start
;
1836 while (start
< finish
)
1837 *s
++ = edit_get_byte (edit
, start
++);
1843 /* save block, returns 1 on success */
1845 edit_save_block (WEdit
* edit
, const char *filename
, long start
,
1851 mc_open (filename
, O_CREAT
| O_WRONLY
| O_TRUNC
,
1852 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
| O_BINARY
)) == -1)
1855 if (column_highlighting
) {
1857 r
= mc_write (file
, VERTICAL_MAGIC
, sizeof(VERTICAL_MAGIC
));
1859 unsigned char *block
, *p
;
1860 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
1862 r
= mc_write (file
, p
, len
);
1873 len
= finish
- start
;
1874 buf
= g_malloc (TEMP_BUF_LEN
);
1875 while (start
!= finish
) {
1876 end
= min (finish
, start
+ TEMP_BUF_LEN
);
1877 for (; i
< end
; i
++)
1878 buf
[i
- start
] = edit_get_byte (edit
, i
);
1879 len
-= mc_write (file
, (char *) buf
, end
- start
);
1890 /* copies a block to clipboard file */
1891 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
1895 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1896 ret
= edit_save_block (edit
, tmp
, start
, finish
);
1902 void edit_paste_from_history (WEdit
*edit
)
1905 edit_error_dialog (_(" Error "), _(" This function is not implemented. "));
1908 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
1910 long start_mark
, end_mark
;
1911 if (eval_marks (edit
, &start_mark
, &end_mark
))
1913 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1914 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
1917 edit_mark_cmd (edit
, 1);
1921 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
1923 long start_mark
, end_mark
;
1924 if (eval_marks (edit
, &start_mark
, &end_mark
))
1926 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1927 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
1930 edit_block_delete_cmd (edit
);
1931 edit_mark_cmd (edit
, 1);
1935 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
1938 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1939 edit_insert_file (edit
, tmp
);
1945 * Ask user for the line and go to that line.
1946 * Negative numbers mean line from the end (i.e. -1 is the last line).
1949 edit_goto_cmd (WEdit
*edit
)
1952 static long line
= 0; /* line as typed, saved as default */
1957 g_snprintf (s
, sizeof (s
), "%ld", line
);
1958 f
= input_dialog (_(" Goto line "), _(" Enter line: "), MC_HISTORY_EDIT_GOTO_LINE
,
1968 l
= strtol (f
, &error
, 0);
1976 l
= edit
->total_lines
+ l
+ 2;
1977 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
1978 edit_move_to_line (edit
, l
- 1);
1979 edit
->force
|= REDRAW_COMPLETELY
;
1984 /* Return 1 on success */
1986 edit_save_block_cmd (WEdit
*edit
)
1988 long start_mark
, end_mark
;
1991 if (eval_marks (edit
, &start_mark
, &end_mark
))
1994 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1996 input_expand_dialog (_(" Save Block "), _(" Enter file name: "),
1997 MC_HISTORY_EDIT_SAVE_BLOCK
,
2000 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2006 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
2008 edit
->force
|= REDRAW_COMPLETELY
;
2012 edit_error_dialog (_(" Save Block "),
2014 (" Cannot save file. ")));
2018 edit
->force
|= REDRAW_COMPLETELY
;
2023 /* returns 1 on success */
2025 edit_insert_file_cmd (WEdit
*edit
)
2030 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
2031 exp
= input_expand_dialog (_(" Insert File "), _(" Enter file name: "),
2032 MC_HISTORY_EDIT_INSERT_FILE
,
2035 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2041 if (edit_insert_file (edit
, exp
)) {
2043 edit
->force
|= REDRAW_COMPLETELY
;
2047 edit_error_dialog (_(" Insert File "),
2049 (" Cannot insert file. ")));
2053 edit
->force
|= REDRAW_COMPLETELY
;
2057 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2058 int edit_sort_cmd (WEdit
* edit
)
2060 static char *old
= 0;
2062 long start_mark
, end_mark
;
2065 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2066 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
2070 tmp
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
);
2071 edit_save_block (edit
, tmp
, start_mark
, end_mark
);
2074 exp
= input_dialog (_(" Run Sort "),
2075 _(" Enter sort options (see manpage) separated by whitespace: "),
2076 MC_HISTORY_EDIT_SORT
, (old
!= NULL
) ? old
: "");
2082 tmp
= g_strconcat (" sort ", exp
, " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
, " > ",
2083 home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
2087 if (e
== -1 || e
== 127) {
2088 edit_error_dialog (_(" Sort "),
2089 get_sys_error (_(" Cannot execute sort command ")));
2092 sprintf (q
, "%d ", e
);
2093 tmp
= g_strconcat (_(" Sort returned non-zero: "), q
, (char *) NULL
);
2094 edit_error_dialog (_(" Sort "), tmp
);
2100 edit
->force
|= REDRAW_COMPLETELY
;
2102 if (edit_block_delete_cmd (edit
))
2104 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
2105 edit_insert_file (edit
, tmp
);
2111 * Ask user for a command, execute it and paste its output back to the
2115 edit_ext_cmd (WEdit
*edit
)
2121 input_dialog (_("Paste output of external command"),
2122 _("Enter shell command(s):"),
2123 MC_HISTORY_EDIT_PASTE_EXTCMD
, NULL
);
2128 tmp
= g_strconcat (exp
, " > ", home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
2134 edit_error_dialog (_("External command"),
2135 get_sys_error (_("Cannot execute command")));
2139 edit
->force
|= REDRAW_COMPLETELY
;
2140 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
2141 edit_insert_file (edit
, tmp
);
2146 /* if block is 1, a block must be highlighted and the shell command
2147 processes it. If block is 0 the shell command is a straight system
2148 command, that just produces some output which is to be inserted */
2150 edit_block_process_cmd (WEdit
*edit
, const char *shell_cmd
, int block
)
2152 long start_mark
, end_mark
;
2154 FILE *script_home
= NULL
;
2155 FILE *script_src
= NULL
;
2156 FILE *block_file
= NULL
;
2157 gchar
*o
, *h
, *b
, *tmp
;
2158 char *quoted_name
= NULL
;
2160 o
= g_strconcat (mc_home
, shell_cmd
, (char *) NULL
); /* original source script */
2161 h
= g_strconcat (home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, (char *) NULL
); /* home script */
2162 b
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
); /* block file */
2164 if (!(script_home
= fopen (h
, "r"))) {
2165 if (!(script_home
= fopen (h
, "w"))) {
2166 tmp
= g_strconcat (_("Error creating script:"), h
, (char *) NULL
);
2167 edit_error_dialog ("", get_sys_error (tmp
));
2169 goto edit_block_process_cmd__EXIT
;
2171 if (!(script_src
= fopen (o
, "r"))) {
2172 o
= g_strconcat (mc_home_alt
, shell_cmd
, (char *) NULL
);
2173 if (!(script_src
= fopen (o
, "r"))) {
2174 fclose (script_home
);
2176 tmp
= g_strconcat (_("Error reading script:"), o
, (char *) NULL
);
2177 edit_error_dialog ("", get_sys_error (tmp
));
2179 goto edit_block_process_cmd__EXIT
;
2182 while (fgets (buf
, sizeof (buf
), script_src
))
2183 fputs (buf
, script_home
);
2184 if (fclose (script_home
)) {
2185 tmp
= g_strconcat (_("Error closing script:"), h
, (char *) NULL
);
2186 edit_error_dialog ("", get_sys_error (tmp
));
2188 goto edit_block_process_cmd__EXIT
;
2191 tmp
= g_strconcat (_("Script created:"), h
, (char *) NULL
);
2192 edit_error_dialog ("", get_sys_error (tmp
));
2198 if (block
) { /* for marked block run indent formatter */
2199 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2200 edit_error_dialog (_("Process block"),
2202 (" You must first highlight a block of text. "));
2203 goto edit_block_process_cmd__EXIT
;
2205 edit_save_block (edit
, b
, start_mark
, end_mark
);
2206 quoted_name
= name_quote (edit
->filename
, 0);
2209 * Initial space is to avoid polluting bash history.
2211 * $1 - name of the edited file (to check its extension etc).
2212 * $2 - file containing the current block.
2213 * $3 - file where error messages should be put
2214 * (for compatibility with old scripts).
2216 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ", quoted_name
,
2217 " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
" /dev/null", (char *) NULL
);
2222 * No block selected, just execute the command for the file.
2224 * $1 - name of the edited file.
2226 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ",
2227 quoted_name
, (char *) NULL
);
2231 g_free (quoted_name
);
2232 close_error_pipe (D_NORMAL
, NULL
);
2234 edit_refresh_cmd (edit
);
2235 edit
->force
|= REDRAW_COMPLETELY
;
2237 /* insert result block */
2239 if (edit_block_delete_cmd (edit
))
2240 goto edit_block_process_cmd__EXIT
;
2241 edit_insert_file (edit
, b
);
2242 if ((block_file
= fopen (b
, "w")))
2243 fclose (block_file
);
2244 goto edit_block_process_cmd__EXIT
;
2246 edit_block_process_cmd__EXIT
:
2253 /* prints at the cursor */
2254 /* returns the number of chars printed */
2255 int edit_print_string (WEdit
* e
, const char *s
)
2259 edit_execute_cmd (e
, -1, (unsigned char) s
[i
++]);
2260 e
->force
|= REDRAW_COMPLETELY
;
2261 edit_update_screen (e
);
2266 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
2271 to
= name_quote (to
, 0);
2272 subject
= name_quote (subject
, 0);
2273 cc
= name_quote (cc
, 0);
2274 s
= g_strconcat ("mail -s ", subject
, *cc
? " -c " : "" , cc
, " ", to
, (char *) NULL
);
2286 for (i
= 0; i
< edit
->last_byte
; i
++)
2287 fputc (edit_get_byte (edit
, i
), p
);
2292 #define MAIL_DLG_HEIGHT 12
2294 void edit_mail_dialog (WEdit
* edit
)
2297 char *tmail_subject
;
2300 static char *mail_cc_last
= 0;
2301 static char *mail_subject_last
= 0;
2302 static char *mail_to_last
= 0;
2304 QuickWidget quick_widgets
[] =
2306 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT
, N_("&Cancel"), B_CANCEL
, NULL
),
2307 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT
, N_("&OK"), B_ENTER
, NULL
),
2308 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, "mail-dlg-input", &tmail_cc
),
2309 /* 3 */ QUICK_LABEL (2, 50, 7, MAIL_DLG_HEIGHT
, N_(" Copies to")),
2310 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, "mail-dlg-input-2", &tmail_subject
),
2311 /* 5 */ QUICK_LABEL (2, 50, 5, MAIL_DLG_HEIGHT
, N_(" Subject")),
2312 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, "mail-dlg-input-3", &tmail_to
),
2313 /* 7 */ QUICK_LABEL (2, 50, 3, MAIL_DLG_HEIGHT
, N_(" To")),
2314 /* 8 */ QUICK_LABEL (2, 50, 2, MAIL_DLG_HEIGHT
, N_(" mail -s <subject> -c <cc> <to>")),
2318 QuickDialog Quick_input
=
2320 50, MAIL_DLG_HEIGHT
, -1, -1, N_(" Mail "),
2321 "[Input Line Keys]", quick_widgets
, FALSE
2324 quick_widgets
[2].u
.input
.text
= mail_cc_last
? mail_cc_last
: "";
2325 quick_widgets
[4].u
.input
.text
= mail_subject_last
? mail_subject_last
: "";
2326 quick_widgets
[6].u
.input
.text
= mail_to_last
? mail_to_last
: "";
2328 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
2329 g_free (mail_cc_last
);
2330 g_free (mail_subject_last
);
2331 g_free (mail_to_last
);
2332 mail_cc_last
= tmail_cc
;
2333 mail_subject_last
= tmail_subject
;
2334 mail_to_last
= tmail_to
;
2335 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);
2340 /*******************/
2341 /* Word Completion */
2342 /*******************/
2344 static gboolean
is_break_char(char c
)
2346 return (isspace(c
) || strchr("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c
));
2349 /* find first character of current word */
2350 static int edit_find_word_start (WEdit
*edit
, long *word_start
, gsize
*word_len
)
2355 /* return if at begin of file */
2356 if (edit
->curs1
<= 0)
2359 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- 1);
2360 /* return if not at end or in word */
2361 if (is_break_char(c
))
2364 /* search start of word to be completed */
2366 /* return if at begin of file */
2367 if (edit
->curs1
- i
< 0)
2371 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- i
);
2373 if (is_break_char(c
)) {
2374 /* return if word starts with digit */
2378 *word_start
= edit
->curs1
- (i
- 1); /* start found */
2387 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2389 /* collect the possible completions */
2391 edit_collect_completions (WEdit
*edit
, long start
, gsize word_len
,
2392 char *match_expr
, struct selection
*compl,
2404 srch
= mc_search_new(match_expr
, -1);
2408 if (mc_config_get_bool(mc_main_config
, CONFIG_APP_SECTION
, "editor_wordcompletion_collect_entire_file", 0)){
2409 last_byte
= edit
->last_byte
;
2414 srch
->search_type
= MC_SEARCH_T_REGEX
;
2415 srch
->is_case_sentitive
= TRUE
;
2416 srch
->search_fn
= edit_search_cmd_callback
;
2418 /* collect max MAX_WORD_COMPLETIONS completions */
2421 /* get next match */
2422 if (mc_search_run (srch
, (void *) edit
, start
+1, last_byte
, &len
) == FALSE
)
2424 start
= srch
->normal_offset
;
2426 /* add matched completion if not yet added */
2427 temp
= g_string_new("");
2428 for (i
= 0; i
< len
; i
++){
2429 skip
= edit_get_byte(edit
, start
+i
);
2432 g_string_append_c (temp
, skip
);
2437 for (i
= 0; i
< (gsize
) *num
; i
++) {
2440 (char *) &compl[i
].text
[word_len
],
2441 (char *) &temp
->str
[word_len
],
2442 max (len
, compl[i
].len
) - (gsize
)word_len
2444 struct selection
this = compl[i
];
2445 for (++i
; i
< *num
; i
++) {
2446 compl[i
- 1] = compl[i
];
2448 compl[*num
- 1] = this;
2450 break; /* skip it, already added */
2454 g_string_free(temp
, TRUE
);
2457 if (*num
== MAX_WORD_COMPLETIONS
&& MAX_WORD_COMPLETIONS
) {
2458 g_free(compl[0].text
);
2459 for (i
= 1; i
< *num
; i
++) {
2460 compl[i
- 1] = compl[i
];
2467 recoded
= str_convert_to_display (temp
->str
);
2469 if (recoded
&& recoded
->len
){
2470 g_string_free(temp
,TRUE
);
2473 g_string_free(recoded
, TRUE
);
2476 compl[*num
].text
= temp
->str
;
2477 compl[*num
].len
= temp
->len
;
2480 g_string_free(temp
, FALSE
);
2482 /* note the maximal length needed for the completion dialog */
2486 mc_search_free(srch
);
2491 * Complete current word using regular expression search
2492 * backwards beginning at the current cursor position.
2495 edit_complete_word_cmd (WEdit
*edit
)
2497 gsize i
, max_len
, word_len
= 0, num_compl
= 0;
2498 long word_start
= 0;
2499 unsigned char *bufpos
;
2501 struct selection
compl[MAX_WORD_COMPLETIONS
]; /* completions */
2503 /* search start of word to be completed */
2504 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2507 /* prepare match expression */
2508 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2509 [word_start
& M_EDIT_BUF_SIZE
];
2511 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2512 match_expr
= g_strdup_printf ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+", word_len
, bufpos
);
2514 /* collect the possible completions */
2515 /* start search from begin to end of file */
2517 edit_collect_completions (edit
, word_start
, word_len
, match_expr
,
2518 (struct selection
*) &compl, &num_compl
);
2520 if (num_compl
> 0) {
2521 /* insert completed word if there is only one match */
2522 if (num_compl
== 1) {
2523 for (i
= word_len
; i
< compl[0].len
; i
++)
2524 edit_insert (edit
, *(compl[0].text
+ i
));
2526 /* more than one possible completion => ask the user */
2528 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2529 /* !!! pressed again the selection dialog pops up, but that !!! */
2530 /* !!! seems to require a further internal state !!! */
2533 /* let the user select the preferred completion */
2534 editcmd_dialog_completion_show (edit
, max_len
, word_len
,
2535 (struct selection
*) &compl,
2540 g_free (match_expr
);
2541 /* release memory before return */
2542 for (i
= 0; i
< num_compl
; i
++)
2543 g_free (compl[i
].text
);
2547 edit_select_codepage_cmd (WEdit
*edit
)
2550 const char *cp_id
= NULL
;
2551 if (do_select_codepage ()) {
2552 cp_id
= get_codepage_id (source_codepage
>= 0 ?
2553 source_codepage
: display_codepage
);
2555 if (cp_id
!= NULL
) {
2557 conv
= str_crt_conv_from (cp_id
);
2558 if (conv
!= INVALID_CONV
) {
2559 if (edit
->converter
!= str_cnv_from_term
)
2560 str_close_conv (edit
->converter
);
2561 edit
->converter
= conv
;
2566 edit
->utf8
= str_isutf8 (cp_id
);
2569 edit
->force
= REDRAW_COMPLETELY
;
2570 edit_refresh_cmd (edit
);
2577 edit_insert_literal_cmd (WEdit
*edit
)
2579 int char_for_insertion
=
2580 editcmd_dialog_raw_key_query (_(" Insert Literal "),
2581 _(" Press any key: "), 0);
2582 edit_execute_key_command (edit
, -1,
2583 ascii_alpha_to_cntrl (char_for_insertion
));
2587 edit_execute_macro_cmd (WEdit
*edit
)
2590 CK_Macro (editcmd_dialog_raw_key_query
2591 (_(" Execute Macro "), _(" Press macro hotkey: "),
2593 if (command
== CK_Macro (0))
2594 command
= CK_Insert_Char
;
2596 edit_execute_key_command (edit
, command
, -1);
2600 edit_begin_end_macro_cmd (WEdit
*edit
)
2602 /* edit is a pointer to the widget */
2604 unsigned long command
= edit
->macro_i
< 0
2605 ? CK_Begin_Record_Macro
: CK_End_Record_Macro
;
2606 edit_execute_key_command (edit
, command
, -1);
2611 edit_load_forward_cmd (WEdit
*edit
)
2613 if (edit
->modified
) {
2614 if (edit_query_dialog2
2616 _(" Current text was modified without a file save. \n"
2617 " Continue discards these changes. "), _("C&ontinue"),
2619 edit
->force
|= REDRAW_COMPLETELY
;
2623 if ( edit_stack_iterator
+ 1 < MAX_HISTORY_MOVETO
) {
2624 if ( edit_history_moveto
[edit_stack_iterator
+ 1].line
< 1 ) {
2627 edit_stack_iterator
++;
2628 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2629 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2630 edit_history_moveto
[edit_stack_iterator
].line
);
2641 edit_load_back_cmd (WEdit
*edit
)
2643 if (edit
->modified
) {
2644 if (edit_query_dialog2
2646 _(" Current text was modified without a file save. \n"
2647 " Continue discards these changes. "), _("C&ontinue"),
2649 edit
->force
|= REDRAW_COMPLETELY
;
2653 if ( edit_stack_iterator
> 0 ) {
2654 edit_stack_iterator
--;
2655 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2656 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2657 edit_history_moveto
[edit_stack_iterator
].line
);
2668 edit_get_match_keyword_cmd (WEdit
*edit
)
2670 gsize word_len
= 0, max_len
= 0;
2673 long word_start
= 0;
2674 unsigned char *bufpos
;
2678 char *tagfile
= NULL
;
2680 etags_hash_t def_hash
[MAX_DEFINITIONS
];
2682 for ( i
= 0; i
< MAX_DEFINITIONS
; i
++) {
2683 def_hash
[i
].filename
= NULL
;
2686 /* search start of word to be completed */
2687 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2690 /* prepare match expression */
2691 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2692 [word_start
& M_EDIT_BUF_SIZE
];
2693 match_expr
= g_strdup_printf ("%.*s", word_len
, bufpos
);
2695 ptr
= g_get_current_dir ();
2696 path
= g_strconcat (ptr
, G_DIR_SEPARATOR_S
, (char *) NULL
);
2699 /* Recursive search file 'TAGS' in parent dirs */
2701 ptr
= g_path_get_dirname (path
);
2702 g_free(path
); path
= ptr
;
2704 tagfile
= g_build_filename (path
, TAGS_NAME
, (char *) NULL
);
2705 if ( exist_file (tagfile
) )
2707 } while (strcmp( path
, G_DIR_SEPARATOR_S
) != 0);
2710 num_def
= etags_set_definition_hash(tagfile
, path
, match_expr
, (etags_hash_t
*) &def_hash
);
2715 max_len
= MAX_WIDTH_DEF_DIALOG
;
2717 if ( num_def
> 0 ) {
2718 editcmd_dialog_select_definition_show (edit
, match_expr
, max_len
, word_len
,
2719 (etags_hash_t
*) &def_hash
,
2722 g_free (match_expr
);
2726 edit_move_block_to_right (WEdit
* edit
)
2728 long start_mark
, end_mark
;
2729 long cur_bol
, start_bol
;
2731 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2734 start_bol
= edit_bol (edit
, start_mark
);
2735 cur_bol
= edit_bol (edit
, end_mark
- 1);
2737 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2738 if ( option_fill_tabs_with_spaces
) {
2739 if ( option_fake_half_tabs
) {
2740 insert_spaces_tab (edit
, 1);
2742 insert_spaces_tab (edit
, 0);
2745 edit_insert (edit
, '\t');
2747 edit_cursor_move (edit
, edit_bol (edit
, cur_bol
) - edit
->curs1
);
2748 if ( cur_bol
== 0 ) {
2751 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2752 } while (cur_bol
>= start_bol
) ;
2753 edit
->force
|= REDRAW_PAGE
;
2757 edit_move_block_to_left (WEdit
* edit
)
2759 long start_mark
, end_mark
;
2760 long cur_bol
, start_bol
;
2761 int i
, del_tab_width
;
2764 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2767 start_bol
= edit_bol (edit
, start_mark
);
2768 cur_bol
= edit_bol (edit
, end_mark
- 1);
2770 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2771 if (option_fake_half_tabs
) {
2772 del_tab_width
= HALF_TAB_SIZE
;
2774 del_tab_width
= option_tab_spacing
;
2776 next_char
= edit_get_byte (edit
, edit
->curs1
);
2777 if ( next_char
== '\t' ) {
2778 edit_delete (edit
, 1);
2779 } else if ( next_char
== ' ' ) {
2780 for (i
= 1; i
<= del_tab_width
; i
++) {
2781 if ( next_char
== ' ' ) {
2782 edit_delete (edit
, 1);
2784 next_char
= edit_get_byte (edit
, edit
->curs1
);
2787 if ( cur_bol
== 0 ) {
2790 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2791 } while (cur_bol
>= start_bol
) ;
2792 edit
->force
|= REDRAW_PAGE
;