Type accuracy and some clean up.
[midnight-commander.git] / lib / keybind.c
blobbe5e01580565756c57b41c14f058474ebbe1ce46
1 /*
2 Copyright (C) 2009 The Free Software Foundation, Inc.
4 Written by: 2005 Vitja Makarov
5 2009 Ilia Maslakov
6 2009, 2010 Andrew Borodin
8 This file is part of the Midnight Commander.
10 The Midnight Commander is free software; you can redistribute it
11 and/or modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
15 The Midnight Commander is distributed in the hope that it will be
16 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 MA 02110-1301, USA.
26 #include <config.h>
28 #include <ctype.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
33 #include "lib/global.h"
34 #include "lib/tty/key.h" /* KEY_M_ */
35 #include "lib/strutil.h" /* str_casecmp() */
36 #include "lib/keybind.h"
38 /*** global variables ****************************************************************************/
40 /*** file scope macro definitions ****************************************************************/
42 /*** file scope type declarations ****************************************************************/
44 /*** file scope variables ************************************************************************/
46 static name_keymap_t command_names[] = {
47 /* common */
48 {"Enter", CK_Enter},
49 {"Up", CK_Up},
50 {"Down", CK_Down},
51 {"Left", CK_Left},
52 {"Right", CK_Right},
53 {"LeftQuick", CK_LeftQuick},
54 {"RightQuick", CK_RightQuick},
55 {"Home", CK_Home},
56 {"End", CK_End},
57 {"PageUp", CK_PageUp},
58 {"PageDown", CK_PageDown},
59 {"HalfPageUp", CK_HalfPageUp},
60 {"HalfPageDown", CK_HalfPageDown},
61 {"Top", CK_Top},
62 {"Bottom", CK_Bottom},
63 {"TopOnScreen", CK_TopOnScreen},
64 {"MiddleOnScreen", CK_MiddleOnScreen},
65 {"BottomOnScreen", CK_BottomOnScreen},
66 {"WordLeft", CK_WordLeft},
67 {"WordRight", CK_WordRight},
68 {"Copy", CK_Copy},
69 {"Move", CK_Move},
70 {"Delete", CK_Delete},
71 {"MakeDir", CK_MakeDir},
72 {"ChangeMode", CK_ChangeMode},
73 {"ChangeOwn", CK_ChangeOwn},
74 {"ChangeOwnAdvanced", CK_ChangeOwnAdvanced},
75 {"Remove", CK_Remove},
76 {"BackSpace", CK_BackSpace},
77 {"Undo", CK_Undo},
78 {"Redo", CK_Redo},
79 {"Clear", CK_Clear},
80 {"Menu", CK_Menu},
81 {"MenuLastSelected", CK_MenuLastSelected},
82 {"UserMenu", CK_UserMenu},
83 {"EditUserMenu", CK_EditUserMenu},
84 {"Search", CK_Search},
85 {"SearchContinue", CK_SearchContinue},
86 {"Replace", CK_Replace},
87 {"ReplaceContinue", CK_ReplaceContinue},
88 {"Help", CK_Help},
89 {"Shell", CK_Shell},
90 {"Edit", CK_Edit},
91 {"EditNew", CK_EditNew},
92 #ifdef HAVE_CHARSET
93 {"SelectCodepage", CK_SelectCodepage},
94 #endif
95 {"History", CK_History},
96 {"HistoryNext", CK_HistoryNext},
97 {"HistoryPrev", CK_HistoryPrev},
98 {"Complete", CK_Complete},
99 {"Save", CK_Save},
100 {"SaveAs", CK_SaveAs},
101 {"Goto", CK_Goto},
102 {"Reread", CK_Reread},
103 {"Refresh", CK_Refresh},
104 {"Suspend", CK_Suspend},
105 {"Swap", CK_Swap},
106 {"HotList", CK_HotList},
107 {"SelectInvert", CK_SelectInvert},
108 {"ScreenList", CK_ScreenList},
109 {"ScreenNext", CK_ScreenNext},
110 {"ScreenPrev", CK_ScreenPrev},
111 {"FileNext", CK_FileNext},
112 {"FilePrev", CK_FilePrev},
113 {"DeleteToWordBegin", CK_DeleteToWordBegin},
114 {"DeleteToWordEnd", CK_DeleteToWordEnd},
115 {"Cut", CK_Cut},
116 {"Store", CK_Store},
117 {"Paste", CK_Paste},
118 {"Mark", CK_Mark},
119 {"MarkLeft", CK_MarkLeft},
120 {"MarkRight", CK_MarkRight},
121 {"MarkUp", CK_MarkUp},
122 {"MarkDown", CK_MarkDown},
123 {"MarkToWordBegin", CK_MarkToWordBegin},
124 {"MarkToWordEnd", CK_MarkToWordEnd},
125 {"MarkToHome", CK_MarkToHome},
126 {"MarkToEnd", CK_MarkToEnd},
127 {"ToggleNavigation", CK_ToggleNavigation},
128 {"Sort", CK_Sort},
129 {"Options", CK_Options},
130 {"LearnKeys", CK_LearnKeys},
131 {"Bookmark", CK_Bookmark},
132 {"Quit", CK_Quit},
133 {"QuitQuiet", CK_QuitQuiet},
134 {"ExtendedKeyMap", CK_ExtendedKeyMap},
136 /* main commands */
137 #ifdef USE_INTERNAL_EDIT
138 {"EditForceInternal", CK_EditForceInternal},
139 #endif
140 {"View", CK_View},
141 {"ViewRaw", CK_ViewRaw},
142 {"ViewFile", CK_ViewFile},
143 {"ViewFiltered", CK_ViewFiltered},
144 {"Find", CK_Find},
145 {"DirSize", CK_DirSize},
146 {"PanelListingSwitch", CK_PanelListingSwitch},
147 {"CompareDirs", CK_CompareDirs},
148 #ifdef USE_DIFF_VIEW
149 {"CompareFiles", CK_CompareFiles},
150 #endif
151 {"OptionsVfs", CK_OptionsVfs},
152 {"OptionsConfirm", CK_OptionsConfirm},
153 {"OptionsDisplayBits", CK_OptionsDisplayBits},
154 {"EditExtensionsFile", CK_EditExtensionsFile},
155 {"EditFileHighlightFile", CK_EditFileHighlightFile},
156 {"LinkSymbolicEdit", CK_LinkSymbolicEdit},
157 {"ExternalPanelize", CK_ExternalPanelize},
158 {"Filter", CK_Filter},
159 #ifdef ENABLE_VFS_FISH
160 {"ConnectFish", CK_ConnectFish},
161 #endif
162 #ifdef ENABLE_VFS_FTP
163 {"ConnectFtp", CK_ConnectFtp},
164 #endif
165 #ifdef ENABLE_VFS_SMB
166 {"ConnectSmb", CK_ConnectSmb},
167 #endif
168 {"PanelInfo", CK_PanelInfo},
169 #ifdef WITH_BACKGROUND
170 {"Jobs", CK_Jobs},
171 #endif
172 {"OptionsLayout", CK_OptionsLayout},
173 {"Link", CK_Link},
174 {"PanelListingChange", CK_PanelListingChange},
175 {"PanelListing", CK_PanelListing},
176 #ifdef LISTMODE_EDITOR
177 {"ListMode", CK_ListMode}.
178 #endif
179 {"OptionsPanel", CK_OptionsPanel},
180 {"CdQuick", CK_CdQuick},
181 {"PanelQuickView", CK_PanelQuickView},
182 {"LinkSymbolicRelative", CK_LinkSymbolicRelative},
183 {"VfsList", CK_VfsList},
184 {"SaveSetup", CK_SaveSetup},
185 {"LinkSymbolic", CK_LinkSymbolic},
186 {"PanelTree", CK_PanelTree},
187 {"Tree", CK_Tree},
188 #ifdef ENABLE_VFS_UNDELFS
189 {"Undelete", CK_Undelete},
190 #endif
191 {"PutCurrentLink", CK_PutCurrentLink},
192 {"PutOtherLink", CK_PutOtherLink},
193 {"HotListAdd", CK_HotListAdd},
194 {"ShowHidden", CK_ShowHidden},
195 {"SplitVertHoriz", CK_SplitVertHoriz},
196 {"PutCurrentPath", CK_PutCurrentPath},
197 {"PutOtherPath", CK_PutOtherPath},
198 {"PutCurrentTagged", CK_PutCurrentTagged},
199 {"PutOtherTagged", CK_PutOtherTagged},
200 {"Select", CK_Select},
201 {"Unselect", CK_Unselect},
203 /* panel */
204 {"PanelOtherCd", CK_PanelOtherCd},
205 {"PanelOtherCdLink", CK_PanelOtherCdLink},
206 {"CopySingle", CK_CopySingle},
207 {"MoveSingle", CK_MoveSingle},
208 {"DeleteSingle", CK_DeleteSingle},
209 {"CdParent", CK_CdParent},
210 {"CdChild", CK_CdChild},
211 {"PanelOtherSync", CK_PanelOtherSync},
212 {"SortNext", CK_SortNext},
213 {"SortPrev", CK_SortPrev},
214 {"SortReverse", CK_SortReverse},
215 {"SortByName", CK_SortByName},
216 {"SortByExt", CK_SortByExt},
217 {"SortBySize", CK_SortBySize},
218 {"SortByMTime", CK_SortByMTime},
219 {"CdParentSmart", CK_CdParentSmart},
221 /* dialog */
222 {"Ok", CK_Ok},
223 {"Cancel", CK_Cancel},
225 /* input line */
226 {"Yank", CK_Yank},
228 /* help */
229 {"Index", CK_Index},
230 {"Back", CK_Back},
231 {"LinkNext", CK_LinkNext},
232 {"LinkPrev", CK_LinkPrev},
233 {"NodeNext", CK_NodeNext},
234 {"NodePrev", CK_NodePrev},
236 /* tree */
237 {"Forget", CK_Forget},
239 #if defined (USE_INTERNAL_EDIT) || defined (USE_DIFF_VIEW)
240 {"ShowNumbers", CK_ShowNumbers},
241 #endif
243 #ifdef USE_INTERNAL_EDIT
244 {"Tab", CK_Tab},
245 {"ScrollUp", CK_ScrollUp},
246 {"ScrollDown", CK_ScrollDown},
247 {"Return", CK_Return},
248 {"ParagraphUp", CK_ParagraphUp},
249 {"ParagraphDown", CK_ParagraphDown},
250 {"EditFile", CK_EditFile},
251 {"MarkWord", CK_MarkWord},
252 {"MarkLine", CK_MarkLine},
253 {"MarkAll", CK_MarkAll},
254 {"Unmark", CK_Unmark},
255 {"MarkColumn", CK_MarkColumn},
256 {"BlockSave", CK_BlockSave},
257 {"InsertFile", CK_InsertFile},
258 {"InsertOverwrite", CK_InsertOverwrite},
259 {"Date", CK_Date},
260 {"DeleteLine", CK_DeleteLine},
261 {"DeleteToHome", CK_DeleteToHome},
262 {"DeleteToEnd", CK_DeleteToEnd},
263 {"EditMail", CK_Mail},
264 {"ParagraphFormat", CK_ParagraphFormat},
265 {"MatchBracket", CK_MatchBracket},
266 {"ExternalCommand", CK_ExternalCommand},
267 {"MacroStartRecord", CK_MacroStartRecord},
268 {"MacroStopRecord", CK_MacroStopRecord},
269 {"MacroStartStopRecord", CK_MacroStartStopRecord},
270 {"MacroDelete", CK_MacroDelete},
271 {"RepeatStartStopRecord", CK_RepeatStartStopRecord},
272 {"BookmarkFlush", CK_BookmarkFlush},
273 {"BookmarkNext", CK_BookmarkNext},
274 {"BookmarkPrev", CK_BookmarkPrev},
275 {"MarkPageUp", CK_MarkPageUp},
276 {"MarkPageDown", CK_MarkPageDown},
277 {"MarkToFileBegin", CK_MarkToFileBegin},
278 {"MarkToFileEnd", CK_MarkToFileEnd},
279 {"MarkToPageBegin", CK_MarkToPageBegin},
280 {"MarkToPageEnd", CK_MarkToPageEnd},
281 {"MarkScrollUp", CK_MarkScrollUp},
282 {"MarkScrollDown", CK_MarkScrollDown},
283 {"MarkParagraphUp", CK_MarkParagraphUp},
284 {"MarkParagraphDown", CK_MarkParagraphDown},
285 {"MarkColumnPageUp", CK_MarkColumnPageUp},
286 {"MarkColumnPageDown", CK_MarkColumnPageDown},
287 {"MarkColumnLeft", CK_MarkColumnLeft},
288 {"MarkColumnRight", CK_MarkColumnRight},
289 {"MarkColumnUp", CK_MarkColumnUp},
290 {"MarkColumnDown", CK_MarkColumnDown},
291 {"MarkColumnScrollUp", CK_MarkColumnScrollUp},
292 {"MarkColumnScrollDown", CK_MarkColumnScrollDown},
293 {"MarkColumnParagraphUp", CK_MarkColumnParagraphUp},
294 {"MarkColumnParagraphDown", CK_MarkColumnParagraphDown},
295 {"BlockShiftLeft", CK_BlockShiftLeft},
296 {"BlockShiftRight", CK_BlockShiftRight},
297 {"InsertLiteral", CK_InsertLiteral},
298 {"ShowTabTws", CK_ShowTabTws},
299 {"SyntaxOnOff", CK_SyntaxOnOff},
300 {"SyntaxChoose", CK_SyntaxChoose},
301 {"ShowMargin", CK_ShowMargin},
302 {"OptionsSaveMode", CK_OptionsSaveMode},
303 {"About", CK_About},
304 /* An action to run external script from macro */
305 {"ExecuteScript", CK_PipeBlock (0)},
306 #endif /* USE_INTERNAL_EDIT */
308 /* viewer */
309 {"WrapMode", CK_WrapMode},
310 {"HexEditMode", CK_HexEditMode},
311 {"HexMode", CK_HexMode},
312 {"MagicMode", CK_MagicMode},
313 {"NroffMode", CK_NroffMode},
314 {"BookmarkGoto", CK_BookmarkGoto},
315 {"Ruler", CK_Ruler},
317 #ifdef USE_DIFF_VIEW
318 /* diff viewer */
319 {"ShowSymbols", CK_ShowSymbols},
320 {"SplitFull", CK_SplitFull},
321 {"SplitEqual", CK_SplitEqual},
322 {"SplitMore", CK_SplitMore},
323 {"SplitLess", CK_SplitLess},
324 {"Tab2", CK_Tab2},
325 {"Tab3", CK_Tab3},
326 {"Tab4", CK_Tab4},
327 {"Tab8", CK_Tab8},
328 {"HunkNext", CK_HunkNext},
329 {"HunkPrev", CK_HunkPrev},
330 {"EditOther", CK_EditOther},
331 {"Merge", CK_Merge},
332 #endif /* USE_DIFF_VIEW */
334 {NULL, CK_IgnoreKey}
337 static const size_t num_command_names = G_N_ELEMENTS (command_names) - 1;
339 /*** file scope functions ************************************************************************/
340 /* --------------------------------------------------------------------------------------------- */
342 static int
343 name_keymap_comparator (const void *p1, const void *p2)
345 const name_keymap_t *m1 = (const name_keymap_t *) p1;
346 const name_keymap_t *m2 = (const name_keymap_t *) p2;
348 return str_casecmp (m1->name, m2->name);
351 /* --------------------------------------------------------------------------------------------- */
353 static inline void
354 sort_command_names (void)
356 static gboolean has_been_sorted = FALSE;
358 if (!has_been_sorted)
360 qsort (command_names, num_command_names,
361 sizeof (command_names[0]), &name_keymap_comparator);
362 has_been_sorted = TRUE;
366 /* --------------------------------------------------------------------------------------------- */
368 static void
369 keymap_add (GArray * keymap, long key, unsigned long cmd, const char *caption)
371 if (key != 0 && cmd != CK_IgnoreKey)
373 global_keymap_t new_bind;
375 new_bind.key = key;
376 new_bind.command = cmd;
377 g_snprintf (new_bind.caption, sizeof (new_bind.caption), "%s", caption);
378 g_array_append_val (keymap, new_bind);
382 /* --------------------------------------------------------------------------------------------- */
383 /*** public functions ****************************************************************************/
384 /* --------------------------------------------------------------------------------------------- */
386 void
387 keybind_cmd_bind (GArray * keymap, const char *keybind, unsigned long action)
389 char *caption = NULL;
390 long key;
392 key = lookup_key (keybind, &caption);
393 keymap_add (keymap, key, action, caption);
394 g_free (caption);
397 /* --------------------------------------------------------------------------------------------- */
399 unsigned long
400 keybind_lookup_action (const char *name)
402 const name_keymap_t key = { name, 0 };
403 name_keymap_t *res;
405 sort_command_names ();
407 res = bsearch (&key, command_names, num_command_names,
408 sizeof (command_names[0]), name_keymap_comparator);
410 return (res != NULL) ? res->val : CK_IgnoreKey;
413 /* --------------------------------------------------------------------------------------------- */
415 const char *
416 keybind_lookup_actionname (unsigned long action)
418 size_t i;
420 for (i = 0; command_names[i].name != NULL; i++)
421 if (command_names[i].val == action)
422 return command_names[i].name;
424 return NULL;
427 /* --------------------------------------------------------------------------------------------- */
429 const char *
430 keybind_lookup_keymap_shortcut (const global_keymap_t * keymap, unsigned long action)
432 size_t i;
434 if (keymap != NULL)
435 for (i = 0; keymap[i].key != 0; i++)
436 if (keymap[i].command == action)
437 return (keymap[i].caption[0] != '\0') ? keymap[i].caption : NULL;
439 return NULL;
442 /* --------------------------------------------------------------------------------------------- */
444 unsigned long
445 keybind_lookup_keymap_command (const global_keymap_t * keymap, long key)
447 size_t i;
449 if (keymap != NULL)
450 for (i = 0; keymap[i].key != 0; i++)
451 if (keymap[i].key == key)
452 return keymap[i].command;
454 return CK_IgnoreKey;
457 /* --------------------------------------------------------------------------------------------- */