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"
64 #include "../edit/edit-impl.h"
65 #include "../edit/edit.h"
66 #include "../edit/editlock.h"
67 #include "../src/cmddef.h"
68 #include "../edit/edit-widget.h"
69 #include "../edit/editcmd_dialogs.h"
70 #include "../edit/etags.h"
74 /* search and replace: */
75 int search_create_bookmark
= 0;
76 /* static int search_in_all_charsets = 0; */
78 /* queries on a save */
79 int edit_confirm_save
= 1;
81 static int edit_save_cmd (WEdit
*edit
);
82 static unsigned char *edit_get_block (WEdit
*edit
, long start
,
86 edit_search_cmd_search_create_bookmark(WEdit
* edit
)
88 int found
= 0, books
= 0;
89 int l
= 0, l_last
= -1;
93 search_create_bookmark
= 0;
94 book_mark_flush (edit
, -1);
97 if (!mc_search_run(edit
->search
, (void *) edit
, q
, edit
->last_byte
, &len
))
100 edit
->search_start
= edit
->search
->normal_offset
;
102 l
+= edit_count_lines (edit
, q
, edit
->search
->normal_offset
);
104 book_mark_insert (edit
, l
, BOOK_MARK_FOUND_COLOR
);
108 q
= edit
->search
->normal_offset
+ 1;
112 edit_error_dialog (_ ("Search"), _ (" Search string not found "));
114 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
115 edit_scroll_screen_over_cursor (edit
);
120 edit_search_cmd_callback(const void *user_data
, gsize char_offset
)
122 return edit_get_byte ((WEdit
* )user_data
, (long) char_offset
);
125 void edit_help_cmd (WEdit
* edit
)
127 interactive_display (NULL
, "[Internal File Editor]");
128 edit
->force
|= REDRAW_COMPLETELY
;
132 edit_refresh_cmd (WEdit
* edit
)
137 edit_get_syntax_color (edit
, -1, &color
);
143 #endif /* !HAVE_SLANG */
147 /* If 0 (quick save) then a) create/truncate <filename> file,
148 b) save to <filename>;
149 if 1 (safe save) then a) save to <tempnam>,
150 b) rename <tempnam> to <filename>;
151 if 2 (do backups) then a) save to <tempnam>,
152 b) rename <filename> to <filename.backup_ext>,
153 c) rename <tempnam> to <filename>. */
155 /* returns 0 on error, -1 on abort */
157 edit_save_file (WEdit
*edit
, const char *filename
)
163 gchar
*real_filename
;
164 int this_save_mode
, fd
= -1;
171 if (*filename
!= PATH_SEP
&& edit
->dir
) {
172 real_filename
= concat_dir_and_file (edit
->dir
, filename
);
174 real_filename
= g_strdup(filename
);
177 this_save_mode
= option_save_mode
;
178 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
179 if (!vfs_file_is_local (real_filename
) ||
180 (fd
= mc_open (real_filename
, O_RDONLY
| O_BINARY
)) == -1) {
182 * The file does not exists yet, so no safe save or
183 * backup are necessary.
185 this_save_mode
= EDIT_QUICK_SAVE
;
191 if (this_save_mode
== EDIT_QUICK_SAVE
&&
192 !edit
->skip_detach_prompt
) {
196 rv
= mc_stat (real_filename
, &sb
);
197 if (rv
== 0 && sb
.st_nlink
> 1) {
198 rv
= edit_query_dialog3 (_("Warning"),
199 _(" File has hard-links. Detach before saving? "),
200 _("&Yes"), _("&No"), _("&Cancel"));
203 this_save_mode
= EDIT_SAFE_SAVE
;
206 edit
->skip_detach_prompt
= 1;
209 g_free(real_filename
);
214 /* Prevent overwriting changes from other editor sessions. */
215 if (rv
== 0 && edit
->stat1
.st_mtime
!= 0 && edit
->stat1
.st_mtime
!= sb
.st_mtime
) {
217 /* The default action is "Cancel". */
220 rv
= edit_query_dialog2 (
222 _("The file has been modified in the meantime. Save anyway?"),
226 g_free(real_filename
);
232 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
233 char *savedir
, *saveprefix
;
234 const char *slashpos
;
235 slashpos
= strrchr (real_filename
, PATH_SEP
);
237 savedir
= g_strdup (real_filename
);
238 savedir
[slashpos
- real_filename
+ 1] = '\0';
240 savedir
= g_strdup (".");
241 saveprefix
= concat_dir_and_file (savedir
, "cooledit");
243 fd
= mc_mkstemps (&savename
, saveprefix
, NULL
);
246 g_free(real_filename
);
250 * Close for now because mc_mkstemps use pure open system call
251 * to create temporary file and it needs to be reopened by
252 * VFS-aware mc_open().
256 savename
= g_strdup (real_filename
);
258 mc_chown (savename
, edit
->stat1
.st_uid
, edit
->stat1
.st_gid
);
259 mc_chmod (savename
, edit
->stat1
.st_mode
);
262 mc_open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| O_BINARY
,
263 edit
->stat1
.st_mode
)) == -1)
267 if ((p
= edit_get_write_filter (savename
, real_filename
))) {
271 file
= (FILE *) popen (p
, "w");
274 filelen
= edit_write_stream (edit
, file
);
278 if (pclose (file
) != 0) {
279 tmp
= g_strconcat (_(" Error writing to pipe: "),
280 p
, " ", (char *) NULL
);
281 edit_error_dialog (_("Error"), tmp
);
288 tmp
= g_strconcat (_(" Cannot open pipe for writing: "),
289 p
, " ", (char *) NULL
);
291 edit_error_dialog (_("Error"),
292 get_sys_error (tmp
));
298 } else if (edit
->lb
== LB_ASIS
) { /* do not change line breaks */
301 filelen
= edit
->last_byte
;
302 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
303 if (mc_write (fd
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
)
311 (fd
, (char *) edit
->buffers1
[buf
],
312 edit
->curs1
& M_EDIT_BUF_SIZE
) !=
313 (edit
->curs1
& M_EDIT_BUF_SIZE
)) {
315 } else if (edit
->curs2
) {
317 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
320 (char *) edit
->buffers2
[buf
] + EDIT_BUF_SIZE
-
321 (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1,
322 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) !=
323 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) {
328 (fd
, (char *) edit
->buffers2
[buf
],
329 EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
340 /* Update the file information, especially the mtime. */
341 if (mc_stat (savename
, &edit
->stat1
) == -1)
343 } else { /* change line breaks */
348 file
= (FILE *) fopen (savename
, "w");
351 filelen
= edit_write_stream (edit
, file
);
356 msg
= g_strdup_printf (_(" Cannot open file for writing: %s "), savename
);
357 edit_error_dialog (_("Error"), msg
);
363 if (filelen
!= edit
->last_byte
)
366 if (this_save_mode
== EDIT_DO_BACKUP
) {
367 assert (option_backup_ext
!= NULL
);
368 tmp
= g_strconcat (real_filename
, option_backup_ext
,(char *) NULL
);
369 if (mc_rename (real_filename
, tmp
) == -1){
375 if (this_save_mode
!= EDIT_QUICK_SAVE
)
376 if (mc_rename (savename
, real_filename
) == -1)
379 g_free(real_filename
);
382 /* FIXME: Is this safe ?
383 * if (this_save_mode != EDIT_QUICK_SAVE)
384 * mc_unlink (savename);
386 g_free(real_filename
);
392 menu_save_mode_cmd (void)
395 const int DLG_X
= 38;
396 const int DLG_Y
= 10;
407 QuickWidget widgets
[] =
409 /* 0 */ QUICK_BUTTON (18, DLG_X
, 7, DLG_Y
, N_("&Cancel"), B_CANCEL
, NULL
),
410 /* 1 */ QUICK_BUTTON ( 6, DLG_X
, 7, DLG_Y
, N_("&OK"), B_ENTER
, NULL
),
411 /* 2 */ QUICK_INPUT (23, DLG_X
, 5, DLG_Y
, option_backup_ext
, 9, 0, "edit-backup-ext", &str_result
),
412 /* 3 */ QUICK_LABEL (22, DLG_X
, 4, DLG_Y
, N_("Extension:")),
413 /* 4 */ QUICK_RADIO ( 4, DLG_X
, 3, DLG_Y
, 3, str
, &option_save_mode
),
419 DLG_X
, DLG_Y
, -1, -1, N_(" Edit Save Mode "),
420 "[Edit Save Mode]", widgets
, FALSE
426 size_t l1
, w0
, w1
, w3
;
428 assert (option_backup_ext
!= NULL
);
430 /* OK/Cancel buttons */
431 w0
= str_term_width1 (_(widgets
[0].u
.button
.text
)) + 2;
432 w1
= str_term_width1 (_(widgets
[1].u
.button
.text
)) + 4; /* default batton */
434 w3
= str_term_width1 (_(widgets
[3].u
.label
.text
));
436 maxlen
= l1
= w0
+ w1
+ 6;
438 for (i
= 0; i
< 3; i
++) {
442 maxlen
= max (maxlen
, (size_t) str_term_width1 (str
[i
]) + 7);
445 dlg_x
= maxlen
+ w3
+ 5 + 2;
446 widgets
[2].u
.input
.len
= w3
; /* input field length */
447 dlg_x
= min (COLS
, dlg_x
);
450 widgets
[0].relative_x
= dlg_x
* 2/3 - w0
/2;
451 widgets
[1].relative_x
= dlg_x
/3 - w1
/2;
452 widgets
[2].relative_x
= widgets
[3].relative_x
= maxlen
+ 3;
454 for (i
= 0; i
< sizeof (widgets
)/sizeof (widgets
[0]); i
++)
455 widgets
[i
].x_divisions
= dlg_x
;
457 if (quick_dialog (&dialog
) != B_CANCEL
) {
458 g_free (option_backup_ext
);
459 option_backup_ext
= str_result
;
464 edit_set_filename (WEdit
*edit
, const char *f
)
466 g_free (edit
->filename
);
469 edit
->filename
= g_strdup (f
);
470 if (edit
->dir
== NULL
&& *f
!= PATH_SEP
)
472 edit
->dir
= g_strdup (vfs_get_current_dir ());
474 edit
->dir
= g_get_current_dir ();
479 edit_get_save_file_as (WEdit
*edit
)
482 #define DLG_HEIGHT 14
484 static LineBreaks cur_lb
= LB_ASIS
;
486 char *filename
= edit
->filename
;
488 const char *lb_names
[LB_NAMES
] =
490 N_("&Do not change"),
491 N_("&Unix format (LF)"),
492 N_("&Windows/DOS format (CR LF)"),
493 N_("&Macintosh format (CR)")
496 QuickWidget quick_widgets
[] =
498 QUICK_BUTTON (6, 10, DLG_HEIGHT
- 3, DLG_HEIGHT
, N_("&Cancel"), B_CANCEL
, NULL
),
499 QUICK_BUTTON (2, 10, DLG_HEIGHT
- 3, DLG_HEIGHT
, N_("&OK"), B_ENTER
, NULL
),
500 QUICK_RADIO (5, DLG_WIDTH
, DLG_HEIGHT
- 8, DLG_HEIGHT
, LB_NAMES
, lb_names
, (int *) &cur_lb
),
501 QUICK_LABEL (3, DLG_WIDTH
, DLG_HEIGHT
- 9, DLG_HEIGHT
, N_("Change line breaks to:")),
502 QUICK_INPUT (3, DLG_WIDTH
, DLG_HEIGHT
- 11, DLG_HEIGHT
, filename
, DLG_WIDTH
- 6, 0, "save-as", &filename
),
503 QUICK_LABEL (2, DLG_WIDTH
, DLG_HEIGHT
- 12, DLG_HEIGHT
, N_(" Enter file name: ")),
507 QuickDialog Quick_options
=
509 DLG_WIDTH
, DLG_HEIGHT
, -1, -1,
510 N_(" Save As "), "[Save File As]",
514 if (quick_dialog (&Quick_options
) != B_CANCEL
) {
525 /* Here we want to warn the users of overwriting an existing file,
526 but only if they have made a change to the filename */
527 /* returns 1 on success */
529 edit_save_as_cmd (WEdit
*edit
)
531 /* This heads the 'Save As' dialog box */
534 int different_filename
= 0;
536 exp
= edit_get_save_file_as (edit
);
537 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
542 edit
->force
|= REDRAW_COMPLETELY
;
546 if (strcmp (edit
->filename
, exp
)) {
548 different_filename
= 1;
549 if ((file
= mc_open (exp
, O_RDONLY
| O_BINARY
)) != -1) {
550 /* the file exists */
552 /* Overwrite the current file or cancel the operation */
553 if (edit_query_dialog2
555 _(" A file already exists with this name. "),
556 _("&Overwrite"), _("&Cancel"))) {
557 edit
->force
|= REDRAW_COMPLETELY
;
562 edit
->stat1
.st_mode
|= S_IWUSR
;
564 save_lock
= edit_lock_file (exp
);
566 /* filenames equal, check if already locked */
567 if (!edit
->locked
&& !edit
->delete_file
)
568 save_lock
= edit_lock_file (exp
);
571 if (different_filename
)
574 * Allow user to write into saved (under another name) file
575 * even if original file had r/o user permissions.
577 edit
->stat1
.st_mode
|= S_IWRITE
;
580 rv
= edit_save_file (edit
, exp
);
583 /* Succesful, so unlock both files */
584 if (different_filename
) {
586 edit_unlock_file (exp
);
588 edit
->locked
= edit_unlock_file (edit
->filename
);
590 if (edit
->locked
|| save_lock
)
591 edit
->locked
= edit_unlock_file (edit
->filename
);
594 edit_set_filename (edit
, exp
);
595 if (edit
->lb
!= LB_ASIS
)
596 edit_reload(edit
, exp
);
599 edit
->delete_file
= 0;
600 if (different_filename
)
601 edit_load_syntax (edit
, NULL
, option_syntax_type
);
602 edit
->force
|= REDRAW_COMPLETELY
;
605 edit_error_dialog (_(" Save As "),
607 (" Cannot save file. ")));
610 /* Failed, so maintain modify (not save) lock */
612 edit_unlock_file (exp
);
614 edit
->force
|= REDRAW_COMPLETELY
;
619 edit
->force
|= REDRAW_COMPLETELY
;
623 /* {{{ Macro stuff starts here */
625 /* creates a macro file if it doesn't exist */
626 static FILE *edit_open_macro_file (const char *r
)
631 filename
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
632 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1){
637 fd
= fopen (filename
, r
);
642 #define MAX_MACROS 1024
643 static int saved_macro
[MAX_MACROS
+ 1];
644 static int saved_macros_loaded
= 0;
647 This is just to stop the macro file be loaded over and over for keys
648 that aren't defined to anything. On slow systems this could be annoying.
654 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
655 if (saved_macro
[i
] == k
)
660 /* returns 1 on error */
662 edit_delete_macro (WEdit
* edit
, int k
)
665 struct macro macro
[MAX_MACRO_LENGTH
];
671 if (saved_macros_loaded
)
672 if ((j
= macro_exists (k
)) < 0)
674 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
675 g
= fopen (tmp
, "w");
678 edit_error_dialog (_(" Delete macro "),
679 get_sys_error (_(" Cannot open temp file ")));
682 f
= edit_open_macro_file ("r");
684 edit_error_dialog (_(" Delete macro "),
685 get_sys_error (_(" Cannot open macro file ")));
690 n
= fscanf (f
, ("key '%d 0': "), &s
);
694 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
698 fprintf (g
, ("key '%d 0': "), s
);
699 for (i
= 0; i
< n
; i
++)
700 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
706 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
707 tmp2
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
708 if (rename ( tmp
, tmp2
) == -1) {
709 edit_error_dialog (_(" Delete macro "),
710 get_sys_error (_(" Cannot overwrite macro file ")));
718 if (saved_macros_loaded
)
719 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
723 /* returns 0 on error */
724 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
729 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
730 s
= editcmd_dialog_raw_key_query (_(" Save macro "),
731 _(" Press the macro's new hotkey: "), 1);
732 edit
->force
|= REDRAW_COMPLETELY
;
734 if (edit_delete_macro (edit
, s
))
736 f
= edit_open_macro_file ("a+");
738 fprintf (f
, ("key '%d 0': "), s
);
739 for (i
= 0; i
< n
; i
++)
740 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
743 if (saved_macros_loaded
) {
744 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
749 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Cannot open macro file ")));
754 void edit_delete_macro_cmd (WEdit
* edit
)
758 command
= editcmd_dialog_raw_key_query (_ (" Delete macro "),
759 _ (" Press macro hotkey: "), 1);
764 edit_delete_macro (edit
, command
);
767 /* return 0 on error */
768 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
771 int s
, i
= 0, found
= 0;
775 if (saved_macros_loaded
)
776 if (macro_exists (k
) < 0)
779 if ((f
= edit_open_macro_file ("r"))) {
783 u
= fscanf (f
, ("key '%d 0': "), &s
);
786 if (!saved_macros_loaded
)
787 saved_macro
[i
++] = s
;
790 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
793 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
798 } while (!found
|| !saved_macros_loaded
);
799 if (!saved_macros_loaded
) {
801 saved_macros_loaded
= 1;
806 edit_error_dialog (_(" Load macro "),
807 get_sys_error (_(" Cannot open macro file ")));
811 /* }}} Macro stuff starts here */
813 /* returns 1 on success */
814 int edit_save_confirm_cmd (WEdit
* edit
)
818 if (edit_confirm_save
) {
819 f
= g_strconcat (_(" Confirm save file? : "), edit
->filename
, " ", NULL
);
820 if (edit_query_dialog2 (_(" Save file "), f
, _("&Save"), _("&Cancel"))){
826 return edit_save_cmd (edit
);
830 /* returns 1 on success */
832 edit_save_cmd (WEdit
*edit
)
834 int res
, save_lock
= 0;
836 if (!edit
->locked
&& !edit
->delete_file
)
837 save_lock
= edit_lock_file (edit
->filename
);
838 res
= edit_save_file (edit
, edit
->filename
);
840 /* Maintain modify (not save) lock on failure */
841 if ((res
> 0 && edit
->locked
) || save_lock
)
842 edit
->locked
= edit_unlock_file (edit
->filename
);
844 /* On failure try 'save as', it does locking on its own */
846 return edit_save_as_cmd (edit
);
847 edit
->force
|= REDRAW_COMPLETELY
;
849 edit
->delete_file
= 0;
857 /* returns 1 on success */
858 int edit_new_cmd (WEdit
* edit
)
860 if (edit
->modified
) {
861 if (edit_query_dialog2 (_ ("Warning"), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("C&ontinue"), _ ("&Cancel"))) {
862 edit
->force
|= REDRAW_COMPLETELY
;
866 edit
->force
|= REDRAW_COMPLETELY
;
868 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
871 /* returns 1 on error */
873 edit_load_file_from_filename (WEdit
* edit
, char *exp
)
875 int prev_locked
= edit
->locked
;
876 char *prev_filename
= g_strdup (edit
->filename
);
878 if (!edit_reload (edit
, exp
)) {
879 g_free (prev_filename
);
884 edit_unlock_file (prev_filename
);
885 g_free (prev_filename
);
890 edit_load_syntax_file (WEdit
* edit
)
895 if (geteuid () == 0) {
896 dir
= query_dialog (_("Syntax file edit"),
897 _(" Which syntax file you want to edit? "), D_NORMAL
, 2,
898 _("&User"), _("&System Wide"));
901 extdir
= concat_dir_and_file (mc_home
, "syntax" PATH_SEP_STR
"Syntax");
902 if (!exist_file(extdir
)) {
904 extdir
= concat_dir_and_file (mc_home_alt
, "syntax" PATH_SEP_STR
"Syntax");
910 buffer
= concat_dir_and_file (home_dir
, EDIT_SYNTAX_FILE
);
911 check_for_default (extdir
, buffer
);
912 edit_load_file_from_filename (edit
, buffer
);
915 edit_load_file_from_filename (edit
, extdir
);
921 edit_load_menu_file (WEdit
* edit
)
929 _(" Which menu file do you want to edit? "), D_NORMAL
,
930 geteuid() ? 2 : 3, _("&Local"), _("&User"), _("&System Wide")
933 menufile
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
935 if (!exist_file (menufile
)) {
937 menufile
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
942 buffer
= g_strdup (EDIT_LOCAL_MENU
);
943 check_for_default (menufile
, buffer
);
944 chmod (buffer
, 0600);
948 buffer
= concat_dir_and_file (home_dir
, EDIT_HOME_MENU
);
949 check_for_default (menufile
, buffer
);
953 buffer
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
954 if (!exist_file (buffer
)) {
956 buffer
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
965 edit_load_file_from_filename (edit
, buffer
);
972 edit_load_cmd (WEdit
*edit
, edit_current_file_t what
)
977 && (edit_query_dialog2
979 _(" Current text was modified without a file save. \n"
980 " Continue discards these changes. "),
981 _("C&ontinue"), _("&Cancel")) == 1)) {
982 edit
->force
|= REDRAW_COMPLETELY
;
987 case EDIT_FILE_COMMON
:
988 exp
= input_expand_dialog (_(" Load "), _(" Enter file name: "),
989 MC_HISTORY_EDIT_LOAD
, edit
->filename
);
993 edit_load_file_from_filename (edit
, exp
);
998 case EDIT_FILE_SYNTAX
:
999 edit_load_syntax_file (edit
);
1002 case EDIT_FILE_MENU
:
1003 edit_load_menu_file (edit
);
1010 edit
->force
|= REDRAW_COMPLETELY
;
1015 if mark2 is -1 then marking is from mark1 to the cursor.
1016 Otherwise its between the markers. This handles this.
1017 Returns 1 if no text is marked.
1019 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
1021 if (edit
->mark1
!= edit
->mark2
) {
1022 if (edit
->mark2
>= 0) {
1023 *start_mark
= min (edit
->mark1
, edit
->mark2
);
1024 *end_mark
= max (edit
->mark1
, edit
->mark2
);
1026 *start_mark
= min (edit
->mark1
, edit
->curs1
);
1027 *end_mark
= max (edit
->mark1
, edit
->curs1
);
1028 edit
->column2
= edit
->curs_col
+ edit
->over_col
;
1032 *start_mark
= *end_mark
= 0;
1033 edit
->column2
= edit
->column1
= 0;
1038 #define space_width 1
1041 edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
)
1045 cursor
= edit
->curs1
;
1046 col
= edit_get_col (edit
);
1047 for (i
= 0; i
< size
; i
++) {
1048 if (data
[i
] == '\n') { /* fill in and move to next line */
1051 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
1052 l
= width
- (edit_get_col (edit
) - col
);
1054 edit_insert (edit
, ' ');
1058 for (p
= edit
->curs1
;; p
++) {
1059 if (p
== edit
->last_byte
) {
1060 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
1061 edit_insert_ahead (edit
, '\n');
1065 if (edit_get_byte (edit
, p
) == '\n') {
1070 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1071 l
= col
- edit_get_col (edit
);
1072 while (l
>= space_width
) {
1073 edit_insert (edit
, ' ');
1078 edit_insert (edit
, data
[i
]);
1080 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1083 #define TEMP_BUF_LEN 1024
1086 edit_insert_column_of_text_from_file (WEdit
* edit
, int file
)
1090 int blocklen
= -1, width
;
1091 unsigned char *data
;
1092 cursor
= edit
->curs1
;
1093 col
= edit_get_col (edit
);
1094 data
= g_malloc (TEMP_BUF_LEN
);
1095 while ((blocklen
= mc_read (file
, (char *) data
, TEMP_BUF_LEN
)) > 0) {
1096 for (width
= 0; width
< blocklen
; width
++) {
1097 if (data
[width
] == '\n')
1100 for (i
= 0; i
< blocklen
; i
++) {
1101 if (data
[i
] == '\n') { /* fill in and move to next line */
1104 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
1105 l
= width
- (edit_get_col (edit
) - col
);
1107 edit_insert (edit
, ' ');
1111 for (p
= edit
->curs1
;; p
++) {
1112 if (p
== edit
->last_byte
) {
1113 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
1114 edit_insert_ahead (edit
, '\n');
1118 if (edit_get_byte (edit
, p
) == '\n') {
1123 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1124 l
= col
- edit_get_col (edit
);
1125 while (l
>= space_width
) {
1126 edit_insert (edit
, ' ');
1131 edit_insert (edit
, data
[i
]);
1134 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1136 edit
->force
|= REDRAW_PAGE
;
1141 edit_block_copy_cmd (WEdit
*edit
)
1143 long start_mark
, end_mark
, current
= edit
->curs1
;
1145 unsigned char *copy_buf
;
1147 edit_update_curs_col (edit
);
1148 if (eval_marks (edit
, &start_mark
, &end_mark
))
1151 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1153 /* all that gets pushed are deletes hence little space is used on the stack */
1155 edit_push_markers (edit
);
1157 if (column_highlighting
) {
1158 edit_insert_column_of_text (edit
, copy_buf
, size
,
1159 abs (edit
->column2
- edit
->column1
));
1162 edit_insert_ahead (edit
, copy_buf
[size
]);
1166 edit_scroll_screen_over_cursor (edit
);
1168 if (column_highlighting
) {
1169 edit_set_markers (edit
, 0, 0, 0, 0);
1170 edit_push_action (edit
, COLUMN_ON
);
1171 column_highlighting
= 0;
1172 } else if (start_mark
< current
&& end_mark
> current
)
1173 edit_set_markers (edit
, start_mark
,
1174 end_mark
+ end_mark
- start_mark
, 0, 0);
1176 edit
->force
|= REDRAW_PAGE
;
1181 edit_block_move_cmd (WEdit
*edit
)
1185 unsigned char *copy_buf
;
1186 long start_mark
, end_mark
;
1190 if (eval_marks (edit
, &start_mark
, &end_mark
))
1192 if (column_highlighting
) {
1193 edit_update_curs_col (edit
);
1195 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1196 if ((x
> edit
->column1
&& x
< edit
->column2
)
1197 || (x
> edit
->column2
&& x
< edit
->column1
))
1199 } else if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1202 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1203 if (edit_query_dialog2
1206 (" Block is large, you may not be able to undo this action. "),
1207 _("C&ontinue"), _("&Cancel")))
1210 edit_push_markers (edit
);
1211 current
= edit
->curs1
;
1212 if (column_highlighting
) {
1213 int size
, c1
, c2
, line
;
1214 line
= edit
->curs_line
;
1215 if (edit
->mark2
< 0)
1216 edit_mark_cmd (edit
, 0);
1217 c1
= min (edit
->column1
, edit
->column2
);
1218 c2
= max (edit
->column1
, edit
->column2
);
1219 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1221 edit_block_delete_cmd (edit
);
1224 edit_move_to_line (edit
, line
);
1225 edit_cursor_move (edit
,
1226 edit_move_forward3 (edit
,
1227 edit_bol (edit
, edit
->curs1
),
1228 x
, 0) - edit
->curs1
);
1229 edit_insert_column_of_text (edit
, copy_buf
, size
, c2
- c1
);
1231 line
= edit
->curs_line
;
1232 edit_update_curs_col (edit
);
1234 edit_block_delete_cmd (edit
);
1235 edit_move_to_line (edit
, line
);
1236 edit_cursor_move (edit
,
1237 edit_move_forward3 (edit
,
1240 x
, 0) - edit
->curs1
);
1242 edit_set_markers (edit
, 0, 0, 0, 0);
1243 edit_push_action (edit
, COLUMN_ON
);
1244 column_highlighting
= 0;
1246 copy_buf
= g_malloc (end_mark
- start_mark
);
1247 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1248 edit_scroll_screen_over_cursor (edit
);
1250 while (count
< end_mark
) {
1251 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
, 1);
1254 edit_scroll_screen_over_cursor (edit
);
1255 edit_cursor_move (edit
,
1256 current
- edit
->curs1
-
1257 (((current
- edit
->curs1
) >
1258 0) ? end_mark
- start_mark
: 0));
1259 edit_scroll_screen_over_cursor (edit
);
1260 while (count
-- > start_mark
)
1261 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1262 edit_set_markers (edit
, edit
->curs1
,
1263 edit
->curs1
+ end_mark
- start_mark
, 0, 0);
1265 edit_scroll_screen_over_cursor (edit
);
1267 edit
->force
|= REDRAW_PAGE
;
1271 edit_delete_column_of_text (WEdit
* edit
)
1273 long p
, q
, r
, m1
, m2
;
1277 eval_marks (edit
, &m1
, &m2
);
1278 n
= edit_move_forward (edit
, m1
, 0, m2
) + 1;
1279 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
1280 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
1282 b
= max(min (c
, d
), min (edit
->column1
, edit
->column2
));
1283 c
= max (c
, d
+ edit
->over_col
);
1286 r
= edit_bol (edit
, edit
->curs1
);
1287 p
= edit_move_forward3 (edit
, r
, b
, 0);
1288 q
= edit_move_forward3 (edit
, r
, c
, 0);
1293 edit_cursor_move (edit
, p
- edit
->curs1
);
1294 while (q
> p
) { /* delete line between margins */
1295 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
1296 edit_delete (edit
, 1);
1299 if (n
) /* move to next line except on the last delete */
1300 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
1304 /* if success return 0 */
1306 edit_block_delete (WEdit
*edit
)
1309 long start_mark
, end_mark
;
1310 if (eval_marks (edit
, &start_mark
, &end_mark
))
1312 if (column_highlighting
&& edit
->mark2
< 0)
1313 edit_mark_cmd (edit
, 0);
1314 if ((end_mark
- start_mark
) > option_max_undo
/ 2) {
1315 /* Warning message with a query to continue or cancel the operation */
1316 if (edit_query_dialog2
1319 (" Block is large, you may not be able to undo this action. "),
1320 _("C&ontinue"), _("&Cancel"))) {
1324 edit_push_markers (edit
);
1325 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1326 edit_scroll_screen_over_cursor (edit
);
1328 if (start_mark
< end_mark
) {
1329 if (column_highlighting
) {
1330 if (edit
->mark2
< 0)
1331 edit_mark_cmd (edit
, 0);
1332 edit_delete_column_of_text (edit
);
1334 while (count
< end_mark
) {
1335 edit_delete (edit
, 1);
1340 edit_set_markers (edit
, 0, 0, 0, 0);
1341 edit
->force
|= REDRAW_PAGE
;
1345 /* returns 1 if canceelled by user */
1346 int edit_block_delete_cmd (WEdit
* edit
)
1348 long start_mark
, end_mark
;
1349 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1350 edit_delete_line (edit
);
1353 return edit_block_delete (edit
);
1356 #define INPUT_INDEX 9
1359 editcmd_find (WEdit
*edit
, gsize
*len
)
1361 off_t search_start
= edit
->search_start
;
1363 long start_mark
= 0;
1364 long end_mark
= edit
->last_byte
;
1367 if (edit
->only_in_selection
) {
1368 mark_res
= eval_marks(edit
, &start_mark
, &end_mark
);
1369 if (mark_res
!= 0) {
1370 edit
->search
->error
= MC_SEARCH_E_NOTFOUND
;
1371 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1374 if (edit
->replace_backwards
) {
1375 if (search_start
> end_mark
|| search_start
<= start_mark
) {
1376 search_start
= end_mark
;
1379 if (search_start
< start_mark
|| search_start
>= end_mark
) {
1380 search_start
= start_mark
;
1384 if (edit
->replace_backwards
)
1385 end_mark
= max(1, edit
->curs1
) - 1;
1387 if (edit
->replace_backwards
) {
1388 search_end
= end_mark
;
1389 while ((int) search_start
>= start_mark
) {
1390 if (search_end
> search_start
+ edit
->search
->original_len
1391 && mc_search_is_fixed_search_str(edit
->search
)) {
1392 search_end
= search_start
+ edit
->search
->original_len
;
1394 if (mc_search_run(edit
->search
, (void *) edit
, search_start
, search_end
, len
)
1395 && edit
->search
->normal_offset
== search_start
) {
1400 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1402 return mc_search_run(edit
->search
, (void *) edit
, search_start
, end_mark
, len
);
1408 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1409 (and the above) routines to work properly - paul */
1411 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1414 edit_replace_cmd__conv_to_display(char *str
)
1418 tmp
= str_convert_to_display (str
);
1420 if (tmp
&& tmp
->len
){
1424 g_string_free (tmp
, FALSE
);
1427 return g_strdup(str
);
1432 edit_replace_cmd__conv_to_input(char *str
)
1436 tmp
= str_convert_to_input (str
);
1438 if (tmp
&& tmp
->len
){
1442 g_string_free (tmp
, FALSE
);
1445 return g_strdup(str
);
1448 /* call with edit = 0 before shutdown to close memory leaks */
1450 edit_replace_cmd (WEdit
*edit
, int again
)
1452 /* 1 = search string, 2 = replace with */
1453 static char *saved1
= NULL
; /* saved default[123] */
1454 static char *saved2
= NULL
;
1455 char *input1
= NULL
; /* user input from the dialog */
1456 char *input2
= NULL
;
1458 long times_replaced
= 0, last_search
;
1459 gboolean once_found
= FALSE
;
1462 g_free (saved1
), saved1
= NULL
;
1463 g_free (saved2
), saved2
= NULL
;
1467 last_search
= edit
->last_byte
;
1469 edit
->force
|= REDRAW_COMPLETELY
;
1471 if (again
&& !saved1
&& !saved2
)
1475 input1
= g_strdup (saved1
? saved1
: "");
1476 input2
= g_strdup (saved2
? saved2
: "");
1478 char *disp1
= edit_replace_cmd__conv_to_display(g_strdup (saved1
? saved1
: ""));
1479 char *disp2
= edit_replace_cmd__conv_to_display(g_strdup (saved2
? saved2
: ""));
1481 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1483 editcmd_dialog_replace_show (edit
, disp1
, disp2
, &input1
, &input2
);
1488 if (input1
== NULL
|| *input1
== '\0') {
1489 edit
->force
= REDRAW_COMPLETELY
;
1493 input1
= edit_replace_cmd__conv_to_input(input1
);
1494 input2
= edit_replace_cmd__conv_to_input(input2
);
1496 g_free (saved1
), saved1
= g_strdup (input1
);
1497 g_free (saved2
), saved2
= g_strdup (input2
);
1500 mc_search_free(edit
->search
);
1501 edit
->search
= NULL
;
1505 if (!edit
->search
) {
1506 edit
->search
= mc_search_new(input1
, -1);
1507 if (edit
->search
== NULL
) {
1508 edit
->search_start
= edit
->curs1
;
1511 edit
->search
->search_type
= edit
->search_type
;
1512 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1513 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1514 edit
->search
->whole_words
= edit
->whole_words
;
1515 edit
->search
->search_fn
= edit_search_cmd_callback
;
1518 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1
1519 && edit
->replace_backwards
)
1520 edit
->search_start
--;
1522 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1
1523 && !edit
->replace_backwards
)
1524 edit
->search_start
++;
1530 if (! editcmd_find(edit
, &len
)) {
1531 if (!(edit
->search
->error
== MC_SEARCH_E_OK
||
1532 (once_found
&& edit
->search
->error
== MC_SEARCH_E_NOTFOUND
))) {
1533 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1538 new_start
= edit
->search
->normal_offset
;
1540 edit
->search_start
= new_start
= edit
->search
->normal_offset
;
1541 /*returns negative on not found or error in pattern */
1543 if (edit
->search_start
>= 0) {
1546 edit
->found_start
= edit
->search_start
;
1547 i
= edit
->found_len
= len
;
1549 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1550 edit_scroll_screen_over_cursor (edit
);
1554 if (edit
->replace_mode
== 0) {
1556 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
1558 edit_scroll_downward (edit
, l
);
1560 edit_scroll_upward (edit
, -l
);
1562 edit_scroll_screen_over_cursor (edit
);
1563 edit
->force
|= REDRAW_PAGE
;
1564 edit_render_keypress (edit
);
1566 /*so that undo stops at each query */
1567 edit_push_key_press (edit
);
1568 /* and prompt 2/3 down */
1569 switch (editcmd_dialog_replace_prompt_show (edit
, input1
, input2
, -1, -1)) {
1573 case B_SKIP_REPLACE
:
1577 edit
->replace_mode
=1;
1581 edit
->replace_mode
= -1;
1585 if (replace_yes
) { /* delete then insert new */
1586 GString
*repl_str
, *tmp_str
;
1587 tmp_str
= g_string_new(input2
);
1589 repl_str
= mc_search_prepare_replace_str (edit
->search
, tmp_str
);
1590 g_string_free(tmp_str
, TRUE
);
1591 if (edit
->search
->error
!= MC_SEARCH_E_OK
)
1593 edit_error_dialog (_ ("Replace"), edit
->search
->error_str
);
1598 edit_delete (edit
, 1);
1600 while (++i
< repl_str
->len
)
1601 edit_insert (edit
, repl_str
->str
[i
]);
1603 g_string_free(repl_str
, TRUE
);
1604 edit
->found_len
= i
;
1606 /* so that we don't find the same string again */
1607 if (edit
->replace_backwards
) {
1608 last_search
= edit
->search_start
;
1609 edit
->search_start
--;
1611 edit
->search_start
+= i
;
1612 last_search
= edit
->last_byte
;
1614 edit_scroll_screen_over_cursor (edit
);
1616 const char *msg
= _(" Replace ");
1617 /* try and find from right here for next search */
1618 edit
->search_start
= edit
->curs1
;
1619 edit_update_curs_col (edit
);
1621 edit
->force
|= REDRAW_PAGE
;
1622 edit_render_keypress (edit
);
1623 if (times_replaced
) {
1624 message (D_NORMAL
, msg
, _(" %ld replacements made. "),
1627 query_dialog (msg
, _(" Search string not found "),
1628 D_NORMAL
, 1, _("&OK"));
1629 edit
->replace_mode
= -1;
1631 } while (edit
->replace_mode
>= 0);
1633 edit
->force
= REDRAW_COMPLETELY
;
1634 edit_scroll_screen_over_cursor (edit
);
1641 void edit_search_cmd (WEdit
* edit
, int again
)
1643 char *search_string
= NULL
, *search_string_dup
= NULL
;
1650 if (edit
->search
!= NULL
) {
1651 search_string
= g_strndup(edit
->search
->original
, edit
->search
->original_len
);
1652 search_string_dup
= search_string
;
1655 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
1656 if (history
!= NULL
&& history
->data
!= NULL
) {
1657 search_string_dup
= search_string
= (char *) g_strdup(history
->data
);
1658 history
= g_list_first (history
);
1659 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
1660 g_list_free (history
);
1662 edit
->search_start
= edit
->curs1
;
1668 if (search_string
&& *search_string
) {
1669 tmp
= str_convert_to_display (search_string
);
1671 g_free(search_string_dup
);
1672 search_string_dup
= NULL
;
1674 if (tmp
&& tmp
->len
)
1675 search_string
= search_string_dup
= tmp
->str
;
1676 g_string_free (tmp
, FALSE
);
1678 #endif /* HAVE_CHARSET */
1679 editcmd_dialog_search_show (edit
, &search_string
);
1681 if (search_string
&& *search_string
) {
1682 tmp
= str_convert_to_input (search_string
);
1683 if (tmp
&& tmp
->len
)
1684 search_string
= tmp
->str
;
1686 g_string_free (tmp
, FALSE
);
1688 if (search_string_dup
)
1689 g_free(search_string_dup
);
1691 #endif /* HAVE_CHARSET */
1693 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1695 if (!search_string
) {
1696 edit
->force
|= REDRAW_COMPLETELY
;
1697 edit_scroll_screen_over_cursor (edit
);
1702 mc_search_free(edit
->search
);
1703 edit
->search
= NULL
;
1707 if (!edit
->search
) {
1708 edit
->search
= mc_search_new(search_string
, -1);
1709 if (edit
->search
== NULL
) {
1710 edit
->search_start
= edit
->curs1
;
1713 edit
->search
->search_type
= edit
->search_type
;
1714 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1715 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1716 edit
->search
->whole_words
= edit
->whole_words
;
1717 edit
->search
->search_fn
= edit_search_cmd_callback
;
1720 if (search_create_bookmark
) {
1721 edit_search_cmd_search_create_bookmark(edit
);
1723 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && edit
->replace_backwards
)
1724 edit
->search_start
--;
1726 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !edit
->replace_backwards
)
1727 edit
->search_start
++;
1730 if (editcmd_find(edit
, &len
)) {
1731 edit
->found_start
= edit
->search_start
= edit
->search
->normal_offset
;
1732 edit
->found_len
= len
;
1734 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1735 edit_scroll_screen_over_cursor (edit
);
1736 if (edit
->replace_backwards
)
1737 edit
->search_start
--;
1739 edit
->search_start
++;
1741 edit
->search_start
= edit
->curs1
;
1742 if (edit
->search
->error_str
)
1743 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1747 edit
->force
|= REDRAW_COMPLETELY
;
1748 edit_scroll_screen_over_cursor (edit
);
1753 * Check if it's OK to close the editor. If there are unsaved changes,
1754 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
1757 edit_ok_to_exit (WEdit
*edit
)
1759 if (!edit
->modified
)
1762 switch (edit_query_dialog3
1763 (_("Quit"), _(" File was modified, Save with exit? "),
1764 _("&Cancel quit"), _("&Yes"), _("&No"))) {
1766 edit_push_markers (edit
);
1767 edit_set_markers (edit
, 0, 0, 0, 0);
1768 if (!edit_save_cmd (edit
))
1781 /* Return a null terminated length of text. Result must be g_free'd */
1782 static unsigned char *
1783 edit_get_block (WEdit
*edit
, long start
, long finish
, int *l
)
1785 unsigned char *s
, *r
;
1786 r
= s
= g_malloc (finish
- start
+ 1);
1787 if (column_highlighting
) {
1789 /* copy from buffer, excluding chars that are out of the column 'margins' */
1790 while (start
< finish
) {
1792 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0,
1794 c
= edit_get_byte (edit
, start
);
1795 if ((x
>= edit
->column1
&& x
< edit
->column2
)
1796 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
1803 *l
= finish
- start
;
1804 while (start
< finish
)
1805 *s
++ = edit_get_byte (edit
, start
++);
1811 /* save block, returns 1 on success */
1813 edit_save_block (WEdit
* edit
, const char *filename
, long start
,
1819 mc_open (filename
, O_CREAT
| O_WRONLY
| O_TRUNC
,
1820 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
| O_BINARY
)) == -1)
1823 if (column_highlighting
) {
1825 r
= mc_write (file
, VERTICAL_MAGIC
, sizeof(VERTICAL_MAGIC
));
1827 unsigned char *block
, *p
;
1828 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
1830 r
= mc_write (file
, p
, len
);
1841 len
= finish
- start
;
1842 buf
= g_malloc (TEMP_BUF_LEN
);
1843 while (start
!= finish
) {
1844 end
= min (finish
, start
+ TEMP_BUF_LEN
);
1845 for (; i
< end
; i
++)
1846 buf
[i
- start
] = edit_get_byte (edit
, i
);
1847 len
-= mc_write (file
, (char *) buf
, end
- start
);
1858 /* copies a block to clipboard file */
1859 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
1863 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1864 ret
= edit_save_block (edit
, tmp
, start
, finish
);
1870 void edit_paste_from_history (WEdit
*edit
)
1873 edit_error_dialog (_(" Error "), _(" This function is not implemented. "));
1876 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
1878 long start_mark
, end_mark
;
1879 if (eval_marks (edit
, &start_mark
, &end_mark
))
1881 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1882 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
1885 edit_mark_cmd (edit
, 1);
1889 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
1891 long start_mark
, end_mark
;
1892 if (eval_marks (edit
, &start_mark
, &end_mark
))
1894 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1895 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
1898 edit_block_delete_cmd (edit
);
1899 edit_mark_cmd (edit
, 1);
1903 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
1906 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1907 edit_insert_file (edit
, tmp
);
1913 * Ask user for the line and go to that line.
1914 * Negative numbers mean line from the end (i.e. -1 is the last line).
1917 edit_goto_cmd (WEdit
*edit
)
1920 static long line
= 0; /* line as typed, saved as default */
1925 g_snprintf (s
, sizeof (s
), "%ld", line
);
1926 f
= input_dialog (_(" Goto line "), _(" Enter line: "), MC_HISTORY_EDIT_GOTO_LINE
,
1936 l
= strtol (f
, &error
, 0);
1944 l
= edit
->total_lines
+ l
+ 2;
1945 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
1946 edit_move_to_line (edit
, l
- 1);
1947 edit
->force
|= REDRAW_COMPLETELY
;
1952 /* Return 1 on success */
1954 edit_save_block_cmd (WEdit
*edit
)
1956 long start_mark
, end_mark
;
1959 if (eval_marks (edit
, &start_mark
, &end_mark
))
1962 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1964 input_expand_dialog (_(" Save Block "), _(" Enter file name: "),
1965 MC_HISTORY_EDIT_SAVE_BLOCK
,
1968 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1974 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
1976 edit
->force
|= REDRAW_COMPLETELY
;
1980 edit_error_dialog (_(" Save Block "),
1982 (" Cannot save file. ")));
1986 edit
->force
|= REDRAW_COMPLETELY
;
1991 /* returns 1 on success */
1993 edit_insert_file_cmd (WEdit
*edit
)
1998 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1999 exp
= input_expand_dialog (_(" Insert File "), _(" Enter file name: "),
2000 MC_HISTORY_EDIT_INSERT_FILE
,
2003 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2009 if (edit_insert_file (edit
, exp
)) {
2011 edit
->force
|= REDRAW_COMPLETELY
;
2015 edit_error_dialog (_(" Insert File "),
2017 (" Cannot insert file. ")));
2021 edit
->force
|= REDRAW_COMPLETELY
;
2025 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2026 int edit_sort_cmd (WEdit
* edit
)
2028 static char *old
= 0;
2030 long start_mark
, end_mark
;
2033 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2034 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
2038 tmp
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
);
2039 edit_save_block (edit
, tmp
, start_mark
, end_mark
);
2042 exp
= input_dialog (_(" Run Sort "),
2043 _(" Enter sort options (see manpage) separated by whitespace: "),
2044 MC_HISTORY_EDIT_SORT
, (old
!= NULL
) ? old
: "");
2050 tmp
= g_strconcat (" sort ", exp
, " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
, " > ",
2051 home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
2055 if (e
== -1 || e
== 127) {
2056 edit_error_dialog (_(" Sort "),
2057 get_sys_error (_(" Cannot execute sort command ")));
2060 sprintf (q
, "%d ", e
);
2061 tmp
= g_strconcat (_(" Sort returned non-zero: "), q
, (char *) NULL
);
2062 edit_error_dialog (_(" Sort "), tmp
);
2068 edit
->force
|= REDRAW_COMPLETELY
;
2070 if (edit_block_delete_cmd (edit
))
2072 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
2073 edit_insert_file (edit
, tmp
);
2079 * Ask user for a command, execute it and paste its output back to the
2083 edit_ext_cmd (WEdit
*edit
)
2089 input_dialog (_("Paste output of external command"),
2090 _("Enter shell command(s):"),
2091 MC_HISTORY_EDIT_PASTE_EXTCMD
, NULL
);
2096 tmp
= g_strconcat (exp
, " > ", home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
2102 edit_error_dialog (_("External command"),
2103 get_sys_error (_("Cannot execute command")));
2107 edit
->force
|= REDRAW_COMPLETELY
;
2108 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
2109 edit_insert_file (edit
, tmp
);
2114 /* if block is 1, a block must be highlighted and the shell command
2115 processes it. If block is 0 the shell command is a straight system
2116 command, that just produces some output which is to be inserted */
2118 edit_block_process_cmd (WEdit
*edit
, const char *shell_cmd
, int block
)
2120 long start_mark
, end_mark
;
2122 FILE *script_home
= NULL
;
2123 FILE *script_src
= NULL
;
2124 FILE *block_file
= NULL
;
2125 gchar
*o
, *h
, *b
, *tmp
;
2126 char *quoted_name
= NULL
;
2128 o
= g_strconcat (mc_home
, shell_cmd
, (char *) NULL
); /* original source script */
2129 h
= g_strconcat (home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, (char *) NULL
); /* home script */
2130 b
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
); /* block file */
2132 if (!(script_home
= fopen (h
, "r"))) {
2133 if (!(script_home
= fopen (h
, "w"))) {
2134 tmp
= g_strconcat (_("Error creating script:"), h
, (char *) NULL
);
2135 edit_error_dialog ("", get_sys_error (tmp
));
2137 goto edit_block_process_cmd__EXIT
;
2139 if (!(script_src
= fopen (o
, "r"))) {
2140 o
= g_strconcat (mc_home_alt
, shell_cmd
, (char *) NULL
);
2141 if (!(script_src
= fopen (o
, "r"))) {
2142 fclose (script_home
);
2144 tmp
= g_strconcat (_("Error reading script:"), o
, (char *) NULL
);
2145 edit_error_dialog ("", get_sys_error (tmp
));
2147 goto edit_block_process_cmd__EXIT
;
2150 while (fgets (buf
, sizeof (buf
), script_src
))
2151 fputs (buf
, script_home
);
2152 if (fclose (script_home
)) {
2153 tmp
= g_strconcat (_("Error closing script:"), h
, (char *) NULL
);
2154 edit_error_dialog ("", get_sys_error (tmp
));
2156 goto edit_block_process_cmd__EXIT
;
2159 tmp
= g_strconcat (_("Script created:"), h
, (char *) NULL
);
2160 edit_error_dialog ("", get_sys_error (tmp
));
2166 if (block
) { /* for marked block run indent formatter */
2167 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2168 edit_error_dialog (_("Process block"),
2170 (" You must first highlight a block of text. "));
2171 goto edit_block_process_cmd__EXIT
;
2173 edit_save_block (edit
, b
, start_mark
, end_mark
);
2174 quoted_name
= name_quote (edit
->filename
, 0);
2177 * Initial space is to avoid polluting bash history.
2179 * $1 - name of the edited file (to check its extension etc).
2180 * $2 - file containing the current block.
2181 * $3 - file where error messages should be put
2182 * (for compatibility with old scripts).
2184 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ", quoted_name
,
2185 " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
" /dev/null", (char *) NULL
);
2190 * No block selected, just execute the command for the file.
2192 * $1 - name of the edited file.
2194 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ",
2195 quoted_name
, (char *) NULL
);
2199 g_free (quoted_name
);
2200 close_error_pipe (D_NORMAL
, NULL
);
2202 edit_refresh_cmd (edit
);
2203 edit
->force
|= REDRAW_COMPLETELY
;
2205 /* insert result block */
2207 if (edit_block_delete_cmd (edit
))
2208 goto edit_block_process_cmd__EXIT
;
2209 edit_insert_file (edit
, b
);
2210 if ((block_file
= fopen (b
, "w")))
2211 fclose (block_file
);
2212 goto edit_block_process_cmd__EXIT
;
2214 edit_block_process_cmd__EXIT
:
2221 /* prints at the cursor */
2222 /* returns the number of chars printed */
2223 int edit_print_string (WEdit
* e
, const char *s
)
2227 edit_execute_cmd (e
, -1, (unsigned char) s
[i
++]);
2228 e
->force
|= REDRAW_COMPLETELY
;
2229 edit_update_screen (e
);
2234 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
2239 to
= name_quote (to
, 0);
2240 subject
= name_quote (subject
, 0);
2241 cc
= name_quote (cc
, 0);
2242 s
= g_strconcat ("mail -s ", subject
, *cc
? " -c " : "" , cc
, " ", to
, (char *) NULL
);
2254 for (i
= 0; i
< edit
->last_byte
; i
++)
2255 fputc (edit_get_byte (edit
, i
), p
);
2260 #define MAIL_DLG_HEIGHT 12
2262 void edit_mail_dialog (WEdit
* edit
)
2265 char *tmail_subject
;
2268 static char *mail_cc_last
= 0;
2269 static char *mail_subject_last
= 0;
2270 static char *mail_to_last
= 0;
2272 QuickWidget quick_widgets
[] =
2274 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT
, N_("&Cancel"), B_CANCEL
, NULL
),
2275 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT
, N_("&OK"), B_ENTER
, NULL
),
2276 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, "mail-dlg-input", &tmail_cc
),
2277 /* 3 */ QUICK_LABEL (2, 50, 7, MAIL_DLG_HEIGHT
, N_(" Copies to")),
2278 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, "mail-dlg-input-2", &tmail_subject
),
2279 /* 5 */ QUICK_LABEL (2, 50, 5, MAIL_DLG_HEIGHT
, N_(" Subject")),
2280 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, "mail-dlg-input-3", &tmail_to
),
2281 /* 7 */ QUICK_LABEL (2, 50, 3, MAIL_DLG_HEIGHT
, N_(" To")),
2282 /* 8 */ QUICK_LABEL (2, 50, 2, MAIL_DLG_HEIGHT
, N_(" mail -s <subject> -c <cc> <to>")),
2286 QuickDialog Quick_input
=
2288 50, MAIL_DLG_HEIGHT
, -1, -1, N_(" Mail "),
2289 "[Input Line Keys]", quick_widgets
, FALSE
2292 quick_widgets
[2].u
.input
.text
= mail_cc_last
? mail_cc_last
: "";
2293 quick_widgets
[4].u
.input
.text
= mail_subject_last
? mail_subject_last
: "";
2294 quick_widgets
[6].u
.input
.text
= mail_to_last
? mail_to_last
: "";
2296 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
2297 g_free (mail_cc_last
);
2298 g_free (mail_subject_last
);
2299 g_free (mail_to_last
);
2300 mail_cc_last
= tmail_cc
;
2301 mail_subject_last
= tmail_subject
;
2302 mail_to_last
= tmail_to
;
2303 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);
2308 /*******************/
2309 /* Word Completion */
2310 /*******************/
2312 static gboolean
is_break_char(char c
)
2314 return (isspace(c
) || strchr("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c
));
2317 /* find first character of current word */
2318 static int edit_find_word_start (WEdit
*edit
, long *word_start
, gsize
*word_len
)
2323 /* return if at begin of file */
2324 if (edit
->curs1
<= 0)
2327 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- 1);
2328 /* return if not at end or in word */
2329 if (is_break_char(c
))
2332 /* search start of word to be completed */
2334 /* return if at begin of file */
2335 if (edit
->curs1
- i
< 0)
2339 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- i
);
2341 if (is_break_char(c
)) {
2342 /* return if word starts with digit */
2346 *word_start
= edit
->curs1
- (i
- 1); /* start found */
2355 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2357 /* collect the possible completions */
2359 edit_collect_completions (WEdit
*edit
, long start
, gsize word_len
,
2360 char *match_expr
, struct selection
*compl,
2372 srch
= mc_search_new(match_expr
, -1);
2376 if (mc_config_get_bool(mc_main_config
, CONFIG_APP_SECTION
, "editor_wordcompletion_collect_entire_file", 0)){
2377 last_byte
= edit
->last_byte
;
2382 srch
->search_type
= MC_SEARCH_T_REGEX
;
2383 srch
->is_case_sentitive
= TRUE
;
2384 srch
->search_fn
= edit_search_cmd_callback
;
2386 /* collect max MAX_WORD_COMPLETIONS completions */
2389 /* get next match */
2390 if (mc_search_run (srch
, (void *) edit
, start
+1, last_byte
, &len
) == FALSE
)
2392 start
= srch
->normal_offset
;
2394 /* add matched completion if not yet added */
2395 temp
= g_string_new("");
2396 for (i
= 0; i
< len
; i
++){
2397 skip
= edit_get_byte(edit
, start
+i
);
2400 g_string_append_c (temp
, skip
);
2405 for (i
= 0; i
< (gsize
) *num
; i
++) {
2408 (char *) &compl[i
].text
[word_len
],
2409 (char *) &temp
->str
[word_len
],
2410 max (len
, compl[i
].len
) - (gsize
)word_len
2412 struct selection
this = compl[i
];
2413 for (++i
; i
< *num
; i
++) {
2414 compl[i
- 1] = compl[i
];
2416 compl[*num
- 1] = this;
2418 break; /* skip it, already added */
2422 g_string_free(temp
, TRUE
);
2425 if (*num
== MAX_WORD_COMPLETIONS
&& MAX_WORD_COMPLETIONS
) {
2426 g_free(compl[0].text
);
2427 for (i
= 1; i
< *num
; i
++) {
2428 compl[i
- 1] = compl[i
];
2435 recoded
= str_convert_to_display (temp
->str
);
2437 if (recoded
&& recoded
->len
){
2438 g_string_free(temp
,TRUE
);
2441 g_string_free(recoded
, TRUE
);
2444 compl[*num
].text
= temp
->str
;
2445 compl[*num
].len
= temp
->len
;
2448 g_string_free(temp
, FALSE
);
2450 /* note the maximal length needed for the completion dialog */
2454 mc_search_free(srch
);
2459 * Complete current word using regular expression search
2460 * backwards beginning at the current cursor position.
2463 edit_complete_word_cmd (WEdit
*edit
)
2465 gsize i
, max_len
, word_len
= 0, num_compl
= 0;
2466 long word_start
= 0;
2467 unsigned char *bufpos
;
2469 struct selection
compl[MAX_WORD_COMPLETIONS
]; /* completions */
2471 /* search start of word to be completed */
2472 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2475 /* prepare match expression */
2476 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2477 [word_start
& M_EDIT_BUF_SIZE
];
2479 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2480 match_expr
= g_strdup_printf ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+", word_len
, bufpos
);
2482 /* collect the possible completions */
2483 /* start search from begin to end of file */
2485 edit_collect_completions (edit
, word_start
, word_len
, match_expr
,
2486 (struct selection
*) &compl, &num_compl
);
2488 if (num_compl
> 0) {
2489 /* insert completed word if there is only one match */
2490 if (num_compl
== 1) {
2491 for (i
= word_len
; i
< compl[0].len
; i
++)
2492 edit_insert (edit
, *(compl[0].text
+ i
));
2494 /* more than one possible completion => ask the user */
2496 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2497 /* !!! pressed again the selection dialog pops up, but that !!! */
2498 /* !!! seems to require a further internal state !!! */
2501 /* let the user select the preferred completion */
2502 editcmd_dialog_completion_show (edit
, max_len
, word_len
,
2503 (struct selection
*) &compl,
2508 g_free (match_expr
);
2509 /* release memory before return */
2510 for (i
= 0; i
< num_compl
; i
++)
2511 g_free (compl[i
].text
);
2516 edit_select_codepage_cmd (WEdit
*edit
)
2519 const char *cp_id
= NULL
;
2520 if (do_select_codepage ()) {
2521 cp_id
= get_codepage_id (source_codepage
>= 0 ?
2522 source_codepage
: display_codepage
);
2524 if (cp_id
!= NULL
) {
2526 conv
= str_crt_conv_from (cp_id
);
2527 if (conv
!= INVALID_CONV
) {
2528 if (edit
->converter
!= str_cnv_from_term
)
2529 str_close_conv (edit
->converter
);
2530 edit
->converter
= conv
;
2536 edit
->utf8
= str_isutf8 (cp_id
);
2539 edit
->force
= REDRAW_COMPLETELY
;
2540 edit_refresh_cmd (edit
);
2545 edit_insert_literal_cmd (WEdit
*edit
)
2547 int char_for_insertion
=
2548 editcmd_dialog_raw_key_query (_(" Insert Literal "),
2549 _(" Press any key: "), 0);
2550 edit_execute_key_command (edit
, -1,
2551 ascii_alpha_to_cntrl (char_for_insertion
));
2555 edit_execute_macro_cmd (WEdit
*edit
)
2558 CK_Macro (editcmd_dialog_raw_key_query
2559 (_(" Execute Macro "), _(" Press macro hotkey: "),
2561 if (command
== CK_Macro (0))
2562 command
= CK_Insert_Char
;
2564 edit_execute_key_command (edit
, command
, -1);
2568 edit_begin_end_macro_cmd(WEdit
*edit
)
2572 /* edit is a pointer to the widget */
2576 0 ? CK_Begin_Record_Macro
: CK_End_Record_Macro
;
2577 edit_execute_key_command (edit
, command
, -1);
2582 edit_load_forward_cmd (WEdit
*edit
)
2584 if (edit
->modified
) {
2585 if (edit_query_dialog2
2587 _(" Current text was modified without a file save. \n"
2588 " Continue discards these changes. "), _("C&ontinue"),
2590 edit
->force
|= REDRAW_COMPLETELY
;
2594 if ( edit_stack_iterator
+ 1 < MAX_HISTORY_MOVETO
) {
2595 if ( edit_history_moveto
[edit_stack_iterator
+ 1].line
< 1 ) {
2598 edit_stack_iterator
++;
2599 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2600 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2601 edit_history_moveto
[edit_stack_iterator
].line
);
2612 edit_load_back_cmd (WEdit
*edit
)
2614 if (edit
->modified
) {
2615 if (edit_query_dialog2
2617 _(" Current text was modified without a file save. \n"
2618 " Continue discards these changes. "), _("C&ontinue"),
2620 edit
->force
|= REDRAW_COMPLETELY
;
2624 if ( edit_stack_iterator
> 0 ) {
2625 edit_stack_iterator
--;
2626 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2627 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2628 edit_history_moveto
[edit_stack_iterator
].line
);
2639 edit_get_match_keyword_cmd (WEdit
*edit
)
2641 gsize word_len
= 0, max_len
= 0;
2644 long word_start
= 0;
2645 unsigned char *bufpos
;
2649 char *tagfile
= NULL
;
2651 etags_hash_t def_hash
[MAX_DEFINITIONS
];
2653 for ( i
= 0; i
< MAX_DEFINITIONS
; i
++) {
2654 def_hash
[i
].filename
= NULL
;
2657 /* search start of word to be completed */
2658 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2661 /* prepare match expression */
2662 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2663 [word_start
& M_EDIT_BUF_SIZE
];
2664 match_expr
= g_strdup_printf ("%.*s", word_len
, bufpos
);
2666 ptr
= g_get_current_dir ();
2667 path
= g_strconcat (ptr
, G_DIR_SEPARATOR_S
, (char *) NULL
);
2670 /* Recursive search file 'TAGS' in parent dirs */
2672 ptr
= g_path_get_dirname (path
);
2673 g_free(path
); path
= ptr
;
2675 tagfile
= g_build_filename (path
, TAGS_NAME
, (char *) NULL
);
2676 if ( exist_file (tagfile
) )
2678 } while (strcmp( path
, G_DIR_SEPARATOR_S
) != 0);
2681 num_def
= etags_set_definition_hash(tagfile
, path
, match_expr
, (etags_hash_t
*) &def_hash
);
2686 max_len
= MAX_WIDTH_DEF_DIALOG
;
2688 if ( num_def
> 0 ) {
2689 editcmd_dialog_select_definition_show (edit
, match_expr
, max_len
, word_len
,
2690 (etags_hash_t
*) &def_hash
,
2693 g_free (match_expr
);
2697 edit_move_block_to_right (WEdit
* edit
)
2699 long start_mark
, end_mark
;
2700 long cur_bol
, start_bol
;
2702 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2705 start_bol
= edit_bol (edit
, start_mark
);
2706 cur_bol
= edit_bol (edit
, end_mark
- 1);
2708 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2709 if ( option_fill_tabs_with_spaces
) {
2710 if ( option_fake_half_tabs
) {
2711 insert_spaces_tab (edit
, 1);
2713 insert_spaces_tab (edit
, 0);
2716 edit_insert (edit
, '\t');
2718 edit_cursor_move (edit
, edit_bol (edit
, cur_bol
) - edit
->curs1
);
2719 if ( cur_bol
== 0 ) {
2722 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2723 } while (cur_bol
>= start_bol
) ;
2724 edit
->force
|= REDRAW_PAGE
;
2728 edit_move_block_to_left (WEdit
* edit
)
2730 long start_mark
, end_mark
;
2731 long cur_bol
, start_bol
;
2732 int i
, del_tab_width
;
2735 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2738 start_bol
= edit_bol (edit
, start_mark
);
2739 cur_bol
= edit_bol (edit
, end_mark
- 1);
2741 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2742 if (option_fake_half_tabs
) {
2743 del_tab_width
= HALF_TAB_SIZE
;
2745 del_tab_width
= option_tab_spacing
;
2747 next_char
= edit_get_byte (edit
, edit
->curs1
);
2748 if ( next_char
== '\t' ) {
2749 edit_delete (edit
, 1);
2750 } else if ( next_char
== ' ' ) {
2751 for (i
= 1; i
<= del_tab_width
; i
++) {
2752 if ( next_char
== ' ' ) {
2753 edit_delete (edit
, 1);
2755 next_char
= edit_get_byte (edit
, edit
->curs1
);
2758 if ( cur_bol
== 0 ) {
2761 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2762 } while (cur_bol
>= start_bol
) ;
2763 edit
->force
|= REDRAW_PAGE
;