From ea107cfd8182f9c16f6554dcade75441984e985c Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Fri, 26 Jun 2009 21:44:11 +0000
Subject: Ability to flag todo items as completed.

---
 ChangeLog      |  7 ++++++
 src/args.c     | 73 ++++++++++++++++++++++++++++++++++++++++------------------
 src/calcurse.c |  4 +++-
 src/todo.c     | 47 ++++++++++++++++++++++++++++++-------
 src/todo.h     |  5 ++--
 5 files changed, 102 insertions(+), 34 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b3b4c9e..6b6a34a 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,13 @@
 
 	* src/args.c: do not print todo items twice if -d and -t flags are
 	given (thanks Timo for reporting the bug)
+
+	* src/todo.c (todo_flag): new function
+
+	* src/args.c (todo_arg): function adapted to display completed
+	tasks
+	
+	* src/todo.c: todos can now be flagged as completed
 	
 2009-06-23  Frederic Culot  <frederic@culot.org>
 
diff --git a/src/args.c b/src/args.c
index 90ecde7..b23a2b0 100755
--- a/src/args.c
+++ b/src/args.c
@@ -1,4 +1,4 @@
-/*	$calcurse: args.c,v 1.48 2009/06/26 19:56:32 culot Exp $	*/
+/*	$calcurse: args.c,v 1.49 2009/06/26 21:44:11 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -194,33 +194,61 @@ print_notefile (FILE *out, char *filename, int nbtab)
 }
 
 /*
- * Print todo list and exit. If a priority number is given (say not equal to
- * zero), then only todo items that have this priority will be displayed.
+ * Print todo list and exit. If a priority number is given, then only todo
+ * then only todo items that have this priority will be displayed.
+ * If priority is < 0, all todos will be displayed.
+ * If priority == 0, only completed tasks will be displayed.
  */
 static void
 todo_arg (int priority, int print_note)
 {
   struct todo_s *i;
   int title = 1;
-  char priority_str[BUFSIZ] = "";
-
+  char *titlestr, priority_str[BUFSIZ] = "";
+  char *all_todos_title = _("to do:\n");
+  char *completed_title = _("completed tasks:\n");
+
+  titlestr = priority == 0 ? completed_title : all_todos_title;
+
+#define DISPLAY_TITLE  do {                                             \
+  if (title)                                                            \
+    {                                                                   \
+      fputs (titlestr, stdout);                                         \
+      title = 0;                                                        \
+    }                                                                   \
+  } while (0)
+
+#define DISPLAY_TODO  do {                                              \
+  (void)snprintf (priority_str, BUFSIZ, "%d. ", abs (i->id));           \
+  fputs (priority_str, stdout);                                         \
+  fputs (i->mesg, stdout);                                              \
+  fputs ("\n", stdout);                                                 \
+  if (print_note && i->note)                                            \
+    print_notefile (stdout, i->note, 1);                                \
+  } while (0)
+  
   for (i = todolist; i != 0; i = i->next)
     {
-      if (priority == 0 || i->id == priority)
-	{
-	  if (title)
-	    {
-	      fputs (_("to do:\n"), stdout);
-	      title = 0;
-	    }
-	  (void)snprintf (priority_str, BUFSIZ, "%d. ", i->id);
-	  fputs (priority_str, stdout);
-	  fputs (i->mesg, stdout);
-	  fputs ("\n", stdout);
-	  if (print_note && i->note)
-	    print_notefile (stdout, i->note, 1);
-	}
+      if (i->id < 0) /* completed task */
+        {
+          if (priority == 0)
+            {
+              DISPLAY_TITLE;
+              DISPLAY_TODO;
+            }
+        }
+      else
+        {
+          if (priority < 0 || i->id == priority)
+            {
+              DISPLAY_TITLE;
+              DISPLAY_TODO;
+            }
+        }
     }
+
+#undef DISPLAY_TITLE
+#undef DISPLAY_TODO  
 }
 
 /* Print the next appointment within the upcoming 24 hours. */
@@ -590,8 +618,7 @@ parse_args (int argc, char **argv, conf_t *conf)
   int vflag = 0;    /* -v: print version number */
   int xflag = 0;    /* -x: export data */
 
-  int tnum = 0, xfmt = 0;
-  int non_interactive = 0, multiple_flag = 0, load_data = 0;
+  int tnum = 0, xfmt = 0, non_interactive = 0, multiple_flag = 0, load_data = 0;
   int no_file = 1;
   char *ddate = "", *cfile = NULL, *range = NULL, *startday = NULL;
   char *datadir = NULL, *ifile = NULL;
@@ -677,7 +704,7 @@ parse_args (int argc, char **argv, conf_t *conf)
 	  if (optarg != NULL)
 	    {
 	      tnum = atoi (optarg);
-	      if (tnum < 1 || tnum > 9)
+	      if (tnum < 0 || tnum > 9)
 		{
 		  usage ();
 		  usage_try ();
@@ -685,7 +712,7 @@ parse_args (int argc, char **argv, conf_t *conf)
 		}
 	    }
 	  else
-	    tnum = 0;
+	    tnum = -1;
 	  break;
 	case 'v':
 	  vflag = 1;
