From e8f12c65ca0245079ae015a90e7a14109759cdda Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Sun, 9 Nov 2008 20:10:18 +0000
Subject: Loading of user-configurable keys implemented

---
 src/calcurse.c | 190 ++++++++++++++++++++++++++++-----------------------------
 src/custom.c   |   4 +-
 src/htable.h   |   2 +-
 src/io.c       | 126 +++++++++++++++++++++++++++++++++++++-
 src/io.h       |   3 +-
 src/keys.c     |  75 +++++++++++++++++++++--
 src/keys.h     |  11 ++--
 src/todo.c     |   7 ++-
 src/utils.h    |   5 +-
 src/vars.c     |   3 +-
 src/vars.h     |   5 +-
 11 files changed, 314 insertions(+), 117 deletions(-)

(limited to 'src')

diff --git a/src/calcurse.c b/src/calcurse.c
index 9ed1d9d..4070d51 100755
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calcurse.c,v 1.68 2008/09/21 08:06:43 culot Exp $	*/
+/*	$calcurse: calcurse.c,v 1.69 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -41,7 +41,7 @@
 #include "todo.h"
 #include "args.h"
 #include "notify.h"
-
+#include "keys.h"
 
 /*
  * Calcurse is a text-based personal organizer which helps keeping track
@@ -55,7 +55,7 @@ main (int argc, char **argv)
 {
   conf_t conf;
   day_items_nb_t inday;
-  int ch, background, foreground;
+  int background, foreground;
   int non_interactive;
   int no_data_file = 1;
   int sav_hilt_app = 0;
@@ -146,6 +146,7 @@ main (int argc, char **argv)
   no_data_file = io_check_data_files ();
   custom_load_conf (&conf, background);
   erase_status_bar ();
+  io_load_keys ();
   io_load_todo ();
   io_load_app ();
   wins_reinit ();
@@ -161,23 +162,29 @@ main (int argc, char **argv)
   /* User input */
   for (;;)
     {
+      int ch, key;
+      
       do_update = true;
       ch = wgetch (win[STA].p);
-      switch (ch)
+      key = keys_get_key (ch);
+      if (key == -1)
+        key = ch;
+      
+      switch (key)
 	{
 	case ERR:
 	  do_update = false;
 	  break;
 
-	case CTRL ('R'):
+	case KEY_GENERIC_REDRAW:
 	case KEY_RESIZE:
 	  do_update = false;
 	  wins_reset ();
 	  break;
 
-	case 9:		/* The TAB key was hit. */
+	case KEY_GENERIC_CHANGE_VIEW:
 	  reset_status_page ();
-	  /* Save previously highlighted event. */
+	  /* Need to save the previously highlighted event. */
 	  switch (wins_slctd ())
 	    {
 	    case TOD:
@@ -214,17 +221,15 @@ main (int argc, char **argv)
 	    }
 	  break;
 
-	case 'O':
-	case 'o':
+        case KEY_GENERIC_OTHER_CMD:
 	  other_status_page (wins_slctd ());
 	  break;
 
-        case CTRL ('G'):
-	case 'G':
-	case 'g':		/* Goto function */
+        case KEY_GENERIC_GOTO:
+        case KEY_GENERIC_GOTO_TODAY:
 	  erase_status_bar ();
 	  calendar_set_current_date ();
-          if (ch == CTRL ('G'))
+          if (ch == KEY_GENERIC_GOTO_TODAY)
             calendar_goto_today ();
           else
             calendar_change_day (conf.input_datefmt);
@@ -232,16 +237,15 @@ main (int argc, char **argv)
 	  day_changed = true;
 	  break;
 
-	case 'V':
-	case 'v':		/* View function */
+        case KEY_APT_VIEW_ITEM:
+        case KEY_TODO_VIEW_ITEM:
 	  if ((wins_slctd () == APP) && (apoint_hilt () != 0))
 	    day_popup_item ();
 	  else if ((wins_slctd () == TOD) && (todo_hilt () != 0))
 	    item_in_popup (NULL, NULL, todo_saved_mesg (), _("To do :"));
 	  break;
 
-	case 'C':
-	case 'c':		/* Configuration menu */
+        case KEY_GENERIC_CONFIG_MENU:
 	  erase_status_bar ();
 	  config_bar ();
 	  while ((ch = wgetch (win[STA].p)) != 'q')
@@ -282,19 +286,19 @@ main (int argc, char **argv)
 	  wins_update ();
 	  break;
 
-	case CTRL ('A'):	/* Add an app, whatever panel selected */
+        case KEY_GENERIC_ADD_APPT:
 	  apoint_add ();
 	  do_storage = true;
 	  break;
 
-	case CTRL ('T'):	/* Add a todo, whatever panel selected */
+        case KEY_GENERIC_ADD_TODO:
 	  todo_new_item ();
 	  if (todo_hilt () == 0 && todo_nb () == 1)
 	    todo_hilt_increase ();
 	  break;
 
-	case 'A':
-	case 'a':		/* Add an item */
+        case KEY_APT_ADD_ITEM:
+        case KEY_TODO_ADD_ITEM:
 	  switch (wins_slctd ())
 	    {
 	    case APP:
@@ -311,8 +315,8 @@ main (int argc, char **argv)
 	    }
 	  break;
 
-	case 'E':
-	case 'e':		/* Edit an existing item */
+        case KEY_APT_EDIT_ITEM:
+        case KEY_TODO_EDIT_ITEM:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    day_edit_item (&conf);
 	  else if (wins_slctd () == TOD && todo_hilt () != 0)
@@ -320,8 +324,8 @@ main (int argc, char **argv)
 	  do_storage = true;
 	  break;
 
-	case 'D':
-	case 'd':		/* Delete an item */
+        case KEY_APT_DEL_ITEM:
+        case KEY_TODO_DEL_ITEM:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    apoint_delete (&conf, &inday.nb_events, &inday.nb_apoints);
 	  else if (wins_slctd () == TOD && todo_hilt () != 0)
@@ -329,24 +333,23 @@ main (int argc, char **argv)
 	  do_storage = true;
 	  break;
 
-	case 'R':
-	case 'r':
+        case KEY_APT_REPEAT:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    recur_repeat_item (&conf);
 	  do_storage = true;
 	  break;
 
-	case '!':
+        case KEY_APT_FLAG_ITEM:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    apoint_switch_notify ();
 	  do_storage = true;
 	  break;
 
-	case '+':
-	case '-':
+        case KEY_TODO_RAISE_PRIORITY:
+        case KEY_TODO_LOWER_PRIORITY:
 	  if (wins_slctd () == TOD && todo_hilt () != 0)
 	    {
-	      todo_chg_priority (ch);
+	      todo_chg_priority (key);
 	      if (todo_hilt_pos () < 0)
 		todo_set_first (todo_hilt ());
 	      else if (todo_hilt_pos () >= win[TOD].h - 4)
@@ -354,9 +357,8 @@ main (int argc, char **argv)
 	    }
 	  break;
 
-	case 'N':
-	case 'n':
-	  /* Attach a note to an item, create it if necessary */
+        case KEY_APT_EDIT_NOTE:
+        case KEY_TODO_EDIT_NOTE:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    day_edit_note (conf.editor);
 	  else if (wins_slctd () == TOD && todo_hilt () != 0)
@@ -364,33 +366,30 @@ main (int argc, char **argv)
 	  do_storage = true;
 	  break;
 
-	case '>':
-	  /* View a note previously attached to an item */
+        case KEY_APT_VIEW_NOTE:
+        case KEY_TODO_VIEW_NOTE:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    day_view_note (conf.pager);
 	  else if (wins_slctd () == TOD && todo_hilt () != 0)
 	    todo_view_note (conf.pager);
 	  break;
 
-	case '?':		/* Online help system */
+        case KEY_GENERIC_HELP:
 	  status_bar ();
 	  help_screen ();
 	  break;
 
-	case 'S':
-	case 's':		/* Save function */
+        case KEY_GENERIC_SAVE:
 	  io_save_cal (IO_MODE_INTERACTIVE, &conf);
 	  break;
 
-        case 'I':
-        case 'i':               /* Import function */
+        case KEY_GENERIC_IMPORT:
           erase_status_bar ();
           io_import_data (IO_MODE_INTERACTIVE, IO_IMPORT_ICAL, &conf, NULL);
           do_storage = true;
           break;
           
-	case 'X':
-	case 'x':		/* Export function */
+        case KEY_GENERIC_EXPORT:
           erase_status_bar ();
           io_export_bar ();
           while ((ch = wgetch (win[STA].p)) != 'q')
@@ -415,11 +414,9 @@ main (int argc, char **argv)
 	  wins_update ();
 	  break;
 
-        case KEY_RIGHT:
-	case ('L'):
-	case ('l'):
-	case CTRL ('L'):
-	  if (wins_slctd () == CAL || ch == CTRL ('L'))
+        case KEY_GENERIC_NEXT_DAY:
+        case KEY_CAL_NEXT_DAY:
+	  if (wins_slctd () == CAL || key == KEY_GENERIC_NEXT_DAY)
 	    {
 	      do_storage = true;
 	      day_changed = true;
@@ -427,11 +424,9 @@ main (int argc, char **argv)
 	    }
 	  break;
 
-        case KEY_LEFT:
-	case ('H'):
-	case ('h'):
-	case CTRL ('H'):
-	  if (wins_slctd () == CAL || ch == CTRL ('H'))
+        case KEY_GENERIC_PREV_DAY:
+        case KEY_CAL_PREV_DAY:
+	  if (wins_slctd () == CAL || key == KEY_GENERIC_PREV_DAY)
 	    {
 	      do_storage = true;
 	      day_changed = true;
@@ -439,60 +434,62 @@ main (int argc, char **argv)
 	    }
 	  break;
 
-        case KEY_UP:
-	case ('K'):
-	case ('k'):
-	case CTRL ('K'):
-	  if (wins_slctd () == CAL || ch == CTRL ('K'))
+        case KEY_GENERIC_PREV_WEEK:
+        case KEY_CAL_PREV_WEEK:
+	  if (wins_slctd () == CAL || key == KEY_GENERIC_PREV_WEEK)
 	    {
 	      do_storage = true;
 	      day_changed = true;
 	      calendar_move (UP);
 	    }
-	  else
-	    {
-	      if ((wins_slctd () == APP) && (apoint_hilt () > 1))
-		{
-		  apoint_hilt_decrease ();
-		  apoint_scroll_pad_up (inday.nb_events);
-		}
-	      else if ((wins_slctd () == TOD) && (todo_hilt () > 1))
-		{
-		  todo_hilt_decrease ();
-		  if (todo_hilt_pos () < 0)
-		    todo_first_decrease ();
-		}
-	    }
-	  break;
+          break;
 
-        case KEY_DOWN:
-	case ('J'):
-	case ('j'):
-	case CTRL ('J'):
-	  if (wins_slctd () == CAL || ch == CTRL ('J'))
+        case KEY_GENERIC_NEXT_WEEK:
+        case KEY_CAL_NEXT_WEEK:
+	  if (wins_slctd () == CAL || key == KEY_GENERIC_NEXT_WEEK)
 	    {
 	      do_storage = true;
 	      day_changed = true;
 	      calendar_move (DOWN);
 	    }
-	  else
-	    {
-	      if ((wins_slctd () == APP) &&
-		  (apoint_hilt () < inday.nb_events + inday.nb_apoints))
-		{
-		  apoint_hilt_increase ();
-		  apoint_scroll_pad_down (inday.nb_events, win[APP].h);
-		}
-	      if ((wins_slctd () == TOD) && (todo_hilt () < todo_nb ()))
-		{
-		  todo_hilt_increase ();
-		  if (todo_hilt_pos () == win[TOD].h - 4)
-		    todo_first_increase ();
-		}
-	    }
+          break;
+
+        case KEY_APT_MOVE_UP:
+          if ((wins_slctd () == APP) && (apoint_hilt () > 1))
+            {
+              apoint_hilt_decrease ();
+              apoint_scroll_pad_up (inday.nb_events);
+            }
+          break;
+
+        case KEY_APT_MOVE_DOWN:
+          if ((wins_slctd () == APP) &&
+              (apoint_hilt () < inday.nb_events + inday.nb_apoints))
+            {
+              apoint_hilt_increase ();
+              apoint_scroll_pad_down (inday.nb_events, win[APP].h);
+            }
+          break;
+          
+        case KEY_TODO_MOVE_UP:
+          if ((wins_slctd () == TOD) && (todo_hilt () > 1))
+            {
+              todo_hilt_decrease ();
+              if (todo_hilt_pos () < 0)
+                todo_first_decrease ();
+            }
+	  break;
+
+        case KEY_TODO_MOVE_DOWN:
+          if ((wins_slctd () == TOD) && (todo_hilt () < todo_nb ()))
+            {
+              todo_hilt_increase ();
+              if (todo_hilt_pos () == win[TOD].h - 4)
+                todo_first_increase ();
+            }
 	  break;
 
-        case '0':
+        case KEY_CAL_START_OF_WEEK:
           if (wins_slctd () == CAL)
 	    {
 	      do_storage = true;
@@ -501,7 +498,7 @@ main (int argc, char **argv)
 	    }
           break;
 
-        case '$':
+        case KEY_CAL_END_OF_WEEK:
           if (wins_slctd () == CAL)
 	    {
 	      do_storage = true;
@@ -510,8 +507,7 @@ main (int argc, char **argv)
 	    }
           break;
           
-	case ('Q'):		/* Quit calcurse :( */
-	case ('q'):
+        case KEY_GENERIC_QUIT:          
 	  if (conf.auto_save)
 	    io_save_cal (IO_MODE_INTERACTIVE, &conf);
 
diff --git a/src/custom.c b/src/custom.c
index e90439d..8afd913 100755
--- a/src/custom.c
+++ b/src/custom.c
@@ -1,4 +1,4 @@
-/*	$calcurse: custom.c,v 1.23 2008/09/21 08:06:43 culot Exp $	*/
+/*	$calcurse: custom.c,v 1.24 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -227,7 +227,7 @@ custom_load_conf (conf_t *conf, int background)
       doupdate ();
       wgetch (win[STA].p);
     }
-  var = 0;
+  var = CUSTOM_CONF_NOVARIABLE;
   pthread_mutex_lock (&nbar->mutex);
   for (;;)
     {
diff --git a/src/htable.h b/src/htable.h
index 31e9d2f..7ceab4c 100644
--- a/src/htable.h
+++ b/src/htable.h
@@ -1,4 +1,4 @@
-/*	$Id: htable.h,v 1.1 2008/11/08 19:05:15 culot Exp $	*/
+/*	$calcurse: htable.h,v 1.2 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Copyright (c) 2008 Frederic Culot <frederic@culot.org>
diff --git a/src/io.c b/src/io.c
index 243128d..b94ef6a 100755
--- a/src/io.c
+++ b/src/io.c
@@ -1,4 +1,4 @@
-/*	$calcurse: io.c,v 1.40 2008/09/29 06:27:53 culot Exp $	*/
+/*	$calcurse: io.c,v 1.41 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -31,6 +31,7 @@
 #include <math.h>
 #include <unistd.h>
 #include <errno.h>
+#include <ctype.h>
 
 #include "i18n.h"
 #include "utils.h"
@@ -39,6 +40,8 @@
 #include "event.h"
 #include "apoint.h"
 #include "recur.h"
+#include "keys.h"
+#include "htable.h"
 #include "io.h"
 
 #define ICALDATEFMT      "%Y%m%d"
@@ -77,6 +80,12 @@ typedef struct {
   unsigned      count;
 } ical_rpt_t;
 
+struct ht_keybindings_s {
+  char *label;
+  keys_e key;
+  HTABLE_ENTRY (ht_keybindings_s);
+};
+
 /* Type definition for callbacks to multiple-mode export functions. */
 typedef void (*cb_export_t)(FILE *);
 typedef void (*cb_dump_t)(FILE *, long, long, char *);
@@ -647,6 +656,7 @@ io_init (char *cfile, char *datadir)
       snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH_NAME, home);
       snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR_NAME, home);
       snprintf (path_apts, BUFSIZ, "%s/" APTS_PATH_NAME, home);
