From b50f4f07e5f63401029f1f9ddf31dabd187e3aac Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 23 Jul 2011 15:30:31 +0400 Subject: [PATCH] Allow move and resize edit window using keyboard. Add "Window" menu entry in editor main menu to handle editor windows. Signed-off-by: Andrew Borodin --- lib/keybind.c | 6 +- lib/keybind.h | 3 + misc/mc.keymap.default | 2 + misc/mc.keymap.emacs | 2 + src/editor/edit-impl.h | 3 + src/editor/edit.c | 8 +- src/editor/editmenu.c | 26 ++++- src/editor/editwidget.c | 239 +++++++++++++++++++++++++++++++++++++++- src/editor/editwidget.h | 4 + 9 files changed, 283 insertions(+), 10 deletions(-) diff --git a/lib/keybind.c b/lib/keybind.c index 09550cb95..8f554b480 100644 --- a/lib/keybind.c +++ b/lib/keybind.c @@ -1,13 +1,13 @@ /* Definitions of key bindings. - Copyright (C) 2009, 2011 + Copyright (C) 2005, 2009, 2010, 2011, 2011, 2012 The Free Software Foundation, Inc. Written by: Vitja Makarov, 2005 Ilia Maslakov , 2009 - Andrew Borodin , 2009, 2010 + Andrew Borodin , 2009, 2010, 2011, 2012 This file is part of the Midnight Commander. @@ -311,6 +311,8 @@ static name_keymap_t command_names[] = { {"About", CK_About}, /* An action to run external script from macro */ {"ExecuteScript", CK_PipeBlock (0)}, + {"WindowMove", CK_WindowMove}, + {"WindowResize", CK_WindowResize}, #endif /* USE_INTERNAL_EDIT */ /* viewer */ diff --git a/lib/keybind.h b/lib/keybind.h index a6aed60a9..d30012848 100644 --- a/lib/keybind.h +++ b/lib/keybind.h @@ -278,6 +278,9 @@ enum CK_RepeatStartRecord, CK_RepeatStopRecord, CK_RepeatStartStopRecord, + /* window commands */ + CK_WindowMove, + CK_WindowResize, /* misc commands */ CK_InsertOverwrite, CK_ParagraphFormat, diff --git a/misc/mc.keymap.default b/misc/mc.keymap.default index 8ac73385d..9bda27eae 100644 --- a/misc/mc.keymap.default +++ b/misc/mc.keymap.default @@ -337,6 +337,8 @@ SelectCodepage = alt-e Options = OptionsSaveMode = LearnKeys = +WindowMove = +WindowResize = ExtendedKeyMap = [viewer] diff --git a/misc/mc.keymap.emacs b/misc/mc.keymap.emacs index 6be8bf665..3a2d2176d 100644 --- a/misc/mc.keymap.emacs +++ b/misc/mc.keymap.emacs @@ -337,6 +337,8 @@ SelectCodepage = alt-e Options = OptionsSaveMode = LearnKeys = +WindowMove = +WindowResize = ExtendedKeyMap = ctrl-x [editor:xmap] diff --git a/src/editor/edit-impl.h b/src/editor/edit-impl.h index b8339e464..4bdcda18e 100644 --- a/src/editor/edit-impl.h +++ b/src/editor/edit-impl.h @@ -178,6 +178,7 @@ extern gboolean search_create_bookmark; /*** declarations of public functions ************************************************************/ +gboolean edit_widget_is_editor (const Widget * w); gboolean edit_drop_hotkey_menu (Dlg_head * h, int key); void edit_menu_cmd (Dlg_head * h); void user_menu (WEdit * edit, const char *menu_file, int selected_entry); @@ -261,6 +262,8 @@ void edit_info_status (WEdit * edit); void edit_status (WEdit * edit); void edit_execute_key_command (WEdit * edit, unsigned long command, int char_for_insertion); void edit_update_screen (WEdit * edit); +void edit_save_size (WEdit * edit); +gboolean edit_handle_move_resize (WEdit * edit, unsigned long command); void edit_move_to_line (WEdit * e, long line); void edit_move_display (WEdit * e, long line); void edit_word_wrap (WEdit * edit); diff --git a/src/editor/edit.c b/src/editor/edit.c index 8f121faa2..885bfbe7b 100644 --- a/src/editor/edit.c +++ b/src/editor/edit.c @@ -2269,6 +2269,7 @@ edit_init (WEdit * edit, int y, int x, int lines, int cols, const vfs_path_t * f edit->widget.x = x; edit->widget.lines = lines; edit->widget.cols = cols; + edit_save_size (edit); edit->stat1.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; edit->stat1.st_uid = getuid (); @@ -3513,6 +3514,10 @@ edit_execute_key_command (WEdit * edit, unsigned long command, int char_for_inse void edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion) { + /* at first, handle window state */ + if (edit_handle_move_resize (edit, command)) + return; + edit->force |= REDRAW_LINE; /* The next key press will unhighlight the found string, so update @@ -4160,9 +4165,6 @@ edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion) case CK_Find: edit_get_match_keyword_cmd (edit); break; - case CK_Quit: - dlg_stop (edit->widget.owner); - break; case CK_EditNew: edit_new_cmd (edit); break; diff --git a/src/editor/editmenu.c b/src/editor/editmenu.c index 212a9b063..c9a8c1a89 100644 --- a/src/editor/editmenu.c +++ b/src/editor/editmenu.c @@ -1,11 +1,12 @@ /* Editor menu definitions and initialisation - Copyright (C) 1996, 1998, 2001, 2002, 2003, 2005, 2007, 2011 + Copyright (C) 1996, 1998, 2001, 2002, 2003, 2005, 2007, 2011, 2012 The Free Software Foundation, Inc. Written by: Paul Sheer, 1996, 1997 + Andrew Borodin 2012 This file is part of the Midnight Commander. @@ -202,6 +203,22 @@ create_format_menu (void) return g_list_reverse (entries); } +/* --------------------------------------------------------------------------------------------- */ +/** + * Create the 'window' popup menu + */ + +static GList * +create_window_menu (void) +{ + GList *entries = NULL; + + entries = g_list_append (entries, menu_entry_create (_("&Move"), CK_WindowMove)); + entries = g_list_append (entries, menu_entry_create (_("&Resize"), CK_WindowResize)); + + return entries; +} + /* --------------------------------------------------------------------------------------------- */ static GList * @@ -263,6 +280,8 @@ edit_init_menu (struct WMenuBar *menubar) "[Internal File Editor]")); menubar_add_menu (menubar, create_menu (_("For&mat"), create_format_menu (), "[Internal File Editor]")); + menubar_add_menu (menubar, + create_menu (_("&Window"), create_window_menu (), "[Internal File Editor]")); menubar_add_menu (menubar, create_menu (_("&Options"), create_options_menu (), "[Internal File Editor]")); @@ -299,9 +318,12 @@ edit_drop_hotkey_menu (Dlg_head * h, int key) case ALT ('m'): m = 4; break; - case ALT ('o'): + case ALT ('w'): m = 5; break; + case ALT ('o'): + m = 6; + break; default: return FALSE; } diff --git a/src/editor/editwidget.c b/src/editor/editwidget.c index c7421907a..7c6b85902 100644 --- a/src/editor/editwidget.c +++ b/src/editor/editwidget.c @@ -63,6 +63,9 @@ /*** file scope macro definitions ****************************************************************/ +#define WINDOW_MIN_LINES (2 + 2) +#define WINDOW_MIN_COLS (2 + LINE_STATE_WIDTH) + /*** file scope type declarations ****************************************************************/ /*** file scope variables ************************************************************************/ @@ -71,6 +74,102 @@ static cb_ret_t edit_callback (Widget * w, widget_msg_t msg, int parm); +/* --------------------------------------------------------------------------------------------- */ +/** + * Restore saved window size. + * + * @param edit editor object + */ + +static void +edit_restore_size (WEdit * edit) +{ + edit->drag_state = MCEDIT_DRAG_NORMAL; + widget_set_size ((Widget *) edit, edit->y_prev, edit->x_prev, + edit->lines_prev, edit->cols_prev); + dlg_redraw (((Widget *) edit)->owner); +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Move window by one row or column in any direction. + * + * @param edit editor object + * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right) + */ + +static void +edit_window_move (WEdit * edit, unsigned long command) +{ + Widget *w = (Widget *) edit; + Dlg_head *h = w->owner; + + switch (command) + { + case CK_Up: + if (w->y > h->y + 1) /* menubar */ + w->y--; + break; + case CK_Down: + if (w->y < h->y + h->lines - 2) /* buttonbar */ + w->y++; + break; + case CK_Left: + if (w->x + w->cols > h->x) + w->x--; + break; + case CK_Right: + if (w->x < h->x + h->cols) + w->x++; + break; + default: + return; + } + + edit->force |= REDRAW_PAGE; + dlg_redraw (h); +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Resize window by one row or column in any direction. + * + * @param edit editor object + * @param command direction (CK_Up, CK_Down, CK_Left, CK_Right) + */ + +static void +edit_window_resize (WEdit * edit, unsigned long command) +{ + Widget *w = (Widget *) edit; + Dlg_head *h = w->owner; + + switch (command) + { + case CK_Up: + if (w->lines > WINDOW_MIN_LINES) + w->lines--; + break; + case CK_Down: + if (w->y + w->lines < h->y + h->lines - 1) /* buttonbar */ + w->lines++; + break; + case CK_Left: + if (w->cols > WINDOW_MIN_COLS) + w->cols--; + break; + case CK_Right: + if (w->x + w->cols < h->x + h->cols) + w->cols++; + break; + default: + return; + } + + edit->force |= REDRAW_COMPLETELY; + dlg_redraw (h); +} + /* --------------------------------------------------------------------------------------------- */ static char * @@ -294,8 +393,8 @@ edit_event (Gpm_Event * event, void *data) local = mouse_get_local (event, w); /* don't use widget_set_size() here to avoid double draw */ - w->lines = max (2 + 2, local.y); - w->cols = max (2 + LINE_STATE_WIDTH, local.x); + w->lines = max (WINDOW_MIN_LINES, local.y); + w->cols = max (WINDOW_MIN_COLS, local.x); edit->force |= REDRAW_COMPLETELY; } @@ -318,6 +417,23 @@ edit_dialog_command_execute (Dlg_head * h, unsigned long command) case CK_Menu: edit_menu_cmd (h); break; + case CK_Quit: + case CK_Cancel: + { + Widget *w = (Widget *) h->current->data; + + if (!edit_widget_is_editor (w) || ((WEdit *) w)->drag_state == MCEDIT_DRAG_NORMAL) + dlg_stop (h); + else + edit_restore_size ((WEdit *) w); + } + break; + case CK_WindowMove: + case CK_WindowResize: + if (edit_widget_is_editor ((Widget *) h->current->data)) + edit_handle_move_resize ((WEdit *) h->current->data, command); + break; + default: ret = MSG_NOT_HANDLED; break; @@ -430,7 +546,9 @@ edit_dialog_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, vo case DLG_VALIDATE: h->state = DLG_ACTIVE; /* don't stop the dialog before final decision */ - if (edit_ok_to_exit (edit)) + if (edit->drag_state != MCEDIT_DRAG_NORMAL) + edit_restore_size (edit); + else if (edit_ok_to_exit (edit)) h->state = DLG_CLOSED; return MSG_HANDLED; @@ -568,6 +686,20 @@ edit_get_file_name (const WEdit * edit) return vfs_path_to_str (edit->filename_vpath); } +/* --------------------------------------------------------------------------------------------- */ +/** + * Check if widget is an WEdit class. + * + * @param w probably editor object + * @return TRUE if widget is an WEdit class, FALSE otherwise + */ + +gboolean +edit_widget_is_editor (const Widget * w) +{ + return (w != NULL && w->callback == edit_callback); +} + /* --------------------------------------------------------------------------------------------- */ void @@ -602,3 +734,104 @@ edit_update_screen (WEdit * e) } /* --------------------------------------------------------------------------------------------- */ +/** + * Save current window size. + * + * @param edit editor object + */ + +void +edit_save_size (WEdit * edit) +{ + edit->y_prev = edit->widget.y; + edit->x_prev = edit->widget.x; + edit->lines_prev = edit->widget.lines; + edit->cols_prev = edit->widget.cols; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Handle move/resize events. + * + * @param edit editor object + * @param command action id + * @return TRUE if mouse actions was handled, FALSE otherwise + */ + +gboolean +edit_handle_move_resize (WEdit * edit, unsigned long command) +{ + gboolean ret = FALSE; + + switch (edit->drag_state) + { + case MCEDIT_DRAG_NORMAL: + /* possible start move/resize */ + switch (command) + { + case CK_WindowMove: + edit->drag_state = MCEDIT_DRAG_MOVE; + edit_save_size (edit); + ret = TRUE; + break; + case CK_WindowResize: + edit->drag_state = MCEDIT_DRAG_RESIZE; + edit_save_size (edit); + ret = TRUE; + break; + default: + break; + } + break; + + case MCEDIT_DRAG_MOVE: + switch (command) + { + case CK_WindowResize: + edit->drag_state = MCEDIT_DRAG_RESIZE; + ret = TRUE; + break; + case CK_Up: + case CK_Down: + case CK_Left: + case CK_Right: + edit_window_move (edit, command); + ret = TRUE; + break; + case CK_Enter: + case CK_WindowMove: + edit->drag_state = MCEDIT_DRAG_NORMAL; + default: + ret = TRUE; + break; + } + break; + + case MCEDIT_DRAG_RESIZE: + switch (command) + { + case CK_WindowMove: + edit->drag_state = MCEDIT_DRAG_MOVE; + ret = TRUE; + break; + case CK_Up: + case CK_Down: + case CK_Left: + case CK_Right: + edit_window_resize (edit, command); + ret = TRUE; + break; + case CK_Enter: + case CK_WindowResize: + edit->drag_state = MCEDIT_DRAG_NORMAL; + default: + ret = TRUE; + break; + } + break; + } + + return ret; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/editor/editwidget.h b/src/editor/editwidget.h index 2c45f0e84..62e0ea825 100644 --- a/src/editor/editwidget.h +++ b/src/editor/editwidget.h @@ -64,6 +64,10 @@ struct WEdit mcedit_drag_state_t drag_state; int drag_state_start; /* save cursor position before window moving */ + /* save location before move/resize */ + int x_prev, y_prev; + int cols_prev, lines_prev; + vfs_path_t *filename_vpath; /* Name of the file */ vfs_path_t *dir_vpath; /* NULL if filename is absolute */