root/lib/keybind.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. name_keymap_comparator
  2. sort_command_names
  3. keymap_add
  4. keybind_cmd_bind
  5. keybind_lookup_action
  6. keybind_lookup_actionname
  7. keybind_lookup_keymap_shortcut
  8. keybind_lookup_keymap_command

   1 /*
   2    Definitions of key bindings.
   3 
   4    Copyright (C) 2005-2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Vitja Makarov, 2005
   9    Ilia Maslakov <il.smind@gmail.com>, 2009, 2012
  10    Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2011, 2012
  11 
  12    This file is part of the Midnight Commander.
  13 
  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.
  18 
  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.
  23 
  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/>.
  26  */
  27 
  28 #include <config.h>
  29 
  30 #include <ctype.h>
  31 #include <stdlib.h>
  32 #include <string.h>
  33 #include <sys/types.h>
  34 
  35 #include "lib/global.h"
  36 #include "lib/tty/key.h"        /* KEY_M_ */
  37 #include "lib/keybind.h"
  38 
  39 /*** global variables ****************************************************************************/
  40 
  41 /*** file scope macro definitions ****************************************************************/
  42 
  43 /*** file scope type declarations ****************************************************************/
  44 
  45 /*** file scope variables ************************************************************************/
  46 
  47 static name_keymap_t command_names[] = {
  48     /* common */
  49     {"InsertChar", CK_InsertChar},
  50     {"Enter", CK_Enter},
  51     {"ChangePanel", CK_ChangePanel},
  52     {"Up", CK_Up},
  53     {"Down", CK_Down},
  54     {"Left", CK_Left},
  55     {"Right", CK_Right},
  56     {"LeftQuick", CK_LeftQuick},
  57     {"RightQuick", CK_RightQuick},
  58     {"Home", CK_Home},
  59     {"End", CK_End},
  60     {"PageUp", CK_PageUp},
  61     {"PageDown", CK_PageDown},
  62     {"HalfPageUp", CK_HalfPageUp},
  63     {"HalfPageDown", CK_HalfPageDown},
  64     {"Top", CK_Top},
  65     {"Bottom", CK_Bottom},
  66     {"TopOnScreen", CK_TopOnScreen},
  67     {"MiddleOnScreen", CK_MiddleOnScreen},
  68     {"BottomOnScreen", CK_BottomOnScreen},
  69     {"WordLeft", CK_WordLeft},
  70     {"WordRight", CK_WordRight},
  71     {"Copy", CK_Copy},
  72     {"Move", CK_Move},
  73     {"Delete", CK_Delete},
  74     {"MakeDir", CK_MakeDir},
  75     {"ChangeMode", CK_ChangeMode},
  76     {"ChangeOwn", CK_ChangeOwn},
  77     {"ChangeOwnAdvanced", CK_ChangeOwnAdvanced},
  78     {"Remove", CK_Remove},
  79     {"BackSpace", CK_BackSpace},
  80     {"Redo", CK_Redo},
  81     {"Clear", CK_Clear},
  82     {"Menu", CK_Menu},
  83     {"MenuLastSelected", CK_MenuLastSelected},
  84     {"UserMenu", CK_UserMenu},
  85     {"EditUserMenu", CK_EditUserMenu},
  86     {"Search", CK_Search},
  87     {"SearchContinue", CK_SearchContinue},
  88     {"Replace", CK_Replace},
  89     {"ReplaceContinue", CK_ReplaceContinue},
  90     {"Help", CK_Help},
  91     {"Shell", CK_Shell},
  92     {"Edit", CK_Edit},
  93     {"EditNew", CK_EditNew},
  94 #ifdef HAVE_CHARSET
  95     {"SelectCodepage", CK_SelectCodepage},
  96 #endif
  97     {"EditorViewerHistory", CK_EditorViewerHistory},
  98     {"History", CK_History},
  99     {"HistoryNext", CK_HistoryNext},
 100     {"HistoryPrev", CK_HistoryPrev},
 101     {"Complete", CK_Complete},
 102     {"Save", CK_Save},
 103     {"SaveAs", CK_SaveAs},
 104     {"Goto", CK_Goto},
 105     {"Reread", CK_Reread},
 106     {"Refresh", CK_Refresh},
 107     {"Suspend", CK_Suspend},
 108     {"Swap", CK_Swap},
 109     {"HotList", CK_HotList},
 110     {"SelectInvert", CK_SelectInvert},
 111     {"ScreenList", CK_ScreenList},
 112     {"ScreenNext", CK_ScreenNext},
 113     {"ScreenPrev", CK_ScreenPrev},
 114     {"FileNext", CK_FileNext},
 115     {"FilePrev", CK_FilePrev},
 116     {"DeleteToHome", CK_DeleteToHome},
 117     {"DeleteToEnd", CK_DeleteToEnd},
 118     {"DeleteToWordBegin", CK_DeleteToWordBegin},
 119     {"DeleteToWordEnd", CK_DeleteToWordEnd},
 120     {"Cut", CK_Cut},
 121     {"Store", CK_Store},
 122     {"Paste", CK_Paste},
 123     {"Mark", CK_Mark},
 124     {"MarkLeft", CK_MarkLeft},
 125     {"MarkRight", CK_MarkRight},
 126     {"MarkUp", CK_MarkUp},
 127     {"MarkDown", CK_MarkDown},
 128     {"MarkToWordBegin", CK_MarkToWordBegin},
 129     {"MarkToWordEnd", CK_MarkToWordEnd},
 130     {"MarkToHome", CK_MarkToHome},
 131     {"MarkToEnd", CK_MarkToEnd},
 132     {"ToggleNavigation", CK_ToggleNavigation},
 133     {"Sort", CK_Sort},
 134     {"Options", CK_Options},
 135     {"LearnKeys", CK_LearnKeys},
 136     {"Bookmark", CK_Bookmark},
 137     {"Quit", CK_Quit},
 138     {"QuitQuiet", CK_QuitQuiet},
 139     {"ExtendedKeyMap", CK_ExtendedKeyMap},
 140 
 141     /* main commands */
 142 #ifdef USE_INTERNAL_EDIT
 143     {"EditForceInternal", CK_EditForceInternal},
 144 #endif
 145     {"View", CK_View},
 146     {"ViewRaw", CK_ViewRaw},
 147     {"ViewFile", CK_ViewFile},
 148     {"ViewFiltered", CK_ViewFiltered},
 149     {"Find", CK_Find},
 150     {"DirSize", CK_DirSize},
 151     {"CompareDirs", CK_CompareDirs},
 152 #ifdef USE_DIFF_VIEW
 153     {"CompareFiles", CK_CompareFiles},
 154 #endif
 155     {"OptionsVfs", CK_OptionsVfs},
 156     {"OptionsConfirm", CK_OptionsConfirm},
 157     {"OptionsDisplayBits", CK_OptionsDisplayBits},
 158     {"EditExtensionsFile", CK_EditExtensionsFile},
 159     {"EditFileHighlightFile", CK_EditFileHighlightFile},
 160     {"LinkSymbolicEdit", CK_LinkSymbolicEdit},
 161     {"ExternalPanelize", CK_ExternalPanelize},
 162     {"Filter", CK_Filter},
 163 #ifdef ENABLE_VFS_FISH
 164     {"ConnectFish", CK_ConnectFish},
 165 #endif
 166 #ifdef ENABLE_VFS_FTP
 167     {"ConnectFtp", CK_ConnectFtp},
 168 #endif
 169 #ifdef ENABLE_VFS_SFTP
 170     {"ConnectSftp", CK_ConnectSftp},
 171 #endif
 172 #ifdef ENABLE_VFS_SMB
 173     {"ConnectSmb", CK_ConnectSmb},
 174 #endif
 175     {"PanelInfo", CK_PanelInfo},
 176 #ifdef ENABLE_BACKGROUND
 177     {"Jobs", CK_Jobs},
 178 #endif
 179     {"OptionsLayout", CK_OptionsLayout},
 180     {"OptionsAppearance", CK_OptionsAppearance},
 181     {"Link", CK_Link},
 182     {"SetupListingFormat", CK_SetupListingFormat},
 183     {"PanelListing", CK_PanelListing},
 184 #ifdef LISTMODE_EDITOR
 185     {"ListMode", CK_ListMode}.
 186 #endif
 187     {"OptionsPanel", CK_OptionsPanel},
 188     {"CdQuick", CK_CdQuick},
 189     {"PanelQuickView", CK_PanelQuickView},
 190     {"LinkSymbolicRelative", CK_LinkSymbolicRelative},
 191     {"VfsList", CK_VfsList},
 192     {"SaveSetup", CK_SaveSetup},
 193     {"LinkSymbolic", CK_LinkSymbolic},
 194     {"PanelTree", CK_PanelTree},
 195     {"Tree", CK_Tree},
 196 #ifdef ENABLE_VFS_UNDELFS
 197     {"Undelete", CK_Undelete},
 198 #endif
 199     {"PutCurrentLink", CK_PutCurrentLink},
 200     {"PutOtherLink", CK_PutOtherLink},
 201     {"HotListAdd", CK_HotListAdd},
 202     {"ShowHidden", CK_ShowHidden},
 203     {"SplitVertHoriz", CK_SplitVertHoriz},
 204     {"SplitEqual", CK_SplitEqual},
 205     {"SplitMore", CK_SplitMore},
 206     {"SplitLess", CK_SplitLess},
 207     {"PutCurrentPath", CK_PutCurrentPath},
 208     {"PutOtherPath", CK_PutOtherPath},
 209     {"PutCurrentSelected", CK_PutCurrentSelected},
 210     {"PutCurrentFullSelected", CK_PutCurrentFullSelected},
 211     {"PutCurrentTagged", CK_PutCurrentTagged},
 212     {"PutOtherTagged", CK_PutOtherTagged},
 213     {"Select", CK_Select},
 214     {"Unselect", CK_Unselect},
 215 
 216     /* panel */
 217     {"SelectExt", CK_SelectExt},
 218     {"ScrollLeft", CK_ScrollLeft},
 219     {"ScrollRight", CK_ScrollRight},
 220     {"PanelOtherCd", CK_PanelOtherCd},
 221     {"PanelOtherCdLink", CK_PanelOtherCdLink},
 222     {"CopySingle", CK_CopySingle},
 223     {"MoveSingle", CK_MoveSingle},
 224     {"DeleteSingle", CK_DeleteSingle},
 225     {"CdParent", CK_CdParent},
 226     {"CdChild", CK_CdChild},
 227     {"Panelize", CK_Panelize},
 228     {"PanelOtherSync", CK_PanelOtherSync},
 229     {"SortNext", CK_SortNext},
 230     {"SortPrev", CK_SortPrev},
 231     {"SortReverse", CK_SortReverse},
 232     {"SortByName", CK_SortByName},
 233     {"SortByExt", CK_SortByExt},
 234     {"SortBySize", CK_SortBySize},
 235     {"SortByMTime", CK_SortByMTime},
 236     {"CdParentSmart", CK_CdParentSmart},
 237     {"CycleListingFormat", CK_CycleListingFormat},
 238 
 239     /* dialog */
 240     {"Ok", CK_Ok},
 241     {"Cancel", CK_Cancel},
 242 
 243     /* input line */
 244     {"Yank", CK_Yank},
 245 
 246     /* help */
 247     {"Index", CK_Index},
 248     {"Back", CK_Back},
 249     {"LinkNext", CK_LinkNext},
 250     {"LinkPrev", CK_LinkPrev},
 251     {"NodeNext", CK_NodeNext},
 252     {"NodePrev", CK_NodePrev},
 253 
 254     /* tree */
 255     {"Forget", CK_Forget},
 256 
 257 #if defined (USE_INTERNAL_EDIT) || defined (USE_DIFF_VIEW)
 258     {"ShowNumbers", CK_ShowNumbers},
 259 #endif
 260 
 261 #ifdef USE_INTERNAL_EDIT
 262     {"Close", CK_Close},
 263     {"Tab", CK_Tab},
 264     {"Undo", CK_Undo},
 265     {"ScrollUp", CK_ScrollUp},
 266     {"ScrollDown", CK_ScrollDown},
 267     {"Return", CK_Return},
 268     {"ParagraphUp", CK_ParagraphUp},
 269     {"ParagraphDown", CK_ParagraphDown},
 270     {"EditFile", CK_EditFile},
 271     {"MarkWord", CK_MarkWord},
 272     {"MarkLine", CK_MarkLine},
 273     {"MarkAll", CK_MarkAll},
 274     {"Unmark", CK_Unmark},
 275     {"MarkColumn", CK_MarkColumn},
 276     {"BlockSave", CK_BlockSave},
 277     {"InsertFile", CK_InsertFile},
 278     {"InsertOverwrite", CK_InsertOverwrite},
 279     {"Date", CK_Date},
 280     {"DeleteLine", CK_DeleteLine},
 281     {"EditMail", CK_Mail},
 282     {"ParagraphFormat", CK_ParagraphFormat},
 283     {"MatchBracket", CK_MatchBracket},
 284     {"ExternalCommand", CK_ExternalCommand},
 285     {"MacroStartRecord", CK_MacroStartRecord},
 286     {"MacroStopRecord", CK_MacroStopRecord},
 287     {"MacroStartStopRecord", CK_MacroStartStopRecord},
 288     {"MacroDelete", CK_MacroDelete},
 289     {"RepeatStartStopRecord", CK_RepeatStartStopRecord},
 290 #ifdef HAVE_ASPELL
 291     {"SpellCheck", CK_SpellCheck},
 292     {"SpellCheckCurrentWord", CK_SpellCheckCurrentWord},
 293     {"SpellCheckSelectLang", CK_SpellCheckSelectLang},
 294 #endif /* HAVE_ASPELL */
 295     {"BookmarkFlush", CK_BookmarkFlush},
 296     {"BookmarkNext", CK_BookmarkNext},
 297     {"BookmarkPrev", CK_BookmarkPrev},
 298     {"MarkPageUp", CK_MarkPageUp},
 299     {"MarkPageDown", CK_MarkPageDown},
 300     {"MarkToFileBegin", CK_MarkToFileBegin},
 301     {"MarkToFileEnd", CK_MarkToFileEnd},
 302     {"MarkToPageBegin", CK_MarkToPageBegin},
 303     {"MarkToPageEnd", CK_MarkToPageEnd},
 304     {"MarkScrollUp", CK_MarkScrollUp},
 305     {"MarkScrollDown", CK_MarkScrollDown},
 306     {"MarkParagraphUp", CK_MarkParagraphUp},
 307     {"MarkParagraphDown", CK_MarkParagraphDown},
 308     {"MarkColumnPageUp", CK_MarkColumnPageUp},
 309     {"MarkColumnPageDown", CK_MarkColumnPageDown},
 310     {"MarkColumnLeft", CK_MarkColumnLeft},
 311     {"MarkColumnRight", CK_MarkColumnRight},
 312     {"MarkColumnUp", CK_MarkColumnUp},
 313     {"MarkColumnDown", CK_MarkColumnDown},
 314     {"MarkColumnScrollUp", CK_MarkColumnScrollUp},
 315     {"MarkColumnScrollDown", CK_MarkColumnScrollDown},
 316     {"MarkColumnParagraphUp", CK_MarkColumnParagraphUp},
 317     {"MarkColumnParagraphDown", CK_MarkColumnParagraphDown},
 318     {"BlockShiftLeft", CK_BlockShiftLeft},
 319     {"BlockShiftRight", CK_BlockShiftRight},
 320     {"InsertLiteral", CK_InsertLiteral},
 321     {"ShowTabTws", CK_ShowTabTws},
 322     {"SyntaxOnOff", CK_SyntaxOnOff},
 323     {"SyntaxChoose", CK_SyntaxChoose},
 324     {"ShowMargin", CK_ShowMargin},
 325     {"OptionsSaveMode", CK_OptionsSaveMode},
 326     {"About", CK_About},
 327     /* An action to run external script from macro */
 328     {"ExecuteScript", CK_PipeBlock (0)},
 329     {"WindowMove", CK_WindowMove},
 330     {"WindowResize", CK_WindowResize},
 331     {"WindowFullscreen", CK_WindowFullscreen},
 332     {"WindowList", CK_WindowList},
 333     {"WindowNext", CK_WindowNext},
 334     {"WindowPrev", CK_WindowPrev},
 335 #endif /* USE_INTERNAL_EDIT */
 336 
 337     /* viewer */
 338     {"WrapMode", CK_WrapMode},
 339     {"HexEditMode", CK_HexEditMode},
 340     {"HexMode", CK_HexMode},
 341     {"MagicMode", CK_MagicMode},
 342     {"NroffMode", CK_NroffMode},
 343     {"BookmarkGoto", CK_BookmarkGoto},
 344     {"Ruler", CK_Ruler},
 345     {"SearchForward", CK_SearchForward},
 346     {"SearchBackward", CK_SearchBackward},
 347     {"SearchForwardContinue", CK_SearchForwardContinue},
 348     {"SearchBackwardContinue", CK_SearchBackwardContinue},
 349     {"SearchOppositeContinue", CK_SearchOppositeContinue},
 350 
 351 #ifdef USE_DIFF_VIEW
 352     /* diff viewer */
 353     {"ShowSymbols", CK_ShowSymbols},
 354     {"SplitFull", CK_SplitFull},
 355     {"Tab2", CK_Tab2},
 356     {"Tab3", CK_Tab3},
 357     {"Tab4", CK_Tab4},
 358     {"Tab8", CK_Tab8},
 359     {"HunkNext", CK_HunkNext},
 360     {"HunkPrev", CK_HunkPrev},
 361     {"EditOther", CK_EditOther},
 362     {"Merge", CK_Merge},
 363     {"MergeOther", CK_MergeOther},
 364 #endif /* USE_DIFF_VIEW */
 365 
 366     {NULL, CK_IgnoreKey}
 367 };
 368 
 369 /* *INDENT-OFF* */
 370 static const size_t num_command_names = G_N_ELEMENTS (command_names) - 1;
 371 /* *INDENT-ON* */
 372 
 373 /*** file scope functions ************************************************************************/
 374 /* --------------------------------------------------------------------------------------------- */
 375 
 376 static int
 377 name_keymap_comparator (const void *p1, const void *p2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 378 {
 379     const name_keymap_t *m1 = (const name_keymap_t *) p1;
 380     const name_keymap_t *m2 = (const name_keymap_t *) p2;
 381 
 382     return g_ascii_strcasecmp (m1->name, m2->name);
 383 }
 384 
 385 /* --------------------------------------------------------------------------------------------- */
 386 
 387 static inline void
 388 sort_command_names (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 389 {
 390     static gboolean has_been_sorted = FALSE;
 391 
 392     if (!has_been_sorted)
 393     {
 394         qsort (command_names, num_command_names,
 395                sizeof (command_names[0]), &name_keymap_comparator);
 396         has_been_sorted = TRUE;
 397     }
 398 }
 399 
 400 /* --------------------------------------------------------------------------------------------- */
 401 
 402 static void
 403 keymap_add (GArray * keymap, long key, long cmd, const char *caption)
     /* [previous][next][first][last][top][bottom][index][help]  */
 404 {
 405     if (key != 0 && cmd != CK_IgnoreKey)
 406     {
 407         global_keymap_t new_bind;
 408 
 409         new_bind.key = key;
 410         new_bind.command = cmd;
 411         g_snprintf (new_bind.caption, sizeof (new_bind.caption), "%s", caption);
 412         g_array_append_val (keymap, new_bind);
 413     }
 414 }
 415 
 416 /* --------------------------------------------------------------------------------------------- */
 417 /*** public functions ****************************************************************************/
 418 /* --------------------------------------------------------------------------------------------- */
 419 
 420 void
 421 keybind_cmd_bind (GArray * keymap, const char *keybind, long action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 422 {
 423     char *caption = NULL;
 424     long key;
 425 
 426     key = lookup_key (keybind, &caption);
 427     keymap_add (keymap, key, action, caption);
 428     g_free (caption);
 429 }
 430 
 431 /* --------------------------------------------------------------------------------------------- */
 432 
 433 long
 434 keybind_lookup_action (const char *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 435 {
 436     const name_keymap_t key = { name, 0 };
 437     name_keymap_t *res;
 438 
 439     sort_command_names ();
 440 
 441     res = bsearch (&key, command_names, num_command_names,
 442                    sizeof (command_names[0]), name_keymap_comparator);
 443 
 444     return (res != NULL) ? res->val : CK_IgnoreKey;
 445 }
 446 
 447 /* --------------------------------------------------------------------------------------------- */
 448 
 449 const char *
 450 keybind_lookup_actionname (long action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 451 {
 452     size_t i;
 453 
 454     for (i = 0; command_names[i].name != NULL; i++)
 455         if (command_names[i].val == action)
 456             return command_names[i].name;
 457 
 458     return NULL;
 459 }
 460 
 461 /* --------------------------------------------------------------------------------------------- */
 462 
 463 const char *
 464 keybind_lookup_keymap_shortcut (const global_keymap_t * keymap, long action)
     /* [previous][next][first][last][top][bottom][index][help]  */
 465 {
 466     if (keymap != NULL)
 467     {
 468         size_t i;
 469 
 470         for (i = 0; keymap[i].key != 0; i++)
 471             if (keymap[i].command == action)
 472                 return (keymap[i].caption[0] != '\0') ? keymap[i].caption : NULL;
 473     }
 474     return NULL;
 475 }
 476 
 477 /* --------------------------------------------------------------------------------------------- */
 478 
 479 long
 480 keybind_lookup_keymap_command (const global_keymap_t * keymap, long key)
     /* [previous][next][first][last][top][bottom][index][help]  */
 481 {
 482     if (keymap != NULL)
 483     {
 484         size_t i;
 485 
 486         for (i = 0; keymap[i].key != 0; i++)
 487             if (keymap[i].key == key)
 488                 return keymap[i].command;
 489     }
 490 
 491     return CK_IgnoreKey;
 492 }
 493 
 494 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */