From cac30a7e1469a8f061f64712dbea100a012dd788 Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Thu, 1 Jan 2009 17:50:41 +0000
Subject: cut/paste feature aded fixed a 2-years old bug that made repeated
 items with exceptions to load uncorrectly in some cases (thanks Jan for
 reporting it)

---
 src/apoint.c   | 124 +++++++++++++++++--
 src/apoint.h   |   8 +-
 src/calcurse.c |  18 ++-
 src/day.c      |  74 ++++++++++-
 src/day.h      |   4 +-
 src/event.c    |  82 +++++++++++--
 src/event.h    |   7 +-
 src/io.c       |  17 +--
 src/keys.c     |  42 ++++++-
 src/keys.h     |   7 +-
 src/recur.c    | 380 ++++++++++++++++++++++++++++++++++++++++++++-------------
 src/recur.h    |  17 ++-
 src/utils.c    |  59 +++++++--
 src/utils.h    |  76 ++++++------
 14 files changed, 742 insertions(+), 173 deletions(-)

(limited to 'src')

diff --git a/src/apoint.c b/src/apoint.c
index 30ecbc7..31bac44 100755
--- a/src/apoint.c
+++ b/src/apoint.c
@@ -1,8 +1,8 @@
-/*	$calcurse: apoint.c,v 1.29 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: apoint.c,v 1.30 2009/01/01 17:50:41 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
@@ -41,8 +41,37 @@
 #include "mem.h"
 #include "apoint.h"
 
-apoint_llist_t *alist_p;
-static int hilt = 0;
+apoint_llist_t             *alist_p;
+static apoint_llist_node_t  bkp_cut_apoint;
+static int                  hilt;
+
+void
+apoint_free_bkp (void)
+{
+  if (bkp_cut_apoint.mesg)
+    {
+      mem_free (bkp_cut_apoint.mesg);
+      bkp_cut_apoint.mesg = 0;
+    }
+  if (bkp_cut_apoint.note)
+    {
+      mem_free (bkp_cut_apoint.note);
+      bkp_cut_apoint.note = 0;
+    }
+}
+
+static void
+apoint_dup (apoint_llist_node_t *in, apoint_llist_node_t *bkp)
+{
+  EXIT_IF (!in || !bkp, _("null pointer"));
+
+  bkp->start = in->start;
+  bkp->dur = in->dur;
+  bkp->state = in->state;
+  bkp->mesg = mem_strdup (in->mesg);
+  if (in->note)
+    bkp->note = mem_strdup (in->note);
+}
 
 void
 apoint_llist_init (void)
@@ -303,6 +332,62 @@ apoint_delete (conf_t *conf, unsigned *nb_events, unsigned *nb_apoints)
     }
 }
 
+/* Cut an item, so that it can be pasted somewhere else later. */
+void
+apoint_cut (unsigned *nb_events, unsigned *nb_apoints)
+{
+  const int NBITEMS = *nb_apoints + *nb_events;
+  int item_type, to_be_removed;  
+  long date;
+
+  if (NBITEMS == 0)
+    return;
+
+  to_be_removed = 0;
+  date = calendar_get_slctd_day_sec ();
+  item_type = day_cut_item (date, hilt);
+  if (item_type == EVNT || item_type == RECUR_EVNT)
+    {
+      (*nb_events)--;
+      to_be_removed = 1;
+    }
+  else if (item_type == APPT || item_type == RECUR_APPT)
+    {
+      (*nb_apoints)--;
+      to_be_removed = 3;
+    }
+  else
+    EXIT (_("no such type"));
+  /* NOTREACHED */
+  
+  if (hilt > 1)
+    hilt--;
+  if (apad->first_onscreen >= to_be_removed)
+    apad->first_onscreen = apad->first_onscreen - to_be_removed;
+  if (NBITEMS == 1)
+    hilt = 0;
+}
+
+/* Paste a previously cut item. */
+void
+apoint_paste (unsigned *nb_events, unsigned *nb_apoints)
+{
+  int item_type;
+  long date;
+
+  date = calendar_get_slctd_day_sec ();
+  item_type = day_paste_item (date);
+  if (item_type == EVNT || item_type == RECUR_EVNT)
+    (*nb_events)++;
+  else if (item_type == APPT || item_type == RECUR_APPT)
+    (*nb_apoints)++;
+  else
+    return;
+  
+  if (hilt == 0)
+    hilt++;
+}
+
 unsigned
 apoint_inday (apoint_llist_node_t *i, long start)
 {
@@ -434,22 +519,30 @@ apoint_delete_bynum (long start, unsigned num, erase_flag_e flag)
 	{
 	  if (n == num)
 	    {
-	      if (flag == ERASE_FORCE_ONLY_NOTE)
+              switch (flag)
                 {
+                case ERASE_FORCE_ONLY_NOTE:
                   erase_note (&i->note, flag);
                   pthread_mutex_unlock (&(alist_p->mutex));
-                }
-	      else
-		{
+                  break;
+                case ERASE_CUT:
+                  apoint_free_bkp ();
+                  apoint_dup (i, &bkp_cut_apoint);
+                  if (i->note)
+                    mem_free (i->note);
+                  /* FALLTHROUGH */
+                default:
 		  if (notify_bar ())
 		    need_check_notify = notify_same_item (i->start);
 		  *iptr = i->next;
 		  mem_free (i->mesg);
-		  erase_note (&i->note, flag);
+                  if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
+                    erase_note (&i->note, flag);
 		  mem_free (i);
 		  pthread_mutex_unlock (&(alist_p->mutex));
 		  if (need_check_notify)
 		    notify_check_next_app ();
+                  break;
 		}
 	      return;
 	    }
@@ -672,3 +765,16 @@ apoint_update_panel (int which_pan)
 		win[APP].y + win[APP].h - 2 * bordr,
 		win[APP].x + win[APP].w - 3 * bordr);
 }
