/* $calcurse: keys.c,v 1.3 2008/11/16 17:42:53 culot Exp $ */ /* * Calcurse - text-based organizer * Copyright (c) 2008 Frederic Culot * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Send your feedback or comments to : calcurse@culot.org * Calcurse home page : http://culot.org/calcurse * */ #include #include "i18n.h" #include "utils.h" #include "keys.h" #define MAXKEYVAL 256 struct keydef_s { char *label; char *binding; }; struct key_str_s { char *str; struct key_str_s *next; }; 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"}, {"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 dump_intro (FILE *fd) { 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); } void keys_init (void) { int i; for (i = 0; i < MAXKEYVAL; i++) actions[i] = KEY_UNDEF; bzero (keys, NBKEYS); } 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 > NBKEYS, _("FATAL ERROR in keys_get_label: key value out of bounds")); 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_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 key_str_s *old, **i; char oldstr[BUFSIZ]; int oldstrlen; if (action < 0 || action > NBKEYS) return; 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; } } } 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; } } char * keys_int2str (int key) { return keyname (key); } char * keys_action_firstkey (keys_e action) { return (keys[action] != NULL) ? keys[action]->str : NULL; } char * keys_action_allkeys (keys_e action) { 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); } return keystr; }