Split file src/keybind.[ch] to lib/keybind.[ch] and src/keybind-defaults.[ch].
[midnight-commander.git] / src / editor / editcmd.c
blob1815acc634c37157367715b0cefb68f7d62a46bd
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/util.h" /* tilde_expand() */
56 #include "lib/vfs/mc-vfs/vfs.h"
57 #include "lib/widget.h"
58 #include "lib/charsets.h"
60 #include "src/history.h"
61 #include "src/layout.h" /* clr_scr() */
62 #include "src/main.h" /* mc_home, midnight_shutdown */
63 #include "src/setup.h" /* option_tab_spacing */
64 #include "src/help.h" /* interactive_display() */
65 #include "src/selcodepage.h"
66 #include "src/keybind-defaults.h"
67 #include "src/clipboard.h" /* copy_file_to_ext_clip, paste_to_file_from_ext_clip */
69 #include "edit-impl.h"
70 #include "edit-widget.h"
71 #include "editcmd_dialogs.h"
72 #include "etags.h"
74 /*** global variables ****************************************************************************/
76 /* search and replace: */
77 int search_create_bookmark = FALSE;
79 /* queries on a save */
80 int edit_confirm_save = 1;
82 static int edit_save_cmd (WEdit * edit);
83 static unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l);
85 /*** file scope macro definitions ****************************************************************/
87 #define space_width 1
89 #define TEMP_BUF_LEN 1024
91 #define INPUT_INDEX 9
93 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
94 (and the above) routines to work properly - paul */
96 #define is_digit(x) ((x) >= '0' && (x) <= '9')
98 #define MAIL_DLG_HEIGHT 12
100 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
102 /*** file scope type declarations ****************************************************************/
104 /*** file scope variables ************************************************************************/
106 /*** file scope functions ************************************************************************/
107 /* --------------------------------------------------------------------------------------------- */
109 /* If 0 (quick save) then a) create/truncate <filename> file,
110 b) save to <filename>;
111 if 1 (safe save) then a) save to <tempnam>,
112 b) rename <tempnam> to <filename>;
113 if 2 (do backups) then a) save to <tempnam>,
114 b) rename <filename> to <filename.backup_ext>,
115 c) rename <tempnam> to <filename>. */
117 /* returns 0 on error, -1 on abort */
119 static int
120 edit_save_file (WEdit * edit, const char *filename)
122 char *p;
123 gchar *tmp;
124 long filelen = 0;
125 char *savename = 0;
126 gchar *real_filename;
127 int this_save_mode, fd = -1;
129 if (!filename)
130 return 0;
131 if (!*filename)
132 return 0;
134 if (*filename != PATH_SEP && edit->dir)
136 real_filename = concat_dir_and_file (edit->dir, filename);
138 else
140 real_filename = g_strdup (filename);
143 this_save_mode = option_save_mode;
144 if (this_save_mode != EDIT_QUICK_SAVE)
146 if (!vfs_file_is_local (real_filename) ||
147 (fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
150 * The file does not exists yet, so no safe save or
151 * backup are necessary.
153 this_save_mode = EDIT_QUICK_SAVE;
155 if (fd != -1)
156 mc_close (fd);
159 if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
161 int rv;
162 struct stat sb;
164 rv = mc_stat (real_filename, &sb);
165 if (rv == 0 && sb.st_nlink > 1)
167 rv = edit_query_dialog3 (_("Warning"),
168 _("File has hard-links. Detach before saving?"),
169 _("&Yes"), _("&No"), _("&Cancel"));
170 switch (rv)
172 case 0:
173 this_save_mode = EDIT_SAFE_SAVE;
174 /* fallthrough */
175 case 1:
176 edit->skip_detach_prompt = 1;
177 break;
178 default:
179 g_free (real_filename);
180 return -1;
184 /* Prevent overwriting changes from other editor sessions. */
185 if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
188 /* The default action is "Cancel". */
189 query_set_sel (1);
191 rv = edit_query_dialog2 (_("Warning"),
192 _("The file has been modified in the meantime. Save anyway?"),
193 _("&Yes"), _("&Cancel"));
194 if (rv != 0)
196 g_free (real_filename);
197 return -1;
202 if (this_save_mode != EDIT_QUICK_SAVE)
204 char *savedir, *saveprefix;
205 const char *slashpos;
206 slashpos = strrchr (real_filename, PATH_SEP);
207 if (slashpos)
209 savedir = g_strdup (real_filename);
210 savedir[slashpos - real_filename + 1] = '\0';
212 else
213 savedir = g_strdup (".");
214 saveprefix = concat_dir_and_file (savedir, "cooledit");
215 g_free (savedir);
216 fd = mc_mkstemps (&savename, saveprefix, NULL);
217 g_free (saveprefix);
218 if (!savename)
220 g_free (real_filename);
221 return 0;
223 /* FIXME:
224 * Close for now because mc_mkstemps use pure open system call
225 * to create temporary file and it needs to be reopened by
226 * VFS-aware mc_open().
228 close (fd);
230 else
231 savename = g_strdup (real_filename);
233 int ret;
234 ret = mc_chown (savename, edit->stat1.st_uid, edit->stat1.st_gid);
235 ret = mc_chmod (savename, edit->stat1.st_mode);
238 fd = mc_open (savename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode);
239 if (fd == -1)
240 goto error_save;
242 /* pipe save */
243 p = edit_get_write_filter (savename, real_filename);
244 if (p != NULL)
246 FILE *file;
248 mc_close (fd);
249 file = (FILE *) popen (p, "w");
251 if (file)
253 filelen = edit_write_stream (edit, file);
254 #if 1
255 pclose (file);
256 #else
257 if (pclose (file) != 0)
259 tmp = g_strdup_printf (_("Error writing to pipe: %s"), p);
260 edit_error_dialog (_("Error"), tmp);
261 g_free (tmp);
262 g_free (p);
263 goto error_save;
265 #endif
267 else
269 tmp = g_strdup_printf (_("Cannot open pipe for writing: %s"), p);
270 edit_error_dialog (_("Error"), get_sys_error (tmp));
271 g_free (p);
272 g_free (tmp);
273 goto error_save;
275 g_free (p);
277 else if (edit->lb == LB_ASIS)
278 { /* do not change line breaks */
279 long buf;
280 buf = 0;
281 filelen = edit->last_byte;
282 while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1)
284 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
286 mc_close (fd);
287 goto error_save;
289 buf++;
291 if (mc_write
292 (fd, (char *) edit->buffers1[buf],
293 edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE))
295 filelen = -1;
297 else if (edit->curs2)
299 edit->curs2--;
300 buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
301 if (mc_write
302 (fd,
303 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
304 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
305 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE))
307 filelen = -1;
309 else
311 while (--buf >= 0)
313 if (mc_write (fd, (char *) edit->buffers2[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
315 filelen = -1;
316 break;
320 edit->curs2++;
322 if (mc_close (fd))
323 goto error_save;
325 /* Update the file information, especially the mtime. */
326 if (mc_stat (savename, &edit->stat1) == -1)
327 goto error_save;
329 else
330 { /* change line breaks */
331 FILE *file;
333 mc_close (fd);
335 file = (FILE *) fopen (savename, "w");
337 if (file)
339 filelen = edit_write_stream (edit, file);
340 fclose (file);
342 else
344 char *msg;
346 msg = g_strdup_printf (_("Cannot open file for writing: %s"), savename);
347 edit_error_dialog (_("Error"), msg);
348 g_free (msg);
349 goto error_save;
353 if (filelen != edit->last_byte)
354 goto error_save;
356 if (this_save_mode == EDIT_DO_BACKUP)
358 assert (option_backup_ext != NULL);
359 tmp = g_strconcat (real_filename, option_backup_ext, (char *) NULL);
360 if (mc_rename (real_filename, tmp) == -1)
362 g_free (tmp);
363 goto error_save;
367 if (this_save_mode != EDIT_QUICK_SAVE)
368 if (mc_rename (savename, real_filename) == -1)
369 goto error_save;
370 g_free (savename);
371 g_free (real_filename);
372 return 1;
373 error_save:
374 /* FIXME: Is this safe ?
375 * if (this_save_mode != EDIT_QUICK_SAVE)
376 * mc_unlink (savename);
378 g_free (real_filename);
379 g_free (savename);
380 return 0;
383 /* --------------------------------------------------------------------------------------------- */
385 static gboolean
386 edit_check_newline (WEdit * edit)
388 return !(option_check_nl_at_eof && edit->last_byte > 0
389 && edit_get_byte (edit, edit->last_byte - 1) != '\n'
390 && edit_query_dialog2 (_("Warning"),
391 _("The file you are saving is not finished with a newline"),
392 _("C&ontinue"), _("&Cancel")));
395 /* --------------------------------------------------------------------------------------------- */
397 static char *
398 edit_get_save_file_as (WEdit * edit)
400 #define DLG_WIDTH 64
401 #define DLG_HEIGHT 14
403 static LineBreaks cur_lb = LB_ASIS;
405 char *filename = edit->filename;
407 const char *lb_names[LB_NAMES] = {
408 N_("&Do not change"),
409 N_("&Unix format (LF)"),
410 N_("&Windows/DOS format (CR LF)"),
411 N_("&Macintosh format (CR)")
414 QuickWidget quick_widgets[] = {
415 QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
416 QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
417 QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
418 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
419 QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
420 "save-as", &filename),
421 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_("Enter file name:")),
422 QUICK_END
425 QuickDialog Quick_options = {
426 DLG_WIDTH, DLG_HEIGHT, -1, -1,
427 N_("Save As"), "[Save File As]",
428 quick_widgets, NULL, FALSE
431 if (quick_dialog (&Quick_options) != B_CANCEL)
433 char *fname;
435 edit->lb = cur_lb;
436 fname = tilde_expand (filename);
437 g_free (filename);
438 return fname;
441 return NULL;
443 #undef DLG_WIDTH
444 #undef DLG_HEIGHT
447 /* {{{ Macro stuff starts here */
449 /* --------------------------------------------------------------------------------------------- */
450 /** creates a macro file if it doesn't exist */
452 static FILE *
453 edit_open_macro_file (const char *r)
455 gchar *filename;
456 FILE *fd;
457 int file;
458 filename = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
459 file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
460 if (file == -1)
462 g_free (filename);
463 return 0;
465 close (file);
466 fd = fopen (filename, r);
467 g_free (filename);
468 return fd;
471 #define MAX_MACROS 1024
472 static int saved_macro[MAX_MACROS + 1];
473 static int saved_macros_loaded = 0;
475 /* --------------------------------------------------------------------------------------------- */
477 This is just to stop the macro file be loaded over and over for keys
478 that aren't defined to anything. On slow systems this could be annoying.
481 static int
482 macro_exists (int k)
484 int i;
485 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
486 if (saved_macro[i] == k)
487 return i;
488 return -1;
491 /* --------------------------------------------------------------------------------------------- */
492 /** returns 1 on error */
494 static int
495 edit_delete_macro (WEdit * edit, int k)
497 gchar *tmp, *tmp2;
498 struct macro macro[MAX_MACRO_LENGTH];
499 FILE *f, *g;
500 int s, i, n, j = 0;
502 (void) edit;
504 if (saved_macros_loaded)
506 j = macro_exists (k);
507 if (j < 0)
508 return 0;
510 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
511 g = fopen (tmp, "w");
512 g_free (tmp);
513 if (!g)
515 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open temp file")));
516 return 1;
518 f = edit_open_macro_file ("r");
519 if (!f)
521 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open macro file")));
522 fclose (g);
523 return 1;
525 for (;;)
527 n = fscanf (f, ("key '%d 0': "), &s);
528 if (!n || n == EOF)
529 break;
530 n = 0;
531 while (fscanf (f, "%lu %d, ", &macro[n].command, &macro[n].ch))
532 n++;
534 int ret;
535 ret = fscanf (f, ";\n");
537 if (s != k)
539 fprintf (g, ("key '%d 0': "), s);
540 for (i = 0; i < n; i++)
541 fprintf (g, "%lu %d, ", macro[i].command, macro[i].ch);
542 fprintf (g, ";\n");
545 fclose (f);
546 fclose (g);
547 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
548 tmp2 = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
549 if (rename (tmp, tmp2) == -1)
551 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot overwrite macro file")));
552 g_free (tmp);
553 g_free (tmp2);
554 return 1;
556 g_free (tmp);
557 g_free (tmp2);
559 if (saved_macros_loaded)
560 memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
561 return 0;
564 /* }}} */
566 /* --------------------------------------------------------------------------------------------- */
567 /** returns 1 on success */
569 static int
570 edit_save_cmd (WEdit * edit)
572 int res, save_lock = 0;
574 if (!edit->locked && !edit->delete_file)
575 save_lock = edit_lock_file (edit);
576 res = edit_save_file (edit, edit->filename);
578 /* Maintain modify (not save) lock on failure */
579 if ((res > 0 && edit->locked) || save_lock)
580 edit->locked = edit_unlock_file (edit);
582 /* On failure try 'save as', it does locking on its own */
583 if (!res)
584 return edit_save_as_cmd (edit);
585 edit->force |= REDRAW_COMPLETELY;
586 if (res > 0)
588 edit->delete_file = 0;
589 edit->modified = 0;
592 return 1;
595 /* --------------------------------------------------------------------------------------------- */
596 /** returns 1 on error */
598 static int
599 edit_load_file_from_filename (WEdit * edit, char *exp)
601 int prev_locked = edit->locked;
602 char *prev_filename = g_strdup (edit->filename);
604 if (!edit_reload (edit, exp))
606 g_free (prev_filename);
607 return 1;
610 if (prev_locked)
612 char *fullpath;
614 fullpath = g_build_filename (edit->dir, prev_filename, (char *) NULL);
615 unlock_file (fullpath);
616 g_free (fullpath);
618 g_free (prev_filename);
619 return 0;
622 /* --------------------------------------------------------------------------------------------- */
624 static void
625 edit_load_syntax_file (WEdit * edit)
627 char *extdir;
628 int dir = 0;
630 if (geteuid () == 0)
632 dir = query_dialog (_("Syntax file edit"),
633 _("Which syntax file you want to edit?"), D_NORMAL, 2,
634 _("&User"), _("&System Wide"));
637 extdir = g_build_filename (mc_home, "syntax", "Syntax", (char *) NULL);
638 if (!exist_file (extdir))
640 g_free (extdir);
641 extdir = g_build_filename (mc_home_alt, "syntax", "Syntax", (char *) NULL);
644 if (dir == 0)
646 char *buffer;
648 buffer = concat_dir_and_file (home_dir, EDIT_SYNTAX_FILE);
649 check_for_default (extdir, buffer);
650 edit_load_file_from_filename (edit, buffer);
651 g_free (buffer);
653 else if (dir == 1)
654 edit_load_file_from_filename (edit, extdir);
656 g_free (extdir);
659 /* --------------------------------------------------------------------------------------------- */
661 static void
662 edit_load_menu_file (WEdit * edit)
664 char *buffer;
665 char *menufile;
666 int dir = 0;
668 dir = query_dialog (_("Menu edit"),
669 _("Which menu file do you want to edit?"), D_NORMAL,
670 geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
672 menufile = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
674 if (!exist_file (menufile))
676 g_free (menufile);
677 menufile = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
680 switch (dir)
682 case 0:
683 buffer = g_strdup (EDIT_LOCAL_MENU);
684 check_for_default (menufile, buffer);
685 chmod (buffer, 0600);
686 break;
688 case 1:
689 buffer = concat_dir_and_file (home_dir, EDIT_HOME_MENU);
690 check_for_default (menufile, buffer);
691 break;
693 case 2:
694 buffer = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
695 if (!exist_file (buffer))
697 g_free (buffer);
698 buffer = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
700 break;
702 default:
703 g_free (menufile);
704 return;
707 edit_load_file_from_filename (edit, buffer);
709 g_free (buffer);
710 g_free (menufile);
713 /* --------------------------------------------------------------------------------------------- */
715 static void
716 edit_delete_column_of_text (WEdit * edit)
718 long p, q, r, m1, m2;
719 long b, c, d, n;
721 eval_marks (edit, &m1, &m2);
722 n = edit_move_forward (edit, m1, 0, m2) + 1;
723 c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
724 d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
725 b = max (min (c, d), min (edit->column1, edit->column2));
726 c = max (c, max (edit->column1, edit->column2));
728 while (n--)
730 r = edit_bol (edit, edit->curs1);
731 p = edit_move_forward3 (edit, r, b, 0);
732 q = edit_move_forward3 (edit, r, c, 0);
733 if (p < m1)
734 p = m1;
735 if (q > m2)
736 q = m2;
737 edit_cursor_move (edit, p - edit->curs1);
738 while (q > p)
740 /* delete line between margins */
741 if (edit_get_byte (edit, edit->curs1) != '\n')
742 edit_delete (edit, 1);
743 q--;
745 if (n)
746 /* move to next line except on the last delete */
747 edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
751 /* --------------------------------------------------------------------------------------------- */
752 /** if success return 0 */
754 static int
755 edit_block_delete (WEdit * edit)
757 long count;
758 long start_mark, end_mark;
759 int curs_pos, line_width;
760 long curs_line, c1, c2;
762 if (eval_marks (edit, &start_mark, &end_mark))
763 return 0;
764 if (edit->column_highlight && edit->mark2 < 0)
765 edit_mark_cmd (edit, 0);
766 if ((end_mark - start_mark) > option_max_undo / 2)
768 /* Warning message with a query to continue or cancel the operation */
769 if (edit_query_dialog2
770 (_("Warning"),
772 ("Block is large, you may not be able to undo this action"),
773 _("C&ontinue"), _("&Cancel")))
775 return 1;
778 c1 = min (edit->column1, edit->column2);
779 c2 = max (edit->column1, edit->column2);
780 edit->column1 = c1;
781 edit->column2 = c2;
783 edit_push_markers (edit);
785 curs_line = edit->curs_line;
787 /* calculate line width and cursor position before cut */
788 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
789 edit_eol (edit, edit->curs1));
790 curs_pos = edit->curs_col + edit->over_col;
792 /* move cursor to start of selection */
793 edit_cursor_move (edit, start_mark - edit->curs1);
794 edit_scroll_screen_over_cursor (edit);
795 count = start_mark;
796 if (start_mark < end_mark)
798 if (edit->column_highlight)
800 if (edit->mark2 < 0)
801 edit_mark_cmd (edit, 0);
802 edit_delete_column_of_text (edit);
803 /* move cursor to the saved position */
804 edit_move_to_line (edit, curs_line);
805 /* calculate line width after cut */
806 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
807 edit_eol (edit, edit->curs1));
808 if (option_cursor_beyond_eol && curs_pos > line_width)
809 edit->over_col = curs_pos - line_width;
811 else
813 while (count < end_mark)
815 edit_delete (edit, 1);
816 count++;
820 edit_set_markers (edit, 0, 0, 0, 0);
821 edit->force |= REDRAW_PAGE;
822 return 0;
825 /* --------------------------------------------------------------------------------------------- */
827 static gboolean
828 editcmd_find (WEdit * edit, gsize * len)
830 off_t search_start = edit->search_start;
831 off_t search_end;
832 long start_mark = 0;
833 long end_mark = edit->last_byte;
834 int mark_res = 0;
836 if (edit_search_options.only_in_selection)
838 mark_res = eval_marks (edit, &start_mark, &end_mark);
839 if (mark_res != 0)
841 edit->search->error = MC_SEARCH_E_NOTFOUND;
842 edit->search->error_str = g_strdup (_("Search string not found"));
843 return FALSE;
845 if (edit_search_options.backwards)
847 if (search_start > end_mark || search_start <= start_mark)
849 search_start = end_mark;
852 else
854 if (search_start < start_mark || search_start >= end_mark)
856 search_start = start_mark;
860 else
862 if (edit_search_options.backwards)
863 end_mark = max (1, edit->curs1) - 1;
865 if (edit_search_options.backwards)
867 search_end = end_mark;
868 while ((int) search_start >= start_mark)
870 if (search_end > (off_t) (search_start + edit->search->original_len) &&
871 mc_search_is_fixed_search_str (edit->search))
873 search_end = search_start + edit->search->original_len;
875 if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
876 && edit->search->normal_offset == search_start)
878 return TRUE;
880 search_start--;
882 edit->search->error_str = g_strdup (_("Search string not found"));
884 else
886 return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
888 return FALSE;
891 /* --------------------------------------------------------------------------------------------- */
893 static char *
894 edit_replace_cmd__conv_to_display (char *str)
896 #ifdef HAVE_CHARSET
897 GString *tmp;
899 tmp = str_convert_to_display (str);
900 if (tmp != NULL)
902 if (tmp->len != 0)
903 return g_string_free (tmp, FALSE);
904 g_string_free (tmp, TRUE);
906 #endif
907 return g_strdup (str);
910 /* --------------------------------------------------------------------------------------------- */
912 static char *
913 edit_replace_cmd__conv_to_input (char *str)
915 #ifdef HAVE_CHARSET
916 GString *tmp;
918 tmp = str_convert_to_input (str);
919 if (tmp != NULL)
921 if (tmp->len != 0)
922 return g_string_free (tmp, FALSE);
923 g_string_free (tmp, TRUE);
925 #endif
926 return g_strdup (str);
929 /* --------------------------------------------------------------------------------------------- */
931 static void
932 edit_do_search (WEdit * edit)
934 gsize len = 0;
936 if (edit->search == NULL)
937 edit->search_start = edit->curs1;
939 edit_push_action (edit, KEY_PRESS + edit->start_display);
941 if (search_create_bookmark)
943 int found = 0, books = 0;
944 long l = 0, l_last = -1;
945 long q = 0;
947 search_create_bookmark = FALSE;
948 book_mark_flush (edit, -1);
950 while (TRUE)
952 if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
953 break;
954 if (found == 0)
955 edit->search_start = edit->search->normal_offset;
956 found++;
957 l += edit_count_lines (edit, q, edit->search->normal_offset);
958 if (l != l_last)
960 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
961 books++;
963 l_last = l;
964 q = edit->search->normal_offset + 1;
967 if (found == 0)
968 edit_error_dialog (_("Search"), _("Search string not found"));
969 else
970 edit_cursor_move (edit, edit->search_start - edit->curs1);
972 else
974 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1
975 && edit_search_options.backwards)
976 edit->search_start--;
978 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1
979 && !edit_search_options.backwards)
980 edit->search_start++;
982 if (editcmd_find (edit, &len))
984 edit->found_start = edit->search_start = edit->search->normal_offset;
985 edit->found_len = len;
986 edit->over_col = 0;
987 edit_cursor_move (edit, edit->search_start - edit->curs1);
988 edit_scroll_screen_over_cursor (edit);
989 if (edit_search_options.backwards)
990 edit->search_start--;
991 else
992 edit->search_start++;
994 else
996 edit->search_start = edit->curs1;
997 if (edit->search->error_str != NULL)
998 edit_error_dialog (_("Search"), edit->search->error_str);
1002 edit->force |= REDRAW_COMPLETELY;
1003 edit_scroll_screen_over_cursor (edit);
1006 /* --------------------------------------------------------------------------------------------- */
1008 static void
1009 edit_search (WEdit *edit)
1011 if (editcmd_dialog_search_show (edit))
1012 edit_do_search (edit);
1015 /* --------------------------------------------------------------------------------------------- */
1016 /** Return a null terminated length of text. Result must be g_free'd */
1018 static unsigned char *
1019 edit_get_block (WEdit * edit, long start, long finish, int *l)
1021 unsigned char *s, *r;
1022 r = s = g_malloc0 (finish - start + 1);
1023 if (edit->column_highlight)
1025 *l = 0;
1026 /* copy from buffer, excluding chars that are out of the column 'margins' */
1027 while (start < finish)
1029 int c;
1030 long x;
1031 x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
1032 c = edit_get_byte (edit, start);
1033 if ((x >= edit->column1 && x < edit->column2)
1034 || (x >= edit->column2 && x < edit->column1) || c == '\n')
1036 *s++ = c;
1037 (*l)++;
1039 start++;
1042 else
1044 *l = finish - start;
1045 while (start < finish)
1046 *s++ = edit_get_byte (edit, start++);
1048 *s = 0;
1049 return r;
1052 /* --------------------------------------------------------------------------------------------- */
1053 /** copies a block to clipboard file */
1055 static int
1056 edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
1058 int ret;
1059 gchar *tmp;
1060 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
1061 ret = edit_save_block (edit, tmp, start, finish);
1062 g_free (tmp);
1063 return ret;
1066 /* --------------------------------------------------------------------------------------------- */
1068 static void
1069 pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
1071 FILE *p = 0;
1072 char *s;
1074 to = name_quote (to, 0);
1075 subject = name_quote (subject, 0);
1076 cc = name_quote (cc, 0);
1077 s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
1078 g_free (to);
1079 g_free (subject);
1080 g_free (cc);
1082 if (s)
1084 p = popen (s, "w");
1085 g_free (s);
1088 if (p)
1090 long i;
1091 for (i = 0; i < edit->last_byte; i++)
1092 fputc (edit_get_byte (edit, i), p);
1093 pclose (p);
1097 /* --------------------------------------------------------------------------------------------- */
1099 static gboolean
1100 is_break_char (char c)
1102 return (isspace (c) || strchr ("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c));
1105 /* --------------------------------------------------------------------------------------------- */
1106 /** find first character of current word */
1108 static int
1109 edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
1111 int c, last;
1112 gsize i;
1114 /* return if at begin of file */
1115 if (edit->curs1 <= 0)
1116 return 0;
1118 c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
1119 /* return if not at end or in word */
1120 if (is_break_char (c))
1121 return 0;
1123 /* search start of word to be completed */
1124 for (i = 2;; i++)
1126 /* return if at begin of file */
1127 if ((gsize) edit->curs1 < i)
1128 return 0;
1130 last = c;
1131 c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
1133 if (is_break_char (c))
1135 /* return if word starts with digit */
1136 if (isdigit (last))
1137 return 0;
1139 *word_start = edit->curs1 - (i - 1); /* start found */
1140 *word_len = i - 1;
1141 break;
1144 /* success */
1145 return 1;
1148 /* --------------------------------------------------------------------------------------------- */
1149 /** collect the possible completions */
1150 static gsize
1151 edit_collect_completions (WEdit * edit, long start, gsize word_len,
1152 char *match_expr, struct selection *compl, gsize * num)
1154 gsize len = 0;
1155 gsize max_len = 0;
1156 gsize i;
1157 int skip;
1158 GString *temp;
1159 mc_search_t *srch;
1161 long last_byte;
1163 srch = mc_search_new (match_expr, -1);
1164 if (srch == NULL)
1165 return 0;
1167 if (mc_config_get_bool
1168 (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
1170 last_byte = edit->last_byte;
1172 else
1174 last_byte = start;
1177 srch->search_type = MC_SEARCH_T_REGEX;
1178 srch->is_case_sensitive = TRUE;
1179 srch->search_fn = edit_search_cmd_callback;
1181 /* collect max MAX_WORD_COMPLETIONS completions */
1182 start = -1;
1183 while (1)
1185 /* get next match */
1186 if (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len) == FALSE)
1187 break;
1188 start = srch->normal_offset;
1190 /* add matched completion if not yet added */
1191 temp = g_string_new ("");
1192 for (i = 0; i < len; i++)
1194 skip = edit_get_byte (edit, start + i);
1195 if (isspace (skip))
1196 continue;
1197 g_string_append_c (temp, skip);
1200 skip = 0;
1202 for (i = 0; i < (gsize) * num; i++)
1204 if (strncmp
1205 ((char *) &compl[i].text[word_len],
1206 (char *) &temp->str[word_len], max (len, compl[i].len) - (gsize) word_len) == 0)
1208 struct selection this = compl[i];
1209 for (++i; i < *num; i++)
1211 compl[i - 1] = compl[i];
1213 compl[*num - 1] = this;
1214 skip = 1;
1215 break; /* skip it, already added */
1218 if (skip)
1220 g_string_free (temp, TRUE);
1221 continue;
1223 if (*num == MAX_WORD_COMPLETIONS && MAX_WORD_COMPLETIONS)
1225 g_free (compl[0].text);
1226 for (i = 1; i < *num; i++)
1228 compl[i - 1] = compl[i];
1230 (*num)--;
1232 #ifdef HAVE_CHARSET
1234 GString *recoded;
1235 recoded = str_convert_to_display (temp->str);
1237 if (recoded && recoded->len)
1239 g_string_free (temp, TRUE);
1240 temp = recoded;
1242 else
1243 g_string_free (recoded, TRUE);
1245 #endif
1246 compl[*num].text = temp->str;
1247 compl[*num].len = temp->len;
1248 (*num)++;
1249 start += len;
1250 g_string_free (temp, FALSE);
1252 /* note the maximal length needed for the completion dialog */
1253 if (len > max_len)
1254 max_len = len;
1256 mc_search_free (srch);
1257 return max_len;
1261 /* --------------------------------------------------------------------------------------------- */
1262 /*** public functions ****************************************************************************/
1263 /* --------------------------------------------------------------------------------------------- */
1265 void
1266 edit_help_cmd (WEdit * edit)
1268 interactive_display (NULL, "[Internal File Editor]");
1269 edit->force |= REDRAW_COMPLETELY;
1272 /* --------------------------------------------------------------------------------------------- */
1274 void
1275 edit_refresh_cmd (WEdit * edit)
1277 #ifdef HAVE_SLANG
1278 int color;
1280 edit_get_syntax_color (edit, -1, &color);
1281 tty_touch_screen ();
1282 mc_refresh ();
1283 #else
1284 (void) edit;
1286 clr_scr ();
1287 repaint_screen ();
1288 #endif /* !HAVE_SLANG */
1289 tty_keypad (TRUE);
1292 /* --------------------------------------------------------------------------------------------- */
1294 void
1295 menu_save_mode_cmd (void)
1297 /* diaog sizes */
1298 const int DLG_X = 38;
1299 const int DLG_Y = 13;
1301 char *str_result;
1303 const char *str[] = {
1304 N_("&Quick save"),
1305 N_("&Safe save"),
1306 N_("&Do backups with following extension:")
1309 QuickWidget widgets[] = {
1310 /* 0 */
1311 QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
1312 /* 1 */
1313 QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
1314 /* 2 */
1315 QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
1316 /* 3 */
1317 QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
1318 /* 4 */
1319 QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
1320 QUICK_END
1323 QuickDialog dialog = {
1324 DLG_X, DLG_Y, -1, -1, N_("Edit Save Mode"),
1325 "[Edit Save Mode]", widgets, NULL, FALSE
1328 size_t i;
1329 size_t maxlen = 0;
1330 size_t w0, w1, b_len, w3;
1332 assert (option_backup_ext != NULL);
1334 /* OK/Cancel buttons */
1335 w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
1336 w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5; /* default button */
1337 b_len = w0 + w1 + 3;
1339 maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
1341 w3 = 0;
1342 for (i = 0; i < 3; i++)
1344 #ifdef ENABLE_NLS
1345 str[i] = _(str[i]);
1346 #endif
1347 w3 = max (w3, (size_t) str_term_width1 (str[i]));
1350 maxlen = max (maxlen, w3 + 4);
1352 dialog.xlen = min ((size_t) COLS, maxlen + 8);
1354 widgets[3].u.input.len = w3;
1355 widgets[1].relative_x = (dialog.xlen - b_len) / 2;
1356 widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
1358 for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
1359 widgets[i].x_divisions = dialog.xlen;
1361 if (quick_dialog (&dialog) != B_CANCEL)
1363 g_free (option_backup_ext);
1364 option_backup_ext = str_result;
1368 /* --------------------------------------------------------------------------------------------- */
1370 void
1371 edit_set_filename (WEdit * edit, const char *name)
1373 g_free (edit->filename);
1375 if (name == NULL)
1376 name = "";
1378 edit->filename = tilde_expand (name);
1379 if (edit->dir == NULL && !g_path_is_absolute (name))
1380 edit->dir = g_strdup (vfs_get_current_dir ());
1383 /* --------------------------------------------------------------------------------------------- */
1384 /* Here we want to warn the users of overwriting an existing file,
1385 but only if they have made a change to the filename */
1386 /* returns 1 on success */
1388 edit_save_as_cmd (WEdit * edit)
1390 /* This heads the 'Save As' dialog box */
1391 char *exp;
1392 int save_lock = 0;
1393 int different_filename = 0;
1395 if (!edit_check_newline (edit))
1396 return 0;
1398 exp = edit_get_save_file_as (edit);
1399 edit_push_action (edit, KEY_PRESS + edit->start_display);
1401 if (exp)
1403 if (!*exp)
1405 g_free (exp);
1406 edit->force |= REDRAW_COMPLETELY;
1407 return 0;
1409 else
1411 int rv;
1412 if (strcmp (edit->filename, exp))
1414 int file;
1415 different_filename = 1;
1416 file = mc_open (exp, O_RDONLY | O_BINARY);
1417 if (file != -1)
1419 /* the file exists */
1420 mc_close (file);
1421 /* Overwrite the current file or cancel the operation */
1422 if (edit_query_dialog2
1423 (_("Warning"),
1424 _("A file already exists with this name"), _("&Overwrite"), _("&Cancel")))
1426 edit->force |= REDRAW_COMPLETELY;
1427 g_free (exp);
1428 return 0;
1431 else
1433 edit->stat1.st_mode |= S_IWUSR;
1435 save_lock = lock_file (exp);
1437 else
1439 /* filenames equal, check if already locked */
1440 if (!edit->locked && !edit->delete_file)
1441 save_lock = lock_file (exp);
1444 if (different_filename)
1447 * Allow user to write into saved (under another name) file
1448 * even if original file had r/o user permissions.
1450 edit->stat1.st_mode |= S_IWRITE;
1453 rv = edit_save_file (edit, exp);
1454 switch (rv)
1456 case 1:
1457 /* Succesful, so unlock both files */
1458 if (different_filename)
1460 if (save_lock)
1461 unlock_file (exp);
1462 if (edit->locked)
1463 edit->locked = edit_unlock_file (edit);
1465 else
1467 if (edit->locked || save_lock)
1468 edit->locked = edit_unlock_file (edit);
1471 edit_set_filename (edit, exp);
1472 if (edit->lb != LB_ASIS)
1473 edit_reload (edit, exp);
1474 g_free (exp);
1475 edit->modified = 0;
1476 edit->delete_file = 0;
1477 if (different_filename)
1478 edit_load_syntax (edit, NULL, edit->syntax_type);
1479 edit->force |= REDRAW_COMPLETELY;
1480 return 1;
1481 default:
1482 edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
1483 /* fallthrough */
1484 case -1:
1485 /* Failed, so maintain modify (not save) lock */
1486 if (save_lock)
1487 unlock_file (exp);
1488 g_free (exp);
1489 edit->force |= REDRAW_COMPLETELY;
1490 return 0;
1494 edit->force |= REDRAW_COMPLETELY;
1495 return 0;
1498 /* {{{ Macro stuff starts here */
1501 /* --------------------------------------------------------------------------------------------- */
1502 /** returns 0 on error */
1505 edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
1507 FILE *f;
1508 int s, i;
1510 edit_push_action (edit, KEY_PRESS + edit->start_display);
1511 s = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
1512 edit->force |= REDRAW_COMPLETELY;
1513 if (s)
1515 if (edit_delete_macro (edit, s))
1516 return 0;
1517 f = edit_open_macro_file ("a+");
1518 if (f)
1520 fprintf (f, ("key '%d 0': "), s);
1521 for (i = 0; i < n; i++)
1522 fprintf (f, "%lu %d, ", macro[i].command, macro[i].ch);
1523 fprintf (f, ";\n");
1524 fclose (f);
1525 if (saved_macros_loaded)
1527 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
1528 saved_macro[i] = s;
1530 return 1;
1532 else
1533 edit_error_dialog (_("Save macro"), get_sys_error (_("Cannot open macro file")));
1535 return 0;
1538 /* --------------------------------------------------------------------------------------------- */
1540 void
1541 edit_delete_macro_cmd (WEdit * edit)
1543 int command;
1545 command = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
1547 if (command != 0)
1548 edit_delete_macro (edit, command);
1551 /* --------------------------------------------------------------------------------------------- */
1552 /** return 0 on error */
1555 edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
1557 FILE *f;
1558 int s, i = 0, found = 0;
1560 (void) edit;
1562 if (saved_macros_loaded)
1563 if (macro_exists (k) < 0)
1564 return 0;
1566 f = edit_open_macro_file ("r");
1567 if (f != NULL)
1569 struct macro dummy;
1572 int u;
1573 u = fscanf (f, ("key '%d 0': "), &s);
1574 if (!u || u == EOF)
1575 break;
1576 if (!saved_macros_loaded)
1577 saved_macro[i++] = s;
1578 if (!found)
1580 *n = 0;
1581 while (*n < MAX_MACRO_LENGTH
1582 && 2 == fscanf (f, "%lu %d, ", &macro[*n].command, &macro[*n].ch))
1583 (*n)++;
1585 else
1587 while (2 == fscanf (f, "%lu %d, ", &dummy.command, &dummy.ch));
1590 int ret;
1591 ret = fscanf (f, ";\n");
1593 if (s == k)
1594 found = 1;
1596 while (!found || !saved_macros_loaded);
1597 if (!saved_macros_loaded)
1599 saved_macro[i] = 0;
1600 saved_macros_loaded = 1;
1602 fclose (f);
1603 return found;
1605 else
1606 edit_error_dialog (_("Load macro"), get_sys_error (_("Cannot open macro file")));
1607 return 0;
1610 /* }}} Macro stuff starts here */
1612 /* --------------------------------------------------------------------------------------------- */
1613 /** returns 1 on success */
1616 edit_save_confirm_cmd (WEdit * edit)
1618 gchar *f = NULL;
1620 if (!edit_check_newline (edit))
1621 return 0;
1623 if (edit_confirm_save)
1625 f = g_strdup_printf (_("Confirm save file: \"%s\""), edit->filename);
1626 if (edit_query_dialog2 (_("Save file"), f, _("&Save"), _("&Cancel")))
1628 g_free (f);
1629 return 0;
1631 g_free (f);
1633 return edit_save_cmd (edit);
1637 /* --------------------------------------------------------------------------------------------- */
1638 /** returns 1 on success */
1641 edit_new_cmd (WEdit * edit)
1643 if (edit->modified)
1645 if (edit_query_dialog2
1646 (_("Warning"),
1648 ("Current text was modified without a file save.\nContinue discards these changes"),
1649 _("C&ontinue"), _("&Cancel")))
1651 edit->force |= REDRAW_COMPLETELY;
1652 return 0;
1655 edit->force |= REDRAW_COMPLETELY;
1657 return edit_renew (edit); /* if this gives an error, something has really screwed up */
1660 /* --------------------------------------------------------------------------------------------- */
1663 edit_load_cmd (WEdit * edit, edit_current_file_t what)
1665 char *exp;
1667 if (edit->modified
1668 && (edit_query_dialog2
1669 (_("Warning"),
1670 _("Current text was modified without a file save.\n"
1671 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")) == 1))
1673 edit->force |= REDRAW_COMPLETELY;
1674 return 0;
1677 switch (what)
1679 case EDIT_FILE_COMMON:
1680 exp = input_expand_dialog (_("Load"), _("Enter file name:"),
1681 MC_HISTORY_EDIT_LOAD, edit->filename);
1683 if (exp)
1685 if (*exp)
1686 edit_load_file_from_filename (edit, exp);
1687 g_free (exp);
1689 break;
1691 case EDIT_FILE_SYNTAX:
1692 edit_load_syntax_file (edit);
1693 break;
1695 case EDIT_FILE_MENU:
1696 edit_load_menu_file (edit);
1697 break;
1699 default:
1700 break;
1703 edit->force |= REDRAW_COMPLETELY;
1704 return 0;
1707 /* --------------------------------------------------------------------------------------------- */
1709 if mark2 is -1 then marking is from mark1 to the cursor.
1710 Otherwise its between the markers. This handles this.
1711 Returns 1 if no text is marked.
1715 eval_marks (WEdit * edit, long *start_mark, long *end_mark)
1717 if (edit->mark1 != edit->mark2)
1719 long start_bol, start_eol;
1720 long end_bol, end_eol;
1721 long col1, col2;
1722 long diff1, diff2;
1723 if (edit->mark2 >= 0)
1725 *start_mark = min (edit->mark1, edit->mark2);
1726 *end_mark = max (edit->mark1, edit->mark2);
1728 else
1730 *start_mark = min (edit->mark1, edit->curs1);
1731 *end_mark = max (edit->mark1, edit->curs1);
1732 edit->column2 = edit->curs_col + edit->over_col;
1734 if (edit->column_highlight
1735 && (((edit->mark1 > edit->curs1) && (edit->column1 < edit->column2))
1736 || ((edit->mark1 < edit->curs1) && (edit->column1 > edit->column2))))
1739 start_bol = edit_bol (edit, *start_mark);
1740 start_eol = edit_eol (edit, start_bol - 1) + 1;
1741 end_bol = edit_bol (edit, *end_mark);
1742 end_eol = edit_eol (edit, *end_mark);
1743 col1 = min (edit->column1, edit->column2);
1744 col2 = max (edit->column1, edit->column2);
1746 diff1 =
1747 edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
1748 col1, 0);
1749 diff2 =
1750 edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
1751 col1, 0);
1753 *start_mark -= diff1;
1754 *end_mark += diff2;
1755 *start_mark = max (*start_mark, start_eol);
1756 *end_mark = min (*end_mark, end_eol);
1758 return 0;
1760 else
1762 *start_mark = *end_mark = 0;
1763 edit->column2 = edit->column1 = 0;
1764 return 1;
1768 /* --------------------------------------------------------------------------------------------- */
1770 void
1771 edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
1773 long cursor;
1774 int i, col;
1775 cursor = edit->curs1;
1776 col = edit_get_col (edit);
1777 for (i = 0; i < size; i++)
1779 if (data[i] == '\n')
1780 { /* fill in and move to next line */
1781 int l;
1782 long p;
1783 if (edit_get_byte (edit, edit->curs1) != '\n')
1785 l = width - (edit_get_col (edit) - col);
1786 while (l > 0)
1788 edit_insert (edit, ' ');
1789 l -= space_width;
1792 for (p = edit->curs1;; p++)
1794 if (p == edit->last_byte)
1796 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1797 edit_insert_ahead (edit, '\n');
1798 p++;
1799 break;
1801 if (edit_get_byte (edit, p) == '\n')
1803 p++;
1804 break;
1807 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1808 l = col - edit_get_col (edit);
1809 while (l >= space_width)
1811 edit_insert (edit, ' ');
1812 l -= space_width;
1814 continue;
1816 edit_insert (edit, data[i]);
1818 edit_cursor_move (edit, cursor - edit->curs1);
1821 /* --------------------------------------------------------------------------------------------- */
1824 edit_insert_column_of_text_from_file (WEdit * edit, int file)
1826 long cursor;
1827 int i, col;
1828 int blocklen = -1, width;
1829 unsigned char *data;
1830 cursor = edit->curs1;
1831 col = edit_get_col (edit);
1832 data = g_malloc0 (TEMP_BUF_LEN);
1833 while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
1835 for (width = 0; width < blocklen; width++)
1837 if (data[width] == '\n')
1838 break;
1840 for (i = 0; i < blocklen; i++)
1842 if (data[i] == '\n')
1843 { /* fill in and move to next line */
1844 int l;
1845 long p;
1846 if (edit_get_byte (edit, edit->curs1) != '\n')
1848 l = width - (edit_get_col (edit) - col);
1849 while (l > 0)
1851 edit_insert (edit, ' ');
1852 l -= space_width;
1855 for (p = edit->curs1;; p++)
1857 if (p == edit->last_byte)
1859 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1860 edit_insert_ahead (edit, '\n');
1861 p++;
1862 break;
1864 if (edit_get_byte (edit, p) == '\n')
1866 p++;
1867 break;
1870 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1871 l = col - edit_get_col (edit);
1872 while (l >= space_width)
1874 edit_insert (edit, ' ');
1875 l -= space_width;
1877 continue;
1879 edit_insert (edit, data[i]);
1882 edit_cursor_move (edit, cursor - edit->curs1);
1883 g_free (data);
1884 edit->force |= REDRAW_PAGE;
1885 return blocklen;
1888 /* --------------------------------------------------------------------------------------------- */
1890 void
1891 edit_block_copy_cmd (WEdit * edit)
1893 long start_mark, end_mark, current = edit->curs1;
1894 int size;
1895 unsigned char *copy_buf;
1897 edit_update_curs_col (edit);
1898 if (eval_marks (edit, &start_mark, &end_mark))
1899 return;
1901 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1903 /* all that gets pushed are deletes hence little space is used on the stack */
1905 edit_push_markers (edit);
1907 if (edit->column_highlight)
1909 edit_insert_column_of_text (edit, copy_buf, size, abs (edit->column2 - edit->column1));
1911 else
1913 while (size--)
1914 edit_insert_ahead (edit, copy_buf[size]);
1917 g_free (copy_buf);
1918 edit_scroll_screen_over_cursor (edit);
1920 if (edit->column_highlight)
1922 edit_set_markers (edit, 0, 0, 0, 0);
1923 edit_push_action (edit, COLUMN_ON);
1924 edit->column_highlight = 0;
1926 else if (start_mark < current && end_mark > current)
1927 edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
1929 edit->force |= REDRAW_PAGE;
1933 /* --------------------------------------------------------------------------------------------- */
1935 void
1936 edit_block_move_cmd (WEdit * edit)
1938 long count;
1939 long current;
1940 unsigned char *copy_buf;
1941 long start_mark, end_mark;
1942 int deleted = 0;
1943 int x = 0;
1945 if (eval_marks (edit, &start_mark, &end_mark))
1946 return;
1947 if (edit->column_highlight)
1949 edit_update_curs_col (edit);
1950 x = edit->curs_col;
1951 if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1952 if ((x > edit->column1 && x < edit->column2)
1953 || (x > edit->column2 && x < edit->column1))
1954 return;
1956 else if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1957 return;
1959 if ((end_mark - start_mark) > option_max_undo / 2)
1960 if (edit_query_dialog2
1961 (_("Warning"),
1963 ("Block is large, you may not be able to undo this action"),
1964 _("C&ontinue"), _("&Cancel")))
1965 return;
1967 edit_push_markers (edit);
1968 current = edit->curs1;
1969 if (edit->column_highlight)
1971 long line;
1972 int size, c1, c2;
1973 line = edit->curs_line;
1974 if (edit->mark2 < 0)
1975 edit_mark_cmd (edit, 0);
1976 c1 = min (edit->column1, edit->column2);
1977 c2 = max (edit->column1, edit->column2);
1978 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1979 if (x < c2)
1981 edit_block_delete_cmd (edit);
1982 deleted = 1;
1984 edit_move_to_line (edit, line);
1985 edit_cursor_move (edit,
1986 edit_move_forward3 (edit,
1987 edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
1988 edit_insert_column_of_text (edit, copy_buf, size, c2 - c1);
1989 if (!deleted)
1991 line = edit->curs_line;
1992 edit_update_curs_col (edit);
1993 x = edit->curs_col;
1994 edit_block_delete_cmd (edit);
1995 edit_move_to_line (edit, line);
1996 edit_cursor_move (edit,
1997 edit_move_forward3 (edit,
1998 edit_bol (edit,
1999 edit->curs1), x, 0) - edit->curs1);
2001 edit_set_markers (edit, 0, 0, 0, 0);
2002 edit_push_action (edit, COLUMN_ON);
2003 edit->column_highlight = 0;
2005 else
2007 copy_buf = g_malloc0 (end_mark - start_mark);
2008 edit_cursor_move (edit, start_mark - edit->curs1);
2009 edit_scroll_screen_over_cursor (edit);
2010 count = start_mark;
2011 while (count < end_mark)
2013 copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
2014 count++;
2016 edit_scroll_screen_over_cursor (edit);
2017 edit_cursor_move (edit,
2018 current - edit->curs1 -
2019 (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
2020 edit_scroll_screen_over_cursor (edit);
2021 while (count-- > start_mark)
2022 edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
2023 edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
2025 edit_scroll_screen_over_cursor (edit);
2026 g_free (copy_buf);
2027 edit->force |= REDRAW_PAGE;
2030 /* --------------------------------------------------------------------------------------------- */
2031 /** returns 1 if canceelled by user */
2034 edit_block_delete_cmd (WEdit * edit)
2036 long start_mark, end_mark;
2037 if (eval_marks (edit, &start_mark, &end_mark))
2039 edit_delete_line (edit);
2040 return 0;
2042 return edit_block_delete (edit);
2045 /* --------------------------------------------------------------------------------------------- */
2046 /** call with edit = 0 before shutdown to close memory leaks */
2048 void
2049 edit_replace_cmd (WEdit * edit, int again)
2051 /* 1 = search string, 2 = replace with */
2052 static char *saved1 = NULL; /* saved default[123] */
2053 static char *saved2 = NULL;
2054 char *input1 = NULL; /* user input from the dialog */
2055 char *input2 = NULL;
2056 char *disp1 = NULL;
2057 char *disp2 = NULL;
2058 long times_replaced = 0;
2059 gboolean once_found = FALSE;
2061 if (!edit)
2063 g_free (saved1), saved1 = NULL;
2064 g_free (saved2), saved2 = NULL;
2065 return;
2068 edit->force |= REDRAW_COMPLETELY;
2070 if (again && !saved1 && !saved2)
2071 again = 0;
2073 if (again)
2075 input1 = g_strdup (saved1 ? saved1 : "");
2076 input2 = g_strdup (saved2 ? saved2 : "");
2078 else
2080 char *tmp_inp1, *tmp_inp2;
2081 disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
2082 disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
2084 edit_push_action (edit, KEY_PRESS + edit->start_display);
2086 editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
2088 g_free (disp1);
2089 g_free (disp2);
2091 if (input1 == NULL || *input1 == '\0')
2093 edit->force = REDRAW_COMPLETELY;
2094 goto cleanup;
2097 tmp_inp1 = input1;
2098 tmp_inp2 = input2;
2099 input1 = edit_replace_cmd__conv_to_input (input1);
2100 input2 = edit_replace_cmd__conv_to_input (input2);
2101 g_free (tmp_inp1);
2102 g_free (tmp_inp2);
2104 g_free (saved1), saved1 = g_strdup (input1);
2105 g_free (saved2), saved2 = g_strdup (input2);
2107 mc_search_free (edit->search);
2108 edit->search = NULL;
2111 if (!edit->search)
2113 edit->search = mc_search_new (input1, -1);
2114 if (edit->search == NULL)
2116 edit->search_start = edit->curs1;
2117 goto cleanup;
2119 edit->search->search_type = edit_search_options.type;
2120 edit->search->is_all_charsets = edit_search_options.all_codepages;
2121 edit->search->is_case_sensitive = edit_search_options.case_sens;
2122 edit->search->whole_words = edit_search_options.whole_words;
2123 edit->search->search_fn = edit_search_cmd_callback;
2126 if (edit->found_len && edit->search_start == edit->found_start + 1
2127 && edit_search_options.backwards)
2128 edit->search_start--;
2130 if (edit->found_len && edit->search_start == edit->found_start - 1
2131 && !edit_search_options.backwards)
2132 edit->search_start++;
2136 gsize len = 0;
2138 if (!editcmd_find (edit, &len))
2140 if (!(edit->search->error == MC_SEARCH_E_OK ||
2141 (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
2143 edit_error_dialog (_("Search"), edit->search->error_str);
2145 break;
2147 once_found = TRUE;
2149 edit->search_start = edit->search->normal_offset;
2150 /*returns negative on not found or error in pattern */
2152 if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
2154 gsize i;
2155 GString *tmp_str, *repl_str;
2157 edit->found_start = edit->search_start;
2158 i = edit->found_len = len;
2160 edit_cursor_move (edit, edit->search_start - edit->curs1);
2161 edit_scroll_screen_over_cursor (edit);
2163 if (edit->replace_mode == 0)
2165 int l;
2166 int prompt;
2168 l = edit->curs_row - edit->num_widget_lines / 3;
2169 if (l > 0)
2170 edit_scroll_downward (edit, l);
2171 if (l < 0)
2172 edit_scroll_upward (edit, -l);
2174 edit_scroll_screen_over_cursor (edit);
2175 edit->force |= REDRAW_PAGE;
2176 edit_render_keypress (edit);
2178 /*so that undo stops at each query */
2179 edit_push_key_press (edit);
2180 /* and prompt 2/3 down */
2181 disp1 = edit_replace_cmd__conv_to_display (saved1);
2182 disp2 = edit_replace_cmd__conv_to_display (saved2);
2183 prompt = editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
2184 g_free (disp1);
2185 g_free (disp2);
2187 if (prompt == B_REPLACE_ALL)
2188 edit->replace_mode = 1;
2189 else if (prompt == B_SKIP_REPLACE)
2191 if (edit_search_options.backwards)
2192 edit->search_start--;
2193 else
2194 edit->search_start++;
2195 continue; /* loop */
2197 else if (prompt == B_CANCEL)
2199 edit->replace_mode = -1;
2200 break; /* loop */
2204 /* don't process string each time */
2205 tmp_str = g_string_new (input2);
2206 repl_str = mc_search_prepare_replace_str (edit->search, tmp_str);
2207 g_string_free (tmp_str, TRUE);
2209 if (edit->search->error != MC_SEARCH_E_OK)
2211 edit_error_dialog (_("Replace"), edit->search->error_str);
2212 g_string_free (repl_str, TRUE);
2213 break;
2216 /* delete then insert new */
2217 for (i = 0; i < len; i++)
2218 edit_delete (edit, 1);
2220 for (i = 0; i < repl_str->len; i++)
2221 edit_insert (edit, repl_str->str[i]);
2223 edit->found_len = repl_str->len;
2224 g_string_free (repl_str, TRUE);
2225 times_replaced++;
2227 /* so that we don't find the same string again */
2228 if (edit_search_options.backwards)
2229 edit->search_start--;
2230 else
2232 edit->search_start += edit->found_len;
2234 if (edit->search_start >= edit->last_byte)
2235 break;
2238 edit_scroll_screen_over_cursor (edit);
2240 else
2242 /* try and find from right here for next search */
2243 edit->search_start = edit->curs1;
2244 edit_update_curs_col (edit);
2246 edit->force |= REDRAW_PAGE;
2247 edit_render_keypress (edit);
2249 if (times_replaced == 0)
2250 query_dialog (_("Replace"), _("Search string not found"), D_NORMAL, 1, _("&OK"));
2251 break;
2254 while (edit->replace_mode >= 0);
2256 edit_scroll_screen_over_cursor (edit);
2257 edit->force |= REDRAW_COMPLETELY;
2258 edit_render_keypress (edit);
2260 if ((edit->replace_mode == 1) && (times_replaced != 0))
2261 message (D_NORMAL, _("Replace"), _("%ld replacements made"), times_replaced);
2263 cleanup:
2264 g_free (input1);
2265 g_free (input2);
2268 /* --------------------------------------------------------------------------------------------- */
2271 edit_search_cmd_callback (const void *user_data, gsize char_offset)
2273 return edit_get_byte ((WEdit *) user_data, (long) char_offset);
2276 /* --------------------------------------------------------------------------------------------- */
2278 void
2279 edit_search_cmd (WEdit * edit, gboolean again)
2281 if (edit == NULL)
2282 return;
2284 if (!again)
2285 edit_search (edit);
2286 else if (edit->last_search_string != NULL)
2287 edit_do_search (edit);
2288 else
2290 /* find last search string in history */
2291 GList *history;
2293 history = history_get (MC_HISTORY_SHARED_SEARCH);
2294 if (history != NULL && history->data != NULL)
2296 edit->last_search_string = (char *) history->data;
2297 history->data = NULL;
2298 history = g_list_first (history);
2299 g_list_foreach (history, (GFunc) g_free, NULL);
2300 g_list_free (history);
2302 edit->search = mc_search_new (edit->last_search_string, -1);
2303 if (edit->search == NULL)
2305 /* if not... then ask for an expression */
2306 g_free (edit->last_search_string);
2307 edit->last_search_string = NULL;
2308 edit_search (edit);
2310 else
2312 edit->search->search_type = edit_search_options.type;
2313 edit->search->is_all_charsets = edit_search_options.all_codepages;
2314 edit->search->is_case_sensitive = edit_search_options.case_sens;
2315 edit->search->whole_words = edit_search_options.whole_words;
2316 edit->search->search_fn = edit_search_cmd_callback;
2317 edit_do_search (edit);
2320 else
2322 /* if not... then ask for an expression */
2323 g_free (edit->last_search_string);
2324 edit->last_search_string = NULL;
2325 edit_search (edit);
2331 /* --------------------------------------------------------------------------------------------- */
2333 * Check if it's OK to close the editor. If there are unsaved changes,
2334 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
2337 gboolean
2338 edit_ok_to_exit (WEdit * edit)
2340 int act;
2342 if (!edit->modified)
2343 return TRUE;
2345 if (!midnight_shutdown)
2347 if (!edit_check_newline (edit))
2348 return FALSE;
2350 query_set_sel (2);
2351 act = edit_query_dialog3 (_("Quit"), _("File was modified. Save with exit?"),
2352 _("&Yes"), _("&No"), _("&Cancel quit"));
2354 else
2356 act =
2357 edit_query_dialog2 (_("Quit"),
2358 _("Midnight Commander is being shut down.\nSave modified file?"),
2359 _("&Yes"), _("&No"));
2361 /* Esc is No */
2362 if (act == -1)
2363 act = 1;
2366 switch (act)
2368 case 0: /* Yes */
2369 edit_push_markers (edit);
2370 edit_set_markers (edit, 0, 0, 0, 0);
2371 if (!edit_save_cmd (edit) || midnight_shutdown)
2372 return (gboolean) midnight_shutdown;
2373 break;
2374 case 1: /* No */
2375 break;
2376 case 2: /* Cancel quit */
2377 case -1: /* Esc */
2378 return FALSE;
2381 return TRUE;
2384 /* --------------------------------------------------------------------------------------------- */
2385 /** save block, returns 1 on success */
2388 edit_save_block (WEdit * edit, const char *filename, long start, long finish)
2390 int len, file;
2392 file = mc_open (filename, O_CREAT | O_WRONLY | O_TRUNC,
2393 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY);
2394 if (file == -1)
2395 return 0;
2397 if (edit->column_highlight)
2399 int r;
2400 r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
2401 if (r > 0)
2403 unsigned char *block, *p;
2404 p = block = edit_get_block (edit, start, finish, &len);
2405 while (len)
2407 r = mc_write (file, p, len);
2408 if (r < 0)
2409 break;
2410 p += r;
2411 len -= r;
2413 g_free (block);
2416 else
2418 unsigned char *buf;
2419 int i = start, end;
2420 len = finish - start;
2421 buf = g_malloc0 (TEMP_BUF_LEN);
2422 while (start != finish)
2424 end = min (finish, start + TEMP_BUF_LEN);
2425 for (; i < end; i++)
2426 buf[i - start] = edit_get_byte (edit, i);
2427 len -= mc_write (file, (char *) buf, end - start);
2428 start = end;
2430 g_free (buf);
2432 mc_close (file);
2433 if (len)
2434 return 0;
2435 return 1;
2438 /* --------------------------------------------------------------------------------------------- */
2440 void
2441 edit_paste_from_history (WEdit * edit)
2443 (void) edit;
2444 edit_error_dialog (_("Error"), _("This function is not implemented"));
2447 /* --------------------------------------------------------------------------------------------- */
2450 edit_copy_to_X_buf_cmd (WEdit * edit)
2452 long start_mark, end_mark;
2453 if (eval_marks (edit, &start_mark, &end_mark))
2454 return 0;
2455 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2457 edit_error_dialog (_("Copy to clipboard"), get_sys_error (_("Unable to save to file")));
2458 return 1;
2460 /* try use external clipboard utility */
2461 copy_file_to_ext_clip ();
2463 edit_mark_cmd (edit, 1);
2464 return 0;
2467 /* --------------------------------------------------------------------------------------------- */
2470 edit_cut_to_X_buf_cmd (WEdit * edit)
2472 long start_mark, end_mark;
2473 if (eval_marks (edit, &start_mark, &end_mark))
2474 return 0;
2475 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2477 edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
2478 return 1;
2480 /* try use external clipboard utility */
2481 copy_file_to_ext_clip ();
2483 edit_block_delete_cmd (edit);
2484 edit_mark_cmd (edit, 1);
2485 return 0;
2488 /* --------------------------------------------------------------------------------------------- */
2490 void
2491 edit_paste_from_X_buf_cmd (WEdit * edit)
2493 gchar *tmp;
2494 /* try use external clipboard utility */
2495 paste_to_file_from_ext_clip ();
2496 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2497 edit_insert_file (edit, tmp);
2498 g_free (tmp);
2502 /* --------------------------------------------------------------------------------------------- */
2504 * Ask user for the line and go to that line.
2505 * Negative numbers mean line from the end (i.e. -1 is the last line).
2508 void
2509 edit_goto_cmd (WEdit * edit)
2511 char *f;
2512 static long line = 0; /* line as typed, saved as default */
2513 long l;
2514 char *error;
2515 char s[32];
2517 g_snprintf (s, sizeof (s), "%ld", line);
2518 f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE, line ? s : "");
2519 if (!f)
2520 return;
2522 if (!*f)
2524 g_free (f);
2525 return;
2528 l = strtol (f, &error, 0);
2529 if (*error)
2531 g_free (f);
2532 return;
2535 line = l;
2536 if (l < 0)
2537 l = edit->total_lines + l + 2;
2538 edit_move_display (edit, l - edit->num_widget_lines / 2 - 1);
2539 edit_move_to_line (edit, l - 1);
2540 edit->force |= REDRAW_COMPLETELY;
2541 g_free (f);
2545 /* --------------------------------------------------------------------------------------------- */
2546 /** Return 1 on success */
2549 edit_save_block_cmd (WEdit * edit)
2551 long start_mark, end_mark;
2552 char *exp, *tmp;
2554 if (eval_marks (edit, &start_mark, &end_mark))
2555 return 1;
2557 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2558 exp =
2559 input_expand_dialog (_("Save block"), _("Enter file name:"),
2560 MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
2561 g_free (tmp);
2562 edit_push_action (edit, KEY_PRESS + edit->start_display);
2563 if (exp)
2565 if (!*exp)
2567 g_free (exp);
2568 return 0;
2570 else
2572 if (edit_save_block (edit, exp, start_mark, end_mark))
2574 g_free (exp);
2575 edit->force |= REDRAW_COMPLETELY;
2576 return 1;
2578 else
2580 g_free (exp);
2581 edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
2585 edit->force |= REDRAW_COMPLETELY;
2586 return 0;
2590 /* --------------------------------------------------------------------------------------------- */
2591 /** returns 1 on success */
2594 edit_insert_file_cmd (WEdit * edit)
2596 gchar *tmp;
2597 char *exp;
2599 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2600 exp = input_expand_dialog (_("Insert file"), _("Enter file name:"),
2601 MC_HISTORY_EDIT_INSERT_FILE, tmp);
2602 g_free (tmp);
2603 edit_push_action (edit, KEY_PRESS + edit->start_display);
2604 if (exp)
2606 if (!*exp)
2608 g_free (exp);
2609 return 0;
2611 else
2613 if (edit_insert_file (edit, exp))
2615 g_free (exp);
2616 edit->force |= REDRAW_COMPLETELY;
2617 return 1;
2619 else
2621 g_free (exp);
2622 edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
2626 edit->force |= REDRAW_COMPLETELY;
2627 return 0;
2630 /* --------------------------------------------------------------------------------------------- */
2631 /** sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2634 edit_sort_cmd (WEdit * edit)
2636 static char *old = 0;
2637 char *exp, *tmp;
2638 long start_mark, end_mark;
2639 int e;
2641 if (eval_marks (edit, &start_mark, &end_mark))
2643 edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
2644 return 0;
2647 tmp = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE);
2648 edit_save_block (edit, tmp, start_mark, end_mark);
2649 g_free (tmp);
2651 exp = input_dialog (_("Run sort"),
2652 _("Enter sort options (see manpage) separated by whitespace:"),
2653 MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
2655 if (!exp)
2656 return 1;
2657 g_free (old);
2658 old = exp;
2659 tmp = g_strconcat (" sort ", exp, " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE, " > ",
2660 home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2661 e = system (tmp);
2662 g_free (tmp);
2663 if (e)
2665 if (e == -1 || e == 127)
2667 edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
2669 else
2671 char q[8];
2672 sprintf (q, "%d ", e);
2673 tmp = g_strdup_printf (_("Sort returned non-zero: %s"), q);
2674 edit_error_dialog (_("Sort"), tmp);
2675 g_free (tmp);
2677 return -1;
2680 edit->force |= REDRAW_COMPLETELY;
2682 if (edit_block_delete_cmd (edit))
2683 return 1;
2684 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2685 edit_insert_file (edit, tmp);
2686 g_free (tmp);
2687 return 0;
2690 /* --------------------------------------------------------------------------------------------- */
2692 * Ask user for a command, execute it and paste its output back to the
2693 * editor.
2697 edit_ext_cmd (WEdit * edit)
2699 char *exp, *tmp;
2700 int e;
2702 exp =
2703 input_dialog (_("Paste output of external command"),
2704 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
2706 if (!exp)
2707 return 1;
2709 tmp = g_strconcat (exp, " > ", home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2710 e = system (tmp);
2711 g_free (tmp);
2712 g_free (exp);
2714 if (e)
2716 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
2717 return -1;
2720 edit->force |= REDRAW_COMPLETELY;
2721 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2722 edit_insert_file (edit, tmp);
2723 g_free (tmp);
2724 return 0;
2727 /* --------------------------------------------------------------------------------------------- */
2728 /** if block is 1, a block must be highlighted and the shell command
2729 processes it. If block is 0 the shell command is a straight system
2730 command, that just produces some output which is to be inserted */
2732 void
2733 edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
2735 long start_mark, end_mark;
2736 char buf[BUFSIZ];
2737 FILE *script_home = NULL;
2738 FILE *block_file = NULL;
2739 gchar *o, *h, *b, *tmp;
2740 char *quoted_name = NULL;
2742 o = g_strconcat (mc_home, shell_cmd, (char *) NULL); /* original source script */
2743 h = g_strconcat (home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, (char *) NULL); /* home script */
2744 b = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE); /* block file */
2746 script_home = fopen (h, "r");
2747 if (script_home == NULL)
2749 FILE *script_src = NULL;
2751 script_home = fopen (h, "w");
2752 if (script_home == NULL)
2754 tmp = g_strconcat (_("Error creating script:"), h, (char *) NULL);
2755 edit_error_dialog ("", get_sys_error (tmp));
2756 g_free (tmp);
2757 goto edit_block_process_cmd__EXIT;
2760 script_src = fopen (o, "r");
2761 if (script_src == NULL)
2763 o = g_strconcat (mc_home_alt, shell_cmd, (char *) NULL);
2764 script_src = fopen (o, "r");
2765 if (script_src == NULL)
2767 fclose (script_home);
2768 unlink (h);
2769 tmp = g_strconcat (_("Error reading script:"), o, (char *) NULL);
2770 edit_error_dialog ("", get_sys_error (tmp));
2771 g_free (tmp);
2772 goto edit_block_process_cmd__EXIT;
2775 while (fgets (buf, sizeof (buf), script_src))
2776 fputs (buf, script_home);
2777 fclose (script_src);
2779 if (fclose (script_home))
2781 tmp = g_strconcat (_("Error closing script:"), h, (char *) NULL);
2782 edit_error_dialog ("", get_sys_error (tmp));
2783 g_free (tmp);
2784 goto edit_block_process_cmd__EXIT;
2786 chmod (h, 0700);
2787 tmp = g_strconcat (_("Script created:"), h, (char *) NULL);
2788 edit_error_dialog ("", get_sys_error (tmp));
2789 g_free (tmp);
2792 open_error_pipe ();
2794 if (block)
2795 { /* for marked block run indent formatter */
2796 if (eval_marks (edit, &start_mark, &end_mark))
2798 edit_error_dialog (_("Process block"), _("You must first highlight a block of text"));
2799 goto edit_block_process_cmd__EXIT;
2801 edit_save_block (edit, b, start_mark, end_mark);
2802 quoted_name = name_quote (edit->filename, 0);
2804 * Run script.
2805 * Initial space is to avoid polluting bash history.
2806 * Arguments:
2807 * $1 - name of the edited file (to check its extension etc).
2808 * $2 - file containing the current block.
2809 * $3 - file where error messages should be put
2810 * (for compatibility with old scripts).
2812 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ", quoted_name,
2813 " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE " /dev/null", (char *) NULL);
2815 else
2818 * No block selected, just execute the command for the file.
2819 * Arguments:
2820 * $1 - name of the edited file.
2822 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
2823 quoted_name, (char *) NULL);
2826 if (system (tmp) == -1)
2828 edit_error_dialog (_("Process block"), _("Error calling program"));
2830 else
2833 g_free (quoted_name);
2834 close_error_pipe (D_NORMAL, NULL);
2836 edit_refresh_cmd (edit);
2837 edit->force |= REDRAW_COMPLETELY;
2839 /* insert result block */
2840 if (block && !edit_block_delete_cmd (edit))
2842 edit_insert_file (edit, b);
2843 block_file = fopen (b, "w");
2844 if (block_file != NULL)
2845 fclose (block_file);
2848 g_free (tmp);
2850 edit_block_process_cmd__EXIT:
2851 g_free (b);
2852 g_free (h);
2853 g_free (o);
2856 /* --------------------------------------------------------------------------------------------- */
2858 * prints at the cursor
2859 * @returns the number of chars printed
2863 edit_print_string (WEdit * e, const char *s)
2865 size_t i = 0;
2866 while (s[i] != '\0')
2867 edit_execute_cmd (e, CK_Insert_Char, (unsigned char) s[i++]);
2868 e->force |= REDRAW_COMPLETELY;
2869 edit_update_screen (e);
2870 return i;
2873 /* --------------------------------------------------------------------------------------------- */
2875 void
2876 edit_mail_dialog (WEdit * edit)
2878 char *tmail_to;
2879 char *tmail_subject;
2880 char *tmail_cc;
2882 static char *mail_cc_last = 0;
2883 static char *mail_subject_last = 0;
2884 static char *mail_to_last = 0;
2886 QuickWidget quick_widgets[] = {
2887 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
2888 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
2889 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
2890 /* 3 */ QUICK_LABEL (3, 50, 7, MAIL_DLG_HEIGHT, N_("Copies to")),
2891 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
2892 &tmail_subject),
2893 /* 5 */ QUICK_LABEL (3, 50, 5, MAIL_DLG_HEIGHT, N_("Subject")),
2894 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
2895 /* 7 */ QUICK_LABEL (3, 50, 3, MAIL_DLG_HEIGHT, N_("To")),
2896 /* 8 */ QUICK_LABEL (3, 50, 2, MAIL_DLG_HEIGHT, N_("mail -s <subject> -c <cc> <to>")),
2897 QUICK_END
2900 QuickDialog Quick_input = {
2901 50, MAIL_DLG_HEIGHT, -1, -1, N_("Mail"),
2902 "[Input Line Keys]", quick_widgets, NULL, FALSE
2905 quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
2906 quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
2907 quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
2909 if (quick_dialog (&Quick_input) != B_CANCEL)
2911 g_free (mail_cc_last);
2912 g_free (mail_subject_last);
2913 g_free (mail_to_last);
2914 mail_cc_last = tmail_cc;
2915 mail_subject_last = tmail_subject;
2916 mail_to_last = tmail_to;
2917 pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
2922 /*******************/
2923 /* Word Completion */
2924 /*******************/
2926 /* --------------------------------------------------------------------------------------------- */
2928 * Complete current word using regular expression search
2929 * backwards beginning at the current cursor position.
2932 void
2933 edit_complete_word_cmd (WEdit * edit)
2935 gsize i, max_len, word_len = 0, num_compl = 0;
2936 long word_start = 0;
2937 unsigned char *bufpos;
2938 char *match_expr;
2939 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
2941 /* search start of word to be completed */
2942 if (!edit_find_word_start (edit, &word_start, &word_len))
2943 return;
2945 /* prepare match expression */
2946 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
2948 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2949 match_expr =
2950 g_strdup_printf
2951 ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
2952 (int) word_len, bufpos);
2954 /* collect the possible completions */
2955 /* start search from begin to end of file */
2956 max_len =
2957 edit_collect_completions (edit, word_start, word_len, match_expr,
2958 (struct selection *) &compl, &num_compl);
2960 if (num_compl > 0)
2962 /* insert completed word if there is only one match */
2963 if (num_compl == 1)
2965 for (i = word_len; i < compl[0].len; i++)
2966 edit_insert (edit, *(compl[0].text + i));
2968 /* more than one possible completion => ask the user */
2969 else
2971 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2972 /* !!! pressed again the selection dialog pops up, but that !!! */
2973 /* !!! seems to require a further internal state !!! */
2974 /*tty_beep (); */
2976 /* let the user select the preferred completion */
2977 editcmd_dialog_completion_show (edit, max_len, word_len,
2978 (struct selection *) &compl, num_compl);
2982 g_free (match_expr);
2983 /* release memory before return */
2984 for (i = 0; i < num_compl; i++)
2985 g_free (compl[i].text);
2988 /* --------------------------------------------------------------------------------------------- */
2990 void
2991 edit_select_codepage_cmd (WEdit * edit)
2993 #ifdef HAVE_CHARSET
2994 if (do_select_codepage ())
2995 edit_set_codeset (edit);
2997 edit->force = REDRAW_COMPLETELY;
2998 edit_refresh_cmd (edit);
2999 #else
3000 (void) edit;
3001 #endif
3004 /* --------------------------------------------------------------------------------------------- */
3006 void
3007 edit_insert_literal_cmd (WEdit * edit)
3009 int char_for_insertion = editcmd_dialog_raw_key_query (_("Insert literal"),
3010 _("Press any key:"), 0);
3011 edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
3014 /* --------------------------------------------------------------------------------------------- */
3016 void
3017 edit_execute_macro_cmd (WEdit * edit)
3019 int command =
3020 CK_Macro (editcmd_dialog_raw_key_query (_("Execute macro"), _("Press macro hotkey:"),
3021 1));
3022 if (command == CK_Macro (0))
3023 command = CK_Insert_Char;
3025 edit_execute_key_command (edit, command, -1);
3028 /* --------------------------------------------------------------------------------------------- */
3030 void
3031 edit_begin_end_macro_cmd (WEdit * edit)
3033 /* edit is a pointer to the widget */
3034 if (edit)
3036 unsigned long command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
3037 edit_execute_key_command (edit, command, -1);
3041 /* --------------------------------------------------------------------------------------------- */
3044 edit_load_forward_cmd (WEdit * edit)
3046 if (edit->modified)
3048 if (edit_query_dialog2
3049 (_("Warning"),
3050 _("Current text was modified without a file save\n"
3051 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3053 edit->force |= REDRAW_COMPLETELY;
3054 return 0;
3057 if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
3059 if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
3061 return 1;
3063 edit_stack_iterator++;
3064 if (edit_history_moveto[edit_stack_iterator].filename)
3066 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3067 edit_history_moveto[edit_stack_iterator].line);
3068 return 0;
3070 else
3072 return 1;
3075 else
3077 return 1;
3081 /* --------------------------------------------------------------------------------------------- */
3084 edit_load_back_cmd (WEdit * edit)
3086 if (edit->modified)
3088 if (edit_query_dialog2
3089 (_("Warning"),
3090 _("Current text was modified without a file save\n"
3091 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3093 edit->force |= REDRAW_COMPLETELY;
3094 return 0;
3097 if (edit_stack_iterator > 0)
3099 edit_stack_iterator--;
3100 if (edit_history_moveto[edit_stack_iterator].filename)
3102 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3103 edit_history_moveto[edit_stack_iterator].line);
3104 return 0;
3106 else
3108 return 1;
3111 else
3113 return 1;
3117 /* --------------------------------------------------------------------------------------------- */
3119 void
3120 edit_get_match_keyword_cmd (WEdit * edit)
3122 gsize word_len = 0, max_len = 0;
3123 int num_def = 0;
3124 int i;
3125 long word_start = 0;
3126 unsigned char *bufpos;
3127 char *match_expr;
3128 char *path = NULL;
3129 char *ptr = NULL;
3130 char *tagfile = NULL;
3132 etags_hash_t def_hash[MAX_DEFINITIONS];
3134 for (i = 0; i < MAX_DEFINITIONS; i++)
3136 def_hash[i].filename = NULL;
3139 /* search start of word to be completed */
3140 if (!edit_find_word_start (edit, &word_start, &word_len))
3141 return;
3143 /* prepare match expression */
3144 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3145 match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
3147 ptr = g_get_current_dir ();
3148 path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
3149 g_free (ptr);
3151 /* Recursive search file 'TAGS' in parent dirs */
3154 ptr = g_path_get_dirname (path);
3155 g_free (path);
3156 path = ptr;
3157 g_free (tagfile);
3158 tagfile = g_build_filename (path, TAGS_NAME, (char *) NULL);
3159 if (exist_file (tagfile))
3160 break;
3162 while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
3164 if (tagfile)
3166 num_def =
3167 etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
3168 g_free (tagfile);
3170 g_free (path);
3172 max_len = MAX_WIDTH_DEF_DIALOG;
3173 word_len = 0;
3174 if (num_def > 0)
3176 editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
3177 (etags_hash_t *) & def_hash, num_def);
3179 g_free (match_expr);
3182 /* --------------------------------------------------------------------------------------------- */
3184 void
3185 edit_move_block_to_right (WEdit * edit)
3187 long start_mark, end_mark;
3188 long cur_bol, start_bol;
3190 if (eval_marks (edit, &start_mark, &end_mark))
3191 return;
3193 start_bol = edit_bol (edit, start_mark);
3194 cur_bol = edit_bol (edit, end_mark - 1);
3197 edit_cursor_move (edit, cur_bol - edit->curs1);
3198 if (option_fill_tabs_with_spaces)
3200 if (option_fake_half_tabs)
3202 insert_spaces_tab (edit, 1);
3204 else
3206 insert_spaces_tab (edit, 0);
3209 else
3211 edit_insert (edit, '\t');
3213 edit_cursor_move (edit, edit_bol (edit, cur_bol) - edit->curs1);
3214 if (cur_bol == 0)
3216 break;
3218 cur_bol = edit_bol (edit, cur_bol - 1);
3220 while (cur_bol >= start_bol);
3221 edit->force |= REDRAW_PAGE;
3224 /* --------------------------------------------------------------------------------------------- */
3226 void
3227 edit_move_block_to_left (WEdit * edit)
3229 long start_mark, end_mark;
3230 long cur_bol, start_bol;
3231 int i, del_tab_width;
3232 int next_char;
3234 if (eval_marks (edit, &start_mark, &end_mark))
3235 return;
3237 start_bol = edit_bol (edit, start_mark);
3238 cur_bol = edit_bol (edit, end_mark - 1);
3241 edit_cursor_move (edit, cur_bol - edit->curs1);
3242 if (option_fake_half_tabs)
3244 del_tab_width = HALF_TAB_SIZE;
3246 else
3248 del_tab_width = option_tab_spacing;
3250 next_char = edit_get_byte (edit, edit->curs1);
3251 if (next_char == '\t')
3253 edit_delete (edit, 1);
3255 else if (next_char == ' ')
3257 for (i = 1; i <= del_tab_width; i++)
3259 if (next_char == ' ')
3261 edit_delete (edit, 1);
3263 next_char = edit_get_byte (edit, edit->curs1);
3266 if (cur_bol == 0)
3268 break;
3270 cur_bol = edit_bol (edit, cur_bol - 1);
3272 while (cur_bol >= start_bol);
3273 edit->force |= REDRAW_PAGE;
3276 /* --------------------------------------------------------------------------------------------- */