tar: avoid strtoul().
[midnight-commander.git] / src / keymap.c
blob969be18708d75ea064b5dffaee6889f8c1f298ea
1 /*
2 Default values and initialization of keybinding engine
4 Copyright (C) 2009-2024
5 Free Software Foundation, Inc.
7 Written by:
8 Vitja Makarov, 2005
9 Ilia Maslakov <il.smind@gmail.com>, 2009, 2010
10 Andrew Borodin <aborodin@vmail.ru>, 2010-2021
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/>.
28 #include <config.h>
30 #include "lib/global.h"
32 #include "lib/fileloc.h"
33 #include "lib/keybind.h"
34 #include "lib/mcconfig.h" /* mc_config_t */
35 #include "lib/util.h"
36 #include "lib/widget.h" /* dialog_map, input_map, listbox_map, menu_map, radio_map */
38 #include "args.h" /* mc_args__keymap_file */
40 #include "keymap.h"
42 /*** global variables ****************************************************************************/
44 GArray *filemanager_keymap = NULL;
45 GArray *filemanager_x_keymap = NULL;
46 GArray *panel_keymap = NULL;
47 GArray *dialog_keymap = NULL;
48 GArray *menu_keymap = NULL;
49 GArray *input_keymap = NULL;
50 GArray *listbox_keymap = NULL;
51 GArray *radio_keymap = NULL;
52 GArray *tree_keymap = NULL;
53 GArray *help_keymap = NULL;
54 #ifdef ENABLE_EXT2FS_ATTR
55 GArray *chattr_keymap = NULL;
56 #endif
57 #ifdef USE_INTERNAL_EDIT
58 GArray *editor_keymap = NULL;
59 GArray *editor_x_keymap = NULL;
60 #endif
61 GArray *viewer_keymap = NULL;
62 GArray *viewer_hex_keymap = NULL;
63 #ifdef USE_DIFF_VIEW
64 GArray *diff_keymap = NULL;
65 #endif
67 const global_keymap_t *filemanager_map = NULL;
68 const global_keymap_t *filemanager_x_map = NULL;
69 const global_keymap_t *panel_map = NULL;
70 const global_keymap_t *tree_map = NULL;
71 const global_keymap_t *help_map = NULL;
72 #ifdef ENABLE_EXT2FS_ATTR
73 const global_keymap_t *chattr_map = NULL;
74 #endif
75 #ifdef USE_INTERNAL_EDIT
76 const global_keymap_t *editor_map = NULL;
77 const global_keymap_t *editor_x_map = NULL;
78 #endif
79 const global_keymap_t *viewer_map = NULL;
80 const global_keymap_t *viewer_hex_map = NULL;
81 #ifdef USE_DIFF_VIEW
82 const global_keymap_t *diff_map = NULL;
83 #endif
85 /*** file scope macro definitions ****************************************************************/
87 /*** file scope type declarations ****************************************************************/
89 /* default keymaps in ini (key=value) format */
90 typedef struct global_keymap_ini_t
92 const char *key;
93 const char *value;
94 } global_keymap_ini_t;
96 /*** forward declarations (file scope functions) *************************************************/
98 /*** file scope variables ************************************************************************/
100 /* midnight */
101 static const global_keymap_ini_t default_filemanager_keymap[] = {
102 {"ChangePanel", "tab; ctrl-i"},
103 {"Help", "f1"},
104 {"UserMenu", "f2"},
105 {"View", "f3"},
106 {"Edit", "f4"},
107 {"Copy", "f5"},
108 {"Move", "f6"},
109 {"MakeDir", "f7"},
110 {"Delete", "f8"},
111 {"Menu", "f9"},
112 {"Quit", "f10"},
113 {"MenuLastSelected", "f19"},
114 {"QuitQuiet", "f20"},
115 {"History", "alt-h"},
116 {"EditorViewerHistory", "alt-shift-e"},
117 {"DirSize", "ctrl-space"},
118 /* Copy useful information to the command line */
119 {"PutCurrentPath", "alt-a"},
120 {"PutOtherPath", "alt-shift-a"},
121 {"PutCurrentSelected", "alt-enter; ctrl-enter"},
122 {"PutCurrentFullSelected", "ctrl-shift-enter"},
123 {"CdQuick", "alt-c"},
124 /* To access the directory hotlist */
125 {"HotList", "ctrl-backslash"},
126 /* Suspend */
127 {"Suspend", "ctrl-z"},
128 /* The filtered view command */
129 {"ViewFiltered", "alt-exclamation"},
130 /* Find file */
131 {"Find", "alt-question"},
132 /* Panel refresh */
133 {"Reread", "ctrl-r"},
134 /* Switch listing between long, user defined and full formats */
135 /* Swap panels */
136 {"Swap", "ctrl-u"},
137 /* Resize panels */
138 {"SplitEqual", "alt-equal"},
139 {"SplitMore", "alt-shift-right"},
140 {"SplitLess", "alt-shift-left"},
141 /* View output */
142 {"Shell", "ctrl-o"},
143 {"ShowHidden", "alt-dot"},
144 {"SplitVertHoriz", "alt-comma"},
145 {"ExtendedKeyMap", "ctrl-x"},
146 /* Select/unselect group */
147 {"Select", "kpplus"},
148 {"Unselect", "kpminus"},
149 {"SelectInvert", "kpasterisk"},
150 /* List of screens */
151 {"ScreenList", "alt-prime"},
152 {NULL, NULL}
155 static const global_keymap_ini_t default_filemanager_x_keymap[] = {
156 {"CompareDirs", "d"},
157 #ifdef USE_DIFF_VIEW
158 {"CompareFiles", "ctrl-d"},
159 #endif /* USE_DIFF_VIEW */
160 #ifdef ENABLE_VFS
161 {"VfsList", "a"},
162 #endif /* ENABLE_VFS */
163 {"PutCurrentPath", "p"},
164 {"PutOtherPath", "ctrl-p"},
165 {"PutCurrentTagged", "t"},
166 {"PutOtherTagged", "ctrl-t"},
167 {"ChangeMode", "c"},
168 {"ChangeOwn", "o"},
169 #ifdef ENABLE_EXT2FS_ATTR
170 {"ChangeAttributes", "e"},
171 #endif /* ENABLE_EXT2FS_ATTR */
172 {"PutCurrentLink", "r"},
173 {"PutOtherLink", "ctrl-r"},
174 {"Link", "l"},
175 {"LinkSymbolic", "s"},
176 {"LinkSymbolicRelative", "v"},
177 {"LinkSymbolicEdit", "ctrl-s"},
178 {"PanelInfo", "i"},
179 {"PanelQuickView", "q"},
180 {"HotListAdd", "h"},
181 #ifdef ENABLE_BACKGROUND
182 {"Jobs", "j"},
183 #endif /* ENABLE_BACKGROUND */
184 {"ExternalPanelize", "!"},
185 {NULL, NULL}
188 /* panel */
189 static const global_keymap_ini_t default_panel_keymap[] = {
190 {"CycleListingFormat", "alt-t"},
191 {"PanelOtherCd", "alt-o"},
192 {"PanelOtherCdLink", "alt-l"},
193 {"CopySingle", "f15"},
194 {"DeleteSingle", "f18"},
195 {"Enter", "enter"},
196 {"EditNew", "f14"},
197 {"MoveSingle", "f16"},
198 {"SelectInvert", "alt-asterisk"},
199 {"Select", "alt-plus"},
200 {"Unselect", "alt-minus"},
201 {"ViewRaw", "f13"},
202 {"CdChild", "ctrl-pgdn"},
203 {"CdParent", "ctrl-pgup"},
204 {"History", "alt-shift-h"},
205 {"HistoryNext", "alt-u"},
206 {"HistoryPrev", "alt-y"},
207 {"BottomOnScreen", "alt-j"},
208 {"MiddleOnScreen", "alt-r"},
209 {"TopOnScreen", "alt-g"},
210 {"Mark", "insert; ctrl-t"},
211 {"MarkDown", "shift-down"},
212 {"MarkUp", "shift-up"},
213 {"Up", "up; ctrl-p"},
214 {"Down", "down; ctrl-n"},
215 {"Left", "left"},
216 {"Right", "right"},
217 {"Top", "alt-lt; home; a1"},
218 {"Bottom", "alt-gt; end; c1"},
219 {"PageDown", "pgdn; ctrl-v"},
220 {"PageUp", "pgup; alt-v"},
221 #ifdef HAVE_CHARSET
222 {"SelectCodepage", "alt-e"},
223 #endif
224 {"Search", "ctrl-s; alt-s"},
225 {"PanelOtherSync", "alt-i"},
226 {NULL, NULL}
229 /* dialog */
230 static const global_keymap_ini_t default_dialog_keymap[] = {
231 {"Ok", "enter"},
232 {"Cancel", "f10; esc; ctrl-g"},
233 {"Up", "up; left"},
234 {"Down", "down; right"},
235 #if 0
236 {"Left", "up; left"},
237 {"Right", "down; right"},
238 #endif
239 {"Help", "f1"},
240 {"Suspend", "ctrl-z"},
241 {"Refresh", "ctrl-l"},
242 {"ScreenList", "alt-prime"},
243 {"ScreenNext", "alt-rbrace"},
244 {"ScreenPrev", "alt-lbrace"},
245 {NULL, NULL}
248 /* menubar */
249 static const global_keymap_ini_t default_menu_keymap[] = {
250 {"Help", "f1"},
251 {"Left", "left; ctrl-b"},
252 {"Right", "right; ctrl-f"},
253 {"Up", "up; ctrl-p"},
254 {"Down", "down; ctrl-n"},
255 {"Home", "home; alt-lt; ctrl-a"},
256 {"End", "end; alt-gt; ctrl-e"},
257 {"Enter", "enter"},
258 {"Quit", "f10; ctrl-g; esc"},
259 {NULL, NULL}
262 /* input line */
263 static const global_keymap_ini_t default_input_keymap[] = {
264 /* Motion */
265 {"Home", "ctrl-a; alt-lt; home; a1"},
266 {"End", "ctrl-e; alt-gt; end; c1"},
267 {"Left", "left; alt-left; ctrl-b"},
268 {"Right", "right; alt-right; ctrl-f"},
269 {"WordLeft", "ctrl-left; alt-b"},
270 {"WordRight", "ctrl-right; alt-f"},
271 /* Mark */
272 {"MarkLeft", "shift-left"},
273 {"MarkRight", "shift-right"},
274 {"MarkToWordBegin", "ctrl-shift-left"},
275 {"MarkToWordEnd", "ctrl-shift-right"},
276 {"MarkToHome", "shift-home"},
277 {"MarkToEnd", "shift-end"},
278 /* Editing */
279 {"Backspace", "backspace; ctrl-h"},
280 {"Delete", "delete; ctrl-d"},
281 {"DeleteToWordEnd", "alt-d"},
282 {"DeleteToWordBegin", "alt-backspace"},
283 /* Region manipulation */
284 {"Remove", "ctrl-w"},
285 {"Store", "alt-w"},
286 {"Yank", "ctrl-y"},
287 {"DeleteToEnd", "ctrl-k"},
288 /* History */
289 {"History", "alt-h"},
290 {"HistoryPrev", "alt-p; ctrl-down"},
291 {"HistoryNext", "alt-n; ctrl-up"},
292 /* Completion */
293 {"Complete", "alt-tab"},
294 {NULL, NULL}
297 /* listbox */
298 static const global_keymap_ini_t default_listbox_keymap[] = {
299 {"Up", "up; ctrl-p"},
300 {"Down", "down; ctrl-n"},
301 {"Top", "home; alt-lt; a1"},
302 {"Bottom", "end; alt-gt; c1"},
303 {"PageUp", "pgup; alt-v"},
304 {"PageDown", "pgdn; ctrl-v"},
305 {"Delete", "delete; d"},
306 {"Clear", "shift-delete; shift-d"},
307 {"View", "f3"},
308 {"Edit", "f4"},
309 {"Enter", "enter"},
310 {NULL, NULL}
313 /* radio */
314 static const global_keymap_ini_t default_radio_keymap[] = {
315 {"Up", "up; ctrl-p"},
316 {"Down", "down; ctrl-n"},
317 {"Top", "home; alt-lt; a1"},
318 {"Bottom", "end; alt-gt; c1"},
319 {"Select", "space"},
320 {NULL, NULL}
323 /* tree */
324 static const global_keymap_ini_t default_tree_keymap[] = {
325 {"Help", "f1"},
326 {"Rescan", "f2; ctrl-r"},
327 {"Forget", "f3"},
328 {"ToggleNavigation", "f4"},
329 {"Copy", "f5"},
330 {"Move", "f6"},
331 #if 0
332 {"MakeDir", "f7"},
333 #endif
334 {"Delete", "f8; delete"},
335 {"Up", "up; ctrl-p"},
336 {"Down", "down; ctrl-n"},
337 {"Left", "left"},
338 {"Right", "right"},
339 {"Top", "home; alt-lt; a1"},
340 {"Bottom", "end; alt-gt; c1"},
341 {"PageUp", "pgup; alt-v"},
342 {"PageDown", "pgdn; ctrl-v"},
343 {"Enter", "enter"},
344 {"Search", "ctrl-s; alt-s"},
345 {NULL, NULL}
348 /* help */
349 static const global_keymap_ini_t default_help_keymap[] = {
350 {"Help", "f1"},
351 {"Index", "f2; c"},
352 {"Back", "f3; left; l"},
353 {"Quit", "f10; esc"},
354 {"Up", "up; ctrl-p"},
355 {"Down", "down; ctrl-n"},
356 {"PageDown", "f; space; pgdn; ctrl-v"},
357 {"PageUp", "b; pgup; alt-v; backspace"},
358 {"HalfPageDown", "d"},
359 {"HalfPageUp", "u"},
360 {"Top", "home; ctrl-home; ctrl-pgup; a1; alt-lt; g"},
361 {"Bottom", "end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g"},
362 {"Enter", "right; enter"},
363 {"LinkNext", "tab"},
364 {"LinkPrev", "alt-tab"},
365 {"NodeNext", "n"},
366 {"NodePrev", "p"},
367 {NULL, NULL}
370 #ifdef ENABLE_EXT2FS_ATTR
371 /* chattr dialog */
372 static const global_keymap_ini_t default_chattr_keymap[] = {
373 {"Up", "up; left; ctrl-p"},
374 {"Down", "down; right; ctrl-n"},
375 {"Top", "home; alt-lt; a1"},
376 {"Bottom", "end; alt-gt; c1"},
377 {"PageUp", "pgup; alt-v"},
378 {"PageDown", "pgdn; ctrl-v"},
379 {"Mark", "t; shift-t"},
380 {"MarkAndDown", "insert"},
381 {NULL, NULL}
383 #endif /* ENABLE_EXT2FS_ATTR */
385 #ifdef USE_INTERNAL_EDIT
386 static const global_keymap_ini_t default_editor_keymap[] = {
387 {"Enter", "enter"},
388 {"Return", "shift-enter; ctrl-enter; ctrl-shift-enter"}, /* useful for pasting multiline text */
389 {"Tab", "tab; shift-tab; ctrl-tab; ctrl-shift-tab"}, /* ditto */
390 {"BackSpace", "backspace; ctrl-h"},
391 {"Delete", "delete; ctrl-d"},
392 {"Left", "left"},
393 {"Right", "right"},
394 {"Up", "up"},
395 {"Down", "down"},
396 {"Home", "home"},
397 {"End", "end"},
398 {"PageUp", "pgup"},
399 {"PageDown", "pgdn"},
400 {"WordLeft", "ctrl-left; ctrl-z"},
401 {"WordRight", "ctrl-right; ctrl-x"},
402 {"InsertOverwrite", "insert"},
403 {"Help", "f1"},
404 {"Save", "f2"},
405 {"Mark", "f3"},
406 {"Replace", "f4"},
407 {"Copy", "f5"},
408 {"Move", "f6"},
409 {"Search", "f7"},
410 {"Remove", "f8; ctrl-delete"},
411 {"Menu", "f9"},
412 {"Quit", "f10; esc"},
413 {"UserMenu", "f11"},
414 {"SaveAs", "f12; ctrl-f2"},
415 {"MarkColumn", "f13"},
416 {"ReplaceContinue", "f14; ctrl-f4"},
417 {"InsertFile", "f15"},
418 {"SearchContinue", "f17; ctrl-f7"},
419 {"EditNew", "ctrl-n"},
420 {"DeleteToWordBegin", "alt-backspace"},
421 {"DeleteToWordEnd", "alt-d"},
422 {"DeleteLine", "ctrl-y"},
423 {"DeleteToEnd", "ctrl-k"},
424 {"Undo", "ctrl-u; ctrl-backspace"},
425 {"Redo", "alt-r"},
426 #ifdef HAVE_CHARSET
427 {"SelectCodepage", "alt-e"},
428 #endif
429 {"Goto", "alt-l; alt-shift-l"},
430 {"Refresh", "ctrl-l"},
431 {"Shell", "ctrl-o"},
432 {"Top", "ctrl-home; ctrl-pgup; alt-lt"},
433 {"Bottom", "ctrl-end; ctrl-pgdn; alt-gt"},
434 {"TopOnScreen", "ctrl-pgup"},
435 {"BottomOnScreen", "ctrl-pgdn"},
436 {"ScrollUp", "ctrl-up"},
437 {"ScrollDown", "ctrl-down"},
438 {"Store", "ctrl-insert"},
439 {"Paste", "shift-insert"},
440 {"Cut", "shift-delete"},
441 {"BlockSave", "ctrl-f"},
442 {"MarkLeft", "shift-left"},
443 {"MarkRight", "shift-right"},
444 {"MarkUp", "shift-up"},
445 {"MarkDown", "shift-down"},
446 {"MarkPageUp", "shift-pgup"},
447 {"MarkPageDown", "shift-pgdn"},
448 {"MarkToWordBegin", "ctrl-shift-left"},
449 {"MarkToWordEnd", "ctrl-shift-right"},
450 {"MarkToHome", "shift-home"},
451 {"MarkToEnd", "shift-end"},
452 {"MarkToFileBegin", "ctrl-shift-home"},
453 {"MarkToFileEnd", "ctrl-shift-end"},
454 {"MarkToPageBegin", "ctrl-shift-pgup"},
455 {"MarkToPageEnd", "ctrl-shift-pgdn"},
456 {"MarkScrollUp", "ctrl-shift-up"},
457 {"MarkScrollDown", "ctrl-shift-down"},
458 {"MarkColumnLeft", "alt-left"},
459 {"MarkColumnRight", "alt-right"},
460 {"MarkColumnUp", "alt-up"},
461 {"MarkColumnDown", "alt-down"},
462 {"MarkColumnPageUp", "alt-pgup"},
463 {"MarkColumnPageDown", "alt-pgdn"},
464 {"InsertLiteral", "ctrl-q"},
465 {"Complete", "alt-tab"},
466 {"MatchBracket", "alt-b"},
467 {"ParagraphFormat", "alt-p"},
468 {"Bookmark", "alt-k"},
469 {"BookmarkFlush", "alt-o"},
470 {"BookmarkNext", "alt-j"},
471 {"BookmarkPrev", "alt-i"},
472 {"MacroStartStopRecord", "ctrl-r"},
473 {"MacroExecute", "ctrl-a"},
474 {"ShowNumbers", "alt-n"},
475 {"ShowTabTws", "alt-underline"},
476 {"SyntaxOnOff", "ctrl-s"},
477 {"Find", "alt-enter"},
478 {"FilePrev", "alt-minus"},
479 {"FileNext", "alt-plus"},
480 {"Sort", "alt-t"},
481 {"Mail", "alt-m"},
482 {"ExternalCommand", "alt-u"},
483 #ifdef HAVE_ASPELL
484 {"SpellCheckCurrentWord", "ctrl-p"},
485 #endif
486 {"ExtendedKeyMap", "ctrl-x"},
487 {NULL, NULL}
490 /* emacs keyboard layout emulation */
491 static const global_keymap_ini_t default_editor_x_keymap[] = {
492 {NULL, NULL}
494 #endif /* USE_INTERNAL_EDIT */
496 /* viewer */
497 static const global_keymap_ini_t default_viewer_keymap[] = {
498 {"Help", "f1"},
499 {"WrapMode", "f2"},
500 {"Quit", "f3; f10; q; esc"},
501 {"HexMode", "f4"},
502 {"Goto", "f5"},
503 {"Search", "f7"},
504 {"SearchContinue", "f17; n"},
505 {"MagicMode", "f8"},
506 {"NroffMode", "f9"},
507 {"Home", "ctrl-a"},
508 {"End", "ctrl-e"},
509 {"Left", "h; left"},
510 {"Right", "l; right"},
511 {"LeftQuick", "ctrl-left"},
512 {"RightQuick", "ctrl-right"},
513 {"Up", "k; y; insert; up; ctrl-p"},
514 {"Down", "j; e; delete; down; enter; ctrl-n"},
515 {"PageDown", "f; space; pgdn; ctrl-v"},
516 {"PageUp", "b; pgup; alt-v; backspace"},
517 {"HalfPageDown", "d"},
518 {"HalfPageUp", "u"},
519 {"Top", "home; ctrl-home; ctrl-pgup; a1; alt-lt; g"},
520 {"Bottom", "end; ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g"},
521 {"BookmarkGoto", "m"},
522 {"Bookmark", "r"},
523 {"FileNext", "ctrl-f"},
524 {"FilePrev", "ctrl-b"},
525 #ifdef HAVE_CHARSET
526 {"SelectCodepage", "alt-e"},
527 #endif
528 {"Shell", "ctrl-o"},
529 {"Ruler", "alt-r"},
530 {"SearchForward", "slash"},
531 {"SearchBackward", "question"},
532 {"SearchForwardContinue", "ctrl-s"},
533 {"SearchBackwardContinue", "ctrl-r"},
534 {"SearchOppositeContinue", "shift-n"},
535 {"History", "alt-shift-e"},
536 {NULL, NULL}
539 /* hex viewer */
540 static const global_keymap_ini_t default_viewer_hex_keymap[] = {
541 {"Help", "f1"},
542 {"HexEditMode", "f2"},
543 {"Quit", "f3; f10; q; esc"},
544 {"HexMode", "f4"},
545 {"Goto", "f5"},
546 {"Save", "f6"},
547 {"Search", "f7"},
548 {"SearchContinue", "f17; n"},
549 {"MagicMode", "f8"},
550 {"NroffMode", "f9"},
551 {"ToggleNavigation", "tab"},
552 {"Home", "ctrl-a; home"},
553 {"End", "ctrl-e; end"},
554 {"Left", "b; left"},
555 {"Right", "f; right"},
556 {"Up", "k; y; up"},
557 {"Down", "j; delete; down"},
558 {"PageDown", "pgdn; ctrl-v"},
559 {"PageUp", "pgup; alt-v"},
560 {"Top", "ctrl-home; ctrl-pgup; a1; alt-lt; g"},
561 {"Bottom", "ctrl-end; ctrl-pgdn; c1; alt-gt; shift-g"},
562 #ifdef HAVE_CHARSET
563 {"SelectCodepage", "alt-e"},
564 #endif
565 {"Shell", "ctrl-o"},
566 {"SearchForward", "slash"},
567 {"SearchBackward", "question"},
568 {"SearchForwardContinue", "ctrl-s"},
569 {"SearchBackwardContinue", "ctrl-r"},
570 {"SearchOppositeContinue", "shift-n"},
571 {"History", "alt-shift-e"},
572 {NULL, NULL}
575 #ifdef USE_DIFF_VIEW
576 /* diff viewer */
577 static const global_keymap_ini_t default_diff_keymap[] = {
578 {"ShowSymbols", "alt-s; s"},
579 {"ShowNumbers", "alt-n; l"},
580 {"SplitFull", "f"},
581 {"SplitEqual", "equal"},
582 {"SplitMore", "gt"},
583 {"SplitLess", "lt"},
584 {"Tab2", "2"},
585 {"Tab3", "3"},
586 {"Tab4", "4"},
587 {"Tab8", "8"},
588 {"Swap", "ctrl-u"},
589 {"Redo", "ctrl-r"},
590 {"HunkNext", "n; enter; space"},
591 {"HunkPrev", "p; backspace"},
592 {"Goto", "g; shift-g"},
593 {"Save", "f2"},
594 {"Edit", "f4"},
595 {"EditOther", "f14"},
596 {"Merge", "f5"},
597 {"MergeOther", "f15"},
598 {"Search", "f7"},
599 {"SearchContinue", "f17"},
600 {"Options", "f9"},
601 {"Top", "ctrl-home"},
602 {"Bottom", "ctrl-end"},
603 {"Down", "down"},
604 {"Up", "up"},
605 {"LeftQuick", "ctrl-left"},
606 {"RightQuick", "ctrl-right"},
607 {"Left", "left"},
608 {"Right", "right"},
609 {"PageDown", "pgdn"},
610 {"PageUp", "pgup"},
611 {"Home", "home"},
612 {"End", "end"},
613 {"Help", "f1"},
614 {"Quit", "f10; q; shift-q; esc"},
615 #ifdef HAVE_CHARSET
616 {"SelectCodepage", "alt-e"},
617 #endif
618 {"Shell", "ctrl-o"},
619 {NULL, NULL}
621 #endif
623 /* --------------------------------------------------------------------------------------------- */
624 /*** file scope functions ************************************************************************/
625 /* --------------------------------------------------------------------------------------------- */
627 static void
628 create_default_keymap_section (mc_config_t *keymap, const char *section,
629 const global_keymap_ini_t *k)
631 size_t i;
633 for (i = 0; k[i].key != NULL; i++)
634 mc_config_set_string_raw (keymap, section, k[i].key, k[i].value);
637 /* --------------------------------------------------------------------------------------------- */
639 static mc_config_t *
640 create_default_keymap (void)
642 mc_config_t *keymap;
644 keymap = mc_config_init (NULL, TRUE);
646 create_default_keymap_section (keymap, KEYMAP_SECTION_FILEMANAGER, default_filemanager_keymap);
647 create_default_keymap_section (keymap, KEYMAP_SECTION_FILEMANAGER_EXT,
648 default_filemanager_x_keymap);
649 create_default_keymap_section (keymap, KEYMAP_SECTION_PANEL, default_panel_keymap);
650 create_default_keymap_section (keymap, KEYMAP_SECTION_DIALOG, default_dialog_keymap);
651 create_default_keymap_section (keymap, KEYMAP_SECTION_MENU, default_menu_keymap);
652 create_default_keymap_section (keymap, KEYMAP_SECTION_INPUT, default_input_keymap);
653 create_default_keymap_section (keymap, KEYMAP_SECTION_LISTBOX, default_listbox_keymap);
654 create_default_keymap_section (keymap, KEYMAP_SECTION_RADIO, default_radio_keymap);
655 create_default_keymap_section (keymap, KEYMAP_SECTION_TREE, default_tree_keymap);
656 create_default_keymap_section (keymap, KEYMAP_SECTION_HELP, default_help_keymap);
657 #ifdef ENABLE_EXT2FS_ATTR
658 create_default_keymap_section (keymap, KEYMAP_SECTION_HELP, default_chattr_keymap);
659 #endif
660 #ifdef USE_INTERNAL_EDIT
661 create_default_keymap_section (keymap, KEYMAP_SECTION_EDITOR, default_editor_keymap);
662 create_default_keymap_section (keymap, KEYMAP_SECTION_EDITOR_EXT, default_editor_x_keymap);
663 #endif
664 create_default_keymap_section (keymap, KEYMAP_SECTION_VIEWER, default_viewer_keymap);
665 create_default_keymap_section (keymap, KEYMAP_SECTION_VIEWER_HEX, default_viewer_hex_keymap);
666 #ifdef USE_DIFF_VIEW
667 create_default_keymap_section (keymap, KEYMAP_SECTION_DIFFVIEWER, default_diff_keymap);
668 #endif
670 return keymap;
673 /* --------------------------------------------------------------------------------------------- */
675 static void
676 load_keymap_from_section (const char *section_name, GArray *keymap, mc_config_t *cfg)
678 gchar **profile_keys, **keys;
680 if (section_name == NULL)
681 return;
683 keys = mc_config_get_keys (cfg, section_name, NULL);
685 for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
687 gchar **values;
689 values = mc_config_get_string_list (cfg, section_name, *profile_keys, NULL);
690 if (values != NULL)
692 long action;
694 action = keybind_lookup_action (*profile_keys);
695 if (action > 0)
697 gchar **curr_values;
699 for (curr_values = values; *curr_values != NULL; curr_values++)
700 keybind_cmd_bind (keymap, *curr_values, action);
703 g_strfreev (values);
707 g_strfreev (keys);
710 /* --------------------------------------------------------------------------------------------- */
712 * Get name of config file.
714 * @param subdir If not NULL, config is also searched in specified subdir.
715 * @param config_file_name If relative, file if searched in standard paths.
717 * @return newly allocated string with config name or NULL if file is not found.
720 static char *
721 load_setup_get_full_config_name (const char *subdir, const char *config_file_name)
724 TODO: IMHO, in future, this function shall be placed in mcconfig module.
726 char *lc_basename, *ret;
727 char *file_name;
729 if (config_file_name == NULL)
730 return NULL;
732 /* check for .keymap suffix */
733 if (g_str_has_suffix (config_file_name, ".keymap"))
734 file_name = g_strdup (config_file_name);
735 else
736 file_name = g_strconcat (config_file_name, ".keymap", (char *) NULL);
738 canonicalize_pathname (file_name);
740 if (g_path_is_absolute (file_name))
741 return file_name;
743 lc_basename = g_path_get_basename (file_name);
744 g_free (file_name);
746 if (lc_basename == NULL)
747 return NULL;
749 if (subdir != NULL)
750 ret = g_build_filename (mc_config_get_path (), subdir, lc_basename, (char *) NULL);
751 else
752 ret = g_build_filename (mc_config_get_path (), lc_basename, (char *) NULL);
754 if (exist_file (ret))
756 g_free (lc_basename);
757 canonicalize_pathname (ret);
758 return ret;
760 g_free (ret);
762 if (subdir != NULL)
763 ret = g_build_filename (mc_global.share_data_dir, subdir, lc_basename, (char *) NULL);
764 else
765 ret = g_build_filename (mc_global.share_data_dir, lc_basename, (char *) NULL);
767 g_free (lc_basename);
769 if (exist_file (ret))
771 canonicalize_pathname (ret);
772 return ret;
775 g_free (ret);
776 return NULL;
779 /* --------------------------------------------------------------------------------------------- */
781 Create new mc_config object from specified ini-file or
782 append data to existing mc_config object from ini-file
785 static void
786 load_setup_init_config_from_file (mc_config_t **config, const char *fname, gboolean read_only)
789 TODO: IMHO, in future, this function shall be placed in mcconfig module.
791 if (exist_file (fname))
793 if (*config != NULL)
794 mc_config_read_file (*config, fname, read_only, TRUE);
795 else
796 *config = mc_config_init (fname, read_only);
800 /* --------------------------------------------------------------------------------------------- */
802 static mc_config_t *
803 load_setup_get_keymap_profile_config (gboolean load_from_file)
806 TODO: IMHO, in future, this function shall be placed in mcconfig module.
808 mc_config_t *keymap_config;
809 char *share_keymap, *sysconfig_keymap;
810 char *fname, *fname2;
812 /* 0) Create default keymap */
813 keymap_config = create_default_keymap ();
814 if (!load_from_file)
815 return keymap_config;
817 /* load and merge global keymaps */
819 /* 1) /usr/share/mc (mc_global.share_data_dir) */
820 share_keymap = g_build_filename (mc_global.share_data_dir, GLOBAL_KEYMAP_FILE, (char *) NULL);
821 load_setup_init_config_from_file (&keymap_config, share_keymap, TRUE);
823 /* 2) /etc/mc (mc_global.sysconfig_dir) */
824 sysconfig_keymap =
825 g_build_filename (mc_global.sysconfig_dir, GLOBAL_KEYMAP_FILE, (char *) NULL);
826 load_setup_init_config_from_file (&keymap_config, sysconfig_keymap, TRUE);
828 /* then load and merge one of user-defined keymap */
830 /* 3) --keymap=<keymap> */
831 fname = load_setup_get_full_config_name (NULL, mc_args__keymap_file);
832 if (fname != NULL && strcmp (fname, sysconfig_keymap) != 0 && strcmp (fname, share_keymap) != 0)
834 load_setup_init_config_from_file (&keymap_config, fname, TRUE);
835 goto done;
837 g_free (fname);
839 /* 4) getenv("MC_KEYMAP") */
840 fname = load_setup_get_full_config_name (NULL, g_getenv ("MC_KEYMAP"));
841 if (fname != NULL && strcmp (fname, sysconfig_keymap) != 0 && strcmp (fname, share_keymap) != 0)
843 load_setup_init_config_from_file (&keymap_config, fname, TRUE);
844 goto done;
847 MC_PTR_FREE (fname);
849 /* 5) main config; [Midnight Commander] -> keymap */
850 fname2 = mc_config_get_string (mc_global.main_config, CONFIG_APP_SECTION, "keymap", NULL);
851 if (fname2 != NULL && *fname2 != '\0')
852 fname = load_setup_get_full_config_name (NULL, fname2);
853 g_free (fname2);
854 if (fname != NULL && strcmp (fname, sysconfig_keymap) != 0 && strcmp (fname, share_keymap) != 0)
856 load_setup_init_config_from_file (&keymap_config, fname, TRUE);
857 goto done;
859 g_free (fname);
861 /* 6) ${XDG_CONFIG_HOME}/mc/mc.keymap */
862 fname = mc_config_get_full_path (GLOBAL_KEYMAP_FILE);
863 load_setup_init_config_from_file (&keymap_config, fname, TRUE);
865 done:
866 g_free (fname);
867 g_free (sysconfig_keymap);
868 g_free (share_keymap);
870 return keymap_config;
873 /* --------------------------------------------------------------------------------------------- */
874 /*** public functions ****************************************************************************/
875 /* --------------------------------------------------------------------------------------------- */
877 void
878 keymap_load (gboolean load_from_file)
881 * Load keymap from GLOBAL_KEYMAP_FILE before ${XDG_CONFIG_HOME}/mc/mc.keymap, so that the user
882 * definitions override global settings.
884 mc_config_t *mc_global_keymap;
886 mc_global_keymap = load_setup_get_keymap_profile_config (load_from_file);
888 if (mc_global_keymap != NULL)
890 #define LOAD_KEYMAP(s,km) \
891 km##_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t)); \
892 load_keymap_from_section (KEYMAP_SECTION_##s, km##_keymap, mc_global_keymap)
894 LOAD_KEYMAP (FILEMANAGER, filemanager);
895 LOAD_KEYMAP (FILEMANAGER_EXT, filemanager_x);
896 LOAD_KEYMAP (PANEL, panel);
897 LOAD_KEYMAP (DIALOG, dialog);
898 LOAD_KEYMAP (MENU, menu);
899 LOAD_KEYMAP (INPUT, input);
900 LOAD_KEYMAP (LISTBOX, listbox);
901 LOAD_KEYMAP (RADIO, radio);
902 LOAD_KEYMAP (TREE, tree);
903 LOAD_KEYMAP (HELP, help);
904 #ifdef ENABLE_EXT2FS_ATTR
905 LOAD_KEYMAP (CHATTR, chattr);
906 #endif
907 #ifdef USE_INTERNAL_EDIT
908 LOAD_KEYMAP (EDITOR, editor);
909 LOAD_KEYMAP (EDITOR_EXT, editor_x);
910 #endif
911 LOAD_KEYMAP (VIEWER, viewer);
912 LOAD_KEYMAP (VIEWER_HEX, viewer_hex);
913 #ifdef USE_DIFF_VIEW
914 LOAD_KEYMAP (DIFFVIEWER, diff);
915 #endif
917 #undef LOAD_KEYMAP
918 mc_config_deinit (mc_global_keymap);
921 #define SET_MAP(m) \
922 m##_map = (global_keymap_t *) m##_keymap->data
924 SET_MAP (filemanager);
925 SET_MAP (filemanager_x);
926 SET_MAP (panel);
927 SET_MAP (dialog);
928 SET_MAP (menu);
929 SET_MAP (input);
930 SET_MAP (listbox);
931 SET_MAP (radio);
932 SET_MAP (tree);
933 SET_MAP (help);
934 #ifdef ENABLE_EXT2FS_ATTR
935 SET_MAP (chattr);
936 #endif
937 #ifdef USE_INTERNAL_EDIT
938 SET_MAP (editor);
939 SET_MAP (editor_x);
940 #endif
941 SET_MAP (viewer);
942 SET_MAP (viewer_hex);
943 #ifdef USE_DIFF_VIEW
944 SET_MAP (diff);
945 #endif
947 #undef SET_MAP
950 /* --------------------------------------------------------------------------------------------- */
952 void
953 keymap_free (void)
955 #define FREE_KEYMAP(km) \
956 if (km##_keymap != NULL) \
957 g_array_free (km##_keymap, TRUE)
959 FREE_KEYMAP (filemanager);
960 FREE_KEYMAP (filemanager_x);
961 FREE_KEYMAP (panel);
962 FREE_KEYMAP (dialog);
963 FREE_KEYMAP (menu);
964 FREE_KEYMAP (input);
965 FREE_KEYMAP (listbox);
966 FREE_KEYMAP (radio);
967 FREE_KEYMAP (tree);
968 FREE_KEYMAP (help);
969 #ifdef ENABLE_EXT2FS_ATTR
970 FREE_KEYMAP (chattr);
971 #endif
972 #ifdef USE_INTERNAL_EDIT
973 FREE_KEYMAP (editor);
974 FREE_KEYMAP (editor_x);
975 #endif
976 FREE_KEYMAP (viewer);
977 FREE_KEYMAP (viewer_hex);
978 #ifdef USE_DIFF_VIEW
979 FREE_KEYMAP (diff);
980 #endif
982 #undef FREE_KEYMAP
985 /* --------------------------------------------------------------------------------------------- */