From bf431d6cd9411714f849050a10071dc0fe0d7741 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer <calcurse@cryptocrack.de>
Date: Thu, 14 Apr 2011 12:49:44 +0200
Subject: Use generic lists for todo items.

Use the new generic list implementation instead of "next" pointers in
todo items.

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
---
 src/args.c     |  19 ++++---
 src/calcurse.c |   1 +
 src/calcurse.h |   4 +-
 src/dmon.c     |   1 +
 src/io.c       |  31 +++++-----
 src/todo.c     | 177 +++++++++++++++++++++++----------------------------------
 6 files changed, 103 insertions(+), 130 deletions(-)

(limited to 'src')

diff --git a/src/args.c b/src/args.c
index e1cd1bc..18a8887 100644
--- a/src/args.c
+++ b/src/args.c
@@ -242,7 +242,7 @@ print_notefile (FILE *out, char *filename, int nbtab)
 static void
 todo_arg (int priority, int print_note, regex_t *regex)
 {
-  struct todo *i;
+  llist_item_t *i;
   int title = 1;
   char *titlestr, priority_str[BUFSIZ] = "";
   char *all_todos_title = _("to do:\n");
@@ -259,20 +259,21 @@ todo_arg (int priority, int print_note, regex_t *regex)
   } while (0)
 
 #define DISPLAY_TODO  do {                                              \
-  (void)snprintf (priority_str, BUFSIZ, "%d. ", abs (i->id));           \
+  (void)snprintf (priority_str, BUFSIZ, "%d. ", abs (todo->id));        \
   fputs (priority_str, stdout);                                         \
-  fputs (i->mesg, stdout);                                              \
+  fputs (todo->mesg, stdout);                                           \
   fputs ("\n", stdout);                                                 \
-  if (print_note && i->note)                                            \
-    print_notefile (stdout, i->note, 1);                                \
+  if (print_note && todo->note)                                         \
+    print_notefile (stdout, todo->note, 1);                             \
   } while (0)
 