+      snprintf (path_keys, BUFSIZ, "%s/" KEYS_PATH_NAME, home);      
     }
   else
     {
@@ -658,6 +668,7 @@ io_init (char *cfile, char *datadir)
       snprintf (path_dir, BUFSIZ, "%s/" DIR_NAME, home);
       snprintf (path_todo, BUFSIZ, "%s/" TODO_PATH, home);
       snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH, home);
+      snprintf (path_keys, BUFSIZ, "%s/" KEYS_PATH, home);      
       snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR, home);
       if (cfile == NULL)
         {
@@ -1159,6 +1170,115 @@ io_load_todo (void)
   todo_set_nb (nb_tod);
 }
 
+static void
+load_keys_ht_getkey (struct ht_keybindings_s *data, char **key, int *len)
+{
+  *key = data->label;
+  *len = strlen (data->label);
+}
+
+static int
+load_keys_ht_compare (struct ht_keybindings_s *data1,
+                      struct ht_keybindings_s *data2)
+{
+  const int KEYLEN = strlen (data1->label);
+
+  if (strlen (data2->label) == KEYLEN
+      && !memcmp (data1->label, data2->label, KEYLEN))
+    return 0;
+  else
+    return 1;
+}
+
+static int
+key_to_ascii (char *key)
+{
+  const string_t CONTROL_KEY = STRING_BUILD ("CTRL-");
+  
+  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
+        return 0;
+    }
+}
+
+/*
+ * Load user-definable keys from file.
+ * A hash table is used to speed up loading process in avoiding string
+ * comparisons.
+ */
+void
+io_load_keys (void)
+{
+  struct ht_keybindings_s keys[NOKEYS];
+  FILE *keyfp;
+  char buf[BUFSIZ];
+  int i;
+
+#define HSIZE 256
+  HTABLE_HEAD (ht_keybindings, HSIZE, ht_keybindings_s) ht_keys =
+    HTABLE_INITIALIZER (&ht_keys);
+  
+  HTABLE_GENERATE (ht_keybindings, ht_keybindings_s, load_keys_ht_getkey,
+                   load_keys_ht_compare);
+
+  for (i = 0; i < NOKEYS; i++)
+    {
+      keys[i].key = (keys_e)i;
+      keys[i].label = keys_get_label ((keys_e)i);
+      HTABLE_INSERT (ht_keybindings, &ht_keys, &keys[i]);
+    }
+
+  keyfp = fopen (path_keys, "r");
+  while (fgets (buf, BUFSIZ, keyfp) != NULL)
+    {
+      char key_label[BUFSIZ], *p;
+      struct ht_keybindings_s *ht_elm, ht_entry;
+      const int AWAITED = 1;
+
+      for (p = buf; isblank ((int)*p); p++)
+        ;
+      if (p != buf)
+        memmove (buf, p, strlen (p));
+      if (buf[0] == '#')
+        continue;
+      
+      if (sscanf (buf, "%s", key_label) != AWAITED)
+        continue;
+      ht_entry.label = key_label;
+      p = buf + strlen (key_label) + 1;      
+      ht_elm = HTABLE_LOOKUP (ht_keybindings, &ht_keys, &ht_entry);
+      for (;;)
+        {
+          char key_ch[BUFSIZ], tmpbuf[BUFSIZ];
+
+          while (*p == ' ')
+            p++;
+          strncpy (tmpbuf, p, BUFSIZ);
+          if (sscanf (tmpbuf, "%s", key_ch) == AWAITED)
+            {
+              int ch;
+              char *unknown_key = _("Error reading key: %s");
+              
+              ch = key_to_ascii (key_ch);
+              p += strlen (key_ch) + 1;              
+              if (ch == 0)
+                ERROR_MSG (unknown_key);
+              else
+                keys_assign_binding (ch, ht_elm->key);
+            }
+          else
+            break;
+        }
+    }
+  fclose (keyfp);
+#undef HSIZE
+}
+
 static void
 check_directory (char *dir, int *missing)
 {
@@ -1218,7 +1338,9 @@ io_check_data_files (void)
   check_file (path_todo, &missing);
   check_file (path_apts, &missing);
   check_file (path_conf, &missing);
-  return (missing);
+  check_file (path_keys, &missing);
+  
+  return missing;
 }
 
 /* Draw the startup screen */
