From cac30a7e1469a8f061f64712dbea100a012dd788 Mon Sep 17 00:00:00 2001 From: Frederic Culot 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-54-g00ecf