Applied MC indentation policy.
[kaloumi3.git] / src / editor / editcmd.c
blob81331e93a8e6720f49e6274064fbd3aa7453a530
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/vfs/mc-vfs/vfs.h"
56 #include "src/history.h"
57 #include "src/widget.h" /* listbox_new() */
58 #include "src/layout.h" /* clr_scr() */
59 #include "src/main.h" /* mc_home source_codepage */
60 #include "src/help.h" /* interactive_display() */
61 #include "src/wtools.h" /* message() */
62 #include "src/charsets.h"
63 #include "src/selcodepage.h"
64 #include "src/cmddef.h"
66 #include "src/editor/edit-impl.h"
67 #include "src/editor/editlock.h"
68 #include "src/editor/edit-widget.h"
69 #include "src/editor/editcmd_dialogs.h"
70 #include "src/editor/etags.h"
72 /* globals: */
74 /* search and replace: */
75 int search_create_bookmark = 0;
76 /* static int search_in_all_charsets = 0; */
78 /* queries on a save */
79 int edit_confirm_save = 1;
81 static int edit_save_cmd (WEdit * edit);
82 static unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l);
84 static void
85 edit_search_cmd_search_create_bookmark (WEdit * edit)
87 int found = 0, books = 0;
88 long l = 0, l_last = -1;
89 long q = 0;
90 gsize len = 0;
92 search_create_bookmark = 0;
93 book_mark_flush (edit, -1);
95 for (;;)
97 if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
98 break;
99 if (found == 0)
100 edit->search_start = edit->search->normal_offset;
101 found++;
102 l += edit_count_lines (edit, q, edit->search->normal_offset);
103 if (l != l_last)
105 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
106 books++;
108 l_last = l;
109 q = edit->search->normal_offset + 1;
112 if (found == 0)
114 edit_error_dialog (_("Search"), _(" Search string not found "));
116 else
118 edit_cursor_move (edit, edit->search_start - edit->curs1);
119 edit_scroll_screen_over_cursor (edit);
123 static int
124 edit_search_cmd_callback (const void *user_data, gsize char_offset)
126 return edit_get_byte ((WEdit *) user_data, (long) char_offset);
129 void
130 edit_help_cmd (WEdit * edit)
132 interactive_display (NULL, "[Internal File Editor]");
133 edit->force |= REDRAW_COMPLETELY;
136 void
137 edit_refresh_cmd (WEdit * edit)
139 #ifdef HAVE_SLANG
140 int color;
142 edit_get_syntax_color (edit, -1, &color);
143 tty_touch_screen ();
144 mc_refresh ();
145 #else
146 (void) edit;
148 clr_scr ();
149 repaint_screen ();
150 #endif /* !HAVE_SLANG */
151 tty_keypad (TRUE);
154 /* If 0 (quick save) then a) create/truncate <filename> file,
155 b) save to <filename>;
156 if 1 (safe save) then a) save to <tempnam>,
157 b) rename <tempnam> to <filename>;
158 if 2 (do backups) then a) save to <tempnam>,
159 b) rename <filename> to <filename.backup_ext>,
160 c) rename <tempnam> to <filename>. */
162 /* returns 0 on error, -1 on abort */
163 static int
164 edit_save_file (WEdit * edit, const char *filename)
166 char *p;
167 gchar *tmp;
168 long filelen = 0;
169 char *savename = 0;
170 gchar *real_filename;
171 int this_save_mode, fd = -1;
173 if (!filename)
174 return 0;
175 if (!*filename)
176 return 0;
178 if (*filename != PATH_SEP && edit->dir)
180 real_filename = concat_dir_and_file (edit->dir, filename);
182 else
184 real_filename = g_strdup (filename);
187 this_save_mode = option_save_mode;
188 if (this_save_mode != EDIT_QUICK_SAVE)
190 if (!vfs_file_is_local (real_filename) ||
191 (fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
194 * The file does not exists yet, so no safe save or
195 * backup are necessary.
197 this_save_mode = EDIT_QUICK_SAVE;
199 if (fd != -1)
200 mc_close (fd);
203 if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
205 int rv;
206 struct stat sb;
208 rv = mc_stat (real_filename, &sb);
209 if (rv == 0 && sb.st_nlink > 1)
211 rv = edit_query_dialog3 (_("Warning"),
212 _(" File has hard-links. Detach before saving? "),
213 _("&Yes"), _("&No"), _("&Cancel"));
214 switch (rv)
216 case 0:
217 this_save_mode = EDIT_SAFE_SAVE;
218 /* fallthrough */
219 case 1:
220 edit->skip_detach_prompt = 1;
221 break;
222 default:
223 g_free (real_filename);
224 return -1;
228 /* Prevent overwriting changes from other editor sessions. */
229 if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
232 /* The default action is "Cancel". */
233 query_set_sel (1);
235 rv = edit_query_dialog2 (_("Warning"),
236 _("The file has been modified in the meantime. Save anyway?"),
237 _("&Yes"), _("&Cancel"));
238 if (rv != 0)
240 g_free (real_filename);
241 return -1;
246 if (this_save_mode != EDIT_QUICK_SAVE)
248 char *savedir, *saveprefix;
249 const char *slashpos;
250 slashpos = strrchr (real_filename, PATH_SEP);
251 if (slashpos)
253 savedir = g_strdup (real_filename);
254 savedir[slashpos - real_filename + 1] = '\0';
256 else
257 savedir = g_strdup (".");
258 saveprefix = concat_dir_and_file (savedir, "cooledit");
259 g_free (savedir);
260 fd = mc_mkstemps (&savename, saveprefix, NULL);
261 g_free (saveprefix);
262 if (!savename)
264 g_free (real_filename);
265 return 0;
267 /* FIXME:
268 * Close for now because mc_mkstemps use pure open system call
269 * to create temporary file and it needs to be reopened by
270 * VFS-aware mc_open().
272 close (fd);
274 else
275 savename = g_strdup (real_filename);
277 mc_chown (savename, edit->stat1.st_uid, edit->stat1.st_gid);
278 mc_chmod (savename, edit->stat1.st_mode);
280 if ((fd =
281 mc_open (savename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode)) == -1)
282 goto error_save;
284 /* pipe save */
285 if ((p = edit_get_write_filter (savename, real_filename)))
287 FILE *file;
289 mc_close (fd);
290 file = (FILE *) popen (p, "w");
292 if (file)
294 filelen = edit_write_stream (edit, file);
295 #if 1
296 pclose (file);
297 #else
298 if (pclose (file) != 0)
300 tmp = g_strconcat (_(" Error writing to pipe: "), p, " ", (char *) NULL);
301 edit_error_dialog (_("Error"), tmp);
302 g_free (tmp);
303 g_free (p);
304 goto error_save;
306 #endif
308 else
310 tmp = g_strconcat (_(" Cannot open pipe for writing: "), p, " ", (char *) NULL);
312 edit_error_dialog (_("Error"), get_sys_error (tmp));
313 g_free (p);
314 g_free (tmp);
315 goto error_save;
317 g_free (p);
319 else if (edit->lb == LB_ASIS)
320 { /* do not change line breaks */
321 long buf;
322 buf = 0;
323 filelen = edit->last_byte;
324 while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1)
326 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
328 mc_close (fd);
329 goto error_save;
331 buf++;
333 if (mc_write
334 (fd, (char *) edit->buffers1[buf],
335 edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE))
337 filelen = -1;
339 else if (edit->curs2)
341 edit->curs2--;
342 buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
343 if (mc_write
344 (fd,
345 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
346 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
347 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE))
349 filelen = -1;
351 else
353 while (--buf >= 0)
355 if (mc_write (fd, (char *) edit->buffers2[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
357 filelen = -1;
358 break;
362 edit->curs2++;
364 if (mc_close (fd))
365 goto error_save;
367 /* Update the file information, especially the mtime. */
368 if (mc_stat (savename, &edit->stat1) == -1)
369 goto error_save;
371 else
372 { /* change line breaks */
373 FILE *file;
375 mc_close (fd);
377 file = (FILE *) fopen (savename, "w");
379 if (file)
381 filelen = edit_write_stream (edit, file);
382 fclose (file);
384 else
386 char *msg;
388 msg = g_strdup_printf (_(" Cannot open file for writing: %s "), savename);
389 edit_error_dialog (_("Error"), msg);
390 g_free (msg);
391 goto error_save;
395 if (filelen != edit->last_byte)
396 goto error_save;
398 if (this_save_mode == EDIT_DO_BACKUP)
400 assert (option_backup_ext != NULL);
401 tmp = g_strconcat (real_filename, option_backup_ext, (char *) NULL);
402 if (mc_rename (real_filename, tmp) == -1)
404 g_free (tmp);
405 goto error_save;
409 if (this_save_mode != EDIT_QUICK_SAVE)
410 if (mc_rename (savename, real_filename) == -1)
411 goto error_save;
412 g_free (savename);
413 g_free (real_filename);
414 return 1;
415 error_save:
416 /* FIXME: Is this safe ?
417 * if (this_save_mode != EDIT_QUICK_SAVE)
418 * mc_unlink (savename);
420 g_free (real_filename);
421 g_free (savename);
422 return 0;
425 void
426 menu_save_mode_cmd (void)
428 /* diaog sizes */
429 const int DLG_X = 38;
430 const int DLG_Y = 13;
432 char *str_result;
434 const char *str[] = {
435 N_("&Quick save"),
436 N_("&Safe save"),
437 N_("&Do backups with following extension:")
440 QuickWidget widgets[] = {
441 /* 0 */
442 QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
443 /* 1 */
444 QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
445 /* 2 */
446 QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
447 /* 3 */
448 QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
449 /* 4 */
450 QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
451 QUICK_END
454 QuickDialog dialog = {
455 DLG_X, DLG_Y, -1, -1, N_(" Edit Save Mode "),
456 "[Edit Save Mode]", widgets, FALSE
459 size_t i;
460 size_t maxlen = 0;
461 size_t w0, w1, b_len, w3;
463 assert (option_backup_ext != NULL);
465 /* OK/Cancel buttons */
466 w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
467 w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5; /* default button */
468 b_len = w0 + w1 + 3;
470 maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
472 w3 = 0;
473 for (i = 0; i < 3; i++)
475 #ifdef ENABLE_NLS
476 str[i] = _(str[i]);
477 #endif
478 w3 = max (w3, (size_t) str_term_width1 (str[i]));
481 maxlen = max (maxlen, w3 + 4);
483 dialog.xlen = min ((size_t) COLS, maxlen + 8);
485 widgets[3].u.input.len = w3;
486 widgets[1].relative_x = (dialog.xlen - b_len) / 2;
487 widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
489 for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
490 widgets[i].x_divisions = dialog.xlen;
492 if (quick_dialog (&dialog) != B_CANCEL)
494 g_free (option_backup_ext);
495 option_backup_ext = str_result;
499 void
500 edit_set_filename (WEdit * edit, const char *f)
502 g_free (edit->filename);
503 if (!f)
504 f = "";
505 edit->filename = g_strdup (f);
506 if (edit->dir == NULL && *f != PATH_SEP)
507 #ifdef ENABLE_VFS
508 edit->dir = g_strdup (vfs_get_current_dir ());
509 #else /* ENABLE_VFS */
510 edit->dir = g_get_current_dir ();
511 #endif /* ENABLE_VFS */
514 static gboolean
515 edit_check_newline (WEdit * edit)
517 return !(option_check_nl_at_eof && edit->last_byte > 0
518 && edit_get_byte (edit, edit->last_byte - 1) != '\n'
519 && edit_query_dialog2 (_("Warning"),
520 _("The file you are saving is not finished with a newline"),
521 _("C&ontinue"), _("&Cancel")));
524 static char *
525 edit_get_save_file_as (WEdit * edit)
527 #define DLG_WIDTH 64
528 #define DLG_HEIGHT 14
530 static LineBreaks cur_lb = LB_ASIS;
532 char *filename = edit->filename;
534 const char *lb_names[LB_NAMES] = {
535 N_("&Do not change"),
536 N_("&Unix format (LF)"),
537 N_("&Windows/DOS format (CR LF)"),
538 N_("&Macintosh format (CR)")
541 QuickWidget quick_widgets[] = {
542 QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
543 QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
544 QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
545 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
546 QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
547 "save-as", &filename),
548 QUICK_LABEL (2, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_(" Enter file name: ")),
549 QUICK_END
552 QuickDialog Quick_options = {
553 DLG_WIDTH, DLG_HEIGHT, -1, -1,
554 N_(" Save As "), "[Save File As]",
555 quick_widgets, FALSE
558 if (quick_dialog (&Quick_options) != B_CANCEL)
560 edit->lb = cur_lb;
561 return filename;
564 return NULL;
566 #undef DLG_WIDTH
567 #undef DLG_HEIGHT
570 /* Here we want to warn the users of overwriting an existing file,
571 but only if they have made a change to the filename */
572 /* returns 1 on success */
574 edit_save_as_cmd (WEdit * edit)
576 /* This heads the 'Save As' dialog box */
577 char *exp;
578 int save_lock = 0;
579 int different_filename = 0;
581 if (!edit_check_newline (edit))
582 return 0;
584 exp = edit_get_save_file_as (edit);
585 edit_push_action (edit, KEY_PRESS + edit->start_display);
587 if (exp)
589 if (!*exp)
591 g_free (exp);
592 edit->force |= REDRAW_COMPLETELY;
593 return 0;
595 else
597 int rv;
598 if (strcmp (edit->filename, exp))
600 int file;
601 different_filename = 1;
602 if ((file = mc_open (exp, O_RDONLY | O_BINARY)) != -1)
604 /* the file exists */
605 mc_close (file);
606 /* Overwrite the current file or cancel the operation */
607 if (edit_query_dialog2
608 (_("Warning"),
609 _(" A file already exists with this name. "),
610 _("&Overwrite"), _("&Cancel")))
612 edit->force |= REDRAW_COMPLETELY;
613 g_free (exp);
614 return 0;
617 else
619 edit->stat1.st_mode |= S_IWUSR;
621 save_lock = edit_lock_file (exp);
623 else
625 /* filenames equal, check if already locked */
626 if (!edit->locked && !edit->delete_file)
627 save_lock = edit_lock_file (exp);
630 if (different_filename)
633 * Allow user to write into saved (under another name) file
634 * even if original file had r/o user permissions.
636 edit->stat1.st_mode |= S_IWRITE;
639 rv = edit_save_file (edit, exp);
640 switch (rv)
642 case 1:
643 /* Succesful, so unlock both files */
644 if (different_filename)
646 if (save_lock)
647 edit_unlock_file (exp);
648 if (edit->locked)
649 edit->locked = edit_unlock_file (edit->filename);
651 else
653 if (edit->locked || save_lock)
654 edit->locked = edit_unlock_file (edit->filename);
657 edit_set_filename (edit, exp);
658 if (edit->lb != LB_ASIS)
659 edit_reload (edit, exp);
660 g_free (exp);
661 edit->modified = 0;
662 edit->delete_file = 0;
663 if (different_filename)
664 edit_load_syntax (edit, NULL, option_syntax_type);
665 edit->force |= REDRAW_COMPLETELY;
666 return 1;
667 default:
668 edit_error_dialog (_(" Save As "), get_sys_error (_(" Cannot save file. ")));
669 /* fallthrough */
670 case -1:
671 /* Failed, so maintain modify (not save) lock */
672 if (save_lock)
673 edit_unlock_file (exp);
674 g_free (exp);
675 edit->force |= REDRAW_COMPLETELY;
676 return 0;
680 edit->force |= REDRAW_COMPLETELY;
681 return 0;
684 /* {{{ Macro stuff starts here */
686 /* creates a macro file if it doesn't exist */
687 static FILE *
688 edit_open_macro_file (const char *r)
690 gchar *filename;
691 FILE *fd;
692 int file;
693 filename = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
694 if ((file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
696 g_free (filename);
697 return 0;
699 close (file);
700 fd = fopen (filename, r);
701 g_free (filename);
702 return fd;
705 #define MAX_MACROS 1024
706 static int saved_macro[MAX_MACROS + 1];
707 static int saved_macros_loaded = 0;
710 This is just to stop the macro file be loaded over and over for keys
711 that aren't defined to anything. On slow systems this could be annoying.
713 static int
714 macro_exists (int k)
716 int i;
717 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
718 if (saved_macro[i] == k)
719 return i;
720 return -1;
723 /* returns 1 on error */
724 static int
725 edit_delete_macro (WEdit * edit, int k)
727 gchar *tmp, *tmp2;
728 struct macro macro[MAX_MACRO_LENGTH];
729 FILE *f, *g;
730 int s, i, n, j = 0;
732 (void) edit;
734 if (saved_macros_loaded)
735 if ((j = macro_exists (k)) < 0)
736 return 0;
737 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
738 g = fopen (tmp, "w");
739 g_free (tmp);
740 if (!g)
742 edit_error_dialog (_(" Delete macro "), get_sys_error (_(" Cannot open temp file ")));
743 return 1;
745 f = edit_open_macro_file ("r");
746 if (!f)
748 edit_error_dialog (_(" Delete macro "), get_sys_error (_(" Cannot open macro file ")));
749 fclose (g);
750 return 1;
752 for (;;)
754 n = fscanf (f, ("key '%d 0': "), &s);
755 if (!n || n == EOF)
756 break;
757 n = 0;
758 while (fscanf (f, "%lu %d, ", &macro[n].command, &macro[n].ch))
759 n++;
760 fscanf (f, ";\n");
761 if (s != k)
763 fprintf (g, ("key '%d 0': "), s);
764 for (i = 0; i < n; i++)
765 fprintf (g, "%lu %d, ", macro[i].command, macro[i].ch);
766 fprintf (g, ";\n");
769 fclose (f);
770 fclose (g);
771 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
772 tmp2 = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
773 if (rename (tmp, tmp2) == -1)
775 edit_error_dialog (_(" Delete macro "), get_sys_error (_(" Cannot overwrite macro file ")));
776 g_free (tmp);
777 g_free (tmp2);
778 return 1;
780 g_free (tmp);
781 g_free (tmp2);
783 if (saved_macros_loaded)
784 memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
785 return 0;
788 /* returns 0 on error */
790 edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
792 FILE *f;
793 int s, i;
795 edit_push_action (edit, KEY_PRESS + edit->start_display);
796 s = editcmd_dialog_raw_key_query (_(" Save macro "), _(" Press the macro's new hotkey: "), 1);
797 edit->force |= REDRAW_COMPLETELY;
798 if (s)
800 if (edit_delete_macro (edit, s))
801 return 0;
802 f = edit_open_macro_file ("a+");
803 if (f)
805 fprintf (f, ("key '%d 0': "), s);
806 for (i = 0; i < n; i++)
807 fprintf (f, "%lu %d, ", macro[i].command, macro[i].ch);
808 fprintf (f, ";\n");
809 fclose (f);
810 if (saved_macros_loaded)
812 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
813 saved_macro[i] = s;
815 return 1;
817 else
818 edit_error_dialog (_(" Save macro "), get_sys_error (_(" Cannot open macro file ")));
820 return 0;
823 void
824 edit_delete_macro_cmd (WEdit * edit)
826 int command;
828 command = editcmd_dialog_raw_key_query (_(" Delete macro "), _(" Press macro hotkey: "), 1);
830 if (command != 0)
831 edit_delete_macro (edit, command);
834 /* return 0 on error */
836 edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
838 FILE *f;
839 int s, i = 0, found = 0;
841 (void) edit;
843 if (saved_macros_loaded)
844 if (macro_exists (k) < 0)
845 return 0;
847 if ((f = edit_open_macro_file ("r")))
849 struct macro dummy;
852 int u;
853 u = fscanf (f, ("key '%d 0': "), &s);
854 if (!u || u == EOF)
855 break;
856 if (!saved_macros_loaded)
857 saved_macro[i++] = s;
858 if (!found)
860 *n = 0;
861 while (*n < MAX_MACRO_LENGTH
862 && 2 == fscanf (f, "%lu %d, ", &macro[*n].command, &macro[*n].ch))
863 (*n)++;
865 else
867 while (2 == fscanf (f, "%lu %d, ", &dummy.command, &dummy.ch));
869 fscanf (f, ";\n");
870 if (s == k)
871 found = 1;
873 while (!found || !saved_macros_loaded);
874 if (!saved_macros_loaded)
876 saved_macro[i] = 0;
877 saved_macros_loaded = 1;
879 fclose (f);
880 return found;
882 else
883 edit_error_dialog (_(" Load macro "), get_sys_error (_(" Cannot open macro file ")));
884 return 0;
887 /* }}} Macro stuff starts here */
889 /* returns 1 on success */
891 edit_save_confirm_cmd (WEdit * edit)
893 gchar *f = NULL;
895 if (!edit_check_newline (edit))
896 return 0;
898 if (edit_confirm_save)
900 f = g_strconcat (_(" Confirm save file? : "), edit->filename, " ", (char *) NULL);
901 if (edit_query_dialog2 (_(" Save file "), f, _("&Save"), _("&Cancel")))
903 g_free (f);
904 return 0;
906 g_free (f);
908 return edit_save_cmd (edit);
912 /* returns 1 on success */
913 static int
914 edit_save_cmd (WEdit * edit)
916 int res, save_lock = 0;
918 if (!edit->locked && !edit->delete_file)
919 save_lock = edit_lock_file (edit->filename);
920 res = edit_save_file (edit, edit->filename);
922 /* Maintain modify (not save) lock on failure */
923 if ((res > 0 && edit->locked) || save_lock)
924 edit->locked = edit_unlock_file (edit->filename);
926 /* On failure try 'save as', it does locking on its own */
927 if (!res)
928 return edit_save_as_cmd (edit);
929 edit->force |= REDRAW_COMPLETELY;
930 if (res > 0)
932 edit->delete_file = 0;
933 edit->modified = 0;
936 return 1;
940 /* returns 1 on success */
942 edit_new_cmd (WEdit * edit)
944 if (edit->modified)
946 if (edit_query_dialog2
947 (_("Warning"),
949 (" Current text was modified without a file save. \n Continue discards these changes. "),
950 _("C&ontinue"), _("&Cancel")))
952 edit->force |= REDRAW_COMPLETELY;
953 return 0;
956 edit->force |= REDRAW_COMPLETELY;
958 return edit_renew (edit); /* if this gives an error, something has really screwed up */
961 /* returns 1 on error */
962 static int
963 edit_load_file_from_filename (WEdit * edit, char *exp)
965 int prev_locked = edit->locked;
966 char *prev_filename = g_strdup (edit->filename);
968 if (!edit_reload (edit, exp))
970 g_free (prev_filename);
971 return 1;
974 if (prev_locked)
975 edit_unlock_file (prev_filename);
976 g_free (prev_filename);
977 return 0;
980 static void
981 edit_load_syntax_file (WEdit * edit)
983 char *extdir;
984 int dir = 0;
986 if (geteuid () == 0)
988 dir = query_dialog (_("Syntax file edit"),
989 _(" Which syntax file you want to edit? "), D_NORMAL, 2,
990 _("&User"), _("&System Wide"));
993 extdir = concat_dir_and_file (mc_home, "syntax" PATH_SEP_STR "Syntax");
994 if (!exist_file (extdir))
996 g_free (extdir);
997 extdir = concat_dir_and_file (mc_home_alt, "syntax" PATH_SEP_STR "Syntax");
1000 if (dir == 0)
1002 char *buffer;
1004 buffer = concat_dir_and_file (home_dir, EDIT_SYNTAX_FILE);
1005 check_for_default (extdir, buffer);
1006 edit_load_file_from_filename (edit, buffer);
1007 g_free (buffer);
1009 else if (dir == 1)
1010 edit_load_file_from_filename (edit, extdir);
1012 g_free (extdir);
1015 static void
1016 edit_load_menu_file (WEdit * edit)
1018 char *buffer;
1019 char *menufile;
1020 int dir = 0;
1022 dir = query_dialog (_(" Menu edit "),
1023 _(" Which menu file do you want to edit? "), D_NORMAL,
1024 geteuid ()? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
1026 menufile = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
1028 if (!exist_file (menufile))
1030 g_free (menufile);
1031 menufile = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
1034 switch (dir)
1036 case 0:
1037 buffer = g_strdup (EDIT_LOCAL_MENU);
1038 check_for_default (menufile, buffer);
1039 chmod (buffer, 0600);
1040 break;
1042 case 1:
1043 buffer = concat_dir_and_file (home_dir, EDIT_HOME_MENU);
1044 check_for_default (menufile, buffer);
1045 break;
1047 case 2:
1048 buffer = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
1049 if (!exist_file (buffer))
1051 g_free (buffer);
1052 buffer = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
1054 break;
1056 default:
1057 g_free (menufile);
1058 return;
1061 edit_load_file_from_filename (edit, buffer);
1063 g_free (buffer);
1064 g_free (menufile);
1068 edit_load_cmd (WEdit * edit, edit_current_file_t what)
1070 char *exp;
1072 if (edit->modified
1073 && (edit_query_dialog2
1074 (_("Warning"),
1075 _(" Current text was modified without a file save. \n"
1076 " Continue discards these changes. "), _("C&ontinue"), _("&Cancel")) == 1))
1078 edit->force |= REDRAW_COMPLETELY;
1079 return 0;
1082 switch (what)
1084 case EDIT_FILE_COMMON:
1085 exp = input_expand_dialog (_(" Load "), _(" Enter file name: "),
1086 MC_HISTORY_EDIT_LOAD, edit->filename);
1088 if (exp)
1090 if (*exp)
1091 edit_load_file_from_filename (edit, exp);
1092 g_free (exp);
1094 break;
1096 case EDIT_FILE_SYNTAX:
1097 edit_load_syntax_file (edit);
1098 break;
1100 case EDIT_FILE_MENU:
1101 edit_load_menu_file (edit);
1102 break;
1104 default:
1105 break;
1108 edit->force |= REDRAW_COMPLETELY;
1109 return 0;
1113 if mark2 is -1 then marking is from mark1 to the cursor.
1114 Otherwise its between the markers. This handles this.
1115 Returns 1 if no text is marked.
1118 eval_marks (WEdit * edit, long *start_mark, long *end_mark)
1120 if (edit->mark1 != edit->mark2)
1122 long start_bol, start_eol;
1123 long end_bol, end_eol;
1124 long col1, col2;
1125 long diff1, diff2;
1126 if (edit->mark2 >= 0)
1128 *start_mark = min (edit->mark1, edit->mark2);
1129 *end_mark = max (edit->mark1, edit->mark2);
1131 else
1133 *start_mark = min (edit->mark1, edit->curs1);
1134 *end_mark = max (edit->mark1, edit->curs1);
1135 edit->column2 = edit->curs_col + edit->over_col;
1137 if (column_highlighting
1138 && (((edit->mark1 > edit->curs1) && (edit->column1 < edit->column2))
1139 || ((edit->mark1 < edit->curs1) && (edit->column1 > edit->column2))))
1142 start_bol = edit_bol (edit, *start_mark);
1143 start_eol = edit_eol (edit, start_bol - 1) + 1;
1144 end_bol = edit_bol (edit, *end_mark);
1145 end_eol = edit_eol (edit, *end_mark);
1146 col1 = min (edit->column1, edit->column2);
1147 col2 = max (edit->column1, edit->column2);
1149 diff1 =
1150 edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
1151 col1, 0);
1152 diff2 =
1153 edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
1154 col1, 0);
1156 *start_mark -= diff1;
1157 *end_mark += diff2;
1158 *start_mark = max (*start_mark, start_eol);
1159 *end_mark = min (*end_mark, end_eol);
1161 return 0;
1163 else
1165 *start_mark = *end_mark = 0;
1166 edit->column2 = edit->column1 = 0;
1167 return 1;
1171 #define space_width 1
1173 void
1174 edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
1176 long cursor;
1177 int i, col;
1178 cursor = edit->curs1;
1179 col = edit_get_col (edit);
1180 for (i = 0; i < size; i++)
1182 if (data[i] == '\n')
1183 { /* fill in and move to next line */
1184 int l;
1185 long p;
1186 if (edit_get_byte (edit, edit->curs1) != '\n')
1188 l = width - (edit_get_col (edit) - col);
1189 while (l > 0)
1191 edit_insert (edit, ' ');
1192 l -= space_width;
1195 for (p = edit->curs1;; p++)
1197 if (p == edit->last_byte)
1199 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1200 edit_insert_ahead (edit, '\n');
1201 p++;
1202 break;
1204 if (edit_get_byte (edit, p) == '\n')
1206 p++;
1207 break;
1210 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1211 l = col - edit_get_col (edit);
1212 while (l >= space_width)
1214 edit_insert (edit, ' ');
1215 l -= space_width;
1217 continue;
1219 edit_insert (edit, data[i]);
1221 edit_cursor_move (edit, cursor - edit->curs1);
1224 #define TEMP_BUF_LEN 1024
1227 edit_insert_column_of_text_from_file (WEdit * edit, int file)
1229 long cursor;
1230 int i, col;
1231 int blocklen = -1, width;
1232 unsigned char *data;
1233 cursor = edit->curs1;
1234 col = edit_get_col (edit);
1235 data = g_malloc0 (TEMP_BUF_LEN);
1236 while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
1238 for (width = 0; width < blocklen; width++)
1240 if (data[width] == '\n')
1241 break;
1243 for (i = 0; i < blocklen; i++)
1245 if (data[i] == '\n')
1246 { /* fill in and move to next line */
1247 int l;
1248 long p;
1249 if (edit_get_byte (edit, edit->curs1) != '\n')
1251 l = width - (edit_get_col (edit) - col);
1252 while (l > 0)
1254 edit_insert (edit, ' ');
1255 l -= space_width;
1258 for (p = edit->curs1;; p++)
1260 if (p == edit->last_byte)
1262 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1263 edit_insert_ahead (edit, '\n');
1264 p++;
1265 break;
1267 if (edit_get_byte (edit, p) == '\n')
1269 p++;
1270 break;
1273 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1274 l = col - edit_get_col (edit);
1275 while (l >= space_width)
1277 edit_insert (edit, ' ');
1278 l -= space_width;
1280 continue;
1282 edit_insert (edit, data[i]);
1285 edit_cursor_move (edit, cursor - edit->curs1);
1286 g_free (data);
1287 edit->force |= REDRAW_PAGE;
1288 return blocklen;
1291 void
1292 edit_block_copy_cmd (WEdit * edit)
1294 long start_mark, end_mark, current = edit->curs1;
1295 int size;
1296 unsigned char *copy_buf;
1298 edit_update_curs_col (edit);
1299 if (eval_marks (edit, &start_mark, &end_mark))
1300 return;
1302 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1304 /* all that gets pushed are deletes hence little space is used on the stack */
1306 edit_push_markers (edit);
1308 if (column_highlighting)
1310 edit_insert_column_of_text (edit, copy_buf, size, abs (edit->column2 - edit->column1));
1312 else
1314 while (size--)
1315 edit_insert_ahead (edit, copy_buf[size]);
1318 g_free (copy_buf);
1319 edit_scroll_screen_over_cursor (edit);
1321 if (column_highlighting)
1323 edit_set_markers (edit, 0, 0, 0, 0);
1324 edit_push_action (edit, COLUMN_ON);
1325 column_highlighting = 0;
1327 else if (start_mark < current && end_mark > current)
1328 edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
1330 edit->force |= REDRAW_PAGE;
1334 void
1335 edit_block_move_cmd (WEdit * edit)
1337 long count;
1338 long current;
1339 unsigned char *copy_buf;
1340 long start_mark, end_mark;
1341 int deleted = 0;
1342 int x = 0;
1344 if (eval_marks (edit, &start_mark, &end_mark))
1345 return;
1346 if (column_highlighting)
1348 edit_update_curs_col (edit);
1349 x = edit->curs_col;
1350 if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1351 if ((x > edit->column1 && x < edit->column2)
1352 || (x > edit->column2 && x < edit->column1))
1353 return;
1355 else if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1356 return;
1358 if ((end_mark - start_mark) > option_max_undo / 2)
1359 if (edit_query_dialog2
1360 (_("Warning"),
1362 (" Block is large, you may not be able to undo this action. "),
1363 _("C&ontinue"), _("&Cancel")))
1364 return;
1366 edit_push_markers (edit);
1367 current = edit->curs1;
1368 if (column_highlighting)
1370 long line;
1371 int size, c1, c2;
1372 line = edit->curs_line;
1373 if (edit->mark2 < 0)
1374 edit_mark_cmd (edit, 0);
1375 c1 = min (edit->column1, edit->column2);
1376 c2 = max (edit->column1, edit->column2);
1377 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1378 if (x < c2)
1380 edit_block_delete_cmd (edit);
1381 deleted = 1;
1383 edit_move_to_line (edit, line);
1384 edit_cursor_move (edit,
1385 edit_move_forward3 (edit,
1386 edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
1387 edit_insert_column_of_text (edit, copy_buf, size, c2 - c1);
1388 if (!deleted)
1390 line = edit->curs_line;
1391 edit_update_curs_col (edit);
1392 x = edit->curs_col;
1393 edit_block_delete_cmd (edit);
1394 edit_move_to_line (edit, line);
1395 edit_cursor_move (edit,
1396 edit_move_forward3 (edit,
1397 edit_bol (edit,
1398 edit->curs1), x, 0) - edit->curs1);
1400 edit_set_markers (edit, 0, 0, 0, 0);
1401 edit_push_action (edit, COLUMN_ON);
1402 column_highlighting = 0;
1404 else
1406 copy_buf = g_malloc0 (end_mark - start_mark);
1407 edit_cursor_move (edit, start_mark - edit->curs1);
1408 edit_scroll_screen_over_cursor (edit);
1409 count = start_mark;
1410 while (count < end_mark)
1412 copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
1413 count++;
1415 edit_scroll_screen_over_cursor (edit);
1416 edit_cursor_move (edit,
1417 current - edit->curs1 -
1418 (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
1419 edit_scroll_screen_over_cursor (edit);
1420 while (count-- > start_mark)
1421 edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
1422 edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
1424 edit_scroll_screen_over_cursor (edit);
1425 g_free (copy_buf);
1426 edit->force |= REDRAW_PAGE;
1429 static void
1430 edit_delete_column_of_text (WEdit * edit)
1432 long p, q, r, m1, m2;
1433 long b, c, d, n;
1435 eval_marks (edit, &m1, &m2);
1436 n = edit_move_forward (edit, m1, 0, m2) + 1;
1437 c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
1438 d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
1439 b = max (min (c, d), min (edit->column1, edit->column2));
1440 c = max (c, max (edit->column1, edit->column2));
1442 while (n--)
1444 r = edit_bol (edit, edit->curs1);
1445 p = edit_move_forward3 (edit, r, b, 0);
1446 q = edit_move_forward3 (edit, r, c, 0);
1447 if (p < m1)
1448 p = m1;
1449 if (q > m2)
1450 q = m2;
1451 edit_cursor_move (edit, p - edit->curs1);
1452 while (q > p)
1454 /* delete line between margins */
1455 if (edit_get_byte (edit, edit->curs1) != '\n')
1456 edit_delete (edit, 1);
1457 q--;
1459 if (n)
1460 /* move to next line except on the last delete */
1461 edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
1465 /* if success return 0 */
1466 static int
1467 edit_block_delete (WEdit * edit)
1469 long count;
1470 long start_mark, end_mark;
1471 int curs_pos, line_width;
1472 long curs_line, c1, c2;
1474 if (eval_marks (edit, &start_mark, &end_mark))
1475 return 0;
1476 if (column_highlighting && edit->mark2 < 0)
1477 edit_mark_cmd (edit, 0);
1478 if ((end_mark - start_mark) > option_max_undo / 2)
1480 /* Warning message with a query to continue or cancel the operation */
1481 if (edit_query_dialog2
1482 (_("Warning"),
1484 (" Block is large, you may not be able to undo this action. "),
1485 _("C&ontinue"), _("&Cancel")))
1487 return 1;
1490 c1 = min (edit->column1, edit->column2);
1491 c2 = max (edit->column1, edit->column2);
1492 edit->column1 = c1;
1493 edit->column2 = c2;
1495 edit_push_markers (edit);
1497 curs_line = edit->curs_line;
1499 /* calculate line width and cursor position before cut */
1500 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
1501 edit_eol (edit, edit->curs1));
1502 curs_pos = edit->curs_col + edit->over_col;
1504 /* move cursor to start of selection */
1505 edit_cursor_move (edit, start_mark - edit->curs1);
1506 edit_scroll_screen_over_cursor (edit);
1507 count = start_mark;
1508 if (start_mark < end_mark)
1510 if (column_highlighting)
1512 if (edit->mark2 < 0)
1513 edit_mark_cmd (edit, 0);
1514 edit_delete_column_of_text (edit);
1515 /* move cursor to the saved position */
1516 edit_move_to_line (edit, curs_line);
1517 /* calculate line width after cut */
1518 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
1519 edit_eol (edit, edit->curs1));
1520 if (option_cursor_beyond_eol && curs_pos > line_width)
1521 edit->over_col = curs_pos - line_width;
1523 else
1525 while (count < end_mark)
1527 edit_delete (edit, 1);
1528 count++;
1532 edit_set_markers (edit, 0, 0, 0, 0);
1533 edit->force |= REDRAW_PAGE;
1534 return 0;
1537 /* returns 1 if canceelled by user */
1539 edit_block_delete_cmd (WEdit * edit)
1541 long start_mark, end_mark;
1542 if (eval_marks (edit, &start_mark, &end_mark))
1544 edit_delete_line (edit);
1545 return 0;
1547 return edit_block_delete (edit);
1550 #define INPUT_INDEX 9
1552 static gboolean
1553 editcmd_find (WEdit * edit, gsize * len)
1555 off_t search_start = edit->search_start;
1556 off_t search_end;
1557 long start_mark = 0;
1558 long end_mark = edit->last_byte;
1559 int mark_res = 0;
1561 if (edit_search_options.only_in_selection)
1563 mark_res = eval_marks (edit, &start_mark, &end_mark);
1564 if (mark_res != 0)
1566 edit->search->error = MC_SEARCH_E_NOTFOUND;
1567 edit->search->error_str = g_strdup (_(" Search string not found "));
1568 return FALSE;
1570 if (edit_search_options.backwards)
1572 if (search_start > end_mark || search_start <= start_mark)
1574 search_start = end_mark;
1577 else
1579 if (search_start < start_mark || search_start >= end_mark)
1581 search_start = start_mark;
1585 else
1587 if (edit_search_options.backwards)
1588 end_mark = max (1, edit->curs1) - 1;
1590 if (edit_search_options.backwards)
1592 search_end = end_mark;
1593 while ((int) search_start >= start_mark)
1595 if (search_end > (off_t) (search_start + edit->search->original_len) &&
1596 mc_search_is_fixed_search_str (edit->search))
1598 search_end = search_start + edit->search->original_len;
1600 if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
1601 && edit->search->normal_offset == search_start)
1603 return TRUE;
1605 search_start--;
1607 edit->search->error_str = g_strdup (_(" Search string not found "));
1609 else
1611 return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
1613 return FALSE;
1617 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1618 (and the above) routines to work properly - paul */
1620 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1622 static char *
1623 edit_replace_cmd__conv_to_display (char *str)
1625 #ifdef HAVE_CHARSET
1626 GString *tmp;
1627 tmp = str_convert_to_display (str);
1629 if (tmp && tmp->len)
1631 return g_string_free (tmp, FALSE);
1633 g_string_free (tmp, TRUE);
1634 #endif
1635 return g_strdup (str);
1638 static char *
1639 edit_replace_cmd__conv_to_input (char *str)
1641 #ifdef HAVE_CHARSET
1642 GString *tmp;
1643 tmp = str_convert_to_input (str);
1645 if (tmp && tmp->len)
1647 return g_string_free (tmp, FALSE);
1649 g_string_free (tmp, TRUE);
1650 return g_strdup (str);
1651 #endif
1652 return g_strdup (str);
1655 /* call with edit = 0 before shutdown to close memory leaks */
1656 void
1657 edit_replace_cmd (WEdit * edit, int again)
1659 /* 1 = search string, 2 = replace with */
1660 static char *saved1 = NULL; /* saved default[123] */
1661 static char *saved2 = NULL;
1662 char *input1 = NULL; /* user input from the dialog */
1663 char *input2 = NULL;
1664 char *disp1 = NULL;
1665 char *disp2 = NULL;
1666 int replace_yes;
1667 long times_replaced = 0, last_search;
1668 gboolean once_found = FALSE;
1670 if (!edit)
1672 g_free (saved1), saved1 = NULL;
1673 g_free (saved2), saved2 = NULL;
1674 return;
1677 last_search = edit->last_byte;
1679 edit->force |= REDRAW_COMPLETELY;
1681 if (again && !saved1 && !saved2)
1682 again = 0;
1684 if (again)
1686 input1 = g_strdup (saved1 ? saved1 : "");
1687 input2 = g_strdup (saved2 ? saved2 : "");
1689 else
1691 char *tmp_inp1, *tmp_inp2;
1692 disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
1693 disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
1695 edit_push_action (edit, KEY_PRESS + edit->start_display);
1697 editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
1699 g_free (disp1);
1700 g_free (disp2);
1702 if (input1 == NULL || *input1 == '\0')
1704 edit->force = REDRAW_COMPLETELY;
1705 goto cleanup;
1708 tmp_inp1 = input1;
1709 tmp_inp2 = input2;
1710 input1 = edit_replace_cmd__conv_to_input (input1);
1711 input2 = edit_replace_cmd__conv_to_input (input2);
1712 g_free (tmp_inp1);
1713 g_free (tmp_inp2);
1715 g_free (saved1), saved1 = g_strdup (input1);
1716 g_free (saved2), saved2 = g_strdup (input2);
1718 if (edit->search)
1720 mc_search_free (edit->search);
1721 edit->search = NULL;
1725 if (!edit->search)
1727 edit->search = mc_search_new (input1, -1);
1728 if (edit->search == NULL)
1730 edit->search_start = edit->curs1;
1731 return;
1733 edit->search->search_type = edit_search_options.type;
1734 edit->search->is_all_charsets = edit_search_options.all_codepages;
1735 edit->search->is_case_sentitive = edit_search_options.case_sens;
1736 edit->search->whole_words = edit_search_options.whole_words;
1737 edit->search->search_fn = edit_search_cmd_callback;
1740 if (edit->found_len && edit->search_start == edit->found_start + 1
1741 && edit_search_options.backwards)
1742 edit->search_start--;
1744 if (edit->found_len && edit->search_start == edit->found_start - 1
1745 && !edit_search_options.backwards)
1746 edit->search_start++;
1750 gsize len = 0;
1751 long new_start;
1753 if (!editcmd_find (edit, &len))
1755 if (!(edit->search->error == MC_SEARCH_E_OK ||
1756 (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
1758 edit_error_dialog (_("Search"), edit->search->error_str);
1760 break;
1762 once_found = TRUE;
1763 new_start = edit->search->normal_offset;
1765 edit->search_start = new_start = edit->search->normal_offset;
1766 /*returns negative on not found or error in pattern */
1768 if (edit->search_start >= 0)
1770 guint i;
1772 edit->found_start = edit->search_start;
1773 i = edit->found_len = len;
1775 edit_cursor_move (edit, edit->search_start - edit->curs1);
1776 edit_scroll_screen_over_cursor (edit);
1778 replace_yes = 1;
1780 if (edit->replace_mode == 0)
1782 int l;
1783 l = edit->curs_row - edit->num_widget_lines / 3;
1784 if (l > 0)
1785 edit_scroll_downward (edit, l);
1786 if (l < 0)
1787 edit_scroll_upward (edit, -l);
1789 edit_scroll_screen_over_cursor (edit);
1790 edit->force |= REDRAW_PAGE;
1791 edit_render_keypress (edit);
1793 /*so that undo stops at each query */
1794 edit_push_key_press (edit);
1795 /* and prompt 2/3 down */
1796 disp1 = edit_replace_cmd__conv_to_display (saved1);
1797 disp2 = edit_replace_cmd__conv_to_display (saved2);
1798 switch (editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1))
1800 case B_ENTER:
1801 replace_yes = 1;
1802 break;
1803 case B_SKIP_REPLACE:
1804 replace_yes = 0;
1805 break;
1806 case B_REPLACE_ALL:
1807 edit->replace_mode = 1;
1808 break;
1809 case B_CANCEL:
1810 replace_yes = 0;
1811 edit->replace_mode = -1;
1812 break;
1814 g_free (disp1);
1815 g_free (disp2);
1817 if (replace_yes)
1818 { /* delete then insert new */
1819 GString *repl_str, *tmp_str;
1820 tmp_str = g_string_new (input2);
1822 repl_str = mc_search_prepare_replace_str (edit->search, tmp_str);
1823 g_string_free (tmp_str, TRUE);
1824 if (edit->search->error != MC_SEARCH_E_OK)
1826 edit_error_dialog (_("Replace"), edit->search->error_str);
1827 break;
1830 while (i--)
1831 edit_delete (edit, 1);
1833 while (++i < repl_str->len)
1834 edit_insert (edit, repl_str->str[i]);
1836 g_string_free (repl_str, TRUE);
1837 edit->found_len = i;
1839 /* so that we don't find the same string again */
1840 if (edit_search_options.backwards)
1842 last_search = edit->search_start;
1843 edit->search_start--;
1845 else
1847 edit->search_start += i;
1848 last_search = edit->last_byte;
1850 edit_scroll_screen_over_cursor (edit);
1852 else
1854 const char *msg = _(" Replace ");
1855 /* try and find from right here for next search */
1856 edit->search_start = edit->curs1;
1857 edit_update_curs_col (edit);
1859 edit->force |= REDRAW_PAGE;
1860 edit_render_keypress (edit);
1861 if (times_replaced)
1863 message (D_NORMAL, msg, _(" %ld replacements made. "), times_replaced);
1865 else
1866 query_dialog (msg, _(" Search string not found "), D_NORMAL, 1, _("&OK"));
1867 edit->replace_mode = -1;
1870 while (edit->replace_mode >= 0);
1872 edit->force = REDRAW_COMPLETELY;
1873 edit_scroll_screen_over_cursor (edit);
1874 cleanup:
1875 g_free (input1);
1876 g_free (input2);
1880 void
1881 edit_search_cmd (WEdit * edit, int again)
1883 char *search_string = NULL, *search_string_dup = NULL;
1885 gsize len = 0;
1887 if (!edit)
1888 return;
1890 if (edit->search != NULL)
1892 search_string = g_strndup (edit->search->original, edit->search->original_len);
1893 search_string_dup = search_string;
1895 else
1897 GList *history;
1898 history = history_get (MC_HISTORY_SHARED_SEARCH);
1899 if (history != NULL && history->data != NULL)
1901 search_string_dup = search_string = (char *) g_strdup (history->data);
1902 history = g_list_first (history);
1903 g_list_foreach (history, (GFunc) g_free, NULL);
1904 g_list_free (history);
1906 edit->search_start = edit->curs1;
1909 if (!again)
1911 #ifdef HAVE_CHARSET
1912 GString *tmp;
1913 if (search_string && *search_string)
1915 tmp = str_convert_to_display (search_string);
1917 g_free (search_string_dup);
1918 search_string_dup = NULL;
1920 if (tmp && tmp->len)
1921 search_string = search_string_dup = tmp->str;
1922 g_string_free (tmp, FALSE);
1924 #endif /* HAVE_CHARSET */
1925 editcmd_dialog_search_show (edit, &search_string);
1926 #ifdef HAVE_CHARSET
1927 if (search_string && *search_string)
1929 tmp = str_convert_to_input (search_string);
1930 if (tmp && tmp->len)
1931 search_string = tmp->str;
1933 g_string_free (tmp, FALSE);
1935 if (search_string_dup)
1936 g_free (search_string_dup);
1938 #endif /* HAVE_CHARSET */
1940 edit_push_action (edit, KEY_PRESS + edit->start_display);
1942 if (!search_string)
1944 edit->force |= REDRAW_COMPLETELY;
1945 edit_scroll_screen_over_cursor (edit);
1946 return;
1949 if (edit->search)
1951 mc_search_free (edit->search);
1952 edit->search = NULL;
1956 if (!edit->search)
1958 edit->search = mc_search_new (search_string, -1);
1959 if (edit->search == NULL)
1961 edit->search_start = edit->curs1;
1962 return;
1964 edit->search->search_type = edit_search_options.type;
1965 edit->search->is_all_charsets = edit_search_options.all_codepages;
1966 edit->search->is_case_sentitive = edit_search_options.case_sens;
1967 edit->search->whole_words = edit_search_options.whole_words;
1968 edit->search->search_fn = edit_search_cmd_callback;
1971 if (search_create_bookmark)
1973 edit_search_cmd_search_create_bookmark (edit);
1975 else
1977 if (edit->found_len && edit->search_start == edit->found_start + 1
1978 && edit_search_options.backwards)
1979 edit->search_start--;
1981 if (edit->found_len && edit->search_start == edit->found_start - 1
1982 && !edit_search_options.backwards)
1983 edit->search_start++;
1985 if (editcmd_find (edit, &len))
1987 edit->found_start = edit->search_start = edit->search->normal_offset;
1988 edit->found_len = len;
1989 edit->over_col = 0;
1990 edit_cursor_move (edit, edit->search_start - edit->curs1);
1991 edit_scroll_screen_over_cursor (edit);
1992 if (edit_search_options.backwards)
1993 edit->search_start--;
1994 else
1995 edit->search_start++;
1997 else
1999 edit->search_start = edit->curs1;
2000 if (edit->search->error_str)
2001 edit_error_dialog (_("Search"), edit->search->error_str);
2005 edit->force |= REDRAW_COMPLETELY;
2006 edit_scroll_screen_over_cursor (edit);
2011 * Check if it's OK to close the editor. If there are unsaved changes,
2012 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
2015 edit_ok_to_exit (WEdit * edit)
2017 if (!edit->modified)
2018 return 1;
2020 if (!edit_check_newline (edit))
2021 return 0;
2023 switch (edit_query_dialog3
2024 (_("Quit"), _(" File was modified, Save with exit? "),
2025 _("&Cancel quit"), _("&Yes"), _("&No")))
2027 case 1:
2028 edit_push_markers (edit);
2029 edit_set_markers (edit, 0, 0, 0, 0);
2030 if (!edit_save_cmd (edit))
2031 return 0;
2032 break;
2033 case 2:
2034 break;
2035 case 0:
2036 case -1:
2037 return 0;
2040 return 1;
2043 /* Return a null terminated length of text. Result must be g_free'd */
2044 static unsigned char *
2045 edit_get_block (WEdit * edit, long start, long finish, int *l)
2047 unsigned char *s, *r;
2048 r = s = g_malloc0 (finish - start + 1);
2049 if (column_highlighting)
2051 *l = 0;
2052 /* copy from buffer, excluding chars that are out of the column 'margins' */
2053 while (start < finish)
2055 int c;
2056 long x;
2057 x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
2058 c = edit_get_byte (edit, start);
2059 if ((x >= edit->column1 && x < edit->column2)
2060 || (x >= edit->column2 && x < edit->column1) || c == '\n')
2062 *s++ = c;
2063 (*l)++;
2065 start++;
2068 else
2070 *l = finish - start;
2071 while (start < finish)
2072 *s++ = edit_get_byte (edit, start++);
2074 *s = 0;
2075 return r;
2078 /* save block, returns 1 on success */
2080 edit_save_block (WEdit * edit, const char *filename, long start, long finish)
2082 int len, file;
2084 if ((file =
2085 mc_open (filename, O_CREAT | O_WRONLY | O_TRUNC,
2086 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY)) == -1)
2087 return 0;
2089 if (column_highlighting)
2091 int r;
2092 r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
2093 if (r > 0)
2095 unsigned char *block, *p;
2096 p = block = edit_get_block (edit, start, finish, &len);
2097 while (len)
2099 r = mc_write (file, p, len);
2100 if (r < 0)
2101 break;
2102 p += r;
2103 len -= r;
2105 g_free (block);
2108 else
2110 unsigned char *buf;
2111 int i = start, end;
2112 len = finish - start;
2113 buf = g_malloc0 (TEMP_BUF_LEN);
2114 while (start != finish)
2116 end = min (finish, start + TEMP_BUF_LEN);
2117 for (; i < end; i++)
2118 buf[i - start] = edit_get_byte (edit, i);
2119 len -= mc_write (file, (char *) buf, end - start);
2120 start = end;
2122 g_free (buf);
2124 mc_close (file);
2125 if (len)
2126 return 0;
2127 return 1;
2130 /* copies a block to clipboard file */
2131 static int
2132 edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
2134 int ret;
2135 gchar *tmp;
2136 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2137 ret = edit_save_block (edit, tmp, start, finish);
2138 g_free (tmp);
2139 return ret;
2143 void
2144 edit_paste_from_history (WEdit * edit)
2146 (void) edit;
2147 edit_error_dialog (_(" Error "), _(" This function is not implemented. "));
2151 edit_copy_to_X_buf_cmd (WEdit * edit)
2153 long start_mark, end_mark;
2154 if (eval_marks (edit, &start_mark, &end_mark))
2155 return 0;
2156 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2158 edit_error_dialog (_(" Copy to clipboard "),
2159 get_sys_error (_(" Unable to save to file. ")));
2160 return 1;
2162 edit_mark_cmd (edit, 1);
2163 return 0;
2167 edit_cut_to_X_buf_cmd (WEdit * edit)
2169 long start_mark, end_mark;
2170 if (eval_marks (edit, &start_mark, &end_mark))
2171 return 0;
2172 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2174 edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
2175 return 1;
2177 edit_block_delete_cmd (edit);
2178 edit_mark_cmd (edit, 1);
2179 return 0;
2182 void
2183 edit_paste_from_X_buf_cmd (WEdit * edit)
2185 gchar *tmp;
2186 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2187 edit_insert_file (edit, tmp);
2188 g_free (tmp);
2193 * Ask user for the line and go to that line.
2194 * Negative numbers mean line from the end (i.e. -1 is the last line).
2196 void
2197 edit_goto_cmd (WEdit * edit)
2199 char *f;
2200 static long line = 0; /* line as typed, saved as default */
2201 long l;
2202 char *error;
2203 char s[32];
2205 g_snprintf (s, sizeof (s), "%ld", line);
2206 f = input_dialog (_(" Goto line "), _(" Enter line: "), MC_HISTORY_EDIT_GOTO_LINE,
2207 line ? s : "");
2208 if (!f)
2209 return;
2211 if (!*f)
2213 g_free (f);
2214 return;
2217 l = strtol (f, &error, 0);
2218 if (*error)
2220 g_free (f);
2221 return;
2224 line = l;
2225 if (l < 0)
2226 l = edit->total_lines + l + 2;
2227 edit_move_display (edit, l - edit->num_widget_lines / 2 - 1);
2228 edit_move_to_line (edit, l - 1);
2229 edit->force |= REDRAW_COMPLETELY;
2230 g_free (f);
2234 /* Return 1 on success */
2236 edit_save_block_cmd (WEdit * edit)
2238 long start_mark, end_mark;
2239 char *exp, *tmp;
2241 if (eval_marks (edit, &start_mark, &end_mark))
2242 return 1;
2244 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2245 exp =
2246 input_expand_dialog (_(" Save Block "), _(" Enter file name: "),
2247 MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
2248 g_free (tmp);
2249 edit_push_action (edit, KEY_PRESS + edit->start_display);
2250 if (exp)
2252 if (!*exp)
2254 g_free (exp);
2255 return 0;
2257 else
2259 if (edit_save_block (edit, exp, start_mark, end_mark))
2261 g_free (exp);
2262 edit->force |= REDRAW_COMPLETELY;
2263 return 1;
2265 else
2267 g_free (exp);
2268 edit_error_dialog (_(" Save Block "), get_sys_error (_(" Cannot save file. ")));
2272 edit->force |= REDRAW_COMPLETELY;
2273 return 0;
2277 /* returns 1 on success */
2279 edit_insert_file_cmd (WEdit * edit)
2281 gchar *tmp;
2282 char *exp;
2284 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2285 exp = input_expand_dialog (_(" Insert File "), _(" Enter file name: "),
2286 MC_HISTORY_EDIT_INSERT_FILE, tmp);
2287 g_free (tmp);
2288 edit_push_action (edit, KEY_PRESS + edit->start_display);
2289 if (exp)
2291 if (!*exp)
2293 g_free (exp);
2294 return 0;
2296 else
2298 if (edit_insert_file (edit, exp))
2300 g_free (exp);
2301 edit->force |= REDRAW_COMPLETELY;
2302 return 1;
2304 else
2306 g_free (exp);
2307 edit_error_dialog (_(" Insert File "), get_sys_error (_(" Cannot insert file. ")));
2311 edit->force |= REDRAW_COMPLETELY;
2312 return 0;
2315 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2317 edit_sort_cmd (WEdit * edit)
2319 static char *old = 0;
2320 char *exp, *tmp;
2321 long start_mark, end_mark;
2322 int e;
2324 if (eval_marks (edit, &start_mark, &end_mark))
2326 edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
2327 return 0;
2330 tmp = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE);
2331 edit_save_block (edit, tmp, start_mark, end_mark);
2332 g_free (tmp);
2334 exp = input_dialog (_(" Run Sort "),
2335 _(" Enter sort options (see manpage) separated by whitespace: "),
2336 MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
2338 if (!exp)
2339 return 1;
2340 g_free (old);
2341 old = exp;
2342 tmp = g_strconcat (" sort ", exp, " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE, " > ",
2343 home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2344 e = system (tmp);
2345 g_free (tmp);
2346 if (e)
2348 if (e == -1 || e == 127)
2350 edit_error_dialog (_(" Sort "), get_sys_error (_(" Cannot execute sort command ")));
2352 else
2354 char q[8];
2355 sprintf (q, "%d ", e);
2356 tmp = g_strconcat (_(" Sort returned non-zero: "), q, (char *) NULL);
2357 edit_error_dialog (_(" Sort "), tmp);
2358 g_free (tmp);
2360 return -1;
2363 edit->force |= REDRAW_COMPLETELY;
2365 if (edit_block_delete_cmd (edit))
2366 return 1;
2367 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2368 edit_insert_file (edit, tmp);
2369 g_free (tmp);
2370 return 0;
2374 * Ask user for a command, execute it and paste its output back to the
2375 * editor.
2378 edit_ext_cmd (WEdit * edit)
2380 char *exp, *tmp;
2381 int e;
2383 exp =
2384 input_dialog (_("Paste output of external command"),
2385 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
2387 if (!exp)
2388 return 1;
2390 tmp = g_strconcat (exp, " > ", home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2391 e = system (tmp);
2392 g_free (tmp);
2393 g_free (exp);
2395 if (e)
2397 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
2398 return -1;
2401 edit->force |= REDRAW_COMPLETELY;
2402 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2403 edit_insert_file (edit, tmp);
2404 g_free (tmp);
2405 return 0;
2408 /* if block is 1, a block must be highlighted and the shell command
2409 processes it. If block is 0 the shell command is a straight system
2410 command, that just produces some output which is to be inserted */
2411 void
2412 edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
2414 long start_mark, end_mark;
2415 char buf[BUFSIZ];
2416 FILE *script_home = NULL;
2417 FILE *block_file = NULL;
2418 gchar *o, *h, *b, *tmp;
2419 char *quoted_name = NULL;
2421 o = g_strconcat (mc_home, shell_cmd, (char *) NULL); /* original source script */
2422 h = g_strconcat (home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, (char *) NULL); /* home script */
2423 b = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE); /* block file */
2425 script_home = fopen (h, "r");
2426 if (script_home == NULL)
2428 FILE *script_src = NULL;
2430 script_home = fopen (h, "w");
2431 if (script_home == NULL)
2433 tmp = g_strconcat (_("Error creating script:"), h, (char *) NULL);
2434 edit_error_dialog ("", get_sys_error (tmp));
2435 g_free (tmp);
2436 goto edit_block_process_cmd__EXIT;
2439 script_src = fopen (o, "r");
2440 if (script_src == NULL)
2442 o = g_strconcat (mc_home_alt, shell_cmd, (char *) NULL);
2443 script_src = fopen (o, "r");
2444 if (script_src == NULL)
2446 fclose (script_home);
2447 unlink (h);
2448 tmp = g_strconcat (_("Error reading script:"), o, (char *) NULL);
2449 edit_error_dialog ("", get_sys_error (tmp));
2450 g_free (tmp);
2451 goto edit_block_process_cmd__EXIT;
2454 while (fgets (buf, sizeof (buf), script_src))
2455 fputs (buf, script_home);
2456 fclose (script_src);
2458 if (fclose (script_home))
2460 tmp = g_strconcat (_("Error closing script:"), h, (char *) NULL);
2461 edit_error_dialog ("", get_sys_error (tmp));
2462 g_free (tmp);
2463 goto edit_block_process_cmd__EXIT;
2465 chmod (h, 0700);
2466 tmp = g_strconcat (_("Script created:"), h, (char *) NULL);
2467 edit_error_dialog ("", get_sys_error (tmp));
2468 g_free (tmp);
2471 open_error_pipe ();
2473 if (block)
2474 { /* for marked block run indent formatter */
2475 if (eval_marks (edit, &start_mark, &end_mark))
2477 edit_error_dialog (_("Process block"),
2478 _(" You must first highlight a block of text. "));
2479 goto edit_block_process_cmd__EXIT;
2481 edit_save_block (edit, b, start_mark, end_mark);
2482 quoted_name = name_quote (edit->filename, 0);
2484 * Run script.
2485 * Initial space is to avoid polluting bash history.
2486 * Arguments:
2487 * $1 - name of the edited file (to check its extension etc).
2488 * $2 - file containing the current block.
2489 * $3 - file where error messages should be put
2490 * (for compatibility with old scripts).
2492 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ", quoted_name,
2493 " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE " /dev/null", (char *) NULL);
2494 system (tmp);
2495 g_free (tmp);
2497 else
2500 * No block selected, just execute the command for the file.
2501 * Arguments:
2502 * $1 - name of the edited file.
2504 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
2505 quoted_name, (char *) NULL);
2506 system (tmp);
2507 g_free (tmp);
2509 g_free (quoted_name);
2510 close_error_pipe (D_NORMAL, NULL);
2512 edit_refresh_cmd (edit);
2513 edit->force |= REDRAW_COMPLETELY;
2515 /* insert result block */
2516 if (block && !edit_block_delete_cmd (edit))
2518 edit_insert_file (edit, b);
2519 block_file = fopen (b, "w");
2520 if (block_file != NULL)
2521 fclose (block_file);
2524 edit_block_process_cmd__EXIT:
2525 g_free (b);
2526 g_free (h);
2527 g_free (o);
2530 /* prints at the cursor */
2531 /* returns the number of chars printed */
2533 edit_print_string (WEdit * e, const char *s)
2535 size_t i = 0;
2536 while (s[i] != '\0')
2537 edit_execute_cmd (e, CK_Insert_Char, (unsigned char) s[i++]);
2538 e->force |= REDRAW_COMPLETELY;
2539 edit_update_screen (e);
2540 return i;
2544 static void
2545 pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
2547 FILE *p = 0;
2548 char *s;
2550 to = name_quote (to, 0);
2551 subject = name_quote (subject, 0);
2552 cc = name_quote (cc, 0);
2553 s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
2554 g_free (to);
2555 g_free (subject);
2556 g_free (cc);
2558 if (s)
2560 p = popen (s, "w");
2561 g_free (s);
2564 if (p)
2566 long i;
2567 for (i = 0; i < edit->last_byte; i++)
2568 fputc (edit_get_byte (edit, i), p);
2569 pclose (p);
2573 #define MAIL_DLG_HEIGHT 12
2575 void
2576 edit_mail_dialog (WEdit * edit)
2578 char *tmail_to;
2579 char *tmail_subject;
2580 char *tmail_cc;
2582 static char *mail_cc_last = 0;
2583 static char *mail_subject_last = 0;
2584 static char *mail_to_last = 0;
2586 QuickWidget quick_widgets[] = {
2587 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
2588 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
2589 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
2590 /* 3 */ QUICK_LABEL (2, 50, 7, MAIL_DLG_HEIGHT, N_(" Copies to")),
2591 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
2592 &tmail_subject),
2593 /* 5 */ QUICK_LABEL (2, 50, 5, MAIL_DLG_HEIGHT, N_(" Subject")),
2594 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
2595 /* 7 */ QUICK_LABEL (2, 50, 3, MAIL_DLG_HEIGHT, N_(" To")),
2596 /* 8 */ QUICK_LABEL (2, 50, 2, MAIL_DLG_HEIGHT, N_(" mail -s <subject> -c <cc> <to>")),
2597 QUICK_END
2600 QuickDialog Quick_input = {
2601 50, MAIL_DLG_HEIGHT, -1, -1, N_(" Mail "),
2602 "[Input Line Keys]", quick_widgets, FALSE
2605 quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
2606 quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
2607 quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
2609 if (quick_dialog (&Quick_input) != B_CANCEL)
2611 g_free (mail_cc_last);
2612 g_free (mail_subject_last);
2613 g_free (mail_to_last);
2614 mail_cc_last = tmail_cc;
2615 mail_subject_last = tmail_subject;
2616 mail_to_last = tmail_to;
2617 pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
2622 /*******************/
2623 /* Word Completion */
2624 /*******************/
2626 static gboolean
2627 is_break_char (char c)
2629 return (isspace (c) || strchr ("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c));
2632 /* find first character of current word */
2633 static int
2634 edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
2636 int c, last;
2637 gsize i;
2639 /* return if at begin of file */
2640 if (edit->curs1 <= 0)
2641 return 0;
2643 c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
2644 /* return if not at end or in word */
2645 if (is_break_char (c))
2646 return 0;
2648 /* search start of word to be completed */
2649 for (i = 2;; i++)
2651 /* return if at begin of file */
2652 if ((gsize) edit->curs1 < i)
2653 return 0;
2655 last = c;
2656 c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
2658 if (is_break_char (c))
2660 /* return if word starts with digit */
2661 if (isdigit (last))
2662 return 0;
2664 *word_start = edit->curs1 - (i - 1); /* start found */
2665 *word_len = i - 1;
2666 break;
2669 /* success */
2670 return 1;
2673 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2675 /* collect the possible completions */
2676 static gsize
2677 edit_collect_completions (WEdit * edit, long start, gsize word_len,
2678 char *match_expr, struct selection *compl, gsize * num)
2680 gsize len = 0;
2681 gsize max_len = 0;
2682 gsize i;
2683 int skip;
2684 GString *temp;
2685 mc_search_t *srch;
2687 long last_byte;
2689 srch = mc_search_new (match_expr, -1);
2690 if (srch == NULL)
2691 return 0;
2693 if (mc_config_get_bool
2694 (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
2696 last_byte = edit->last_byte;
2698 else
2700 last_byte = start;
2703 srch->search_type = MC_SEARCH_T_REGEX;
2704 srch->is_case_sentitive = TRUE;
2705 srch->search_fn = edit_search_cmd_callback;
2707 /* collect max MAX_WORD_COMPLETIONS completions */
2708 start = -1;
2709 while (1)
2711 /* get next match */
2712 if (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len) == FALSE)
2713 break;
2714 start = srch->normal_offset;
2716 /* add matched completion if not yet added */
2717 temp = g_string_new ("");
2718 for (i = 0; i < len; i++)
2720 skip = edit_get_byte (edit, start + i);
2721 if (isspace (skip))
2722 continue;
2723 g_string_append_c (temp, skip);
2726 skip = 0;
2728 for (i = 0; i < (gsize) * num; i++)
2730 if (strncmp
2731 ((char *) &compl[i].text[word_len],
2732 (char *) &temp->str[word_len], max (len, compl[i].len) - (gsize) word_len) == 0)
2734 struct selection this = compl[i];
2735 for (++i; i < *num; i++)
2737 compl[i - 1] = compl[i];
2739 compl[*num - 1] = this;
2740 skip = 1;
2741 break; /* skip it, already added */
2744 if (skip)
2746 g_string_free (temp, TRUE);
2747 continue;
2749 if (*num == MAX_WORD_COMPLETIONS && MAX_WORD_COMPLETIONS)
2751 g_free (compl[0].text);
2752 for (i = 1; i < *num; i++)
2754 compl[i - 1] = compl[i];
2756 (*num)--;
2758 #ifdef HAVE_CHARSET
2760 GString *recoded;
2761 recoded = str_convert_to_display (temp->str);
2763 if (recoded && recoded->len)
2765 g_string_free (temp, TRUE);
2766 temp = recoded;
2768 else
2769 g_string_free (recoded, TRUE);
2771 #endif
2772 compl[*num].text = temp->str;
2773 compl[*num].len = temp->len;
2774 (*num)++;
2775 start += len;
2776 g_string_free (temp, FALSE);
2778 /* note the maximal length needed for the completion dialog */
2779 if (len > max_len)
2780 max_len = len;
2782 mc_search_free (srch);
2783 return max_len;
2787 * Complete current word using regular expression search
2788 * backwards beginning at the current cursor position.
2790 void
2791 edit_complete_word_cmd (WEdit * edit)
2793 gsize i, max_len, word_len = 0, num_compl = 0;
2794 long word_start = 0;
2795 unsigned char *bufpos;
2796 char *match_expr;
2797 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
2799 /* search start of word to be completed */
2800 if (!edit_find_word_start (edit, &word_start, &word_len))
2801 return;
2803 /* prepare match expression */
2804 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
2806 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2807 match_expr =
2808 g_strdup_printf
2809 ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
2810 (int) word_len, bufpos);
2812 /* collect the possible completions */
2813 /* start search from begin to end of file */
2814 max_len =
2815 edit_collect_completions (edit, word_start, word_len, match_expr,
2816 (struct selection *) &compl, &num_compl);
2818 if (num_compl > 0)
2820 /* insert completed word if there is only one match */
2821 if (num_compl == 1)
2823 for (i = word_len; i < compl[0].len; i++)
2824 edit_insert (edit, *(compl[0].text + i));
2826 /* more than one possible completion => ask the user */
2827 else
2829 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2830 /* !!! pressed again the selection dialog pops up, but that !!! */
2831 /* !!! seems to require a further internal state !!! */
2832 /*tty_beep (); */
2834 /* let the user select the preferred completion */
2835 editcmd_dialog_completion_show (edit, max_len, word_len,
2836 (struct selection *) &compl, num_compl);
2840 g_free (match_expr);
2841 /* release memory before return */
2842 for (i = 0; i < num_compl; i++)
2843 g_free (compl[i].text);
2846 void
2847 edit_select_codepage_cmd (WEdit * edit)
2849 #ifdef HAVE_CHARSET
2850 const char *cp_id = NULL;
2851 if (do_select_codepage ())
2853 cp_id = get_codepage_id (source_codepage >= 0 ? source_codepage : display_codepage);
2855 if (cp_id != NULL)
2857 GIConv conv;
2858 conv = str_crt_conv_from (cp_id);
2859 if (conv != INVALID_CONV)
2861 if (edit->converter != str_cnv_from_term)
2862 str_close_conv (edit->converter);
2863 edit->converter = conv;
2867 if (cp_id != NULL)
2868 edit->utf8 = str_isutf8 (cp_id);
2871 edit->force = REDRAW_COMPLETELY;
2872 edit_refresh_cmd (edit);
2873 #else
2874 (void) edit;
2875 #endif
2878 void
2879 edit_insert_literal_cmd (WEdit * edit)
2881 int char_for_insertion = editcmd_dialog_raw_key_query (_(" Insert Literal "),
2882 _(" Press any key: "), 0);
2883 edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
2886 void
2887 edit_execute_macro_cmd (WEdit * edit)
2889 int command =
2890 CK_Macro (editcmd_dialog_raw_key_query (_(" Execute Macro "), _(" Press macro hotkey: "),
2891 1));
2892 if (command == CK_Macro (0))
2893 command = CK_Insert_Char;
2895 edit_execute_key_command (edit, command, -1);
2898 void
2899 edit_begin_end_macro_cmd (WEdit * edit)
2901 /* edit is a pointer to the widget */
2902 if (edit)
2904 unsigned long command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
2905 edit_execute_key_command (edit, command, -1);
2910 edit_load_forward_cmd (WEdit * edit)
2912 if (edit->modified)
2914 if (edit_query_dialog2
2915 (_("Warning"),
2916 _(" Current text was modified without a file save. \n"
2917 " Continue discards these changes. "), _("C&ontinue"), _("&Cancel")))
2919 edit->force |= REDRAW_COMPLETELY;
2920 return 0;
2923 if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
2925 if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
2927 return 1;
2929 edit_stack_iterator++;
2930 if (edit_history_moveto[edit_stack_iterator].filename)
2932 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
2933 edit_history_moveto[edit_stack_iterator].line);
2934 return 0;
2936 else
2938 return 1;
2941 else
2943 return 1;
2948 edit_load_back_cmd (WEdit * edit)
2950 if (edit->modified)
2952 if (edit_query_dialog2
2953 (_("Warning"),
2954 _(" Current text was modified without a file save. \n"
2955 " Continue discards these changes. "), _("C&ontinue"), _("&Cancel")))
2957 edit->force |= REDRAW_COMPLETELY;
2958 return 0;
2961 if (edit_stack_iterator > 0)
2963 edit_stack_iterator--;
2964 if (edit_history_moveto[edit_stack_iterator].filename)
2966 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
2967 edit_history_moveto[edit_stack_iterator].line);
2968 return 0;
2970 else
2972 return 1;
2975 else
2977 return 1;
2981 void
2982 edit_get_match_keyword_cmd (WEdit * edit)
2984 gsize word_len = 0, max_len = 0;
2985 int num_def = 0;
2986 int i;
2987 long word_start = 0;
2988 unsigned char *bufpos;
2989 char *match_expr;
2990 char *path = NULL;
2991 char *ptr = NULL;
2992 char *tagfile = NULL;
2994 etags_hash_t def_hash[MAX_DEFINITIONS];
2996 for (i = 0; i < MAX_DEFINITIONS; i++)
2998 def_hash[i].filename = NULL;
3001 /* search start of word to be completed */
3002 if (!edit_find_word_start (edit, &word_start, &word_len))
3003 return;
3005 /* prepare match expression */
3006 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3007 match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
3009 ptr = g_get_current_dir ();
3010 path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
3011 g_free (ptr);
3013 /* Recursive search file 'TAGS' in parent dirs */
3016 ptr = g_path_get_dirname (path);
3017 g_free (path);
3018 path = ptr;
3019 g_free (tagfile);
3020 tagfile = g_build_filename (path, TAGS_NAME, (char *) NULL);
3021 if (exist_file (tagfile))
3022 break;
3024 while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
3026 if (tagfile)
3028 num_def =
3029 etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
3030 g_free (tagfile);
3032 g_free (path);
3034 max_len = MAX_WIDTH_DEF_DIALOG;
3035 word_len = 0;
3036 if (num_def > 0)
3038 editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
3039 (etags_hash_t *) & def_hash, num_def);
3041 g_free (match_expr);
3044 void
3045 edit_move_block_to_right (WEdit * edit)
3047 long start_mark, end_mark;
3048 long cur_bol, start_bol;
3050 if (eval_marks (edit, &start_mark, &end_mark))
3051 return;
3053 start_bol = edit_bol (edit, start_mark);
3054 cur_bol = edit_bol (edit, end_mark - 1);
3057 edit_cursor_move (edit, cur_bol - edit->curs1);
3058 if (option_fill_tabs_with_spaces)
3060 if (option_fake_half_tabs)
3062 insert_spaces_tab (edit, 1);
3064 else
3066 insert_spaces_tab (edit, 0);
3069 else
3071 edit_insert (edit, '\t');
3073 edit_cursor_move (edit, edit_bol (edit, cur_bol) - edit->curs1);
3074 if (cur_bol == 0)
3076 break;
3078 cur_bol = edit_bol (edit, cur_bol - 1);
3080 while (cur_bol >= start_bol);
3081 edit->force |= REDRAW_PAGE;
3084 void
3085 edit_move_block_to_left (WEdit * edit)
3087 long start_mark, end_mark;
3088 long cur_bol, start_bol;
3089 int i, del_tab_width;
3090 int next_char;
3092 if (eval_marks (edit, &start_mark, &end_mark))
3093 return;
3095 start_bol = edit_bol (edit, start_mark);
3096 cur_bol = edit_bol (edit, end_mark - 1);
3099 edit_cursor_move (edit, cur_bol - edit->curs1);
3100 if (option_fake_half_tabs)
3102 del_tab_width = HALF_TAB_SIZE;
3104 else
3106 del_tab_width = option_tab_spacing;
3108 next_char = edit_get_byte (edit, edit->curs1);
3109 if (next_char == '\t')
3111 edit_delete (edit, 1);
3113 else if (next_char == ' ')
3115 for (i = 1; i <= del_tab_width; i++)
3117 if (next_char == ' ')
3119 edit_delete (edit, 1);
3121 next_char = edit_get_byte (edit, edit->curs1);
3124 if (cur_bol == 0)
3126 break;
3128 cur_bol = edit_bol (edit, cur_bol - 1);
3130 while (cur_bol >= start_bol);
3131 edit->force |= REDRAW_PAGE;