/* Default values and initialization of keybinding engine Copyright (C) 2009-2025 Free Software Foundation, Inc. Written by: Vitja Makarov, 2005 Ilia Maslakov , 2009, 2010 Andrew Borodin , 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 . */ #include #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 #ifdef ENABLE_VFS { "VfsList", "a" }, #endif { "PutCurrentPath", "p" }, { "PutOtherPath", "ctrl-p" }, { "PutCurrentTagged", "t" }, { "PutOtherTagged", "ctrl-t" }, { "ChangeMode", "c" }, { "ChangeOwn", "o" }, #ifdef ENABLE_EXT2FS_ATTR { "ChangeAttributes", "e" }, #endif { "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 { "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" }, { "SelectCodepage", "alt-e" }, { "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 #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" }, { "SelectCodepage", "alt-e" }, { "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 /* 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" }, { "SelectCodepage", "alt-e" }, { "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" }, { "SelectCodepage", "alt-e" }, { "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" }, { "SelectCodepage", "alt-e" }, { "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= 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 } /* --------------------------------------------------------------------------------------------- */