From 639058740a44c6380258e0152f9916af1e53bb27 Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Sun, 7 Dec 2008 09:20:38 +0000
Subject: Checks added while loading key bindings configuration.

---
 src/apoint.c   |   8 +-
 src/args.c     |   9 +-
 src/calcurse.c |  16 +--
 src/calendar.c |   4 +-
 src/custom.c   |  18 ++--
 src/day.c      |  22 ++---
 src/io.c       | 306 ++++++++++++++++++++++++++++++++++++++-------------------
 src/io.h       |  48 ++++-----
 src/keys.c     |  29 +++++-
 src/notify.c   |   4 +-
 src/recur.c    |  14 +--
 src/todo.c     |   8 +-
 src/utils.c    |   8 +-
 13 files changed, 311 insertions(+), 183 deletions(-)

(limited to 'src')

diff --git a/src/apoint.c b/src/apoint.c
index 3f846ff..6686572 100755
--- a/src/apoint.c
+++ b/src/apoint.c
@@ -1,4 +1,4 @@
-/*	$calcurse: apoint.c,v 1.24 2008/11/16 17:42:53 culot Exp $	*/
+/*	$calcurse: apoint.c,v 1.25 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -151,7 +151,7 @@ apoint_add (void)
 	  else if (check_time (item_time) != 1)
 	    {
 	      status_mesg (format_message_1, enter_str);
-	      keys_getch (win[STA].p);
+	      (void)wgetch (win[STA].p);
 	    }
 	  else
 	    sscanf (item_time, "%u:%u", &heures, &minutes);
@@ -175,7 +175,7 @@ apoint_add (void)
 	  else if (check_time (item_time) == 0)
 	    {
 	      status_mesg (format_message_2, enter_str);
-	      keys_getch (win[STA].p);
+	      (void)wgetch (win[STA].p);
 	    }
 	  else
 	    {
@@ -242,7 +242,7 @@ apoint_delete (conf_t *conf, unsigned *nb_events, unsigned *nb_apoints)
   if (conf->confirm_delete)
     {
       status_mesg (del_app_str, choices);
-      answer = keys_getch (win[STA].p);
+      answer = wgetch (win[STA].p);
       if ((answer == 'y') && (nb_items != 0))
 	go_for_deletion = true;
       else
diff --git a/src/args.c b/src/args.c
index 4f676d1..812c572 100755
--- a/src/args.c
+++ b/src/args.c
@@ -1,4 +1,4 @@
-/*	$calcurse: args.c,v 1.40 2008/09/21 08:06:43 culot Exp $	*/
+/*	$calcurse: args.c,v 1.41 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -765,9 +765,8 @@ parse_args (int argc, char **argv, conf_t *conf)
 	      vars_init (conf);              
               custom_load_conf (conf, 0);
               io_load_todo ();
-              io_import_data (IO_MODE_NONINTERACTIVE, IO_IMPORT_ICAL, conf,
-                              ifile);
-              io_save_cal (IO_MODE_NONINTERACTIVE, conf);
+              io_import_data (IO_IMPORT_ICAL, conf, ifile);
+              io_save_cal (conf);
               non_interactive = 1;
             }
 	  if (xflag)
@@ -775,7 +774,7 @@ parse_args (int argc, char **argv, conf_t *conf)
 	      notify_init_vars ();
 	      custom_load_conf (conf, 0);
               io_load_todo ();
-	      io_export_data (IO_MODE_NONINTERACTIVE, xfmt, conf);
+	      io_export_data (xfmt, conf);
 	      non_interactive = 1;
 	      return (non_interactive);
 	    }
diff --git a/src/calcurse.c b/src/calcurse.c
index c327af2..2257d3c 100755
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calcurse.c,v 1.71 2008/11/23 20:38:56 culot Exp $	*/
+/*	$calcurse: calcurse.c,v 1.72 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -147,7 +147,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_keys (conf.pager);
   io_load_todo ();
   io_load_app ();
   wins_reinit ();
@@ -375,29 +375,29 @@ main (int argc, char **argv)
 	  break;
 
         case KEY_GENERIC_SAVE:
-	  io_save_cal (IO_MODE_INTERACTIVE, &conf);
+	  io_save_cal (&conf);
 	  break;
 
         case KEY_GENERIC_IMPORT:
           erase_status_bar ();
-          io_import_data (IO_MODE_INTERACTIVE, IO_IMPORT_ICAL, &conf, NULL);
+          io_import_data (IO_IMPORT_ICAL, &conf, NULL);
           do_storage = true;
           break;
           
         case KEY_GENERIC_EXPORT:
           erase_status_bar ();
           io_export_bar ();
-          while ((key = keys_getch (win[STA].p)) != 'q')
+          while ((key = wgetch (win[STA].p)) != 'q')
 	    {
 	      switch (key)
 		{
 		case 'I':
 		case 'i':
-                  io_export_data (IO_MODE_INTERACTIVE, IO_EXPORT_ICAL, &conf);
+                  io_export_data (IO_EXPORT_ICAL, &conf);
 		  break;
 		case 'P':
 		case 'p':
-                  io_export_data (IO_MODE_INTERACTIVE, IO_EXPORT_PCAL, &conf);
+                  io_export_data (IO_EXPORT_PCAL, &conf);
 		  break;
 		}
 	      wins_reset ();
@@ -492,7 +492,7 @@ main (int argc, char **argv)
           
         case KEY_GENERIC_QUIT:          
 	  if (conf.auto_save)
-	    io_save_cal (IO_MODE_INTERACTIVE, &conf);
+	    io_save_cal (&conf);
 
 	  if (conf.confirm_quit)
 	    {
diff --git a/src/calendar.c b/src/calendar.c
index ca1ec2f..31403d1 100755
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calendar.c,v 1.18 2008/11/16 17:42:53 culot Exp $	*/
+/*	$calcurse: calendar.c,v 1.19 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -388,7 +388,7 @@ calendar_change_day (int datefmt)
 	  if (wrong_day)
 	    {
 	      status_mesg (mesg_line1, mesg_line2);
-	      keys_getch (win[STA].p);
+	      (void)wgetch (win[STA].p);
 	    }
 	}
     }
diff --git a/src/custom.c b/src/custom.c
index a1defe5..1c3217e 100755
--- a/src/custom.c
+++ b/src/custom.c
@@ -1,4 +1,4 @@
-/*	$calcurse: custom.c,v 1.27 2008/11/25 20:48:58 culot Exp $	*/
+/*	$calcurse: custom.c,v 1.28 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -396,11 +396,11 @@ layout_config (void)
     _(" [1]AT    [2]AC    [3]TA    [4]CA    [5]TA    [6]TC    [7]AT    [8]CT");
 
   status_mesg (layout_mesg, choice_mesg);
-  keys_getch (win[STA].p);
+  (void)wgetch (win[STA].p);
   status_mesg (layout_up_mesg, layout_down_mesg);
   wnoutrefresh (win[STA].p);
   doupdate ();
-  while ((ch = keys_getch (win[STA].p)) != 'q')
+  while ((ch = wgetch (win[STA].p)) != 'q')
     {
       if (ch <= '8' && ch >= '1')
 	{
@@ -585,7 +585,7 @@ custom_color_config (void)
   display_color_config (&conf_win, &mark_fore, &mark_back, cursor,
 			need_reset, theme_changed);
 
-  while ((ch = keys_getch (win[STA].p)) != 'q')
+  while ((ch = wgetch (win[STA].p)) != 'q')
     {
       need_reset = 0;
       theme_changed = 0;
@@ -611,28 +611,28 @@ custom_color_config (void)
 	    mark_fore = cursor;
 	  break;
 
-	case 258:
+	case KEY_DOWN:
 	case 'J':
 	case 'j':
 	  if (cursor < SIZE - 1)
 	    ++cursor;
 	  break;
 
-	case 259:
+	case KEY_UP:
 	case 'K':
 	case 'k':
 	  if (cursor > 0)
 	    --cursor;
 	  break;
 
-	case 260:
+	case KEY_LEFT:
 	case 'H':
 	case 'h':
 	  if (cursor > NBUSERCOLORS)
 	    cursor -= (NBUSERCOLORS + 1);
 	  break;
 
-	case 261:
+	case KEY_RIGHT:
 	case 'L':
 	case 'l':
 	  if (cursor <= NBUSERCOLORS)
@@ -816,7 +816,7 @@ custom_general_config (conf_t *conf)
   cwin.total_lines = print_general_options (cwin.pad.p, conf);
   wins_scrollwin_display (&cwin);
 
-  while ((ch = keys_getch (win[STA].p)) != 'q')
+  while ((ch = wgetch (win[STA].p)) != 'q')
     {
       switch (ch)
 	{
diff --git a/src/day.c b/src/day.c
index c8ca3cb..640f69f 100755
--- a/src/day.c
+++ b/src/day.c
@@ -1,4 +1,4 @@
-/*	$calcurse: day.c,v 1.38 2008/11/16 17:42:53 culot Exp $	*/
+/*	$calcurse: day.c,v 1.39 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -527,7 +527,7 @@ day_edit_time (long time)
       if (check_time (timestr) != 1 || strlen (timestr) == 0)
 	{
 	  status_mesg (fmt_msg, enter_str);
-	  keys_getch (win[STA].p);
+	  (void)wgetch (win[STA].p);
 	}
       else
 	return (timestr);
@@ -559,7 +559,7 @@ update_start_time (long *start, long *dur)
       else
 	{
 	  status_mesg (msg_wrong_time, msg_enter);
-	  keys_getch (win[STA].p);
+	  (void)wgetch (win[STA].p);
 	  valid_date = 0;
 	}
     }
@@ -642,7 +642,7 @@ update_rept (struct rpt_s **rpt, const long start, conf_t *conf)
 	  if (newfreq == 0)
 	    {
 	      status_mesg (msg_wrong_freq, msg_enter);
-	      keys_getch (win[STA].p);
+	      (void)wgetch (win[STA].p);
 	    }
 	}
     }
@@ -685,7 +685,7 @@ update_rept (struct rpt_s **rpt, const long start, conf_t *conf)
 	      if (newuntil < start)
 		{
 		  status_mesg (msg_wrong_time, msg_enter);
-		  keys_getch (win[STA].p);
+		  (void)wgetch (win[STA].p);
 		  date_entered = 0;
 		}
 	      else
@@ -696,7 +696,7 @@ update_rept (struct rpt_s **rpt, const long start, conf_t *conf)
 	      snprintf (outstr, BUFSIZ, msg_fmts,
 			DATEFMT_DESC (conf->input_datefmt));
 	      status_mesg (msg_wrong_date, _(outstr));
-	      keys_getch (win[STA].p);
+	      (void)wgetch (win[STA].p);
 	      date_entered = 0;
 	    }
 	}
@@ -737,7 +737,7 @@ day_edit_item (conf_t *conf)
       re = recur_get_event (date, day_item_nb (date, item_num, RECUR_EVNT));
       status_mesg (_("Edit: (1)Description or (2)Repetition?"), "[1/2] ");
       while (ch != '1' && ch != '2' && ch != KEY_GENERIC_ESCAPE)
-	ch = keys_getch (win[STA].p);
+	ch = wgetch (win[STA].p);
       switch (ch)
 	{
 	case '1':
@@ -760,7 +760,7 @@ day_edit_item (conf_t *conf)
 		     "(3)Description or (4)Repetition?"), "[1/2/3/4] ");
       while (ch != STRT && ch != END && ch != DESC &&
 	     ch != REPT && ch != KEY_GENERIC_ESCAPE)
-	ch = keys_getch (win[STA].p);
+	ch = wgetch (win[STA].p);
       switch (ch)
 	{
 	case STRT:
@@ -784,7 +784,7 @@ day_edit_item (conf_t *conf)
       status_mesg (_("Edit: (1)Start time, (2)End time "
 		     "or (3)Description?"), "[1/2/3] ");
       while (ch != STRT && ch != END && ch != DESC && ch != KEY_GENERIC_ESCAPE)
-	ch = keys_getch (win[STA].p);
+	ch = wgetch (win[STA].p);
       switch (ch)
 	{
 	case STRT:
@@ -833,7 +833,7 @@ day_erase_item (long date, int item_number, erase_flag_e flag)
       while (ans != 'i' && ans != 'n')
 	{
 	  status_mesg (note_warning, note_choice);
-	  ans = keys_getch (win[STA].p);
+	  ans = wgetch (win[STA].p);
 	}
       if (ans == 'i')
 	flag = ERASE_FORCE;
@@ -855,7 +855,7 @@ day_erase_item (long date, int item_number, erase_flag_e flag)
       while ((ch != 'a') && (ch != 'o') && (ch != KEY_GENERIC_ESCAPE))
 	{
 	  status_mesg (erase_warning, erase_choice);
-	  ch = keys_getch (win[STA].p);
+	  ch = wgetch (win[STA].p);
 	}
       if (ch == 'a')
 	{
diff --git a/src/io.c b/src/io.c
index 9be3d9b..cc56b97 100755
--- a/src/io.c
+++ b/src/io.c
@@ -1,4 +1,4 @@
-/*	$calcurse: io.c,v 1.44 2008/12/03 19:31:03 culot Exp $	*/
+/*	$calcurse: io.c,v 1.45 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -168,18 +168,15 @@ progress_bar (progress_bar_t type, int progress)
   switch (type)
     {
     case PROGRESS_BAR_SAVE:
-      EXIT_IF (progress < 0 || progress > PROGRESS_BAR_KEYS,
-               error_msg);
+      EXIT_IF (progress < 0 || progress > PROGRESS_BAR_KEYS, error_msg);
       status_mesg (mesg_sav, file[progress]);
       break;
     case PROGRESS_BAR_LOAD:
-      EXIT_IF (progress < 0 || progress > PROGRESS_BAR_KEYS,
-               error_msg);
+      EXIT_IF (progress < 0 || progress > PROGRESS_BAR_KEYS, error_msg);
       status_mesg (mesg_load, file[progress]);
       break;
     case PROGRESS_BAR_EXPORT:
-      EXIT_IF (progress < 0 || progress > PROGRESS_BAR_TODO,
-               error_msg);
+      EXIT_IF (progress < 0 || progress > PROGRESS_BAR_EXPORT_TODO, error_msg);
       status_mesg (mesg_export, data[progress]);
       break;
     }
@@ -233,7 +230,7 @@ get_export_stream (export_type_t type)
       if (stream == NULL)
 	{
 	  status_mesg (wrong_name, press_enter);
-	  keys_getch (win[STA].p);
+	  (void)wgetch (win[STA].p);
 	}
     }
   free (stream_name);
@@ -751,7 +748,7 @@ io_extract_data (char *dst_data, const char *org, int len)
 
 /* Save the calendar data */
 void