diff --git a/src/calcurse.c b/src/calcurse.c
index 30beffb..4bc9f75 100755
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calcurse.c,v 1.79 2009/06/21 18:16:22 culot Exp $	*/
+/*	$calcurse: calcurse.c,v 1.80 2009/06/26 21:44:12 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -360,6 +360,8 @@ main (int argc, char **argv)
         case KEY_FLAG_ITEM:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    apoint_switch_notify ();
+          else if (wins_slctd () == TOD && todo_hilt () != 0)
+            todo_flag ();
 	  do_storage = true;
 	  break;
 
diff --git a/src/todo.c b/src/todo.c
index a8c5ab5..f20188c 100755
--- a/src/todo.c
+++ b/src/todo.c
@@ -1,8 +1,8 @@
-/*	$calcurse: todo.c,v 1.31 2009/01/03 21:32:11 culot Exp $	*/
+/*	$calcurse: todo.c,v 1.32 2009/06/26 21:44:12 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
- * Copyright (c) 2004-2008 Frederic Culot
+ * Copyright (c) 2004-2009 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
@@ -154,19 +154,30 @@ todo_new_item (void)
     }
 }
 
-/* Add an item in the todo linked list. */
+/*
+ * Add an item in the todo linked list.
+ */
 struct todo_s *
 todo_add (char *mesg, int id, char *note)
 {
   struct todo_s *o, **i;
+  int absid;
+  
   o = (struct todo_s *) mem_malloc (sizeof (struct todo_s));
   o->mesg = mem_strdup (mesg);
   o->id = id;
   o->note = (note != NULL && note[0] != '\0') ? mem_strdup (note) : NULL;
   i = &todolist;
+
+  /*
+   * As of version 2.6, todo items can have a negative id, which means they
+   * were completed. To keep them sorted, we need to consider the absolute id
+   * value.
+   */
+  absid = abs (id);
   for (;;)
     {
-      if (*i == 0 || (*i)->id > id)
+      if (*i == 0 || abs ((*i)->id) > absid)
 	{
 	  o->next = *i;
 	  *i = o;
@@ -229,6 +240,21 @@ todo_delete_bynum (unsigned num, erase_flag_e flag)
   EXIT (_("no such todo"));
 }
 
+/*
+ * Flag a todo item (for now on, only the 'completed' state is available).
+ * Internally, a completed item keeps its priority, but it becomes negative.
+ * This way, it is easy to retrive its original priority if the user decides
+ * that in fact it was not completed.
+ */
+void
+todo_flag (void)
+{
+  struct todo_s *t;
+
+  t = todo_get_item (hilt);
+  t->id = -t->id;
+}
+
 /* Delete an item from the ToDo list. */
 void
 todo_delete (conf_t *conf)
@@ -350,7 +376,7 @@ todo_chg_priority (int action)
       (backup_id > 1) ? backup_id-- : do_chg--;
       break;
     case KEY_LOWER_PRIORITY:
-      (backup_id < 9) ? backup_id++ : do_chg--;
+      (backup_id > 0 && backup_id < 9) ? backup_id++ : do_chg--;
       break;
     default:
       EXIT (_("no such action"));
@@ -383,19 +409,24 @@ display_todo_item (int incolor, char *msg, int prio, int note, int len, int y,
 {
   WINDOW *w;
   int ch_note;
-  char buf[len];
+  char buf[len], priostr[2];
 
   w = win[TOD].p;
   ch_note = (note) ? '>' : '.';
+  if (prio > 0)
+    snprintf (priostr, sizeof priostr, "%d", prio);
+  else
+    snprintf (priostr, sizeof priostr, "X");
+    
   if (incolor == 0)
     custom_apply_attr (w, ATTR_HIGHEST);
   if (strlen (msg) < len)
-    mvwprintw (w, y, x, "%d%c %s", prio, ch_note, msg);
+    mvwprintw (w, y, x, "%s%c %s", priostr, ch_note, msg);
   else
     {
       (void)strncpy (buf, msg, len - 1);
       buf[len - 1] = '\0';
-      mvwprintw (w, y, x, "%d%c %s...", prio, ch_note, buf);
+      mvwprintw (w, y, x, "%s%c %s...", priostr, ch_note, buf);
     }
   if (incolor == 0)
     custom_remove_attr (w, ATTR_HIGHEST);
diff --git a/src/todo.h b/src/todo.h
index 42a4da8..847a876 100755
--- a/src/todo.h
+++ b/src/todo.h
@@ -1,8 +1,8 @@
-/*	$calcurse: todo.h,v 1.13 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: todo.h,v 1.14 2009/06/26 21:44:12 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
- * Copyright (c) 2004-2008 Frederic Culot
+ * Copyright (c) 2004-2009 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
@@ -50,6 +50,7 @@ int            todo_hilt_pos (void);
 char          *todo_saved_mesg (void);
 void           todo_new_item (void);
 struct todo_s *todo_add (char *, int, char *);
+void           todo_flag (void);
 void           todo_delete (conf_t *);
 void           todo_chg_priority (int);
 void           todo_edit_item (void);
-- 
cgit v1.2.3-70-g09d2