extfs helpers: Replace all 'gawk' occurences with @AWK@ meta variable.
[midnight-commander.git] / src / editor / editcmd.c
blobcdc3eb13e800b00c921f7def603b548f96616faa
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/filemanager/layout.h" /* clr_scr() */
62 #include "src/history.h"
63 #include "src/main.h" /* mc_home, midnight_shutdown */
64 #include "src/setup.h" /* option_tab_spacing */
65 #include "src/help.h" /* interactive_display() */
66 #include "src/selcodepage.h"
67 #include "src/keybind-defaults.h"
68 #include "src/clipboard.h" /* copy_file_to_ext_clip, paste_to_file_from_ext_clip */
70 #include "edit-impl.h"
71 #include "edit-widget.h"
72 #include "editcmd_dialogs.h"
73 #include "etags.h"
75 /*** global variables ****************************************************************************/
77 /* search and replace: */
78 int search_create_bookmark = FALSE;
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 /*** file scope macro definitions ****************************************************************/
88 #define space_width 1
90 #define TEMP_BUF_LEN 1024
92 #define INPUT_INDEX 9
94 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
95 (and the above) routines to work properly - paul */
97 #define is_digit(x) ((x) >= '0' && (x) <= '9')
99 #define MAIL_DLG_HEIGHT 12
101 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
103 /*** file scope type declarations ****************************************************************/
105 /*** file scope variables ************************************************************************/
107 /*** file scope functions ************************************************************************/
108 /* --------------------------------------------------------------------------------------------- */
110 /* If 0 (quick save) then a) create/truncate <filename> file,
111 b) save to <filename>;
112 if 1 (safe save) then a) save to <tempnam>,
113 b) rename <tempnam> to <filename>;
114 if 2 (do backups) then a) save to <tempnam>,
115 b) rename <filename> to <filename.backup_ext>,
116 c) rename <tempnam> to <filename>. */
118 /* returns 0 on error, -1 on abort */
120 static int
121 edit_save_file (WEdit * edit, const char *filename)
123 char *p;
124 gchar *tmp;
125 long filelen = 0;
126 char *savename = 0;
127 gchar *real_filename;
128 int this_save_mode, fd = -1;
130 if (!filename)
131 return 0;
132 if (!*filename)
133 return 0;
135 if (*filename != PATH_SEP && edit->dir)
137 real_filename = concat_dir_and_file (edit->dir, filename);
139 else
141 real_filename = g_strdup (filename);
144 this_save_mode = option_save_mode;
145 if (this_save_mode != EDIT_QUICK_SAVE)
147 if (!vfs_file_is_local (real_filename) ||
148 (fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
151 * The file does not exists yet, so no safe save or
152 * backup are necessary.
154 this_save_mode = EDIT_QUICK_SAVE;
156 if (fd != -1)
157 mc_close (fd);
160 if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
162 int rv;
163 struct stat sb;
165 rv = mc_stat (real_filename, &sb);
166 if (rv == 0 && sb.st_nlink > 1)
168 rv = edit_query_dialog3 (_("Warning"),
169 _("File has hard-links. Detach before saving?"),
170 _("&Yes"), _("&No"), _("&Cancel"));
171 switch (rv)
173 case 0:
174 this_save_mode = EDIT_SAFE_SAVE;
175 /* fallthrough */
176 case 1:
177 edit->skip_detach_prompt = 1;
178 break;
179 default:
180 g_free (real_filename);
181 return -1;
185 /* Prevent overwriting changes from other editor sessions. */
186 if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
189 /* The default action is "Cancel". */
190 query_set_sel (1);
192 rv = edit_query_dialog2 (_("Warning"),
193 _("The file has been modified in the meantime. Save anyway?"),
194 _("&Yes"), _("&Cancel"));
195 if (rv != 0)
197 g_free (real_filename);
198 return -1;
203 if (this_save_mode != EDIT_QUICK_SAVE)
205 char *savedir, *saveprefix;
206 const char *slashpos;
207 slashpos = strrchr (real_filename, PATH_SEP);
208 if (slashpos)
210 savedir = g_strdup (real_filename);
211 savedir[slashpos - real_filename + 1] = '\0';
213 else
214 savedir = g_strdup (".");
215 saveprefix = concat_dir_and_file (savedir, "cooledit");
216 g_free (savedir);
217 fd = mc_mkstemps (&savename, saveprefix, NULL);
218 g_free (saveprefix);
219 if (!savename)
221 g_free (real_filename);
222 return 0;
224 /* FIXME:
225 * Close for now because mc_mkstemps use pure open system call
226 * to create temporary file and it needs to be reopened by
227 * VFS-aware mc_open().
229 close (fd);
231 else
232 savename = g_strdup (real_filename);
234 int ret;
235 ret = mc_chown (savename, edit->stat1.st_uid, edit->stat1.st_gid);
236 ret = mc_chmod (savename, edit->stat1.st_mode);
239 fd = mc_open (savename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode);
240 if (fd == -1)
241 goto error_save;
243 /* pipe save */
244 p = edit_get_write_filter (savename, real_filename);
245 if (p != NULL)
247 FILE *file;
249 mc_close (fd);
250 file = (FILE *) popen (p, "w");
252 if (file)
254 filelen = edit_write_stream (edit, file);
255 #if 1
256 pclose (file);
257 #else
258 if (pclose (file) != 0)
260 tmp = g_strdup_printf (_("Error writing to pipe: %s"), p);
261 edit_error_dialog (_("Error"), tmp);
262 g_free (tmp);
263 g_free (p);
264 goto error_save;
266 #endif
268 else
270 tmp = g_strdup_printf (_("Cannot open pipe for writing: %s"), p);
271 edit_error_dialog (_("Error"), get_sys_error (tmp));
272 g_free (p);
273 g_free (tmp);
274 goto error_save;
276 g_free (p);
278 else if (edit->lb == LB_ASIS)
279 { /* do not change line breaks */
280 long buf;
281 buf = 0;
282 filelen = edit->last_byte;
283 while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1)
285 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
287 mc_close (fd);
288 goto error_save;
290 buf++;
292 if (mc_write
293 (fd, (char *) edit->buffers1[buf],
294 edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE))
296 filelen = -1;
298 else if (edit->curs2)
300 edit->curs2--;
301 buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
302 if (mc_write
303 (fd,
304 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
305 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
306 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE))
308 filelen = -1;
310 else
312 while (--buf >= 0)
314 if (mc_write (fd, (char *) edit->buffers2[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
316 filelen = -1;
317 break;
321 edit->curs2++;
323 if (mc_close (fd))
324 goto error_save;
326 /* Update the file information, especially the mtime. */
327 if (mc_stat (savename, &edit->stat1) == -1)
328 goto error_save;
330 else
331 { /* change line breaks */
332 FILE *file;
334 mc_close (fd);
336 file = (FILE *) fopen (savename, "w");
338 if (file)
340 filelen = edit_write_stream (edit, file);
341 fclose (file);
343 else
345 char *msg;
347 msg = g_strdup_printf (_("Cannot open file for writing: %s"), savename);
348 edit_error_dialog (_("Error"), msg);
349 g_free (msg);
350 goto error_save;
354 if (filelen != edit->last_byte)
355 goto error_save;
357 if (this_save_mode == EDIT_DO_BACKUP)
359 assert (option_backup_ext != NULL);
360 tmp = g_strconcat (real_filename, option_backup_ext, (char *) NULL);
361 if (mc_rename (real_filename, tmp) == -1)
363 g_free (tmp);
364 goto error_save;
368 if (this_save_mode != EDIT_QUICK_SAVE)
369 if (mc_rename (savename, real_filename) == -1)
370 goto error_save;
371 g_free (savename);
372 g_free (real_filename);
373 return 1;
374 error_save:
375 /* FIXME: Is this safe ?
376 * if (this_save_mode != EDIT_QUICK_SAVE)
377 * mc_unlink (savename);
379 g_free (real_filename);
380 g_free (savename);
381 return 0;
384 /* --------------------------------------------------------------------------------------------- */
386 static gboolean
387 edit_check_newline (WEdit * edit)
389 return !(option_check_nl_at_eof && edit->last_byte > 0
390 && edit_get_byte (edit, edit->last_byte - 1) != '\n'
391 && edit_query_dialog2 (_("Warning"),
392 _("The file you are saving is not finished with a newline"),
393 _("C&ontinue"), _("&Cancel")));
396 /* --------------------------------------------------------------------------------------------- */
398 static char *
399 edit_get_save_file_as (WEdit * edit)
401 #define DLG_WIDTH 64
402 #define DLG_HEIGHT 14
404 static LineBreaks cur_lb = LB_ASIS;
406 char *filename = edit->filename;
408 const char *lb_names[LB_NAMES] = {
409 N_("&Do not change"),
410 N_("&Unix format (LF)"),
411 N_("&Windows/DOS format (CR LF)"),
412 N_("&Macintosh format (CR)")
415 QuickWidget quick_widgets[] = {
416 QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
417 QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
418 QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
419 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
420 QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
421 "save-as", &filename),
422 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_("Enter file name:")),
423 QUICK_END
426 QuickDialog Quick_options = {
427 DLG_WIDTH, DLG_HEIGHT, -1, -1,
428 N_("Save As"), "[Save File As]",
429 quick_widgets, NULL, FALSE
432 if (quick_dialog (&Quick_options) != B_CANCEL)
434 char *fname;
436 edit->lb = cur_lb;
437 fname = tilde_expand (filename);
438 g_free (filename);
439 return fname;
442 return NULL;
444 #undef DLG_WIDTH
445 #undef DLG_HEIGHT
448 /* {{{ Macro stuff starts here */
450 /* --------------------------------------------------------------------------------------------- */
451 /** creates a macro file if it doesn't exist */
453 static FILE *
454 edit_open_macro_file (const char *r)
456 gchar *filename;
457 FILE *fd;
458 int file;
459 filename = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
460 file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
461 if (file == -1)
463 g_free (filename);
464 return 0;
466 close (file);
467 fd = fopen (filename, r);
468 g_free (filename);
469 return fd;
472 #define MAX_MACROS 1024
473 static int saved_macro[MAX_MACROS + 1];
474 static int saved_macros_loaded = 0;
476 /* --------------------------------------------------------------------------------------------- */
478 This is just to stop the macro file be loaded over and over for keys
479 that aren't defined to anything. On slow systems this could be annoying.
482 static int
483 macro_exists (int k)
485 int i;
486 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
487 if (saved_macro[i] == k)
488 return i;
489 return -1;
492 /* --------------------------------------------------------------------------------------------- */
493 /** returns 1 on error */
495 static int
496 edit_delete_macro (WEdit * edit, int k)
498 gchar *tmp, *tmp2;
499 struct macro macro[MAX_MACRO_LENGTH];
500 FILE *f, *g;
501 int s, i, n, j = 0;
503 (void) edit;
505 if (saved_macros_loaded)
507 j = macro_exists (k);
508 if (j < 0)
509 return 0;
511 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
512 g = fopen (tmp, "w");
513 g_free (tmp);
514 if (!g)
516 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open temp file")));
517 return 1;
519 f = edit_open_macro_file ("r");
520 if (!f)
522 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open macro file")));
523 fclose (g);
524 return 1;
526 for (;;)
528 n = fscanf (f, ("key '%d 0': "), &s);
529 if (!n || n == EOF)
530 break;
531 n = 0;
532 while (fscanf (f, "%lu %d, ", &macro[n].command, &macro[n].ch))
533 n++;
535 int ret;
536 ret = fscanf (f, ";\n");
538 if (s != k)
540 fprintf (g, ("key '%d 0': "), s);
541 for (i = 0; i < n; i++)
542 fprintf (g, "%lu %d, ", macro[i].command, macro[i].ch);
543 fprintf (g, ";\n");
546 fclose (f);
547 fclose (g);
548 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
549 tmp2 = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
550 if (rename (tmp, tmp2) == -1)
552 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot overwrite macro file")));
553 g_free (tmp);
554 g_free (tmp2);
555 return 1;
557 g_free (tmp);
558 g_free (tmp2);
560 if (saved_macros_loaded)
561 memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
562 return 0;
565 /* }}} */
567 /* --------------------------------------------------------------------------------------------- */
568 /** returns 1 on success */
570 static int
571 edit_save_cmd (WEdit * edit)
573 int res, save_lock = 0;
575 if (!edit->locked && !edit->delete_file)
576 save_lock = edit_lock_file (edit);
577 res = edit_save_file (edit, edit->filename);
579 /* Maintain modify (not save) lock on failure */
580 if ((res > 0 && edit->locked) || save_lock)
581 edit->locked = edit_unlock_file (edit);
583 /* On failure try 'save as', it does locking on its own */
584 if (!res)
585 return edit_save_as_cmd (edit);
586 edit->force |= REDRAW_COMPLETELY;
587 if (res > 0)
589 edit->delete_file = 0;
590 edit->modified = 0;
593 return 1;
596 /* --------------------------------------------------------------------------------------------- */
597 /** returns 1 on error */
599 static int
600 edit_load_file_from_filename (WEdit * edit, char *exp)
602 int prev_locked = edit->locked;
603 char *prev_filename = g_strdup (edit->filename);
605 if (!edit_reload (edit, exp))
607 g_free (prev_filename);
608 return 1;
611 if (prev_locked)
613 char *fullpath;
615 fullpath = g_build_filename (edit->dir, prev_filename, (char *) NULL);
616 unlock_file (fullpath);
617 g_free (fullpath);
619 g_free (prev_filename);
620 return 0;
623 /* --------------------------------------------------------------------------------------------- */
625 static void
626 edit_load_syntax_file (WEdit * edit)
628 char *extdir;
629 int dir = 0;
631 if (geteuid () == 0)
633 dir = query_dialog (_("Syntax file edit"),
634 _("Which syntax file you want to edit?"), D_NORMAL, 2,
635 _("&User"), _("&System Wide"));
638 extdir = g_build_filename (mc_home, "syntax", "Syntax", (char *) NULL);
639 if (!exist_file (extdir))
641 g_free (extdir);
642 extdir = g_build_filename (mc_home_alt, "syntax", "Syntax", (char *) NULL);
645 if (dir == 0)
647 char *buffer;
649 buffer = concat_dir_and_file (home_dir, EDIT_SYNTAX_FILE);
650 check_for_default (extdir, buffer);
651 edit_load_file_from_filename (edit, buffer);
652 g_free (buffer);
654 else if (dir == 1)
655 edit_load_file_from_filename (edit, extdir);
657 g_free (extdir);
660 /* --------------------------------------------------------------------------------------------- */
662 static void
663 edit_load_menu_file (WEdit * edit)
665 char *buffer;
666 char *menufile;
667 int dir = 0;
669 dir = query_dialog (_("Menu edit"),
670 _("Which menu file do you want to edit?"), D_NORMAL,
671 geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
673 menufile = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
675 if (!exist_file (menufile))
677 g_free (menufile);
678 menufile = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
681 switch (dir)
683 case 0:
684 buffer = g_strdup (EDIT_LOCAL_MENU);
685 check_for_default (menufile, buffer);
686 chmod (buffer, 0600);
687 break;
689 case 1:
690 buffer = concat_dir_and_file (home_dir, EDIT_HOME_MENU);
691 check_for_default (menufile, buffer);
692 break;
694 case 2:
695 buffer = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
696 if (!exist_file (buffer))
698 g_free (buffer);
699 buffer = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
701 break;
703 default:
704 g_free (menufile);
705 return;
708 edit_load_file_from_filename (edit, buffer);
710 g_free (buffer);
711 g_free (menufile);
714 /* --------------------------------------------------------------------------------------------- */
716 static void
717 edit_delete_column_of_text (WEdit * edit)
719 long p, q, r, m1, m2;
720 long b, c, d, n;
722 eval_marks (edit, &m1, &m2);
723 n = edit_move_forward (edit, m1, 0, m2) + 1;
724 c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
725 d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
726 b = max (min (c, d), min (edit->column1, edit->column2));
727 c = max (c, max (edit->column1, edit->column2));
729 while (n--)
731 r = edit_bol (edit, edit->curs1);
732 p = edit_move_forward3 (edit, r, b, 0);
733 q = edit_move_forward3 (edit, r, c, 0);
734 if (p < m1)
735 p = m1;
736 if (q > m2)
737 q = m2;
738 edit_cursor_move (edit, p - edit->curs1);
739 while (q > p)
741 /* delete line between margins */
742 if (edit_get_byte (edit, edit->curs1) != '\n')
743 edit_delete (edit, 1);
744 q--;
746 if (n)
747 /* move to next line except on the last delete */
748 edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
752 /* --------------------------------------------------------------------------------------------- */
753 /** if success return 0 */
755 static int
756 edit_block_delete (WEdit * edit)
758 long count;
759 long start_mark, end_mark;
760 int curs_pos, line_width;
761 long curs_line, c1, c2;
763 if (eval_marks (edit, &start_mark, &end_mark))
764 return 0;
765 if (edit->column_highlight && edit->mark2 < 0)
766 edit_mark_cmd (edit, 0);
767 if ((end_mark - start_mark) > option_max_undo / 2)
769 /* Warning message with a query to continue or cancel the operation */
770 if (edit_query_dialog2
771 (_("Warning"),
773 ("Block is large, you may not be able to undo this action"),
774 _("C&ontinue"), _("&Cancel")))
776 return 1;
779 c1 = min (edit->column1, edit->column2);
780 c2 = max (edit->column1, edit->column2);
781 edit->column1 = c1;
782 edit->column2 = c2;
784 edit_push_markers (edit);
786 curs_line = edit->curs_line;
788 /* calculate line width and cursor position before cut */
789 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
790 edit_eol (edit, edit->curs1));
791 curs_pos = edit->curs_col + edit->over_col;
793 /* move cursor to start of selection */
794 edit_cursor_move (edit, start_mark - edit->curs1);
795 edit_scroll_screen_over_cursor (edit);
796 count = start_mark;
797 if (start_mark < end_mark)
799 if (edit->column_highlight)
801 if (edit->mark2 < 0)
802 edit_mark_cmd (edit, 0);
803 edit_delete_column_of_text (edit);
804 /* move cursor to the saved position */
805 edit_move_to_line (edit, curs_line);
806 /* calculate line width after cut */
807 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
808 edit_eol (edit, edit->curs1));
809 if (option_cursor_beyond_eol && curs_pos > line_width)
810 edit->over_col = curs_pos - line_width;
812 else
814 while (count < end_mark)
816 edit_delete (edit, 1);
817 count++;
821 edit_set_markers (edit, 0, 0, 0, 0);
822 edit->force |= REDRAW_PAGE;
823 return 0;
826 /* --------------------------------------------------------------------------------------------- */
828 static gboolean
829 editcmd_find (WEdit * edit, gsize * len)
831 off_t search_start = edit->search_start;
832 off_t search_end;
833 long start_mark = 0;
834 long end_mark = edit->last_byte;
835 int mark_res = 0;
837 if (edit_search_options.only_in_selection)
839 mark_res = eval_marks (edit, &start_mark, &end_mark);
840 if (mark_res != 0)
842 edit->search->error = MC_SEARCH_E_NOTFOUND;
843 edit->search->error_str = g_strdup (_("Search string not found"));
844 return FALSE;
846 if (edit_search_options.backwards)
848 if (search_start > end_mark || search_start <= start_mark)
850 search_start = end_mark;
853 else
855 if (search_start < start_mark || search_start >= end_mark)
857 search_start = start_mark;
861 else
863 if (edit_search_options.backwards)
864 end_mark = max (1, edit->curs1) - 1;
866 if (edit_search_options.backwards)
868 search_end = end_mark;
869 while ((int) search_start >= start_mark)
871 if (search_end > (off_t) (search_start + edit->search->original_len) &&
872 mc_search_is_fixed_search_str (edit->search))
874 search_end = search_start + edit->search->original_len;
876 if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
877 && edit->search->normal_offset == search_start)
879 return TRUE;
881 search_start--;
883 edit->search->error_str = g_strdup (_("Search string not found"));
885 else
887 return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
889 return FALSE;
892 /* --------------------------------------------------------------------------------------------- */
894 static char *
895 edit_replace_cmd__conv_to_display (char *str)
897 #ifdef HAVE_CHARSET
898 GString *tmp;
900 tmp = str_convert_to_display (str);
901 if (tmp != NULL)
903 if (tmp->len != 0)
904 return g_string_free (tmp, FALSE);
905 g_string_free (tmp, TRUE);
907 #endif
908 return g_strdup (str);
911 /* --------------------------------------------------------------------------------------------- */
913 static char *
914 edit_replace_cmd__conv_to_input (char *str)
916 #ifdef HAVE_CHARSET
917 GString *tmp;
919 tmp = str_convert_to_input (str);
920 if (tmp != NULL)
922 if (tmp->len != 0)
923 return g_string_free (tmp, FALSE);
924 g_string_free (tmp, TRUE);
926 #endif
927 return g_strdup (str);
930 /* --------------------------------------------------------------------------------------------- */
932 static void
933 edit_do_search (WEdit * edit)
935 gsize len = 0;
937 if (edit->search == NULL)
938 edit->search_start = edit->curs1;
940 edit_push_action (edit, KEY_PRESS + edit->start_display);
942 if (search_create_bookmark)
944 int found = 0, books = 0;
945 long l = 0, l_last = -1;
946 long q = 0;
948 search_create_bookmark = FALSE;
949 book_mark_flush (edit, -1);
951 while (TRUE)
953 if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
954 break;
955 if (found == 0)
956 edit->search_start = edit->search->normal_offset;
957 found++;
958 l += edit_count_lines (edit, q, edit->search->normal_offset);
959 if (l != l_last)
961 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
962 books++;
964 l_last = l;
965 q = edit->search->normal_offset + 1;
968 if (found == 0)
969 edit_error_dialog (_("Search"), _("Search string not found"));
970 else
971 edit_cursor_move (edit, edit->search_start - edit->curs1);
973 else
975 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1
976 && edit_search_options.backwards)
977 edit->search_start--;
979 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1
980 && !edit_search_options.backwards)
981 edit->search_start++;
983 if (editcmd_find (edit, &len))
985 edit->found_start = edit->search_start = edit->search->normal_offset;
986 edit->found_len = len;
987 edit->over_col = 0;
988 edit_cursor_move (edit, edit->search_start - edit->curs1);
989 edit_scroll_screen_over_cursor (edit);
990 if (edit_search_options.backwards)
991 edit->search_start--;
992 else
993 edit->search_start++;
995 else
997 edit->search_start = edit->curs1;
998 if (edit->search->error_str != NULL)
999 edit_error_dialog (_("Search"), edit->search->error_str);
1003 edit->force |= REDRAW_COMPLETELY;
1004 edit_scroll_screen_over_cursor (edit);
1007 /* --------------------------------------------------------------------------------------------- */
1009 static void
1010 edit_search (WEdit *edit)
1012 if (editcmd_dialog_search_show (edit))
1013 edit_do_search (edit);
1016 /* --------------------------------------------------------------------------------------------- */
1017 /** Return a null terminated length of text. Result must be g_free'd */
1019 static unsigned char *
1020 edit_get_block (WEdit * edit, long start, long finish, int *l)
1022 unsigned char *s, *r;
1023 r = s = g_malloc0 (finish - start + 1);
1024 if (edit->column_highlight)
1026 *l = 0;
1027 /* copy from buffer, excluding chars that are out of the column 'margins' */
1028 while (start < finish)
1030 int c;
1031 long x;
1032 x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
1033 c = edit_get_byte (edit, start);
1034 if ((x >= edit->column1 && x < edit->column2)
1035 || (x >= edit->column2 && x < edit->column1) || c == '\n')
1037 *s++ = c;
1038 (*l)++;
1040 start++;
1043 else
1045 *l = finish - start;
1046 while (start < finish)
1047 *s++ = edit_get_byte (edit, start++);
1049 *s = 0;
1050 return r;
1053 /* --------------------------------------------------------------------------------------------- */
1054 /** copies a block to clipboard file */
1056 static int
1057 edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
1059 int ret;
1060 gchar *tmp;
1061 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
1062 ret = edit_save_block (edit, tmp, start, finish);
1063 g_free (tmp);
1064 return ret;
1067 /* --------------------------------------------------------------------------------------------- */
1069 static void
1070 pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
1072 FILE *p = 0;
1073 char *s;
1075 to = name_quote (to, 0);
1076 subject = name_quote (subject, 0);
1077 cc = name_quote (cc, 0);
1078 s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
1079 g_free (to);
1080 g_free (subject);
1081 g_free (cc);
1083 if (s)
1085 p = popen (s, "w");
1086 g_free (s);
1089 if (p)
1091 long i;
1092 for (i = 0; i < edit->last_byte; i++)
1093 fputc (edit_get_byte (edit, i), p);
1094 pclose (p);
1098 /* --------------------------------------------------------------------------------------------- */
1100 static gboolean
1101 is_break_char (char c)
1103 return (isspace (c) || strchr ("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c));
1106 /* --------------------------------------------------------------------------------------------- */
1107 /** find first character of current word */
1109 static int
1110 edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
1112 int c, last;
1113 gsize i;
1115 /* return if at begin of file */
1116 if (edit->curs1 <= 0)
1117 return 0;
1119 c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
1120 /* return if not at end or in word */
1121 if (is_break_char (c))
1122 return 0;
1124 /* search start of word to be completed */
1125 for (i = 2;; i++)
1127 /* return if at begin of file */
1128 if ((gsize) edit->curs1 < i)
1129 return 0;
1131 last = c;
1132 c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
1134 if (is_break_char (c))
1136 /* return if word starts with digit */
1137 if (isdigit (last))
1138 return 0;
1140 *word_start = edit->curs1 - (i - 1); /* start found */
1141 *word_len = i - 1;
1142 break;
1145 /* success */
1146 return 1;
1149 /* --------------------------------------------------------------------------------------------- */
1150 /** collect the possible completions */
1151 static gsize
1152 edit_collect_completions (WEdit * edit, long start, gsize word_len,
1153 char *match_expr, struct selection *compl, gsize * num)
1155 gsize len = 0;
1156 gsize max_len = 0;
1157 gsize i;
1158 int skip;
1159 GString *temp;
1160 mc_search_t *srch;
1162 long last_byte;
1164 srch = mc_search_new (match_expr, -1);
1165 if (srch == NULL)
1166 return 0;
1168 if (mc_config_get_bool
1169 (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
1171 last_byte = edit->last_byte;
1173 else
1175 last_byte = start;
1178 srch->search_type = MC_SEARCH_T_REGEX;
1179 srch->is_case_sensitive = TRUE;
1180 srch->search_fn = edit_search_cmd_callback;
1182 /* collect max MAX_WORD_COMPLETIONS completions */
1183 start = -1;
1184 while (1)
1186 /* get next match */
1187 if (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len) == FALSE)
1188 break;
1189 start = srch->normal_offset;
1191 /* add matched completion if not yet added */
1192 temp = g_string_new ("");
1193 for (i = 0; i < len; i++)
1195 skip = edit_get_byte (edit, start + i);
1196 if (isspace (skip))
1197 continue;
1198 g_string_append_c (temp, skip);
1201 skip = 0;
1203 for (i = 0; i < (gsize) * num; i++)
1205 if (strncmp
1206 ((char *) &compl[i].text[word_len],
1207 (char *) &temp->str[word_len], max (len, compl[i].len) - (gsize) word_len) == 0)
1209 struct selection this = compl[i];
1210 for (++i; i < *num; i++)
1212 compl[i - 1] = compl[i];
1214 compl[*num - 1] = this;
1215 skip = 1;
1216 break; /* skip it, already added */
1219 if (skip)
1221 g_string_free (temp, TRUE);
1222 continue;
1224 if (*num == MAX_WORD_COMPLETIONS && MAX_WORD_COMPLETIONS)
1226 g_free (compl[0].text);
1227 for (i = 1; i < *num; i++)
1229 compl[i - 1] = compl[i];
1231 (*num)--;
1233 #ifdef HAVE_CHARSET
1235 GString *recoded;
1236 recoded = str_convert_to_display (temp->str);
1238 if (recoded && recoded->len)
1240 g_string_free (temp, TRUE);
1241 temp = recoded;
1243 else
1244 g_string_free (recoded, TRUE);
1246 #endif
1247 compl[*num].text = temp->str;
1248 compl[*num].len = temp->len;
1249 (*num)++;
1250 start += len;
1251 g_string_free (temp, FALSE);
1253 /* note the maximal length needed for the completion dialog */
1254 if (len > max_len)
1255 max_len = len;
1257 mc_search_free (srch);
1258 return max_len;
1262 /* --------------------------------------------------------------------------------------------- */
1263 /*** public functions ****************************************************************************/
1264 /* --------------------------------------------------------------------------------------------- */
1266 void
1267 edit_help_cmd (WEdit * edit)
1269 interactive_display (NULL, "[Internal File Editor]");
1270 edit->force |= REDRAW_COMPLETELY;
1273 /* --------------------------------------------------------------------------------------------- */
1275 void
1276 edit_refresh_cmd (WEdit * edit)
1278 #ifdef HAVE_SLANG
1279 int color;
1281 edit_get_syntax_color (edit, -1, &color);
1282 tty_touch_screen ();
1283 mc_refresh ();
1284 #else
1285 (void) edit;
1287 clr_scr ();
1288 repaint_screen ();
1289 #endif /* !HAVE_SLANG */
1290 tty_keypad (TRUE);
1293 /* --------------------------------------------------------------------------------------------- */
1295 void
1296 menu_save_mode_cmd (void)
1298 /* diaog sizes */
1299 const int DLG_X = 38;
1300 const int DLG_Y = 13;
1302 char *str_result;
1304 const char *str[] = {
1305 N_("&Quick save"),
1306 N_("&Safe save"),
1307 N_("&Do backups with following extension:")
1310 QuickWidget widgets[] = {
1311 /* 0 */
1312 QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
1313 /* 1 */
1314 QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
1315 /* 2 */
1316 QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
1317 /* 3 */
1318 QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
1319 /* 4 */
1320 QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
1321 QUICK_END
1324 QuickDialog dialog = {
1325 DLG_X, DLG_Y, -1, -1, N_("Edit Save Mode"),
1326 "[Edit Save Mode]", widgets, NULL, FALSE
1329 size_t i;
1330 size_t maxlen = 0;
1331 size_t w0, w1, b_len, w3;
1333 assert (option_backup_ext != NULL);
1335 /* OK/Cancel buttons */
1336 w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
1337 w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5; /* default button */
1338 b_len = w0 + w1 + 3;
1340 maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
1342 w3 = 0;
1343 for (i = 0; i < 3; i++)
1345 #ifdef ENABLE_NLS
1346 str[i] = _(str[i]);
1347 #endif
1348 w3 = max (w3, (size_t) str_term_width1 (str[i]));
1351 maxlen = max (maxlen, w3 + 4);
1353 dialog.xlen = min ((size_t) COLS, maxlen + 8);
1355 widgets[3].u.input.len = w3;
1356 widgets[1].relative_x = (dialog.xlen - b_len) / 2;
1357 widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
1359 for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
1360 widgets[i].x_divisions = dialog.xlen;
1362 if (quick_dialog (&dialog) != B_CANCEL)
1364 g_free (option_backup_ext);
1365 option_backup_ext = str_result;
1369 /* --------------------------------------------------------------------------------------------- */
1371 void
1372 edit_set_filename (WEdit * edit, const char *name)
1374 g_free (edit->filename);
1376 if (name == NULL)
1377 name = "";
1379 edit->filename = tilde_expand (name);
1380 if (edit->dir == NULL && !g_path_is_absolute (name))
1381 edit->dir = g_strdup (vfs_get_current_dir ());
1384 /* --------------------------------------------------------------------------------------------- */
1385 /* Here we want to warn the users of overwriting an existing file,
1386 but only if they have made a change to the filename */
1387 /* returns 1 on success */
1389 edit_save_as_cmd (WEdit * edit)
1391 /* This heads the 'Save As' dialog box */
1392 char *exp;
1393 int save_lock = 0;
1394 int different_filename = 0;
1396 if (!edit_check_newline (edit))
1397 return 0;
1399 exp = edit_get_save_file_as (edit);
1400 edit_push_action (edit, KEY_PRESS + edit->start_display);
1402 if (exp)
1404 if (!*exp)
1406 g_free (exp);
1407 edit->force |= REDRAW_COMPLETELY;
1408 return 0;
1410 else
1412 int rv;
1413 if (strcmp (edit->filename, exp))
1415 int file;
1416 different_filename = 1;
1417 file = mc_open (exp, O_RDONLY | O_BINARY);
1418 if (file != -1)
1420 /* the file exists */
1421 mc_close (file);
1422 /* Overwrite the current file or cancel the operation */
1423 if (edit_query_dialog2
1424 (_("Warning"),
1425 _("A file already exists with this name"), _("&Overwrite"), _("&Cancel")))
1427 edit->force |= REDRAW_COMPLETELY;
1428 g_free (exp);
1429 return 0;
1432 else
1434 edit->stat1.st_mode |= S_IWUSR;
1436 save_lock = lock_file (exp);
1438 else
1440 /* filenames equal, check if already locked */
1441 if (!edit->locked && !edit->delete_file)
1442 save_lock = lock_file (exp);
1445 if (different_filename)
1448 * Allow user to write into saved (under another name) file
1449 * even if original file had r/o user permissions.
1451 edit->stat1.st_mode |= S_IWRITE;
1454 rv = edit_save_file (edit, exp);
1455 switch (rv)
1457 case 1:
1458 /* Succesful, so unlock both files */
1459 if (different_filename)
1461 if (save_lock)
1462 unlock_file (exp);
1463 if (edit->locked)
1464 edit->locked = edit_unlock_file (edit);
1466 else
1468 if (edit->locked || save_lock)
1469 edit->locked = edit_unlock_file (edit);
1472 edit_set_filename (edit, exp);
1473 if (edit->lb != LB_ASIS)
1474 edit_reload (edit, exp);
1475 g_free (exp);
1476 edit->modified = 0;
1477 edit->delete_file = 0;
1478 if (different_filename)
1479 edit_load_syntax (edit, NULL, edit->syntax_type);
1480 edit->force |= REDRAW_COMPLETELY;
1481 return 1;
1482 default:
1483 edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
1484 /* fallthrough */
1485 case -1:
1486 /* Failed, so maintain modify (not save) lock */
1487 if (save_lock)
1488 unlock_file (exp);
1489 g_free (exp);
1490 edit->force |= REDRAW_COMPLETELY;
1491 return 0;
1495 edit->force |= REDRAW_COMPLETELY;
1496 return 0;
1499 /* {{{ Macro stuff starts here */
1502 /* --------------------------------------------------------------------------------------------- */
1503 /** returns 0 on error */
1506 edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
1508 FILE *f;
1509 int s, i;
1511 edit_push_action (edit, KEY_PRESS + edit->start_display);
1512 s = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
1513 edit->force |= REDRAW_COMPLETELY;
1514 if (s)
1516 if (edit_delete_macro (edit, s))
1517 return 0;
1518 f = edit_open_macro_file ("a+");
1519 if (f)
1521 fprintf (f, ("key '%d 0': "), s);
1522 for (i = 0; i < n; i++)
1523 fprintf (f, "%lu %d, ", macro[i].command, macro[i].ch);
1524 fprintf (f, ";\n");
1525 fclose (f);
1526 if (saved_macros_loaded)
1528 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
1529 saved_macro[i] = s;
1531 return 1;
1533 else
1534 edit_error_dialog (_("Save macro"), get_sys_error (_("Cannot open macro file")));
1536 return 0;
1539 /* --------------------------------------------------------------------------------------------- */
1541 void
1542 edit_delete_macro_cmd (WEdit * edit)
1544 int command;
1546 command = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
1548 if (command != 0)
1549 edit_delete_macro (edit, command);
1552 /* --------------------------------------------------------------------------------------------- */
1553 /** return 0 on error */
1556 edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
1558 FILE *f;
1559 int s, i = 0, found = 0;
1561 (void) edit;
1563 if (saved_macros_loaded)
1564 if (macro_exists (k) < 0)
1565 return 0;
1567 f = edit_open_macro_file ("r");
1568 if (f != NULL)
1570 struct macro dummy;
1573 int u;
1574 u = fscanf (f, ("key '%d 0': "), &s);
1575 if (!u || u == EOF)
1576 break;
1577 if (!saved_macros_loaded)
1578 saved_macro[i++] = s;
1579 if (!found)
1581 *n = 0;
1582 while (*n < MAX_MACRO_LENGTH
1583 && 2 == fscanf (f, "%lu %d, ", &macro[*n].command, &macro[*n].ch))
1584 (*n)++;
1586 else
1588 while (2 == fscanf (f, "%lu %d, ", &dummy.command, &dummy.ch));
1591 int ret;
1592 ret = fscanf (f, ";\n");
1594 if (s == k)
1595 found = 1;
1597 while (!found || !saved_macros_loaded);
1598 if (!saved_macros_loaded)
1600 saved_macro[i] = 0;
1601 saved_macros_loaded = 1;
1603 fclose (f);
1604 return found;
1606 else
1607 edit_error_dialog (_("Load macro"), get_sys_error (_("Cannot open macro file")));
1608 return 0;
1611 /* }}} Macro stuff starts here */
1613 /* --------------------------------------------------------------------------------------------- */
1614 /** returns 1 on success */
1617 edit_save_confirm_cmd (WEdit * edit)
1619 gchar *f = NULL;
1621 if (!edit_check_newline (edit))
1622 return 0;
1624 if (edit_confirm_save)
1626 f = g_strdup_printf (_("Confirm save file: \"%s\""), edit->filename);
1627 if (edit_query_dialog2 (_("Save file"), f, _("&Save"), _("&Cancel")))
1629 g_free (f);
1630 return 0;
1632 g_free (f);
1634 return edit_save_cmd (edit);
1638 /* --------------------------------------------------------------------------------------------- */
1639 /** returns 1 on success */
1642 edit_new_cmd (WEdit * edit)
1644 if (edit->modified)
1646 if (edit_query_dialog2
1647 (_("Warning"),
1649 ("Current text was modified without a file save.\nContinue discards these changes"),
1650 _("C&ontinue"), _("&Cancel")))
1652 edit->force |= REDRAW_COMPLETELY;
1653 return 0;
1656 edit->force |= REDRAW_COMPLETELY;
1658 return edit_renew (edit); /* if this gives an error, something has really screwed up */
1661 /* --------------------------------------------------------------------------------------------- */
1664 edit_load_cmd (WEdit * edit, edit_current_file_t what)
1666 char *exp;
1668 if (edit->modified
1669 && (edit_query_dialog2
1670 (_("Warning"),
1671 _("Current text was modified without a file save.\n"
1672 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")) == 1))
1674 edit->force |= REDRAW_COMPLETELY;
1675 return 0;
1678 switch (what)
1680 case EDIT_FILE_COMMON:
1681 exp = input_expand_dialog (_("Load"), _("Enter file name:"),
1682 MC_HISTORY_EDIT_LOAD, edit->filename);
1684 if (exp)
1686 if (*exp)
1687 edit_load_file_from_filename (edit, exp);
1688 g_free (exp);
1690 break;
1692 case EDIT_FILE_SYNTAX:
1693 edit_load_syntax_file (edit);
1694 break;
1696 case EDIT_FILE_MENU:
1697 edit_load_menu_file (edit);
1698 break;
1700 default:
1701 break;
1704 edit->force |= REDRAW_COMPLETELY;
1705 return 0;
1708 /* --------------------------------------------------------------------------------------------- */
1710 if mark2 is -1 then marking is from mark1 to the cursor.
1711 Otherwise its between the markers. This handles this.
1712 Returns 1 if no text is marked.
1716 eval_marks (WEdit * edit, long *start_mark, long *end_mark)
1718 if (edit->mark1 != edit->mark2)
1720 long start_bol, start_eol;
1721 long end_bol, end_eol;
1722 long col1, col2;
1723 long diff1, diff2;
1724 long end_mark_curs;
1726 if (edit->end_mark_curs < 0)
1727 end_mark_curs = edit->curs1;
1728 else
1729 end_mark_curs = edit->end_mark_curs;
1731 if (edit->mark2 >= 0)
1733 *start_mark = min (edit->mark1, edit->mark2);
1734 *end_mark = max (edit->mark1, edit->mark2);
1736 else
1738 *start_mark = min (edit->mark1, end_mark_curs);
1739 *end_mark = max (edit->mark1, end_mark_curs);
1740 edit->column2 = edit->curs_col + edit->over_col;
1743 if (edit->column_highlight
1744 && (((edit->mark1 > end_mark_curs) && (edit->column1 < edit->column2))
1745 || ((edit->mark1 < end_mark_curs) && (edit->column1 > edit->column2))))
1747 start_bol = edit_bol (edit, *start_mark);
1748 start_eol = edit_eol (edit, start_bol - 1) + 1;
1749 end_bol = edit_bol (edit, *end_mark);
1750 end_eol = edit_eol (edit, *end_mark);
1751 col1 = min (edit->column1, edit->column2);
1752 col2 = max (edit->column1, edit->column2);
1754 diff1 =
1755 edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
1756 col1, 0);
1757 diff2 =
1758 edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
1759 col1, 0);
1761 *start_mark -= diff1;
1762 *end_mark += diff2;
1763 *start_mark = max (*start_mark, start_eol);
1764 *end_mark = min (*end_mark, end_eol);
1766 return 0;
1768 else
1770 *start_mark = *end_mark = 0;
1771 edit->column2 = edit->column1 = 0;
1772 return 1;
1776 /* --------------------------------------------------------------------------------------------- */
1778 void
1779 edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
1781 long cursor;
1782 int i, col;
1783 cursor = edit->curs1;
1784 col = edit_get_col (edit);
1785 for (i = 0; i < size; i++)
1787 if (data[i] == '\n')
1788 { /* fill in and move to next line */
1789 int l;
1790 long p;
1791 if (edit_get_byte (edit, edit->curs1) != '\n')
1793 l = width - (edit_get_col (edit) - col);
1794 while (l > 0)
1796 edit_insert (edit, ' ');
1797 l -= space_width;
1800 for (p = edit->curs1;; p++)
1802 if (p == edit->last_byte)
1804 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1805 edit_insert_ahead (edit, '\n');
1806 p++;
1807 break;
1809 if (edit_get_byte (edit, p) == '\n')
1811 p++;
1812 break;
1815 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1816 l = col - edit_get_col (edit);
1817 while (l >= space_width)
1819 edit_insert (edit, ' ');
1820 l -= space_width;
1822 continue;
1824 edit_insert (edit, data[i]);
1826 edit_cursor_move (edit, cursor - edit->curs1);
1829 /* --------------------------------------------------------------------------------------------- */
1832 edit_insert_column_of_text_from_file (WEdit * edit, int file)
1834 long cursor;
1835 int i, col;
1836 int blocklen = -1, width;
1837 unsigned char *data;
1838 cursor = edit->curs1;
1839 col = edit_get_col (edit);
1840 data = g_malloc0 (TEMP_BUF_LEN);
1841 while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
1843 for (width = 0; width < blocklen; width++)
1845 if (data[width] == '\n')
1846 break;
1848 for (i = 0; i < blocklen; i++)
1850 if (data[i] == '\n')
1851 { /* fill in and move to next line */
1852 int l;
1853 long p;
1854 if (edit_get_byte (edit, edit->curs1) != '\n')
1856 l = width - (edit_get_col (edit) - col);
1857 while (l > 0)
1859 edit_insert (edit, ' ');
1860 l -= space_width;
1863 for (p = edit->curs1;; p++)
1865 if (p == edit->last_byte)
1867 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1868 edit_insert_ahead (edit, '\n');
1869 p++;
1870 break;
1872 if (edit_get_byte (edit, p) == '\n')
1874 p++;
1875 break;
1878 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1879 l = col - edit_get_col (edit);
1880 while (l >= space_width)
1882 edit_insert (edit, ' ');
1883 l -= space_width;
1885 continue;
1887 edit_insert (edit, data[i]);
1890 edit_cursor_move (edit, cursor - edit->curs1);
1891 g_free (data);
1892 edit->force |= REDRAW_PAGE;
1893 return blocklen;
1896 /* --------------------------------------------------------------------------------------------- */
1898 void
1899 edit_block_copy_cmd (WEdit * edit)
1901 long start_mark, end_mark, current = edit->curs1;
1902 int size;
1903 unsigned char *copy_buf;
1905 edit_update_curs_col (edit);
1906 if (eval_marks (edit, &start_mark, &end_mark))
1907 return;
1909 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1911 /* all that gets pushed are deletes hence little space is used on the stack */
1913 edit_push_markers (edit);
1915 if (edit->column_highlight)
1917 edit_insert_column_of_text (edit, copy_buf, size, abs (edit->column2 - edit->column1));
1919 else
1921 while (size--)
1922 edit_insert_ahead (edit, copy_buf[size]);
1925 g_free (copy_buf);
1926 edit_scroll_screen_over_cursor (edit);
1928 if (edit->column_highlight)
1930 edit_set_markers (edit, 0, 0, 0, 0);
1931 edit_push_action (edit, COLUMN_ON);
1932 edit->column_highlight = 0;
1934 else if (start_mark < current && end_mark > current)
1935 edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
1937 edit->force |= REDRAW_PAGE;
1941 /* --------------------------------------------------------------------------------------------- */
1943 void
1944 edit_block_move_cmd (WEdit * edit)
1946 long count;
1947 long current;
1948 unsigned char *copy_buf;
1949 long start_mark, end_mark;
1950 int deleted = 0;
1951 int x = 0;
1953 if (eval_marks (edit, &start_mark, &end_mark))
1954 return;
1955 if (edit->column_highlight)
1957 edit_update_curs_col (edit);
1958 x = edit->curs_col;
1959 if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1960 if ((x > edit->column1 && x < edit->column2)
1961 || (x > edit->column2 && x < edit->column1))
1962 return;
1964 else if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1965 return;
1967 if ((end_mark - start_mark) > option_max_undo / 2)
1968 if (edit_query_dialog2
1969 (_("Warning"),
1971 ("Block is large, you may not be able to undo this action"),
1972 _("C&ontinue"), _("&Cancel")))
1973 return;
1975 edit_push_markers (edit);
1976 current = edit->curs1;
1977 if (edit->column_highlight)
1979 long line;
1980 int size, c1, c2;
1981 line = edit->curs_line;
1982 if (edit->mark2 < 0)
1983 edit_mark_cmd (edit, 0);
1984 c1 = min (edit->column1, edit->column2);
1985 c2 = max (edit->column1, edit->column2);
1986 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1987 if (x < c2)
1989 edit_block_delete_cmd (edit);
1990 deleted = 1;
1992 edit_move_to_line (edit, line);
1993 edit_cursor_move (edit,
1994 edit_move_forward3 (edit,
1995 edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
1996 edit_insert_column_of_text (edit, copy_buf, size, c2 - c1);
1997 if (!deleted)
1999 line = edit->curs_line;
2000 edit_update_curs_col (edit);
2001 x = edit->curs_col;
2002 edit_block_delete_cmd (edit);
2003 edit_move_to_line (edit, line);
2004 edit_cursor_move (edit,
2005 edit_move_forward3 (edit,
2006 edit_bol (edit,
2007 edit->curs1), x, 0) - edit->curs1);
2009 edit_set_markers (edit, 0, 0, 0, 0);
2010 edit_push_action (edit, COLUMN_ON);
2011 edit->column_highlight = 0;
2013 else
2015 copy_buf = g_malloc0 (end_mark - start_mark);
2016 edit_cursor_move (edit, start_mark - edit->curs1);
2017 edit_scroll_screen_over_cursor (edit);
2018 count = start_mark;
2019 while (count < end_mark)
2021 copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
2022 count++;
2024 edit_scroll_screen_over_cursor (edit);
2025 edit_cursor_move (edit,
2026 current - edit->curs1 -
2027 (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
2028 edit_scroll_screen_over_cursor (edit);
2029 while (count-- > start_mark)
2030 edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
2031 edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
2033 edit_scroll_screen_over_cursor (edit);
2034 g_free (copy_buf);
2035 edit->force |= REDRAW_PAGE;
2038 /* --------------------------------------------------------------------------------------------- */
2039 /** returns 1 if canceelled by user */
2042 edit_block_delete_cmd (WEdit * edit)
2044 long start_mark, end_mark;
2045 if (eval_marks (edit, &start_mark, &end_mark))
2047 edit_delete_line (edit);
2048 return 0;
2050 return edit_block_delete (edit);
2053 /* --------------------------------------------------------------------------------------------- */
2054 /** call with edit = 0 before shutdown to close memory leaks */
2056 void
2057 edit_replace_cmd (WEdit * edit, int again)
2059 /* 1 = search string, 2 = replace with */
2060 static char *saved1 = NULL; /* saved default[123] */
2061 static char *saved2 = NULL;
2062 char *input1 = NULL; /* user input from the dialog */
2063 char *input2 = NULL;
2064 char *disp1 = NULL;
2065 char *disp2 = NULL;
2066 long times_replaced = 0;
2067 gboolean once_found = FALSE;
2069 if (!edit)
2071 g_free (saved1), saved1 = NULL;
2072 g_free (saved2), saved2 = NULL;
2073 return;
2076 edit->force |= REDRAW_COMPLETELY;
2078 if (again && !saved1 && !saved2)
2079 again = 0;
2081 if (again)
2083 input1 = g_strdup (saved1 ? saved1 : "");
2084 input2 = g_strdup (saved2 ? saved2 : "");
2086 else
2088 char *tmp_inp1, *tmp_inp2;
2089 disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
2090 disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
2092 edit_push_action (edit, KEY_PRESS + edit->start_display);
2094 editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
2096 g_free (disp1);
2097 g_free (disp2);
2099 if (input1 == NULL || *input1 == '\0')
2101 edit->force = REDRAW_COMPLETELY;
2102 goto cleanup;
2105 tmp_inp1 = input1;
2106 tmp_inp2 = input2;
2107 input1 = edit_replace_cmd__conv_to_input (input1);
2108 input2 = edit_replace_cmd__conv_to_input (input2);
2109 g_free (tmp_inp1);
2110 g_free (tmp_inp2);
2112 g_free (saved1), saved1 = g_strdup (input1);
2113 g_free (saved2), saved2 = g_strdup (input2);
2115 mc_search_free (edit->search);
2116 edit->search = NULL;
2119 if (!edit->search)
2121 edit->search = mc_search_new (input1, -1);
2122 if (edit->search == NULL)
2124 edit->search_start = edit->curs1;
2125 goto cleanup;
2127 edit->search->search_type = edit_search_options.type;
2128 edit->search->is_all_charsets = edit_search_options.all_codepages;
2129 edit->search->is_case_sensitive = edit_search_options.case_sens;
2130 edit->search->whole_words = edit_search_options.whole_words;
2131 edit->search->search_fn = edit_search_cmd_callback;
2134 if (edit->found_len && edit->search_start == edit->found_start + 1
2135 && edit_search_options.backwards)
2136 edit->search_start--;
2138 if (edit->found_len && edit->search_start == edit->found_start - 1
2139 && !edit_search_options.backwards)
2140 edit->search_start++;
2144 gsize len = 0;
2146 if (!editcmd_find (edit, &len))
2148 if (!(edit->search->error == MC_SEARCH_E_OK ||
2149 (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
2151 edit_error_dialog (_("Search"), edit->search->error_str);
2153 break;
2155 once_found = TRUE;
2157 edit->search_start = edit->search->normal_offset;
2158 /*returns negative on not found or error in pattern */
2160 if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
2162 gsize i;
2163 GString *tmp_str, *repl_str;
2165 edit->found_start = edit->search_start;
2166 i = edit->found_len = len;
2168 edit_cursor_move (edit, edit->search_start - edit->curs1);
2169 edit_scroll_screen_over_cursor (edit);
2171 if (edit->replace_mode == 0)
2173 int l;
2174 int prompt;
2176 l = edit->curs_row - edit->widget.lines / 3;
2177 if (l > 0)
2178 edit_scroll_downward (edit, l);
2179 if (l < 0)
2180 edit_scroll_upward (edit, -l);
2182 edit_scroll_screen_over_cursor (edit);
2183 edit->force |= REDRAW_PAGE;
2184 edit_render_keypress (edit);
2186 /*so that undo stops at each query */
2187 edit_push_key_press (edit);
2188 /* and prompt 2/3 down */
2189 disp1 = edit_replace_cmd__conv_to_display (saved1);
2190 disp2 = edit_replace_cmd__conv_to_display (saved2);
2191 prompt = editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
2192 g_free (disp1);
2193 g_free (disp2);
2195 if (prompt == B_REPLACE_ALL)
2196 edit->replace_mode = 1;
2197 else if (prompt == B_SKIP_REPLACE)
2199 if (edit_search_options.backwards)
2200 edit->search_start--;
2201 else
2202 edit->search_start++;
2203 continue; /* loop */
2205 else if (prompt == B_CANCEL)
2207 edit->replace_mode = -1;
2208 break; /* loop */
2212 /* don't process string each time */
2213 tmp_str = g_string_new (input2);
2214 repl_str = mc_search_prepare_replace_str (edit->search, tmp_str);
2215 g_string_free (tmp_str, TRUE);
2217 if (edit->search->error != MC_SEARCH_E_OK)
2219 edit_error_dialog (_("Replace"), edit->search->error_str);
2220 g_string_free (repl_str, TRUE);
2221 break;
2224 /* delete then insert new */
2225 for (i = 0; i < len; i++)
2226 edit_delete (edit, 1);
2228 for (i = 0; i < repl_str->len; i++)
2229 edit_insert (edit, repl_str->str[i]);
2231 edit->found_len = repl_str->len;
2232 g_string_free (repl_str, TRUE);
2233 times_replaced++;
2235 /* so that we don't find the same string again */
2236 if (edit_search_options.backwards)
2237 edit->search_start--;
2238 else
2240 edit->search_start += edit->found_len;
2242 if (edit->search_start >= edit->last_byte)
2243 break;
2246 edit_scroll_screen_over_cursor (edit);
2248 else
2250 /* try and find from right here for next search */
2251 edit->search_start = edit->curs1;
2252 edit_update_curs_col (edit);
2254 edit->force |= REDRAW_PAGE;
2255 edit_render_keypress (edit);
2257 if (times_replaced == 0)
2258 query_dialog (_("Replace"), _("Search string not found"), D_NORMAL, 1, _("&OK"));
2259 break;
2262 while (edit->replace_mode >= 0);
2264 edit_scroll_screen_over_cursor (edit);
2265 edit->force |= REDRAW_COMPLETELY;
2266 edit_render_keypress (edit);
2268 if ((edit->replace_mode == 1) && (times_replaced != 0))
2269 message (D_NORMAL, _("Replace"), _("%ld replacements made"), times_replaced);
2271 cleanup:
2272 g_free (input1);
2273 g_free (input2);
2276 /* --------------------------------------------------------------------------------------------- */
2279 edit_search_cmd_callback (const void *user_data, gsize char_offset)
2281 return edit_get_byte ((WEdit *) user_data, (long) char_offset);
2284 /* --------------------------------------------------------------------------------------------- */
2286 void
2287 edit_search_cmd (WEdit * edit, gboolean again)
2289 if (edit == NULL)
2290 return;
2292 if (!again)
2293 edit_search (edit);
2294 else if (edit->last_search_string != NULL)
2295 edit_do_search (edit);
2296 else
2298 /* find last search string in history */
2299 GList *history;
2301 history = history_get (MC_HISTORY_SHARED_SEARCH);
2302 if (history != NULL && history->data != NULL)
2304 edit->last_search_string = (char *) history->data;
2305 history->data = NULL;
2306 history = g_list_first (history);
2307 g_list_foreach (history, (GFunc) g_free, NULL);
2308 g_list_free (history);
2310 edit->search = mc_search_new (edit->last_search_string, -1);
2311 if (edit->search == NULL)
2313 /* if not... then ask for an expression */
2314 g_free (edit->last_search_string);
2315 edit->last_search_string = NULL;
2316 edit_search (edit);
2318 else
2320 edit->search->search_type = edit_search_options.type;
2321 edit->search->is_all_charsets = edit_search_options.all_codepages;
2322 edit->search->is_case_sensitive = edit_search_options.case_sens;
2323 edit->search->whole_words = edit_search_options.whole_words;
2324 edit->search->search_fn = edit_search_cmd_callback;
2325 edit_do_search (edit);
2328 else
2330 /* if not... then ask for an expression */
2331 g_free (edit->last_search_string);
2332 edit->last_search_string = NULL;
2333 edit_search (edit);
2339 /* --------------------------------------------------------------------------------------------- */
2341 * Check if it's OK to close the editor. If there are unsaved changes,
2342 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
2345 gboolean
2346 edit_ok_to_exit (WEdit * edit)
2348 int act;
2350 if (!edit->modified)
2351 return TRUE;
2353 if (!midnight_shutdown)
2355 if (!edit_check_newline (edit))
2356 return FALSE;
2358 query_set_sel (2);
2359 act = edit_query_dialog3 (_("Quit"), _("File was modified. Save with exit?"),
2360 _("&Yes"), _("&No"), _("&Cancel quit"));
2362 else
2364 act =
2365 edit_query_dialog2 (_("Quit"),
2366 _("Midnight Commander is being shut down.\nSave modified file?"),
2367 _("&Yes"), _("&No"));
2369 /* Esc is No */
2370 if (act == -1)
2371 act = 1;
2374 switch (act)
2376 case 0: /* Yes */
2377 edit_push_markers (edit);
2378 edit_set_markers (edit, 0, 0, 0, 0);
2379 if (!edit_save_cmd (edit) || midnight_shutdown)
2380 return (gboolean) midnight_shutdown;
2381 break;
2382 case 1: /* No */
2383 break;
2384 case 2: /* Cancel quit */
2385 case -1: /* Esc */
2386 return FALSE;
2389 return TRUE;
2392 /* --------------------------------------------------------------------------------------------- */
2393 /** save block, returns 1 on success */
2396 edit_save_block (WEdit * edit, const char *filename, long start, long finish)
2398 int len, file;
2400 file = mc_open (filename, O_CREAT | O_WRONLY | O_TRUNC,
2401 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY);
2402 if (file == -1)
2403 return 0;
2405 if (edit->column_highlight)
2407 int r;
2408 r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
2409 if (r > 0)
2411 unsigned char *block, *p;
2412 p = block = edit_get_block (edit, start, finish, &len);
2413 while (len)
2415 r = mc_write (file, p, len);
2416 if (r < 0)
2417 break;
2418 p += r;
2419 len -= r;
2421 g_free (block);
2424 else
2426 unsigned char *buf;
2427 int i = start, end;
2428 len = finish - start;
2429 buf = g_malloc0 (TEMP_BUF_LEN);
2430 while (start != finish)
2432 end = min (finish, start + TEMP_BUF_LEN);
2433 for (; i < end; i++)
2434 buf[i - start] = edit_get_byte (edit, i);
2435 len -= mc_write (file, (char *) buf, end - start);
2436 start = end;
2438 g_free (buf);
2440 mc_close (file);
2441 if (len)
2442 return 0;
2443 return 1;
2446 /* --------------------------------------------------------------------------------------------- */
2448 void
2449 edit_paste_from_history (WEdit * edit)
2451 (void) edit;
2452 edit_error_dialog (_("Error"), _("This function is not implemented"));
2455 /* --------------------------------------------------------------------------------------------- */
2458 edit_copy_to_X_buf_cmd (WEdit * edit)
2460 long start_mark, end_mark;
2461 if (eval_marks (edit, &start_mark, &end_mark))
2462 return 0;
2463 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2465 edit_error_dialog (_("Copy to clipboard"), get_sys_error (_("Unable to save to file")));
2466 return 1;
2468 /* try use external clipboard utility */
2469 copy_file_to_ext_clip ();
2471 return 0;
2474 /* --------------------------------------------------------------------------------------------- */
2477 edit_cut_to_X_buf_cmd (WEdit * edit)
2479 long start_mark, end_mark;
2480 if (eval_marks (edit, &start_mark, &end_mark))
2481 return 0;
2482 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2484 edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
2485 return 1;
2487 /* try use external clipboard utility */
2488 copy_file_to_ext_clip ();
2490 edit_block_delete_cmd (edit);
2491 edit_mark_cmd (edit, 1);
2492 return 0;
2495 /* --------------------------------------------------------------------------------------------- */
2497 void
2498 edit_paste_from_X_buf_cmd (WEdit * edit)
2500 gchar *tmp;
2501 /* try use external clipboard utility */
2502 paste_to_file_from_ext_clip ();
2503 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2504 edit_insert_file (edit, tmp);
2505 g_free (tmp);
2509 /* --------------------------------------------------------------------------------------------- */
2511 * Ask user for the line and go to that line.
2512 * Negative numbers mean line from the end (i.e. -1 is the last line).
2515 void
2516 edit_goto_cmd (WEdit * edit)
2518 char *f;
2519 static long line = 0; /* line as typed, saved as default */
2520 long l;
2521 char *error;
2522 char s[32];
2524 g_snprintf (s, sizeof (s), "%ld", line);
2525 f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE, line ? s : "");
2526 if (!f)
2527 return;
2529 if (!*f)
2531 g_free (f);
2532 return;
2535 l = strtol (f, &error, 0);
2536 if (*error)
2538 g_free (f);
2539 return;
2542 line = l;
2543 if (l < 0)
2544 l = edit->total_lines + l + 2;
2545 edit_move_display (edit, l - edit->widget.lines / 2 - 1);
2546 edit_move_to_line (edit, l - 1);
2547 edit->force |= REDRAW_COMPLETELY;
2548 g_free (f);
2552 /* --------------------------------------------------------------------------------------------- */
2553 /** Return 1 on success */
2556 edit_save_block_cmd (WEdit * edit)
2558 long start_mark, end_mark;
2559 char *exp, *tmp;
2561 if (eval_marks (edit, &start_mark, &end_mark))
2562 return 1;
2564 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2565 exp =
2566 input_expand_dialog (_("Save block"), _("Enter file name:"),
2567 MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
2568 g_free (tmp);
2569 edit_push_action (edit, KEY_PRESS + edit->start_display);
2570 if (exp)
2572 if (!*exp)
2574 g_free (exp);
2575 return 0;
2577 else
2579 if (edit_save_block (edit, exp, start_mark, end_mark))
2581 g_free (exp);
2582 edit->force |= REDRAW_COMPLETELY;
2583 return 1;
2585 else
2587 g_free (exp);
2588 edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
2592 edit->force |= REDRAW_COMPLETELY;
2593 return 0;
2597 /* --------------------------------------------------------------------------------------------- */
2598 /** returns 1 on success */
2601 edit_insert_file_cmd (WEdit * edit)
2603 gchar *tmp;
2604 char *exp;
2606 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2607 exp = input_expand_dialog (_("Insert file"), _("Enter file name:"),
2608 MC_HISTORY_EDIT_INSERT_FILE, tmp);
2609 g_free (tmp);
2610 edit_push_action (edit, KEY_PRESS + edit->start_display);
2611 if (exp)
2613 if (!*exp)
2615 g_free (exp);
2616 return 0;
2618 else
2620 if (edit_insert_file (edit, exp))
2622 g_free (exp);
2623 edit->force |= REDRAW_COMPLETELY;
2624 return 1;
2626 else
2628 g_free (exp);
2629 edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
2633 edit->force |= REDRAW_COMPLETELY;
2634 return 0;
2637 /* --------------------------------------------------------------------------------------------- */
2638 /** sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2641 edit_sort_cmd (WEdit * edit)
2643 static char *old = 0;
2644 char *exp, *tmp;
2645 long start_mark, end_mark;
2646 int e;
2648 if (eval_marks (edit, &start_mark, &end_mark))
2650 edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
2651 return 0;
2654 tmp = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE);
2655 edit_save_block (edit, tmp, start_mark, end_mark);
2656 g_free (tmp);
2658 exp = input_dialog (_("Run sort"),
2659 _("Enter sort options (see manpage) separated by whitespace:"),
2660 MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
2662 if (!exp)
2663 return 1;
2664 g_free (old);
2665 old = exp;
2666 tmp = g_strconcat (" sort ", exp, " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE, " > ",
2667 home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2668 e = system (tmp);
2669 g_free (tmp);
2670 if (e)
2672 if (e == -1 || e == 127)
2674 edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
2676 else
2678 char q[8];
2679 sprintf (q, "%d ", e);
2680 tmp = g_strdup_printf (_("Sort returned non-zero: %s"), q);
2681 edit_error_dialog (_("Sort"), tmp);
2682 g_free (tmp);
2684 return -1;
2687 edit->force |= REDRAW_COMPLETELY;
2689 if (edit_block_delete_cmd (edit))
2690 return 1;
2691 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2692 edit_insert_file (edit, tmp);
2693 g_free (tmp);
2694 return 0;
2697 /* --------------------------------------------------------------------------------------------- */
2699 * Ask user for a command, execute it and paste its output back to the
2700 * editor.
2704 edit_ext_cmd (WEdit * edit)
2706 char *exp, *tmp;
2707 int e;
2709 exp =
2710 input_dialog (_("Paste output of external command"),
2711 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
2713 if (!exp)
2714 return 1;
2716 tmp = g_strconcat (exp, " > ", home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2717 e = system (tmp);
2718 g_free (tmp);
2719 g_free (exp);
2721 if (e)
2723 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
2724 return -1;
2727 edit->force |= REDRAW_COMPLETELY;
2728 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2729 edit_insert_file (edit, tmp);
2730 g_free (tmp);
2731 return 0;
2734 /* --------------------------------------------------------------------------------------------- */
2735 /** if block is 1, a block must be highlighted and the shell command
2736 processes it. If block is 0 the shell command is a straight system
2737 command, that just produces some output which is to be inserted */
2739 void
2740 edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
2742 long start_mark, end_mark;
2743 char buf[BUFSIZ];
2744 FILE *script_home = NULL;
2745 FILE *block_file = NULL;
2746 gchar *o, *h, *b, *tmp;
2747 char *quoted_name = NULL;
2749 o = g_strconcat (mc_home, shell_cmd, (char *) NULL); /* original source script */
2750 h = g_strconcat (home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, (char *) NULL); /* home script */
2751 b = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE); /* block file */
2753 script_home = fopen (h, "r");
2754 if (script_home == NULL)
2756 FILE *script_src = NULL;
2758 script_home = fopen (h, "w");
2759 if (script_home == NULL)
2761 tmp = g_strconcat (_("Error creating script:"), h, (char *) NULL);
2762 edit_error_dialog ("", get_sys_error (tmp));
2763 g_free (tmp);
2764 goto edit_block_process_cmd__EXIT;
2767 script_src = fopen (o, "r");
2768 if (script_src == NULL)
2770 o = g_strconcat (mc_home_alt, shell_cmd, (char *) NULL);
2771 script_src = fopen (o, "r");
2772 if (script_src == NULL)
2774 fclose (script_home);
2775 unlink (h);
2776 tmp = g_strconcat (_("Error reading script:"), o, (char *) NULL);
2777 edit_error_dialog ("", get_sys_error (tmp));
2778 g_free (tmp);
2779 goto edit_block_process_cmd__EXIT;
2782 while (fgets (buf, sizeof (buf), script_src))
2783 fputs (buf, script_home);
2784 fclose (script_src);
2786 if (fclose (script_home))
2788 tmp = g_strconcat (_("Error closing script:"), h, (char *) NULL);
2789 edit_error_dialog ("", get_sys_error (tmp));
2790 g_free (tmp);
2791 goto edit_block_process_cmd__EXIT;
2793 chmod (h, 0700);
2794 tmp = g_strconcat (_("Script created:"), h, (char *) NULL);
2795 edit_error_dialog ("", get_sys_error (tmp));
2796 g_free (tmp);
2799 open_error_pipe ();
2801 if (block)
2802 { /* for marked block run indent formatter */
2803 if (eval_marks (edit, &start_mark, &end_mark))
2805 edit_error_dialog (_("Process block"), _("You must first highlight a block of text"));
2806 goto edit_block_process_cmd__EXIT;
2808 edit_save_block (edit, b, start_mark, end_mark);
2809 quoted_name = name_quote (edit->filename, 0);
2811 * Run script.
2812 * Initial space is to avoid polluting bash history.
2813 * Arguments:
2814 * $1 - name of the edited file (to check its extension etc).
2815 * $2 - file containing the current block.
2816 * $3 - file where error messages should be put
2817 * (for compatibility with old scripts).
2819 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ", quoted_name,
2820 " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE " /dev/null", (char *) NULL);
2822 else
2825 * No block selected, just execute the command for the file.
2826 * Arguments:
2827 * $1 - name of the edited file.
2829 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
2830 quoted_name, (char *) NULL);
2833 if (system (tmp) == -1)
2835 edit_error_dialog (_("Process block"), _("Error calling program"));
2837 else
2840 g_free (quoted_name);
2841 close_error_pipe (D_NORMAL, NULL);
2843 edit_refresh_cmd (edit);
2844 edit->force |= REDRAW_COMPLETELY;
2846 /* insert result block */
2847 if (block && !edit_block_delete_cmd (edit))
2849 edit_insert_file (edit, b);
2850 block_file = fopen (b, "w");
2851 if (block_file != NULL)
2852 fclose (block_file);
2855 g_free (tmp);
2857 edit_block_process_cmd__EXIT:
2858 g_free (b);
2859 g_free (h);
2860 g_free (o);
2863 /* --------------------------------------------------------------------------------------------- */
2865 * prints at the cursor
2866 * @returns the number of chars printed
2870 edit_print_string (WEdit * e, const char *s)
2872 size_t i = 0;
2873 while (s[i] != '\0')
2874 edit_execute_cmd (e, CK_Insert_Char, (unsigned char) s[i++]);
2875 e->force |= REDRAW_COMPLETELY;
2876 edit_update_screen (e);
2877 return i;
2880 /* --------------------------------------------------------------------------------------------- */
2882 void
2883 edit_mail_dialog (WEdit * edit)
2885 char *tmail_to;
2886 char *tmail_subject;
2887 char *tmail_cc;
2889 static char *mail_cc_last = 0;
2890 static char *mail_subject_last = 0;
2891 static char *mail_to_last = 0;
2893 QuickWidget quick_widgets[] = {
2894 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
2895 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
2896 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
2897 /* 3 */ QUICK_LABEL (3, 50, 7, MAIL_DLG_HEIGHT, N_("Copies to")),
2898 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
2899 &tmail_subject),
2900 /* 5 */ QUICK_LABEL (3, 50, 5, MAIL_DLG_HEIGHT, N_("Subject")),
2901 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
2902 /* 7 */ QUICK_LABEL (3, 50, 3, MAIL_DLG_HEIGHT, N_("To")),
2903 /* 8 */ QUICK_LABEL (3, 50, 2, MAIL_DLG_HEIGHT, N_("mail -s <subject> -c <cc> <to>")),
2904 QUICK_END
2907 QuickDialog Quick_input = {
2908 50, MAIL_DLG_HEIGHT, -1, -1, N_("Mail"),
2909 "[Input Line Keys]", quick_widgets, NULL, FALSE
2912 quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
2913 quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
2914 quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
2916 if (quick_dialog (&Quick_input) != B_CANCEL)
2918 g_free (mail_cc_last);
2919 g_free (mail_subject_last);
2920 g_free (mail_to_last);
2921 mail_cc_last = tmail_cc;
2922 mail_subject_last = tmail_subject;
2923 mail_to_last = tmail_to;
2924 pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
2929 /*******************/
2930 /* Word Completion */
2931 /*******************/
2933 /* --------------------------------------------------------------------------------------------- */
2935 * Complete current word using regular expression search
2936 * backwards beginning at the current cursor position.
2939 void
2940 edit_complete_word_cmd (WEdit * edit)
2942 gsize i, max_len, word_len = 0, num_compl = 0;
2943 long word_start = 0;
2944 unsigned char *bufpos;
2945 char *match_expr;
2946 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
2948 /* search start of word to be completed */
2949 if (!edit_find_word_start (edit, &word_start, &word_len))
2950 return;
2952 /* prepare match expression */
2953 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
2955 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2956 match_expr =
2957 g_strdup_printf
2958 ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
2959 (int) word_len, bufpos);
2961 /* collect the possible completions */
2962 /* start search from begin to end of file */
2963 max_len =
2964 edit_collect_completions (edit, word_start, word_len, match_expr,
2965 (struct selection *) &compl, &num_compl);
2967 if (num_compl > 0)
2969 /* insert completed word if there is only one match */
2970 if (num_compl == 1)
2972 for (i = word_len; i < compl[0].len; i++)
2973 edit_insert (edit, *(compl[0].text + i));
2975 /* more than one possible completion => ask the user */
2976 else
2978 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2979 /* !!! pressed again the selection dialog pops up, but that !!! */
2980 /* !!! seems to require a further internal state !!! */
2981 /*tty_beep (); */
2983 /* let the user select the preferred completion */
2984 editcmd_dialog_completion_show (edit, max_len, word_len,
2985 (struct selection *) &compl, num_compl);
2989 g_free (match_expr);
2990 /* release memory before return */
2991 for (i = 0; i < num_compl; i++)
2992 g_free (compl[i].text);
2995 /* --------------------------------------------------------------------------------------------- */
2997 void
2998 edit_select_codepage_cmd (WEdit * edit)
3000 #ifdef HAVE_CHARSET
3001 if (do_select_codepage ())
3002 edit_set_codeset (edit);
3004 edit->force = REDRAW_COMPLETELY;
3005 edit_refresh_cmd (edit);
3006 #else
3007 (void) edit;
3008 #endif
3011 /* --------------------------------------------------------------------------------------------- */
3013 void
3014 edit_insert_literal_cmd (WEdit * edit)
3016 int char_for_insertion = editcmd_dialog_raw_key_query (_("Insert literal"),
3017 _("Press any key:"), 0);
3018 edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
3021 /* --------------------------------------------------------------------------------------------- */
3023 void
3024 edit_execute_macro_cmd (WEdit * edit)
3026 int command =
3027 CK_Macro (editcmd_dialog_raw_key_query (_("Execute macro"), _("Press macro hotkey:"),
3028 1));
3029 if (command == CK_Macro (0))
3030 command = CK_Insert_Char;
3032 edit_execute_key_command (edit, command, -1);
3035 /* --------------------------------------------------------------------------------------------- */
3037 void
3038 edit_begin_end_macro_cmd (WEdit * edit)
3040 /* edit is a pointer to the widget */
3041 if (edit)
3043 unsigned long command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
3044 edit_execute_key_command (edit, command, -1);
3048 /* --------------------------------------------------------------------------------------------- */
3051 edit_load_forward_cmd (WEdit * edit)
3053 if (edit->modified)
3055 if (edit_query_dialog2
3056 (_("Warning"),
3057 _("Current text was modified without a file save\n"
3058 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3060 edit->force |= REDRAW_COMPLETELY;
3061 return 0;
3064 if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
3066 if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
3068 return 1;
3070 edit_stack_iterator++;
3071 if (edit_history_moveto[edit_stack_iterator].filename)
3073 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3074 edit_history_moveto[edit_stack_iterator].line);
3075 return 0;
3077 else
3079 return 1;
3082 else
3084 return 1;
3088 /* --------------------------------------------------------------------------------------------- */
3091 edit_load_back_cmd (WEdit * edit)
3093 if (edit->modified)
3095 if (edit_query_dialog2
3096 (_("Warning"),
3097 _("Current text was modified without a file save\n"
3098 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3100 edit->force |= REDRAW_COMPLETELY;
3101 return 0;
3104 if (edit_stack_iterator > 0)
3106 edit_stack_iterator--;
3107 if (edit_history_moveto[edit_stack_iterator].filename)
3109 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3110 edit_history_moveto[edit_stack_iterator].line);
3111 return 0;
3113 else
3115 return 1;
3118 else
3120 return 1;
3124 /* --------------------------------------------------------------------------------------------- */
3126 void
3127 edit_get_match_keyword_cmd (WEdit * edit)
3129 gsize word_len = 0, max_len = 0;
3130 int num_def = 0;
3131 int i;
3132 long word_start = 0;
3133 unsigned char *bufpos;
3134 char *match_expr;
3135 char *path = NULL;
3136 char *ptr = NULL;
3137 char *tagfile = NULL;
3139 etags_hash_t def_hash[MAX_DEFINITIONS];
3141 for (i = 0; i < MAX_DEFINITIONS; i++)
3143 def_hash[i].filename = NULL;
3146 /* search start of word to be completed */
3147 if (!edit_find_word_start (edit, &word_start, &word_len))
3148 return;
3150 /* prepare match expression */
3151 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3152 match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
3154 ptr = g_get_current_dir ();
3155 path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
3156 g_free (ptr);
3158 /* Recursive search file 'TAGS' in parent dirs */
3161 ptr = g_path_get_dirname (path);
3162 g_free (path);
3163 path = ptr;
3164 g_free (tagfile);
3165 tagfile = g_build_filename (path, TAGS_NAME, (char *) NULL);
3166 if (exist_file (tagfile))
3167 break;
3169 while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
3171 if (tagfile)
3173 num_def =
3174 etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
3175 g_free (tagfile);
3177 g_free (path);
3179 max_len = MAX_WIDTH_DEF_DIALOG;
3180 word_len = 0;
3181 if (num_def > 0)
3183 editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
3184 (etags_hash_t *) & def_hash, num_def);
3186 g_free (match_expr);
3189 /* --------------------------------------------------------------------------------------------- */
3191 void
3192 edit_move_block_to_right (WEdit * edit)
3194 long start_mark, end_mark;
3195 long cur_bol, start_bol;
3197 if (eval_marks (edit, &start_mark, &end_mark))
3198 return;
3200 start_bol = edit_bol (edit, start_mark);
3201 cur_bol = edit_bol (edit, end_mark - 1);
3204 edit_cursor_move (edit, cur_bol - edit->curs1);
3205 if (option_fill_tabs_with_spaces)
3207 if (option_fake_half_tabs)
3209 insert_spaces_tab (edit, 1);
3211 else
3213 insert_spaces_tab (edit, 0);
3216 else
3218 edit_insert (edit, '\t');
3220 edit_cursor_move (edit, edit_bol (edit, cur_bol) - edit->curs1);
3221 if (cur_bol == 0)
3223 break;
3225 cur_bol = edit_bol (edit, cur_bol - 1);
3227 while (cur_bol >= start_bol);
3228 edit->force |= REDRAW_PAGE;
3231 /* --------------------------------------------------------------------------------------------- */
3233 void
3234 edit_move_block_to_left (WEdit * edit)
3236 long start_mark, end_mark;
3237 long cur_bol, start_bol;
3238 int i, del_tab_width;
3239 int next_char;
3241 if (eval_marks (edit, &start_mark, &end_mark))
3242 return;
3244 start_bol = edit_bol (edit, start_mark);
3245 cur_bol = edit_bol (edit, end_mark - 1);
3248 edit_cursor_move (edit, cur_bol - edit->curs1);
3249 if (option_fake_half_tabs)
3251 del_tab_width = HALF_TAB_SIZE;
3253 else
3255 del_tab_width = option_tab_spacing;
3257 next_char = edit_get_byte (edit, edit->curs1);
3258 if (next_char == '\t')
3260 edit_delete (edit, 1);
3262 else if (next_char == ' ')
3264 for (i = 1; i <= del_tab_width; i++)
3266 if (next_char == ' ')
3268 edit_delete (edit, 1);
3270 next_char = edit_get_byte (edit, edit->curs1);
3273 if (cur_bol == 0)
3275 break;
3277 cur_bol = edit_bol (edit, cur_bol - 1);
3279 while (cur_bol >= start_bol);
3280 edit->force |= REDRAW_PAGE;
3283 /* --------------------------------------------------------------------------------------------- */