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 */
63 #include "../edit/edit-impl.h"
64 #include "../edit/edit.h"
65 #include "../edit/editlock.h"
66 #include "../edit/editcmddef.h"
67 #include "../edit/edit-widget.h"
68 #include "../edit/editcmd_dialogs.h"
69 #include "../edit/etags.h"
73 /* search and replace: */
74 static int search_create_bookmark
= 0;
75 /* static int search_in_all_charsets = 0; */
77 /* queries on a save */
78 int edit_confirm_save
= 1;
80 static int edit_save_cmd (WEdit
*edit
);
81 static unsigned char *edit_get_block (WEdit
*edit
, long start
,
85 edit_search_cmd_search_create_bookmark(WEdit
* edit
)
87 int found
= 0, books
= 0;
88 int l
= 0, l_last
= -1;
93 if (!mc_search_run(edit
->search
, (void *) edit
, q
, edit
->last_byte
, &len
))
97 l
+= edit_count_lines (edit
, q
, edit
->search
->normal_offset
);
99 book_mark_insert (edit
, l
, BOOK_MARK_FOUND_COLOR
);
103 q
= edit
->search
->normal_offset
+ 1;
107 /* in response to number of bookmarks added because of string being found %d times */
108 message (D_NORMAL
, _("Search"), _(" %d items found, %d bookmarks added "), found
, books
);
110 edit_error_dialog (_ ("Search"), _ (" Search string not found "));
115 edit_search_cmd_callback(const void *user_data
, gsize char_offset
)
117 return edit_get_byte ((WEdit
* )user_data
, (long) char_offset
);
120 void edit_help_cmd (WEdit
* edit
)
122 interactive_display (NULL
, "[Internal File Editor]");
123 edit
->force
|= REDRAW_COMPLETELY
;
127 edit_refresh_cmd (WEdit
* edit
)
132 edit_get_syntax_color (edit
, -1, &color
);
138 #endif /* !HAVE_SLANG */
142 /* If 0 (quick save) then a) create/truncate <filename> file,
143 b) save to <filename>;
144 if 1 (safe save) then a) save to <tempnam>,
145 b) rename <tempnam> to <filename>;
146 if 2 (do backups) then a) save to <tempnam>,
147 b) rename <filename> to <filename.backup_ext>,
148 c) rename <tempnam> to <filename>. */
150 /* returns 0 on error, -1 on abort */
152 edit_save_file (WEdit
*edit
, const char *filename
)
158 gchar
*real_filename
;
159 int this_save_mode
, fd
= -1;
166 if (*filename
!= PATH_SEP
&& edit
->dir
) {
167 real_filename
= concat_dir_and_file (edit
->dir
, filename
);
169 real_filename
= g_strdup(filename
);
172 this_save_mode
= option_save_mode
;
173 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
174 if (!vfs_file_is_local (real_filename
) ||
175 (fd
= mc_open (real_filename
, O_RDONLY
| O_BINARY
)) == -1) {
177 * The file does not exists yet, so no safe save or
178 * backup are necessary.
180 this_save_mode
= EDIT_QUICK_SAVE
;
186 if (this_save_mode
== EDIT_QUICK_SAVE
&&
187 !edit
->skip_detach_prompt
) {
191 rv
= mc_stat (real_filename
, &sb
);
192 if (rv
== 0 && sb
.st_nlink
> 1) {
193 rv
= edit_query_dialog3 (_("Warning"),
194 _(" File has hard-links. Detach before saving? "),
195 _("&Yes"), _("&No"), _("&Cancel"));
198 this_save_mode
= EDIT_SAFE_SAVE
;
201 edit
->skip_detach_prompt
= 1;
204 g_free(real_filename
);
209 /* Prevent overwriting changes from other editor sessions. */
210 if (rv
== 0 && edit
->stat1
.st_mtime
!= 0 && edit
->stat1
.st_mtime
!= sb
.st_mtime
) {
212 /* The default action is "Cancel". */
215 rv
= edit_query_dialog2 (
217 _("The file has been modified in the meantime. Save anyway?"),
221 g_free(real_filename
);
227 if (this_save_mode
!= EDIT_QUICK_SAVE
) {
228 char *savedir
, *saveprefix
;
229 const char *slashpos
;
230 slashpos
= strrchr (real_filename
, PATH_SEP
);
232 savedir
= g_strdup (real_filename
);
233 savedir
[slashpos
- real_filename
+ 1] = '\0';
235 savedir
= g_strdup (".");
236 saveprefix
= concat_dir_and_file (savedir
, "cooledit");
238 fd
= mc_mkstemps (&savename
, saveprefix
, NULL
);
241 g_free(real_filename
);
245 * Close for now because mc_mkstemps use pure open system call
246 * to create temporary file and it needs to be reopened by
247 * VFS-aware mc_open().
251 savename
= g_strdup (real_filename
);
253 mc_chown (savename
, edit
->stat1
.st_uid
, edit
->stat1
.st_gid
);
254 mc_chmod (savename
, edit
->stat1
.st_mode
);
257 mc_open (savename
, O_CREAT
| O_WRONLY
| O_TRUNC
| O_BINARY
,
258 edit
->stat1
.st_mode
)) == -1)
262 if ((p
= edit_get_write_filter (savename
, real_filename
))) {
266 file
= (FILE *) popen (p
, "w");
269 filelen
= edit_write_stream (edit
, file
);
273 if (pclose (file
) != 0) {
274 tmp
= g_strconcat (_(" Error writing to pipe: "),
275 p
, " ", (char *) NULL
);
276 edit_error_dialog (_("Error"), tmp
);
283 tmp
= g_strconcat (_(" Cannot open pipe for writing: "),
284 p
, " ", (char *) NULL
);
286 edit_error_dialog (_("Error"),
287 get_sys_error (tmp
));
296 filelen
= edit
->last_byte
;
297 while (buf
<= (edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1) {
298 if (mc_write (fd
, (char *) edit
->buffers1
[buf
], EDIT_BUF_SIZE
)
306 (fd
, (char *) edit
->buffers1
[buf
],
307 edit
->curs1
& M_EDIT_BUF_SIZE
) !=
308 (edit
->curs1
& M_EDIT_BUF_SIZE
)) {
310 } else if (edit
->curs2
) {
312 buf
= (edit
->curs2
>> S_EDIT_BUF_SIZE
);
315 (char *) edit
->buffers2
[buf
] + EDIT_BUF_SIZE
-
316 (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1,
317 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) !=
318 1 + (edit
->curs2
& M_EDIT_BUF_SIZE
)) {
323 (fd
, (char *) edit
->buffers2
[buf
],
324 EDIT_BUF_SIZE
) != EDIT_BUF_SIZE
) {
335 /* Update the file information, especially the mtime. */
336 if (mc_stat (savename
, &edit
->stat1
) == -1)
340 if (filelen
!= edit
->last_byte
)
343 if (this_save_mode
== EDIT_DO_BACKUP
) {
344 assert (option_backup_ext
!= NULL
);
345 tmp
= g_strconcat (real_filename
, option_backup_ext
,(char *) NULL
);
346 if (mc_rename (real_filename
, tmp
) == -1){
352 if (this_save_mode
!= EDIT_QUICK_SAVE
)
353 if (mc_rename (savename
, real_filename
) == -1)
356 g_free(real_filename
);
359 /* FIXME: Is this safe ?
360 * if (this_save_mode != EDIT_QUICK_SAVE)
361 * mc_unlink (savename);
363 g_free(real_filename
);
368 void menu_save_mode_cmd (void)
372 static char *str_result
;
373 static int save_mode_new
;
374 static const char *str
[] =
378 N_("Do backups -->")};
380 static QuickWidget widgets
[] =
382 {quick_button
, 18, DLG_X
, 7, DLG_Y
, N_("&Cancel"), 0,
383 B_CANCEL
, 0, 0, NULL
, NULL
, NULL
},
384 {quick_button
, 6, DLG_X
, 7, DLG_Y
, N_("&OK"), 0,
385 B_ENTER
, 0, 0, NULL
, NULL
, NULL
},
386 {quick_input
, 23, DLG_X
, 5, DLG_Y
, 0, 9,
387 0, 0, &str_result
, "edit-backup-ext", NULL
, NULL
},
388 {quick_label
, 22, DLG_X
, 4, DLG_Y
, N_("Extension:"), 0,
389 0, 0, 0, NULL
, NULL
, NULL
},
390 {quick_radio
, 4, DLG_X
, 3, DLG_Y
, "", 3,
391 0, &save_mode_new
, (char **) str
, NULL
, NULL
, NULL
},
393 static QuickDialog dialog
=
394 {DLG_X
, DLG_Y
, -1, -1, N_(" Edit Save Mode "), "[Edit Save Mode]",
396 static int i18n_flag
= 0;
404 /* OK/Cancel buttons */
405 l1
= str_term_width1 (_(widgets
[0].text
)) + str_term_width1 (_(widgets
[1].text
)) + 5;
406 maxlen
= max (maxlen
, l1
);
408 for (i
= 0; i
< 3; i
++ ) {
410 maxlen
= max (maxlen
, (size_t) str_term_width1 (str
[i
]) + 7);
414 dlg_x
= maxlen
+ str_term_width1 (_(widgets
[3].text
)) + 5 + 1;
415 widgets
[2].hotkey_pos
= str_term_width1 (_(widgets
[3].text
)); /* input field length */
416 dlg_x
= min (COLS
, dlg_x
);
420 widgets
[1].relative_x
= i
;
421 widgets
[0].relative_x
= i
+ str_term_width1 (_(widgets
[1].text
)) + i
+ 4;
423 widgets
[2].relative_x
= widgets
[3].relative_x
= maxlen
+ 2;
425 for (i
= 0; i
< sizeof (widgets
)/sizeof (widgets
[0]); i
++)
426 widgets
[i
].x_divisions
= dlg_x
;
429 assert (option_backup_ext
!= NULL
);
430 widgets
[2].text
= option_backup_ext
;
431 widgets
[4].value
= option_save_mode
;
432 if (quick_dialog (&dialog
) != B_ENTER
)
434 option_save_mode
= save_mode_new
;
436 g_free (option_backup_ext
);
437 option_backup_ext
= str_result
;
442 edit_set_filename (WEdit
*edit
, const char *f
)
444 g_free (edit
->filename
);
447 edit
->filename
= g_strdup (f
);
448 if (edit
->dir
== NULL
&& *f
!= PATH_SEP
)
450 edit
->dir
= g_strdup (vfs_get_current_dir ());
452 edit
->dir
= g_get_current_dir ();
456 /* Here we want to warn the users of overwriting an existing file,
457 but only if they have made a change to the filename */
458 /* returns 1 on success */
460 edit_save_as_cmd (WEdit
*edit
)
462 /* This heads the 'Save As' dialog box */
465 int different_filename
= 0;
467 exp
= input_expand_dialog (
468 _(" Save As "), _(" Enter file name: "),MC_HISTORY_EDIT_SAVE_AS
, edit
->filename
);
469 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
474 edit
->force
|= REDRAW_COMPLETELY
;
478 if (strcmp (edit
->filename
, exp
)) {
480 different_filename
= 1;
481 if ((file
= mc_open (exp
, O_RDONLY
| O_BINARY
)) != -1) {
482 /* the file exists */
484 /* Overwrite the current file or cancel the operation */
485 if (edit_query_dialog2
487 _(" A file already exists with this name. "),
488 _("&Overwrite"), _("&Cancel"))) {
489 edit
->force
|= REDRAW_COMPLETELY
;
494 edit
->stat1
.st_mode
|= S_IWUSR
;
496 save_lock
= edit_lock_file (exp
);
498 /* filenames equal, check if already locked */
499 if (!edit
->locked
&& !edit
->delete_file
)
500 save_lock
= edit_lock_file (exp
);
503 if (different_filename
)
506 * Allow user to write into saved (under another name) file
507 * even if original file had r/o user permissions.
509 edit
->stat1
.st_mode
|= S_IWRITE
;
512 rv
= edit_save_file (edit
, exp
);
515 /* Succesful, so unlock both files */
516 if (different_filename
) {
518 edit_unlock_file (exp
);
520 edit
->locked
= edit_unlock_file (edit
->filename
);
522 if (edit
->locked
|| save_lock
)
523 edit
->locked
= edit_unlock_file (edit
->filename
);
526 edit_set_filename (edit
, exp
);
529 edit
->delete_file
= 0;
530 if (different_filename
)
531 edit_load_syntax (edit
, NULL
, option_syntax_type
);
532 edit
->force
|= REDRAW_COMPLETELY
;
535 edit_error_dialog (_(" Save As "),
537 (" Cannot save file. ")));
540 /* Failed, so maintain modify (not save) lock */
542 edit_unlock_file (exp
);
544 edit
->force
|= REDRAW_COMPLETELY
;
549 edit
->force
|= REDRAW_COMPLETELY
;
553 /* {{{ Macro stuff starts here */
555 /* creates a macro file if it doesn't exist */
556 static FILE *edit_open_macro_file (const char *r
)
561 filename
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
562 if ((file
= open (filename
, O_CREAT
| O_RDWR
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1){
567 fd
= fopen (filename
, r
);
572 #define MAX_MACROS 1024
573 static int saved_macro
[MAX_MACROS
+ 1];
574 static int saved_macros_loaded
= 0;
577 This is just to stop the macro file be loaded over and over for keys
578 that aren't defined to anything. On slow systems this could be annoying.
584 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++)
585 if (saved_macro
[i
] == k
)
590 /* returns 1 on error */
592 edit_delete_macro (WEdit
* edit
, int k
)
595 struct macro macro
[MAX_MACRO_LENGTH
];
601 if (saved_macros_loaded
)
602 if ((j
= macro_exists (k
)) < 0)
604 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
605 g
= fopen (tmp
, "w");
608 edit_error_dialog (_(" Delete macro "),
609 get_sys_error (_(" Cannot open temp file ")));
612 f
= edit_open_macro_file ("r");
614 edit_error_dialog (_(" Delete macro "),
615 get_sys_error (_(" Cannot open macro file ")));
620 n
= fscanf (f
, ("key '%d 0': "), &s
);
624 while (fscanf (f
, "%hd %hd, ", ¯o
[n
].command
, ¯o
[n
].ch
))
628 fprintf (g
, ("key '%d 0': "), s
);
629 for (i
= 0; i
< n
; i
++)
630 fprintf (g
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
636 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
637 tmp2
= concat_dir_and_file (home_dir
, EDIT_MACRO_FILE
);
638 if (rename ( tmp
, tmp2
) == -1) {
639 edit_error_dialog (_(" Delete macro "),
640 get_sys_error (_(" Cannot overwrite macro file ")));
648 if (saved_macros_loaded
)
649 memmove (saved_macro
+ j
, saved_macro
+ j
+ 1, sizeof (int) * (MAX_MACROS
- j
- 1));
653 /* returns 0 on error */
654 int edit_save_macro_cmd (WEdit
* edit
, struct macro macro
[], int n
)
659 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
660 s
= editcmd_dialog_raw_key_query (_(" Save macro "),
661 _(" Press the macro's new hotkey: "), 1);
662 edit
->force
|= REDRAW_COMPLETELY
;
664 if (edit_delete_macro (edit
, s
))
666 f
= edit_open_macro_file ("a+");
668 fprintf (f
, ("key '%d 0': "), s
);
669 for (i
= 0; i
< n
; i
++)
670 fprintf (f
, "%hd %hd, ", macro
[i
].command
, macro
[i
].ch
);
673 if (saved_macros_loaded
) {
674 for (i
= 0; i
< MAX_MACROS
&& saved_macro
[i
]; i
++);
679 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Cannot open macro file ")));
684 void edit_delete_macro_cmd (WEdit
* edit
)
688 command
= editcmd_dialog_raw_key_query (_ (" Delete macro "),
689 _ (" Press macro hotkey: "), 1);
694 edit_delete_macro (edit
, command
);
697 /* return 0 on error */
698 int edit_load_macro_cmd (WEdit
* edit
, struct macro macro
[], int *n
, int k
)
701 int s
, i
= 0, found
= 0;
705 if (saved_macros_loaded
)
706 if (macro_exists (k
) < 0)
709 if ((f
= edit_open_macro_file ("r"))) {
713 u
= fscanf (f
, ("key '%d 0': "), &s
);
716 if (!saved_macros_loaded
)
717 saved_macro
[i
++] = s
;
720 while (*n
< MAX_MACRO_LENGTH
&& 2 == fscanf (f
, "%hd %hd, ", ¯o
[*n
].command
, ¯o
[*n
].ch
))
723 while (2 == fscanf (f
, "%hd %hd, ", &dummy
.command
, &dummy
.ch
));
728 } while (!found
|| !saved_macros_loaded
);
729 if (!saved_macros_loaded
) {
731 saved_macros_loaded
= 1;
736 edit_error_dialog (_(" Load macro "),
737 get_sys_error (_(" Cannot open macro file ")));
741 /* }}} Macro stuff starts here */
743 /* returns 1 on success */
744 int edit_save_confirm_cmd (WEdit
* edit
)
748 if (edit_confirm_save
) {
749 f
= g_strconcat (_(" Confirm save file? : "), edit
->filename
, " ", NULL
);
750 if (edit_query_dialog2 (_(" Save file "), f
, _("&Save"), _("&Cancel"))){
756 return edit_save_cmd (edit
);
760 /* returns 1 on success */
762 edit_save_cmd (WEdit
*edit
)
764 int res
, save_lock
= 0;
766 if (!edit
->locked
&& !edit
->delete_file
)
767 save_lock
= edit_lock_file (edit
->filename
);
768 res
= edit_save_file (edit
, edit
->filename
);
770 /* Maintain modify (not save) lock on failure */
771 if ((res
> 0 && edit
->locked
) || save_lock
)
772 edit
->locked
= edit_unlock_file (edit
->filename
);
774 /* On failure try 'save as', it does locking on its own */
776 return edit_save_as_cmd (edit
);
777 edit
->force
|= REDRAW_COMPLETELY
;
779 edit
->delete_file
= 0;
787 /* returns 1 on success */
788 int edit_new_cmd (WEdit
* edit
)
790 if (edit
->modified
) {
791 if (edit_query_dialog2 (_ ("Warning"), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("C&ontinue"), _ ("&Cancel"))) {
792 edit
->force
|= REDRAW_COMPLETELY
;
796 edit
->force
|= REDRAW_COMPLETELY
;
798 return edit_renew (edit
); /* if this gives an error, something has really screwed up */
801 /* returns 1 on error */
803 edit_load_file_from_filename (WEdit
* edit
, char *exp
)
805 int prev_locked
= edit
->locked
;
806 char *prev_filename
= g_strdup (edit
->filename
);
808 if (!edit_reload (edit
, exp
)) {
809 g_free (prev_filename
);
814 edit_unlock_file (prev_filename
);
815 g_free (prev_filename
);
820 edit_load_syntax_file (WEdit
* edit
)
825 if (geteuid () == 0) {
826 dir
= query_dialog (_("Syntax file edit"),
827 _(" Which syntax file you want to edit? "), D_NORMAL
, 2,
828 _("&User"), _("&System Wide"));
831 extdir
= concat_dir_and_file (mc_home
, "syntax" PATH_SEP_STR
"Syntax");
832 if (!exist_file(extdir
)) {
834 extdir
= concat_dir_and_file (mc_home_alt
, "syntax" PATH_SEP_STR
"Syntax");
840 buffer
= concat_dir_and_file (home_dir
, EDIT_SYNTAX_FILE
);
841 check_for_default (extdir
, buffer
);
842 edit_load_file_from_filename (edit
, buffer
);
845 edit_load_file_from_filename (edit
, extdir
);
851 edit_load_menu_file (WEdit
* edit
)
859 _(" Which menu file do you want to edit? "), D_NORMAL
,
860 geteuid() ? 2 : 3, _("&Local"), _("&User"), _("&System Wide")
863 menufile
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
865 if (!exist_file (menufile
)) {
867 menufile
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
872 buffer
= g_strdup (EDIT_LOCAL_MENU
);
873 check_for_default (menufile
, buffer
);
874 chmod (buffer
, 0600);
878 buffer
= concat_dir_and_file (home_dir
, EDIT_HOME_MENU
);
879 check_for_default (menufile
, buffer
);
883 buffer
= concat_dir_and_file (mc_home
, EDIT_GLOBAL_MENU
);
884 if (!exist_file (buffer
)) {
886 buffer
= concat_dir_and_file (mc_home_alt
, EDIT_GLOBAL_MENU
);
895 edit_load_file_from_filename (edit
, buffer
);
902 edit_load_cmd (WEdit
*edit
, edit_current_file_t what
)
907 && (edit_query_dialog2
909 _(" Current text was modified without a file save. \n"
910 " Continue discards these changes. "),
911 _("C&ontinue"), _("&Cancel")) == 1)) {
912 edit
->force
|= REDRAW_COMPLETELY
;
917 case EDIT_FILE_COMMON
:
918 exp
= input_expand_dialog (_(" Load "), _(" Enter file name: "),
919 MC_HISTORY_EDIT_LOAD
, edit
->filename
);
923 edit_load_file_from_filename (edit
, exp
);
928 case EDIT_FILE_SYNTAX
:
929 edit_load_syntax_file (edit
);
933 edit_load_menu_file (edit
);
940 edit
->force
|= REDRAW_COMPLETELY
;
945 if mark2 is -1 then marking is from mark1 to the cursor.
946 Otherwise its between the markers. This handles this.
947 Returns 1 if no text is marked.
949 int eval_marks (WEdit
* edit
, long *start_mark
, long *end_mark
)
951 if (edit
->mark1
!= edit
->mark2
) {
952 if (edit
->mark2
>= 0) {
953 *start_mark
= min (edit
->mark1
, edit
->mark2
);
954 *end_mark
= max (edit
->mark1
, edit
->mark2
);
956 *start_mark
= min (edit
->mark1
, edit
->curs1
);
957 *end_mark
= max (edit
->mark1
, edit
->curs1
);
958 edit
->column2
= edit
->curs_col
+ edit
->over_col
;
962 *start_mark
= *end_mark
= 0;
963 edit
->column2
= edit
->column1
= 0;
968 #define space_width 1
971 edit_insert_column_of_text (WEdit
* edit
, unsigned char *data
, int size
, int width
)
975 cursor
= edit
->curs1
;
976 col
= edit_get_col (edit
);
977 for (i
= 0; i
< size
; i
++) {
978 if (data
[i
] == '\n') { /* fill in and move to next line */
981 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
982 l
= width
- (edit_get_col (edit
) - col
);
984 edit_insert (edit
, ' ');
988 for (p
= edit
->curs1
;; p
++) {
989 if (p
== edit
->last_byte
) {
990 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
991 edit_insert_ahead (edit
, '\n');
995 if (edit_get_byte (edit
, p
) == '\n') {
1000 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1001 l
= col
- edit_get_col (edit
);
1002 while (l
>= space_width
) {
1003 edit_insert (edit
, ' ');
1008 edit_insert (edit
, data
[i
]);
1010 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1013 #define TEMP_BUF_LEN 1024
1016 edit_insert_column_of_text_from_file (WEdit
* edit
, int file
)
1020 int blocklen
= -1, width
;
1021 unsigned char *data
;
1022 cursor
= edit
->curs1
;
1023 col
= edit_get_col (edit
);
1024 data
= g_malloc (TEMP_BUF_LEN
);
1025 while ((blocklen
= mc_read (file
, (char *) data
, TEMP_BUF_LEN
)) > 0) {
1026 for (width
= 0; width
< blocklen
; width
++) {
1027 if (data
[width
] == '\n')
1030 for (i
= 0; i
< blocklen
; i
++) {
1031 if (data
[i
] == '\n') { /* fill in and move to next line */
1034 if (edit_get_byte (edit
, edit
->curs1
) != '\n') {
1035 l
= width
- (edit_get_col (edit
) - col
);
1037 edit_insert (edit
, ' ');
1041 for (p
= edit
->curs1
;; p
++) {
1042 if (p
== edit
->last_byte
) {
1043 edit_cursor_move (edit
, edit
->last_byte
- edit
->curs1
);
1044 edit_insert_ahead (edit
, '\n');
1048 if (edit_get_byte (edit
, p
) == '\n') {
1053 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, col
, 0) - edit
->curs1
);
1054 l
= col
- edit_get_col (edit
);
1055 while (l
>= space_width
) {
1056 edit_insert (edit
, ' ');
1061 edit_insert (edit
, data
[i
]);
1064 edit_cursor_move (edit
, cursor
- edit
->curs1
);
1066 edit
->force
|= REDRAW_PAGE
;
1071 edit_block_copy_cmd (WEdit
*edit
)
1073 long start_mark
, end_mark
, current
= edit
->curs1
;
1075 unsigned char *copy_buf
;
1077 edit_update_curs_col (edit
);
1078 if (eval_marks (edit
, &start_mark
, &end_mark
))
1081 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1083 /* all that gets pushed are deletes hence little space is used on the stack */
1085 edit_push_markers (edit
);
1087 if (column_highlighting
) {
1088 edit_insert_column_of_text (edit
, copy_buf
, size
,
1089 abs (edit
->column2
- edit
->column1
));
1092 edit_insert_ahead (edit
, copy_buf
[size
]);
1096 edit_scroll_screen_over_cursor (edit
);
1098 if (column_highlighting
) {
1099 edit_set_markers (edit
, 0, 0, 0, 0);
1100 edit_push_action (edit
, COLUMN_ON
);
1101 column_highlighting
= 0;
1102 } else if (start_mark
< current
&& end_mark
> current
)
1103 edit_set_markers (edit
, start_mark
,
1104 end_mark
+ end_mark
- start_mark
, 0, 0);
1106 edit
->force
|= REDRAW_PAGE
;
1111 edit_block_move_cmd (WEdit
*edit
)
1115 unsigned char *copy_buf
;
1116 long start_mark
, end_mark
;
1120 if (eval_marks (edit
, &start_mark
, &end_mark
))
1122 if (column_highlighting
) {
1123 edit_update_curs_col (edit
);
1125 if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1126 if ((x
> edit
->column1
&& x
< edit
->column2
)
1127 || (x
> edit
->column2
&& x
< edit
->column1
))
1129 } else if (start_mark
<= edit
->curs1
&& end_mark
>= edit
->curs1
)
1132 if ((end_mark
- start_mark
) > option_max_undo
/ 2)
1133 if (edit_query_dialog2
1136 (" Block is large, you may not be able to undo this action. "),
1137 _("C&ontinue"), _("&Cancel")))
1140 edit_push_markers (edit
);
1141 current
= edit
->curs1
;
1142 if (column_highlighting
) {
1143 int size
, c1
, c2
, line
;
1144 line
= edit
->curs_line
;
1145 if (edit
->mark2
< 0)
1146 edit_mark_cmd (edit
, 0);
1147 c1
= min (edit
->column1
, edit
->column2
);
1148 c2
= max (edit
->column1
, edit
->column2
);
1149 copy_buf
= edit_get_block (edit
, start_mark
, end_mark
, &size
);
1151 edit_block_delete_cmd (edit
);
1154 edit_move_to_line (edit
, line
);
1155 edit_cursor_move (edit
,
1156 edit_move_forward3 (edit
,
1157 edit_bol (edit
, edit
->curs1
),
1158 x
, 0) - edit
->curs1
);
1159 edit_insert_column_of_text (edit
, copy_buf
, size
, c2
- c1
);
1161 line
= edit
->curs_line
;
1162 edit_update_curs_col (edit
);
1164 edit_block_delete_cmd (edit
);
1165 edit_move_to_line (edit
, line
);
1166 edit_cursor_move (edit
,
1167 edit_move_forward3 (edit
,
1170 x
, 0) - edit
->curs1
);
1172 edit_set_markers (edit
, 0, 0, 0, 0);
1173 edit_push_action (edit
, COLUMN_ON
);
1174 column_highlighting
= 0;
1176 copy_buf
= g_malloc (end_mark
- start_mark
);
1177 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1178 edit_scroll_screen_over_cursor (edit
);
1180 while (count
< end_mark
) {
1181 copy_buf
[end_mark
- count
- 1] = edit_delete (edit
, 1);
1184 edit_scroll_screen_over_cursor (edit
);
1185 edit_cursor_move (edit
,
1186 current
- edit
->curs1
-
1187 (((current
- edit
->curs1
) >
1188 0) ? end_mark
- start_mark
: 0));
1189 edit_scroll_screen_over_cursor (edit
);
1190 while (count
-- > start_mark
)
1191 edit_insert_ahead (edit
, copy_buf
[end_mark
- count
- 1]);
1192 edit_set_markers (edit
, edit
->curs1
,
1193 edit
->curs1
+ end_mark
- start_mark
, 0, 0);
1195 edit_scroll_screen_over_cursor (edit
);
1197 edit
->force
|= REDRAW_PAGE
;
1201 edit_delete_column_of_text (WEdit
* edit
)
1203 long p
, q
, r
, m1
, m2
;
1207 eval_marks (edit
, &m1
, &m2
);
1208 n
= edit_move_forward (edit
, m1
, 0, m2
) + 1;
1209 c
= edit_move_forward3 (edit
, edit_bol (edit
, m1
), 0, m1
);
1210 d
= edit_move_forward3 (edit
, edit_bol (edit
, m2
), 0, m2
);
1212 b
= max(min (c
, d
), min (edit
->column1
, edit
->column2
));
1213 c
= max (c
, d
+ edit
->over_col
);
1216 r
= edit_bol (edit
, edit
->curs1
);
1217 p
= edit_move_forward3 (edit
, r
, b
, 0);
1218 q
= edit_move_forward3 (edit
, r
, c
, 0);
1223 edit_cursor_move (edit
, p
- edit
->curs1
);
1224 while (q
> p
) { /* delete line between margins */
1225 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
1226 edit_delete (edit
, 1);
1229 if (n
) /* move to next line except on the last delete */
1230 edit_cursor_move (edit
, edit_move_forward (edit
, edit
->curs1
, 1, 0) - edit
->curs1
);
1234 /* if success return 0 */
1236 edit_block_delete (WEdit
*edit
)
1239 long start_mark
, end_mark
;
1240 if (eval_marks (edit
, &start_mark
, &end_mark
))
1242 if (column_highlighting
&& edit
->mark2
< 0)
1243 edit_mark_cmd (edit
, 0);
1244 if ((end_mark
- start_mark
) > option_max_undo
/ 2) {
1245 /* Warning message with a query to continue or cancel the operation */
1246 if (edit_query_dialog2
1249 (" Block is large, you may not be able to undo this action. "),
1250 _("C&ontinue"), _("&Cancel"))) {
1254 edit_push_markers (edit
);
1255 edit_cursor_move (edit
, start_mark
- edit
->curs1
);
1256 edit_scroll_screen_over_cursor (edit
);
1258 if (start_mark
< end_mark
) {
1259 if (column_highlighting
) {
1260 if (edit
->mark2
< 0)
1261 edit_mark_cmd (edit
, 0);
1262 edit_delete_column_of_text (edit
);
1264 while (count
< end_mark
) {
1265 edit_delete (edit
, 1);
1270 edit_set_markers (edit
, 0, 0, 0, 0);
1271 edit
->force
|= REDRAW_PAGE
;
1275 /* returns 1 if canceelled by user */
1276 int edit_block_delete_cmd (WEdit
* edit
)
1278 long start_mark
, end_mark
;
1279 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1280 edit_delete_line (edit
);
1283 return edit_block_delete (edit
);
1286 #define INPUT_INDEX 9
1289 editcmd_find (WEdit
*edit
, gsize
*len
)
1291 off_t search_start
= edit
->search_start
;
1293 long start_mark
= 0;
1294 long end_mark
= edit
->last_byte
;
1297 if (edit
->only_in_selection
) {
1298 mark_res
= eval_marks(edit
, &start_mark
, &end_mark
);
1299 if (mark_res
!= 0) {
1300 edit
->search
->error
= MC_SEARCH_E_NOTFOUND
;
1301 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1304 if (edit
->replace_backwards
) {
1305 if (search_start
> end_mark
|| search_start
<= start_mark
) {
1306 search_start
= end_mark
;
1309 if (search_start
< start_mark
|| search_start
>= end_mark
) {
1310 search_start
= start_mark
;
1314 if (edit
->replace_backwards
)
1315 end_mark
= max(1, edit
->curs1
) - 1;
1317 if (edit
->replace_backwards
) {
1318 search_end
= end_mark
;
1319 while ((int) search_start
>= start_mark
) {
1320 if (search_end
> search_start
+ edit
->search
->original_len
1321 && mc_search_is_fixed_search_str(edit
->search
)) {
1322 search_end
= search_start
+ edit
->search
->original_len
;
1324 if (mc_search_run(edit
->search
, (void *) edit
, search_start
, search_end
, len
)
1325 && edit
->search
->normal_offset
== search_start
) {
1330 edit
->search
->error_str
= g_strdup(_(" Search string not found "));
1332 return mc_search_run(edit
->search
, (void *) edit
, search_start
, end_mark
, len
);
1338 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1339 (and the above) routines to work properly - paul */
1341 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1344 edit_replace_cmd__conv_to_display(char *str
)
1348 tmp
= str_convert_to_display (str
);
1350 if (tmp
&& tmp
->len
){
1354 g_string_free (tmp
, FALSE
);
1357 return g_strdup(str
);
1362 edit_replace_cmd__conv_to_input(char *str
)
1366 tmp
= str_convert_to_input (str
);
1368 if (tmp
&& tmp
->len
){
1372 g_string_free (tmp
, FALSE
);
1375 return g_strdup(str
);
1378 /* call with edit = 0 before shutdown to close memory leaks */
1380 edit_replace_cmd (WEdit
*edit
, int again
)
1382 /* 1 = search string, 2 = replace with */
1383 static char *saved1
= NULL
; /* saved default[123] */
1384 static char *saved2
= NULL
;
1385 char *input1
= NULL
; /* user input from the dialog */
1386 char *input2
= NULL
;
1388 long times_replaced
= 0, last_search
;
1389 gboolean once_found
= FALSE
;
1392 g_free (saved1
), saved1
= NULL
;
1393 g_free (saved2
), saved2
= NULL
;
1397 last_search
= edit
->last_byte
;
1399 edit
->force
|= REDRAW_COMPLETELY
;
1401 if (again
&& !saved1
&& !saved2
)
1405 input1
= g_strdup (saved1
? saved1
: "");
1406 input2
= g_strdup (saved2
? saved2
: "");
1408 char *disp1
= edit_replace_cmd__conv_to_display(g_strdup (saved1
? saved1
: ""));
1409 char *disp2
= edit_replace_cmd__conv_to_display(g_strdup (saved2
? saved2
: ""));
1411 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1413 editcmd_dialog_replace_show (edit
, disp1
, disp2
, &input1
, &input2
);
1418 if (input1
== NULL
|| *input1
== '\0') {
1419 edit
->force
= REDRAW_COMPLETELY
;
1423 input1
= edit_replace_cmd__conv_to_input(input1
);
1424 input2
= edit_replace_cmd__conv_to_input(input2
);
1426 g_free (saved1
), saved1
= g_strdup (input1
);
1427 g_free (saved2
), saved2
= g_strdup (input2
);
1430 mc_search_free(edit
->search
);
1431 edit
->search
= NULL
;
1435 if (!edit
->search
) {
1436 edit
->search
= mc_search_new(input1
, -1);
1437 if (edit
->search
== NULL
) {
1438 edit
->search_start
= edit
->curs1
;
1441 edit
->search
->search_type
= edit
->search_type
;
1442 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1443 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1444 edit
->search
->whole_words
= edit
->whole_words
;
1445 edit
->search
->search_fn
= edit_search_cmd_callback
;
1448 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1
1449 && edit
->replace_backwards
)
1450 edit
->search_start
--;
1452 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1
1453 && !edit
->replace_backwards
)
1454 edit
->search_start
++;
1460 if (! editcmd_find(edit
, &len
)) {
1461 if (!(edit
->search
->error
== MC_SEARCH_E_OK
||
1462 (once_found
&& edit
->search
->error
== MC_SEARCH_E_NOTFOUND
))) {
1463 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1468 new_start
= edit
->search
->normal_offset
;
1470 edit
->search_start
= new_start
= edit
->search
->normal_offset
;
1471 /*returns negative on not found or error in pattern */
1473 if (edit
->search_start
>= 0) {
1476 edit
->found_start
= edit
->search_start
;
1477 i
= edit
->found_len
= len
;
1479 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1480 edit_scroll_screen_over_cursor (edit
);
1484 if (edit
->replace_mode
== 0) {
1486 l
= edit
->curs_row
- edit
->num_widget_lines
/ 3;
1488 edit_scroll_downward (edit
, l
);
1490 edit_scroll_upward (edit
, -l
);
1492 edit_scroll_screen_over_cursor (edit
);
1493 edit
->force
|= REDRAW_PAGE
;
1494 edit_render_keypress (edit
);
1496 /*so that undo stops at each query */
1497 edit_push_key_press (edit
);
1498 /* and prompt 2/3 down */
1499 switch (editcmd_dialog_replace_prompt_show (edit
, input1
, input2
, -1, -1)) {
1503 case B_SKIP_REPLACE
:
1507 edit
->replace_mode
=1;
1511 edit
->replace_mode
= -1;
1515 if (replace_yes
) { /* delete then insert new */
1516 GString
*repl_str
, *tmp_str
;
1517 tmp_str
= g_string_new(input2
);
1519 repl_str
= mc_search_prepare_replace_str (edit
->search
, tmp_str
);
1520 g_string_free(tmp_str
, TRUE
);
1521 if (edit
->search
->error
!= MC_SEARCH_E_OK
)
1523 edit_error_dialog (_ ("Replace"), edit
->search
->error_str
);
1528 edit_delete (edit
, 1);
1530 while (++i
< repl_str
->len
)
1531 edit_insert (edit
, repl_str
->str
[i
]);
1533 g_string_free(repl_str
, TRUE
);
1534 edit
->found_len
= i
;
1536 /* so that we don't find the same string again */
1537 if (edit
->replace_backwards
) {
1538 last_search
= edit
->search_start
;
1539 edit
->search_start
--;
1541 edit
->search_start
+= i
;
1542 last_search
= edit
->last_byte
;
1544 edit_scroll_screen_over_cursor (edit
);
1546 const char *msg
= _(" Replace ");
1547 /* try and find from right here for next search */
1548 edit
->search_start
= edit
->curs1
;
1549 edit_update_curs_col (edit
);
1551 edit
->force
|= REDRAW_PAGE
;
1552 edit_render_keypress (edit
);
1553 if (times_replaced
) {
1554 message (D_NORMAL
, msg
, _(" %ld replacements made. "),
1557 query_dialog (msg
, _(" Search string not found "),
1558 D_NORMAL
, 1, _("&OK"));
1559 edit
->replace_mode
= -1;
1561 } while (edit
->replace_mode
>= 0);
1563 edit
->force
= REDRAW_COMPLETELY
;
1564 edit_scroll_screen_over_cursor (edit
);
1571 void edit_search_cmd (WEdit
* edit
, int again
)
1573 char *search_string
= NULL
, *search_string_dup
= NULL
;
1580 if (edit
->search
!= NULL
) {
1581 search_string
= g_strndup(edit
->search
->original
, edit
->search
->original_len
);
1582 search_string_dup
= search_string
;
1585 history
= history_get (MC_HISTORY_SHARED_SEARCH
);
1586 if (history
!= NULL
&& history
->data
!= NULL
) {
1587 search_string_dup
= search_string
= (char *) g_strdup(history
->data
);
1588 history
= g_list_first (history
);
1589 g_list_foreach (history
, (GFunc
) g_free
, NULL
);
1590 g_list_free (history
);
1592 edit
->search_start
= edit
->curs1
;
1598 if (search_string
&& *search_string
) {
1599 tmp
= str_convert_to_display (search_string
);
1601 g_free(search_string_dup
);
1602 search_string_dup
= NULL
;
1604 if (tmp
&& tmp
->len
)
1605 search_string
= search_string_dup
= tmp
->str
;
1606 g_string_free (tmp
, FALSE
);
1608 #endif /* HAVE_CHARSET */
1609 editcmd_dialog_search_show (edit
, &search_string
);
1611 if (search_string
&& *search_string
) {
1612 tmp
= str_convert_to_input (search_string
);
1613 if (tmp
&& tmp
->len
)
1614 search_string
= tmp
->str
;
1616 g_string_free (tmp
, FALSE
);
1618 if (search_string_dup
)
1619 g_free(search_string_dup
);
1621 #endif /* HAVE_CHARSET */
1623 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1625 if (!search_string
) {
1626 edit
->force
|= REDRAW_COMPLETELY
;
1627 edit_scroll_screen_over_cursor (edit
);
1632 mc_search_free(edit
->search
);
1633 edit
->search
= NULL
;
1637 if (!edit
->search
) {
1638 edit
->search
= mc_search_new(search_string
, -1);
1639 if (edit
->search
== NULL
) {
1640 edit
->search_start
= edit
->curs1
;
1643 edit
->search
->search_type
= edit
->search_type
;
1644 edit
->search
->is_all_charsets
= edit
->all_codepages
;
1645 edit
->search
->is_case_sentitive
= edit
->replace_case
;
1646 edit
->search
->whole_words
= edit
->whole_words
;
1647 edit
->search
->search_fn
= edit_search_cmd_callback
;
1650 if (search_create_bookmark
) {
1651 edit_search_cmd_search_create_bookmark(edit
);
1653 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
+ 1 && edit
->replace_backwards
)
1654 edit
->search_start
--;
1656 if (edit
->found_len
&& edit
->search_start
== edit
->found_start
- 1 && !edit
->replace_backwards
)
1657 edit
->search_start
++;
1660 if (editcmd_find(edit
, &len
)) {
1661 edit
->found_start
= edit
->search_start
= edit
->search
->normal_offset
;
1662 edit
->found_len
= len
;
1664 edit_cursor_move (edit
, edit
->search_start
- edit
->curs1
);
1665 edit_scroll_screen_over_cursor (edit
);
1666 if (edit
->replace_backwards
)
1667 edit
->search_start
--;
1669 edit
->search_start
++;
1671 edit
->search_start
= edit
->curs1
;
1672 if (edit
->search
->error_str
)
1673 edit_error_dialog (_ ("Search"), edit
->search
->error_str
);
1677 edit
->force
|= REDRAW_COMPLETELY
;
1678 edit_scroll_screen_over_cursor (edit
);
1683 * Check if it's OK to close the editor. If there are unsaved changes,
1684 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
1687 edit_ok_to_exit (WEdit
*edit
)
1689 if (!edit
->modified
)
1692 switch (edit_query_dialog3
1693 (_("Quit"), _(" File was modified, Save with exit? "),
1694 _("&Cancel quit"), _("&Yes"), _("&No"))) {
1696 edit_push_markers (edit
);
1697 edit_set_markers (edit
, 0, 0, 0, 0);
1698 if (!edit_save_cmd (edit
))
1711 /* Return a null terminated length of text. Result must be g_free'd */
1712 static unsigned char *
1713 edit_get_block (WEdit
*edit
, long start
, long finish
, int *l
)
1715 unsigned char *s
, *r
;
1716 r
= s
= g_malloc (finish
- start
+ 1);
1717 if (column_highlighting
) {
1719 /* copy from buffer, excluding chars that are out of the column 'margins' */
1720 while (start
< finish
) {
1722 x
= edit_move_forward3 (edit
, edit_bol (edit
, start
), 0,
1724 c
= edit_get_byte (edit
, start
);
1725 if ((x
>= edit
->column1
&& x
< edit
->column2
)
1726 || (x
>= edit
->column2
&& x
< edit
->column1
) || c
== '\n') {
1733 *l
= finish
- start
;
1734 while (start
< finish
)
1735 *s
++ = edit_get_byte (edit
, start
++);
1741 /* save block, returns 1 on success */
1743 edit_save_block (WEdit
* edit
, const char *filename
, long start
,
1749 mc_open (filename
, O_CREAT
| O_WRONLY
| O_TRUNC
,
1750 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
| O_BINARY
)) == -1)
1753 if (column_highlighting
) {
1755 r
= mc_write (file
, VERTICAL_MAGIC
, sizeof(VERTICAL_MAGIC
));
1757 unsigned char *block
, *p
;
1758 p
= block
= edit_get_block (edit
, start
, finish
, &len
);
1760 r
= mc_write (file
, p
, len
);
1771 len
= finish
- start
;
1772 buf
= g_malloc (TEMP_BUF_LEN
);
1773 while (start
!= finish
) {
1774 end
= min (finish
, start
+ TEMP_BUF_LEN
);
1775 for (; i
< end
; i
++)
1776 buf
[i
- start
] = edit_get_byte (edit
, i
);
1777 len
-= mc_write (file
, (char *) buf
, end
- start
);
1788 /* copies a block to clipboard file */
1789 static int edit_save_block_to_clip_file (WEdit
* edit
, long start
, long finish
)
1793 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1794 ret
= edit_save_block (edit
, tmp
, start
, finish
);
1800 void edit_paste_from_history (WEdit
*edit
)
1803 edit_error_dialog (_(" Error "), _(" This function is not implemented. "));
1806 int edit_copy_to_X_buf_cmd (WEdit
* edit
)
1808 long start_mark
, end_mark
;
1809 if (eval_marks (edit
, &start_mark
, &end_mark
))
1811 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1812 edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
1815 edit_mark_cmd (edit
, 1);
1819 int edit_cut_to_X_buf_cmd (WEdit
* edit
)
1821 long start_mark
, end_mark
;
1822 if (eval_marks (edit
, &start_mark
, &end_mark
))
1824 if (!edit_save_block_to_clip_file (edit
, start_mark
, end_mark
)) {
1825 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
1828 edit_block_delete_cmd (edit
);
1829 edit_mark_cmd (edit
, 1);
1833 void edit_paste_from_X_buf_cmd (WEdit
* edit
)
1836 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1837 edit_insert_file (edit
, tmp
);
1843 * Ask user for the line and go to that line.
1844 * Negative numbers mean line from the end (i.e. -1 is the last line).
1847 edit_goto_cmd (WEdit
*edit
)
1850 static long line
= 0; /* line as typed, saved as default */
1855 g_snprintf (s
, sizeof (s
), "%ld", line
);
1856 f
= input_dialog (_(" Goto line "), _(" Enter line: "), MC_HISTORY_EDIT_GOTO_LINE
,
1866 l
= strtol (f
, &error
, 0);
1874 l
= edit
->total_lines
+ l
+ 2;
1875 edit_move_display (edit
, l
- edit
->num_widget_lines
/ 2 - 1);
1876 edit_move_to_line (edit
, l
- 1);
1877 edit
->force
|= REDRAW_COMPLETELY
;
1882 /* Return 1 on success */
1884 edit_save_block_cmd (WEdit
*edit
)
1886 long start_mark
, end_mark
;
1889 if (eval_marks (edit
, &start_mark
, &end_mark
))
1892 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1894 input_expand_dialog (_(" Save Block "), _(" Enter file name: "),
1895 MC_HISTORY_EDIT_SAVE_BLOCK
,
1898 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1904 if (edit_save_block (edit
, exp
, start_mark
, end_mark
)) {
1906 edit
->force
|= REDRAW_COMPLETELY
;
1910 edit_error_dialog (_(" Save Block "),
1912 (" Cannot save file. ")));
1916 edit
->force
|= REDRAW_COMPLETELY
;
1921 /* returns 1 on success */
1923 edit_insert_file_cmd (WEdit
*edit
)
1928 tmp
= concat_dir_and_file (home_dir
, EDIT_CLIP_FILE
);
1929 exp
= input_expand_dialog (_(" Insert File "), _(" Enter file name: "),
1930 MC_HISTORY_EDIT_INSERT_FILE
,
1933 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
1939 if (edit_insert_file (edit
, exp
)) {
1941 edit
->force
|= REDRAW_COMPLETELY
;
1945 edit_error_dialog (_(" Insert File "),
1947 (" Cannot insert file. ")));
1951 edit
->force
|= REDRAW_COMPLETELY
;
1955 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
1956 int edit_sort_cmd (WEdit
* edit
)
1958 static char *old
= 0;
1960 long start_mark
, end_mark
;
1963 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
1964 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
1968 tmp
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
);
1969 edit_save_block (edit
, tmp
, start_mark
, end_mark
);
1972 exp
= input_dialog (_(" Run Sort "),
1973 _(" Enter sort options (see manpage) separated by whitespace: "),
1974 MC_HISTORY_EDIT_SORT
, (old
!= NULL
) ? old
: "");
1980 tmp
= g_strconcat (" sort ", exp
, " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
, " > ",
1981 home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
1985 if (e
== -1 || e
== 127) {
1986 edit_error_dialog (_(" Sort "),
1987 get_sys_error (_(" Cannot execute sort command ")));
1990 sprintf (q
, "%d ", e
);
1991 tmp
= g_strconcat (_(" Sort returned non-zero: "), q
, (char *) NULL
);
1992 edit_error_dialog (_(" Sort "), tmp
);
1998 edit
->force
|= REDRAW_COMPLETELY
;
2000 if (edit_block_delete_cmd (edit
))
2002 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
2003 edit_insert_file (edit
, tmp
);
2009 * Ask user for a command, execute it and paste its output back to the
2013 edit_ext_cmd (WEdit
*edit
)
2019 input_dialog (_("Paste output of external command"),
2020 _("Enter shell command(s):"),
2021 MC_HISTORY_EDIT_PASTE_EXTCMD
, NULL
);
2026 tmp
= g_strconcat (exp
, " > ", home_dir
, PATH_SEP_STR EDIT_TEMP_FILE
, (char *) NULL
);
2032 edit_error_dialog (_("External command"),
2033 get_sys_error (_("Cannot execute command")));
2037 edit
->force
|= REDRAW_COMPLETELY
;
2038 tmp
= concat_dir_and_file (home_dir
, EDIT_TEMP_FILE
);
2039 edit_insert_file (edit
, tmp
);
2044 /* if block is 1, a block must be highlighted and the shell command
2045 processes it. If block is 0 the shell command is a straight system
2046 command, that just produces some output which is to be inserted */
2048 edit_block_process_cmd (WEdit
*edit
, const char *shell_cmd
, int block
)
2050 long start_mark
, end_mark
;
2052 FILE *script_home
= NULL
;
2053 FILE *script_src
= NULL
;
2054 FILE *block_file
= NULL
;
2055 gchar
*o
, *h
, *b
, *tmp
;
2056 char *quoted_name
= NULL
;
2058 o
= g_strconcat (mc_home
, shell_cmd
, (char *) NULL
); /* original source script */
2059 h
= g_strconcat (home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, (char *) NULL
); /* home script */
2060 b
= concat_dir_and_file (home_dir
, EDIT_BLOCK_FILE
); /* block file */
2062 if (!(script_home
= fopen (h
, "r"))) {
2063 if (!(script_home
= fopen (h
, "w"))) {
2064 tmp
= g_strconcat (_("Error creating script:"), h
, (char *) NULL
);
2065 edit_error_dialog ("", get_sys_error (tmp
));
2067 goto edit_block_process_cmd__EXIT
;
2069 if (!(script_src
= fopen (o
, "r"))) {
2070 o
= g_strconcat (mc_home_alt
, shell_cmd
, (char *) NULL
);
2071 if (!(script_src
= fopen (o
, "r"))) {
2072 fclose (script_home
);
2074 tmp
= g_strconcat (_("Error reading script:"), o
, (char *) NULL
);
2075 edit_error_dialog ("", get_sys_error (tmp
));
2077 goto edit_block_process_cmd__EXIT
;
2080 while (fgets (buf
, sizeof (buf
), script_src
))
2081 fputs (buf
, script_home
);
2082 if (fclose (script_home
)) {
2083 tmp
= g_strconcat (_("Error closing script:"), h
, (char *) NULL
);
2084 edit_error_dialog ("", get_sys_error (tmp
));
2086 goto edit_block_process_cmd__EXIT
;
2089 tmp
= g_strconcat (_("Script created:"), h
, (char *) NULL
);
2090 edit_error_dialog ("", get_sys_error (tmp
));
2096 if (block
) { /* for marked block run indent formatter */
2097 if (eval_marks (edit
, &start_mark
, &end_mark
)) {
2098 edit_error_dialog (_("Process block"),
2100 (" You must first highlight a block of text. "));
2101 goto edit_block_process_cmd__EXIT
;
2103 edit_save_block (edit
, b
, start_mark
, end_mark
);
2104 quoted_name
= name_quote (edit
->filename
, 0);
2107 * Initial space is to avoid polluting bash history.
2109 * $1 - name of the edited file (to check its extension etc).
2110 * $2 - file containing the current block.
2111 * $3 - file where error messages should be put
2112 * (for compatibility with old scripts).
2114 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ", quoted_name
,
2115 " ", home_dir
, PATH_SEP_STR EDIT_BLOCK_FILE
" /dev/null", (char *) NULL
);
2120 * No block selected, just execute the command for the file.
2122 * $1 - name of the edited file.
2124 tmp
= g_strconcat (" ", home_dir
, PATH_SEP_STR EDIT_DIR
, shell_cmd
, " ",
2125 quoted_name
, (char *) NULL
);
2129 g_free (quoted_name
);
2130 close_error_pipe (D_NORMAL
, NULL
);
2132 edit_refresh_cmd (edit
);
2133 edit
->force
|= REDRAW_COMPLETELY
;
2135 /* insert result block */
2137 if (edit_block_delete_cmd (edit
))
2138 goto edit_block_process_cmd__EXIT
;
2139 edit_insert_file (edit
, b
);
2140 if ((block_file
= fopen (b
, "w")))
2141 fclose (block_file
);
2142 goto edit_block_process_cmd__EXIT
;
2144 edit_block_process_cmd__EXIT
:
2151 /* prints at the cursor */
2152 /* returns the number of chars printed */
2153 int edit_print_string (WEdit
* e
, const char *s
)
2157 edit_execute_cmd (e
, -1, (unsigned char) s
[i
++]);
2158 e
->force
|= REDRAW_COMPLETELY
;
2159 edit_update_screen (e
);
2164 static void pipe_mail (WEdit
*edit
, char *to
, char *subject
, char *cc
)
2169 to
= name_quote (to
, 0);
2170 subject
= name_quote (subject
, 0);
2171 cc
= name_quote (cc
, 0);
2172 s
= g_strconcat ("mail -s ", subject
, *cc
? " -c " : "" , cc
, " ", to
, (char *) NULL
);
2184 for (i
= 0; i
< edit
->last_byte
; i
++)
2185 fputc (edit_get_byte (edit
, i
), p
);
2190 #define MAIL_DLG_HEIGHT 12
2192 void edit_mail_dialog (WEdit
* edit
)
2195 char *tmail_subject
;
2198 static char *mail_cc_last
= 0;
2199 static char *mail_subject_last
= 0;
2200 static char *mail_to_last
= 0;
2202 QuickDialog Quick_input
=
2203 {50, MAIL_DLG_HEIGHT
, -1, 0, N_(" Mail "),
2204 "[Input Line Keys]", 0, 0};
2206 QuickWidget quick_widgets
[] =
2208 {quick_button
, 6, 10, 9, MAIL_DLG_HEIGHT
, N_("&Cancel"), 0, B_CANCEL
, 0,
2209 0, NULL
, NULL
, NULL
},
2210 {quick_button
, 2, 10, 9, MAIL_DLG_HEIGHT
, N_("&OK"), 0, B_ENTER
, 0,
2211 0, NULL
, NULL
, NULL
},
2212 {quick_input
, 3, 50, 8, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2213 0, "mail-dlg-input", NULL
, NULL
},
2214 {quick_label
, 2, 50, 7, MAIL_DLG_HEIGHT
, N_(" Copies to"), 0, 0, 0,
2216 {quick_input
, 3, 50, 6, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2217 0, "mail-dlg-input-2", NULL
, NULL
},
2218 {quick_label
, 2, 50, 5, MAIL_DLG_HEIGHT
, N_(" Subject"), 0, 0, 0,
2220 {quick_input
, 3, 50, 4, MAIL_DLG_HEIGHT
, "", 44, 0, 0,
2221 0, "mail-dlg-input-3", NULL
, NULL
},
2222 {quick_label
, 2, 50, 3, MAIL_DLG_HEIGHT
, N_(" To"), 0, 0, 0,
2224 {quick_label
, 2, 50, 2, MAIL_DLG_HEIGHT
, N_(" mail -s <subject> -c <cc> <to>"), 0, 0, 0,
2228 quick_widgets
[2].str_result
= &tmail_cc
;
2229 quick_widgets
[2].text
= mail_cc_last
? mail_cc_last
: "";
2230 quick_widgets
[4].str_result
= &tmail_subject
;
2231 quick_widgets
[4].text
= mail_subject_last
? mail_subject_last
: "";
2232 quick_widgets
[6].str_result
= &tmail_to
;
2233 quick_widgets
[6].text
= mail_to_last
? mail_to_last
: "";
2235 Quick_input
.widgets
= quick_widgets
;
2237 if (quick_dialog (&Quick_input
) != B_CANCEL
) {
2238 g_free (mail_cc_last
);
2239 g_free (mail_subject_last
);
2240 g_free (mail_to_last
);
2241 mail_cc_last
= tmail_cc
;
2242 mail_subject_last
= tmail_subject
;
2243 mail_to_last
= tmail_to
;
2244 pipe_mail (edit
, mail_to_last
, mail_subject_last
, mail_cc_last
);
2249 /*******************/
2250 /* Word Completion */
2251 /*******************/
2253 static gboolean
is_break_char(char c
)
2255 return (isspace(c
) || strchr("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c
));
2258 /* find first character of current word */
2259 static int edit_find_word_start (WEdit
*edit
, long *word_start
, int *word_len
)
2263 /* return if at begin of file */
2264 if (edit
->curs1
<= 0)
2267 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- 1);
2268 /* return if not at end or in word */
2269 if (is_break_char(c
))
2272 /* search start of word to be completed */
2274 /* return if at begin of file */
2275 if (edit
->curs1
- i
< 0)
2279 c
= (unsigned char) edit_get_byte (edit
, edit
->curs1
- i
);
2281 if (is_break_char(c
)) {
2282 /* return if word starts with digit */
2286 *word_start
= edit
->curs1
- (i
- 1); /* start found */
2295 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2297 /* collect the possible completions */
2299 edit_collect_completions (WEdit
*edit
, long start
, int word_len
,
2300 char *match_expr
, struct selection
*compl,
2303 int max_len
= 0, i
, skip
;
2308 srch
= mc_search_new(match_expr
, -1);
2312 srch
->search_type
= MC_SEARCH_T_REGEX
;
2313 srch
->is_case_sentitive
= TRUE
;
2314 srch
->search_fn
= edit_search_cmd_callback
;
2316 /* collect max MAX_WORD_COMPLETIONS completions */
2318 while (*num
< MAX_WORD_COMPLETIONS
) {
2319 /* get next match */
2320 if (mc_search_run (srch
, (void *) edit
, start
+1, edit
->last_byte
, &len
) == FALSE
)
2322 start
= srch
->normal_offset
;
2324 /* add matched completion if not yet added */
2325 temp
= g_string_new("");
2326 for (i
= 0; i
< len
; i
++){
2327 skip
= edit_get_byte(edit
, start
+i
);
2330 g_string_append_c (temp
, skip
);
2335 for (i
= 0; i
< *num
; i
++) {
2338 (char *) &compl[i
].text
[word_len
],
2339 (char *) &temp
->str
[word_len
],
2340 max (len
, compl[i
].len
) - word_len
2343 break; /* skip it, already added */
2347 g_string_free(temp
, TRUE
);
2351 compl[*num
].text
= temp
->str
;
2352 compl[*num
].len
= temp
->len
;
2354 g_string_free(temp
, FALSE
);
2356 /* note the maximal length needed for the completion dialog */
2360 mc_search_free(srch
);
2365 * Complete current word using regular expression search
2366 * backwards beginning at the current cursor position.
2369 edit_complete_word_cmd (WEdit
*edit
)
2371 int word_len
= 0, i
, num_compl
= 0, max_len
;
2372 long word_start
= 0;
2373 unsigned char *bufpos
;
2375 struct selection
compl[MAX_WORD_COMPLETIONS
]; /* completions */
2377 /* search start of word to be completed */
2378 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2381 /* prepare match expression */
2382 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2383 [word_start
& M_EDIT_BUF_SIZE
];
2385 match_expr
= g_strdup_printf ("(^|\\s)%.*s[^\\s\\.=\\+\\{\\}\\[\\]\\(\\)\\\\\\!\\,<>\\?\\/@#\\$%%\\^&\\*\\~\\|\\\"'\\:\\;]+", word_len
, bufpos
);
2387 /* collect the possible completions */
2388 /* start search from begin to end of file */
2390 edit_collect_completions (edit
, 0, word_len
, match_expr
,
2391 (struct selection
*) &compl, &num_compl
);
2393 if (num_compl
> 0) {
2394 /* insert completed word if there is only one match */
2395 if (num_compl
== 1) {
2396 for (i
= word_len
; i
< compl[0].len
; i
++)
2397 edit_insert (edit
, *(compl[0].text
+ i
));
2399 /* more than one possible completion => ask the user */
2401 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2402 /* !!! pressed again the selection dialog pops up, but that !!! */
2403 /* !!! seems to require a further internal state !!! */
2406 /* let the user select the preferred completion */
2407 editcmd_dialog_completion_show (edit
, max_len
, word_len
,
2408 (struct selection
*) &compl,
2413 g_free (match_expr
);
2414 /* release memory before return */
2415 for (i
= 0; i
< num_compl
; i
++)
2416 g_free (compl[i
].text
);
2421 edit_select_codepage_cmd (WEdit
*edit
)
2424 const char *cp_id
= NULL
;
2425 if (do_select_codepage ()) {
2426 cp_id
= get_codepage_id (source_codepage
>= 0 ?
2427 source_codepage
: display_codepage
);
2429 if (cp_id
!= NULL
) {
2431 conv
= str_crt_conv_from (cp_id
);
2432 if (conv
!= INVALID_CONV
) {
2433 if (edit
->converter
!= str_cnv_from_term
)
2434 str_close_conv (edit
->converter
);
2435 edit
->converter
= conv
;
2441 edit
->utf8
= str_isutf8 (cp_id
);
2444 edit
->force
= REDRAW_COMPLETELY
;
2445 edit_refresh_cmd (edit
);
2450 edit_insert_literal_cmd (WEdit
*edit
)
2452 int char_for_insertion
=
2453 editcmd_dialog_raw_key_query (_(" Insert Literal "),
2454 _(" Press any key: "), 0);
2455 edit_execute_key_command (edit
, -1,
2456 ascii_alpha_to_cntrl (char_for_insertion
));
2460 edit_execute_macro_cmd (WEdit
*edit
)
2463 CK_Macro (editcmd_dialog_raw_key_query
2464 (_(" Execute Macro "), _(" Press macro hotkey: "),
2466 if (command
== CK_Macro (0))
2467 command
= CK_Insert_Char
;
2469 edit_execute_key_command (edit
, command
, -1);
2473 edit_begin_end_macro_cmd(WEdit
*edit
)
2477 /* edit is a pointer to the widget */
2481 0 ? CK_Begin_Record_Macro
: CK_End_Record_Macro
;
2482 edit_execute_key_command (edit
, command
, -1);
2487 edit_load_forward_cmd (WEdit
*edit
)
2489 if (edit
->modified
) {
2490 if (edit_query_dialog2
2492 _(" Current text was modified without a file save. \n"
2493 " Continue discards these changes. "), _("C&ontinue"),
2495 edit
->force
|= REDRAW_COMPLETELY
;
2499 if ( edit_stack_iterator
+ 1 < MAX_HISTORY_MOVETO
) {
2500 if ( edit_history_moveto
[edit_stack_iterator
+ 1].line
< 1 ) {
2503 edit_stack_iterator
++;
2504 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2505 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2506 edit_history_moveto
[edit_stack_iterator
].line
);
2517 edit_load_back_cmd (WEdit
*edit
)
2519 if (edit
->modified
) {
2520 if (edit_query_dialog2
2522 _(" Current text was modified without a file save. \n"
2523 " Continue discards these changes. "), _("C&ontinue"),
2525 edit
->force
|= REDRAW_COMPLETELY
;
2529 if ( edit_stack_iterator
> 0 ) {
2530 edit_stack_iterator
--;
2531 if ( edit_history_moveto
[edit_stack_iterator
].filename
) {
2532 edit_reload_line (edit
, edit_history_moveto
[edit_stack_iterator
].filename
,
2533 edit_history_moveto
[edit_stack_iterator
].line
);
2544 edit_get_match_keyword_cmd (WEdit
*edit
)
2550 long word_start
= 0;
2551 unsigned char *bufpos
;
2555 char *tagfile
= NULL
;
2557 etags_hash_t def_hash
[MAX_DEFINITIONS
];
2559 for ( i
= 0; i
< MAX_DEFINITIONS
; i
++) {
2560 def_hash
[i
].filename
= NULL
;
2563 /* search start of word to be completed */
2564 if (!edit_find_word_start (edit
, &word_start
, &word_len
))
2567 /* prepare match expression */
2568 bufpos
= &edit
->buffers1
[word_start
>> S_EDIT_BUF_SIZE
]
2569 [word_start
& M_EDIT_BUF_SIZE
];
2570 match_expr
= g_strdup_printf ("%.*s", word_len
, bufpos
);
2572 ptr
= g_get_current_dir ();
2573 path
= g_strconcat (ptr
, G_DIR_SEPARATOR_S
, (char *) NULL
);
2576 /* Recursive search file 'TAGS' in parent dirs */
2578 ptr
= g_path_get_dirname (path
);
2579 g_free(path
); path
= ptr
;
2581 tagfile
= g_build_filename (path
, TAGS_NAME
, (char *) NULL
);
2582 if ( exist_file (tagfile
) )
2584 } while (strcmp( path
, G_DIR_SEPARATOR_S
) != 0);
2587 num_def
= etags_set_definition_hash(tagfile
, path
, match_expr
, (etags_hash_t
*) &def_hash
);
2592 max_len
= MAX_WIDTH_DEF_DIALOG
;
2594 if ( num_def
> 0 ) {
2595 editcmd_dialog_select_definition_show (edit
, match_expr
, max_len
, word_len
,
2596 (etags_hash_t
*) &def_hash
,
2599 g_free (match_expr
);
2603 edit_move_block_to_right (WEdit
* edit
)
2605 long start_mark
, end_mark
;
2606 long cur_bol
, start_bol
;
2608 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2611 start_bol
= edit_bol (edit
, start_mark
);
2612 cur_bol
= edit_bol (edit
, end_mark
- 1);
2614 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2615 if ( option_fill_tabs_with_spaces
) {
2616 if ( option_fake_half_tabs
) {
2617 insert_spaces_tab (edit
, 1);
2619 insert_spaces_tab (edit
, 0);
2622 edit_insert (edit
, '\t');
2624 edit_cursor_move (edit
, edit_bol (edit
, cur_bol
) - edit
->curs1
);
2625 if ( cur_bol
== 0 ) {
2628 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2629 } while (cur_bol
>= start_bol
) ;
2630 edit
->force
|= REDRAW_PAGE
;
2634 edit_move_block_to_left (WEdit
* edit
)
2636 long start_mark
, end_mark
;
2637 long cur_bol
, start_bol
;
2638 int i
, del_tab_width
;
2641 if ( eval_marks (edit
, &start_mark
, &end_mark
) )
2644 start_bol
= edit_bol (edit
, start_mark
);
2645 cur_bol
= edit_bol (edit
, end_mark
- 1);
2647 edit_cursor_move (edit
, cur_bol
- edit
->curs1
);
2648 if (option_fake_half_tabs
) {
2649 del_tab_width
= HALF_TAB_SIZE
;
2651 del_tab_width
= option_tab_spacing
;
2653 next_char
= edit_get_byte (edit
, edit
->curs1
);
2654 if ( next_char
== '\t' ) {
2655 edit_delete (edit
, 1);
2656 } else if ( next_char
== ' ' ) {
2657 for (i
= 1; i
<= del_tab_width
; i
++) {
2658 if ( next_char
== ' ' ) {
2659 edit_delete (edit
, 1);
2661 next_char
= edit_get_byte (edit
, edit
->curs1
);
2664 if ( cur_bol
== 0 ) {
2667 cur_bol
= edit_bol (edit
, cur_bol
- 1);
2668 } while (cur_bol
>= start_bol
) ;
2669 edit
->force
|= REDRAW_PAGE
;