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
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
38 #include <sys/types.h>
46 #include "lib/global.h"
48 #include "lib/tty/tty.h" /* LINES, COLS */
49 #include "lib/tty/key.h" /* is_idle() */
50 #include "lib/tty/color.h" /* tty_setcolor() */
52 #include "lib/strutil.h" /* str_term_trim() */
53 #include "lib/util.h" /* mc_build_filename() */
54 #include "lib/widget.h"
55 #include "lib/mcconfig.h"
56 #include "lib/event.h" /* mc_event_raise() */
58 #include "src/keybind-defaults.h"
59 #include "src/main.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_callback (Widget
* w
, widget_msg_t msg
, int parm
);
88 static cb_ret_t
edit_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
,
91 /* --------------------------------------------------------------------------------------------- */
93 * Init the 'edit' subsystem
99 if (edit_dlg_init_refcounter
== 0)
101 edit_window_state_char
= mc_skin_get ("editor", "window-state-char", "*");
102 edit_window_close_char
= mc_skin_get ("editor", "window-close-char", "X");
109 edit_dlg_init_refcounter
++;
112 /* --------------------------------------------------------------------------------------------- */
114 * Deinit the 'edit' subsystem
118 edit_dlg_deinit (void)
120 if (edit_dlg_init_refcounter
!= 0)
121 edit_dlg_init_refcounter
--;
123 if (edit_dlg_init_refcounter
== 0)
125 g_free (edit_window_state_char
);
126 g_free (edit_window_close_char
);
134 /* --------------------------------------------------------------------------------------------- */
136 * Show info about editor
142 const char *header
= N_("About");
143 const char *button_name
= N_("&OK");
144 const char *const version
= "MCEdit " VERSION
;
145 char text
[BUF_LARGE
];
147 int win_len
, version_len
, button_len
;
154 button_name
= _(button_name
);
157 button_len
= str_term_width1 (button_name
) + 5;
158 version_len
= str_term_width1 (version
);
160 g_snprintf (text
, sizeof (text
),
161 _("Copyright (C) 1996-2012 the Free Software Foundation\n\n"
162 " A user friendly text editor\n"
163 " written for the Midnight Commander"));
165 win_len
= str_term_width1 (header
);
166 win_len
= max (win_len
, version_len
);
167 win_len
= max (win_len
, button_len
);
169 /* count width and height of text */
170 str_msg_term_size (text
, &lines
, &cols
);
172 cols
= max (win_len
, cols
) + 6;
175 about_dlg
= create_dlg (TRUE
, 0, 0, lines
, cols
, dialog_colors
, NULL
, NULL
,
176 "[Internal File Editor]", header
, DLG_CENTER
| DLG_TRYUP
);
178 add_widget (about_dlg
, label_new (3, (cols
- version_len
) / 2, version
));
179 add_widget (about_dlg
, label_new (5, 3, text
));
180 add_widget (about_dlg
, button_new (lines
- 3, (cols
- button_len
) / 2,
181 B_ENTER
, NORMAL_BUTTON
, button_name
, NULL
));
184 destroy_dlg (about_dlg
);
187 /* --------------------------------------------------------------------------------------------- */
195 ev_help_t event_data
= { NULL
, "[Internal File Editor]" };
196 mc_event_raise (MCEVENT_GROUP_CORE
, "help", &event_data
);
199 /* --------------------------------------------------------------------------------------------- */
201 * Callback for the iteration of objects in the 'editors' array.
202 * Resize the editor window.
204 * @param data probably WEdit object
205 * @param user_data unused
209 edit_dialog_resize_cb (void *data
, void *user_data
)
211 Widget
*w
= (Widget
*) data
;
215 if (edit_widget_is_editor (w
) && ((WEdit
*) w
)->fullscreen
)
217 Dlg_head
*h
= w
->owner
;
219 w
->lines
= h
->lines
- 2;
224 /* --------------------------------------------------------------------------------------------- */
226 * Restore saved window size.
228 * @param edit editor object
232 edit_restore_size (WEdit
* edit
)
234 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
235 widget_set_size ((Widget
*) edit
, edit
->y_prev
, edit
->x_prev
,
236 edit
->lines_prev
, edit
->cols_prev
);
237 dlg_redraw (((Widget
*) edit
)->owner
);
240 /* --------------------------------------------------------------------------------------------- */
242 * Move window by one row or column in any direction.
244 * @param edit editor object
245 * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right)
249 edit_window_move (WEdit
* edit
, unsigned long command
)
251 Widget
*w
= (Widget
*) edit
;
252 Dlg_head
*h
= w
->owner
;
257 if (w
->y
> h
->y
+ 1) /* menubar */
261 if (w
->y
< h
->y
+ h
->lines
- 2) /* buttonbar */
265 if (w
->x
+ w
->cols
> h
->x
)
269 if (w
->x
< h
->x
+ h
->cols
)
276 edit
->force
|= REDRAW_PAGE
;
280 /* --------------------------------------------------------------------------------------------- */
282 * Resize window by one row or column in any direction.
284 * @param edit editor object
285 * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right)
289 edit_window_resize (WEdit
* edit
, unsigned long command
)
291 Widget
*w
= (Widget
*) edit
;
292 Dlg_head
*h
= w
->owner
;
297 if (w
->lines
> WINDOW_MIN_LINES
)
301 if (w
->y
+ w
->lines
< h
->y
+ h
->lines
- 1) /* buttonbar */
305 if (w
->cols
> WINDOW_MIN_COLS
)
309 if (w
->x
+ w
->cols
< h
->x
+ h
->cols
)
316 edit
->force
|= REDRAW_COMPLETELY
;
320 /* --------------------------------------------------------------------------------------------- */
322 * Get hotkey by number.
331 return (n
<= 9) ? '0' + n
: 'a' + n
- 10;
334 /* --------------------------------------------------------------------------------------------- */
337 edit_window_list (const Dlg_head
* h
)
339 const size_t offset
= 2; /* skip menu and buttonbar */
340 const size_t dlg_num
= g_list_length (h
->widgets
) - offset
;
347 lines
= min ((size_t) (LINES
* 2 / 3), dlg_num
);
350 listbox
= create_listbox_window (lines
, cols
, _("Open files"), "[Open files]");
352 for (w
= h
->widgets
; w
!= NULL
; w
= g_list_next (w
))
353 if (edit_widget_is_editor ((Widget
*) w
->data
))
355 WEdit
*e
= (WEdit
*) w
->data
;
358 if (e
->filename_vpath
== NULL
)
359 fname
= g_strdup_printf ("%c [%s]", e
->modified
? '*' : ' ', _("NoName"));
364 fname2
= vfs_path_to_str (e
->filename_vpath
);
365 fname
= g_strdup_printf ("%c%s", e
->modified
? '*' : ' ', fname2
);
369 listbox_add_item (listbox
->list
, LISTBOX_APPEND_AT_END
, get_hotkey (i
++),
370 str_term_trim (fname
, listbox
->list
->widget
.cols
- 2), NULL
);
374 rv
= g_list_position (h
->widgets
, h
->current
) - offset
;
375 listbox_select_entry (listbox
->list
, rv
);
376 rv
= run_listbox (listbox
);
379 w
= g_list_nth (h
->widgets
, rv
+ offset
);
380 dlg_set_top_widget (w
->data
);
384 /* --------------------------------------------------------------------------------------------- */
387 edit_get_shortcut (unsigned long command
)
390 const char *shortcut
= NULL
;
392 shortcut
= keybind_lookup_keymap_shortcut (editor_map
, command
);
393 if (shortcut
!= NULL
)
394 return g_strdup (shortcut
);
396 ext_map
= keybind_lookup_keymap_shortcut (editor_map
, CK_ExtendedKeyMap
);
398 shortcut
= keybind_lookup_keymap_shortcut (editor_x_map
, command
);
399 if (shortcut
!= NULL
)
400 return g_strdup_printf ("%s %s", ext_map
, shortcut
);
405 /* --------------------------------------------------------------------------------------------- */
408 edit_get_title (const Dlg_head
* h
, size_t len
)
410 const WEdit
*edit
= find_editor (h
);
411 const char *modified
= edit
->modified
? "(*) " : " ";
412 const char *file_label
;
417 filename
= vfs_path_to_str (edit
->filename_vpath
);
418 if (filename
== NULL
)
419 filename
= g_strdup (_("[NoName]"));
420 file_label
= str_term_trim (filename
, len
- str_term_width1 (_("Edit: ")));
423 return g_strconcat (_("Edit: "), modified
, file_label
, (char *) NULL
);
426 /* --------------------------------------------------------------------------------------------- */
428 * Handle mouse events of editor window
430 * @param event mouse event
431 * @param data editor window
432 * @return MOU_NORMAL if event was handled, MOU_UNHANDLED otherwise
436 edit_event (Gpm_Event
* event
, void *data
)
438 WEdit
*edit
= (WEdit
*) data
;
439 Widget
*w
= (Widget
*) data
;
442 if (!mouse_global_in_widget (event
, w
))
443 return MOU_UNHANDLED
;
445 local
= mouse_get_local (event
, w
);
447 /* Unknown event type */
448 if ((event
->type
& (GPM_DOWN
| GPM_DRAG
| GPM_UP
)) == 0)
451 dlg_set_top_widget (w
);
453 edit_update_curs_row (edit
);
454 edit_update_curs_col (edit
);
456 if (edit
->fullscreen
|| (local
.buttons
& GPM_B_LEFT
) == 0 || (local
.type
& GPM_UP
) != 0)
457 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
458 else if (local
.y
== 1 && edit
->drag_state
!= MCEDIT_DRAG_RESIZE
)
460 /* click on the top line (move) */
461 int dx
= edit
->fullscreen
? 0 : 2;
463 if (local
.x
== edit
->widget
.cols
- dx
- 1)
465 edit_dialog_callback (w
->owner
, NULL
, DLG_ACTION
, CK_Close
, NULL
);
469 if (local
.x
== edit
->widget
.cols
- dx
- 4)
471 edit_toggle_fullscreen (edit
);
475 if ((local
.type
& (GPM_DOWN
| GPM_DRAG
)) != 0)
477 /* move if not fullscreen */
478 edit
->drag_state_start
= local
.x
;
479 edit
->drag_state
= MCEDIT_DRAG_MOVE
;
480 edit
->force
|= REDRAW_COMPLETELY
;
481 edit_update_screen (edit
);
484 else if (!edit
->fullscreen
&& local
.y
== w
->lines
&& local
.x
== w
->cols
)
486 /* click on bottom-right corner (resize) */
487 if ((local
.type
& (GPM_DOWN
| GPM_DRAG
)) != 0)
489 edit
->drag_state
= MCEDIT_DRAG_RESIZE
;
490 edit
->force
|= REDRAW_COMPLETELY
;
491 edit_update_screen (edit
);
495 if (edit
->drag_state
== MCEDIT_DRAG_NORMAL
)
497 gboolean done
= TRUE
;
500 if ((local
.type
& (GPM_DOUBLE
| GPM_UP
)) == (GPM_UP
| GPM_DOUBLE
))
502 edit_mark_current_word_cmd (edit
);
507 if ((local
.type
& (GPM_TRIPLE
| GPM_UP
)) == (GPM_UP
| GPM_TRIPLE
))
509 edit_mark_current_line_cmd (edit
);
514 if ((local
.buttons
& GPM_B_UP
) != 0 && (local
.type
& GPM_DOWN
) != 0)
516 edit_move_up (edit
, 2, 1);
519 if ((local
.buttons
& GPM_B_DOWN
) != 0 && (local
.type
& GPM_DOWN
) != 0)
521 edit_move_down (edit
, 2, 1);
525 /* continue handle current event */
528 /* handle DRAG mouse event, don't use standard way to continue
529 * event handling outside of widget */
534 c
= tty_get_event (event
, FALSE
, TRUE
);
535 if (c
== EV_NONE
|| c
!= EV_MOUSE
)
538 local
= mouse_get_local (event
, w
);
541 /* A lone up mustn't do anything */
542 if (edit
->mark2
!= -1 && (local
.type
& (GPM_UP
| GPM_DRAG
)) != 0)
545 if ((local
.type
& (GPM_DOWN
| GPM_UP
)) != 0)
546 edit_push_key_press (edit
);
548 if (!edit
->fullscreen
)
550 if (!option_cursor_beyond_eol
)
551 edit
->prev_col
= local
.x
- edit
->start_col
- option_line_state_width
- 1;
554 long line_len
= edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), 0,
555 edit_eol (edit
, edit
->curs1
));
557 if (local
.x
> line_len
)
560 local
.x
- line_len
- edit
->start_col
- option_line_state_width
- 1;
561 edit
->prev_col
= line_len
;
566 edit
->prev_col
= local
.x
- option_line_state_width
- edit
->start_col
- 1;
570 if (!edit
->fullscreen
)
572 if (local
.y
> (edit
->curs_row
+ 1))
573 edit_move_down (edit
, local
.y
- (edit
->curs_row
+ 1), 0);
574 else if (local
.y
< (edit
->curs_row
+ 1))
575 edit_move_up (edit
, (edit
->curs_row
+ 1) - local
.y
, 0);
577 edit_move_to_prev_col (edit
, edit_bol (edit
, edit
->curs1
));
579 if ((local
.type
& GPM_DOWN
) != 0)
581 edit_mark_cmd (edit
, TRUE
); /* reset */
585 done
= (local
.type
& GPM_DRAG
) == 0;
587 edit_mark_cmd (edit
, FALSE
);
590 edit_find_bracket (edit
);
591 edit
->force
|= REDRAW_COMPLETELY
;
592 edit_update_curs_row (edit
);
593 edit_update_curs_col (edit
);
594 edit_update_screen (edit
);
596 while (!edit
->fullscreen
&& !done
);
599 while (edit
->drag_state
!= MCEDIT_DRAG_NORMAL
)
604 c
= tty_get_event (event
, FALSE
, TRUE
);
607 if (c
== EV_NONE
|| c
!= EV_MOUSE
)
610 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
611 edit
->force
|= REDRAW_COMPLETELY
;
612 edit_update_screen (edit
);
614 else if (y
== w
->y
&& (event
->type
& (GPM_DOUBLE
| GPM_UP
)) == (GPM_DOUBLE
| GPM_UP
))
616 /* double click on top line (toggle fullscreen) */
617 edit_toggle_fullscreen (edit
);
618 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
619 edit
->force
|= REDRAW_COMPLETELY
;
620 edit_update_screen (edit
);
622 else if ((event
->type
& (GPM_DRAG
| GPM_DOWN
)) == 0)
625 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
626 edit
->force
|= REDRAW_COMPLETELY
;
627 edit_update_screen (edit
);
629 else if (!edit
->fullscreen
)
631 Dlg_head
*h
= w
->owner
;
633 if (edit
->drag_state
== MCEDIT_DRAG_MOVE
)
635 int x
= event
->x
- 1;
637 y
= max (y
, h
->y
+ 1); /* status line */
638 y
= min (y
, h
->y
+ h
->lines
- 2); /* buttonbar */
640 x
= min (x
, h
->x
+ h
->cols
- 1);
641 /* don't use widget_set_size() here to avoid double draw */
643 w
->x
= x
- edit
->drag_state_start
;
644 edit
->force
|= REDRAW_COMPLETELY
;
646 else if (edit
->drag_state
== MCEDIT_DRAG_RESIZE
)
648 event
->y
= min (event
->y
, h
->y
+ h
->lines
- 1); /* buttonbar */
649 event
->x
= min (event
->x
, h
->x
+ h
->cols
);
650 local
= mouse_get_local (event
, w
);
652 /* don't use widget_set_size() here to avoid double draw */
653 w
->lines
= max (WINDOW_MIN_LINES
, local
.y
);
654 w
->cols
= max (WINDOW_MIN_COLS
, local
.x
);
655 edit
->force
|= REDRAW_COMPLETELY
;
665 /* --------------------------------------------------------------------------------------------- */
667 * Handle mouse events of editor screen.
669 * @param event mouse event
670 * @param data editor screen
671 * @return MOU_NORMAL if event was handled, MOU_UNHANDLED otherwise
675 edit_dialog_event (Gpm_Event
* event
, void *data
)
677 Dlg_head
*h
= (Dlg_head
*) data
;
679 int ret
= MOU_UNHANDLED
;
681 w
= (Widget
*) find_menubar (h
);
683 if (event
->y
== h
->y
+ 1 && (event
->type
& GPM_DOWN
) != 0 && !((WMenuBar
*) w
)->is_active
)
691 /* Try find top fullscreen window */
692 for (l
= h
->widgets
; l
!= NULL
; l
= g_list_next (l
))
693 if (edit_widget_is_editor ((Widget
*) l
->data
) && ((WEdit
*) l
->data
)->fullscreen
)
696 /* Handle fullscreen/close buttons in the top line */
697 x
= h
->x
+ h
->cols
+ 1 - 6;
699 if (top
!= NULL
&& event
->x
>= x
)
703 e
= (WEdit
*) top
->data
;
706 if (top
!= h
->current
)
708 /* Window is not active. Activate it */
709 dlg_set_top_widget (e
);
714 edit_toggle_fullscreen (e
);
716 edit_dialog_callback (h
, NULL
, DLG_ACTION
, CK_Close
, NULL
);
721 if (ret
== MOU_UNHANDLED
)
722 dlg_select_widget (w
);
724 else if (event
->y
== h
->y
+ h
->lines
)
728 /* In general, this can be handled in default way (dlg_mouse_event)
729 * but let make it here to avoid walking in widget list */
730 w
= (Widget
*) find_buttonbar (h
);
731 ret
= w
->mouse (event
, w
);
737 /* --------------------------------------------------------------------------------------------- */
740 edit_dialog_command_execute (Dlg_head
* h
, unsigned long command
)
742 gboolean ret
= MSG_HANDLED
;
747 edit_add_window (h
, h
->y
+ 1, h
->x
, h
->lines
- 2, h
->cols
, NULL
, 0);
752 case CK_EditSyntaxFile
:
753 edit_load_syntax_file (h
);
755 case CK_EditUserMenu
:
756 edit_load_menu_file (h
);
759 /* if there are no opened files anymore, close MC editor */
760 if (edit_widget_is_editor ((Widget
*) h
->current
->data
) &&
761 edit_close_cmd ((WEdit
*) h
->current
->data
) && find_editor (h
) == NULL
)
766 /* edit->force |= REDRAW_COMPLETELY; */
774 Widget
*w
= (Widget
*) h
->current
->data
;
776 if (!edit_widget_is_editor (w
) || ((WEdit
*) w
)->drag_state
== MCEDIT_DRAG_NORMAL
)
779 edit_restore_size ((WEdit
*) w
);
786 edit_syntax_onoff_cmd (h
);
789 edit_show_tabs_tws_cmd (h
);
792 edit_show_margin_cmd (h
);
795 edit_show_numbers_cmd (h
);
807 case CK_WindowResize
:
808 if (edit_widget_is_editor ((Widget
*) h
->current
->data
))
809 edit_handle_move_resize ((WEdit
*) h
->current
->data
, command
);
812 edit_window_list (h
);
816 dlg_set_top_widget (h
->current
->data
);
820 dlg_set_top_widget (h
->current
->data
);
823 edit_options_dialog (h
);
825 case CK_OptionsSaveMode
:
826 edit_save_mode_cmd ();
832 ret
= MSG_NOT_HANDLED
;
839 /* --------------------------------------------------------------------------------------------- */
842 edit_quit (Dlg_head
* h
)
847 h
->state
= DLG_ACTIVE
; /* don't stop the dialog before final decision */
849 for (l
= h
->widgets
; l
!= NULL
; l
= g_list_next (l
))
850 if (edit_widget_is_editor ((Widget
*) l
->data
))
852 e
= (WEdit
*) l
->data
;
854 if (e
->drag_state
!= MCEDIT_DRAG_NORMAL
)
856 edit_restore_size (e
);
862 dlg_select_widget (e
);
864 if (!edit_ok_to_exit (e
))
869 /* no editors in dialog at all or no any file required to be saved */
870 if (e
== NULL
|| l
== NULL
)
871 h
->state
= DLG_CLOSED
;
874 /* --------------------------------------------------------------------------------------------- */
877 edit_set_buttonbar (WEdit
* edit
, WButtonBar
* bb
)
879 buttonbar_set_label (bb
, 1, Q_ ("ButtonBar|Help"), editor_map
, NULL
);
880 buttonbar_set_label (bb
, 2, Q_ ("ButtonBar|Save"), editor_map
, (Widget
*) edit
);
881 buttonbar_set_label (bb
, 3, Q_ ("ButtonBar|Mark"), editor_map
, (Widget
*) edit
);
882 buttonbar_set_label (bb
, 4, Q_ ("ButtonBar|Replac"), editor_map
, (Widget
*) edit
);
883 buttonbar_set_label (bb
, 5, Q_ ("ButtonBar|Copy"), editor_map
, (Widget
*) edit
);
884 buttonbar_set_label (bb
, 6, Q_ ("ButtonBar|Move"), editor_map
, (Widget
*) edit
);
885 buttonbar_set_label (bb
, 7, Q_ ("ButtonBar|Search"), editor_map
, (Widget
*) edit
);
886 buttonbar_set_label (bb
, 8, Q_ ("ButtonBar|Delete"), editor_map
, (Widget
*) edit
);
887 buttonbar_set_label (bb
, 9, Q_ ("ButtonBar|PullDn"), editor_map
, NULL
);
888 buttonbar_set_label (bb
, 10, Q_ ("ButtonBar|Quit"), editor_map
, NULL
);
891 /* --------------------------------------------------------------------------------------------- */
892 /** Callback for the edit dialog */
895 edit_dialog_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
898 WButtonBar
*buttonbar
;
907 /* don't use common_dialog_repaint() -- we don't need a frame */
908 tty_setcolor (EDITOR_BACKGROUND
);
913 menubar
= find_menubar (h
);
914 buttonbar
= find_buttonbar (h
);
915 /* dlg_set_size() is surplus for this case */
918 widget_set_size (&buttonbar
->widget
, h
->lines
- 1, h
->x
, 1, h
->cols
);
919 widget_set_size (&menubar
->widget
, h
->y
, h
->x
, 1, h
->cols
);
920 menubar_arrange (menubar
);
921 g_list_foreach (h
->widgets
, (GFunc
) edit_dialog_resize_cb
, NULL
);
927 return edit_dialog_command_execute (h
, parm
);
928 /* message from menu */
929 menubar
= find_menubar (h
);
930 if (sender
== (Widget
*) menubar
)
932 if (edit_dialog_command_execute (h
, parm
) == MSG_HANDLED
)
934 /* try send command to the current window */
935 return send_message ((Widget
*) h
->current
->data
, WIDGET_COMMAND
, parm
);
937 /* message from buttonbar */
938 buttonbar
= find_buttonbar (h
);
939 if (sender
== (Widget
*) buttonbar
)
942 return send_message ((Widget
*) data
, WIDGET_COMMAND
, parm
);
943 return edit_dialog_command_execute (h
, parm
);
945 return MSG_NOT_HANDLED
;
949 Widget
*w
= h
->current
->data
;
950 cb_ret_t ret
= MSG_NOT_HANDLED
;
952 if (edit_widget_is_editor (w
))
954 WEdit
*e
= (WEdit
*) w
;
955 unsigned long command
;
958 command
= keybind_lookup_keymap_command (editor_map
, parm
);
962 command
= keybind_lookup_keymap_command (editor_x_map
, parm
);
965 if (command
!= CK_IgnoreKey
)
966 ret
= edit_dialog_command_execute (h
, command
);
972 /* hardcoded menu hotkeys (see edit_drop_hotkey_menu) */
973 case DLG_UNHANDLED_KEY
:
974 return edit_drop_hotkey_menu (h
, parm
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
985 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
989 /* --------------------------------------------------------------------------------------------- */
992 edit_callback (Widget
* w
, widget_msg_t msg
, int parm
)
994 WEdit
*e
= (WEdit
*) w
;
999 edit_set_buttonbar (e
, find_buttonbar (e
->widget
.owner
));
1003 e
->force
|= REDRAW_COMPLETELY
;
1004 edit_update_screen (e
);
1007 case WIDGET_UNFOCUS
:
1008 /* redraw frame and status */
1009 edit_status (e
, FALSE
);
1015 cb_ret_t ret
= MSG_NOT_HANDLED
;
1017 /* The user may override the access-keys for the menu bar. */
1018 if (macro_index
== -1 && edit_execute_macro (e
, parm
))
1020 edit_update_screen (e
);
1023 else if (edit_translate_key (e
, parm
, &cmd
, &ch
))
1025 edit_execute_key_command (e
, cmd
, ch
);
1026 edit_update_screen (e
);
1033 case WIDGET_COMMAND
:
1034 /* command from menubar or buttonbar */
1035 edit_execute_key_command (e
, parm
, -1);
1036 edit_update_screen (e
);
1043 y
= (e
->fullscreen
? 0 : 1) + EDIT_TEXT_VERTICAL_OFFSET
+ e
->curs_row
;
1044 x
= (e
->fullscreen
? 0 : 1) + EDIT_TEXT_HORIZONTAL_OFFSET
+ option_line_state_width
+
1045 e
->curs_col
+ e
->start_col
+ e
->over_col
;
1047 widget_move (w
, y
, x
);
1051 case WIDGET_DESTROY
:
1056 return default_proc (msg
, parm
);
1060 /* --------------------------------------------------------------------------------------------- */
1061 /*** public functions ****************************************************************************/
1062 /* --------------------------------------------------------------------------------------------- */
1066 * @param file_vpath file object
1067 * @param line line number
1068 * @return TRUE if no errors was occured, FALSE otherwise
1072 edit_file (const vfs_path_t
* file_vpath
, long line
)
1074 mcedit_arg_t arg
= { (vfs_path_t
*) file_vpath
, line
};
1078 files
= g_list_prepend (NULL
, &arg
);
1079 ok
= edit_files (files
);
1080 g_list_free (files
);
1085 /* --------------------------------------------------------------------------------------------- */
1088 edit_files (const GList
* files
)
1090 static gboolean made_directory
= FALSE
;
1094 gboolean ok
= FALSE
;
1096 if (!made_directory
)
1100 dir
= mc_build_filename (mc_config_get_cache_path (), EDIT_DIR
, NULL
);
1101 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
1104 dir
= mc_build_filename (mc_config_get_path (), EDIT_DIR
, NULL
);
1105 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
1108 dir
= mc_build_filename (mc_config_get_data_path (), EDIT_DIR
, NULL
);
1109 made_directory
= (mkdir (dir
, 0700) != -1 || errno
== EEXIST
);
1113 /* Create a new dialog and add it widgets to it */
1115 create_dlg (FALSE
, 0, 0, LINES
, COLS
, NULL
, edit_dialog_callback
, edit_dialog_event
,
1116 "[Internal File Editor]", NULL
, DLG_WANT_TAB
);
1118 edit_dlg
->get_shortcut
= edit_get_shortcut
;
1119 edit_dlg
->get_title
= edit_get_title
;
1121 menubar
= menubar_new (0, 0, COLS
, NULL
);
1122 add_widget (edit_dlg
, menubar
);
1123 edit_init_menu (menubar
);
1125 add_widget (edit_dlg
, buttonbar_new (TRUE
));
1127 for (file
= files
; file
!= NULL
; file
= g_list_next (file
))
1129 mcedit_arg_t
*f
= (mcedit_arg_t
*) file
->data
;
1132 f_ok
= edit_add_window (edit_dlg
, edit_dlg
->y
+ 1, edit_dlg
->x
,
1133 edit_dlg
->lines
- 2, edit_dlg
->cols
, f
->file_vpath
, f
->line_number
);
1134 /* at least one file has been opened succefully */
1141 if (!ok
|| edit_dlg
->state
== DLG_CLOSED
)
1142 destroy_dlg (edit_dlg
);
1147 /* --------------------------------------------------------------------------------------------- */
1150 edit_get_file_name (const WEdit
* edit
)
1152 return vfs_path_to_str (edit
->filename_vpath
);
1155 /* --------------------------------------------------------------------------------------------- */
1158 find_editor (const Dlg_head
* h
)
1160 if (edit_widget_is_editor ((Widget
*) h
->current
->data
))
1161 return (WEdit
*) h
->current
->data
;
1162 return (WEdit
*) find_widget_type (h
, edit_callback
);
1165 /* --------------------------------------------------------------------------------------------- */
1167 * Check if widget is an WEdit class.
1169 * @param w probably editor object
1170 * @return TRUE if widget is an WEdit class, FALSE otherwise
1174 edit_widget_is_editor (const Widget
* w
)
1176 return (w
!= NULL
&& w
->callback
== edit_callback
);
1179 /* --------------------------------------------------------------------------------------------- */
1182 edit_update_screen (WEdit
* e
)
1184 edit_scroll_screen_over_cursor (e
);
1185 edit_update_curs_col (e
);
1187 edit_status (e
, (e
->force
& REDRAW_COMPLETELY
) != 0 &&
1188 (void *) e
== ((Widget
*) e
)->owner
->current
->data
);
1190 /* pop all events for this window for internal handling */
1192 e
->force
|= REDRAW_PAGE
;
1195 if ((e
->force
& REDRAW_COMPLETELY
) != 0)
1196 e
->force
|= REDRAW_PAGE
;
1197 edit_render_keypress (e
);
1200 buttonbar_redraw (find_buttonbar (((Widget
*) e
)->owner
));
1203 /* --------------------------------------------------------------------------------------------- */
1205 * Save current window size.
1207 * @param edit editor object
1211 edit_save_size (WEdit
* edit
)
1213 edit
->y_prev
= edit
->widget
.y
;
1214 edit
->x_prev
= edit
->widget
.x
;
1215 edit
->lines_prev
= edit
->widget
.lines
;
1216 edit
->cols_prev
= edit
->widget
.cols
;
1219 /* --------------------------------------------------------------------------------------------- */
1221 * Create new editor window and insert it into editor screen.
1223 * @param h editor dialog (screen)
1224 * @param y y coordinate
1225 * @param x x coordinate
1226 * @param lines window height
1227 * @param cols window width
1228 * @param f file object
1229 * @param fline line number in file
1230 * @return TRUE if new window was successfully created and inserted into editor screen,
1235 edit_add_window (Dlg_head
* h
, int y
, int x
, int lines
, int cols
, const vfs_path_t
* f
, long fline
)
1240 edit
= edit_init (NULL
, y
, x
, lines
, cols
, f
, fline
);
1244 w
= (Widget
*) edit
;
1245 w
->callback
= edit_callback
;
1246 w
->mouse
= edit_event
;
1247 widget_want_cursor (*w
, TRUE
);
1255 /* --------------------------------------------------------------------------------------------- */
1257 * Handle move/resize events.
1259 * @param edit editor object
1260 * @param command action id
1261 * @return TRUE if mouse actions was handled, FALSE otherwise
1265 edit_handle_move_resize (WEdit
* edit
, unsigned long command
)
1267 gboolean ret
= FALSE
;
1269 if (edit
->fullscreen
)
1271 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
1275 switch (edit
->drag_state
)
1277 case MCEDIT_DRAG_NORMAL
:
1278 /* possible start move/resize */
1282 edit
->drag_state
= MCEDIT_DRAG_MOVE
;
1283 edit_save_size (edit
);
1286 case CK_WindowResize
:
1287 edit
->drag_state
= MCEDIT_DRAG_RESIZE
;
1288 edit_save_size (edit
);
1296 case MCEDIT_DRAG_MOVE
:
1299 case CK_WindowResize
:
1300 edit
->drag_state
= MCEDIT_DRAG_RESIZE
;
1307 edit_window_move (edit
, command
);
1312 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
1313 /* redraw frame and status */
1314 edit_status (edit
, TRUE
);
1321 case MCEDIT_DRAG_RESIZE
:
1325 edit
->drag_state
= MCEDIT_DRAG_MOVE
;
1332 edit_window_resize (edit
, command
);
1336 case CK_WindowResize
:
1337 edit
->drag_state
= MCEDIT_DRAG_NORMAL
;
1338 /* redraw frame and status */
1339 edit_status (edit
, TRUE
);
1350 /* --------------------------------------------------------------------------------------------- */
1352 * Toggle window fuulscreen mode.
1354 * @param edit editor object
1358 edit_toggle_fullscreen (WEdit
* edit
)
1360 Dlg_head
*h
= ((Widget
*) edit
)->owner
;
1362 edit
->fullscreen
= !edit
->fullscreen
;
1363 edit
->force
= REDRAW_COMPLETELY
;
1365 if (!edit
->fullscreen
)
1366 edit_restore_size (edit
);
1369 edit_save_size (edit
);
1370 widget_set_size ((Widget
*) edit
, h
->y
+ 1, h
->x
, h
->lines
- 2, h
->cols
);
1371 edit
->force
|= REDRAW_PAGE
;
1372 edit_update_screen (edit
);
1376 /* --------------------------------------------------------------------------------------------- */