From 738a3a417071bfaed53297cbefad39b996e55dfb Mon Sep 17 00:00:00 2001 From: Frederic Culot Date: Sun, 13 Jan 2008 12:40:45 +0000 Subject: Ability to attach notes to appointments and events added --- ChangeLog | 3 + src/apoint.c | 73 ++++++++++---------- src/apoint.h | 12 ++-- src/calcurse.c | 8 +-- src/day.c | 207 +++++++++++++++++++++++++++++++++++++++++---------------- src/day.h | 7 +- src/event.c | 33 ++++++--- src/event.h | 10 +-- src/io.c | 31 ++++++--- src/recur.c | 138 +++++++++++++++++++++++--------------- src/recur.h | 25 ++++--- src/todo.c | 13 +--- src/utils.c | 21 +++++- src/utils.h | 5 +- 14 files changed, 378 insertions(+), 208 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1efc89b..10af4c4 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +13 Jan 2008: + Ability to attach notes to appointments and events added + 31 Dec 2007: Notes attached to todos can now be suppressed diff --git a/src/apoint.c b/src/apoint.c index d963cd8..03573e6 100755 --- a/src/apoint.c +++ b/src/apoint.c @@ -1,8 +1,8 @@ -/* $calcurse: apoint.c,v 1.19 2007/12/30 16:27:58 culot Exp $ */ +/* $calcurse: apoint.c,v 1.20 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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,7 +43,8 @@ apoint_llist_t *alist_p; static int hilt = 0; -int apoint_llist_init(void) +int +apoint_llist_init(void) { alist_p = (apoint_llist_t *) malloc(sizeof(apoint_llist_t)); alist_p->root = NULL; @@ -79,13 +80,14 @@ apoint_hilt(void) } apoint_llist_node_t * -apoint_new(char *mesg, long start, long dur, char state) +apoint_new(char *mesg, char *note, long start, long dur, char state) { apoint_llist_node_t *o, **i; o = (apoint_llist_node_t *) malloc(sizeof(apoint_llist_node_t)); o->mesg = (char *) malloc(strlen(mesg) + 1); strncpy(o->mesg, mesg, strlen(mesg) + 1); + o->note = note; o->state = state; o->start = start; o->dur = dur; @@ -192,12 +194,12 @@ apoint_add(void) apoint_start = date2sec(*calendar_get_slctd_day(), heures, minutes); - apoint_pointeur = apoint_new(item_mesg, apoint_start, + apoint_pointeur = apoint_new(item_mesg, 0L, apoint_start, min2sec(apoint_duration), 0L); if (notify_bar()) notify_check_added(item_mesg, apoint_start, 0L); } else - event_pointeur = event_new(item_mesg, + event_pointeur = event_new(item_mesg, 0L, date2sec(*calendar_get_slctd_day(), 12, 0), Id); if (hilt == 0) @@ -317,6 +319,9 @@ apoint_write(apoint_llist_node_t *o, FILE * f) lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, lt->tm_hour, lt->tm_min); + if (o->note != NULL) + fprintf(f, ">%s ", o->note); + if (o->state & APOINT_NOTIFY) fprintf(f, "!"); else @@ -326,7 +331,7 @@ apoint_write(apoint_llist_node_t *o, FILE * f) } apoint_llist_node_t * -apoint_scan(FILE * f, struct tm start, struct tm end, char state) +apoint_scan(FILE * f, struct tm start, struct tm end, char state, char *note) { struct tm *lt; char buf[MESG_MAXSIZE], *nl; @@ -355,29 +360,37 @@ apoint_scan(FILE * f, struct tm start, struct tm end, char state) fputs(_("FATAL ERROR in apoint_scan: date error in the appointment\n"), stderr); exit(EXIT_FAILURE); } - return apoint_new(buf, tstart, tend - tstart, state); + return (apoint_new(buf, note, tstart, tend - tstart, state)); } -void apoint_delete_bynum(long start, unsigned num) +void +apoint_delete_bynum(long start, unsigned num, int only_note) { unsigned n; int need_check_notify = 0; apoint_llist_node_t *i, **iptr; - n = 0; - + n = 0; pthread_mutex_lock(&(alist_p->mutex)); iptr = &alist_p->root; for (i = alist_p->root; i != 0; i = i->next) { if (apoint_inday(i, start)) { if (n == num) { - if (notify_bar()) - need_check_notify = notify_same_item(i->start); - *iptr = i->next; - free(i->mesg); - free(i); - pthread_mutex_unlock(&(alist_p->mutex)); - if (need_check_notify) notify_check_next_app(); + if (only_note) + erase_note(&i->note); + else { + if (notify_bar()) + need_check_notify = + notify_same_item(i->start); + *iptr = i->next; + free(i->mesg); + if (i->note != NULL) + erase_note(&i->note); + free(i); + pthread_mutex_unlock(&(alist_p->mutex)); + if (need_check_notify) + notify_check_next_app(); + } return; } n++; @@ -414,7 +427,8 @@ get_item_line(int item_nb, int nb_events_inday) * Update (if necessary) the first displayed pad line to make the * appointment panel scroll down next time pnoutrefresh is called. */ -void apoint_scroll_pad_down(int nb_events_inday, int win_length) +void +apoint_scroll_pad_down(int nb_events_inday, int win_length) { int pad_last_line = 0; int item_first_line = 0, item_last_line = 0; @@ -435,7 +449,8 @@ void apoint_scroll_pad_down(int nb_events_inday, int win_length) * Update (if necessary) the first displayed pad line to make the * appointment panel scroll up next time pnoutrefresh is called. */ -void apoint_scroll_pad_up(int nb_events_inday) +void +apoint_scroll_pad_up(int nb_events_inday) { int item_first_line = 0; @@ -476,8 +491,8 @@ apoint_check_next(struct notify_app_s *app, long start) * Returns a structure of type apoint_llist_t given a structure of type * recur_apoint_s */ -apoint_llist_node_t *apoint_recur_s2apoint_s( - recur_apoint_llist_node_t *p) +apoint_llist_node_t * +apoint_recur_s2apoint_s(recur_apoint_llist_node_t *p) { apoint_llist_node_t *a; @@ -589,17 +604,3 @@ apoint_update_panel(window_t *winapp, int which_pan) winapp->y + title_lines + 1, winapp->x + bordr, winapp->y + winapp->h - 2*bordr, winapp->x + winapp->w - 3*bordr); } - -/* Attach a note to an appointment or event */ -void -apoint_edit_note(void) -{ - -} - -/* View a note previously attached to an appointment or event */ -void -apoint_view_note(void) -{ - -} diff --git a/src/apoint.h b/src/apoint.h index 182f03d..3f5d704 100755 --- a/src/apoint.h +++ b/src/apoint.h @@ -1,8 +1,8 @@ -/* $calcurse: apoint.h,v 1.10 2007/12/30 16:27:58 culot Exp $ */ +/* $calcurse: apoint.h,v 1.11 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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,22 +59,20 @@ void apoint_hilt_set(int); void apoint_hilt_decrease(void); void apoint_hilt_increase(void); int apoint_hilt(void); -apoint_llist_node_t *apoint_new(char *, long, long, char); +apoint_llist_node_t *apoint_new(char *, char *, long, long, char); void apoint_add(void); void apoint_delete(conf_t *, unsigned *, unsigned *); unsigned apoint_inday(apoint_llist_node_t *, long); void apoint_sec2str(apoint_llist_node_t *, int, long, char *, char *); void apoint_write(apoint_llist_node_t *, FILE *); -apoint_llist_node_t *apoint_scan(FILE *, struct tm, struct tm, char); -void apoint_delete_bynum(long, unsigned); +apoint_llist_node_t *apoint_scan(FILE *, struct tm, struct tm, char, char *); +void apoint_delete_bynum(long, unsigned, int); void apoint_scroll_pad_down(int, int); void apoint_scroll_pad_up(int); 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(window_t *, int); -void apoint_edit_note(void); -void apoint_view_note(void); #endif /* CALCURSE_APOINT_H */ diff --git a/src/calcurse.c b/src/calcurse.c index ab25298..d004ae8 100755 --- a/src/calcurse.c +++ b/src/calcurse.c @@ -1,8 +1,8 @@ -/* $calcurse: calcurse.c,v 1.59 2007/12/30 16:27:58 culot Exp $ */ +/* $calcurse: calcurse.c,v 1.60 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -350,7 +350,7 @@ main(int argc, char **argv) case 'n': /* Attach a note to an item, create it if necessary */ if (wins_slctd() == APP && apoint_hilt() != 0) - apoint_edit_note(); + day_edit_note(conf.editor); else if (wins_slctd() == TOD && todo_hilt() != 0) todo_edit_note(conf.editor); do_storage = true; @@ -359,7 +359,7 @@ main(int argc, char **argv) case '>': /* View a note previously attached to an item */ if (wins_slctd() == APP && apoint_hilt() != 0) - apoint_view_note(); + day_view_note(conf.pager); else if (wins_slctd() == TOD && todo_hilt() != 0) todo_view_note(conf.pager); break; diff --git a/src/day.c b/src/day.c index 0d27bee..052bda2 100755 --- a/src/day.c +++ b/src/day.c @@ -1,8 +1,8 @@ -/* $calcurse: day.c,v 1.31 2007/12/30 16:27:59 culot Exp $ */ +/* $calcurse: day.c,v 1.32 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -56,12 +56,13 @@ day_free_list(void) /* Add an event in the current day list */ static struct day_item_s * -day_add_event(int type, char *mesg, long day, int id) +day_add_event(int type, char *mesg, char *note, long day, int id) { struct day_item_s *o, **i; o = (struct day_item_s *) malloc(sizeof(struct day_item_s)); o->mesg = (char *) malloc(strlen(mesg) + 1); strncpy(o->mesg, mesg, strlen(mesg) + 1); + o->note = note; o->type = type; o->appt_dur = 0; o->appt_pos = 0; @@ -81,8 +82,8 @@ day_add_event(int type, char *mesg, long day, int id) /* Add an appointment in the current day list. */ static struct day_item_s * -day_add_apoint(int type, char *mesg, long start, long dur, char state, - int real_pos) +day_add_apoint(int type, char *mesg, char *note, long start, long dur, + char state, int real_pos) { struct day_item_s *o, **i; int insert_item = 0; @@ -90,6 +91,7 @@ day_add_apoint(int type, char *mesg, long start, long dur, char state, o = (struct day_item_s *) malloc(sizeof(struct day_item_s)); o->mesg = (char *) malloc(strlen(mesg) + 1); strncpy(o->mesg, mesg, strlen(mesg) + 1); + o->note = note; o->start = start; o->appt_dur = dur; o->appt_pos = real_pos; @@ -131,7 +133,8 @@ day_store_events(long date) for (j = eventlist; j != 0; j = j->next) { if (event_inday(j, date)) { e_nb++; - ptr = day_add_event(EVNT, j->mesg, j->day, j->id); + ptr = day_add_event(EVNT, j->mesg, j->note, j->day, + j->id); } } @@ -154,9 +157,10 @@ day_store_recur_events(long date) for (j = recur_elist; j != 0; j = j->next) { if (recur_item_inday(j->day, j->exc, j->rpt->type, j->rpt->freq, - j->rpt->until, date)) { + j->rpt->until, date)) { e_nb++; - ptr = day_add_event(RECUR_EVNT, j->mesg, j->day, j->id); + ptr = day_add_event(RECUR_EVNT, j->mesg, j->note, + j->day, j->id); } } @@ -181,8 +185,8 @@ day_store_apoints(long date) for (j = alist_p->root; j != 0; j = j->next) { if (apoint_inday(j, date)) { a_nb++; - ptr = day_add_apoint(APPT, j->mesg, j->start, j->dur, - j->state, 0); + ptr = day_add_apoint(APPT, j->mesg, j->note, j->start, + j->dur, j->state, 0); } } pthread_mutex_unlock(&(alist_p->mutex)); @@ -210,9 +214,8 @@ day_store_recur_apoints(long date) if ((real_start = recur_item_inday(j->start, j->exc, j->rpt->type, j->rpt->freq, j->rpt->until, date)) ){ a_nb++; - ptr = day_add_apoint( - RECUR_APPT, j->mesg, real_start, j->dur, - j->state, n); + ptr = day_add_apoint(RECUR_APPT, j->mesg, j->note, + real_start, j->dur, j->state, n); n++; } } @@ -397,8 +400,8 @@ day_write_pad(long date, int width, int length, int incolor) day_saved_item->type = p->type; day_saved_item->mesg = p->mesg; } - display_item(item_number - incolor, p->mesg, recur, 0, - width - 7, line, x_pos); + display_item(item_number - incolor, p->mesg, recur, + (p->note != NULL) ? 1 : 0, width - 7, line, x_pos); line++; draw_line = true; } else { @@ -420,9 +423,10 @@ day_write_pad(long date, int width, int length, int incolor) } display_item_date(item_number - incolor, &a, p->type, date, line + 1, x_pos); - display_item(item_number - incolor, p->mesg, 0, 0, - width - 7, line + 2, x_pos); - line = line + 3; + display_item(item_number - incolor, p->mesg, 0, + (p->note != NULL) ? 1 : 0, width - 7, line + 2, + x_pos); + line += 3; } } } @@ -448,7 +452,7 @@ void day_popup_item(void) * Need to know if there is an item for the current selected day inside * calendar. This is used to put the correct colors inside calendar panel. */ - int day_check_if_item(date_t day) { +int day_check_if_item(date_t day) { struct recur_event_s *re; recur_apoint_llist_node_t *ra; struct event_s *e; @@ -485,9 +489,41 @@ void day_popup_item(void) return 0; } +/* Update an existing item. */ +static void update_item(long date, int item_num, struct day_item_s *p, + struct rpt_s *rpt) +{ + recur_apoint_llist_node_t *ra_new; + + day_erase_item(date, item_num, 1); + + switch (p->type) { + case RECUR_EVNT: + recur_event_new(p->mesg, p->note, p->start, p->evnt_id, + rpt->type, rpt->freq, rpt->until, NULL); + break; + case EVNT: + event_new(p->mesg, p->note, p->start, p->evnt_id); + break; + case RECUR_APPT: + ra_new = recur_apoint_new(p->mesg, p->note, p->start, + p->appt_dur, p->state, rpt->type, rpt->freq, rpt->until, + NULL); + if (notify_bar()) + notify_check_repeated(ra_new); + break; + case APPT: + apoint_new(p->mesg, p->note, p->start, p->appt_dur, p->state); + if (notify_bar()) + notify_check_added(p->mesg, p->start, p->state); + break; + } +} + /* Request the user to enter a new time. */ static char * -day_edit_time(long time) { +day_edit_time(long time) +{ char *timestr; char *msg_time = _("Enter the new time ([hh:mm] or [h:mm]) : "); char *enter_str = _("Press [Enter] to continue"); @@ -521,7 +557,7 @@ day_edit_item(void) struct tm *lt; time_t t; date_t new_date; - recur_apoint_llist_node_t *ra, *ra_new; + recur_apoint_llist_node_t *ra; long date, newtime = 0; int cancel, ch = 0, valid_date = 0, newfreq = 0, date_entered = 0; int newmonth, newday, newyear; @@ -697,28 +733,7 @@ day_edit_item(void) rpt->type = recur_char2def(ch); break; } - day_erase_item(date, item_num, 1); - - switch (p->type) { - case RECUR_EVNT: - recur_event_new(p->mesg, p->start, p->evnt_id, - rpt->type, rpt->freq, rpt->until, NULL); - break; - case EVNT: - event_new(p->mesg, p->start, p->evnt_id); - break; - case RECUR_APPT: - ra_new = recur_apoint_new(p->mesg, p->start, p->appt_dur, - p->state, rpt->type, rpt->freq, rpt->until, NULL); - if (notify_bar()) - notify_check_repeated(ra_new); - break; - case APPT: - apoint_new(p->mesg, p->start, p->appt_dur, p->state); - if (notify_bar()) - notify_check_added(p->mesg, p->start, p->state); - break; - } + update_item(date, item_num, p, rpt); } /* @@ -727,26 +742,48 @@ day_edit_item(void) * recurrent appointments and appointments) and then to test the * type of the item to be deleted. */ -int day_erase_item(long date, int item_number, int force_erase) { - int ch = 0; - unsigned delete_whole; +int +day_erase_item(long date, int item_number, int force_erase) +{ struct day_item_s *p; char *erase_warning = _("This item is recurrent. " "Delete (a)ll occurences or just this (o)ne ?"); - char *erase_choice = - _("[a/o] "); + char *note_warning = + _("This item has a note attached to it. " + "Delete (i)tem or just its (n)ote ?"); + char *note_choice = _("[i/n] "); + char *erase_choice = _("[a/o] "); + int ch = 0, only_note, has_note, ans = 0; + unsigned delete_whole; - if (force_erase) + p = day_get_item(item_number); + if (force_erase) { ch = 'a'; + only_note = 0; + } else { + has_note = (p->note != NULL ) ? 1 : 0; + if (has_note == 0) + ans = 'i'; + while (ans != 'i' && ans != 'n') { + status_mesg(note_warning, note_choice); + ans = wgetch(win[STA].p); + } + if (ans == 'i') + only_note = 0; + else + only_note = 1; + } - p = day_get_item(item_number); - if (p->type == EVNT) { - event_delete_bynum(date, day_item_nb(date, item_number, EVNT)); + event_delete_bynum(date, day_item_nb(date, item_number, EVNT), + only_note); } else if (p->type == APPT) { - apoint_delete_bynum(date, day_item_nb(date, item_number, APPT)); + apoint_delete_bynum(date, day_item_nb(date, item_number, APPT), + only_note); } else { + if (only_note) + ch = 'a'; while ( (ch != 'a') && (ch != 'o') && (ch != ESCAPE)) { status_mesg(erase_warning, erase_choice); ch = wgetch(win[STA].p); @@ -761,12 +798,13 @@ int day_erase_item(long date, int item_number, int force_erase) { if (p->type == RECUR_EVNT) { recur_event_erase(date, day_item_nb(date, item_number, RECUR_EVNT), - delete_whole); + delete_whole, only_note); } else { - recur_apoint_erase(date, p->appt_pos, delete_whole); + recur_apoint_erase(date, p->appt_pos, delete_whole, + only_note); } } - return p->type; + return (p->type); } /* Returns a structure containing the selected item. */ @@ -801,3 +839,60 @@ day_item_nb(long date, int day_num, int type) return (nb_item[type - 1]); } + +/* Attach a note to an appointment or event. */ +void +day_edit_note(char *editor) +{ + struct day_item_s *p; + recur_apoint_llist_node_t *ra; + struct recur_event_s *re; + struct rpt_s *rpt; + char fullname[BUFSIZ]; + char *filename; + long date; + int item_num; + + item_num = apoint_hilt(); + p = day_get_item(item_num); + if (p->note == NULL) { + if ((filename = new_tempfile(path_notes, NOTESIZ)) + != NULL) + p->note = filename; + else + return; + } + snprintf(fullname, BUFSIZ, "%s%s", path_notes, p->note); + wins_launch_external(fullname, editor); + + date = calendar_get_slctd_day_sec(); + switch (p->type) { + case RECUR_EVNT: + re = recur_get_event(date, + day_item_nb(date, item_num, RECUR_EVNT)); + rpt = re->rpt; + break; + case RECUR_APPT: + ra = recur_get_apoint(date, + day_item_nb(date, item_num, RECUR_APPT)); + rpt = ra->rpt; + break; + default: + rpt = NULL; + } + update_item(date, item_num, p, rpt); +} + +/* View a note previously attached to an appointment or event */ +void +day_view_note(char *pager) +{ + struct day_item_s *p; + char fullname[BUFSIZ]; + + p = day_get_item(apoint_hilt()); + if (p->note == NULL) + return; + snprintf(fullname, BUFSIZ, "%s%s", path_notes, p->note); + wins_launch_external(fullname, pager); +} diff --git a/src/day.h b/src/day.h index 73b88b6..a1866d2 100755 --- a/src/day.h +++ b/src/day.h @@ -1,8 +1,8 @@ -/* $calcurse: day.h,v 1.15 2007/08/15 15:37:10 culot Exp $ */ +/* $calcurse: day.h,v 1.16 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 Frederic Culot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,6 +50,7 @@ struct day_item_s { int appt_pos; /* real position in recurrent list */ char state; /* appointment state */ char *mesg; /* item description */ + char *note; /* note attached to item */ }; struct day_saved_item_s { @@ -68,5 +69,7 @@ void day_edit_item(void); int day_erase_item(long, int, int); struct day_item_s *day_get_item(int); int day_item_nb(long, int, int); +void day_edit_note(char *); +void day_view_note(char *); #endif /* CALCURSE_DAY_H */ diff --git a/src/event.c b/src/event.c index 6aca296..919d71a 100755 --- a/src/event.c +++ b/src/event.c @@ -1,8 +1,8 @@ -/* $calcurse: event.c,v 1.4 2007/07/28 13:11:42 culot Exp $ */ +/* $calcurse: event.c,v 1.5 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -31,13 +31,14 @@ #include "vars.h" #include "i18n.h" +#include "utils.h" #include "event.h" struct event_s *eventlist; /* Create a new event */ struct event_s * -event_new(char *mesg, long day, int id) +event_new(char *mesg, char *note, long day, int id) { struct event_s *o, **i; o = (struct event_s *) malloc(sizeof(struct event_s)); @@ -45,6 +46,7 @@ event_new(char *mesg, long day, int id) strncpy(o->mesg, mesg, strlen(mesg) + 1); o->day = day; o->id = id; + o->note = note; i = &eventlist; for (;;) { if (*i == 0 || (*i)->day > day) { @@ -76,13 +78,16 @@ event_write(struct event_s *o, FILE * f) t = o->day; lt = localtime(&t); - fprintf(f, "%02u/%02u/%04u [%d] %s\n", - lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, o->id, o->mesg); + fprintf(f, "%02u/%02u/%04u [%d] ", + lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, o->id); + if (o->note != NULL) + fprintf(f, ">%s ", o->note); + fprintf(f, "%s\n", o->mesg); } /* Load the events from file */ struct event_s * -event_scan(FILE * f, struct tm start, int id) +event_scan(FILE * f, struct tm start, int id, char *note) { struct tm *lt; char buf[MESG_MAXSIZE], *nl; @@ -109,12 +114,12 @@ event_scan(FILE * f, struct tm start, int id) fputs(_("FATAL ERROR in event_scan: date error in the event\n"), stderr); exit(EXIT_FAILURE); } - return event_new(buf, tstart, id); + return (event_new(buf, note, tstart, id)); } /* Delete an event from the list */ void -event_delete_bynum(long start, unsigned num) +event_delete_bynum(long start, unsigned num, int only_note) { unsigned n; struct event_s *i, **iptr; @@ -124,9 +129,15 @@ event_delete_bynum(long start, unsigned num) for (i = eventlist; i != 0; i = i->next) { if (event_inday(i, start)) { if (n == num) { - *iptr = i->next; - free(i->mesg); - free(i); + if (only_note) + erase_note(&i->note); + else { + *iptr = i->next; + free(i->mesg); + if (i->note != NULL) + erase_note(&i->note); + free(i); + } return; } n++; diff --git a/src/event.h b/src/event.h index 48e2ac5..2fa8908 100755 --- a/src/event.h +++ b/src/event.h @@ -1,8 +1,8 @@ -/* $calcurse: event.h,v 1.3 2007/12/30 16:27:59 culot Exp $ */ +/* $calcurse: event.h,v 1.4 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2006 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -40,10 +40,10 @@ struct event_s { extern struct event_s *eventlist; -struct event_s *event_new(char *, long, int); +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); -void event_delete_bynum(long, unsigned); +struct event_s *event_scan(FILE *, struct tm, int, char *); +void event_delete_bynum(long, unsigned, int); #endif /* CALCURSE_EVENT_H */ diff --git a/src/io.c b/src/io.c index 00625a3..4cce160 100755 --- a/src/io.c +++ b/src/io.c @@ -1,8 +1,8 @@ -/* $calcurse: io.c,v 1.24 2007/12/30 16:27:59 culot Exp $ */ +/* $calcurse: io.c,v 1.25 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -508,7 +508,8 @@ io_save_cal(conf_t *conf) * appointments first, and then the events. * Recursive items are written first. */ - if (show_bar) progress_bar(PROGRESS_BAR_SAVE, 2); + if (show_bar) + progress_bar(PROGRESS_BAR_SAVE, 2); data_file = fopen(path_apts, "w"); if (data_file == (FILE *) 0) status_mesg(access_pb, ""); @@ -549,6 +550,7 @@ io_load_app(void) int id = 0; int freq; char type, state = 0L; + char note[NOTESIZ + 1], *notep; char *error = _("FATAL ERROR in io_load_app: wrong format in the appointment or event\n"); @@ -642,6 +644,18 @@ io_load_app(void) } else ungetc(c, data_file); + /* Check if a note is attached to the item. */ + c = getc(data_file); + if (c == '>') { + fgets(note, NOTESIZ + 1, data_file); + note[NOTESIZ] = '\0'; + notep = strdup(note); + getc(data_file); + } else { + notep = NULL; + ungetc(c, data_file); + } + /* * Last: read the item description and load it into its * corresponding linked list, depending on the item type. @@ -659,16 +673,16 @@ io_load_app(void) } if (is_recursive) { recur_apoint_scan(data_file, start, end, - type, freq, until, exc, state); + type, freq, until, notep, exc, state); } else { - apoint_scan(data_file, start, end, state); + apoint_scan(data_file, start, end, state, notep); } } else if (is_event) { if (is_recursive) { - recur_event_scan(data_file, start, id, - type, freq, until, exc); + recur_event_scan(data_file, start, id, type, + freq, until, notep, exc); } else { - event_scan(data_file, start, id); + event_scan(data_file, start, id, notep); } } else { /* NOT REACHED */ fputs(error, stderr); @@ -710,7 +724,6 @@ io_load_todo(void) if (c == '>') { fgets(note, NOTESIZ + 1, data_file); note[NOTESIZ] = '\0'; - fprintf(stderr, "note: [%s]\n", note); getc(data_file); } else note[0] = '\0'; diff --git a/src/recur.c b/src/recur.c index 655cda8..6683310 100755 --- a/src/recur.c +++ b/src/recur.c @@ -1,8 +1,8 @@ -/* $calcurse: recur.c,v 1.31 2007/12/10 19:03:23 culot Exp $ */ +/* $calcurse: recur.c,v 1.32 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -39,7 +39,8 @@ recur_apoint_llist_t *recur_alist_p; struct recur_event_s *recur_elist; -int recur_apoint_llist_init(void) +int +recur_apoint_llist_init(void) { recur_alist_p = (recur_apoint_llist_t *) malloc(sizeof(recur_apoint_llist_t)); @@ -51,8 +52,8 @@ int recur_apoint_llist_init(void) /* Insert a new recursive appointment in the general linked list */ recur_apoint_llist_node_t * -recur_apoint_new(char *mesg, long start, long dur, char state, int type, - int freq, long until, struct days_s *except) +recur_apoint_new(char *mesg, char *note, long start, long dur, char state, + int type, int freq, long until, struct days_s *except) { recur_apoint_llist_node_t *o, **i; o = (recur_apoint_llist_node_t *) @@ -61,6 +62,7 @@ recur_apoint_new(char *mesg, long start, long dur, char state, int type, o->mesg = (char *) malloc(strlen(mesg) + 1); o->exc = (struct days_s *) malloc(sizeof(struct days_s)); strncpy(o->mesg, mesg, strlen(mesg) + 1); + o->note = note; o->start = start; o->state = state; o->dur = dur; @@ -85,13 +87,15 @@ recur_apoint_new(char *mesg, long start, long dur, char state, int type, } /* Insert a new recursive event in the general linked list */ -struct recur_event_s *recur_event_new(char *mesg, long day, int id, - int type, int freq, long until, struct days_s *except) +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) { struct recur_event_s *o, **i; o = (struct recur_event_s *) malloc(sizeof(struct recur_event_s)); o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s)); o->mesg = (char *) malloc(strlen(mesg) + 1); + o->note = note; o->exc = (struct days_s *) malloc(sizeof(struct days_s)); strncpy(o->mesg, mesg, strlen(mesg) + 1); o->day = day; @@ -147,7 +151,9 @@ recur_def2char(recur_types_t define) * Correspondance between the letters written in file and the defines * concerning the recursive type. */ -int recur_char2def(char type){ +int +recur_char2def(char type) +{ int recur_def; char *error = _("FATAL ERROR in recur_char2def: unknown char\n"); @@ -192,7 +198,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, struct days_s *exc, char state) + int freq, struct tm until, char *note, struct days_s *exc, char state) { struct tm *lt; char buf[MESG_MAXSIZE], *nl; @@ -234,13 +240,14 @@ recur_apoint_scan(FILE * f, struct tm start, struct tm end, char type, exit(EXIT_FAILURE); } - return recur_apoint_new(buf, tstart, tend - tstart, - state, recur_char2def(type), freq, tuntil, exc); + return (recur_apoint_new(buf, note, tstart, tend - tstart, state, + recur_char2def(type), freq, tuntil, exc)); } /* 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, struct days_s *exc) +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 *lt; char buf[MESG_MAXSIZE], *nl; @@ -275,7 +282,7 @@ struct recur_event_s *recur_event_scan(FILE * f, struct tm start, int id, exit(EXIT_FAILURE); } - return recur_event_new(buf, tstart, id, recur_char2def(type), + return recur_event_new(buf, note, tstart, id, recur_char2def(type), freq, tuntil, exc); } @@ -310,10 +317,13 @@ recur_apoint_write(recur_apoint_llist_node_t *o, FILE *f) } if (o->exc != 0) recur_write_exc(o->exc, f); + fprintf(f, "} "); + if (o->note != NULL) + fprintf(f, ">%s ", o->note); if (o->state & APOINT_NOTIFY) - fprintf(f, "} !"); + fprintf(f, "!"); else - fprintf(f, "} |"); + fprintf(f, "|"); fprintf(f, "%s\n", o->mesg); } @@ -336,8 +346,6 @@ recur_event_write(struct recur_event_s *o, FILE *f) fprintf(f, "%02u/%02u/%04u [%d] {%d%c", st_mon, st_day, st_year, o->id, o->rpt->freq, recur_def2char(o->rpt->type)); - if (o->exc != 0) recur_write_exc(o->exc, f); - fprintf(f,"} %s\n", o->mesg); } else { lt = localtime(&t); end_mon = lt->tm_mon + 1; @@ -347,13 +355,18 @@ recur_event_write(struct recur_event_s *o, FILE *f) st_mon, st_day, st_year, o->id, o->rpt->freq, recur_def2char(o->rpt->type), end_mon, end_day, end_year); - if (o->exc != 0) recur_write_exc(o->exc, f); - fprintf(f, "} %s\n", o->mesg); - } + } + if (o->exc != 0) + recur_write_exc(o->exc, f); + fprintf(f, "} "); + if (o->note != NULL) + fprintf(f, ">%s ", o->note); + fprintf(f, "%s\n", o->mesg); } /* Write recursive items to file. */ -void recur_save_data(FILE *f) +void +recur_save_data(FILE *f) { struct recur_event_s *re; recur_apoint_llist_node_t *ra; @@ -373,8 +386,8 @@ void recur_save_data(FILE *f) * This function was improved thanks to Tony's patch. */ unsigned -recur_item_inday(long item_start, struct days_s *item_exc, - int rpt_type, int rpt_freq, long rpt_until, long day_start) +recur_item_inday(long item_start, struct days_s *item_exc, int rpt_type, + int rpt_freq, long rpt_until, long day_start) { date_t start_date; long day_end, diff; @@ -459,7 +472,8 @@ recur_item_inday(long item_start, struct days_s *item_exc, * Delete a recurrent event from the list (if delete_whole is not null), * or delete only one occurence of the recurrent event. */ -void recur_event_erase(long start, unsigned num, unsigned delete_whole) +void +recur_event_erase(long start, unsigned num, unsigned delete_whole, int only_note) { unsigned n = 0; struct recur_event_s *i, **iptr; @@ -471,11 +485,17 @@ void recur_event_erase(long start, unsigned num, unsigned delete_whole) i->rpt->freq, i->rpt->until, start)) { if (n == num) { if (delete_whole) { - *iptr = i->next; - free(i->mesg); - free(i->rpt); - free(i->exc); - free(i); + if (only_note) + erase_note(&i->note); + else { + *iptr = i->next; + free(i->mesg); + free(i->rpt); + free(i->exc); + if (i->note != NULL) + erase_note(&i->note); + free(i); + } return; } else { o = (struct days_s *) @@ -507,7 +527,9 @@ void recur_event_erase(long start, unsigned num, unsigned delete_whole) * Delete a recurrent appointment from the list (if delete_whole is not null), * or delete only one occurence of the recurrent appointment. */ -void recur_apoint_erase(long start, unsigned num, unsigned delete_whole) +void +recur_apoint_erase(long start, unsigned num, unsigned delete_whole, + int only_note) { unsigned n = 0; recur_apoint_llist_node_t *i, **iptr; @@ -518,20 +540,27 @@ void recur_apoint_erase(long start, unsigned num, unsigned delete_whole) iptr = &recur_alist_p->root; for (i = recur_alist_p->root; i != 0; i = i->next) { if (recur_item_inday(i->start, i->exc, i->rpt->type, - i->rpt->freq, i->rpt->until, start)) { + i->rpt->freq, i->rpt->until, start)) { if (n == num) { - if (notify_bar()) - need_check_notify = notify_same_recur_item(i); + if (notify_bar() && only_note != 0) + need_check_notify = + notify_same_recur_item(i); if (delete_whole) { - *iptr = i->next; - free(i->mesg); - free(i->rpt); - free(i->exc); - free(i); - pthread_mutex_unlock( - &(recur_alist_p->mutex)); - if (need_check_notify) - notify_check_next_app(); + if (only_note) + erase_note(&i->note); + else { + *iptr = i->next; + free(i->mesg); + free(i->rpt); + free(i->exc); + if (i->note != NULL) + erase_note(&i->note); + free(i); + pthread_mutex_unlock( + &(recur_alist_p->mutex)); + if (need_check_notify) + notify_check_next_app(); + } return; } else { o = (struct days_s *) @@ -571,7 +600,7 @@ void recur_apoint_erase(long start, unsigned num, unsigned delete_whole) * and then delete the selected item to recreate it as a recurrent one */ void -recur_repeat_item(void) +recur_repeat_item(void) { struct tm *lt; time_t t; @@ -677,12 +706,13 @@ recur_repeat_item(void) date = calendar_get_slctd_day_sec(); day_erase_item(date, item_nb, 0); if (p->type == EVNT) { - re = recur_event_new(p->mesg, p->start, p->evnt_id, + re = recur_event_new(p->mesg, p->note, p->start, p->evnt_id, type, freq, until, NULL); } else if (p->type == APPT) { - ra = recur_apoint_new(p->mesg, p->start, p->appt_dur, p->state, - type, freq, until, NULL); - if (notify_bar()) notify_check_repeated(ra); + ra = recur_apoint_new(p->mesg, p->note, p->start, p->appt_dur, + p->state, type, freq, until, NULL); + if (notify_bar()) + notify_check_repeated(ra); } else { /* NOTREACHED */ fputs(_("FATAL ERROR in recur_repeat_item: wrong item type\n"), stderr); @@ -694,7 +724,8 @@ recur_repeat_item(void) * Read days for which recurrent items must not be repeated * (such days are called exceptions). */ -struct days_s *recur_exc_scan(FILE *data_file) +struct days_s * +recur_exc_scan(FILE *data_file) { int c = 0; struct tm *lt, day; @@ -758,7 +789,8 @@ recur_apoint_check_next(struct notify_app_s *app, long start, long day) } /* Returns a structure containing the selected recurrent appointment. */ -recur_apoint_llist_node_t *recur_get_apoint(long date, int num) +recur_apoint_llist_node_t * +recur_get_apoint(long date, int num) { recur_apoint_llist_node_t *o; int n = 0; @@ -780,7 +812,8 @@ recur_apoint_llist_node_t *recur_get_apoint(long date, int num) } /* Returns a structure containing the selected recurrent event. */ -struct recur_event_s *recur_get_event(long date, int num) +struct recur_event_s * +recur_get_event(long date, int num) { struct recur_event_s *o; int n = 0; @@ -830,6 +863,5 @@ recur_apoint_switch_notify(long date, int recur_nb) /* NOTREACHED */ fputs(_("FATAL ERROR in recur_apoint_switch_notify: no such item\n"), stderr); - exit(EXIT_FAILURE); - + exit(EXIT_FAILURE); } diff --git a/src/recur.h b/src/recur.h index 7a3c036..01b8840 100755 --- a/src/recur.h +++ b/src/recur.h @@ -1,8 +1,8 @@ -/* $calcurse: recur.h,v 1.15 2007/08/15 15:37:31 culot Exp $ */ +/* $calcurse: recur.h,v 1.16 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -54,6 +54,7 @@ typedef struct recur_apoint_llist_node { long dur; /* duration of the appointment */ char state; /* 8 bits to store item state */ char *mesg; /* appointment description */ + char *note; /* note attached to appointment */ } recur_apoint_llist_node_t; typedef struct recur_apoint_llist { @@ -68,28 +69,30 @@ struct recur_event_s { int id; /* event type */ long day; /* day at which event occurs */ char *mesg; /* event description */ + char *note; /* note attached to event */ }; extern recur_apoint_llist_t *recur_alist_p; extern struct recur_event_s *recur_elist; int recur_apoint_llist_init(void); -recur_apoint_llist_node_t *recur_apoint_new(char *, long, long, char, int, - int, long, struct days_s *); -struct recur_event_s *recur_event_new(char *, long, int, int, int, - long, struct days_s *); +recur_apoint_llist_node_t *recur_apoint_new(char *, char *, long, long, + char, int, int, long, struct days_s *); +struct recur_event_s *recur_event_new(char *, char *, long, int, int, + int, 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, struct days_s *, - char); + char, int, struct tm, char *, + struct days_s *, char); struct recur_event_s *recur_event_scan(FILE *, struct tm, int, char, - int, struct tm, struct days_s *); + int, struct tm, char *, struct days_s *); void recur_save_data(FILE *); unsigned recur_item_inday(long, struct days_s *, int, int, long, long); -void recur_event_erase(long, unsigned, unsigned); -void recur_apoint_erase(long, unsigned, unsigned); +void recur_event_erase(long, unsigned, unsigned, int); +void recur_apoint_erase(long, unsigned, unsigned, + int); void recur_repeat_item(void); struct days_s *recur_exc_scan(FILE *); struct notify_app_s *recur_apoint_check_next(struct notify_app_s *, diff --git a/src/todo.c b/src/todo.c index 987492f..322ec6d 100755 --- a/src/todo.c +++ b/src/todo.c @@ -1,4 +1,4 @@ -/* $calcurse: todo.c,v 1.17 2007/12/31 17:37:53 culot Exp $ */ +/* $calcurse: todo.c,v 1.18 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -179,7 +179,6 @@ todo_delete_note_bynum(unsigned num) { unsigned n; struct todo_s *i, **iptr; - char fullname[BUFSIZ]; n = 0; iptr = &todolist; @@ -189,13 +188,7 @@ todo_delete_note_bynum(unsigned num) ierror( _("FATAL ERROR in todo_delete_note_bynum: " "no note attached\n"), IERROR_FATAL); - snprintf(fullname, BUFSIZ, "%s%s", path_notes, i->note); - if (unlink(fullname) != 0) - ierror( - _("FATAL ERROR in todo_delete_note_bynum: " - "could not remove note\n"), IERROR_FATAL); - free(i->note); - i->note = NULL; + erase_note(&i->note); return; } iptr = &i->next; @@ -221,7 +214,7 @@ todo_delete_bynum(unsigned num) *iptr = i->next; free(i->mesg); if (i->note != NULL) - free(i->note); + erase_note(&i->note); free(i); return; } diff --git a/src/utils.c b/src/utils.c index d2963a5..22cda23 100755 --- a/src/utils.c +++ b/src/utils.c @@ -1,8 +1,8 @@ -/* $calcurse: utils.c,v 1.38 2007/12/30 16:27:59 culot Exp $ */ +/* $calcurse: utils.c,v 1.39 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -900,3 +900,20 @@ new_tempfile(const char *prefix, int trailing_len) return (strdup(fullname + prefix_len)); } + +/* Erase a note previously attached to a todo, event or appointment. */ +void +erase_note(char **note) +{ + char fullname[BUFSIZ]; + + if (*note == NULL) + ierror(_("FATAL ERROR in erase_note: null pointer!\n"), + IERROR_FATAL); + snprintf(fullname, BUFSIZ, "%s%s", path_notes, *note); + if (unlink(fullname) != 0) + ierror(_("FATAL ERROR in erase_note: could not remove note\n"), + IERROR_FATAL); + free(*note); + *note = NULL; +} diff --git a/src/utils.h b/src/utils.h index 4d57a66..69b2d09 100755 --- a/src/utils.h +++ b/src/utils.h @@ -1,8 +1,8 @@ -/* $calcurse: utils.h,v 1.24 2007/12/30 16:27:59 culot Exp $ */ +/* $calcurse: utils.h,v 1.25 2008/01/13 12:40:45 culot Exp $ */ /* * Calcurse - text-based organizer - * Copyright (c) 2004-2007 Frederic Culot + * Copyright (c) 2004-2008 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 @@ -93,5 +93,6 @@ char *mycpy(const char *); long mystrtol(const char *); void print_option_incolor(WINDOW *, bool, int, int); char *new_tempfile(const char *, int); +void erase_note(char **); #endif /* CALCURSE_UTILS_H */ -- cgit v1.2.3-54-g00ecf