123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- /*
- Handle keyspresses and bind them to events.
- Copyright (C) 2005-2014
- Free Software Foundation, Inc.
- Written by:
- Vitja Makarov, 2005
- Ilia Maslakov <il.smind@gmail.com>, 2009, 2012
- Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2011, 2012
- Totally rewritten by:
- Slava Zanko <slavazanko@gmail.com>, 2014
- 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 <http://www.gnu.org/licenses/>.
- */
- #include <config.h>
- #include "lib/global.h"
- #include "lib/event.h"
- #include "lib/keymap.h"
- #include "lib/tty/key.h"
- /*** global variables ****************************************************************************/
- /*** file scope macro definitions ****************************************************************/
- #define MC_KEYMAP_EVENT_GROUP "keymap"
- #define MC_KEYMAP_EVENT_SWITCH_GROUP_NAME "switch_group"
- #define KEYMAP_ERR_NOT_INITIALIZED N_ ("Keymap system not initialized")
- #define KEYMAP_ERR_INPUT_DATA N_ ("Check input data! Some of parameters are NULL!")
- /*** file scope type declarations ****************************************************************/
- typedef struct
- {
- long code;
- const char *name;
- } mc_keymap_keycode_t;
- typedef struct
- {
- char *group;
- char *name;
- char *switch_group;
- } mc_keymap_event_t;
- typedef struct
- {
- GTree *keymap_group;
- const char *name;
- } mc_keymap_clear_keycodes_t;
- /*** file scope variables ************************************************************************/
- static GTree *all_key_codes = NULL;
- static GTree *all_key_events = NULL;
- static const char *switched_group = NULL;
- static gboolean switch_group_cmd_was_called = FALSE;
- /*** file scope functions ************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
- /* event callback */
- static gboolean
- mc_keymap_cmd_switch_group (event_info_t * event_info, gpointer data, GError ** error)
- {
- (void) event_info;
- (void) error;
- switched_group = (const char *) data;
- switch_group_cmd_was_called = TRUE;
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- static gboolean
- mc_keymap_is_initialised (GError ** error)
- {
- if (all_key_codes == NULL)
- {
- g_propagate_error (error, g_error_new (MC_ERROR, 1, _(KEYMAP_ERR_NOT_INITIALIZED)));
- return FALSE;
- }
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- static gint
- mc_keymap_keycode_compare (gconstpointer a, gconstpointer b)
- {
- return (a > b) ? 1 : (a < b) ? -1 : 0;
- }
- /* --------------------------------------------------------------------------------------------- */
- static GTree *
- mc_keymap_get_key_group (const char *group, GError ** error)
- {
- GTree *keymap_group;
- keymap_group = (GTree *) g_tree_lookup (all_key_codes, (gconstpointer) group);
- if (keymap_group == NULL)
- {
- keymap_group =
- g_tree_new_full ((GCompareDataFunc) mc_keymap_keycode_compare, NULL, NULL,
- (GDestroyNotify) g_free);
- if (keymap_group == NULL)
- g_propagate_error (error,
- g_error_new (MC_ERROR, 1,
- _("Unable to create group '%s' for keymaps!"), group));
- else
- g_tree_insert (all_key_codes, g_strdup (group), (gpointer) keymap_group);
- }
- return keymap_group;
- }
- /* --------------------------------------------------------------------------------------------- */
- static gboolean
- mc_keymap_clear_keycodes (gpointer key, gpointer value, gpointer data)
- {
- mc_keymap_clear_keycodes_t *keymap_data = (mc_keymap_clear_keycodes_t *) data;
- if (strcmp (value, keymap_data->name) == 0)
- g_tree_remove (keymap_data->keymap_group, key);
- return FALSE;
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- mc_keymap_add_keycode_to_group (GTree * keymap_group, const char *name,
- const char *pressed_keynames, gboolean isDeleteOld)
- {
- char **keyname_list, **one_keyname;
- keyname_list = g_strsplit_set (pressed_keynames, ";", -1);
- if (isDeleteOld)
- {
- mc_keymap_clear_keycodes_t data = {
- .keymap_group = keymap_group,
- .name = name
- };
- g_tree_foreach (keymap_group, mc_keymap_clear_keycodes, &data);
- }
- for (one_keyname = keyname_list; one_keyname != NULL && *one_keyname != NULL; one_keyname++)
- {
- long keycode;
- char *caption = NULL;
- if ((*one_keyname)[0] == '\0')
- continue;
- keycode = lookup_key (*one_keyname, &caption);
- g_tree_replace (keymap_group, (void *) keycode, g_strdup (name));
- g_free (caption);
- }
- g_strfreev (keyname_list);
- }
- /* --------------------------------------------------------------------------------------------- */
- static char *
- keymap_make_event_key (const char *group, const char *name)
- {
- return g_strdup_printf ("[%s][%s]", group, name);
- }
- /* --------------------------------------------------------------------------------------------- */
- static mc_keymap_event_t *
- keymap_get_event (const char *group, const char *name)
- {
- char *event_key;
- mc_keymap_event_t *ret_value;
- event_key = keymap_make_event_key (group, name);
- ret_value = (mc_keymap_event_t *) g_tree_lookup (all_key_events, (gconstpointer) event_key);
- g_free (event_key);
- return ret_value;
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- keymap_event_free (mc_keymap_event_t * keymap_event)
- {
- g_free (keymap_event->group);
- g_free (keymap_event->name);
- g_free (keymap_event->switch_group);
- g_free (keymap_event);
- }
- /* --------------------------------------------------------------------------------------------- */
- static gboolean
- mc_keymap_bind_event_with_data (const char *group, const char *name, const char *event_group,
- const char *event_name, const char *switch_group, GError ** error)
- {
- char *event_key;
- mc_keymap_event_t *keymap_event;
- if (!mc_keymap_is_initialised (error))
- return FALSE;
- event_key = keymap_make_event_key (group, name);
- keymap_event = g_new (mc_keymap_event_t, 1);
- keymap_event->group = g_strdup (event_group);
- keymap_event->name = g_strdup (event_name);
- keymap_event->switch_group = g_strdup (switch_group);
- g_tree_replace (all_key_events, event_key, (gpointer) keymap_event);
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- /*** public functions ****************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_init (GError ** error)
- {
- if (all_key_codes != NULL)
- {
- g_propagate_error (error,
- g_error_new (MC_ERROR, 1, _("Keymap system already initialized")));
- return FALSE;
- }
- all_key_codes =
- g_tree_new_full ((GCompareDataFunc) g_ascii_strcasecmp,
- NULL, (GDestroyNotify) g_free, (GDestroyNotify) g_tree_destroy);
- if (all_key_codes == NULL)
- {
- g_propagate_error (error, g_error_new (MC_ERROR, 2, _(KEYMAP_ERR_NOT_INITIALIZED)));
- return FALSE;
- }
- all_key_events = g_tree_new_full ((GCompareDataFunc) g_ascii_strcasecmp,
- NULL, (GDestroyNotify) g_free,
- (GDestroyNotify) keymap_event_free);
- if (all_key_events == NULL)
- {
- g_propagate_error (error, g_error_new (MC_ERROR, 2, _(KEYMAP_ERR_NOT_INITIALIZED)));
- g_tree_destroy (all_key_codes);
- return FALSE;
- }
- mc_event_add (MC_KEYMAP_EVENT_GROUP, MC_KEYMAP_EVENT_SWITCH_GROUP_NAME,
- mc_keymap_cmd_switch_group, NULL, error);
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_deinit (GError ** error)
- {
- if (!mc_keymap_is_initialised (error))
- return FALSE;
- g_tree_destroy (all_key_codes);
- all_key_codes = NULL;
- g_tree_destroy (all_key_events);
- all_key_events = NULL;
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_bind_keycode (const char *group, const char *name, const char *pressed_keynames,
- gboolean isDeleteOld, GError ** error)
- {
- GTree *keymap_group;
- if (!mc_keymap_is_initialised (error))
- return FALSE;
- if (group == NULL || name == NULL)
- {
- g_propagate_error (error, g_error_new (MC_ERROR, 1, _(KEYMAP_ERR_INPUT_DATA)));
- return FALSE;
- }
- keymap_group = mc_keymap_get_key_group (group, error);
- if (keymap_group == NULL)
- return FALSE;
- mc_keymap_add_keycode_to_group (keymap_group, name, pressed_keynames, isDeleteOld);
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_bind_event (const char *group, const char *name, const char *event_group,
- const char *event_name, GError ** error)
- {
- return mc_keymap_bind_event_with_data (group, name, event_group, event_name, NULL, error);
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_bind_switch_event (const char *group, const char *name, const char *switch_group,
- GError ** error)
- {
- return mc_keymap_bind_event_with_data (group, name, MC_KEYMAP_EVENT_GROUP,
- MC_KEYMAP_EVENT_SWITCH_GROUP_NAME, switch_group, error);
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_mass_bind_event (const mc_keymap_event_init_t * group_keymap_events, GError ** error)
- {
- size_t array_group_index;
- gboolean ret_value = TRUE;
- for (array_group_index = 0; group_keymap_events[array_group_index].group != NULL;
- array_group_index++)
- {
- size_t array_index;
- const char *group_name = group_keymap_events[array_group_index].group;
- const mc_keymap_event_init_group_t *keymap_events =
- group_keymap_events[array_group_index].keymap_events;
- for (array_index = 0; keymap_events[array_index].name != NULL; array_index++)
- if (!mc_keymap_bind_event (group_name, keymap_events[array_index].name,
- keymap_events[array_index].event_group,
- keymap_events[array_index].event_name, error))
- {
- ret_value = FALSE;
- break;
- }
- }
- return ret_value;
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mc_keymap_process_group (const char *group, long pressed_keycode, void *data, event_return_t * ret,
- GError ** error)
- {
- const char *key_name;
- mc_keymap_event_t *keymap_event;
- gboolean ret_value;
- if (switched_group != NULL)
- {
- group = switched_group;
- switched_group = NULL;
- }
- key_name = mc_keymap_get_key_name_by_code (group, pressed_keycode, error);
- if (key_name == NULL)
- return FALSE;
- keymap_event = keymap_get_event (group, key_name);
- if (keymap_event == NULL)
- return FALSE;
- if (keymap_event->switch_group != NULL)
- data = keymap_event->switch_group;
- ret_value = mc_event_dispatch (keymap_event->group, keymap_event->name, data, ret, error);
- if (switch_group_cmd_was_called && switched_group == NULL)
- {
- switched_group = group;
- switch_group_cmd_was_called = FALSE;
- }
- return ret_value;
- }
- /* --------------------------------------------------------------------------------------------- */
- const char *
- mc_keymap_get_key_name_by_code (const char *group, long pressed_keycode, GError ** error)
- {
- GTree *keymap_group;
- keymap_group = mc_keymap_get_key_group (group, error);
- if (keymap_group == NULL)
- return FALSE;
- return (const char *) g_tree_lookup (keymap_group, (gconstpointer) pressed_keycode);
- }
- /* --------------------------------------------------------------------------------------------- */
|