-  for (i = todolist; i != NULL; i = i->next)
+  LLIST_FOREACH (&todolist, i)
     {
-      if (regex && regexec (regex, i->mesg, 0, 0, 0) != 0)
+      struct todo *todo = LLIST_TS_GET_DATA (i);
+      if (regex && regexec (regex, todo->mesg, 0, 0, 0) != 0)
         continue;
 
-      if (i->id < 0) /* completed task */
+      if (todo->id < 0) /* completed task */
         {
           if (priority == 0)
             {
@@ -282,7 +283,7 @@ todo_arg (int priority, int print_note, regex_t *regex)
         }
       else
         {
-          if (priority < 0 || i->id == priority)
+          if (priority < 0 || todo->id == priority)
             {
               DISPLAY_TITLE;
               DISPLAY_TODO;
diff --git a/src/calcurse.c b/src/calcurse.c
index 95c9de8..3741614 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -77,6 +77,7 @@ main (int argc, char **argv)
 
   /* Initialize non-thread-safe data structures. */
   event_llist_init ();
+  todo_init_list ();
 
   /*
    * Begin by parsing and handling command line arguments.
diff --git a/src/calcurse.h b/src/calcurse.h
index a4f33fa..7bcdb31 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -278,7 +278,6 @@ struct event {
 
 /* Todo item definition. */
 struct todo {
-  struct todo  *next;
   char         *mesg;
   int           id;
   char         *note;
@@ -810,7 +809,7 @@ void      sigs_init (void);
 unsigned  sigs_set_hdlr (int, void (*)(int));
 
 /* todo.c */
-extern struct todo *todolist;
+extern llist_t todolist;
 void          todo_hilt_set (int);
 void          todo_hilt_decrease (void);
 void          todo_hilt_increase (void);
@@ -831,6 +830,7 @@ void          todo_edit_item (void);
 void          todo_update_panel (int);
 void          todo_edit_note (char *);
 void          todo_view_note (char *);
+void          todo_init_list (void);
 void          todo_free_list (void);
 
 /* utils.c */
diff --git a/src/dmon.c b/src/dmon.c
index 234cf67..89ef80d 100644
--- a/src/dmon.c
+++ b/src/dmon.c
@@ -173,6 +173,7 @@ dmon_start (int parent_exit_status)
   apoint_llist_init ();
   recur_apoint_llist_init ();
   event_llist_init ();
+  todo_init_list ();
   io_load_app ();
   data_loaded = 1;
 
diff --git a/src/io.c b/src/io.c
index 2e6fcf1..d6f6565 100644
--- a/src/io.c
+++ b/src/io.c
@@ -637,16 +637,17 @@ pcal_export_apoints (FILE *stream)
 static void
 ical_export_todo (FILE *stream)
 {
-  struct todo *i;
+  llist_item_t *i;
 
-  for (i = todolist; i != NULL; i = i->next)
+  LLIST_FOREACH (&todolist, i)
     {
-      if (i->id < 0)  /* completed items */
+      struct todo *todo = LLIST_TS_GET_DATA (i);
+      if (todo->id < 0)  /* completed items */
         continue;
 
       (void)fprintf (stream, "BEGIN:VTODO\n");
-      (void)fprintf (stream, "PRIORITY:%d\n", i->id);
-      (void)fprintf (stream, "SUMMARY:%s\n", i->mesg);
+      (void)fprintf (stream, "PRIORITY:%d\n", todo->id);
+      (void)fprintf (stream, "SUMMARY:%s\n", todo->mesg);
       (void)fprintf (stream, "END:VTODO\n");
     }
 }
@@ -654,16 +655,17 @@ ical_export_todo (FILE *stream)
 static void
 pcal_export_todo (FILE *stream)
 {
-  struct todo *i;
+  llist_item_t *i;
 
   (void)fprintf (stream, "#\n# Todos\n#\n");
-  for (i = todolist; i != NULL; i = i->next)
+  LLIST_FOREACH (&todolist, i)
     {
-      if (i->id < 0)  /* completed items */
+      struct todo *todo = LLIST_TS_GET_DATA (i);
+      if (todo->id < 0)  /* completed items */
         continue;
 
       (void)fprintf (stream, "note all  ");
-      (void)fprintf (stream, "%d. %s\n", i->id, i->mesg);
+      (void)fprintf (stream, "%d. %s\n", todo->id, todo->mesg);
     }
   (void)fprintf (stream, "\n");
 }
@@ -999,18 +1001,19 @@ io_save_apts (void)
 unsigned
 io_save_todo (void)
 {
-  struct todo *t;
+  llist_item_t *i;
   FILE *fp;
 
   if ((fp = fopen (path_todo, "w")) == NULL)
     return 0;
 
-  for (t = todolist; t != NULL; t = t->next)
+  LLIST_FOREACH (&todolist, i)
     {
-      if (t->note)
-        (void)fprintf (fp, "[%d]>%s %s\n", t->id, t->note, t->mesg);
+      struct todo *todo = LLIST_TS_GET_DATA (i);
+      if (todo->note)
+        (void)fprintf (fp, "[%d]>%s %s\n", todo->id, todo->note, todo->mesg);
       else
-        (void)fprintf (fp, "[%d] %s\n", t->id, t->mesg);
+        (void)fprintf (fp, "[%d] %s\n", todo->id, todo->mesg);
     }
   file_close (fp, __FILE_POS__);
 
diff --git a/src/todo.c b/src/todo.c
index 125b128..47c5ea2 100644
--- a/src/todo.c
+++ b/src/todo.c
@@ -40,7 +40,7 @@
 
 #include "calcurse.h"
 
-struct todo *todolist;
+llist_t todolist;
 static int hilt = 0;
 static int todos = 0;
 static int first = 1;
@@ -50,15 +50,7 @@ static char *msgsav;
 static struct todo *
 todo_get_item (int item_number)
 {
-  struct todo *o;
-  int i;
-
-  o = todolist;
-  for (i = 1; i < item_number; i++)
-    {
-      o = o->next;
-    }
-  return (o);
+  return LLIST_GET_DATA (LLIST_NTH (&todolist, item_number - 1));
 }
 
 /* Sets which todo is highlighted. */
@@ -159,87 +151,67 @@ todo_new_item (void)
     }
 }
 
+static int
+todo_cmp_id (struct todo *a, struct todo *b)
+{
+  /*
+   * 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.
+   */
+  int abs_a = abs (a->id);
+  int abs_b = abs (b->id);
+
+  return (abs_a < abs_b ? -1 : (abs_a == abs_b ? 0 : 1));
+}
+
 /*
  * Add an item in the todo linked list.
  */
 struct todo *
 todo_add (char *mesg, int id, char *note)
 {
-  struct todo *o, **i;
-  int absid;
+  struct todo *todo;
 
-  o = mem_malloc (sizeof (struct todo));
-  o->mesg = mem_strdup (mesg);
-  o->id = id;
-  o->note = (note != NULL && note[0] != '\0') ? mem_strdup (note) : NULL;
-  i = &todolist;
+  todo = mem_malloc (sizeof (struct todo));
+  todo->mesg = mem_strdup (mesg);
+  todo->id = id;
+  todo->note = (note != NULL && note[0] != '\0') ? mem_strdup (note) : NULL;
 
-  /*
-   * 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 == NULL || abs ((*i)->id) > absid)
-        {
-          o->next = *i;
-          *i = o;
-          break;
-        }
-      i = &(*i)->next;
-    }
-  return (o);
+  LLIST_ADD_SORTED (&todolist, todo, todo_cmp_id);
+
+  return todo;
 }
 
 /* Delete a note previously attached to a todo item. */
 static void
 todo_delete_note_bynum (unsigned num)
 {
-  unsigned n;
-  struct todo *i;
+  llist_item_t *i = LLIST_NTH (&todolist, num);
 
-  n = 0;
-  for (i = todolist; i != NULL; i = i->next)
-    {
-      if (n == num)
-        {
-          if (i->note == NULL)
-            EXIT (_("no note attached"));
-          erase_note (&i->note, ERASE_FORCE_ONLY_NOTE);
-          return;
-        }
-      n++;
-    }
-  /* NOTREACHED */
-  EXIT (_("no such todo"));
+  if (!i)
+    EXIT (_("no such todo"));
+  struct todo *todo = LLIST_TS_GET_DATA (i);
+
+  if (!todo->note)
+    EXIT (_("no note attached"));
+  erase_note (&todo->note, ERASE_FORCE_ONLY_NOTE);
 }
 
 /* Delete an item from the todo linked list. */
 static void
 todo_delete_bynum (unsigned num, enum eraseflg flag)
 {
-  unsigned n;
-  struct todo *i, **iptr;
+  llist_item_t *i = LLIST_NTH (&todolist, num);
 
-  n = 0;
-  iptr = &todolist;
-  for (i = todolist; i != NULL; i = i->next)
-    {
-      if (n == num)
-        {
-          *iptr = i->next;
-          mem_free (i->mesg);
-          erase_note (&i->note, flag);
-          mem_free (i);
-          return;
-        }
-      iptr = &i->next;
-      n++;
-    }
-  /* NOTREACHED */
-  EXIT (_("no such todo"));
+  if (!i)
+    EXIT (_("no such todo"));
+  struct todo *todo = LLIST_TS_GET_DATA (i);
+
+  LLIST_REMOVE (&todolist, i);
+  mem_free (todo->mesg);
+  erase_note (&todo->note, flag);
+  mem_free (todo);
 }
 
 /*
@@ -330,29 +302,20 @@ todo_delete (struct conf *conf)
  * given todo item.
  */
 static int
-todo_get_position (struct todo *i)
+todo_get_position (struct todo *needle)
 {
-  struct todo *o;
-  int n = 1, found = 0;
+  llist_item_t *i;
+  int n = 0;
 
-  for (o = todolist; o; o = o->next)
+  LLIST_FOREACH (&todolist, i)
     {
-      if (o == i)
-        {
-          found = 1;
-          break;
-        }
       n++;
+      if (LLIST_TS_GET_DATA (i) == needle)
+        return n;
     }
-  if (found)
-    {
-      return (n);
-    }
-  else
-    {
-      EXIT (_("todo not found"));
-      return -1; /* avoid compiler warnings */
-    }
+
+  EXIT (_("todo not found"));
+  return -1; /* avoid compiler warnings */
 }
 
 /* Change an item priority by pressing '+' or '-' inside TODO panel. */
@@ -438,7 +401,7 @@ display_todo_item (int incolor, char *msg, int prio, int note, int len, int y,
 void
 todo_update_panel (int which_pan)
 {
-  struct todo *i;
+  llist_item_t *i;
   int len = win[TOD].w - 8;
   int num_todo = 0;
   int y_offset = 3, x_offset = 1;
@@ -451,17 +414,18 @@ todo_update_panel (int which_pan)
   /* Print todo item in the panel. */
   erase_window_part (win[TOD].p, 1, title_lines, win[TOD].w - 2,
                      win[TOD].h - 2);
-  for (i = todolist; i != NULL; i = i->next)
+  LLIST_FOREACH (&todolist, i)
     {
+      struct todo *todo = LLIST_TS_GET_DATA (i);
       num_todo++;
       t_realpos = num_todo - first;
       incolor = num_todo - hilt;
       if (incolor == 0)
-        msgsav = i->mesg;
+        msgsav = todo->mesg;
       if (t_realpos >= 0 && t_realpos < max_items)
         {
-          display_todo_item (incolor, i->mesg, i->id,
-                             (i->note != NULL) ? 1 : 0, len, y_offset,
+          display_todo_item (incolor, todo->mesg, todo->id,
+                             (todo->note != NULL) ? 1 : 0, len, y_offset,
                              x_offset);
           y_offset = y_offset + todo_lines;
         }
@@ -523,19 +487,22 @@ todo_view_note (char *pager)
 }
 
 void
-todo_free_list (void)
+todo_free (struct todo *todo)
 {
-  struct todo *o, **i;
+  mem_free (todo->mesg);
+  erase_note (&todo->note, ERASE_FORCE_KEEP_NOTE);
+  mem_free (todo);
+}
 
-  i = &todolist;
-  while (*i)
-    {
-      o = *i;
-      *i = o->next;
-      mem_free (o->mesg);
-      erase_note (&o->note, ERASE_FORCE_KEEP_NOTE);
-      mem_free (o);
-    }
-  if (todolist)
-    mem_free (todolist);
+void
+todo_init_list (void)
+{
+  LLIST_INIT (&todolist);
+}
+
+void
+todo_free_list (void)
+{
+  LLIST_FREE_INNER (&todolist, todo_free);
+  LLIST_FREE (&todolist);
 }
-- 
cgit v1.2.3-70-g09d2