-io_save_cal (io_mode_t mode, conf_t *conf)
+io_save_cal (conf_t *conf)
 {
   FILE *data_file;
   struct event_s *k;
@@ -773,7 +770,7 @@ io_save_cal (io_mode_t mode, conf_t *conf)
   char *enter = _("Press [ENTER] to continue");
   bool show_bar = false;
 
-  if (mode == IO_MODE_INTERACTIVE && !conf->skip_progress_bar)
+  if (ui_mode == UI_CURSES && !conf->skip_progress_bar)
     show_bar = true;
 
   /* Save the user configuration. */
@@ -833,7 +830,7 @@ io_save_cal (io_mode_t mode, conf_t *conf)
       fprintf (data_file, "layout=\n");
       fprintf (data_file, "%d\n", wins_layout ());
 
-      if (mode == IO_MODE_INTERACTIVE)
+      if (ui_mode == UI_CURSES)
         pthread_mutex_lock (&nbar->mutex);
       fprintf (data_file,
 	       "\n# If this option is set to yes, "
@@ -875,7 +872,7 @@ io_save_cal (io_mode_t mode, conf_t *conf)
       fprintf (data_file, "input_datefmt=\n");
       fprintf (data_file, "%d\n", conf->input_datefmt);
 
-      if (mode == IO_MODE_INTERACTIVE)
+      if (ui_mode == UI_CURSES)
         pthread_mutex_unlock (&nbar->mutex);
 
       fclose (data_file);
@@ -913,11 +910,11 @@ io_save_cal (io_mode_t mode, conf_t *conf)
     {
       recur_save_data (data_file);
 
-      if (mode == IO_MODE_INTERACTIVE)
+      if (ui_mode == UI_CURSES)
         pthread_mutex_lock (&(alist_p->mutex));
       for (j = alist_p->root; j != 0; j = j->next)
 	apoint_write (j, data_file);
-      if (mode == IO_MODE_INTERACTIVE)
+      if (ui_mode == UI_CURSES)
         pthread_mutex_unlock (&(alist_p->mutex));
 
       for (k = eventlist; k != 0; k = k->next)
@@ -938,10 +935,10 @@ io_save_cal (io_mode_t mode, conf_t *conf)
     }
   
   /* Print a message telling data were saved */
-  if (mode == IO_MODE_INTERACTIVE && !conf->skip_system_dialogs)
+  if (ui_mode == UI_CURSES && !conf->skip_system_dialogs)
     {
       status_mesg (save_success, enter);
-      keys_getch (win[STA].p);
+      (void)wgetch (win[STA].p);
     }
 }
 
@@ -1155,7 +1152,7 @@ io_load_todo (void)
   if (data_file == NULL)
     {
       status_mesg (mesg_line1, mesg_line2);
-      keys_getch (win[STA].p);
+      (void)wgetch (win[STA].p);
     }
   for (;;)
     {
@@ -1232,15 +1229,19 @@ static int is_blank (int c)
  * Load user-definable keys from file.
  * A hash table is used to speed up loading process in avoiding string
  * comparisons.
+ * A log file is also built in case some errors were found in the key
+ * configuration file.
  */
 void
-io_load_keys (void)
+io_load_keys (char *pager)
 {
   struct ht_keybindings_s keys[NBKEYS];
   FILE *keyfp;
   char buf[BUFSIZ];
-  int i;
-
+  io_file_t *log;
+  int i, skipped, loaded, line;
+  const int MAX_ERRORS = 5;
+  
 #define HSIZE 256
   HTABLE_HEAD (ht_keybindings, HSIZE, ht_keybindings_s) ht_keys =
     HTABLE_INITIALIZER (&ht_keys);
@@ -1256,24 +1257,51 @@ io_load_keys (void)
     }
 
   keyfp = fopen (path_keys, "r");
+  EXIT_IF (keyfp == NULL,
+           _("FATAL ERROR in io_load_keys: could not find any key file."));
+  log = io_log_init ();
+  skipped = loaded = line = 0;
   while (fgets (buf, BUFSIZ, keyfp) != NULL)
     {
       char key_label[BUFSIZ], *p;
       struct ht_keybindings_s *ht_elm, ht_entry;
       const int AWAITED = 1;
+      int assigned;
 
+      line++;
+      if (skipped > MAX_ERRORS)
+        {
+          char *too_many =
+            _("\nToo many errors while reading configuration file!\n"
+              "Please backup your keys file, remove it from directory, "
+              "and launch calcurse again.\n");
+
+          io_log_print (log, line, too_many);
+          break;
+        }
       for (p = buf; is_blank ((int)*p); p++)
         ;
       if (p != buf)
         memmove (buf, p, strlen (p));
-      if (buf[0] == '#')
+      if (buf[0] == '#' || buf[0] == '\n')
         continue;
       
       if (sscanf (buf, "%s", key_label) != AWAITED)
-        continue;
+        {
+          skipped++;
+          io_log_print (log, line, _("Could not read key label"));
+          continue;
+        }
       ht_entry.label = key_label;
       p = buf + strlen (key_label) + 1;      
       ht_elm = HTABLE_LOOKUP (ht_keybindings, &ht_keys, &ht_entry);
+      if (!ht_elm)
+        {
+          skipped++;
+          io_log_print (log, line, _("Key label not recognized"));
+          continue;
+        }
+      assigned = 0;
       for (;;)
         {
           char key_ch[BUFSIZ], tmpbuf[BUFSIZ];
@@ -1283,26 +1311,58 @@ io_load_keys (void)
           strncpy (tmpbuf, p, BUFSIZ);
           if (sscanf (tmpbuf, "%s", key_ch) == AWAITED)
             {
-              int ch, used;
-              char *unknown_key = _("Error reading key: \"%s\"");
-              char *already_used =
-                _("\"%s\" assigned multiple times in keys file!");
-              
+              int ch;
+                    
               if ((ch = keys_str2int (key_ch)) < 0)
-                ERROR_MSG (unknown_key, key_ch);
+                {
+                  char unknown_key[BUFSIZ];
+
+                  skipped++;
+                  snprintf (unknown_key, BUFSIZ, _("Error reading key: \"%s\""),
+                            key_ch);
+                  io_log_print (log, line, unknown_key);
+                }
               else
                 {
-                  p += strlen (key_ch) + 1;              
+                  int used;
+                  
                   used = keys_assign_binding (ch, ht_elm->key);
                   if (used)
-                    ERROR_MSG (already_used, key_ch);
+                    {
+                      char already_assigned[BUFSIZ];
+
+                      skipped++;
+                      snprintf (already_assigned, BUFSIZ,
+                                _("\"%s\" assigned multiple times!"), key_ch);
+                      io_log_print (log, line, already_assigned);
+                    }
+                  else
+                    assigned++;
                 }
+              p += strlen (key_ch) + 1;
             }
           else
-            break;
+            {
+              if (assigned)
+                loaded++;
+              break;
+            }
         }
     }
   fclose (keyfp);
+  fclose (log->fd);
+  if (skipped > 0)
+    {
+      char *view_log =
+        _("There were some errors when loading keys file, see log file ?");
+      
+      io_log_display (log, view_log, pager);
+    }
+  io_log_free (log);
+  EXIT_IF (skipped > MAX_ERRORS,
+           _("Too many errors while reading keys file, aborting..."));
+  if (loaded < NBKEYS)
+    ERROR_MSG (_("Some actions do not have any associated key bindings!"));
 #undef HSIZE
 }
 
@@ -1388,18 +1448,18 @@ io_startup_screen (bool skip_dialogs, int no_data_file)
   if (no_data_file != 0)
     {
       status_mesg (welcome_mesg, enter);
-      keys_getch (win[STA].p);
+      (void)wgetch (win[STA].p);
     }
   else if (!skip_dialogs)
     {
       status_mesg (data_mesg, enter);
-      keys_getch (win[STA].p);
+      (void)wgetch (win[STA].p);
     }
 }
 
 /* Export calcurse data. */
 void
