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

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