diff --git a/src/io.h b/src/io.h
index 16b896b..a710f0d 100755
--- a/src/io.h
+++ b/src/io.h
@@ -1,4 +1,4 @@
-/*	$calcurse: io.h,v 1.15 2008/09/21 08:06:43 culot Exp $	*/
+/*	$calcurse: io.h,v 1.16 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -54,6 +54,7 @@ void io_extract_data (char *, const char *, int);
 void io_save_cal (io_mode_t, conf_t *);
 void io_load_app (void);
 void io_load_todo (void);
+void io_load_keys (void);
 int  io_check_data_files (void);
 void io_startup_screen (bool, int);
 void io_export_data (io_mode_t, export_type_t, conf_t *);
diff --git a/src/keys.c b/src/keys.c
index f024be9..2c0fc98 100755
--- a/src/keys.c
+++ b/src/keys.c
@@ -1,4 +1,4 @@
-/*	$calcurse: keys.c,v 1.1 2008/11/08 19:05:15 culot Exp $	*/
+/*	$calcurse: keys.c,v 1.2 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -26,9 +26,21 @@
 
 #include "i18n.h"
 #include "utils.h"
+#include "htable.h"
 #include "keys.h"
 
-const char *keylabel[NOKEYS] = {
+#define HTKEYSIZE 512
+
+struct keys_s {
+  int    key;
+  keys_e action;
+  HTABLE_ENTRY (keys_s);
+};
+
+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",
@@ -85,10 +97,65 @@ const char *keylabel[NOKEYS] = {
   "config-notify-menu"
 };
 
-char *keys_get_label (keys_e key)
+static void
+ht_getkey (struct keys_s *data, char **key, int *len)
+{
+  *key = (char *)&data->key;
+  *len = sizeof (int);
+}
+
+static int
+ht_compare (struct keys_s *data1, struct keys_s *data2)
+{
+  if (data1->key == data2->key)
+    return 0;
+  else
+    return 1;
+}
+
+HTABLE_GENERATE (ht_keys, keys_s, ht_getkey, ht_compare);
+
+char *
+keys_get_label (keys_e key)
 {
   EXIT_IF (key < 0 || key > NOKEYS,
            _("FATAL ERROR in keys_get_label: key value out of bounds"));
 
-  return keylabel (key);
+  return keylabel[key];
+}
+
+int
+keys_get_key (int pressed)
+{
+  struct keys_s *key, find;
+
+  find.key = pressed;
+  key = HTABLE_LOOKUP (ht_keys, &ht_keys_action, &find);
+
+  if (key)
+    return (int)key->action;
+  else
+    return -1;
+}
+
+void
+keys_assign_binding (int key, keys_e action)
+{
+  struct keys_s *binding;
+
+  binding = malloc (sizeof (struct keys_s));
+  binding->key = key;
+  binding->action = action;
+  HTABLE_INSERT (ht_keys, &ht_keys_action, binding);
+}
+
+void
+key_remove_binding (int key, keys_e action)
+{
+  struct keys_s find, *removed;
+
+  find.key = key;
+  find.action = action;
+  removed = HTABLE_REMOVE (ht_keys, &ht_keys_action, &find);
+  mem_free (removed);
 }
diff --git a/src/keys.h b/src/keys.h
index 4551070..c16d3e1 100755
--- a/src/keys.h
+++ b/src/keys.h
@@ -1,4 +1,4 @@
-/*	$calcurse: keys.h,v 1.1 2008/11/08 19:05:15 culot Exp $	*/
+/*	$calcurse: keys.h,v 1.2 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -41,7 +41,7 @@ typedef enum
     KEY_GENERIC_REDRAW,
     KEY_GENERIC_ADD_APPT,
     KEY_GENERIC_ADD_TODO,
-    KEY_GENERIC_NEXT_ADY,
+    KEY_GENERIC_NEXT_DAY,
     KEY_GENERIC_PREV_DAY,
     KEY_GENERIC_NEXT_WEEK,
     KEY_GENERIC_PREV_WEEK,
@@ -74,7 +74,7 @@ typedef enum
     KEY_TODO_MOVE_UP,
     KEY_TODO_MOVE_DOWN,
     KEY_TODO_EDIT_NOTE,
-    KEY_TODO_VIEW_BOTE,
+    KEY_TODO_VIEW_NOTE,
 
     KEY_CONFIG_QUIT,
     KEY_CONFIG_GENERAL_MENU,
@@ -86,6 +86,9 @@ typedef enum
   }
 keys_e;
 
-char *keys_get_label (keys_e);
+char   *keys_get_label (keys_e);
+int     keys_get_key (int);
+void    keys_assign_binding (int, keys_e);
+void    key_remove_binding (int, keys_e);
 
 #endif /* CALCURSE_KEYS_H */