+
+void
+apoint_paste_item (void)
+{
+  long bkp_time, bkp_start;
+
+  bkp_time = get_item_time (bkp_cut_apoint.start);
+  bkp_start = calendar_get_slctd_day_sec () + bkp_time;
+  (void)apoint_new (bkp_cut_apoint.mesg, bkp_cut_apoint.note,
+                    bkp_start, bkp_cut_apoint.dur,
+                    bkp_cut_apoint.state);
+  apoint_free_bkp ();
+}
diff --git a/src/apoint.h b/src/apoint.h
index ca3b4b3..d51829c 100755
--- a/src/apoint.h
+++ b/src/apoint.h
@@ -1,8 +1,8 @@
-/*	$calcurse: apoint.h,v 1.15 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: apoint.h,v 1.16 2009/01/01 17:50:41 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
@@ -59,6 +59,7 @@ apoint_llist_t;
 
 extern apoint_llist_t *alist_p;
 
+void                 apoint_free_bkp (void);
 void                 apoint_llist_init (void);
 void                 apoint_llist_free (void);
 void                 apoint_hilt_set (int);
@@ -68,6 +69,8 @@ int                  apoint_hilt (void);
 apoint_llist_node_t *apoint_new (char *, char *, long, long, char);
 void                 apoint_add (void);
 void                 apoint_delete (conf_t *, unsigned *, unsigned *);
+void                 apoint_cut (unsigned *, unsigned *);
+void                 apoint_paste (unsigned *, unsigned *);
 unsigned             apoint_inday (apoint_llist_node_t *, long);
 void                 apoint_sec2str (apoint_llist_node_t *, int, long, char *,
                                      char *);
@@ -81,5 +84,6 @@ struct notify_app_s *apoint_check_next (struct notify_app_s *, long);
 apoint_llist_node_t *apoint_recur_s2apoint_s (recur_apoint_llist_node_t *);
 void                 apoint_switch_notify (void);
 void                 apoint_update_panel (int);
+void                 apoint_paste_item (void);
 
 #endif /* CALCURSE_APOINT_H */
diff --git a/src/calcurse.c b/src/calcurse.c
index fb2db0f..e2d398b 100755
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calcurse.c,v 1.75 2008/12/28 19:41:45 culot Exp $	*/
+/*	$calcurse: calcurse.c,v 1.76 2009/01/01 17:50:41 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -332,6 +332,22 @@ main (int argc, char **argv)
 	  do_storage = true;
 	  break;
 
+        case KEY_GENERIC_CUT:
+          if (wins_slctd () == APP && apoint_hilt () != 0)
+            {
+              apoint_cut (&inday.nb_events, &inday.nb_apoints);
+              do_storage = true;
+            }
+          break;
+
+        case KEY_GENERIC_PASTE:
+          if (wins_slctd () == APP)
+            {
+              apoint_paste (&inday.nb_events, &inday.nb_apoints);
+              do_storage = true;
+            }
+          break;
+          
         case KEY_REPEAT_ITEM:
 	  if (wins_slctd () == APP && apoint_hilt () != 0)
 	    recur_repeat_item (&conf);
diff --git a/src/day.c b/src/day.c
index a3574b9..8de0a94 100755
--- a/src/day.c
+++ b/src/day.c
@@ -1,8 +1,8 @@
-/*	$calcurse: day.c,v 1.44 2008/12/28 19:41:45 culot Exp $	*/
+/*	$calcurse: day.c,v 1.45 2009/01/01 17:50:41 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
@@ -38,8 +38,9 @@
 #include "mem.h"
 #include "day.h"
 
-static struct day_item_s *day_items_ptr;
-static struct day_saved_item_s *day_saved_item;
+static struct day_item_s        *day_items_ptr;
+static struct day_saved_item_s  *day_saved_item;
+static int                       cut_item_type;
 
 void
 day_saved_item_init (void)
@@ -899,6 +900,71 @@ day_erase_item (long date, int item_number, erase_flag_e flag)
     return (p->type);
 }
 
+/* Cut an item so it can be pasted somewhere else later. */
+int
+day_cut_item (long date, int item_number)
+{
+  const int DELETE_WHOLE = 1;
+  struct day_item_s *p;
+
+  p = day_get_item (item_number);
+  switch (p->type)
+    {
+    case EVNT:
+      event_delete_bynum (date, day_item_nb (date, item_number, EVNT),
+                          ERASE_CUT);      
+      break;
+    case RECUR_EVNT:
+      recur_event_erase (date, day_item_nb (date, item_number, RECUR_EVNT),
+                         DELETE_WHOLE, ERASE_CUT);
+      break;
+    case APPT:
+      apoint_delete_bynum (date, day_item_nb (date, item_number, APPT),
+                           ERASE_CUT);
+      break;
+    case RECUR_APPT:
+      recur_apoint_erase (date, p->appt_pos, DELETE_WHOLE, ERASE_CUT);
+      break;
+    default:
+      EXIT (_("unknwon type"));
+      /* NOTREACHED */
+    }
+  cut_item_type = p->type;
+  return cut_item_type;
+}
+
+/* Paste a previously cut item. */
+int
+day_paste_item (long date)
+{
+  int pasted_item_type;
+
+  pasted_item_type = cut_item_type;
+  switch (cut_item_type)
+    {
+    case 0:
+      return 0;
+    case EVNT:
+      event_paste_item ();
+      break;
+    case RECUR_EVNT:
+      recur_event_paste_item ();
+      break;
+    case APPT:
+      apoint_paste_item ();
+      break;
+    case RECUR_APPT:
+      recur_apoint_paste_item ();
+      break;
+    default:
+      EXIT (_("unknwon type"));
+      /* NOTREACHED */
+    }
+  cut_item_type = 0;
+
+  return pasted_item_type;
+}
+
 /* Returns a structure containing the selected item. */
 struct day_item_s *
 day_get_item (int item_number)
diff --git a/src/day.h b/src/day.h
index c053833..bb3fe37 100755
--- a/src/day.h
+++ b/src/day.h
@@ -1,4 +1,4 @@
-/*	$calcurse: day.h,v 1.20 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: day.h,v 1.21 2009/01/01 17:50:41 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -76,6 +76,8 @@ void               day_popup_item (void);
 int                day_check_if_item (date_t);
 void               day_edit_item (conf_t *);
 int                day_erase_item (long, int, erase_flag_e);
+int                day_cut_item (long, int);
+int                day_paste_item (long);
 struct day_item_s *day_get_item (int);
 int                day_item_nb (long, int, int);
 void               day_edit_note (char *);
diff --git a/src/event.c b/src/event.c
index f366b6d..7bc6aeb 100755
--- a/src/event.c
+++ b/src/event.c
@@ -1,8 +1,8 @@
-/*	$calcurse: event.c,v 1.9 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: event.c,v 1.10 2009/01/01 17:50:41 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
@@ -34,7 +34,52 @@
 #include "mem.h"
 #include "event.h"
 
-struct event_s *eventlist;
+struct event_s        *eventlist;
+static struct event_s  bkp_cut_event;
+
+void
+event_free_bkp (void)
+{
+  if (bkp_cut_event.mesg)
+    {
+      mem_free (bkp_cut_event.mesg);
+      bkp_cut_event.mesg = 0;
+    }
+  if (bkp_cut_event.note)
+    {
+      mem_free (bkp_cut_event.note);
+      bkp_cut_event.note = 0;
+    }
+}
+
+static void
+event_dup (struct event_s *in, struct event_s *bkp)
+{
+  EXIT_IF (!in || !bkp, _("null pointer"));
+
+  bkp->id = in->id;
+  bkp->day = in->day;
+  bkp->mesg = mem_strdup (in->mesg);
+  if (in->note)
+    bkp->note = mem_strdup (in->note);
+}
+
+void
+event_llist_free (void)
+{
+  struct event_s *o, **i;
+
+  i = &eventlist;
+  for (o = eventlist; o; o = o->next)
+    {
+      *i = o->next;
+      mem_free (o->mesg);
+      if (o->note)
+        mem_free (o->note);
+      mem_free (o);
+      i = &(*i)->next;
+    }
+}
 
 /* Create a new event */
 struct event_s *
