2 Editor initialisation and callback handler.
4 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
6 The Free Software Foundation, Inc.
10 Andrew Borodin <aborodin@vmail.ru> 2012, 2013
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 * \brief Source: editor initialisation and callback handler
40 #include <sys/types.h>
43 #include "lib/global.h"
45 #include "lib/tty/tty.h" /* LINES, COLS */
46 #include "lib/tty/key.h" /* is_idle() */
47 #include "lib/tty/color.h" /* tty_setcolor() */
49 #include "lib/strutil.h" /* str_term_trim() */
50 #include "lib/util.h" /* mc_build_filename() */
51 #include "lib/widget.h"
52 #include "lib/mcconfig.h"
53 #include "lib/event.h" /* mc_event_raise() */
55 #include "lib/charsets.h"
58 #include "src/keybind-defaults.h" /* keybind_lookup_keymap_command() */
59 #include "src/setup.h" /* home_dir */
60 #include "src/filemanager/cmd.h" /* view_other_cmd(), save_setup_cmd() */
61 #include "src/learn.h" /* learn_keys() */
62 #include "src/args.h" /* mcedit_arg_t */
64 #include "edit-impl.h"
65 #include "editwidget.h"
70 /*** global variables ****************************************************************************/
72 char *edit_window_state_char
= NULL
;
73 char *edit_window_close_char
= NULL
;
75 /*** file scope macro definitions ****************************************************************/
77 #define WINDOW_MIN_LINES (2 + 2)
78 #define WINDOW_MIN_COLS (2 + LINE_STATE_WIDTH + 2)
80 /*** file scope type declarations ****************************************************************/
82 /*** file scope variables ************************************************************************/
83 static unsigned int edit_dlg_init_refcounter
= 0;
85 /*** file scope functions ************************************************************************/
87 static cb_ret_t
edit_dialog_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
,
90 /* --------------------------------------------------------------------------------------------- */
92 * Init the 'edit' subsystem
98 if (edit_dlg_init_refcounter
== 0)
100 edit_window_state_char
= mc_skin_get ("editor", "window-state-char", "*");
101 edit_window_close_char
= mc_skin_get ("editor", "window-close-char", "X");
108 edit_dlg_init_refcounter
++;
111 /* --------------------------------------------------------------------------------------------- */
113 * Deinit the 'edit' subsystem
117 edit_dlg_deinit (void)
119 if (edit_dlg_init_refcounter
!= 0)
120 edit_dlg_init_refcounter
--;
122 if (edit_dlg_init_refcounter
== 0)
124 g_free (edit_window_state_char
);
125 g_free (edit_window_close_char
);
133 /* --------------------------------------------------------------------------------------------- */
135 * Show info about editor
141 quick_widget_t quick_widgets
[] = {
143 QUICK_LABEL ("MCEdit " VERSION
, NULL
),
144 QUICK_SEPARATOR (TRUE
),
145 QUICK_LABEL (N_("A user friendly text editor\n"
146 "written for the Midnight Commander."), NULL
),
147 QUICK_SEPARATOR (FALSE
),
148 QUICK_LABEL (N_("Copyright (C) 1996-2012 the Free Software Foundation"), NULL
),
149 QUICK_START_BUTTONS (TRUE
, TRUE
),
150 QUICK_BUTTON (N_("&OK"), B_ENTER
, NULL
, NULL
),
155 quick_dialog_t qdlg
= {
157 N_("About"), "[Internal File Editor]",
158 quick_widgets
, NULL
, NULL
161 quick_widgets
[0].pos_flags
= WPOS_KEEP_TOP
| WPOS_CENTER_HORZ
;
162 quick_widgets
[2].pos_flags
= WPOS_KEEP_TOP
| WPOS_CENTER_HORZ
;
163 quick_widgets
[4].pos_flags
= WPOS_KEEP_TOP
| WPOS_CENTER_HORZ
;
165 (void) quick_dialog (&qdlg
);
168 /* --------------------------------------------------------------------------------------------- */
176 ev_help_t event_data
= { NULL
, "[Internal File Editor]" };
177 mc_event_raise (MCEVENT_GROUP_CORE
, "help", &event_data
);
180 /* --------------------------------------------------------------------------------------------- */
182 * Callback for the iteration of objects in the 'editors' array.
183 * Resize the editor window.
185 * @param data probably WEdit object
186 * @param user_data unused
190 edit_dialog_resize_cb (void *data
, void *user_data
)
192 Widget
*w
= WIDGET (data
);
196 if (edit_widget_is_editor (w
) && ((WEdit
*) w
)->fullscreen
)
198 Widget
*wh
= WIDGET (w
->owner
);
200 w
->lines
= wh
->lines
- 2;
205 /* --------------------------------------------------------------------------------------------- */
207 * Restore saved window size.
209 * @param edit editor object
213 edit_restore_size (WEdit
* edit
)
215 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
216 widget_set_size (WIDGET (edit
), edit
->y_prev
, edit
->x_prev
, edit
->lines_prev
, edit
->cols_prev
);
217 dlg_redraw (WIDGET (edit
)->owner
);
220 /* --------------------------------------------------------------------------------------------- */
222 * Move window by one row or column in any direction.
224 * @param edit editor object
225 * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right)
229 edit_window_move (WEdit
* edit
, unsigned long command
)
231 Widget
*w
= WIDGET (edit
);
232 Widget
*wh
= WIDGET (w
->owner
);
237 if (w
->y
> wh
->y
+ 1) /* menubar */
241 if (w
->y
< wh
->y
+ wh
->lines
- 2) /* buttonbar */
245 if (w
->x
+ w
->cols
> wh
->x
)
249 if (w
->x
< wh
->x
+ wh
->cols
)
256 edit
->force
|= REDRAW_PAGE
;
257 dlg_redraw (w
->owner
);
260 /* --------------------------------------------------------------------------------------------- */
262 * Resize window by one row or column in any direction.
264 * @param edit editor object
265 * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right)
269 edit_window_resize (WEdit
* edit
, unsigned long command
)
271 Widget
*w
= WIDGET (edit
);
272 Widget
*wh
= WIDGET (w
->owner
);
277 if (w
->lines
> WINDOW_MIN_LINES
)
281 if (w
->y
+ w
->lines
< wh
->y
+ wh
->lines
- 1) /* buttonbar */
285 if (w
->cols
> WINDOW_MIN_COLS
)
289 if (w
->x
+ w
->cols
< wh
->x
+ wh
->cols
)
296 edit
->force
|= REDRAW_COMPLETELY
;
297 dlg_redraw (w
->owner
);
300 /* --------------------------------------------------------------------------------------------- */
302 * Get hotkey by number.
311 return (n
<= 9) ? '0' + n
: 'a' + n
- 10;
314 /* --------------------------------------------------------------------------------------------- */
317 edit_window_list (const WDialog
* h
)
319 const size_t offset
= 2; /* skip menu and buttonbar */
320 const size_t dlg_num
= g_list_length (h
->widgets
) - offset
;
327 lines
= min ((size_t) (LINES
* 2 / 3), dlg_num
);
330 listbox
= create_listbox_window (lines
, cols
, _("Open files"), "[Open files]");
332 for (w
= h
->widgets
; w
!= NULL
; w
= g_list_next (w
))
333 if (edit_widget_is_editor (WIDGET (w
->data
)))
335 WEdit
*e
= (WEdit
*) w
->data
;
338 if (e
->filename_vpath
== NULL
)
339 fname
= g_strdup_printf ("%c [%s]", e
->modified
? '*' : ' ', _("NoName"));
344 fname2
= vfs_path_to_str (e
->filename_vpath
);
345 fname
= g_strdup_printf ("%c%s", e
->modified
? '*' : ' ', fname2
);
349 listbox_add_item (listbox
->list
, LISTBOX_APPEND_AT_END
, get_hotkey (i
++),
350 str_term_trim (fname
, WIDGET (listbox
->list
)->cols
- 2), NULL
);
354 rv
= g_list_position (h
->widgets
, h
->current
) - offset
;
355 listbox_select_entry (listbox
->list
, rv
);
356 rv
= run_listbox (listbox
);
359 w
= g_list_nth (h
->widgets
, rv
+ offset
);
360 dlg_set_top_widget (w
->data
);
364 /* --------------------------------------------------------------------------------------------- */
367 edit_get_shortcut (unsigned long command
)
370 const char *shortcut
= NULL
;
372 shortcut
= keybind_lookup_keymap_shortcut (editor_map
, command
);
373 if (shortcut
!= NULL
)
374 return g_strdup (shortcut
);
376 ext_map
= keybind_lookup_keymap_shortcut (editor_map
, CK_ExtendedKeyMap
);
378 shortcut
= keybind_lookup_keymap_shortcut (editor_x_map
, command
);
379 if (shortcut
!= NULL
)
380 return g_strdup_printf ("%s %s", ext_map
, shortcut
);
385 /* --------------------------------------------------------------------------------------------- */
388 edit_get_title (const WDialog
* h
, size_t len
)
390 const WEdit
*edit
= find_editor (h
);
391 const char *modified
= edit
->modified
? "(*) " : " ";
392 const char *file_label
;
397 filename
= vfs_path_to_str (edit
->filename_vpath
);
398 if (filename
== NULL
)
399 filename
= g_strdup (_("[NoName]"));
400 file_label
= str_term_trim (filename
, len
- str_term_width1 (_("Edit: ")));
403 return g_strconcat (_("Edit: "), modified
, file_label
, (char *) NULL
);
406 /* --------------------------------------------------------------------------------------------- */
408 * Handle mouse events of editor window
410 * @param event mouse event
411 * @param data editor window
412 * @return MOU_NORMAL if event was handled, MOU_UNHANDLED otherwise
416 edit_event (Gpm_Event
* event
, void *data
)
418 WEdit
*edit
= (WEdit
*) data
;
419 Widget
*w
= WIDGET (data
);
422 if (!mouse_global_in_widget (event
, w
))
423 return MOU_UNHANDLED
;
425 local
= mouse_get_local (event
, w
);
427 /* Unknown event type */
428 if ((event
->type
& (GPM_DOWN
| GPM_DRAG
| GPM_UP
)) == 0)
431 dlg_set_top_widget (w
);
433 edit_update_curs_row (edit
);
434 edit_update_curs_col (edit
);
436 if (edit
->fullscreen
|| (local
.buttons
& GPM_B_LEFT
) == 0 || (local
.type
& GPM_UP
) != 0)
437 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
438 else if (local
.y
== 1 && edit
->drag_state
!= MCEDIT_DRAG_RESIZE
)
440 /* click on the top line (move) */
441 int dx
= edit
->fullscreen
? 0 : 2;
443 if (local
.x
== w
->cols
- dx
- 1)
445 send_message (w
->owner
, NULL
, MSG_ACTION
, CK_Close
, NULL
);
449 if (local
.x
== w
->cols
- dx
- 4)
451 edit_toggle_fullscreen (edit
);
455 if ((local
.type
& (GPM_DOWN
| GPM_DRAG
)) != 0)
457 /* move if not fullscreen */
458 edit
->drag_state_start
= local
.x
;
459 edit
->drag_state
= MCEDIT_DRAG_MOVE
;
460 edit
->force
|= REDRAW_COMPLETELY
;
461 edit_update_screen (edit
);
464 else if (!edit
->fullscreen
&& local
.y
== w
->lines
&& local
.x
== w
->cols
)
466 /* click on bottom-right corner (resize) */
467 if ((local
.type
& (GPM_DOWN
| GPM_DRAG
)) != 0)
469 edit
->drag_state
= MCEDIT_DRAG_RESIZE
;
470 edit
->force
|= REDRAW_COMPLETELY
;
471 edit_update_screen (edit
);
475 if (edit
->drag_state
== MCEDIT_DRAG_NORMAL
)
477 gboolean done
= TRUE
;
480 if ((local
.type
& (GPM_DOUBLE
| GPM_UP
)) == (GPM_UP
| GPM_DOUBLE
))
482 edit_mark_current_word_cmd (edit
);
487 if ((local
.type
& (GPM_TRIPLE
| GPM_UP
)) == (GPM_UP
| GPM_TRIPLE
))
489 edit_mark_current_line_cmd (edit
);
494 if ((local
.buttons
& GPM_B_UP
) != 0 && (local
.type
& GPM_DOWN
) != 0)
496 edit_move_up (edit
, 2, 1);
499 if ((local
.buttons
& GPM_B_DOWN
) != 0 && (local
.type
& GPM_DOWN
) != 0)
501 edit_move_down (edit
, 2, 1);
505 /* continue handle current event */
508 /* handle DRAG mouse event, don't use standard way to continue
509 * event handling outside of widget */
514 c
= tty_get_event (event
, FALSE
, TRUE
);
515 if (c
== EV_NONE
|| c
!= EV_MOUSE
)
518 local
= mouse_get_local (event
, w
);
521 /* A lone up mustn't do anything */
522 if (edit
->mark2
!= -1 && (local
.type
& (GPM_UP
| GPM_DRAG
)) != 0)
525 if ((local
.type
& (GPM_DOWN
| GPM_UP
)) != 0)
526 edit_push_key_press (edit
);
528 if (!edit
->fullscreen
)
530 if (!option_cursor_beyond_eol
)
531 edit
->prev_col
= local
.x
- edit
->start_col
- option_line_state_width
- 1;
534 long line_len
= edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), 0,
535 edit_eol (edit
, edit
->curs1
));
537 if (local
.x
> line_len
)
540 local
.x
- line_len
- edit
->start_col
- option_line_state_width
- 1;
541 edit
->prev_col
= line_len
;
546 edit
->prev_col
= local
.x
- option_line_state_width
- edit
->start_col
- 1;
550 if (!edit
->fullscreen
)
552 if (local
.y
> (edit
->curs_row
+ 1))
553 edit_move_down (edit
, local
.y
- (edit
->curs_row
+ 1), 0);
554 else if (local
.y
< (edit
->curs_row
+ 1))
555 edit_move_up (edit
, (edit
->curs_row
+ 1) - local
.y
, 0);
557 edit_move_to_prev_col (edit
, edit_bol (edit
, edit
->curs1
));
559 if ((local
.type
& GPM_DOWN
) != 0)
561 edit_mark_cmd (edit
, TRUE
); /* reset */
565 done
= (local
.type
& GPM_DRAG
) == 0;
567 edit_mark_cmd (edit
, FALSE
);
570 edit_find_bracket (edit
);
571 edit
->force
|= REDRAW_COMPLETELY
;
572 edit_update_curs_row (edit
);
573 edit_update_curs_col (edit
);
574 edit_update_screen (edit
);
576 while (!edit
->fullscreen
&& !done
);
579 while (edit
->drag_state
!= MCEDIT_DRAG_NORMAL
)
584 c
= tty_get_event (event
, FALSE
, TRUE
);
587 if (c
== EV_NONE
|| c
!= EV_MOUSE
)
590 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
591 edit
->force
|= REDRAW_COMPLETELY
;
592 edit_update_screen (edit
);
594 else if (y
== w
->y
&& (event
->type
& (GPM_DOUBLE
| GPM_UP
)) == (GPM_DOUBLE
| GPM_UP
))
596 /* double click on top line (toggle fullscreen) */
597 edit_toggle_fullscreen (edit
);
598 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
599 edit
->force
|= REDRAW_COMPLETELY
;
600 edit_update_screen (edit
);
602 else if ((event
->type
& (GPM_DRAG
| GPM_DOWN
)) == 0)
605 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
606 edit
->force
|= REDRAW_COMPLETELY
;
607 edit_update_screen (edit
);
609 else if (!edit
->fullscreen
)
611 Widget
*h
= WIDGET (w
->owner
);
613 if (edit
->drag_state
== MCEDIT_DRAG_MOVE
)
615 int x
= event
->x
- 1;
617 y
= max (y
, h
->y
+ 1); /* status line */
618 y
= min (y
, h
->y
+ h
->lines
- 2); /* buttonbar */
620 x
= min (x
, h
->x
+ h
->cols
- 1);
621 /* don't use widget_set_size() here to avoid double draw */
623 w
->x
= x
- edit
->drag_state_start
;
624 edit
->force
|= REDRAW_COMPLETELY
;
626 else if (edit
->drag_state
== MCEDIT_DRAG_RESIZE
)
628 event
->y
= min (event
->y
, h
->y
+ h
->lines
- 1); /* buttonbar */
629 event
->x
= min (event
->x
, h
->x
+ h
->cols
);
630 local
= mouse_get_local (event
, w
);
632 /* don't use widget_set_size() here to avoid double draw */
633 w
->lines
= max (WINDOW_MIN_LINES
, local
.y
);
634 w
->cols
= max (WINDOW_MIN_COLS
, local
.x
);
635 edit
->force
|= REDRAW_COMPLETELY
;
638 dlg_redraw (w
->owner
);
645 /* --------------------------------------------------------------------------------------------- */
647 * Handle mouse events of editor screen.
649 * @param event mouse event
650 * @param data editor screen
651 * @return MOU_NORMAL if event was handled, MOU_UNHANDLED otherwise
655 edit_dialog_event (Gpm_Event
* event
, void *data
)
657 WDialog
*h
= DIALOG (data
);
659 Widget
*wh
= WIDGET (h
);
660 int ret
= MOU_UNHANDLED
;
662 w
= WIDGET (find_menubar (h
));
664 if (event
->y
== wh
->y
+ 1 && (event
->type
& GPM_DOWN
) != 0 && !MENUBAR (w
)->is_active
)
672 /* Try find top fullscreen window */
673 for (l
= h
->widgets
; l
!= NULL
; l
= g_list_next (l
))
674 if (edit_widget_is_editor (WIDGET (l
->data
)) && ((WEdit
*) l
->data
)->fullscreen
)
677 /* Handle fullscreen/close buttons in the top line */
678 x
= wh
->x
+ wh
->cols
+ 1 - 6;
680 if (top
!= NULL
&& event
->x
>= x
)
684 e
= (WEdit
*) top
->data
;
687 if (top
!= h
->current
)
689 /* Window is not active. Activate it */
690 dlg_set_top_widget (e
);
695 edit_toggle_fullscreen (e
);
697 send_message (h
, NULL
, MSG_ACTION
, CK_Close
, NULL
);
702 if (ret
== MOU_UNHANDLED
)
703 dlg_select_widget (w
);
709 /* --------------------------------------------------------------------------------------------- */
712 edit_dialog_command_execute (WDialog
* h
, unsigned long command
)
714 Widget
*wh
= WIDGET (h
);
715 gboolean ret
= MSG_HANDLED
;
720 edit_add_window (h
, wh
->y
+ 1, wh
->x
, wh
->lines
- 2, wh
->cols
, NULL
, 0);
725 case CK_EditSyntaxFile
:
726 edit_load_syntax_file (h
);
728 case CK_EditUserMenu
:
729 edit_load_menu_file (h
);
732 /* if there are no opened files anymore, close MC editor */
733 if (edit_widget_is_editor (WIDGET (h
->current
->data
)) &&
734 edit_close_cmd ((WEdit
*) h
->current
->data
) && find_editor (h
) == NULL
)
739 /* edit->force |= REDRAW_COMPLETELY; */
747 Widget
*w
= WIDGET (h
->current
->data
);
749 if (!edit_widget_is_editor (w
) || ((WEdit
*) w
)->drag_state
== MCEDIT_DRAG_NORMAL
)
752 edit_restore_size ((WEdit
*) w
);
759 edit_syntax_onoff_cmd (h
);
762 edit_show_tabs_tws_cmd (h
);
765 edit_show_margin_cmd (h
);
768 edit_show_numbers_cmd (h
);
780 case CK_WindowResize
:
781 if (edit_widget_is_editor (WIDGET (h
->current
->data
)))
782 edit_handle_move_resize ((WEdit
*) h
->current
->data
, command
);
785 edit_window_list (h
);
789 dlg_set_top_widget (h
->current
->data
);
793 dlg_set_top_widget (h
->current
->data
);
796 edit_options_dialog (h
);
798 case CK_OptionsSaveMode
:
799 edit_save_mode_cmd ();
805 ret
= MSG_NOT_HANDLED
;
812 /* --------------------------------------------------------------------------------------------- */
814 * Translate the keycode into either 'command' or 'char_for_insertion'.
815 * 'command' is one of the editor commands from cmddef.h.
819 edit_translate_key (WEdit
* edit
, long x_key
, int *cmd
, int *ch
)
821 unsigned long command
= (unsigned long) CK_InsertChar
;
822 int char_for_insertion
= -1;
824 /* an ordinary insertable character */
825 if (!edit
->extmod
&& x_key
< 256)
828 if (is_printable (x_key
))
830 char_for_insertion
= x_key
;
836 if (edit
->charpoint
>= 4)
839 edit
->charbuf
[edit
->charpoint
] = '\0';
841 if (edit
->charpoint
< 4)
843 edit
->charbuf
[edit
->charpoint
++] = x_key
;
844 edit
->charbuf
[edit
->charpoint
] = '\0';
847 /* input from 8-bit locale */
848 if (!mc_global
.utf8_display
)
850 /* source in 8-bit codeset */
851 c
= convert_from_input_c (x_key
);
853 if (is_printable (c
))
856 char_for_insertion
= c
;
858 char_for_insertion
= convert_from_8bit_to_utf_c2 ((unsigned char) x_key
);
867 res
= str_is_valid_char (edit
->charbuf
, edit
->charpoint
);
868 if (res
< 0 && res
!= -2)
870 edit
->charpoint
= 0; /* broken multibyte char, skip */
876 /* source in UTF-8 codeset */
879 char_for_insertion
= x_key
;
883 edit
->charbuf
[edit
->charpoint
] = '\0';
885 if (g_unichar_isprint (g_utf8_get_char (edit
->charbuf
)))
887 char_for_insertion
= x_key
;
896 /* not finised multibyte input (in meddle multibyte utf-8 char) */
900 if (g_unichar_isprint (g_utf8_get_char (edit
->charbuf
)))
902 c
= convert_from_utf_to_current (edit
->charbuf
);
903 edit
->charbuf
[0] = '\0';
905 char_for_insertion
= c
;
909 /* unprinteble utf input, skip it */
910 edit
->charbuf
[0] = '\0';
914 #endif /* HAVE_CHARSET */
917 /* Commands specific to the key emulation */
920 edit
->extmod
= FALSE
;
921 command
= keybind_lookup_keymap_command (editor_x_map
, x_key
);
924 command
= keybind_lookup_keymap_command (editor_map
, x_key
);
926 if (command
== CK_IgnoreKey
)
927 command
= CK_InsertChar
;
930 *cmd
= (int) command
; /* FIXME */
931 *ch
= char_for_insertion
;
933 return !(command
== (unsigned long) CK_InsertChar
&& char_for_insertion
== -1);
937 /* --------------------------------------------------------------------------------------------- */
940 edit_quit (WDialog
* h
)
945 h
->state
= DLG_ACTIVE
; /* don't stop the dialog before final decision */
947 for (l
= h
->widgets
; l
!= NULL
; l
= g_list_next (l
))
948 if (edit_widget_is_editor (WIDGET (l
->data
)))
950 e
= (WEdit
*) l
->data
;
952 if (e
->drag_state
!= MCEDIT_DRAG_NORMAL
)
954 edit_restore_size (e
);
960 dlg_select_widget (e
);
962 if (!edit_ok_to_exit (e
))
967 /* no editors in dialog at all or no any file required to be saved */
968 if (e
== NULL
|| l
== NULL
)
969 h
->state
= DLG_CLOSED
;
972 /* --------------------------------------------------------------------------------------------- */
975 edit_set_buttonbar (WEdit
* edit
, WButtonBar
* bb
)
977 buttonbar_set_label (bb
, 1, Q_ ("ButtonBar|Help"), editor_map
, NULL
);
978 buttonbar_set_label (bb
, 2, Q_ ("ButtonBar|Save"), editor_map
, WIDGET (edit
));
979 buttonbar_set_label (bb
, 3, Q_ ("ButtonBar|Mark"), editor_map
, WIDGET (edit
));
980 buttonbar_set_label (bb
, 4, Q_ ("ButtonBar|Replac"), editor_map
, WIDGET (edit
));
981 buttonbar_set_label (bb
, 5, Q_ ("ButtonBar|Copy"), editor_map
, WIDGET (edit
));
982 buttonbar_set_label (bb
, 6, Q_ ("ButtonBar|Move"), editor_map
, WIDGET (edit
));
983 buttonbar_set_label (bb
, 7, Q_ ("ButtonBar|Search"), editor_map
, WIDGET (edit
));
984 buttonbar_set_label (bb
, 8, Q_ ("ButtonBar|Delete"), editor_map
, WIDGET (edit
));
985 buttonbar_set_label (bb
, 9, Q_ ("ButtonBar|PullDn"), editor_map
, NULL
);
986 buttonbar_set_label (bb
, 10, Q_ ("ButtonBar|Quit"), editor_map
, NULL
);
989 /* --------------------------------------------------------------------------------------------- */
990 /** Callback for the edit dialog */
993 edit_dialog_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
996 WButtonBar
*buttonbar
;
997 WDialog
*h
= DIALOG (w
);
1006 /* don't use dlg_default_repaint() -- we don't need a frame */
1007 tty_setcolor (EDITOR_BACKGROUND
);
1012 menubar
= find_menubar (h
);
1013 buttonbar
= find_buttonbar (h
);
1014 /* dlg_set_size() is surplus for this case */
1017 widget_set_size (WIDGET (buttonbar
), w
->lines
- 1, w
->x
, 1, w
->cols
);
1018 widget_set_size (WIDGET (menubar
), w
->y
, w
->x
, 1, w
->cols
);
1019 menubar_arrange (menubar
);
1020 g_list_foreach (h
->widgets
, (GFunc
) edit_dialog_resize_cb
, NULL
);
1026 return edit_dialog_command_execute (h
, parm
);
1027 /* message from menu */
1028 menubar
= find_menubar (h
);
1029 if (sender
== WIDGET (menubar
))
1031 if (edit_dialog_command_execute (h
, parm
) == MSG_HANDLED
)
1033 /* try send command to the current window */
1034 return send_message (h
->current
->data
, NULL
, MSG_ACTION
, parm
, NULL
);
1036 /* message from buttonbar */
1037 buttonbar
= find_buttonbar (h
);
1038 if (sender
== WIDGET (buttonbar
))
1041 return send_message (data
, NULL
, MSG_ACTION
, parm
, NULL
);
1042 return edit_dialog_command_execute (h
, parm
);
1044 return MSG_NOT_HANDLED
;
1048 Widget
*we
= WIDGET (h
->current
->data
);
1049 cb_ret_t ret
= MSG_NOT_HANDLED
;
1051 if (edit_widget_is_editor (we
))
1053 WEdit
*e
= (WEdit
*) we
;
1054 unsigned long command
;
1057 command
= keybind_lookup_keymap_command (editor_map
, parm
);
1061 command
= keybind_lookup_keymap_command (editor_x_map
, parm
);
1064 if (command
!= CK_IgnoreKey
)
1065 ret
= edit_dialog_command_execute (h
, command
);
1071 /* hardcoded menu hotkeys (see edit_drop_hotkey_menu) */
1072 case MSG_UNHANDLED_KEY
:
1073 return edit_drop_hotkey_menu (h
, parm
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
1084 return dlg_default_callback (w
, sender
, msg
, parm
, data
);
1088 /* --------------------------------------------------------------------------------------------- */
1091 edit_callback (Widget
* w
, Widget
* sender
, widget_msg_t msg
, int parm
, void *data
)
1093 WEdit
*e
= (WEdit
*) w
;
1098 edit_set_buttonbar (e
, find_buttonbar (w
->owner
));
1102 e
->force
|= REDRAW_COMPLETELY
;
1103 edit_update_screen (e
);
1107 /* redraw frame and status */
1108 edit_status (e
, FALSE
);
1114 cb_ret_t ret
= MSG_NOT_HANDLED
;
1116 /* The user may override the access-keys for the menu bar. */
1117 if (macro_index
== -1 && edit_execute_macro (e
, parm
))
1119 edit_update_screen (e
);
1122 else if (edit_translate_key (e
, parm
, &cmd
, &ch
))
1124 edit_execute_key_command (e
, cmd
, ch
);
1125 edit_update_screen (e
);
1133 /* command from menubar or buttonbar */
1134 edit_execute_key_command (e
, parm
, -1);
1135 edit_update_screen (e
);
1142 y
= (e
->fullscreen
? 0 : 1) + EDIT_TEXT_VERTICAL_OFFSET
+ e
->curs_row
;
1143 x
= (e
->fullscreen
? 0 : 1) + EDIT_TEXT_HORIZONTAL_OFFSET
+ option_line_state_width
+
1144 e
->curs_col
+ e
->start_col
+ e
->over_col
;
1146 widget_move (w
, y
, x
);
1155 return widget_default_callback (w
, sender
, msg
, parm
, data
);
1159 /* --------------------------------------------------------------------------------------------- */
1160 /*** public functions ****************************************************************************/
1161 /* --------------------------------------------------------------------------------------------- */
1165 * @param file_vpath file object
1166 * @param line line number
1167 * @return TRUE if no errors was occurred, FALSE otherwise
1171 edit_file (const vfs_path_t
* file_vpath
, long line
)
1173 mcedit_arg_t arg
= { (vfs_path_t
*) file_vpath
, line
};
1177 files
= g_list_prepend (NULL
, &arg
);
1178 ok
= edit_files (files
);
1179 g_list_free (files
);
1184 /* --------------------------------------------------------------------------------------------- */
1187 edit_files (const GList
* files
)
1189 static gboolean made_directory
= FALSE
;
1193 gboolean ok
= FALSE
;
1195 if (!made_directory
)
1199 dir
= mc_build_filename (mc_config_get_cache_path (), EDIT_DIR
, NULL
);
1200 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
1203 dir
= mc_build_filename (mc_config_get_path (), EDIT_DIR
, NULL
);
1204 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
1207 dir
= mc_build_filename (mc_config_get_data_path (), EDIT_DIR
, NULL
);
1208 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
1212 /* Create a new dialog and add it widgets to it */
1214 create_dlg (FALSE
, 0, 0, LINES
, COLS
, NULL
, edit_dialog_callback
, edit_dialog_event
,
1215 "[Internal File Editor]", NULL
, DLG_WANT_TAB
);
1217 edit_dlg
->get_shortcut
= edit_get_shortcut
;
1218 edit_dlg
->get_title
= edit_get_title
;
1220 menubar
= menubar_new (0, 0, COLS
, NULL
);
1221 add_widget (edit_dlg
, menubar
);
1222 edit_init_menu (menubar
);
1224 add_widget (edit_dlg
, buttonbar_new (TRUE
));
1226 for (file
= files
; file
!= NULL
; file
= g_list_next (file
))
1228 Widget
*w
= WIDGET (edit_dlg
);
1229 mcedit_arg_t
*f
= (mcedit_arg_t
*) file
->data
;
1232 f_ok
= edit_add_window (edit_dlg
, w
->y
+ 1, w
->x
, w
->lines
- 2, w
->cols
, f
->file_vpath
,
1234 /* at least one file has been opened succefully */
1241 if (!ok
|| edit_dlg
->state
== DLG_CLOSED
)
1242 destroy_dlg (edit_dlg
);
1247 /* --------------------------------------------------------------------------------------------- */
1250 edit_get_file_name (const WEdit
* edit
)
1252 return vfs_path_to_str (edit
->filename_vpath
);
1255 /* --------------------------------------------------------------------------------------------- */
1258 find_editor (const WDialog
* h
)
1260 if (edit_widget_is_editor (WIDGET (h
->current
->data
)))
1261 return (WEdit
*) h
->current
->data
;
1262 return (WEdit
*) find_widget_type (h
, edit_callback
);
1265 /* --------------------------------------------------------------------------------------------- */
1267 * Check if widget is an WEdit class.
1269 * @param w probably editor object
1270 * @return TRUE if widget is an WEdit class, FALSE otherwise
1274 edit_widget_is_editor (const Widget
* w
)
1276 return (w
!= NULL
&& w
->callback
== edit_callback
);
1279 /* --------------------------------------------------------------------------------------------- */
1282 edit_update_screen (WEdit
* e
)
1284 WDialog
*h
= WIDGET (e
)->owner
;
1286 edit_scroll_screen_over_cursor (e
);
1287 edit_update_curs_col (e
);
1289 edit_status (e
, (e
->force
& REDRAW_COMPLETELY
) != 0 && (void *) e
== h
->current
->data
);
1291 /* pop all events for this window for internal handling */
1293 e
->force
|= REDRAW_PAGE
;
1296 if ((e
->force
& REDRAW_COMPLETELY
) != 0)
1297 e
->force
|= REDRAW_PAGE
;
1298 edit_render_keypress (e
);
1301 widget_redraw (WIDGET (find_buttonbar (h
)));
1304 /* --------------------------------------------------------------------------------------------- */
1306 * Save current window size.
1308 * @param edit editor object
1312 edit_save_size (WEdit
* edit
)
1314 Widget
*w
= WIDGET (edit
);
1316 edit
->y_prev
= w
->y
;
1317 edit
->x_prev
= w
->x
;
1318 edit
->lines_prev
= w
->lines
;
1319 edit
->cols_prev
= w
->cols
;
1322 /* --------------------------------------------------------------------------------------------- */
1324 * Create new editor window and insert it into editor screen.
1326 * @param h editor dialog (screen)
1327 * @param y y coordinate
1328 * @param x x coordinate
1329 * @param lines window height
1330 * @param cols window width
1331 * @param f file object
1332 * @param fline line number in file
1333 * @return TRUE if new window was successfully created and inserted into editor screen,
1338 edit_add_window (WDialog
* h
, int y
, int x
, int lines
, int cols
, const vfs_path_t
* f
, long fline
)
1343 edit
= edit_init (NULL
, y
, x
, lines
, cols
, f
, fline
);
1348 w
->callback
= edit_callback
;
1349 w
->mouse
= edit_event
;
1357 /* --------------------------------------------------------------------------------------------- */
1359 * Handle move/resize events.
1361 * @param edit editor object
1362 * @param command action id
1363 * @return TRUE if mouse actions was handled, FALSE otherwise
1367 edit_handle_move_resize (WEdit
* edit
, unsigned long command
)
1369 gboolean ret
= FALSE
;
1371 if (edit
->fullscreen
)
1373 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
1377 switch (edit
->drag_state
)
1379 case MCEDIT_DRAG_NORMAL
:
1380 /* possible start move/resize */
1384 edit
->drag_state
= MCEDIT_DRAG_MOVE
;
1385 edit_save_size (edit
);
1388 case CK_WindowResize
:
1389 edit
->drag_state
= MCEDIT_DRAG_RESIZE
;
1390 edit_save_size (edit
);
1398 case MCEDIT_DRAG_MOVE
:
1401 case CK_WindowResize
:
1402 edit
->drag_state
= MCEDIT_DRAG_RESIZE
;
1409 edit_window_move (edit
, command
);
1414 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
1415 /* redraw frame and status */
1416 edit_status (edit
, TRUE
);
1423 case MCEDIT_DRAG_RESIZE
:
1427 edit
->drag_state
= MCEDIT_DRAG_MOVE
;
1434 edit_window_resize (edit
, command
);
1438 case CK_WindowResize
:
1439 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
1440 /* redraw frame and status */
1441 edit_status (edit
, TRUE
);
1452 /* --------------------------------------------------------------------------------------------- */
1454 * Toggle window fuulscreen mode.
1456 * @param edit editor object
1460 edit_toggle_fullscreen (WEdit
* edit
)
1462 edit
->fullscreen
= !edit
->fullscreen
;
1463 edit
->force
= REDRAW_COMPLETELY
;
1465 if (!edit
->fullscreen
)
1466 edit_restore_size (edit
);
1469 Widget
*w
= WIDGET (edit
);
1470 Widget
*h
= WIDGET (w
->owner
);
1472 edit_save_size (edit
);
1473 widget_set_size (w
, h
->y
+ 1, h
->x
, h
->lines
- 2, h
->cols
);
1474 edit
->force
|= REDRAW_PAGE
;
1475 edit_update_screen (edit
);
1479 /* --------------------------------------------------------------------------------------------- */