Merge branch '2123_crash_while_copy'
[midnight-commander.git] / src / editor / editcmd.c
blob2c5949bca26115d94d85eb898b6915f09b770b53
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
21 02110-1301, USA.
25 /** \file
26 * \brief Source: editor high level editing commands
27 * \author Paul Sheer
28 * \date 1996, 1997
31 /* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
33 #include <config.h>
35 #include <assert.h>
36 #include <ctype.h>
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <sys/stat.h>
45 #include <stdlib.h>
46 #include <fcntl.h>
48 #include "lib/global.h"
49 #include "lib/tty/tty.h"
50 #include "lib/tty/key.h" /* XCTRL */
51 #include "lib/mcconfig.h"
52 #include "lib/skin.h"
53 #include "lib/strutil.h" /* utf string functions */
54 #include "lib/lock.h"
55 #include "lib/vfs/mc-vfs/vfs.h"
57 #include "src/history.h"
58 #include "src/widget.h" /* listbox_new() */
59 #include "src/layout.h" /* clr_scr() */
60 #include "src/main.h" /* mc_home, midnight_shutdown */
61 #include "src/setup.h" /* option_tab_spacing */
62 #include "src/help.h" /* interactive_display() */
63 #include "src/wtools.h" /* message() */
64 #include "src/charsets.h"
65 #include "src/selcodepage.h"
66 #include "src/cmddef.h"
67 #include "src/clipboard.h" /* copy_file_to_ext_clip, paste_to_file_from_ext_clip */
69 #include "src/editor/edit-impl.h"
70 #include "src/editor/edit-widget.h"
71 #include "src/editor/editcmd_dialogs.h"
72 #include "src/editor/etags.h"
74 /* globals: */
76 /* search and replace: */
77 int search_create_bookmark = 0;
78 /* static int search_in_all_charsets = 0; */
80 /* queries on a save */
81 int edit_confirm_save = 1;
83 static int edit_save_cmd (WEdit * edit);
84 static unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l);
86 static void
87 edit_search_cmd_search_create_bookmark (WEdit * edit)
89 int found = 0, books = 0;
90 long l = 0, l_last = -1;
91 long q = 0;
92 gsize len = 0;
94 search_create_bookmark = 0;
95 book_mark_flush (edit, -1);
97 for (;;)
99 if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
100 break;
101 if (found == 0)
102 edit->search_start = edit->search->normal_offset;
103 found++;
104 l += edit_count_lines (edit, q, edit->search->normal_offset);
105 if (l != l_last)
107 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
108 books++;
110 l_last = l;
111 q = edit->search->normal_offset + 1;
114 if (found == 0)
116 edit_error_dialog (_("Search"), _("Search string not found"));
118 else
120 edit_cursor_move (edit, edit->search_start - edit->curs1);
121 edit_scroll_screen_over_cursor (edit);
125 static int
126 edit_search_cmd_callback (const void *user_data, gsize char_offset)
128 return edit_get_byte ((WEdit *) user_data, (long) char_offset);
131 void
132 edit_help_cmd (WEdit * edit)
134 interactive_display (NULL, "[Internal File Editor]");
135 edit->force |= REDRAW_COMPLETELY;
138 void
139 edit_refresh_cmd (WEdit * edit)
141 #ifdef HAVE_SLANG
142 int color;
144 edit_get_syntax_color (edit, -1, &color);
145 tty_touch_screen ();
146 mc_refresh ();
147 #else
148 (void) edit;
150 clr_scr ();
151 repaint_screen ();
152 #endif /* !HAVE_SLANG */
153 tty_keypad (TRUE);
156 /* If 0 (quick save) then a) create/truncate <filename> file,
157 b) save to <filename>;
158 if 1 (safe save) then a) save to <tempnam>,
159 b) rename <tempnam> to <filename>;
160 if 2 (do backups) then a) save to <tempnam>,
161 b) rename <filename> to <filename.backup_ext>,
162 c) rename <tempnam> to <filename>. */
164 /* returns 0 on error, -1 on abort */
165 static int
166 edit_save_file (WEdit * edit, const char *filename)
168 char *p;
169 gchar *tmp;
170 long filelen = 0;
171 char *savename = 0;
172 gchar *real_filename;
173 int this_save_mode, fd = -1;
175 if (!filename)
176 return 0;
177 if (!*filename)
178 return 0;
180 if (*filename != PATH_SEP && edit->dir)
182 real_filename = concat_dir_and_file (edit->dir, filename);
184 else
186 real_filename = g_strdup (filename);
189 this_save_mode = option_save_mode;
190 if (this_save_mode != EDIT_QUICK_SAVE)
192 if (!vfs_file_is_local (real_filename) ||
193 (fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
196 * The file does not exists yet, so no safe save or
197 * backup are necessary.
199 this_save_mode = EDIT_QUICK_SAVE;
201 if (fd != -1)
202 mc_close (fd);
205 if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
207 int rv;
208 struct stat sb;
210 rv = mc_stat (real_filename, &sb);
211 if (rv == 0 && sb.st_nlink > 1)
213 rv = edit_query_dialog3 (_("Warning"),
214 _("File has hard-links. Detach before saving?"),
215 _("&Yes"), _("&No"), _("&Cancel"));
216 switch (rv)
218 case 0:
219 this_save_mode = EDIT_SAFE_SAVE;
220 /* fallthrough */
221 case 1:
222 edit->skip_detach_prompt = 1;
223 break;
224 default:
225 g_free (real_filename);
226 return -1;
230 /* Prevent overwriting changes from other editor sessions. */
231 if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
234 /* The default action is "Cancel". */
235 query_set_sel (1);
237 rv = edit_query_dialog2 (_("Warning"),
238 _("The file has been modified in the meantime. Save anyway?"),
239 _("&Yes"), _("&Cancel"));
240 if (rv != 0)
242 g_free (real_filename);
243 return -1;
248 if (this_save_mode != EDIT_QUICK_SAVE)
250 char *savedir, *saveprefix;
251 const char *slashpos;
252 slashpos = strrchr (real_filename, PATH_SEP);
253 if (slashpos)
255 savedir = g_strdup (real_filename);
256 savedir[slashpos - real_filename + 1] = '\0';
258 else
259 savedir = g_strdup (".");
260 saveprefix = concat_dir_and_file (savedir, "cooledit");
261 g_free (savedir);
262 fd = mc_mkstemps (&savename, saveprefix, NULL);
263 g_free (saveprefix);
264 if (!savename)
266 g_free (real_filename);
267 return 0;
269 /* FIXME:
270 * Close for now because mc_mkstemps use pure open system call
271 * to create temporary file and it needs to be reopened by
272 * VFS-aware mc_open().
274 close (fd);
276 else
277 savename = g_strdup (real_filename);
279 int ret;
280 ret = mc_chown (savename, edit->stat1.st_uid, edit->stat1.st_gid);
281 ret = mc_chmod (savename, edit->stat1.st_mode);
284 fd = mc_open (savename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode);
285 if (fd == -1)
286 goto error_save;
288 /* pipe save */
289 p = edit_get_write_filter (savename, real_filename);
290 if (p != NULL)
292 FILE *file;
294 mc_close (fd);
295 file = (FILE *) popen (p, "w");
297 if (file)
299 filelen = edit_write_stream (edit, file);
300 #if 1
301 pclose (file);
302 #else
303 if (pclose (file) != 0)
305 tmp = g_strdup_printf (_("Error writing to pipe: %s"), p);
306 edit_error_dialog (_("Error"), tmp);
307 g_free (tmp);
308 g_free (p);
309 goto error_save;
311 #endif
313 else
315 tmp = g_strdup_printf (_("Cannot open pipe for writing: %s"), p);
316 edit_error_dialog (_("Error"), get_sys_error (tmp));
317 g_free (p);
318 g_free (tmp);
319 goto error_save;
321 g_free (p);
323 else if (edit->lb == LB_ASIS)
324 { /* do not change line breaks */
325 long buf;
326 buf = 0;
327 filelen = edit->last_byte;
328 while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1)
330 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
332 mc_close (fd);
333 goto error_save;
335 buf++;
337 if (mc_write
338 (fd, (char *) edit->buffers1[buf],
339 edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE))
341 filelen = -1;
343 else if (edit->curs2)
345 edit->curs2--;
346 buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
347 if (mc_write
348 (fd,
349 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
350 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
351 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE))
353 filelen = -1;
355 else
357 while (--buf >= 0)
359 if (mc_write (fd, (char *) edit->buffers2[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
361 filelen = -1;
362 break;
366 edit->curs2++;
368 if (mc_close (fd))
369 goto error_save;
371 /* Update the file information, especially the mtime. */
372 if (mc_stat (savename, &edit->stat1) == -1)
373 goto error_save;
375 else
376 { /* change line breaks */
377 FILE *file;
379 mc_close (fd);
381 file = (FILE *) fopen (savename, "w");
383 if (file)
385 filelen = edit_write_stream (edit, file);
386 fclose (file);
388 else
390 char *msg;
392 msg = g_strdup_printf (_("Cannot open file for writing: %s"), savename);
393 edit_error_dialog (_("Error"), msg);
394 g_free (msg);
395 goto error_save;
399 if (filelen != edit->last_byte)
400 goto error_save;
402 if (this_save_mode == EDIT_DO_BACKUP)
404 assert (option_backup_ext != NULL);
405 tmp = g_strconcat (real_filename, option_backup_ext, (char *) NULL);
406 if (mc_rename (real_filename, tmp) == -1)
408 g_free (tmp);
409 goto error_save;
413 if (this_save_mode != EDIT_QUICK_SAVE)
414 if (mc_rename (savename, real_filename) == -1)
415 goto error_save;
416 g_free (savename);
417 g_free (real_filename);
418 return 1;
419 error_save:
420 /* FIXME: Is this safe ?
421 * if (this_save_mode != EDIT_QUICK_SAVE)
422 * mc_unlink (savename);
424 g_free (real_filename);
425 g_free (savename);
426 return 0;
429 void
430 menu_save_mode_cmd (void)
432 /* diaog sizes */
433 const int DLG_X = 38;
434 const int DLG_Y = 13;
436 char *str_result;
438 const char *str[] = {
439 N_("&Quick save"),
440 N_("&Safe save"),
441 N_("&Do backups with following extension:")
444 QuickWidget widgets[] = {
445 /* 0 */
446 QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
447 /* 1 */
448 QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
449 /* 2 */
450 QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
451 /* 3 */
452 QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
453 /* 4 */
454 QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
455 QUICK_END
458 QuickDialog dialog = {
459 DLG_X, DLG_Y, -1, -1, N_("Edit Save Mode"),
460 "[Edit Save Mode]", widgets, FALSE
463 size_t i;
464 size_t maxlen = 0;
465 size_t w0, w1, b_len, w3;
467 assert (option_backup_ext != NULL);
469 /* OK/Cancel buttons */
470 w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
471 w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5; /* default button */
472 b_len = w0 + w1 + 3;
474 maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
476 w3 = 0;
477 for (i = 0; i < 3; i++)
479 #ifdef ENABLE_NLS
480 str[i] = _(str[i]);
481 #endif
482 w3 = max (w3, (size_t) str_term_width1 (str[i]));
485 maxlen = max (maxlen, w3 + 4);
487 dialog.xlen = min ((size_t) COLS, maxlen + 8);
489 widgets[3].u.input.len = w3;
490 widgets[1].relative_x = (dialog.xlen - b_len) / 2;
491 widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
493 for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
494 widgets[i].x_divisions = dialog.xlen;
496 if (quick_dialog (&dialog) != B_CANCEL)
498 g_free (option_backup_ext);
499 option_backup_ext = str_result;
503 void
504 edit_set_filename (WEdit * edit, const char *f)
506 g_free (edit->filename);
507 if (!f)
508 f = "";
509 edit->filename = g_strdup (f);
510 if (edit->dir == NULL && *f != PATH_SEP)
511 #ifdef ENABLE_VFS
512 edit->dir = g_strdup (vfs_get_current_dir ());
513 #else /* ENABLE_VFS */
514 edit->dir = g_get_current_dir ();
515 #endif /* ENABLE_VFS */
518 static gboolean
519 edit_check_newline (WEdit * edit)
521 return !(option_check_nl_at_eof && edit->last_byte > 0
522 && edit_get_byte (edit, edit->last_byte - 1) != '\n'
523 && edit_query_dialog2 (_("Warning"),
524 _("The file you are saving is not finished with a newline"),
525 _("C&ontinue"), _("&Cancel")));
528 static char *
529 edit_get_save_file_as (WEdit * edit)
531 #define DLG_WIDTH 64
532 #define DLG_HEIGHT 14
534 static LineBreaks cur_lb = LB_ASIS;
536 char *filename = edit->filename;
538 const char *lb_names[LB_NAMES] = {
539 N_("&Do not change"),
540 N_("&Unix format (LF)"),
541 N_("&Windows/DOS format (CR LF)"),
542 N_("&Macintosh format (CR)")
545 QuickWidget quick_widgets[] = {
546 QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
547 QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
548 QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
549 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
550 QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
551 "save-as", &filename),
552 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_("Enter file name:")),
553 QUICK_END
556 QuickDialog Quick_options = {
557 DLG_WIDTH, DLG_HEIGHT, -1, -1,
558 N_("Save As"), "[Save File As]",
559 quick_widgets, FALSE
562 if (quick_dialog (&Quick_options) != B_CANCEL)
564 edit->lb = cur_lb;
565 return filename;
568 return NULL;
570 #undef DLG_WIDTH
571 #undef DLG_HEIGHT
574 /* Here we want to warn the users of overwriting an existing file,
575 but only if they have made a change to the filename */
576 /* returns 1 on success */
578 edit_save_as_cmd (WEdit * edit)
580 /* This heads the 'Save As' dialog box */
581 char *exp;
582 int save_lock = 0;
583 int different_filename = 0;
585 if (!edit_check_newline (edit))
586 return 0;
588 exp = edit_get_save_file_as (edit);
589 edit_push_action (edit, KEY_PRESS + edit->start_display);
591 if (exp)
593 if (!*exp)
595 g_free (exp);
596 edit->force |= REDRAW_COMPLETELY;
597 return 0;
599 else
601 int rv;
602 if (strcmp (edit->filename, exp))
604 int file;
605 different_filename = 1;
606 file = mc_open (exp, O_RDONLY | O_BINARY);
607 if (file != -1)
609 /* the file exists */
610 mc_close (file);
611 /* Overwrite the current file or cancel the operation */
612 if (edit_query_dialog2
613 (_("Warning"),
614 _("A file already exists with this name"),
615 _("&Overwrite"), _("&Cancel")))
617 edit->force |= REDRAW_COMPLETELY;
618 g_free (exp);
619 return 0;
622 else
624 edit->stat1.st_mode |= S_IWUSR;
626 save_lock = lock_file (exp);
628 else
630 /* filenames equal, check if already locked */
631 if (!edit->locked && !edit->delete_file)
632 save_lock = lock_file (exp);
635 if (different_filename)
638 * Allow user to write into saved (under another name) file
639 * even if original file had r/o user permissions.
641 edit->stat1.st_mode |= S_IWRITE;
644 rv = edit_save_file (edit, exp);
645 switch (rv)
647 case 1:
648 /* Succesful, so unlock both files */
649 if (different_filename)
651 if (save_lock)
652 unlock_file (exp);
653 if (edit->locked)
654 edit->locked = edit_unlock_file (edit);
656 else
658 if (edit->locked || save_lock)
659 edit->locked = edit_unlock_file (edit);
662 edit_set_filename (edit, exp);
663 if (edit->lb != LB_ASIS)
664 edit_reload (edit, exp);
665 g_free (exp);
666 edit->modified = 0;
667 edit->delete_file = 0;
668 if (different_filename)
669 edit_load_syntax (edit, NULL, edit->syntax_type);
670 edit->force |= REDRAW_COMPLETELY;
671 return 1;
672 default:
673 edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
674 /* fallthrough */
675 case -1:
676 /* Failed, so maintain modify (not save) lock */
677 if (save_lock)
678 unlock_file (exp);
679 g_free (exp);
680 edit->force |= REDRAW_COMPLETELY;
681 return 0;
685 edit->force |= REDRAW_COMPLETELY;
686 return 0;
689 /* {{{ Macro stuff starts here */
691 /* creates a macro file if it doesn't exist */
692 static FILE *
693 edit_open_macro_file (const char *r)
695 gchar *filename;
696 FILE *fd;
697 int file;
698 filename = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
699 file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
700 if (file == -1)
702 g_free (filename);
703 return 0;
705 close (file);
706 fd = fopen (filename, r);
707 g_free (filename);
708 return fd;
711 #define MAX_MACROS 1024
712 static int saved_macro[MAX_MACROS + 1];
713 static int saved_macros_loaded = 0;
716 This is just to stop the macro file be loaded over and over for keys
717 that aren't defined to anything. On slow systems this could be annoying.
719 static int
720 macro_exists (int k)
722 int i;
723 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
724 if (saved_macro[i] == k)
725 return i;
726 return -1;
729 /* returns 1 on error */
730 static int
731 edit_delete_macro (WEdit * edit, int k)
733 gchar *tmp, *tmp2;
734 struct macro macro[MAX_MACRO_LENGTH];
735 FILE *f, *g;
736 int s, i, n, j = 0;
738 (void) edit;
740 if (saved_macros_loaded)
742 j = macro_exists (k);
743 if (j < 0)
744 return 0;
746 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
747 g = fopen (tmp, "w");
748 g_free (tmp);
749 if (!g)
751 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open temp file")));
752 return 1;
754 f = edit_open_macro_file ("r");
755 if (!f)
757 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open macro file")));
758 fclose (g);
759 return 1;
761 for (;;)
763 n = fscanf (f, ("key '%d 0': "), &s);
764 if (!n || n == EOF)
765 break;
766 n = 0;
767 while (fscanf (f, "%lu %d, ", &macro[n].command, &macro[n].ch))
768 n++;
770 int ret;
771 ret = fscanf (f, ";\n");
773 if (s != k)
775 fprintf (g, ("key '%d 0': "), s);
776 for (i = 0; i < n; i++)
777 fprintf (g, "%lu %d, ", macro[i].command, macro[i].ch);
778 fprintf (g, ";\n");
781 fclose (f);
782 fclose (g);
783 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
784 tmp2 = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
785 if (rename (tmp, tmp2) == -1)
787 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot overwrite macro file")));
788 g_free (tmp);
789 g_free (tmp2);
790 return 1;
792 g_free (tmp);
793 g_free (tmp2);
795 if (saved_macros_loaded)
796 memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
797 return 0;
800 /* returns 0 on error */
802 edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
804 FILE *f;
805 int s, i;
807 edit_push_action (edit, KEY_PRESS + edit->start_display);
808 s = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
809 edit->force |= REDRAW_COMPLETELY;
810 if (s)
812 if (edit_delete_macro (edit, s))
813 return 0;
814 f = edit_open_macro_file ("a+");
815 if (f)
817 fprintf (f, ("key '%d 0': "), s);
818 for (i = 0; i < n; i++)
819 fprintf (f, "%lu %d, ", macro[i].command, macro[i].ch);
820 fprintf (f, ";\n");
821 fclose (f);
822 if (saved_macros_loaded)
824 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
825 saved_macro[i] = s;
827 return 1;
829 else
830 edit_error_dialog (_("Save macro"), get_sys_error (_("Cannot open macro file")));
832 return 0;
835 void
836 edit_delete_macro_cmd (WEdit * edit)
838 int command;
840 command = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
842 if (command != 0)
843 edit_delete_macro (edit, command);
846 /* return 0 on error */
848 edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
850 FILE *f;
851 int s, i = 0, found = 0;
853 (void) edit;
855 if (saved_macros_loaded)
856 if (macro_exists (k) < 0)
857 return 0;
859 f = edit_open_macro_file ("r");
860 if (f != NULL)
862 struct macro dummy;
865 int u;
866 u = fscanf (f, ("key '%d 0': "), &s);
867 if (!u || u == EOF)
868 break;
869 if (!saved_macros_loaded)
870 saved_macro[i++] = s;
871 if (!found)
873 *n = 0;
874 while (*n < MAX_MACRO_LENGTH
875 && 2 == fscanf (f, "%lu %d, ", &macro[*n].command, &macro[*n].ch))
876 (*n)++;
878 else
880 while (2 == fscanf (f, "%lu %d, ", &dummy.command, &dummy.ch));
883 int ret;
884 ret = fscanf (f, ";\n");
886 if (s == k)
887 found = 1;
889 while (!found || !saved_macros_loaded);
890 if (!saved_macros_loaded)
892 saved_macro[i] = 0;
893 saved_macros_loaded = 1;
895 fclose (f);
896 return found;
898 else
899 edit_error_dialog (_("Load macro"), get_sys_error (_("Cannot open macro file")));
900 return 0;
903 /* }}} Macro stuff starts here */
905 /* returns 1 on success */
907 edit_save_confirm_cmd (WEdit * edit)
909 gchar *f = NULL;
911 if (!edit_check_newline (edit))
912 return 0;
914 if (edit_confirm_save)
916 f = g_strdup_printf (_("Confirm save file: \"%s\""), edit->filename);
917 if (edit_query_dialog2 (_("Save file"), f, _("&Save"), _("&Cancel")))
919 g_free (f);
920 return 0;
922 g_free (f);
924 return edit_save_cmd (edit);
928 /* returns 1 on success */
929 static int
930 edit_save_cmd (WEdit * edit)
932 int res, save_lock = 0;
934 if (!edit->locked && !edit->delete_file)
935 save_lock = edit_lock_file (edit);
936 res = edit_save_file (edit, edit->filename);
938 /* Maintain modify (not save) lock on failure */
939 if ((res > 0 && edit->locked) || save_lock)
940 edit->locked = edit_unlock_file (edit);
942 /* On failure try 'save as', it does locking on its own */
943 if (!res)
944 return edit_save_as_cmd (edit);
945 edit->force |= REDRAW_COMPLETELY;
946 if (res > 0)
948 edit->delete_file = 0;
949 edit->modified = 0;
952 return 1;
956 /* returns 1 on success */
958 edit_new_cmd (WEdit * edit)
960 if (edit->modified)
962 if (edit_query_dialog2
963 (_("Warning"),
965 ("Current text was modified without a file save.\nContinue discards these changes"),
966 _("C&ontinue"), _("&Cancel")))
968 edit->force |= REDRAW_COMPLETELY;
969 return 0;
972 edit->force |= REDRAW_COMPLETELY;
974 return edit_renew (edit); /* if this gives an error, something has really screwed up */
977 /* returns 1 on error */
978 static int
979 edit_load_file_from_filename (WEdit * edit, char *exp)
981 int prev_locked = edit->locked;
982 char *prev_filename = g_strdup (edit->filename);
984 if (!edit_reload (edit, exp))
986 g_free (prev_filename);
987 return 1;
990 if (prev_locked)
992 char *fullpath;
994 fullpath = g_build_filename (edit->dir, prev_filename, (char *) NULL);
995 unlock_file (fullpath);
996 g_free (fullpath);
998 g_free (prev_filename);
999 return 0;
1002 static void
1003 edit_load_syntax_file (WEdit * edit)
1005 char *extdir;
1006 int dir = 0;
1008 if (geteuid () == 0)
1010 dir = query_dialog (_("Syntax file edit"),
1011 _("Which syntax file you want to edit?"), D_NORMAL, 2,
1012 _("&User"), _("&System Wide"));
1015 extdir = concat_dir_and_file (mc_home, "syntax" PATH_SEP_STR "Syntax");
1016 if (!exist_file (extdir))
1018 g_free (extdir);
1019 extdir = concat_dir_and_file (mc_home_alt, "syntax" PATH_SEP_STR "Syntax");
1022 if (dir == 0)
1024 char *buffer;
1026 buffer = concat_dir_and_file (home_dir, EDIT_SYNTAX_FILE);
1027 check_for_default (extdir, buffer);
1028 edit_load_file_from_filename (edit, buffer);
1029 g_free (buffer);
1031 else if (dir == 1)
1032 edit_load_file_from_filename (edit, extdir);
1034 g_free (extdir);
1037 static void
1038 edit_load_menu_file (WEdit * edit)
1040 char *buffer;
1041 char *menufile;
1042 int dir = 0;
1044 dir = query_dialog (_("Menu edit"),
1045 _("Which menu file do you want to edit?"), D_NORMAL,
1046 geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
1048 menufile = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
1050 if (!exist_file (menufile))
1052 g_free (menufile);
1053 menufile = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
1056 switch (dir)
1058 case 0:
1059 buffer = g_strdup (EDIT_LOCAL_MENU);
1060 check_for_default (menufile, buffer);
1061 chmod (buffer, 0600);
1062 break;
1064 case 1:
1065 buffer = concat_dir_and_file (home_dir, EDIT_HOME_MENU);
1066 check_for_default (menufile, buffer);
1067 break;
1069 case 2:
1070 buffer = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
1071 if (!exist_file (buffer))
1073 g_free (buffer);
1074 buffer = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
1076 break;
1078 default:
1079 g_free (menufile);
1080 return;
1083 edit_load_file_from_filename (edit, buffer);
1085 g_free (buffer);
1086 g_free (menufile);
1090 edit_load_cmd (WEdit * edit, edit_current_file_t what)
1092 char *exp;
1094 if (edit->modified
1095 && (edit_query_dialog2
1096 (_("Warning"),
1097 _("Current text was modified without a file save.\n"
1098 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")) == 1))
1100 edit->force |= REDRAW_COMPLETELY;
1101 return 0;
1104 switch (what)
1106 case EDIT_FILE_COMMON:
1107 exp = input_expand_dialog (_("Load"), _("Enter file name:"),
1108 MC_HISTORY_EDIT_LOAD, edit->filename);
1110 if (exp)
1112 if (*exp)
1113 edit_load_file_from_filename (edit, exp);
1114 g_free (exp);
1116 break;
1118 case EDIT_FILE_SYNTAX:
1119 edit_load_syntax_file (edit);
1120 break;
1122 case EDIT_FILE_MENU:
1123 edit_load_menu_file (edit);
1124 break;
1126 default:
1127 break;
1130 edit->force |= REDRAW_COMPLETELY;
1131 return 0;
1135 if mark2 is -1 then marking is from mark1 to the cursor.
1136 Otherwise its between the markers. This handles this.
1137 Returns 1 if no text is marked.
1140 eval_marks (WEdit * edit, long *start_mark, long *end_mark)
1142 if (edit->mark1 != edit->mark2)
1144 long start_bol, start_eol;
1145 long end_bol, end_eol;
1146 long col1, col2;
1147 long diff1, diff2;
1148 if (edit->mark2 >= 0)
1150 *start_mark = min (edit->mark1, edit->mark2);
1151 *end_mark = max (edit->mark1, edit->mark2);
1153 else
1155 *start_mark = min (edit->mark1, edit->curs1);
1156 *end_mark = max (edit->mark1, edit->curs1);
1157 edit->column2 = edit->curs_col + edit->over_col;
1159 if (edit->column_highlight
1160 && (((edit->mark1 > edit->curs1) && (edit->column1 < edit->column2))
1161 || ((edit->mark1 < edit->curs1) && (edit->column1 > edit->column2))))
1164 start_bol = edit_bol (edit, *start_mark);
1165 start_eol = edit_eol (edit, start_bol - 1) + 1;
1166 end_bol = edit_bol (edit, *end_mark);
1167 end_eol = edit_eol (edit, *end_mark);
1168 col1 = min (edit->column1, edit->column2);
1169 col2 = max (edit->column1, edit->column2);
1171 diff1 =
1172 edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
1173 col1, 0);
1174 diff2 =
1175 edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
1176 col1, 0);
1178 *start_mark -= diff1;
1179 *end_mark += diff2;
1180 *start_mark = max (*start_mark, start_eol);
1181 *end_mark = min (*end_mark, end_eol);
1183 return 0;
1185 else
1187 *start_mark = *end_mark = 0;
1188 edit->column2 = edit->column1 = 0;
1189 return 1;
1193 #define space_width 1
1195 void
1196 edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
1198 long cursor;
1199 int i, col;
1200 cursor = edit->curs1;
1201 col = edit_get_col (edit);
1202 for (i = 0; i < size; i++)
1204 if (data[i] == '\n')
1205 { /* fill in and move to next line */
1206 int l;
1207 long p;
1208 if (edit_get_byte (edit, edit->curs1) != '\n')
1210 l = width - (edit_get_col (edit) - col);
1211 while (l > 0)
1213 edit_insert (edit, ' ');
1214 l -= space_width;
1217 for (p = edit->curs1;; p++)
1219 if (p == edit->last_byte)
1221 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1222 edit_insert_ahead (edit, '\n');
1223 p++;
1224 break;
1226 if (edit_get_byte (edit, p) == '\n')
1228 p++;
1229 break;
1232 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1233 l = col - edit_get_col (edit);
1234 while (l >= space_width)
1236 edit_insert (edit, ' ');
1237 l -= space_width;
1239 continue;
1241 edit_insert (edit, data[i]);
1243 edit_cursor_move (edit, cursor - edit->curs1);
1246 #define TEMP_BUF_LEN 1024
1249 edit_insert_column_of_text_from_file (WEdit * edit, int file)
1251 long cursor;
1252 int i, col;
1253 int blocklen = -1, width;
1254 unsigned char *data;
1255 cursor = edit->curs1;
1256 col = edit_get_col (edit);
1257 data = g_malloc0 (TEMP_BUF_LEN);
1258 while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
1260 for (width = 0; width < blocklen; width++)
1262 if (data[width] == '\n')
1263 break;
1265 for (i = 0; i < blocklen; i++)
1267 if (data[i] == '\n')
1268 { /* fill in and move to next line */
1269 int l;
1270 long p;
1271 if (edit_get_byte (edit, edit->curs1) != '\n')
1273 l = width - (edit_get_col (edit) - col);
1274 while (l > 0)
1276 edit_insert (edit, ' ');
1277 l -= space_width;
1280 for (p = edit->curs1;; p++)
1282 if (p == edit->last_byte)
1284 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1285 edit_insert_ahead (edit, '\n');
1286 p++;
1287 break;
1289 if (edit_get_byte (edit, p) == '\n')
1291 p++;
1292 break;
1295 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1296 l = col - edit_get_col (edit);
1297 while (l >= space_width)
1299 edit_insert (edit, ' ');
1300 l -= space_width;
1302 continue;
1304 edit_insert (edit, data[i]);
1307 edit_cursor_move (edit, cursor - edit->curs1);
1308 g_free (data);
1309 edit->force |= REDRAW_PAGE;
1310 return blocklen;
1313 void
1314 edit_block_copy_cmd (WEdit * edit)
1316 long start_mark, end_mark, current = edit->curs1;
1317 int size;
1318 unsigned char *copy_buf;
1320 edit_update_curs_col (edit);
1321 if (eval_marks (edit, &start_mark, &end_mark))
1322 return;
1324 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1326 /* all that gets pushed are deletes hence little space is used on the stack */
1328 edit_push_markers (edit);
1330 if (edit->column_highlight)
1332 edit_insert_column_of_text (edit, copy_buf, size, abs (edit->column2 - edit->column1));
1334 else
1336 while (size--)
1337 edit_insert_ahead (edit, copy_buf[size]);
1340 g_free (copy_buf);
1341 edit_scroll_screen_over_cursor (edit);
1343 if (edit->column_highlight)
1345 edit_set_markers (edit, 0, 0, 0, 0);
1346 edit_push_action (edit, COLUMN_ON);
1347 edit->column_highlight = 0;
1349 else if (start_mark < current && end_mark > current)
1350 edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
1352 edit->force |= REDRAW_PAGE;
1356 void
1357 edit_block_move_cmd (WEdit * edit)
1359 long count;
1360 long current;
1361 unsigned char *copy_buf;
1362 long start_mark, end_mark;
1363 int deleted = 0;
1364 int x = 0;
1366 if (eval_marks (edit, &start_mark, &end_mark))
1367 return;
1368 if (edit->column_highlight)
1370 edit_update_curs_col (edit);
1371 x = edit->curs_col;
1372 if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1373 if ((x > edit->column1 && x < edit->column2)
1374 || (x > edit->column2 && x < edit->column1))
1375 return;
1377 else if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1378 return;
1380 if ((end_mark - start_mark) > option_max_undo / 2)
1381 if (edit_query_dialog2
1382 (_("Warning"),
1384 ("Block is large, you may not be able to undo this action"),
1385 _("C&ontinue"), _("&Cancel")))
1386 return;
1388 edit_push_markers (edit);
1389 current = edit->curs1;
1390 if (edit->column_highlight)
1392 long line;
1393 int size, c1, c2;
1394 line = edit->curs_line;
1395 if (edit->mark2 < 0)
1396 edit_mark_cmd (edit, 0);
1397 c1 = min (edit->column1, edit->column2);
1398 c2 = max (edit->column1, edit->column2);
1399 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1400 if (x < c2)
1402 edit_block_delete_cmd (edit);
1403 deleted = 1;
1405 edit_move_to_line (edit, line);
1406 edit_cursor_move (edit,
1407 edit_move_forward3 (edit,
1408 edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
1409 edit_insert_column_of_text (edit, copy_buf, size, c2 - c1);
1410 if (!deleted)
1412 line = edit->curs_line;
1413 edit_update_curs_col (edit);
1414 x = edit->curs_col;
1415 edit_block_delete_cmd (edit);
1416 edit_move_to_line (edit, line);
1417 edit_cursor_move (edit,
1418 edit_move_forward3 (edit,
1419 edit_bol (edit,
1420 edit->curs1), x, 0) - edit->curs1);
1422 edit_set_markers (edit, 0, 0, 0, 0);
1423 edit_push_action (edit, COLUMN_ON);
1424 edit->column_highlight = 0;
1426 else
1428 copy_buf = g_malloc0 (end_mark - start_mark);
1429 edit_cursor_move (edit, start_mark - edit->curs1);
1430 edit_scroll_screen_over_cursor (edit);
1431 count = start_mark;
1432 while (count < end_mark)
1434 copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
1435 count++;
1437 edit_scroll_screen_over_cursor (edit);
1438 edit_cursor_move (edit,
1439 current - edit->curs1 -
1440 (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
1441 edit_scroll_screen_over_cursor (edit);
1442 while (count-- > start_mark)
1443 edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
1444 edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
1446 edit_scroll_screen_over_cursor (edit);
1447 g_free (copy_buf);
1448 edit->force |= REDRAW_PAGE;
1451 static void
1452 edit_delete_column_of_text (WEdit * edit)
1454 long p, q, r, m1, m2;
1455 long b, c, d, n;
1457 eval_marks (edit, &m1, &m2);
1458 n = edit_move_forward (edit, m1, 0, m2) + 1;
1459 c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
1460 d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
1461 b = max (min (c, d), min (edit->column1, edit->column2));
1462 c = max (c, max (edit->column1, edit->column2));
1464 while (n--)
1466 r = edit_bol (edit, edit->curs1);
1467 p = edit_move_forward3 (edit, r, b, 0);
1468 q = edit_move_forward3 (edit, r, c, 0);
1469 if (p < m1)
1470 p = m1;
1471 if (q > m2)
1472 q = m2;
1473 edit_cursor_move (edit, p - edit->curs1);
1474 while (q > p)
1476 /* delete line between margins */
1477 if (edit_get_byte (edit, edit->curs1) != '\n')
1478 edit_delete (edit, 1);
1479 q--;
1481 if (n)
1482 /* move to next line except on the last delete */
1483 edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
1487 /* if success return 0 */
1488 static int
1489 edit_block_delete (WEdit * edit)
1491 long count;
1492 long start_mark, end_mark;
1493 int curs_pos, line_width;
1494 long curs_line, c1, c2;
1496 if (eval_marks (edit, &start_mark, &end_mark))
1497 return 0;
1498 if (edit->column_highlight && edit->mark2 < 0)
1499 edit_mark_cmd (edit, 0);
1500 if ((end_mark - start_mark) > option_max_undo / 2)
1502 /* Warning message with a query to continue or cancel the operation */
1503 if (edit_query_dialog2
1504 (_("Warning"),
1506 ("Block is large, you may not be able to undo this action"),
1507 _("C&ontinue"), _("&Cancel")))
1509 return 1;
1512 c1 = min (edit->column1, edit->column2);
1513 c2 = max (edit->column1, edit->column2);
1514 edit->column1 = c1;
1515 edit->column2 = c2;
1517 edit_push_markers (edit);
1519 curs_line = edit->curs_line;
1521 /* calculate line width and cursor position before cut */
1522 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
1523 edit_eol (edit, edit->curs1));
1524 curs_pos = edit->curs_col + edit->over_col;
1526 /* move cursor to start of selection */
1527 edit_cursor_move (edit, start_mark - edit->curs1);
1528 edit_scroll_screen_over_cursor (edit);
1529 count = start_mark;
1530 if (start_mark < end_mark)
1532 if (edit->column_highlight)
1534 if (edit->mark2 < 0)
1535 edit_mark_cmd (edit, 0);
1536 edit_delete_column_of_text (edit);
1537 /* move cursor to the saved position */
1538 edit_move_to_line (edit, curs_line);
1539 /* calculate line width after cut */
1540 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
1541 edit_eol (edit, edit->curs1));
1542 if (option_cursor_beyond_eol && curs_pos > line_width)
1543 edit->over_col = curs_pos - line_width;
1545 else
1547 while (count < end_mark)
1549 edit_delete (edit, 1);
1550 count++;
1554 edit_set_markers (edit, 0, 0, 0, 0);
1555 edit->force |= REDRAW_PAGE;
1556 return 0;
1559 /* returns 1 if canceelled by user */
1561 edit_block_delete_cmd (WEdit * edit)
1563 long start_mark, end_mark;
1564 if (eval_marks (edit, &start_mark, &end_mark))
1566 edit_delete_line (edit);
1567 return 0;
1569 return edit_block_delete (edit);
1572 #define INPUT_INDEX 9
1574 static gboolean
1575 editcmd_find (WEdit * edit, gsize * len)
1577 off_t search_start = edit->search_start;
1578 off_t search_end;
1579 long start_mark = 0;
1580 long end_mark = edit->last_byte;
1581 int mark_res = 0;
1583 if (edit_search_options.only_in_selection)
1585 mark_res = eval_marks (edit, &start_mark, &end_mark);
1586 if (mark_res != 0)
1588 edit->search->error = MC_SEARCH_E_NOTFOUND;
1589 edit->search->error_str = g_strdup (_("Search string not found"));
1590 return FALSE;
1592 if (edit_search_options.backwards)
1594 if (search_start > end_mark || search_start <= start_mark)
1596 search_start = end_mark;
1599 else
1601 if (search_start < start_mark || search_start >= end_mark)
1603 search_start = start_mark;
1607 else
1609 if (edit_search_options.backwards)
1610 end_mark = max (1, edit->curs1) - 1;
1612 if (edit_search_options.backwards)
1614 search_end = end_mark;
1615 while ((int) search_start >= start_mark)
1617 if (search_end > (off_t) (search_start + edit->search->original_len) &&
1618 mc_search_is_fixed_search_str (edit->search))
1620 search_end = search_start + edit->search->original_len;
1622 if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
1623 && edit->search->normal_offset == search_start)
1625 return TRUE;
1627 search_start--;
1629 edit->search->error_str = g_strdup (_("Search string not found"));
1631 else
1633 return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
1635 return FALSE;
1639 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1640 (and the above) routines to work properly - paul */
1642 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1644 static char *
1645 edit_replace_cmd__conv_to_display (char *str)
1647 #ifdef HAVE_CHARSET
1648 GString *tmp;
1649 tmp = str_convert_to_display (str);
1651 if (tmp && tmp->len)
1653 return g_string_free (tmp, FALSE);
1655 g_string_free (tmp, TRUE);
1656 #endif
1657 return g_strdup (str);
1660 static char *
1661 edit_replace_cmd__conv_to_input (char *str)
1663 #ifdef HAVE_CHARSET
1664 GString *tmp;
1665 tmp = str_convert_to_input (str);
1667 if (tmp && tmp->len)
1669 return g_string_free (tmp, FALSE);
1671 g_string_free (tmp, TRUE);
1672 return g_strdup (str);
1673 #endif
1674 return g_strdup (str);
1677 /* call with edit = 0 before shutdown to close memory leaks */
1678 void
1679 edit_replace_cmd (WEdit * edit, int again)
1681 /* 1 = search string, 2 = replace with */
1682 static char *saved1 = NULL; /* saved default[123] */
1683 static char *saved2 = NULL;
1684 char *input1 = NULL; /* user input from the dialog */
1685 char *input2 = NULL;
1686 char *disp1 = NULL;
1687 char *disp2 = NULL;
1688 long times_replaced = 0;
1689 gboolean once_found = FALSE;
1690 GString *repl_str = NULL, *tmp_str = NULL;
1692 if (!edit)
1694 g_free (saved1), saved1 = NULL;
1695 g_free (saved2), saved2 = NULL;
1696 return;
1699 edit->force |= REDRAW_COMPLETELY;
1701 if (again && !saved1 && !saved2)
1702 again = 0;
1704 if (again)
1706 input1 = g_strdup (saved1 ? saved1 : "");
1707 input2 = g_strdup (saved2 ? saved2 : "");
1709 else
1711 char *tmp_inp1, *tmp_inp2;
1712 disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
1713 disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
1715 edit_push_action (edit, KEY_PRESS + edit->start_display);
1717 editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
1719 g_free (disp1);
1720 g_free (disp2);
1722 if (input1 == NULL || *input1 == '\0')
1724 edit->force = REDRAW_COMPLETELY;
1725 goto cleanup;
1728 tmp_inp1 = input1;
1729 tmp_inp2 = input2;
1730 input1 = edit_replace_cmd__conv_to_input (input1);
1731 input2 = edit_replace_cmd__conv_to_input (input2);
1732 g_free (tmp_inp1);
1733 g_free (tmp_inp2);
1735 g_free (saved1), saved1 = g_strdup (input1);
1736 g_free (saved2), saved2 = g_strdup (input2);
1738 if (edit->search)
1740 mc_search_free (edit->search);
1741 edit->search = NULL;
1745 if (!edit->search)
1747 edit->search = mc_search_new (input1, -1);
1748 if (edit->search == NULL)
1750 edit->search_start = edit->curs1;
1751 goto cleanup;
1753 edit->search->search_type = edit_search_options.type;
1754 edit->search->is_all_charsets = edit_search_options.all_codepages;
1755 edit->search->is_case_sensitive = edit_search_options.case_sens;
1756 edit->search->whole_words = edit_search_options.whole_words;
1757 edit->search->search_fn = edit_search_cmd_callback;
1760 if (edit->found_len && edit->search_start == edit->found_start + 1
1761 && edit_search_options.backwards)
1762 edit->search_start--;
1764 if (edit->found_len && edit->search_start == edit->found_start - 1
1765 && !edit_search_options.backwards)
1766 edit->search_start++;
1770 gsize len = 0;
1772 if (!editcmd_find (edit, &len))
1774 if (!(edit->search->error == MC_SEARCH_E_OK ||
1775 (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
1777 edit_error_dialog (_("Search"), edit->search->error_str);
1779 break;
1781 once_found = TRUE;
1783 edit->search_start = edit->search->normal_offset;
1784 /*returns negative on not found or error in pattern */
1786 if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
1788 gboolean replace_yes;
1789 gsize i;
1791 edit->found_start = edit->search_start;
1792 i = edit->found_len = len;
1794 edit_cursor_move (edit, edit->search_start - edit->curs1);
1795 edit_scroll_screen_over_cursor (edit);
1797 replace_yes = TRUE;
1799 if (edit->replace_mode == 0)
1801 int l;
1802 l = edit->curs_row - edit->num_widget_lines / 3;
1803 if (l > 0)
1804 edit_scroll_downward (edit, l);
1805 if (l < 0)
1806 edit_scroll_upward (edit, -l);
1808 edit_scroll_screen_over_cursor (edit);
1809 edit->force |= REDRAW_PAGE;
1810 edit_render_keypress (edit);
1812 /*so that undo stops at each query */
1813 edit_push_key_press (edit);
1814 /* and prompt 2/3 down */
1815 disp1 = edit_replace_cmd__conv_to_display (saved1);
1816 disp2 = edit_replace_cmd__conv_to_display (saved2);
1818 switch (editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1))
1820 case B_ENTER:
1821 replace_yes = TRUE;
1822 break;
1823 case B_SKIP_REPLACE:
1824 replace_yes = FALSE;
1825 break;
1826 case B_REPLACE_ALL:
1827 edit->replace_mode = 1;
1828 break;
1829 case B_CANCEL:
1830 replace_yes = FALSE;
1831 edit->replace_mode = -1;
1832 break;
1834 g_free (disp1);
1835 g_free (disp2);
1838 if (replace_yes)
1840 /* don't process string each time */
1841 if (tmp_str == NULL)
1843 tmp_str = g_string_new (input2);
1844 repl_str = mc_search_prepare_replace_str (edit->search, tmp_str);
1846 if (edit->search->error != MC_SEARCH_E_OK)
1848 edit_error_dialog (_("Replace"), edit->search->error_str);
1849 break;
1853 /* delete then insert new */
1854 for (i = 0; i < len; i++)
1855 edit_delete (edit, 1);
1857 for (i = 0; i < repl_str->len; i++)
1858 edit_insert (edit, repl_str->str[i]);
1860 edit->found_len = repl_str->len;
1861 times_replaced++;
1864 /* so that we don't find the same string again */
1865 if (edit_search_options.backwards)
1866 edit->search_start--;
1867 else
1869 edit->search_start += repl_str->len;
1871 if (edit->search_start >= edit->last_byte)
1872 break;
1875 edit_scroll_screen_over_cursor (edit);
1877 else
1879 /* try and find from right here for next search */
1880 edit->search_start = edit->curs1;
1881 edit_update_curs_col (edit);
1883 edit->force |= REDRAW_PAGE;
1884 edit_render_keypress (edit);
1886 if (times_replaced == 0)
1887 query_dialog (_("Replace"), _("Search string not found"), D_NORMAL, 1, _("&OK"));
1888 break;
1891 while (edit->replace_mode >= 0);
1893 if (tmp_str != NULL)
1894 g_string_free (tmp_str, TRUE);
1895 if (repl_str != NULL)
1896 g_string_free (repl_str, TRUE);
1898 edit_scroll_screen_over_cursor (edit);
1899 edit->force |= REDRAW_COMPLETELY;
1900 edit_render_keypress (edit);
1902 if ((edit->replace_mode == 1) && (times_replaced != 0))
1903 message (D_NORMAL, _("Replace"), _("%ld replacements made"), times_replaced);
1905 cleanup:
1906 g_free (input1);
1907 g_free (input2);
1911 void
1912 edit_search_cmd (WEdit * edit, int again)
1914 char *search_string = NULL, *search_string_dup = NULL;
1915 gsize len = 0;
1917 if (!edit)
1918 return;
1920 if (edit->search != NULL)
1922 search_string = g_strndup (edit->search->original, edit->search->original_len);
1923 search_string_dup = search_string;
1925 else
1927 GList *history;
1928 history = history_get (MC_HISTORY_SHARED_SEARCH);
1929 if (history != NULL && history->data != NULL)
1931 search_string_dup = search_string = (char *) g_strdup (history->data);
1932 history = g_list_first (history);
1933 g_list_foreach (history, (GFunc) g_free, NULL);
1934 g_list_free (history);
1936 edit->search_start = edit->curs1;
1939 if (!again)
1941 #ifdef HAVE_CHARSET
1942 GString *tmp;
1944 if (search_string && *search_string)
1946 tmp = str_convert_to_display (search_string);
1947 if (tmp != NULL)
1949 if (tmp->len == 0)
1950 g_string_free (tmp, TRUE);
1951 else
1953 g_free (search_string);
1954 search_string = search_string_dup = g_string_free (tmp, FALSE);
1958 #endif /* HAVE_CHARSET */
1959 editcmd_dialog_search_show (edit, &search_string);
1960 g_free (search_string_dup);
1961 search_string_dup = NULL;
1962 #ifdef HAVE_CHARSET
1963 if (search_string && *search_string)
1965 tmp = str_convert_to_input (search_string);
1966 if (tmp != NULL)
1968 if (tmp->len == 0)
1969 g_string_free (tmp, TRUE);
1970 else
1972 g_free (search_string);
1973 search_string = g_string_free (tmp, FALSE);
1977 #endif /* HAVE_CHARSET */
1979 edit_push_action (edit, KEY_PRESS + edit->start_display);
1981 if (search_string == NULL)
1983 edit->force |= REDRAW_COMPLETELY;
1984 edit_scroll_screen_over_cursor (edit);
1985 return;
1988 if (edit->search)
1990 mc_search_free (edit->search);
1991 edit->search = NULL;
1995 if (!edit->search)
1997 edit->search = mc_search_new (search_string, -1);
1998 if (edit->search == NULL)
2000 edit->search_start = edit->curs1;
2001 g_free (search_string);
2002 return;
2005 edit->search->search_type = edit_search_options.type;
2006 edit->search->is_all_charsets = edit_search_options.all_codepages;
2007 edit->search->is_case_sensitive = edit_search_options.case_sens;
2008 edit->search->whole_words = edit_search_options.whole_words;
2009 edit->search->search_fn = edit_search_cmd_callback;
2012 g_free (search_string);
2014 if (search_create_bookmark)
2016 edit_search_cmd_search_create_bookmark (edit);
2018 else
2020 if (edit->found_len && edit->search_start == edit->found_start + 1
2021 && edit_search_options.backwards)
2022 edit->search_start--;
2024 if (edit->found_len && edit->search_start == edit->found_start - 1
2025 && !edit_search_options.backwards)
2026 edit->search_start++;
2028 if (editcmd_find (edit, &len))
2030 edit->found_start = edit->search_start = edit->search->normal_offset;
2031 edit->found_len = len;
2032 edit->over_col = 0;
2033 edit_cursor_move (edit, edit->search_start - edit->curs1);
2034 edit_scroll_screen_over_cursor (edit);
2035 if (edit_search_options.backwards)
2036 edit->search_start--;
2037 else
2038 edit->search_start++;
2040 else
2042 edit->search_start = edit->curs1;
2043 if (edit->search->error_str)
2044 edit_error_dialog (_("Search"), edit->search->error_str);
2048 edit->force |= REDRAW_COMPLETELY;
2049 edit_scroll_screen_over_cursor (edit);
2054 * Check if it's OK to close the editor. If there are unsaved changes,
2055 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
2057 gboolean
2058 edit_ok_to_exit (WEdit * edit)
2060 int act;
2062 if (!edit->modified)
2063 return TRUE;
2065 if (!midnight_shutdown)
2067 if (!edit_check_newline (edit))
2068 return FALSE;
2070 act = edit_query_dialog3 (_("Quit"), _("File was modified. Save with exit?"),
2071 _("&Yes"), _("&No"), _("&Cancel quit"));
2073 else
2075 act = edit_query_dialog2 (_("Quit"), _("Midnight Commander is being shut down.\nSave modified file?"),
2076 _("&Yes"), _("&No"));
2078 /* Esc is No */
2079 if (act == -1)
2080 act = 1;
2083 switch (act)
2085 case 0: /* Yes */
2086 edit_push_markers (edit);
2087 edit_set_markers (edit, 0, 0, 0, 0);
2088 if (!edit_save_cmd (edit) || midnight_shutdown)
2089 return (gboolean) midnight_shutdown;
2090 break;
2091 case 1: /* No */
2092 break;
2093 case 2: /* Cancel quit */
2094 case -1: /* Esc */
2095 return FALSE;
2098 return TRUE;
2101 /* Return a null terminated length of text. Result must be g_free'd */
2102 static unsigned char *
2103 edit_get_block (WEdit * edit, long start, long finish, int *l)
2105 unsigned char *s, *r;
2106 r = s = g_malloc0 (finish - start + 1);
2107 if (edit->column_highlight)
2109 *l = 0;
2110 /* copy from buffer, excluding chars that are out of the column 'margins' */
2111 while (start < finish)
2113 int c;
2114 long x;
2115 x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
2116 c = edit_get_byte (edit, start);
2117 if ((x >= edit->column1 && x < edit->column2)
2118 || (x >= edit->column2 && x < edit->column1) || c == '\n')
2120 *s++ = c;
2121 (*l)++;
2123 start++;
2126 else
2128 *l = finish - start;
2129 while (start < finish)
2130 *s++ = edit_get_byte (edit, start++);
2132 *s = 0;
2133 return r;
2136 /* save block, returns 1 on success */
2138 edit_save_block (WEdit * edit, const char *filename, long start, long finish)
2140 int len, file;
2142 file = mc_open (filename, O_CREAT | O_WRONLY | O_TRUNC,
2143 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY);
2144 if (file == -1)
2145 return 0;
2147 if (edit->column_highlight)
2149 int r;
2150 r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
2151 if (r > 0)
2153 unsigned char *block, *p;
2154 p = block = edit_get_block (edit, start, finish, &len);
2155 while (len)
2157 r = mc_write (file, p, len);
2158 if (r < 0)
2159 break;
2160 p += r;
2161 len -= r;
2163 g_free (block);
2166 else
2168 unsigned char *buf;
2169 int i = start, end;
2170 len = finish - start;
2171 buf = g_malloc0 (TEMP_BUF_LEN);
2172 while (start != finish)
2174 end = min (finish, start + TEMP_BUF_LEN);
2175 for (; i < end; i++)
2176 buf[i - start] = edit_get_byte (edit, i);
2177 len -= mc_write (file, (char *) buf, end - start);
2178 start = end;
2180 g_free (buf);
2182 mc_close (file);
2183 if (len)
2184 return 0;
2185 return 1;
2188 /* copies a block to clipboard file */
2189 static int
2190 edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
2192 int ret;
2193 gchar *tmp;
2194 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2195 ret = edit_save_block (edit, tmp, start, finish);
2196 g_free (tmp);
2197 return ret;
2200 void
2201 edit_paste_from_history (WEdit * edit)
2203 (void) edit;
2204 edit_error_dialog (_("Error"), _("This function is not implemented"));
2208 edit_copy_to_X_buf_cmd (WEdit * edit)
2210 long start_mark, end_mark;
2211 if (eval_marks (edit, &start_mark, &end_mark))
2212 return 0;
2213 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2215 edit_error_dialog (_("Copy to clipboard"),
2216 get_sys_error (_("Unable to save to file")));
2217 return 1;
2219 /* try use external clipboard utility */
2220 copy_file_to_ext_clip ();
2222 edit_mark_cmd (edit, 1);
2223 return 0;
2227 edit_cut_to_X_buf_cmd (WEdit * edit)
2229 long start_mark, end_mark;
2230 if (eval_marks (edit, &start_mark, &end_mark))
2231 return 0;
2232 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2234 edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
2235 return 1;
2237 /* try use external clipboard utility */
2238 copy_file_to_ext_clip ();
2240 edit_block_delete_cmd (edit);
2241 edit_mark_cmd (edit, 1);
2242 return 0;
2245 void
2246 edit_paste_from_X_buf_cmd (WEdit * edit)
2248 gchar *tmp;
2249 /* try use external clipboard utility */
2250 paste_to_file_from_ext_clip ();
2251 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2252 edit_insert_file (edit, tmp);
2253 g_free (tmp);
2258 * Ask user for the line and go to that line.
2259 * Negative numbers mean line from the end (i.e. -1 is the last line).
2261 void
2262 edit_goto_cmd (WEdit * edit)
2264 char *f;
2265 static long line = 0; /* line as typed, saved as default */
2266 long l;
2267 char *error;
2268 char s[32];
2270 g_snprintf (s, sizeof (s), "%ld", line);
2271 f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE,
2272 line ? s : "");
2273 if (!f)
2274 return;
2276 if (!*f)
2278 g_free (f);
2279 return;
2282 l = strtol (f, &error, 0);
2283 if (*error)
2285 g_free (f);
2286 return;
2289 line = l;
2290 if (l < 0)
2291 l = edit->total_lines + l + 2;
2292 edit_move_display (edit, l - edit->num_widget_lines / 2 - 1);
2293 edit_move_to_line (edit, l - 1);
2294 edit->force |= REDRAW_COMPLETELY;
2295 g_free (f);
2299 /* Return 1 on success */
2301 edit_save_block_cmd (WEdit * edit)
2303 long start_mark, end_mark;
2304 char *exp, *tmp;
2306 if (eval_marks (edit, &start_mark, &end_mark))
2307 return 1;
2309 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2310 exp =
2311 input_expand_dialog (_("Save block"), _("Enter file name:"),
2312 MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
2313 g_free (tmp);
2314 edit_push_action (edit, KEY_PRESS + edit->start_display);
2315 if (exp)
2317 if (!*exp)
2319 g_free (exp);
2320 return 0;
2322 else
2324 if (edit_save_block (edit, exp, start_mark, end_mark))
2326 g_free (exp);
2327 edit->force |= REDRAW_COMPLETELY;
2328 return 1;
2330 else
2332 g_free (exp);
2333 edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
2337 edit->force |= REDRAW_COMPLETELY;
2338 return 0;
2342 /* returns 1 on success */
2344 edit_insert_file_cmd (WEdit * edit)
2346 gchar *tmp;
2347 char *exp;
2349 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2350 exp = input_expand_dialog (_("Insert file"), _("Enter file name:"),
2351 MC_HISTORY_EDIT_INSERT_FILE, tmp);
2352 g_free (tmp);
2353 edit_push_action (edit, KEY_PRESS + edit->start_display);
2354 if (exp)
2356 if (!*exp)
2358 g_free (exp);
2359 return 0;
2361 else
2363 if (edit_insert_file (edit, exp))
2365 g_free (exp);
2366 edit->force |= REDRAW_COMPLETELY;
2367 return 1;
2369 else
2371 g_free (exp);
2372 edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
2376 edit->force |= REDRAW_COMPLETELY;
2377 return 0;
2380 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2382 edit_sort_cmd (WEdit * edit)
2384 static char *old = 0;
2385 char *exp, *tmp;
2386 long start_mark, end_mark;
2387 int e;
2389 if (eval_marks (edit, &start_mark, &end_mark))
2391 edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
2392 return 0;
2395 tmp = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE);
2396 edit_save_block (edit, tmp, start_mark, end_mark);
2397 g_free (tmp);
2399 exp = input_dialog (_("Run sort"),
2400 _("Enter sort options (see manpage) separated by whitespace:"),
2401 MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
2403 if (!exp)
2404 return 1;
2405 g_free (old);
2406 old = exp;
2407 tmp = g_strconcat (" sort ", exp, " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE, " > ",
2408 home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2409 e = system (tmp);
2410 g_free (tmp);
2411 if (e)
2413 if (e == -1 || e == 127)
2415 edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
2417 else
2419 char q[8];
2420 sprintf (q, "%d ", e);
2421 tmp = g_strdup_printf (_("Sort returned non-zero: %s"), q);
2422 edit_error_dialog (_("Sort"), tmp);
2423 g_free (tmp);
2425 return -1;
2428 edit->force |= REDRAW_COMPLETELY;
2430 if (edit_block_delete_cmd (edit))
2431 return 1;
2432 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2433 edit_insert_file (edit, tmp);
2434 g_free (tmp);
2435 return 0;
2439 * Ask user for a command, execute it and paste its output back to the
2440 * editor.
2443 edit_ext_cmd (WEdit * edit)
2445 char *exp, *tmp;
2446 int e;
2448 exp =
2449 input_dialog (_("Paste output of external command"),
2450 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
2452 if (!exp)
2453 return 1;
2455 tmp = g_strconcat (exp, " > ", home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2456 e = system (tmp);
2457 g_free (tmp);
2458 g_free (exp);
2460 if (e)
2462 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
2463 return -1;
2466 edit->force |= REDRAW_COMPLETELY;
2467 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2468 edit_insert_file (edit, tmp);
2469 g_free (tmp);
2470 return 0;
2473 /* if block is 1, a block must be highlighted and the shell command
2474 processes it. If block is 0 the shell command is a straight system
2475 command, that just produces some output which is to be inserted */
2476 void
2477 edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
2479 long start_mark, end_mark;
2480 char buf[BUFSIZ];
2481 FILE *script_home = NULL;
2482 FILE *block_file = NULL;
2483 gchar *o, *h, *b, *tmp;
2484 char *quoted_name = NULL;
2486 o = g_strconcat (mc_home, shell_cmd, (char *) NULL); /* original source script */
2487 h = g_strconcat (home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, (char *) NULL); /* home script */
2488 b = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE); /* block file */
2490 script_home = fopen (h, "r");
2491 if (script_home == NULL)
2493 FILE *script_src = NULL;
2495 script_home = fopen (h, "w");
2496 if (script_home == NULL)
2498 tmp = g_strconcat (_("Error creating script:"), h, (char *) NULL);
2499 edit_error_dialog ("", get_sys_error (tmp));
2500 g_free (tmp);
2501 goto edit_block_process_cmd__EXIT;
2504 script_src = fopen (o, "r");
2505 if (script_src == NULL)
2507 o = g_strconcat (mc_home_alt, shell_cmd, (char *) NULL);
2508 script_src = fopen (o, "r");
2509 if (script_src == NULL)
2511 fclose (script_home);
2512 unlink (h);
2513 tmp = g_strconcat (_("Error reading script:"), o, (char *) NULL);
2514 edit_error_dialog ("", get_sys_error (tmp));
2515 g_free (tmp);
2516 goto edit_block_process_cmd__EXIT;
2519 while (fgets (buf, sizeof (buf), script_src))
2520 fputs (buf, script_home);
2521 fclose (script_src);
2523 if (fclose (script_home))
2525 tmp = g_strconcat (_("Error closing script:"), h, (char *) NULL);
2526 edit_error_dialog ("", get_sys_error (tmp));
2527 g_free (tmp);
2528 goto edit_block_process_cmd__EXIT;
2530 chmod (h, 0700);
2531 tmp = g_strconcat (_("Script created:"), h, (char *) NULL);
2532 edit_error_dialog ("", get_sys_error (tmp));
2533 g_free (tmp);
2536 open_error_pipe ();
2538 if (block)
2539 { /* for marked block run indent formatter */
2540 if (eval_marks (edit, &start_mark, &end_mark))
2542 edit_error_dialog (_("Process block"),
2543 _("You must first highlight a block of text"));
2544 goto edit_block_process_cmd__EXIT;
2546 edit_save_block (edit, b, start_mark, end_mark);
2547 quoted_name = name_quote (edit->filename, 0);
2549 * Run script.
2550 * Initial space is to avoid polluting bash history.
2551 * Arguments:
2552 * $1 - name of the edited file (to check its extension etc).
2553 * $2 - file containing the current block.
2554 * $3 - file where error messages should be put
2555 * (for compatibility with old scripts).
2557 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ", quoted_name,
2558 " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE " /dev/null", (char *) NULL);
2560 else
2563 * No block selected, just execute the command for the file.
2564 * Arguments:
2565 * $1 - name of the edited file.
2567 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
2568 quoted_name, (char *) NULL);
2571 if (system (tmp) == -1)
2573 edit_error_dialog (_("Process block"), _("Error calling program"));
2575 else
2578 g_free (quoted_name);
2579 close_error_pipe (D_NORMAL, NULL);
2581 edit_refresh_cmd (edit);
2582 edit->force |= REDRAW_COMPLETELY;
2584 /* insert result block */
2585 if (block && !edit_block_delete_cmd (edit))
2587 edit_insert_file (edit, b);
2588 block_file = fopen (b, "w");
2589 if (block_file != NULL)
2590 fclose (block_file);
2593 g_free (tmp);
2595 edit_block_process_cmd__EXIT:
2596 g_free (b);
2597 g_free (h);
2598 g_free (o);
2601 /* prints at the cursor */
2602 /* returns the number of chars printed */
2604 edit_print_string (WEdit * e, const char *s)
2606 size_t i = 0;
2607 while (s[i] != '\0')
2608 edit_execute_cmd (e, CK_Insert_Char, (unsigned char) s[i++]);
2609 e->force |= REDRAW_COMPLETELY;
2610 edit_update_screen (e);
2611 return i;
2615 static void
2616 pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
2618 FILE *p = 0;
2619 char *s;
2621 to = name_quote (to, 0);
2622 subject = name_quote (subject, 0);
2623 cc = name_quote (cc, 0);
2624 s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
2625 g_free (to);
2626 g_free (subject);
2627 g_free (cc);
2629 if (s)
2631 p = popen (s, "w");
2632 g_free (s);
2635 if (p)
2637 long i;
2638 for (i = 0; i < edit->last_byte; i++)
2639 fputc (edit_get_byte (edit, i), p);
2640 pclose (p);
2644 #define MAIL_DLG_HEIGHT 12
2646 void
2647 edit_mail_dialog (WEdit * edit)
2649 char *tmail_to;
2650 char *tmail_subject;
2651 char *tmail_cc;
2653 static char *mail_cc_last = 0;
2654 static char *mail_subject_last = 0;
2655 static char *mail_to_last = 0;
2657 QuickWidget quick_widgets[] = {
2658 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
2659 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
2660 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
2661 /* 3 */ QUICK_LABEL (3, 50, 7, MAIL_DLG_HEIGHT, N_("Copies to")),
2662 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
2663 &tmail_subject),
2664 /* 5 */ QUICK_LABEL (3, 50, 5, MAIL_DLG_HEIGHT, N_("Subject")),
2665 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
2666 /* 7 */ QUICK_LABEL (3, 50, 3, MAIL_DLG_HEIGHT, N_("To")),
2667 /* 8 */ QUICK_LABEL (3, 50, 2, MAIL_DLG_HEIGHT, N_("mail -s <subject> -c <cc> <to>")),
2668 QUICK_END
2671 QuickDialog Quick_input = {
2672 50, MAIL_DLG_HEIGHT, -1, -1, N_("Mail"),
2673 "[Input Line Keys]", quick_widgets, FALSE
2676 quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
2677 quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
2678 quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
2680 if (quick_dialog (&Quick_input) != B_CANCEL)
2682 g_free (mail_cc_last);
2683 g_free (mail_subject_last);
2684 g_free (mail_to_last);
2685 mail_cc_last = tmail_cc;
2686 mail_subject_last = tmail_subject;
2687 mail_to_last = tmail_to;
2688 pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
2693 /*******************/
2694 /* Word Completion */
2695 /*******************/
2697 static gboolean
2698 is_break_char (char c)
2700 return (isspace (c) || strchr ("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c));
2703 /* find first character of current word */
2704 static int
2705 edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
2707 int c, last;
2708 gsize i;
2710 /* return if at begin of file */
2711 if (edit->curs1 <= 0)
2712 return 0;
2714 c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
2715 /* return if not at end or in word */
2716 if (is_break_char (c))
2717 return 0;
2719 /* search start of word to be completed */
2720 for (i = 2;; i++)
2722 /* return if at begin of file */
2723 if ((gsize) edit->curs1 < i)
2724 return 0;
2726 last = c;
2727 c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
2729 if (is_break_char (c))
2731 /* return if word starts with digit */
2732 if (isdigit (last))
2733 return 0;
2735 *word_start = edit->curs1 - (i - 1); /* start found */
2736 *word_len = i - 1;
2737 break;
2740 /* success */
2741 return 1;
2744 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2746 /* collect the possible completions */
2747 static gsize
2748 edit_collect_completions (WEdit * edit, long start, gsize word_len,
2749 char *match_expr, struct selection *compl, gsize * num)
2751 gsize len = 0;
2752 gsize max_len = 0;
2753 gsize i;
2754 int skip;
2755 GString *temp;
2756 mc_search_t *srch;
2758 long last_byte;
2760 srch = mc_search_new (match_expr, -1);
2761 if (srch == NULL)
2762 return 0;
2764 if (mc_config_get_bool
2765 (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
2767 last_byte = edit->last_byte;
2769 else
2771 last_byte = start;
2774 srch->search_type = MC_SEARCH_T_REGEX;
2775 srch->is_case_sensitive = TRUE;
2776 srch->search_fn = edit_search_cmd_callback;
2778 /* collect max MAX_WORD_COMPLETIONS completions */
2779 start = -1;
2780 while (1)
2782 /* get next match */
2783 if (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len) == FALSE)
2784 break;
2785 start = srch->normal_offset;
2787 /* add matched completion if not yet added */
2788 temp = g_string_new ("");
2789 for (i = 0; i < len; i++)
2791 skip = edit_get_byte (edit, start + i);
2792 if (isspace (skip))
2793 continue;
2794 g_string_append_c (temp, skip);
2797 skip = 0;
2799 for (i = 0; i < (gsize) * num; i++)
2801 if (strncmp
2802 ((char *) &compl[i].text[word_len],
2803 (char *) &temp->str[word_len], max (len, compl[i].len) - (gsize) word_len) == 0)
2805 struct selection this = compl[i];
2806 for (++i; i < *num; i++)
2808 compl[i - 1] = compl[i];
2810 compl[*num - 1] = this;
2811 skip = 1;
2812 break; /* skip it, already added */
2815 if (skip)
2817 g_string_free (temp, TRUE);
2818 continue;
2820 if (*num == MAX_WORD_COMPLETIONS && MAX_WORD_COMPLETIONS)
2822 g_free (compl[0].text);
2823 for (i = 1; i < *num; i++)
2825 compl[i - 1] = compl[i];
2827 (*num)--;
2829 #ifdef HAVE_CHARSET
2831 GString *recoded;
2832 recoded = str_convert_to_display (temp->str);
2834 if (recoded && recoded->len)
2836 g_string_free (temp, TRUE);
2837 temp = recoded;
2839 else
2840 g_string_free (recoded, TRUE);
2842 #endif
2843 compl[*num].text = temp->str;
2844 compl[*num].len = temp->len;
2845 (*num)++;
2846 start += len;
2847 g_string_free (temp, FALSE);
2849 /* note the maximal length needed for the completion dialog */
2850 if (len > max_len)
2851 max_len = len;
2853 mc_search_free (srch);
2854 return max_len;
2858 * Complete current word using regular expression search
2859 * backwards beginning at the current cursor position.
2861 void
2862 edit_complete_word_cmd (WEdit * edit)
2864 gsize i, max_len, word_len = 0, num_compl = 0;
2865 long word_start = 0;
2866 unsigned char *bufpos;
2867 char *match_expr;
2868 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
2870 /* search start of word to be completed */
2871 if (!edit_find_word_start (edit, &word_start, &word_len))
2872 return;
2874 /* prepare match expression */
2875 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
2877 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2878 match_expr =
2879 g_strdup_printf
2880 ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
2881 (int) word_len, bufpos);
2883 /* collect the possible completions */
2884 /* start search from begin to end of file */
2885 max_len =
2886 edit_collect_completions (edit, word_start, word_len, match_expr,
2887 (struct selection *) &compl, &num_compl);
2889 if (num_compl > 0)
2891 /* insert completed word if there is only one match */
2892 if (num_compl == 1)
2894 for (i = word_len; i < compl[0].len; i++)
2895 edit_insert (edit, *(compl[0].text + i));
2897 /* more than one possible completion => ask the user */
2898 else
2900 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2901 /* !!! pressed again the selection dialog pops up, but that !!! */
2902 /* !!! seems to require a further internal state !!! */
2903 /*tty_beep (); */
2905 /* let the user select the preferred completion */
2906 editcmd_dialog_completion_show (edit, max_len, word_len,
2907 (struct selection *) &compl, num_compl);
2911 g_free (match_expr);
2912 /* release memory before return */
2913 for (i = 0; i < num_compl; i++)
2914 g_free (compl[i].text);
2917 void
2918 edit_select_codepage_cmd (WEdit * edit)
2920 #ifdef HAVE_CHARSET
2921 if (do_select_codepage ())
2922 edit_set_codeset (edit);
2924 edit->force = REDRAW_COMPLETELY;
2925 edit_refresh_cmd (edit);
2926 #else
2927 (void) edit;
2928 #endif
2931 void
2932 edit_insert_literal_cmd (WEdit * edit)
2934 int char_for_insertion = editcmd_dialog_raw_key_query (_("Insert literal"),
2935 _("Press any key:"), 0);
2936 edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
2939 void
2940 edit_execute_macro_cmd (WEdit * edit)
2942 int command =
2943 CK_Macro (editcmd_dialog_raw_key_query (_("Execute macro"), _("Press macro hotkey:"),
2944 1));
2945 if (command == CK_Macro (0))
2946 command = CK_Insert_Char;
2948 edit_execute_key_command (edit, command, -1);
2951 void
2952 edit_begin_end_macro_cmd (WEdit * edit)
2954 /* edit is a pointer to the widget */
2955 if (edit)
2957 unsigned long command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
2958 edit_execute_key_command (edit, command, -1);
2963 edit_load_forward_cmd (WEdit * edit)
2965 if (edit->modified)
2967 if (edit_query_dialog2
2968 (_("Warning"),
2969 _("Current text was modified without a file save\n"
2970 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
2972 edit->force |= REDRAW_COMPLETELY;
2973 return 0;
2976 if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
2978 if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
2980 return 1;
2982 edit_stack_iterator++;
2983 if (edit_history_moveto[edit_stack_iterator].filename)
2985 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
2986 edit_history_moveto[edit_stack_iterator].line);
2987 return 0;
2989 else
2991 return 1;
2994 else
2996 return 1;
3001 edit_load_back_cmd (WEdit * edit)
3003 if (edit->modified)
3005 if (edit_query_dialog2
3006 (_("Warning"),
3007 _("Current text was modified without a file save\n"
3008 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3010 edit->force |= REDRAW_COMPLETELY;
3011 return 0;
3014 if (edit_stack_iterator > 0)
3016 edit_stack_iterator--;
3017 if (edit_history_moveto[edit_stack_iterator].filename)
3019 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3020 edit_history_moveto[edit_stack_iterator].line);
3021 return 0;
3023 else
3025 return 1;
3028 else
3030 return 1;
3034 void
3035 edit_get_match_keyword_cmd (WEdit * edit)
3037 gsize word_len = 0, max_len = 0;
3038 int num_def = 0;
3039 int i;
3040 long word_start = 0;
3041 unsigned char *bufpos;
3042 char *match_expr;
3043 char *path = NULL;
3044 char *ptr = NULL;
3045 char *tagfile = NULL;
3047 etags_hash_t def_hash[MAX_DEFINITIONS];
3049 for (i = 0; i < MAX_DEFINITIONS; i++)
3051 def_hash[i].filename = NULL;
3054 /* search start of word to be completed */
3055 if (!edit_find_word_start (edit, &word_start, &word_len))
3056 return;
3058 /* prepare match expression */
3059 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3060 match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
3062 ptr = g_get_current_dir ();
3063 path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
3064 g_free (ptr);
3066 /* Recursive search file 'TAGS' in parent dirs */
3069 ptr = g_path_get_dirname (path);
3070 g_free (path);
3071 path = ptr;
3072 g_free (tagfile);
3073 tagfile = g_build_filename (path, TAGS_NAME, (char *) NULL);
3074 if (exist_file (tagfile))
3075 break;
3077 while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
3079 if (tagfile)
3081 num_def =
3082 etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
3083 g_free (tagfile);
3085 g_free (path);
3087 max_len = MAX_WIDTH_DEF_DIALOG;
3088 word_len = 0;
3089 if (num_def > 0)
3091 editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
3092 (etags_hash_t *) & def_hash, num_def);
3094 g_free (match_expr);
3097 void
3098 edit_move_block_to_right (WEdit * edit)
3100 long start_mark, end_mark;
3101 long cur_bol, start_bol;
3103 if (eval_marks (edit, &start_mark, &end_mark))
3104 return;
3106 start_bol = edit_bol (edit, start_mark);
3107 cur_bol = edit_bol (edit, end_mark - 1);
3110 edit_cursor_move (edit, cur_bol - edit->curs1);
3111 if (option_fill_tabs_with_spaces)
3113 if (option_fake_half_tabs)
3115 insert_spaces_tab (edit, 1);
3117 else
3119 insert_spaces_tab (edit, 0);
3122 else
3124 edit_insert (edit, '\t');
3126 edit_cursor_move (edit, edit_bol (edit, cur_bol) - edit->curs1);
3127 if (cur_bol == 0)
3129 break;
3131 cur_bol = edit_bol (edit, cur_bol - 1);
3133 while (cur_bol >= start_bol);
3134 edit->force |= REDRAW_PAGE;
3137 void
3138 edit_move_block_to_left (WEdit * edit)
3140 long start_mark, end_mark;
3141 long cur_bol, start_bol;
3142 int i, del_tab_width;
3143 int next_char;
3145 if (eval_marks (edit, &start_mark, &end_mark))
3146 return;
3148 start_bol = edit_bol (edit, start_mark);
3149 cur_bol = edit_bol (edit, end_mark - 1);
3152 edit_cursor_move (edit, cur_bol - edit->curs1);
3153 if (option_fake_half_tabs)
3155 del_tab_width = HALF_TAB_SIZE;
3157 else
3159 del_tab_width = option_tab_spacing;
3161 next_char = edit_get_byte (edit, edit->curs1);
3162 if (next_char == '\t')
3164 edit_delete (edit, 1);
3166 else if (next_char == ' ')
3168 for (i = 1; i <= del_tab_width; i++)
3170 if (next_char == ' ')
3172 edit_delete (edit, 1);
3174 next_char = edit_get_byte (edit, edit->curs1);
3177 if (cur_bol == 0)
3179 break;
3181 cur_bol = edit_bol (edit, cur_bol - 1);
3183 while (cur_bol >= start_bol);
3184 edit->force |= REDRAW_PAGE;