summaryrefslogtreecommitdiffstats
path: root/src/keymap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keymap.c')
-rw-r--r--src/keymap.c985
1 files changed, 985 insertions, 0 deletions
diff --git a/src/keymap.c b/src/keymap.c
new file mode 100644
index 0000000..3f6cce4
--- /dev/null
+++ b/src/keymap.c
@@ -0,0 +1,985 @@
+/*
+ Default values and initialization of keybinding engine
+
+ Copyright (C) 2009-2023
+ Free Software Foundation, Inc.
+
+ Written by:
+ Vitja Makarov, 2005
+ Ilia Maslakov <il.smind@gmail.com>, 2009, 2010
+ Andrew Borodin <aborodin@vmail.ru>, 2010-2021
+
+ This file is part of the Midnight Commander.
+
+ The Midnight Commander is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ The Midnight Commander is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lib/global.h"
+
+#include "lib/fileloc.h"
+#include "lib/keybind.h"
+#include "lib/mcconfig.h" /* mc_config_t */
+#include "lib/util.h"
+#include "lib/widget.h" /* dialog_map, input_map, listbox_map, menu_map, radio_map */
+
+#include "args.h" /* mc_args__keymap_file */
+
+#include "keymap.h"
+
+/*** global variables ****************************************************************************/
+
+GArray *filemanager_keymap = NULL;
+GArray *filemanager_x_keymap = NULL;
+GArray *panel_keymap = NULL;
+GArray *dialog_keymap = NULL;
+GArray *menu_keymap = NULL;
+GArray *input_keymap = NULL;
+GArray *listbox_keymap = NULL;
+GArray *radio_keymap = NULL;
+GArray *tree_keymap = NULL;
+GArray *help_keymap = NULL;
+#ifdef ENABLE_EXT2FS_ATTR
+GArray *chattr_keymap = NULL;
+#endif
+#ifdef USE_INTERNAL_EDIT
+GArray *editor_keymap = NULL;
+GArray *editor_x_keymap = NULL;
+#endif
+GArray *viewer_keymap = NULL;
+GArray *viewer_hex_keymap = NULL;
+#ifdef USE_DIFF_VIEW
+GArray *diff_keymap = NULL;
+#endif
+
+const global_keymap_t *filemanager_map = NULL;
+const global_keymap_t *filemanager_x_map = NULL;
+const global_keymap_t *panel_map = NULL;
+const global_keymap_t *tree_map = NULL;
+const global_keymap_t *help_map = NULL;
+#ifdef ENABLE_EXT2FS_ATTR
+const global_keymap_t *chattr_map = NULL;
+#endif
+#ifdef USE_INTERNAL_EDIT
+const global_keymap_t *editor_map = NULL;
+const global_keymap_t *editor_x_map = NULL;
+#endif
+const global_keymap_t *viewer_map = NULL;
+const global_keymap_t *viewer_hex_map = NULL;
+#ifdef USE_DIFF_VIEW
+const global_keymap_t *diff_map = NULL;
+#endif
+
+/*** file scope macro definitions ****************************************************************/
+
+/*** file scope type declarations ****************************************************************/
+
+/* default keymaps in ini (key=value) format */
+typedef struct global_keymap_ini_t
+{
+ const char *key;
+ const char *value;
+} global_keymap_ini_t;
+
+/*** forward declarations (file scope functions) *************************************************/
+
+/*** file scope variables ************************************************************************/
+
+/* midnight */
+static const global_keymap_ini_t default_filemanager_keymap[] = {
+ {"ChangePanel", "tab; ctrl-i"},
+ {"Help", "f1"},
+ {"UserMenu", "f2"},
+ {"View", "f3"},
+ {"Edit", "f4"},
+ {"Copy", "f5"},
+ {"Move", "f6"},
+ {"MakeDir", "f7"},
+ {"Delete", "f8"},
+ {"Menu", "f9"},
+ {"Quit", "f10"},
+ {"MenuLastSelected", "f19"},
+ {"QuitQuiet", "f20"},
+ {"History", "alt-h"},
+ {"EditorViewerHistory", "alt-shift-e"},
+ {"DirSize", "ctrl-space"},
+ /* Copy useful information to the command line */
+ {"PutCurrentPath", "alt-a"},
+ {"PutOtherPath", "alt-shift-a"},
+ {"PutCurrentSelected", "alt-enter; ctrl-enter"},
+ {"PutCurrentFullSelected", "ctrl-shift-enter"},
+ {"CdQuick", "alt-c"},
+ /* To access the directory hotlist */
+ {"HotList", "ctrl-backslash"},
+ /* Suspend */
+ {"Suspend", "ctrl-z"},
+ /* The filtered view command */
+ {"ViewFiltered", "alt-exclamation"},
+ /* Find file */
+ {"Find", "alt-question"},
+ /* Panel refresh */
+ {"Reread", "ctrl-r"},
+ /* Switch listing between long, user defined and full formats */
+ /* Swap panels */
+ {"Swap", "ctrl-u"},
+ /* Resize panels */
+ {"SplitEqual", "alt-equal"},
+ {"SplitMore", "alt-shift-right"},
+ {"SplitLess", "alt-shift-left"},
+ /* View output */
+ {"Shell", "ctrl-o"},
+ {"ShowHidden", "alt-dot"},
+ {"SplitVertHoriz", "alt-comma"},
+ {"ExtendedKeyMap", "ctrl-x"},
+ /* Select/unselect group */
+ {"Select", "kpplus"},
+ {"Unselect", "kpminus"},
+ {"SelectInvert", "kpasterisk"},
+ /* List of screens */
+ {"ScreenList", "alt-prime"},
+ {NULL, NULL}
+};
+
+static const global_keymap_ini_t default_filemanager_x_keymap[] = {
+ {"CompareDirs", "d"},
+#ifdef USE_DIFF_VIEW
+ {"CompareFiles", "ctrl-d"},
+#endif /* USE_DIFF_VIEW */
+#ifdef ENABLE_VFS
+ {"VfsList", "a"},
+#endif /* ENABLE_VFS */
+ {"PutCurrentPath", "p"},
+ {"PutOtherPath", "ctrl-p"},
+ {"PutCurrentTagged", "t"},
+ {"PutOtherTagged", "ctrl-t"},
+ {"ChangeMode", "c"},
+ {"ChangeOwn", "o"},
+#ifdef ENABLE_EXT2FS_ATTR
+ {"ChangeAttributes", "e"},
+#endif /* ENABLE_EXT2FS_ATTR */
+ {"PutCurrentLink", "r"},
+ {"PutOtherLink", "ctrl-r"},
+ {"Link", "l"},
+ {"LinkSymbolic", "s"},
+ {"LinkSymbolicRelative", "v"},
+ {"LinkSymbolicEdit", "ctrl-s"},
+ {"PanelInfo", "i"},
+ {"PanelQuickView", "q"},
+ {"HotListAdd", "h"},
+#ifdef ENABLE_BACKGROUND
+ {"Jobs", "j"},
+#endif /* ENABLE_BACKGROUND */
+ {"ExternalPanelize", "!"},
+ {NULL, NULL}
+};
+
+/* panel */
+static const global_keymap_ini_t default_panel_keymap[] = {
+ {"CycleListingFormat", "alt-t"},
+ {"PanelOtherCd", "alt-o"},
+ {"PanelOtherCdLink", "alt-l"},
+ {"CopySingle", "f15"},
+ {"DeleteSingle", "f18"},
+ {"Enter", "enter"},
+ {"EditNew", "f14"},
+ {"MoveSingle", "f16"},
+ {"SelectInvert", "alt-asterisk"},
+ {"Select", "alt-plus"},
+ {"Unselect", "alt-minus"},
+ {"ViewRaw", "f13"},
+ {"CdChild", "ctrl-pgdn"},
+ {"CdParent", "ctrl-pgup"},
+ {"History", "alt-shift-h"},
+ {"HistoryNext", "alt-u"},
+ {"HistoryPrev", "alt-y"},
+ {"BottomOnScreen", "alt-j"},
+ {"MiddleOnScreen", "alt-r"},
+ {"TopOnScreen", "alt-g"},
+ {"Mark", "insert; ctrl-t"},
+ {"MarkDown", "shift-down"},
+ {"MarkUp", "shift-up"},
+ {"Up", "up; ctrl-p"},
+ {"Down", "down; ctrl-n"},
+ {"Left", "left"},
+ {"Right", "right"},
+ {"Top", "alt-lt; home; a1"},
+ {"Bottom", "alt-gt; end; c1"},
+ {"PageDown", "pgdn; ctrl-v"},
+ {"PageUp", "pgup; alt-v"},
+#ifdef HAVE_CHARSET
+ {"SelectCodepage", "alt-e"},
+#endif
+ {"Search", "ctrl-s; alt-s"},
+ {"PanelOtherSync", "alt-i"},
+ {NULL, NULL}
+};
+
+/* dialog */
+static const global_keymap_ini_t default_dialog_keymap[] = {
+ {"Ok", "enter"},
+ {"Cancel", "f10; esc; ctrl-g"},
+ {"Up", "up; left"},
+ {"Down", "down; right"},
+#if 0
+ {"Left", "up; left"},
+ {"Right", "down; right"},
+#endif
+ {"Help", "f1"},
+ {"Suspend", "ctrl-z"},
+ {"Refresh", "ctrl-l"},
+ {"ScreenList", "alt-prime"},
+ {"ScreenNext", "alt-rbrace"},
+ {"ScreenPrev", "alt-lbrace"},
+ {NULL, NULL}
+};
+
+/* menubar */
+static const global_keymap_ini_t default_menu_keymap[] = {
+ {"Help", "f1"},
+ {"Left", "left; ctrl-b"},
+ {"Right", "right; ctrl-f"},
+ {"Up", "up; ctrl-p"},
+ {"Down", "down; ctrl-n"},
+ {"Home", "home; alt-lt; ctrl-a"},
+ {"End", "end; alt-gt; ctrl-e"},
+ {"Enter", "enter"},
+ {"Quit", "f10; ctrl-g; esc"},
+ {NULL, NULL}
+};
+
+/* input line */
+static const global_keymap_ini_t default_input_keymap[] = {
+ /* Motion */
+ {"Home", "ctrl-a; alt-lt; home; a1"},
+ {"End", "ctrl-e; alt-gt; end; c1"},
+ {"Left", "left; alt-left; ctrl-b"},
+ {"Right", "right; alt-right; ctrl-f"},
+ {"WordLeft", "ctrl-left; alt-b"},
+ {"WordRight", "ctrl-right; alt-f"},
+ /* Mark */
+ {"MarkLeft", "shift-left"},
+ {"MarkRight", "shift-right"},
+ {"MarkToWordBegin", "ctrl-shift-left"},
+ {"MarkToWordEnd", "ctrl-shift-right"},
+ {"MarkToHome", "shift-home"},
+ {"MarkToEnd", "shift-end"},
+ /* Editing */
+ {"Backspace", "backspace; ctrl-h"},
+ {"Delete", "delete; ctrl-d"},
+ {"DeleteToWordEnd", "alt-d"},
+ {"DeleteToWordBegin", "alt-backspace"},
+ /* Region manipulation */
+ {"Remove", "ctrl-w"},
+ {"Store", "alt-w"},
+ {"Yank", "ctrl-y"},
+ {"DeleteToEnd", "ctrl-k"},
+ /* History */
+ {"History", "alt-h"},
+ {"HistoryPrev", "alt-p; ctrl-down"},
+ {"HistoryNext", "alt-n; ctrl-up"},
+ /* Completion */
+ {"Complete", "alt-tab"},
+ {NULL, NULL}
+};
+
+/* listbox */
+static const global_keymap_ini_t default_listbox_keymap[] = {
+ {"Up", "up; ctrl-p"},
+ {"Down", "down; ctrl-n"},
+ {"Top", "home; alt-lt; a1"},
+ {"Bottom", "end; alt-gt; c1"},
+ {"PageUp", "pgup; alt-v"},
+ {"PageDown", "pgdn; ctrl-v"},
+ {"Delete", "delete; d"},
+ {"Clear", "shift-delete; shift-d"},
+ {"View", "f3"},
+ {"Edit", "f4"},
+ {"Enter", "enter"},
+ {NULL, NULL}
+};
+
+/* radio */
+static const global_keymap_ini_t default_radio_keymap[] = {
+ {"Up", "up; ctrl-p"},
+ {"Down", "down; ctrl-n"},
+ {"Top", "home; alt-lt; a1"},
+ {"Bottom", "end; alt-gt; c1"},
+ {"Select", "space"},
+ {NULL, NULL}
+};
+
+/* tree */
+static const global_keymap_ini_t default_tree_keymap[] = {
+ {"Help", "f1"},
+ {"Rescan", "f2; ctrl-r"},
+ {"Forget", "f3"},
+ {"ToggleNavigation", "f4"},
+ {"Copy", "f5"},
+ {"Move", "f6"},
+#if 0
+ {"MakeDir", "f7"},
+#endif
+ {"Delete", "f8; delete"},
+ {"Up", "up; ctrl-p"},
+ {"Down", "down; ctrl-n"},
+ {"Left", "left"},
+ {"Right", "right"},
+ {"Top", "home; alt-lt; a1"},
+ {"Bottom", "end; alt-gt; c1"},
+ {"PageUp", "pgup; alt-v"},
+ {"PageDown", "pgdn; ctrl-v"},
+ {"Enter", "enter"},
+ {"Search", "ctrl-s; alt-s"},
+ {NULL, NULL}
+};
+
+/* help */
+static const global_keymap_ini_t default_help_keymap[] = {
+ {"Help", "f1"},
+ {"Index", "f2; c"},
+ {"Back", "f3; left; l"},
+ {"Quit", "f10; esc"},
+ {"Up", "up; ctrl-p"},
+ {"Down", "down; ctrl-n"},
+ {"PageDown", "f; space; pgdn; ctrl-v"},
+ {"PageUp", "b; pgup; alt-v; backspace"},
+ {"HalfPageDown", "d"},
+ {"HalfPageUp", "u"},
+ {"Top", "home; ctrl-home; ctrl-pgup; a1; alt-lt; g"},
+ {"Bottom", "end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g"},
+ {"Enter", "right; enter"},
+ {"LinkNext", "tab"},
+ {"LinkPrev", "alt-tab"},
+ {"NodeNext", "n"},
+ {"NodePrev", "p"},
+ {NULL, NULL}
+};
+
+#ifdef ENABLE_EXT2FS_ATTR
+/* chattr dialog */
+static const global_keymap_ini_t default_chattr_keymap[] = {
+ {"Up", "up; left; ctrl-p"},
+ {"Down", "down; right; ctrl-n"},
+ {"Top", "home; alt-lt; a1"},
+ {"Bottom", "end; alt-gt; c1"},
+ {"PageUp", "pgup; alt-v"},
+ {"PageDown", "pgdn; ctrl-v"},
+ {"Mark", "t; shift-t"},
+ {"MarkAndDown", "insert"},
+ {NULL, NULL}
+};
+#endif /* ENABLE_EXT2FS_ATTR */
+
+#ifdef USE_INTERNAL_EDIT
+static const global_keymap_ini_t default_editor_keymap[] = {
+ {"Enter", "enter"},
+ {"Return", "shift-enter; ctrl-enter; ctrl-shift-enter"}, /* useful for pasting multiline text */
+ {"Tab", "tab; shift-tab; ctrl-tab; ctrl-shift-tab"}, /* ditto */
+ {"BackSpace", "backspace; ctrl-h"},
+ {"Delete", "delete; ctrl-d"},
+ {"Left", "left"},
+ {"Right", "right"},
+ {"Up", "up"},
+ {"Down", "down"},
+ {"Home", "home"},
+ {"End", "end"},
+ {"PageUp", "pgup"},
+ {"PageDown", "pgdn"},
+ {"WordLeft", "ctrl-left; ctrl-z"},
+ {"WordRight", "ctrl-right; ctrl-x"},
+ {"InsertOverwrite", "insert"},
+ {"Help", "f1"},
+ {"Save", "f2"},
+ {"Mark", "f3"},
+ {"Replace", "f4"},
+ {"Copy", "f5"},
+ {"Move", "f6"},
+ {"Search", "f7"},
+ {"Remove", "f8; ctrl-delete"},
+ {"Menu", "f9"},
+ {"Quit", "f10; esc"},
+ {"UserMenu", "f11"},
+ {"SaveAs", "f12; ctrl-f2"},
+ {"MarkColumn", "f13"},
+ {"ReplaceContinue", "f14; ctrl-f4"},
+ {"InsertFile", "f15"},
+ {"SearchContinue", "f17; ctrl-f7"},
+ {"EditNew", "ctrl-n"},
+ {"DeleteToWordBegin", "alt-backspace"},
+ {"DeleteToWordEnd", "alt-d"},
+ {"DeleteLine", "ctrl-y"},
+ {"DeleteToEnd", "ctrl-k"},
+ {"Undo", "ctrl-u; ctrl-backspace"},
+ {"Redo", "alt-r"},
+#ifdef HAVE_CHARSET
+ {"SelectCodepage", "alt-e"},
+#endif
+ {"Goto", "alt-l; alt-shift-l"},
+ {"Refresh", "ctrl-l"},
+ {"Shell", "ctrl-o"},
+ {"Top", "ctrl-home; ctrl-pgup; alt-lt"},
+ {"Bottom", "ctrl-end; ctrl-pgdn; alt-gt"},
+ {"TopOnScreen", "ctrl-pgup"},
+ {"BottomOnScreen", "ctrl-pgdn"},
+ {"ScrollUp", "ctrl-up"},
+ {"ScrollDown", "ctrl-down"},
+ {"Store", "ctrl-insert"},
+ {"Paste", "shift-insert"},
+ {"Cut", "shift-delete"},
+ {"BlockSave", "ctrl-f"},
+ {"MarkLeft", "shift-left"},
+ {"MarkRight", "shift-right"},
+ {"MarkUp", "shift-up"},
+ {"MarkDown", "shift-down"},
+ {"MarkPageUp", "shift-pgup"},
+ {"MarkPageDown", "shift-pgdn"},
+ {"MarkToWordBegin", "ctrl-shift-left"},
+ {"MarkToWordEnd", "ctrl-shift-right"},
+ {"MarkToHome", "shift-home"},
+ {"MarkToEnd", "shift-end"},
+ {"MarkToFileBegin", "ctrl-shift-home"},
+ {"MarkToFileEnd", "ctrl-shift-end"},
+ {"MarkToPageBegin", "ctrl-shift-pgup"},
+ {"MarkToPageEnd", "ctrl-shift-pgdn"},
+ {"MarkScrollUp", "ctrl-shift-up"},
+ {"MarkScrollDown", "ctrl-shift-down"},
+ {"MarkColumnLeft", "alt-left"},
+ {"MarkColumnRight", "alt-right"},
+ {"MarkColumnUp", "alt-up"},
+ {"MarkColumnDown", "alt-down"},
+ {"MarkColumnPageUp", "alt-pgup"},
+ {"MarkColumnPageDown", "alt-pgdn"},
+ {"InsertLiteral", "ctrl-q"},
+ {"Complete", "alt-tab"},
+ {"MatchBracket", "alt-b"},
+ {"ParagraphFormat", "alt-p"},
+ {"Bookmark", "alt-k"},
+ {"BookmarkFlush", "alt-o"},
+ {"BookmarkNext", "alt-j"},
+ {"BookmarkPrev", "alt-i"},
+ {"MacroStartStopRecord", "ctrl-r"},
+ {"MacroExecute", "ctrl-a"},
+ {"ShowNumbers", "alt-n"},
+ {"ShowTabTws", "alt-underline"},
+ {"SyntaxOnOff", "ctrl-s"},
+ {"Find", "alt-enter"},
+ {"FilePrev", "alt-minus"},
+ {"FileNext", "alt-plus"},
+ {"Sort", "alt-t"},
+ {"Mail", "alt-m"},
+ {"ExternalCommand", "alt-u"},
+#ifdef HAVE_ASPELL
+ {"SpellCheckCurrentWord", "ctrl-p"},
+#endif
+ {"ExtendedKeyMap", "ctrl-x"},
+ {NULL, NULL}
+};
+
+/* emacs keyboard layout emulation */
+static const global_keymap_ini_t default_editor_x_keymap[] = {
+ {NULL, NULL}
+};
+#endif /* USE_INTERNAL_EDIT */
+
+/* viewer */
+static const global_keymap_ini_t default_viewer_keymap[] = {
+ {"Help", "f1"},
+ {"WrapMode", "f2"},
+ {"Quit", "f3; f10; q; esc"},
+ {"HexMode", "f4"},
+ {"Goto", "f5"},
+ {"Search", "f7"},
+ {"SearchContinue", "f17; n"},
+ {"MagicMode", "f8"},
+ {"NroffMode", "f9"},
+ {"Home", "ctrl-a"},
+ {"End", "ctrl-e"},
+ {"Left", "h; left"},
+ {"Right", "l; right"},
+ {"LeftQuick", "ctrl-left"},
+ {"RightQuick", "ctrl-right"},
+ {"Up", "k; y; insert; up; ctrl-p"},
+ {"Down", "j; e; delete; down; enter; ctrl-n"},
+ {"PageDown", "f; space; pgdn; ctrl-v"},
+ {"PageUp", "b; pgup; alt-v; backspace"},
+ {"HalfPageDown", "d"},
+ {"HalfPageUp", "u"},
+ {"Top", "home; ctrl-home; ctrl-pgup; a1; alt-lt; g"},
+ {"Bottom", "end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g"},
+ {"BookmarkGoto", "m"},
+ {"Bookmark", "r"},
+ {"FileNext", "ctrl-f"},
+ {"FilePrev", "ctrl-b"},
+#ifdef HAVE_CHARSET
+ {"SelectCodepage", "alt-e"},
+#endif
+ {"Shell", "ctrl-o"},
+ {"Ruler", "alt-r"},
+ {"SearchForward", "slash"},
+ {"SearchBackward", "question"},
+ {"SearchForwardContinue", "ctrl-s"},
+ {"SearchBackwardContinue", "ctrl-r"},
+ {"SearchOppositeContinue", "shift-n"},
+ {"History", "alt-shift-e"},
+ {NULL, NULL}
+};
+
+/* hex viewer */
+static const global_keymap_ini_t default_viewer_hex_keymap[] = {
+ {"Help", "f1"},
+ {"HexEditMode", "f2"},
+ {"Quit", "f3; f10; q; esc"},
+ {"HexMode", "f4"},
+ {"Goto", "f5"},
+ {"Save", "f6"},
+ {"Search", "f7"},
+ {"SearchContinue", "f17; n"},
+ {"MagicMode", "f8"},
+ {"NroffMode", "f9"},
+ {"ToggleNavigation", "tab"},
+ {"Home", "ctrl-a; home"},
+ {"End", "ctrl-e; end"},
+ {"Left", "b; left"},
+ {"Right", "f; right"},
+ {"Up", "k; y; up"},
+ {"Down", "j; delete; down"},
+ {"PageDown", "pgdn; ctrl-v"},
+ {"PageUp", "pgup; alt-v"},
+ {"Top", "ctrl-home; ctrl-pgup; a1; alt-lt; g"},
+ {"Bottom", "ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g"},
+#ifdef HAVE_CHARSET
+ {"SelectCodepage", "alt-e"},
+#endif
+ {"Shell", "ctrl-o"},
+ {"SearchForward", "slash"},
+ {"SearchBackward", "question"},
+ {"SearchForwardContinue", "ctrl-s"},
+ {"SearchBackwardContinue", "ctrl-r"},
+ {"SearchOppositeContinue", "shift-n"},
+ {"History", "alt-shift-e"},
+ {NULL, NULL}
+};
+
+#ifdef USE_DIFF_VIEW
+/* diff viewer */
+static const global_keymap_ini_t default_diff_keymap[] = {
+ {"ShowSymbols", "alt-s; s"},
+ {"ShowNumbers", "alt-n; l"},
+ {"SplitFull", "f"},
+ {"SplitEqual", "equal"},
+ {"SplitMore", "gt"},
+ {"SplitLess", "lt"},
+ {"Tab2", "2"},
+ {"Tab3", "3"},
+ {"Tab4", "4"},
+ {"Tab8", "8"},
+ {"Swap", "ctrl-u"},
+ {"Redo", "ctrl-r"},
+ {"HunkNext", "n; enter; space"},
+ {"HunkPrev", "p; backspace"},
+ {"Goto", "g; shift-g"},
+ {"Save", "f2"},
+ {"Edit", "f4"},
+ {"EditOther", "f14"},
+ {"Merge", "f5"},
+ {"MergeOther", "f15"},
+ {"Search", "f7"},
+ {"SearchContinue", "f17"},
+ {"Options", "f9"},
+ {"Top", "ctrl-home"},
+ {"Bottom", "ctrl-end"},
+ {"Down", "down"},
+ {"Up", "up"},
+ {"LeftQuick", "ctrl-left"},
+ {"RightQuick", "ctrl-right"},
+ {"Left", "left"},
+ {"Right", "right"},
+ {"PageDown", "pgdn"},
+ {"PageUp", "pgup"},
+ {"Home", "home"},
+ {"End", "end"},
+ {"Help", "f1"},
+ {"Quit", "f10; q; shift-q; esc"},
+#ifdef HAVE_CHARSET
+ {"SelectCodepage", "alt-e"},
+#endif
+ {"Shell", "ctrl-o"},
+ {NULL, NULL}
+};
+#endif
+
+/* --------------------------------------------------------------------------------------------- */
+/*** file scope functions ************************************************************************/
+/* --------------------------------------------------------------------------------------------- */
+
+static void
+create_default_keymap_section (mc_config_t * keymap, const char *section,
+ const global_keymap_ini_t * k)
+{
+ size_t i;
+
+ for (i = 0; k[i].key != NULL; i++)
+ mc_config_set_string_raw (keymap, section, k[i].key, k[i].value);
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+static mc_config_t *
+create_default_keymap (void)
+{
+ mc_config_t *keymap;
+
+ keymap = mc_config_init (NULL, TRUE);
+
+ create_default_keymap_section (keymap, KEYMAP_SECTION_FILEMANAGER, default_filemanager_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_FILEMANAGER_EXT,
+ default_filemanager_x_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_PANEL, default_panel_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_DIALOG, default_dialog_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_MENU, default_menu_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_INPUT, default_input_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_LISTBOX, default_listbox_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_RADIO, default_radio_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_TREE, default_tree_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_HELP, default_help_keymap);
+#ifdef ENABLE_EXT2FS_ATTR
+ create_default_keymap_section (keymap, KEYMAP_SECTION_HELP, default_chattr_keymap);
+#endif
+#ifdef USE_INTERNAL_EDIT
+ create_default_keymap_section (keymap, KEYMAP_SECTION_EDITOR, default_editor_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_EDITOR_EXT, default_editor_x_keymap);
+#endif
+ create_default_keymap_section (keymap, KEYMAP_SECTION_VIEWER, default_viewer_keymap);
+ create_default_keymap_section (keymap, KEYMAP_SECTION_VIEWER_HEX, default_viewer_hex_keymap);
+#ifdef USE_DIFF_VIEW
+ create_default_keymap_section (keymap, KEYMAP_SECTION_DIFFVIEWER, default_diff_keymap);
+#endif
+
+ return keymap;
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+static void
+load_keymap_from_section (const char *section_name, GArray * keymap, mc_config_t * cfg)
+{
+ gchar **profile_keys, **keys;
+
+ if (section_name == NULL)
+ return;
+
+ keys = mc_config_get_keys (cfg, section_name, NULL);
+
+ for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
+ {
+ gchar **values;
+
+ values = mc_config_get_string_list (cfg, section_name, *profile_keys, NULL);
+ if (values != NULL)
+ {
+ long action;
+
+ action = keybind_lookup_action (*profile_keys);
+ if (action > 0)
+ {
+ gchar **curr_values;
+
+ for (curr_values = values; *curr_values != NULL; curr_values++)
+ keybind_cmd_bind (keymap, *curr_values, action);
+ }
+
+ g_strfreev (values);
+ }
+ }
+
+ g_strfreev (keys);
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * Get name of config file.
+ *
+ * @param subdir If not NULL, config is also searched in specified subdir.
+ * @param config_file_name If relative, file if searched in standard paths.
+ *
+ * @return newly allocated string with config name or NULL if file is not found.
+ */
+
+static char *
+load_setup_get_full_config_name (const char *subdir, const char *config_file_name)
+{
+ /*
+ TODO: IMHO, in future, this function shall be placed in mcconfig module.
+ */
+ char *lc_basename, *ret;
+ char *file_name;
+
+ if (config_file_name == NULL)
+ return NULL;
+
+ /* check for .keymap suffix */
+ if (g_str_has_suffix (config_file_name, ".keymap"))
+ file_name = g_strdup (config_file_name);
+ else
+ file_name = g_strconcat (config_file_name, ".keymap", (char *) NULL);
+
+ canonicalize_pathname (file_name);
+
+ if (g_path_is_absolute (file_name))
+ return file_name;
+
+ lc_basename = g_path_get_basename (file_name);
+ g_free (file_name);
+
+ if (lc_basename == NULL)
+ return NULL;
+
+ if (subdir != NULL)
+ ret = g_build_filename (mc_config_get_path (), subdir, lc_basename, (char *) NULL);
+ else
+ ret = g_build_filename (mc_config_get_path (), lc_basename, (char *) NULL);
+
+ if (exist_file (ret))
+ {
+ g_free (lc_basename);
+ canonicalize_pathname (ret);
+ return ret;
+ }
+ g_free (ret);
+
+ if (subdir != NULL)
+ ret = g_build_filename (mc_global.share_data_dir, subdir, lc_basename, (char *) NULL);
+ else
+ ret = g_build_filename (mc_global.share_data_dir, lc_basename, (char *) NULL);
+
+ g_free (lc_basename);
+
+ if (exist_file (ret))
+ {
+ canonicalize_pathname (ret);
+ return ret;
+ }
+
+ g_free (ret);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/**
+ Create new mc_config object from specified ini-file or
+ append data to existing mc_config object from ini-file
+*/
+
+static void
+load_setup_init_config_from_file (mc_config_t ** config, const char *fname, gboolean read_only)
+{
+ /*
+ TODO: IMHO, in future, this function shall be placed in mcconfig module.
+ */
+ if (exist_file (fname))
+ {
+ if (*config != NULL)
+ mc_config_read_file (*config, fname, read_only, TRUE);
+ else
+ *config = mc_config_init (fname, read_only);
+ }
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+static mc_config_t *
+load_setup_get_keymap_profile_config (gboolean load_from_file)
+{
+ /*
+ TODO: IMHO, in future, this function shall be placed in mcconfig module.
+ */
+ mc_config_t *keymap_config;
+ char *share_keymap, *sysconfig_keymap;
+ char *fname, *fname2;
+
+ /* 0) Create default keymap */
+ keymap_config = create_default_keymap ();
+ if (!load_from_file)
+ return keymap_config;
+
+ /* load and merge global keymaps */
+
+ /* 1) /usr/share/mc (mc_global.share_data_dir) */
+ share_keymap = g_build_filename (mc_global.share_data_dir, GLOBAL_KEYMAP_FILE, (char *) NULL);
+ load_setup_init_config_from_file (&keymap_config, share_keymap, TRUE);
+
+ /* 2) /etc/mc (mc_global.sysconfig_dir) */
+ sysconfig_keymap =
+ g_build_filename (mc_global.sysconfig_dir, GLOBAL_KEYMAP_FILE, (char *) NULL);
+ load_setup_init_config_from_file (&keymap_config, sysconfig_keymap, TRUE);
+
+ /* then load and merge one of user-defined keymap */
+
+ /* 3) --keymap=<keymap> */
+ fname = load_setup_get_full_config_name (NULL, mc_args__keymap_file);
+ if (fname != NULL && strcmp (fname, sysconfig_keymap) != 0 && strcmp (fname, share_keymap) != 0)
+ {
+ load_setup_init_config_from_file (&keymap_config, fname, TRUE);
+ goto done;
+ }
+ g_free (fname);
+
+ /* 4) getenv("MC_KEYMAP") */
+ fname = load_setup_get_full_config_name (NULL, g_getenv ("MC_KEYMAP"));
+ if (fname != NULL && strcmp (fname, sysconfig_keymap) != 0 && strcmp (fname, share_keymap) != 0)
+ {
+ load_setup_init_config_from_file (&keymap_config, fname, TRUE);
+ goto done;
+ }
+
+ MC_PTR_FREE (fname);
+
+ /* 5) main config; [Midnight Commander] -> keymap */
+ fname2 = mc_config_get_string (mc_global.main_config, CONFIG_APP_SECTION, "keymap", NULL);
+ if (fname2 != NULL && *fname2 != '\0')
+ fname = load_setup_get_full_config_name (NULL, fname2);
+ g_free (fname2);
+ if (fname != NULL && strcmp (fname, sysconfig_keymap) != 0 && strcmp (fname, share_keymap) != 0)
+ {
+ load_setup_init_config_from_file (&keymap_config, fname, TRUE);
+ goto done;
+ }
+ g_free (fname);
+
+ /* 6) ${XDG_CONFIG_HOME}/mc/mc.keymap */
+ fname = mc_config_get_full_path (GLOBAL_KEYMAP_FILE);
+ load_setup_init_config_from_file (&keymap_config, fname, TRUE);
+
+ done:
+ g_free (fname);
+ g_free (sysconfig_keymap);
+ g_free (share_keymap);
+
+ return keymap_config;
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/*** public functions ****************************************************************************/
+/* --------------------------------------------------------------------------------------------- */
+
+void
+keymap_load (gboolean load_from_file)
+{
+ /*
+ * Load keymap from GLOBAL_KEYMAP_FILE before ${XDG_CONFIG_HOME}/mc/mc.keymap, so that the user
+ * definitions override global settings.
+ */
+ mc_config_t *mc_global_keymap;
+
+ mc_global_keymap = load_setup_get_keymap_profile_config (load_from_file);
+
+ if (mc_global_keymap != NULL)
+ {
+#define LOAD_KEYMAP(s,km) \
+ km##_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t)); \
+ load_keymap_from_section (KEYMAP_SECTION_##s, km##_keymap, mc_global_keymap)
+
+ LOAD_KEYMAP (FILEMANAGER, filemanager);
+ LOAD_KEYMAP (FILEMANAGER_EXT, filemanager_x);
+ LOAD_KEYMAP (PANEL, panel);
+ LOAD_KEYMAP (DIALOG, dialog);
+ LOAD_KEYMAP (MENU, menu);
+ LOAD_KEYMAP (INPUT, input);
+ LOAD_KEYMAP (LISTBOX, listbox);
+ LOAD_KEYMAP (RADIO, radio);
+ LOAD_KEYMAP (TREE, tree);
+ LOAD_KEYMAP (HELP, help);
+#ifdef ENABLE_EXT2FS_ATTR
+ LOAD_KEYMAP (CHATTR, chattr);
+#endif
+#ifdef USE_INTERNAL_EDIT
+ LOAD_KEYMAP (EDITOR, editor);
+ LOAD_KEYMAP (EDITOR_EXT, editor_x);
+#endif
+ LOAD_KEYMAP (VIEWER, viewer);
+ LOAD_KEYMAP (VIEWER_HEX, viewer_hex);
+#ifdef USE_DIFF_VIEW
+ LOAD_KEYMAP (DIFFVIEWER, diff);
+#endif
+
+#undef LOAD_KEYMAP
+ mc_config_deinit (mc_global_keymap);
+ }
+
+#define SET_MAP(m) \
+ m##_map = (global_keymap_t *) m##_keymap->data
+
+ SET_MAP (filemanager);
+ SET_MAP (filemanager_x);
+ SET_MAP (panel);
+ SET_MAP (dialog);
+ SET_MAP (menu);
+ SET_MAP (input);
+ SET_MAP (listbox);
+ SET_MAP (radio);
+ SET_MAP (tree);
+ SET_MAP (help);
+#ifdef ENABLE_EXT2FS_ATTR
+ SET_MAP (chattr);
+#endif
+#ifdef USE_INTERNAL_EDIT
+ SET_MAP (editor);
+ SET_MAP (editor_x);
+#endif
+ SET_MAP (viewer);
+ SET_MAP (viewer_hex);
+#ifdef USE_DIFF_VIEW
+ SET_MAP (diff);
+#endif
+
+#undef SET_MAP
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+void
+keymap_free (void)
+{
+#define FREE_KEYMAP(km) \
+ if (km##_keymap != NULL) \
+ g_array_free (km##_keymap, TRUE)
+
+ FREE_KEYMAP (filemanager);
+ FREE_KEYMAP (filemanager_x);
+ FREE_KEYMAP (panel);
+ FREE_KEYMAP (dialog);
+ FREE_KEYMAP (menu);
+ FREE_KEYMAP (input);
+ FREE_KEYMAP (listbox);
+ FREE_KEYMAP (radio);
+ FREE_KEYMAP (tree);
+ FREE_KEYMAP (help);
+#ifdef ENABLE_EXT2FS_ATTR
+ FREE_KEYMAP (chattr);
+#endif
+#ifdef USE_INTERNAL_EDIT
+ FREE_KEYMAP (editor);
+ FREE_KEYMAP (editor_x);
+#endif
+ FREE_KEYMAP (viewer);
+ FREE_KEYMAP (viewer_hex);
+#ifdef USE_DIFF_VIEW
+ FREE_KEYMAP (diff);
+#endif
+
+#undef FREE_KEYMAP
+}
+
+/* --------------------------------------------------------------------------------------------- */