diff --git a/src/todo.c b/src/todo.c
index 9b3d786..54fd059 100755
--- a/src/todo.c
+++ b/src/todo.c
@@ -1,4 +1,4 @@
-/*	$calcurse: todo.c,v 1.22 2008/04/19 21:05:15 culot Exp $	*/
+/*	$calcurse: todo.c,v 1.23 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -30,6 +30,7 @@
 
 #include "utils.h"
 #include "custom.h"
+#include "keys.h"
 #include "i18n.h"
 #include "todo.h"
 
@@ -347,11 +348,11 @@ todo_chg_priority (int action)
     strncpy (backup_note, backup->note, NOTESIZ + 1);
   else
     backup_note[0] = '\0';
-  if (action == '+')
+  if (action == KEY_TODO_RAISE_PRIORITY)
     {
       (backup_id > 1) ? backup_id-- : do_chg--;
     }
-  else if (action == '-')
+  else if (action == KEY_TODO_LOWER_PRIORITY)
     {
       (backup_id < 9) ? backup_id++ : do_chg--;
     }
diff --git a/src/utils.h b/src/utils.h
index c6d483c..ceaf430 100755
--- a/src/utils.h
+++ b/src/utils.h
@@ -1,4 +1,4 @@
-/*	$calcurse: utils.h,v 1.36 2008/09/23 17:31:57 culot Exp $	*/
+/*	$calcurse: utils.h,v 1.37 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -27,7 +27,10 @@
 #ifndef CALCURSE_UTILS_H
 #define CALCURSE_UTILS_H
 
+#include <stdlib.h>
+
 #include "calendar.h"
+#include "vars.h"
 
 #define MAX(x,y) 	((x)>(y)?(x):(y))
 #define MIN(x,y) 	((x)<(y)?(x):(y))
diff --git a/src/vars.c b/src/vars.c
index 8a54628..4e838ee 100755
--- a/src/vars.c
+++ b/src/vars.c
@@ -1,4 +1,4 @@
-/*	$calcurse: vars.c,v 1.9 2008/09/20 12:47:06 culot Exp $	*/
+/*	$calcurse: vars.c,v 1.10 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -87,6 +87,7 @@ char path_todo[] = "";
 char path_apts[] = "";
 char path_conf[] = "";
 char path_notes[] = "";
+char path_keys[] = "";
 
 /* Variable to handle pads. */
 struct pad_s *apad;