-io_export_data (io_mode_t mode, export_type_t type, conf_t *conf)
+io_export_data (export_type_t type, conf_t *conf)
 {
   FILE *stream;
   char *wrong_mode = _("FATAL ERROR in io_export_data: wrong export mode\n");
@@ -1412,12 +1472,12 @@ io_export_data (io_mode_t mode, export_type_t type, conf_t *conf)
       fputs (wrong_type, stderr);
       exit (EXIT_FAILURE);
     }
-  switch (mode)
+  switch (ui_mode)
     {
-    case IO_MODE_NONINTERACTIVE:
+    case UI_CMDLINE:
       stream = stdout;
       break;
-    case IO_MODE_INTERACTIVE:
+    case UI_CURSES:
       stream = get_export_stream (type);
       break;
     default:
@@ -1431,18 +1491,18 @@ io_export_data (io_mode_t mode, export_type_t type, conf_t *conf)
 
   cb_export_header[type] (stream);
 
-  if (!conf->skip_progress_bar && mode == IO_MODE_INTERACTIVE)
-    progress_bar (PROGRESS_BAR_EXPORT, 0);
+  if (!conf->skip_progress_bar && ui_mode == UI_CURSES)
+    progress_bar (PROGRESS_BAR_EXPORT, PROGRESS_BAR_EXPORT_EVENTS);
   cb_export_recur_events[type] (stream);
   cb_export_events[type] (stream);
 
-  if (!conf->skip_progress_bar && mode == IO_MODE_INTERACTIVE)
-    progress_bar (PROGRESS_BAR_EXPORT, 1);
+  if (!conf->skip_progress_bar && ui_mode == UI_CURSES)
+    progress_bar (PROGRESS_BAR_EXPORT, PROGRESS_BAR_EXPORT_APOINTS);
   cb_export_recur_apoints[type] (stream);
   cb_export_apoints[type] (stream);
 
-  if (!conf->skip_progress_bar && mode == IO_MODE_INTERACTIVE)
-    progress_bar (PROGRESS_BAR_EXPORT, 2);
+  if (!conf->skip_progress_bar && ui_mode == UI_CURSES)
+    progress_bar (PROGRESS_BAR_EXPORT, PROGRESS_BAR_EXPORT_TODO);
   cb_export_todo[type] (stream);
 
   cb_export_footer[type] (stream);
@@ -1450,10 +1510,10 @@ io_export_data (io_mode_t mode, export_type_t type, conf_t *conf)
   if (stream != stdout)
     fclose (stream);
 
-  if (!conf->skip_system_dialogs && mode == IO_MODE_INTERACTIVE)
+  if (!conf->skip_system_dialogs && ui_mode == UI_CURSES)
     {
       status_mesg (success, enter);
-      keys_getch (win[STA].p);
+      (void)wgetch (win[STA].p);
     }
 }
 