@@ -154,15 +199,25 @@ event_delete_bynum (long start, unsigned num, erase_flag_e flag)
 	{
 	  if (n == num)
 	    {
-	      if (flag == ERASE_FORCE_ONLY_NOTE)
-		erase_note (&i->note, flag);
-	      else
-		{
+              switch (flag)
+                {
+                case ERASE_FORCE_ONLY_NOTE:
+                  erase_note (&i->note, flag);
+                  break;
+                case ERASE_CUT:
+                  event_free_bkp ();
+                  event_dup (i, &bkp_cut_event);
+                  if (i->note)
+                    mem_free (i->note);
+                  /* FALLTHROUGH */
+                default:
 		  *iptr = i->next;
 		  mem_free (i->mesg);
-		  erase_note (&i->note, flag);
+                  if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
+                    erase_note (&i->note, flag);
 		  mem_free (i);
-		}
+                  break;
+                }
 	      return;
 	    }
 	  n++;
@@ -172,3 +227,12 @@ event_delete_bynum (long start, unsigned num, erase_flag_e flag)
   EXIT (_("event not found"));
   /* NOTREACHED */  
 }
+
+void
+event_paste_item (void)
+{
+  (void)event_new (bkp_cut_event.mesg, bkp_cut_event.note,
+                   date2sec (*calendar_get_slctd_day (), 12, 0),
+                   bkp_cut_event.id);
+  event_free_bkp ();
+}
diff --git a/src/event.h b/src/event.h
index 6c6c2d6..9fcc7d7 100755
--- a/src/event.h
+++ b/src/event.h
@@ -1,8 +1,8 @@
-/*	$calcurse: event.h,v 1.6 2008/04/12 21:14:03 culot Exp $	*/
+/*	$calcurse: event.h,v 1.7 2009/01/01 17:50:41 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
@@ -43,11 +43,14 @@ struct event_s
 
 extern struct event_s *eventlist;
 
+void            event_free_bkp (void);
+void            event_llist_free (void);
 struct event_s *event_new (char *, char *, long, int);
 unsigned        event_inday (struct event_s *, long);
 void            event_write (struct event_s *, FILE *);
 struct event_s *event_scan (FILE *, struct tm, int, char *);
 struct event_s *event_get (long, int);
 void            event_delete_bynum (long, unsigned, erase_flag_e);
+void            event_paste_item (void);
 
 #endif /* CALCURSE_EVENT_H */
diff --git a/src/io.c b/src/io.c
index b0f02b2..a2da17b 100755
--- a/src/io.c
+++ b/src/io.c
@@ -1,8 +1,8 @@
-/*	$calcurse: io.c,v 1.51 2008/12/28 19:41:45 culot Exp $	*/
+/*	$calcurse: io.c,v 1.52 2009/01/01 17:50:41 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
@@ -995,7 +995,7 @@ io_load_app (void)
   FILE *data_file;
   int c, is_appointment, is_event, is_recursive;
   struct tm start, end, until, *lt;
-  struct days_s *exc = NULL;
+  struct days_s *exc;
   time_t t;
   int id = 0;
   int freq;
@@ -1009,6 +1009,7 @@ io_load_app (void)
   data_file = fopen (path_apts, "r");
   for (;;)
     {
+      exc = 0;
       is_appointment = is_event = is_recursive = 0;
       c = getc (data_file);
       if (c == EOF)
@@ -1144,7 +1145,7 @@ io_load_app (void)
 	  if (is_recursive)
 	    {
 	      recur_apoint_scan (data_file, start, end,
-				 type, freq, until, notep, exc, state);
+				 type, freq, until, notep, &exc, state);
 	    }
 	  else
 	    {
@@ -1156,7 +1157,7 @@ io_load_app (void)
 	  if (is_recursive)
 	    {
 	      recur_event_scan (data_file, start, id, type,
-				freq, until, notep, exc);
+				freq, until, notep, &exc);
 	    }
 	  else
 	    {
@@ -1395,6 +1396,8 @@ io_load_keys (char *pager)
   EXIT_IF (skipped > MAX_ERRORS,
            _("Too many errors while reading keys file, aborting..."));
   if (loaded < NBKEYS)
+    keys_fill_missing ();
+  if (keys_check_missing_bindings ())
     ERROR_MSG (_("Some actions do not have any associated key bindings!"));
 #undef HSIZE
 }
@@ -1627,7 +1630,7 @@ ical_store_event (char *mesg, char *note, long day, ical_rpt_t *rpt,
   if (rpt != NULL)
     {
       recur_event_new (mesg, note, day, EVENTID, rpt->type, rpt->freq,
-                       rpt->until, exc);
+                       rpt->until, &exc);
       mem_free (rpt);
     }
   else
@@ -1649,7 +1652,7 @@ ical_store_apoint (char *mesg, char *note, long start, long dur,
   if (rpt != NULL)
     {
       recur_apoint_new (mesg, note, start, dur, state, rpt->type, rpt->freq,
-                        rpt->until, exc);
+                        rpt->until, &exc);
       mem_free (rpt);
     }
   else
diff --git a/src/keys.c b/src/keys.c
index bfebe24..ecfeb38 100755
--- a/src/keys.c
+++ b/src/keys.c
@@ -1,4 +1,4 @@
-/*	$calcurse: keys.c,v 1.11 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: keys.c,v 1.12 2009/01/01 17:50:41 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -56,6 +56,8 @@ static struct keydef_s keydef[NBKEYS] = {
   {"generic-help", "?"},
   {"generic-quit", "q Q"},
   {"generic-save", "s S C-s"},
+  {"generic-cut", "C-x"},
+  {"generic-paste", "C-v"},
   {"generic-change-view", "TAB"},
   {"generic-import", "i I"},
   {"generic-export", "x X"},
@@ -591,3 +593,41 @@ keys_check_missing_bindings (void)
     }
   return 0;
 }
+
+void
+keys_fill_missing (void)
+{
+  int i;
+
+  for (i = 0; i < NBKEYS; i++)
+    {
+      if (keys[i] == 0)
+        {
+          char *p, tmpbuf[BUFSIZ];
+
+          (void)strncpy (tmpbuf, keydef[i].binding, BUFSIZ);          
+          p = tmpbuf;
+          for (;;)
+            {
+              char key_ch[BUFSIZ];
+
+              while (*p == ' ')
+                p++;
+              if (sscanf (p, "%s", key_ch) == 1)
+                {
+                  int ch, used;
+                  
+                  ch = keys_str2int (key_ch);
+                  used = keys_assign_binding (ch, i);
+                  if (used)
+                    ERROR_MSG (_("When adding default key for \"%s\", "
+                                 "\"%s\" was already assigned!"),
+                               keydef[i].label, key_ch);
+                  p += strlen (key_ch) + 1;
+                }
+              else
+                break;
+            }
+        }
+    }
+}
diff --git a/src/keys.h b/src/keys.h
index 6c4e020..6e48016 100755
--- a/src/keys.h
+++ b/src/keys.h
@@ -1,4 +1,4 @@
-/*	$calcurse: keys.h,v 1.7 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: keys.h,v 1.8 2009/01/01 17:50:41 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -27,7 +27,7 @@
 #ifndef CALCURSE_KEYS_H
 #define CALCURSE_KEYS_H
 
-#define CTRLVAL   0x1F
+#define CTRLVAL                 0x1F
 #define CTRL(x)                 ((x) & CTRLVAL)
 #define ESCAPE		        27
 #define TAB       		9
@@ -45,6 +45,8 @@ typedef enum
     KEY_GENERIC_HELP,
     KEY_GENERIC_QUIT,
     KEY_GENERIC_SAVE,
+    KEY_GENERIC_CUT,
+    KEY_GENERIC_PASTE,
     KEY_GENERIC_CHANGE_VIEW,
     KEY_GENERIC_IMPORT,
     KEY_GENERIC_EXPORT,
@@ -107,5 +109,6 @@ void    keys_display_bindings_bar (WINDOW *, binding_t **, int, int);
 void    keys_popup_info (keys_e);
 void    keys_save_bindings (FILE *);
 int     keys_check_missing_bindings (void);
+void    keys_fill_missing (void);
 
 #endif /* CALCURSE_KEYS_H */