diff --git a/src/vars.h b/src/vars.h
index c48819c..1527f81 100755
--- a/src/vars.h
+++ b/src/vars.h
@@ -1,4 +1,4 @@
-/*	$calcurse: vars.h,v 1.24 2008/09/20 12:47:06 culot Exp $	*/
+/*	$calcurse: vars.h,v 1.25 2008/11/09 20:10:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -35,10 +35,12 @@
 #define TODO_PATH_NAME   "todo"
 #define APTS_PATH_NAME   "apts"
 #define CONF_PATH_NAME   "conf"
+#define KEYS_PATH_NAME   "keys"
 #define NOTES_DIR_NAME   "notes/"
 #define TODO_PATH        DIR_NAME TODO_PATH_NAME
 #define APTS_PATH        DIR_NAME APTS_PATH_NAME
 #define CONF_PATH        DIR_NAME CONF_PATH_NAME
+#define KEYS_PATH        DIR_NAME KEYS_PATH_NAME
 #define NOTES_DIR        DIR_NAME NOTES_DIR_NAME
 
 #define CTRL(x)         ((x) & 0x1f)
@@ -116,6 +118,7 @@ extern char           path_dir[BUFSIZ];
 extern char           path_todo[BUFSIZ];
 extern char           path_apts[BUFSIZ];
 extern char           path_conf[BUFSIZ];
+extern char           path_keys[BUFSIZ];
 extern char           path_notes[BUFSIZ];
 extern struct pad_s  *apad;
 extern struct nbar_s *nbar;
-- 
cgit v1.2.3-70-g09d2