Changed interface of function mc_open() for handle vfs_path_t object as parameter
[midnight-commander.git] / src / editor / editcmd.c
blob6bdd950dccdc7189ef460a29211290fb0e690957
1 /*
2 Editor high level editing commands
4 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
5 2007, 2011
6 The Free Software Foundation, Inc.
8 Written by:
9 Paul Sheer, 1996, 1997
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 /** \file
28 * \brief Source: editor high level editing commands
29 * \author Paul Sheer
30 * \date 1996, 1997
33 /* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
35 #include <config.h>
37 #ifdef HAVE_ASSERT_H
38 #include <assert.h>
39 #endif
40 #include <ctype.h>
42 #include <stdio.h>
43 #include <stdarg.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <errno.h>
48 #include <sys/stat.h>
49 #include <stdlib.h>
50 #include <fcntl.h>
52 #include "lib/global.h"
53 #include "lib/tty/tty.h"
54 #include "lib/tty/key.h" /* XCTRL */
55 #include "lib/mcconfig.h"
56 #include "lib/skin.h"
57 #include "lib/strutil.h" /* utf string functions */
58 #include "lib/lock.h"
59 #include "lib/util.h" /* tilde_expand() */
60 #include "lib/vfs/vfs.h"
61 #include "lib/widget.h"
62 #include "lib/charsets.h"
63 #include "lib/event.h" /* mc_event_raise() */
65 #include "src/history.h"
66 #include "src/setup.h" /* option_tab_spacing */
67 #include "src/main.h" /* mactos_t */
68 #include "src/selcodepage.h"
69 #include "src/keybind-defaults.h"
70 #include "src/util.h" /* check_for_default() */
71 #include "src/filemanager/layout.h" /* mc_refresh() */
73 #include "edit-impl.h"
74 #include "edit-widget.h"
75 #include "editcmd_dialogs.h"
76 #include "etags.h"
78 /*** global variables ****************************************************************************/
80 /* search and replace: */
81 int search_create_bookmark = FALSE;
83 /* queries on a save */
84 int edit_confirm_save = 1;
86 /*** file scope macro definitions ****************************************************************/
88 #define space_width 1
90 #define TEMP_BUF_LEN 1024
92 #define INPUT_INDEX 9
94 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
95 (and the above) routines to work properly - paul */
97 #define is_digit(x) ((x) >= '0' && (x) <= '9')
99 #define MAIL_DLG_HEIGHT 12
101 #define MAX_WORD_COMPLETIONS 100 /* in listbox */
103 /*** file scope type declarations ****************************************************************/
105 /*** file scope variables ************************************************************************/
107 /*** file scope functions ************************************************************************/
108 /* --------------------------------------------------------------------------------------------- */
110 /* If 0 (quick save) then a) create/truncate <filename> file,
111 b) save to <filename>;
112 if 1 (safe save) then a) save to <tempnam>,
113 b) rename <tempnam> to <filename>;
114 if 2 (do backups) then a) save to <tempnam>,
115 b) rename <filename> to <filename.backup_ext>,
116 c) rename <tempnam> to <filename>. */
118 /* returns 0 on error, -1 on abort */
120 static int
121 edit_save_file (WEdit * edit, const char *filename)
123 char *p;
124 gchar *tmp;
125 long filelen = 0;
126 char *savename = 0;
127 gchar *real_filename;
128 int this_save_mode, fd = -1;
129 vfs_path_t *real_filename_vpath;
130 vfs_path_t *savename_vpath;
132 if (!filename)
133 return 0;
134 if (!*filename)
135 return 0;
137 if (*filename != PATH_SEP && edit->dir)
139 real_filename = concat_dir_and_file (edit->dir, filename);
141 else
143 real_filename = g_strdup (filename);
145 real_filename_vpath = vfs_path_from_str (real_filename);
147 this_save_mode = option_save_mode;
148 if (this_save_mode != EDIT_QUICK_SAVE)
150 if (!vfs_file_is_local (real_filename_vpath)
151 || (fd = mc_open (real_filename_vpath, O_RDONLY | O_BINARY)) == -1)
154 * The file does not exists yet, so no safe save or
155 * backup are necessary.
157 this_save_mode = EDIT_QUICK_SAVE;
159 if (fd != -1)
160 mc_close (fd);
163 if (this_save_mode == EDIT_QUICK_SAVE && !edit->skip_detach_prompt)
165 int rv;
166 struct stat sb;
168 rv = mc_stat (real_filename_vpath, &sb);
169 if (rv == 0 && sb.st_nlink > 1)
171 rv = edit_query_dialog3 (_("Warning"),
172 _("File has hard-links. Detach before saving?"),
173 _("&Yes"), _("&No"), _("&Cancel"));
174 switch (rv)
176 case 0:
177 this_save_mode = EDIT_SAFE_SAVE;
178 /* fallthrough */
179 case 1:
180 edit->skip_detach_prompt = 1;
181 break;
182 default:
183 g_free (real_filename);
184 vfs_path_free (real_filename_vpath);
185 return -1;
189 /* Prevent overwriting changes from other editor sessions. */
190 if (rv == 0 && edit->stat1.st_mtime != 0 && edit->stat1.st_mtime != sb.st_mtime)
193 /* The default action is "Cancel". */
194 query_set_sel (1);
196 rv = edit_query_dialog2 (_("Warning"),
197 _("The file has been modified in the meantime. Save anyway?"),
198 _("&Yes"), _("&Cancel"));
199 if (rv != 0)
201 g_free (real_filename);
202 vfs_path_free (real_filename_vpath);
203 return -1;
208 if (this_save_mode != EDIT_QUICK_SAVE)
210 char *savedir, *saveprefix;
211 const char *slashpos;
212 slashpos = strrchr (real_filename, PATH_SEP);
213 if (slashpos)
215 savedir = g_strdup (real_filename);
216 savedir[slashpos - real_filename + 1] = '\0';
218 else
219 savedir = g_strdup (".");
220 saveprefix = concat_dir_and_file (savedir, "cooledit");
221 g_free (savedir);
222 fd = mc_mkstemps (&savename, saveprefix, NULL);
223 g_free (saveprefix);
224 if (!savename)
226 g_free (real_filename);
227 vfs_path_free (real_filename_vpath);
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 savename_vpath = vfs_path_from_str (savename);
242 (void) mc_chown (savename_vpath, edit->stat1.st_uid, edit->stat1.st_gid);
243 (void) mc_chmod (savename_vpath, edit->stat1.st_mode);
245 fd = mc_open (savename_vpath, 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 savename_vpath = vfs_path_from_str (savename);
334 if (mc_stat (savename_vpath, &edit->stat1) == -1)
335 goto error_save;
337 else
338 { /* change line breaks */
339 FILE *file;
341 mc_close (fd);
343 file = (FILE *) fopen (savename, "w");
345 if (file)
347 filelen = edit_write_stream (edit, file);
348 fclose (file);
350 else
352 char *msg;
354 msg = g_strdup_printf (_("Cannot open file for writing: %s"), savename);
355 edit_error_dialog (_("Error"), msg);
356 g_free (msg);
357 goto error_save;
361 if (filelen != edit->last_byte)
362 goto error_save;
364 if (this_save_mode == EDIT_DO_BACKUP)
366 vfs_path_t *tmp_vpath;
367 gboolean ok;
369 #ifdef HAVE_ASSERT_H
370 assert (option_backup_ext != NULL);
371 #endif
372 tmp_vpath = vfs_path_append_new (real_filename_vpath, option_backup_ext, (char *) NULL);
373 ok = (mc_rename (real_filename_vpath, tmp_vpath) != -1);
374 vfs_path_free (tmp_vpath);
375 if (!ok)
376 goto error_save;
379 if (this_save_mode != EDIT_QUICK_SAVE)
380 if (mc_rename (savename_vpath, real_filename_vpath) == -1)
381 goto error_save;
382 g_free (real_filename);
383 g_free (savename);
384 vfs_path_free (real_filename_vpath);
385 vfs_path_free (savename_vpath);
386 return 1;
387 error_save:
388 /* FIXME: Is this safe ?
389 * if (this_save_mode != EDIT_QUICK_SAVE)
390 * mc_unlink (savename);
392 g_free (real_filename);
393 g_free (savename);
394 vfs_path_free (real_filename_vpath);
395 vfs_path_free (savename_vpath);
396 return 0;
399 /* --------------------------------------------------------------------------------------------- */
401 static gboolean
402 edit_check_newline (WEdit * edit)
404 return !(option_check_nl_at_eof && edit->last_byte > 0
405 && edit_get_byte (edit, edit->last_byte - 1) != '\n'
406 && edit_query_dialog2 (_("Warning"),
407 _("The file you are saving is not finished with a newline"),
408 _("C&ontinue"), _("&Cancel")));
411 /* --------------------------------------------------------------------------------------------- */
413 static char *
414 edit_get_save_file_as (WEdit * edit)
416 #define DLG_WIDTH 64
417 #define DLG_HEIGHT 14
419 static LineBreaks cur_lb = LB_ASIS;
421 char *filename = edit->filename;
423 const char *lb_names[LB_NAMES] = {
424 N_("&Do not change"),
425 N_("&Unix format (LF)"),
426 N_("&Windows/DOS format (CR LF)"),
427 N_("&Macintosh format (CR)")
430 QuickWidget quick_widgets[] = {
431 QUICK_BUTTON (6, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
432 QUICK_BUTTON (2, 10, DLG_HEIGHT - 3, DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
433 QUICK_RADIO (5, DLG_WIDTH, DLG_HEIGHT - 8, DLG_HEIGHT, LB_NAMES, lb_names, (int *) &cur_lb),
434 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 9, DLG_HEIGHT, N_("Change line breaks to:")),
435 QUICK_INPUT (3, DLG_WIDTH, DLG_HEIGHT - 11, DLG_HEIGHT, filename, DLG_WIDTH - 6, 0,
436 "save-as", &filename),
437 QUICK_LABEL (3, DLG_WIDTH, DLG_HEIGHT - 12, DLG_HEIGHT, N_("Enter file name:")),
438 QUICK_END
441 QuickDialog Quick_options = {
442 DLG_WIDTH, DLG_HEIGHT, -1, -1,
443 N_("Save As"), "[Save File As]",
444 quick_widgets, NULL, FALSE
447 if (quick_dialog (&Quick_options) != B_CANCEL)
449 char *fname;
451 edit->lb = cur_lb;
452 fname = tilde_expand (filename);
453 g_free (filename);
454 return fname;
457 return NULL;
459 #undef DLG_WIDTH
460 #undef DLG_HEIGHT
463 /** returns 1 on success */
465 static int
466 edit_save_cmd (WEdit * edit)
468 int res, save_lock = 0;
470 if (!edit->locked && !edit->delete_file)
471 save_lock = edit_lock_file (edit);
472 res = edit_save_file (edit, edit->filename);
474 /* Maintain modify (not save) lock on failure */
475 if ((res > 0 && edit->locked) || save_lock)
476 edit->locked = edit_unlock_file (edit);
478 /* On failure try 'save as', it does locking on its own */
479 if (!res)
480 return edit_save_as_cmd (edit);
481 edit->force |= REDRAW_COMPLETELY;
482 if (res > 0)
484 edit->delete_file = 0;
485 edit->modified = 0;
488 return 1;
491 /* --------------------------------------------------------------------------------------------- */
492 /** returns 1 on error */
494 static int
495 edit_load_file_from_filename (WEdit * edit, char *exp)
497 int prev_locked = edit->locked;
498 char *prev_filename = g_strdup (edit->filename);
500 if (!edit_reload (edit, exp))
502 g_free (prev_filename);
503 return 1;
506 if (prev_locked)
508 char *fullpath;
510 fullpath = mc_build_filename (edit->dir, prev_filename, (char *) NULL);
511 unlock_file (fullpath);
512 g_free (fullpath);
514 g_free (prev_filename);
515 return 0;
518 /* --------------------------------------------------------------------------------------------- */
520 static void
521 edit_load_syntax_file (WEdit * edit)
523 char *extdir;
524 int dir = 0;
526 if (geteuid () == 0)
528 dir = query_dialog (_("Syntax file edit"),
529 _("Which syntax file you want to edit?"), D_NORMAL, 2,
530 _("&User"), _("&System Wide"));
533 extdir = g_build_filename (mc_global.sysconfig_dir, "syntax", "Syntax", (char *) NULL);
534 if (!exist_file (extdir))
536 g_free (extdir);
537 extdir = g_build_filename (mc_global.share_data_dir, "syntax", "Syntax", (char *) NULL);
540 if (dir == 0)
542 char *buffer;
544 buffer = mc_config_get_full_path (EDIT_SYNTAX_FILE);
545 check_for_default (extdir, buffer);
546 edit_load_file_from_filename (edit, buffer);
547 g_free (buffer);
549 else if (dir == 1)
550 edit_load_file_from_filename (edit, extdir);
552 g_free (extdir);
555 /* --------------------------------------------------------------------------------------------- */
557 static void
558 edit_load_menu_file (WEdit * edit)
560 char *buffer;
561 char *menufile;
562 int dir = 0;
564 dir = query_dialog (_("Menu edit"),
565 _("Which menu file do you want to edit?"), D_NORMAL,
566 geteuid () != 0 ? 2 : 3, _("&Local"), _("&User"), _("&System Wide"));
568 menufile = concat_dir_and_file (mc_global.sysconfig_dir, EDIT_GLOBAL_MENU);
570 if (!exist_file (menufile))
572 g_free (menufile);
573 menufile = concat_dir_and_file (mc_global.share_data_dir, EDIT_GLOBAL_MENU);
576 switch (dir)
578 case 0:
579 buffer = g_strdup (EDIT_LOCAL_MENU);
580 check_for_default (menufile, buffer);
581 chmod (buffer, 0600);
582 break;
584 case 1:
585 buffer = mc_config_get_full_path (EDIT_HOME_MENU);
586 check_for_default (menufile, buffer);
587 break;
589 case 2:
590 buffer = concat_dir_and_file (mc_global.sysconfig_dir, EDIT_GLOBAL_MENU);
591 if (!exist_file (buffer))
593 g_free (buffer);
594 buffer = concat_dir_and_file (mc_global.share_data_dir, EDIT_GLOBAL_MENU);
596 break;
598 default:
599 g_free (menufile);
600 return;
603 edit_load_file_from_filename (edit, buffer);
605 g_free (buffer);
606 g_free (menufile);
609 /* --------------------------------------------------------------------------------------------- */
611 static void
612 edit_delete_column_of_text (WEdit * edit)
614 long p, q, r, m1, m2;
615 long b, c, d, n;
617 eval_marks (edit, &m1, &m2);
618 n = edit_move_forward (edit, m1, 0, m2) + 1;
619 c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
620 d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
621 b = max (min (c, d), min (edit->column1, edit->column2));
622 c = max (c, max (edit->column1, edit->column2));
624 while (n--)
626 r = edit_bol (edit, edit->curs1);
627 p = edit_move_forward3 (edit, r, b, 0);
628 q = edit_move_forward3 (edit, r, c, 0);
629 if (p < m1)
630 p = m1;
631 if (q > m2)
632 q = m2;
633 edit_cursor_move (edit, p - edit->curs1);
634 while (q > p)
636 /* delete line between margins */
637 if (edit_get_byte (edit, edit->curs1) != '\n')
638 edit_delete (edit, 1);
639 q--;
641 if (n)
642 /* move to next line except on the last delete */
643 edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
647 /* --------------------------------------------------------------------------------------------- */
648 /** if success return 0 */
650 static int
651 edit_block_delete (WEdit * edit)
653 long count;
654 long start_mark, end_mark;
655 int curs_pos, line_width;
656 long curs_line, c1, c2;
658 if (eval_marks (edit, &start_mark, &end_mark))
659 return 0;
660 if (edit->column_highlight && edit->mark2 < 0)
661 edit_mark_cmd (edit, 0);
662 if ((end_mark - start_mark) > option_max_undo / 2)
664 /* Warning message with a query to continue or cancel the operation */
665 if (edit_query_dialog2
666 (_("Warning"),
668 ("Block is large, you may not be able to undo this action"),
669 _("C&ontinue"), _("&Cancel")))
671 return 1;
674 c1 = min (edit->column1, edit->column2);
675 c2 = max (edit->column1, edit->column2);
676 edit->column1 = c1;
677 edit->column2 = c2;
679 edit_push_markers (edit);
681 curs_line = edit->curs_line;
683 /* calculate line width and cursor position before cut */
684 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
685 edit_eol (edit, edit->curs1));
686 curs_pos = edit->curs_col + edit->over_col;
688 /* move cursor to start of selection */
689 edit_cursor_move (edit, start_mark - edit->curs1);
690 edit_scroll_screen_over_cursor (edit);
691 count = start_mark;
692 if (start_mark < end_mark)
694 if (edit->column_highlight)
696 if (edit->mark2 < 0)
697 edit_mark_cmd (edit, 0);
698 edit_delete_column_of_text (edit);
699 /* move cursor to the saved position */
700 edit_move_to_line (edit, curs_line);
701 /* calculate line width after cut */
702 line_width = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0,
703 edit_eol (edit, edit->curs1));
704 if (option_cursor_beyond_eol && curs_pos > line_width)
705 edit->over_col = curs_pos - line_width;
707 else
709 while (count < end_mark)
711 edit_delete (edit, 1);
712 count++;
716 edit_set_markers (edit, 0, 0, 0, 0);
717 edit->force |= REDRAW_PAGE;
718 return 0;
721 /* --------------------------------------------------------------------------------------------- */
723 * Get EOL symbol for searching.
725 * @param edit editor object
726 * @return EOL symbol
729 static inline char
730 edit_search_get_current_end_line_char (const WEdit * edit)
732 switch (edit->lb)
734 case LB_MAC:
735 return '\r';
736 default:
737 return '\n';
741 /* --------------------------------------------------------------------------------------------- */
743 * Checking if search condition have BOL(^) or EOL ($) regexp special characters.
745 * @param search search object
746 * @return result of checks.
749 static edit_search_line_t
750 edit_get_search_line_type (mc_search_t * search)
752 edit_search_line_t search_line_type = 0;
754 if (search->search_type != MC_SEARCH_T_REGEX)
755 return search_line_type;
757 if (*search->original == '^')
758 search_line_type |= AT_START_LINE;
760 if (search->original[search->original_len - 1] == '$')
761 search_line_type |= AT_END_LINE;
762 return search_line_type;
765 /* --------------------------------------------------------------------------------------------- */
767 * Calculating the start position of next line.
769 * @param edit editor object
770 * @param current_pos current position
771 * @param max_pos max position
772 * @param end_string_symbol end of line symbol
773 * @return start position of next line
776 static off_t
777 edit_calculate_start_of_next_line (WEdit * edit, off_t current_pos, off_t max_pos,
778 char end_string_symbol)
780 off_t i;
782 for (i = current_pos; i < max_pos; i++)
784 current_pos++;
785 if (edit_get_byte (edit, i) == end_string_symbol)
786 break;
789 return current_pos;
792 /* --------------------------------------------------------------------------------------------- */
794 * Calculating the end position of previous line.
796 * @param edit editor object
797 * @param current_pos current position
798 * @param end_string_symbol end of line symbol
799 * @return end position of previous line
802 static off_t
803 edit_calculate_end_of_previous_line (WEdit * edit, off_t current_pos, char end_string_symbol)
805 off_t i;
807 for (i = current_pos - 1; i >= 0; i--)
808 if (edit_get_byte (edit, i) == end_string_symbol)
809 break;
811 return i;
814 /* --------------------------------------------------------------------------------------------- */
816 * Calculating the start position of previous line.
818 * @param edit editor object
819 * @param current_pos current position
820 * @param end_string_symbol end of line symbol
821 * @return start position of previous line
824 static inline off_t
825 edit_calculate_start_of_previous_line (WEdit * edit, off_t current_pos, char end_string_symbol)
827 current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
828 current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
830 return (current_pos + 1);
833 /* --------------------------------------------------------------------------------------------- */
835 * Calculating the start position of current line.
837 * @param edit editor object
838 * @param current_pos current position
839 * @param end_string_symbol end of line symbol
840 * @return start position of current line
843 static inline off_t
844 edit_calculate_start_of_current_line (WEdit * edit, off_t current_pos, char end_string_symbol)
846 current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
848 return (current_pos + 1);
851 /* --------------------------------------------------------------------------------------------- */
853 * Fixing (if needed) search start position if 'only in selection' option present.
855 * @param edit editor object
858 static void
859 edit_search_fix_search_start_if_selection (WEdit * edit)
861 long start_mark = 0;
862 long end_mark = 0;
864 if (!edit_search_options.only_in_selection)
865 return;
867 if (eval_marks (edit, &start_mark, &end_mark) != 0)
868 return;
870 if (edit_search_options.backwards)
872 if (edit->search_start > end_mark || edit->search_start <= start_mark)
873 edit->search_start = end_mark;
875 else
877 if (edit->search_start < start_mark || edit->search_start >= end_mark)
878 edit->search_start = start_mark;
882 /* --------------------------------------------------------------------------------------------- */
884 static gboolean
885 editcmd_find (WEdit * edit, gsize * len)
887 off_t search_start = edit->search_start;
888 off_t search_end;
889 long start_mark = 0;
890 long end_mark = edit->last_byte;
891 int mark_res = 0;
892 char end_string_symbol;
894 end_string_symbol = edit_search_get_current_end_line_char (edit);
896 /* prepare for search */
897 if (edit_search_options.only_in_selection)
899 mark_res = eval_marks (edit, &start_mark, &end_mark);
900 if (mark_res != 0)
902 edit->search->error = MC_SEARCH_E_NOTFOUND;
903 edit->search->error_str = g_strdup (_("Search string not found"));
904 return FALSE;
907 /* fix the start and the end of search block positions */
908 if ((edit->search_line_type & AT_START_LINE) != 0
909 && (start_mark != 0 || edit_get_byte (edit, start_mark - 1) != end_string_symbol))
911 start_mark =
912 edit_calculate_start_of_next_line (edit, start_mark, edit->last_byte,
913 end_string_symbol);
915 if ((edit->search_line_type & AT_END_LINE) != 0
916 && (end_mark - 1 != edit->last_byte
917 || edit_get_byte (edit, end_mark) != end_string_symbol))
919 end_mark = edit_calculate_end_of_previous_line (edit, end_mark, end_string_symbol);
921 if (start_mark >= end_mark)
923 edit->search->error = MC_SEARCH_E_NOTFOUND;
924 edit->search->error_str = g_strdup (_("Search string not found"));
925 return FALSE;
928 else
930 if (edit_search_options.backwards)
931 end_mark = max (1, edit->curs1) - 1;
934 /* search */
935 if (edit_search_options.backwards)
937 /* backward search */
938 search_end = end_mark;
940 if ((edit->search_line_type & AT_START_LINE) != 0)
941 search_start =
942 edit_calculate_start_of_current_line (edit, search_start, end_string_symbol);
944 while ((int) search_start >= start_mark)
946 if (search_end > (off_t) (search_start + edit->search->original_len)
947 && mc_search_is_fixed_search_str (edit->search))
949 search_end = search_start + edit->search->original_len;
951 if (mc_search_run (edit->search, (void *) edit, search_start, search_end, len)
952 && edit->search->normal_offset == search_start)
954 return TRUE;
958 if ((edit->search_line_type & AT_START_LINE) != 0)
959 search_start =
960 edit_calculate_start_of_previous_line (edit, search_start, end_string_symbol);
961 else
962 search_start--;
964 edit->search->error_str = g_strdup (_("Search string not found"));
966 else
968 /* forward search */
969 if ((edit->search_line_type & AT_START_LINE) != 0 && search_start != start_mark)
970 search_start =
971 edit_calculate_start_of_next_line (edit, search_start, end_mark, end_string_symbol);
972 return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
974 return FALSE;
977 /* --------------------------------------------------------------------------------------------- */
979 static char *
980 edit_replace_cmd__conv_to_display (char *str)
982 #ifdef HAVE_CHARSET
983 GString *tmp;
985 tmp = str_convert_to_display (str);
986 if (tmp != NULL)
988 if (tmp->len != 0)
989 return g_string_free (tmp, FALSE);
990 g_string_free (tmp, TRUE);
992 #endif
993 return g_strdup (str);
996 /* --------------------------------------------------------------------------------------------- */
998 static char *
999 edit_replace_cmd__conv_to_input (char *str)
1001 #ifdef HAVE_CHARSET
1002 GString *tmp;
1004 tmp = str_convert_to_input (str);
1005 if (tmp != NULL)
1007 if (tmp->len != 0)
1008 return g_string_free (tmp, FALSE);
1009 g_string_free (tmp, TRUE);
1011 #endif
1012 return g_strdup (str);
1015 /* --------------------------------------------------------------------------------------------- */
1017 static void
1018 edit_do_search (WEdit * edit)
1020 gsize len = 0;
1022 if (edit->search == NULL)
1023 edit->search_start = edit->curs1;
1025 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
1027 if (search_create_bookmark)
1029 int found = 0, books = 0;
1030 long l = 0, l_last = -1;
1031 long q = 0;
1033 search_create_bookmark = FALSE;
1034 book_mark_flush (edit, -1);
1036 while (TRUE)
1038 if (!mc_search_run (edit->search, (void *) edit, q, edit->last_byte, &len))
1039 break;
1040 if (found == 0)
1041 edit->search_start = edit->search->normal_offset;
1042 found++;
1043 l += edit_count_lines (edit, q, edit->search->normal_offset);
1044 if (l != l_last)
1046 book_mark_insert (edit, l, BOOK_MARK_FOUND_COLOR);
1047 books++;
1049 l_last = l;
1050 q = edit->search->normal_offset + 1;
1053 if (found == 0)
1054 edit_error_dialog (_("Search"), _("Search string not found"));
1055 else
1056 edit_cursor_move (edit, edit->search_start - edit->curs1);
1058 else
1060 if (edit->found_len != 0 && edit->search_start == edit->found_start + 1
1061 && edit_search_options.backwards)
1062 edit->search_start--;
1064 if (edit->found_len != 0 && edit->search_start == edit->found_start - 1
1065 && !edit_search_options.backwards)
1066 edit->search_start++;
1068 if (editcmd_find (edit, &len))
1070 edit->found_start = edit->search_start = edit->search->normal_offset;
1071 edit->found_len = len;
1072 edit->over_col = 0;
1073 edit_cursor_move (edit, edit->search_start - edit->curs1);
1074 edit_scroll_screen_over_cursor (edit);
1075 if (edit_search_options.backwards)
1076 edit->search_start--;
1077 else
1078 edit->search_start++;
1080 else
1082 edit->search_start = edit->curs1;
1083 if (edit->search->error_str != NULL)
1084 edit_error_dialog (_("Search"), edit->search->error_str);
1088 edit->force |= REDRAW_COMPLETELY;
1089 edit_scroll_screen_over_cursor (edit);
1092 /* --------------------------------------------------------------------------------------------- */
1094 static void
1095 edit_search (WEdit * edit)
1097 if (editcmd_dialog_search_show (edit))
1099 edit->search_line_type = edit_get_search_line_type (edit->search);
1100 edit_search_fix_search_start_if_selection (edit);
1101 edit_do_search (edit);
1105 /* --------------------------------------------------------------------------------------------- */
1106 /** Return a null terminated length of text. Result must be g_free'd */
1108 static unsigned char *
1109 edit_get_block (WEdit * edit, long start, long finish, int *l)
1111 unsigned char *s, *r;
1112 r = s = g_malloc0 (finish - start + 1);
1113 if (edit->column_highlight)
1115 *l = 0;
1116 /* copy from buffer, excluding chars that are out of the column 'margins' */
1117 while (start < finish)
1119 int c;
1120 long x;
1121 x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
1122 c = edit_get_byte (edit, start);
1123 if ((x >= edit->column1 && x < edit->column2)
1124 || (x >= edit->column2 && x < edit->column1) || c == '\n')
1126 *s++ = c;
1127 (*l)++;
1129 start++;
1132 else
1134 *l = finish - start;
1135 while (start < finish)
1136 *s++ = edit_get_byte (edit, start++);
1138 *s = 0;
1139 return r;
1142 /* --------------------------------------------------------------------------------------------- */
1143 /** copies a block to clipboard file */
1145 static int
1146 edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
1148 int ret;
1149 gchar *tmp;
1150 tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
1151 ret = edit_save_block (edit, tmp, start, finish);
1152 g_free (tmp);
1153 return ret;
1156 /* --------------------------------------------------------------------------------------------- */
1158 static void
1159 pipe_mail (WEdit * edit, char *to, char *subject, char *cc)
1161 FILE *p = 0;
1162 char *s;
1164 to = name_quote (to, 0);
1165 subject = name_quote (subject, 0);
1166 cc = name_quote (cc, 0);
1167 s = g_strconcat ("mail -s ", subject, *cc ? " -c " : "", cc, " ", to, (char *) NULL);
1168 g_free (to);
1169 g_free (subject);
1170 g_free (cc);
1172 if (s)
1174 p = popen (s, "w");
1175 g_free (s);
1178 if (p)
1180 long i;
1181 for (i = 0; i < edit->last_byte; i++)
1182 fputc (edit_get_byte (edit, i), p);
1183 pclose (p);
1187 /* --------------------------------------------------------------------------------------------- */
1189 static gboolean
1190 is_break_char (char c)
1192 return (isspace (c) || strchr ("{}[]()<>=|/\\!?~-+`'\",.;:#$%^&*", c));
1195 /* --------------------------------------------------------------------------------------------- */
1196 /** find first character of current word */
1198 static int
1199 edit_find_word_start (WEdit * edit, long *word_start, gsize * word_len)
1201 int c, last;
1202 gsize i;
1204 /* return if at begin of file */
1205 if (edit->curs1 <= 0)
1206 return 0;
1208 c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
1209 /* return if not at end or in word */
1210 if (is_break_char (c))
1211 return 0;
1213 /* search start of word to be completed */
1214 for (i = 2;; i++)
1216 /* return if at begin of file */
1217 if ((gsize) edit->curs1 < i)
1218 return 0;
1220 last = c;
1221 c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
1223 if (is_break_char (c))
1225 /* return if word starts with digit */
1226 if (isdigit (last))
1227 return 0;
1229 *word_start = edit->curs1 - (i - 1); /* start found */
1230 *word_len = i - 1;
1231 break;
1234 /* success */
1235 return 1;
1238 /* --------------------------------------------------------------------------------------------- */
1240 * Get current word under cursor
1242 * @param edit editor object
1243 * @param srch mc_search object
1244 * @param word_start start word position
1246 * @return newly allocated string or NULL if no any words under cursor
1249 static char *
1250 edit_collect_completions_get_current_word (WEdit * edit, mc_search_t * srch, long word_start)
1252 gsize len = 0, i;
1253 GString *temp;
1255 if (!mc_search_run (srch, (void *) edit, word_start, edit->last_byte, &len))
1256 return NULL;
1258 temp = g_string_sized_new (len);
1260 for (i = 0; i < len; i++)
1262 int chr;
1264 chr = edit_get_byte (edit, word_start + i);
1265 if (!isspace (chr))
1266 g_string_append_c (temp, chr);
1269 return g_string_free (temp, temp->len == 0);
1272 /* --------------------------------------------------------------------------------------------- */
1273 /** collect the possible completions */
1275 static gsize
1276 edit_collect_completions (WEdit * edit, long word_start, gsize word_len,
1277 char *match_expr, struct selection *compl, gsize * num)
1279 gsize len = 0;
1280 gsize max_len = 0;
1281 gsize i;
1282 int skip;
1283 GString *temp;
1284 mc_search_t *srch;
1285 long last_byte, start = -1;
1286 char *current_word;
1288 srch = mc_search_new (match_expr, -1);
1289 if (srch == NULL)
1290 return 0;
1292 if (mc_config_get_bool
1293 (mc_main_config, CONFIG_APP_SECTION, "editor_wordcompletion_collect_entire_file", 0))
1295 last_byte = edit->last_byte;
1297 else
1299 last_byte = word_start;
1302 srch->search_type = MC_SEARCH_T_REGEX;
1303 srch->is_case_sensitive = TRUE;
1304 srch->search_fn = edit_search_cmd_callback;
1306 current_word = edit_collect_completions_get_current_word (edit, srch, word_start);
1308 temp = g_string_new ("");
1310 /* collect max MAX_WORD_COMPLETIONS completions */
1311 while (mc_search_run (srch, (void *) edit, start + 1, last_byte, &len))
1313 g_string_set_size (temp, 0);
1314 start = srch->normal_offset;
1316 /* add matched completion if not yet added */
1317 for (i = 0; i < len; i++)
1319 skip = edit_get_byte (edit, start + i);
1320 if (isspace (skip))
1321 continue;
1323 /* skip current word */
1324 if (start + (long) i == word_start)
1325 break;
1327 g_string_append_c (temp, skip);
1330 if (temp->len == 0)
1331 continue;
1333 if (current_word != NULL && strcmp (current_word, temp->str) == 0)
1334 continue;
1336 skip = 0;
1338 for (i = 0; i < *num; i++)
1340 if (strncmp
1341 ((char *) &compl[i].text[word_len],
1342 (char *) &temp->str[word_len], max (len, compl[i].len) - word_len) == 0)
1344 struct selection this = compl[i];
1345 for (++i; i < *num; i++)
1347 compl[i - 1] = compl[i];
1349 compl[*num - 1] = this;
1350 skip = 1;
1351 break; /* skip it, already added */
1354 if (skip != 0)
1355 continue;
1357 if (*num == MAX_WORD_COMPLETIONS)
1359 g_free (compl[0].text);
1360 for (i = 1; i < *num; i++)
1362 compl[i - 1] = compl[i];
1364 (*num)--;
1366 #ifdef HAVE_CHARSET
1368 GString *recoded;
1369 recoded = str_convert_to_display (temp->str);
1371 if (recoded && recoded->len)
1372 g_string_assign (temp, recoded->str);
1374 g_string_free (recoded, TRUE);
1376 #endif
1377 compl[*num].text = g_strdup (temp->str);
1378 compl[*num].len = temp->len;
1379 (*num)++;
1380 start += len;
1382 /* note the maximal length needed for the completion dialog */
1383 if (len > max_len)
1384 max_len = len;
1387 mc_search_free (srch);
1388 g_string_free (temp, TRUE);
1389 g_free (current_word);
1391 return max_len;
1394 /* --------------------------------------------------------------------------------------------- */
1396 static void
1397 edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width,
1398 long *start_pos, long *end_pos, int *col1, int *col2)
1400 long cursor;
1401 int i, col;
1403 cursor = edit->curs1;
1404 col = edit_get_col (edit);
1406 for (i = 0; i < size; i++)
1408 if (data[i] != '\n')
1409 edit_insert (edit, data[i]);
1410 else
1411 { /* fill in and move to next line */
1412 int l;
1413 long p;
1415 if (edit_get_byte (edit, edit->curs1) != '\n')
1417 l = width - (edit_get_col (edit) - col);
1418 while (l > 0)
1420 edit_insert (edit, ' ');
1421 l -= space_width;
1424 for (p = edit->curs1;; p++)
1426 if (p == edit->last_byte)
1428 edit_cursor_move (edit, edit->last_byte - edit->curs1);
1429 edit_insert_ahead (edit, '\n');
1430 p++;
1431 break;
1433 if (edit_get_byte (edit, p) == '\n')
1435 p++;
1436 break;
1439 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
1440 l = col - edit_get_col (edit);
1441 while (l >= space_width)
1443 edit_insert (edit, ' ');
1444 l -= space_width;
1449 *col1 = col;
1450 *col2 = col + width;
1451 *start_pos = cursor;
1452 *end_pos = edit->curs1;
1453 edit_cursor_move (edit, cursor - edit->curs1);
1456 /* --------------------------------------------------------------------------------------------- */
1458 static int
1459 edit_macro_comparator (gconstpointer * macro1, gconstpointer * macro2)
1461 const macros_t *m1 = (const macros_t *) macro1;
1462 const macros_t *m2 = (const macros_t *) macro2;
1464 return m1->hotkey - m2->hotkey;
1467 /* --------------------------------------------------------------------------------------------- */
1469 static void
1470 edit_macro_sort_by_hotkey (void)
1472 if (macros_list != NULL && macros_list->len != 0)
1473 g_array_sort (macros_list, (GCompareFunc) edit_macro_comparator);
1476 /* --------------------------------------------------------------------------------------------- */
1478 static gboolean
1479 edit_get_macro (WEdit * edit, int hotkey, const macros_t ** macros, guint * indx)
1481 const macros_t *array_start = &g_array_index (macros_list, struct macros_t, 0);
1482 macros_t *result;
1483 macros_t search_macro;
1485 (void) edit;
1487 search_macro.hotkey = hotkey;
1488 result = bsearch (&search_macro, macros_list->data, macros_list->len,
1489 sizeof (macros_t), (GCompareFunc) edit_macro_comparator);
1491 if (result != NULL && result->macro != NULL)
1493 *indx = (result - array_start);
1494 *macros = result;
1495 return TRUE;
1497 *indx = 0;
1498 return FALSE;
1501 /* --------------------------------------------------------------------------------------------- */
1502 /** returns FALSE on error */
1504 static gboolean
1505 edit_delete_macro (WEdit * edit, int hotkey)
1507 mc_config_t *macros_config = NULL;
1508 const char *section_name = "editor";
1509 gchar *macros_fname;
1510 guint indx;
1511 char *skeyname;
1512 const macros_t *macros = NULL;
1514 /* clear array of actions for current hotkey */
1515 while (edit_get_macro (edit, hotkey, &macros, &indx))
1517 if (macros->macro != NULL)
1518 g_array_free (macros->macro, TRUE);
1519 macros = NULL;
1520 g_array_remove_index (macros_list, indx);
1521 edit_macro_sort_by_hotkey ();
1524 macros_fname = mc_config_get_full_path (MC_MACRO_FILE);
1525 macros_config = mc_config_init (macros_fname);
1526 g_free (macros_fname);
1528 if (macros_config == NULL)
1529 return FALSE;
1531 skeyname = lookup_key_by_code (hotkey);
1532 while (mc_config_del_key (macros_config, section_name, skeyname))
1534 g_free (skeyname);
1535 mc_config_save_file (macros_config, NULL);
1536 mc_config_deinit (macros_config);
1537 return TRUE;
1541 /* --------------------------------------------------------------------------------------------- */
1542 /*** public functions ****************************************************************************/
1543 /* --------------------------------------------------------------------------------------------- */
1545 void
1546 edit_help_cmd (WEdit * edit)
1548 ev_help_t event_data = { NULL, "[Internal File Editor]" };
1549 mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
1551 edit->force |= REDRAW_COMPLETELY;
1554 /* --------------------------------------------------------------------------------------------- */
1556 void
1557 edit_refresh_cmd (WEdit * edit)
1559 #ifdef HAVE_SLANG
1560 int color;
1562 edit_get_syntax_color (edit, -1, &color);
1563 tty_touch_screen ();
1564 mc_refresh ();
1565 #else
1566 (void) edit;
1568 clr_scr ();
1569 repaint_screen ();
1570 #endif /* !HAVE_SLANG */
1571 tty_keypad (TRUE);
1574 /* --------------------------------------------------------------------------------------------- */
1576 void
1577 menu_save_mode_cmd (void)
1579 /* diaog sizes */
1580 const int DLG_X = 38;
1581 const int DLG_Y = 13;
1583 char *str_result;
1585 const char *str[] = {
1586 N_("&Quick save"),
1587 N_("&Safe save"),
1588 N_("&Do backups with following extension:")
1591 QuickWidget widgets[] = {
1592 /* 0 */
1593 QUICK_BUTTON (18, DLG_X, DLG_Y - 3, DLG_Y, N_("&Cancel"), B_CANCEL, NULL),
1594 /* 1 */
1595 QUICK_BUTTON (6, DLG_X, DLG_Y - 3, DLG_Y, N_("&OK"), B_ENTER, NULL),
1596 /* 2 */
1597 QUICK_CHECKBOX (4, DLG_X, 8, DLG_Y, N_("Check &POSIX new line"), &option_check_nl_at_eof),
1598 /* 3 */
1599 QUICK_INPUT (8, DLG_X, 6, DLG_Y, option_backup_ext, 9, 0, "edit-backup-ext", &str_result),
1600 /* 4 */
1601 QUICK_RADIO (4, DLG_X, 3, DLG_Y, 3, str, &option_save_mode),
1602 QUICK_END
1605 QuickDialog dialog = {
1606 DLG_X, DLG_Y, -1, -1, N_("Edit Save Mode"),
1607 "[Edit Save Mode]", widgets, NULL, FALSE
1610 size_t i;
1611 size_t maxlen = 0;
1612 size_t w0, w1, b_len, w3;
1614 #ifdef HAVE_ASSERT_H
1615 assert (option_backup_ext != NULL);
1616 #endif
1618 /* OK/Cancel buttons */
1619 w0 = str_term_width1 (_(widgets[0].u.button.text)) + 3;
1620 w1 = str_term_width1 (_(widgets[1].u.button.text)) + 5; /* default button */
1621 b_len = w0 + w1 + 3;
1623 maxlen = max (b_len, (size_t) str_term_width1 (_(dialog.title)) + 2);
1625 w3 = 0;
1626 for (i = 0; i < 3; i++)
1628 #ifdef ENABLE_NLS
1629 str[i] = _(str[i]);
1630 #endif
1631 w3 = max (w3, (size_t) str_term_width1 (str[i]));
1634 maxlen = max (maxlen, w3 + 4);
1636 dialog.xlen = min ((size_t) COLS, maxlen + 8);
1638 widgets[3].u.input.len = w3;
1639 widgets[1].relative_x = (dialog.xlen - b_len) / 2;
1640 widgets[0].relative_x = widgets[1].relative_x + w0 + 2;
1642 for (i = 0; i < sizeof (widgets) / sizeof (widgets[0]); i++)
1643 widgets[i].x_divisions = dialog.xlen;
1645 if (quick_dialog (&dialog) != B_CANCEL)
1647 g_free (option_backup_ext);
1648 option_backup_ext = str_result;
1652 /* --------------------------------------------------------------------------------------------- */
1654 void
1655 edit_set_filename (WEdit * edit, const char *name)
1657 g_free (edit->filename);
1659 if (name == NULL)
1660 name = "";
1662 edit->filename = tilde_expand (name);
1663 if (edit->dir == NULL && !g_path_is_absolute (name))
1664 edit->dir = vfs_get_current_dir ();
1667 /* --------------------------------------------------------------------------------------------- */
1668 /* Here we want to warn the users of overwriting an existing file,
1669 but only if they have made a change to the filename */
1670 /* returns 1 on success */
1672 edit_save_as_cmd (WEdit * edit)
1674 /* This heads the 'Save As' dialog box */
1675 char *exp;
1676 int save_lock = 0;
1677 int different_filename = 0;
1679 if (!edit_check_newline (edit))
1680 return 0;
1682 exp = edit_get_save_file_as (edit);
1683 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
1685 if (exp)
1687 if (!*exp)
1689 g_free (exp);
1690 edit->force |= REDRAW_COMPLETELY;
1691 return 0;
1693 else
1695 int rv;
1697 if (strcmp (edit->filename, exp))
1699 int file;
1700 vfs_path_t *tmp_vpath;
1701 struct stat sb;
1703 tmp_vpath = vfs_path_from_str (exp);
1704 if (mc_stat (tmp_vpath, &sb) == 0 && !S_ISREG (sb.st_mode))
1706 edit_error_dialog (_("Save as"),
1707 get_sys_error (_
1708 ("Cannot save: destination is not a regular file")));
1709 g_free (exp);
1710 edit->force |= REDRAW_COMPLETELY;
1711 vfs_path_free (tmp_vpath);
1712 return 0;
1715 different_filename = 1;
1716 file = mc_open (tmp_vpath, O_RDONLY | O_BINARY);
1717 vfs_path_free (tmp_vpath);
1718 if (file != -1)
1720 /* the file exists */
1721 mc_close (file);
1722 /* Overwrite the current file or cancel the operation */
1723 if (edit_query_dialog2
1724 (_("Warning"),
1725 _("A file already exists with this name"), _("&Overwrite"), _("&Cancel")))
1727 edit->force |= REDRAW_COMPLETELY;
1728 g_free (exp);
1729 return 0;
1732 else
1734 edit->stat1.st_mode |= S_IWUSR;
1736 save_lock = lock_file (exp);
1738 else
1740 /* filenames equal, check if already locked */
1741 if (!edit->locked && !edit->delete_file)
1742 save_lock = lock_file (exp);
1745 if (different_filename)
1748 * Allow user to write into saved (under another name) file
1749 * even if original file had r/o user permissions.
1751 edit->stat1.st_mode |= S_IWRITE;
1754 rv = edit_save_file (edit, exp);
1755 switch (rv)
1757 case 1:
1758 /* Succesful, so unlock both files */
1759 if (different_filename)
1761 if (save_lock)
1762 unlock_file (exp);
1763 if (edit->locked)
1764 edit->locked = edit_unlock_file (edit);
1766 else
1768 if (edit->locked || save_lock)
1769 edit->locked = edit_unlock_file (edit);
1772 edit_set_filename (edit, exp);
1773 if (edit->lb != LB_ASIS)
1774 edit_reload (edit, exp);
1775 g_free (exp);
1776 edit->modified = 0;
1777 edit->delete_file = 0;
1778 if (different_filename)
1779 edit_load_syntax (edit, NULL, edit->syntax_type);
1780 edit->force |= REDRAW_COMPLETELY;
1781 return 1;
1782 default:
1783 edit_error_dialog (_("Save as"), get_sys_error (_("Cannot save file")));
1784 /* fallthrough */
1785 case -1:
1786 /* Failed, so maintain modify (not save) lock */
1787 if (save_lock)
1788 unlock_file (exp);
1789 g_free (exp);
1790 edit->force |= REDRAW_COMPLETELY;
1791 return 0;
1795 edit->force |= REDRAW_COMPLETELY;
1796 return 0;
1799 /* {{{ Macro stuff starts here */
1800 /* --------------------------------------------------------------------------------------------- */
1802 void
1803 edit_delete_macro_cmd (WEdit * edit)
1805 int hotkey;
1807 hotkey = editcmd_dialog_raw_key_query (_("Delete macro"), _("Press macro hotkey:"), 1);
1809 if (hotkey != 0 && !edit_delete_macro (edit, hotkey))
1810 message (D_ERROR, _("Delete macro"), _("Macro not deleted"));
1813 /* --------------------------------------------------------------------------------------------- */
1815 /** returns FALSE on error */
1816 gboolean
1817 edit_execute_macro (WEdit * edit, int hotkey)
1819 gboolean res = FALSE;
1821 if (hotkey != 0)
1823 const macros_t *macros;
1824 guint indx;
1826 if (edit_get_macro (edit, hotkey, &macros, &indx) &&
1827 macros->macro != NULL && macros->macro->len != 0)
1829 guint i;
1831 edit->force |= REDRAW_PAGE;
1833 for (i = 0; i < macros->macro->len; i++)
1835 const macro_action_t *m_act;
1837 m_act = &g_array_index (macros->macro, struct macro_action_t, i);
1838 edit_execute_cmd (edit, m_act->action, m_act->ch);
1839 res = TRUE;
1844 return res;
1847 /* --------------------------------------------------------------------------------------------- */
1849 /** returns FALSE on error */
1850 gboolean
1851 edit_store_macro_cmd (WEdit * edit)
1853 int i;
1854 int hotkey;
1855 GString *marcros_string;
1856 mc_config_t *macros_config = NULL;
1857 const char *section_name = "editor";
1858 gchar *macros_fname;
1859 GArray *macros; /* current macro */
1860 int tmp_act;
1861 gboolean have_macro = FALSE;
1862 char *skeyname = NULL;
1864 hotkey = editcmd_dialog_raw_key_query (_("Save macro"), _("Press the macro's new hotkey:"), 1);
1865 if (hotkey == ESC_CHAR)
1866 return FALSE;
1868 tmp_act = keybind_lookup_keymap_command (editor_map, hotkey);
1870 /* return FALSE if try assign macro into restricted hotkeys */
1871 if (tmp_act == CK_MacroStartRecord
1872 || tmp_act == CK_MacroStopRecord || tmp_act == CK_MacroStartStopRecord)
1873 return FALSE;
1875 edit_delete_macro (edit, hotkey);
1877 macros_fname = mc_config_get_full_path (MC_MACRO_FILE);
1878 macros_config = mc_config_init (macros_fname);
1879 g_free (macros_fname);
1881 if (macros_config == NULL)
1882 return FALSE;
1884 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
1886 marcros_string = g_string_sized_new (250);
1887 macros = g_array_new (TRUE, FALSE, sizeof (macro_action_t));
1889 skeyname = lookup_key_by_code (hotkey);
1891 for (i = 0; i < macro_index; i++)
1893 macro_action_t m_act;
1894 const char *action_name;
1896 action_name = keybind_lookup_actionname (record_macro_buf[i].action);
1898 if (action_name == NULL)
1899 break;
1901 m_act.action = record_macro_buf[i].action;
1902 m_act.ch = record_macro_buf[i].ch;
1903 g_array_append_val (macros, m_act);
1904 have_macro = TRUE;
1905 g_string_append_printf (marcros_string, "%s:%i;", action_name,
1906 (int) record_macro_buf[i].ch);
1908 if (have_macro)
1910 macros_t macro;
1911 macro.hotkey = hotkey;
1912 macro.macro = macros;
1913 g_array_append_val (macros_list, macro);
1914 mc_config_set_string (macros_config, section_name, skeyname, marcros_string->str);
1916 else
1917 mc_config_del_key (macros_config, section_name, skeyname);
1919 g_free (skeyname);
1920 edit_macro_sort_by_hotkey ();
1922 g_string_free (marcros_string, TRUE);
1923 mc_config_save_file (macros_config, NULL);
1924 mc_config_deinit (macros_config);
1925 return TRUE;
1928 /* --------------------------------------------------------------------------------------------- */
1930 gboolean
1931 edit_repeat_macro_cmd (WEdit * edit)
1933 int i, j;
1934 char *f;
1935 long count_repeat;
1936 char *error = NULL;
1938 f = input_dialog (_("Repeat last commands"), _("Repeat times:"), MC_HISTORY_EDIT_REPEAT, NULL);
1939 if (f == NULL || *f == '\0')
1941 g_free (f);
1942 return FALSE;
1945 count_repeat = strtol (f, &error, 0);
1947 if (*error != '\0')
1949 g_free (f);
1950 return FALSE;
1953 g_free (f);
1955 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
1956 edit->force |= REDRAW_PAGE;
1958 for (j = 0; j < count_repeat; j++)
1959 for (i = 0; i < macro_index; i++)
1960 edit_execute_cmd (edit, record_macro_buf[i].action, record_macro_buf[i].ch);
1961 edit_update_screen (edit);
1962 return TRUE;
1965 /* --------------------------------------------------------------------------------------------- */
1966 /** return FALSE on error */
1968 gboolean
1969 edit_load_macro_cmd (WEdit * edit)
1971 mc_config_t *macros_config = NULL;
1972 gchar **profile_keys, **keys;
1973 gchar **values, **curr_values;
1974 gsize len, values_len;
1975 const char *section_name = "editor";
1976 gchar *macros_fname;
1977 int hotkey;
1979 (void) edit;
1981 macros_fname = mc_config_get_full_path (MC_MACRO_FILE);
1982 macros_config = mc_config_init (macros_fname);
1983 g_free (macros_fname);
1985 if (macros_config == NULL)
1986 return FALSE;
1988 profile_keys = keys = mc_config_get_keys (macros_config, section_name, &len);
1989 while (*profile_keys != NULL)
1991 gboolean have_macro;
1992 GArray *macros;
1993 macros_t macro;
1995 macros = g_array_new (TRUE, FALSE, sizeof (macro_action_t));
1997 curr_values = values = mc_config_get_string_list (macros_config, section_name,
1998 *profile_keys, &values_len);
1999 hotkey = lookup_key (*profile_keys, NULL);
2000 have_macro = FALSE;
2002 while (*curr_values != NULL && *curr_values[0] != '\0')
2004 char **macro_pair = NULL;
2006 macro_pair = g_strsplit (*curr_values, ":", 2);
2008 if (macro_pair != NULL)
2010 macro_action_t m_act;
2011 if (macro_pair[0] == NULL || macro_pair[0][0] == '\0')
2012 m_act.action = 0;
2013 else
2015 m_act.action = keybind_lookup_action (macro_pair[0]);
2016 g_free (macro_pair[0]);
2017 macro_pair[0] = NULL;
2019 if (macro_pair[1] == NULL || macro_pair[1][0] == '\0')
2020 m_act.ch = -1;
2021 else
2023 m_act.ch = strtol (macro_pair[1], NULL, 0);
2024 g_free (macro_pair[1]);
2025 macro_pair[1] = NULL;
2027 if (m_act.action != 0)
2029 /* a shell command */
2030 if ((m_act.action / CK_PipeBlock (0)) == 1)
2032 m_act.action = CK_PipeBlock (0) + (m_act.ch > 0 ? m_act.ch : 0);
2033 m_act.ch = -1;
2035 g_array_append_val (macros, m_act);
2036 have_macro = TRUE;
2038 g_strfreev (macro_pair);
2039 macro_pair = NULL;
2041 curr_values++;
2043 if (have_macro)
2045 macro.hotkey = hotkey;
2046 macro.macro = macros;
2047 g_array_append_val (macros_list, macro);
2049 profile_keys++;
2050 g_strfreev (values);
2052 g_strfreev (keys);
2053 mc_config_deinit (macros_config);
2054 edit_macro_sort_by_hotkey ();
2055 return TRUE;
2058 /* }}} Macro stuff end here */
2060 /* --------------------------------------------------------------------------------------------- */
2061 /** returns 1 on success */
2064 edit_save_confirm_cmd (WEdit * edit)
2066 gchar *f = NULL;
2068 if (!edit_check_newline (edit))
2069 return 0;
2071 if (edit_confirm_save)
2073 f = g_strdup_printf (_("Confirm save file: \"%s\""), edit->filename);
2074 if (edit_query_dialog2 (_("Save file"), f, _("&Save"), _("&Cancel")))
2076 g_free (f);
2077 return 0;
2079 g_free (f);
2081 return edit_save_cmd (edit);
2084 /* --------------------------------------------------------------------------------------------- */
2085 /** returns 1 on success */
2088 edit_new_cmd (WEdit * edit)
2090 if (edit->modified)
2092 if (edit_query_dialog2
2093 (_("Warning"),
2095 ("Current text was modified without a file save.\nContinue discards these changes"),
2096 _("C&ontinue"), _("&Cancel")))
2098 edit->force |= REDRAW_COMPLETELY;
2099 return 0;
2102 edit->force |= REDRAW_COMPLETELY;
2104 return edit_renew (edit); /* if this gives an error, something has really screwed up */
2107 /* --------------------------------------------------------------------------------------------- */
2110 edit_load_cmd (WEdit * edit, edit_current_file_t what)
2112 char *exp;
2114 if (edit->modified
2115 && (edit_query_dialog2
2116 (_("Warning"),
2117 _("Current text was modified without a file save.\n"
2118 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")) == 1))
2120 edit->force |= REDRAW_COMPLETELY;
2121 return 0;
2124 switch (what)
2126 case EDIT_FILE_COMMON:
2127 exp = input_expand_dialog (_("Load"), _("Enter file name:"),
2128 MC_HISTORY_EDIT_LOAD, edit->filename);
2130 if (exp)
2132 if (*exp)
2133 edit_load_file_from_filename (edit, exp);
2134 g_free (exp);
2136 break;
2138 case EDIT_FILE_SYNTAX:
2139 edit_load_syntax_file (edit);
2140 break;
2142 case EDIT_FILE_MENU:
2143 edit_load_menu_file (edit);
2144 break;
2146 default:
2147 break;
2150 edit->force |= REDRAW_COMPLETELY;
2151 return 0;
2154 /* --------------------------------------------------------------------------------------------- */
2156 if mark2 is -1 then marking is from mark1 to the cursor.
2157 Otherwise its between the markers. This handles this.
2158 Returns 1 if no text is marked.
2162 eval_marks (WEdit * edit, long *start_mark, long *end_mark)
2164 if (edit->mark1 != edit->mark2)
2166 long start_bol, start_eol;
2167 long end_bol, end_eol;
2168 long col1, col2;
2169 long diff1, diff2;
2170 long end_mark_curs;
2172 if (edit->end_mark_curs < 0)
2173 end_mark_curs = edit->curs1;
2174 else
2175 end_mark_curs = edit->end_mark_curs;
2177 if (edit->mark2 >= 0)
2179 *start_mark = min (edit->mark1, edit->mark2);
2180 *end_mark = max (edit->mark1, edit->mark2);
2182 else
2184 *start_mark = min (edit->mark1, end_mark_curs);
2185 *end_mark = max (edit->mark1, end_mark_curs);
2186 edit->column2 = edit->curs_col + edit->over_col;
2189 if (edit->column_highlight
2190 && (((edit->mark1 > end_mark_curs) && (edit->column1 < edit->column2))
2191 || ((edit->mark1 < end_mark_curs) && (edit->column1 > edit->column2))))
2193 start_bol = edit_bol (edit, *start_mark);
2194 start_eol = edit_eol (edit, start_bol - 1) + 1;
2195 end_bol = edit_bol (edit, *end_mark);
2196 end_eol = edit_eol (edit, *end_mark);
2197 col1 = min (edit->column1, edit->column2);
2198 col2 = max (edit->column1, edit->column2);
2200 diff1 =
2201 edit_move_forward3 (edit, start_bol, col2, 0) - edit_move_forward3 (edit, start_bol,
2202 col1, 0);
2203 diff2 =
2204 edit_move_forward3 (edit, end_bol, col2, 0) - edit_move_forward3 (edit, end_bol,
2205 col1, 0);
2207 *start_mark -= diff1;
2208 *end_mark += diff2;
2209 *start_mark = max (*start_mark, start_eol);
2210 *end_mark = min (*end_mark, end_eol);
2212 return 0;
2214 else
2216 *start_mark = *end_mark = 0;
2217 edit->column2 = edit->column1 = 0;
2218 return 1;
2222 /* --------------------------------------------------------------------------------------------- */
2224 void
2225 edit_insert_over (WEdit * edit)
2227 int i;
2229 for (i = 0; i < edit->over_col; i++)
2231 edit_insert (edit, ' ');
2233 edit->over_col = 0;
2236 /* --------------------------------------------------------------------------------------------- */
2239 edit_insert_column_of_text_from_file (WEdit * edit, int file,
2240 long *start_pos, long *end_pos, int *col1, int *col2)
2242 long cursor;
2243 int col;
2244 int blocklen = -1, width = 0;
2245 unsigned char *data;
2247 cursor = edit->curs1;
2248 col = edit_get_col (edit);
2249 data = g_malloc0 (TEMP_BUF_LEN);
2251 while ((blocklen = mc_read (file, (char *) data, TEMP_BUF_LEN)) > 0)
2253 int i;
2254 for (width = 0; width < blocklen; width++)
2256 if (data[width] == '\n')
2257 break;
2259 for (i = 0; i < blocklen; i++)
2261 if (data[i] == '\n')
2262 { /* fill in and move to next line */
2263 int l;
2264 long p;
2265 if (edit_get_byte (edit, edit->curs1) != '\n')
2267 l = width - (edit_get_col (edit) - col);
2268 while (l > 0)
2270 edit_insert (edit, ' ');
2271 l -= space_width;
2274 for (p = edit->curs1;; p++)
2276 if (p == edit->last_byte)
2278 edit_cursor_move (edit, edit->last_byte - edit->curs1);
2279 edit_insert_ahead (edit, '\n');
2280 p++;
2281 break;
2283 if (edit_get_byte (edit, p) == '\n')
2285 p++;
2286 break;
2289 edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
2290 l = col - edit_get_col (edit);
2291 while (l >= space_width)
2293 edit_insert (edit, ' ');
2294 l -= space_width;
2296 continue;
2298 edit_insert (edit, data[i]);
2301 *col1 = col;
2302 *col2 = col + width;
2303 *start_pos = cursor;
2304 *end_pos = edit->curs1;
2305 edit_cursor_move (edit, cursor - edit->curs1);
2306 g_free (data);
2308 return blocklen;
2311 /* --------------------------------------------------------------------------------------------- */
2313 void
2314 edit_block_copy_cmd (WEdit * edit)
2316 long start_mark, end_mark, current = edit->curs1;
2317 long col_delta = 0;
2318 long mark1, mark2;
2319 int c1, c2;
2320 int size;
2321 unsigned char *copy_buf;
2323 edit_update_curs_col (edit);
2324 if (eval_marks (edit, &start_mark, &end_mark))
2325 return;
2327 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
2329 /* all that gets pushed are deletes hence little space is used on the stack */
2331 edit_push_markers (edit);
2333 if (edit->column_highlight)
2335 col_delta = abs (edit->column2 - edit->column1);
2336 edit_insert_column_of_text (edit, copy_buf, size, col_delta, &mark1, &mark2, &c1, &c2);
2338 else
2340 while (size--)
2341 edit_insert_ahead (edit, copy_buf[size]);
2344 g_free (copy_buf);
2345 edit_scroll_screen_over_cursor (edit);
2347 if (edit->column_highlight)
2348 edit_set_markers (edit, edit->curs1, mark2, c1, c2);
2349 else if (start_mark < current && end_mark > current)
2350 edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
2352 edit->force |= REDRAW_PAGE;
2356 /* --------------------------------------------------------------------------------------------- */
2358 void
2359 edit_block_move_cmd (WEdit * edit)
2361 long current;
2362 unsigned char *copy_buf = NULL;
2363 long start_mark, end_mark;
2364 long line;
2366 if (eval_marks (edit, &start_mark, &end_mark))
2367 return;
2369 line = edit->curs_line;
2370 if (edit->mark2 < 0)
2371 edit_mark_cmd (edit, 0);
2372 edit_push_markers (edit);
2374 if (edit->column_highlight)
2376 long mark1, mark2;
2377 int size;
2378 int b_width = 0;
2379 int c1, c2;
2380 int x, x2;
2382 c1 = min (edit->column1, edit->column2);
2383 c2 = max (edit->column1, edit->column2);
2384 b_width = (c2 - c1);
2386 edit_update_curs_col (edit);
2388 x = edit->curs_col;
2389 x2 = x + edit->over_col;
2391 /* do nothing when cursor inside first line of selected area */
2392 if ((edit_eol (edit, edit->curs1) == edit_eol (edit, start_mark)) && (x2 > c1 && x2 <= c2))
2393 return;
2395 if (edit->curs1 > start_mark && edit->curs1 < edit_eol (edit, end_mark))
2397 if (x > c2)
2398 x -= b_width;
2399 else if (x > c1 && x <= c2)
2400 x = c1;
2402 /* save current selection into buffer */
2403 copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
2405 /* remove current selection */
2406 edit_block_delete_cmd (edit);
2408 edit->over_col = max (0, edit->over_col - b_width);
2409 /* calculate the cursor pos after delete block */
2410 current = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), x, 0);
2411 edit_cursor_move (edit, current - edit->curs1);
2412 edit_scroll_screen_over_cursor (edit);
2414 /* add TWS if need before block insertion */
2415 if (option_cursor_beyond_eol && edit->over_col > 0)
2416 edit_insert_over (edit);
2418 edit_insert_column_of_text (edit, copy_buf, size, b_width, &mark1, &mark2, &c1, &c2);
2419 edit_set_markers (edit, mark1, mark2, c1, c2);
2421 else
2423 long count;
2425 current = edit->curs1;
2426 copy_buf = g_malloc0 (end_mark - start_mark);
2427 edit_cursor_move (edit, start_mark - edit->curs1);
2428 edit_scroll_screen_over_cursor (edit);
2429 count = start_mark;
2430 while (count < end_mark)
2432 copy_buf[end_mark - count - 1] = edit_delete (edit, 1);
2433 count++;
2435 edit_scroll_screen_over_cursor (edit);
2436 edit_cursor_move (edit,
2437 current - edit->curs1 -
2438 (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
2439 edit_scroll_screen_over_cursor (edit);
2440 while (count-- > start_mark)
2441 edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
2442 edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
2445 edit_scroll_screen_over_cursor (edit);
2446 g_free (copy_buf);
2447 edit->force |= REDRAW_PAGE;
2450 /* --------------------------------------------------------------------------------------------- */
2451 /** returns 1 if canceelled by user */
2454 edit_block_delete_cmd (WEdit * edit)
2456 long start_mark, end_mark;
2457 if (eval_marks (edit, &start_mark, &end_mark))
2459 edit_delete_line (edit);
2460 return 0;
2462 return edit_block_delete (edit);
2465 /* --------------------------------------------------------------------------------------------- */
2466 /** call with edit = 0 before shutdown to close memory leaks */
2468 void
2469 edit_replace_cmd (WEdit * edit, int again)
2471 /* 1 = search string, 2 = replace with */
2472 static char *saved1 = NULL; /* saved default[123] */
2473 static char *saved2 = NULL;
2474 char *input1 = NULL; /* user input from the dialog */
2475 char *input2 = NULL;
2476 GString *input2_str = NULL;
2477 char *disp1 = NULL;
2478 char *disp2 = NULL;
2479 long times_replaced = 0;
2480 gboolean once_found = FALSE;
2482 if (!edit)
2484 g_free (saved1), saved1 = NULL;
2485 g_free (saved2), saved2 = NULL;
2486 return;
2489 edit->force |= REDRAW_COMPLETELY;
2491 if (again && !saved1 && !saved2)
2492 again = 0;
2494 if (again)
2496 input1 = g_strdup (saved1 ? saved1 : "");
2497 input2 = g_strdup (saved2 ? saved2 : "");
2499 else
2501 char *tmp_inp1, *tmp_inp2;
2503 disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
2504 disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
2506 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
2508 editcmd_dialog_replace_show (edit, disp1, disp2, &input1, &input2);
2510 g_free (disp1);
2511 g_free (disp2);
2513 if (input1 == NULL || *input1 == '\0')
2515 edit->force = REDRAW_COMPLETELY;
2516 goto cleanup;
2519 tmp_inp1 = input1;
2520 tmp_inp2 = input2;
2521 input1 = edit_replace_cmd__conv_to_input (input1);
2522 input2 = edit_replace_cmd__conv_to_input (input2);
2523 g_free (tmp_inp1);
2524 g_free (tmp_inp2);
2526 g_free (saved1), saved1 = g_strdup (input1);
2527 g_free (saved2), saved2 = g_strdup (input2);
2529 mc_search_free (edit->search);
2530 edit->search = NULL;
2533 input2_str = g_string_new (input2);
2535 if (!edit->search)
2537 edit->search = mc_search_new (input1, -1);
2538 if (edit->search == NULL)
2540 edit->search_start = edit->curs1;
2541 goto cleanup;
2543 edit->search->search_type = edit_search_options.type;
2544 edit->search->is_all_charsets = edit_search_options.all_codepages;
2545 edit->search->is_case_sensitive = edit_search_options.case_sens;
2546 edit->search->whole_words = edit_search_options.whole_words;
2547 edit->search->search_fn = edit_search_cmd_callback;
2548 edit->search_line_type = edit_get_search_line_type (edit->search);
2549 edit_search_fix_search_start_if_selection (edit);
2552 if (edit->found_len && edit->search_start == edit->found_start + 1
2553 && edit_search_options.backwards)
2554 edit->search_start--;
2556 if (edit->found_len && edit->search_start == edit->found_start - 1
2557 && !edit_search_options.backwards)
2558 edit->search_start++;
2562 gsize len = 0;
2564 if (!editcmd_find (edit, &len))
2566 if (!(edit->search->error == MC_SEARCH_E_OK ||
2567 (once_found && edit->search->error == MC_SEARCH_E_NOTFOUND)))
2569 edit_error_dialog (_("Search"), edit->search->error_str);
2571 break;
2573 once_found = TRUE;
2575 edit->search_start = edit->search->normal_offset;
2576 /*returns negative on not found or error in pattern */
2578 if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
2580 gsize i;
2581 GString *repl_str;
2583 edit->found_start = edit->search_start;
2584 i = edit->found_len = len;
2586 edit_cursor_move (edit, edit->search_start - edit->curs1);
2587 edit_scroll_screen_over_cursor (edit);
2589 if (edit->replace_mode == 0)
2591 int l;
2592 int prompt;
2594 l = edit->curs_row - edit->widget.lines / 3;
2595 if (l > 0)
2596 edit_scroll_downward (edit, l);
2597 if (l < 0)
2598 edit_scroll_upward (edit, -l);
2600 edit_scroll_screen_over_cursor (edit);
2601 edit->force |= REDRAW_PAGE;
2602 edit_render_keypress (edit);
2604 /*so that undo stops at each query */
2605 edit_push_key_press (edit);
2606 /* and prompt 2/3 down */
2607 disp1 = edit_replace_cmd__conv_to_display (saved1);
2608 disp2 = edit_replace_cmd__conv_to_display (saved2);
2609 prompt = editcmd_dialog_replace_prompt_show (edit, disp1, disp2, -1, -1);
2610 g_free (disp1);
2611 g_free (disp2);
2613 if (prompt == B_REPLACE_ALL)
2614 edit->replace_mode = 1;
2615 else if (prompt == B_SKIP_REPLACE)
2617 if (edit_search_options.backwards)
2618 edit->search_start--;
2619 else
2620 edit->search_start++;
2621 continue; /* loop */
2623 else if (prompt == B_CANCEL)
2625 edit->replace_mode = -1;
2626 break; /* loop */
2630 repl_str = mc_search_prepare_replace_str (edit->search, input2_str);
2632 if (edit->search->error != MC_SEARCH_E_OK)
2634 edit_error_dialog (_("Replace"), edit->search->error_str);
2635 g_string_free (repl_str, TRUE);
2636 break;
2639 /* delete then insert new */
2640 for (i = 0; i < len; i++)
2641 edit_delete (edit, 1);
2643 for (i = 0; i < repl_str->len; i++)
2644 edit_insert (edit, repl_str->str[i]);
2646 edit->found_len = repl_str->len;
2647 g_string_free (repl_str, TRUE);
2648 times_replaced++;
2650 /* so that we don't find the same string again */
2651 if (edit_search_options.backwards)
2653 edit->search_start--;
2655 else
2657 edit->search_start += edit->found_len + (len == 0 ? 1 : 0);
2659 if (edit->search_start >= edit->last_byte)
2660 break;
2663 edit_scroll_screen_over_cursor (edit);
2665 else
2667 /* try and find from right here for next search */
2668 edit->search_start = edit->curs1;
2669 edit_update_curs_col (edit);
2671 edit->force |= REDRAW_PAGE;
2672 edit_render_keypress (edit);
2674 if (times_replaced == 0)
2675 query_dialog (_("Replace"), _("Search string not found"), D_NORMAL, 1, _("&OK"));
2676 break;
2679 while (edit->replace_mode >= 0);
2681 edit_scroll_screen_over_cursor (edit);
2682 edit->force |= REDRAW_COMPLETELY;
2683 edit_render_keypress (edit);
2685 if ((edit->replace_mode == 1) && (times_replaced != 0))
2686 message (D_NORMAL, _("Replace"), _("%ld replacements made"), times_replaced);
2688 cleanup:
2689 g_free (input1);
2690 g_free (input2);
2691 if (input2_str != NULL)
2692 g_string_free (input2_str, TRUE);
2695 /* --------------------------------------------------------------------------------------------- */
2698 edit_search_cmd_callback (const void *user_data, gsize char_offset)
2700 return edit_get_byte ((WEdit *) user_data, (long) char_offset);
2703 /* --------------------------------------------------------------------------------------------- */
2705 void
2706 edit_search_cmd (WEdit * edit, gboolean again)
2709 if (edit == NULL)
2710 return;
2712 if (!again)
2713 edit_search (edit);
2714 else if (edit->last_search_string != NULL)
2715 edit_do_search (edit);
2716 else
2718 /* find last search string in history */
2719 GList *history;
2721 history = history_get (MC_HISTORY_SHARED_SEARCH);
2722 if (history != NULL && history->data != NULL)
2724 edit->last_search_string = (char *) history->data;
2725 history->data = NULL;
2726 history = g_list_first (history);
2727 g_list_foreach (history, (GFunc) g_free, NULL);
2728 g_list_free (history);
2730 edit->search = mc_search_new (edit->last_search_string, -1);
2731 if (edit->search == NULL)
2733 /* if not... then ask for an expression */
2734 g_free (edit->last_search_string);
2735 edit->last_search_string = NULL;
2736 edit_search (edit);
2738 else
2740 edit->search->search_type = edit_search_options.type;
2741 edit->search->is_all_charsets = edit_search_options.all_codepages;
2742 edit->search->is_case_sensitive = edit_search_options.case_sens;
2743 edit->search->whole_words = edit_search_options.whole_words;
2744 edit->search->search_fn = edit_search_cmd_callback;
2745 edit->search_line_type = edit_get_search_line_type (edit->search);
2746 edit_do_search (edit);
2749 else
2751 /* if not... then ask for an expression */
2752 g_free (edit->last_search_string);
2753 edit->last_search_string = NULL;
2754 edit_search (edit);
2760 /* --------------------------------------------------------------------------------------------- */
2762 * Check if it's OK to close the editor. If there are unsaved changes,
2763 * ask user. Return 1 if it's OK to exit, 0 to continue editing.
2766 gboolean
2767 edit_ok_to_exit (WEdit * edit)
2769 int act;
2771 if (!edit->modified)
2772 return TRUE;
2774 if (!mc_global.midnight_shutdown)
2776 if (!edit_check_newline (edit))
2777 return FALSE;
2779 query_set_sel (2);
2780 act = edit_query_dialog3 (_("Quit"), _("File was modified. Save with exit?"),
2781 _("&Yes"), _("&No"), _("&Cancel quit"));
2783 else
2785 act =
2786 edit_query_dialog2 (_("Quit"),
2787 _("Midnight Commander is being shut down.\nSave modified file?"),
2788 _("&Yes"), _("&No"));
2790 /* Esc is No */
2791 if (act == -1)
2792 act = 1;
2795 switch (act)
2797 case 0: /* Yes */
2798 edit_push_markers (edit);
2799 edit_set_markers (edit, 0, 0, 0, 0);
2800 if (!edit_save_cmd (edit) || mc_global.midnight_shutdown)
2801 return mc_global.midnight_shutdown;
2802 break;
2803 case 1: /* No */
2804 break;
2805 case 2: /* Cancel quit */
2806 case -1: /* Esc */
2807 return FALSE;
2810 return TRUE;
2813 /* --------------------------------------------------------------------------------------------- */
2814 /** save block, returns 1 on success */
2817 edit_save_block (WEdit * edit, const char *filename, long start, long finish)
2819 int len, file;
2820 vfs_path_t *vpath;
2822 vpath = vfs_path_from_str (filename);
2823 file = mc_open (vpath, O_CREAT | O_WRONLY | O_TRUNC,
2824 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | O_BINARY);
2825 vfs_path_free (vpath);
2826 if (file == -1)
2827 return 0;
2829 if (edit->column_highlight)
2831 int r;
2833 r = mc_write (file, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC));
2834 if (r > 0)
2836 unsigned char *block, *p;
2838 p = block = edit_get_block (edit, start, finish, &len);
2839 while (len)
2841 r = mc_write (file, p, len);
2842 if (r < 0)
2843 break;
2844 p += r;
2845 len -= r;
2847 g_free (block);
2850 else
2852 unsigned char *buf;
2853 int i = start, end;
2855 len = finish - start;
2856 buf = g_malloc0 (TEMP_BUF_LEN);
2857 while (start != finish)
2859 end = min (finish, start + TEMP_BUF_LEN);
2860 for (; i < end; i++)
2861 buf[i - start] = edit_get_byte (edit, i);
2862 len -= mc_write (file, (char *) buf, end - start);
2863 start = end;
2865 g_free (buf);
2867 mc_close (file);
2868 if (len)
2869 return 0;
2870 return 1;
2873 /* --------------------------------------------------------------------------------------------- */
2875 void
2876 edit_paste_from_history (WEdit * edit)
2878 (void) edit;
2879 edit_error_dialog (_("Error"), _("This function is not implemented"));
2882 /* --------------------------------------------------------------------------------------------- */
2885 edit_copy_to_X_buf_cmd (WEdit * edit)
2887 long start_mark, end_mark;
2888 if (eval_marks (edit, &start_mark, &end_mark))
2889 return 0;
2890 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2892 edit_error_dialog (_("Copy to clipboard"), get_sys_error (_("Unable to save to file")));
2893 return 1;
2895 /* try use external clipboard utility */
2896 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", NULL);
2898 return 0;
2901 /* --------------------------------------------------------------------------------------------- */
2904 edit_cut_to_X_buf_cmd (WEdit * edit)
2906 long start_mark, end_mark;
2907 if (eval_marks (edit, &start_mark, &end_mark))
2908 return 0;
2909 if (!edit_save_block_to_clip_file (edit, start_mark, end_mark))
2911 edit_error_dialog (_("Cut to clipboard"), _("Unable to save to file"));
2912 return 1;
2914 /* try use external clipboard utility */
2915 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", NULL);
2917 edit_block_delete_cmd (edit);
2918 edit_mark_cmd (edit, 1);
2919 return 0;
2922 /* --------------------------------------------------------------------------------------------- */
2924 void
2925 edit_paste_from_X_buf_cmd (WEdit * edit)
2927 gchar *tmp;
2928 /* try use external clipboard utility */
2929 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_from_ext_clip", NULL);
2930 tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
2931 edit_insert_file (edit, tmp);
2932 g_free (tmp);
2936 /* --------------------------------------------------------------------------------------------- */
2938 * Ask user for the line and go to that line.
2939 * Negative numbers mean line from the end (i.e. -1 is the last line).
2942 void
2943 edit_goto_cmd (WEdit * edit)
2945 char *f;
2946 static long line = 0; /* line as typed, saved as default */
2947 long l;
2948 char *error;
2949 char s[32];
2951 g_snprintf (s, sizeof (s), "%ld", line);
2952 f = input_dialog (_("Goto line"), _("Enter line:"), MC_HISTORY_EDIT_GOTO_LINE, line ? s : "");
2953 if (!f)
2954 return;
2956 if (!*f)
2958 g_free (f);
2959 return;
2962 l = strtol (f, &error, 0);
2963 if (*error)
2965 g_free (f);
2966 return;
2969 line = l;
2970 if (l < 0)
2971 l = edit->total_lines + l + 2;
2972 edit_move_display (edit, l - edit->widget.lines / 2 - 1);
2973 edit_move_to_line (edit, l - 1);
2974 edit->force |= REDRAW_COMPLETELY;
2975 g_free (f);
2979 /* --------------------------------------------------------------------------------------------- */
2980 /** Return 1 on success */
2983 edit_save_block_cmd (WEdit * edit)
2985 long start_mark, end_mark;
2986 char *exp, *tmp;
2988 if (eval_marks (edit, &start_mark, &end_mark))
2989 return 1;
2991 tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
2992 exp =
2993 input_expand_dialog (_("Save block"), _("Enter file name:"),
2994 MC_HISTORY_EDIT_SAVE_BLOCK, tmp);
2995 g_free (tmp);
2996 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
2997 if (exp)
2999 if (!*exp)
3001 g_free (exp);
3002 return 0;
3004 else
3006 if (edit_save_block (edit, exp, start_mark, end_mark))
3008 g_free (exp);
3009 edit->force |= REDRAW_COMPLETELY;
3010 return 1;
3012 else
3014 g_free (exp);
3015 edit_error_dialog (_("Save block"), get_sys_error (_("Cannot save file")));
3019 edit->force |= REDRAW_COMPLETELY;
3020 return 0;
3024 /* --------------------------------------------------------------------------------------------- */
3025 /** returns TRUE on success */
3027 gboolean
3028 edit_insert_file_cmd (WEdit * edit)
3030 gchar *tmp;
3031 char *exp;
3032 gboolean ret = FALSE;
3034 tmp = mc_config_get_full_path (EDIT_CLIP_FILE);
3035 exp = input_expand_dialog (_("Insert file"), _("Enter file name:"),
3036 MC_HISTORY_EDIT_INSERT_FILE, tmp);
3037 g_free (tmp);
3039 edit_push_undo_action (edit, KEY_PRESS + edit->start_display);
3041 if (exp != NULL && *exp != '\0')
3043 ret = (edit_insert_file (edit, exp) >= 0);
3044 if (!ret)
3045 edit_error_dialog (_("Insert file"), get_sys_error (_("Cannot insert file")));
3048 g_free (exp);
3050 edit->force |= REDRAW_COMPLETELY;
3051 return ret;
3054 /* --------------------------------------------------------------------------------------------- */
3055 /** sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
3058 edit_sort_cmd (WEdit * edit)
3060 static char *old = 0;
3061 char *exp, *tmp, *tmp_edit_block_name, *tmp_edit_temp_name;
3062 long start_mark, end_mark;
3063 int e;
3065 if (eval_marks (edit, &start_mark, &end_mark))
3067 edit_error_dialog (_("Sort block"), _("You must first highlight a block of text"));
3068 return 0;
3071 tmp = mc_config_get_full_path (EDIT_BLOCK_FILE);
3072 edit_save_block (edit, tmp, start_mark, end_mark);
3073 g_free (tmp);
3075 exp = input_dialog (_("Run sort"),
3076 _("Enter sort options (see manpage) separated by whitespace:"),
3077 MC_HISTORY_EDIT_SORT, (old != NULL) ? old : "");
3079 if (!exp)
3080 return 1;
3081 g_free (old);
3082 old = exp;
3083 tmp_edit_block_name = mc_config_get_full_path (EDIT_BLOCK_FILE);
3084 tmp_edit_temp_name = mc_config_get_full_path (EDIT_TEMP_FILE);
3085 tmp =
3086 g_strconcat (" sort ", exp, " ", tmp_edit_block_name,
3087 " > ", tmp_edit_temp_name, (char *) NULL);
3088 g_free (tmp_edit_temp_name);
3089 g_free (tmp_edit_block_name);
3091 e = system (tmp);
3092 g_free (tmp);
3093 if (e)
3095 if (e == -1 || e == 127)
3097 edit_error_dialog (_("Sort"), get_sys_error (_("Cannot execute sort command")));
3099 else
3101 char q[8];
3102 sprintf (q, "%d ", e);
3103 tmp = g_strdup_printf (_("Sort returned non-zero: %s"), q);
3104 edit_error_dialog (_("Sort"), tmp);
3105 g_free (tmp);
3107 return -1;
3110 edit->force |= REDRAW_COMPLETELY;
3112 if (edit_block_delete_cmd (edit))
3113 return 1;
3114 tmp = mc_config_get_full_path (EDIT_TEMP_FILE);
3115 edit_insert_file (edit, tmp);
3116 g_free (tmp);
3117 return 0;
3120 /* --------------------------------------------------------------------------------------------- */
3122 * Ask user for a command, execute it and paste its output back to the
3123 * editor.
3127 edit_ext_cmd (WEdit * edit)
3129 char *exp, *tmp, *tmp_edit_temp_file;
3130 int e;
3132 exp =
3133 input_dialog (_("Paste output of external command"),
3134 _("Enter shell command(s):"), MC_HISTORY_EDIT_PASTE_EXTCMD, NULL);
3136 if (!exp)
3137 return 1;
3139 tmp_edit_temp_file = mc_config_get_full_path (EDIT_TEMP_FILE);
3140 tmp = g_strconcat (exp, " > ", tmp_edit_temp_file, (char *) NULL);
3141 g_free (tmp_edit_temp_file);
3142 e = system (tmp);
3143 g_free (tmp);
3144 g_free (exp);
3146 if (e)
3148 edit_error_dialog (_("External command"), get_sys_error (_("Cannot execute command")));
3149 return -1;
3152 edit->force |= REDRAW_COMPLETELY;
3153 tmp = mc_config_get_full_path (EDIT_TEMP_FILE);
3154 edit_insert_file (edit, tmp);
3155 g_free (tmp);
3156 return 0;
3159 /* --------------------------------------------------------------------------------------------- */
3160 /** if block is 1, a block must be highlighted and the shell command
3161 processes it. If block is 0 the shell command is a straight system
3162 command, that just produces some output which is to be inserted */
3164 void
3165 edit_block_process_cmd (WEdit * edit, int macro_number)
3167 char *fname;
3168 char *macros_fname = NULL;
3170 fname = g_strdup_printf ("%s.%i.sh", MC_EXTMACRO_FILE, macro_number);
3171 macros_fname = g_build_filename (mc_config_get_data_path (), fname, (char *) NULL);
3172 user_menu (edit, macros_fname, 0);
3173 g_free (fname);
3174 g_free (macros_fname);
3175 edit->force |= REDRAW_COMPLETELY;
3178 /* --------------------------------------------------------------------------------------------- */
3180 void
3181 edit_mail_dialog (WEdit * edit)
3183 char *tmail_to;
3184 char *tmail_subject;
3185 char *tmail_cc;
3187 static char *mail_cc_last = 0;
3188 static char *mail_subject_last = 0;
3189 static char *mail_to_last = 0;
3191 QuickWidget quick_widgets[] = {
3192 /* 0 */ QUICK_BUTTON (6, 10, 9, MAIL_DLG_HEIGHT, N_("&Cancel"), B_CANCEL, NULL),
3193 /* 1 */ QUICK_BUTTON (2, 10, 9, MAIL_DLG_HEIGHT, N_("&OK"), B_ENTER, NULL),
3194 /* 2 */ QUICK_INPUT (3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input", &tmail_cc),
3195 /* 3 */ QUICK_LABEL (3, 50, 7, MAIL_DLG_HEIGHT, N_("Copies to")),
3196 /* 4 */ QUICK_INPUT (3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-2",
3197 &tmail_subject),
3198 /* 5 */ QUICK_LABEL (3, 50, 5, MAIL_DLG_HEIGHT, N_("Subject")),
3199 /* 6 */ QUICK_INPUT (3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, "mail-dlg-input-3", &tmail_to),
3200 /* 7 */ QUICK_LABEL (3, 50, 3, MAIL_DLG_HEIGHT, N_("To")),
3201 /* 8 */ QUICK_LABEL (3, 50, 2, MAIL_DLG_HEIGHT, N_("mail -s <subject> -c <cc> <to>")),
3202 QUICK_END
3205 QuickDialog Quick_input = {
3206 50, MAIL_DLG_HEIGHT, -1, -1, N_("Mail"),
3207 "[Input Line Keys]", quick_widgets, NULL, FALSE
3210 quick_widgets[2].u.input.text = mail_cc_last ? mail_cc_last : "";
3211 quick_widgets[4].u.input.text = mail_subject_last ? mail_subject_last : "";
3212 quick_widgets[6].u.input.text = mail_to_last ? mail_to_last : "";
3214 if (quick_dialog (&Quick_input) != B_CANCEL)
3216 g_free (mail_cc_last);
3217 g_free (mail_subject_last);
3218 g_free (mail_to_last);
3219 mail_cc_last = tmail_cc;
3220 mail_subject_last = tmail_subject;
3221 mail_to_last = tmail_to;
3222 pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
3227 /*******************/
3228 /* Word Completion */
3229 /*******************/
3231 /* --------------------------------------------------------------------------------------------- */
3233 * Complete current word using regular expression search
3234 * backwards beginning at the current cursor position.
3237 void
3238 edit_complete_word_cmd (WEdit * edit)
3240 gsize i, max_len, word_len = 0, num_compl = 0;
3241 long word_start = 0;
3242 unsigned char *bufpos;
3243 char *match_expr;
3244 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
3246 /* search start of word to be completed */
3247 if (!edit_find_word_start (edit, &word_start, &word_len))
3248 return;
3250 /* prepare match expression */
3251 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3253 /* match_expr = g_strdup_printf ("\\b%.*s[a-zA-Z_0-9]+", word_len, bufpos); */
3254 match_expr =
3255 g_strdup_printf
3256 ("(^|\\s+|\\b)%.*s[^\\s\\.=\\+\\[\\]\\(\\)\\,\\;\\:\\\"\\'\\-\\?\\/\\|\\\\\\{\\}\\*\\&\\^\\%%\\$#@\\!]+",
3257 (int) word_len, bufpos);
3259 /* collect the possible completions */
3260 /* start search from begin to end of file */
3261 max_len =
3262 edit_collect_completions (edit, word_start, word_len, match_expr,
3263 (struct selection *) &compl, &num_compl);
3265 if (num_compl > 0)
3267 /* insert completed word if there is only one match */
3268 if (num_compl == 1)
3270 for (i = word_len; i < compl[0].len; i++)
3271 edit_insert (edit, *(compl[0].text + i));
3273 /* more than one possible completion => ask the user */
3274 else
3276 /* !!! usually only a beep is expected and when <ALT-TAB> is !!! */
3277 /* !!! pressed again the selection dialog pops up, but that !!! */
3278 /* !!! seems to require a further internal state !!! */
3279 /*tty_beep (); */
3281 /* let the user select the preferred completion */
3282 editcmd_dialog_completion_show (edit, max_len, word_len,
3283 (struct selection *) &compl, num_compl);
3287 g_free (match_expr);
3288 /* release memory before return */
3289 for (i = 0; i < num_compl; i++)
3290 g_free (compl[i].text);
3293 /* --------------------------------------------------------------------------------------------- */
3295 void
3296 edit_select_codepage_cmd (WEdit * edit)
3298 #ifdef HAVE_CHARSET
3299 if (do_select_codepage ())
3300 edit_set_codeset (edit);
3302 edit->force = REDRAW_COMPLETELY;
3303 edit_refresh_cmd (edit);
3304 #else
3305 (void) edit;
3306 #endif
3309 /* --------------------------------------------------------------------------------------------- */
3311 void
3312 edit_insert_literal_cmd (WEdit * edit)
3314 int char_for_insertion = editcmd_dialog_raw_key_query (_("Insert literal"),
3315 _("Press any key:"), 0);
3316 edit_execute_key_command (edit, -1, ascii_alpha_to_cntrl (char_for_insertion));
3319 /* --------------------------------------------------------------------------------------------- */
3321 void
3322 edit_begin_end_macro_cmd (WEdit * edit)
3324 /* edit is a pointer to the widget */
3325 if (edit != NULL)
3327 unsigned long command = macro_index < 0 ? CK_MacroStartRecord : CK_MacroStopRecord;
3328 edit_execute_key_command (edit, command, -1);
3332 /* --------------------------------------------------------------------------------------------- */
3334 void
3335 edit_begin_end_repeat_cmd (WEdit * edit)
3337 /* edit is a pointer to the widget */
3338 if (edit != NULL)
3340 unsigned long command = macro_index < 0 ? CK_RepeatStartRecord : CK_RepeatStopRecord;
3341 edit_execute_key_command (edit, command, -1);
3345 /* --------------------------------------------------------------------------------------------- */
3348 edit_load_forward_cmd (WEdit * edit)
3350 if (edit->modified)
3352 if (edit_query_dialog2
3353 (_("Warning"),
3354 _("Current text was modified without a file save\n"
3355 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3357 edit->force |= REDRAW_COMPLETELY;
3358 return 0;
3361 if (edit_stack_iterator + 1 < MAX_HISTORY_MOVETO)
3363 if (edit_history_moveto[edit_stack_iterator + 1].line < 1)
3365 return 1;
3367 edit_stack_iterator++;
3368 if (edit_history_moveto[edit_stack_iterator].filename)
3370 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3371 edit_history_moveto[edit_stack_iterator].line);
3372 return 0;
3374 else
3376 return 1;
3379 else
3381 return 1;
3385 /* --------------------------------------------------------------------------------------------- */
3388 edit_load_back_cmd (WEdit * edit)
3390 if (edit->modified)
3392 if (edit_query_dialog2
3393 (_("Warning"),
3394 _("Current text was modified without a file save\n"
3395 "Continue discards these changes"), _("C&ontinue"), _("&Cancel")))
3397 edit->force |= REDRAW_COMPLETELY;
3398 return 0;
3401 if (edit_stack_iterator > 0)
3403 edit_stack_iterator--;
3404 if (edit_history_moveto[edit_stack_iterator].filename)
3406 edit_reload_line (edit, edit_history_moveto[edit_stack_iterator].filename,
3407 edit_history_moveto[edit_stack_iterator].line);
3408 return 0;
3410 else
3412 return 1;
3415 else
3417 return 1;
3421 /* --------------------------------------------------------------------------------------------- */
3423 void
3424 edit_get_match_keyword_cmd (WEdit * edit)
3426 gsize word_len = 0, max_len = 0;
3427 int num_def = 0;
3428 int i;
3429 long word_start = 0;
3430 unsigned char *bufpos;
3431 char *match_expr;
3432 char *path = NULL;
3433 char *ptr = NULL;
3434 char *tagfile = NULL;
3436 etags_hash_t def_hash[MAX_DEFINITIONS];
3438 for (i = 0; i < MAX_DEFINITIONS; i++)
3440 def_hash[i].filename = NULL;
3443 /* search start of word to be completed */
3444 if (!edit_find_word_start (edit, &word_start, &word_len))
3445 return;
3447 /* prepare match expression */
3448 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE][word_start & M_EDIT_BUF_SIZE];
3449 match_expr = g_strdup_printf ("%.*s", (int) word_len, bufpos);
3451 ptr = g_get_current_dir ();
3452 path = g_strconcat (ptr, G_DIR_SEPARATOR_S, (char *) NULL);
3453 g_free (ptr);
3455 /* Recursive search file 'TAGS' in parent dirs */
3458 ptr = g_path_get_dirname (path);
3459 g_free (path);
3460 path = ptr;
3461 g_free (tagfile);
3462 tagfile = mc_build_filename (path, TAGS_NAME, (char *) NULL);
3463 if (exist_file (tagfile))
3464 break;
3466 while (strcmp (path, G_DIR_SEPARATOR_S) != 0);
3468 if (tagfile)
3470 num_def =
3471 etags_set_definition_hash (tagfile, path, match_expr, (etags_hash_t *) & def_hash);
3472 g_free (tagfile);
3474 g_free (path);
3476 max_len = MAX_WIDTH_DEF_DIALOG;
3477 word_len = 0;
3478 if (num_def > 0)
3480 editcmd_dialog_select_definition_show (edit, match_expr, max_len, word_len,
3481 (etags_hash_t *) & def_hash, num_def);
3483 g_free (match_expr);
3486 /* --------------------------------------------------------------------------------------------- */