aboutsummaryrefslogtreecommitdiffstats
path: root/src/keys.c
diff options
context:
space:
mode:
authorFrederic Culot <calcurse@culot.org>2008-11-16 17:42:53 +0000
committerFrederic Culot <calcurse@culot.org>2008-11-16 17:42:53 +0000
commit9d4899110a067d4899116ac229c8b4c489096b60 (patch)
treef10f31dc5e8114791236ada1ebee8d27b31b7e72 /src/keys.c
parente8f12c65ca0245079ae015a90e7a14109759cdda (diff)
downloadcalcurse-9d4899110a067d4899116ac229c8b4c489096b60.tar.gz
calcurse-9d4899110a067d4899116ac229c8b4c489096b60.zip
More work on implementing user-definable keybindings
Diffstat (limited to 'src/keys.c')
-rwxr-xr-xsrc/keys.c331
1 files changed, 235 insertions, 96 deletions
diff --git a/src/keys.c b/src/keys.c
index 2c0fc98..4f8f9bc 100755
--- a/src/keys.c
+++ b/src/keys.c
@@ -1,4 +1,4 @@
-/* $calcurse: keys.c,v 1.2 2008/11/09 20:10:18 culot Exp $ */
+/* $calcurse: keys.c,v 1.3 2008/11/16 17:42:53 culot Exp $ */
/*
* Calcurse - text-based organizer
@@ -24,138 +24,277 @@
*
*/
+#include <string.h>
+
#include "i18n.h"
#include "utils.h"
-#include "htable.h"
#include "keys.h"
-#define HTKEYSIZE 512
+#define MAXKEYVAL 256
+
+struct keydef_s {
+ char *label;
+ char *binding;
+};
-struct keys_s {
- int key;
- keys_e action;
- HTABLE_ENTRY (keys_s);
+struct key_str_s {
+ char *str;
+ struct key_str_s *next;
};
-static HTABLE_HEAD (ht_keys, HTKEYSIZE, keys_s) ht_keys_action =
- HTABLE_INITIALIZER (&ht_keys_action);
-
-static char *keylabel[NOKEYS] = {
- "generic-help",
- "generic-quit",
- "generic-save",
- "generic-change-view",
- "generic-import",
- "generic-export",
-
- "generic-goto",
- "generic-other-cmd",
- "generic-config-menu",
- "generic-redraw",
-
- "generic-add-appt",
- "generic-add-todo",
- "generic-next-ady",
- "generic-prev-day",
- "generic-next-week",
- "generic-prev-week",
- "generic-goto-today",
+static struct key_str_s *keys[NBKEYS];
+
+static keys_e actions[MAXKEYVAL];
+
+static struct keydef_s keydef[NBKEYS] = {
+ {"generic-escape", "ESC"},
+ {"generic-credits", "@"},
+ {"generic-help", "?"},
+ {"generic-quit", "q Q"},
+ {"generic-save", "s S C-s"},
+ {"generic-change-view", "TAB"},
+ {"generic-import", "i I"},
+ {"generic-export", "x X"},
+ {"generic-goto", "g G"},
+ {"generic-other-cmd", "o O"},
+ {"generic-config-menu", "c C"},
+ {"generic-redraw", "C-r"},
+ {"generic-add-appt", "C-a"},
+ {"generic-add-todo", "C-t"},
+ {"generic-next-day", "C-l"},
+ {"generic-prev-day", "C-h"},
+ {"generic-next-week", "C-j"},
+ {"generic-prev-week", "C-k"},
+ {"generic-scroll-down", "C-n"},
+ {"generic-scroll-up", "C-p"},
+ {"generic-goto-today", "C-g"},
- "cal-next-day",
- "cal-prev-day",
- "cal-next-week",
- "cal-prev-week",
- "cal-start-of-week",
- "cal-end-of-week",
-
- "apt-add-item",
- "apt-del-item",
- "apt-edit-item",
- "apt-view-item",
- "apt-flag-item",
- "apt-repeat",
- "apt-move-up",
- "apt-move-down",
- "apt-edit-note",
- "apt-view-note",
-
- "todo-add-item",
- "todo-del-item",
- "todo-edit-item",
- "todo-view-item",
- "todo-raise-priority",
- "todo-lower-priority",
- "todo-move-up",
- "todo-move-down",
- "todo-edit-note",
- "todo-view-bote",
-
- "config-quit",
- "config-general-menu",
- "config-layout-menu",
- "config-color-menu",
- "config-notify-menu"
+ {"move-right", "l L"},
+ {"move-left", "h H"},
+ {"move-down", "j J"},
+ {"move-up", "k K"},
+ {"start-of-week", "0"},
+ {"end-of-week", "$"},
+ {"add-item", "a A"},
+ {"del-item", "d D"},
+ {"edit-item", "e E"},
+ {"view-item", "v V"},
+ {"flag-item", "!"},
+ {"repeat", "r R"},
+ {"edit-note", "n N"},
+ {"view-note", ">"},
+ {"raise-priority", "+"},
+ {"lower-priority", "-"},
};
static void
-ht_getkey (struct keys_s *data, char **key, int *len)
+dump_intro (FILE *fd)
{
- *key = (char *)&data->key;
- *len = sizeof (int);
+ char *intro =
+ _("#\n"
+ "# Calcurse keys configuration file\n#\n"
+ "# This file sets the keybindings used by Calcurse.\n"
+ "# Lines beginning with \"#\" are comments, and ignored by Calcurse.\n"
+ "# To assign a keybinding to an action, this file must contain a line\n"
+ "# with the following syntax:\n#\n"
+ "# ACTION KEY1 KEY2 ... KEYn\n#\n"
+ "# Where ACTION is what will be performed when KEY1, KEY2, ..., or KEYn\n"
+ "# will be pressed.\n"
+ "#\n"
+ "# To define bindings which use the CONTROL key, prefix the key with "
+ "'C-'.\n"
+ "# The escape and horizontal Tab key can be specified using the 'ESC'\n"
+ "# and 'TAB' keyword, respectively.\n");
+
+ fprintf (fd, "%s\n", intro);
}
-static int
-ht_compare (struct keys_s *data1, struct keys_s *data2)
+void
+keys_init (void)
{
- if (data1->key == data2->key)
- return 0;
- else
- return 1;
+ int i;
+
+ for (i = 0; i < MAXKEYVAL; i++)
+ actions[i] = KEY_UNDEF;
+ bzero (keys, NBKEYS);
}
-HTABLE_GENERATE (ht_keys, keys_s, ht_getkey, ht_compare);
+void
+keys_dump_defaults (char *file)
+{
+ FILE *fd;
+ int i;
+
+ fd = fopen (file, "w");
+ EXIT_IF (fd == NULL, _("FATAL ERROR in keys_dump_defaults: "
+ "could not create default keys file."));
+
+ dump_intro (fd);
+ for (i = 0; i < NBKEYS; i++)
+ fprintf (fd, "%s %s\n", keydef[i].label, keydef[i].binding);
+ fclose (fd);
+}
char *
keys_get_label (keys_e key)
{
- EXIT_IF (key < 0 || key > NOKEYS,
+ EXIT_IF (key < 0 || key > NBKEYS,
_("FATAL ERROR in keys_get_label: key value out of bounds"));
- return keylabel[key];
+ return keydef[key].label;
+}
+
+static int
+keys_get_action (int pressed)
+{
+ if (pressed < 0 || pressed > MAXKEYVAL)
+ return -1;
+ else
+ return actions[pressed];
+}
+
+keys_e
+keys_getch (WINDOW *win)
+{
+ int ch;
+
+ ch = wgetch (win);
+
+ return keys_get_action (ch);
+}
+
+static void
+add_key_str (keys_e action, int key)
+{
+ struct key_str_s *new, **i;
+
+ if (action < 0 || action > NBKEYS)
+ return;
+
+ new = malloc (sizeof (struct key_str_s));
+ new->str = strdup (keys_int2str (key));
+ new->next = NULL;
+ i = &keys[action];
+ for (;;)
+ {
+ if (*i == NULL)
+ {
+ *i = new;
+ break;
+ }
+ else if ((*i)->next == NULL)
+ {
+ (*i)->next = new;
+ break;
+ }
+ i = &(*i)->next;
+ }
}
int
-keys_get_key (int pressed)
+keys_assign_binding (int key, keys_e action)
+{
+ if (key < 0 || key > MAXKEYVAL || actions[key] != KEY_UNDEF)
+ return 1;
+ else
+ {
+ actions[key] = action;
+ add_key_str (action, key);
+ }
+
+ return 0;
+}
+
+static void
+del_key_str (keys_e action, int key)
{
- struct keys_s *key, find;
+ struct key_str_s *old, **i;
+ char oldstr[BUFSIZ];
+ int oldstrlen;
+
+ if (action < 0 || action > NBKEYS)
+ return;
- find.key = pressed;
- key = HTABLE_LOOKUP (ht_keys, &ht_keys_action, &find);
+ strncpy (oldstr, keys_int2str (key), BUFSIZ);
+ oldstrlen = strlen (oldstr);
+ for (i = &keys[action]; *i; i = &(*i)->next)
+ {
+ if (strlen ((*i)->str) == oldstrlen
+ && !(strncmp ((*i)->str, oldstr, oldstrlen)))
+ {
+ old = (*i);
+ (*i) = old->next;
+ mem_free (old->str);
+ mem_free (old);
+ break;
+ }
+ }
+}
- if (key)
- return (int)key->action;
+void
+keys_remove_binding (int key, keys_e action)
+{
+ if (key < 0 || key > MAXKEYVAL)
+ return;
else
+ {
+ actions[key] = KEY_UNDEF;
+ del_key_str (action, key);
+ }
+}
+
+int
+keys_str2int (char *key)
+{
+ const string_t CONTROL_KEY = STRING_BUILD ("C-");
+ const string_t TAB_KEY = STRING_BUILD ("TAB");
+ const string_t ESCAPE_KEY = STRING_BUILD ("ESC");
+
+ if (!key)
return -1;
+ if (strlen (key) == 1)
+ return (int)key[0];
+ else
+ {
+ if (!strncmp (key, CONTROL_KEY.str, CONTROL_KEY.len))
+ return CTRL ((int)key[CONTROL_KEY.len]);
+ else if (!strncmp (key, TAB_KEY.str, TAB_KEY.len))
+ return TAB;
+ else if (!strncmp (key, ESCAPE_KEY.str, ESCAPE_KEY.len))
+ return ESCAPE;
+ else
+ return -1;
+ }
}
-void
-keys_assign_binding (int key, keys_e action)
+char *
+keys_int2str (int key)
{
- struct keys_s *binding;
+ return keyname (key);
+}
- binding = malloc (sizeof (struct keys_s));
- binding->key = key;
- binding->action = action;
- HTABLE_INSERT (ht_keys, &ht_keys_action, binding);
+char *
+keys_action_firstkey (keys_e action)
+{
+ return (keys[action] != NULL) ? keys[action]->str : NULL;
}
-void
-key_remove_binding (int key, keys_e action)
+char *
+keys_action_allkeys (keys_e action)
{
- struct keys_s find, *removed;
+ static char keystr[BUFSIZ];
+ struct key_str_s *i;
+ const char *SPACE = " ";
+
+ if (keys[action] == NULL)
+ return NULL;
+ keystr[0] = '\0';
+ for (i = keys[action]; i; i = i->next)
+ {
+ const int MAXLEN = sizeof (keystr) - 1 - strlen (keystr);
+ strncat (keystr, i->str, MAXLEN - 1);
+ strncat (keystr, SPACE, 1);
+ }
- find.key = key;
- find.action = action;
- removed = HTABLE_REMOVE (ht_keys, &ht_keys_action, &find);
- mem_free (removed);
+ return keystr;
}