Reimplemented search engine in editor.
[pantumic.git] / src / editor / editcmd.c
blob3f677129fc475c20d38be17ac5c8b838f49d354a
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"
58 #include "src/history.h"
59 #include "src/widget.h" /* listbox_new() */
60 #include "src/layout.h" /* clr_scr() */
61 #include "src/main.h" /* mc_home, midnight_shutdown */
62 #include "src/setup.h" /* option_tab_spacing */
63 #include "src/help.h" /* interactive_display() */
64 #include "src/wtools.h" /* message() */
65 #include "src/charsets.h"
66 #include "src/selcodepage.h"
67 #include "src/cmddef.h"
68 #include "src/clipboard.h" /* copy_file_to_ext_clip, paste_to_file_from_ext_clip */
70 #include "src/editor/edit-impl.h"
71 #include "src/editor/edit-widget.h"
72 #include "src/editor/editcmd_dialogs.h"
73 #include "src/editor/etags.h"
75 /* globals: */
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 int
87 edit_search_cmd_callback (const void *user_data, gsize char_offset)
89 return edit_get_byte ((WEdit *) user_data, (long) char_offset);
92 void
93 edit_help_cmd (WEdit * edit)
95 interactive_display (NULL, "[Internal File Editor]");
96 edit->force |= REDRAW_COMPLETELY;
99 void
100 edit_refresh_cmd (WEdit * edit)
102 #ifdef HAVE_SLANG
103 int color;
105 edit_get_syntax_color (edit, -1, &color);
106 tty_touch_screen ();
107 mc_refresh ();
108 #else
109 (void) edit;
111 clr_scr ();
112 repaint_screen ();
113 #endif /* !HAVE_SLANG */
114 tty_keypad (TRUE);
117 /* If 0 (quick save) then a) create/truncate <filename> file,
118 b) save to <filename>;
119 if 1 (safe save) then a) save to <tempnam>,
120 b) rename <tempnam> to <filename>;
121 if 2 (do backups) then a) save to <tempnam>,
122 b) rename <filename> to <filename.backup_ext>,
123 c) rename <tempnam> to <filename>. */
125 /* returns 0 on error, -1 on abort */
126 static int
127 edit_save_file (WEdit * edit, const char *filename)
129 char *p;
130 gchar *tmp;
131 long filelen = 0;
132 char *savename = 0;
133 gchar *real_filename;
134 int this_save_mode, fd = -1;
136 if (!filename)
137 return 0;
138 if (!*filename)
139 return 0;
141 if (*filename != PATH_SEP && edit->dir)
143 real_filename = concat_dir_and_file (edit->dir, filename);
145 else
147 real_filename = g_strdup (filename);
150 this_save_mode = option_save_mode;
151 if (this_save_mode != EDIT_QUICK_SAVE)
153 if (!vfs_file_is_local (real_filename) ||
154 (fd = mc_open (real_filename, O_RDONLY | O_BINARY)) == -1)
157 * The file does not exists yet, so no safe save or
158 * backup are necessary.
160 this_save_mode = EDIT_QUICK_SAVE;
162 if (fd != -1)
163 mc_close (fd);
166 if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
168 int rv;
169 struct stat sb;
171 rv = mc_stat (real_filename, &sb);
172 if (rv == 0 && sb.st_nlink > 1)
174 rv = edit_query_dialog3 (_("Warning"),
175 _("File has hard-links. Detach before saving?"),
176 _("&Yes"), _("&No"), _("&Cancel"));
177 switch (rv)
179 case 0:
180 this_save_mode = EDIT_SAFE_SAVE;
181 /* fallthrough */
182 case 1:
183 edit->skip_detach_prompt = 1;
184 break;
185 default:
186 g_free (real_filename);
187 return -1;
191 /* Prevent overwriting changes from other editor sessions. */
192 if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
195 /* The default action is "Cancel". */
196 query_set_sel (1);
198 rv = edit_query_dialog2 (_("Warning"),
199 _("The file has been modified in the meantime. Save anyway?"),
200 _("&Yes"), _("&Cancel"));
201 if (rv != 0)
203 g_free (real_filename);
204 return -1;
209 if (this_save_mode != EDIT_QUICK_SAVE)
211 char *savedir, *saveprefix;
212 const char *slashpos;
213 slashpos = strrchr (real_filename, PATH_SEP);
214 if (slashpos)
216 savedir = g_strdup (real_filename);
217 savedir[slashpos - real_filename + 1] = '\0';
219 else
220 savedir = g_strdup (".");
221 saveprefix = concat_dir_and_file (savedir, "cooledit");
222 g_free (savedir);
223 fd = mc_mkstemps (&savename, saveprefix, NULL);
224 g_free (saveprefix);
225 if (!savename)
227 g_free (real_filename);
228 return 0;
230 /* FIXME:
231 * Close for now because mc_mkstemps use pure open system call
232 * to create temporary file and it needs to be reopened by
233 * VFS-aware mc_open().
235 close (fd);
237 else
238 savename = g_strdup (real_filename);
240 int ret;
241 ret = mc_chown (savename, edit->stat1.st_uid, edit->stat1.st_gid);
242 ret = mc_chmod (savename, edit->stat1.st_mode);
245 fd = mc_open (savename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode);
246 if (fd == -1)
247 goto error_save;
249 /* pipe save */
250 p = edit_get_write_filter (savename, real_filename);
251 if (p != NULL)
253 FILE *file;
255 mc_close (fd);
256 file = (FILE *) popen (p, "w");
258 if (file)
260 filelen = edit_write_stream (edit, file);
261 #if 1
262 pclose (file);
263 #else
264 if (pclose (file) != 0)
266 tmp = g_strdup_printf (_("Error writing to pipe: %s"), p);
267 edit_error_dialog (_("Error"), tmp);
268 g_free (tmp);
269 g_free (p);
270 goto error_save;
272 #endif
274 else
276 tmp = g_strdup_printf (_("Cannot open pipe for writing: %s"), p);
277 edit_error_dialog (_("Error"), get_sys_error (tmp));
278 g_free (p);
279 g_free (tmp);
280 goto error_save;
282 g_free (p);
284 else if (edit->lb == LB_ASIS)
285 { /* do not change line breaks */
286 long buf;
287 buf = 0;
288 filelen = edit->last_byte;
289 while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1)
291 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
293 mc_close (fd);
294 goto error_save;
296 buf++;
298 if (mc_write
299 (fd, (char *) edit->buffers1[buf],
300 edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE))
302 filelen = -1;
304 else if (edit->curs2)
306 edit->curs2--;
307 buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
308 if (mc_write
309 (fd,
310 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
311 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
312 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE))
314 filelen = -1;
316 else
318 while (--buf >= 0)
320 if (mc_write (fd, (char *) edit->buffers2[buf], EDIT_BUF_SIZE) != EDIT_BUF_SIZE)
322 filelen = -1;
323 break;
327 edit->curs2++;
329 if (mc_close (fd))
330 goto error_save;
332 /* Update the file information, especially the mtime. */
333 if (mc_stat (savename, &edit->stat1) == -1)
334 goto error_save;
336 else
337 { /* change line breaks */
338 FILE *file;
340 mc_close (fd);
342 file = (FILE *) fopen (savename, "w");
344 if (file)
346 filelen = edit_write_stream (edit, file);
347 fclose (file);
349 else
351 char *msg;
353 msg = g_strdup_printf (_("Cannot open file for writing: %s"), savename);
354 edit_error_dialog (_("Error"), msg);
355 g_free (msg);
356 goto error_save;
360 if (filelen != edit->last_byte)
361 goto error_save;
363 if (this_save_mode == EDIT_DO_BACKUP)
365 assert (option_backup_ext != NULL);
366 tmp = g_strconcat (real_filename, option_backup_ext, (char *) NULL);
367 if (mc_rename (real_filename, tmp) == -1)
369 g_free (tmp);
370 goto error_save;
374 if (this_save_mode != EDIT_QUICK_SAVE)
375 if (mc_rename (savename, real_filename) == -1)
376 goto error_save;
377 g_free (savename);
378 g_free (real_filename);
379 return 1;
380 error_save:
381 /* FIXME: Is this safe ?
382 * if (this_save_mode != EDIT_QUICK_SAVE)
383 * mc_unlink (savename);
385 g_free (real_filename);
386 g_free (savename);
387 return 0;
390 void
391 menu_save_mode_cmd (void)
393 /* diaog sizes */
394 const int DLG_X = 38;
395 const int DLG_Y = 13;
397 char *str_result;
399 const char *str[] = {
400 N_("&Quick save"),
401 N_("&Safe save"),
402 N_("&Do backups with following extension:")
405 QuickWidget widgets[] = {
406 /* 0 */
407 QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
408 /* 1 */
409 QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
410 /* 2 */
411 QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
412 /* 3 */
413 QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
414 /* 4 */
415 QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
416 QUICK_END
419 QuickDialog dialog = {
420 DLG_X, DLG_Y, -1, -1, N_("Edit Save Mode"),
421 "[Edit Save Mode]", widgets, NULL, FALSE
424 size_t i;
425 size_t maxlen = 0;
426 size_t w0, w1, b_len, w3;
428 assert (option_backup_ext != NULL);
430 /* OK/Cancel buttons */
431 w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
432 w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5; /* default button */
433 b_len = w0 + w1 + 3;
435 maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
437 w3 = 0;
438 for (i = 0; i < 3; i++)
440 #ifdef ENABLE_NLS
441 str[i] = _(str[i]);
442 #endif
443 w3 = max (w3, (size_t) str_term_width1 (str[i]));
446 maxlen = max (maxlen, w3 + 4);
448 dialog.xlen = min ((size_t) COLS, maxlen + 8);
450 widgets[3].u.input.len = w3;
451 widgets[1].relative_x = (dialog.xlen - b_len) / 2;
452 widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
454 for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
455 widgets[i].x_divisions = dialog.xlen;
457 if (quick_dialog (&dialog) != B_CANCEL)
459 g_free (option_backup_ext);
460 option_backup_ext = str_result;
464 void
465 edit_set_filename (WEdit * edit, const char *name)
467 g_free (edit->filename);
469 if (name == NULL)
470 name = "";
472 edit->filename = tilde_expand (name);
473 if (edit->dir == NULL && !g_path_is_absolute (name))
474 edit->dir = g_strdup (vfs_get_current_dir ());
477 static gboolean
478 edit_check_newline (WEdit * edit)
480 return !(option_check_nl_at_eof && edit->last_byte > 0
481 && edit_get_byte (edit, edit->last_byte - 1) != '\n'
482 && edit_query_dialog2 (_("Warning"),
483 _("The file you are saving is not finished with a newline"),
484 _("C&ontinue"), _("&Cancel")));
487 static char *
488 edit_get_save_file_as (WEdit * edit)
490 #define DLG_WIDTH 64
491 #define DLG_HEIGHT 14
493 static LineBreaks cur_lb = LB_ASIS;
495 char *filename = edit->filename;
497 const char *lb_names[LB_NAMES] = {
498 N_("&Do not change"),
499 N_("&Unix format (LF)"),
500 N_("&Windows/DOS format (CR LF)"),
501 N_("&Macintosh format (CR)")
504 QuickWidget quick_widgets[] = {
505 QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
506 QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
507 QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
508 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
509 QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
510 "save-as", &filename),
511 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_("Enter file name:")),
512 QUICK_END
515 QuickDialog Quick_options = {
516 DLG_WIDTH, DLG_HEIGHT, -1, -1,
517 N_("Save As"), "[Save File As]",
518 quick_widgets, NULL, FALSE
521 if (quick_dialog (&Quick_options) != B_CANCEL)
523 char *fname;
525 edit->lb = cur_lb;
526 fname = tilde_expand (filename);
527 g_free (filename);
528 return fname;
531 return NULL;
533 #undef DLG_WIDTH
534 #undef DLG_HEIGHT
537 /* Here we want to warn the users of overwriting an existing file,
538 but only if they have made a change to the filename */
539 /* returns 1 on success */
541 edit_save_as_cmd (WEdit * edit)
543 /* This heads the 'Save As' dialog box */
544 char *exp;
545 int save_lock = 0;
546 int different_filename = 0;
548 if (!edit_check_newline (edit))
549 return 0;
551 exp = edit_get_save_file_as (edit);
552 edit_push_action (edit, KEY_PRESS + edit->start_display);
554 if (exp)
556 if (!*exp)
558 g_free (exp);
559 edit->force |= REDRAW_COMPLETELY;
560 return 0;
562 else
564 int rv;
565 if (strcmp (edit->filename, exp))
567 int file;
568 different_filename = 1;
569 file = mc_open (exp, O_RDONLY | O_BINARY);
570 if (file != -1)
572 /* the file exists */
573 mc_close (file);
574 /* Overwrite the current file or cancel the operation */
575 if (edit_query_dialog2
576 (_("Warning"),
577 _("A file already exists with this name"),
578 _("&Overwrite"), _("&Cancel")))
580 edit->force |= REDRAW_COMPLETELY;
581 g_free (exp);
582 return 0;
585 else
587 edit->stat1.st_mode |= S_IWUSR;
589 save_lock = lock_file (exp);
591 else
593 /* filenames equal, check if already locked */
594 if (!edit->locked && !edit->delete_file)
595 save_lock = lock_file (exp);
598 if (different_filename)
601 * Allow user to write into saved (under another name) file
602 * even if original file had r/o user permissions.
604 edit->stat1.st_mode |= S_IWRITE;
607 rv = edit_save_file (edit, exp);
608 switch (rv)
610 case 1:
611 /* Succesful, so unlock both files */
612 if (different_filename)
614 if (save_lock)
615 unlock_file (exp);
616 if (edit->locked)
617 edit->locked = edit_unlock_file (edit);
619 else
621 if (edit->locked || save_lock)
622 edit->locked = edit_unlock_file (edit);
625 edit_set_filename (edit, exp);
626 if (edit->lb != LB_ASIS)
627 edit_reload (edit, exp);
628 g_free (exp);
629 edit->modified = 0;
630 edit->delete_file = 0;
631 if (different_filename)
632 edit_load_syntax (edit, NULL, edit->syntax_type);
633 edit->force |= REDRAW_COMPLETELY;
634 return 1;
635 default:
636 edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
637 /* fallthrough */
638 case -1:
639 /* Failed, so maintain modify (not save) lock */
640 if (save_lock)
641 unlock_file (exp);
642 g_free (exp);
643 edit->force |= REDRAW_COMPLETELY;
644 return 0;
648 edit->force |= REDRAW_COMPLETELY;
649 return 0;
652 /* {{{ Macro stuff starts here */
654 /* creates a macro file if it doesn't exist */
655 static FILE *
656 edit_open_macro_file (const char *r)
658 gchar *filename;
659 FILE *fd;
660 int file;
661 filename = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
662 file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
663 if (file == -1)
665 g_free (filename);
666 return 0;
668 close (file);
669 fd = fopen (filename, r);
670 g_free (filename);
671 return fd;
674 #define MAX_MACROS 1024
675 static int saved_macro[MAX_MACROS + 1];
676 static int saved_macros_loaded = 0;
679 This is just to stop the macro file be loaded over and over for keys
680 that aren't defined to anything. On slow systems this could be annoying.
682 static int
683 macro_exists (int k)
685 int i;
686 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
687 if (saved_macro[i] == k)
688 return i;
689 return -1;
692 /* returns 1 on error */
693 static int
694 edit_delete_macro (WEdit * edit, int k)
696 gchar *tmp, *tmp2;
697 struct macro macro[MAX_MACRO_LENGTH];
698 FILE *f, *g;
699 int s, i, n, j = 0;
701 (void) edit;
703 if (saved_macros_loaded)
705 j = macro_exists (k);
706 if (j < 0)
707 return 0;
709 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
710 g = fopen (tmp, "w");
711 g_free (tmp);
712 if (!g)
714 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open temp file")));
715 return 1;
717 f = edit_open_macro_file ("r");
718 if (!f)
720 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot open macro file")));
721 fclose (g);
722 return 1;
724 for (;;)
726 n = fscanf (f, ("key '%d 0': "), &s);
727 if (!n || n == EOF)
728 break;
729 n = 0;
730 while (fscanf (f, "%lu %d, ", &macro[n].command, &macro[n].ch))
731 n++;
733 int ret;
734 ret = fscanf (f, ";\n");
736 if (s != k)
738 fprintf (g, ("key '%d 0': "), s);
739 for (i = 0; i < n; i++)
740 fprintf (g, "%lu %d, ", macro[i].command, macro[i].ch);
741 fprintf (g, ";\n");
744 fclose (f);
745 fclose (g);
746 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
747 tmp2 = concat_dir_and_file (home_dir, EDIT_MACRO_FILE);
748 if (rename (tmp, tmp2) == -1)
750 edit_error_dialog (_("Delete macro"), get_sys_error (_("Cannot overwrite macro file")));
751 g_free (tmp);
752 g_free (tmp2);
753 return 1;
755 g_free (tmp);
756 g_free (tmp2);
758 if (saved_macros_loaded)
759 memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
760 return 0;
763 /* returns 0 on error */
765 edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
767 FILE *f;
768 int s, i;
770 edit_push_action (edit, KEY_PRESS + edit->start_display);
771 s = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
772 edit->force |= REDRAW_COMPLETELY;
773 if (s)
775 if (edit_delete_macro (edit, s))
776 return 0;
777 f = edit_open_macro_file ("a+");
778 if (f)
780 fprintf (f, ("key '%d 0': "), s);
781 for (i = 0; i < n; i++)
782 fprintf (f, "%lu %d, ", macro[i].command, macro[i].ch);
783 fprintf (f, ";\n");
784 fclose (f);
785 if (saved_macros_loaded)
787 for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
788 saved_macro[i] = s;
790 return 1;
792 else
793 edit_error_dialog (_("Save macro"), get_sys_error (_("Cannot open macro file")));
795 return 0;
798 void
799 edit_delete_macro_cmd (WEdit * edit)
801 int command;
803 command = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
805 if (command != 0)
806 edit_delete_macro (edit, command);
809 /* return 0 on error */
811 edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
813 FILE *f;
814 int s, i = 0, found = 0;
816 (void) edit;
818 if (saved_macros_loaded)
819 if (macro_exists (k) < 0)
820 return 0;
822 f = edit_open_macro_file ("r");
823 if (f != NULL)
825 struct macro dummy;
828 int u;
829 u = fscanf (f, ("key '%d 0': "), &s);
830 if (!u || u == EOF)
831 break;
832 if (!saved_macros_loaded)
833 saved_macro[i++] = s;
834 if (!found)
836 *n = 0;
837 while (*n < MAX_MACRO_LENGTH
838 && 2 == fscanf (f, "%lu %d, ", &macro[*n].command, &macro[*n].ch))
839 (*n)++;
841 else
843 while (2 == fscanf (f, "%lu %d, ", &dummy.command, &dummy.ch));
846 int ret;
847 ret = fscanf (f, ";\n");
849 if (s == k)
850 found = 1;
852 while (!found || !saved_macros_loaded);
853 if (!saved_macros_loaded)
855 saved_macro[i] = 0;
856 saved_macros_loaded = 1;
858 fclose (f);
859 return found;
861 else
862 edit_error_dialog (_("Load macro"), get_sys_error (_("Cannot open macro file")));
863 return 0;
866 /* }}} Macro stuff starts here */
868 /* returns 1 on success */
870 edit_save_confirm_cmd (WEdit * edit)
872 gchar *f = NULL;
874 if (!edit_check_newline (edit))
875 return 0;
877 if (edit_confirm_save)
879 f = g_strdup_printf (_("Confirm save file: \"%s\""), edit->filename);
880 if (edit_query_dialog2 (_("Save file"), f, _("&Save"), _("&Cancel")))
882 g_free (f);
883 return 0;
885 g_free (f);
887 return edit_save_cmd (edit);
891 /* returns 1 on success */
892 static int
893 edit_save_cmd (WEdit * edit)
895 int res, save_lock = 0;
897 if (!edit->locked && !edit->delete_file)
898 save_lock = edit_lock_file (edit);
899 res = edit_save_file (edit, edit->filename);
901 /* Maintain modify (not save) lock on failure */
902 if ((res > 0 && edit->locked) || save_lock)
903 edit->locked = edit_unlock_file (edit);
905 /* On failure try 'save as', it does locking on its own */
906 if (!res)
907 return edit_save_as_cmd (edit);
908 edit->force |= REDRAW_COMPLETELY;
909 if (res > 0)
911 edit->delete_file = 0;
912 edit->modified = 0;
915 return 1;
919 /* returns 1 on success */
921 edit_new_cmd (WEdit * edit)
923 if (edit->modified)
925 if (edit_query_dialog2
926 (_("Warning"),
928 ("Current text was modified without a file save.\nContinue discards these changes"),
929 _("C&ontinue"), _("&Cancel")))
931 edit->force |= REDRAW_COMPLETELY;
932 return 0;
935 edit->force |= REDRAW_COMPLETELY;
937 return edit_renew (edit); /* if this gives an error, something has really screwed up */
940 /* returns 1 on error */
941 static int
942 edit_load_file_from_filename (WEdit * edit, char *exp)
944 int prev_locked = edit->locked;
945 char *prev_filename = g_strdup (edit->filename);
947 if (!edit_reload (edit, exp))
949 g_free (prev_filename);
950 return 1;
953 if (prev_locked)
955 char *fullpath;
957 fullpath = g_build_filename (edit->dir, prev_filename, (char *) NULL);
958 unlock_file (fullpath);
959 g_free (fullpath);
961 g_free (prev_filename);
962 return 0;
965 static void
966 edit_load_syntax_file (WEdit * edit)
968 char *extdir;
969 int dir = 0;
971 if (geteuid () == 0)
973 dir = query_dialog (_("Syntax file edit"),
974 _("Which syntax file you want to edit?"), D_NORMAL, 2,
975 _("&User"), _("&System Wide"));
978 extdir = g_build_filename (mc_home, "syntax", "Syntax", (char *) NULL);
979 if (!exist_file (extdir))
981 g_free (extdir);
982 extdir = g_build_filename (mc_home_alt, "syntax", "Syntax", (char *) NULL);
985 if (dir == 0)
987 char *buffer;
989 buffer = concat_dir_and_file (home_dir, EDIT_SYNTAX_FILE);
990 check_for_default (extdir, buffer);
991 edit_load_file_from_filename (edit, buffer);
992 g_free (buffer);
994 else if (dir == 1)
995 edit_load_file_from_filename (edit, extdir);
997 g_free (extdir);
1000 static void
1001 edit_load_menu_file (WEdit * edit)
1003 char *buffer;
1004 char *menufile;
1005 int dir = 0;
1007 dir = query_dialog (_("Menu edit"),
1008 _("Which menu file do you want to edit?"), D_NORMAL,
1009 geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
1011 menufile = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
1013 if (!exist_file (menufile))
1015 g_free (menufile);
1016 menufile = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
1019 switch (dir)
1021 case 0:
1022 buffer = g_strdup (EDIT_LOCAL_MENU);
1023 check_for_default (menufile, buffer);
1024 chmod (buffer, 0600);
1025 break;
1027 case 1:
1028 buffer = concat_dir_and_file (home_dir, EDIT_HOME_MENU);
1029 check_for_default (menufile, buffer);
1030 break;
1032 case 2:
1033 buffer = concat_dir_and_file (mc_home, EDIT_GLOBAL_MENU);
1034 if (!exist_file (buffer))
1036 g_free (buffer);
1037 buffer = concat_dir_and_file (mc_home_alt, EDIT_GLOBAL_MENU);
1039 break;
1041 default:
1042 g_free (menufile);
1043 return;
1046 edit_load_file_from_filename (edit, buffer);
1048 g_free (buffer);
1049 g_free (menufile);
1053 edit_load_cmd (WEdit * edit, edit_current_file_t what)
1055 char *exp;
1057 if (edit->modified
1058 && (edit_query_dialog2
1059 (_("Warning"),
1060 _("Current text was modified without a file save.\n"
1061 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")) == 1))
1063 edit->force |= REDRAW_COMPLETELY;
1064 return 0;
1067 switch (what)
1069 case EDIT_FILE_COMMON:
1070 exp = input_expand_dialog (_("Load"), _("Enter file name:"),
1071 MC_HISTORY_EDIT_LOAD, edit->filename);
1073 if (exp)
1075 if (*exp)
1076 edit_load_file_from_filename (edit, exp);
1077 g_free (exp);
1079 break;
1081 case EDIT_FILE_SYNTAX:
1082 edit_load_syntax_file (edit);
1083 break;
1085 case EDIT_FILE_MENU:
1086 edit_load_menu_file (edit);
1087 break;
1089 default:
1090 break;
1093 edit->force |= REDRAW_COMPLETELY;
1094 return 0;
1098 if mark2 is -1 then marking is from mark1 to the cursor.
1099 Otherwise its between the markers. This handles this.
1100 Returns 1 if no text is marked.
1103 eval_marks (WEdit * edit, long *start_mark, long *end_mark)
1105 if (edit->mark1 != edit->mark2)
1107 long start_bol, start_eol;
1108 long end_bol, end_eol;
1109 long col1, col2;
1110 long diff1, diff2;
1111 if (edit->mark2 >= 0)
1113 *start_mark = min (edit->mark1, edit->mark2);
1114 *end_mark = max (edit->mark1, edit->mark2);
1116 else
1118 *start_mark = min (edit->mark1, edit->curs1);
1119 *end_mark = max (edit->mark1, edit->curs1);
1120 edit->column2 = edit->curs_col + edit->over_col;
1122 if (edit->column_highlight
1123 && (((edit->mark1 > edit->curs1) && (edit->column1 < edit->column2))
1124 || ((edit->mark1 < edit->curs1) && (edit->column1 > edit->column2))))
1127 start_bol = edit_bol (edit, *start_mark);
1128 start_eol = edit_eol (edit, start_bol - 1) + 1;
1129 end_bol = edit_bol (edit, *end_mark);
1130 end_eol = edit_eol (edit, *end_mark);
1131 col1 = min (edit->column1, edit->column2);
1132 col2 = max (edit->column1, edit->column2);
1134 diff1 =
1135 edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
1136 col1, 0);
1137 diff2 =
1138 edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
1139 col1, 0);
1141 *start_mark -= diff1;
1142 *end_mark += diff2;
1143 *start_mark = max (*start_mark, start_eol);
1144 *end_mark = min (*end_mark, end_eol);
1146 return 0;
1148 else
1150 *start_mark = *end_mark = 0;
1151 edit->column2 = edit->column1 = 0;
1152 return 1;
1156 #define space_width 1
1158 void
1159 edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
1161 long cursor;
1162 int i, col;
1163 cursor = edit->curs1;
1164 col = edit_get_col (edit);
1165 for (i = 0; i < size; i++)
1167 if (data[i] == '\n')
1168 { /* fill in and move to next line */
1169 int l;
1170 long p;
1171 if (edit_get_byte (edit, edit->curs1) != '\n')
1173 l = width - (edit_get_col (edit) - col);
1174 while (l > 0)
1176 edit_insert (edit, ' ');
1177 l -= space_width;
1180 for (p = edit->curs1;; p++)
1182 if (p == edit->last_byte)
1184 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1185 edit_insert_ahead (edit, '\n');
1186 p++;
1187 break;
1189 if (edit_get_byte (edit, p) == '\n')
1191 p++;
1192 break;
1195 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1196 l = col - edit_get_col (edit);
1197 while (l >= space_width)
1199 edit_insert (edit, ' ');
1200 l -= space_width;
1202 continue;
1204 edit_insert (edit, data[i]);
1206 edit_cursor_move (edit, cursor - edit->curs1);
1209 #define TEMP_BUF_LEN 1024
1212 edit_insert_column_of_text_from_file (WEdit * edit, int file)
1214 long cursor;
1215 int i, col;
1216 int blocklen = -1, width;
1217 unsigned char *data;
1218 cursor = edit->curs1;
1219 col = edit_get_col (edit);
1220 data = g_malloc0 (TEMP_BUF_LEN);
1221 while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
1223 for (width = 0; width < blocklen; width++)
1225 if (data[width] == '\n')
1226 break;
1228 for (i = 0; i < blocklen; i++)
1230 if (data[i] == '\n')
1231 { /* fill in and move to next line */
1232 int l;
1233 long p;
1234 if (edit_get_byte (edit, edit->curs1) != '\n')
1236 l = width - (edit_get_col (edit) - col);
1237 while (l > 0)
1239 edit_insert (edit, ' ');
1240 l -= space_width;
1243 for (p = edit->curs1;; p++)
1245 if (p == edit->last_byte)
1247 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1248 edit_insert_ahead (edit, '\n');
1249 p++;
1250 break;
1252 if (edit_get_byte (edit, p) == '\n')
1254 p++;
1255 break;
1258 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1259 l = col - edit_get_col (edit);
1260 while (l >= space_width)
1262 edit_insert (edit, ' ');
1263 l -= space_width;
1265 continue;
1267 edit_insert (edit, data[i]);
1270 edit_cursor_move (edit, cursor - edit->curs1);
1271 g_free (data);
1272 edit->force |= REDRAW_PAGE;
1273 return blocklen;
1276 void
1277 edit_block_copy_cmd (WEdit * edit)
1279 long start_mark, end_mark, current = edit->curs1;
1280 int size;
1281 unsigned char *copy_buf;
1283 edit_update_curs_col (edit);
1284 if (eval_marks (edit, &start_mark, &end_mark))
1285 return;
1287 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1289 /* all that gets pushed are deletes hence little space is used on the stack */
1291 edit_push_markers (edit);
1293 if (edit->column_highlight)
1295 edit_insert_column_of_text (edit, copy_buf, size, abs (edit->column2 - edit->column1));
1297 else
1299 while (size--)
1300 edit_insert_ahead (edit, copy_buf[size]);
1303 g_free (copy_buf);
1304 edit_scroll_screen_over_cursor (edit);
1306 if (edit->column_highlight)
1308 edit_set_markers (edit, 0, 0, 0, 0);
1309 edit_push_action (edit, COLUMN_ON);
1310 edit->column_highlight = 0;
1312 else if (start_mark < current && end_mark > current)
1313 edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
1315 edit->force |= REDRAW_PAGE;
1319 void
1320 edit_block_move_cmd (WEdit * edit)
1322 long count;
1323 long current;
1324 unsigned char *copy_buf;
1325 long start_mark, end_mark;
1326 int deleted = 0;
1327 int x = 0;
1329 if (eval_marks (edit, &start_mark, &end_mark))
1330 return;
1331 if (edit->column_highlight)
1333 edit_update_curs_col (edit);
1334 x = edit->curs_col;
1335 if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1336 if ((x > edit->column1 && x < edit->column2)
1337 || (x > edit->column2 && x < edit->column1))
1338 return;
1340 else if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
1341 return;
1343 if ((end_mark - start_mark) > option_max_undo / 2)
1344 if (edit_query_dialog2
1345 (_("Warning"),
1347 ("Block is large, you may not be able to undo this action"),
1348 _("C&ontinue"), _("&Cancel")))
1349 return;
1351 edit_push_markers (edit);
1352 current = edit->curs1;
1353 if (edit->column_highlight)
1355 long line;
1356 int size, c1, c2;
1357 line = edit->curs_line;
1358 if (edit->mark2 < 0)
1359 edit_mark_cmd (edit, 0);
1360 c1 = min (edit->column1, edit->column2);
1361 c2 = max (edit->column1, edit->column2);
1362 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
1363 if (x < c2)
1365 edit_block_delete_cmd (edit);
1366 deleted = 1;
1368 edit_move_to_line (edit, line);
1369 edit_cursor_move (edit,
1370 edit_move_forward3 (edit,
1371 edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
1372 edit_insert_column_of_text (edit, copy_buf, size, c2 - c1);
1373 if (!deleted)
1375 line = edit->curs_line;
1376 edit_update_curs_col (edit);
1377 x = edit->curs_col;
1378 edit_block_delete_cmd (edit);
1379 edit_move_to_line (edit, line);
1380 edit_cursor_move (edit,
1381 edit_move_forward3 (edit,
1382 edit_bol (edit,
1383 edit->curs1), x, 0) - edit->curs1);
1385 edit_set_markers (edit, 0, 0, 0, 0);
1386 edit_push_action (edit, COLUMN_ON);
1387 edit->column_highlight = 0;
1389 else
1391 copy_buf = g_malloc0 (end_mark - start_mark);
1392 edit_cursor_move (edit, start_mark - edit->curs1);
1393 edit_scroll_screen_over_cursor (edit);
1394 count = start_mark;
1395 while (count < end_mark)
1397 copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
1398 count++;
1400 edit_scroll_screen_over_cursor (edit);
1401 edit_cursor_move (edit,
1402 current - edit->curs1 -
1403 (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
1404 edit_scroll_screen_over_cursor (edit);
1405 while (count-- > start_mark)
1406 edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
1407 edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
1409 edit_scroll_screen_over_cursor (edit);
1410 g_free (copy_buf);
1411 edit->force |= REDRAW_PAGE;
1414 static void
1415 edit_delete_column_of_text (WEdit * edit)
1417 long p, q, r, m1, m2;
1418 long b, c, d, n;
1420 eval_marks (edit, &m1, &m2);
1421 n = edit_move_forward (edit, m1, 0, m2) + 1;
1422 c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
1423 d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
1424 b = max (min (c, d), min (edit->column1, edit->column2));
1425 c = max (c, max (edit->column1, edit->column2));
1427 while (n--)
1429 r = edit_bol (edit, edit->curs1);
1430 p = edit_move_forward3 (edit, r, b, 0);
1431 q = edit_move_forward3 (edit, r, c, 0);
1432 if (p < m1)
1433 p = m1;
1434 if (q > m2)
1435 q = m2;
1436 edit_cursor_move (edit, p - edit->curs1);
1437 while (q > p)
1439 /* delete line between margins */
1440 if (edit_get_byte (edit, edit->curs1) != '\n')
1441 edit_delete (edit, 1);
1442 q--;
1444 if (n)
1445 /* move to next line except on the last delete */
1446 edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
1450 /* if success return 0 */
1451 static int
1452 edit_block_delete (WEdit * edit)
1454 long count;
1455 long start_mark, end_mark;
1456 int curs_pos, line_width;
1457 long curs_line, c1, c2;
1459 if (eval_marks (edit, &start_mark, &end_mark))
1460 return 0;
1461 if (edit->column_highlight && edit->mark2 < 0)
1462 edit_mark_cmd (edit, 0);
1463 if ((end_mark - start_mark) > option_max_undo / 2)
1465 /* Warning message with a query to continue or cancel the operation */
1466 if (edit_query_dialog2
1467 (_("Warning"),
1469 ("Block is large, you may not be able to undo this action"),
1470 _("C&ontinue"), _("&Cancel")))
1472 return 1;
1475 c1 = min (edit->column1, edit->column2);
1476 c2 = max (edit->column1, edit->column2);
1477 edit->column1 = c1;
1478 edit->column2 = c2;
1480 edit_push_markers (edit);
1482 curs_line = edit->curs_line;
1484 /* calculate line width and cursor position before cut */
1485 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
1486 edit_eol (edit, edit->curs1));
1487 curs_pos = edit->curs_col + edit->over_col;
1489 /* move cursor to start of selection */
1490 edit_cursor_move (edit, start_mark - edit->curs1);
1491 edit_scroll_screen_over_cursor (edit);
1492 count = start_mark;
1493 if (start_mark < end_mark)
1495 if (edit->column_highlight)
1497 if (edit->mark2 < 0)
1498 edit_mark_cmd (edit, 0);
1499 edit_delete_column_of_text (edit);
1500 /* move cursor to the saved position */
1501 edit_move_to_line (edit, curs_line);
1502 /* calculate line width after cut */
1503 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
1504 edit_eol (edit, edit->curs1));
1505 if (option_cursor_beyond_eol && curs_pos > line_width)
1506 edit->over_col = curs_pos - line_width;
1508 else
1510 while (count < end_mark)
1512 edit_delete (edit, 1);
1513 count++;
1517 edit_set_markers (edit, 0, 0, 0, 0);
1518 edit->force |= REDRAW_PAGE;
1519 return 0;
1522 /* returns 1 if canceelled by user */
1524 edit_block_delete_cmd (WEdit * edit)
1526 long start_mark, end_mark;
1527 if (eval_marks (edit, &start_mark, &end_mark))
1529 edit_delete_line (edit);
1530 return 0;
1532 return edit_block_delete (edit);
1535 #define INPUT_INDEX 9
1537 static gboolean
1538 editcmd_find (WEdit * edit, gsize * len)
1540 off_t search_start = edit->search_start;
1541 off_t search_end;
1542 long start_mark = 0;
1543 long end_mark = edit->last_byte;
1544 int mark_res = 0;
1546 if (edit_search_options.only_in_selection)
1548 mark_res = eval_marks (edit, &start_mark, &end_mark);
1549 if (mark_res != 0)
1551 edit->search->error = MC_SEARCH_E_NOTFOUND;
1552 edit->search->error_str = g_strdup (_("Search string not found"));
1553 return FALSE;
1555 if (edit_search_options.backwards)
1557 if (search_start > end_mark || search_start <= start_mark)
1559 search_start = end_mark;
1562 else
1564 if (search_start < start_mark || search_start >= end_mark)
1566 search_start = start_mark;
1570 else
1572 if (edit_search_options.backwards)
1573 end_mark = max (1, edit->curs1) - 1;
1575 if (edit_search_options.backwards)
1577 search_end = end_mark;
1578 while ((int) search_start >= start_mark)
1580 if (search_end > (off_t) (search_start + edit->search->original_len) &&
1581 mc_search_is_fixed_search_str (edit->search))
1583 search_end = search_start + edit->search->original_len;
1585 if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
1586 && edit->search->normal_offset == search_start)
1588 return TRUE;
1590 search_start--;
1592 edit->search->error_str = g_strdup (_("Search string not found"));
1594 else
1596 return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
1598 return FALSE;
1602 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1603 (and the above) routines to work properly - paul */
1605 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1607 static char *
1608 edit_replace_cmd__conv_to_display (char *str)
1610 #ifdef HAVE_CHARSET
1611 GString *tmp;
1613 tmp = str_convert_to_display (str);
1614 if (tmp != NULL)
1616 if (tmp->len != 0)
1617 return g_string_free (tmp, FALSE);
1618 g_string_free (tmp, TRUE);
1620 #endif
1621 return g_strdup (str);
1624 static char *
1625 edit_replace_cmd__conv_to_input (char *str)
1627 #ifdef HAVE_CHARSET
1628 GString *tmp;
1630 tmp = str_convert_to_input (str);
1631 if (tmp != NULL)
1633 if (tmp->len != 0)
1634 return g_string_free (tmp, FALSE);
1635 g_string_free (tmp, TRUE);
1637 #endif
1638 return g_strdup (str);
1641 /* call with edit = 0 before shutdown to close memory leaks */
1642 void
1643 edit_replace_cmd (WEdit * edit, int again)
1645 /* 1 = search string, 2 = replace with */
1646 static char *saved1 = NULL; /* saved default[123] */
1647 static char *saved2 = NULL;
1648 char *input1 = NULL; /* user input from the dialog */
1649 char *input2 = NULL;
1650 char *disp1 = NULL;
1651 char *disp2 = NULL;
1652 long times_replaced = 0;
1653 gboolean once_found = FALSE;
1655 if (!edit)
1657 g_free (saved1), saved1 = NULL;
1658 g_free (saved2), saved2 = NULL;
1659 return;
1662 edit->force |= REDRAW_COMPLETELY;
1664 if (again && !saved1 && !saved2)
1665 again = 0;
1667 if (again)
1669 input1 = g_strdup (saved1 ? saved1 : "");
1670 input2 = g_strdup (saved2 ? saved2 : "");
1672 else
1674 char *tmp_inp1, *tmp_inp2;
1675 disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
1676 disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
1678 edit_push_action (edit, KEY_PRESS + edit->start_display);
1680 editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
1682 g_free (disp1);
1683 g_free (disp2);
1685 if (input1 == NULL || *input1 == '\0')
1687 edit->force = REDRAW_COMPLETELY;
1688 goto cleanup;
1691 tmp_inp1 = input1;
1692 tmp_inp2 = input2;
1693 input1 = edit_replace_cmd__conv_to_input (input1);
1694 input2 = edit_replace_cmd__conv_to_input (input2);
1695 g_free (tmp_inp1);
1696 g_free (tmp_inp2);
1698 g_free (saved1), saved1 = g_strdup (input1);
1699 g_free (saved2), saved2 = g_strdup (input2);
1701 if (edit->search)
1703 mc_search_free (edit->search);
1704 edit->search = NULL;
1708 if (!edit->search)
1710 edit->search = mc_search_new (input1, -1);
1711 if (edit->search == NULL)
1713 edit->search_start = edit->curs1;
1714 goto cleanup;
1716 edit->search->search_type = edit_search_options.type;
1717 edit->search->is_all_charsets = edit_search_options.all_codepages;
1718 edit->search->is_case_sensitive = edit_search_options.case_sens;
1719 edit->search->whole_words = edit_search_options.whole_words;
1720 edit->search->search_fn = edit_search_cmd_callback;
1723 if (edit->found_len && edit->search_start == edit->found_start + 1
1724 && edit_search_options.backwards)
1725 edit->search_start--;
1727 if (edit->found_len && edit->search_start == edit->found_start - 1
1728 && !edit_search_options.backwards)
1729 edit->search_start++;
1733 gsize len = 0;
1735 if (!editcmd_find (edit, &len))
1737 if (!(edit->search->error == MC_SEARCH_E_OK ||
1738 (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
1740 edit_error_dialog (_("Search"), edit->search->error_str);
1742 break;
1744 once_found = TRUE;
1746 edit->search_start = edit->search->normal_offset;
1747 /*returns negative on not found or error in pattern */
1749 if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
1751 gsize i;
1752 GString *tmp_str, *repl_str;
1754 edit->found_start = edit->search_start;
1755 i = edit->found_len = len;
1757 edit_cursor_move (edit, edit->search_start - edit->curs1);
1758 edit_scroll_screen_over_cursor (edit);
1760 if (edit->replace_mode == 0)
1762 int l;
1763 int prompt;
1765 l = edit->curs_row - edit->num_widget_lines / 3;
1766 if (l > 0)
1767 edit_scroll_downward (edit, l);
1768 if (l < 0)
1769 edit_scroll_upward (edit, -l);
1771 edit_scroll_screen_over_cursor (edit);
1772 edit->force |= REDRAW_PAGE;
1773 edit_render_keypress (edit);
1775 /*so that undo stops at each query */
1776 edit_push_key_press (edit);
1777 /* and prompt 2/3 down */
1778 disp1 = edit_replace_cmd__conv_to_display (saved1);
1779 disp2 = edit_replace_cmd__conv_to_display (saved2);
1780 prompt = editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
1781 g_free (disp1);
1782 g_free (disp2);
1784 if (prompt == B_REPLACE_ALL)
1785 edit->replace_mode = 1;
1786 else if (prompt == B_SKIP_REPLACE)
1788 if (edit_search_options.backwards)
1789 edit->search_start--;
1790 else
1791 edit->search_start++;
1792 continue; /* loop */
1794 else if (prompt == B_CANCEL)
1796 edit->replace_mode = -1;
1797 break; /* loop */
1801 /* don't process string each time */
1802 tmp_str = g_string_new (input2);
1803 repl_str = mc_search_prepare_replace_str (edit->search, tmp_str);
1804 g_string_free (tmp_str, TRUE);
1806 if (edit->search->error != MC_SEARCH_E_OK)
1808 edit_error_dialog (_("Replace"), edit->search->error_str);
1809 g_string_free (repl_str, TRUE);
1810 break;
1813 /* delete then insert new */
1814 for (i = 0; i < len; i++)
1815 edit_delete (edit, 1);
1817 for (i = 0; i < repl_str->len; i++)
1818 edit_insert (edit, repl_str->str[i]);
1820 edit->found_len = repl_str->len;
1821 g_string_free (repl_str, TRUE);
1822 times_replaced++;
1824 /* so that we don't find the same string again */
1825 if (edit_search_options.backwards)
1826 edit->search_start--;
1827 else
1829 edit->search_start += edit->found_len;
1831 if (edit->search_start >= edit->last_byte)
1832 break;
1835 edit_scroll_screen_over_cursor (edit);
1837 else
1839 /* try and find from right here for next search */
1840 edit->search_start = edit->curs1;
1841 edit_update_curs_col (edit);
1843 edit->force |= REDRAW_PAGE;
1844 edit_render_keypress (edit);
1846 if (times_replaced == 0)
1847 query_dialog (_("Replace"), _("Search string not found"), D_NORMAL, 1, _("&OK"));
1848 break;
1851 while (edit->replace_mode >= 0);
1853 edit_scroll_screen_over_cursor (edit);
1854 edit->force |= REDRAW_COMPLETELY;
1855 edit_render_keypress (edit);
1857 if ((edit->replace_mode == 1) && (times_replaced != 0))
1858 message (D_NORMAL, _("Replace"), _("%ld replacements made"), times_replaced);
1860 cleanup:
1861 g_free (input1);
1862 g_free (input2);
1865 static void
1866 edit_do_search (WEdit * edit)
1868 gsize len = 0;
1870 if (edit->search == NULL)
1871 edit->search_start = edit->curs1;
1873 edit_push_action (edit, KEY_PRESS + edit->start_display);
1875 if (search_create_bookmark)
1877 int found = 0, books = 0;
1878 long l = 0, l_last = -1;
1879 long q = 0;
1881 search_create_bookmark = FALSE;
1882 book_mark_flush (edit, -1);
1884 while (TRUE)
1886 if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
1887 break;
1888 if (found == 0)
1889 edit->search_start = edit->search->normal_offset;
1890 found++;
1891 l += edit_count_lines (edit, q, edit->search->normal_offset);
1892 if (l != l_last)
1894 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
1895 books++;
1897 l_last = l;
1898 q = edit->search->normal_offset + 1;
1901 if (found == 0)
1902 edit_error_dialog (_("Search"), _("Search string not found"));
1903 else
1904 edit_cursor_move (edit, edit->search_start - edit->curs1);
1906 else
1908 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1
1909 && edit_search_options.backwards)
1910 edit->search_start--;
1912 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1
1913 && !edit_search_options.backwards)
1914 edit->search_start++;
1916 if (editcmd_find (edit, &len))
1918 edit->found_start = edit->search_start = edit->search->normal_offset;
1919 edit->found_len = len;
1920 edit->over_col = 0;
1921 edit_cursor_move (edit, edit->search_start - edit->curs1);
1922 edit_scroll_screen_over_cursor (edit);
1923 if (edit_search_options.backwards)
1924 edit->search_start--;
1925 else
1926 edit->search_start++;
1928 else
1930 edit->search_start = edit->curs1;
1931 if (edit->search->error_str != NULL)
1932 edit_error_dialog (_("Search"), edit->search->error_str);
1936 edit->force |= REDRAW_COMPLETELY;
1937 edit_scroll_screen_over_cursor (edit);
1940 static void
1941 edit_search (WEdit *edit)
1943 if (editcmd_dialog_search_show (edit))
1944 edit_do_search (edit);
1947 void
1948 edit_search_cmd (WEdit * edit, gboolean again)
1950 if (edit == NULL)
1951 return;
1953 if (!again)
1954 edit_search (edit);
1955 else if (edit->last_search_string != NULL)
1956 edit_do_search (edit);
1957 else
1959 /* find last search string in history */
1960 GList *history;
1962 history = history_get (MC_HISTORY_SHARED_SEARCH);
1963 if (history != NULL && history->data != NULL)
1965 edit->last_search_string = (char *) history->data;
1966 history->data = NULL;
1967 history = g_list_first (history);
1968 g_list_foreach (history, (GFunc) g_free, NULL);
1969 g_list_free (history);
1971 edit->search = mc_search_new (edit->last_search_string, -1);
1972 if (edit->search == NULL)
1974 /* if not... then ask for an expression */
1975 g_free (edit->last_search_string);
1976 edit->last_search_string = NULL;
1977 edit_search (edit);
1979 else
1981 edit->search->search_type = edit_search_options.type;
1982 edit->search->is_all_charsets = edit_search_options.all_codepages;
1983 edit->search->is_case_sensitive = edit_search_options.case_sens;
1984 edit->search->whole_words = edit_search_options.whole_words;
1985 edit->search->search_fn = edit_search_cmd_callback;
1986 edit_do_search (edit);
1989 else
1991 /* if not... then ask for an expression */
1992 g_free (edit->last_search_string);
1993 edit->last_search_string = NULL;
1994 edit_search (edit);
2001 * Check if it's OK to close the editor. If there are unsaved changes,
2002 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
2004 gboolean
2005 edit_ok_to_exit (WEdit * edit)
2007 int act;
2009 if (!edit->modified)
2010 return TRUE;
2012 if (!midnight_shutdown)
2014 if (!edit_check_newline (edit))
2015 return FALSE;
2017 query_set_sel (2);
2018 act = edit_query_dialog3 (_("Quit"), _("File was modified. Save with exit?"),
2019 _("&Yes"), _("&No"), _("&Cancel quit"));
2021 else
2023 act = edit_query_dialog2 (_("Quit"), _("Midnight Commander is being shut down.\nSave modified file?"),
2024 _("&Yes"), _("&No"));
2026 /* Esc is No */
2027 if (act == -1)
2028 act = 1;
2031 switch (act)
2033 case 0: /* Yes */
2034 edit_push_markers (edit);
2035 edit_set_markers (edit, 0, 0, 0, 0);
2036 if (!edit_save_cmd (edit) || midnight_shutdown)
2037 return (gboolean) midnight_shutdown;
2038 break;
2039 case 1: /* No */
2040 break;
2041 case 2: /* Cancel quit */
2042 case -1: /* Esc */
2043 return FALSE;
2046 return TRUE;
2049 /* Return a null terminated length of text. Result must be g_free'd */
2050 static unsigned char *
2051 edit_get_block (WEdit * edit, long start, long finish, int *l)
2053 unsigned char *s, *r;
2054 r = s = g_malloc0 (finish - start + 1);
2055 if (edit->column_highlight)
2057 *l = 0;
2058 /* copy from buffer, excluding chars that are out of the column 'margins' */
2059 while (start < finish)
2061 int c;
2062 long x;
2063 x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
2064 c = edit_get_byte (edit, start);
2065 if ((x >= edit->column1 && x < edit->column2)
2066 || (x >= edit->column2 && x < edit->column1) || c == '\n')
2068 *s++ = c;
2069 (*l)++;
2071 start++;
2074 else
2076 *l = finish - start;
2077 while (start < finish)
2078 *s++ = edit_get_byte (edit, start++);
2080 *s = 0;
2081 return r;
2084 /* save block, returns 1 on success */
2086 edit_save_block (WEdit * edit, const char *filename, long start, long finish)
2088 int len, file;
2090 file = mc_open (filename, O_CREAT | O_WRONLY | O_TRUNC,
2091 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY);
2092 if (file == -1)
2093 return 0;
2095 if (edit->column_highlight)
2097 int r;
2098 r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
2099 if (r > 0)
2101 unsigned char *block, *p;
2102 p = block = edit_get_block (edit, start, finish, &len);
2103 while (len)
2105 r = mc_write (file, p, len);
2106 if (r < 0)
2107 break;
2108 p += r;
2109 len -= r;
2111 g_free (block);
2114 else
2116 unsigned char *buf;
2117 int i = start, end;
2118 len = finish - start;
2119 buf = g_malloc0 (TEMP_BUF_LEN);
2120 while (start != finish)
2122 end = min (finish, start + TEMP_BUF_LEN);
2123 for (; i < end; i++)
2124 buf[i - start] = edit_get_byte (edit, i);
2125 len -= mc_write (file, (char *) buf, end - start);
2126 start = end;
2128 g_free (buf);
2130 mc_close (file);
2131 if (len)
2132 return 0;
2133 return 1;
2136 /* copies a block to clipboard file */
2137 static int
2138 edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
2140 int ret;
2141 gchar *tmp;
2142 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2143 ret = edit_save_block (edit, tmp, start, finish);
2144 g_free (tmp);
2145 return ret;
2148 void
2149 edit_paste_from_history (WEdit * edit)
2151 (void) edit;
2152 edit_error_dialog (_("Error"), _("This function is not implemented"));
2156 edit_copy_to_X_buf_cmd (WEdit * edit)
2158 long start_mark, end_mark;
2159 if (eval_marks (edit, &start_mark, &end_mark))
2160 return 0;
2161 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2163 edit_error_dialog (_("Copy to clipboard"),
2164 get_sys_error (_("Unable to save to file")));
2165 return 1;
2167 /* try use external clipboard utility */
2168 copy_file_to_ext_clip ();
2170 edit_mark_cmd (edit, 1);
2171 return 0;
2175 edit_cut_to_X_buf_cmd (WEdit * edit)
2177 long start_mark, end_mark;
2178 if (eval_marks (edit, &start_mark, &end_mark))
2179 return 0;
2180 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2182 edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
2183 return 1;
2185 /* try use external clipboard utility */
2186 copy_file_to_ext_clip ();
2188 edit_block_delete_cmd (edit);
2189 edit_mark_cmd (edit, 1);
2190 return 0;
2193 void
2194 edit_paste_from_X_buf_cmd (WEdit * edit)
2196 gchar *tmp;
2197 /* try use external clipboard utility */
2198 paste_to_file_from_ext_clip ();
2199 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2200 edit_insert_file (edit, tmp);
2201 g_free (tmp);
2206 * Ask user for the line and go to that line.
2207 * Negative numbers mean line from the end (i.e. -1 is the last line).
2209 void
2210 edit_goto_cmd (WEdit * edit)
2212 char *f;
2213 static long line = 0; /* line as typed, saved as default */
2214 long l;
2215 char *error;
2216 char s[32];
2218 g_snprintf (s, sizeof (s), "%ld", line);
2219 f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE,
2220 line ? s : "");
2221 if (!f)
2222 return;
2224 if (!*f)
2226 g_free (f);
2227 return;
2230 l = strtol (f, &error, 0);
2231 if (*error)
2233 g_free (f);
2234 return;
2237 line = l;
2238 if (l < 0)
2239 l = edit->total_lines + l + 2;
2240 edit_move_display (edit, l - edit->num_widget_lines / 2 - 1);
2241 edit_move_to_line (edit, l - 1);
2242 edit->force |= REDRAW_COMPLETELY;
2243 g_free (f);
2247 /* Return 1 on success */
2249 edit_save_block_cmd (WEdit * edit)
2251 long start_mark, end_mark;
2252 char *exp, *tmp;
2254 if (eval_marks (edit, &start_mark, &end_mark))
2255 return 1;
2257 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2258 exp =
2259 input_expand_dialog (_("Save block"), _("Enter file name:"),
2260 MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
2261 g_free (tmp);
2262 edit_push_action (edit, KEY_PRESS + edit->start_display);
2263 if (exp)
2265 if (!*exp)
2267 g_free (exp);
2268 return 0;
2270 else
2272 if (edit_save_block (edit, exp, start_mark, end_mark))
2274 g_free (exp);
2275 edit->force |= REDRAW_COMPLETELY;
2276 return 1;
2278 else
2280 g_free (exp);
2281 edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
2285 edit->force |= REDRAW_COMPLETELY;
2286 return 0;
2290 /* returns 1 on success */
2292 edit_insert_file_cmd (WEdit * edit)
2294 gchar *tmp;
2295 char *exp;
2297 tmp = concat_dir_and_file (home_dir, EDIT_CLIP_FILE);
2298 exp = input_expand_dialog (_("Insert file"), _("Enter file name:"),
2299 MC_HISTORY_EDIT_INSERT_FILE, tmp);
2300 g_free (tmp);
2301 edit_push_action (edit, KEY_PRESS + edit->start_display);
2302 if (exp)
2304 if (!*exp)
2306 g_free (exp);
2307 return 0;
2309 else
2311 if (edit_insert_file (edit, exp))
2313 g_free (exp);
2314 edit->force |= REDRAW_COMPLETELY;
2315 return 1;
2317 else
2319 g_free (exp);
2320 edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
2324 edit->force |= REDRAW_COMPLETELY;
2325 return 0;
2328 /* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
2330 edit_sort_cmd (WEdit * edit)
2332 static char *old = 0;
2333 char *exp, *tmp;
2334 long start_mark, end_mark;
2335 int e;
2337 if (eval_marks (edit, &start_mark, &end_mark))
2339 edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
2340 return 0;
2343 tmp = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE);
2344 edit_save_block (edit, tmp, start_mark, end_mark);
2345 g_free (tmp);
2347 exp = input_dialog (_("Run sort"),
2348 _("Enter sort options (see manpage) separated by whitespace:"),
2349 MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
2351 if (!exp)
2352 return 1;
2353 g_free (old);
2354 old = exp;
2355 tmp = g_strconcat (" sort ", exp, " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE, " > ",
2356 home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2357 e = system (tmp);
2358 g_free (tmp);
2359 if (e)
2361 if (e == -1 || e == 127)
2363 edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
2365 else
2367 char q[8];
2368 sprintf (q, "%d ", e);
2369 tmp = g_strdup_printf (_("Sort returned non-zero: %s"), q);
2370 edit_error_dialog (_("Sort"), tmp);
2371 g_free (tmp);
2373 return -1;
2376 edit->force |= REDRAW_COMPLETELY;
2378 if (edit_block_delete_cmd (edit))
2379 return 1;
2380 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2381 edit_insert_file (edit, tmp);
2382 g_free (tmp);
2383 return 0;
2387 * Ask user for a command, execute it and paste its output back to the
2388 * editor.
2391 edit_ext_cmd (WEdit * edit)
2393 char *exp, *tmp;
2394 int e;
2396 exp =
2397 input_dialog (_("Paste output of external command"),
2398 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
2400 if (!exp)
2401 return 1;
2403 tmp = g_strconcat (exp, " > ", home_dir, PATH_SEP_STR EDIT_TEMP_FILE, (char *) NULL);
2404 e = system (tmp);
2405 g_free (tmp);
2406 g_free (exp);
2408 if (e)
2410 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
2411 return -1;
2414 edit->force |= REDRAW_COMPLETELY;
2415 tmp = concat_dir_and_file (home_dir, EDIT_TEMP_FILE);
2416 edit_insert_file (edit, tmp);
2417 g_free (tmp);
2418 return 0;
2421 /* if block is 1, a block must be highlighted and the shell command
2422 processes it. If block is 0 the shell command is a straight system
2423 command, that just produces some output which is to be inserted */
2424 void
2425 edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
2427 long start_mark, end_mark;
2428 char buf[BUFSIZ];
2429 FILE *script_home = NULL;
2430 FILE *block_file = NULL;
2431 gchar *o, *h, *b, *tmp;
2432 char *quoted_name = NULL;
2434 o = g_strconcat (mc_home, shell_cmd, (char *) NULL); /* original source script */
2435 h = g_strconcat (home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, (char *) NULL); /* home script */
2436 b = concat_dir_and_file (home_dir, EDIT_BLOCK_FILE); /* block file */
2438 script_home = fopen (h, "r");
2439 if (script_home == NULL)
2441 FILE *script_src = NULL;
2443 script_home = fopen (h, "w");
2444 if (script_home == NULL)
2446 tmp = g_strconcat (_("Error creating script:"), h, (char *) NULL);
2447 edit_error_dialog ("", get_sys_error (tmp));
2448 g_free (tmp);
2449 goto edit_block_process_cmd__EXIT;
2452 script_src = fopen (o, "r");
2453 if (script_src == NULL)
2455 o = g_strconcat (mc_home_alt, shell_cmd, (char *) NULL);
2456 script_src = fopen (o, "r");
2457 if (script_src == NULL)
2459 fclose (script_home);
2460 unlink (h);
2461 tmp = g_strconcat (_("Error reading script:"), o, (char *) NULL);
2462 edit_error_dialog ("", get_sys_error (tmp));
2463 g_free (tmp);
2464 goto edit_block_process_cmd__EXIT;
2467 while (fgets (buf, sizeof (buf), script_src))
2468 fputs (buf, script_home);
2469 fclose (script_src);
2471 if (fclose (script_home))
2473 tmp = g_strconcat (_("Error closing script:"), h, (char *) NULL);
2474 edit_error_dialog ("", get_sys_error (tmp));
2475 g_free (tmp);
2476 goto edit_block_process_cmd__EXIT;
2478 chmod (h, 0700);
2479 tmp = g_strconcat (_("Script created:"), h, (char *) NULL);
2480 edit_error_dialog ("", get_sys_error (tmp));
2481 g_free (tmp);
2484 open_error_pipe ();
2486 if (block)
2487 { /* for marked block run indent formatter */
2488 if (eval_marks (edit, &start_mark, &end_mark))
2490 edit_error_dialog (_("Process block"),
2491 _("You must first highlight a block of text"));
2492 goto edit_block_process_cmd__EXIT;
2494 edit_save_block (edit, b, start_mark, end_mark);
2495 quoted_name = name_quote (edit->filename, 0);
2497 * Run script.
2498 * Initial space is to avoid polluting bash history.
2499 * Arguments:
2500 * $1 - name of the edited file (to check its extension etc).
2501 * $2 - file containing the current block.
2502 * $3 - file where error messages should be put
2503 * (for compatibility with old scripts).
2505 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ", quoted_name,
2506 " ", home_dir, PATH_SEP_STR EDIT_BLOCK_FILE " /dev/null", (char *) NULL);
2508 else
2511 * No block selected, just execute the command for the file.
2512 * Arguments:
2513 * $1 - name of the edited file.
2515 tmp = g_strconcat (" ", home_dir, PATH_SEP_STR EDIT_DIR, shell_cmd, " ",
2516 quoted_name, (char *) NULL);
2519 if (system (tmp) == -1)
2521 edit_error_dialog (_("Process block"), _("Error calling program"));
2523 else
2526 g_free (quoted_name);
2527 close_error_pipe (D_NORMAL, NULL);
2529 edit_refresh_cmd (edit);
2530 edit->force |= REDRAW_COMPLETELY;
2532 /* insert result block */
2533 if (block && !edit_block_delete_cmd (edit))
2535 edit_insert_file (edit, b);
2536 block_file = fopen (b, "w");
2537 if (block_file != NULL)
2538 fclose (block_file);
2541 g_free (tmp);
2543 edit_block_process_cmd__EXIT:
2544 g_free (b);
2545 g_free (h);
2546 g_free (o);
2549 /* prints at the cursor */
2550 /* returns the number of chars printed */
2552 edit_print_string (WEdit * e, const char *s)
2554 size_t i = 0;
2555 while (s[i] != '\0')
2556 edit_execute_cmd (e, CK_Insert_Char, (unsigned char) s[i++]);
2557 e->force |= REDRAW_COMPLETELY;
2558 edit_update_screen (e);
2559 return i;
2563 static void
2564 pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
2566 FILE *p = 0;
2567 char *s;
2569 to = name_quote (to, 0);
2570 subject = name_quote (subject, 0);
2571 cc = name_quote (cc, 0);
2572 s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
2573 g_free (to);
2574 g_free (subject);
2575 g_free (cc);
2577 if (s)
2579 p = popen (s, "w");
2580 g_free (s);
2583 if (p)
2585 long i;
2586 for (i = 0; i < edit->last_byte; i++)
2587 fputc (edit_get_byte (edit, i), p);
2588 pclose (p);
2592 #define MAIL_DLG_HEIGHT 12
2594 void
2595 edit_mail_dialog (WEdit * edit)
2597 char *tmail_to;
2598 char *tmail_subject;
2599 char *tmail_cc;
2601 static char *mail_cc_last = 0;
2602 static char *mail_subject_last = 0;
2603 static char *mail_to_last = 0;
2605 QuickWidget quick_widgets[] = {
2606 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
2607 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
2608 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
2609 /* 3 */ QUICK_LABEL (3, 50, 7, MAIL_DLG_HEIGHT, N_("Copies to")),
2610 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
2611 &tmail_subject),
2612 /* 5 */ QUICK_LABEL (3, 50, 5, MAIL_DLG_HEIGHT, N_("Subject")),
2613 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
2614 /* 7 */ QUICK_LABEL (3, 50, 3, MAIL_DLG_HEIGHT, N_("To")),
2615 /* 8 */ QUICK_LABEL (3, 50, 2, MAIL_DLG_HEIGHT, N_("mail -s <subject> -c <cc> <to>")),
2616 QUICK_END
2619 QuickDialog Quick_input = {
2620 50, MAIL_DLG_HEIGHT, -1, -1, N_("Mail"),
2621 "[Input Line Keys]", quick_widgets, NULL, FALSE
2624 quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
2625 quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
2626 quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
2628 if (quick_dialog (&Quick_input) != B_CANCEL)
2630 g_free (mail_cc_last);
2631 g_free (mail_subject_last);
2632 g_free (mail_to_last);
2633 mail_cc_last = tmail_cc;
2634 mail_subject_last = tmail_subject;
2635 mail_to_last = tmail_to;
2636 pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
2641 /*******************/
2642 /* Word Completion */
2643 /*******************/
2645 static gboolean
2646 is_break_char (char c)
2648 return (isspace (c) || strchr ("{}[]()<>=|/\\!?~'\",.;:#$%^&*", c));
2651 /* find first character of current word */
2652 static int
2653 edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
2655 int c, last;
2656 gsize i;
2658 /* return if at begin of file */
2659 if (edit->curs1 <= 0)
2660 return 0;
2662 c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
2663 /* return if not at end or in word */
2664 if (is_break_char (c))
2665 return 0;
2667 /* search start of word to be completed */
2668 for (i = 2;; i++)
2670 /* return if at begin of file */
2671 if ((gsize) edit->curs1 < i)
2672 return 0;
2674 last = c;
2675 c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
2677 if (is_break_char (c))
2679 /* return if word starts with digit */
2680 if (isdigit (last))
2681 return 0;
2683 *word_start = edit->curs1 - (i - 1); /* start found */
2684 *word_len = i - 1;
2685 break;
2688 /* success */
2689 return 1;
2692 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
2694 /* collect the possible completions */
2695 static gsize
2696 edit_collect_completions (WEdit * edit, long start, gsize word_len,
2697 char *match_expr, struct selection *compl, gsize * num)
2699 gsize len = 0;
2700 gsize max_len = 0;
2701 gsize i;
2702 int skip;
2703 GString *temp;
2704 mc_search_t *srch;
2706 long last_byte;
2708 srch = mc_search_new (match_expr, -1);
2709 if (srch == NULL)
2710 return 0;
2712 if (mc_config_get_bool
2713 (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
2715 last_byte = edit->last_byte;
2717 else
2719 last_byte = start;
2722 srch->search_type = MC_SEARCH_T_REGEX;
2723 srch->is_case_sensitive = TRUE;
2724 srch->search_fn = edit_search_cmd_callback;
2726 /* collect max MAX_WORD_COMPLETIONS completions */
2727 start = -1;
2728 while (1)
2730 /* get next match */
2731 if (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len) == FALSE)
2732 break;
2733 start = srch->normal_offset;
2735 /* add matched completion if not yet added */
2736 temp = g_string_new ("");
2737 for (i = 0; i < len; i++)
2739 skip = edit_get_byte (edit, start + i);
2740 if (isspace (skip))
2741 continue;
2742 g_string_append_c (temp, skip);
2745 skip = 0;
2747 for (i = 0; i < (gsize) * num; i++)
2749 if (strncmp
2750 ((char *) &compl[i].text[word_len],
2751 (char *) &temp->str[word_len], max (len, compl[i].len) - (gsize) word_len) == 0)
2753 struct selection this = compl[i];
2754 for (++i; i < *num; i++)
2756 compl[i - 1] = compl[i];
2758 compl[*num - 1] = this;
2759 skip = 1;
2760 break; /* skip it, already added */
2763 if (skip)
2765 g_string_free (temp, TRUE);
2766 continue;
2768 if (*num == MAX_WORD_COMPLETIONS && MAX_WORD_COMPLETIONS)
2770 g_free (compl[0].text);
2771 for (i = 1; i < *num; i++)
2773 compl[i - 1] = compl[i];
2775 (*num)--;
2777 #ifdef HAVE_CHARSET
2779 GString *recoded;
2780 recoded = str_convert_to_display (temp->str);
2782 if (recoded && recoded->len)
2784 g_string_free (temp, TRUE);
2785 temp = recoded;
2787 else
2788 g_string_free (recoded, TRUE);
2790 #endif
2791 compl[*num].text = temp->str;
2792 compl[*num].len = temp->len;
2793 (*num)++;
2794 start += len;
2795 g_string_free (temp, FALSE);
2797 /* note the maximal length needed for the completion dialog */
2798 if (len > max_len)
2799 max_len = len;
2801 mc_search_free (srch);
2802 return max_len;
2806 * Complete current word using regular expression search
2807 * backwards beginning at the current cursor position.
2809 void
2810 edit_complete_word_cmd (WEdit * edit)
2812 gsize i, max_len, word_len = 0, num_compl = 0;
2813 long word_start = 0;
2814 unsigned char *bufpos;
2815 char *match_expr;
2816 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
2818 /* search start of word to be completed */
2819 if (!edit_find_word_start (edit, &word_start, &word_len))
2820 return;
2822 /* prepare match expression */
2823 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
2825 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
2826 match_expr =
2827 g_strdup_printf
2828 ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
2829 (int) word_len, bufpos);
2831 /* collect the possible completions */
2832 /* start search from begin to end of file */
2833 max_len =
2834 edit_collect_completions (edit, word_start, word_len, match_expr,
2835 (struct selection *) &compl, &num_compl);
2837 if (num_compl > 0)
2839 /* insert completed word if there is only one match */
2840 if (num_compl == 1)
2842 for (i = word_len; i < compl[0].len; i++)
2843 edit_insert (edit, *(compl[0].text + i));
2845 /* more than one possible completion => ask the user */
2846 else
2848 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
2849 /* !!! pressed again the selection dialog pops up, but that !!! */
2850 /* !!! seems to require a further internal state !!! */
2851 /*tty_beep (); */
2853 /* let the user select the preferred completion */
2854 editcmd_dialog_completion_show (edit, max_len, word_len,
2855 (struct selection *) &compl, num_compl);
2859 g_free (match_expr);
2860 /* release memory before return */
2861 for (i = 0; i < num_compl; i++)
2862 g_free (compl[i].text);
2865 void
2866 edit_select_codepage_cmd (WEdit * edit)
2868 #ifdef HAVE_CHARSET
2869 if (do_select_codepage ())
2870 edit_set_codeset (edit);
2872 edit->force = REDRAW_COMPLETELY;
2873 edit_refresh_cmd (edit);
2874 #else
2875 (void) edit;
2876 #endif
2879 void
2880 edit_insert_literal_cmd (WEdit * edit)
2882 int char_for_insertion = editcmd_dialog_raw_key_query (_("Insert literal"),
2883 _("Press any key:"), 0);
2884 edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
2887 void
2888 edit_execute_macro_cmd (WEdit * edit)
2890 int command =
2891 CK_Macro (editcmd_dialog_raw_key_query (_("Execute macro"), _("Press macro hotkey:"),
2892 1));
2893 if (command == CK_Macro (0))
2894 command = CK_Insert_Char;
2896 edit_execute_key_command (edit, command, -1);
2899 void
2900 edit_begin_end_macro_cmd (WEdit * edit)
2902 /* edit is a pointer to the widget */
2903 if (edit)
2905 unsigned long command = edit->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
2906 edit_execute_key_command (edit, command, -1);
2911 edit_load_forward_cmd (WEdit * edit)
2913 if (edit->modified)
2915 if (edit_query_dialog2
2916 (_("Warning"),
2917 _("Current text was modified without a file save\n"
2918 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
2920 edit->force |= REDRAW_COMPLETELY;
2921 return 0;
2924 if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
2926 if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
2928 return 1;
2930 edit_stack_iterator++;
2931 if (edit_history_moveto[edit_stack_iterator].filename)
2933 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
2934 edit_history_moveto[edit_stack_iterator].line);
2935 return 0;
2937 else
2939 return 1;
2942 else
2944 return 1;
2949 edit_load_back_cmd (WEdit * edit)
2951 if (edit->modified)
2953 if (edit_query_dialog2
2954 (_("Warning"),
2955 _("Current text was modified without a file save\n"
2956 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
2958 edit->force |= REDRAW_COMPLETELY;
2959 return 0;
2962 if (edit_stack_iterator > 0)
2964 edit_stack_iterator--;
2965 if (edit_history_moveto[edit_stack_iterator].filename)
2967 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
2968 edit_history_moveto[edit_stack_iterator].line);
2969 return 0;
2971 else
2973 return 1;
2976 else
2978 return 1;
2982 void
2983 edit_get_match_keyword_cmd (WEdit * edit)
2985 gsize word_len = 0, max_len = 0;
2986 int num_def = 0;
2987 int i;
2988 long word_start = 0;
2989 unsigned char *bufpos;
2990 char *match_expr;
2991 char *path = NULL;
2992 char *ptr = NULL;
2993 char *tagfile = NULL;
2995 etags_hash_t def_hash[MAX_DEFINITIONS];
2997 for (i = 0; i < MAX_DEFINITIONS; i++)
2999 def_hash[i].filename = NULL;
3002 /* search start of word to be completed */
3003 if (!edit_find_word_start (edit, &word_start, &word_len))
3004 return;
3006 /* prepare match expression */
3007 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3008 match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
3010 ptr = g_get_current_dir ();
3011 path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
3012 g_free (ptr);
3014 /* Recursive search file 'TAGS' in parent dirs */
3017 ptr = g_path_get_dirname (path);
3018 g_free (path);
3019 path = ptr;
3020 g_free (tagfile);
3021 tagfile = g_build_filename (path, TAGS_NAME, (char *) NULL);
3022 if (exist_file (tagfile))
3023 break;
3025 while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
3027 if (tagfile)
3029 num_def =
3030 etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
3031 g_free (tagfile);
3033 g_free (path);
3035 max_len = MAX_WIDTH_DEF_DIALOG;
3036 word_len = 0;
3037 if (num_def > 0)
3039 editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
3040 (etags_hash_t *) & def_hash, num_def);
3042 g_free (match_expr);
3045 void
3046 edit_move_block_to_right (WEdit * edit)
3048 long start_mark, end_mark;
3049 long cur_bol, start_bol;
3051 if (eval_marks (edit, &start_mark, &end_mark))
3052 return;
3054 start_bol = edit_bol (edit, start_mark);
3055 cur_bol = edit_bol (edit, end_mark - 1);
3058 edit_cursor_move (edit, cur_bol - edit->curs1);
3059 if (option_fill_tabs_with_spaces)
3061 if (option_fake_half_tabs)
3063 insert_spaces_tab (edit, 1);
3065 else
3067 insert_spaces_tab (edit, 0);
3070 else
3072 edit_insert (edit, '\t');
3074 edit_cursor_move (edit, edit_bol (edit, cur_bol) - edit->curs1);
3075 if (cur_bol == 0)
3077 break;
3079 cur_bol = edit_bol (edit, cur_bol - 1);
3081 while (cur_bol >= start_bol);
3082 edit->force |= REDRAW_PAGE;
3085 void
3086 edit_move_block_to_left (WEdit * edit)
3088 long start_mark, end_mark;
3089 long cur_bol, start_bol;
3090 int i, del_tab_width;
3091 int next_char;
3093 if (eval_marks (edit, &start_mark, &end_mark))
3094 return;
3096 start_bol = edit_bol (edit, start_mark);
3097 cur_bol = edit_bol (edit, end_mark - 1);
3100 edit_cursor_move (edit, cur_bol - edit->curs1);
3101 if (option_fake_half_tabs)
3103 del_tab_width = HALF_TAB_SIZE;
3105 else
3107 del_tab_width = option_tab_spacing;
3109 next_char = edit_get_byte (edit, edit->curs1);
3110 if (next_char == '\t')
3112 edit_delete (edit, 1);
3114 else if (next_char == ' ')
3116 for (i = 1; i <= del_tab_width; i++)
3118 if (next_char == ' ')
3120 edit_delete (edit, 1);
3122 next_char = edit_get_byte (edit, edit->curs1);
3125 if (cur_bol == 0)
3127 break;
3129 cur_bol = edit_bol (edit, cur_bol - 1);
3131 while (cur_bol >= start_bol);
3132 edit->force |= REDRAW_PAGE;