@@ -1500,8 +1560,9 @@ ical_log_init (FILE *log, float version)
     "|  * LINE is the line in the input stream at which this item begins |\n"
     "|  * DESCRIPTION indicates why the item could not be imported       |\n"
     "+-------------------------------------------------------------------+\n\n";
-    
-  fprintf (log, header, version);
+
+  if (log)
+    fprintf (log, header, version);
 }
 
 /*
@@ -1517,7 +1578,8 @@ ical_log (FILE *log, ical_types_e type, unsigned lineno, char *msg)
 
   RETURN_IF (type < 0 || type >= ICAL_TYPES,
              _("ERROR in ical_log: unknown ical type"));
-  fprintf (log, "%s [%d]: %s\n", typestr[type], lineno, msg);
+  if (log)
+    fprintf (log, "%s [%d]: %s\n", typestr[type], lineno, msg);
 }
 
 static void
@@ -2493,7 +2555,7 @@ get_import_stream (export_type_t type)
       if (stream == NULL)
 	{
 	  status_mesg (wrong_file, press_enter);
-	  keys_getch (win[STA].p);
+	  (void)wgetch (win[STA].p);
 	}
     }
   mem_free (stream_name);
@@ -2508,10 +2570,8 @@ get_import_stream (export_type_t type)
  * and is cleared at the end.
  */
 void