diff --git a/src/recur.c b/src/recur.c
index cfc2ff3..b3cfc77 100755
--- a/src/recur.c
+++ b/src/recur.c
@@ -1,8 +1,8 @@
-/*	$calcurse: recur.c,v 1.46 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: recur.c,v 1.47 2009/01/01 17:50:41 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
@@ -38,8 +38,147 @@
 #include "mem.h"
 #include "recur.h"
 
-recur_apoint_llist_t *recur_alist_p;
-struct recur_event_s *recur_elist;
+recur_apoint_llist_t             *recur_alist_p;
+struct recur_event_s             *recur_elist;
+static struct recur_event_s       bkp_cut_recur_event;
+static recur_apoint_llist_node_t  bkp_cut_recur_apoint;
+
+static void
+free_exc (struct days_s **exc)
+{
+  struct days_s *o, **i;
+
+  i = exc;
+  for (o = *exc; o; o = o->next)
+    {
+      *i = o->next;
+      mem_free (o);
+      i = &(*i)->next;
+    }
+  *exc = 0;
+}
+
+static void
+recur_add_exc (struct days_s **exc, long day)
+{
+  struct days_s **i, *o;
+  
+  o = mem_malloc (sizeof (struct days_s));
+  o->st = day;
+  i = exc;
+  for (;;)
+    {
+      if (*i == 0 || (*i)->st > day)
+        {
+          o->next = *i;
+          *i = o;
+          break;
+        }
+      i = &(*i)->next;
+    }
+}
+
+static void
+exc_dup (struct days_s **in, struct days_s *exc)
+{
+  struct days_s *p;
+  
+  for (p = exc; p; p = p->next)
+    recur_add_exc (in, p->st);
+}
+
+void
+recur_event_free_bkp (void)
+{
+  if (bkp_cut_recur_event.mesg)
+    {
+      mem_free (bkp_cut_recur_event.mesg);
+      bkp_cut_recur_event.mesg = 0;
+    }
+  if (bkp_cut_recur_event.note)
+    {
+      mem_free (bkp_cut_recur_event.note);
+      bkp_cut_recur_event.note = 0;
+    }
+  if (bkp_cut_recur_event.rpt)
+    {
+      mem_free (bkp_cut_recur_event.rpt);
+      bkp_cut_recur_event.rpt = 0;
+    }
+  if (bkp_cut_recur_event.exc)
+    {
+      free_exc (&bkp_cut_recur_event.exc);
+      bkp_cut_recur_event.exc = 0;
+    }
+}
+
+void
+recur_apoint_free_bkp (void)
+{
+  if (bkp_cut_recur_apoint.mesg)
+    {
+      mem_free (bkp_cut_recur_apoint.mesg);
+      bkp_cut_recur_apoint.mesg = 0;
+    }
+  if (bkp_cut_recur_apoint.note)
+    {
+      mem_free (bkp_cut_recur_apoint.note);
+      bkp_cut_recur_apoint.note = 0;
+    }
+  if (bkp_cut_recur_apoint.rpt)
+    {
+      mem_free (bkp_cut_recur_apoint.rpt);
+      bkp_cut_recur_apoint.rpt = 0;
+    }
+  if (bkp_cut_recur_apoint.exc)
+    {
+      free_exc (&bkp_cut_recur_apoint.exc);
+      bkp_cut_recur_apoint.exc = 0;
+    }
+}
+
+static void
+recur_event_dup (struct recur_event_s *in, struct recur_event_s *bkp)
+{
+  EXIT_IF (!in || !bkp, _("null pointer"));
+
+  bkp->id = in->id;
+  bkp->day = in->day;
+  bkp->mesg = mem_strdup (in->mesg);
+  
+  bkp->rpt = mem_malloc (sizeof (struct rpt_s));
+  bkp->rpt->type = in->rpt->type;
+  bkp->rpt->freq = in->rpt->freq;
+  bkp->rpt->until = in->rpt->until;
+
+  if (in->exc)
+    exc_dup (&bkp->exc, in->exc);
+
+  if (in->note)
+    bkp->note = mem_strdup (in->note);
+}
+
+static void
+recur_apoint_dup (recur_apoint_llist_node_t *in, recur_apoint_llist_node_t *bkp)
+{
+  EXIT_IF (!in || !bkp, _("null pointer"));
+
+  bkp->start = in->start;
+  bkp->dur = in->dur;
+  bkp->state = in->state;
+  bkp->mesg = mem_strdup (in->mesg);
+  
+  bkp->rpt = mem_malloc (sizeof (struct rpt_s));
+  bkp->rpt->type = in->rpt->type;
+  bkp->rpt->freq = in->rpt->freq;
+  bkp->rpt->until = in->rpt->until;
+
+  if (in->exc)
+    exc_dup (&bkp->exc, in->exc);
+
+  if (in->note)
+    bkp->note = mem_strdup (in->note);
+} 
 
 void
 recur_apoint_llist_init (void)
@@ -49,28 +188,38 @@ recur_apoint_llist_init (void)
   pthread_mutex_init (&(recur_alist_p->mutex), NULL);
 }
 
-static void
-free_exc (struct days_s *exc)
+void
+recur_apoint_llist_free (void)
 {
-  struct days_s *o, **i;
+  recur_apoint_llist_node_t *o, **i;
 
-  i = &exc;
-  for (o = exc; o; o = o->next)
+  i = &recur_alist_p->root;
+  for (o = recur_alist_p->root; o; o = o->next)
     {
       *i = o->next;
+      mem_free (o->mesg);
+      if (o->note)
+        mem_free (o->note);
+      if (o->rpt)
+        mem_free (o->rpt);
+      if (o->exc)
+        {
+          free_exc (&o->exc);
+          o->exc = 0;
+        }
       mem_free (o);
       i = &(*i)->next;
     }
-  mem_free (exc);
+  mem_free (recur_alist_p);
 }
 
 void
-recur_apoint_llist_free (void)
+recur_event_llist_free (void)
 {
-  recur_apoint_llist_node_t *o, **i;
+  struct recur_event_s *o, **i;
 
-  i = &recur_alist_p->root;
-  for (o = recur_alist_p->root; o; o = o->next)
+  i = &recur_elist;
+  for (o = recur_elist; o; o = o->next)
     {
       *i = o->next;
       mem_free (o->mesg);
@@ -79,31 +228,38 @@ recur_apoint_llist_free (void)
       if (o->rpt)
         mem_free (o->rpt);
       if (o->exc)
-        free_exc (o->exc);
+        {
+          free_exc (&o->exc);
+          o->exc = 0;
+        }
       mem_free (o);
       i = &(*i)->next;
     }
-  mem_free (recur_alist_p);
 }
 
 /* Insert a new recursive appointment in the general linked list */
 recur_apoint_llist_node_t *
 recur_apoint_new (char *mesg, char *note, long start, long dur, char state,
-		  int type, int freq, long until, struct days_s *except)
+		  int type, int freq, long until, struct days_s **except)
 {
   recur_apoint_llist_node_t *o, **i;
-  o = (recur_apoint_llist_node_t *)
-      mem_malloc (sizeof (recur_apoint_llist_node_t));
-  o->rpt = (struct rpt_s *) mem_malloc (sizeof (struct rpt_s));
+  
+  o = mem_malloc (sizeof (recur_apoint_llist_node_t));
+  o->rpt = mem_malloc (sizeof (struct rpt_s));
   o->mesg = mem_strdup (mesg);
-  o->note = (note != NULL) ? strdup (note) : NULL;
+  o->note = (note != 0) ? strdup (note) : 0;
   o->start = start;
   o->state = state;
   o->dur = dur;
   o->rpt->type = type;
   o->rpt->freq = freq;
   o->rpt->until = until;
-  o->exc = except;
+  o->exc = 0;
+  if (except && *except)
+    {
+      exc_dup (&o->exc, *except);
+      free_exc (except);
+    }
 
   pthread_mutex_lock (&(recur_alist_p->mutex));
   i = &recur_alist_p->root;
@@ -125,19 +281,26 @@ recur_apoint_new (char *mesg, char *note, long start, long dur, char state,
 /* Insert a new recursive event in the general linked list */
 struct recur_event_s *
 recur_event_new (char *mesg, char *note, long day, int id, int type, int freq,
-		 long until, struct days_s *except)
+		 long until, struct days_s **except)
 {
   struct recur_event_s *o, **i;
-  o = (struct recur_event_s *) mem_malloc (sizeof (struct recur_event_s));
-  o->rpt = (struct rpt_s *) mem_malloc (sizeof (struct rpt_s));
+  
+  o = mem_malloc (sizeof (struct recur_event_s));
+  o->rpt = mem_malloc (sizeof (struct rpt_s));
   o->mesg = mem_strdup (mesg);
-  (void)strncpy (o->mesg, mesg, strlen (mesg) + 1);
+  o->note = (note != 0) ? strdup (note) : 0;  
   o->day = day;
   o->id = id;
   o->rpt->type = type;
   o->rpt->freq = freq;
   o->rpt->until = until;
-  o->exc = except;
+  o->exc = 0;
+  if (except && *except)
+    {
+      exc_dup (&o->exc, *except);
+      free_exc (except);
+    }
+
   i = &recur_elist;
   for (;;)
     {
@@ -236,7 +399,7 @@ recur_write_exc (struct days_s *exc, FILE *f)
 /* Load the recursive appointment description */
 recur_apoint_llist_node_t *
 recur_apoint_scan (FILE *f, struct tm start, struct tm end, char type,
-		   int freq, struct tm until, char *note, struct days_s *exc,
+		   int freq, struct tm until, char *note, struct days_s **exc,
 		   char state)
 {
   struct tm *lt;
@@ -286,14 +449,10 @@ recur_apoint_scan (FILE *f, struct tm start, struct tm end, char type,
 /* Load the recursive events from file */
 struct recur_event_s *
 recur_event_scan (FILE *f, struct tm start, int id, char type, int freq,
-		  struct tm until, char *note, struct days_s *exc)
+		  struct tm until, char *note, struct days_s **exc)
 {
-  struct tm *lt;
   char buf[MESG_MAXSIZE], *nl;
-  time_t tstart, t, tuntil;
-
-  t = time (NULL);
-  lt = localtime (&t);
+  time_t tstart, tuntil;
 
   /* Read the event description */
   (void)fgets (buf, MESG_MAXSIZE, f);
@@ -322,8 +481,8 @@ recur_event_scan (FILE *f, struct tm start, int id, char type, int freq,
   EXIT_IF (tstart == -1 || tuntil == -1,
            _("date error in event"));
 
-  return (recur_event_new (buf, note, tstart, id, recur_char2def (type),
-                           freq, tuntil, exc));
+  return recur_event_new (buf, note, tstart, id, recur_char2def (type),
+                          freq, tuntil, exc);
 }
 
 /* Writting of a recursive appointment into file. */
@@ -519,7 +678,6 @@ recur_event_erase (long start, unsigned num, unsigned delete_whole,
 {
   unsigned n = 0;
   struct recur_event_s *i, **iptr;
-  struct days_s *o, **j;
 
   iptr = &recur_elist;
   for (i = recur_elist; i != 0; i = i->next)
@@ -531,34 +689,33 @@ recur_event_erase (long start, unsigned num, unsigned delete_whole,
 	    {
 	      if (delete_whole)
 		{
-		  if (flag == ERASE_FORCE_ONLY_NOTE)
-		    erase_note (&i->note, flag);
-		  else
-		    {
+                  switch (flag)
+                    {
+                    case ERASE_FORCE_ONLY_NOTE:
+                      erase_note (&i->note, flag);                      
+                      break;
+                    case ERASE_CUT:
+                      recur_event_free_bkp ();
+                      recur_event_dup (i, &bkp_cut_recur_event);
+                      if (i->note)
+                        mem_free (i->note);
+                      /* FALLTHROUGH */
+                    default:
 		      *iptr = i->next;
 		      mem_free (i->mesg);
 		      mem_free (i->rpt);
-		      mem_free (i->exc);
-		      erase_note (&i->note, flag);
+		      free_exc (&i->exc);
+                      i->exc = 0;
+                      if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
+                        erase_note (&i->note, flag);
 		      mem_free (i);
+                      break;
 		    }
 		  return;
 		}
 	      else
 		{
-		  o = (struct days_s *) mem_malloc (sizeof (struct days_s));
-		  o->st = start;
-		  j = &i->exc;
-		  for (;;)
-		    {
-		      if (*j == 0 || (*j)->st > start)
-			{
-			  o->next = *j;
-			  *j = o;
-			  break;
-			}
-		      j = &(*j)->next;
-		    }
+                  recur_add_exc (&i->exc, start);
 		  return;
 		}
 	    }
@@ -580,7 +737,6 @@ recur_apoint_erase (long start, unsigned num, unsigned delete_whole,
 {
   unsigned n = 0;
   recur_apoint_llist_node_t *i, **iptr;
-  struct days_s *o, **j;
   int need_check_notify = 0;
 
   pthread_mutex_lock (&(recur_alist_p->mutex));
@@ -596,37 +752,36 @@ recur_apoint_erase (long start, unsigned num, unsigned delete_whole,
 		need_check_notify = notify_same_recur_item (i);
 	      if (delete_whole)
 		{
-		  if (flag == ERASE_FORCE_ONLY_NOTE)
-		    erase_note (&i->note, flag);
-		  else
-		    {
+                  switch (flag)
+                    {
+                    case ERASE_FORCE_ONLY_NOTE:
+                      erase_note (&i->note, flag);
+                      break;
+                    case ERASE_CUT:
+                      recur_apoint_free_bkp ();
+                      recur_apoint_dup (i, &bkp_cut_recur_apoint);
+                      if (i->note)
+                        mem_free (i->note);
+                      /* FALLTHROUGH */
+                    default:
 		      *iptr = i->next;
 		      mem_free (i->mesg);
 		      mem_free (i->rpt);
-		      mem_free (i->exc);
-		      erase_note (&i->note, flag);
+		      free_exc (&i->exc);
+                      i->exc = 0;
+                      if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT)
+                        erase_note (&i->note, flag);
 		      mem_free (i);
 		      pthread_mutex_unlock (&(recur_alist_p->mutex));
 		      if (need_check_notify)
 			notify_check_next_app ();
+                      break;
 		    }
 		  return;
 		}
 	      else
 		{
-		  o = (struct days_s *) mem_malloc (sizeof (struct days_s));
-		  o->st = start;
-		  j = &i->exc;
-		  for (;;)
-		    {
-		      if (*j == 0 || (*j)->st > start)
-			{
-			  o->next = *j;
-			  *j = o;
-			  break;
-			}
-		      j = &(*j)->next;
-		    }
+                  recur_add_exc (&i->exc, start);
 		  pthread_mutex_unlock (&(recur_alist_p->mutex));
 		  if (need_check_notify)
 		    notify_check_next_app ();
@@ -800,14 +955,10 @@ struct days_s *
 recur_exc_scan (FILE *data_file)
 {
   int c = 0;
-  struct tm *lt, day;
-  time_t t;
+  struct tm day;
   struct days_s *exc_head, *exc;
 
-  exc_head = NULL;
-  t = time (NULL);
-  lt = localtime (&t);
-  day = *lt;
+  exc_head = 0;
   while ((c = getc (data_file)) == '!')
     {
       (void)ungetc (c, data_file);
@@ -816,16 +967,17 @@ recur_exc_scan (FILE *data_file)
 	{
           EXIT (_("syntax error in item date"));
 	}
-      day.tm_sec = 0;
+      day.tm_hour = 12;
+      day.tm_min = day.tm_sec = 0;
       day.tm_isdst = -1;
       day.tm_year -= 1900;
       day.tm_mon--;
-      exc = (struct days_s *) mem_malloc (sizeof (struct days_s));
+      exc = mem_malloc (sizeof (struct days_s));
       exc->st = mktime (&day);
       exc->next = exc_head;
       exc_head = exc;
     }
-  return (exc_head);
+  return exc_head;
 }
 
 /*
@@ -950,3 +1102,61 @@ recur_apoint_switch_notify (long date, int recur_nb)
   /* NOTREACHED */
 }
 
+void
+recur_event_paste_item (void)
+{
+  long new_start, time_shift;
+
+  new_start = date2sec (*calendar_get_slctd_day (), 12, 0);
+  time_shift = new_start - bkp_cut_recur_event.day;
+
+  bkp_cut_recur_event.day += time_shift;
+  if (bkp_cut_recur_event.rpt->until != 0)
+    bkp_cut_recur_event.rpt->until += time_shift;
+  if (bkp_cut_recur_event.exc)
+    {
+      struct days_s *exc;
+      
+      for (exc = bkp_cut_recur_event.exc; exc != 0; exc = exc->next)
+        exc->st += time_shift;
+    }
+  
+  (void)recur_event_new (bkp_cut_recur_event.mesg, bkp_cut_recur_event.note,
+                         bkp_cut_recur_event.day, bkp_cut_recur_event.id,
+                         bkp_cut_recur_event.rpt->type,
+                         bkp_cut_recur_event.rpt->freq,
+                         bkp_cut_recur_event.rpt->until,
+                         &bkp_cut_recur_event.exc);
+  recur_event_free_bkp ();
+}
+
+void
+recur_apoint_paste_item (void)
+{
+  long new_start, time_shift;
+
+  new_start = date2sec (*calendar_get_slctd_day (),
+                        get_item_hour (bkp_cut_recur_apoint.start),
+                        get_item_min (bkp_cut_recur_apoint.start));
+  time_shift = new_start - bkp_cut_recur_apoint.start;
+
+  bkp_cut_recur_apoint.start += time_shift;
+  if (bkp_cut_recur_apoint.rpt->until != 0)
+    bkp_cut_recur_apoint.rpt->until += time_shift;
+  if (bkp_cut_recur_apoint.exc)
+    {
+      struct days_s *exc;
+      
+      for (exc = bkp_cut_recur_apoint.exc; exc != 0; exc = exc->next)
+        exc->st += time_shift;
+    }
+  
+  (void)recur_apoint_new (bkp_cut_recur_apoint.mesg, bkp_cut_recur_apoint.note,
+                          bkp_cut_recur_apoint.start, bkp_cut_recur_apoint.dur,
+                          bkp_cut_recur_apoint.state,
+                          bkp_cut_recur_apoint.rpt->type,
+                          bkp_cut_recur_apoint.rpt->freq,
+                          bkp_cut_recur_apoint.rpt->until,
+                          &bkp_cut_recur_apoint.exc);
+  recur_apoint_free_bkp ();
+}
diff --git a/src/recur.h b/src/recur.h
index 84f5226..60231f2 100755
--- a/src/recur.h
+++ b/src/recur.h
@@ -1,8 +1,8 @@
-/*	$calcurse: recur.h,v 1.24 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: recur.h,v 1.25 2009/01/01 17:50:41 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
@@ -86,20 +86,23 @@ typedef void (*recur_cb_foreach_date_t)(FILE *, long, char *);
 extern recur_apoint_llist_t *recur_alist_p;
 extern struct recur_event_s *recur_elist;
 
+void                       recur_event_free_bkp (void);
+void                       recur_apoint_free_bkp (void);
 void                       recur_apoint_llist_init (void);
 void                       recur_apoint_llist_free (void);
+void                       recur_event_llist_free (void);
 recur_apoint_llist_node_t *recur_apoint_new (char *, char *, long, long, char,
-                                             int, int, long, struct days_s *);
+                                             int, int, long, struct days_s **);
 struct recur_event_s      *recur_event_new (char *, char *, long, int, int, int,
-                                            long, struct days_s *);
+                                            long, struct days_s **);
 char                       recur_def2char (recur_types_t);
 int                        recur_char2def (char);
 recur_apoint_llist_node_t *recur_apoint_scan (FILE *, struct tm, struct tm,
 					      char, int, struct tm, char *,
-					      struct days_s *, char);
+					      struct days_s **, char);
 struct recur_event_s      *recur_event_scan (FILE *, struct tm, int, char,
                                              int, struct tm, char *,
-                                             struct days_s *);
+                                             struct days_s **);
 void                       recur_save_data (FILE *);
 unsigned                   recur_item_inday (long, struct days_s *, int, int,
                                              long, long);
@@ -114,5 +117,7 @@ struct notify_app_s       *recur_apoint_check_next (struct notify_app_s *,
 recur_apoint_llist_node_t *recur_get_apoint (long, int);
 struct recur_event_s      *recur_get_event (long, int);
 void                       recur_apoint_switch_notify (long, int);
+void                       recur_event_paste_item (void);
+void                       recur_apoint_paste_item (void);
 
 #endif /* CALCURSE_RECUR_H */
diff --git a/src/utils.c b/src/utils.c
index cee945f..87f2a16 100755
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,8 +1,8 @@
-/*	$calcurse: utils.c,v 1.63 2008/12/28 19:41:45 culot Exp $	*/
+/*	$calcurse: utils.c,v 1.64 2009/01/01 17:50:41 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
@@ -42,6 +42,7 @@
 #include "keys.h"
 #include "io.h"
 #include "recur.h"
+#include "event.h"
 #include "apoint.h"
 #include "todo.h"
 #include "day.h"
@@ -50,7 +51,7 @@
 #include "mem.h"
 
 #define NB_CAL_CMDS	24	/* number of commands while in cal view */
-#define NB_APP_CMDS	29	/* same thing while in appointment view */
+#define NB_APP_CMDS	31	/* same thing while in appointment view */
 #define NB_TOD_CMDS	29	/* same thing while in todo view */
 #define TOTAL_CMDS	NB_CAL_CMDS + NB_APP_CMDS + NB_TOD_CMDS
 #define CMDS_PER_LINE	6	/* max number of commands per line */  
@@ -75,8 +76,14 @@ exit_calcurse (int status)
   notify_free_bar ();
   day_saved_item_free ();
   day_free_list ();
+  event_llist_free ();
+  event_free_bkp ();
   apoint_llist_free ();
+  apoint_free_bkp ();
   recur_apoint_llist_free ();
+  recur_event_llist_free ();
+  recur_apoint_free_bkp ();
+  recur_event_free_bkp ();
   todo_free_list ();
   keys_free ();
   mem_stats ();
@@ -415,7 +422,7 @@ is_all_digit (char *string)
       digit++;
   if (digit == strlen (string))
     all_digit = 1;
-  return (all_digit);
+  return all_digit;
 }
 
 /* 
@@ -436,6 +443,8 @@ status_bar (void)
   binding_t help   = {_("Help"),     KEY_GENERIC_HELP};
   binding_t quit   = {_("Quit"),     KEY_GENERIC_QUIT};
   binding_t save   = {_("Save"),     KEY_GENERIC_SAVE};
+  binding_t cut    = {_("Cut"),      KEY_GENERIC_CUT};
+  binding_t paste  = {_("Paste"),    KEY_GENERIC_PASTE};    
   binding_t chgvu  = {_("Chg View"), KEY_GENERIC_CHANGE_VIEW};
   binding_t import = {_("Import"),   KEY_GENERIC_IMPORT};  
   binding_t export = {_("Export"),   KEY_GENERIC_EXPORT};
@@ -465,7 +474,8 @@ status_bar (void)
   binding_t enote  = {_("EditNote"), KEY_EDIT_NOTE};
   binding_t vnote  = {_("ViewNote"), KEY_VIEW_NOTE};
   binding_t rprio  = {_("Prio.+"),   KEY_RAISE_PRIORITY};
-  binding_t lprio  = {_("Prio.-"),   KEY_LOWER_PRIORITY};  
+  binding_t lprio  = {_("Prio.-"),   KEY_LOWER_PRIORITY};
+
   
   binding_t *binding[TOTAL_CMDS] = {
     /* calendar keys */
@@ -475,7 +485,8 @@ status_bar (void)
     /* appointment keys */
     &help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view,
     &draw, &othr, &rept, &flag, &enote, &vnote, &up, &down, &gnday, &gpday,
-    &gnweek, &gpweek, &togo, &othr, &today, &conf, &appt, &todo, &othr,
+    &gnweek, &gpweek, &togo, &othr, &today, &conf, &appt, &todo, &cut, &paste,
+    &othr,
     /* todo keys */
     &help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view,
     &draw, &othr, &rprio, &lprio, &enote, &vnote, &up, &down, &gnday, &gpday,
@@ -489,6 +500,38 @@ status_bar (void)
   keys_display_bindings_bar (win[STA].p, binding, start, end);
 }
 
+/* Given an item date expressed in seconds, return its start time in seconds. */
+long
+get_item_time (long date)
+{
+  return (long)(get_item_hour (date) * HOURINSEC
+                + get_item_min (date) * MININSEC);
+}
+
+int
+get_item_hour (long date)
+{
+  struct tm *lt;
+  time_t t;
+
+  t = (time_t)date;
+  lt = localtime (&t);
+
+  return lt->tm_hour;
+}
+
+int
+get_item_min (long date)
+{
+  struct tm *lt;
+  time_t t;
+
+  t = (time_t)date;
+  lt = localtime (&t);
+
+  return lt->tm_min;
+}
+
 long
 date2sec (date_t day, unsigned hour, unsigned min)
 {
@@ -511,7 +554,7 @@ date2sec (date_t day, unsigned hour, unsigned min)
   tstart = mktime (&start);
   EXIT_IF (tstart == -1, _("failure in mktime"));
 
-  return (tstart);
+  return tstart;
 }
 
 /* Return a string containing the hour of a given date in seconds. */
@@ -527,7 +570,7 @@ date_sec2hour_str (long sec)
   lt = localtime (&t);
   timestr = (char *) mem_malloc (TIME_LEN);
   (void)snprintf (timestr, TIME_LEN, "%02u:%02u", lt->tm_hour, lt->tm_min);
-  return (timestr);
+  return timestr;
 }
 
 /* Return a string containing the date, given a date in seconds. */
diff --git a/src/utils.h b/src/utils.h
index 0be7d85..6f4b13c 100755
--- a/src/utils.h
+++ b/src/utils.h
@@ -1,8 +1,8 @@
-/*	$calcurse: utils.h,v 1.41 2008/12/28 13:13:59 culot Exp $	*/
+/*	$calcurse: utils.h,v 1.42 2009/01/01 17:50:41 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
@@ -96,42 +96,46 @@ typedef enum
   ERASE_DONT_FORCE,
   ERASE_FORCE,
   ERASE_FORCE_KEEP_NOTE,
-  ERASE_FORCE_ONLY_NOTE
+  ERASE_FORCE_ONLY_NOTE,
+  ERASE_CUT
 }
 erase_flag_e;
 
-void    exit_calcurse (int);
-void    fatalbox (const char *);
-void    status_mesg (char *, char *);
-void    erase_status_bar (void);
-void    erase_window_part (WINDOW *, int, int, int, int);
-WINDOW *popup (int, int, int, int, char *, char *, int);
-void    print_in_middle (WINDOW *, int, int, int, char *);
-int     getstring (WINDOW *, char *, int, int, int);
-int     updatestring (WINDOW *, char **, int, int);
-int     is_all_digit (char *);
-void    status_bar (void);
-long    date2sec (date_t, unsigned, unsigned);
-char   *date_sec2hour_str (long);
-char   *date_sec2date_str (long, char *);
-void    date_sec2date_fmt (long, const char *, char *);
-long    date_sec_change (long, int, int);
-long    update_time_in_date (long, unsigned, unsigned);
-long    get_sec_date (date_t);
-long    min2sec (unsigned);
-int     check_time (char *);
-void    draw_scrollbar (WINDOW *, int, int, int, int, int, bool);
-void    item_in_popup (char *, char *, char *, char *);
-void    reset_status_page (void);
-void    other_status_page (int);
-long    get_today (void);
-long    now (void);
-long    mystrtol (const char *);
-void    print_bool_option_incolor (WINDOW *, bool, int, int);
-char   *new_tempfile (const char *, int);
-void    erase_note (char **, erase_flag_e);
-int     parse_date (char *, int, int *, int *, int *);
-char   *str_toupper (char *);
-void    file_close (FILE *, const char *);
+void      exit_calcurse (int);
+void      fatalbox (const char *);
+void      status_mesg (char *, char *);
+void      erase_status_bar (void);
+void      erase_window_part (WINDOW *, int, int, int, int);
+WINDOW   *popup (int, int, int, int, char *, char *, int);
+void      print_in_middle (WINDOW *, int, int, int, char *);
+int       getstring (WINDOW *, char *, int, int, int);
+int       updatestring (WINDOW *, char **, int, int);
+int       is_all_digit (char *);
+void      status_bar (void);
+long      get_item_time (long);
+int       get_item_hour (long);
+int       get_item_min (long);
+long      date2sec (date_t, unsigned, unsigned);
+char     *date_sec2hour_str (long);
+char     *date_sec2date_str (long, char *);
+void      date_sec2date_fmt (long, const char *, char *);
+long      date_sec_change (long, int, int);
+long      update_time_in_date (long, unsigned, unsigned);
+long      get_sec_date (date_t);
+long      min2sec (unsigned);
+int       check_time (char *);
+void      draw_scrollbar (WINDOW *, int, int, int, int, int, bool);
+void      item_in_popup (char *, char *, char *, char *);
+void      reset_status_page (void);
+void      other_status_page (int);
+long      get_today (void);
+long      now (void);
+long      mystrtol (const char *);
+void      print_bool_option_incolor (WINDOW *, bool, int, int);
+char     *new_tempfile (const char *, int);
+void      erase_note (char **, erase_flag_e);
+int       parse_date (char *, int, int *, int *, int *);
+char     *str_toupper (char *);
+void      file_close (FILE *, const char *);
 
 #endif /* CALCURSE_UTILS_H */
-- 
cgit v1.2.3-70-g09d2