-io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
-                char *stream_name)
+io_import_data (import_type_t type, conf_t *conf, char *stream_name)
 {
-  const char *logprefix = "/tmp/calcurse_log.";
   const string_t vevent = STRING_BUILD ("BEGIN:VEVENT");
   const string_t vtodo = STRING_BUILD ("BEGIN:VTODO");
   char *proc_report = _("Import process report: %04d lines read ");
@@ -2519,8 +2579,9 @@ io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
     _("%d apps / %d events / %d todos / %d skipped ");
   char *lines_stats_interactive =
     _("%d apps / %d events / %d todos / %d skipped ([ENTER] to continue)");
-  char *logname, flogname[BUFSIZ], buf[BUFSIZ];
-  FILE *stream = NULL, *logfd;
+  char buf[BUFSIZ];
+  FILE *stream = NULL;
+  io_file_t *log;
   float ical_version;
   struct {
     unsigned events, apoints, todos, lines, skipped;
@@ -2528,15 +2589,15 @@ io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
 
   EXIT_IF (type < 0 || type >= IO_IMPORT_NBTYPES,
            _("FATAL ERROR in io_import_data: unknown import type"));
-  switch (mode)
+  switch (ui_mode)
     {
-    case IO_MODE_NONINTERACTIVE:
+    case UI_CMDLINE:
       stream = fopen (stream_name, "r");
       EXIT_IF (stream == NULL,
                _("FATAL ERROR: the input file cannot be accessed, "
                  "Aborting..."));
       break;
-    case IO_MODE_INTERACTIVE:
+    case UI_CURSES:
       stream = get_import_stream (type);
       break;
     default:
@@ -2553,15 +2614,14 @@ io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
              _("Warning: ical header malformed or wrong version number. "
                "Aborting..."));
 
-  logname = new_tempfile (logprefix, NOTESIZ);
-  RETURN_IF (logname == NULL,
-             _("Warning: could not create new note file to store "
-               "description. Aborting...\n"));
-  snprintf (flogname, BUFSIZ, "%s%s", logprefix, logname);
-  logfd = fopen (flogname, "w");
-  RETURN_IF (logfd == NULL, 
-             _("Warning: could not open temporary log file, Aborting..."));
-  ical_log_init (logfd, ical_version);
+  log = io_log_init ();
+  if (log == 0)
+    {
+      if (stream != stdin)
+        fclose (stream);
+      return;
+    }
+  ical_log_init (log->fd, ical_version);
 
   while (fgets (buf, BUFSIZ, stream) != NULL)
     {
@@ -2569,19 +2629,19 @@ io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
       str_toupper (buf);
       if (strncmp (buf, vevent.str, vevent.len) == 0)
         {
-          ical_read_event (stream, logfd, &stats.events, &stats.apoints,
+          ical_read_event (stream, log->fd, &stats.events, &stats.apoints,
                            &stats.skipped, &stats.lines);
         }
       else if (strncmp (buf, vtodo.str, vtodo.len) == 0)
         {
-          ical_read_todo (stream, logfd, &stats.todos, &stats.skipped,
+          ical_read_todo (stream, log->fd, &stats.todos, &stats.skipped,
                           &stats.lines);
         }
     }
   if (stream != stdin)
     fclose (stream);
 
-  if (mode == IO_MODE_INTERACTIVE && !conf->skip_system_dialogs)
+  if (ui_mode == UI_CURSES && !conf->skip_system_dialogs)
     {
       char read[BUFSIZ], stat[BUFSIZ];
 
@@ -2589,9 +2649,9 @@ io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
       snprintf (stat, BUFSIZ, lines_stats_interactive, stats.apoints,
                 stats.events, stats.todos, stats.skipped);
       status_mesg (read, stat);
-      keys_getch (win[STA].p);
+      (void)wgetch (win[STA].p);
     }
-  else if (mode == IO_MODE_NONINTERACTIVE)
+  else if (ui_mode == UI_CMDLINE)
     {
       printf (proc_report, stats.lines);
       printf ("\n");
@@ -2603,43 +2663,91 @@ io_import_data (io_mode_t mode, import_type_t type, conf_t *conf,
   /* User has the choice to look at the log file if some items could not be
      imported.
   */
-  fclose (logfd);
+  fclose (log->fd);
   if (stats.skipped > 0)
     {
       char *view_log = _("Some items could not be imported, see log file ?");
-      char *choices = "[y/n] ";
-      int ans;
-      
-      if (mode == IO_MODE_NONINTERACTIVE)
-        {
-          int ans;
 
-          printf ("\n%s %s", view_log, choices);
-          ans = fgetc (stdin);
-          if (ans == 'y')
-            {
-              char cmd[BUFSIZ];
+      io_log_display (log, view_log, conf->pager);
+    }
+  io_log_free (log);
+}
 
-              snprintf (cmd, BUFSIZ, "%s %s", conf->pager, flogname);
-              system (cmd);
-            }
+io_file_t *
+io_log_init (void)
+{
+  const char *logprefix = "/tmp/calcurse_log.";
+  char *logname;
+  io_file_t *log;
+
+  logname = new_tempfile (logprefix, NOTESIZ);
+  RETVAL_IF (logname == 0, 0,
+             _("Warning: could not create temporary log file, Aborting..."));
+  log = malloc (sizeof (io_file_t));
+  RETVAL_IF (log == 0, 0,
+             _("Warning: could not open temporary log file, Aborting..."));
+  snprintf (log->name, sizeof (log->name), "%s%s", logprefix, logname);
+  mem_free (logname);
+  log->fd = fopen (log->name, "w");
+  if (log->fd == 0)
+    {
+      ERROR_MSG (_("Warning: could not open temporary log file, Aborting..."));
+      mem_free (log);
+      return 0;
+    }
+
+  return log;
+}
+
+void
+io_log_print (io_file_t *log, int line, char *msg)
+{
+  if (log && log->fd)
+    fprintf (log->fd, "[%d]: %s\n", line, msg);
+}
+
+void
+io_log_display (io_file_t *log, char *msg, char *pager)
+{
+  char *choices = "[y/n] ";
+  int ans;
+
+  RETURN_IF (log == 0, _("No log file to display!"));
+  if (ui_mode == UI_CMDLINE)
+    {
+      printf ("\n%s %s", msg, choices);
+      ans = fgetc (stdin);
+      if (ans == 'y')
+        {
+          char cmd[BUFSIZ];
+          
+          snprintf (cmd, BUFSIZ, "%s %s", pager, log->name);
+          system (cmd);
         }
-      else
+    }
+  else
+    {
+      status_mesg (msg, choices);
+      do
         {
-          status_mesg (view_log, choices);
-          do
+          ans = wgetch (win[STA].p);
+          if (ans == 'y')
             {
-              ans = keys_getch (win[STA].p);
-              if (ans == 'y')
-                {
-                  wins_launch_external (flogname, conf->pager);
-                }
+              wins_launch_external (log->name, pager);
             }
-          while (ans != 'y' && ans != 'n');
-          erase_status_bar ();
         }
+      while (ans != 'y' && ans != 'n');
+      erase_status_bar ();
     }
-  EXIT_IF (unlink (flogname) != 0,
-           _("Warning: could not erase temporary log file, Aborting..."));
-  mem_free (logname);
+}
+
+void
+io_log_free (io_file_t *log)
+{
+  if (!log)
+    return;
+  EXIT_IF (unlink (log->name) != 0,
+           _("Warning: could not erase temporary log file %s, Aborting..."),
+           log->name);
+  mem_free (log);
 }
diff --git a/src/io.h b/src/io.h
index a710f0d..2741c52 100755
--- a/src/io.h
+++ b/src/io.h
@@ -1,4 +1,4 @@
-/*	$calcurse: io.h,v 1.16 2008/11/09 20:10:18 culot Exp $	*/
+/*	$calcurse: io.h,v 1.17 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -29,36 +29,36 @@
 
 #include "vars.h"
 
-typedef enum
-{
-  IO_MODE_NONINTERACTIVE,
-  IO_MODE_INTERACTIVE,
-  IO_NBMODES
-} io_mode_t;
-
-typedef enum
-{
+typedef enum {
   IO_IMPORT_ICAL,
   IO_IMPORT_NBTYPES
 } import_type_t;
 
-typedef enum
-{
+typedef enum {
   IO_EXPORT_ICAL,
   IO_EXPORT_PCAL,
   IO_EXPORT_NBTYPES
 } export_type_t;
 
-void io_init (char *, char *);
-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 *);
-void io_export_bar (void);
-void io_import_data (io_mode_t, import_type_t, conf_t *, char *);
+typedef struct {
+  FILE *fd;
+  char name[BUFSIZ];
+} io_file_t;
+
+void        io_init (char *, char *);
+void        io_extract_data (char *, const char *, int);
+void        io_save_cal (conf_t *);
+void        io_load_app (void);
+void        io_load_todo (void);
+void        io_load_keys (char *);
+int         io_check_data_files (void);
+void        io_startup_screen (bool, int);
+void        io_export_data (export_type_t, conf_t *);
+void        io_export_bar (void);
+void        io_import_data (import_type_t, conf_t *, char *);
+io_file_t  *io_log_init (void);
+void        io_log_print (io_file_t *, int, char *);
+void        io_log_display (io_file_t *, char *, char *);
+void        io_log_free (io_file_t *);
 
-#endif /* CALCURSE_IO_H */
+#endif /* !CALCURSE_IO_H */
diff --git a/src/keys.c b/src/keys.c
index 89f1787..c3fbde4 100755
--- a/src/keys.c
+++ b/src/keys.c
@@ -1,4 +1,4 @@
-/*	$calcurse: keys.c,v 1.6 2008/11/30 20:48:10 culot Exp $	*/
+/*	$calcurse: keys.c,v 1.7 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -32,7 +32,7 @@
 #include "custom.h"
 #include "keys.h"
 
-#define MAXKEYVAL     256
+#define MAXKEYVAL   KEY_MAX  /* ncurses defines KEY_MAX as maximum key value */
 
 struct keydef_s {
   char *label;
@@ -106,7 +106,8 @@ dump_intro (FILE *fd)
       "# 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#\n"
+      "# and 'TAB' keyword, respectively. Arrow keys can also be specified\n"
+      "# with the UP, DWN, LFT, RGT keywords.\n#\n"
       "# A description of what each ACTION keyword is used for is available\n"
       "# from calcurse online configuration menu.\n");
 
@@ -252,7 +253,11 @@ 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");  
+  const string_t ESCAPE_KEY = STRING_BUILD ("ESC");
+  const string_t CURSES_KEY_UP = STRING_BUILD ("UP");
+  const string_t CURSES_KEY_DOWN = STRING_BUILD ("DWN");
+  const string_t CURSES_KEY_LEFT = STRING_BUILD ("LFT");
+  const string_t CURSES_KEY_RIGHT = STRING_BUILD ("RGT");
 
   if (!key)
     return -1;
@@ -268,6 +273,14 @@ keys_str2int (char *key)
         return TAB;
       else if (!strncmp (key, ESCAPE_KEY.str, ESCAPE_KEY.len))
         return ESCAPE;
+      else if (!strncmp (key, CURSES_KEY_UP.str, CURSES_KEY_UP.len))
+        return KEY_UP;
+      else if (!strncmp (key, CURSES_KEY_DOWN.str, CURSES_KEY_DOWN.len))
+        return KEY_DOWN;
+      else if (!strncmp (key, CURSES_KEY_LEFT.str, CURSES_KEY_LEFT.len))
+        return KEY_LEFT;
+      else if (!strncmp (key, CURSES_KEY_RIGHT.str, CURSES_KEY_RIGHT.len))
+        return KEY_RIGHT;
       else
         return -1;
     }
@@ -282,6 +295,14 @@ keys_int2str (int key)
       return "TAB";
     case ESCAPE:
       return "ESC";
+    case KEY_UP:
+      return "UP";
+    case KEY_DOWN:
+      return "DWN";
+    case KEY_LEFT:
+      return "LFT";
+    case KEY_RIGHT:
+      return "RGT";
     default:
       return (char *)keyname (key);
     }
diff --git a/src/notify.c b/src/notify.c
index 67f96db..321b5fc 100755
--- a/src/notify.c
+++ b/src/notify.c
@@ -1,4 +1,4 @@
-/*	$calcurse: notify.c,v 1.29 2008/11/23 20:38:56 culot Exp $	*/
+/*	$calcurse: notify.c,v 1.30 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -539,7 +539,7 @@ notify_config_bar (void)
       status_mesg (number_str, "");
       notify_print_options (conf_win.p, col);
       *buf = '\0';
-      ch = keys_getch (win[STA].p);
+      ch = wgetch (win[STA].p);
 
       switch (ch)
 	{
diff --git a/src/recur.c b/src/recur.c
index 0207e9d..f6c46e8 100755
--- a/src/recur.c
+++ b/src/recur.c
@@ -1,4 +1,4 @@
-/*	$calcurse: recur.c,v 1.39 2008/11/16 17:42:53 culot Exp $	*/
+/*	$calcurse: recur.c,v 1.40 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -689,7 +689,7 @@ recur_repeat_item (conf_t *conf)
   if (p->type != APPT && p->type != EVNT)
     {
       status_mesg (wrong_type_1, wrong_type_2);
-      ch = keys_getch (win[STA].p);
+      ch = wgetch (win[STA].p);
       return;
     }
 
@@ -697,10 +697,10 @@ recur_repeat_item (conf_t *conf)
 	 && (ch != 'Y') && (ch != KEY_GENERIC_ESCAPE))
     {
       status_mesg (mesg_type_1, mesg_type_2);
-      ch = keys_getch (win[STA].p);
+      ch = wgetch (win[STA].p);
       ch = toupper (ch);
     }
-  if (ch == KEY_GENERIC_ESCAPE)
+  if (ch == ESCAPE)
     {
       return;
     }
@@ -719,7 +719,7 @@ recur_repeat_item (conf_t *conf)
 	  if (freq == 0)
 	    {
 	      status_mesg (mesg_wrong_freq, wrong_type_2);
-	      keys_getch (win[STA].p);
+	      (void)wgetch (win[STA].p);
 	    }
 	  user_input[0] = '\0';
 	}
@@ -753,7 +753,7 @@ recur_repeat_item (conf_t *conf)
 		  if (until < p->start)
 		    {
 		      status_mesg (mesg_older, wrong_type_2);
-		      keys_getch (win[STA].p);
+		      (void)wgetch (win[STA].p);
 		      date_entered = 0;
 		    }
 		  else
@@ -766,7 +766,7 @@ recur_repeat_item (conf_t *conf)
 		  snprintf (outstr, BUFSIZ, mesg_wrong_2,
 			    DATEFMT_DESC (conf->input_datefmt));
 		  status_mesg (mesg_wrong_1, _(outstr));
-		  keys_getch (win[STA].p);
+		  (void)wgetch (win[STA].p);
 		  date_entered = 0;
 		}
 	    }
diff --git a/src/todo.c b/src/todo.c
index 0a54074..6f17729 100755
--- a/src/todo.c
+++ b/src/todo.c
@@ -1,4 +1,4 @@
-/*	$calcurse: todo.c,v 1.24 2008/11/16 17:42:53 culot Exp $	*/
+/*	$calcurse: todo.c,v 1.25 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -146,7 +146,7 @@ todo_new_item (void)
       while ((ch < '1') || (ch > '9'))
 	{
 	  status_mesg (mesg_id, "");
-	  ch = keys_getch (win[STA].p);
+	  ch = wgetch (win[STA].p);
 	}
       todo_add (todo_input, ch - '0', NULL);
       todos++;
@@ -249,7 +249,7 @@ todo_delete (conf_t *conf)
   if (conf->confirm_delete)
     {
       status_mesg (del_todo_str, choices);
-      answer = keys_getch (win[STA].p);
+      answer = wgetch (win[STA].p);
       if ((answer == 'y') && (todos > 0))
 	{
 	  go_for_todo_del = true;
@@ -277,7 +277,7 @@ todo_delete (conf_t *conf)
   while (answer != 't' && answer != 'n' && answer != KEY_GENERIC_ESCAPE)
     {
       status_mesg (erase_warning, erase_choice);
-      answer = keys_getch (win[STA].p);
+      answer = wgetch (win[STA].p);
     }
 
   switch (answer)
diff --git a/src/utils.c b/src/utils.c
index 2b8e5e1..31a4bf4 100755
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,4 +1,4 @@
-/*	$calcurse: utils.c,v 1.54 2008/11/23 20:38:56 culot Exp $	*/
+/*	$calcurse: utils.c,v 1.55 2008/12/07 09:20:38 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -86,7 +86,7 @@ ierror (const char *errmsg, ierror_sev_e sev)
 	       exitmsg);
   custom_remove_attr (errwin, ATTR_HIGHEST);
   wrefresh (errwin);
-  keys_getch (errwin);
+  (void)wgetch (errwin);
   if (sev == IERROR_FATAL)
     exit_calcurse (EXIT_FAILURE);
 }
@@ -118,7 +118,7 @@ warnbox (const char *msg)
   warnwin = popup (WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2,
                    "/!\\", displmsg, 1);
   wrefresh (warnwin);
-  keys_getch (warnwin);
+  (void)wgetch (warnwin);
   delwin (warnwin);
   doupdate ();
 }
@@ -758,7 +758,7 @@ item_in_popup (char *saved_a_start, char *saved_a_end, char *msg,
   wmove (win[STA].p, 0, 0);
   pnoutrefresh (pad, 0, 0, margin_top + 2, margin_left, padl, winw);
   doupdate ();
-  keys_getch (popup_win);
+  (void)wgetch (popup_win);
   delwin (pad);
   delwin (popup_win);
 }
-- 
cgit v1.2.3-70-g09d2