diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/apoint.c | 712 | ||||
-rw-r--r-- | src/args.c | 1283 | ||||
-rw-r--r-- | src/calcurse.c | 925 | ||||
-rw-r--r-- | src/calcurse.h | 1091 | ||||
-rw-r--r-- | src/calendar.c | 849 | ||||
-rw-r--r-- | src/config.c | 574 | ||||
-rw-r--r-- | src/custom.c | 1920 | ||||
-rw-r--r-- | src/day.c | 1298 | ||||
-rw-r--r-- | src/dmon.c | 184 | ||||
-rw-r--r-- | src/event.c | 179 | ||||
-rw-r--r-- | src/getstring.c | 280 | ||||
-rw-r--r-- | src/help.c | 1173 | ||||
-rw-r--r-- | src/htable.h | 14 | ||||
-rw-r--r-- | src/ical.c | 1090 | ||||
-rw-r--r-- | src/io.c | 3338 | ||||
-rw-r--r-- | src/keys.c | 725 | ||||
-rw-r--r-- | src/llist.c | 211 | ||||
-rw-r--r-- | src/llist.h | 37 | ||||
-rw-r--r-- | src/llist_ts.h | 13 | ||||
-rw-r--r-- | src/mem.c | 271 | ||||
-rw-r--r-- | src/note.c | 235 | ||||
-rw-r--r-- | src/notify.c | 882 | ||||
-rw-r--r-- | src/pcal.c | 291 | ||||
-rw-r--r-- | src/recur.c | 1332 | ||||
-rw-r--r-- | src/sha1.c | 267 | ||||
-rw-r--r-- | src/sha1.h | 57 | ||||
-rw-r--r-- | src/sigs.c | 73 | ||||
-rw-r--r-- | src/todo.c | 497 | ||||
-rw-r--r-- | src/utf8.c | 335 | ||||
-rw-r--r-- | src/utils.c | 1523 | ||||
-rw-r--r-- | src/vars.c | 56 | ||||
-rw-r--r-- | src/wins.c | 878 |
33 files changed, 11719 insertions, 10884 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index faacf46..7eab77f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,26 +2,36 @@ AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = calcurse +AM_CFLAGS = -std=c99 -pedantic -D_POSIX_C_SOURCE=200809L + calcurse_SOURCES = \ calcurse.c \ calcurse.h \ htable.h \ llist.h \ llist_ts.h \ + sha1.h \ apoint.c \ args.c \ calendar.c \ + config.c \ custom.c \ day.c \ event.c \ + getstring.c \ help.c \ + ical.c \ io.c \ keys.c \ llist.c \ + note.c \ notify.c \ + pcal.c \ recur.c \ + sha1.c \ sigs.c \ todo.c \ + utf8.c \ utils.c \ vars.c \ wins.c \ diff --git a/src/apoint.c b/src/apoint.c index 6fd9e64..1483beb 100644 --- a/src/apoint.c +++ b/src/apoint.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,46 +41,41 @@ #include "calcurse.h" -llist_ts_t alist_p; -static struct apoint bkp_cut_apoint; -static int hilt; +llist_ts_t alist_p; +static struct apoint bkp_cut_apoint; +static int hilt; -void -apoint_free_bkp (enum eraseflg flag) +void apoint_free_bkp(void) { - if (bkp_cut_apoint.mesg) - { - mem_free (bkp_cut_apoint.mesg); - bkp_cut_apoint.mesg = 0; - } - erase_note (&bkp_cut_apoint.note, flag); + if (bkp_cut_apoint.mesg) { + mem_free(bkp_cut_apoint.mesg); + bkp_cut_apoint.mesg = 0; + } + erase_note(&bkp_cut_apoint.note); } -static void -apoint_free (struct apoint *apt) +static void apoint_free(struct apoint *apt) { - mem_free (apt->mesg); - erase_note (&apt->note, ERASE_FORCE_KEEP_NOTE); - mem_free (apt); + mem_free(apt->mesg); + erase_note(&apt->note); + mem_free(apt); } -static void -apoint_dup (struct apoint *in, struct apoint *bkp) +static void apoint_dup(struct apoint *in, struct apoint *bkp) { - EXIT_IF (!in || !bkp, _("null pointer")); + 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->mesg = mem_strdup(in->mesg); if (in->note) - bkp->note = mem_strdup (in->note); + bkp->note = mem_strdup(in->note); } -void -apoint_llist_init (void) +void apoint_llist_init(void) { - LLIST_TS_INIT (&alist_p); + LLIST_TS_INIT(&alist_p); } /* @@ -88,60 +83,54 @@ apoint_llist_init (void) * list. No need to be thread safe, as only the main process remains when * calling this function. */ -void -apoint_llist_free (void) +void apoint_llist_free(void) { - LLIST_TS_FREE_INNER (&alist_p, apoint_free); - LLIST_TS_FREE (&alist_p); + LLIST_TS_FREE_INNER(&alist_p, apoint_free); + LLIST_TS_FREE(&alist_p); } /* Sets which appointment is highlighted. */ -void -apoint_hilt_set (int highlighted) +void apoint_hilt_set(int highlighted) { hilt = highlighted; } -void -apoint_hilt_decrease (void) +void apoint_hilt_decrease(int n) { - hilt--; + hilt -= n; } -void -apoint_hilt_increase (void) +void apoint_hilt_increase(int n) { - hilt++; + hilt += n; } /* Return which appointment is highlighted. */ -int -apoint_hilt (void) +int apoint_hilt(void) { - return (hilt); + return hilt; } -static int -apoint_cmp_start (struct apoint *a, struct apoint *b) +static int apoint_cmp_start(struct apoint *a, struct apoint *b) { - return (a->start < b->start ? -1 : (a->start == b->start ? 0 : 1)); + return a->start < b->start ? -1 : (a->start == b->start ? 0 : 1); } -struct apoint * -apoint_new (char *mesg, char *note, long start, long dur, char state) +struct apoint *apoint_new(char *mesg, char *note, long start, long dur, + char state) { struct apoint *apt; - apt = mem_malloc (sizeof (struct apoint)); - apt->mesg = mem_strdup (mesg); - apt->note = (note != NULL) ? mem_strdup (note) : NULL; + apt = mem_malloc(sizeof(struct apoint)); + apt->mesg = mem_strdup(mesg); + apt->note = (note != NULL) ? mem_strdup(note) : NULL; apt->state = state; apt->start = start; apt->dur = dur; - LLIST_TS_LOCK (&alist_p); - LLIST_TS_ADD_SORTED (&alist_p, apt, apoint_cmp_start); - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_LOCK(&alist_p); + LLIST_TS_ADD_SORTED(&alist_p, apt, apoint_cmp_start); + LLIST_TS_UNLOCK(&alist_p); return apt; } @@ -150,181 +139,148 @@ apoint_new (char *mesg, char *note, long start, long dur, char state) * Add an item in either the appointment or the event list, * depending if the start time is entered or not. */ -void -apoint_add (void) +void apoint_add(void) { #define LTIME 6 - char *mesg_1 = - _("Enter start time ([hh:mm] or [h:mm]), " - "leave blank for an all-day event : "); - char *mesg_2 = - _("Enter end time ([hh:mm] or [h:mm]) or duration (in minutes) : "); - char *mesg_3 = _("Enter description :"); - char *format_message_1 = - _("You entered an invalid start time, should be [h:mm] or [hh:mm]"); - char *format_message_2 = - _("You entered an invalid end time, should be [h:mm] or [hh:mm] or [mm]"); - char *enter_str = _("Press [Enter] to continue"); +#define LDUR 12 + const char *mesg_1 = + _("Enter start time ([hh:mm]), leave blank for an all-day event : "); + const char *mesg_2 = + _ + ("Enter end time ([hh:mm]) or duration ([+hh:mm], [+xxxdxxhxxm] or [+mm]) : "); + const char *mesg_3 = _("Enter description :"); + const char *format_message_1 = + _("You entered an invalid start time, should be [hh:mm]"); + const char *format_message_2 = + _ + ("Invalid end time/duration, should be [hh:mm], [+hh:mm], [+xxxdxxhxxm] or [+mm]"); + const char *enter_str = _("Press [Enter] to continue"); int Id = 1; - char item_time[LTIME] = ""; + char item_time[LDUR] = ""; char item_mesg[BUFSIZ] = ""; - long apoint_duration = 0, apoint_start; + long apoint_start; unsigned heures, minutes; + unsigned apoint_duration; unsigned end_h, end_m; int is_appointment = 1; /* Get the starting time */ - do - { - status_mesg (mesg_1, ""); - if (getstring (win[STA].p, item_time, LTIME, 0, 1) != GETSTRING_ESC) - { - if (strlen (item_time) == 0) - { - is_appointment = 0; - break; - } - else if (check_time (item_time) != 1) - { - status_mesg (format_message_1, enter_str); - (void)wgetch (win[STA].p); - } - else - (void)sscanf (item_time, "%u:%u", &heures, &minutes); - } - else - return; - } - while (check_time (item_time) != 1); + for (;;) { + status_mesg(mesg_1, ""); + if (getstring(win[STA].p, item_time, LTIME, 0, 1) != GETSTRING_ESC) { + if (strlen(item_time) == 0) { + is_appointment = 0; + break; + } + + if (parse_time(item_time, &heures, &minutes) == 1) + break; + else { + status_mesg(format_message_1, enter_str); + wgetch(win[STA].p); + } + } else + return; + } /* * Check if an event or appointment is entered, * depending on the starting time, and record the * corresponding item. */ - if (is_appointment) - { /* Get the appointment duration */ - item_time[0] = '\0'; - do - { - status_mesg (mesg_2, ""); - if (getstring (win[STA].p, item_time, LTIME, 0, 1) != GETSTRING_VALID) - return; //nothing entered, cancel adding of event - else if (check_time (item_time) == 0) - { - status_mesg (format_message_2, enter_str); - (void)wgetch (win[STA].p); - } - else - { - if (check_time (item_time) == 2) - apoint_duration = atoi (item_time); - else if (check_time (item_time) == 1) - { - (void)sscanf (item_time, "%u:%u", &end_h, &end_m); - if (end_h < heures || ((end_h == heures) && (end_m < minutes))) - { - apoint_duration = MININSEC - minutes + end_m - + (24 + end_h - (heures + 1)) * MININSEC; - } - else - { - apoint_duration = MININSEC - minutes - + end_m + (end_h - (heures + 1)) * MININSEC; - } - } - } + if (is_appointment) { /* Get the appointment duration */ + item_time[0] = '\0'; + for (;;) { + status_mesg(mesg_2, ""); + if (getstring(win[STA].p, item_time, LDUR, 0, 1) != GETSTRING_ESC) { + if (*item_time == '+' && parse_duration(item_time + 1, + &apoint_duration) == 1) + break; + else if (parse_time(item_time, &end_h, &end_m) == 1) { + if (end_h < heures || ((end_h == heures) && (end_m < minutes))) { + apoint_duration = MININSEC - minutes + end_m + + (24 + end_h - (heures + 1)) * MININSEC; + } else { + apoint_duration = MININSEC - minutes + + end_m + (end_h - (heures + 1)) * MININSEC; + } + break; + } else { + status_mesg(format_message_2, enter_str); + wgetch(win[STA].p); } - while (check_time (item_time) == 0); + } else + return; } - else /* Insert the event Id */ + } else /* Insert the event Id */ Id = 1; - status_mesg (mesg_3, ""); - if (getstring (win[STA].p, item_mesg, BUFSIZ, 0, 1) == GETSTRING_VALID) - { - if (is_appointment) - { - apoint_start = date2sec (*calendar_get_slctd_day (), heures, minutes); - (void)apoint_new (item_mesg, 0L, apoint_start, - min2sec (apoint_duration), 0L); - if (notify_bar ()) - notify_check_added (item_mesg, apoint_start, 0L); - } - else - (void)event_new (item_mesg, 0L, - date2sec (*calendar_get_slctd_day (), 12, 0), Id); - - if (hilt == 0) - hilt++; - } - wins_erase_status_bar (); + status_mesg(mesg_3, ""); + if (getstring(win[STA].p, item_mesg, BUFSIZ, 0, 1) == GETSTRING_VALID) { + if (is_appointment) { + apoint_start = date2sec(*calendar_get_slctd_day(), heures, minutes); + apoint_new(item_mesg, 0L, apoint_start, min2sec(apoint_duration), 0L); + if (notify_bar()) + notify_check_added(item_mesg, apoint_start, 0L); + } else + event_new(item_mesg, 0L, date2sec(*calendar_get_slctd_day(), 0, 0), Id); + + if (hilt == 0) + hilt++; + } + wins_erase_status_bar(); } /* Delete an item from the appointment list. */ -void -apoint_delete (struct conf *conf, unsigned *nb_events, unsigned *nb_apoints) +void apoint_delete(unsigned *nb_events, unsigned *nb_apoints) { - char *choices = "[y/n] "; - char *del_app_str = _("Do you really want to delete this item ?"); + const char *del_app_str = _("Do you really want to delete this item ?"); long date; int nb_items = *nb_apoints + *nb_events; - unsigned go_for_deletion = 0; int to_be_removed = 0; - int answer = 0; - int deleted_item_type = 0; - - date = calendar_get_slctd_day_sec (); - - if (conf->confirm_delete) - { - status_mesg (del_app_str, choices); - answer = wgetch (win[STA].p); - if ((answer == 'y') && (nb_items != 0)) - go_for_deletion = 1; - else - { - wins_erase_status_bar (); - return; - } + + date = calendar_get_slctd_day_sec(); + + if (nb_items == 0) + return; + + if (conf.confirm_delete) { + if (status_ask_bool(del_app_str) != 1) { + wins_erase_status_bar(); + return; } - else if (nb_items != 0) - go_for_deletion = 1; - - if (go_for_deletion) - { - if (nb_items != 0) - { - deleted_item_type = day_erase_item (date, hilt, ERASE_DONT_FORCE); - if (deleted_item_type == EVNT || deleted_item_type == RECUR_EVNT) - { - (*nb_events)--; - to_be_removed = 1; - } - else if (deleted_item_type == APPT || deleted_item_type == RECUR_APPT) - { - (*nb_apoints)--; - to_be_removed = 3; - } - else if (deleted_item_type == 0) - return; - 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 (nb_items == 1) - hilt = 0; - } + } + + if (nb_items != 0) { + switch (day_erase_item(date, hilt, ERASE_DONT_FORCE)) { + case EVNT: + case RECUR_EVNT: + (*nb_events)--; + to_be_removed = 1; + break; + case APPT: + case RECUR_APPT: + (*nb_apoints)--; + to_be_removed = 3; + break; + case 0: + return; + default: + 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 (nb_items == 1) + hilt = 0; + } } /* Cut an item, so that it can be pasted somewhere else later. */ -int -apoint_cut (unsigned *nb_events, unsigned *nb_apoints) +int apoint_cut(unsigned *nb_events, unsigned *nb_apoints) { const int NBITEMS = *nb_apoints + *nb_events; int item_type, to_be_removed; @@ -333,20 +289,16 @@ apoint_cut (unsigned *nb_events, unsigned *nb_apoints) if (NBITEMS == 0) return 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")); + 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) @@ -360,14 +312,13 @@ apoint_cut (unsigned *nb_events, unsigned *nb_apoints) } /* Paste a previously cut item. */ -void -apoint_paste (unsigned *nb_events, unsigned *nb_apoints, int cut_item_type) +void apoint_paste(unsigned *nb_events, unsigned *nb_apoints, int cut_item_type) { int item_type; long date; - date = calendar_get_slctd_day_sec (); - item_type = day_paste_item (date, cut_item_type); + date = calendar_get_slctd_day_sec(); + item_type = day_paste_item(date, cut_item_type); if (item_type == EVNT || item_type == RECUR_EVNT) (*nb_events)++; else if (item_type == APPT || item_type == RECUR_APPT) @@ -379,81 +330,72 @@ apoint_paste (unsigned *nb_events, unsigned *nb_apoints, int cut_item_type) hilt++; } -unsigned -apoint_inday (struct apoint *i, long start) +unsigned apoint_inday(struct apoint *i, long start) { - if (i->start <= start + DAYINSEC && i->start + i->dur > start) - { - return (1); - } - return (0); + return (i->start <= start + DAYINSEC && i->start + i->dur > start); } -void -apoint_sec2str (struct apoint *o, int type, long day, char *start, char *end) +void apoint_sec2str(struct apoint *o, long day, char *start, char *end) { struct tm *lt; time_t t; - if (o->start < day && type == APPT) - (void)strncpy (start, "..:..", 6); - else - { - t = o->start; - lt = localtime (&t); - (void)snprintf (start, HRMIN_SIZE, "%02u:%02u", lt->tm_hour, lt->tm_min); - } - if (o->start + o->dur > day + DAYINSEC && type == APPT) - (void)strncpy (end, "..:..", 6); - else - { - t = o->start + o->dur; - lt = localtime (&t); - (void)snprintf (end, HRMIN_SIZE, "%02u:%02u", lt->tm_hour, lt->tm_min); - } + if (o->start < day) + strncpy(start, "..:..", 6); + else { + t = o->start; + lt = localtime(&t); + snprintf(start, HRMIN_SIZE, "%02u:%02u", lt->tm_hour, lt->tm_min); + } + if (o->start + o->dur > day + DAYINSEC) + strncpy(end, "..:..", 6); + else { + t = o->start + o->dur; + lt = localtime(&t); + snprintf(end, HRMIN_SIZE, "%02u:%02u", lt->tm_hour, lt->tm_min); + } } -void -apoint_write (struct apoint *o, FILE *f) +void apoint_write(struct apoint *o, FILE * f) { struct tm *lt; time_t t; t = o->start; - lt = localtime (&t); - (void)fprintf (f, "%02u/%02u/%04u @ %02u:%02u", - lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, lt->tm_hour, - lt->tm_min); + lt = localtime(&t); + fprintf(f, "%02u/%02u/%04u @ %02u:%02u", lt->tm_mon + 1, lt->tm_mday, + 1900 + lt->tm_year, lt->tm_hour, lt->tm_min); t = o->start + o->dur; - lt = localtime (&t); - (void)fprintf (f, " -> %02u/%02u/%04u @ %02u:%02u ", - lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, lt->tm_hour, - lt->tm_min); + lt = localtime(&t); + fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u ", lt->tm_mon + 1, lt->tm_mday, + 1900 + lt->tm_year, lt->tm_hour, lt->tm_min); if (o->note != NULL) - (void)fprintf (f, ">%s ", o->note); + fprintf(f, ">%s ", o->note); if (o->state & APOINT_NOTIFY) - (void)fprintf (f, "!"); + fputc('!', f); else - (void)fprintf (f, "|"); + fputc('|', f); - (void)fprintf (f, "%s\n", o->mesg); + fprintf(f, "%s\n", o->mesg); } -struct apoint * -apoint_scan (FILE *f, struct tm start, struct tm end, char state, char *note) +struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, char state, + char *note) { char buf[BUFSIZ], *newline; time_t tstart, tend, t; - t = time (NULL); - (void)localtime (&t); + t = time(NULL); + localtime(&t); /* Read the appointment description */ - (void)fgets (buf, sizeof buf, f); - newline = strchr (buf, '\n'); + if (!fgets(buf, sizeof buf, f)) + return NULL; + + newline = strchr(buf, '\n'); if (newline) *newline = '\0'; @@ -464,63 +406,58 @@ apoint_scan (FILE *f, struct tm start, struct tm end, char state, char *note) end.tm_year -= 1900; end.tm_mon--; - tstart = mktime (&start); - tend = mktime (&end); - EXIT_IF (tstart == -1 || tend == -1 || tstart > tend, - _("date error in appointment")); - return (apoint_new (buf, note, tstart, tend - tstart, state)); + tstart = mktime(&start); + tend = mktime(&end); + EXIT_IF(tstart == -1 || tend == -1 || tstart > tend, + _("date error in appointment")); + return apoint_new(buf, note, tstart, tend - tstart, state); } /* Retrieve an appointment from the list, given the day and item position. */ -struct apoint * -apoint_get (long day, int pos) +struct apoint *apoint_get(long day, int pos) { - llist_item_t *i = LLIST_TS_FIND_NTH (&alist_p, pos, day, apoint_inday); + llist_item_t *i = LLIST_TS_FIND_NTH(&alist_p, pos, day, apoint_inday); if (i) - return LLIST_TS_GET_DATA (i); + return LLIST_TS_GET_DATA(i); - EXIT (_("item not found")); + EXIT(_("item not found")); /* NOTREACHED */ } -void -apoint_delete_bynum (long start, unsigned num, enum eraseflg flag) +void apoint_delete_bynum(long start, unsigned num, enum eraseflg flag) { llist_item_t *i; int need_check_notify = 0; - LLIST_TS_LOCK (&alist_p); - i = LLIST_TS_FIND_NTH (&alist_p, num, start, apoint_inday); + LLIST_TS_LOCK(&alist_p); + i = LLIST_TS_FIND_NTH(&alist_p, num, start, apoint_inday); if (!i) - EXIT (_("no such appointment")); - struct apoint *apt = LLIST_TS_GET_DATA (i); - - switch (flag) - { - case ERASE_FORCE_ONLY_NOTE: - erase_note (&apt->note, flag); - break; - case ERASE_CUT: - apoint_free_bkp (ERASE_FORCE); - apoint_dup (apt, &bkp_cut_apoint); - erase_note (&apt->note, ERASE_FORCE_KEEP_NOTE); - /* FALLTHROUGH */ - default: - if (notify_bar ()) - need_check_notify = notify_same_item (apt->start); - LLIST_TS_REMOVE (&alist_p, i); - mem_free (apt->mesg); - if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT) - erase_note (&apt->note, flag); - mem_free (apt); - if (need_check_notify) - notify_check_next_app (0); - break; - } - - LLIST_TS_UNLOCK (&alist_p); + EXIT(_("no such appointment")); + struct apoint *apt = LLIST_TS_GET_DATA(i); + + switch (flag) { + case ERASE_FORCE_ONLY_NOTE: + erase_note(&apt->note); + break; + case ERASE_CUT: + apoint_free_bkp(); + apoint_dup(apt, &bkp_cut_apoint); + erase_note(&apt->note); + /* FALLTHROUGH */ + default: + if (notify_bar()) + need_check_notify = notify_same_item(apt->start); + LLIST_TS_REMOVE(&alist_p, i); + mem_free(apt->mesg); + mem_free(apt); + if (need_check_notify) + notify_check_next_app(0); + break; + } + + LLIST_TS_UNLOCK(&alist_p); } /* @@ -528,8 +465,7 @@ apoint_delete_bynum (long start, unsigned num, enum eraseflg flag) * the appointment panel. This is to help the appointment scroll function * to place beggining of the pad correctly. */ -static int -get_item_line (int item_nb, int nb_events_inday) +static int get_item_line(int item_nb, int nb_events_inday) { int separator = 2; int line = 0; @@ -538,7 +474,7 @@ get_item_line (int item_nb, int nb_events_inday) line = item_nb - 1; else line = nb_events_inday + separator - + (item_nb - (nb_events_inday + 1)) * 3 - 1; + + (item_nb - (nb_events_inday + 1)) * 3 - 1; return line; } @@ -546,15 +482,14 @@ 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; int borders = 6; int awin_length = win_length - borders; - item_first_line = get_item_line (hilt, nb_events_inday); + item_first_line = get_item_line(hilt, nb_events_inday); if (hilt < nb_events_inday) item_last_line = item_first_line; else @@ -568,109 +503,84 @@ 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; - item_first_line = get_item_line (hilt, nb_events_inday); + item_first_line = get_item_line(hilt, nb_events_inday); if (item_first_line < apad.first_onscreen) apad.first_onscreen = item_first_line; } -static int -apoint_starts_after (struct apoint *apt, long time) +static int apoint_starts_after(struct apoint *apt, long time) { - return (apt->start > time); + return apt->start > time; } /* * Look in the appointment list if we have an item which starts before the item * stored in the notify_app structure (which is the next item to be notified). */ -struct notify_app * -apoint_check_next (struct notify_app *app, long start) +struct notify_app *apoint_check_next(struct notify_app *app, long start) { llist_item_t *i; - LLIST_TS_LOCK (&alist_p); - i = LLIST_TS_FIND_FIRST (&alist_p, start, apoint_starts_after); + LLIST_TS_LOCK(&alist_p); + i = LLIST_TS_FIND_FIRST(&alist_p, start, apoint_starts_after); - if (i) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - - if (apt->start <= app->time) - { - app->time = apt->start; - app->txt = mem_strdup (apt->mesg); - app->state = apt->state; - app->got_app = 1; - } + if (i) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + + if (apt->start <= app->time) { + app->time = apt->start; + app->txt = mem_strdup(apt->mesg); + app->state = apt->state; + app->got_app = 1; } + } - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_UNLOCK(&alist_p); - return (app); -} - -/* - * Returns a structure of type struct apoint_list given a structure of type - * recur_apoint_s - */ -struct apoint * -apoint_recur_s2apoint_s (struct recur_apoint *p) -{ - struct apoint *a; - - a = mem_malloc (sizeof (struct apoint)); - a->mesg = mem_strdup (p->mesg); - a->start = p->start; - a->dur = p->dur; - return (a); + return app; } /* * Switch notification state. */ -void -apoint_switch_notify (void) +void apoint_switch_notify(void) { struct day_item *p; long date; int apoint_nb = 0, need_chk_notify; - p = day_get_item (hilt); + p = day_get_item(hilt); if (p->type != APPT && p->type != RECUR_APPT) return; - date = calendar_get_slctd_day_sec (); + date = calendar_get_slctd_day_sec(); - if (p->type == RECUR_APPT) - { - recur_apoint_switch_notify (date, p->appt_pos); - return; - } - else if (p->type == APPT) - apoint_nb = day_item_nb (date, hilt, APPT); + if (p->type == RECUR_APPT) { + recur_apoint_switch_notify(date, p->appt_pos); + return; + } else if (p->type == APPT) + apoint_nb = day_item_nb(date, hilt, APPT); need_chk_notify = 0; - LLIST_TS_LOCK (&alist_p); + LLIST_TS_LOCK(&alist_p); - struct apoint *apt = apoint_get (date, apoint_nb); + struct apoint *apt = apoint_get(date, apoint_nb); apt->state ^= APOINT_NOTIFY; - if (notify_bar ()) - notify_check_added (apt->mesg, apt->start, apt->state); + if (notify_bar()) + notify_check_added(apt->mesg, apt->start, apt->state); if (need_chk_notify) - notify_check_next_app (0); + notify_check_next_app(0); - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_UNLOCK(&alist_p); } /* Updates the Appointment panel */ -void -apoint_update_panel (int which_pan) +void apoint_update_panel(int which_pan) { int title_xpos; int bordr = 1; @@ -681,57 +591,53 @@ apoint_update_panel (int which_pan) struct date slctd_date; /* variable inits */ - slctd_date = *calendar_get_slctd_day (); - title_xpos = win[APP].w - (strlen (_(monthnames[slctd_date.mm - 1])) + 16); + slctd_date = *calendar_get_slctd_day(); + title_xpos = win[APP].w - (strlen(_(monthnames[slctd_date.mm - 1])) + 16); if (slctd_date.dd < 10) title_xpos++; - date = date2sec (slctd_date, 0, 0); - day_write_pad (date, app_width, app_length, hilt); + date = date2sec(slctd_date, 0, 0); + day_write_pad(date, app_width, app_length, (which_pan == APP) ? hilt : 0); /* Print current date in the top right window corner. */ - erase_window_part (win[APP].p, 1, title_lines, win[APP].w - 2, - win[APP].h - 2); - custom_apply_attr (win[APP].p, ATTR_HIGHEST); - mvwprintw (win[APP].p, title_lines, title_xpos, "%s %s %d, %d", - calendar_get_pom (date), _(monthnames[slctd_date.mm - 1]), - slctd_date.dd, slctd_date.yyyy); - custom_remove_attr (win[APP].p, ATTR_HIGHEST); + erase_window_part(win[APP].p, 1, title_lines, win[APP].w - 2, win[APP].h - 2); + custom_apply_attr(win[APP].p, ATTR_HIGHEST); + mvwprintw(win[APP].p, title_lines, title_xpos, "%s %s %d, %d", + calendar_get_pom(date), _(monthnames[slctd_date.mm - 1]), + slctd_date.dd, slctd_date.yyyy); + custom_remove_attr(win[APP].p, ATTR_HIGHEST); /* Draw the scrollbar if necessary. */ - if ((apad.length >= app_length) || (apad.first_onscreen > 0)) - { - float ratio = ((float) app_length) / ((float) apad.length); - int sbar_length = (int) (ratio * app_length); - int highend = (int) (ratio * apad.first_onscreen); - unsigned hilt_bar = (which_pan == APP) ? 1 : 0; - int sbar_top = highend + title_lines + 1; - - if ((sbar_top + sbar_length) > win[APP].h - 1) - sbar_length = win[APP].h - 1 - sbar_top; - draw_scrollbar (win[APP].p, sbar_top, win[APP].w - 2, sbar_length, - title_lines + 1, win[APP].h - 1, hilt_bar); - } - - wnoutrefresh (win[APP].p); - pnoutrefresh (apad.ptrwin, apad.first_onscreen, 0, - win[APP].y + title_lines + 1, win[APP].x + bordr, - win[APP].y + win[APP].h - 2 * bordr, - win[APP].x + win[APP].w - 3 * bordr); + if ((apad.length >= app_length) || (apad.first_onscreen > 0)) { + float ratio = ((float)app_length) / ((float)apad.length); + int sbar_length = (int)(ratio * app_length); + int highend = (int)(ratio * apad.first_onscreen); + unsigned hilt_bar = (which_pan == APP) ? 1 : 0; + int sbar_top = highend + title_lines + 1; + + if ((sbar_top + sbar_length) > win[APP].h - 1) + sbar_length = win[APP].h - 1 - sbar_top; + draw_scrollbar(win[APP].p, sbar_top, win[APP].w - 2, sbar_length, + title_lines + 1, win[APP].h - 1, hilt_bar); + } + + wnoutrefresh(win[APP].p); + pnoutrefresh(apad.ptrwin, apad.first_onscreen, 0, + win[APP].y + title_lines + 1, win[APP].x + bordr, + win[APP].y + win[APP].h - 2 * bordr, + win[APP].x + win[APP].w - 3 * bordr); } -void -apoint_paste_item (void) +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); + bkp_time = get_item_time(bkp_cut_apoint.start); + bkp_start = calendar_get_slctd_day_sec() + bkp_time; + apoint_new(bkp_cut_apoint.mesg, bkp_cut_apoint.note, bkp_start, + bkp_cut_apoint.dur, bkp_cut_apoint.state); - if (notify_bar ()) - notify_check_added (bkp_cut_apoint.mesg, bkp_start, bkp_cut_apoint.state); + if (notify_bar()) + notify_check_added(bkp_cut_apoint.mesg, bkp_start, bkp_cut_apoint.state); - apoint_free_bkp (ERASE_FORCE_KEEP_NOTE); + apoint_free_bkp(); } @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,112 +45,114 @@ #include "calcurse.h" +/* Long options */ +enum { + OPT_FMT_APT = 1000, + OPT_FMT_RAPT, + OPT_FMT_EV, + OPT_FMT_REV, + OPT_FMT_TODO, + OPT_READ_ONLY +}; + /* * Print Calcurse usage and exit. */ -static void -usage () +static void usage(void) { - char *arg_usage = - _("Usage: calcurse [-h|-v] [-N] [-an] [-t[num]] [-i<file>] [-x[format]]\n" - " [-d <date>|<num>] [-s[date]] [-r[range]]\n" - " [-c<file> | -D<dir>] [-S<regex>] [--status]\n"); - fputs (arg_usage, stdout); + const char *arg_usage = + _("Usage: calcurse [-g|-h|-v] [-an] [-t[num]] [-i<file>] [-x[format]]\n" + " [-d <date>|<num>] [-s[date]] [-r[range]]\n" + " [-c<file> | -D<dir>] [-S<regex>] [--status]\n" + " [--read-only]\n"); + fputs(arg_usage, stdout); } -static void -usage_try () +static void usage_try(void) { - char *arg_usage_try = _("Try 'calcurse -h' for more information.\n"); - fputs (arg_usage_try, stdout); + const char *arg_usage_try = _("Try 'calcurse -h' for more information.\n"); + fputs(arg_usage_try, stdout); } /* * Print Calcurse version with a short copyright text and exit. */ -static void -version_arg () +static void version_arg(void) { - char vtitle[BUFSIZ]; - char *vtext = - _("\nCopyright (c) 2004-2011 calcurse Development Team.\n" + const char *vtext = + _("\nCopyright (c) 2004-2012 calcurse Development Team.\n" "This is free software; see the source for copying conditions.\n"); - (void)snprintf (vtitle, BUFSIZ, _("Calcurse %s - text-based organizer\n"), - VERSION); - fputs (vtitle, stdout); - fputs (vtext, stdout); + fprintf(stdout, _("Calcurse %s - text-based organizer\n"), VERSION); + fputs(vtext, stdout); } /* * Print the command line options and exit. */ -static void -help_arg () +static void help_arg(void) { - char htitle[BUFSIZ]; - char *htext = - _("\nMiscellaneous:\n" - " -h, --help\n" - " print this help and exit.\n" - "\n -v, --version\n" - " print calcurse version and exit.\n" - "\n --status\n" - " display the status of running instances of calcurse.\n" - "\nFiles:\n" - " -c <file>, --calendar <file>\n" - " specify the calendar <file> to use (incompatible with '-D').\n" - "\n -D <dir>, --directory <dir>\n" - " specify the data directory to use (incompatible with '-c').\n" - "\tIf not specified, the default directory is ~/.calcurse\n" - "\nNon-interactive:\n" - " -a, --appointment\n" - " print events and appointments for current day and exit.\n" - "\n -d <date|num>, --day <date|num>\n" - " print events and appointments for <date> or <num> upcoming days and" - "\n\texit. To specify both a starting date and a range, use the\n" - "\t'--startday' and the '--range' option.\n" - "\n -i <file>, --import <file>\n" - " import the icalendar data contained in <file>. \n" - "\n -n, --next\n" - " print next appointment within upcoming 24 hours " - "and exit. Also given\n\tis the remaining time before this " - "next appointment.\n" - "\n -N, --note\n" - " when used with the '-a' or '-t' flag, also print note content\n" - " if one is associated with the displayed item.\n" - "\n -r[num], --range[=num]\n" - " print events and appointments for the [num] number of days" - "\n\tand exit. If no [num] is given, a range of 1 day is considered.\n" - "\n -s[date], --startday[=date]\n" - " print events and appointments from [date] and exit.\n" - "\tIf no [date] is given, the current day is considered.\n" - "\n -S<regex>, --search=<regex>\n" - " search for the given regular expression within events, appointments,\n" - "\tand todos description.\n" - "\n -t[num], --todo[=num]\n" - " print todo list and exit. If the optional number [num] is given,\n" - "\tthen only todos having a priority equal to [num] will be returned.\n" - "\tThe priority number must be between 1 (highest) and 9 (lowest).\n" - "\tIt is also possible to specify '0' for the priority, in which case\n" - "\tonly completed tasks will be shown.\n" - "\n -x[format], --export[=format]\n" - " export user data to the specified format. Events, appointments and\n" - "\ttodos are converted and echoed to stdout.\n" - "\tTwo possible formats are available: 'ical' and 'pcal'.\n" - "\tIf the optional argument format is not given, ical format is\n" - "\tselected by default.\n" - "\tnote: redirect standard output to export data to a file,\n" - "\tby issuing a command such as: calcurse --export > calcurse.dat\n" - "\nFor more information, type '?' from within Calcurse, " - "or read the manpage.\n" - "Mail bug reports and suggestions to <misc@calcurse.org>.\n"); - - (void)snprintf (htitle, BUFSIZ, _("Calcurse %s - text-based organizer\n"), - VERSION); - fputs (htitle, stdout); - usage (); - fputs (htext, stdout); + const char *htext = + _("\nMiscellaneous:\n" + " -h, --help\n" + " print this help and exit.\n" + "\n -v, --version\n" + " print calcurse version and exit.\n" + "\n --status\n" + " display the status of running instances of calcurse.\n" + "\n --read-only\n" + " Don't save configuration nor appointments/todos. Use with care.\n" + "\nFiles:\n" + " -c <file>, --calendar <file>\n" + " specify the calendar <file> to use (incompatible with '-D').\n" + "\n -D <dir>, --directory <dir>\n" + " specify the data directory to use (incompatible with '-c').\n" + "\tIf not specified, the default directory is ~/.calcurse\n" + "\nNon-interactive:\n" + " -a, --appointment\n" + " print events and appointments for current day and exit.\n" + "\n -d <date|num>, --day <date|num>\n" + " print events and appointments for <date> or <num> upcoming days and" + "\n\texit. To specify both a starting date and a range, use the\n" + "\t'--startday' and the '--range' option.\n" + "\n -g, --gc\n" + " run the garbage collector for note files and exit. \n" + "\n -i <file>, --import <file>\n" + " import the icalendar data contained in <file>. \n" + "\n -n, --next\n" + " print next appointment within upcoming 24 hours " + "and exit. Also given\n\tis the remaining time before this " + "next appointment.\n" + "\n -r[num], --range[=num]\n" + " print events and appointments for the [num] number of days" + "\n\tand exit. If no [num] is given, a range of 1 day is considered.\n" + "\n -s[date], --startday[=date]\n" + " print events and appointments from [date] and exit.\n" + "\tIf no [date] is given, the current day is considered.\n" + "\n -S<regex>, --search=<regex>\n" + " search for the given regular expression within events, appointments,\n" + "\tand todos description.\n" + "\n -t[num], --todo[=num]\n" + " print todo list and exit. If the optional number [num] is given,\n" + "\tthen only todos having a priority equal to [num] will be returned.\n" + "\tThe priority number must be between 1 (highest) and 9 (lowest).\n" + "\tIt is also possible to specify '0' for the priority, in which case\n" + "\tonly completed tasks will be shown.\n" + "\n -x[format], --export[=format]\n" + " export user data to the specified format. Events, appointments and\n" + "\ttodos are converted and echoed to stdout.\n" + "\tTwo possible formats are available: 'ical' and 'pcal'.\n" + "\tIf the optional argument format is not given, ical format is\n" + "\tselected by default.\n" + "\tnote: redirect standard output to export data to a file,\n" + "\tby issuing a command such as: calcurse --export > calcurse.dat\n" + "\nFor more information, type '?' from within Calcurse, " + "or read the manpage.\n" + "Mail bug reports and suggestions to <misc@calcurse.org>.\n"); + + fprintf(stdout, _("Calcurse %s - text-based organizer\n"), VERSION); + usage(); + fputs(htext, stdout); } /* @@ -164,78 +166,24 @@ help_arg () * The status is obtained by looking at pid files in user data directory * (.calcurse.pid and .daemon.pid). */ -static void -status_arg (void) +static void status_arg(void) { int cpid, dpid; - cpid = io_get_pid (path_cpid); - dpid = io_get_pid (path_dpid); + cpid = io_get_pid(path_cpid); + dpid = io_get_pid(path_dpid); - EXIT_IF (cpid && dpid, - _("Error: both calcurse (pid: %d) and its daemon (pid: %d)\n" - "seem to be running at the same time!\n" - "Please check manually and restart calcurse.\n"), - cpid, dpid); + EXIT_IF(cpid && dpid, + _("Error: both calcurse (pid: %d) and its daemon (pid: %d)\n" + "seem to be running at the same time!\n" + "Please check manually and restart calcurse.\n"), cpid, dpid); if (cpid) - fprintf (stdout, _("calcurse is running (pid %d)\n"), cpid); + fprintf(stdout, _("calcurse is running (pid %d)\n"), cpid); else if (dpid) - fprintf (stdout, _("calcurse is running in background (pid %d)\n"), dpid); + fprintf(stdout, _("calcurse is running in background (pid %d)\n"), dpid); else - fprintf (stdout, _("calcurse is not running\n")); -} - -/* - * Display note contents if one is asociated with the currently displayed item - * (to be used together with the '-a' or '-t' flag in non-interactive mode). - * Each line begins with nbtab tabs. - * Print "No note file found", if the notefile does not exists. - * - * (patch submitted by Erik Saule). - */ -static void -print_notefile (FILE *out, char *filename, int nbtab) -{ - char path_to_notefile[BUFSIZ]; - FILE *notefile; - char linestarter[BUFSIZ]; - char buffer[BUFSIZ]; - int i; - int printlinestarter = 1; - - if (nbtab < BUFSIZ) - { - for (i = 0; i < nbtab; i++) - linestarter[i] = '\t'; - linestarter[nbtab] = '\0'; - } - else - linestarter[0] = '\0'; - - (void)snprintf (path_to_notefile, BUFSIZ, "%s/%s", path_notes, filename); - notefile = fopen (path_to_notefile, "r"); - if (notefile) - { - while (fgets (buffer, BUFSIZ, notefile) != 0) - { - if (printlinestarter) - { - fputs (linestarter, out); - printlinestarter = 0; - } - fputs (buffer, out); - if (buffer[strlen (buffer) - 1] == '\n') - printlinestarter = 1; - } - fputs ("\n", out); - file_close (notefile, __FILE_POS__); - } - else - { - fputs (linestarter, out); - fputs (_("No note file found\n"), out); - } + puts(_("calcurse is not running\n")); } /* @@ -245,14 +193,13 @@ print_notefile (FILE *out, char *filename, int nbtab) * If priority == 0, only completed tasks will be displayed. * If regex is not null, only the matching todos are printed. */ -static void -todo_arg (int priority, int print_note, regex_t *regex) +static void todo_arg(int priority, const char *format, regex_t * regex) { llist_item_t *i; int title = 1; - char *titlestr, priority_str[BUFSIZ] = ""; - char *all_todos_title = _("to do:\n"); - char *completed_title = _("completed tasks:\n"); + const char *titlestr; + const char *all_todos_title = _("to do:\n"); + const char *completed_title = _("completed tasks:\n"); titlestr = priority == 0 ? completed_title : all_todos_title; @@ -264,49 +211,32 @@ todo_arg (int priority, int print_note, regex_t *regex) } \ } while (0) -#define DISPLAY_TODO do { \ - (void)snprintf (priority_str, BUFSIZ, "%d. ", abs (todo->id)); \ - fputs (priority_str, stdout); \ - fputs (todo->mesg, stdout); \ - fputs ("\n", stdout); \ - if (print_note && todo->note) \ - print_notefile (stdout, todo->note, 1); \ - } while (0) - - LLIST_FOREACH (&todolist, i) - { - struct todo *todo = LLIST_TS_GET_DATA (i); - if (regex && regexec (regex, todo->mesg, 0, 0, 0) != 0) - continue; - - if (todo->id < 0) /* completed task */ - { - if (priority == 0) - { - DISPLAY_TITLE; - DISPLAY_TODO; - } - } - else - { - if (priority < 0 || todo->id == priority) - { - DISPLAY_TITLE; - DISPLAY_TODO; - } - } + LLIST_FOREACH(&todolist, i) { + struct todo *todo = LLIST_TS_GET_DATA(i); + if (regex && regexec(regex, todo->mesg, 0, 0, 0) != 0) + continue; + + if (todo->id < 0) { /* completed task */ + if (priority == 0) { + DISPLAY_TITLE; + print_todo(format, todo); + } + } else { + if (priority < 0 || todo->id == priority) { + DISPLAY_TITLE; + print_todo(format, todo); + } } + } #undef DISPLAY_TITLE -#undef DISPLAY_TODO } /* Print the next appointment within the upcoming 24 hours. */ -static void -next_arg (void) +static void next_arg(void) { struct notify_app next_app; - const long current_time = now (); + const long current_time = now(); int time_left, hours_left, min_left; char mesg[BUFSIZ]; @@ -314,37 +244,35 @@ next_arg (void) next_app.got_app = 0; next_app.txt = NULL; - next_app = *recur_apoint_check_next (&next_app, current_time, get_today ()); - next_app = *apoint_check_next (&next_app, current_time); - - if (next_app.got_app) - { - time_left = next_app.time - current_time; - hours_left = (time_left / HOURINSEC); - min_left = (time_left - hours_left * HOURINSEC) / MININSEC; - fputs (_("next appointment:\n"), stdout); - (void)snprintf (mesg, BUFSIZ, " [%02d:%02d] %s\n", hours_left, min_left, - next_app.txt); - fputs (mesg, stdout); - mem_free (next_app.txt); - } + next_app = *recur_apoint_check_next(&next_app, current_time, get_today()); + next_app = *apoint_check_next(&next_app, current_time); + + if (next_app.got_app) { + time_left = next_app.time - current_time; + hours_left = (time_left / HOURINSEC); + min_left = (time_left - hours_left * HOURINSEC) / MININSEC; + fputs(_("next appointment:\n"), stdout); + snprintf(mesg, BUFSIZ, " [%02d:%02d] %s\n", hours_left, min_left, + next_app.txt); + fputs(mesg, stdout); + mem_free(next_app.txt); + } } /* * Print the date on stdout. */ -static void -arg_print_date (long date, struct conf *conf) +static void arg_print_date(long date) { char date_str[BUFSIZ]; time_t t; struct tm *lt; t = date; - lt = localtime (&t); - strftime (date_str, BUFSIZ, conf->output_datefmt, lt); - fputs (date_str, stdout); - fputs (":\n", stdout); + lt = localtime(&t); + strftime(date_str, BUFSIZ, conf.output_datefmt, lt); + fputs(date_str, stdout); + fputs(":\n", stdout); } /* @@ -354,18 +282,17 @@ arg_print_date (long date, struct conf *conf) * If regex is not null, only the matching appointments or events are printed. */ static int -app_arg (int add_line, struct date *day, long date, int print_note, - struct conf *conf, regex_t *regex) +app_arg(int add_line, struct date *day, long date, const char *fmt_apt, + const char *fmt_rapt, const char *fmt_ev, const char *fmt_rev, + regex_t * regex) { llist_item_t *i, *j; long today; unsigned print_date = 1; int app_found = 0; - char apoint_start_time[HRMIN_SIZE]; - char apoint_end_time[HRMIN_SIZE]; if (date == 0) - today = get_sec_date (*day); + today = get_sec_date(*day); else today = date; @@ -374,159 +301,114 @@ app_arg (int add_line, struct date *day, long date, int print_note, * that date and it is the first one, and then print all the events for * that date. */ - LLIST_FIND_FOREACH (&recur_elist, today, recur_event_inday, i) - { - struct recur_event *re = LLIST_GET_DATA (i); - if (regex && regexec (regex, re->mesg, 0, 0, 0) != 0) - continue; - - app_found = 1; - if (add_line) - { - fputs ("\n", stdout); - add_line = 0; - } - if (print_date) - { - arg_print_date (today, conf); - print_date = 0; - } - fputs (" * ", stdout); - fputs (re->mesg, stdout); - fputs ("\n", stdout); - if (print_note && re->note) - print_notefile (stdout, re->note, 2); + LLIST_FIND_FOREACH(&recur_elist, today, recur_event_inday, i) { + struct recur_event *re = LLIST_GET_DATA(i); + if (regex && regexec(regex, re->mesg, 0, 0, 0) != 0) + continue; + + app_found = 1; + if (add_line) { + fputs("\n", stdout); + add_line = 0; } - - LLIST_FIND_FOREACH (&eventlist, today, event_inday, i) - { - struct event *ev = LLIST_TS_GET_DATA (i); - if (regex && regexec (regex, ev->mesg, 0, 0, 0) != 0) - continue; - - app_found = 1; - if (add_line) - { - fputs ("\n", stdout); - add_line = 0; - } - if (print_date) - { - arg_print_date (today, conf); - print_date = 0; - } - fputs (" * ", stdout); - fputs (ev->mesg, stdout); - fputs ("\n", stdout); - if (print_note && ev->note) - print_notefile (stdout, ev->note, 2); + if (print_date) { + arg_print_date(today); + print_date = 0; + } + print_recur_event(fmt_rev, today, re); + } + + LLIST_FIND_FOREACH_CONT(&eventlist, today, event_inday, i) { + struct event *ev = LLIST_TS_GET_DATA(i); + if (regex && regexec(regex, ev->mesg, 0, 0, 0) != 0) + continue; + + app_found = 1; + if (add_line) { + fputs("\n", stdout); + add_line = 0; + } + if (print_date) { + arg_print_date(today); + print_date = 0; } + print_event(fmt_ev, today, ev); + } /* Same process is performed but this time on the appointments. */ - LLIST_TS_LOCK (&alist_p); - LLIST_TS_LOCK (&recur_alist_p); + LLIST_TS_LOCK(&alist_p); + LLIST_TS_LOCK(&recur_alist_p); /* * Iterate over regular appointments and recurrent ones simultaneously (fixes * http://lists.calcurse.org/bugs/msg00002.html). */ - i = LLIST_TS_FIND_FIRST (&alist_p, today, apoint_inday); - j = LLIST_TS_FIND_FIRST (&recur_alist_p, today, recur_apoint_inday); - while (i || j) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - struct recur_apoint *ra = LLIST_TS_GET_DATA (j); - - while (i && regex && regexec (regex, apt->mesg, 0, 0, 0) != 0) - { - i = LLIST_TS_FIND_NEXT (i, today, apoint_inday); - apt = LLIST_TS_GET_DATA (i); - } + i = LLIST_TS_FIND_FIRST(&alist_p, today, apoint_inday); + j = LLIST_TS_FIND_FIRST(&recur_alist_p, today, recur_apoint_inday); + while (i || j) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + struct recur_apoint *ra = LLIST_TS_GET_DATA(j); + unsigned occurrence; + + while (i && regex && regexec(regex, apt->mesg, 0, 0, 0) != 0) { + i = LLIST_TS_FIND_NEXT(i, today, apoint_inday); + apt = LLIST_TS_GET_DATA(i); + } - while (j && regex && regexec (regex, ra->mesg, 0, 0, 0) != 0) - { - j = LLIST_TS_FIND_NEXT (j, today, recur_apoint_inday); - ra = LLIST_TS_GET_DATA (j); - } + while (j && regex && regexec(regex, ra->mesg, 0, 0, 0) != 0) { + j = LLIST_TS_FIND_NEXT(j, today, recur_apoint_inday); + ra = LLIST_TS_GET_DATA(j); + } - if (apt && ra) - { - if (apt->start <= recur_apoint_inday (ra, today)) - ra = NULL; - else - apt = NULL; - } + if (apt && ra) { + if (recur_apoint_find_occurrence(ra, today, &occurrence) && + apt->start <= occurrence) + ra = NULL; + else + apt = NULL; + } - if (apt) - { - app_found = 1; - if (add_line) - { - fputs ("\n", stdout); - add_line = 0; - } - if (print_date) - { - arg_print_date (today, conf); - print_date = 0; - } - apoint_sec2str (apt, APPT, today, apoint_start_time, apoint_end_time); - fputs (" - ", stdout); - fputs (apoint_start_time, stdout); - fputs (" -> ", stdout); - fputs (apoint_end_time, stdout); - fputs ("\n\t", stdout); - fputs (apt->mesg, stdout); - fputs ("\n", stdout); - if (print_note && apt->note) - print_notefile (stdout, apt->note, 2); - i = LLIST_TS_FIND_NEXT (i, today, apoint_inday); - } - else if (ra) - { - app_found = 1; - if (add_line) - { - fputs ("\n", stdout); - add_line = 0; - } - if (print_date) - { - arg_print_date (today, conf); - print_date = 0; - } - apt = apoint_recur_s2apoint_s (ra); - apoint_sec2str (apt, RECUR_APPT, today, apoint_start_time, - apoint_end_time); - mem_free (apt->mesg); - mem_free (apt); - fputs (" - ", stdout); - fputs (apoint_start_time, stdout); - fputs (" -> ", stdout); - fputs (apoint_end_time, stdout); - fputs ("\n\t", stdout); - fputs (ra->mesg, stdout); - fputs ("\n", stdout); - if (print_note && ra->note) - print_notefile (stdout, ra->note, 2); - apt = NULL; - j = LLIST_TS_FIND_NEXT (j, today, recur_apoint_inday); - } + if (apt) { + app_found = 1; + if (add_line) { + fputs("\n", stdout); + add_line = 0; + } + if (print_date) { + arg_print_date(today); + print_date = 0; + } + print_apoint(fmt_apt, today, apt); + i = LLIST_TS_FIND_NEXT(i, today, apoint_inday); + } else if (ra) { + app_found = 1; + if (add_line) { + fputs("\n", stdout); + add_line = 0; + } + if (print_date) { + arg_print_date(today); + print_date = 0; + } + recur_apoint_find_occurrence(ra, today, &occurrence); + print_recur_apoint(fmt_rapt, today, occurrence, ra); + apt = NULL; + j = LLIST_TS_FIND_NEXT(j, today, recur_apoint_inday); } + } - LLIST_TS_UNLOCK (&recur_alist_p); - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_UNLOCK(&recur_alist_p); + LLIST_TS_UNLOCK(&alist_p); - return (app_found); + return app_found; } -static void -more_info (void) +static void more_info(void) { - fputs (_("\nFor more information, type '?' from within Calcurse, " - "or read the manpage.\n"), stdout); - fputs (_("Mail bug reports and suggestions to " - "<misc@calcurse.org>.\n"), stdout); + fputs(_("\nFor more information, type '?' from within Calcurse, " + "or read the manpage.\n"), stdout); + fputs(_("Mail bug reports and suggestions to " + "<misc@calcurse.org>.\n"), stdout); } /* @@ -535,23 +417,24 @@ more_info (void) * to format the output correctly. */ static void -display_app (struct tm *t, int numdays, int add_line, int print_note, - struct conf *conf, regex_t *regex) +display_app(struct tm *t, int numdays, int add_line, const char *fmt_apt, + const char *fmt_rapt, const char *fmt_ev, const char *fmt_rev, + regex_t * regex) { int i, app_found; struct date day; - for (i = 0; i < numdays; i++) - { - day.dd = t->tm_mday; - day.mm = t->tm_mon + 1; - day.yyyy = t->tm_year + 1900; - app_found = app_arg (add_line, &day, 0, print_note, conf, regex); - if (app_found) - add_line = 1; - t->tm_mday++; - (void)mktime (t); - } + for (i = 0; i < numdays; i++) { + day.dd = t->tm_mday; + day.mm = t->tm_mon + 1; + day.yyyy = t->tm_year + 1900; + app_found = app_arg(add_line, &day, 0, fmt_apt, fmt_rapt, fmt_ev, + fmt_rev, regex); + if (app_found) + add_line = 1; + t->tm_mday++; + mktime(t); + } } /* @@ -559,8 +442,9 @@ display_app (struct tm *t, int numdays, int add_line, int print_note, * days. */ static void -date_arg (char *ddate, int add_line, int print_note, struct conf *conf, - regex_t *regex) +date_arg(const char *ddate, int add_line, const char *fmt_apt, + const char *fmt_rapt, const char *fmt_ev, const char *fmt_rev, + regex_t * regex) { int i; struct date day; @@ -573,44 +457,38 @@ date_arg (char *ddate, int add_line, int print_note, struct conf *conf, * Check (with the argument length) if a date or a number of days * was entered, and then call app_arg() to print appointments */ - arg_len = strlen (ddate); - if (arg_len <= 4) - { /* a number of days was entered */ - for (i = 0; i <= arg_len - 1; i++) - { - if (isdigit (ddate[i])) - num_digit++; - } - if (num_digit == arg_len) - numdays = atoi (ddate); - - /* - * Get current date, and print appointments for each day - * in the chosen interval. app_found and add_line are used - * to format the output correctly. - */ - timer = time (NULL); - t = *localtime (&timer); - display_app (&t, numdays, add_line, print_note, conf, regex); + arg_len = strlen(ddate); + if (arg_len <= 4) { /* a number of days was entered */ + for (i = 0; i <= arg_len - 1; i++) { + if (isdigit(ddate[i])) + num_digit++; } - else - { /* a date was entered */ - if (parse_date (ddate, conf->input_datefmt, (int *)&day.yyyy, - (int *)&day.mm, (int *)&day.dd, NULL)) - { - (void)app_arg (add_line, &day, 0, print_note, conf, regex); - } - else - { - char outstr[BUFSIZ]; - fputs (_("Argument to the '-d' flag is not valid\n"), stderr); - (void)snprintf (outstr, BUFSIZ, - "Possible argument format are: '%s' or 'n'\n", - DATEFMT_DESC (conf->input_datefmt)); - fputs (_(outstr), stdout); - more_info (); - } + if (num_digit == arg_len) + numdays = atoi(ddate); + + /* + * Get current date, and print appointments for each day + * in the chosen interval. app_found and add_line are used + * to format the output correctly. + */ + timer = time(NULL); + t = *localtime(&timer); + display_app(&t, numdays, add_line, fmt_apt, fmt_rapt, fmt_ev, fmt_rev, + regex); + } else { /* a date was entered */ + if (parse_date(ddate, conf.input_datefmt, (int *)&day.yyyy, + (int *)&day.mm, (int *)&day.dd, NULL)) { + app_arg(add_line, &day, 0, fmt_apt, fmt_rapt, fmt_ev, fmt_rev, regex); + } else { + char outstr[BUFSIZ]; + fputs(_("Argument to the '-d' flag is not valid\n"), stderr); + snprintf(outstr, BUFSIZ, + "Possible argument format are: '%s' or 'n'\n", + DATEFMT_DESC(conf.input_datefmt)); + fputs(_(outstr), stdout); + more_info(); } + } } /* @@ -622,8 +500,9 @@ date_arg (char *ddate, int add_line, int print_note, struct conf *conf, * Many thanks to Erik Saule for providing this function. */ static void -date_arg_extended (char *startday, char *range, int add_line, int print_note, - struct conf *conf, regex_t *regex) +date_arg_extended(const char *startday, const char *range, int add_line, + const char *fmt_apt, const char *fmt_rapt, + const char *fmt_ev, const char *fmt_rev, regex_t * regex) { int i, numdays = 1, error = 0, arg_len = 0; static struct tm t; @@ -632,95 +511,91 @@ date_arg_extended (char *startday, char *range, int add_line, int print_note, /* * Check arguments and extract information */ - if (range != NULL) - { - arg_len = strlen (range); - for (i = 0; i <= arg_len - 1; i++) - { - if (!isdigit (range[i])) - error = 1; - } - if (!error) - numdays = atoi (range); + if (range != NULL) { + arg_len = strlen(range); + for (i = 0; i <= arg_len - 1; i++) { + if (!isdigit(range[i])) + error = 1; } - timer = time (NULL); - t = *localtime (&timer); - if (startday != NULL) - { - if (parse_date (startday, conf->input_datefmt, (int *)&t.tm_year, - (int *)&t.tm_mon, (int *)&t.tm_mday, NULL)) - { - t.tm_year -= 1900; - t.tm_mon--; - (void)mktime (&t); - } - else - { - error = 1; - } - } - if (!error) - { - display_app (&t, numdays, add_line, print_note, conf, regex); - } - else - { - char outstr[BUFSIZ]; - fputs (_("Argument is not valid\n"), stderr); - (void)snprintf (outstr, BUFSIZ, - "Argument format for -s and --startday is: '%s'\n", - DATEFMT_DESC (conf->input_datefmt)); - fputs (_(outstr), stdout); - fputs (_("Argument format for -r and --range is: 'n'\n"), stdout); - more_info (); + if (!error) + numdays = atoi(range); + } + timer = time(NULL); + t = *localtime(&timer); + if (startday != NULL) { + if (parse_date(startday, conf.input_datefmt, (int *)&t.tm_year, + (int *)&t.tm_mon, (int *)&t.tm_mday, NULL)) { + t.tm_year -= 1900; + t.tm_mon--; + mktime(&t); + } else { + error = 1; } + } + if (!error) { + display_app(&t, numdays, add_line, fmt_apt, fmt_rapt, fmt_ev, fmt_rev, + regex); + } else { + char outstr[BUFSIZ]; + fputs(_("Argument is not valid\n"), stderr); + snprintf(outstr, BUFSIZ, + "Argument format for -s and --startday is: '%s'\n", + DATEFMT_DESC(conf.input_datefmt)); + fputs(_(outstr), stdout); + fputs(_("Argument format for -r and --range is: 'n'\n"), stdout); + more_info(); + } } - /* * Parse the command-line arguments and call the appropriate * routines to handle those arguments. Also initialize the data paths. */ -int -parse_args (int argc, char **argv, struct conf *conf) +int parse_args(int argc, char **argv) { int ch, add_line = 0; int unknown_flag = 0; /* Command-line flags */ - int aflag = 0; /* -a: print appointments for current day */ - int cflag = 0; /* -c: specify the calendar file to use */ - int dflag = 0; /* -d: print appointments for a specified days */ - int Dflag = 0; /* -D: specify data directory to use */ - int hflag = 0; /* -h: print help text */ - int iflag = 0; /* -i: import data */ - int nflag = 0; /* -n: print next appointment */ - int Nflag = 0; /* -N: also print note content with apps and todos */ - int rflag = 0; /* -r: specify the range of days to consider */ - int sflag = 0; /* -s: specify the first day to consider */ - int Sflag = 0; /* -S: specify a regex to search for */ - int tflag = 0; /* -t: print todo list */ - int vflag = 0; /* -v: print version number */ - int xflag = 0; /* -x: export data */ + int aflag = 0; /* -a: print appointments for current day */ + int cflag = 0; /* -c: specify the calendar file to use */ + int dflag = 0; /* -d: print appointments for a specified days */ + int Dflag = 0; /* -D: specify data directory to use */ + int hflag = 0; /* -h: print help text */ + int gflag = 0; /* -g: run garbage collector */ + int iflag = 0; /* -i: import data */ + int nflag = 0; /* -n: print next appointment */ + int rflag = 0; /* -r: specify the range of days to consider */ + int sflag = 0; /* -s: specify the first day to consider */ + int Sflag = 0; /* -S: specify a regex to search for */ + int tflag = 0; /* -t: print todo list */ + int vflag = 0; /* -v: print version number */ + int xflag = 0; /* -x: export data */ + /* Format strings */ + const char *fmt_apt = " - %S -> %E\n\t%m\n"; + const char *fmt_rapt = " - %S -> %E\n\t%m\n"; + const char *fmt_ev = " * %m\n"; + const char *fmt_rev = " * %m\n"; + const char *fmt_todo = "%p. %m\n"; int tnum = 0, xfmt = 0, non_interactive = 0, multiple_flag = 0, load_data = 0; - char *ddate = "", *cfile = NULL, *range = NULL, *startday = NULL; - char *datadir = NULL, *ifile = NULL; + const char *ddate = "", *cfile = NULL, *range = NULL, *startday = NULL; + const char *datadir = NULL, *ifile = NULL; regex_t reg, *preg = NULL; /* Long options only */ - int statusflag = 0; /* --status: get the status of running instances */ - enum - { + int statusflag = 0; /* --status: get the status of running instances */ + enum { STATUS_OPT = CHAR_MAX + 1 }; - static char *optstr = "hvnNax::t::d:c:r::s::S:D:i:"; + static const char *optstr = "ghvnNax::t::d:c:r::s::S:D:i:"; struct option longopts[] = { {"appointment", no_argument, NULL, 'a'}, {"calendar", required_argument, NULL, 'c'}, {"day", required_argument, NULL, 'd'}, {"directory", required_argument, NULL, 'D'}, + {"gc", no_argument, NULL, 'g'}, {"help", no_argument, NULL, 'h'}, {"import", required_argument, NULL, 'i'}, {"next", no_argument, NULL, 'n'}, @@ -732,255 +607,253 @@ parse_args (int argc, char **argv, struct conf *conf) {"todo", optional_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, {"export", optional_argument, NULL, 'x'}, + + {"format-apt", required_argument, NULL, OPT_FMT_APT}, + {"format-recur-apt", required_argument, NULL, OPT_FMT_RAPT}, + {"format-event", required_argument, NULL, OPT_FMT_EV}, + {"format-recur-event", required_argument, NULL, OPT_FMT_REV}, + {"format-todo", required_argument, NULL, OPT_FMT_TODO}, + {"read-only", no_argument, NULL, OPT_READ_ONLY}, {NULL, no_argument, NULL, 0} }; - while ((ch = getopt_long (argc, argv, optstr, longopts, NULL)) != -1) - { - switch (ch) - { - case STATUS_OPT: - statusflag = 1; - break; - case 'a': - aflag = 1; - multiple_flag++; - load_data++; - break; - case 'c': - cflag = 1; - multiple_flag++; - cfile = optarg; - load_data++; - break; - case 'd': - dflag = 1; - multiple_flag++; - load_data++; - ddate = optarg; - break; - case 'D': - Dflag = 1; - datadir = optarg; - break; - case 'h': - hflag = 1; - break; - case 'i': - iflag = 1; - multiple_flag++; - load_data++; - ifile = optarg; - break; - case 'n': - nflag = 1; - multiple_flag++; - load_data++; - break; - case 'N': - Nflag = 1; - break; - case 'r': - rflag = 1; - multiple_flag++; - load_data++; - range = optarg; - break; - case 's': - sflag = 1; - multiple_flag++; - load_data++; - startday = optarg; - break; - case 'S': - EXIT_IF (Sflag > 0, - _("Can not handle more than one regular expression.")); - Sflag = 1; - if (regcomp (®, optarg, REG_EXTENDED)) - EXIT (_("Could not compile regular expression.")); - preg = ® - break; - case 't': - tflag = 1; - multiple_flag++; - load_data++; - add_line = 1; - if (optarg != NULL) - { - tnum = atoi (optarg); - if (tnum < 0 || tnum > 9) - { - usage (); - usage_try (); - return (EXIT_FAILURE); - } - } - else - tnum = -1; - break; - case 'v': - vflag = 1; - break; - case 'x': - xflag = 1; - multiple_flag++; - load_data++; - if (optarg != NULL) - { - if (strcmp (optarg, "ical") == 0) - xfmt = IO_EXPORT_ICAL; - else if (strcmp (optarg, "pcal") == 0) - xfmt = IO_EXPORT_PCAL; - else - { - fputs (_("Argument for '-x' should be either " - "'ical' or 'pcal'\n"), stderr); - usage (); - usage_try (); - return EXIT_FAILURE; - } - } - else - { - xfmt = IO_EXPORT_ICAL; - } - break; - default: - usage (); - usage_try (); - unknown_flag = 1; - non_interactive = 1; - /* NOTREACHED */ + while ((ch = getopt_long(argc, argv, optstr, longopts, NULL)) != -1) { + switch (ch) { + case STATUS_OPT: + statusflag = 1; + break; + case 'a': + aflag = 1; + multiple_flag++; + load_data++; + break; + case 'c': + cflag = 1; + multiple_flag++; + cfile = optarg; + load_data++; + break; + case 'd': + dflag = 1; + multiple_flag++; + load_data++; + ddate = optarg; + break; + case 'D': + Dflag = 1; + datadir = optarg; + break; + case 'h': + hflag = 1; + break; + case 'g': + gflag = 1; + break; + case 'i': + iflag = 1; + multiple_flag++; + load_data++; + ifile = optarg; + break; + case 'n': + nflag = 1; + multiple_flag++; + load_data++; + break; + case 'r': + rflag = 1; + multiple_flag++; + load_data++; + range = optarg; + break; + case 's': + sflag = 1; + multiple_flag++; + load_data++; + startday = optarg; + break; + case 'S': + EXIT_IF(Sflag > 0, _("Can not handle more than one regular expression.")); + Sflag = 1; + if (regcomp(®, optarg, REG_EXTENDED)) + EXIT(_("Could not compile regular expression.")); + preg = ® + break; + case 't': + tflag = 1; + multiple_flag++; + load_data++; + add_line = 1; + if (optarg != NULL) { + tnum = atoi(optarg); + if (tnum < 0 || tnum > 9) { + usage(); + usage_try(); + return EXIT_FAILURE; } + } else + tnum = -1; + break; + case 'v': + vflag = 1; + break; + case 'x': + xflag = 1; + multiple_flag++; + load_data++; + if (optarg != NULL) { + if (strcmp(optarg, "ical") == 0) + xfmt = IO_EXPORT_ICAL; + else if (strcmp(optarg, "pcal") == 0) + xfmt = IO_EXPORT_PCAL; + else { + fputs(_("Argument for '-x' should be either " + "'ical' or 'pcal'\n"), stderr); + usage(); + usage_try(); + return EXIT_FAILURE; + } + } else { + xfmt = IO_EXPORT_ICAL; + } + break; + case OPT_FMT_APT: + fmt_apt = optarg; + break; + case OPT_FMT_RAPT: + fmt_rapt = optarg; + break; + case OPT_FMT_EV: + fmt_ev = optarg; + break; + case OPT_FMT_REV: + fmt_rev = optarg; + break; + case OPT_FMT_TODO: + fmt_todo = optarg; + break; + case OPT_READ_ONLY: + read_only = 1; + break; + default: + usage(); + usage_try(); + unknown_flag = 1; + non_interactive = 1; + /* NOTREACHED */ } + } argc -= optind; - if (argc >= 1) - { - usage (); - usage_try (); - return EXIT_FAILURE; - /* Incorrect arguments */ - } - else if (Dflag && cflag) - { - fputs (_("Options '-D' and '-c' cannot be used at the same time\n"), - stderr); - usage (); - usage_try (); - return EXIT_FAILURE; - } - else if (Sflag && !(aflag || dflag || rflag || sflag || tflag)) - { - fputs (_("Option '-S' must be used with either '-d', '-r', '-s', " - "'-a' or '-t'\n"), stderr); - usage (); - usage_try (); - return EXIT_FAILURE; - } - else - { - if (unknown_flag) - { - non_interactive = 1; - } - else if (hflag) - { - help_arg (); - non_interactive = 1; - } - else if (vflag) - { - version_arg (); - non_interactive = 1; - } - else if (statusflag) - { - io_init (cfile, datadir); - status_arg (); - non_interactive = 1; - } - else if (multiple_flag) - { - if (load_data) - { - io_init (cfile, datadir); - io_check_dir (path_dir, (int *)0); - io_check_dir (path_notes, (int *)0); - } - if (iflag) - { - io_check_file (path_apts, (int *)0); - io_check_file (path_todo, (int *)0); - /* Get default pager in case we need to show a log file. */ - vars_init (conf); - io_load_app (); - io_load_todo (); - io_import_data (IO_IMPORT_ICAL, conf, ifile); - io_save_apts (); - io_save_todo (); - non_interactive = 1; - } - if (xflag) - { - io_check_file (path_apts, (int *)0); - io_check_file (path_todo, (int *)0); - io_load_app (); - io_load_todo (); - io_export_data (xfmt, conf); - non_interactive = 1; - return non_interactive; - } - if (tflag) - { - io_check_file (path_todo, (int *)0); - io_load_todo (); - todo_arg (tnum, Nflag, preg); - non_interactive = 1; - } - if (nflag) - { - io_check_file (path_apts, (int *)0); - io_load_app (); - next_arg (); - non_interactive = 1; - } - if (dflag || rflag || sflag) - { - io_check_file (path_apts, (int *)0); - io_check_file (path_conf, (int *)0); - io_load_app (); - custom_load_conf (conf, 0); /* To get output date format. */ - if (dflag) - date_arg (ddate, add_line, Nflag, conf, preg); - if (rflag || sflag) - date_arg_extended (startday, range, add_line, Nflag, conf, - preg); - non_interactive = 1; - } - else if (aflag) - { - struct date day; - - io_check_file (path_apts, (int *)0); - io_check_file (path_conf, (int *)0); - vars_init (conf); - custom_load_conf (conf, 0); /* To get output date format. */ - io_load_app (); - day.dd = day.mm = day.yyyy = 0; - (void)app_arg (add_line, &day, 0, Nflag, conf, preg); - non_interactive = 1; - } - } - else - { - non_interactive = 0; - io_init (cfile, datadir); - } + if (argc >= 1) { + usage(); + usage_try(); + return EXIT_FAILURE; + /* Incorrect arguments */ + } else if (Dflag && cflag) { + fputs(_("Options '-D' and '-c' cannot be used at the same time\n"), stderr); + usage(); + usage_try(); + return EXIT_FAILURE; + } else if (Sflag && !(aflag || dflag || rflag || sflag || tflag)) { + fputs(_("Option '-S' must be used with either '-d', '-r', '-s', " + "'-a' or '-t'\n"), stderr); + usage(); + usage_try(); + return EXIT_FAILURE; + } else { + if (unknown_flag) { + non_interactive = 1; + } else if (hflag) { + help_arg(); + non_interactive = 1; + } else if (vflag) { + version_arg(); + non_interactive = 1; + } else if (statusflag) { + io_init(cfile, datadir); + status_arg(); + non_interactive = 1; + } else if (gflag) { + io_init(cfile, datadir); + io_check_dir(path_dir, NULL); + io_check_dir(path_notes, NULL); + io_check_file(path_apts, NULL); + io_check_file(path_todo, NULL); + io_load_app(); + io_load_todo(); + note_gc(); + non_interactive = 1; + } else if (multiple_flag) { + if (load_data) { + io_init(cfile, datadir); + io_check_dir(path_dir, NULL); + io_check_dir(path_notes, NULL); + } + if (iflag) { + io_check_file(path_apts, NULL); + io_check_file(path_todo, NULL); + /* Get default pager in case we need to show a log file. */ + vars_init(); + io_load_app(); + io_load_todo(); + io_import_data(IO_IMPORT_ICAL, ifile); + io_save_apts(); + io_save_todo(); + non_interactive = 1; + } + if (xflag) { + io_check_file(path_apts, NULL); + io_check_file(path_todo, NULL); + io_load_app(); + io_load_todo(); + io_export_data(xfmt); + non_interactive = 1; + return non_interactive; + } + if (tflag) { + io_check_file(path_todo, NULL); + io_load_todo(); + todo_arg(tnum, fmt_todo, preg); + non_interactive = 1; + } + if (nflag) { + io_check_file(path_apts, NULL); + io_load_app(); + next_arg(); + non_interactive = 1; + } + if (dflag || rflag || sflag) { + io_check_file(path_apts, NULL); + io_check_file(path_conf, NULL); + io_load_app(); + config_load(); /* To get output date format. */ + if (dflag) + date_arg(ddate, add_line, fmt_apt, fmt_rapt, fmt_ev, fmt_rev, preg); + if (rflag || sflag) + date_arg_extended(startday, range, add_line, fmt_apt, + fmt_rapt, fmt_ev, fmt_rev, preg); + non_interactive = 1; + } else if (aflag) { + struct date day; + + io_check_file(path_apts, NULL); + io_check_file(path_conf, NULL); + vars_init(); + config_load(); /* To get output date format. */ + io_load_app(); + day.dd = day.mm = day.yyyy = 0; + app_arg(add_line, &day, 0, fmt_apt, fmt_rapt, fmt_ev, fmt_rev, preg); + non_interactive = 1; + } + } else { + non_interactive = 0; + io_init(cfile, datadir); } + } if (preg) - regfree (preg); + regfree(preg); return non_interactive; } diff --git a/src/calcurse.c b/src/calcurse.c index 662f185..9e42eee 100644 --- a/src/calcurse.c +++ b/src/calcurse.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,541 +39,484 @@ #include "calcurse.h" /* + * Store the events and appointments for the selected day and reset the + * appointment highlight pointer if a new day was selected. + */ +static struct day_items_nb do_storage(int day_changed) +{ + struct day_items_nb inday = *day_process_storage(calendar_get_slctd_day(), + day_changed, &inday); + + if (day_changed) + apoint_hilt_set(1); + + return inday; +} + +/* * Calcurse is a text-based personal organizer which helps keeping track * of events and everyday tasks. It contains a calendar, a 'todo' list, * and puts your appointments in order. The user interface is configurable, * and one can choose between different color schemes and layouts. * All of the commands are documented within an online help system. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - struct conf conf; struct day_items_nb inday; - int background, foreground; - int non_interactive; int no_data_file = 1; - int sav_hilt_app = 0; - int sav_hilt_tod = 0; int cut_item = 0; - unsigned do_storage = 0; - unsigned do_update = 1; - unsigned day_changed = 0; - char *no_color_support = - _("Sorry, colors are not supported by your terminal\n" - "(Press [ENTER] to continue)"); - char *quit_message = _("Do you really want to quit ?"); - char choices[] = "[y/n] "; + int count; #if ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); #endif /* ENABLE_NLS */ /* Thread-safe data structure init */ - apoint_llist_init (); - recur_apoint_llist_init (); + apoint_llist_init(); + recur_apoint_llist_init(); /* Initialize non-thread-safe data structures. */ - event_llist_init (); - todo_init_list (); + event_llist_init(); + todo_init_list(); /* * Begin by parsing and handling command line arguments. * The data path is also initialized here. */ - non_interactive = parse_args (argc, argv, &conf); - if (non_interactive) - exit_calcurse (EXIT_SUCCESS); - else - { - no_data_file = io_check_data_files (); - dmon_stop (); - io_set_lock (); - } + if (parse_args(argc, argv)) { + /* Non-interactive mode. */ + exit_calcurse(EXIT_SUCCESS); + } else { + no_data_file = io_check_data_files(); + dmon_stop(); + io_set_lock(); + } /* Begin of interactive mode with ncurses interface. */ - sigs_init (); /* signal handling init */ - initscr (); /* start the curses mode */ - cbreak (); /* control chars generate a signal */ - noecho (); /* controls echoing of typed chars */ - curs_set (0); /* make cursor invisible */ - calendar_set_current_date (); - notify_init_vars (); - wins_get_config (); + sigs_init(); /* signal handling init */ + initscr(); /* start the curses mode */ + cbreak(); /* control chars generate a signal */ + noecho(); /* controls echoing of typed chars */ + curs_set(0); /* make cursor invisible */ + calendar_set_current_date(); + notify_init_vars(); + wins_get_config(); /* Check if terminal supports color. */ - if (has_colors ()) - { - colorize = 1; - background = COLOR_BLACK; - foreground = COLOR_WHITE; - start_color (); + if (has_colors()) { + colorize = 1; + background = COLOR_BLACK; + foreground = COLOR_WHITE; + start_color(); #ifdef NCURSES_VERSION - if (use_default_colors () != ERR) - { - background = -1; - foreground = -1; - } -#endif /* NCURSES_VERSION */ - - /* Color assignment */ - init_pair (COLR_RED, COLOR_RED, background); - init_pair (COLR_GREEN, COLOR_GREEN, background); - init_pair (COLR_YELLOW, COLOR_YELLOW, background); - init_pair (COLR_BLUE, COLOR_BLUE, background); - init_pair (COLR_MAGENTA, COLOR_MAGENTA, background); - init_pair (COLR_CYAN, COLOR_CYAN, background); - init_pair (COLR_DEFAULT, foreground, background); - init_pair (COLR_HIGH, COLOR_BLACK, COLOR_GREEN); - init_pair (COLR_CUSTOM, COLOR_RED, background); - - } - else - { - colorize = 0; - background = COLOR_BLACK; + if (use_default_colors() != ERR) { + background = -1; + foreground = -1; } +#endif /* NCURSES_VERSION */ - vars_init (&conf); - wins_init (); - wins_slctd_init (); - notify_init_bar (); - wins_reset_status_page (); + /* Color assignment */ + init_pair(COLR_RED, COLOR_RED, background); + init_pair(COLR_GREEN, COLOR_GREEN, background); + init_pair(COLR_YELLOW, COLOR_YELLOW, background); + init_pair(COLR_BLUE, COLOR_BLUE, background); + init_pair(COLR_MAGENTA, COLOR_MAGENTA, background); + init_pair(COLR_CYAN, COLOR_CYAN, background); + init_pair(COLR_DEFAULT, foreground, background); + init_pair(COLR_HIGH, COLOR_BLACK, COLOR_GREEN); + init_pair(COLR_CUSTOM, COLOR_RED, background); + } else { + colorize = 0; + background = COLOR_BLACK; + } + + vars_init(); + wins_init(); + wins_slctd_init(); + notify_init_bar(); + wins_reset_status_page(); /* * Read the data from files : first the user * configuration (the display is then updated), and then * the todo list, appointments and events. */ - custom_load_conf (&conf, background); - wins_erase_status_bar (); - io_load_keys (conf.pager); - io_load_todo (); - io_load_app (); - wins_reinit (); - if (notify_bar ()) - notify_start_main_thread (); - wins_update (); - io_startup_screen (conf.skip_system_dialogs, no_data_file); - inday = *day_process_storage (0, day_changed, &inday); - wins_slctd_set (CAL); - wins_update (); - calendar_start_date_thread (); + config_load(); + wins_erase_status_bar(); + io_load_keys(conf.pager); + io_load_todo(); + io_load_app(); + wins_reinit(); + if (conf.system_dialogs) { + wins_update(FLAG_ALL); + io_startup_screen(no_data_file); + } + inday = *day_process_storage(0, 0, &inday); + wins_slctd_set(CAL); + wins_update(FLAG_ALL); + + /* Start miscellaneous threads. */ + if (notify_bar()) + notify_start_main_thread(); + calendar_start_date_thread(); if (conf.periodic_save > 0) - io_start_psave_thread (&conf); + io_start_psave_thread(); /* User input */ - for (;;) - { - int key; - - do_update = 1; - key = keys_getch (win[STA].p); - switch (key) - { - case ERR: - do_update = 0; - break; - - case KEY_GENERIC_REDRAW: - resize = 1; - break; - - case KEY_GENERIC_CHANGE_VIEW: - wins_reset_status_page (); - /* Need to save the previously highlighted event. */ - switch (wins_slctd ()) - { - case TOD: - sav_hilt_tod = todo_hilt (); - todo_hilt_set (0); - break; - case APP: - sav_hilt_app = apoint_hilt (); - apoint_hilt_set (0); - break; - default: - break; - } - wins_slctd_next (); - - /* Select the event to highlight. */ - switch (wins_slctd ()) - { - case TOD: - if ((sav_hilt_tod == 0) && (todo_nb () != 0)) - todo_hilt_set (1); - else - todo_hilt_set (sav_hilt_tod); - break; - case APP: - if ((sav_hilt_app == 0) - && ((inday.nb_events + inday.nb_apoints) != 0)) - apoint_hilt_set (1); - else - apoint_hilt_set (sav_hilt_app); - break; - default: - break; - } - break; - - case KEY_GENERIC_OTHER_CMD: - wins_other_status_page (wins_slctd ()); - break; - - case KEY_GENERIC_GOTO: - case KEY_GENERIC_GOTO_TODAY: - wins_erase_status_bar (); - calendar_set_current_date (); - if (key == KEY_GENERIC_GOTO_TODAY) - calendar_goto_today (); - else - calendar_change_day (conf.input_datefmt); - do_storage = 1; - day_changed = 1; - break; - - case KEY_VIEW_ITEM: - if ((wins_slctd () == APP) && (apoint_hilt () != 0)) - day_popup_item (); - else if ((wins_slctd () == TOD) && (todo_hilt () != 0)) - item_in_popup (NULL, NULL, todo_saved_mesg (), _("To do :")); - break; - - case KEY_GENERIC_CONFIG_MENU: - wins_erase_status_bar (); - custom_config_bar (); - while ((key = wgetch (win[STA].p)) != 'q') - { - switch (key) - { - case 'C': - case 'c': - if (has_colors ()) - custom_color_config (); - else - { - colorize = 0; - wins_erase_status_bar (); - mvwprintw (win[STA].p, 0, 0, _(no_color_support)); - wgetch (win[STA].p); - } - break; - case 'L': - case 'l': - custom_layout_config (); - break; - case 'G': - case 'g': - custom_general_config (&conf); - break; - case 'N': - case 'n': - notify_config_bar (); - break; - case 'K': - case 'k': - custom_keys_config (); - break; - case 's': - case 'S': - custom_sidebar_config (); - break; - } - wins_reset (); - wins_update (); - do_storage = 1; - wins_erase_status_bar (); - custom_config_bar (); - } - wins_update (); - break; - - case KEY_GENERIC_ADD_APPT: - apoint_add (); - do_storage = 1; - break; - - case KEY_GENERIC_ADD_TODO: - todo_new_item (); - if (todo_hilt () == 0 && todo_nb () == 1) - todo_hilt_increase (); - break; - - case KEY_ADD_ITEM: - switch (wins_slctd ()) - { - case APP: - apoint_add (); - do_storage = 1; - break; - case TOD: - todo_new_item (); - if (todo_hilt () == 0 && todo_nb () == 1) - todo_hilt_increase (); - break; - default: - break; - } - break; - - case KEY_EDIT_ITEM: - if (wins_slctd () == APP && apoint_hilt () != 0) - day_edit_item (&conf); - else if (wins_slctd () == TOD && todo_hilt () != 0) - todo_edit_item (); - do_storage = 1; - break; - - case KEY_DEL_ITEM: - if (wins_slctd () == APP && apoint_hilt () != 0) - apoint_delete (&conf, &inday.nb_events, &inday.nb_apoints); - else if (wins_slctd () == TOD && todo_hilt () != 0) - todo_delete (&conf); - do_storage = 1; - break; - - case KEY_GENERIC_CUT: - if (wins_slctd () == APP && apoint_hilt () != 0) - { - cut_item = apoint_cut (&inday.nb_events, &inday.nb_apoints); - do_storage = 1; - } - break; - - case KEY_GENERIC_PASTE: - if (wins_slctd () == APP) - { - apoint_paste (&inday.nb_events, &inday.nb_apoints, cut_item); - cut_item = 0; - do_storage = 1; - } - break; + for (;;) { + int key; - case KEY_REPEAT_ITEM: - if (wins_slctd () == APP && apoint_hilt () != 0) - recur_repeat_item (&conf); - do_storage = 1; - break; - - case KEY_FLAG_ITEM: - if (wins_slctd () == APP && apoint_hilt () != 0) - apoint_switch_notify (); - else if (wins_slctd () == TOD && todo_hilt () != 0) - todo_flag (); - do_storage = 1; - break; - - case KEY_RAISE_PRIORITY: - case KEY_LOWER_PRIORITY: - if (wins_slctd () == TOD && todo_hilt () != 0) - { - todo_chg_priority (key); - if (todo_hilt_pos () < 0) - todo_set_first (todo_hilt ()); - else if (todo_hilt_pos () >= win[TOD].h - 4) - todo_set_first (todo_hilt () - win[TOD].h + 5); - } - break; - - case KEY_EDIT_NOTE: - if (wins_slctd () == APP && apoint_hilt () != 0) - day_edit_note (conf.editor); - else if (wins_slctd () == TOD && todo_hilt () != 0) - todo_edit_note (conf.editor); - do_storage = 1; - break; - - case KEY_VIEW_NOTE: - if (wins_slctd () == APP && apoint_hilt () != 0) - day_view_note (conf.pager); - else if (wins_slctd () == TOD && todo_hilt () != 0) - todo_view_note (conf.pager); - break; - - case KEY_GENERIC_HELP: - wins_status_bar (); - help_screen (); - break; - - case KEY_GENERIC_SAVE: - io_save_cal (&conf, IO_SAVE_DISPLAY_BAR); - break; - - case KEY_GENERIC_IMPORT: - wins_erase_status_bar (); - io_import_data (IO_IMPORT_ICAL, &conf, NULL); - do_storage = 1; - break; - - case KEY_GENERIC_EXPORT: - wins_erase_status_bar (); - io_export_bar (); - while ((key = wgetch (win[STA].p)) != 'q') - { - switch (key) - { - case 'I': - case 'i': - io_export_data (IO_EXPORT_ICAL, &conf); - break; - case 'P': - case 'p': - io_export_data (IO_EXPORT_PCAL, &conf); - break; - } - wins_reset (); - wins_update (); - do_storage = 1; - wins_erase_status_bar (); - io_export_bar (); - } - wins_update (); - break; - - case KEY_GENERIC_NEXT_DAY: - case KEY_MOVE_RIGHT: - if (wins_slctd () == CAL || key == KEY_GENERIC_NEXT_DAY) - { - do_storage = 1; - day_changed = 1; - calendar_move (RIGHT); - } - break; - - case KEY_GENERIC_PREV_DAY: - case KEY_MOVE_LEFT: - if (wins_slctd () == CAL || key == KEY_GENERIC_PREV_DAY) - { - do_storage = 1; - day_changed = 1; - calendar_move (LEFT); - } - break; - - case KEY_GENERIC_PREV_WEEK: - case KEY_MOVE_UP: - if (wins_slctd () == CAL || key == KEY_GENERIC_PREV_WEEK) - { - do_storage = 1; - day_changed = 1; - calendar_move (UP); - } - else if ((wins_slctd () == APP) && (apoint_hilt () > 1)) - { - apoint_hilt_decrease (); - apoint_scroll_pad_up (inday.nb_events); - } - else if ((wins_slctd () == TOD) && (todo_hilt () > 1)) - { - todo_hilt_decrease (); - if (todo_hilt_pos () < 0) - todo_first_decrease (); - } - break; - - case KEY_GENERIC_NEXT_WEEK: - case KEY_MOVE_DOWN: - if (wins_slctd () == CAL || key == KEY_GENERIC_NEXT_WEEK) - { - do_storage = 1; - day_changed = 1; - calendar_move (DOWN); - } - else if ((wins_slctd () == APP) && - (apoint_hilt () < inday.nb_events + inday.nb_apoints)) - { - apoint_hilt_increase (); - apoint_scroll_pad_down (inday.nb_events, win[APP].h); - } - else if ((wins_slctd () == TOD) && (todo_hilt () < todo_nb ())) - { - todo_hilt_increase (); - if (todo_hilt_pos () == win[TOD].h - 4) - todo_first_increase (); - } - break; - - case KEY_START_OF_WEEK: - if (wins_slctd () == CAL) - { - do_storage = 1; - day_changed = 1; - calendar_move (WEEK_START); - } - break; - - case KEY_END_OF_WEEK: - if (wins_slctd () == CAL) - { - do_storage = 1; - day_changed = 1; - calendar_move (WEEK_END); - } - break; - - case KEY_GENERIC_SCROLL_UP: - if (wins_slctd () == CAL) - calendar_view_prev (); - break; - - case KEY_GENERIC_SCROLL_DOWN: - if (wins_slctd () == CAL) - calendar_view_next (); - break; - - case KEY_GENERIC_QUIT: - if (conf.auto_save) - io_save_cal (&conf, IO_SAVE_DISPLAY_BAR); - - if (conf.confirm_quit) - { - status_mesg (_(quit_message), choices); - key = wgetch (win[STA].p); - if (key == 'y') - exit_calcurse (EXIT_SUCCESS); - else - { - wins_erase_status_bar (); - break; - } - } - else - exit_calcurse (EXIT_SUCCESS); - break; + if (resize) { + resize = 0; + wins_reset(); + } - default: - do_update = 0; + key = keys_getch(win[STA].p, &count); + switch (key) { + case KEY_GENERIC_REDRAW: + resize = 1; + break; + + case KEY_GENERIC_CHANGE_VIEW: + wins_reset_status_page(); + wins_slctd_next(); + + /* Select the event to highlight. */ + switch (wins_slctd()) { + case TOD: + if ((todo_hilt() == 0) && (todo_nb() > 0)) + todo_hilt_set(1); + break; + case APP: + if ((apoint_hilt() == 0) && ((inday.nb_events + inday.nb_apoints) > 0)) + apoint_hilt_set(1); + break; + default: + break; + } + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_OTHER_CMD: + wins_other_status_page(wins_slctd()); + wins_update(FLAG_STA); + break; + + case KEY_GENERIC_GOTO: + case KEY_GENERIC_GOTO_TODAY: + wins_erase_status_bar(); + calendar_set_current_date(); + if (key == KEY_GENERIC_GOTO_TODAY) + calendar_goto_today(); + else + calendar_change_day(conf.input_datefmt); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP | FLAG_STA); + break; + + case KEY_VIEW_ITEM: + if ((wins_slctd() == APP) && (apoint_hilt() != 0)) + day_popup_item(); + else if ((wins_slctd() == TOD) && (todo_hilt() != 0)) + item_in_popup(NULL, NULL, todo_saved_mesg(), _("To do :")); + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_CONFIG_MENU: + wins_erase_status_bar(); + custom_config_main(); + inday = do_storage(0); + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_ADD_APPT: + apoint_add(); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP | FLAG_STA); + break; + + case KEY_GENERIC_ADD_TODO: + todo_new_item(); + if (todo_hilt() == 0 && todo_nb() == 1) + todo_hilt_increase(1); + wins_update(FLAG_TOD | FLAG_STA); + break; + + case KEY_ADD_ITEM: + switch (wins_slctd()) { + case APP: + apoint_add(); + inday = do_storage(0); + wins_update(FLAG_CAL | FLAG_APP | FLAG_STA); + break; + case TOD: + todo_new_item(); + if (todo_hilt() == 0 && todo_nb() == 1) + todo_hilt_increase(1); + wins_update(FLAG_TOD | FLAG_STA); + break; + default: + break; + } + break; + + case KEY_EDIT_ITEM: + if (wins_slctd() == APP && apoint_hilt() != 0) { + day_edit_item(); + inday = do_storage(0); + wins_update(FLAG_CAL | FLAG_APP | FLAG_STA); + } else if (wins_slctd() == TOD && todo_hilt() != 0) { + todo_edit_item(); + wins_update(FLAG_TOD | FLAG_STA); + } + break; + + case KEY_DEL_ITEM: + if (wins_slctd() == APP && apoint_hilt() != 0) { + apoint_delete(&inday.nb_events, &inday.nb_apoints); + inday = do_storage(0); + wins_update(FLAG_CAL | FLAG_APP | FLAG_STA); + } else if (wins_slctd() == TOD && todo_hilt() != 0) { + todo_delete(); + wins_update(FLAG_TOD | FLAG_STA); + } + break; + + case KEY_GENERIC_CUT: + if (wins_slctd() == APP && apoint_hilt() != 0) { + cut_item = apoint_cut(&inday.nb_events, &inday.nb_apoints); + inday = do_storage(0); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_GENERIC_PASTE: + if (wins_slctd() == APP) { + apoint_paste(&inday.nb_events, &inday.nb_apoints, cut_item); + cut_item = 0; + inday = do_storage(0); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_REPEAT_ITEM: + if (wins_slctd() == APP && apoint_hilt() != 0) + recur_repeat_item(); + inday = do_storage(0); + wins_update(FLAG_CAL | FLAG_APP | FLAG_STA); + break; + + case KEY_FLAG_ITEM: + if (wins_slctd() == APP && apoint_hilt() != 0) { + apoint_switch_notify(); + inday = do_storage(0); + wins_update(FLAG_APP); + } else if (wins_slctd() == TOD && todo_hilt() != 0) { + todo_flag(); + wins_update(FLAG_TOD); + } + break; + + case KEY_PIPE_ITEM: + if (wins_slctd() == APP && apoint_hilt() != 0) + day_pipe_item(); + else if (wins_slctd() == TOD && todo_hilt() != 0) + todo_pipe_item(); + wins_update(FLAG_ALL); + break; + + case KEY_RAISE_PRIORITY: + case KEY_LOWER_PRIORITY: + if (wins_slctd() == TOD && todo_hilt() != 0) { + todo_chg_priority(key); + if (todo_hilt_pos() < 0) + todo_set_first(todo_hilt()); + else if (todo_hilt_pos() >= win[TOD].h - 4) + todo_set_first(todo_hilt() - win[TOD].h + 5); + wins_update(FLAG_TOD); + } + break; + + case KEY_EDIT_NOTE: + if (wins_slctd() == APP && apoint_hilt() != 0) { + day_edit_note(conf.editor); + inday = do_storage(0); + } else if (wins_slctd() == TOD && todo_hilt() != 0) + todo_edit_note(conf.editor); + wins_update(FLAG_ALL); + break; + + case KEY_VIEW_NOTE: + if (wins_slctd() == APP && apoint_hilt() != 0) + day_view_note(conf.pager); + else if (wins_slctd() == TOD && todo_hilt() != 0) + todo_view_note(conf.pager); + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_HELP: + wins_status_bar(); + help_screen(); + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_SAVE: + io_save_cal(IO_SAVE_DISPLAY_BAR); + wins_update(FLAG_STA); + break; + + case KEY_GENERIC_IMPORT: + wins_erase_status_bar(); + io_import_data(IO_IMPORT_ICAL, NULL); + inday = do_storage(0); + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_EXPORT: + wins_erase_status_bar(); + io_export_bar(); + while ((key = wgetch(win[STA].p)) != 'q') { + switch (key) { + case 'I': + case 'i': + io_export_data(IO_EXPORT_ICAL); + break; + case 'P': + case 'p': + io_export_data(IO_EXPORT_PCAL); break; } - - if (do_storage) - { - inday = *day_process_storage (calendar_get_slctd_day (), - day_changed, &inday); - do_storage = !do_storage; - if (day_changed) - { - sav_hilt_app = 0; - day_changed = !day_changed; - if ((wins_slctd () == APP) && - (inday.nb_events + inday.nb_apoints != 0)) - apoint_hilt_set (1); - } + wins_reset(); + wins_update(FLAG_ALL); + wins_erase_status_bar(); + io_export_bar(); + } + inday = do_storage(0); + wins_update(FLAG_ALL); + break; + + case KEY_GENERIC_NEXT_DAY: + case KEY_MOVE_RIGHT: + if (wins_slctd() == CAL || key == KEY_GENERIC_NEXT_DAY) { + calendar_move(RIGHT, count); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_GENERIC_PREV_DAY: + case KEY_MOVE_LEFT: + if (wins_slctd() == CAL || key == KEY_GENERIC_PREV_DAY) { + calendar_move(LEFT, count); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_GENERIC_PREV_WEEK: + case KEY_MOVE_UP: + if (wins_slctd() == CAL || key == KEY_GENERIC_PREV_WEEK) { + calendar_move(UP, count); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP); + } else if (wins_slctd() == APP) { + if (count >= apoint_hilt()) + count = apoint_hilt() - 1; + apoint_hilt_decrease(count); + apoint_scroll_pad_up(inday.nb_events); + wins_update(FLAG_APP); + } else if (wins_slctd() == TOD) { + if (count >= todo_hilt()) + count = todo_hilt() - 1; + todo_hilt_decrease(count); + if (todo_hilt_pos() < 0) + todo_first_increase(todo_hilt_pos()); + wins_update(FLAG_TOD); + } + break; + + case KEY_GENERIC_NEXT_WEEK: + case KEY_MOVE_DOWN: + if (wins_slctd() == CAL || key == KEY_GENERIC_NEXT_WEEK) { + calendar_move(DOWN, count); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP); + } else if (wins_slctd() == APP) { + if (count > inday.nb_events + inday.nb_apoints - apoint_hilt()) + count = inday.nb_events + inday.nb_apoints - apoint_hilt(); + apoint_hilt_increase(count); + apoint_scroll_pad_down(inday.nb_events, win[APP].h); + wins_update(FLAG_APP); + } else if (wins_slctd() == TOD) { + if (count > todo_nb() - todo_hilt()) + count = todo_nb() - todo_hilt(); + todo_hilt_increase(count); + if (todo_hilt_pos() >= win[TOD].h - 4) + todo_first_increase(todo_hilt_pos() - win[TOD].h + 5); + wins_update(FLAG_TOD); + } + break; + + case KEY_START_OF_WEEK: + if (wins_slctd() == CAL) { + calendar_move(WEEK_START, count); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_END_OF_WEEK: + if (wins_slctd() == CAL) { + calendar_move(WEEK_END, count); + inday = do_storage(1); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_GENERIC_SCROLL_UP: + if (wins_slctd() == CAL) { + calendar_view_prev(); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_GENERIC_SCROLL_DOWN: + if (wins_slctd() == CAL) { + calendar_view_next(); + wins_update(FLAG_CAL | FLAG_APP); + } + break; + + case KEY_GENERIC_QUIT: + if (conf.auto_save) + io_save_cal(IO_SAVE_DISPLAY_BAR); + if (conf.auto_gc) + note_gc(); + + if (conf.confirm_quit) { + if (status_ask_bool(_("Do you really want to quit ?")) == 1) + exit_calcurse(EXIT_SUCCESS); + else { + wins_erase_status_bar(); + wins_update(FLAG_STA); + break; } + } else + exit_calcurse(EXIT_SUCCESS); + break; - if (resize) - { - resize = 0; - do_update = 0; - wins_reset (); - } + case KEY_RESIZE: + case ERR: + /* Do not reset the count parameter on resize or error. */ + continue; - if (do_update) - wins_update (); + default: + break; } + + count = 0; + } } diff --git a/src/calcurse.h b/src/calcurse.h index 091d16a..9efb4fd 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,13 +40,13 @@ #include "config.h" #ifdef HAVE_NCURSES_H -# include <ncurses.h> +#include <ncurses.h> #elif defined HAVE_NCURSES_NCURSES_H -# include <ncurses/ncurses.h> +#include <ncurses/ncurses.h> #elif defined HAVE_NCURSESW_NCURSES_H -# include <ncursesw/ncurses.h> +#include <ncursesw/ncurses.h> #else -# error "Missing ncurses header. Aborting..." +#error "Missing ncurses header. Aborting..." #endif #include <pthread.h> @@ -60,24 +60,24 @@ /* Internationalization. */ #if ENABLE_NLS -# include <locale.h> -# include <libintl.h> -# undef _ -# define _(String) gettext(String) -# ifdef gettext_noop -# define N_(String) gettext_noop(String) -# else -# define N_(String) (String) -# endif +#include <locale.h> +#include <libintl.h> +#undef _ +#define _(String) gettext(String) +#ifdef gettext_noop +#define N_(String) gettext_noop(String) +#else +#define N_(String) (String) +#endif #else /* NLS disabled */ -# define _(String) (String) -# define N_(String) (String) -# define textdomain(String) (String) -# define gettext(String) (String) -# define dgettext(String) (String) -# define dcgettext(String) (String) -# define bindtextdomain(String) (String) -# define bind_textdomain_codeset(Domain,Codeset) (Codeset) +#define _(String) (String) +#define N_(String) (String) +#define textdomain(String) (String) +#define gettext(String) (String) +#define dgettext(String) (String) +#define dcgettext(String) (String) +#define bindtextdomain(String) (String) +#define bind_textdomain_codeset(Domain,Codeset) (Codeset) #endif /* ENABLE_NLS */ /* Paths configuration. */ @@ -103,132 +103,148 @@ #define DEFAULT_EDITOR "vi" #define DEFAULT_PAGER "less" -#define ATTR_FALSE 0 -#define ATTR_TRUE 1 -#define ATTR_LOWEST 2 -#define ATTR_LOW 3 -#define ATTR_MIDDLE 4 -#define ATTR_HIGH 5 -#define ATTR_HIGHEST 6 +#define ATTR_FALSE 0 +#define ATTR_TRUE 1 +#define ATTR_LOWEST 2 +#define ATTR_LOW 3 +#define ATTR_MIDDLE 4 +#define ATTR_HIGH 5 +#define ATTR_HIGHEST 6 -#define STATUSHEIGHT 2 -#define NOTESIZ 6 +#define STATUSHEIGHT 2 +#define MAX_NOTESIZ 40 +#define TMPEXTSIZ 6 /* Format for appointment hours is: HH:MM */ #define HRMIN_SIZE 6 /* Maximum number of colors available. */ -#define NBUSERCOLORS 6 +#define NBUSERCOLORS 6 /* Side bar width acceptable boundaries. */ #define SBARMINWIDTH 32 #define SBARMAXWIDTHPERC 50 /* Related to date manipulation. */ -#define DAYINSEC 86400 -#define HOURINSEC 3600 -#define MININSEC 60 -#define YEARINDAYS 365 #define YEARINMONTHS 12 -#define WEEKINDAYS 7 +#define YEARINDAYS 365 #define TM_YEAR_BASE 1900 +#define WEEKINDAYS 7 +#define DAYINHOURS 24 +#define HOURINMIN 60 +#define MININSEC 60 + +#define WEEKINHOURS (WEEKINDAYS * DAYINHOURS) +#define WEEKINMIN (WEEKINHOURS * HOURINMIN) +#define WEEKINSEC (WEEKINMIN * MININSEC) +#define DAYINMIN (DAYINHOURS * HOURINMIN) +#define DAYINSEC (DAYINMIN * MININSEC) +#define HOURINSEC (HOURINMIN * MININSEC) + /* Calendar window. */ -#define CALHEIGHT 12 +#define CALHEIGHT 12 /* Key definitions. */ #define CTRLVAL 0x1F #define CTRL(x) ((x) & CTRLVAL) -#define ESCAPE 27 -#define TAB 9 +#define ESCAPE 27 +#define TAB 9 #define SPACE 32 -#define KEYS_KEYLEN 3 /* length of each keybinding */ -#define KEYS_LABELEN 8 /* length of command description */ -#define KEYS_CMDS_PER_LINE 6 /* max number of commands per line */ - -#define ERROR_MSG(...) do { \ - char msg[BUFSIZ]; \ - int len; \ - \ - len = snprintf (msg, BUFSIZ, "%s: %d: ", __FILE__, __LINE__); \ - (void)snprintf (msg + len, BUFSIZ - len, __VA_ARGS__); \ - if (ui_mode == UI_CURSES) \ - fatalbox (msg); \ - else \ - (void)fprintf (stderr, "%s\n", msg); \ +#define KEYS_KEYLEN 3 /* length of each keybinding */ +#define KEYS_LABELEN 8 /* length of command description */ +#define KEYS_CMDS_PER_LINE 6 /* max number of commands per line */ + +/* Size of the hash table the note garbage collector uses. */ +#define NOTE_GC_HSIZE 1024 + +#define ERROR_MSG(...) do { \ + char msg[BUFSIZ]; \ + int len; \ + \ + len = snprintf (msg, BUFSIZ, "%s: %d: ", __FILE__, __LINE__); \ + snprintf (msg + len, BUFSIZ - len, __VA_ARGS__); \ + if (ui_mode == UI_CURSES) \ + fatalbox (msg); \ + else \ + fprintf (stderr, "%s\n", msg); \ } while (0) -#define WARN_MSG(...) do { \ - char msg[BUFSIZ]; \ - \ - (void)snprintf (msg, BUFSIZ, __VA_ARGS__); \ - if (ui_mode == UI_CURSES) \ - warnbox (msg); \ - else \ - (void)fprintf (stderr, "%s\n", msg); \ +#define WARN_MSG(...) do { \ + char msg[BUFSIZ]; \ + \ + snprintf (msg, BUFSIZ, __VA_ARGS__); \ + if (ui_mode == UI_CURSES) \ + warnbox (msg); \ + else \ + fprintf (stderr, "%s\n", msg); \ } while (0) -#define EXIT(...) do { \ - ERROR_MSG(__VA_ARGS__); \ - if (ui_mode == UI_CURSES) \ - exit_calcurse (EXIT_FAILURE); \ - else \ - exit (EXIT_FAILURE); \ +#define EXIT(...) do { \ + ERROR_MSG(__VA_ARGS__); \ + if (ui_mode == UI_CURSES) \ + exit_calcurse (EXIT_FAILURE); \ + else \ + exit (EXIT_FAILURE); \ } while (0) -#define EXIT_IF(cond, ...) do { \ - if ((cond)) \ - EXIT(__VA_ARGS__); \ +#define EXIT_IF(cond, ...) do { \ + if ((cond)) \ + EXIT(__VA_ARGS__); \ } while (0) -#define RETURN_IF(cond, ...) do { \ - if ((cond)) \ - { \ - ERROR_MSG(__VA_ARGS__); \ - return; \ - } \ +#define RETURN_IF(cond, ...) do { \ + if ((cond)) \ + { \ + ERROR_MSG(__VA_ARGS__); \ + return; \ + } \ } while (0) -#define RETVAL_IF(cond, val, ...) do { \ - if ((cond)) \ - { \ - ERROR_MSG(__VA_ARGS__); \ - return (val); \ - } \ +#define RETVAL_IF(cond, val, ...) do { \ + if ((cond)) \ + { \ + ERROR_MSG(__VA_ARGS__); \ + return (val); \ + } \ } while (0) -#define STRING_BUILD(str) {str, sizeof (str) - 1} #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #define __FILE_POS__ __FILE__ ":" TOSTRING(__LINE__) +#define UTF8_MAXLEN 6 +#define UTF8_LENGTH(ch) ((unsigned char)ch >= 0xFC ? 6 : \ + ((unsigned char)ch >= 0xF8 ? 5 : \ + ((unsigned char)ch >= 0xF0 ? 4 : \ + ((unsigned char)ch >= 0xE0 ? 3 : \ + ((unsigned char)ch >= 0xC0 ? 2 : 1))))) +#define UTF8_ISCONT(ch) ((unsigned char)ch >= 0x80 && \ + (unsigned char)ch <= 0xBF) + #define MAX(x,y) ((x)>(y)?(x):(y)) #define MIN(x,y) ((x)<(y)?(x):(y)) /* General configuration variables. */ struct conf { - unsigned auto_save; - unsigned periodic_save; - unsigned confirm_quit; - unsigned confirm_delete; - unsigned skip_system_dialogs; - unsigned skip_progress_bar; - char *editor; - char *pager; - char output_datefmt[BUFSIZ]; /* format for displaying date */ - int input_datefmt; /* format for reading date */ + unsigned auto_save; + unsigned auto_gc; + unsigned periodic_save; + unsigned confirm_quit; + unsigned confirm_delete; + unsigned system_dialogs; + unsigned progress_bar; + const char *editor; + const char *pager; + char output_datefmt[BUFSIZ]; /* format for displaying date */ + int input_datefmt; /* format for reading date */ }; /* Daemon-related configuration. */ struct dmon_conf { - unsigned enable; /* launch daemon automatically when exiting */ - unsigned log; /* log daemon activity */ -}; - -struct string { - const char *str; - const int len; + unsigned enable; /* launch daemon automatically when exiting */ + unsigned log; /* log daemon activity */ }; enum datefmt { @@ -239,16 +255,13 @@ enum datefmt { DATE_FORMATS }; -#define DATEFMT(datefmt) (datefmt == DATEFMT_MMDDYYYY ? "%m/%d/%Y" : \ - (datefmt == DATEFMT_DDMMYYYY ? "%d/%m/%Y" : \ - (datefmt == DATEFMT_YYYYMMDD ? "%Y/%m/%d" : "%Y-%m-%d"))) +#define DATEFMT(datefmt) (datefmt == DATEFMT_MMDDYYYY ? "%m/%d/%Y" : \ + (datefmt == DATEFMT_DDMMYYYY ? "%d/%m/%Y" : \ + (datefmt == DATEFMT_YYYYMMDD ? "%Y/%m/%d" : "%Y-%m-%d"))) -#define DATEFMT_DESC(datefmt) (datefmt == DATEFMT_MMDDYYYY ? \ - _("mm/dd/yyyy") : \ - (datefmt == DATEFMT_DDMMYYYY ? \ - _("dd/mm/yyyy") : \ - (datefmt == DATEFMT_YYYYMMDD ? \ - _("yyyy/mm/dd") : _("yyyy-mm-dd")))) +#define DATEFMT_DESC(datefmt) (datefmt == DATEFMT_MMDDYYYY ? \ + _("mm/dd/yyyy") : (datefmt == DATEFMT_DDMMYYYY ? _("dd/mm/yyyy") : \ + (datefmt == DATEFMT_YYYYMMDD ? _("yyyy/mm/dd") : _("yyyy-mm-dd")))) struct date { unsigned dd; @@ -257,33 +270,32 @@ struct date { }; /* Appointment definition. */ -struct apoint -{ - long start; /* seconds since 1 jan 1970 */ - long dur; /* duration of the appointment in seconds */ +struct apoint { + long start; /* seconds since 1 jan 1970 */ + long dur; /* duration of the appointment in seconds */ #define APOINT_NULL 0x0 -#define APOINT_NOTIFY 0x1 /* Item needs to be notified */ -#define APOINT_NOTIFIED 0x2 /* Item was already notified */ - int state; +#define APOINT_NOTIFY 0x1 /* Item needs to be notified */ +#define APOINT_NOTIFIED 0x2 /* Item was already notified */ + int state; - char *mesg; - char *note; + char *mesg; + char *note; }; /* Event definition. */ struct event { - int id; /* event identifier */ - long day; /* seconds since 1 jan 1970 */ - char *mesg; - char *note; + int id; /* event identifier */ + long day; /* seconds since 1 jan 1970 */ + char *mesg; + char *note; }; /* Todo item definition. */ struct todo { - char *mesg; - int id; - char *note; + char *mesg; + int id; + char *note; }; /* Number of items in current day. */ @@ -294,18 +306,18 @@ struct day_items_nb { /* Generic item description (to hold appointments, events...). */ struct day_item { - long start; /* seconds since 1 jan 1970 */ - long appt_dur; /* appointment duration in seconds */ - int type; /* (recursive or normal) event or appointment */ - int evnt_id; /* event identifier */ - int appt_pos; /* real position in recurrent list */ - char state; /* appointment state */ - char *mesg; /* item description */ - char *note; /* note attached to item */ + long start; /* seconds since 1 jan 1970 */ + long appt_dur; /* appointment duration in seconds */ + int type; /* (recursive or normal) event or appointment */ + int evnt_id; /* event identifier */ + int appt_pos; /* real position in recurrent list */ + char state; /* appointment state */ + char *mesg; /* item description */ + char *note; /* note attached to item */ }; struct excp { - long st; /* beggining of the considered day, in seconds */ + long st; /* beggining of the considered day, in seconds */ }; enum recur_type { @@ -319,43 +331,43 @@ enum recur_type { /* To describe an item's repetition. */ struct rpt { - enum recur_type type; /* repetition type */ - int freq; /* repetition frequence */ - long until; /* ending date for repeated event */ + enum recur_type type; /* repetition type */ + int freq; /* repetition frequence */ + long until; /* ending date for repeated event */ }; /* Recurrent appointment definition. */ struct recur_apoint { - struct rpt *rpt; /* information about repetition */ - llist_t exc; /* days when the item should not be repeated */ - long start; /* beggining of the appointment */ - long dur; /* duration of the appointment */ - char state; /* 8 bits to store item state */ - char *mesg; /* appointment description */ - char *note; /* note attached to appointment */ + struct rpt *rpt; /* information about repetition */ + llist_t exc; /* days when the item should not be repeated */ + long start; /* beggining of the appointment */ + long dur; /* duration of the appointment */ + char state; /* 8 bits to store item state */ + char *mesg; /* appointment description */ + char *note; /* note attached to appointment */ }; /* Reccurent event definition. */ struct recur_event { - struct rpt *rpt; /* information about repetition */ - llist_t exc; /* days when the item should not be repeated */ - int id; /* event type */ - long day; /* day at which event occurs */ - char *mesg; /* event description */ - char *note; /* note attached to event */ + struct rpt *rpt; /* information about repetition */ + llist_t exc; /* days when the item should not be repeated */ + int id; /* event type */ + long day; /* day at which event occurs */ + char *mesg; /* event description */ + char *note; /* note attached to event */ }; struct notify_app { - long time; - int got_app; - char *txt; - char state; - pthread_mutex_t mutex; + long time; + int got_app; + char *txt; + char state; + pthread_mutex_t mutex; }; struct io_file { FILE *fd; - char name[BUFSIZ]; + char name[BUFSIZ]; }; /* Available keys. */ @@ -395,6 +407,7 @@ enum key { KEY_DEL_ITEM, KEY_EDIT_ITEM, KEY_VIEW_ITEM, + KEY_PIPE_ITEM, KEY_FLAG_ITEM, KEY_REPEAT_ITEM, KEY_EDIT_NOTE, @@ -408,8 +421,8 @@ enum key { /* To describe a key binding. */ struct binding { - char *label; - enum key action; + char *label; + enum key action; }; enum win { @@ -421,6 +434,13 @@ enum win { NBWINS }; +#define FLAG_CAL (1 << CAL) +#define FLAG_APP (1 << APP) +#define FLAG_TOD (1 << TOD) +#define FLAG_NOT (1 << NOT) +#define FLAG_STA (1 << STA) +#define FLAG_ALL ((1 << NBWINS) - 1) + enum ui_mode { UI_CURSES, UI_CMDLINE, @@ -429,40 +449,41 @@ enum ui_mode { /* Generic window structure. */ struct window { - WINDOW *p; /* pointer to window */ - unsigned w; /* width */ - unsigned h; /* height */ - int x; /* x position */ - int y; /* y position */ + WINDOW *p; /* pointer to window */ + unsigned w; /* width */ + unsigned h; /* height */ + int x; /* x position */ + int y; /* y position */ }; /* Generic scrolling window structure. */ struct scrollwin { - struct window win; - struct window pad; - unsigned first_visible_line; - unsigned total_lines; - char label[BUFSIZ]; + struct window win; + struct window pad; + unsigned first_visible_line; + unsigned total_lines; + const char *label; }; /* Pad structure to handle scrolling. */ struct pad { - int width; - int length; - int first_onscreen; /* first line to be displayed inside window */ - WINDOW *ptrwin; /* pointer to the pad window */ + int width; + int length; + int first_onscreen; /* first line to be displayed inside window */ + WINDOW *ptrwin; /* pointer to the pad window */ }; /* Notification bar definition. */ struct nbar { - int show; /* display or hide the notify-bar */ - int cntdwn; /* warn when time left before next app - becomes lesser than cntdwn */ - char datefmt[BUFSIZ]; /* format for displaying date */ - char timefmt[BUFSIZ]; /* format for displaying time */ - char cmd[BUFSIZ]; /* notification command */ - char *shell; /* user shell to launch notif. cmd */ - pthread_mutex_t mutex; + unsigned show; /* display or hide the notify-bar */ + int cntdwn; /* warn when time left before next app + becomes lesser than cntdwn */ + char datefmt[BUFSIZ]; /* format for displaying date */ + char timefmt[BUFSIZ]; /* format for displaying time */ + char cmd[BUFSIZ]; /* notification command */ + const char *shell; /* user shell to launch notif. cmd */ + unsigned notify_all; /* notify all appointments */ + pthread_mutex_t mutex; }; /* Available types of items. */ @@ -478,7 +499,6 @@ enum item_type { enum eraseflg { ERASE_DONT_FORCE, ERASE_FORCE, - ERASE_FORCE_KEEP_NOTE, ERASE_FORCE_ONLY_NOTE, ERASE_CUT }; @@ -486,8 +506,8 @@ enum eraseflg { /* Return codes for the getstring() function. */ enum getstr { GETSTRING_VALID, - GETSTRING_ESC, /* user pressed escape to cancel editing. */ - GETSTRING_RET /* return was pressed without entering any text. */ + GETSTRING_ESC, /* user pressed escape to cancel editing. */ + GETSTRING_RET /* return was pressed without entering any text. */ }; /* Week days. */ @@ -548,380 +568,429 @@ enum save_display { /* apoint.c */ extern llist_ts_t alist_p; -void apoint_free_bkp (enum eraseflg); -void apoint_llist_init (void); -void apoint_llist_free (void); -void apoint_hilt_set (int); -void apoint_hilt_decrease (void); -void apoint_hilt_increase (void); -int apoint_hilt (void); -struct apoint *apoint_new (char *, char *, long, long, char); -void apoint_add (void); -void apoint_delete (struct conf *, unsigned *, unsigned *); -int apoint_cut (unsigned *, unsigned *); -void apoint_paste (unsigned *, unsigned *, int); -unsigned apoint_inday (struct apoint *, long); -void apoint_sec2str (struct apoint *, int, long, char *, char *); -void apoint_write (struct apoint *, FILE *); -struct apoint *apoint_scan (FILE *, struct tm, struct tm, char, char *); -struct apoint *apoint_get (long, int); -void apoint_delete_bynum (long, unsigned, enum eraseflg); -void apoint_scroll_pad_down (int, int); -void apoint_scroll_pad_up (int); -struct notify_app *apoint_check_next (struct notify_app *, long); -struct apoint *apoint_recur_s2apoint_s (struct recur_apoint *); -void apoint_switch_notify (void); -void apoint_update_panel (int); -void apoint_paste_item (void); +void apoint_free_bkp(void); +void apoint_llist_init(void); +void apoint_llist_free(void); +void apoint_hilt_set(int); +void apoint_hilt_decrease(int); +void apoint_hilt_increase(int); +int apoint_hilt(void); +struct apoint *apoint_new(char *, char *, long, long, char); +void apoint_add(void); +void apoint_delete(unsigned *, unsigned *); +int apoint_cut(unsigned *, unsigned *); +void apoint_paste(unsigned *, unsigned *, int); +unsigned apoint_inday(struct apoint *, long); +void apoint_sec2str(struct apoint *, long, char *, char *); +void apoint_write(struct apoint *, FILE *); +struct apoint *apoint_scan(FILE *, struct tm, struct tm, char, char *); +struct apoint *apoint_get(long, int); +void apoint_delete_bynum(long, unsigned, enum eraseflg); +void apoint_scroll_pad_down(int, int); +void apoint_scroll_pad_up(int); +struct notify_app *apoint_check_next(struct notify_app *, long); +void apoint_switch_notify(void); +void apoint_update_panel(int); +void apoint_paste_item(void); /* args.c */ -int parse_args (int, char **, struct conf *); +int parse_args(int, char **); /* calendar.c */ -void calendar_view_next (void); -void calendar_view_prev (void); -void calendar_set_view (int); -int calendar_get_view (void); -void calendar_start_date_thread (void); -void calendar_stop_date_thread (void); -void calendar_set_current_date (void); -void calendar_set_first_day_of_week (enum wday); -void calendar_change_first_day_of_week (void); -unsigned calendar_week_begins_on_monday (void); -void calendar_store_current_date (struct date *); -void calendar_init_slctd_day (void); -struct date *calendar_get_slctd_day (void); -long calendar_get_slctd_day_sec (void); -void calendar_update_panel (struct window *); -void calendar_goto_today (void); -void calendar_change_day (int); -void calendar_move (enum move); -long calendar_start_of_year (void); -long calendar_end_of_year (void); -char *calendar_get_pom (time_t); +void calendar_view_next(void); +void calendar_view_prev(void); +void calendar_set_view(int); +int calendar_get_view(void); +void calendar_start_date_thread(void); +void calendar_stop_date_thread(void); +void calendar_set_current_date(void); +void calendar_set_first_day_of_week(enum wday); +void calendar_change_first_day_of_week(void); +unsigned calendar_week_begins_on_monday(void); +void calendar_store_current_date(struct date *); +void calendar_init_slctd_day(void); +struct date *calendar_get_slctd_day(void); +long calendar_get_slctd_day_sec(void); +void calendar_update_panel(struct window *); +void calendar_goto_today(void); +void calendar_change_day(int); +void calendar_move(enum move, int); +long calendar_start_of_year(void); +long calendar_end_of_year(void); +const char *calendar_get_pom(time_t); + +/* config.c */ + +void config_load(void); +unsigned config_save(void); /* custom.c */ -void custom_init_attr (void); -void custom_apply_attr (WINDOW *, int); -void custom_remove_attr (WINDOW *, int); -void custom_load_conf (struct conf *, int); -void custom_config_bar (void); -void custom_layout_config (void); -void custom_sidebar_config (void); -void custom_color_config (void); -void custom_color_theme_name (char *); -void custom_confwin_init (struct window *, char *); -void custom_set_swsiz (struct scrollwin *); -void custom_general_config (struct conf *); -void custom_keys_config (void); +void custom_init_attr(void); +void custom_apply_attr(WINDOW *, int); +void custom_remove_attr(WINDOW *, int); +void custom_config_bar(void); +void custom_layout_config(void); +void custom_sidebar_config(void); +void custom_color_config(void); +void custom_color_theme_name(char *); +void custom_confwin_init(struct window *, const char *); +void custom_set_swsiz(struct scrollwin *); +void custom_general_config(void); +void custom_keys_config(void); +void custom_config_main(void); /* day.c */ -void day_free_list (void); -struct day_items_nb *day_process_storage (struct date *, unsigned, - struct day_items_nb *); -void day_write_pad (long, int, int, int); -void day_popup_item (void); -int day_check_if_item (struct date); -unsigned day_chk_busy_slices (struct date, int, int *); -void day_edit_item (struct conf *); -int day_erase_item (long, int, enum eraseflg); -int day_cut_item (long, int); -int day_paste_item (long, int); -struct day_item *day_get_item (int); -int day_item_nb (long, int, int); -void day_edit_note (char *); -void day_view_note (char *); +void day_free_list(void); +struct day_items_nb *day_process_storage(struct date *, unsigned, + struct day_items_nb *); +void day_write_pad(long, int, int, int); +void day_popup_item(void); +int day_check_if_item(struct date); +unsigned day_chk_busy_slices(struct date, int, int *); +void day_edit_item(void); +int day_erase_item(long, int, enum eraseflg); +int day_cut_item(long, int); +int day_paste_item(long, int); +struct day_item *day_get_item(int); +int day_item_nb(long, int, int); +void day_edit_note(const char *); +void day_view_note(const char *); +void day_pipe_item(void); /* dmon.c */ -void dmon_start (int); -void dmon_stop (void); +void dmon_start(int); +void dmon_stop(void); /* event.c */ extern llist_t eventlist; -void event_free_bkp (enum eraseflg); -void event_llist_init (void); -void event_llist_free (void); -struct event *event_new (char *, char *, long, int); -unsigned event_inday (struct event *, long); -void event_write (struct event *, FILE *); -struct event *event_scan (FILE *, struct tm, int, char *); -struct event *event_get (long, int); -void event_delete_bynum (long, unsigned, enum eraseflg); -void event_paste_item (void); +void event_free_bkp(void); +void event_llist_init(void); +void event_llist_free(void); +struct event *event_new(char *, char *, long, int); +unsigned event_inday(struct event *, long); +void event_write(struct event *, FILE *); +struct event *event_scan(FILE *, struct tm, int, char *); +struct event *event_get(long, int); +void event_delete_bynum(long, unsigned, enum eraseflg); +void event_paste_item(void); /* help.c */ -void help_wins_init (struct scrollwin *, int, int, int, int); -void help_screen (void); +void help_wins_init(struct scrollwin *, int, int, int, int); +void help_screen(void); + +/* getstring.c */ +enum getstr getstring(WINDOW *, char *, int, int, int); +int updatestring(WINDOW *, char **, int, int); + +/* ical.c */ +void ical_import_data(FILE *, FILE *, unsigned *, unsigned *, unsigned *, + unsigned *, unsigned *); +void ical_export_data(FILE *); /* io.c */ -unsigned io_fprintln (const char *, const char *, ...); -void io_init (char *, char *); -void io_extract_data (char *, const char *, int); -unsigned io_save_conf (struct conf *); -unsigned io_save_apts (void); -unsigned io_save_todo (void); -unsigned io_save_keys (void); -void io_save_cal (struct conf *, enum save_display); -void io_load_app (void); -void io_load_todo (void); -void io_load_keys (char *); -void io_check_dir (char *, int *); -unsigned io_file_exist (char *); -void io_check_file (char *, int *); -int io_check_data_files (void); -void io_startup_screen (unsigned, int); -void io_export_data (enum export_type, struct conf *); -void io_export_bar (void); -void io_import_data (enum import_type, struct conf *, char *); -struct io_file *io_log_init (void); -void io_log_print (struct io_file *, int, char *); -void io_log_display (struct io_file *, char *, char *); -void io_log_free (struct io_file *); -void io_start_psave_thread (struct conf *); -void io_stop_psave_thread (void); -void io_set_lock (void); -unsigned io_dump_pid (char *); -unsigned io_get_pid (char *); -int io_file_is_empty (char *); +unsigned io_fprintln(const char *, const char *, ...); +void io_init(const char *, const char *); +void io_extract_data(char *, const char *, int); +unsigned io_save_apts(void); +unsigned io_save_todo(void); +unsigned io_save_keys(void); +void io_save_cal(enum save_display); +void io_load_app(void); +void io_load_todo(void); +void io_load_keys(const char *); +void io_check_dir(char *, int *); +unsigned io_file_exist(char *); +void io_check_file(char *, int *); +int io_check_data_files(void); +void io_startup_screen(int); +void io_export_data(enum export_type); +void io_export_bar(void); +void io_import_data(enum import_type, const char *); +struct io_file *io_log_init(void); +void io_log_print(struct io_file *, int, const char *); +void io_log_display(struct io_file *, const char *, const char *); +void io_log_free(struct io_file *); +void io_start_psave_thread(void); +void io_stop_psave_thread(void); +void io_set_lock(void); +unsigned io_dump_pid(char *); +unsigned io_get_pid(char *); +int io_file_is_empty(char *); +int io_file_cp(const char *, const char *); /* keys.c */ -void keys_init (void); -void keys_free (void); -void keys_dump_defaults (char *); -char *keys_get_label (enum key); -enum key keys_get_action (int); -enum key keys_getch (WINDOW *win); -int keys_assign_binding (int, enum key); -void keys_remove_binding (int, enum key); -int keys_str2int (char *); -char *keys_int2str (int); -int keys_action_count_keys (enum key); -char *keys_action_firstkey (enum key); -char *keys_action_nkey (enum key, int); -char *keys_action_allkeys (enum key); -void keys_display_bindings_bar (WINDOW *, struct binding **, int, int); -void keys_popup_info (enum key); -void keys_save_bindings (FILE *); -int keys_check_missing_bindings (void); -void keys_fill_missing (void); +void keys_init(void); +void keys_free(void); +void keys_dump_defaults(char *); +const char *keys_get_label(enum key); +enum key keys_get_action(int); +enum key keys_getch(WINDOW * win, int *); +int keys_assign_binding(int, enum key); +void keys_remove_binding(int, enum key); +int keys_str2int(const char *); +const char *keys_int2str(int); +int keys_action_count_keys(enum key); +const char *keys_action_firstkey(enum key); +const char *keys_action_nkey(enum key, int); +char *keys_action_allkeys(enum key); +void keys_display_bindings_bar(WINDOW *, struct binding *[], int, int, + int, struct binding *); +void keys_popup_info(enum key); +void keys_save_bindings(FILE *); +int keys_check_missing_bindings(void); +void keys_fill_missing(void); /* mem.c */ -void *xmalloc (size_t); -void *xcalloc (size_t, size_t); -void *xrealloc (void *, size_t, size_t); -char *xstrdup (const char *); -void xfree (void *); +void *xmalloc(size_t); +void *xcalloc(size_t, size_t); +void *xrealloc(void *, size_t, size_t); +char *xstrdup(const char *); +void xfree(void *); #ifdef CALCURSE_MEMORY_DEBUG -# define mem_malloc(s) dbg_malloc ((s), __FILE_POS__) -# define mem_calloc(n, s) dbg_calloc ((n), (s), __FILE_POS__) -# define mem_realloc(p, n, s) dbg_realloc ((p), (n), (s), __FILE_POS__) -# define mem_strdup(s) dbg_strdup ((s), __FILE_POS__) -# define mem_free(p) dbg_free ((p), __FILE_POS__) +#define mem_malloc(s) dbg_malloc ((s), __FILE_POS__) +#define mem_calloc(n, s) dbg_calloc ((n), (s), __FILE_POS__) +#define mem_realloc(p, n, s) dbg_realloc ((p), (n), (s), __FILE_POS__) +#define mem_strdup(s) dbg_strdup ((s), __FILE_POS__) +#define mem_free(p) dbg_free ((p), __FILE_POS__) -void *dbg_malloc (size_t, const char *); -void *dbg_calloc (size_t, size_t, const char *); -void *dbg_realloc (void *, size_t, size_t, const char *); -char *dbg_strdup (const char *, const char *); -void dbg_free (void *, const char *); -void mem_stats (void); +void *dbg_malloc(size_t, const char *); +void *dbg_calloc(size_t, size_t, const char *); +void *dbg_realloc(void *, size_t, size_t, const char *); +char *dbg_strdup(const char *, const char *); +void dbg_free(void *, const char *); +void mem_stats(void); #else /* MEMORY DEBUG disabled */ -# define mem_malloc(s) xmalloc ((s)) -# define mem_calloc(n, s) xcalloc ((n), (s)) -# define mem_realloc(p, n, s) xrealloc ((p), (n), (s)) -# define mem_strdup(s) xstrdup ((s)) -# define mem_free(p) xfree ((p)) -# define mem_stats() +#define mem_malloc(s) xmalloc ((s)) +#define mem_calloc(n, s) xcalloc ((n), (s)) +#define mem_realloc(p, n, s) xrealloc ((p), (n), (s)) +#define mem_strdup(s) xstrdup ((s)) +#define mem_free(p) xfree ((p)) +#define mem_stats() #endif /* CALCURSE_MEMORY_DEBUG */ +/* note.c */ +char *generate_note(const char *); +void edit_note(char **, const char *); +void view_note(const char *, const char *); +void erase_note(char **); +void note_read(char *, FILE *); +void note_gc(void); + /* notify.c */ -int notify_time_left (void); -unsigned notify_needs_reminder (void); -void notify_update_app (long, char, char *); -int notify_bar (void); -void notify_init_vars (void); -void notify_init_bar (void); -void notify_free_app (void); -void notify_start_main_thread (void); -void notify_stop_main_thread (void); -void notify_reinit_bar (void); -unsigned notify_launch_cmd (void); -void notify_update_bar (void); -unsigned notify_get_next (struct notify_app *); -unsigned notify_get_next_bkgd (void); -char *notify_app_txt (void); -void notify_check_next_app (int); -void notify_check_added (char *, long, char); -void notify_check_repeated (struct recur_apoint *); -int notify_same_item (long); -int notify_same_recur_item (struct recur_apoint *); -void notify_config_bar (void); +int notify_time_left(void); +unsigned notify_needs_reminder(void); +void notify_update_app(long, char, char *); +int notify_bar(void); +void notify_init_vars(void); +void notify_init_bar(void); +void notify_free_app(void); +void notify_start_main_thread(void); +void notify_stop_main_thread(void); +void notify_reinit_bar(void); +unsigned notify_launch_cmd(void); +void notify_update_bar(void); +unsigned notify_get_next(struct notify_app *); +unsigned notify_get_next_bkgd(void); +char *notify_app_txt(void); +void notify_check_next_app(int); +void notify_check_added(char *, long, char); +void notify_check_repeated(struct recur_apoint *); +int notify_same_item(long); +int notify_same_recur_item(struct recur_apoint *); +void notify_config_bar(void); + +/* pcal.c */ +void pcal_export_data(FILE *); /* recur.c */ extern llist_ts_t recur_alist_p; extern llist_t recur_elist; -void recur_event_free_bkp (enum eraseflg); -void recur_apoint_free_bkp (enum eraseflg); -void recur_apoint_llist_init (void); -void recur_apoint_llist_free (void); -void recur_event_llist_free (void); -struct recur_apoint *recur_apoint_new (char *, char *, long, long, char, - int, int, long, llist_t *); -struct recur_event *recur_event_new (char *, char *, long, int, int, int, - long, llist_t *); -char recur_def2char (enum recur_type); -int recur_char2def (char); -struct recur_apoint *recur_apoint_scan (FILE *, struct tm, struct tm, - char, int, struct tm, char *, - llist_t *, char); -struct recur_event *recur_event_scan (FILE *, struct tm, int, char, - int, struct tm, char *, - llist_t *); -void recur_save_data (FILE *); -unsigned recur_item_inday (long, llist_t *, int, int, long, long); -unsigned recur_apoint_inday(struct recur_apoint *, long); -unsigned recur_event_inday(struct recur_event *, long); -void recur_event_erase (long, unsigned, unsigned, - enum eraseflg); -void recur_apoint_erase (long, unsigned, unsigned, - enum eraseflg); -void recur_repeat_item (struct conf *); -void recur_exc_scan (llist_t *, FILE *); -struct notify_app *recur_apoint_check_next (struct notify_app *, long, long); -struct recur_apoint *recur_get_apoint (long, int); -struct recur_event *recur_get_event (long, int); -void recur_apoint_switch_notify (long, int); -void recur_event_paste_item (void); -void recur_apoint_paste_item (void); +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); +struct recur_apoint *recur_apoint_new(char *, char *, long, long, char, + int, int, long, llist_t *); +struct recur_event *recur_event_new(char *, char *, long, int, int, int, + long, llist_t *); +char recur_def2char(enum recur_type); +int recur_char2def(char); +struct recur_apoint *recur_apoint_scan(FILE *, struct tm, struct tm, + char, int, struct tm, char *, + llist_t *, char); +struct recur_event *recur_event_scan(FILE *, struct tm, int, char, + int, struct tm, char *, llist_t *); +void recur_apoint_write(struct recur_apoint *, FILE *); +void recur_event_write(struct recur_event *, FILE *); +void recur_save_data(FILE *); +unsigned recur_item_find_occurrence(long, long, llist_t *, int, + int, long, long, unsigned *); +unsigned recur_apoint_find_occurrence(struct recur_apoint *, long, unsigned *); +unsigned recur_event_find_occurrence(struct recur_event *, long, unsigned *); +unsigned recur_item_inday(long, long, llist_t *, int, int, long, long); +unsigned recur_apoint_inday(struct recur_apoint *, long); +unsigned recur_event_inday(struct recur_event *, long); +void recur_event_erase(long, unsigned, unsigned, enum eraseflg); +void recur_apoint_erase(long, unsigned, unsigned, enum eraseflg); +void recur_repeat_item(void); +void recur_exc_scan(llist_t *, FILE *); +struct notify_app *recur_apoint_check_next(struct notify_app *, long, long); +struct recur_apoint *recur_get_apoint(long, int); +struct recur_event *recur_get_event(long, int); +void recur_apoint_switch_notify(long, int); +void recur_event_paste_item(void); +void recur_apoint_paste_item(void); /* sigs.c */ -void sigs_init (void); -unsigned sigs_set_hdlr (int, void (*)(int)); +void sigs_init(void); +unsigned sigs_set_hdlr(int, void (*)(int)); /* todo.c */ extern llist_t todolist; -void todo_hilt_set (int); -void todo_hilt_decrease (void); -void todo_hilt_increase (void); -int todo_hilt (void); -int todo_nb (void); -void todo_set_nb (int); -void todo_set_first (int); -void todo_first_increase (void); -void todo_first_decrease (void); -int todo_hilt_pos (void); -char *todo_saved_mesg (void); -void todo_new_item (void); -struct todo *todo_add (char *, int, char *); -void todo_flag (void); -void todo_delete (struct conf *); -void todo_chg_priority (int); -void todo_edit_item (void); -void todo_update_panel (int); -void todo_edit_note (char *); -void todo_view_note (char *); -void todo_init_list (void); -void todo_free_list (void); +void todo_hilt_set(int); +void todo_hilt_decrease(int); +void todo_hilt_increase(int); +int todo_hilt(void); +int todo_nb(void); +void todo_set_nb(int); +void todo_set_first(int); +void todo_first_increase(int); +void todo_first_decrease(int); +int todo_hilt_pos(void); +char *todo_saved_mesg(void); +void todo_new_item(void); +struct todo *todo_add(char *, int, char *); +void todo_write(struct todo *, FILE *); +void todo_flag(void); +void todo_delete(void); +void todo_chg_priority(int); +void todo_edit_item(void); +void todo_update_panel(int); +void todo_edit_note(const char *); +void todo_view_note(const char *); +void todo_pipe_item(void); +void todo_init_list(void); +void todo_free_list(void); + +/* utf8.c */ +int utf8_width(char *); +int utf8_strwidth(char *); /* utils.c */ -void exit_calcurse (int) __attribute__((__noreturn__)); -void free_user_data (void); -void fatalbox (const char *); -void warnbox (const char *); -void status_mesg (char *, char *); -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 *); -enum getstr getstring (WINDOW *, char *, int, int, int); -int updatestring (WINDOW *, char **, int, int); -int is_all_digit (char *); -long get_item_time (long); -int get_item_hour (long); -int get_item_min (long); -long date2sec (struct date, unsigned, unsigned); -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 (struct date); -long min2sec (unsigned); -int check_time (char *); -void draw_scrollbar (WINDOW *, int, int, int, int, int, unsigned); -void item_in_popup (char *, char *, char *, char *); -long get_today (void); -long now (void); -char *nowstr (void); -long mystrtol (const char *); -void print_bool_option_incolor (WINDOW *, unsigned, int, int); -const char *get_tempdir (void); -char *new_tempfile (const char *, int); -void erase_note (char **, enum eraseflg); -int parse_date (char *, enum datefmt, int *, int *, int *, - struct date *); -void str_toupper (char *); -void file_close (FILE *, const char *); -void psleep (unsigned); +void exit_calcurse(int) __attribute__ ((__noreturn__)); +void free_user_data(void); +void fatalbox(const char *); +void warnbox(const char *); +void status_mesg(const char *, const char *); +int status_ask_choice(const char *, const char[], int); +int status_ask_bool(const char *); +int status_ask_simplechoice(const char *, const char *[], int); +void erase_window_part(WINDOW *, int, int, int, int); +WINDOW *popup(int, int, int, int, const char *, const char *, int); +void print_in_middle(WINDOW *, int, int, int, const char *); +int is_all_digit(const char *); +long get_item_time(long); +int get_item_hour(long); +int get_item_min(long); +long date2sec(struct date, unsigned, unsigned); +char *date_sec2date_str(long, const 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(struct date); +long min2sec(unsigned); +void draw_scrollbar(WINDOW *, int, int, int, int, int, unsigned); +void item_in_popup(const char *, const char *, const char *, const char *); +long get_today(void); +long now(void); +char *nowstr(void); +long mystrtol(const char *); +void print_bool_option_incolor(WINDOW *, unsigned, int, int); +const char *get_tempdir(void); +char *new_tempfile(const char *, int); +int parse_date(const char *, enum datefmt, int *, int *, int *, struct date *); +int parse_time(const char *, unsigned *, unsigned *); +int parse_duration(const char *, unsigned *); +void str_toupper(char *); +void file_close(FILE *, const char *); +void psleep(unsigned); +int fork_exec(int *, int *, const char *, const char *const *); +int shell_exec(int *, int *, const char *, const char *const *); +int child_wait(int *, int *, int); +void press_any_key(void); +void print_apoint(const char *, long, struct apoint *); +void print_event(const char *, long, struct event *); +void print_recur_apoint(const char *, long, unsigned, struct recur_apoint *); +void print_recur_event(const char *, long, struct recur_event *); +void print_todo(const char *, struct todo *); /* vars.c */ -extern int col, row; -extern int resize; -extern unsigned colorize; -extern enum ui_mode ui_mode; -extern int days[12]; -extern char *monthnames[12]; -extern char *daynames[8]; -extern char path_dir[BUFSIZ]; -extern char path_todo[BUFSIZ]; -extern char path_apts[BUFSIZ]; -extern char path_conf[BUFSIZ]; -extern char path_keys[BUFSIZ]; -extern char path_notes[BUFSIZ]; -extern char path_cpid[BUFSIZ]; -extern char path_dpid[BUFSIZ]; -extern char path_dmon_log[BUFSIZ]; -extern struct pad apad; -extern struct nbar nbar; -extern struct dmon_conf dmon; -void vars_init (struct conf *); +extern int col, row; +extern int resize; +extern unsigned colorize; +extern int foreground, background; +extern enum ui_mode ui_mode; +extern int read_only; +extern int days[12]; +extern const char *monthnames[12]; +extern const char *daynames[8]; +extern char path_dir[BUFSIZ]; +extern char path_todo[BUFSIZ]; +extern char path_apts[BUFSIZ]; +extern char path_conf[BUFSIZ]; +extern char path_keys[BUFSIZ]; +extern char path_notes[BUFSIZ]; +extern char path_cpid[BUFSIZ]; +extern char path_dpid[BUFSIZ]; +extern char path_dmon_log[BUFSIZ]; +extern struct conf conf; +extern struct pad apad; +extern struct nbar nbar; +extern struct dmon_conf dmon; +void vars_init(void); /* wins.c */ extern struct window win[NBWINS]; -int wins_refresh (void); -int wins_wrefresh (WINDOW *); -int wins_doupdate (void); -int wins_layout (void); -void wins_set_layout (int); -unsigned wins_sbar_width (void); -unsigned wins_sbar_wperc (void); -void wins_set_sbar_width (unsigned); -void wins_sbar_winc (void); -void wins_sbar_wdec (void); -void wins_slctd_init (void); -enum win wins_slctd (void); -void wins_slctd_set (enum win); -void wins_slctd_next (void); -void wins_init (void); -void wins_scrollwin_init (struct scrollwin *); -void wins_scrollwin_delete (struct scrollwin *); -void wins_scrollwin_display (struct scrollwin *); -void wins_scrollwin_up (struct scrollwin *, int); -void wins_scrollwin_down (struct scrollwin *, int); -void wins_reinit (void); -void wins_reinit_panels (void); -void wins_show (WINDOW *, char *); -void wins_get_config (void); -void wins_update_border (void); -void wins_update_panels (void); -void wins_update (void); -void wins_reset (void); -void wins_launch_external (const char *, const char *); -void wins_status_bar (void); -void wins_erase_status_bar (void); -void wins_other_status_page (int); -void wins_reset_status_page (void); +int wins_refresh(void); +int wins_wrefresh(WINDOW *); +int wins_doupdate(void); +int wins_layout(void); +void wins_set_layout(int); +unsigned wins_sbar_width(void); +unsigned wins_sbar_wperc(void); +void wins_set_sbar_width(unsigned); +void wins_sbar_winc(void); +void wins_sbar_wdec(void); +void wins_slctd_init(void); +enum win wins_slctd(void); +void wins_slctd_set(enum win); +void wins_slctd_next(void); +void wins_init(void); +void wins_scrollwin_init(struct scrollwin *); +void wins_scrollwin_delete(struct scrollwin *); +void wins_scrollwin_display(struct scrollwin *); +void wins_scrollwin_up(struct scrollwin *, int); +void wins_scrollwin_down(struct scrollwin *, int); +void wins_reinit(void); +void wins_reinit_panels(void); +void wins_show(WINDOW *, const char *); +void wins_get_config(void); +void wins_update_border(int); +void wins_update_panels(int); +void wins_update(int); +void wins_reset(void); +void wins_prepare_external(void); +void wins_unprepare_external(void); +void wins_launch_external(const char *, const char *); +void wins_status_bar(void); +void wins_erase_status_bar(void); +void wins_other_status_page(int); +void wins_reset_status_page(void); #endif /* CALCURSE_H */ diff --git a/src/calendar.c b/src/calendar.c index e303ab9..7328718 100644 --- a/src/calendar.c +++ b/src/calendar.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,12 +48,12 @@ #endif #define EPOCH 90 -#define EPSILONg 279.403303 /* solar ecliptic long at EPOCH */ -#define RHOg 282.768422 /* solar ecliptic long of perigee at EPOCH */ -#define ECCEN 0.016713 /* solar orbit eccentricity */ -#define lzero 318.351648 /* lunar mean long at EPOCH */ -#define Pzero 36.340410 /* lunar mean long of perigee at EPOCH */ -#define Nzero 318.510107 /* lunar mean long of node at EPOCH */ +#define EPSILONg 279.403303 /* solar ecliptic long at EPOCH */ +#define RHOg 282.768422 /* solar ecliptic long of perigee at EPOCH */ +#define ECCEN 0.016713 /* solar orbit eccentricity */ +#define lzero 318.351648 /* lunar mean long at EPOCH */ +#define Pzero 36.340410 /* lunar mean long of perigee at EPOCH */ +#define Nzero 318.510107 /* lunar mean long of node at EPOCH */ #define ISLEAP(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) @@ -77,208 +77,184 @@ static unsigned calendar_view, week_begins_on_monday; static pthread_mutex_t date_thread_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_t calendar_t_date; -static void draw_monthly_view (struct window *, struct date *, unsigned); -static void draw_weekly_view (struct window *, struct date *, unsigned); +static void draw_monthly_view(struct window *, struct date *, unsigned); +static void draw_weekly_view(struct window *, struct date *, unsigned); static void (*draw_calendar[CAL_VIEWS]) (struct window *, struct date *, - unsigned) = - {draw_monthly_view, draw_weekly_view}; + unsigned) = { +draw_monthly_view, draw_weekly_view}; /* Switch between calendar views (monthly view is selected by default). */ -void -calendar_view_next (void) +void calendar_view_next(void) { calendar_view++; if (calendar_view == CAL_VIEWS) calendar_view = 0; } -void -calendar_view_prev (void) +void calendar_view_prev(void) { if (calendar_view == 0) calendar_view = CAL_VIEWS; calendar_view--; } -void -calendar_set_view (int view) +void calendar_set_view(int view) { calendar_view = (view < 0 || view >= CAL_VIEWS) ? CAL_MONTH_VIEW : view; } -int -calendar_get_view (void) +int calendar_get_view(void) { return (int)calendar_view; } /* Thread needed to update current date in calendar. */ /* ARGSUSED0 */ -static void * -calendar_date_thread (void *arg) +static void *calendar_date_thread(void *arg) { time_t actual, tomorrow; - for (;;) - { - tomorrow = (time_t) (get_today () + DAYINSEC); + for (;;) { + tomorrow = (time_t) (get_today() + DAYINSEC); - while ((actual = time (NULL)) < tomorrow) - (void)sleep (tomorrow - actual); + while ((actual = time(NULL)) < tomorrow) + sleep(tomorrow - actual); - calendar_set_current_date (); - calendar_update_panel (&win[CAL]); - } + calendar_set_current_date(); + calendar_update_panel(&win[CAL]); + } - return (void *)0; + return NULL; } /* Launch the calendar date thread. */ -void -calendar_start_date_thread (void) +void calendar_start_date_thread(void) { - pthread_create (&calendar_t_date, NULL, calendar_date_thread, NULL); + pthread_create(&calendar_t_date, NULL, calendar_date_thread, NULL); } /* Stop the calendar date thread. */ -void -calendar_stop_date_thread (void) +void calendar_stop_date_thread(void) { - if (calendar_t_date) - { - pthread_cancel (calendar_t_date); - pthread_join (calendar_t_date, NULL); - } + if (calendar_t_date) { + pthread_cancel(calendar_t_date); + pthread_join(calendar_t_date, NULL); + } } /* Set static variable today to current date */ -void -calendar_set_current_date (void) +void calendar_set_current_date(void) { time_t timer; struct tm *tm; - timer = time (NULL); - tm = localtime (&timer); + timer = time(NULL); + tm = localtime(&timer); - pthread_mutex_lock (&date_thread_mutex); + pthread_mutex_lock(&date_thread_mutex); today.dd = tm->tm_mday; today.mm = tm->tm_mon + 1; today.yyyy = tm->tm_year + 1900; - pthread_mutex_unlock (&date_thread_mutex); + pthread_mutex_unlock(&date_thread_mutex); } /* Needed to display sunday or monday as the first day of week in calendar. */ -void -calendar_set_first_day_of_week (enum wday first_day) -{ - switch (first_day) - { - case SUNDAY: - week_begins_on_monday = 0; - break; - case MONDAY: - week_begins_on_monday = 1; - break; - default: - ERROR_MSG (_("ERROR setting first day of week")); - week_begins_on_monday = 0; - /* NOTREACHED */ - } +void calendar_set_first_day_of_week(enum wday first_day) +{ + switch (first_day) { + case SUNDAY: + week_begins_on_monday = 0; + break; + case MONDAY: + week_begins_on_monday = 1; + break; + default: + ERROR_MSG(_("ERROR setting first day of week")); + week_begins_on_monday = 0; + /* NOTREACHED */ + } } /* Swap first day of week in calendar. */ -void -calendar_change_first_day_of_week (void) +void calendar_change_first_day_of_week(void) { week_begins_on_monday = !week_begins_on_monday; } /* Return 1 if week begins on monday, 0 otherwise. */ -unsigned -calendar_week_begins_on_monday (void) +unsigned calendar_week_begins_on_monday(void) { - return (week_begins_on_monday); + return week_begins_on_monday; } /* Fill in the given variable with the current date. */ -void -calendar_store_current_date (struct date *date) +void calendar_store_current_date(struct date *date) { - pthread_mutex_lock (&date_thread_mutex); + pthread_mutex_lock(&date_thread_mutex); *date = today; - pthread_mutex_unlock (&date_thread_mutex); + pthread_mutex_unlock(&date_thread_mutex); } /* This is to start at the current date in calendar. */ -void -calendar_init_slctd_day (void) +void calendar_init_slctd_day(void) { - calendar_store_current_date (&slctd_day); + calendar_store_current_date(&slctd_day); } /* Return the selected day in calendar */ -struct date * -calendar_get_slctd_day (void) +struct date *calendar_get_slctd_day(void) { - return (&slctd_day); + return &slctd_day; } /* Returned value represents the selected day in calendar (in seconds) */ -long -calendar_get_slctd_day_sec (void) +long calendar_get_slctd_day_sec(void) { - return (date2sec (slctd_day, 0, 0)); + return date2sec(slctd_day, 0, 0); } -static int -calendar_get_wday (struct date *date) +static int calendar_get_wday(struct date *date) { struct tm t; - (void)memset (&t, 0, sizeof (struct tm)); + memset(&t, 0, sizeof(struct tm)); t.tm_mday = date->dd; t.tm_mon = date->mm - 1; t.tm_year = date->yyyy - 1900; - (void)mktime (&t); + mktime(&t); return t.tm_wday; } -static unsigned -months_to_days (unsigned month) +static unsigned months_to_days(unsigned month) { - return ((month * 3057 - 3007) / 100); + return (month * 3057 - 3007) / 100; } - -static long -years_to_days (unsigned year) +static long years_to_days(unsigned year) { - return (year * 365L + year / 4 - year / 100 + year / 400); + return year * 365L + year / 4 - year / 100 + year / 400; } -static long -ymd_to_scalar (unsigned year, unsigned month, unsigned day) +static long ymd_to_scalar(unsigned year, unsigned month, unsigned day) { long scalar; - scalar = day + months_to_days (month); + scalar = day + months_to_days(month); if (month > 2) - scalar -= ISLEAP (year) ? 1 : 2; + scalar -= ISLEAP(year) ? 1 : 2; year--; - scalar += years_to_days (year); + scalar += years_to_days(year); - return (scalar); + return scalar; } /* * Used to change date by adding a certain amount of days or weeks. * Returns 0 on success, 1 otherwise. */ -static int -date_change (struct tm *date, int delta_month, int delta_day) +static int date_change(struct tm *date, int delta_month, int delta_day) { struct tm t; @@ -286,19 +262,18 @@ date_change (struct tm *date, int delta_month, int delta_day) t.tm_mon += delta_month; t.tm_mday += delta_day; - if (mktime (&t) == -1) - return (1); - else - { - *date = t; - return (0); - } + if (mktime(&t) == -1) + return 1; + else { + *date = t; + return 0; + } } /* Draw the monthly view inside calendar panel. */ static void -draw_monthly_view (struct window *cwin, struct date *current_day, - unsigned sunday_first) +draw_monthly_view(struct window *cwin, struct date *current_day, + unsigned sunday_first) { const int OFFY = 2 + (CALHEIGHT - 9) / 2; struct date check_day; @@ -311,106 +286,92 @@ draw_monthly_view (struct window *cwin, struct date *current_day, yr = slctd_day.yyyy; /* offset for centering calendar in window */ - SBAR_WIDTH = wins_sbar_width (); + SBAR_WIDTH = wins_sbar_width(); OFFX = (SBAR_WIDTH - 27) / 2; ofs_y = OFFY; ofs_x = OFFX; /* checking the number of days in february */ numdays = days[mo - 1]; - if (2 == mo && ISLEAP (yr)) + if (2 == mo && ISLEAP(yr)) ++numdays; /* * the first calendar day will be monday or sunday, depending on * 'week_begins_on_monday' value */ - c_day_1 = (int) ((ymd_to_scalar (yr, mo, 1 + sunday_first) - (long) 1) % 7L); + c_day_1 = (int)((ymd_to_scalar(yr, mo, 1 + sunday_first) - (long)1) % 7L); /* Write the current month and year on top of the calendar */ - custom_apply_attr (cwin->p, ATTR_HIGHEST); - mvwprintw (cwin->p, ofs_y, - (SBAR_WIDTH - (strlen (_(monthnames[mo - 1])) + 5)) / 2, - "%s %d", _(monthnames[mo - 1]), slctd_day.yyyy); - custom_remove_attr (cwin->p, ATTR_HIGHEST); + custom_apply_attr(cwin->p, ATTR_HIGHEST); + mvwprintw(cwin->p, ofs_y, + (SBAR_WIDTH - (strlen(_(monthnames[mo - 1])) + 5)) / 2, + "%s %d", _(monthnames[mo - 1]), slctd_day.yyyy); + custom_remove_attr(cwin->p, ATTR_HIGHEST); ++ofs_y; /* print the days, with regards to the first day of the week */ - custom_apply_attr (cwin->p, ATTR_HIGHEST); - for (j = 0; j < WEEKINDAYS; j++) - { - mvwprintw (cwin->p, ofs_y, ofs_x + 4 * j, "%s", - _(daynames[1 + j - sunday_first])); - } - custom_remove_attr (cwin->p, ATTR_HIGHEST); + custom_apply_attr(cwin->p, ATTR_HIGHEST); + for (j = 0; j < WEEKINDAYS; j++) { + mvwprintw(cwin->p, ofs_y, ofs_x + 4 * j, "%s", + _(daynames[1 + j - sunday_first])); + } + custom_remove_attr(cwin->p, ATTR_HIGHEST); day_1_sav = (c_day_1 + 1) * 3 + c_day_1 - 7; - for (c_day = 1; c_day <= numdays; ++c_day, ++c_day_1, c_day_1 %= 7) - { - check_day.dd = c_day; - check_day.mm = slctd_day.mm; - check_day.yyyy = slctd_day.yyyy; - - /* check if the day contains an event or an appointment */ - item_this_day = day_check_if_item (check_day); + for (c_day = 1; c_day <= numdays; ++c_day, ++c_day_1, c_day_1 %= 7) { + check_day.dd = c_day; + check_day.mm = slctd_day.mm; + check_day.yyyy = slctd_day.yyyy; - /* Go to next line, the week is over. */ - if (!c_day_1 && 1 != c_day) - { - ofs_y++; - ofs_x = OFFX - day_1_sav - 4 * c_day; - } + /* check if the day contains an event or an appointment */ + item_this_day = day_check_if_item(check_day); - /* This is today, so print it in yellow. */ - if (c_day == current_day->dd - && current_day->mm == slctd_day.mm - && current_day->yyyy == slctd_day.yyyy - && current_day->dd != slctd_day.dd) - { - custom_apply_attr (cwin->p, ATTR_LOWEST); - mvwprintw (cwin->p, ofs_y + 1, - ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); - custom_remove_attr (cwin->p, ATTR_LOWEST); - } - else if (c_day == slctd_day.dd) - { - /* This is the selected day, print it according to user's theme. */ - custom_apply_attr (cwin->p, ATTR_HIGHEST); - mvwprintw (cwin->p, ofs_y + 1, - ofs_x + day_1_sav + 4 * c_day + 1, "%2d", - c_day); - custom_remove_attr (cwin->p, ATTR_HIGHEST); - } - else if (item_this_day) - { - custom_apply_attr (cwin->p, ATTR_LOW); - mvwprintw (cwin->p, ofs_y + 1, - ofs_x + day_1_sav + 4 * c_day + 1, "%2d", - c_day); - custom_remove_attr (cwin->p, ATTR_LOW); - } - else - /* otherwise, print normal days in black */ - mvwprintw (cwin->p, ofs_y + 1, - ofs_x + day_1_sav + 4 * c_day + 1, "%2d", - c_day); + /* Go to next line, the week is over. */ + if (!c_day_1 && 1 != c_day) { + ofs_y++; + ofs_x = OFFX - day_1_sav - 4 * c_day; } -} -static int -weeknum (const struct tm *t, int firstweekday) + /* This is today, so print it in yellow. */ + if (c_day == current_day->dd + && current_day->mm == slctd_day.mm + && current_day->yyyy == slctd_day.yyyy + && current_day->dd != slctd_day.dd) { + custom_apply_attr(cwin->p, ATTR_LOWEST); + mvwprintw(cwin->p, ofs_y + 1, + ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); + custom_remove_attr(cwin->p, ATTR_LOWEST); + } else if (c_day == slctd_day.dd) { + /* This is the selected day, print it according to user's theme. */ + custom_apply_attr(cwin->p, ATTR_HIGHEST); + mvwprintw(cwin->p, ofs_y + 1, + ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); + custom_remove_attr(cwin->p, ATTR_HIGHEST); + } else if (item_this_day) { + custom_apply_attr(cwin->p, ATTR_LOW); + mvwprintw(cwin->p, ofs_y + 1, + ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); + custom_remove_attr(cwin->p, ATTR_LOW); + } else + /* otherwise, print normal days in black */ + mvwprintw(cwin->p, ofs_y + 1, + ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day); + } +} + +static int weeknum(const struct tm *t, int firstweekday) { int wday, wnum; wday = t->tm_wday; - if (firstweekday == MONDAY) - { - if (wday == SUNDAY) - wday = 6; - else - wday--; - } + if (firstweekday == MONDAY) { + if (wday == SUNDAY) + wday = 6; + else + wday--; + } wnum = ((t->tm_yday + WEEKINDAYS - wday) / WEEKINDAYS); if (wnum < 0) wnum = 0; @@ -421,64 +382,60 @@ weeknum (const struct tm *t, int firstweekday) /* * Compute the week number according to ISO 8601. */ -static int -ISO8601weeknum (const struct tm *t) +static int ISO8601weeknum(const struct tm *t) { int wnum, jan1day; - wnum = weeknum (t, MONDAY); + wnum = weeknum(t, MONDAY); jan1day = t->tm_wday - (t->tm_yday % WEEKINDAYS); if (jan1day < 0) jan1day += WEEKINDAYS; - switch (jan1day) - { - case MONDAY: - break; - case TUESDAY: - case WEDNESDAY: - case THURSDAY: - wnum++; - break; - case FRIDAY: - case SATURDAY: - case SUNDAY: - if (wnum == 0) - { - /* Get week number of last week of last year. */ - struct tm dec31ly; /* 12/31 last year */ - - dec31ly = *t; - dec31ly.tm_year--; - dec31ly.tm_mon = 11; - dec31ly.tm_mday = 31; - dec31ly.tm_wday = (jan1day == SUNDAY) ? 6 : jan1day - 1; - dec31ly.tm_yday = 364 + ISLEAP (dec31ly.tm_year + 1900); - wnum = ISO8601weeknum (&dec31ly); - } - break; + switch (jan1day) { + case MONDAY: + break; + case TUESDAY: + case WEDNESDAY: + case THURSDAY: + wnum++; + break; + case FRIDAY: + case SATURDAY: + case SUNDAY: + if (wnum == 0) { + /* Get week number of last week of last year. */ + struct tm dec31ly; /* 12/31 last year */ + + dec31ly = *t; + dec31ly.tm_year--; + dec31ly.tm_mon = 11; + dec31ly.tm_mday = 31; + dec31ly.tm_wday = (jan1day == SUNDAY) ? 6 : jan1day - 1; + dec31ly.tm_yday = 364 + ISLEAP(dec31ly.tm_year + 1900); + wnum = ISO8601weeknum(&dec31ly); } + break; + } - if (t->tm_mon == 11) - { - int wday, mday; + if (t->tm_mon == 11) { + int wday, mday; - wday = t->tm_wday; - mday = t->tm_mday; - if ((wday == MONDAY && (mday >= 29 && mday <= 31)) - || (wday == TUESDAY && (mday == 30 || mday == 31)) - || (wday == WEDNESDAY && mday == 31)) - wnum = 1; - } + wday = t->tm_wday; + mday = t->tm_mday; + if ((wday == MONDAY && (mday >= 29 && mday <= 31)) + || (wday == TUESDAY && (mday == 30 || mday == 31)) + || (wday == WEDNESDAY && mday == 31)) + wnum = 1; + } return wnum; } /* Draw the weekly view inside calendar panel. */ static void -draw_weekly_view (struct window *cwin, struct date *current_day, - unsigned sunday_first) +draw_weekly_view(struct window *cwin, struct date *current_day, + unsigned sunday_first) { #define DAYSLICESNO 6 const int WCALWIDTH = 30; @@ -486,129 +443,123 @@ draw_weekly_view (struct window *cwin, struct date *current_day, struct tm t; int OFFX, j, c_wday, days_to_remove, weeknum; - OFFX = (wins_sbar_width () - WCALWIDTH) / 2 + 1; + OFFX = (wins_sbar_width() - WCALWIDTH) / 2 + 1; /* Fill in a tm structure with the first day of the selected week. */ - c_wday = calendar_get_wday (&slctd_day); + c_wday = calendar_get_wday(&slctd_day); if (sunday_first) days_to_remove = c_wday; else days_to_remove = c_wday == 0 ? WEEKINDAYS - 1 : c_wday - 1; - (void)memset (&t, 0, sizeof (struct tm)); + memset(&t, 0, sizeof(struct tm)); t.tm_mday = slctd_day.dd; t.tm_mon = slctd_day.mm - 1; t.tm_year = slctd_day.yyyy - 1900; - (void)mktime (&t); - (void)date_change (&t, 0, -days_to_remove); + mktime(&t); + date_change(&t, 0, -days_to_remove); /* Print the week number. */ - weeknum = ISO8601weeknum (&t); - custom_apply_attr (cwin->p, ATTR_HIGHEST); - mvwprintw (cwin->p, 2, cwin->w - 9, "(# %02d)", weeknum); - custom_remove_attr (cwin->p, ATTR_HIGHEST); + weeknum = ISO8601weeknum(&t); + custom_apply_attr(cwin->p, ATTR_HIGHEST); + mvwprintw(cwin->p, 2, cwin->w - 9, "(# %02d)", weeknum); + custom_remove_attr(cwin->p, ATTR_HIGHEST); /* Now draw calendar view. */ - for (j = 0; j < WEEKINDAYS; j++) - { - struct date date; - unsigned attr, item_this_day; - int i, slices[DAYSLICESNO]; - - /* print the day names, with regards to the first day of the week */ - custom_apply_attr (cwin->p, ATTR_HIGHEST); - mvwprintw (cwin->p, OFFY, OFFX + 4 * j, "%s", - _(daynames[1 + j - sunday_first])); - custom_remove_attr (cwin->p, ATTR_HIGHEST); - - /* Check if the day to be printed has an item or not. */ - date.dd = t.tm_mday; - date.mm = t.tm_mon + 1; - date.yyyy = t.tm_year + 1900; - item_this_day = day_check_if_item (date); - - /* Print the day numbers with appropriate decoration. */ - if (t.tm_mday == current_day->dd - && current_day->mm == slctd_day.mm - && current_day->yyyy == slctd_day.yyyy - && current_day->dd != slctd_day.dd) - attr = ATTR_LOWEST; /* today, but not selected */ - else if (t.tm_mday == slctd_day.dd) - attr = ATTR_HIGHEST; /* selected day */ - else if (item_this_day) - attr = ATTR_LOW; - else - attr = 0; - - if (attr) - custom_apply_attr (cwin->p, attr); - mvwprintw (cwin->p, OFFY + 1, OFFX + 1 + 4 * j, "%02d", t.tm_mday); - if (attr) - custom_remove_attr (cwin->p, attr); - - /* Draw slices indicating appointment times. */ - bzero (slices, DAYSLICESNO * sizeof *slices); - if (day_chk_busy_slices (date, DAYSLICESNO, slices)) - { - for (i = 0; i < DAYSLICESNO; i++) - { - if (j != WEEKINDAYS - 1 && i != DAYSLICESNO - 1) - mvwhline (cwin->p, OFFY + 2 + i, OFFX + 3 + 4 * j, ACS_S9, 2); - if (slices[i]) - { - int highlight; - - highlight = (t.tm_mday == slctd_day.dd) ? 1 : 0; - if (highlight) - custom_apply_attr (cwin->p, attr); - wattron (cwin->p, A_REVERSE); - mvwprintw (cwin->p, OFFY + 2 + i, OFFX + 1 + 4 * j, " "); - mvwprintw (cwin->p, OFFY + 2 + i, OFFX + 2 + 4 * j, " "); - wattroff (cwin->p, A_REVERSE); - if (highlight) - custom_remove_attr (cwin->p, attr); - } - } + for (j = 0; j < WEEKINDAYS; j++) { + struct date date; + unsigned attr, item_this_day; + int i, slices[DAYSLICESNO]; + + /* print the day names, with regards to the first day of the week */ + custom_apply_attr(cwin->p, ATTR_HIGHEST); + mvwprintw(cwin->p, OFFY, OFFX + 4 * j, "%s", + _(daynames[1 + j - sunday_first])); + custom_remove_attr(cwin->p, ATTR_HIGHEST); + + /* Check if the day to be printed has an item or not. */ + date.dd = t.tm_mday; + date.mm = t.tm_mon + 1; + date.yyyy = t.tm_year + 1900; + item_this_day = day_check_if_item(date); + + /* Print the day numbers with appropriate decoration. */ + if (t.tm_mday == current_day->dd + && current_day->mm == slctd_day.mm + && current_day->yyyy == slctd_day.yyyy + && current_day->dd != slctd_day.dd) + attr = ATTR_LOWEST; /* today, but not selected */ + else if (t.tm_mday == slctd_day.dd) + attr = ATTR_HIGHEST; /* selected day */ + else if (item_this_day) + attr = ATTR_LOW; + else + attr = 0; + + if (attr) + custom_apply_attr(cwin->p, attr); + mvwprintw(cwin->p, OFFY + 1, OFFX + 1 + 4 * j, "%02d", t.tm_mday); + if (attr) + custom_remove_attr(cwin->p, attr); + + /* Draw slices indicating appointment times. */ + memset(slices, 0, DAYSLICESNO * sizeof *slices); + if (day_chk_busy_slices(date, DAYSLICESNO, slices)) { + for (i = 0; i < DAYSLICESNO; i++) { + if (j != WEEKINDAYS - 1 && i != DAYSLICESNO - 1) + mvwhline(cwin->p, OFFY + 2 + i, OFFX + 3 + 4 * j, ACS_S9, 2); + if (slices[i]) { + int highlight; + + highlight = (t.tm_mday == slctd_day.dd) ? 1 : 0; + if (highlight) + custom_apply_attr(cwin->p, attr); + wattron(cwin->p, A_REVERSE); + mvwprintw(cwin->p, OFFY + 2 + i, OFFX + 1 + 4 * j, " "); + mvwprintw(cwin->p, OFFY + 2 + i, OFFX + 2 + 4 * j, " "); + wattroff(cwin->p, A_REVERSE); + if (highlight) + custom_remove_attr(cwin->p, attr); } - - /* get next day */ - (void)date_change (&t, 0, 1); + } } + /* get next day */ + date_change(&t, 0, 1); + } + /* Draw marks to indicate midday on the sides of the calendar. */ - custom_apply_attr (cwin->p, ATTR_HIGHEST); - mvwhline (cwin->p, OFFY + 1 + DAYSLICESNO / 2, OFFX, ACS_S9, 1); - mvwhline (cwin->p, OFFY + 1 + DAYSLICESNO / 2, - OFFX + WCALWIDTH - 3, ACS_S9, 1); - custom_remove_attr (cwin->p, ATTR_HIGHEST); + custom_apply_attr(cwin->p, ATTR_HIGHEST); + mvwhline(cwin->p, OFFY + 1 + DAYSLICESNO / 2, OFFX, ACS_S9, 1); + mvwhline(cwin->p, OFFY + 1 + DAYSLICESNO / 2, + OFFX + WCALWIDTH - 3, ACS_S9, 1); + custom_remove_attr(cwin->p, ATTR_HIGHEST); #undef DAYSLICESNO } /* Function used to display the calendar panel. */ -void -calendar_update_panel (struct window *cwin) +void calendar_update_panel(struct window *cwin) { struct date current_day; unsigned sunday_first; - calendar_store_current_date (¤t_day); - erase_window_part (cwin->p, 1, 3, cwin->w - 2, cwin->h - 2); - mvwhline (cwin->p, 2, 1, ACS_HLINE, cwin->w - 2); - sunday_first = calendar_week_begins_on_monday () ? 0 : 1; + calendar_store_current_date(¤t_day); + erase_window_part(cwin->p, 1, 3, cwin->w - 2, cwin->h - 2); + mvwhline(cwin->p, 2, 1, ACS_HLINE, cwin->w - 2); + sunday_first = calendar_week_begins_on_monday()? 0 : 1; draw_calendar[calendar_view] (cwin, ¤t_day, sunday_first); - wnoutrefresh (cwin->p); + wnoutrefresh(cwin->p); } /* Set the selected day in calendar to current day. */ -void -calendar_goto_today (void) +void calendar_goto_today(void) { struct date today; - calendar_store_current_date (&today); + calendar_store_current_date(&today); slctd_day.dd = today.dd; slctd_day.mm = today.mm; slctd_day.yyyy = today.yyyy; @@ -620,154 +571,143 @@ calendar_goto_today (void) * If the entered date is empty, automatically jump to the current date. * slctd_day is updated with the newly selected date. */ -void -calendar_change_day (int datefmt) +void calendar_change_day(int datefmt) { #define LDAY 11 char selected_day[LDAY] = ""; char outstr[BUFSIZ]; int dday, dmonth, dyear; int wrong_day = 1; - char *mesg_line1 = - _("The day you entered is not valid " - "(should be between 01/01/1902 and 12/31/2037)"); - char *mesg_line2 = _("Press [ENTER] to continue"); - char *request_date = "Enter the day to go to [ENTER for today] : %s"; - - while (wrong_day) - { - (void)snprintf (outstr, BUFSIZ, request_date, DATEFMT_DESC (datefmt)); - status_mesg (_(outstr), ""); - if (getstring (win[STA].p, selected_day, LDAY, 0, 1) == GETSTRING_ESC) - return; - else - { - if (strlen (selected_day) == 0) - { - wrong_day = 0; - calendar_goto_today (); - } - else if (parse_date (selected_day, datefmt, &dyear, &dmonth, &dday, - calendar_get_slctd_day ())) - { - wrong_day = 0; - /* go to chosen day */ - slctd_day.dd = dday; - slctd_day.mm = dmonth; - slctd_day.yyyy = dyear; - } - if (wrong_day) - { - status_mesg (mesg_line1, mesg_line2); - (void)wgetch (win[STA].p); - } - } + const char *mesg_line1 = + _("The day you entered is not valid " + "(should be between 01/01/1902 and 12/31/2037)"); + const char *mesg_line2 = _("Press [ENTER] to continue"); + const char *request_date = "Enter the day to go to [ENTER for today] : %s"; + + while (wrong_day) { + snprintf(outstr, BUFSIZ, request_date, DATEFMT_DESC(datefmt)); + status_mesg(_(outstr), ""); + if (getstring(win[STA].p, selected_day, LDAY, 0, 1) == GETSTRING_ESC) + return; + else { + if (strlen(selected_day) == 0) { + wrong_day = 0; + calendar_goto_today(); + } else if (parse_date(selected_day, datefmt, &dyear, &dmonth, &dday, + calendar_get_slctd_day())) { + wrong_day = 0; + /* go to chosen day */ + slctd_day.dd = dday; + slctd_day.mm = dmonth; + slctd_day.yyyy = dyear; + } + if (wrong_day) { + status_mesg(mesg_line1, mesg_line2); + wgetch(win[STA].p); + } } + } return; } -void -calendar_move (enum move move) +void calendar_move(enum move move, int count) { int ret, days_to_remove, days_to_add; struct tm t; - (void)memset (&t, 0, sizeof (struct tm)); + memset(&t, 0, sizeof(struct tm)); t.tm_mday = slctd_day.dd; t.tm_mon = slctd_day.mm - 1; t.tm_year = slctd_day.yyyy - 1900; - switch (move) - { - case UP: - if ((slctd_day.dd <= 7) && (slctd_day.mm == 1) - && (slctd_day.yyyy == 1902)) - return; - ret = date_change (&t, 0, -WEEKINDAYS); - break; - case DOWN: - if ((slctd_day.dd > days[slctd_day.mm - 1] - 7) - && (slctd_day.mm == 12) && (slctd_day.yyyy == 2037)) - return; - ret = date_change (&t, 0, WEEKINDAYS); - break; - case LEFT: - if ((slctd_day.dd == 1) && (slctd_day.mm == 1) - && (slctd_day.yyyy == 1902)) - return; - ret = date_change (&t, 0, -1); - break; - case RIGHT: - if ((slctd_day.dd == 31) && (slctd_day.mm == 12) - && (slctd_day.yyyy == 2037)) - return; - ret = date_change (&t, 0, 1); - break; - case WEEK_START: - /* Normalize struct tm to get week day number. */ - (void)mktime (&t); - if (calendar_week_begins_on_monday ()) - days_to_remove = ((t.tm_wday == 0) ? WEEKINDAYS - 1 : t.tm_wday - 1); - else - days_to_remove = ((t.tm_wday == 0) ? 0 : t.tm_wday); - ret = date_change (&t, 0, 0 - days_to_remove); - break; - case WEEK_END: - (void)mktime (&t); - if (calendar_week_begins_on_monday ()) - days_to_add = ((t.tm_wday == 0) ? 0 : WEEKINDAYS - t.tm_wday); - else - days_to_add = ((t.tm_wday == 0) ? - WEEKINDAYS - 1 : WEEKINDAYS - 1 - t.tm_wday); - ret = date_change (&t, 0, days_to_add); - break; - default: - ret = 1; - /* NOTREACHED */ - } - if (ret == 0) - { - slctd_day.dd = t.tm_mday; - slctd_day.mm = t.tm_mon + 1; - slctd_day.yyyy = t.tm_year + 1900; + switch (move) { + case UP: + ret = date_change(&t, 0, -count * WEEKINDAYS); + break; + case DOWN: + ret = date_change(&t, 0, count * WEEKINDAYS); + break; + case LEFT: + ret = date_change(&t, 0, -count); + break; + case RIGHT: + ret = date_change(&t, 0, count); + break; + case WEEK_START: + /* Normalize struct tm to get week day number. */ + mktime(&t); + if (calendar_week_begins_on_monday()) + days_to_remove = ((t.tm_wday == 0) ? WEEKINDAYS - 1 : t.tm_wday - 1); + else + days_to_remove = ((t.tm_wday == 0) ? 0 : t.tm_wday); + days_to_remove += (count - 1) * WEEKINDAYS; + ret = date_change(&t, 0, -days_to_remove); + break; + case WEEK_END: + mktime(&t); + if (calendar_week_begins_on_monday()) + days_to_add = ((t.tm_wday == 0) ? 0 : WEEKINDAYS - t.tm_wday); + else + days_to_add = ((t.tm_wday == 0) ? + WEEKINDAYS - 1 : WEEKINDAYS - 1 - t.tm_wday); + days_to_add += (count - 1) * WEEKINDAYS; + ret = date_change(&t, 0, days_to_add); + break; + default: + ret = 1; + /* NOTREACHED */ + } + + if (ret == 0) { + if (t.tm_year < 2) { + t.tm_mday = 1; + t.tm_mon = 0; + t.tm_year = 2; + } else if (t.tm_year > 137) { + t.tm_mday = 31; + t.tm_mon = 11; + t.tm_year = 137; } + + slctd_day.dd = t.tm_mday; + slctd_day.mm = t.tm_mon + 1; + slctd_day.yyyy = t.tm_year + 1900; + } } /* Returns the beginning of current year as a long. */ -long -calendar_start_of_year (void) +long calendar_start_of_year(void) { time_t timer; struct tm *tm; - timer = time (NULL); - tm = localtime (&timer); + timer = time(NULL); + tm = localtime(&timer); tm->tm_mon = 0; tm->tm_mday = 1; tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; - timer = mktime (tm); + timer = mktime(tm); return (long)timer; } -long -calendar_end_of_year (void) +long calendar_end_of_year(void) { time_t timer; struct tm *tm; - timer = time (NULL); - tm = localtime (&timer); + timer = time(NULL); + tm = localtime(&timer); tm->tm_mon = 0; tm->tm_mday = 1; tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; tm->tm_year++; - timer = mktime (tm); + timer = mktime(tm); return (long)(timer - 1); } @@ -813,18 +753,16 @@ calendar_end_of_year (void) * dtor -- * convert degrees to radians */ -static double -dtor (double deg) +static double dtor(double deg) { - return (deg * M_PI / 180); + return deg * M_PI / 180; } /* * adj360 -- * adjust value so 0 <= deg <= 360 */ -static void -adj360 (double *deg) +static void adj360(double *deg) { for (;;) if (*deg < 0.0) @@ -839,36 +777,35 @@ adj360 (double *deg) * potm -- * return phase of the moon */ -static double -potm (double days) +static double potm(double days) { double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime; double A4, lprime, V, ldprime, D, Nm; - N = 360.0 * days / 365.242191; /* sec 46 #3 */ - adj360 (&N); - Msol = N + EPSILONg - RHOg; /* sec 46 #4 */ - adj360 (&Msol); - Ec = 360 / M_PI * ECCEN * sin (dtor (Msol)); /* sec 46 #5 */ - LambdaSol = N + Ec + EPSILONg; /* sec 46 #6 */ - adj360 (&LambdaSol); - l = 13.1763966 * days + lzero; /* sec 65 #4 */ - adj360 (&l); - Mm = l - (0.1114041 * days) - Pzero; /* sec 65 #5 */ - adj360 (&Mm); - Nm = Nzero - (0.0529539 * days); /* sec 65 #6 */ - adj360 (&Nm); - Ev = 1.2739 * sin (dtor (2 * (l - LambdaSol) - Mm)); /* sec 65 #7 */ - Ac = 0.1858 * sin (dtor (Msol)); /* sec 65 #8 */ - A3 = 0.37 * sin (dtor (Msol)); - Mmprime = Mm + Ev - Ac - A3; /* sec 65 #9 */ - Ec = 6.2886 * sin (dtor (Mmprime)); /* sec 65 #10 */ - A4 = 0.214 * sin (dtor (2 * Mmprime)); /* sec 65 #11 */ - lprime = l + Ev + Ec - Ac + A4; /* sec 65 #12 */ - V = 0.6583 * sin (dtor (2 * (lprime - LambdaSol))); /* sec 65 #13 */ - ldprime = lprime + V; /* sec 65 #14 */ - D = ldprime - LambdaSol; /* sec 67 #2 */ - return (50.0 * (1 - cos (dtor (D)))); /* sec 67 #3 */ + N = 360.0 * days / 365.242191; /* sec 46 #3 */ + adj360(&N); + Msol = N + EPSILONg - RHOg; /* sec 46 #4 */ + adj360(&Msol); + Ec = 360 / M_PI * ECCEN * sin(dtor(Msol)); /* sec 46 #5 */ + LambdaSol = N + Ec + EPSILONg; /* sec 46 #6 */ + adj360(&LambdaSol); + l = 13.1763966 * days + lzero; /* sec 65 #4 */ + adj360(&l); + Mm = l - (0.1114041 * days) - Pzero; /* sec 65 #5 */ + adj360(&Mm); + Nm = Nzero - (0.0529539 * days); /* sec 65 #6 */ + adj360(&Nm); + Ev = 1.2739 * sin(dtor(2 * (l - LambdaSol) - Mm)); /* sec 65 #7 */ + Ac = 0.1858 * sin(dtor(Msol)); /* sec 65 #8 */ + A3 = 0.37 * sin(dtor(Msol)); + Mmprime = Mm + Ev - Ac - A3; /* sec 65 #9 */ + Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 65 #10 */ + A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 65 #11 */ + lprime = l + Ev + Ec - Ac + A4; /* sec 65 #12 */ + V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 65 #13 */ + ldprime = lprime + V; /* sec 65 #14 */ + D = ldprime - LambdaSol; /* sec 67 #2 */ + return 50.0 * (1 - cos(dtor(D))); /* sec 67 #3 */ } /* @@ -882,23 +819,22 @@ potm (double days) * Updated to the Third Edition of Duffett-Smith's book, IX 1998 * */ -static double -pom (time_t tmpt) +static double pom(time_t tmpt) { struct tm *GMT; double days; int cnt; - GMT = gmtime (&tmpt); + GMT = gmtime(&tmpt); days = (GMT->tm_yday + 1) + ((GMT->tm_hour + (GMT->tm_min / 60.0) + (GMT->tm_sec / 3600.0)) / 24.0); for (cnt = EPOCH; cnt < GMT->tm_year; ++cnt) - days += ISLEAP (cnt + TM_YEAR_BASE) ? 366 : 365; + days += ISLEAP(cnt + TM_YEAR_BASE) ? 366 : 365; /* Selected time could be before EPOCH */ for (cnt = GMT->tm_year; cnt < EPOCH; ++cnt) - days -= ISLEAP (cnt + TM_YEAR_BASE) ? 366 : 365; + days -= ISLEAP(cnt + TM_YEAR_BASE) ? 366 : 365; - return (potm (days)); + return potm(days); } /* @@ -906,25 +842,24 @@ pom (time_t tmpt) * Careful: date is the selected day in calendar at 00:00, so it represents * the phase of the moon for previous day. */ -char * -calendar_get_pom (time_t date) +const char *calendar_get_pom(time_t date) { - char *pom_pict[MOON_PHASES] = { " ", "|) ", "(|)", "(| ", " | " }; + const char *pom_pict[MOON_PHASES] = { " ", "|) ", "(|)", "(| ", " | " }; enum pom phase = NO_POM; double pom_today, relative_pom, pom_yesterday, pom_tomorrow; const double half = 50.0; - pom_yesterday = pom (date); - pom_today = pom (date + DAYINSEC); - relative_pom = abs (pom_today - half); - pom_tomorrow = pom (date + 2 * DAYINSEC); + pom_yesterday = pom(date); + pom_today = pom(date + DAYINSEC); + relative_pom = abs(pom_today - half); + pom_tomorrow = pom(date + 2 * DAYINSEC); if (pom_today > pom_yesterday && pom_today > pom_tomorrow) phase = FULL_MOON; else if (pom_today < pom_yesterday && pom_today < pom_tomorrow) phase = NEW_MOON; - else if (relative_pom < abs (pom_yesterday - half) - && relative_pom < abs (pom_tomorrow - half)) + else if (relative_pom < abs(pom_yesterday - half) + && relative_pom < abs(pom_tomorrow - half)) phase = (pom_tomorrow > pom_today) ? FIRST_QUARTER : LAST_QUARTER; - return (pom_pict[phase]); + return pom_pict[phase]; } diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..edf1f3b --- /dev/null +++ b/src/config.c @@ -0,0 +1,574 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#include <ctype.h> +#include <unistd.h> + +#include "calcurse.h" + +typedef int (*config_fn_parse_t) (void *, const char *); +typedef int (*config_fn_serialize_t) (char *, void *); + +struct confvar { + const char *key; + config_fn_parse_t fn_parse; + config_fn_serialize_t fn_serialize; + void *target; +}; + +static int config_parse_bool(unsigned *, const char *); +static int config_serialize_bool(char *, unsigned *); +static int config_parse_int(int *, const char *); +static int config_serialize_int(char *, int *); +static int config_parse_unsigned(unsigned *, const char *); +static int config_serialize_unsigned(char *, unsigned *); +static int config_parse_str(char *, const char *); +static int config_serialize_str(char *, const char *); +static int config_parse_calendar_view(void *, const char *); +static int config_serialize_calendar_view(char *, void *); +static int config_parse_first_day_of_week(void *, const char *); +static int config_serialize_first_day_of_week(char *, void *); +static int config_parse_color_theme(void *, const char *); +static int config_serialize_color_theme(char *, void *); +static int config_parse_layout(void *, const char *); +static int config_serialize_layout(char *, void *); +static int config_parse_sidebar_width(void *, const char *); +static int config_serialize_sidebar_width(char *, void *); +static int config_parse_output_datefmt(void *, const char *); +static int config_serialize_output_datefmt(char *, void *); +static int config_parse_input_datefmt(void *, const char *); +static int config_serialize_input_datefmt(char *, void *); + +#define CONFIG_HANDLER_BOOL(var) (config_fn_parse_t) config_parse_bool, \ + (config_fn_serialize_t) config_serialize_bool, &(var) +#define CONFIG_HANDLER_INT(var) (config_fn_parse_t) config_parse_int, \ + (config_fn_serialize_t) config_serialize_int, &(var) +#define CONFIG_HANDLER_UNSIGNED(var) (config_fn_parse_t) config_parse_unsigned, \ + (config_fn_serialize_t) config_serialize_unsigned, &(var) +#define CONFIG_HANDLER_STR(var) (config_fn_parse_t) config_parse_str, \ + (config_fn_serialize_t) config_serialize_str, &(var) + +static const struct confvar confmap[] = { + {"appearance.calendarview", config_parse_calendar_view, + config_serialize_calendar_view, NULL}, + {"appearance.layout", config_parse_layout, config_serialize_layout, NULL}, + {"appearance.notifybar", CONFIG_HANDLER_BOOL(nbar.show)}, + {"appearance.sidebarwidth", config_parse_sidebar_width, + config_serialize_sidebar_width, NULL}, + {"appearance.theme", config_parse_color_theme, config_serialize_color_theme, + NULL}, + {"daemon.enable", CONFIG_HANDLER_BOOL(dmon.enable)}, + {"daemon.log", CONFIG_HANDLER_BOOL(dmon.log)}, + {"format.inputdate", config_parse_input_datefmt, + config_serialize_input_datefmt, NULL}, + {"format.notifydate", CONFIG_HANDLER_STR(nbar.datefmt)}, + {"format.notifytime", CONFIG_HANDLER_STR(nbar.timefmt)}, + {"format.outputdate", config_parse_output_datefmt, + config_serialize_output_datefmt, NULL}, + {"general.autogc", CONFIG_HANDLER_BOOL(conf.auto_gc)}, + {"general.autosave", CONFIG_HANDLER_BOOL(conf.auto_save)}, + {"general.confirmdelete", CONFIG_HANDLER_BOOL(conf.confirm_delete)}, + {"general.confirmquit", CONFIG_HANDLER_BOOL(conf.confirm_quit)}, + {"general.firstdayofweek", config_parse_first_day_of_week, + config_serialize_first_day_of_week, NULL}, + {"general.periodicsave", CONFIG_HANDLER_UNSIGNED(conf.periodic_save)}, + {"general.progressbar", CONFIG_HANDLER_BOOL(conf.progress_bar)}, + {"general.systemdialogs", CONFIG_HANDLER_BOOL(conf.system_dialogs)}, + {"notification.command", CONFIG_HANDLER_STR(nbar.cmd)}, + {"notification.notifyall", CONFIG_HANDLER_BOOL(nbar.notify_all)}, + {"notification.warning", CONFIG_HANDLER_INT(nbar.cntdwn)} +}; + +struct config_save_status { + FILE *fp; + int done[sizeof(confmap) / sizeof(confmap[0])]; +}; + +typedef int (*config_fn_walk_cb_t) (const char *, const char *, void *); +typedef int (*config_fn_walk_junk_cb_t) (const char *, void *); + +static int config_parse_bool(unsigned *dest, const char *val) +{ + if (strcmp(val, "yes") == 0) + *dest = 1; + else if (strcmp(val, "no") == 0) + *dest = 0; + else + return 0; + + return 1; +} + +static int config_parse_unsigned(unsigned *dest, const char *val) +{ + if (is_all_digit(val)) + *dest = atoi(val); + else + return 0; + + return 1; +} + +static int config_parse_int(int *dest, const char *val) +{ + if ((*val == '+' || *val == '-' || isdigit(*val)) && is_all_digit(val + 1)) + *dest = atoi(val); + else + return 0; + + return 1; +} + +static int config_parse_str(char *dest, const char *val) +{ + strncpy(dest, val, BUFSIZ); + return 1; +} + +static int config_parse_color(int *dest, const char *val) +{ + if (!strcmp(val, "black")) + *dest = COLOR_BLACK; + else if (!strcmp(val, "red")) + *dest = COLOR_RED; + else if (!strcmp(val, "green")) + *dest = COLOR_GREEN; + else if (!strcmp(val, "yellow")) + *dest = COLOR_YELLOW; + else if (!strcmp(val, "blue")) + *dest = COLOR_BLUE; + else if (!strcmp(val, "magenta")) + *dest = COLOR_MAGENTA; + else if (!strcmp(val, "cyan")) + *dest = COLOR_CYAN; + else if (!strcmp(val, "white")) + *dest = COLOR_WHITE; + else if (!strcmp(val, "default")) + *dest = background; + else + return 0; + + return 1; +} + +static int config_parse_color_pair(int *dest1, int *dest2, const char *val) +{ + char s1[BUFSIZ], s2[BUFSIZ]; + + if (sscanf(val, "%s on %s", s1, s2) != 2) + return 0; + + return (config_parse_color(dest1, s1) && config_parse_color(dest2, s2)); +} + +static int config_parse_calendar_view(void *dummy, const char *val) +{ + calendar_set_view(atoi(val)); + return 1; +} + +static int config_parse_first_day_of_week(void *dummy, const char *val) +{ + if (!strcmp(val, "monday")) + calendar_set_first_day_of_week(MONDAY); + else if (!strcmp(val, "sunday")) + calendar_set_first_day_of_week(SUNDAY); + else + return 0; + + return 1; +} + +static int config_parse_color_theme(void *dummy, const char *val) +{ + int color1, color2; + if (!config_parse_color_pair(&color1, &color2, val)) + return 0; + init_pair(COLR_CUSTOM, color1, color2); + return 1; +} + +static int config_parse_layout(void *dummy, const char *val) +{ + wins_set_layout(atoi(val)); + return 1; +} + +static int config_parse_sidebar_width(void *dummy, const char *val) +{ + wins_set_sbar_width(atoi(val)); + return 1; +} + +static int config_parse_output_datefmt(void *dummy, const char *val) +{ + if (val[0] != '\0') + return config_parse_str(conf.output_datefmt, val); + return 1; +} + +static int config_parse_input_datefmt(void *dummy, const char *val) +{ + if (config_parse_int(&conf.input_datefmt, val)) { + if (conf.input_datefmt <= 0 || conf.input_datefmt >= DATE_FORMATS) + conf.input_datefmt = 1; + return 1; + } else + return 0; +} + +/* Set a configuration variable. */ +static int config_set_conf(const char *key, const char *value) +{ + int i; + + if (!key) + return -1; + + for (i = 0; i < sizeof(confmap) / sizeof(confmap[0]); i++) { + if (!strcmp(confmap[i].key, key)) + return confmap[i].fn_parse(confmap[i].target, value); + } + + return -1; +} + +static int config_serialize_bool(char *dest, unsigned *val) +{ + if (*val) { + dest[0] = 'y'; + dest[1] = 'e'; + dest[2] = 's'; + dest[3] = '\0'; + } else { + dest[0] = 'n'; + dest[1] = 'o'; + dest[2] = '\0'; + } + + return 1; +} + +static int config_serialize_unsigned(char *dest, unsigned *val) +{ + snprintf(dest, BUFSIZ, "%u", *val); + return 1; +} + +static int config_serialize_int(char *dest, int *val) +{ + snprintf(dest, BUFSIZ, "%d", *val); + return 1; +} + +static int config_serialize_str(char *dest, const char *val) +{ + strncpy(dest, val, BUFSIZ); + return 1; +} + +/* + * Return a string defining the color theme in the form: + * foreground color 'on' background color + * in order to dump this data in the configuration file. + * Color numbers follow the ncurses library definitions. + * If ncurses library was compiled with --enable-ext-funcs, + * then default color is -1. + */ +static void config_color_theme_name(char *theme_name) +{ +#define MAXCOLORS 8 +#define NBCOLORS 2 +#define DEFAULTCOLOR 255 +#define DEFAULTCOLOR_EXT -1 + + int i; + short color[NBCOLORS]; + const char *color_name[NBCOLORS]; + const char *default_color = "default"; + const char *name[MAXCOLORS] = { + "black", + "red", + "green", + "yellow", + "blue", + "magenta", + "cyan", + "white" + }; + + if (!colorize) + strncpy(theme_name, "0", BUFSIZ); + else { + pair_content(COLR_CUSTOM, &color[0], &color[1]); + for (i = 0; i < NBCOLORS; i++) { + if ((color[i] == DEFAULTCOLOR) || (color[i] == DEFAULTCOLOR_EXT)) + color_name[i] = default_color; + else if (color[i] >= 0 && color[i] <= MAXCOLORS) + color_name[i] = name[color[i]]; + else { + EXIT(_("unknown color")); + /* NOTREACHED */ + } + } + snprintf(theme_name, BUFSIZ, "%s on %s", color_name[0], color_name[1]); + } +} + +static int config_serialize_calendar_view(char *buf, void *dummy) +{ + int tmp = calendar_get_view(); + return config_serialize_int(buf, &tmp); +} + +static int config_serialize_first_day_of_week(char *buf, void *dummy) +{ + if (calendar_week_begins_on_monday()) + strcpy(buf, "monday"); + else + strcpy(buf, "sunday"); + + return 1; +} + +static int config_serialize_color_theme(char *buf, void *dummy) +{ + config_color_theme_name(buf); + return 1; +} + +static int config_serialize_layout(char *buf, void *dummy) +{ + int tmp = wins_layout(); + return config_serialize_int(buf, &tmp); +} + +static int config_serialize_sidebar_width(char *buf, void *dummy) +{ + int tmp = wins_sbar_wperc(); + return config_serialize_int(buf, &tmp); +} + +static int config_serialize_output_datefmt(char *buf, void *dummy) +{ + return config_serialize_str(buf, conf.output_datefmt); +} + +static int config_serialize_input_datefmt(char *buf, void *dummy) +{ + return config_serialize_int(buf, &conf.input_datefmt); +} + +/* Serialize the value of a configuration variable. */ +static int +config_serialize_conf(char *buf, const char *key, + struct config_save_status *status) +{ + int i; + + if (!key) + return -1; + + for (i = 0; i < sizeof(confmap) / sizeof(confmap[0]); i++) { + if (!strcmp(confmap[i].key, key)) { + if (confmap[i].fn_serialize(buf, confmap[i].target)) { + if (status) + status->done[i] = 1; + return 1; + } else + return 0; + } + } + + return -1; +} + +static void +config_file_walk(config_fn_walk_cb_t fn_cb, + config_fn_walk_junk_cb_t fn_junk_cb, void *data) +{ + FILE *data_file; + char buf[BUFSIZ], e_conf[BUFSIZ]; + char *key, *value; + + data_file = fopen(path_conf, "r"); + EXIT_IF(data_file == NULL, _("failed to open configuration file")); + + pthread_mutex_lock(&nbar.mutex); + for (;;) { + if (fgets(buf, sizeof buf, data_file) == NULL) + break; + io_extract_data(e_conf, buf, sizeof buf); + + if (*e_conf == '\0') { + if (fn_junk_cb) + fn_junk_cb(buf, data); + continue; + } + + key = e_conf; + value = strchr(e_conf, '='); + if (value) { + *value = '\0'; + value++; + } + + if (strcmp(key, "auto_save") == 0 || + strcmp(key, "auto_gc") == 0 || + strcmp(key, "periodic_save") == 0 || + strcmp(key, "confirm_quit") == 0 || + strcmp(key, "confirm_delete") == 0 || + strcmp(key, "skip_system_dialogs") == 0 || + strcmp(key, "skip_progress_bar") == 0 || + strcmp(key, "calendar_default_view") == 0 || + strcmp(key, "week_begins_on_monday") == 0 || + strcmp(key, "color-theme") == 0 || + strcmp(key, "layout") == 0 || + strcmp(key, "side-bar_width") == 0 || + strcmp(key, "notify-bar_show") == 0 || + strcmp(key, "notify-bar_date") == 0 || + strcmp(key, "notify-bar_clock") == 0 || + strcmp(key, "notify-bar_warning") == 0 || + strcmp(key, "notify-bar_command") == 0 || + strcmp(key, "notify-all") == 0 || + strcmp(key, "output_datefmt") == 0 || + strcmp(key, "input_datefmt") == 0 || + strcmp(key, "notify-daemon_enable") == 0 || + strcmp(key, "notify-daemon_log") == 0) { + WARN_MSG(_("Pre-3.0.0 configuration file format detected, " + "please upgrade running `calcurse-upgrade`.")); + } + + if (value && (*value == '\0' || *value == '\n')) { + /* Backward compatibility mode. */ + if (fgets(buf, sizeof buf, data_file) == NULL) + break; + io_extract_data(e_conf, buf, sizeof buf); + value = e_conf; + } + + fn_cb(key, value, data); + } + file_close(data_file, __FILE_POS__); + pthread_mutex_unlock(&nbar.mutex); +} + +static int config_load_cb(const char *key, const char *value, void *dummy) +{ + int result = config_set_conf(key, value); + + if (result < 0) + EXIT(_("configuration variable unknown: \"%s\""), key); + /* NOTREACHED */ + else if (result == 0) + EXIT(_("wrong configuration variable format for \"%s\""), key); + /* NOTREACHED */ + + return 1; +} + +/* Load the user configuration. */ +void config_load(void) +{ + config_file_walk(config_load_cb, NULL, NULL); +} + +static int config_save_cb(const char *key, const char *value, void *status) +{ + char buf[BUFSIZ]; + int result = + config_serialize_conf(buf, key, (struct config_save_status *)status); + + if (result < 0) + EXIT(_("configuration variable unknown: \"%s\""), key); + /* NOTREACHED */ + else if (result == 0) + EXIT(_("wrong configuration variable format for \"%s\""), key); + /* NOTREACHED */ + + fputs(key, ((struct config_save_status *)status)->fp); + fputc('=', ((struct config_save_status *)status)->fp); + fputs(buf, ((struct config_save_status *)status)->fp); + fputc('\n', ((struct config_save_status *)status)->fp); + + return 1; +} + +static int config_save_junk_cb(const char *data, void *status) +{ + fputs(data, ((struct config_save_status *)status)->fp); + return 1; +} + +/* Save the user configuration. */ +unsigned config_save(void) +{ + char tmppath[BUFSIZ]; + char *tmpext; + struct config_save_status status; + int i; + + if (read_only) + return 1; + + strncpy(tmppath, get_tempdir(), BUFSIZ); + strncat(tmppath, "/" CONF_PATH_NAME ".", BUFSIZ - strlen(tmppath) - 1); + if ((tmpext = new_tempfile(tmppath, TMPEXTSIZ)) == NULL) + return 0; + strncat(tmppath, tmpext, BUFSIZ - strlen(tmppath) - 1); + mem_free(tmpext); + + status.fp = fopen(tmppath, "w"); + if (!status.fp) + return 0; + + memset(status.done, 0, sizeof(status.done)); + + config_file_walk(config_save_cb, config_save_junk_cb, (void *)&status); + + /* Set variables that were missing from the configuration file. */ + for (i = 0; i < sizeof(confmap) / sizeof(confmap[0]); i++) { + if (!status.done[i]) + config_save_cb(confmap[i].key, NULL, &status); + } + + file_close(status.fp, __FILE_POS__); + + if (io_file_cp(tmppath, path_conf)) + unlink(tmppath); + + return 1; +} diff --git a/src/custom.c b/src/custom.c index 1f75978..ef84703 100644 --- a/src/custom.c +++ b/src/custom.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,35 +37,10 @@ #include <string.h> #include <stdlib.h> #include <math.h> +#include <ctype.h> #include "calcurse.h" -/* Available configuration variables. */ -enum conf_var { - CUSTOM_CONF_NOVARIABLE, - CUSTOM_CONF_AUTOSAVE, - CUSTOM_CONF_PERIODICSAVE, - CUSTOM_CONF_CONFIRMQUIT, - CUSTOM_CONF_CONFIRMDELETE, - CUSTOM_CONF_SKIPSYSTEMDIALOGS, - CUSTOM_CONF_SKIPPROGRESSBAR, - CUSTOM_CONF_CALENDAR_DEFAULTVIEW, - CUSTOM_CONF_WEEKBEGINSONMONDAY, - CUSTOM_CONF_COLORTHEME, - CUSTOM_CONF_LAYOUT, - CUSTOM_CONF_SBAR_WIDTH, - CUSTOM_CONF_NOTIFYBARSHOW, - CUSTOM_CONF_NOTIFYBARDATE, - CUSTOM_CONF_NOTIFYBARCLOCK, - CUSTOM_CONF_NOTIFYBARWARNING, - CUSTOM_CONF_NOTIFYBARCOMMAND, - CUSTOM_CONF_OUTPUTDATEFMT, - CUSTOM_CONF_INPUTDATEFMT, - CUSTOM_CONF_DMON_ENABLE, - CUSTOM_CONF_DMON_LOG, - CUSTOM_CONF_VARIABLES -}; - struct attribute { int color[7]; int nocolor[7]; @@ -73,118 +48,6 @@ struct attribute { static struct attribute attr; -static unsigned -fill_config_var (char *string) -{ - if (strncmp (string, "yes", 3) == 0) - return 1; - else if (strncmp (string, "no", 2) == 0) - return 0; - else - { - EXIT (_("wrong configuration variable format.")); - return 0; - } -} - -/* - * Load user color theme from file. - * Need to handle calcurse versions prior to 1.8, where colors where handled - * differently (number between 1 and 8). - */ -static void -custom_load_color (char *color, int background) -{ -#define AWAITED_COLORS 2 - - int i, len, color_num; - char c[AWAITED_COLORS][BUFSIZ]; - int colr[AWAITED_COLORS]; - - len = strlen (color); - if (len > 1) - { - /* New version configuration */ - if (sscanf (color, "%s on %s", c[0], c[1]) != AWAITED_COLORS) - { - EXIT (_("missing colors in config file")); - /* NOTREACHED */ - } - - for (i = 0; i < AWAITED_COLORS; i++) - { - if (!strncmp (c[i], "black", 5)) - colr[i] = COLOR_BLACK; - else if (!strncmp (c[i], "red", 3)) - colr[i] = COLOR_RED; - else if (!strncmp (c[i], "green", 5)) - colr[i] = COLOR_GREEN; - else if (!strncmp (c[i], "yellow", 6)) - colr[i] = COLOR_YELLOW; - else if (!strncmp (c[i], "blue", 4)) - colr[i] = COLOR_BLUE; - else if (!strncmp (c[i], "magenta", 7)) - colr[i] = COLOR_MAGENTA; - else if (!strncmp (c[i], "cyan", 4)) - colr[i] = COLOR_CYAN; - else if (!strncmp (c[i], "white", 5)) - colr[i] = COLOR_WHITE; - else if (!strncmp (c[i], "default", 7)) - colr[i] = background; - else - { - EXIT (_("wrong color name")); - /* NOTREACHED */ - } - } - init_pair (COLR_CUSTOM, colr[0], colr[1]); - } - else if (len > 0 && len < 2) - { - /* Old version configuration */ - color_num = atoi (color); - - switch (color_num) - { - case 0: - colorize = 0; - break; - case 1: - init_pair (COLR_CUSTOM, COLOR_RED, background); - break; - case 2: - init_pair (COLR_CUSTOM, COLOR_GREEN, background); - break; - case 3: - init_pair (COLR_CUSTOM, COLOR_BLUE, background); - break; - case 4: - init_pair (COLR_CUSTOM, COLOR_CYAN, background); - break; - case 5: - init_pair (COLR_CUSTOM, COLOR_YELLOW, background); - break; - case 6: - init_pair (COLR_CUSTOM, COLOR_BLACK, COLR_GREEN); - break; - case 7: - init_pair (COLR_CUSTOM, COLOR_BLACK, COLR_YELLOW); - break; - case 8: - init_pair (COLR_CUSTOM, COLOR_RED, COLR_BLUE); - break; - default: - EXIT (_("wrong color number")); - /* NOTREACHED */ - } - } - else - { - EXIT (_("wrong configuration variable format")); - /* NOTREACHED */ - } -} - /* * Define window attributes (for both color and non-color terminals): * ATTR_HIGHEST are for window titles @@ -193,16 +56,15 @@ custom_load_color (char *color, int background) * ATTR_LOW are for days inside calendar panel which contains an event * ATTR_LOWEST are for current day inside calendar panel */ -void -custom_init_attr (void) +void custom_init_attr(void) { - attr.color[ATTR_HIGHEST] = COLOR_PAIR (COLR_CUSTOM); - attr.color[ATTR_HIGH] = COLOR_PAIR (COLR_HIGH); - attr.color[ATTR_MIDDLE] = COLOR_PAIR (COLR_RED); - attr.color[ATTR_LOW] = COLOR_PAIR (COLR_CYAN); - attr.color[ATTR_LOWEST] = COLOR_PAIR (COLR_YELLOW); - attr.color[ATTR_TRUE] = COLOR_PAIR (COLR_GREEN); - attr.color[ATTR_FALSE] = COLOR_PAIR (COLR_RED); + attr.color[ATTR_HIGHEST] = COLOR_PAIR(COLR_CUSTOM); + attr.color[ATTR_HIGH] = COLOR_PAIR(COLR_HIGH); + attr.color[ATTR_MIDDLE] = COLOR_PAIR(COLR_RED); + attr.color[ATTR_LOW] = COLOR_PAIR(COLR_CYAN); + attr.color[ATTR_LOWEST] = COLOR_PAIR(COLR_YELLOW); + attr.color[ATTR_TRUE] = COLOR_PAIR(COLR_GREEN); + attr.color[ATTR_FALSE] = COLOR_PAIR(COLR_RED); attr.nocolor[ATTR_HIGHEST] = A_BOLD; attr.nocolor[ATTR_HIGH] = A_REVERSE; @@ -214,458 +76,278 @@ custom_init_attr (void) } /* Apply window attribute */ -void -custom_apply_attr (WINDOW *win, int attr_num) +void custom_apply_attr(WINDOW * win, int attr_num) { if (colorize) - wattron (win, attr.color[attr_num]); + wattron(win, attr.color[attr_num]); else - wattron (win, attr.nocolor[attr_num]); + wattron(win, attr.nocolor[attr_num]); } /* Remove window attribute */ -void -custom_remove_attr (WINDOW *win, int attr_num) +void custom_remove_attr(WINDOW * win, int attr_num) { if (colorize) - wattroff (win, attr.color[attr_num]); + wattroff(win, attr.color[attr_num]); else - wattroff (win, attr.nocolor[attr_num]); -} - -/* Load the user configuration. */ -void -custom_load_conf (struct conf *conf, int background) -{ - FILE *data_file; - char *mesg_line1 = _("Failed to open config file"); - char *mesg_line2 = _("Press [ENTER] to continue"); - char buf[BUFSIZ], e_conf[BUFSIZ]; - enum conf_var var; - - data_file = fopen (path_conf, "r"); - if (data_file == NULL) - { - status_mesg (mesg_line1, mesg_line2); - wnoutrefresh (win[STA].p); - wins_doupdate (); - (void)keys_getch (win[STA].p); - } - var = CUSTOM_CONF_NOVARIABLE; - pthread_mutex_lock (&nbar.mutex); - for (;;) - { - if (fgets (buf, sizeof buf, data_file) == NULL) - { - break; - } - io_extract_data (e_conf, buf, sizeof buf); - - switch (var) - { - case CUSTOM_CONF_NOVARIABLE: - break; - case CUSTOM_CONF_AUTOSAVE: - conf->auto_save = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_PERIODICSAVE: - if (atoi (e_conf) < 0) - conf->periodic_save = 0; - else - conf->periodic_save = atoi (e_conf); - var = 0; - break; - case CUSTOM_CONF_CONFIRMQUIT: - conf->confirm_quit = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_CONFIRMDELETE: - conf->confirm_delete = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_SKIPSYSTEMDIALOGS: - conf->skip_system_dialogs = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_SKIPPROGRESSBAR: - conf->skip_progress_bar = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_CALENDAR_DEFAULTVIEW: - calendar_set_view (atoi (e_conf)); - var = 0; - break; - case CUSTOM_CONF_WEEKBEGINSONMONDAY: - if (fill_config_var (e_conf)) - calendar_set_first_day_of_week (MONDAY); - else - calendar_set_first_day_of_week (SUNDAY); - var = 0; - break; - case CUSTOM_CONF_COLORTHEME: - custom_load_color (e_conf, background); - var = 0; - break; - case CUSTOM_CONF_LAYOUT: - wins_set_layout (atoi (e_conf)); - var = 0; - break; - case CUSTOM_CONF_SBAR_WIDTH: - wins_set_sbar_width (atoi (e_conf)); - var = 0; - break; - case CUSTOM_CONF_NOTIFYBARSHOW: - nbar.show = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_NOTIFYBARDATE: - (void)strncpy (nbar.datefmt, e_conf, strlen (e_conf) + 1); - var = 0; - break; - case CUSTOM_CONF_NOTIFYBARCLOCK: - (void)strncpy (nbar.timefmt, e_conf, strlen (e_conf) + 1); - var = 0; - break; - case CUSTOM_CONF_NOTIFYBARWARNING: - nbar.cntdwn = atoi (e_conf); - var = 0; - break; - case CUSTOM_CONF_NOTIFYBARCOMMAND: - (void)strncpy (nbar.cmd, e_conf, strlen (e_conf) + 1); - var = 0; - break; - case CUSTOM_CONF_OUTPUTDATEFMT: - if (e_conf[0] != '\0') - (void)strncpy (conf->output_datefmt, e_conf, strlen (e_conf) + 1); - var = 0; - break; - case CUSTOM_CONF_INPUTDATEFMT: - conf->input_datefmt = atoi (e_conf); - if (conf->input_datefmt <= 0 || conf->input_datefmt >= DATE_FORMATS) - conf->input_datefmt = 1; - var = 0; - break; - case CUSTOM_CONF_DMON_ENABLE: - dmon.enable = fill_config_var (e_conf); - var = 0; - break; - case CUSTOM_CONF_DMON_LOG: - dmon.log = fill_config_var (e_conf); - var = 0; - break; - default: - EXIT (_("configuration variable unknown")); - /* NOTREACHED */ - } - - if (strncmp (e_conf, "auto_save=", 10) == 0) - var = CUSTOM_CONF_AUTOSAVE; - else if (strncmp (e_conf, "periodic_save=", 14) == 0) - var = CUSTOM_CONF_PERIODICSAVE; - else if (strncmp (e_conf, "confirm_quit=", 13) == 0) - var = CUSTOM_CONF_CONFIRMQUIT; - else if (strncmp (e_conf, "confirm_delete=", 15) == 0) - var = CUSTOM_CONF_CONFIRMDELETE; - else if (strncmp (e_conf, "skip_system_dialogs=", 20) == 0) - var = CUSTOM_CONF_SKIPSYSTEMDIALOGS; - else if (strncmp (e_conf, "skip_progress_bar=", 18) == 0) - var = CUSTOM_CONF_SKIPPROGRESSBAR; - else if (strncmp (e_conf, "calendar_default_view=", 22) == 0) - var = CUSTOM_CONF_CALENDAR_DEFAULTVIEW; - else if (strncmp (e_conf, "week_begins_on_monday=", 22) == 0) - var = CUSTOM_CONF_WEEKBEGINSONMONDAY; - else if (strncmp (e_conf, "color-theme=", 12) == 0) - var = CUSTOM_CONF_COLORTHEME; - else if (strncmp (e_conf, "layout=", 7) == 0) - var = CUSTOM_CONF_LAYOUT; - else if (strncmp (e_conf, "side-bar_width=", 15) == 0) - var = CUSTOM_CONF_SBAR_WIDTH; - else if (strncmp (e_conf, "notify-bar_show=", 16) == 0) - var = CUSTOM_CONF_NOTIFYBARSHOW; - else if (strncmp (e_conf, "notify-bar_date=", 16) == 0) - var = CUSTOM_CONF_NOTIFYBARDATE; - else if (strncmp (e_conf, "notify-bar_clock=", 17) == 0) - var = CUSTOM_CONF_NOTIFYBARCLOCK; - else if (strncmp (e_conf, "notify-bar_warning=", 19) == 0) - var = CUSTOM_CONF_NOTIFYBARWARNING; - else if (strncmp (e_conf, "notify-bar_command=", 19) == 0) - var = CUSTOM_CONF_NOTIFYBARCOMMAND; - else if (strncmp (e_conf, "output_datefmt=", 15) == 0) - var = CUSTOM_CONF_OUTPUTDATEFMT; - else if (strncmp (e_conf, "input_datefmt=", 14) == 0) - var = CUSTOM_CONF_INPUTDATEFMT; - else if (strncmp (e_conf, "notify-daemon_enable=", 21) == 0) - var = CUSTOM_CONF_DMON_ENABLE; - else if (strncmp (e_conf, "notify-daemon_log=", 18) == 0) - var = CUSTOM_CONF_DMON_LOG; - } - file_close (data_file, __FILE_POS__); - pthread_mutex_unlock (&nbar.mutex); + wattroff(win, attr.nocolor[attr_num]); } /* Draws the configuration bar */ -void -custom_config_bar (void) +void custom_config_bar(void) { const int SMLSPC = 2; const int SPC = 15; - custom_apply_attr (win[STA].p, ATTR_HIGHEST); - mvwprintw (win[STA].p, 0, 2, "Q"); - mvwprintw (win[STA].p, 1, 2, "G"); - mvwprintw (win[STA].p, 0, 2 + SPC, "L"); - mvwprintw (win[STA].p, 1, 2 + SPC, "S"); - mvwprintw (win[STA].p, 0, 2 + 2 * SPC, "C"); - mvwprintw (win[STA].p, 1, 2 + 2 * SPC, "N"); - mvwprintw (win[STA].p, 0, 2 + 3 * SPC, "K"); - custom_remove_attr (win[STA].p, ATTR_HIGHEST); - - mvwprintw (win[STA].p, 0, 2 + SMLSPC, _("Exit")); - mvwprintw (win[STA].p, 1, 2 + SMLSPC, _("General")); - mvwprintw (win[STA].p, 0, 2 + SPC + SMLSPC, _("Layout")); - mvwprintw (win[STA].p, 1, 2 + SPC + SMLSPC, _("Sidebar")); - mvwprintw (win[STA].p, 0, 2 + 2 * SPC + SMLSPC, _("Color")); - mvwprintw (win[STA].p, 1, 2 + 2 * SPC + SMLSPC, _("Notify")); - mvwprintw (win[STA].p, 0, 2 + 3 * SPC + SMLSPC, _("Keys")); - - wnoutrefresh (win[STA].p); - wmove (win[STA].p, 0, 0); - wins_doupdate (); + custom_apply_attr(win[STA].p, ATTR_HIGHEST); + mvwprintw(win[STA].p, 0, 2, "Q"); + mvwprintw(win[STA].p, 1, 2, "G"); + mvwprintw(win[STA].p, 0, 2 + SPC, "L"); + mvwprintw(win[STA].p, 1, 2 + SPC, "S"); + mvwprintw(win[STA].p, 0, 2 + 2 * SPC, "C"); + mvwprintw(win[STA].p, 1, 2 + 2 * SPC, "N"); + mvwprintw(win[STA].p, 0, 2 + 3 * SPC, "K"); + custom_remove_attr(win[STA].p, ATTR_HIGHEST); + + mvwprintw(win[STA].p, 0, 2 + SMLSPC, _("Exit")); + mvwprintw(win[STA].p, 1, 2 + SMLSPC, _("General")); + mvwprintw(win[STA].p, 0, 2 + SPC + SMLSPC, _("Layout")); + mvwprintw(win[STA].p, 1, 2 + SPC + SMLSPC, _("Sidebar")); + mvwprintw(win[STA].p, 0, 2 + 2 * SPC + SMLSPC, _("Color")); + mvwprintw(win[STA].p, 1, 2 + 2 * SPC + SMLSPC, _("Notify")); + mvwprintw(win[STA].p, 0, 2 + 3 * SPC + SMLSPC, _("Keys")); + + wnoutrefresh(win[STA].p); + wmove(win[STA].p, 0, 0); + wins_doupdate(); } -static void -layout_selection_bar (void) +static void layout_selection_bar(void) { - struct binding quit = {_("Exit"), KEY_GENERIC_QUIT}; - struct binding select = {_("Select"), KEY_GENERIC_SELECT}; - struct binding up = {_("Up"), KEY_MOVE_UP}; - struct binding down = {_("Down"), KEY_MOVE_DOWN}; - struct binding left = {_("Left"), KEY_MOVE_LEFT}; - struct binding right = {_("Right"), KEY_MOVE_RIGHT}; - struct binding help = {_("Help"), KEY_GENERIC_HELP}; - - struct binding *binding[] = {&quit, &select, &up, &down, &left, &right, &help}; - int binding_size = sizeof (binding) / sizeof (binding[0]); - - keys_display_bindings_bar (win[STA].p, binding, 0, binding_size); + struct binding quit = { _("Exit"), KEY_GENERIC_QUIT }; + struct binding select = { _("Select"), KEY_GENERIC_SELECT }; + struct binding up = { _("Up"), KEY_MOVE_UP }; + struct binding down = { _("Down"), KEY_MOVE_DOWN }; + struct binding left = { _("Left"), KEY_MOVE_LEFT }; + struct binding right = { _("Right"), KEY_MOVE_RIGHT }; + struct binding help = { _("Help"), KEY_GENERIC_HELP }; + + struct binding *bindings[] = { + &quit, &select, &up, &down, &left, &right, &help + }; + int bindings_size = sizeof(bindings) / sizeof(bindings[0]); + + keys_display_bindings_bar(win[STA].p, bindings, bindings_size, 0, + bindings_size, NULL); } #define NBLAYOUTS 8 #define LAYOUTSPERCOL 2 /* Used to display available layouts in layout configuration menu. */ -static void -display_layout_config (struct window *lwin, int mark, int cursor) +static void display_layout_config(struct window *lwin, int mark, int cursor) { #define CURSOR (32 | A_REVERSE) #define MARK 88 #define LAYOUTH 5 #define LAYOUTW 9 - char *box = "[ ]"; - const int BOXSIZ = strlen (box); + const char *box = "[ ]"; + const int BOXSIZ = strlen(box); const int NBCOLS = NBLAYOUTS / LAYOUTSPERCOL; const int COLSIZ = LAYOUTW + BOXSIZ + 1; const int XSPC = (lwin->w - NBCOLS * COLSIZ) / (NBCOLS + 1); const int XOFST = (lwin->w - NBCOLS * (XSPC + COLSIZ)) / 2; - const int YSPC = (lwin->h - 8 - LAYOUTSPERCOL * LAYOUTH) / (LAYOUTSPERCOL + 1); + const int YSPC = + (lwin->h - 8 - LAYOUTSPERCOL * LAYOUTH) / (LAYOUTSPERCOL + 1); const int YOFST = (lwin->h - LAYOUTSPERCOL * (YSPC + LAYOUTH)) / 2; - enum {YPOS, XPOS, NBPOS}; + enum { YPOS, XPOS, NBPOS }; int pos[NBLAYOUTS][NBPOS]; - char *layouts[LAYOUTH][NBLAYOUTS] = { - {"+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+"}, - {"| | c |", "| | t |", "| c | |", "| t | |", "| | c |", "| | a |", "| c | |", "| a | |"}, - {"| a +---+", "| a +---+", "+---+ a |", "|---+ a |", "| t +---+", "| t +---+", "+---+ t |", "+---+ t |"}, - {"| | t |", "| | c |", "| t | |", "| c | |", "| | a |", "| | c |", "| a | |", "| c | |"}, - {"+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+"} + const char *layouts[LAYOUTH][NBLAYOUTS] = { + {"+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", + "+---+---+", "+---+---+", "+---+---+"}, + {"| | c |", "| | t |", "| c | |", "| t | |", "| | c |", + "| | a |", "| c | |", "| a | |"}, + {"| a +---+", "| a +---+", "+---+ a |", "|---+ a |", "| t +---+", + "| t +---+", "+---+ t |", "+---+ t |"}, + {"| | t |", "| | c |", "| t | |", "| c | |", "| | a |", + "| | c |", "| a | |", "| c | |"}, + {"+---+---+", "+---+---+", "+---+---+", "+---+---+", "+---+---+", + "+---+---+", "+---+---+", "+---+---+"} }; int i; - for (i = 0; i < NBLAYOUTS; i++) - { - pos[i][YPOS] = YOFST + (i % LAYOUTSPERCOL) * (YSPC + LAYOUTH); - pos[i][XPOS] = XOFST + (i / LAYOUTSPERCOL) * (XSPC + COLSIZ); - } + for (i = 0; i < NBLAYOUTS; i++) { + pos[i][YPOS] = YOFST + (i % LAYOUTSPERCOL) * (YSPC + LAYOUTH); + pos[i][XPOS] = XOFST + (i / LAYOUTSPERCOL) * (XSPC + COLSIZ); + } - for (i = 0; i < NBLAYOUTS; i++) - { - int j; - - mvwprintw (lwin->p, pos[i][YPOS] + 2, pos[i][XPOS], box); - if (i == mark) - custom_apply_attr (lwin->p, ATTR_HIGHEST); - for (j = 0; j < LAYOUTH; j++) - { - mvwprintw (lwin->p, pos[i][YPOS] + j, pos[i][XPOS] + BOXSIZ + 1, - layouts[j][i]); - } - if (i == mark) - custom_remove_attr (lwin->p, ATTR_HIGHEST); + for (i = 0; i < NBLAYOUTS; i++) { + int j; + + mvwprintw(lwin->p, pos[i][YPOS] + 2, pos[i][XPOS], box); + if (i == mark) + custom_apply_attr(lwin->p, ATTR_HIGHEST); + for (j = 0; j < LAYOUTH; j++) { + mvwprintw(lwin->p, pos[i][YPOS] + j, pos[i][XPOS] + BOXSIZ + 1, + layouts[j][i]); } - mvwaddch (lwin->p, pos[mark][YPOS] + 2, pos[mark][XPOS] + 1, MARK); - mvwaddch (lwin->p, pos[cursor][YPOS] + 2, pos[cursor][XPOS] + 1, CURSOR); - - layout_selection_bar (); - wnoutrefresh (win[STA].p); - wnoutrefresh (lwin->p); - wins_doupdate (); - if (notify_bar ()) - notify_update_bar (); + if (i == mark) + custom_remove_attr(lwin->p, ATTR_HIGHEST); + } + mvwaddch(lwin->p, pos[mark][YPOS] + 2, pos[mark][XPOS] + 1, MARK); + mvwaddch(lwin->p, pos[cursor][YPOS] + 2, pos[cursor][XPOS] + 1, CURSOR); + + layout_selection_bar(); + wnoutrefresh(win[STA].p); + wnoutrefresh(lwin->p); + wins_doupdate(); + if (notify_bar()) + notify_update_bar(); } /* Choose the layout */ -void -custom_layout_config (void) +void custom_layout_config(void) { struct scrollwin hwin; struct window conf_win; int ch, mark, cursor, need_reset; - char label[BUFSIZ]; - char *help_text = - _("With this configuration menu, one can choose where panels will be\n" - "displayed inside calcurse screen. \n" - "It is possible to choose between eight different configurations.\n" - "\nIn the configuration representations, letters correspond to:\n\n" - " 'c' -> calendar panel\n\n" - " 'a' -> appointment panel\n\n" - " 't' -> todo panel\n\n"); - - conf_win.p = (WINDOW *)0; - (void)snprintf (label, BUFSIZ, _("layout configuration")); - custom_confwin_init (&conf_win, label); - cursor = mark = wins_layout () - 1; - display_layout_config (&conf_win, mark, cursor); - clear (); - - while ((ch = keys_getch (win[STA].p)) != KEY_GENERIC_QUIT) - { - need_reset = 0; - switch (ch) - { - case KEY_GENERIC_HELP: - help_wins_init (&hwin, 0, 0, - (notify_bar ()) ? row - 3 : row - 2, col); - mvwprintw (hwin.pad.p, 1, 0, "%s", help_text); - hwin.total_lines = 7; - wins_scrollwin_display (&hwin); - wgetch (hwin.win.p); - wins_scrollwin_delete (&hwin); - need_reset = 1; - break; - case KEY_GENERIC_SELECT: - mark = cursor; - break; - case KEY_MOVE_DOWN: - if (cursor % LAYOUTSPERCOL < LAYOUTSPERCOL - 1) - cursor++; - break; - case KEY_MOVE_UP: - if (cursor % LAYOUTSPERCOL > 0) - cursor--; - break; - case KEY_MOVE_LEFT: - if (cursor >= LAYOUTSPERCOL) - cursor -= LAYOUTSPERCOL; - break; - case KEY_MOVE_RIGHT: - if (cursor < NBLAYOUTS - LAYOUTSPERCOL) - cursor += LAYOUTSPERCOL; - break; - case KEY_GENERIC_CANCEL: - need_reset = 1; - break; - } + const char *label = _("layout configuration"); + const char *help_text = + _("With this configuration menu, one can choose where panels will be\n" + "displayed inside calcurse screen. \n" + "It is possible to choose between eight different configurations.\n" + "\nIn the configuration representations, letters correspond to:\n\n" + " 'c' -> calendar panel\n\n" + " 'a' -> appointment panel\n\n" " 't' -> todo panel\n\n"); + + conf_win.p = NULL; + custom_confwin_init(&conf_win, label); + cursor = mark = wins_layout() - 1; + display_layout_config(&conf_win, mark, cursor); + clear(); + + while ((ch = keys_getch(win[STA].p, NULL)) != KEY_GENERIC_QUIT) { + need_reset = 0; + switch (ch) { + case KEY_GENERIC_HELP: + help_wins_init(&hwin, 0, 0, (notify_bar())? row - 3 : row - 2, col); + mvwprintw(hwin.pad.p, 1, 0, "%s", help_text); + hwin.total_lines = 7; + wins_scrollwin_display(&hwin); + wgetch(hwin.win.p); + wins_scrollwin_delete(&hwin); + need_reset = 1; + break; + case KEY_GENERIC_SELECT: + mark = cursor; + break; + case KEY_MOVE_DOWN: + if (cursor % LAYOUTSPERCOL < LAYOUTSPERCOL - 1) + cursor++; + break; + case KEY_MOVE_UP: + if (cursor % LAYOUTSPERCOL > 0) + cursor--; + break; + case KEY_MOVE_LEFT: + if (cursor >= LAYOUTSPERCOL) + cursor -= LAYOUTSPERCOL; + break; + case KEY_MOVE_RIGHT: + if (cursor < NBLAYOUTS - LAYOUTSPERCOL) + cursor += LAYOUTSPERCOL; + break; + case KEY_GENERIC_CANCEL: + need_reset = 1; + break; + } - if (resize) - { - resize = 0; - endwin (); - wins_refresh (); - curs_set (0); - need_reset = 1; - } + if (resize) { + resize = 0; + endwin(); + wins_refresh(); + curs_set(0); + need_reset = 1; + } - if (need_reset) - custom_confwin_init (&conf_win, label); + if (need_reset) + custom_confwin_init(&conf_win, label); - display_layout_config (&conf_win, mark, cursor); - } - wins_set_layout (mark + 1); - delwin (conf_win.p); + display_layout_config(&conf_win, mark, cursor); + } + wins_set_layout(mark + 1); + delwin(conf_win.p); } #undef NBLAYOUTS #undef LAYOUTSPERCOL /* Sidebar configuration screen. */ -void -custom_sidebar_config (void) +void custom_sidebar_config(void) { struct scrollwin hwin; - struct binding quit = {_("Exit"), KEY_GENERIC_QUIT}; - struct binding inc = {_("Width +"), KEY_MOVE_UP}; - struct binding dec = {_("Width -"), KEY_MOVE_DOWN}; - struct binding help = {_("Help"), KEY_GENERIC_HELP}; - struct binding *binding[] = {&inc, &dec, &help, &quit}; - char *help_text = - _("This configuration screen is used to change the width of the side bar.\n" - "The side bar is the part of the screen which contains two panels:\n" - "the calendar and, depending on the chosen layout, either the todo list\n" - "or the appointment list.\n\n" - "The side bar width can be up to 50% of the total screen width, but\n" - "can't be smaller than " TOSTRING(SBARMINWIDTH) " characters wide.\n\n"); - int ch, binding_size; - - binding_size = sizeof (binding) / sizeof (binding[0]); - - keys_display_bindings_bar (win[STA].p, binding, 0, binding_size); - wins_doupdate (); - - while ((ch = keys_getch (win[STA].p)) != KEY_GENERIC_QUIT) - { - switch (ch) - { - case KEY_MOVE_UP: - wins_sbar_winc (); - break; - case KEY_MOVE_DOWN: - wins_sbar_wdec (); - break; - case KEY_GENERIC_HELP: - help_wins_init (&hwin, 0, 0, - (notify_bar ()) ? row - 3 : row - 2, col); - mvwprintw (hwin.pad.p, 1, 0, "%s", help_text); - hwin.total_lines = 6; - wins_scrollwin_display (&hwin); - wgetch (hwin.win.p); - wins_scrollwin_delete (&hwin); - break; - case KEY_RESIZE: - break; - default: - continue; - } + struct binding quit = { _("Exit"), KEY_GENERIC_QUIT }; + struct binding inc = { _("Width +"), KEY_MOVE_UP }; + struct binding dec = { _("Width -"), KEY_MOVE_DOWN }; + struct binding help = { _("Help"), KEY_GENERIC_HELP }; + struct binding *bindings[] = { + &inc, &dec, &help, &quit + }; + const char *help_text = + _ + ("This configuration screen is used to change the width of the side bar.\n" + "The side bar is the part of the screen which contains two panels:\n" + "the calendar and, depending on the chosen layout, either the todo list\n" + "or the appointment list.\n\n" + "The side bar width can be up to 50% of the total screen width, but\n" + "can't be smaller than " TOSTRING(SBARMINWIDTH) " characters wide.\n\n"); + int ch, bindings_size; + + bindings_size = sizeof(bindings) / sizeof(bindings[0]); + + keys_display_bindings_bar(win[STA].p, bindings, bindings_size, 0, + bindings_size, NULL); + wins_doupdate(); + + while ((ch = keys_getch(win[STA].p, NULL)) != KEY_GENERIC_QUIT) { + switch (ch) { + case KEY_MOVE_UP: + wins_sbar_winc(); + break; + case KEY_MOVE_DOWN: + wins_sbar_wdec(); + break; + case KEY_GENERIC_HELP: + help_wins_init(&hwin, 0, 0, (notify_bar())? row - 3 : row - 2, col); + mvwprintw(hwin.pad.p, 1, 0, "%s", help_text); + hwin.total_lines = 6; + wins_scrollwin_display(&hwin); + wgetch(hwin.win.p); + wins_scrollwin_delete(&hwin); + break; + case KEY_RESIZE: + break; + default: + continue; + } - if (resize) - { - resize = 0; - wins_reset (); - } - else - { - wins_reinit_panels (); - wins_update_border (); - wins_update_panels (); - keys_display_bindings_bar (win[STA].p, binding, 0, binding_size); - wins_doupdate (); - } + if (resize) { + resize = 0; + wins_reset(); + } else { + wins_reinit_panels(); + wins_update_border(FLAG_ALL); + wins_update_panels(FLAG_ALL); + keys_display_bindings_bar(win[STA].p, bindings, bindings_size, 0, + bindings_size, NULL); + wins_doupdate(); } + } } -static void -set_confwin_attr (struct window *cwin) +static void set_confwin_attr(struct window *cwin) { - cwin->h = (notify_bar ())? row - 3 : row - 2; + cwin->h = (notify_bar())? row - 3 : row - 2; cwin->w = col; cwin->x = cwin->y = 0; } @@ -674,49 +356,45 @@ set_confwin_attr (struct window *cwin) * Create a configuration window and initialize status and notification bar * (useful in case of window resize). */ -void -custom_confwin_init (struct window *confwin, char *label) +void custom_confwin_init(struct window *confwin, const char *label) { - if (confwin->p) - { - erase_window_part (confwin->p, confwin->x, confwin->y, - confwin->x + confwin->w, confwin->y + confwin->h); - (void)delwin (confwin->p); - } - - wins_get_config (); - set_confwin_attr (confwin); - confwin->p = newwin (confwin->h, col, 0, 0); - box (confwin->p, 0, 0); - wins_show (confwin->p, label); - delwin (win[STA].p); - win[STA].p = newwin (win[STA].h, win[STA].w, win[STA].y, win[STA].x); - keypad (win[STA].p, TRUE); - if (notify_bar ()) - { - notify_reinit_bar (); - notify_update_bar (); - } + if (confwin->p) { + erase_window_part(confwin->p, confwin->x, confwin->y, + confwin->x + confwin->w, confwin->y + confwin->h); + delwin(confwin->p); + } + + wins_get_config(); + set_confwin_attr(confwin); + confwin->p = newwin(confwin->h, col, 0, 0); + box(confwin->p, 0, 0); + wins_show(confwin->p, label); + delwin(win[STA].p); + win[STA].p = newwin(win[STA].h, win[STA].w, win[STA].y, win[STA].x); + keypad(win[STA].p, TRUE); + if (notify_bar()) { + notify_reinit_bar(); + notify_update_bar(); + } } -static void -color_selection_bar (void) +static void color_selection_bar(void) { - struct binding quit = {_("Exit"), KEY_GENERIC_QUIT}; - struct binding select = {_("Select"), KEY_GENERIC_SELECT}; - struct binding nocolor = {_("No color"), KEY_GENERIC_CANCEL}; - struct binding up = {_("Up"), KEY_MOVE_UP}; - struct binding down = {_("Down"), KEY_MOVE_DOWN}; - struct binding left = {_("Left"), KEY_MOVE_LEFT}; - struct binding right = {_("Right"), KEY_MOVE_RIGHT}; - - - struct binding *binding[] = { + struct binding quit = { _("Exit"), KEY_GENERIC_QUIT }; + struct binding select = { _("Select"), KEY_GENERIC_SELECT }; + struct binding nocolor = { _("No color"), KEY_GENERIC_CANCEL }; + struct binding up = { _("Up"), KEY_MOVE_UP }; + struct binding down = { _("Down"), KEY_MOVE_DOWN }; + struct binding left = { _("Left"), KEY_MOVE_LEFT }; + struct binding right = { _("Right"), KEY_MOVE_RIGHT }; + + struct binding *bindings[] = { &quit, &nocolor, &up, &down, &left, &right, &select }; - int binding_size = sizeof (binding) / sizeof (binding[0]); + int bindings_size = sizeof(bindings) / sizeof(bindings[0]); - keys_display_bindings_bar (win[STA].p, binding, 0, binding_size); + keys_display_bindings_bar(win[STA].p, bindings, bindings_size, 0, + bindings_size, NULL); } /* @@ -724,8 +402,8 @@ color_selection_bar (void) * This is useful for window resizing. */ static void -display_color_config (struct window *cwin, int *mark_fore, int *mark_back, - int cursor, int theme_changed) +display_color_config(struct window *cwin, int *mark_fore, int *mark_back, + int cursor, int theme_changed) { #define SIZE (2 * (NBUSERCOLORS + 1)) #define DEFAULTCOLOR 255 @@ -733,21 +411,20 @@ display_color_config (struct window *cwin, int *mark_fore, int *mark_back, #define CURSOR (32 | A_REVERSE) #define MARK 88 - char *fore_txt = _("Foreground"); - char *back_txt = _("Background"); - char *default_txt = _("(terminal's default)"); - char *bar = " "; - char *box = "[ ]"; + const char *fore_txt = _("Foreground"); + const char *back_txt = _("Background"); + const char *default_txt = _("(terminal's default)"); + const char *bar = " "; + const char *box = "[ ]"; const unsigned Y = 3; const unsigned XOFST = 5; const unsigned YSPC = (cwin->h - 8) / (NBUSERCOLORS + 1); - const unsigned BARSIZ = strlen (bar); - const unsigned BOXSIZ = strlen (box); + const unsigned BARSIZ = strlen(bar); + const unsigned BOXSIZ = strlen(box); const unsigned XSPC = (cwin->w - 2 * BARSIZ - 2 * BOXSIZ - 6) / 3; const unsigned XFORE = XSPC; const unsigned XBACK = 2 * XSPC + BOXSIZ + XOFST + BARSIZ; - enum - { YPOS, XPOS, NBPOS }; + enum { YPOS, XPOS, NBPOS }; unsigned i; int pos[SIZE][NBPOS]; short colr_fore, colr_back; @@ -758,234 +435,168 @@ display_color_config (struct window *cwin, int *mark_fore, int *mark_back, COLR_MAGENTA, COLR_CYAN, COLR_DEFAULT }; - for (i = 0; i < NBUSERCOLORS + 1; i++) - { - pos[i][YPOS] = Y + YSPC * (i + 1); - pos[NBUSERCOLORS + i + 1][YPOS] = Y + YSPC * (i + 1); - pos[i][XPOS] = XFORE; - pos[NBUSERCOLORS + i + 1][XPOS] = XBACK; - } - - if (colorize) - { - if (theme_changed) - { - pair_content (colr[*mark_fore], &colr_fore, 0L); - if (colr_fore == 255) - colr_fore = -1; - pair_content (colr[*mark_back], &colr_back, 0L); - if (colr_back == 255) - colr_back = -1; - init_pair (COLR_CUSTOM, colr_fore, colr_back); - } + for (i = 0; i < NBUSERCOLORS + 1; i++) { + pos[i][YPOS] = Y + YSPC * (i + 1); + pos[NBUSERCOLORS + i + 1][YPOS] = Y + YSPC * (i + 1); + pos[i][XPOS] = XFORE; + pos[NBUSERCOLORS + i + 1][XPOS] = XBACK; + } + + if (colorize) { + if (theme_changed) { + pair_content(colr[*mark_fore], &colr_fore, 0L); + if (colr_fore == 255) + colr_fore = -1; + pair_content(colr[*mark_back], &colr_back, 0L); + if (colr_back == 255) + colr_back = -1; + init_pair(COLR_CUSTOM, colr_fore, colr_back); + } else { + /* Retrieve the actual color theme. */ + pair_content(COLR_CUSTOM, &colr_fore, &colr_back); + + if ((colr_fore == DEFAULTCOLOR) || (colr_fore == DEFAULTCOLOR_EXT)) + *mark_fore = NBUSERCOLORS; else - { - /* Retrieve the actual color theme. */ - pair_content (COLR_CUSTOM, &colr_fore, &colr_back); - - if ((colr_fore == DEFAULTCOLOR) || (colr_fore == DEFAULTCOLOR_EXT)) - *mark_fore = NBUSERCOLORS; - else - for (i = 0; i < NBUSERCOLORS + 1; i++) - if (colr_fore == colr[i]) - *mark_fore = i; + for (i = 0; i < NBUSERCOLORS + 1; i++) + if (colr_fore == colr[i]) + *mark_fore = i; - if ((colr_back == DEFAULTCOLOR) || (colr_back == DEFAULTCOLOR_EXT)) - *mark_back = SIZE - 1; - else - for (i = 0; i < NBUSERCOLORS + 1; i++) - if (colr_back == colr[NBUSERCOLORS + 1 + i]) - *mark_back = NBUSERCOLORS + 1 + i; - } + if ((colr_back == DEFAULTCOLOR) || (colr_back == DEFAULTCOLOR_EXT)) + *mark_back = SIZE - 1; + else + for (i = 0; i < NBUSERCOLORS + 1; i++) + if (colr_back == colr[NBUSERCOLORS + 1 + i]) + *mark_back = NBUSERCOLORS + 1 + i; } + } /* color boxes */ - for (i = 0; i < SIZE - 1; i++) - { - mvwprintw (cwin->p, pos[i][YPOS], pos[i][XPOS], box); - wattron (cwin->p, COLOR_PAIR (colr[i]) | A_REVERSE); - mvwprintw (cwin->p, pos[i][YPOS], pos[i][XPOS] + XOFST, bar); - wattroff (cwin->p, COLOR_PAIR (colr[i]) | A_REVERSE); - } + for (i = 0; i < SIZE - 1; i++) { + mvwprintw(cwin->p, pos[i][YPOS], pos[i][XPOS], box); + wattron(cwin->p, COLOR_PAIR(colr[i]) | A_REVERSE); + mvwprintw(cwin->p, pos[i][YPOS], pos[i][XPOS] + XOFST, bar); + wattroff(cwin->p, COLOR_PAIR(colr[i]) | A_REVERSE); + } /* Terminal's default color */ i = SIZE - 1; - mvwprintw (cwin->p, pos[i][YPOS], pos[i][XPOS], box); - wattron (cwin->p, COLOR_PAIR (colr[i])); - mvwprintw (cwin->p, pos[i][YPOS], pos[i][XPOS] + XOFST, bar); - wattroff (cwin->p, COLOR_PAIR (colr[i])); - mvwprintw (cwin->p, pos[NBUSERCOLORS][YPOS] + 1, - pos[NBUSERCOLORS][XPOS] + XOFST, default_txt); - mvwprintw (cwin->p, pos[SIZE - 1][YPOS] + 1, - pos[SIZE - 1][XPOS] + XOFST, default_txt); - - custom_apply_attr (cwin->p, ATTR_HIGHEST); - mvwprintw (cwin->p, Y, XFORE + XOFST, fore_txt); - mvwprintw (cwin->p, Y, XBACK + XOFST, back_txt); - custom_remove_attr (cwin->p, ATTR_HIGHEST); - - if (colorize) - { - mvwaddch (cwin->p, pos[*mark_fore][YPOS], - pos[*mark_fore][XPOS] + 1, MARK); - mvwaddch (cwin->p, pos[*mark_back][YPOS], - pos[*mark_back][XPOS] + 1, MARK); - } - - mvwaddch (cwin->p, pos[cursor][YPOS], pos[cursor][XPOS] + 1, CURSOR); - color_selection_bar (); - wnoutrefresh (win[STA].p); - wnoutrefresh (cwin->p); - wins_doupdate (); - if (notify_bar ()) - notify_update_bar (); + mvwprintw(cwin->p, pos[i][YPOS], pos[i][XPOS], box); + wattron(cwin->p, COLOR_PAIR(colr[i])); + mvwprintw(cwin->p, pos[i][YPOS], pos[i][XPOS] + XOFST, bar); + wattroff(cwin->p, COLOR_PAIR(colr[i])); + mvwprintw(cwin->p, pos[NBUSERCOLORS][YPOS] + 1, + pos[NBUSERCOLORS][XPOS] + XOFST, default_txt); + mvwprintw(cwin->p, pos[SIZE - 1][YPOS] + 1, + pos[SIZE - 1][XPOS] + XOFST, default_txt); + + custom_apply_attr(cwin->p, ATTR_HIGHEST); + mvwprintw(cwin->p, Y, XFORE + XOFST, fore_txt); + mvwprintw(cwin->p, Y, XBACK + XOFST, back_txt); + custom_remove_attr(cwin->p, ATTR_HIGHEST); + + if (colorize) { + mvwaddch(cwin->p, pos[*mark_fore][YPOS], pos[*mark_fore][XPOS] + 1, MARK); + mvwaddch(cwin->p, pos[*mark_back][YPOS], pos[*mark_back][XPOS] + 1, MARK); + } + + mvwaddch(cwin->p, pos[cursor][YPOS], pos[cursor][XPOS] + 1, CURSOR); + color_selection_bar(); + wnoutrefresh(win[STA].p); + wnoutrefresh(cwin->p); + wins_doupdate(); + if (notify_bar()) + notify_update_bar(); } /* Color theme configuration. */ -void -custom_color_config (void) +void custom_color_config(void) { struct window conf_win; int ch, cursor, need_reset, theme_changed; int mark_fore, mark_back; - char label[BUFSIZ]; + const char *label = _("color theme"); conf_win.p = 0; - (void)snprintf (label, BUFSIZ, _("color theme")); - custom_confwin_init (&conf_win, label); + custom_confwin_init(&conf_win, label); mark_fore = NBUSERCOLORS; mark_back = SIZE - 1; cursor = 0; theme_changed = 0; - display_color_config (&conf_win, &mark_fore, &mark_back, cursor, theme_changed); - clear (); - - while ((ch = keys_getch (win[STA].p)) != KEY_GENERIC_QUIT) - { - need_reset = 0; - theme_changed = 0; - - switch (ch) - { - case KEY_GENERIC_SELECT: - colorize = 1; - need_reset = 1; - theme_changed = 1; - if (cursor > NBUSERCOLORS) - mark_back = cursor; - else - mark_fore = cursor; - break; - - case KEY_MOVE_DOWN: - if (cursor < SIZE - 1) - ++cursor; - break; - - case KEY_MOVE_UP: - if (cursor > 0) - --cursor; - break; - - case KEY_MOVE_LEFT: - if (cursor > NBUSERCOLORS) - cursor -= (NBUSERCOLORS + 1); - break; - - case KEY_MOVE_RIGHT: - if (cursor <= NBUSERCOLORS) - cursor += (NBUSERCOLORS + 1); - break; - - case KEY_GENERIC_CANCEL: - colorize = 0; - need_reset = 1; - break; - } - - if (resize) - { - resize = 0; - endwin (); - wins_refresh (); - curs_set (0); - need_reset = 1; - } - - if (need_reset) - custom_confwin_init (&conf_win, label); - - display_color_config (&conf_win, &mark_fore, &mark_back, cursor, - theme_changed); + display_color_config(&conf_win, &mark_fore, &mark_back, cursor, + theme_changed); + clear(); + + while ((ch = keys_getch(win[STA].p, NULL)) != KEY_GENERIC_QUIT) { + need_reset = 0; + theme_changed = 0; + + switch (ch) { + case KEY_GENERIC_SELECT: + colorize = 1; + need_reset = 1; + theme_changed = 1; + if (cursor > NBUSERCOLORS) + mark_back = cursor; + else + mark_fore = cursor; + break; + + case KEY_MOVE_DOWN: + if (cursor < SIZE - 1) + ++cursor; + break; + + case KEY_MOVE_UP: + if (cursor > 0) + --cursor; + break; + + case KEY_MOVE_LEFT: + if (cursor > NBUSERCOLORS) + cursor -= (NBUSERCOLORS + 1); + break; + + case KEY_MOVE_RIGHT: + if (cursor <= NBUSERCOLORS) + cursor += (NBUSERCOLORS + 1); + break; + + case KEY_GENERIC_CANCEL: + colorize = 0; + need_reset = 1; + break; } - delwin (conf_win.p); -} -/* - * Return a string defining the color theme in the form: - * foreground color 'on' background color - * in order to dump this data in the configuration file. - * Color numbers follow the ncurses library definitions. - * If ncurses library was compiled with --enable-ext-funcs, - * then default color is -1. - */ -void -custom_color_theme_name (char *theme_name) -{ -#define MAXCOLORS 8 -#define NBCOLORS 2 -#define DEFAULTCOLOR 255 -#define DEFAULTCOLOR_EXT -1 + if (resize) { + resize = 0; + endwin(); + wins_refresh(); + curs_set(0); + need_reset = 1; + } - int i; - short color[NBCOLORS]; - char *color_name[NBCOLORS]; - char *default_color = "default"; - char *name[MAXCOLORS] = { - "black", - "red", - "green", - "yellow", - "blue", - "magenta", - "cyan", - "white" - }; + if (need_reset) + custom_confwin_init(&conf_win, label); - if (!colorize) - (void)snprintf (theme_name, BUFSIZ, "0"); - else - { - pair_content (COLR_CUSTOM, &color[0], &color[1]); - for (i = 0; i < NBCOLORS; i++) - { - if ((color[i] == DEFAULTCOLOR) || (color[i] == DEFAULTCOLOR_EXT)) - color_name[i] = default_color; - else if (color[i] >= 0 && color[i] <= MAXCOLORS) - color_name[i] = name[color[i]]; - else - { - EXIT (_("unknown color")); - /* NOTREACHED */ - } - } - (void)snprintf (theme_name, BUFSIZ, "%s on %s", color_name[0], - color_name[1]); - } + display_color_config(&conf_win, &mark_fore, &mark_back, cursor, + theme_changed); + } + delwin(conf_win.p); } /* Prints the general options. */ -static int -print_general_options (WINDOW *win, struct conf *conf) +static int print_general_options(WINDOW * win) { enum { AUTO_SAVE, + AUTO_GC, PERIODIC_SAVE, CONFIRM_QUIT, CONFIRM_DELETE, - SKIP_SYSTEM_DIAGS, - SKIP_PROGRESS_BAR, - WEEK_BEGINS_MONDAY, + SYSTEM_DIAGS, + PROGRESS_BAR, + FIRST_DAY_OF_WEEK, OUTPUT_DATE_FMT, INPUT_DATE_FMT, NB_OPTIONS @@ -994,93 +605,99 @@ print_general_options (WINDOW *win, struct conf *conf) const int YOFF = 3; int y; char *opt[NB_OPTIONS] = { - _("auto_save = "), - _("periodic_save = "), - _("confirm_quit = "), - _("confirm_delete = "), - _("skip_system_dialogs = "), - _("skip_progress_bar = "), - _("week_begins_on_monday = "), - _("output_datefmt = "), - _("input_datefmt = ") + _("general.autosave = "), + _("general.autogc = "), + _("general.periodicsave = "), + _("general.confirmquit = "), + _("general.confirmdelete = "), + _("general.systemdialogs = "), + _("general.progressbar = "), + _("general.firstdayofweek = "), + _("format.outputdate = "), + _("format.inputdate = ") }; y = 0; - mvwprintw (win, y, XPOS, "[1] %s ", opt[AUTO_SAVE]); - print_bool_option_incolor (win, conf->auto_save, y, - XPOS + 4 + strlen (opt[AUTO_SAVE])); - mvwprintw (win, y + 1, XPOS, - _("(if set to YES, automatic save is done when quitting)")); + mvwprintw(win, y, XPOS, "[1] %s ", opt[AUTO_SAVE]); + print_bool_option_incolor(win, conf.auto_save, y, + XPOS + 4 + strlen(opt[AUTO_SAVE])); + mvwprintw(win, y + 1, XPOS, + _("(if set to YES, automatic save is done when quitting)")); y += YOFF; - mvwprintw (win, y, XPOS, "[2] %s ", opt[PERIODIC_SAVE]); - custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, XPOS + 4 + strlen (opt[PERIODIC_SAVE]), "%d", - conf->periodic_save); - custom_remove_attr (win, ATTR_HIGHEST); - mvwprintw (win, y + 1, XPOS, - _("(if not null, automatically save data every 'periodic_save' " - "minutes)")); + mvwprintw(win, y, XPOS, "[2] %s ", opt[AUTO_GC]); + print_bool_option_incolor(win, conf.auto_gc, y, + XPOS + 4 + strlen(opt[AUTO_GC])); + mvwprintw(win, y + 1, XPOS, _("(run the garbage collector when quitting)")); y += YOFF; - mvwprintw (win, y, XPOS, "[3] %s ", opt[CONFIRM_QUIT]); - print_bool_option_incolor (win, conf->confirm_quit, y, - XPOS + 4 + strlen (opt[CONFIRM_QUIT])); - mvwprintw (win, y + 1, XPOS, - _("(if set to YES, confirmation is required before quitting)")); + mvwprintw(win, y, XPOS, "[3] %s ", opt[PERIODIC_SAVE]); + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, y, XPOS + 4 + strlen(opt[PERIODIC_SAVE]), "%d", + conf.periodic_save); + custom_remove_attr(win, ATTR_HIGHEST); + mvwprintw(win, y + 1, XPOS, + _("(if not null, automatically save data every 'periodic_save' " + "minutes)")); y += YOFF; - mvwprintw (win, y, XPOS, "[4] %s ", opt[CONFIRM_DELETE]); - print_bool_option_incolor (win, conf->confirm_delete, y, - XPOS + 4 + strlen (opt[CONFIRM_DELETE])); - mvwprintw (win, y + 1, XPOS, - _("(if set to YES, confirmation is required " - "before deleting an event)")); + mvwprintw(win, y, XPOS, "[4] %s ", opt[CONFIRM_QUIT]); + print_bool_option_incolor(win, conf.confirm_quit, y, + XPOS + 4 + strlen(opt[CONFIRM_QUIT])); + mvwprintw(win, y + 1, XPOS, + _("(if set to YES, confirmation is required before quitting)")); y += YOFF; - mvwprintw (win, y, XPOS, "[5] %s ", opt[SKIP_SYSTEM_DIAGS]); - print_bool_option_incolor (win, conf->skip_system_dialogs, y, - XPOS + 4 + strlen (opt[SKIP_SYSTEM_DIAGS])); - mvwprintw (win, y + 1, XPOS, - _("(if set to YES, messages about loaded " - "and saved data will not be displayed)")); + mvwprintw(win, y, XPOS, "[5] %s ", opt[CONFIRM_DELETE]); + print_bool_option_incolor(win, conf.confirm_delete, y, + XPOS + 4 + strlen(opt[CONFIRM_DELETE])); + mvwprintw(win, y + 1, XPOS, + _("(if set to YES, confirmation is required " + "before deleting an event)")); y += YOFF; - mvwprintw (win, y, XPOS, "[6] %s ", opt[SKIP_PROGRESS_BAR]); - print_bool_option_incolor (win, conf->skip_progress_bar, y, - XPOS + 4 + strlen (opt[SKIP_PROGRESS_BAR])); - mvwprintw (win, y + 1, XPOS, - _("(if set to YES, progress bar will not be displayed " - "when saving data)")); + mvwprintw(win, y, XPOS, "[6] %s ", opt[SYSTEM_DIAGS]); + print_bool_option_incolor(win, conf.system_dialogs, y, + XPOS + 4 + strlen(opt[SYSTEM_DIAGS])); + mvwprintw(win, y + 1, XPOS, + _("(if set to YES, messages about loaded " + "and saved data will be displayed)")); y += YOFF; - mvwprintw (win, y, XPOS, "[7] %s ", opt[WEEK_BEGINS_MONDAY]); - print_bool_option_incolor (win, calendar_week_begins_on_monday (), y, - XPOS + 4 + strlen (opt[WEEK_BEGINS_MONDAY])); - mvwprintw (win, y + 1, XPOS, - _("(if set to YES, monday is the first day of the week, " - "else it is sunday)")); + mvwprintw(win, y, XPOS, "[7] %s ", opt[PROGRESS_BAR]); + print_bool_option_incolor(win, conf.progress_bar, y, + XPOS + 4 + strlen(opt[PROGRESS_BAR])); + mvwprintw(win, y + 1, XPOS, + _("(if set to YES, progress bar will be displayed " + "when saving data)")); y += YOFF; - mvwprintw (win, y, XPOS, "[8] %s ", opt[OUTPUT_DATE_FMT]); - custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, XPOS + 4 + strlen (opt[OUTPUT_DATE_FMT]), "%s", - conf->output_datefmt); - custom_remove_attr (win, ATTR_HIGHEST); - mvwprintw (win, y + 1, XPOS, - _("(Format of the date to be displayed in non-interactive mode)")); + mvwprintw(win, y, XPOS, "[8] %s ", opt[FIRST_DAY_OF_WEEK]); + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, y, XPOS + 4 + strlen(opt[FIRST_DAY_OF_WEEK]), "%s", + calendar_week_begins_on_monday()? _("Monday") : _("Sunday")); + custom_remove_attr(win, ATTR_HIGHEST); + mvwprintw(win, y + 1, XPOS, + _("(specifies the first day of week in the calendar view)")); y += YOFF; - mvwprintw (win, y, XPOS, "[9] %s ", opt[INPUT_DATE_FMT]); - custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, XPOS + 4 + strlen (opt[INPUT_DATE_FMT]), "%d", - conf->input_datefmt); - custom_remove_attr (win, ATTR_HIGHEST); - mvwprintw (win, y + 1, XPOS, _("(Format to be used when entering a date: ")); - mvwprintw (win, y + 2, XPOS, - _(" (1)mm/dd/yyyy (2)dd/mm/yyyy (3)yyyy/mm/dd (4)yyyy-mm-dd)")); + mvwprintw(win, y, XPOS, "[9] %s ", opt[OUTPUT_DATE_FMT]); + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, y, XPOS + 4 + strlen(opt[OUTPUT_DATE_FMT]), "%s", + conf.output_datefmt); + custom_remove_attr(win, ATTR_HIGHEST); + mvwprintw(win, y + 1, XPOS, + _("(Format of the date to be displayed in non-interactive mode)")); + y += YOFF; + mvwprintw(win, y, XPOS, "[0] %s ", opt[INPUT_DATE_FMT]); + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, y, XPOS + 4 + strlen(opt[INPUT_DATE_FMT]), "%d", + conf.input_datefmt); + custom_remove_attr(win, ATTR_HIGHEST); + mvwprintw(win, y + 1, XPOS, _("(Format to be used when entering a date: ")); + mvwprintw(win, y + 2, XPOS, + _(" (1)mm/dd/yyyy (2)dd/mm/yyyy (3)yyyy/mm/dd (4)yyyy-mm-dd)")); return y + YOFF; } -void -custom_set_swsiz (struct scrollwin *sw) +void custom_set_swsiz(struct scrollwin *sw) { sw->win.x = 0; sw->win.y = 0; - sw->win.h = (notify_bar ()) ? row - 3 : row - 2; + sw->win.h = (notify_bar())? row - 3 : row - 2; sw->win.w = col; sw->pad.x = 1; @@ -1090,143 +707,132 @@ custom_set_swsiz (struct scrollwin *sw) } /* General configuration. */ -void -custom_general_config (struct conf *conf) +void custom_general_config(void) { struct scrollwin cwin; - char *number_str = - _("Enter an option number to change its value"); - char *keys = - _("(Press '^P' or '^N' to move up or down, 'Q' to quit)"); - char *output_datefmt_str = - _("Enter the date format (see 'man 3 strftime' for possible formats) "); - char *input_datefmt_str = - _("Enter the date format (1)mm/dd/yyyy (2)dd/mm/yyyy (3)yyyy/mm/dd " - "(4)yyyy-mm-dd"); - char *periodic_save_str = - _("Enter the delay, in minutes, between automatic saves (0 to disable) "); + const char *number_str = _("Enter an option number to change its value"); + const char *keys = _("(Press '^P' or '^N' to move up or down, 'Q' to quit)"); + const char *output_datefmt_str = + _("Enter the date format (see 'man 3 strftime' for possible formats) "); + const char *input_datefmt_str = + _("Enter the date format (1)mm/dd/yyyy (2)dd/mm/yyyy (3)yyyy/mm/dd " + "(4)yyyy-mm-dd"); + const char *periodic_save_str = + _("Enter the delay, in minutes, between automatic saves (0 to disable) "); int ch; char *buf; - clear (); - custom_set_swsiz (&cwin); - (void)snprintf (cwin.label, BUFSIZ, _("general options")); - wins_scrollwin_init (&cwin); - wins_show (cwin.win.p, cwin.label); - status_mesg (number_str, keys); - cwin.total_lines = print_general_options (cwin.pad.p, conf); - wins_scrollwin_display (&cwin); - - buf = mem_malloc (BUFSIZ); - while ((ch = wgetch (win[STA].p)) != 'q') - { - buf[0] = '\0'; - - switch (ch) - { - case CTRL ('N'): - wins_scrollwin_down (&cwin, 1); - break; - case CTRL ('P'): - wins_scrollwin_up (&cwin, 1); - break; - case '1': - conf->auto_save = !conf->auto_save; - break; - case '2': - status_mesg (periodic_save_str, ""); - if (updatestring (win[STA].p, &buf, 0, 1) == 0) - { - int val = atoi (buf); - if (val >= 0) - conf->periodic_save = val; - if (conf->periodic_save > 0) - io_start_psave_thread (conf); - else if (conf->periodic_save == 0) - io_stop_psave_thread (); - } - status_mesg (number_str, keys); - break; - case '3': - conf->confirm_quit = !conf->confirm_quit; - break; - case '4': - conf->confirm_delete = !conf->confirm_delete; - break; - case '5': - conf->skip_system_dialogs = !conf->skip_system_dialogs; - break; - case '6': - conf->skip_progress_bar = !conf->skip_progress_bar; - break; - case '7': - calendar_change_first_day_of_week (); - break; - case '8': - status_mesg (output_datefmt_str, ""); - (void)strncpy (buf, conf->output_datefmt, - strlen (conf->output_datefmt) + 1); - if (updatestring (win[STA].p, &buf, 0, 1) == 0) - { - (void)strncpy (conf->output_datefmt, buf, strlen (buf) + 1); - } - status_mesg (number_str, keys); - break; - case '9': - status_mesg (input_datefmt_str, ""); - if (updatestring (win[STA].p, &buf, 0, 1) == 0) - { - int val = atoi (buf); - if (val > 0 && val <= DATE_FORMATS) - conf->input_datefmt = val; - } - status_mesg (number_str, keys); - break; - } - - if (resize) - { - resize = 0; - wins_reset (); - wins_scrollwin_delete (&cwin); - custom_set_swsiz (&cwin); - wins_scrollwin_init (&cwin); - wins_show (cwin.win.p, cwin.label); - cwin.first_visible_line = 0; - delwin (win[STA].p); - win[STA].p = newwin (win[STA].h, win[STA].w, win[STA].y, - win[STA].x); - keypad (win[STA].p, TRUE); - if (notify_bar ()) - { - notify_reinit_bar (); - notify_update_bar (); - } - } + clear(); + custom_set_swsiz(&cwin); + cwin.label = _("general options"); + wins_scrollwin_init(&cwin); + wins_show(cwin.win.p, cwin.label); + status_mesg(number_str, keys); + cwin.total_lines = print_general_options(cwin.pad.p); + wins_scrollwin_display(&cwin); + + buf = mem_malloc(BUFSIZ); + while ((ch = wgetch(win[STA].p)) != 'q') { + buf[0] = '\0'; + + switch (ch) { + case CTRL('N'): + wins_scrollwin_down(&cwin, 1); + break; + case CTRL('P'): + wins_scrollwin_up(&cwin, 1); + break; + case '1': + conf.auto_save = !conf.auto_save; + break; + case '2': + conf.auto_gc = !conf.auto_gc; + break; + case '3': + status_mesg(periodic_save_str, ""); + if (updatestring(win[STA].p, &buf, 0, 1) == 0) { + int val = atoi(buf); + if (val >= 0) + conf.periodic_save = val; + if (conf.periodic_save > 0) + io_start_psave_thread(); + else if (conf.periodic_save == 0) + io_stop_psave_thread(); + } + status_mesg(number_str, keys); + break; + case '4': + conf.confirm_quit = !conf.confirm_quit; + break; + case '5': + conf.confirm_delete = !conf.confirm_delete; + break; + case '6': + conf.system_dialogs = !conf.system_dialogs; + break; + case '7': + conf.progress_bar = !conf.progress_bar; + break; + case '8': + calendar_change_first_day_of_week(); + break; + case '9': + status_mesg(output_datefmt_str, ""); + strncpy(buf, conf.output_datefmt, strlen(conf.output_datefmt) + 1); + if (updatestring(win[STA].p, &buf, 0, 1) == 0) { + strncpy(conf.output_datefmt, buf, strlen(buf) + 1); + } + status_mesg(number_str, keys); + break; + case '0': + status_mesg(input_datefmt_str, ""); + if (updatestring(win[STA].p, &buf, 0, 1) == 0) { + int val = atoi(buf); + if (val > 0 && val <= DATE_FORMATS) + conf.input_datefmt = val; + } + status_mesg(number_str, keys); + break; + } - status_mesg (number_str, keys); - cwin.total_lines = print_general_options (cwin.pad.p, conf); - wins_scrollwin_display (&cwin); + if (resize) { + resize = 0; + wins_reset(); + wins_scrollwin_delete(&cwin); + custom_set_swsiz(&cwin); + wins_scrollwin_init(&cwin); + wins_show(cwin.win.p, cwin.label); + cwin.first_visible_line = 0; + delwin(win[STA].p); + win[STA].p = newwin(win[STA].h, win[STA].w, win[STA].y, win[STA].x); + keypad(win[STA].p, TRUE); + if (notify_bar()) { + notify_reinit_bar(); + notify_update_bar(); + } } - mem_free (buf); - wins_scrollwin_delete (&cwin); -} + status_mesg(number_str, keys); + cwin.total_lines = print_general_options(cwin.pad.p); + wins_scrollwin_display(&cwin); + } + mem_free(buf); + wins_scrollwin_delete(&cwin); +} static void -print_key_incolor (WINDOW *win, char *option, int pos_y, int pos_x) +print_key_incolor(WINDOW * win, const char *option, int pos_y, int pos_x) { const int color = ATTR_HIGHEST; - RETURN_IF (!option, _("Undefined option!")); - custom_apply_attr (win, color); - mvwprintw (win, pos_y, pos_x, "%s ", option); - custom_remove_attr (win, color); - wnoutrefresh (win); + RETURN_IF(!option, _("Undefined option!")); + custom_apply_attr(win, color); + mvwprintw(win, pos_y, pos_x, "%s ", option); + custom_remove_attr(win, color); } static int -print_keys_bindings (WINDOW *win, int selected_row, int selected_elm, int yoff) +print_keys_bindings(WINDOW * win, int selected_row, int selected_elm, int yoff) { const int XPOS = 1; const int EQUALPOS = 23; @@ -1234,208 +840,242 @@ print_keys_bindings (WINDOW *win, int selected_row, int selected_elm, int yoff) int noelm, action, y; noelm = y = 0; - for (action = 0; action < NBKEYS; action++) - { - char actionstr[BUFSIZ]; - int nbkeys; - - nbkeys = keys_action_count_keys (action); - (void)snprintf (actionstr, BUFSIZ, "%s", keys_get_label (action)); - if (action == selected_row) - custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, XPOS, "%s ", actionstr); - mvwprintw (win, y, EQUALPOS, "="); - if (nbkeys == 0) - mvwprintw (win, y, KEYPOS, _("undefined")); - if (action == selected_row) - custom_remove_attr (win, ATTR_HIGHEST); - if (nbkeys > 0) - { - if (action == selected_row) - { - char *key; - int pos; - - pos = KEYPOS; - while ((key = keys_action_nkey (action, noelm)) != NULL) - { - if (noelm == selected_elm) - print_key_incolor (win, key, y, pos); - else - mvwprintw (win, y, pos, "%s ", key); - noelm++; - pos += strlen (key) + 1; - } - } + for (action = 0; action < NBKEYS; action++) { + char actionstr[BUFSIZ]; + int nbkeys; + + nbkeys = keys_action_count_keys(action); + snprintf(actionstr, BUFSIZ, "%s", keys_get_label(action)); + if (action == selected_row) + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, y, XPOS, "%s ", actionstr); + mvwprintw(win, y, EQUALPOS, "="); + if (nbkeys == 0) + mvwprintw(win, y, KEYPOS, _("undefined")); + if (action == selected_row) + custom_remove_attr(win, ATTR_HIGHEST); + if (nbkeys > 0) { + if (action == selected_row) { + const char *key; + int pos; + + pos = KEYPOS; + while ((key = keys_action_nkey(action, noelm)) != NULL) { + if (noelm == selected_elm) + print_key_incolor(win, key, y, pos); else - { - mvwprintw (win, y, KEYPOS, "%s", keys_action_allkeys (action)); - } + mvwprintw(win, y, pos, "%s ", key); + noelm++; + pos += strlen(key) + 1; } - y += yoff; + } else { + mvwprintw(win, y, KEYPOS, "%s", keys_action_allkeys(action)); + } } + y += yoff; + } return noelm; } -static void -custom_keys_config_bar (void) +static void custom_keys_config_bar(void) { - struct binding quit = {_("Exit"), KEY_GENERIC_QUIT}; - struct binding info = {_("Key info"), KEY_GENERIC_HELP}; - struct binding add = {_("Add key"), KEY_ADD_ITEM}; - struct binding del = {_("Del key"), KEY_DEL_ITEM}; - struct binding up = {_("Up"), KEY_MOVE_UP}; - struct binding down = {_("Down"), KEY_MOVE_DOWN}; - struct binding left = {_("Prev Key"), KEY_MOVE_LEFT}; - struct binding right = {_("Next Key"), KEY_MOVE_RIGHT}; - - struct binding *binding[] = { + struct binding quit = { _("Exit"), KEY_GENERIC_QUIT }; + struct binding info = { _("Key info"), KEY_GENERIC_HELP }; + struct binding add = { _("Add key"), KEY_ADD_ITEM }; + struct binding del = { _("Del key"), KEY_DEL_ITEM }; + struct binding up = { _("Up"), KEY_MOVE_UP }; + struct binding down = { _("Down"), KEY_MOVE_DOWN }; + struct binding left = { _("Prev Key"), KEY_MOVE_LEFT }; + struct binding right = { _("Next Key"), KEY_MOVE_RIGHT }; + + struct binding *bindings[] = { &quit, &info, &add, &del, &up, &down, &left, &right }; - int binding_size = sizeof (binding) / sizeof (binding[0]); + int bindings_size = sizeof(bindings) / sizeof(bindings[0]); - keys_display_bindings_bar (win[STA].p, binding, 0, binding_size); + keys_display_bindings_bar(win[STA].p, bindings, bindings_size, 0, + bindings_size, NULL); } -void -custom_keys_config (void) +void custom_keys_config(void) { struct scrollwin kwin; int selrow, selelm, firstrow, lastrow, nbrowelm, nbdisplayed; int keyval, used, not_recognized; - char *keystr; + const char *keystr; WINDOW *grabwin; const int LINESPERKEY = 2; const int LABELLINES = 3; - clear (); - custom_set_swsiz (&kwin); + clear(); + custom_set_swsiz(&kwin); nbdisplayed = (kwin.win.h - LABELLINES) / LINESPERKEY; - (void)snprintf (kwin.label, BUFSIZ, _("keys configuration")); - wins_scrollwin_init (&kwin); - wins_show (kwin.win.p, kwin.label); - custom_keys_config_bar (); + kwin.label = _("keys configuration"); + wins_scrollwin_init(&kwin); + wins_show(kwin.win.p, kwin.label); + custom_keys_config_bar(); selrow = selelm = 0; - nbrowelm = print_keys_bindings (kwin.pad.p, selrow, selelm, LINESPERKEY); + nbrowelm = print_keys_bindings(kwin.pad.p, selrow, selelm, LINESPERKEY); kwin.total_lines = NBKEYS * LINESPERKEY; - wins_scrollwin_display (&kwin); + wins_scrollwin_display(&kwin); firstrow = 0; lastrow = firstrow + nbdisplayed - 1; - for (;;) - { - int ch; - - ch = keys_getch (win[STA].p); - switch (ch) - { - case KEY_MOVE_UP: - if (selrow > 0) - { - selrow--; - selelm = 0; - if (selrow == firstrow) - { - firstrow--; - lastrow--; - wins_scrollwin_up (&kwin, LINESPERKEY); - } - } - break; - case KEY_MOVE_DOWN: - if (selrow < NBKEYS - 1) - { - selrow++; - selelm = 0; - if (selrow == lastrow) - { - firstrow++; - lastrow++; - wins_scrollwin_down (&kwin, LINESPERKEY); - } - } - break; - case KEY_MOVE_LEFT: - if (selelm > 0) - selelm--; - break; - case KEY_MOVE_RIGHT: - if (selelm < nbrowelm - 1) - selelm++; - break; - case KEY_GENERIC_HELP: - keys_popup_info (selrow); - break; - case KEY_ADD_ITEM: + for (;;) { + int ch; + + ch = keys_getch(win[STA].p, NULL); + switch (ch) { + case KEY_MOVE_UP: + if (selrow > 0) { + selrow--; + selelm = 0; + if (selrow == firstrow) { + firstrow--; + lastrow--; + wins_scrollwin_up(&kwin, LINESPERKEY); + } + } + break; + case KEY_MOVE_DOWN: + if (selrow < NBKEYS - 1) { + selrow++; + selelm = 0; + if (selrow == lastrow) { + firstrow++; + lastrow++; + wins_scrollwin_down(&kwin, LINESPERKEY); + } + } + break; + case KEY_MOVE_LEFT: + if (selelm > 0) + selelm--; + break; + case KEY_MOVE_RIGHT: + if (selelm < nbrowelm - 1) + selelm++; + break; + case KEY_GENERIC_HELP: + keys_popup_info(selrow); + break; + case KEY_ADD_ITEM: #define WINROW 10 #define WINCOL 50 - do - { - used = 0; - grabwin = popup (WINROW, WINCOL, (row - WINROW) / 2, - (col - WINCOL) / 2, - _("Press the key you want to assign to:"), - keys_get_label (selrow), 0); - keyval = wgetch (grabwin); - - /* First check if this key would be recognized by calcurse. */ - if (keys_str2int (keys_int2str (keyval)) == -1) - { - not_recognized = 1; - WARN_MSG (_("This key is not yet recognized by calcurse, " - "please choose another one.")); - werase (kwin.pad.p); - nbrowelm = print_keys_bindings (kwin.pad.p, selrow, selelm, - LINESPERKEY); - wins_scrollwin_display (&kwin); - continue; - } - else - not_recognized = 0; - - used = keys_assign_binding (keyval, selrow); - if (used) - { - enum key action; - - action = keys_get_action (keyval); - WARN_MSG (_("This key is already in use for %s, " - "please choose another one."), - keys_get_label (action)); - werase (kwin.pad.p); - nbrowelm = print_keys_bindings (kwin.pad.p, selrow, selelm, - LINESPERKEY); - wins_scrollwin_display (&kwin); - } - delwin (grabwin); - } - while (used || not_recognized); - nbrowelm++; - if (selelm < nbrowelm - 1) - selelm++; + do { + used = 0; + grabwin = popup(WINROW, WINCOL, (row - WINROW) / 2, + (col - WINCOL) / 2, + _("Press the key you want to assign to:"), + keys_get_label(selrow), 0); + keyval = wgetch(grabwin); + + /* First check if this key would be recognized by calcurse. */ + if (keys_str2int(keys_int2str(keyval)) == -1) { + not_recognized = 1; + WARN_MSG(_("This key is not yet recognized by calcurse, " + "please choose another one.")); + werase(kwin.pad.p); + nbrowelm = print_keys_bindings(kwin.pad.p, selrow, selelm, + LINESPERKEY); + wins_scrollwin_display(&kwin); + continue; + } else + not_recognized = 0; + + used = keys_assign_binding(keyval, selrow); + if (used) { + enum key action; + + action = keys_get_action(keyval); + WARN_MSG(_("This key is already in use for %s, " + "please choose another one."), keys_get_label(action)); + werase(kwin.pad.p); + nbrowelm = print_keys_bindings(kwin.pad.p, selrow, selelm, + LINESPERKEY); + wins_scrollwin_display(&kwin); + } + delwin(grabwin); + } + while (used || not_recognized); + nbrowelm++; + if (selelm < nbrowelm - 1) + selelm++; #undef WINROW #undef WINCOL - break; - case KEY_DEL_ITEM: - keystr = keys_action_nkey (selrow, selelm); - keyval = keys_str2int (keystr); - keys_remove_binding (keyval, selrow); - nbrowelm--; - if (selelm > 0 && selelm <= nbrowelm) - selelm--; - break; - case KEY_GENERIC_QUIT: - if (keys_check_missing_bindings () != 0) - { - WARN_MSG (_("Some actions do not have any associated " - "key bindings!")); - } - wins_scrollwin_delete (&kwin); - return; - } - custom_keys_config_bar (); - werase (kwin.pad.p); - nbrowelm = print_keys_bindings (kwin.pad.p, selrow, selelm, LINESPERKEY); - wins_scrollwin_display (&kwin); + break; + case KEY_DEL_ITEM: + keystr = keys_action_nkey(selrow, selelm); + keyval = keys_str2int(keystr); + keys_remove_binding(keyval, selrow); + nbrowelm--; + if (selelm > 0 && selelm <= nbrowelm) + selelm--; + break; + case KEY_GENERIC_QUIT: + if (keys_check_missing_bindings() != 0) { + WARN_MSG(_("Some actions do not have any associated " "key bindings!")); + } + wins_scrollwin_delete(&kwin); + return; + } + custom_keys_config_bar(); + werase(kwin.pad.p); + nbrowelm = print_keys_bindings(kwin.pad.p, selrow, selelm, LINESPERKEY); + wins_scrollwin_display(&kwin); + } +} + +void custom_config_main(void) +{ + const char *no_color_support = + _("Sorry, colors are not supported by your terminal\n" + "(Press [ENTER] to continue)"); + int ch; + int old_layout; + + custom_config_bar(); + while ((ch = wgetch(win[STA].p)) != 'q') { + switch (ch) { + case 'C': + case 'c': + if (has_colors()) + custom_color_config(); + else { + colorize = 0; + wins_erase_status_bar(); + mvwprintw(win[STA].p, 0, 0, _(no_color_support)); + wgetch(win[STA].p); + } + break; + case 'L': + case 'l': + old_layout = wins_layout(); + custom_layout_config(); + if (wins_layout() != old_layout) + wins_reset(); + break; + case 'G': + case 'g': + custom_general_config(); + break; + case 'N': + case 'n': + notify_config_bar(); + break; + case 'K': + case 'k': + custom_keys_config(); + break; + case 's': + case 'S': + custom_sidebar_config(); + break; + default: + continue; } + wins_update(FLAG_ALL); + wins_erase_status_bar(); + custom_config_bar(); + } } @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,26 +43,24 @@ #include "calcurse.h" struct day_saved_item { - char start[BUFSIZ]; - char end[BUFSIZ]; - char state; - char type; + char start[BUFSIZ]; + char end[BUFSIZ]; + char state; + char type; char *mesg; }; -static llist_t day_items; -static struct day_saved_item day_saved_item; +static llist_t day_items; +static struct day_saved_item day_saved_item; -static void -day_free (struct day_item *day) +static void day_free(struct day_item *day) { - mem_free (day); + mem_free(day); } -static void -day_init_list (void) +static void day_init_list(void) { - LLIST_INIT (&day_items); + LLIST_INIT(&day_items); } /* @@ -70,20 +68,19 @@ day_init_list (void) * Must not free associated message and note, because their are not dynamically * allocated (only pointers to real objects are stored in this structure). */ -void -day_free_list (void) +void day_free_list(void) { - LLIST_FREE_INNER (&day_items, day_free); - LLIST_FREE (&day_items); + LLIST_FREE_INNER(&day_items, day_free); + LLIST_FREE(&day_items); } /* Add an event in the current day list */ -static struct day_item * -day_add_event (int type, char *mesg, char *note, long nday, int id) +static struct day_item *day_add_event(int type, char *mesg, char *note, + long nday, int id) { struct day_item *day; - day = mem_malloc (sizeof (struct day_item)); + day = mem_malloc(sizeof(struct day_item)); day->mesg = mesg; day->note = note; day->type = type; @@ -92,35 +89,32 @@ day_add_event (int type, char *mesg, char *note, long nday, int id) day->start = nday; day->evnt_id = id; - LLIST_ADD (&day_items, day); + LLIST_ADD(&day_items, day); return day; } -static int -day_cmp_start (struct day_item *a, struct day_item *b) +static int day_cmp_start(struct day_item *a, struct day_item *b) { - if (a->type <= EVNT) - { - if (b->type <= EVNT) - return 0; - else - return -1; - } - else if (b->type <= EVNT) + if (a->type <= EVNT) { + if (b->type <= EVNT) + return 0; + else + return -1; + } else if (b->type <= EVNT) return 1; else - return (a->start < b->start ? -1 : (a->start == b->start ? 0 : 1)); + return a->start < b->start ? -1 : (a->start == b->start ? 0 : 1); } /* Add an appointment in the current day list. */ -static struct day_item * -day_add_apoint (int type, char *mesg, char *note, long start, long dur, - char state, int real_pos) +static struct day_item *day_add_apoint(int type, char *mesg, char *note, + long start, long dur, char state, + int real_pos) { struct day_item *day; - day = mem_malloc (sizeof (struct day_item)); + day = mem_malloc(sizeof(struct day_item)); day->mesg = mesg; day->note = note; day->start = start; @@ -130,7 +124,7 @@ day_add_apoint (int type, char *mesg, char *note, long start, long dur, day->type = type; day->evnt_id = 0; - LLIST_ADD_SORTED (&day_items, day, day_cmp_start); + LLIST_ADD_SORTED(&day_items, day, day_cmp_start); return day; } @@ -142,18 +136,16 @@ day_add_apoint (int type, char *mesg, char *note, long start, long dur, * dedicated to the selected day. * Returns the number of events for the selected day. */ -static int -day_store_events (long date) +static int day_store_events(long date) { llist_item_t *i; int e_nb = 0; - LLIST_FIND_FOREACH (&eventlist, date, event_inday, i) - { - struct event *ev = LLIST_TS_GET_DATA (i); - (void)day_add_event (EVNT, ev->mesg, ev->note, ev->day, ev->id); - e_nb++; - } + LLIST_FIND_FOREACH_CONT(&eventlist, date, event_inday, i) { + struct event *ev = LLIST_TS_GET_DATA(i); + day_add_event(EVNT, ev->mesg, ev->note, ev->day, ev->id); + e_nb++; + } return e_nb; } @@ -165,19 +157,16 @@ day_store_events (long date) * dedicated to the selected day. * Returns the number of recurrent events for the selected day. */ -static int -day_store_recur_events (long date) +static int day_store_recur_events(long date) { llist_item_t *i; int e_nb = 0; - LLIST_FIND_FOREACH (&recur_elist, date, recur_event_inday, i) - { - struct recur_event *rev = LLIST_TS_GET_DATA (i); - (void)day_add_event (RECUR_EVNT, rev->mesg, rev->note, rev->day, - rev->id); - e_nb++; - } + LLIST_FIND_FOREACH(&recur_elist, date, recur_event_inday, i) { + struct recur_event *rev = LLIST_TS_GET_DATA(i); + day_add_event(RECUR_EVNT, rev->mesg, rev->note, rev->day, rev->id); + e_nb++; + } return e_nb; } @@ -189,21 +178,23 @@ day_store_recur_events (long date) * structure dedicated to the selected day. * Returns the number of appointments for the selected day. */ -static int -day_store_apoints (long date) +static int day_store_apoints(long date) { llist_item_t *i; int a_nb = 0; - LLIST_TS_LOCK (&alist_p); - LLIST_TS_FIND_FOREACH (&alist_p, date, apoint_inday, i) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - (void)day_add_apoint (APPT, apt->mesg, apt->note, apt->start, apt->dur, - apt->state, 0); - a_nb++; - } - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_LOCK(&alist_p); + LLIST_TS_FIND_FOREACH(&alist_p, date, apoint_inday, i) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + + if (apt->start >= date + DAYINSEC) + break; + + day_add_apoint(APPT, apt->mesg, apt->note, apt->start, apt->dur, + apt->state, 0); + a_nb++; + } + LLIST_TS_UNLOCK(&alist_p); return a_nb; } @@ -215,22 +206,22 @@ day_store_apoints (long date) * structure dedicated to the selected day. * Returns the number of recurrent appointments for the selected day. */ -static int -day_store_recur_apoints (long date) +static int day_store_recur_apoints(long date) { llist_item_t *i; int a_nb = 0; - LLIST_TS_LOCK (&recur_alist_p); - LLIST_TS_FIND_FOREACH (&recur_alist_p, date, recur_apoint_inday, i) - { - struct recur_apoint *rapt = LLIST_TS_GET_DATA (i); - int real_start = recur_apoint_inday (rapt, date); - (void)day_add_apoint (RECUR_APPT, rapt->mesg, rapt->note, real_start, - rapt->dur, rapt->state, a_nb); + LLIST_TS_LOCK(&recur_alist_p); + LLIST_TS_FIND_FOREACH(&recur_alist_p, date, recur_apoint_inday, i) { + struct recur_apoint *rapt = LLIST_TS_GET_DATA(i); + unsigned real_start; + if (recur_apoint_find_occurrence(rapt, date, &real_start)) { + day_add_apoint(RECUR_APPT, rapt->mesg, rapt->note, real_start, + rapt->dur, rapt->state, a_nb); a_nb++; } - LLIST_TS_UNLOCK (&recur_alist_p); + } + LLIST_TS_UNLOCK(&recur_alist_p); return a_nb; } @@ -244,19 +235,19 @@ day_store_recur_apoints (long date) * The number of events and appointments in the current day are also updated. */ static int -day_store_items (long date, unsigned *pnb_events, unsigned *pnb_apoints) +day_store_items(long date, unsigned *pnb_events, unsigned *pnb_apoints) { int pad_length; int nb_events, nb_recur_events; int nb_apoints, nb_recur_apoints; - day_free_list (); - day_init_list (); - nb_recur_events = day_store_recur_events (date); - nb_events = day_store_events (date); + day_free_list(); + day_init_list(); + nb_recur_events = day_store_recur_events(date); + nb_events = day_store_events(date); *pnb_events = nb_events; - nb_recur_apoints = day_store_recur_apoints (date); - nb_apoints = day_store_apoints (date); + nb_recur_apoints = day_store_recur_apoints(date); + nb_apoints = day_store_apoints(date); *pnb_apoints = nb_apoints; pad_length = (nb_recur_events + nb_events + 1 + 3 * (nb_recur_apoints + nb_apoints)); @@ -271,9 +262,9 @@ day_store_items (long date, unsigned *pnb_events, unsigned *pnb_apoints) * those items in a pad. If selected day is null, then store items for current * day. This is useful to speed up the appointment panel update. */ -struct day_items_nb * -day_process_storage (struct date *slctd_date, unsigned day_changed, - struct day_items_nb *inday) +struct day_items_nb *day_process_storage(struct date *slctd_date, + unsigned day_changed, + struct day_items_nb *inday) { long date; struct date day; @@ -281,21 +272,21 @@ day_process_storage (struct date *slctd_date, unsigned day_changed, if (slctd_date) day = *slctd_date; else - calendar_store_current_date (&day); + calendar_store_current_date(&day); - date = date2sec (day, 0, 0); + date = date2sec(day, 0, 0); /* Inits */ if (apad.length != 0) - delwin (apad.ptrwin); + delwin(apad.ptrwin); /* Store the events and appointments (recursive and normal items). */ - apad.length = day_store_items (date, &inday->nb_events, &inday->nb_apoints); + apad.length = day_store_items(date, &inday->nb_events, &inday->nb_apoints); /* Create the new pad with its new length. */ if (day_changed) apad.first_onscreen = 0; - apad.ptrwin = newpad (apad.length, apad.width); + apad.ptrwin = newpad(apad.length, apad.width); return inday; } @@ -304,8 +295,7 @@ day_process_storage (struct date *slctd_date, unsigned day_changed, * Returns a structure of type apoint_llist_node_t given a structure of type * day_item_s */ -static void -day_item_s2apoint_s (struct apoint *a, struct day_item *p) +static void day_item_s2apoint_s(struct apoint *a, struct day_item *p) { a->state = p->state; a->start = p->start; @@ -317,61 +307,65 @@ day_item_s2apoint_s (struct apoint *a, struct day_item *p) * Print an item date in the appointment panel. */ static void -display_item_date (int incolor, struct apoint *i, int type, long date, - int y, int x) +display_item_date(int incolor, struct apoint *i, int type, long date, + int y, int x) { WINDOW *win; char a_st[100], a_end[100]; - int recur = 0; win = apad.ptrwin; - apoint_sec2str (i, type, date, a_st, a_end); - if (type == RECUR_EVNT || type == RECUR_APPT) - recur = 1; + apoint_sec2str(i, date, a_st, a_end); if (incolor == 0) - custom_apply_attr (win, ATTR_HIGHEST); - if (recur) + custom_apply_attr(win, ATTR_HIGHEST); + if (type == RECUR_EVNT || type == RECUR_APPT) if (i->state & APOINT_NOTIFY) - mvwprintw (win, y, x, " *!%s -> %s", a_st, a_end); + mvwprintw(win, y, x, " *!%s -> %s", a_st, a_end); else - mvwprintw (win, y, x, " * %s -> %s", a_st, a_end); + mvwprintw(win, y, x, " * %s -> %s", a_st, a_end); else if (i->state & APOINT_NOTIFY) - mvwprintw (win, y, x, " -!%s -> %s", a_st, a_end); + mvwprintw(win, y, x, " -!%s -> %s", a_st, a_end); else - mvwprintw (win, y, x, " - %s -> %s", a_st, a_end); + mvwprintw(win, y, x, " - %s -> %s", a_st, a_end); if (incolor == 0) - custom_remove_attr (win, ATTR_HIGHEST); + custom_remove_attr(win, ATTR_HIGHEST); } /* * Print an item description in the corresponding panel window. */ static void -display_item (int incolor, char *msg, int recur, int note, int len, int y, - int x) +display_item(int incolor, char *msg, int recur, int note, int width, int y, + int x) { WINDOW *win; int ch_recur, ch_note; - char buf[len]; + char buf[width * UTF8_MAXLEN]; + int i; - if (len <= 0) + if (width <= 0) return; win = apad.ptrwin; ch_recur = (recur) ? '*' : ' '; ch_note = (note) ? '>' : ' '; if (incolor == 0) - custom_apply_attr (win, ATTR_HIGHEST); - if (strlen (msg) < len) - mvwprintw (win, y, x, " %c%c%s", ch_recur, ch_note, msg); - else - { - (void)strncpy (buf, msg, len - 1); - buf[len - 1] = '\0'; - mvwprintw (win, y, x, " %c%c%s...", ch_recur, ch_note, buf); + custom_apply_attr(win, ATTR_HIGHEST); + if (utf8_strwidth(msg) < width) + mvwprintw(win, y, x, " %c%c%s", ch_recur, ch_note, msg); + else { + for (i = 0; msg[i] && width > 0; i++) { + if (!UTF8_ISCONT(msg[i])) + width -= utf8_width(&msg[i]); + buf[i] = msg[i]; } + if (i) + buf[i - 1] = 0; + else + buf[0] = 0; + mvwprintw(win, y, x, " %c%c%s...", ch_recur, ch_note, buf); + } if (incolor == 0) - custom_remove_attr (win, ATTR_HIGHEST); + custom_remove_attr(win, ATTR_HIGHEST); } /* @@ -381,8 +375,7 @@ display_item (int incolor, char *msg, int recur, int note, int len, int y, * structure (pointed by day_saved_item), to be later displayed in a * popup window if requested. */ -void -day_write_pad (long date, int width, int length, int incolor) +void day_write_pad(long date, int width, int length, int incolor) { llist_item_t *i; struct apoint a; @@ -392,67 +385,57 @@ day_write_pad (long date, int width, int length, int incolor) line = item_number = 0; - LLIST_FOREACH (&day_items, i) - { - struct day_item *day = LLIST_TS_GET_DATA (i); - if (day->type == RECUR_EVNT || day->type == RECUR_APPT) - recur = 1; - else - recur = 0; - /* First print the events for current day. */ - if (day->type < RECUR_APPT) - { - item_number++; - if (item_number - incolor == 0) - { - day_saved_item.type = day->type; - day_saved_item.mesg = day->mesg; - } - display_item (item_number - incolor, day->mesg, recur, - (day->note != NULL) ? 1 : 0, width - 7, line, x_pos); - line++; - draw_line = 1; - } - else - { - /* Draw a line between events and appointments. */ - if (line > 0 && draw_line) - { - wmove (apad.ptrwin, line, 0); - whline (apad.ptrwin, 0, width); - draw_line = 0; - } - /* Last print the appointments for current day. */ - item_number++; - day_item_s2apoint_s (&a, day); - if (item_number - incolor == 0) - { - day_saved_item.type = day->type; - day_saved_item.mesg = day->mesg; - apoint_sec2str (&a, day->type, date, - day_saved_item.start, day_saved_item.end); - } - display_item_date (item_number - incolor, &a, day->type, - date, line + 1, x_pos); - display_item (item_number - incolor, day->mesg, 0, - (day->note != NULL) ? 1 : 0, width - 7, line + 2, - x_pos); - line += 3; - } + LLIST_FOREACH(&day_items, i) { + struct day_item *day = LLIST_TS_GET_DATA(i); + if (day->type == RECUR_EVNT || day->type == RECUR_APPT) + recur = 1; + else + recur = 0; + /* First print the events for current day. */ + if (day->type < RECUR_APPT) { + item_number++; + if (item_number - incolor == 0) { + day_saved_item.type = day->type; + day_saved_item.mesg = day->mesg; + } + display_item(item_number - incolor, day->mesg, recur, + (day->note != NULL) ? 1 : 0, width - 7, line, x_pos); + line++; + draw_line = 1; + } else { + /* Draw a line between events and appointments. */ + if (line > 0 && draw_line) { + wmove(apad.ptrwin, line, 0); + whline(apad.ptrwin, 0, width); + draw_line = 0; + } + /* Last print the appointments for current day. */ + item_number++; + day_item_s2apoint_s(&a, day); + if (item_number - incolor == 0) { + day_saved_item.type = day->type; + day_saved_item.mesg = day->mesg; + apoint_sec2str(&a, date, day_saved_item.start, day_saved_item.end); + } + display_item_date(item_number - incolor, &a, day->type, + date, line + 1, x_pos); + display_item(item_number - incolor, day->mesg, 0, + (day->note != NULL) ? 1 : 0, width - 7, line + 2, x_pos); + line += 3; } + } } /* Display an item inside a popup window. */ -void -day_popup_item (void) +void day_popup_item(void) { if (day_saved_item.type == EVNT || day_saved_item.type == RECUR_EVNT) - item_in_popup (NULL, NULL, day_saved_item.mesg, _("Event :")); + item_in_popup(NULL, NULL, day_saved_item.mesg, _("Event :")); else if (day_saved_item.type == APPT || day_saved_item.type == RECUR_APPT) - item_in_popup (day_saved_item.start, day_saved_item.end, - day_saved_item.mesg, _("Appointment :")); + item_in_popup(day_saved_item.start, day_saved_item.end, + day_saved_item.mesg, _("Appointment :")); else - EXIT (_("unknown item type")); + EXIT(_("unknown item type")); /* NOTREACHED */ } @@ -460,38 +443,34 @@ 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 (struct date day) +int day_check_if_item(struct date day) { - const long date = date2sec (day, 0, 0); + const long date = date2sec(day, 0, 0); - if (LLIST_FIND_FIRST (&recur_elist, date, recur_event_inday)) - return (1); + if (LLIST_FIND_FIRST(&recur_elist, date, recur_event_inday)) + return 1; - LLIST_TS_LOCK (&recur_alist_p); - if (LLIST_TS_FIND_FIRST (&recur_alist_p, date, recur_apoint_inday)) - { - LLIST_TS_UNLOCK (&recur_alist_p); - return (1); - } - LLIST_TS_UNLOCK (&recur_alist_p); + LLIST_TS_LOCK(&recur_alist_p); + if (LLIST_TS_FIND_FIRST(&recur_alist_p, date, recur_apoint_inday)) { + LLIST_TS_UNLOCK(&recur_alist_p); + return 1; + } + LLIST_TS_UNLOCK(&recur_alist_p); - if (LLIST_FIND_FIRST (&eventlist, date, event_inday)) - return (1); + if (LLIST_FIND_FIRST(&eventlist, date, event_inday)) + return 1; - LLIST_TS_LOCK (&alist_p); - if (LLIST_TS_FIND_FIRST (&alist_p, date, apoint_inday)) - { - LLIST_TS_UNLOCK (&alist_p); - return (1); - } - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_LOCK(&alist_p); + if (LLIST_TS_FIND_FIRST(&alist_p, date, apoint_inday)) { + LLIST_TS_UNLOCK(&alist_p); + return 1; + } + LLIST_TS_UNLOCK(&alist_p); - return (0); + return 0; } -static unsigned -fill_slices (int *slices, int slicesno, int first, int last) +static unsigned fill_slices(int *slices, int slicesno, int first, int last) { int i; @@ -499,7 +478,7 @@ fill_slices (int *slices, int slicesno, int first, int last) return 0; if (last >= slicesno) - last = slicesno - 1; /* Appointment spanning more than one day. */ + last = slicesno - 1; /* Appointment spanning more than one day. */ for (i = first; i <= last; i++) slices[i] = 1; @@ -512,353 +491,375 @@ fill_slices (int *slices, int slicesno, int first, int last) * appointment in the corresponding time slice, 0 otherwise. * A 24 hours day is divided into 'slicesno' number of time slices. */ -unsigned -day_chk_busy_slices (struct date day, int slicesno, int *slices) +unsigned day_chk_busy_slices(struct date day, int slicesno, int *slices) { llist_item_t *i; int slicelen; - const long date = date2sec (day, 0, 0); + const long date = date2sec(day, 0, 0); slicelen = DAYINSEC / slicesno; #define SLICENUM(tsec) ((tsec) / slicelen % slicesno) - LLIST_TS_LOCK (&recur_alist_p); - LLIST_TS_FIND_FOREACH (&recur_alist_p, date, recur_apoint_inday, i) - { - struct apoint *rapt = LLIST_TS_GET_DATA (i); - long start = get_item_time (rapt->start); - long end = get_item_time (rapt->start + rapt->dur); - - if (!fill_slices (slices, slicesno, SLICENUM (start), SLICENUM (end))) - { - LLIST_TS_UNLOCK (&recur_alist_p); - return 0; - } + LLIST_TS_LOCK(&recur_alist_p); + LLIST_TS_FIND_FOREACH(&recur_alist_p, date, recur_apoint_inday, i) { + struct apoint *rapt = LLIST_TS_GET_DATA(i); + long start = get_item_time(rapt->start); + long end = get_item_time(rapt->start + rapt->dur); + + if (!fill_slices(slices, slicesno, SLICENUM(start), SLICENUM(end))) { + LLIST_TS_UNLOCK(&recur_alist_p); + return 0; } - LLIST_TS_UNLOCK (&recur_alist_p); - - LLIST_TS_LOCK (&alist_p); - LLIST_TS_FIND_FOREACH (&alist_p, date, apoint_inday, i) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - long start = get_item_time (apt->start); - long end = get_item_time (apt->start + apt->dur); - - if (!fill_slices (slices, slicesno, SLICENUM (start), SLICENUM (end))) - { - LLIST_TS_UNLOCK (&alist_p); - return 0; - } + } + LLIST_TS_UNLOCK(&recur_alist_p); + + LLIST_TS_LOCK(&alist_p); + LLIST_TS_FIND_FOREACH(&alist_p, date, apoint_inday, i) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + long start = get_item_time(apt->start); + long end = get_item_time(apt->start + apt->dur); + + if (apt->start >= date + DAYINSEC) + break; + + if (!fill_slices(slices, slicesno, SLICENUM(start), SLICENUM(end))) { + LLIST_TS_UNLOCK(&alist_p); + return 0; } - LLIST_TS_UNLOCK (&alist_p); + } + LLIST_TS_UNLOCK(&alist_p); #undef SLICENUM return 1; } /* Request the user to enter a new time. */ -static char * -day_edit_time (long time) +static int day_edit_time(int time, unsigned *new_hour, unsigned *new_minute) { - char *timestr; - char *msg_time = _("Enter the new time ([hh:mm] or [h:mm]) : "); - char *enter_str = _("Press [Enter] to continue"); - char *fmt_msg = _("You entered an invalid time, should be [h:mm] or [hh:mm]"); - - while (1) - { - status_mesg (msg_time, ""); - timestr = date_sec2date_str (time, "%H:%M"); - updatestring (win[STA].p, ×tr, 0, 1); - if (check_time (timestr) != 1 || strlen (timestr) == 0) - { - status_mesg (fmt_msg, enter_str); - (void)wgetch (win[STA].p); - } - else - return (timestr); - } + char *timestr = date_sec2date_str(time, "%H:%M"); + const char *msg_time = _("Enter the new time ([hh:mm]) : "); + const char *enter_str = _("Press [Enter] to continue"); + const char *fmt_msg = _("You entered an invalid time, should be [hh:mm]"); + + for (;;) { + status_mesg(msg_time, ""); + if (updatestring(win[STA].p, ×tr, 0, 1) == GETSTRING_VALID) { + if (parse_time(timestr, new_hour, new_minute) == 1) { + mem_free(timestr); + return 1; + } else { + status_mesg(fmt_msg, enter_str); + wgetch(win[STA].p); + } + } else + return 0; + } } -static void -update_start_time (long *start, long *dur) +/* Request the user to enter a new time or duration. */ +static int day_edit_duration(int start, int dur, unsigned *new_duration) +{ + char *timestr = date_sec2date_str(start + dur, "%H:%M"); + const char *msg_time = + _ + ("Enter new end time ([hh:mm]) or duration ([+hh:mm], [+xxxdxxhxxm] or [+mm]) : "); + const char *enter_str = _("Press [Enter] to continue"); + const char *fmt_msg = _("You entered an invalid time, should be [hh:mm]"); + long newtime; + unsigned hr, mn; + + for (;;) { + status_mesg(msg_time, ""); + if (updatestring(win[STA].p, ×tr, 0, 1) == GETSTRING_VALID) { + if (*timestr == '+' && parse_duration(timestr + 1, new_duration) == 1) { + *new_duration *= MININSEC; + break; + } else if (parse_time(timestr, &hr, &mn) == 1) { + newtime = update_time_in_date(start + dur, hr, mn); + *new_duration = (newtime > start) ? newtime - start : + DAYINSEC + newtime - start; + break; + } else { + status_mesg(fmt_msg, enter_str); + wgetch(win[STA].p); + } + } else + return 0; + } + + mem_free(timestr); + return 1; +} + +/* Request the user to enter a new end time or duration. */ +static void update_start_time(long *start, long *dur) { long newtime; unsigned hr, mn; int valid_date; - char *timestr; - char *msg_wrong_time = _("Invalid time: start time must be before end time!"); - char *msg_enter = _("Press [Enter] to continue"); - - do - { - timestr = day_edit_time (*start); - (void)sscanf (timestr, "%u:%u", &hr, &mn); - mem_free (timestr); - newtime = update_time_in_date (*start, hr, mn); - if (newtime < *start + *dur) - { - *dur -= (newtime - *start); - *start = newtime; - valid_date = 1; - } - else - { - status_mesg (msg_wrong_time, msg_enter); - (void)wgetch (win[STA].p); - valid_date = 0; - } + const char *msg_wrong_time = + _("Invalid time: start time must be before end time!"); + const char *msg_enter = _("Press [Enter] to continue"); + + do { + day_edit_time(*start, &hr, &mn); + newtime = update_time_in_date(*start, hr, mn); + if (newtime < *start + *dur) { + *dur -= (newtime - *start); + *start = newtime; + valid_date = 1; + } else { + status_mesg(msg_wrong_time, msg_enter); + wgetch(win[STA].p); + valid_date = 0; } + } while (valid_date == 0); } -static void -update_duration (long *start, long *dur) +static void update_duration(long *start, long *dur) { - long newtime; - unsigned hr, mn; - char *timestr; + unsigned newdur; - timestr = day_edit_time (*start + *dur); - (void)sscanf (timestr, "%u:%u", &hr, &mn); - mem_free (timestr); - newtime = update_time_in_date (*start, hr, mn); - *dur = (newtime > *start) ? newtime - *start : DAYINSEC + newtime - *start; + day_edit_duration(*start, *dur, &newdur); + *dur = newdur; } -static void -update_desc (char **desc) +static void update_desc(char **desc) { - status_mesg (_("Enter the new item description:"), ""); - updatestring (win[STA].p, desc, 0, 1); + status_mesg(_("Enter the new item description:"), ""); + updatestring(win[STA].p, desc, 0, 1); } -static void -update_rept (struct rpt **rpt, const long start, struct conf *conf) +static void update_rept(struct rpt **rpt, const long start) { - const int SINGLECHAR = 2; - int ch, cancel, newfreq, date_entered; + int newtype, newfreq, date_entered; long newuntil; char outstr[BUFSIZ]; - char *typstr, *freqstr, *timstr; - char *msg_rpt_type = _("Enter the new repetition type: (D)aily, (W)eekly, " - "(M)onthly, (Y)early"); - char *msg_rpt_ans = _("[D/W/M/Y] "); - char *msg_wrong_freq = _("The frequence you entered is not valid."); - char *msg_wrong_time = _("Invalid time: start time must be before end time!"); - char *msg_wrong_date = _("The entered date is not valid."); - char *msg_fmts = - "Possible formats are [%s] or '0' for an endless repetetition"; - char *msg_enter = _("Press [Enter] to continue"); - - do - { - status_mesg (msg_rpt_type, msg_rpt_ans); - typstr = mem_calloc (SINGLECHAR, sizeof (char)); - (void)snprintf (typstr, SINGLECHAR, "%c", recur_def2char ((*rpt)->type)); - cancel = updatestring (win[STA].p, &typstr, 0, 1); - if (cancel) - { - mem_free (typstr); - return; - } - else - { - ch = toupper (*typstr); - mem_free (typstr); - } - } - while ((ch != 'D') && (ch != 'W') && (ch != 'M') && (ch != 'Y')); - - do - { - status_mesg (_("Enter the new repetition frequence:"), ""); - freqstr = mem_malloc (BUFSIZ); - (void)snprintf (freqstr, BUFSIZ, "%d", (*rpt)->freq); - cancel = updatestring (win[STA].p, &freqstr, 0, 1); - if (cancel) - { - mem_free (freqstr); - return; - } - else - { - newfreq = atoi (freqstr); - mem_free (freqstr); - if (newfreq == 0) - { - status_mesg (msg_wrong_freq, msg_enter); - (void)wgetch (win[STA].p); - } - } + char *freqstr, *timstr; + const char *msg_rpt_prefix = _("Enter the new repetition type:"); + const char *msg_rpt_daily = _("(d)aily"); + const char *msg_rpt_weekly = _("(w)eekly"); + const char *msg_rpt_monthly = _("(m)onthly"); + const char *msg_rpt_yearly = _("(y)early"); + + /* Find the current repetition type. */ + const char *rpt_current; + char msg_rpt_current[BUFSIZ]; + switch (recur_def2char((*rpt)->type)) { + case 'D': + rpt_current = msg_rpt_daily; + break; + case 'W': + rpt_current = msg_rpt_weekly; + break; + case 'M': + rpt_current = msg_rpt_monthly; + break; + case 'Y': + rpt_current = msg_rpt_yearly; + break; + default: + /* NOTREACHED, but makes the compiler happier. */ + rpt_current = msg_rpt_daily; + } + + snprintf(msg_rpt_current, BUFSIZ, _("(currently using %s)"), rpt_current); + + char msg_rpt_asktype[BUFSIZ]; + snprintf(msg_rpt_asktype, BUFSIZ, "%s %s, %s, %s, %s ? %s", + msg_rpt_prefix, + msg_rpt_daily, + msg_rpt_weekly, msg_rpt_monthly, msg_rpt_yearly, msg_rpt_current); + + const char *msg_rpt_choice = _("[dwmy]"); + const char *msg_wrong_freq = _("The frequence you entered is not valid."); + const char *msg_wrong_time = + _("Invalid time: start time must be before end time!"); + const char *msg_wrong_date = _("The entered date is not valid."); + const char *msg_fmts = + _("Possible formats are [%s] or '0' for an endless repetetition"); + const char *msg_enter = _("Press [Enter] to continue"); + + switch (status_ask_choice(msg_rpt_asktype, msg_rpt_choice, 4)) { + case 1: + newtype = 'D'; + break; + case 2: + newtype = 'W'; + break; + case 3: + newtype = 'M'; + break; + case 4: + newtype = 'Y'; + break; + default: + return; + } + + do { + status_mesg(_("Enter the new repetition frequence:"), ""); + freqstr = mem_malloc(BUFSIZ); + snprintf(freqstr, BUFSIZ, "%d", (*rpt)->freq); + if (updatestring(win[STA].p, &freqstr, 0, 1) == GETSTRING_VALID) { + newfreq = atoi(freqstr); + mem_free(freqstr); + if (newfreq == 0) { + status_mesg(msg_wrong_freq, msg_enter); + wgetch(win[STA].p); + } + } else { + mem_free(freqstr); + return; } + } while (newfreq == 0); - do - { - (void)snprintf (outstr, BUFSIZ, "Enter the new ending date: [%s] or '0'", - DATEFMT_DESC (conf->input_datefmt)); - status_mesg (_(outstr), ""); - timstr = - date_sec2date_str ((*rpt)->until, DATEFMT (conf->input_datefmt)); - cancel = updatestring (win[STA].p, &timstr, 0, 1); - if (cancel) - { - mem_free (timstr); - return; - } - if (strcmp (timstr, "0") == 0) - { - newuntil = 0; + do { + snprintf(outstr, BUFSIZ, "Enter the new ending date: [%s] or '0'", + DATEFMT_DESC(conf.input_datefmt)); + status_mesg(_(outstr), ""); + timstr = date_sec2date_str((*rpt)->until, DATEFMT(conf.input_datefmt)); + if (updatestring(win[STA].p, &timstr, 0, 1) != GETSTRING_VALID) { + mem_free(timstr); + return; + } + if (strcmp(timstr, "0") == 0) { + newuntil = 0; + date_entered = 1; + } else { + struct tm *lt; + time_t t; + struct date new_date; + int newmonth, newday, newyear; + + if (parse_date(timstr, conf.input_datefmt, &newyear, &newmonth, + &newday, calendar_get_slctd_day())) { + t = start; + lt = localtime(&t); + new_date.dd = newday; + new_date.mm = newmonth; + new_date.yyyy = newyear; + newuntil = date2sec(new_date, lt->tm_hour, lt->tm_min); + if (newuntil < start) { + status_mesg(msg_wrong_time, msg_enter); + wgetch(win[STA].p); + date_entered = 0; + } else date_entered = 1; - } - else - { - struct tm *lt; - time_t t; - struct date new_date; - int newmonth, newday, newyear; - - if (parse_date (timstr, conf->input_datefmt, - &newyear, &newmonth, &newday, calendar_get_slctd_day ())) - { - t = start; - lt = localtime (&t); - new_date.dd = newday; - new_date.mm = newmonth; - new_date.yyyy = newyear; - newuntil = date2sec (new_date, lt->tm_hour, lt->tm_min); - if (newuntil < start) - { - status_mesg (msg_wrong_time, msg_enter); - (void)wgetch (win[STA].p); - date_entered = 0; - } - else - date_entered = 1; - } - else - { - (void)snprintf (outstr, BUFSIZ, msg_fmts, - DATEFMT_DESC (conf->input_datefmt)); - status_mesg (msg_wrong_date, _(outstr)); - (void)wgetch (win[STA].p); - date_entered = 0; - } - } + } else { + snprintf(outstr, BUFSIZ, msg_fmts, DATEFMT_DESC(conf.input_datefmt)); + status_mesg(msg_wrong_date, _(outstr)); + wgetch(win[STA].p); + date_entered = 0; + } } + } while (date_entered == 0); - mem_free (timstr); - (*rpt)->type = recur_char2def (ch); + mem_free(timstr); + (*rpt)->type = recur_char2def(newtype); (*rpt)->freq = newfreq; (*rpt)->until = newuntil; } /* Edit an already existing item. */ -void -day_edit_item (struct conf *conf) +void day_edit_item(void) { -#define STRT '1' -#define END '2' -#define DESC '3' -#define REPT '4' - struct day_item *p; struct recur_event *re; struct event *e; struct recur_apoint *ra; struct apoint *a; long date; - int item_num, ch; + int item_num; int need_check_notify = 0; - item_num = apoint_hilt (); - p = day_get_item (item_num); - date = calendar_get_slctd_day_sec (); - - ch = -1; - switch (p->type) - { - case RECUR_EVNT: - re = recur_get_event (date, day_item_nb (date, item_num, RECUR_EVNT)); - status_mesg (_("Edit: (1)Description or (2)Repetition?"), "[1/2] "); - while (ch != '1' && ch != '2' && ch != KEY_GENERIC_CANCEL) - ch = wgetch (win[STA].p); - switch (ch) - { - case '1': - update_desc (&re->mesg); - break; - case '2': - update_rept (&re->rpt, re->day, conf); - break; - default: - return; - } + item_num = apoint_hilt(); + p = day_get_item(item_num); + 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)); + const char *choice_recur_evnt[2] = { + "Description", + "Repetition", + }; + switch (status_ask_simplechoice(_("Edit: "), choice_recur_evnt, 2)) { + case 1: + update_desc(&re->mesg); break; - case EVNT: - e = event_get (date, day_item_nb (date, item_num, EVNT)); - update_desc (&e->mesg); + case 2: + update_rept(&re->rpt, re->day); break; - case RECUR_APPT: - ra = recur_get_apoint (date, day_item_nb (date, item_num, RECUR_APPT)); - status_mesg (_("Edit: (1)Start time, (2)End time, " - "(3)Description or (4)Repetition?"), "[1/2/3/4] "); - while (ch != STRT && ch != END && ch != DESC && - ch != REPT && ch != KEY_GENERIC_CANCEL) - ch = wgetch (win[STA].p); - switch (ch) - { - case STRT: - need_check_notify = 1; - update_start_time (&ra->start, &ra->dur); - break; - case END: - update_duration (&ra->start, &ra->dur); - break; - case DESC: - if (notify_bar ()) - need_check_notify = notify_same_recur_item (ra); - update_desc (&ra->mesg); - break; - case REPT: - need_check_notify = 1; - update_rept (&ra->rpt, ra->start, conf); - break; - case KEY_GENERIC_CANCEL: - return; - } + default: + return; + } + break; + case EVNT: + e = event_get(date, day_item_nb(date, item_num, EVNT)); + update_desc(&e->mesg); + break; + case RECUR_APPT: + ra = recur_get_apoint(date, day_item_nb(date, item_num, RECUR_APPT)); + const char *choice_recur_appt[4] = { + "Start time", + "End time", + "Description", + "Repetition", + }; + switch (status_ask_simplechoice(_("Edit: "), choice_recur_appt, 4)) { + case 1: + need_check_notify = 1; + update_start_time(&ra->start, &ra->dur); break; - case APPT: - a = apoint_get (date, day_item_nb (date, item_num, APPT)); - status_mesg (_("Edit: (1)Start time, (2)End time " - "or (3)Description?"), "[1/2/3] "); - while (ch != STRT && ch != END && ch != DESC && ch != KEY_GENERIC_CANCEL) - ch = wgetch (win[STA].p); - switch (ch) - { - case STRT: - need_check_notify = 1; - update_start_time (&a->start, &a->dur); - break; - case END: - update_duration (&a->start, &a->dur); - break; - case DESC: - if (notify_bar ()) - need_check_notify = notify_same_item (a->start); - update_desc (&a->mesg); - break; - case KEY_GENERIC_CANCEL: - return; - } + case 2: + update_duration(&ra->start, &ra->dur); + break; + case 3: + if (notify_bar()) + need_check_notify = notify_same_recur_item(ra); + update_desc(&ra->mesg); + break; + case 4: + need_check_notify = 1; + update_rept(&ra->rpt, ra->start); break; + default: + return; } + break; + case APPT: + a = apoint_get(date, day_item_nb(date, item_num, APPT)); + const char *choice_appt[3] = { + "Start time", + "End time", + "Description", + }; + switch (status_ask_simplechoice(_("Edit: "), choice_appt, 3)) { + case 1: + need_check_notify = 1; + update_start_time(&a->start, &a->dur); + break; + case 2: + update_duration(&a->start, &a->dur); + break; + case 3: + if (notify_bar()) + need_check_notify = notify_same_item(a->start); + update_desc(&a->mesg); + break; + default: + return; + } + break; + } if (need_check_notify) - notify_check_next_app (1); + notify_check_next_app(1); } /* @@ -867,157 +868,142 @@ day_edit_item (struct conf *conf) * 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, enum eraseflg flag) +int day_erase_item(long date, int item_number, enum eraseflg flag) { struct day_item *p; - char *erase_warning = + + const char *erase_warning = _("This item is recurrent. " "Delete (a)ll occurences or just this (o)ne ?"); - char *note_warning = + const char *erase_choices = _("[ao]"); + const int nb_erase_choices = 2; + + const 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, ans; + const char *note_choices = _("[in]"); + const int nb_note_choices = 2; + int ans; unsigned delete_whole; - ch = -1; - p = day_get_item (item_number); - if (flag == ERASE_DONT_FORCE) - { - ans = 0; - if (p->note == NULL) - ans = 'i'; - while (ans != 'i' && ans != 'n') - { - status_mesg (note_warning, note_choice); - ans = wgetch (win[STA].p); - } - if (ans == 'i') - flag = ERASE_FORCE; - else - flag = ERASE_FORCE_ONLY_NOTE; - } - if (p->type == EVNT) - { - event_delete_bynum (date, day_item_nb (date, item_number, EVNT), flag); + p = day_get_item(item_number); + if (flag == ERASE_DONT_FORCE) { + if (p->note == NULL) + ans = 1; + else + ans = status_ask_choice(note_warning, note_choices, nb_note_choices); + + switch (ans) { + case 1: + flag = ERASE_FORCE; + break; + case 2: + flag = ERASE_FORCE_ONLY_NOTE; + break; + default: /* User escaped */ + return 0; } - else if (p->type == APPT) - { - apoint_delete_bynum (date, day_item_nb (date, item_number, APPT), flag); + } + if (p->type == EVNT) { + event_delete_bynum(date, day_item_nb(date, item_number, EVNT), flag); + } else if (p->type == APPT) { + apoint_delete_bynum(date, day_item_nb(date, item_number, APPT), flag); + } else { + if (flag == ERASE_FORCE_ONLY_NOTE) + ans = 1; + else + ans = status_ask_choice(erase_warning, erase_choices, nb_erase_choices); + + switch (ans) { + case 1: + delete_whole = 1; + break; + case 2: + delete_whole = 0; + break; + default: + return 0; } - else - { - if (flag == ERASE_FORCE_ONLY_NOTE) - ch = 'a'; - while ((ch != 'a') && (ch != 'o') && (ch != KEY_GENERIC_CANCEL)) - { - status_mesg (erase_warning, erase_choice); - ch = wgetch (win[STA].p); - } - if (ch == 'a') - { - delete_whole = 1; - } - else if (ch == 'o') - { - delete_whole = 0; - } - else - { - return (0); - } - if (p->type == RECUR_EVNT) - { - recur_event_erase (date, day_item_nb (date, item_number, RECUR_EVNT), - delete_whole, flag); - } - else - { - recur_apoint_erase (date, p->appt_pos, delete_whole, flag); - } + + if (p->type == RECUR_EVNT) { + recur_event_erase(date, day_item_nb(date, item_number, RECUR_EVNT), + delete_whole, flag); + } else { + recur_apoint_erase(date, p->appt_pos, delete_whole, flag); } + } if (flag == ERASE_FORCE_ONLY_NOTE) return 0; else - return (p->type); + return p->type; } /* Cut an item so it can be pasted somewhere else later. */ -int -day_cut_item (long date, int item_number) +int day_cut_item(long date, int item_number) { const int DELETE_WHOLE = 1; struct day_item *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 */ - } + 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 */ + } return p->type; } /* Paste a previously cut item. */ -int -day_paste_item (long date, int cut_item_type) +int day_paste_item(long date, int cut_item_type) { 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 */ - } + 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 */ + } return pasted_item_type; } /* Returns a structure containing the selected item. */ -struct day_item * -day_get_item (int item_number) +struct day_item *day_get_item(int item_number) { - return LLIST_GET_DATA (LLIST_NTH (&day_items, item_number - 1)); + return LLIST_GET_DATA(LLIST_NTH(&day_items, item_number - 1)); } /* Returns the real item number, given its type. */ -int -day_item_nb (long date, int day_num, int type) +int day_item_nb(long date, int day_num, int type) { int i, nb_item[MAX_TYPES]; llist_item_t *j; @@ -1025,78 +1011,108 @@ day_item_nb (long date, int day_num, int type) for (i = 0; i < MAX_TYPES; i++) nb_item[i] = 0; - j = LLIST_FIRST (&day_items); - for (i = 1; i < day_num; i++) - { - struct day_item *day = LLIST_TS_GET_DATA (j); - nb_item[day->type - 1]++; - j = LLIST_TS_NEXT (j); - } + j = LLIST_FIRST(&day_items); + for (i = 1; i < day_num; i++) { + struct day_item *day = LLIST_TS_GET_DATA(j); + nb_item[day->type - 1]++; + j = LLIST_TS_NEXT(j); + } - return (nb_item[type - 1]); + return nb_item[type - 1]; } /* Attach a note to an appointment or event. */ -void -day_edit_note (char *editor) +void day_edit_note(const char *editor) { struct day_item *p; struct recur_apoint *ra; struct apoint *a; struct recur_event *re; struct event *e; - 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) - return; - else - p->note = filename; - } - (void)snprintf (fullname, BUFSIZ, "%s%s", path_notes, p->note); - wins_launch_external (fullname, editor); + item_num = apoint_hilt(); + p = day_get_item(item_num); + edit_note(&p->note, 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)); + re->note = p->note; + break; + case EVNT: + e = event_get(date, day_item_nb(date, item_num, EVNT)); + e->note = p->note; + break; + case RECUR_APPT: + ra = recur_get_apoint(date, day_item_nb(date, item_num, RECUR_APPT)); + ra->note = p->note; + break; + case APPT: + a = apoint_get(date, day_item_nb(date, item_num, APPT)); + a->note = p->note; + break; + } +} + +/* View a note previously attached to an appointment or event */ +void day_view_note(const char *pager) +{ + struct day_item *p = day_get_item(apoint_hilt()); + view_note(p->note, pager); +} - if (io_file_is_empty (fullname) > 0) - erase_note (&p->note, ERASE_FORCE); +/* Pipe an appointment or event to an external program. */ +void day_pipe_item(void) +{ + char cmd[BUFSIZ] = ""; + char const *arg[] = { cmd, NULL }; + int pout; + int pid; + FILE *fpout; + int item_num; + long date; + struct day_item *p; + struct recur_apoint *ra; + struct apoint *a; + struct recur_event *re; + struct event *e; - date = calendar_get_slctd_day_sec (); - switch (p->type) - { + status_mesg(_("Pipe item to external command:"), ""); + if (getstring(win[STA].p, cmd, BUFSIZ, 0, 1) != GETSTRING_VALID) + return; + + wins_prepare_external(); + if ((pid = shell_exec(NULL, &pout, *arg, arg))) { + fpout = fdopen(pout, "w"); + + item_num = apoint_hilt(); + p = day_get_item(item_num); + 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)); - re->note = p->note; + re = recur_get_event(date, day_item_nb(date, item_num, RECUR_EVNT)); + recur_event_write(re, fpout); break; case EVNT: - e = event_get (date, day_item_nb (date, item_num, EVNT)); - e->note = p->note; + e = event_get(date, day_item_nb(date, item_num, EVNT)); + event_write(e, fpout); break; case RECUR_APPT: - ra = recur_get_apoint (date, day_item_nb (date, item_num, RECUR_APPT)); - ra->note = p->note; + ra = recur_get_apoint(date, day_item_nb(date, item_num, RECUR_APPT)); + recur_apoint_write(ra, fpout); break; case APPT: - a = apoint_get (date, day_item_nb (date, item_num, APPT)); - a->note = p->note; + a = apoint_get(date, day_item_nb(date, item_num, APPT)); + apoint_write(a, fpout); break; } -} - -/* View a note previously attached to an appointment or event */ -void -day_view_note (char *pager) -{ - struct day_item *p; - char fullname[BUFSIZ]; - p = day_get_item (apoint_hilt ()); - if (p->note == NULL) - return; - (void)snprintf (fullname, BUFSIZ, "%s%s", path_notes, p->note); - wins_launch_external (fullname, pager); + fclose(fpout); + child_wait(NULL, &pout, pid); + press_any_key(); + } + wins_unprepare_external(); } @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ #define DMON_LOG(...) do { \ if (dmon.log) \ - (void)io_fprintln (path_dmon_log, __VA_ARGS__); \ + io_fprintln (path_dmon_log, __VA_ARGS__); \ } while (0) #define DMON_ABRT(...) do { \ @@ -64,26 +64,22 @@ static unsigned data_loaded; -static void -dmon_sigs_hdlr (int sig) +static void dmon_sigs_hdlr(int sig) { if (data_loaded) - free_user_data (); + free_user_data(); - DMON_LOG (_("terminated at %s with signal %d\n"), nowstr (), sig); + DMON_LOG(_("terminated at %s with signal %d\n"), nowstr(), sig); - if (unlink (path_dpid) != 0) - { - DMON_LOG (_("Could not remove daemon lock file: %s\n"), - strerror (errno)); - exit (EXIT_FAILURE); - } + if (unlink(path_dpid) != 0) { + DMON_LOG(_("Could not remove daemon lock file: %s\n"), strerror(errno)); + exit(EXIT_FAILURE); + } - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); } -static unsigned -daemonize (int status) +static unsigned daemonize(int status) { int fd; @@ -93,16 +89,15 @@ daemonize (int status) * First need to fork in order to become a child of the init process, * once the father exits. */ - switch (fork ()) - { - case -1: /* fork error */ - EXIT (_("Could not fork: %s\n"), strerror (errno)); - break; - case 0: /* child */ - break; - default: /* parent */ - exit (status); - } + switch (fork()) { + case -1: /* fork error */ + EXIT(_("Could not fork: %s\n"), strerror(errno)); + break; + case 0: /* child */ + break; + default: /* parent */ + exit(status); + } /* * Process independency. @@ -110,110 +105,99 @@ daemonize (int status) * Obtain a new process group and session in order to get detached from the * controlling terminal. */ - if (setsid () == -1) - { - DMON_LOG (_("Could not detach from the controlling terminal: %s\n"), - strerror (errno)); - return 0; - } + if (setsid() == -1) { + DMON_LOG(_("Could not detach from the controlling terminal: %s\n"), + strerror(errno)); + return 0; + } /* * Change working directory to root directory, * to prevent filesystem unmounts. */ - if (chdir ("/") == -1) - { - DMON_LOG (_("Could not change working directory: %s\n"), - strerror (errno)); - return 0; - } + if (chdir("/") == -1) { + DMON_LOG(_("Could not change working directory: %s\n"), strerror(errno)); + return 0; + } /* Redirect standard file descriptors to /dev/null. */ - if ((fd = open (_PATH_DEVNULL, O_RDWR, 0)) != -1) - { - (void)dup2 (fd, STDIN_FILENO); - (void)dup2 (fd, STDOUT_FILENO); - (void)dup2 (fd, STDERR_FILENO); - if (fd > 2) - (void)close (fd); - } + if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > 2) + close(fd); + } /* Write access for the owner only. */ - (void)umask (0022); + umask(0022); - if (!sigs_set_hdlr (SIGINT, dmon_sigs_hdlr) - || !sigs_set_hdlr (SIGTERM, dmon_sigs_hdlr) - || !sigs_set_hdlr (SIGALRM, dmon_sigs_hdlr) - || !sigs_set_hdlr (SIGQUIT, dmon_sigs_hdlr) - || !sigs_set_hdlr (SIGCHLD, SIG_IGN)) + if (!sigs_set_hdlr(SIGINT, dmon_sigs_hdlr) + || !sigs_set_hdlr(SIGTERM, dmon_sigs_hdlr) + || !sigs_set_hdlr(SIGALRM, dmon_sigs_hdlr) + || !sigs_set_hdlr(SIGQUIT, dmon_sigs_hdlr) + || !sigs_set_hdlr(SIGCHLD, SIG_IGN)) return 0; return 1; } -void -dmon_start (int parent_exit_status) +void dmon_start(int parent_exit_status) { - struct conf conf; - - if (!daemonize (parent_exit_status)) - DMON_ABRT (_("Cannot daemonize, aborting\n")); - - if (!io_dump_pid (path_dpid)) - DMON_ABRT (_("Could not set lock file\n")); - - if (!io_file_exist (path_conf)) - DMON_ABRT (_("Could not access \"%s\": %s\n"), - path_conf, strerror (errno)); - custom_load_conf (&conf, 0); - - if (!io_file_exist (path_apts)) - DMON_ABRT (_("Could not access \"%s\": %s\n"), - path_apts, strerror (errno)); - apoint_llist_init (); - recur_apoint_llist_init (); - event_llist_init (); - todo_init_list (); - io_load_app (); + if (!daemonize(parent_exit_status)) + DMON_ABRT(_("Cannot daemonize, aborting\n")); + + if (!io_dump_pid(path_dpid)) + DMON_ABRT(_("Could not set lock file\n")); + + if (!io_file_exist(path_conf)) + DMON_ABRT(_("Could not access \"%s\": %s\n"), path_conf, strerror(errno)); + config_load(); + + if (!io_file_exist(path_apts)) + DMON_ABRT(_("Could not access \"%s\": %s\n"), path_apts, strerror(errno)); + apoint_llist_init(); + recur_apoint_llist_init(); + event_llist_init(); + todo_init_list(); + io_load_app(); data_loaded = 1; - DMON_LOG (_("started at %s\n"), nowstr ()); - for (;;) - { - int left; - - if (!notify_get_next_bkgd ()) - DMON_ABRT (_("error loading next appointment\n")); - - left = notify_time_left (); - if (left > 0 && left < nbar.cntdwn && notify_needs_reminder ()) - { - DMON_LOG (_("launching notification at %s for: \"%s\"\n"), - nowstr (), notify_app_txt ()); - if (!notify_launch_cmd ()) - DMON_LOG (_("error while sending notification\n")); - } - - DMON_LOG (_("sleeping at %s for %d seconds\n"), nowstr (), - DMON_SLEEP_TIME); - psleep (DMON_SLEEP_TIME); - DMON_LOG (_("awakened at %s\n"), nowstr ()); + DMON_LOG(_("started at %s\n"), nowstr()); + for (;;) { + int left; + + if (!notify_get_next_bkgd()) + DMON_ABRT(_("error loading next appointment\n")); + + left = notify_time_left(); + if (left > 0 && left < nbar.cntdwn && notify_needs_reminder()) { + DMON_LOG(_("launching notification at %s for: \"%s\"\n"), + nowstr(), notify_app_txt()); + if (!notify_launch_cmd()) + DMON_LOG(_("error while sending notification\n")); } + + DMON_LOG(ngettext("sleeping at %s for %d second\n", + "sleeping at %s for %d seconds\n", + DMON_SLEEP_TIME), nowstr(), DMON_SLEEP_TIME); + psleep(DMON_SLEEP_TIME); + DMON_LOG(_("awakened at %s\n"), nowstr()); + } } /* * Check if calcurse is running in background, and if yes, send a SIGINT * signal to stop it. */ -void -dmon_stop (void) +void dmon_stop(void) { int dpid; - dpid = io_get_pid (path_dpid); + dpid = io_get_pid(path_dpid); if (!dpid) return; - if (kill ((pid_t)dpid, SIGINT) < 0 && errno != ESRCH) - EXIT (_("Could not stop calcurse daemon: %s\n"), strerror (errno)); + if (kill((pid_t) dpid, SIGINT) < 0 && errno != ESRCH) + EXIT(_("Could not stop calcurse daemon: %s\n"), strerror(errno)); } diff --git a/src/event.c b/src/event.c index c395ed8..f460ded 100644 --- a/src/event.c +++ b/src/event.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,181 +41,160 @@ #include "calcurse.h" -llist_t eventlist; -static struct event bkp_cut_event; +llist_t eventlist; +static struct event bkp_cut_event; -void -event_free_bkp (enum eraseflg flag) +void event_free_bkp(void) { - if (bkp_cut_event.mesg) - { - mem_free (bkp_cut_event.mesg); - bkp_cut_event.mesg = 0; - } - erase_note (&bkp_cut_event.note, flag); + if (bkp_cut_event.mesg) { + mem_free(bkp_cut_event.mesg); + bkp_cut_event.mesg = 0; + } + erase_note(&bkp_cut_event.note); } -static void -event_free (struct event *ev) +static void event_free(struct event *ev) { - mem_free (ev->mesg); - erase_note (&ev->note, ERASE_FORCE_KEEP_NOTE); - mem_free (ev); + mem_free(ev->mesg); + erase_note(&ev->note); + mem_free(ev); } -static void -event_dup (struct event *in, struct event *bkp) +static void event_dup(struct event *in, struct event *bkp) { - EXIT_IF (!in || !bkp, _("null pointer")); + EXIT_IF(!in || !bkp, _("null pointer")); bkp->id = in->id; bkp->day = in->day; - bkp->mesg = mem_strdup (in->mesg); + bkp->mesg = mem_strdup(in->mesg); if (in->note) - bkp->note = mem_strdup (in->note); + bkp->note = mem_strdup(in->note); } -void -event_llist_init (void) +void event_llist_init(void) { - LLIST_INIT (&eventlist); + LLIST_INIT(&eventlist); } -void -event_llist_free (void) +void event_llist_free(void) { - LLIST_FREE_INNER (&eventlist, event_free); - LLIST_FREE (&eventlist); + LLIST_FREE_INNER(&eventlist, event_free); + LLIST_FREE(&eventlist); } -static int -event_cmp_day (struct event *a, struct event *b) +static int event_cmp_day(struct event *a, struct event *b) { - return (a->day < b->day ? -1 : (a->day == b->day ? 0 : 1)); + return a->day < b->day ? -1 : (a->day == b->day ? 0 : 1); } /* Create a new event */ -struct event * -event_new (char *mesg, char *note, long day, int id) +struct event *event_new(char *mesg, char *note, long day, int id) { struct event *ev; - ev = mem_malloc (sizeof (struct event)); - ev->mesg = mem_strdup (mesg); + ev = mem_malloc(sizeof(struct event)); + ev->mesg = mem_strdup(mesg); ev->day = day; ev->id = id; - ev->note = (note != NULL) ? mem_strdup (note) : NULL; + ev->note = (note != NULL) ? mem_strdup(note) : NULL; - LLIST_ADD_SORTED (&eventlist, ev, event_cmp_day); + LLIST_ADD_SORTED(&eventlist, ev, event_cmp_day); return ev; } /* Check if the event belongs to the selected day */ -unsigned -event_inday (struct event *i, long start) +unsigned event_inday(struct event *i, long start) { - if (i->day <= start + DAYINSEC && i->day > start) - { - return (1); - } - return (0); + return (i->day < start + DAYINSEC && i->day >= start); } /* Write to file the event in user-friendly format */ -void -event_write (struct event *o, FILE *f) +void event_write(struct event *o, FILE * f) { struct tm *lt; time_t t; t = o->day; - lt = localtime (&t); - (void)fprintf (f, "%02u/%02u/%04u [%d] ", lt->tm_mon + 1, lt->tm_mday, - 1900 + lt->tm_year, o->id); + lt = localtime(&t); + fprintf(f, "%02u/%02u/%04u [%d] ", lt->tm_mon + 1, lt->tm_mday, + 1900 + lt->tm_year, o->id); if (o->note != NULL) - (void)fprintf (f, ">%s ", o->note); - (void)fprintf (f, "%s\n", o->mesg); + fprintf(f, ">%s ", o->note); + fprintf(f, "%s\n", o->mesg); } /* Load the events from file */ -struct event * -event_scan (FILE *f, struct tm start, int id, char *note) +struct event *event_scan(FILE * f, struct tm start, int id, char *note) { char buf[BUFSIZ], *nl; time_t tstart, t; - t = time (NULL); - (void)localtime (&t); + t = time(NULL); + localtime(&t); /* Read the event description */ - (void)fgets (buf, sizeof buf, f); - nl = strchr (buf, '\n'); - if (nl) - { - *nl = '\0'; - } - start.tm_hour = 12; + if (!fgets(buf, sizeof buf, f)) + return NULL; + + nl = strchr(buf, '\n'); + if (nl) { + *nl = '\0'; + } + start.tm_hour = 0; start.tm_min = 0; start.tm_sec = 0; start.tm_isdst = -1; start.tm_year -= 1900; start.tm_mon--; - tstart = mktime (&start); - EXIT_IF (tstart == -1, _("date error in the event\n")); + tstart = mktime(&start); + EXIT_IF(tstart == -1, _("date error in the event\n")); - return event_new (buf, note, tstart, id); + return event_new(buf, note, tstart, id); } /* Retrieve an event from the list, given the day and item position. */ -struct event * -event_get (long day, int pos) +struct event *event_get(long day, int pos) { - llist_item_t *i = LLIST_FIND_NTH (&eventlist, pos, day, event_inday); + llist_item_t *i = LLIST_FIND_NTH(&eventlist, pos, day, event_inday); if (i) - return LLIST_TS_GET_DATA (i); + return LLIST_TS_GET_DATA(i); - EXIT (_("event not found")); + EXIT(_("event not found")); /* NOTREACHED */ } /* Delete an event from the list. */ -void -event_delete_bynum (long start, unsigned num, enum eraseflg flag) +void event_delete_bynum(long start, unsigned num, enum eraseflg flag) { - llist_item_t *i = LLIST_FIND_NTH (&eventlist, num, start, event_inday); + llist_item_t *i = LLIST_FIND_NTH(&eventlist, num, start, event_inday); if (!i) - EXIT (_("no such appointment")); - struct event *ev = LLIST_TS_GET_DATA (i); - - switch (flag) - { - case ERASE_FORCE_ONLY_NOTE: - erase_note (&ev->note, flag); - break; - case ERASE_CUT: - event_free_bkp (ERASE_FORCE); - event_dup (ev, &bkp_cut_event); - erase_note (&ev->note, ERASE_FORCE_KEEP_NOTE); - /* FALLTHROUGH */ - default: - LLIST_REMOVE (&eventlist, i); - mem_free (ev->mesg); - if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT) - erase_note (&ev->note, flag); - mem_free (ev); - break; - } + EXIT(_("no such appointment")); + struct event *ev = LLIST_TS_GET_DATA(i); + + switch (flag) { + case ERASE_FORCE_ONLY_NOTE: + erase_note(&ev->note); + break; + case ERASE_CUT: + event_free_bkp(); + event_dup(ev, &bkp_cut_event); + erase_note(&ev->note); + /* FALLTHROUGH */ + default: + LLIST_REMOVE(&eventlist, i); + mem_free(ev->mesg); + mem_free(ev); + break; + } } -void -event_paste_item (void) +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 (ERASE_FORCE_KEEP_NOTE); + event_new(bkp_cut_event.mesg, bkp_cut_event.note, + date2sec(*calendar_get_slctd_day(), 0, 0), bkp_cut_event.id); + event_free_bkp(); } diff --git a/src/getstring.c b/src/getstring.c new file mode 100644 index 0000000..cc2a949 --- /dev/null +++ b/src/getstring.c @@ -0,0 +1,280 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#include "calcurse.h" + +struct getstr_charinfo { + unsigned int offset, dpyoff; +}; + +struct getstr_status { + char *s; + struct getstr_charinfo *ci; + int pos, len; + int scrpos; +}; + +/* Print the string at the desired position. */ +static void getstr_print(WINDOW * win, int x, int y, struct getstr_status *st) +{ + char c = 0; + + /* print string */ + mvwaddnstr(win, y, x, &st->s[st->ci[st->scrpos].offset], -1); + wclrtoeol(win); + + /* print scrolling indicator */ + if (st->scrpos > 0 && st->ci[st->len].dpyoff - + st->ci[st->scrpos].dpyoff > col - 2) + c = '*'; + else if (st->scrpos > 0) + c = '<'; + else if (st->ci[st->len].dpyoff - st->ci[st->scrpos].dpyoff > col - 2) + c = '>'; + mvwprintw(win, y, col - 2, " %c", c); + + /* print cursor */ + wmove(win, y, st->ci[st->pos].dpyoff - st->ci[st->scrpos].dpyoff); + wchgat(win, 1, A_REVERSE, COLR_CUSTOM, NULL); +} + +/* Delete a character at the given position in string. */ +static void getstr_del_char(struct getstr_status *st) +{ + char *str = st->s + st->ci[st->pos].offset; + int cl = st->ci[st->pos + 1].offset - st->ci[st->pos].offset; + int cw = st->ci[st->pos + 1].dpyoff - st->ci[st->pos].dpyoff; + int i; + + memmove(str, str + cl, strlen(str) + 1); + + st->len--; + for (i = st->pos; i <= st->len; i++) { + st->ci[i].offset = st->ci[i + 1].offset - cl; + st->ci[i].dpyoff = st->ci[i + 1].dpyoff - cw; + } +} + +/* Add a character at the given position in string. */ +static void getstr_ins_char(struct getstr_status *st, char *c) +{ + char *str = st->s + st->ci[st->pos].offset; + int cl = UTF8_LENGTH(c[0]); + int cw = utf8_width(c); + int i; + + memmove(str + cl, str, strlen(str) + 1); + for (i = 0; i < cl; i++, str++) + *str = c[i]; + + for (i = st->len; i >= st->pos; i--) { + st->ci[i + 1].offset = st->ci[i].offset + cl; + st->ci[i + 1].dpyoff = st->ci[i].dpyoff + cw; + } + st->len++; +} + +static void bell(void) +{ + putchar('\a'); +} + +/* Initialize getstring data structure. */ +static void +getstr_init(struct getstr_status *st, char *str, struct getstr_charinfo *ci) +{ + int width; + + st->s = str; + st->ci = ci; + + st->len = width = 0; + while (*str) { + st->ci[st->len].offset = str - st->s; + st->ci[st->len].dpyoff = width; + + st->len++; + width += utf8_width(str); + str += UTF8_LENGTH(*str); + } + st->ci[st->len].offset = str - st->s; + st->ci[st->len].dpyoff = width; + + st->pos = st->len; + st->scrpos = 0; +} + +/* Scroll left/right if the cursor moves outside the window range. */ +static void getstr_fixscr(struct getstr_status *st) +{ + const int pgsize = col / 3; + int pgskip; + + while (st->pos < st->scrpos) { + pgskip = 0; + while (pgskip < pgsize && st->scrpos > 0) { + st->scrpos--; + pgskip += st->ci[st->scrpos + 1].dpyoff - st->ci[st->scrpos].dpyoff; + } + } + while (st->ci[st->pos].dpyoff - st->ci[st->scrpos].dpyoff > col - 2) { + pgskip = 0; + while (pgskip < pgsize && st->scrpos < st->len) { + pgskip += st->ci[st->scrpos + 1].dpyoff - st->ci[st->scrpos].dpyoff; + st->scrpos++; + } + } +} + +/* + * Getstring allows to get user input and to print it on a window, + * even if noecho() is on. This function is also used to modify an existing + * text (the variable string can be non-NULL). + * We need to do the echoing manually because of the multi-threading + * environment, otherwise the cursor would move from place to place without + * control. + */ +enum getstr getstring(WINDOW * win, char *str, int l, int x, int y) +{ + struct getstr_status st; + struct getstr_charinfo ci[l + 1]; + + int ch, k; + char c[UTF8_MAXLEN]; + + getstr_init(&st, str, ci); + custom_apply_attr(win, ATTR_HIGHEST); + + for (;;) { + getstr_fixscr(&st); + getstr_print(win, x, y, &st); + wins_doupdate(); + + if ((ch = wgetch(win)) == '\n') + break; + switch (ch) { + case KEY_BACKSPACE: /* delete one character */ + case 330: + case 127: + case CTRL('H'): + if (st.pos > 0) { + st.pos--; + getstr_del_char(&st); + } else + bell(); + break; + case CTRL('D'): /* delete next character */ + if (st.pos < st.len) + getstr_del_char(&st); + else + bell(); + break; + case CTRL('W'): /* delete a word */ + if (st.pos > 0) { + while (st.pos && st.s[st.ci[st.pos - 1].offset] == ' ') { + st.pos--; + getstr_del_char(&st); + } + while (st.pos && st.s[st.ci[st.pos - 1].offset] != ' ') { + st.pos--; + getstr_del_char(&st); + } + } else + bell(); + break; + case CTRL('K'): /* delete to end-of-line */ + st.s[st.ci[st.pos].offset] = 0; + st.len = st.pos; + break; + case CTRL('A'): /* go to begginning of string */ + st.pos = 0; + break; + case CTRL('E'): /* go to end of string */ + st.pos = st.len; + break; + case KEY_LEFT: /* move one char backward */ + case CTRL('B'): + if (st.pos > 0) + st.pos--; + break; + case KEY_RIGHT: /* move one char forward */ + case CTRL('F'): + if (st.pos < st.len) + st.pos++; + break; + case ESCAPE: /* cancel editing */ + return GETSTRING_ESC; + break; + default: /* insert one character */ + c[0] = ch; + for (k = 1; k < MIN(UTF8_LENGTH(c[0]), UTF8_MAXLEN); k++) + c[k] = (unsigned char)wgetch(win); + if (st.ci[st.len].offset + k < l) { + getstr_ins_char(&st, c); + st.pos++; + } + } + } + + custom_remove_attr(win, ATTR_HIGHEST); + + return st.len == 0 ? GETSTRING_RET : GETSTRING_VALID; +} + +/* Update an already existing string. */ +int updatestring(WINDOW * win, char **str, int x, int y) +{ + int len = strlen(*str); + char *buf; + enum getstr ret; + + EXIT_IF(len + 1 > BUFSIZ, _("Internal error: line too long")); + + buf = mem_malloc(BUFSIZ); + memcpy(buf, *str, len + 1); + + ret = getstring(win, buf, BUFSIZ, x, y); + + if (ret == GETSTRING_VALID) { + len = strlen(buf); + *str = mem_realloc(*str, len + 1, 1); + EXIT_IF(*str == NULL, _("out of memory")); + memcpy(*str, buf, len + 1); + } + + mem_free(buf); + return ret; +} @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,14 +48,14 @@ typedef struct { char text[HELPTEXTSIZ]; } help_page_t; -typedef enum -{ +typedef enum { HELP_MAIN, HELP_SAVE, HELP_IMPORT, HELP_EXPORT, HELP_DISPLACEMENT, HELP_VIEW, + HELP_PIPE, HELP_TAB, HELP_GOTO, HELP_DELETE, @@ -73,21 +73,18 @@ typedef enum HELP_CREDITS, HELPSCREENS, NOPAGE -} -help_pages_e; +} help_pages_e; /* Returns the number of lines in an help text. */ -static int -get_help_lines (char *text) +static int get_help_lines(char *text) { int i, newline; newline = 0; - for (i = 0; text[i]; i++) - { - if (text[i] == '\n') - newline++; - } + for (i = 0; text[i]; i++) { + if (text[i] == '\n') + newline++; + } return newline + 1; } @@ -96,54 +93,52 @@ get_help_lines (char *text) * of lines that were written. */ static int -help_write_pad (struct window *win, char *title, char *text, enum key action) +help_write_pad(struct window *win, char *title, char *text, enum key action) { int colnum, rownum; - char *bindings_title = "key bindings: %s"; + const char *bindings_title = "key bindings: %s"; char *bindings; colnum = 0; rownum = 0; - erase_window_part (win->p, rownum, colnum, BUFSIZ, win->w); - custom_apply_attr (win->p, ATTR_HIGHEST); - mvwprintw (win->p, rownum, colnum, "%s", title); - if ((int) action != KEY_RESIZE && action < NBKEYS) { - switch (action) - { - case KEY_END_OF_WEEK: - case KEY_START_OF_WEEK: - case KEY_MOVE_UP: - case KEY_MOVE_DOWN: - case KEY_MOVE_RIGHT: - case KEY_MOVE_LEFT: - case KEY_GENERIC_HELP: - case KEY_GENERIC_REDRAW: - case KEY_GENERIC_ADD_APPT: - case KEY_GENERIC_ADD_TODO: - case KEY_GENERIC_NEXT_DAY: - case KEY_GENERIC_PREV_DAY: - case KEY_GENERIC_NEXT_WEEK: - case KEY_GENERIC_PREV_WEEK: - case KEY_GENERIC_GOTO_TODAY: - case KEY_GENERIC_CREDITS: - case KEY_GENERIC_CUT: - case KEY_GENERIC_PASTE: - break; - default: - bindings = keys_action_allkeys (action); - - if (bindings) - { - colnum = win->w - strlen (bindings_title) - strlen (bindings); - mvwprintw (win->p, rownum, colnum, bindings_title, bindings); - } + erase_window_part(win->p, rownum, colnum, BUFSIZ, win->w); + custom_apply_attr(win->p, ATTR_HIGHEST); + mvwprintw(win->p, rownum, colnum, "%s", title); + if ((int)action != KEY_RESIZE && action < NBKEYS) { + switch (action) { + case KEY_END_OF_WEEK: + case KEY_START_OF_WEEK: + case KEY_MOVE_UP: + case KEY_MOVE_DOWN: + case KEY_MOVE_RIGHT: + case KEY_MOVE_LEFT: + case KEY_GENERIC_HELP: + case KEY_GENERIC_REDRAW: + case KEY_GENERIC_ADD_APPT: + case KEY_GENERIC_ADD_TODO: + case KEY_GENERIC_NEXT_DAY: + case KEY_GENERIC_PREV_DAY: + case KEY_GENERIC_NEXT_WEEK: + case KEY_GENERIC_PREV_WEEK: + case KEY_GENERIC_GOTO_TODAY: + case KEY_GENERIC_CREDITS: + case KEY_GENERIC_CUT: + case KEY_GENERIC_PASTE: + break; + default: + bindings = keys_action_allkeys(action); + + if (bindings) { + colnum = win->w - strlen(bindings_title) - strlen(bindings); + mvwprintw(win->p, rownum, colnum, bindings_title, bindings); } + } } colnum = 0; - rownum += get_help_lines (title); - custom_remove_attr (win->p, ATTR_HIGHEST); - mvwprintw (win->p, rownum, colnum, "%s", text); - rownum += get_help_lines (text); + rownum += get_help_lines(title); + custom_remove_attr(win->p, ATTR_HIGHEST); + mvwprintw(win->p, rownum, colnum, "%s", text); + rownum += get_help_lines(text); return rownum; } @@ -151,8 +146,7 @@ help_write_pad (struct window *win, char *title, char *text, enum key action) * Create and init help screen and its pad, which is used to make the scrolling * faster. */ -void -help_wins_init (struct scrollwin *hwin, int x, int y, int h, int w) +void help_wins_init(struct scrollwin *hwin, int x, int y, int h, int w) { const int PADOFFSET = 4; const int TITLELINES = 3; @@ -167,159 +161,158 @@ help_wins_init (struct scrollwin *hwin, int x, int y, int h, int w) hwin->pad.h = BUFSIZ; hwin->pad.w = hwin->win.w - 2 * PADOFFSET + 1; - (void)snprintf (hwin->label, BUFSIZ, _("Calcurse help")); - wins_scrollwin_init (hwin); - wins_show (hwin->win.p, hwin->label); + hwin->label = _("Calcurse help"); + wins_scrollwin_init(hwin); + wins_show(hwin->win.p, hwin->label); } /* * Delete the existing windows and recreate them with their new * size and placement. */ -static void -help_wins_reinit (struct scrollwin *hwin) +static void help_wins_reinit(struct scrollwin *hwin) { - wins_scrollwin_delete (hwin); - wins_get_config (); - help_wins_init (hwin, 0, 0, (notify_bar ()) ? row - 3 : row - 2, col); + wins_scrollwin_delete(hwin); + wins_get_config(); + help_wins_init(hwin, 0, 0, (notify_bar())? row - 3 : row - 2, col); } /* Reset the screen, needed when resizing terminal for example. */ -static void -help_wins_reset (struct scrollwin *hwin) +static void help_wins_reset(struct scrollwin *hwin) { - endwin (); - wins_refresh (); - curs_set (0); - delwin (win[STA].p); - help_wins_reinit (hwin); - win[STA].p = newwin (win[STA].h, win[STA].w, win[STA].y, win[STA].x); - keypad (win[STA].p, TRUE); - if (notify_bar ()) - notify_reinit_bar (); - wins_status_bar (); - if (notify_bar ()) - notify_update_bar (); + endwin(); + wins_refresh(); + curs_set(0); + delwin(win[STA].p); + help_wins_reinit(hwin); + win[STA].p = newwin(win[STA].h, win[STA].w, win[STA].y, win[STA].x); + keypad(win[STA].p, TRUE); + if (notify_bar()) + notify_reinit_bar(); + wins_status_bar(); + if (notify_bar()) + notify_update_bar(); } /* Association between a key pressed and its corresponding help page. */ -static int -wanted_page (int ch) +static int wanted_page(int ch) { int page; - switch (ch) - { - - case KEY_GENERIC_HELP: - page = HELP_MAIN; - break; - - case KEY_FLAG_ITEM: - page = HELP_FLAG; - break; - - case KEY_GENERIC_REDRAW: - case KEY_GENERIC_ADD_APPT: - case KEY_GENERIC_ADD_TODO: - case KEY_GENERIC_NEXT_DAY: - case KEY_GENERIC_PREV_DAY: - case KEY_GENERIC_NEXT_WEEK: - case KEY_GENERIC_PREV_WEEK: - case KEY_GENERIC_GOTO_TODAY: - page = HELP_GENERAL; - break; - - case KEY_GENERIC_SAVE: - page = HELP_SAVE; - break; - - case KEY_GENERIC_IMPORT: - page = HELP_IMPORT; - break; - - case KEY_GENERIC_EXPORT: - page = HELP_EXPORT; - break; - - case KEY_END_OF_WEEK: - case KEY_START_OF_WEEK: - case KEY_MOVE_UP: - case KEY_MOVE_DOWN: - case KEY_MOVE_RIGHT: - case KEY_MOVE_LEFT: - page = HELP_DISPLACEMENT; - break; - - case KEY_ADD_ITEM: - page = HELP_ADD; - break; - - case KEY_GENERIC_GOTO: - page = HELP_GOTO; - break; - - case KEY_DEL_ITEM: - page = HELP_DELETE; - break; - - case KEY_GENERIC_CUT: - case KEY_GENERIC_PASTE: - page = HELP_CUT_PASTE; - break; - - case KEY_EDIT_ITEM: - page = HELP_EDIT; - break; - - case KEY_EDIT_NOTE: - page = HELP_ENOTE; - break; - - case KEY_VIEW_NOTE: - page = HELP_VNOTE; - break; - - case KEY_GENERIC_CONFIG_MENU: - page = HELP_CONFIG; - break; - - case KEY_GENERIC_OTHER_CMD: - page = HELP_OTHER; - break; - - case KEY_REPEAT_ITEM: - page = HELP_REPEAT; - break; - - case KEY_VIEW_ITEM: - page = HELP_VIEW; - break; - - case KEY_RAISE_PRIORITY: - case KEY_LOWER_PRIORITY: - page = HELP_PRIORITY; - break; - - case KEY_GENERIC_CHANGE_VIEW: - page = HELP_TAB; - break; - - case KEY_GENERIC_CREDITS: - page = HELP_CREDITS; - break; - - default: - page = NOPAGE; - break; - } + switch (ch) { + + case KEY_GENERIC_HELP: + page = HELP_MAIN; + break; + + case KEY_FLAG_ITEM: + page = HELP_FLAG; + break; + + case KEY_GENERIC_REDRAW: + case KEY_GENERIC_ADD_APPT: + case KEY_GENERIC_ADD_TODO: + case KEY_GENERIC_NEXT_DAY: + case KEY_GENERIC_PREV_DAY: + case KEY_GENERIC_NEXT_WEEK: + case KEY_GENERIC_PREV_WEEK: + case KEY_GENERIC_GOTO_TODAY: + page = HELP_GENERAL; + break; + + case KEY_GENERIC_SAVE: + page = HELP_SAVE; + break; + + case KEY_GENERIC_IMPORT: + page = HELP_IMPORT; + break; + + case KEY_GENERIC_EXPORT: + page = HELP_EXPORT; + break; + + case KEY_END_OF_WEEK: + case KEY_START_OF_WEEK: + case KEY_MOVE_UP: + case KEY_MOVE_DOWN: + case KEY_MOVE_RIGHT: + case KEY_MOVE_LEFT: + page = HELP_DISPLACEMENT; + break; + + case KEY_ADD_ITEM: + page = HELP_ADD; + break; + + case KEY_GENERIC_GOTO: + page = HELP_GOTO; + break; + + case KEY_DEL_ITEM: + page = HELP_DELETE; + break; + + case KEY_GENERIC_CUT: + case KEY_GENERIC_PASTE: + page = HELP_CUT_PASTE; + break; + + case KEY_EDIT_ITEM: + page = HELP_EDIT; + break; + + case KEY_EDIT_NOTE: + page = HELP_ENOTE; + break; + + case KEY_VIEW_NOTE: + page = HELP_VNOTE; + break; + + case KEY_GENERIC_CONFIG_MENU: + page = HELP_CONFIG; + break; + + case KEY_GENERIC_OTHER_CMD: + page = HELP_OTHER; + break; + + case KEY_REPEAT_ITEM: + page = HELP_REPEAT; + break; + + case KEY_VIEW_ITEM: + page = HELP_VIEW; + break; + + case KEY_PIPE_ITEM: + page = HELP_PIPE; + break; + + case KEY_RAISE_PRIORITY: + case KEY_LOWER_PRIORITY: + page = HELP_PRIORITY; + break; + + case KEY_GENERIC_CHANGE_VIEW: + page = HELP_TAB; + break; + + case KEY_GENERIC_CREDITS: + page = HELP_CREDITS; + break; + + default: + page = NOPAGE; + break; + } - return (page); + return page; } /* Draws the help screen */ -void -help_screen (void) +void help_screen(void) { enum { MOVE_UP, @@ -336,452 +329,460 @@ help_screen (void) char keystr[DIRECTIONS][BUFSIZ]; hscr[HELP_MAIN].title = - _(" Welcome to Calcurse. This is the main help screen.\n"); - (void)snprintf (hscr[HELP_MAIN].text, HELPTEXTSIZ, - _("Moving around: Press '%s' or '%s' to scroll text upward or downward\n" - " inside help screens, if necessary.\n\n" - " Exit help: When finished, press '%s' to exit help and go back to\n" - " the main Calcurse screen.\n\n" - " Help topic: At the bottom of this screen you can see a panel with\n" - " different fields, represented by a letter and a short\n" - " title. This panel contains all the available actions\n" - " you can perform when using Calcurse.\n" - " By pressing one of the letters appearing in this\n" - " panel, you will be shown a short description of the\n" - " corresponding action. At the top right side of the\n" - " description screen are indicated the user-defined key\n" - " bindings that lead to the action.\n\n" - " Credits: Press '%s' for credits."), - keys_action_firstkey (KEY_GENERIC_SCROLL_UP), - keys_action_firstkey (KEY_GENERIC_SCROLL_DOWN), - keys_action_firstkey (KEY_GENERIC_QUIT), - keys_action_firstkey (KEY_GENERIC_CREDITS)); + _(" Welcome to Calcurse. This is the main help screen.\n"); + snprintf(hscr[HELP_MAIN].text, HELPTEXTSIZ, + _ + ("Moving around: Press '%s' or '%s' to scroll text upward or downward\n" + " inside help screens, if necessary.\n\n" + " Exit help: When finished, press '%s' to exit help and go back to\n" + " the main Calcurse screen.\n\n" + " Help topic: At the bottom of this screen you can see a panel with\n" + " different fields, represented by a letter and a short\n" + " title. This panel contains all the available actions\n" + " you can perform when using Calcurse.\n" + " By pressing one of the letters appearing in this\n" + " panel, you will be shown a short description of the\n" + " corresponding action. At the top right side of the\n" + " description screen are indicated the user-defined key\n" + " bindings that lead to the action.\n\n" + " Credits: Press '%s' for credits."), + keys_action_firstkey(KEY_GENERIC_SCROLL_UP), + keys_action_firstkey(KEY_GENERIC_SCROLL_DOWN), + keys_action_firstkey(KEY_GENERIC_QUIT), + keys_action_firstkey(KEY_GENERIC_CREDITS)); hscr[HELP_SAVE].title = _("Save\n"); - (void)snprintf (hscr[HELP_SAVE].text, HELPTEXTSIZ, - _("Save calcurse data.\n" - "Data are splitted into four different files which contain :" - "\n\n" - " / ~/.calcurse/conf -> user configuration\n" - " | (layout, color, general options)\n" - " | ~/.calcurse/apts -> data related to the appointments\n" - " | ~/.calcurse/todo -> data related to the todo list\n" - " \\ ~/.calcurse/keys -> user-defined key bindings\n" - "\nIn the config menu, you can choose to save the Calcurse data\n" - "automatically before quitting.")); + snprintf(hscr[HELP_SAVE].text, HELPTEXTSIZ, + _("Save calcurse data.\n" + "Data are splitted into four different files which contain :" + "\n\n" + " / ~/.calcurse/conf -> user configuration\n" + " | (layout, color, general options)\n" + " | ~/.calcurse/apts -> data related to the appointments\n" + " | ~/.calcurse/todo -> data related to the todo list\n" + " \\ ~/.calcurse/keys -> user-defined key bindings\n" + "\nIn the config menu, you can choose to save the Calcurse data\n" + "automatically before quitting.")); hscr[HELP_IMPORT].title = _("Import\n"); - (void)snprintf (hscr[HELP_IMPORT].text, HELPTEXTSIZ, - _("Import data from an icalendar file.\n" - "You will be asked to enter the file name from which to load ical\n" - "items. At the end of the import process, and if the general option\n" - "'skip_system_dialogs' is not set to 'yes', a report indicating how\n" - "many items were imported is shown.\n" - "This report contains the total number of lines read, the number of\n" - "appointments, events and todo items which were successfully imported,\n" - "together with the number of items for which problems occured and that\n" - "were skipped, if any.\n\n" - "If one or more items could not be imported, one has the possibility to\n" - "read the import process report in order to identify which problems\n" - "occured.\n" - "In this report is shown one item per line, with the line in the input\n" - "stream at which this item begins, together with the description of why\n" - "the item could not be imported.\n")); + snprintf(hscr[HELP_IMPORT].text, HELPTEXTSIZ, + _("Import data from an icalendar file.\n" + "You will be asked to enter the file name from which to load ical\n" + "items. At the end of the import process, and if the general option\n" + "'system_dialogs' is set to 'yes', a report indicating how many items\n" + "were imported is shown.\n" + "This report contains the total number of lines read, the number of\n" + "appointments, events and todo items which were successfully imported,\n" + "together with the number of items for which problems occured and that\n" + "were skipped, if any.\n\n" + "If one or more items could not be imported, one has the possibility to\n" + "read the import process report in order to identify which problems\n" + "occured.\n" + "In this report is shown one item per line, with the line in the input\n" + "stream at which this item begins, together with the description of why\n" + "the item could not be imported.\n")); hscr[HELP_EXPORT].title = _("Export\n"); - (void)snprintf (hscr[HELP_EXPORT].text, HELPTEXTSIZ, - _("Export calcurse data (appointments, events and todos).\n" - "This leads to the export submenu, from which you can choose between\n" - "two different export formats: 'ical' and 'pcal'. Choosing one of\n" - "those formats lets you export calcurse data to icalendar or pcal\n" - "format.\n\n" - "You first need to specify the file to which the data will be exported.\n" - "By default, this file is:\n\n" - " ~/calcurse.ics\n\n" - "for an ical export, and:\n\n" - " ~/calcurse.txt\n\n" - "for a pcal export.\n\n" - "Calcurse data are exported in the following order:\n" - " events, appointments, todos.\n")); - - (void)strncpy (keystr[MOVE_UP], keys_action_allkeys (KEY_MOVE_UP), BUFSIZ); - (void)strncpy (keystr[MOVE_DOWN], keys_action_allkeys (KEY_MOVE_DOWN), - BUFSIZ); - (void)strncpy (keystr[MOVE_LEFT], keys_action_allkeys (KEY_MOVE_LEFT), - BUFSIZ); - (void)strncpy (keystr[MOVE_RIGHT], keys_action_allkeys (KEY_MOVE_RIGHT), - BUFSIZ); + snprintf(hscr[HELP_EXPORT].text, HELPTEXTSIZ, + _("Export calcurse data (appointments, events and todos).\n" + "This leads to the export submenu, from which you can choose between\n" + "two different export formats: 'ical' and 'pcal'. Choosing one of\n" + "those formats lets you export calcurse data to icalendar or pcal\n" + "format.\n\n" + "You first need to specify the file to which the data will be exported.\n" + "By default, this file is:\n\n" + " ~/calcurse.ics\n\n" + "for an ical export, and:\n\n" + " ~/calcurse.txt\n\n" + "for a pcal export.\n\n" + "Calcurse data are exported in the following order:\n" + " events, appointments, todos.\n")); + + strncpy(keystr[MOVE_UP], keys_action_allkeys(KEY_MOVE_UP), BUFSIZ); + strncpy(keystr[MOVE_DOWN], keys_action_allkeys(KEY_MOVE_DOWN), BUFSIZ); + strncpy(keystr[MOVE_LEFT], keys_action_allkeys(KEY_MOVE_LEFT), BUFSIZ); + strncpy(keystr[MOVE_RIGHT], keys_action_allkeys(KEY_MOVE_RIGHT), BUFSIZ); hscr[HELP_DISPLACEMENT].title = _("Displacement keys\n"); - (void)snprintf (hscr[HELP_DISPLACEMENT].text, HELPTEXTSIZ, - _("Move around inside calcurse screens.\n" - "The following scheme summarizes how to get around:\n\n" - " move up\n" - " move to previous week\n" - "\n" - " %s\n" - " move left ^ \n" - " move to previous day |\n" - " %s\n" - " <-- + -->\n" - " %s\n" - " | move right\n" - " v move to next day\n" - " %s\n" - "\n" - " move to next week\n" - " move down\n" - "\nMoreover, while inside the calendar panel, the '%s' key moves\n" - "to the first day of the week, and the '%s' key selects the last day of\n" - "the week.\n"), - keystr[MOVE_UP], keystr[MOVE_LEFT], - keystr[MOVE_RIGHT], keystr[MOVE_DOWN], - keys_action_firstkey (KEY_START_OF_WEEK), - keys_action_firstkey (KEY_END_OF_WEEK)); + snprintf(hscr[HELP_DISPLACEMENT].text, HELPTEXTSIZ, + _("Move around inside calcurse screens.\n" + "The following scheme summarizes how to get around:\n\n" + " move up\n" + " move to previous week\n" + "\n" + " %s\n" + " move left ^ \n" + " move to previous day |\n" + " %s\n" + " <-- + -->\n" + " %s\n" + " | move right\n" + " v move to next day\n" + " %s\n" + "\n" + " move to next week\n" + " move down\n" + "\nMoreover, while inside the calendar panel, the '%s' key moves\n" + "to the first day of the week, and the '%s' key selects the last day of\n" + "the week.\n"), + keystr[MOVE_UP], keystr[MOVE_LEFT], + keystr[MOVE_RIGHT], keystr[MOVE_DOWN], + keys_action_firstkey(KEY_START_OF_WEEK), + keys_action_firstkey(KEY_END_OF_WEEK)); hscr[HELP_VIEW].title = _("View\n"); - (void)snprintf (hscr[HELP_VIEW].text, HELPTEXTSIZ, - _("View the item you select in either the Todo or Appointment panel.\n" - "\nThis is usefull when an event description is longer than the " - "available\nspace to display it. " - "If that is the case, the description will be\n" - "shortened and its end replaced by '...'. To be able to read the entire\n" - "description, just press '%s' and a popup window will appear, containing\n" - "the whole event.\n" - "\nPress any key to close the popup window and go back to the main\n" - "Calcurse screen."), - keys_action_firstkey (KEY_VIEW_ITEM)); + snprintf(hscr[HELP_VIEW].text, HELPTEXTSIZ, + _ + ("View the item you select in either the Todo or Appointment panel.\n" + "\nThis is usefull when an event description is longer than the " + "available\nspace to display it. " + "If that is the case, the description will be\n" + "shortened and its end replaced by '...'. To be able to read the entire\n" + "description, just press '%s' and a popup window will appear, containing\n" + "the whole event.\n" + "\nPress any key to close the popup window and go back to the main\n" + "Calcurse screen."), keys_action_firstkey(KEY_VIEW_ITEM)); + + hscr[HELP_PIPE].title = _("Pipe\n"); + snprintf(hscr[HELP_PIPE].text, HELPTEXTSIZ, + _("Pipe the selected item to an external program.\n" + "\nPress the '%s' key to pipe the currently selected appointment or\n" + "todo entry to an external program.\n" + "\nYou will be driven back to calcurse as soon as the program exits.\n"), + keys_action_firstkey(KEY_PIPE_ITEM)); hscr[HELP_TAB].title = _("Tab\n"); - (void)snprintf (hscr[HELP_TAB].text, HELPTEXTSIZ, - _("Switch between panels.\n" - "The panel currently in use has its border colorized.\n" - "\nSome actions are possible only if the right panel is selected.\n" - "For example, if you want to add a task in the TODO list, you need first" - "\nto press the '%s' key to get the TODO panel selected. Then you can\n" - "press '%s' to add your item.\n" - "\nNotice that at the bottom of the screen the list of possible actions\n" - "change while pressing '%s', so you always know what action can be\n" - "performed on the selected panel."), - keys_action_firstkey (KEY_GENERIC_CHANGE_VIEW), - keys_action_firstkey (KEY_ADD_ITEM), - keys_action_firstkey (KEY_GENERIC_CHANGE_VIEW)); + snprintf(hscr[HELP_TAB].text, HELPTEXTSIZ, + _("Switch between panels.\n" + "The panel currently in use has its border colorized.\n" + "\nSome actions are possible only if the right panel is selected.\n" + "For example, if you want to add a task in the TODO list, you need first" + "\nto press the '%s' key to get the TODO panel selected. Then you can\n" + "press '%s' to add your item.\n" + "\nNotice that at the bottom of the screen the list of possible actions\n" + "change while pressing '%s', so you always know what action can be\n" + "performed on the selected panel."), + keys_action_firstkey(KEY_GENERIC_CHANGE_VIEW), + keys_action_firstkey(KEY_ADD_ITEM), + keys_action_firstkey(KEY_GENERIC_CHANGE_VIEW)); hscr[HELP_GOTO].title = _("Goto\n"); - (void)snprintf (hscr[HELP_GOTO].text, HELPTEXTSIZ, - _("Jump to a specific day in the calendar.\n" - "\nUsing this command, you do not need to travel to that day using\n" - "the displacement keys inside the calendar panel.\n" - "If you hit [ENTER] without specifying any date, Calcurse checks the\n" - "system current date and you will be taken to that date.\n" - "\nNotice that pressing '%s', whatever panel is\n" - "selected, will select current day in the calendar."), - keys_action_firstkey (KEY_GENERIC_GOTO_TODAY)); + snprintf(hscr[HELP_GOTO].text, HELPTEXTSIZ, + _("Jump to a specific day in the calendar.\n" + "\nUsing this command, you do not need to travel to that day using\n" + "the displacement keys inside the calendar panel.\n" + "If you hit [ENTER] without specifying any date, Calcurse checks the\n" + "system current date and you will be taken to that date.\n" + "\nNotice that pressing '%s', whatever panel is\n" + "selected, will select current day in the calendar."), + keys_action_firstkey(KEY_GENERIC_GOTO_TODAY)); hscr[HELP_DELETE].title = _("Delete\n"); - (void)snprintf (hscr[HELP_DELETE].text, HELPTEXTSIZ, - _("Delete an element in the ToDo or Appointment list.\n" - "\nDepending on which panel is selected when you press the delete key,\n" - "the hilighted item of either the ToDo or Appointment list will be \n" - "removed from this list.\n" - "\nIf the item to be deleted is recurrent, you will be asked if you\n" - "wish to suppress all of the item occurences or just the one you\n" - "selected.\n" - "\nIf the general option 'confirm_delete' is set to 'YES', then you will" - "\nbe asked for confirmation before deleting the selected event.\n" - "Do not forget to save the calendar data to retrieve the modifications\n" - "next time you launch Calcurse.")); + snprintf(hscr[HELP_DELETE].text, HELPTEXTSIZ, + _("Delete an element in the ToDo or Appointment list.\n" + "\nDepending on which panel is selected when you press the delete key,\n" + "the hilighted item of either the ToDo or Appointment list will be \n" + "removed from this list.\n" + "\nIf the item to be deleted is recurrent, you will be asked if you\n" + "wish to suppress all of the item occurences or just the one you\n" + "selected.\n" + "\nIf the general option 'confirm_delete' is set to 'YES', then you will" + "\nbe asked for confirmation before deleting the selected event.\n" + "Do not forget to save the calendar data to retrieve the modifications\n" + "next time you launch Calcurse.")); hscr[HELP_ADD].title = _("Add\n"); - (void)snprintf (hscr[HELP_ADD].text, HELPTEXTSIZ, - _("Add an item in either the ToDo or Appointment list, depending on which\n" - "panel is selected when you press '%s'.\n" - "\nTo enter a new item in the TODO list, you will need first to enter the" - "\ndescription of this new item. Then you will be asked to specify the " - "todo\npriority. This priority is represented by a number going from 9 " - "for the\nlowest priority, to 1 for the highest one. It is still " - "possible to\nchange the item priority afterwards, by using the '%s' and " - "'%s' keys\ninside the todo panel.\n" - "\nIf the APPOINTMENT panel is selected while pressing '%s', you will be\n" - "able to enter either a new appointment or a new all-day long event.\n" - "To enter a new event, press [ENTER] instead of the item start time, " - "and\njust fill in the event description.\n" - "To enter a new appointment to be added in the APPOINTMENT list, you\n" - "will need to enter successively the time at which the appointment\n" - "begins, the appointment length (either by specifying the duration in\n" - "minutes, or the end time in [hh:mm] or [h:mm] format), and the\n" - "description of the event.\n" - "\nThe day at which occurs the event or appointment is the day currently" - "\nselected in the calendar, so you need to move to the desired day " - "before\npressing '%s'.\n" "\nNotes:\n" - " o if an appointment lasts for such a long time that it continues\n" - " on the next days, this event will be indicated on all the\n" - " corresponding days, and the beginning or ending hour will be\n" - " replaced by '..' if the event does not begin or end on the day.\n" - " o if you only press [ENTER] at the APPOINTMENT or TODO event\n" - " description prompt, without any description, no item will be\n" - " added.\n" - " o do not forget to save the calendar data to retrieve the new\n" - " event next time you launch Calcurse."), - keys_action_firstkey (KEY_ADD_ITEM), - keys_action_firstkey (KEY_RAISE_PRIORITY), - keys_action_firstkey (KEY_LOWER_PRIORITY), - keys_action_firstkey (KEY_ADD_ITEM), - keys_action_firstkey (KEY_ADD_ITEM)); + snprintf(hscr[HELP_ADD].text, HELPTEXTSIZ, + _ + ("Add an item in either the ToDo or Appointment list, depending on which\n" + "panel is selected when you press '%s'.\n" + "\nTo enter a new item in the TODO list, you will need first to enter the" + "\ndescription of this new item. Then you will be asked to specify the " + "todo\npriority. This priority is represented by a number going from 9 " + "for the\nlowest priority, to 1 for the highest one. It is still " + "possible to\nchange the item priority afterwards, by using the '%s' and " + "'%s' keys\ninside the todo panel.\n" + "\nIf the APPOINTMENT panel is selected while pressing '%s', you will be\n" + "able to enter either a new appointment or a new all-day long event.\n" + "To enter a new event, press [ENTER] instead of the item start time, " + "and\njust fill in the event description.\n" + "To enter a new appointment to be added in the APPOINTMENT list, you\n" + "will need to enter successively the time at which the appointment\n" + "begins, the appointment length (either by specifying the end time in\n" + "[hh:mm] or the duration in [+hh:mm], [+xxdxxhxxm] or [+mm] format), \n" + "and the description of the event.\n" + "\nThe day at which occurs the event or appointment is the day currently" + "\nselected in the calendar, so you need to move to the desired day " + "before\npressing '%s'.\n" "\nNotes:\n" + " o if an appointment lasts for such a long time that it continues\n" + " on the next days, this event will be indicated on all the\n" + " corresponding days, and the beginning or ending hour will be\n" + " replaced by '..' if the event does not begin or end on the day.\n" + " o if you only press [ENTER] at the APPOINTMENT or TODO event\n" + " description prompt, without any description, no item will be\n" + " added.\n" + " o do not forget to save the calendar data to retrieve the new\n" + " event next time you launch Calcurse."), + keys_action_firstkey(KEY_ADD_ITEM), + keys_action_firstkey(KEY_RAISE_PRIORITY), + keys_action_firstkey(KEY_LOWER_PRIORITY), + keys_action_firstkey(KEY_ADD_ITEM), + keys_action_firstkey(KEY_ADD_ITEM)); hscr[HELP_CUT_PASTE].title = _("Cut and Paste\n"); - (void)snprintf (hscr[HELP_CUT_PASTE].text, HELPTEXTSIZ, - _("Cut and paste the currently selected item. This is useful to quickly\n" - "move an item from one date to another.\n" - "To do so, one must first highlight the item that needs to be moved,\n" - "then press '%s' to cut this item. It will be removed from the panel.\n" - "Once the new date is chosen in the calendar, the appointment panel must\n" - "be selected and the '%s' key must be pressed to paste the item.\n" - "The item will appear again in the appointment panel, assigned to the\n" - "newly selected date.\n\n" - "Be careful that if two cuts are performed successively without pasting\n" - "between them, the item that was cut at first will be lost, together\n" - "with its associated note if it had one."), - keys_action_firstkey (KEY_GENERIC_CUT), - keys_action_firstkey (KEY_GENERIC_PASTE)); + snprintf(hscr[HELP_CUT_PASTE].text, HELPTEXTSIZ, + _ + ("Cut and paste the currently selected item. This is useful to quickly\n" + "move an item from one date to another.\n" + "To do so, one must first highlight the item that needs to be moved,\n" + "then press '%s' to cut this item. It will be removed from the panel.\n" + "Once the new date is chosen in the calendar, the appointment panel must\n" + "be selected and the '%s' key must be pressed to paste the item.\n" + "The item will appear again in the appointment panel, assigned to the\n" + "newly selected date.\n\n" + "Be careful that if two cuts are performed successively without pasting\n" + "between them, the item that was cut at first will be lost, together\n" + "with its associated note if it had one."), + keys_action_firstkey(KEY_GENERIC_CUT), + keys_action_firstkey(KEY_GENERIC_PASTE)); hscr[HELP_EDIT].title = _("Edit Item\n"); - (void)snprintf (hscr[HELP_EDIT].text, HELPTEXTSIZ, - _("Edit the item which is currently selected.\n" - "Depending on the item type (appointment, event, or todo), and if it is\n" - "repeated or not, you will be asked to choose one of the item properties" - "\nto modify. An item property is one of the following: the start time, " - "the\nend time, the description, or the item repetition.\n" - "Once you have chosen the property you want to modify, you will be shown" - "\nits actual value, and you will be able to change it as you like.\n" - "\nNotes:\n" - " o if you choose to edit the item repetition properties, you will\n" - " be asked to re-enter all of the repetition characteristics\n" - " (repetition type, frequence, and ending date). Moreover, the\n" - " previous data concerning the deleted occurences will be lost.\n" - " o do not forget to save the calendar data to retrieve the\n" - " modified properties next time you launch Calcurse.")); + snprintf(hscr[HELP_EDIT].text, HELPTEXTSIZ, + _("Edit the item which is currently selected.\n" + "Depending on the item type (appointment, event, or todo), and if it is\n" + "repeated or not, you will be asked to choose one of the item properties" + "\nto modify. An item property is one of the following: the start time, " + "the\nend time, the description, or the item repetition.\n" + "Once you have chosen the property you want to modify, you will be shown" + "\nits actual value, and you will be able to change it as you like.\n" + "\nNotes:\n" + " o if you choose to edit the item repetition properties, you will\n" + " be asked to re-enter all of the repetition characteristics\n" + " (repetition type, frequence, and ending date). Moreover, the\n" + " previous data concerning the deleted occurences will be lost.\n" + " o do not forget to save the calendar data to retrieve the\n" + " modified properties next time you launch Calcurse.")); hscr[HELP_ENOTE].title = _("EditNote\n"); - (void)snprintf (hscr[HELP_ENOTE].text, HELPTEXTSIZ, - _("Attach a note to any type of item, or edit an already existing note.\n" - "This feature is useful if you do not have enough space to store all\n" - "of your item description, or if you would like to add sub-tasks to an\n" - "already existing todo item for example.\n" - "Before pressing the '%s' key, you first need to highlight the item you\n" - "want the note to be attached to. Then you will be driven to an\n" - "external editor to edit your note. This editor is chosen the following\n" - "way:\n" - " o if the 'VISUAL' environment variable is set, then this will be\n" - " the default editor to be called.\n" - " o if 'VISUAL' is not set, then the 'EDITOR' environment variable\n" - " will be used as the default editor.\n" - " o if none of the above environment variables is set, then\n" - " '/usr/bin/vi' will be used.\n" - "\nOnce the item note is edited and saved, quit your favorite editor.\n" - "You will then go back to Calcurse, and the '>' sign will appear in front" - "\nof the highlighted item, meaning there is a note attached to it."), - keys_action_firstkey (KEY_EDIT_NOTE)); + snprintf(hscr[HELP_ENOTE].text, HELPTEXTSIZ, + _ + ("Attach a note to any type of item, or edit an already existing note.\n" + "This feature is useful if you do not have enough space to store all\n" + "of your item description, or if you would like to add sub-tasks to an\n" + "already existing todo item for example.\n" + "Before pressing the '%s' key, you first need to highlight the item you\n" + "want the note to be attached to. Then you will be driven to an\n" + "external editor to edit your note. This editor is chosen the following\n" + "way:\n" + " o if the 'VISUAL' environment variable is set, then this will be\n" + " the default editor to be called.\n" + " o if 'VISUAL' is not set, then the 'EDITOR' environment variable\n" + " will be used as the default editor.\n" + " o if none of the above environment variables is set, then\n" + " '/usr/bin/vi' will be used.\n" + "\nOnce the item note is edited and saved, quit your favorite editor.\n" + "You will then go back to Calcurse, and the '>' sign will appear in front" + "\nof the highlighted item, meaning there is a note attached to it."), + keys_action_firstkey(KEY_EDIT_NOTE)); hscr[HELP_VNOTE].title = _("ViewNote\n"); - (void)snprintf (hscr[HELP_VNOTE].text, HELPTEXTSIZ, - _("View a note which was previously attached to an item (an item which\n" - "owns a note has a '>' sign in front of it).\n" - "This command only permits to view the note, not to edit it (to do so,\n" - "use the 'EditNote' command, by pressing the '%s' key).\n" - "Once you highlighted an item with a note attached to it, and the '%s' key" - "\nwas pressed, you will be driven to an external pager to view that " - "note.\n" - "The default pager is chosen the following way:\n" - " o if the 'PAGER' environment variable is set, then this will be\n" - " the default viewer to be called.\n" - " o if the above environment variable is not set, then\n" - " '/usr/bin/less' will be used.\n" - "As for editing a note, quit the pager and you will be driven back to\n" - "Calcurse."), - keys_action_firstkey (KEY_EDIT_NOTE), - keys_action_firstkey (KEY_VIEW_NOTE)); + snprintf(hscr[HELP_VNOTE].text, HELPTEXTSIZ, + _ + ("View a note which was previously attached to an item (an item which\n" + "owns a note has a '>' sign in front of it).\n" + "This command only permits to view the note, not to edit it (to do so,\n" + "use the 'EditNote' command, by pressing the '%s' key).\n" + "Once you highlighted an item with a note attached to it, and the '%s' key" + "\nwas pressed, you will be driven to an external pager to view that " + "note.\n" "The default pager is chosen the following way:\n" + " o if the 'PAGER' environment variable is set, then this will be\n" + " the default viewer to be called.\n" + " o if the above environment variable is not set, then\n" + " '/usr/bin/less' will be used.\n" + "As for editing a note, quit the pager and you will be driven back to\n" + "Calcurse."), keys_action_firstkey(KEY_EDIT_NOTE), + keys_action_firstkey(KEY_VIEW_NOTE)); hscr[HELP_PRIORITY].title = _("Priority\n"); - (void)snprintf (hscr[HELP_PRIORITY].text, HELPTEXTSIZ, - _("Change the priority of the currently selected item in the ToDo list.\n" - "Priorities are represented by the number appearing in front of the\n" - "todo description. This number goes from 9 for the lowest priority to\n" - "1 for the highest priority.\n" - "Todo having higher priorities are placed first (at the top) inside the\n" - "todo panel.\n\n" - "If you want to raise the priority of a todo item, you need to press " - "'%s'.\n" - "In doing so, the number in front of this item will decrease, " - "meaning its\npriority increases. The item position inside the todo " - "panel may change,\ndepending on the priority of the items above it.\n\n" - "At the opposite, to lower a todo priority, press '%s'. The todo position" - "\nmay also change depending on the priority of the items below."), - keys_action_firstkey (KEY_RAISE_PRIORITY), - keys_action_firstkey (KEY_LOWER_PRIORITY)); + snprintf(hscr[HELP_PRIORITY].text, HELPTEXTSIZ, + _ + ("Change the priority of the currently selected item in the ToDo list.\n" + "Priorities are represented by the number appearing in front of the\n" + "todo description. This number goes from 9 for the lowest priority to\n" + "1 for the highest priority.\n" + "Todo having higher priorities are placed first (at the top) inside the\n" + "todo panel.\n\n" + "If you want to raise the priority of a todo item, you need to press " + "'%s'.\n" + "In doing so, the number in front of this item will decrease, " + "meaning its\npriority increases. The item position inside the todo " + "panel may change,\ndepending on the priority of the items above it.\n\n" + "At the opposite, to lower a todo priority, press '%s'. The todo position" + "\nmay also change depending on the priority of the items below."), + keys_action_firstkey(KEY_RAISE_PRIORITY), + keys_action_firstkey(KEY_LOWER_PRIORITY)); hscr[HELP_REPEAT].title = _("Repeat\n"); - (void)snprintf (hscr[HELP_REPEAT].text, HELPTEXTSIZ, - _("Repeat an event or an appointment.\n" - "You must first select the item to be repeated by moving inside the\n" - "appointment panel. Then pressing '%s' will lead you to a set of three\n" - "questions, with which you will be able to specify the repetition\n" - "characteristics:\n\n" - " o type: you can choose between a daily, weekly, monthly or\n" - " yearly repetition by pressing 'D', 'W', 'M' or 'Y'\n" - " respectively.\n\n" - " o frequence: this indicates how often the item shall be repeated.\n" - " For example, if you want to remember an anniversary,\n" - " choose a 'yearly' repetition with a frequence of '1',\n" - " which means it must be repeated every year. Another\n" - " example: if you go to the restaurant every two days,\n" - " choose a 'daily' repetition with a frequence of '2'.\n\n" - " o ending date: this specifies when to stop repeating the selected\n" - " event or appointment. To indicate an endless \n" - " repetition, enter '0' and the item will be repeated\n" - " forever.\n" "\nNotes:\n" - " o repeated items are marked with an '*' inside the appointment\n" - " panel, to be easily recognizable from non-repeated ones.\n" - " o the 'Repeat' and 'Delete' command can be mixed to create\n" - " complicated configurations, as it is possible to delete only\n" - " one occurence of a repeated item."), - keys_action_firstkey (KEY_REPEAT_ITEM)); + snprintf(hscr[HELP_REPEAT].text, HELPTEXTSIZ, + _("Repeat an event or an appointment.\n" + "You must first select the item to be repeated by moving inside the\n" + "appointment panel. Then pressing '%s' will lead you to a set of three\n" + "questions, with which you will be able to specify the repetition\n" + "characteristics:\n\n" + " o type: you can choose between a daily, weekly, monthly or\n" + " yearly repetition by pressing 'D', 'W', 'M' or 'Y'\n" + " respectively.\n\n" + " o frequence: this indicates how often the item shall be repeated.\n" + " For example, if you want to remember an anniversary,\n" + " choose a 'yearly' repetition with a frequence of '1',\n" + " which means it must be repeated every year. Another\n" + " example: if you go to the restaurant every two days,\n" + " choose a 'daily' repetition with a frequence of '2'.\n\n" + " o ending date: this specifies when to stop repeating the selected\n" + " event or appointment. To indicate an endless \n" + " repetition, enter '0' and the item will be repeated\n" + " forever.\n" "\nNotes:\n" + " o repeated items are marked with an '*' inside the appointment\n" + " panel, to be easily recognizable from non-repeated ones.\n" + " o the 'Repeat' and 'Delete' command can be mixed to create\n" + " complicated configurations, as it is possible to delete only\n" + " one occurence of a repeated item."), + keys_action_firstkey(KEY_REPEAT_ITEM)); hscr[HELP_FLAG].title = _("Flag Item\n"); - (void)snprintf (hscr[HELP_FLAG].text, HELPTEXTSIZ, - _("Toggle an appointment's 'important' flag or a todo's 'completed' flag.\n" - "If a todo is flagged as completed, its priority number will be replaced\n" - "by an 'X' sign. Completed tasks will no longer appear in exported data\n" - "or when using the '-t' command line flag (unless specifying '0' as the\n" - "priority number, in which case only completed tasks will be shown).\n\n" - "If an appointment is flagged as important, an exclamation mark appears\n" - "in front of it, and you will be warned if time gets closed to the\n" - "appointment start time.\n" - "To customize the way one gets notified, the configuration submenu lets\n" - "you choose the command launched to warn user of an upcoming appointment," - "\nand how long before it he gets notified.")); + snprintf(hscr[HELP_FLAG].text, HELPTEXTSIZ, + _ + ("Toggle an appointment's 'important' flag or a todo's 'completed' flag.\n" + "If a todo is flagged as completed, its priority number will be replaced\n" + "by an 'X' sign. Completed tasks will no longer appear in exported data\n" + "or when using the '-t' command line flag (unless specifying '0' as the\n" + "priority number, in which case only completed tasks will be shown).\n\n" + "If an appointment is flagged as important, an exclamation mark appears\n" + "in front of it, and you will be warned if time gets closed to the\n" + "appointment start time.\n" + "To customize the way one gets notified, the configuration submenu lets\n" + "you choose the command launched to warn user of an upcoming appointment," + "\nand how long before it he gets notified.")); hscr[HELP_CONFIG].title = _("Config\n"); - (void)snprintf (hscr[HELP_CONFIG].text, HELPTEXTSIZ, - _("Open the configuration submenu.\n" - "From this submenu, you can select between color, layout, notification\n" - "and general options, and you can also configure your keybindings.\n" - "\nThe color submenu lets you choose the color theme.\n" - "The layout submenu lets you choose the Calcurse screen layout, in other" - "\nwords where to place the three different panels on the screen.\n" - "The general options submenu brings a screen with the different options" - "\nwhich modifies the way Calcurse interacts with the user.\n" - "The notify submenu allows you to change the notify-bar settings.\n" - "The keys submenu lets you define your own key bindings.\n" - "\nDo not forget to save the calendar data to retrieve your configuration" - "\nnext time you launch Calcurse.")); + snprintf(hscr[HELP_CONFIG].text, HELPTEXTSIZ, + _("Open the configuration submenu.\n" + "From this submenu, you can select between color, layout, notification\n" + "and general options, and you can also configure your keybindings.\n" + "\nThe color submenu lets you choose the color theme.\n" + "The layout submenu lets you choose the Calcurse screen layout, in other" + "\nwords where to place the three different panels on the screen.\n" + "The general options submenu brings a screen with the different options" + "\nwhich modifies the way Calcurse interacts with the user.\n" + "The notify submenu allows you to change the notify-bar settings.\n" + "The keys submenu lets you define your own key bindings.\n" + "\nDo not forget to save the calendar data to retrieve your configuration" + "\nnext time you launch Calcurse.")); hscr[HELP_GENERAL].title = _("Generic keybindings\n"); - (void)snprintf (hscr[HELP_GENERAL].text, HELPTEXTSIZ, - _("Some of the keybindings apply whatever panel is selected. They are\n" - "called generic keybinding.\n" - "Here is the list of all the generic key bindings, together with their\n" - "corresponding action:\n\n" - " '%s' : Redraw function -> redraws calcurse panels, this is useful if\n" - " you resize your terminal screen or when\n" - " garbage appears inside the display\n" - " '%s' : Add Appointment -> add an appointment or an event\n" - " '%s' : Add ToDo -> add a todo\n" - " '%s' : -1 Day -> move to previous day\n" - " '%s' : +1 Day -> move to next day\n" - " '%s' : -1 Week -> move to previous week\n" - " '%s' : +1 Week -> move to next week\n" - " '%s' : Goto today -> move to current day\n" - "\nThe '%s' and '%s' keys are used to scroll text upward or downward\n" - "when inside specific screens such the help screens for example.\n" - "They are also used when the calendar screen is selected to switch\n" - "between the available views (monthly and weekly calendar views)."), - keys_action_firstkey (KEY_GENERIC_REDRAW), - keys_action_firstkey (KEY_GENERIC_ADD_APPT), - keys_action_firstkey (KEY_GENERIC_ADD_TODO), - keys_action_firstkey (KEY_GENERIC_PREV_DAY), - keys_action_firstkey (KEY_GENERIC_NEXT_DAY), - keys_action_firstkey (KEY_GENERIC_PREV_WEEK), - keys_action_firstkey (KEY_GENERIC_NEXT_WEEK), - keys_action_firstkey (KEY_GENERIC_GOTO_TODAY), - keys_action_firstkey (KEY_GENERIC_SCROLL_UP), - keys_action_firstkey (KEY_GENERIC_SCROLL_DOWN)); + snprintf(hscr[HELP_GENERAL].text, HELPTEXTSIZ, + _ + ("Some of the keybindings apply whatever panel is selected. They are\n" + "called generic keybinding.\n" + "Here is the list of all the generic key bindings, together with their\n" + "corresponding action:\n\n" + " '%s' : Redraw function -> redraws calcurse panels, this is useful if\n" + " you resize your terminal screen or when\n" + " garbage appears inside the display\n" + " '%s' : Add Appointment -> add an appointment or an event\n" + " '%s' : Add ToDo -> add a todo\n" + " '%s' : -1 Day -> move to previous day\n" + " '%s' : +1 Day -> move to next day\n" + " '%s' : -1 Week -> move to previous week\n" + " '%s' : +1 Week -> move to next week\n" + " '%s' : Goto today -> move to current day\n" + "\nThe '%s' and '%s' keys are used to scroll text upward or downward\n" + "when inside specific screens such the help screens for example.\n" + "They are also used when the calendar screen is selected to switch\n" + "between the available views (monthly and weekly calendar views)."), + keys_action_firstkey(KEY_GENERIC_REDRAW), + keys_action_firstkey(KEY_GENERIC_ADD_APPT), + keys_action_firstkey(KEY_GENERIC_ADD_TODO), + keys_action_firstkey(KEY_GENERIC_PREV_DAY), + keys_action_firstkey(KEY_GENERIC_NEXT_DAY), + keys_action_firstkey(KEY_GENERIC_PREV_WEEK), + keys_action_firstkey(KEY_GENERIC_NEXT_WEEK), + keys_action_firstkey(KEY_GENERIC_GOTO_TODAY), + keys_action_firstkey(KEY_GENERIC_SCROLL_UP), + keys_action_firstkey(KEY_GENERIC_SCROLL_DOWN)); hscr[HELP_OTHER].title = _("OtherCmd\n"); - (void)snprintf (hscr[HELP_OTHER].text, HELPTEXTSIZ, - _("Switch between status bar help pages.\n" - "Because the terminal screen is too narrow to display all of the\n" - "available commands, you need to press '%s' to see the next set of\n" - "commands together with their keybindings.\n" - "Once the last status bar page is reached, pressing '%s' another time\n" - "leads you back to the first page."), - keys_action_firstkey (KEY_GENERIC_OTHER_CMD), - keys_action_firstkey (KEY_GENERIC_OTHER_CMD)); + snprintf(hscr[HELP_OTHER].text, HELPTEXTSIZ, + _("Switch between status bar help pages.\n" + "Because the terminal screen is too narrow to display all of the\n" + "available commands, you need to press '%s' to see the next set of\n" + "commands together with their keybindings.\n" + "Once the last status bar page is reached, pressing '%s' another time\n" + "leads you back to the first page."), + keys_action_firstkey(KEY_GENERIC_OTHER_CMD), + keys_action_firstkey(KEY_GENERIC_OTHER_CMD)); hscr[HELP_CREDITS].title = _("Calcurse - text-based organizer"); - (void)snprintf (hscr[HELP_CREDITS].text, HELPTEXTSIZ, - _("\nCopyright (c) 2004-2011 calcurse Development Team\n" - "All rights reserved.\n" - "\n" - "Redistribution and use in source and binary forms, with or without\n" - "modification, are permitted provided that the following conditions\n" - "are met:\n" - "\n" - "\t- Redistributions of source code must retain the above\n" - "\t copyright notice, this list of conditions and the\n" - "\t following disclaimer.\n" - "\n" - "\t- Redistributions in binary form must reproduce the above\n" - "\t copyright notice, this list of conditions and the\n" - "\t following disclaimer in the documentation and/or other\n" - "\t materials provided with the distribution.\n" - "\n\n" - "Send your feedback or comments to : misc@calcurse.org\n" - "Calcurse home page : http://calcurse.org")); - - help_wins_init (&hwin, 0, 0, (notify_bar ()) ? row - 3 : row - 2, col); + snprintf(hscr[HELP_CREDITS].text, HELPTEXTSIZ, + _("\nCopyright (c) 2004-2012 calcurse Development Team\n" + "All rights reserved.\n" + "\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n" + "\n" + "\t- Redistributions of source code must retain the above\n" + "\t copyright notice, this list of conditions and the\n" + "\t following disclaimer.\n" + "\n" + "\t- Redistributions in binary form must reproduce the above\n" + "\t copyright notice, this list of conditions and the\n" + "\t following disclaimer in the documentation and/or other\n" + "\t materials provided with the distribution.\n" + "\n\n" + "Send your feedback or comments to : misc@calcurse.org\n" + "Calcurse home page : http://calcurse.org")); + + help_wins_init(&hwin, 0, 0, (notify_bar())? row - 3 : row - 2, col); oldpage = HELP_MAIN; need_resize = 0; /* Display the help screen related to user input. */ - while (ch != KEY_GENERIC_QUIT) - { - erase_window_part (hwin.win.p, 1, hwin.pad.y, col - 2, - hwin.win.h - 2); - - switch (ch) { - case KEY_GENERIC_SCROLL_DOWN: - wins_scrollwin_down (&hwin, 1); - break; - - case KEY_GENERIC_SCROLL_UP: - wins_scrollwin_up (&hwin, 1); - break; - - default: - page = wanted_page (ch); - if (page != NOPAGE) { - hwin.first_visible_line = 0; - hwin.total_lines = help_write_pad (&hwin.pad, hscr[page].title, - hscr[page].text, ch); - oldpage = page; - } + while (ch != KEY_GENERIC_QUIT) { + erase_window_part(hwin.win.p, 1, hwin.pad.y, col - 2, hwin.win.h - 2); + + switch (ch) { + case KEY_GENERIC_SCROLL_DOWN: + wins_scrollwin_down(&hwin, 1); + break; + + case KEY_GENERIC_SCROLL_UP: + wins_scrollwin_up(&hwin, 1); + break; + + default: + page = wanted_page(ch); + if (page != NOPAGE) { + hwin.first_visible_line = 0; + hwin.total_lines = help_write_pad(&hwin.pad, hscr[page].title, + hscr[page].text, ch); + oldpage = page; } + } - if (resize) - { - resize = 0; - wins_get_config (); - help_wins_reset (&hwin); - hwin.first_visible_line = 0; - hwin.total_lines = help_write_pad (&hwin.pad, hscr[oldpage].title, - hscr[oldpage].text, ch); - need_resize = 1; - } - - wins_scrollwin_display (&hwin); - ch = keys_getch (win[STA].p); + if (resize) { + resize = 0; + wins_get_config(); + help_wins_reset(&hwin); + hwin.first_visible_line = 0; + hwin.total_lines = help_write_pad(&hwin.pad, hscr[oldpage].title, + hscr[oldpage].text, ch); + need_resize = 1; } - wins_scrollwin_delete (&hwin); + + wins_scrollwin_display(&hwin); + ch = keys_getch(win[STA].p, NULL); + } + wins_scrollwin_delete(&hwin); if (need_resize) - wins_reset (); + wins_reset(); } diff --git a/src/htable.h b/src/htable.h index 10d04c1..3bde5ef 100644 --- a/src/htable.h +++ b/src/htable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,9 +69,7 @@ struct name { \ } #define HTABLE_ENTRY(type) \ -struct { \ - struct type *next; /* To build the bucket chain list. */ \ -} +struct type *next /* To build the bucket chain list. */ #define HTABLE_SIZE(head) \ (sizeof (*(head)->bkts) ? sizeof ((head)->bkts) / sizeof (*(head)->bkts) : 0) @@ -106,7 +104,11 @@ struct { \ #define HTABLE_PROTOTYPE(name, type) \ struct type *name##_HTABLE_INSERT(struct name *, struct type *); \ struct type *name##_HTABLE_REMOVE(struct name *, struct type *); \ -struct type *name##_HTABLE_LOOKUP(struct name *, struct type *); +struct type *name##_HTABLE_LOOKUP(struct name *, struct type *); \ +uint32_t name##_HTABLE_FIND_BKT(struct name *, struct type *); \ +int name##_HTABLE_CHAIN_LEN(struct name *, uint32_t); \ +struct type *name##_HTABLE_FIRST_FROM(struct name *, int); \ +struct type *name##_HTABLE_NEXT(struct name *, struct type *); /* * Generate function bodies. @@ -116,7 +118,7 @@ uint32_t \ name##_HTABLE_FIND_BKT(struct name *head, struct type *elm) \ { \ uint32_t __bkt; \ - char *__key; \ + const char *__key; \ int __len; \ \ (key) (elm, &__key, &__len); \ diff --git a/src/ical.c b/src/ical.c new file mode 100644 index 0000000..ca10865 --- /dev/null +++ b/src/ical.c @@ -0,0 +1,1090 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#include <sys/types.h> + +#include "calcurse.h" + +#define ICALDATEFMT "%Y%m%d" +#define ICALDATETIMEFMT "%Y%m%dT%H%M%S" + +typedef enum { + ICAL_VEVENT, + ICAL_VTODO, + ICAL_TYPES +} ical_types_e; + +typedef enum { + UNDEFINED, + APPOINTMENT, + EVENT +} ical_vevent_e; + +typedef struct { + enum recur_type type; + int freq; + long until; + unsigned count; +} ical_rpt_t; + +static void ical_export_header(FILE *); +static void ical_export_recur_events(FILE *); +static void ical_export_events(FILE *); +static void ical_export_recur_apoints(FILE *); +static void ical_export_apoints(FILE *); +static void ical_export_todo(FILE *); +static void ical_export_footer(FILE *); + +static const char *ical_recur_type[RECUR_TYPES] = + { "", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" }; + +/* iCal alarm notification. */ +static void ical_export_valarm(FILE * stream) +{ + fputs("BEGIN:VALARM\n", stream); + pthread_mutex_lock(&nbar.mutex); + fprintf(stream, "TRIGGER:-P%dS\n", nbar.cntdwn); + pthread_mutex_unlock(&nbar.mutex); + fputs("ACTION:DISPLAY\n", stream); + fputs("END:VALARM\n", stream); +} + +/* Export header. */ +static void ical_export_header(FILE * stream) +{ + fputs("BEGIN:VCALENDAR\n", stream); + fprintf(stream, "PRODID:-//calcurse//NONSGML v%s//EN\n", VERSION); + fputs("VERSION:2.0\n", stream); +} + +/* Export footer. */ +static void ical_export_footer(FILE * stream) +{ + fputs("END:VCALENDAR\n", stream); +} + +/* Export recurrent events. */ +static void ical_export_recur_events(FILE * stream) +{ + llist_item_t *i, *j; + char ical_date[BUFSIZ]; + + LLIST_FOREACH(&recur_elist, i) { + struct recur_event *rev = LLIST_GET_DATA(i); + date_sec2date_fmt(rev->day, ICALDATEFMT, ical_date); + fputs("BEGIN:VEVENT\n", stream); + fprintf(stream, "DTSTART:%s\n", ical_date); + fprintf(stream, "RRULE:FREQ=%s;INTERVAL=%d", + ical_recur_type[rev->rpt->type], rev->rpt->freq); + + if (rev->rpt->until != 0) { + date_sec2date_fmt(rev->rpt->until, ICALDATEFMT, ical_date); + fprintf(stream, ";UNTIL=%s\n", ical_date); + } else + fputc('\n', stream); + + if (LLIST_FIRST(&rev->exc)) { + fputs("EXDATE:", stream); + LLIST_FOREACH(&rev->exc, j) { + struct excp *exc = LLIST_GET_DATA(j); + date_sec2date_fmt(exc->st, ICALDATEFMT, ical_date); + fprintf(stream, "%s", ical_date); + if (LLIST_NEXT(j)) + fputc(',', stream); + else + fputc('\n', stream); + } + } + + fprintf(stream, "SUMMARY:%s\n", rev->mesg); + fputs("END:VEVENT\n", stream); + } +} + +/* Export events. */ +static void ical_export_events(FILE * stream) +{ + llist_item_t *i; + char ical_date[BUFSIZ]; + + LLIST_FOREACH(&eventlist, i) { + struct event *ev = LLIST_TS_GET_DATA(i); + date_sec2date_fmt(ev->day, ICALDATEFMT, ical_date); + fputs("BEGIN:VEVENT\n", stream); + fprintf(stream, "DTSTART:%s\n", ical_date); + fprintf(stream, "SUMMARY:%s\n", ev->mesg); + fputs("END:VEVENT\n", stream); + } +} + +/* Export recurrent appointments. */ +static void ical_export_recur_apoints(FILE * stream) +{ + llist_item_t *i, *j; + char ical_datetime[BUFSIZ]; + char ical_date[BUFSIZ]; + + LLIST_TS_LOCK(&recur_alist_p); + LLIST_TS_FOREACH(&recur_alist_p, i) { + struct recur_apoint *rapt = LLIST_TS_GET_DATA(i); + + date_sec2date_fmt(rapt->start, ICALDATETIMEFMT, ical_datetime); + fputs("BEGIN:VEVENT\n", stream); + fprintf(stream, "DTSTART:%s\n", ical_datetime); + fprintf(stream, "DURATION:PT0H0M%ldS\n", rapt->dur); + fprintf(stream, "RRULE:FREQ=%s;INTERVAL=%d", + ical_recur_type[rapt->rpt->type], rapt->rpt->freq); + + if (rapt->rpt->until != 0) { + date_sec2date_fmt(rapt->rpt->until + HOURINSEC, ICALDATEFMT, ical_date); + fprintf(stream, ";UNTIL=%s\n", ical_date); + } else + fputc('\n', stream); + + if (LLIST_FIRST(&rapt->exc)) { + fputs("EXDATE:", stream); + LLIST_FOREACH(&rapt->exc, j) { + struct excp *exc = LLIST_GET_DATA(j); + date_sec2date_fmt(exc->st, ICALDATEFMT, ical_date); + fprintf(stream, "%s", ical_date); + if (LLIST_NEXT(j)) + fputc(',', stream); + else + fputc('\n', stream); + } + } + + fprintf(stream, "SUMMARY:%s\n", rapt->mesg); + if (rapt->state & APOINT_NOTIFY) + ical_export_valarm(stream); + fputs("END:VEVENT\n", stream); + } + LLIST_TS_UNLOCK(&recur_alist_p); +} + +/* Export appointments. */ +static void ical_export_apoints(FILE * stream) +{ + llist_item_t *i; + char ical_datetime[BUFSIZ]; + + LLIST_TS_LOCK(&alist_p); + LLIST_TS_FOREACH(&alist_p, i) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + date_sec2date_fmt(apt->start, ICALDATETIMEFMT, ical_datetime); + fputs("BEGIN:VEVENT\n", stream); + fprintf(stream, "DTSTART:%s\n", ical_datetime); + fprintf(stream, "DURATION:P%ldDT%ldH%ldM%ldS\n", + apt->dur / DAYINSEC, + (apt->dur / HOURINSEC) % DAYINHOURS, + (apt->dur / MININSEC) % HOURINMIN, apt->dur % MININSEC); + fprintf(stream, "SUMMARY:%s\n", apt->mesg); + if (apt->state & APOINT_NOTIFY) + ical_export_valarm(stream); + fputs("END:VEVENT\n", stream); + } + LLIST_TS_UNLOCK(&alist_p); +} + +/* Export todo items. */ +static void ical_export_todo(FILE * stream) +{ + llist_item_t *i; + + LLIST_FOREACH(&todolist, i) { + struct todo *todo = LLIST_TS_GET_DATA(i); + if (todo->id < 0) /* completed items */ + continue; + + fputs("BEGIN:VTODO\n", stream); + fprintf(stream, "PRIORITY:%d\n", todo->id); + fprintf(stream, "SUMMARY:%s\n", todo->mesg); + fputs("END:VTODO\n", stream); + } +} + +/* Print a header to describe import log report format. */ +static void ical_log_init(FILE * log, float version) +{ + const char *header = + "+-------------------------------------------------------------------+\n" + "| Calcurse icalendar import log. |\n" + "| |\n" + "| Items imported from icalendar file, version %1.1f |\n" + "| Some items could not be imported, they are described hereafter. |\n" + "| The log line format is as follows: |\n" + "| |\n" + "| TYPE [LINE]: DESCRIPTION |\n" + "| |\n" + "| where: |\n" + "| * TYPE represents the item type ('VEVENT' or 'VTODO') |\n" + "| * LINE is the line in the input stream at which this item begins |\n" + "| * DESCRIPTION indicates why the item could not be imported |\n" + "+-------------------------------------------------------------------+\n\n"; + + if (log) + fprintf(log, header, version); +} + +/* + * Used to build a report of the import process. + * The icalendar item for which a problem occurs is mentioned (by giving its + * first line inside the icalendar file), together with a message describing the + * problem. + */ +static void ical_log(FILE * log, ical_types_e type, unsigned lineno, char *msg) +{ + const char *typestr[ICAL_TYPES] = { "VEVENT", "VTODO" }; + + RETURN_IF(type < 0 || type >= ICAL_TYPES, _("unknown ical type")); + if (log) + fprintf(log, "%s [%d]: %s\n", typestr[type], lineno, msg); +} + +static void ical_store_todo(int priority, char *mesg, char *note) +{ + todo_add(mesg, priority, note); + mem_free(mesg); + erase_note(¬e); +} + +static void +ical_store_event(char *mesg, char *note, long day, long end, ical_rpt_t * rpt, + llist_t * exc) +{ + const int EVENTID = 1; + + if (rpt) { + recur_event_new(mesg, note, day, EVENTID, rpt->type, rpt->freq, + rpt->until, exc); + mem_free(rpt); + } else if (end && end != day) { + /* Here we have an event that spans over several days. */ + rpt = mem_malloc(sizeof(ical_rpt_t)); + rpt->type = RECUR_DAILY; + rpt->freq = 1; + rpt->count = 0; + rpt->until = end; + recur_event_new(mesg, note, day, EVENTID, rpt->type, rpt->freq, + rpt->until, exc); + mem_free(rpt); + } else { + event_new(mesg, note, day, EVENTID); + } + mem_free(mesg); + erase_note(¬e); +} + +static void +ical_store_apoint(char *mesg, char *note, long start, long dur, + ical_rpt_t * rpt, llist_t * exc, int has_alarm) +{ + char state = 0L; + + if (has_alarm) + state |= APOINT_NOTIFY; + if (rpt) { + recur_apoint_new(mesg, note, start, dur, state, rpt->type, rpt->freq, + rpt->until, exc); + mem_free(rpt); + } else { + apoint_new(mesg, note, start, dur, state); + } + mem_free(mesg); + erase_note(¬e); +} + +/* + * Returns an allocated string representing the string given in argument once + * unformatted. + * + * Note: + * Even if the RFC2445 recommends not to have more than 75 octets on one line of + * text, I prefer not to restrict the parsing to this size, thus I use a buffer + * of size BUFSIZ. + * + * Extract from RFC2445: + * Lines of text SHOULD NOT be longer than 75 octets, excluding the line + * break. + */ +static char *ical_unformat_line(char *line) +{ + char *p, uline[BUFSIZ]; + int len; + + if (strlen(line) >= BUFSIZ) + return NULL; + + memset(uline, 0, BUFSIZ); + for (len = 0, p = line; *p; p++) { + switch (*p) { + case '\\': + switch (*(p + 1)) { + case 'n': + uline[len++] = '\n'; + p++; + break; + case 't': + uline[len++] = '\t'; + p++; + break; + case ';': + case ':': + case ',': + uline[len++] = *(p + 1); + p++; + break; + default: + uline[len++] = *p; + break; + } + break; + default: + uline[len++] = *p; + break; + } + } + + return mem_strdup(uline); +} + +static void +ical_readline_init(FILE * fdi, char *buf, char *lstore, unsigned *ln) +{ + char *eol; + + *buf = *lstore = '\0'; + if (fgets(lstore, BUFSIZ, fdi)) { + if ((eol = strchr(lstore, '\n')) != NULL) + *eol = '\0'; + (*ln)++; + } +} + +static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln) +{ + char *eol; + + strncpy(buf, lstore, BUFSIZ); + (*ln)++; + + while (fgets(lstore, BUFSIZ, fdi) != NULL) { + if ((eol = strchr(lstore, '\n')) != NULL) + *eol = '\0'; + if (*lstore != SPACE && *lstore != TAB) + break; + strncat(buf, lstore + 1, BUFSIZ - strlen(buf) - 1); + (*ln)++; + } + + if (feof(fdi)) { + *lstore = '\0'; + if (*buf == '\0') + return 0; + } + + return 1; +} + +static float +ical_chk_header(FILE * fd, char *buf, char *lstore, unsigned *lineno) +{ + const int HEADER_MALFORMED = -1; + const char icalheader[] = "BEGIN:VCALENDAR"; + float version; + + if (!ical_readline(fd, buf, lstore, lineno)) + return HEADER_MALFORMED; + + str_toupper(buf); + if (strncmp(buf, icalheader, sizeof(icalheader) - 1) != 0) + return HEADER_MALFORMED; + + while (!sscanf(buf, "VERSION:%f", &version)) { + if (!ical_readline(fd, buf, lstore, lineno)) + return HEADER_MALFORMED; + } + return version; +} + +/* + * iCalendar date-time format is based on the ISO 8601 complete + * representation. It should be something like : DATE 'T' TIME + * where DATE is 'YYYYMMDD' and TIME is 'HHMMSS'. + * The time and 'T' separator are optional (in the case of an day-long event). + * + * Optionnaly, if the type pointer is given, specify if it is an event + * (no time is given, meaning it is an all-day event), or an appointment + * (time is given). + * + * The timezone is not yet handled by calcurse. + */ +static long ical_datetime2long(char *datestr, ical_vevent_e * type) +{ + const int NOTFOUND = 0, FORMAT_DATE = 3, FORMAT_DATETIME = 5; + struct date date; + unsigned hour, min; + long datelong; + int format; + + format = sscanf(datestr, "%04u%02u%02uT%02u%02u", + &date.yyyy, &date.mm, &date.dd, &hour, &min); + if (format == FORMAT_DATE) { + if (type) + *type = EVENT; + datelong = date2sec(date, 0, 0); + } else if (format == FORMAT_DATETIME) { + if (type) + *type = APPOINTMENT; + datelong = date2sec(date, hour, min); + } else { + datelong = NOTFOUND; + } + return datelong; +} + +static long ical_durtime2long(char *timestr) +{ + long timelong; + char *p; + + if ((p = strchr(timestr, 'T')) == NULL) + timelong = 0; + else { + int nbmatch; + struct { + unsigned hour, min, sec; + } time; + + p++; + memset(&time, 0, sizeof time); + nbmatch = sscanf(p, "%uH%uM%uS", &time.hour, &time.min, &time.sec); + if (nbmatch < 1 || nbmatch > 3) + timelong = 0; + else + timelong = time.hour * HOURINSEC + time.min * MININSEC + time.sec; + } + return timelong; +} + +/* + * Extract from RFC2445: + * + * Value Name: DURATION + * + * Purpose: This value type is used to identify properties that contain + * duration of time. + * + * Formal Definition: The value type is defined by the following + * notation: + * + * dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week) + * dur-date = dur-day [dur-time] + * dur-time = "T" (dur-hour / dur-minute / dur-second) + * dur-week = 1*DIGIT "W" + * dur-hour = 1*DIGIT "H" [dur-minute] + * dur-minute = 1*DIGIT "M" [dur-second] + * dur-second = 1*DIGIT "S" + * dur-day = 1*DIGIT "D" + * + * Example: A duration of 15 days, 5 hours and 20 seconds would be: + * P15DT5H0M20S + * A duration of 7 weeks would be: + * P7W + */ +static long ical_dur2long(char *durstr) +{ + const int NOTFOUND = -1; + long durlong; + char *p; + struct { + unsigned week, day; + } date; + + memset(&date, 0, sizeof date); + if ((p = strchr(durstr, 'P')) == NULL) + durlong = NOTFOUND; + else { + p++; + if (*p == '-') + return NOTFOUND; + else if (*p == '+') + p++; + + if (*p == 'T') /* dur-time */ + durlong = ical_durtime2long(p); + else if (strchr(p, 'W')) { /* dur-week */ + if (sscanf(p, "%u", &date.week) == 1) + durlong = date.week * WEEKINDAYS * DAYINSEC; + else + durlong = NOTFOUND; + } else { + if (strchr(p, 'D')) { /* dur-date */ + if (sscanf(p, "%uD", &date.day) == 1) { + durlong = date.day * DAYINSEC; + durlong += ical_durtime2long(p); + } else + durlong = NOTFOUND; + } else + durlong = NOTFOUND; + } + } + return durlong; +} + +/* + * Compute the vevent repetition end date from the repetition count. + * + * Extract from RFC2445: + * The COUNT rule part defines the number of occurrences at which to + * range-bound the recurrence. The "DTSTART" property value, if specified, + * counts as the first occurrence. + */ +static long ical_compute_rpt_until(long start, ical_rpt_t * rpt) +{ + long until; + + switch (rpt->type) { + case RECUR_DAILY: + until = date_sec_change(start, 0, rpt->freq * (rpt->count - 1)); + break; + case RECUR_WEEKLY: + until = date_sec_change(start, 0, + rpt->freq * WEEKINDAYS * (rpt->count - 1)); + break; + case RECUR_MONTHLY: + until = date_sec_change(start, rpt->freq * (rpt->count - 1), 0); + break; + case RECUR_YEARLY: + until = date_sec_change(start, rpt->freq * 12 * (rpt->count - 1), 0); + break; + default: + until = 0; + break; + /* NOTREACHED */ + } + return until; +} + +/* + * Read a recurrence rule from an iCalendar RRULE string. + * + * Value Name: RECUR + * + * Purpose: This value type is used to identify properties that contain + * a recurrence rule specification. + * + * Formal Definition: The value type is defined by the following + * notation: + * + * recur = "FREQ"=freq *( + * + * ; either UNTIL or COUNT may appear in a 'recur', + * ; but UNTIL and COUNT MUST NOT occur in the same 'recur' + * + * ( ";" "UNTIL" "=" enddate ) / + * ( ";" "COUNT" "=" 1*DIGIT ) / + * + * ; the rest of these keywords are optional, + * ; but MUST NOT occur more than + * ; once + * + * ( ";" "INTERVAL" "=" 1*DIGIT ) / + * ( ";" "BYSECOND" "=" byseclist ) / + * ( ";" "BYMINUTE" "=" byminlist ) / + * ( ";" "BYHOUR" "=" byhrlist ) / + * ( ";" "BYDAY" "=" bywdaylist ) / + * ( ";" "BYMONTHDAY" "=" bymodaylist ) / + * ( ";" "BYYEARDAY" "=" byyrdaylist ) / + * ( ";" "BYWEEKNO" "=" bywknolist ) / + * ( ";" "BYMONTH" "=" bymolist ) / + * ( ";" "BYSETPOS" "=" bysplist ) / + * ( ";" "WKST" "=" weekday ) / + * ( ";" x-name "=" text ) + * ) +*/ +static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr, + unsigned *noskipped, const int itemline) +{ + const char daily[] = "DAILY"; + const char weekly[] = "WEEKLY"; + const char monthly[] = "MONTHLY"; + const char yearly[] = "YEARLY"; + const char count[] = "COUNT="; + const char interv[] = "INTERVAL="; + unsigned interval; + ical_rpt_t *rpt; + char *p; + + rpt = NULL; + if ((p = strchr(rrulestr, ':')) != NULL) { + char freqstr[BUFSIZ]; + + p++; + rpt = mem_malloc(sizeof(ical_rpt_t)); + memset(rpt, 0, sizeof(ical_rpt_t)); + if (sscanf(p, "FREQ=%s", freqstr) != 1) { + ical_log(log, ICAL_VEVENT, itemline, + _("recurrence frequence not found.")); + (*noskipped)++; + mem_free(rpt); + return NULL; + } else { + if (strncmp(freqstr, daily, sizeof(daily) - 1) == 0) + rpt->type = RECUR_DAILY; + else if (strncmp(freqstr, weekly, sizeof(weekly) - 1) == 0) + rpt->type = RECUR_WEEKLY; + else if (strncmp(freqstr, monthly, sizeof(monthly) - 1) == 0) + rpt->type = RECUR_MONTHLY; + else if (strncmp(freqstr, yearly, sizeof(yearly) - 1) == 0) + rpt->type = RECUR_YEARLY; + else { + ical_log(log, ICAL_VEVENT, itemline, + _("recurrence frequence not recognized.")); + (*noskipped)++; + mem_free(rpt); + return NULL; + } + } + /* + The UNTIL rule part defines a date-time value which bounds the + recurrence rule in an inclusive manner. If not present, and the + COUNT rule part is also not present, the RRULE is considered to + repeat forever. + + The COUNT rule part defines the number of occurrences at which to + range-bound the recurrence. The "DTSTART" property value, if + specified, counts as the first occurrence. + */ + if ((p = strstr(rrulestr, "UNTIL")) != NULL) { + char *untilstr; + + untilstr = strchr(p, '='); + rpt->until = ical_datetime2long(++untilstr, NULL); + } else { + unsigned cnt; + char *countstr; + + if ((countstr = strstr(rrulestr, count)) != NULL) { + countstr += sizeof(count) - 1; + if (sscanf(countstr, "%u", &cnt) != 1) { + rpt->until = 0; + /* endless repetition */ + } else { + rpt->count = cnt; + } + } else + rpt->until = 0; + } + + if ((p = strstr(rrulestr, interv)) != NULL) { + p += sizeof(interv) - 1; + if (sscanf(p, "%u", &interval) != 1) { + rpt->freq = 1; + /* default frequence if none specified */ + } else { + rpt->freq = interval; + } + } else { + rpt->freq = 1; + } + } else { + ical_log(log, ICAL_VEVENT, itemline, _("recurrence rule malformed.")); + (*noskipped)++; + } + return rpt; +} + +static void ical_add_exc(llist_t * exc_head, long date) +{ + if (date != 0) { + struct excp *exc = mem_malloc(sizeof(struct excp)); + exc->st = date; + + LLIST_ADD(exc_head, exc); + } +} + +/* + * This property defines the list of date/time exceptions for a + * recurring calendar component. + */ +static void +ical_read_exdate(llist_t * exc, FILE * log, char *exstr, unsigned *noskipped, + const int itemline) +{ + char *p, *q; + long date; + + LLIST_INIT(exc); + if ((p = strchr(exstr, ':')) != NULL) { + p++; + while ((q = strchr(p, ',')) != NULL) { + char buf[BUFSIZ]; + const int buflen = q - p; + + strncpy(buf, p, buflen); + buf[buflen] = '\0'; + date = ical_datetime2long(buf, NULL); + ical_add_exc(exc, date); + p = ++q; + } + date = ical_datetime2long(p, NULL); + ical_add_exc(exc, date); + } else { + ical_log(log, ICAL_VEVENT, itemline, + _("recurrence exception dates malformed.")); + (*noskipped)++; + } +} + +/* Return an allocated string containing the name of the newly created note. */ +static char *ical_read_note(char *line, unsigned *noskipped, + ical_vevent_e item_type, const int itemline, + FILE * log) +{ + char *p, *notestr, *note; + + if ((p = strchr(line, ':')) != NULL) { + p++; + notestr = ical_unformat_line(p); + if (notestr == NULL) { + ical_log(log, item_type, itemline, + _("could not get entire item description.")); + (*noskipped)++; + return NULL; + } else if (strlen(notestr) == 0) { + mem_free(notestr); + return NULL; + } else { + note = generate_note(notestr); + mem_free(notestr); + return note; + } + } else { + ical_log(log, item_type, itemline, _("description malformed.")); + (*noskipped)++; + return NULL; + } +} + +/* Returns an allocated string containing the ical item summary. */ +static char *ical_read_summary(char *line) +{ + char *p, *summary; + + if ((p = strchr(line, ':')) != NULL) { + p++; + summary = ical_unformat_line(p); + return summary; + } else + return NULL; +} + +static void +ical_read_event(FILE * fdi, FILE * log, unsigned *noevents, unsigned *noapoints, + unsigned *noskipped, char *buf, char *lstore, unsigned *lineno) +{ + const int ITEMLINE = *lineno; + const char endevent[] = "END:VEVENT"; + const char summary[] = "SUMMARY"; + const char dtstart[] = "DTSTART"; + const char dtend[] = "DTEND"; + const char duration[] = "DURATION"; + const char rrule[] = "RRULE"; + const char exdate[] = "EXDATE"; + const char alarm[] = "BEGIN:VALARM"; + const char endalarm[] = "END:VALARM"; + const char desc[] = "DESCRIPTION"; + ical_vevent_e vevent_type; + char *p, buf_upper[BUFSIZ]; + struct { + llist_t exc; + ical_rpt_t *rpt; + char *mesg, *note; + long start, end, dur; + int has_alarm; + } vevent; + int skip_alarm; + + vevent_type = UNDEFINED; + memset(&vevent, 0, sizeof vevent); + skip_alarm = 0; + while (ical_readline(fdi, buf, lstore, lineno)) { + strncpy(buf_upper, buf, BUFSIZ); + buf_upper[BUFSIZ - 1] = '\0'; + str_toupper(buf_upper); + + if (skip_alarm) { + /* Need to skip VALARM properties because some keywords could + interfere, such as DURATION, SUMMARY,.. */ + if (strncmp(buf_upper, endalarm, sizeof(endalarm) - 1) == 0) + skip_alarm = 0; + continue; + } + if (strncmp(buf_upper, endevent, sizeof(endevent) - 1) == 0) { + if (vevent.mesg) { + if (vevent.rpt && vevent.rpt->count) + vevent.rpt->until = ical_compute_rpt_until(vevent.start, vevent.rpt); + + switch (vevent_type) { + case APPOINTMENT: + if (vevent.start == 0) { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("appointment has no start time.")); + goto cleanup; + } + if (vevent.dur == 0) { + if (vevent.end == 0) { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("could not compute duration " "(no end time).")); + goto cleanup; + } else if (vevent.start == vevent.end) { + vevent_type = EVENT; + vevent.end = 0L; + ical_store_event(vevent.mesg, vevent.note, + vevent.start, vevent.end, + vevent.rpt, &vevent.exc); + (*noevents)++; + return; + } else { + vevent.dur = vevent.end - vevent.start; + if (vevent.dur < 0) { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("item has a negative duration.")); + goto cleanup; + } + } + } + ical_store_apoint(vevent.mesg, vevent.note, vevent.start, + vevent.dur, vevent.rpt, &vevent.exc, + vevent.has_alarm); + (*noapoints)++; + break; + case EVENT: + if (vevent.start == 0) { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("event date is not defined.")); + goto cleanup; + } + ical_store_event(vevent.mesg, vevent.note, vevent.start, + vevent.end, vevent.rpt, &vevent.exc); + (*noevents)++; + break; + case UNDEFINED: + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("item could not be identified.")); + goto cleanup; + break; + } + } else { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("could not retrieve item summary.")); + goto cleanup; + } + return; + } else { + if (strncmp(buf_upper, dtstart, sizeof(dtstart) - 1) == 0) { + if ((p = strchr(buf, ':')) != NULL) + vevent.start = ical_datetime2long(++p, &vevent_type); + if (!vevent.start) { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("could not retrieve event start time.")); + goto cleanup; + } + } else if (strncmp(buf_upper, dtend, sizeof(dtend) - 1) == 0) { + if ((p = strchr(buf, ':')) != NULL) + vevent.end = ical_datetime2long(++p, &vevent_type); + if (!vevent.end) { + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("could not retrieve event end time.")); + goto cleanup; + } + } else if (strncmp(buf_upper, duration, sizeof(duration) - 1) == 0) { + if ((vevent.dur = ical_dur2long(buf)) <= 0) { + ical_log(log, ICAL_VEVENT, ITEMLINE, _("item duration malformed.")); + goto cleanup; + } + } else if (strncmp(buf_upper, rrule, sizeof(rrule) - 1) == 0) { + vevent.rpt = ical_read_rrule(log, buf, noskipped, ITEMLINE); + } else if (strncmp(buf_upper, exdate, sizeof(exdate) - 1) == 0) { + ical_read_exdate(&vevent.exc, log, buf, noskipped, ITEMLINE); + } else if (strncmp(buf_upper, summary, sizeof(summary) - 1) == 0) { + vevent.mesg = ical_read_summary(buf); + } else if (strncmp(buf_upper, alarm, sizeof(alarm) - 1) == 0) { + skip_alarm = 1; + vevent.has_alarm = 1; + } else if (strncmp(buf_upper, desc, sizeof(desc) - 1) == 0) { + vevent.note = ical_read_note(buf, noskipped, ICAL_VEVENT, + ITEMLINE, log); + } + } + } + ical_log(log, ICAL_VEVENT, ITEMLINE, + _("The ical file seems to be malformed. " + "The end of item was not found.")); + +cleanup: + + if (vevent.note) + mem_free(vevent.note); + if (vevent.mesg) + mem_free(vevent.mesg); + if (vevent.rpt) + mem_free(vevent.rpt); + LLIST_FREE(&vevent.exc); + (*noskipped)++; +} + +static void +ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped, + char *buf, char *lstore, unsigned *lineno) +{ + const char endtodo[] = "END:VTODO"; + const char summary[] = "SUMMARY"; + const char alarm[] = "BEGIN:VALARM"; + const char endalarm[] = "END:VALARM"; + const char desc[] = "DESCRIPTION"; + const int LOWEST = 9; + const int ITEMLINE = *lineno; + char buf_upper[BUFSIZ]; + struct { + char *mesg, *note; + int has_priority, priority; + } vtodo; + int skip_alarm; + + memset(&vtodo, 0, sizeof vtodo); + skip_alarm = 0; + while (ical_readline(fdi, buf, lstore, lineno)) { + strncpy(buf_upper, buf, BUFSIZ); + buf_upper[BUFSIZ - 1] = '\0'; + str_toupper(buf_upper); + if (skip_alarm) { + /* Need to skip VALARM properties because some keywords could + interfere, such as DURATION, SUMMARY,.. */ + if (strncmp(buf_upper, endalarm, sizeof(endalarm) - 1) == 0) + skip_alarm = 0; + continue; + } + if (strncmp(buf_upper, endtodo, sizeof(endtodo) - 1) == 0) { + if (!vtodo.has_priority) + vtodo.priority = LOWEST; + if (vtodo.mesg) { + ical_store_todo(vtodo.priority, vtodo.mesg, vtodo.note); + (*notodos)++; + } else { + ical_log(log, ICAL_VTODO, ITEMLINE, + _("could not retrieve item summary.")); + goto cleanup; + } + return; + } else { + int tmpint; + + if (sscanf(buf_upper, "PRIORITY:%d", &tmpint) == 1) { + if (tmpint <= 9 && tmpint >= 1) { + vtodo.priority = tmpint; + vtodo.has_priority = 1; + } else { + ical_log(log, ICAL_VTODO, ITEMLINE, + _("item priority is not acceptable " + "(must be between 1 and 9).")); + vtodo.priority = LOWEST; + } + } else if (strncmp(buf_upper, summary, sizeof(summary) - 1) == 0) { + vtodo.mesg = ical_read_summary(buf); + } else if (strncmp(buf_upper, alarm, sizeof(alarm) - 1) == 0) { + skip_alarm = 1; + } else if (strncmp(buf_upper, desc, sizeof(desc) - 1) == 0) { + vtodo.note = ical_read_note(buf, noskipped, ICAL_VTODO, ITEMLINE, log); + } + } + } + ical_log(log, ICAL_VTODO, ITEMLINE, + _("The ical file seems to be malformed. " + "The end of item was not found.")); + +cleanup: + + if (vtodo.note) + mem_free(vtodo.note); + if (vtodo.mesg) + mem_free(vtodo.mesg); + (*noskipped)++; +} + +/* Import calcurse data. */ +void +ical_import_data(FILE * stream, FILE * log, unsigned *events, unsigned *apoints, + unsigned *todos, unsigned *lines, unsigned *skipped) +{ + const char vevent[] = "BEGIN:VEVENT"; + const char vtodo[] = "BEGIN:VTODO"; + char buf[BUFSIZ], lstore[BUFSIZ]; + float ical_version; + + ical_readline_init(stream, buf, lstore, lines); + ical_version = ical_chk_header(stream, buf, lstore, lines); + RETURN_IF(ical_version < 0, + _("Warning: ical header malformed or wrong version number. " + "Aborting...")); + + ical_log_init(log, ical_version); + + while (ical_readline(stream, buf, lstore, lines)) { + (*lines)++; + str_toupper(buf); + if (strncmp(buf, vevent, sizeof(vevent) - 1) == 0) { + ical_read_event(stream, log, events, apoints, skipped, buf, lstore, + lines); + } else if (strncmp(buf, vtodo, sizeof(vtodo) - 1) == 0) { + ical_read_todo(stream, log, todos, skipped, buf, lstore, lines); + } + } +} + +/* Export calcurse data. */ +void ical_export_data(FILE * stream) +{ + ical_export_header(stream); + ical_export_recur_events(stream); + ical_export_events(stream); + ical_export_recur_apoints(stream); + ical_export_apoints(stream); + ical_export_todo(stream); + ical_export_footer(stream); +} @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,9 +45,7 @@ #include <errno.h> #include "calcurse.h" - -#define ICALDATEFMT "%Y%m%d" -#define ICALDATETIMEFMT "%Y%m%dT%H%M%S" +#include "sha1.h" typedef enum { PROGRESS_BAR_SAVE, @@ -68,650 +66,147 @@ enum { PROGRESS_BAR_EXPORT_TODO }; -typedef enum { - ICAL_VEVENT, - ICAL_VTODO, - ICAL_TYPES -} ical_types_e; - -typedef enum { - UNDEFINED, - APPOINTMENT, - EVENT -} ical_vevent_e; - -typedef struct { - enum recur_type type; - int freq; - long until; - unsigned count; -} ical_rpt_t; - struct ht_keybindings_s { - char *label; - enum key key; - HTABLE_ENTRY (ht_keybindings_s); + const char *label; + enum key key; + HTABLE_ENTRY(ht_keybindings_s); }; -/* Type definition for callbacks to multiple-mode export functions. */ -typedef void (*cb_export_t)(FILE *); -typedef void (*cb_dump_t)(FILE *, long, long, char *); - -/* Static functions used to add export functionalities. */ -static void ical_export_header (FILE *); -static void ical_export_recur_events (FILE *); -static void ical_export_events (FILE *); -static void ical_export_recur_apoints (FILE *); -static void ical_export_apoints (FILE *); -static void ical_export_todo (FILE *); -static void ical_export_footer (FILE *); - -static void pcal_export_header (FILE *); -static void pcal_export_recur_events (FILE *); -static void pcal_export_events (FILE *); -static void pcal_export_recur_apoints (FILE *); -static void pcal_export_apoints (FILE *); -static void pcal_export_todo (FILE *); -static void pcal_export_footer (FILE *); - -cb_export_t cb_export_header[IO_EXPORT_NBTYPES] = - {ical_export_header, pcal_export_header}; -cb_export_t cb_export_recur_events[IO_EXPORT_NBTYPES] = - {ical_export_recur_events, pcal_export_recur_events}; -cb_export_t cb_export_events[IO_EXPORT_NBTYPES] = - {ical_export_events, pcal_export_events}; -cb_export_t cb_export_recur_apoints[IO_EXPORT_NBTYPES] = - {ical_export_recur_apoints, pcal_export_recur_apoints}; -cb_export_t cb_export_apoints[IO_EXPORT_NBTYPES] = - {ical_export_apoints, pcal_export_apoints}; -cb_export_t cb_export_todo[IO_EXPORT_NBTYPES] = - {ical_export_todo, pcal_export_todo}; -cb_export_t cb_export_footer[IO_EXPORT_NBTYPES] = - {ical_export_footer, pcal_export_footer}; - -static char *ical_recur_type[RECUR_TYPES] = - { "", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" }; +static void load_keys_ht_getkey(struct ht_keybindings_s *, const char **, + int *); +static int load_keys_ht_compare(struct ht_keybindings_s *, + struct ht_keybindings_s *); + +#define HSIZE 256 +HTABLE_HEAD(ht_keybindings, HSIZE, ht_keybindings_s); +HTABLE_PROTOTYPE(ht_keybindings, ht_keybindings_s) + HTABLE_GENERATE(ht_keybindings, ht_keybindings_s, load_keys_ht_getkey, + load_keys_ht_compare) /* Draw a progress bar while saving, loading or exporting data. */ -static void -progress_bar (progress_bar_t type, int progress) +static void progress_bar(progress_bar_t type, int progress) { -#define SLEEPTIME 125000 #define NBFILES 4 #define NBEXPORTED 3 #define LABELENGTH 15 int i, step, steps; - char *mesg_sav = _("Saving..."); - char *mesg_load = _("Loading..."); - char *mesg_export = _("Exporting..."); - char *error_msg = _("Internal error while displaying progress bar"); - char *barchar = "|"; - char *file[NBFILES] = { + const char *mesg_sav = _("Saving..."); + const char *mesg_load = _("Loading..."); + const char *mesg_export = _("Exporting..."); + const char *error_msg = _("Internal error while displaying progress bar"); + const char *barchar = "|"; + const char *file[NBFILES] = { "[ conf ]", "[ todo ]", "[ apts ]", "[ keys ]" }; - char *data[NBEXPORTED] = { + const char *data[NBEXPORTED] = { "[ events ]", "[appointments]", "[ todo ]" }; - int ipos = LABELENGTH + 2; + int ipos = LABELENGTH + 2; int epos[NBFILES]; /* progress bar length init. */ ipos = LABELENGTH + 2; steps = (type == PROGRESS_BAR_EXPORT) ? NBEXPORTED : NBFILES; - step = floor (col / (steps + 1)); + step = floor(col / (steps + 1)); for (i = 0; i < steps - 1; i++) epos[i] = (i + 2) * step; epos[steps - 1] = col - 2; - switch (type) - { - case PROGRESS_BAR_SAVE: - EXIT_IF (progress < 0 || progress > PROGRESS_BAR_KEYS, "%s", error_msg); - status_mesg (mesg_sav, file[progress]); - break; - case PROGRESS_BAR_LOAD: - EXIT_IF (progress < 0 || progress > PROGRESS_BAR_KEYS, "%s", error_msg); - status_mesg (mesg_load, file[progress]); - break; - case PROGRESS_BAR_EXPORT: - EXIT_IF (progress < 0 - || progress > PROGRESS_BAR_EXPORT_TODO, "%s", error_msg); - status_mesg (mesg_export, data[progress]); - break; - } + switch (type) { + case PROGRESS_BAR_SAVE: + EXIT_IF(progress < 0 || progress > PROGRESS_BAR_KEYS, "%s", error_msg); + status_mesg(mesg_sav, file[progress]); + break; + case PROGRESS_BAR_LOAD: + EXIT_IF(progress < 0 || progress > PROGRESS_BAR_KEYS, "%s", error_msg); + status_mesg(mesg_load, file[progress]); + break; + case PROGRESS_BAR_EXPORT: + EXIT_IF(progress < 0 + || progress > PROGRESS_BAR_EXPORT_TODO, "%s", error_msg); + status_mesg(mesg_export, data[progress]); + break; + } /* Draw the progress bar. */ - mvwprintw (win[STA].p, 1, ipos, barchar); - mvwprintw (win[STA].p, 1, epos[steps - 1], barchar); - custom_apply_attr (win[STA].p, ATTR_HIGHEST); + mvwprintw(win[STA].p, 1, ipos, barchar); + mvwprintw(win[STA].p, 1, epos[steps - 1], barchar); + custom_apply_attr(win[STA].p, ATTR_HIGHEST); for (i = ipos + 1; i < epos[progress]; i++) - mvwaddch (win[STA].p, 1, i, ' ' | A_REVERSE); - custom_remove_attr (win[STA].p, ATTR_HIGHEST); - wmove (win[STA].p, 0, 0); - wins_wrefresh (win[STA].p); - (void)usleep (SLEEPTIME); -#undef SLEEPTIME + mvwaddch(win[STA].p, 1, i, ' ' | A_REVERSE); + custom_remove_attr(win[STA].p, ATTR_HIGHEST); + wmove(win[STA].p, 0, 0); + wins_wrefresh(win[STA].p); #undef NBFILES #undef NBEXPORTED #undef LABELENGTH } /* Ask user for a file name to export data to. */ -static FILE * -get_export_stream (enum export_type type) +static FILE *get_export_stream(enum export_type type) { FILE *stream; int cancel; char *home, *stream_name; - char *question = _("Choose the file used to export calcurse data:"); - char *wrong_name = - _("The file cannot be accessed, please enter another file name."); - char *press_enter = _("Press [ENTER] to continue."); - const char *file_ext[IO_EXPORT_NBTYPES] = {"ical", "txt"}; + const char *question = _("Choose the file used to export calcurse data:"); + const char *wrong_name = + _("The file cannot be accessed, please enter another file name."); + const char *press_enter = _("Press [ENTER] to continue."); + const char *file_ext[IO_EXPORT_NBTYPES] = { "ical", "txt" }; stream = NULL; - stream_name = (char *) mem_malloc (BUFSIZ); - if ((home = getenv ("HOME")) != NULL) - (void)snprintf (stream_name, BUFSIZ, "%s/calcurse.%s", home, - file_ext[type]); + stream_name = (char *)mem_malloc(BUFSIZ); + if ((home = getenv("HOME")) != NULL) + snprintf(stream_name, BUFSIZ, "%s/calcurse.%s", home, file_ext[type]); else - (void)snprintf (stream_name, BUFSIZ, "%s/calcurse.%s", get_tempdir (), - file_ext[type]); - - while (stream == NULL) - { - status_mesg (question, ""); - cancel = updatestring (win[STA].p, &stream_name, 0, 1); - if (cancel) - { - mem_free (stream_name); - return (NULL); - } - stream = fopen (stream_name, "w"); - if (stream == NULL) - { - status_mesg (wrong_name, press_enter); - (void)wgetch (win[STA].p); - } - } - mem_free (stream_name); - - return (stream); -} - -/* - * Travel through each occurence of an item, and execute the given callback - * (mainly used to export data). - */ -static void -foreach_date_dump (const long date_end, struct rpt *rpt, llist_t *exc, - long item_first_date, long item_dur, char *item_mesg, - cb_dump_t cb_dump, FILE *stream) -{ - long date, item_time; - struct tm lt; - time_t t; - - t = item_first_date; - lt = *localtime (&t); - lt.tm_hour = lt.tm_min = lt.tm_sec = 0; - lt.tm_isdst = -1; - date = mktime (<); - item_time = item_first_date - date; - - while (date <= date_end && date <= rpt->until) - { - if (recur_item_inday (item_first_date, exc, rpt->type, rpt->freq, - rpt->until, date)) - { - (*cb_dump)(stream, date + item_time, item_dur, item_mesg); - } - switch (rpt->type) - { - case RECUR_DAILY: - date = date_sec_change (date, 0, rpt->freq); - break; - case RECUR_WEEKLY: - date = date_sec_change (date, 0, rpt->freq * WEEKINDAYS); - break; - case RECUR_MONTHLY: - date = date_sec_change (date, rpt->freq, 0); - break; - case RECUR_YEARLY: - date = date_sec_change (date, rpt->freq * 12, 0); - break; - default: - EXIT (_("incoherent repetition type")); - /* NOTREACHED */ - break; - } - } -} - -/* iCal alarm notification. */ -static void -ical_export_valarm (FILE *stream) -{ - (void)fprintf (stream, "BEGIN:VALARM\n"); - pthread_mutex_lock (&nbar.mutex); - (void)fprintf (stream, "TRIGGER:-P%dS\n", nbar.cntdwn); - pthread_mutex_unlock (&nbar.mutex); - (void)fprintf (stream, "ACTION:DISPLAY\n"); - (void)fprintf (stream, "END:VALARM\n"); -} - -/* Export header. */ -static void -ical_export_header (FILE *stream) -{ - (void)fprintf (stream, "BEGIN:VCALENDAR\n"); - (void)fprintf (stream, "PRODID:-//calcurse//NONSGML v%s//EN\n", VERSION); - (void)fprintf (stream, "VERSION:2.0\n"); -} - -static void -pcal_export_header (FILE *stream) -{ - (void)fprintf (stream, "# calcurse pcal export\n"); - (void)fprintf (stream, "\n# =======\n# options\n# =======\n"); - (void)fprintf (stream, "opt -A -K -l -m -F %s\n", - calendar_week_begins_on_monday () ? - "Monday" : "Sunday"); - (void)fprintf (stream, "# Display week number (i.e. 1-52) on every Monday\n"); - (void)fprintf (stream, "all monday in all week %%w\n"); - (void)fprintf (stream, "\n"); -} - -/* Export footer. */ -static void -ical_export_footer (FILE *stream) -{ - (void)fprintf (stream, "END:VCALENDAR\n"); -} - -static void -pcal_export_footer (FILE *stream) -{ -} - -/* Export recurrent events. */ -static void -ical_export_recur_events (FILE *stream) -{ - llist_item_t *i, *j; - char ical_date[BUFSIZ]; - - LLIST_FOREACH (&recur_elist, i) - { - struct recur_event *rev = LLIST_GET_DATA (i); - date_sec2date_fmt (rev->day, ICALDATEFMT, ical_date); - (void)fprintf (stream, "BEGIN:VEVENT\n"); - (void)fprintf (stream, "DTSTART:%s\n", ical_date); - (void)fprintf (stream, "RRULE:FREQ=%s;INTERVAL=%d", - ical_recur_type[rev->rpt->type], rev->rpt->freq); - - if (rev->rpt->until != 0) - { - date_sec2date_fmt (rev->rpt->until, ICALDATEFMT, ical_date); - (void)fprintf (stream, ";UNTIL=%s\n", ical_date); - } - else - (void)fprintf (stream, "\n"); - - if (LLIST_FIRST (&rev->exc)) - { - (void)fprintf (stream, "EXDATE:"); - LLIST_FOREACH (&rev->exc, j) - { - struct excp *exc = LLIST_GET_DATA (j); - date_sec2date_fmt (exc->st, ICALDATEFMT, ical_date); - (void)fprintf (stream, "%s", ical_date); - if (LLIST_NEXT (j)) - (void)fprintf (stream, ","); - else - (void)fprintf (stream, "\n"); - } - } - - (void)fprintf (stream, "SUMMARY:%s\n", rev->mesg); - (void)fprintf (stream, "END:VEVENT\n"); - } -} - -/* Format and dump event data to a pcal formatted file. */ -static void -pcal_dump_event (FILE *stream, long event_date, long event_dur, - char *event_mesg) -{ - char pcal_date[BUFSIZ]; - - date_sec2date_fmt (event_date, "%b %d", pcal_date); - (void)fprintf (stream, "%s %s\n", pcal_date, event_mesg); -} - -/* Format and dump appointment data to a pcal formatted file. */ -static void -pcal_dump_apoint (FILE *stream, long apoint_date, long apoint_dur, - char *apoint_mesg) -{ - char pcal_date[BUFSIZ], pcal_beg[BUFSIZ], pcal_end[BUFSIZ]; - - date_sec2date_fmt (apoint_date, "%b %d", pcal_date); - date_sec2date_fmt (apoint_date, "%R", pcal_beg); - date_sec2date_fmt (apoint_date + apoint_dur, "%R", pcal_end); - (void)fprintf (stream, "%s ", pcal_date); - (void)fprintf (stream, "(%s -> %s) %s\n", pcal_beg, pcal_end, apoint_mesg); -} - -static void -pcal_export_recur_events (FILE *stream) -{ - llist_item_t *i; - char pcal_date[BUFSIZ]; - - (void)fprintf (stream, "\n# ============="); - (void)fprintf (stream, "\n# Recur. Events"); - (void)fprintf (stream, "\n# =============\n"); - (void)fprintf (stream, - "# (pcal does not support from..until dates specification\n"); - - LLIST_FOREACH (&recur_elist, i) - { - struct recur_event *rev = LLIST_GET_DATA (i); - if (rev->rpt->until == 0 && rev->rpt->freq == 1) - { - switch (rev->rpt->type) - { - case RECUR_DAILY: - date_sec2date_fmt (rev->day, "%b %d", pcal_date); - (void)fprintf (stream, "all day on_or_after %s %s\n", - pcal_date, rev->mesg); - break; - case RECUR_WEEKLY: - date_sec2date_fmt (rev->day, "%a", pcal_date); - (void)fprintf (stream, "all %s on_or_after ", pcal_date); - date_sec2date_fmt (rev->day, "%b %d", pcal_date); - (void)fprintf (stream, "%s %s\n", pcal_date, rev->mesg); - break; - case RECUR_MONTHLY: - date_sec2date_fmt (rev->day, "%d", pcal_date); - (void)fprintf (stream, "day on all %s %s\n", pcal_date, - rev->mesg); - break; - case RECUR_YEARLY: - date_sec2date_fmt (rev->day, "%b %d", pcal_date); - (void)fprintf (stream, "%s %s\n", pcal_date, rev->mesg); - break; - default: - EXIT (_("incoherent repetition type")); - } - } - else - { - const long YEAR_START = calendar_start_of_year (); - const long YEAR_END = calendar_end_of_year (); - - if (rev->day < YEAR_END && rev->day > YEAR_START) - foreach_date_dump (YEAR_END, rev->rpt, &rev->exc, rev->day, 0, - rev->mesg, (cb_dump_t) pcal_dump_event, stream); - } - } -} - -/* Export events. */ -static void -ical_export_events (FILE *stream) -{ - llist_item_t *i; - char ical_date[BUFSIZ]; - - LLIST_FOREACH (&eventlist, i) - { - struct event *ev = LLIST_TS_GET_DATA (i); - date_sec2date_fmt (ev->day, ICALDATEFMT, ical_date); - (void)fprintf (stream, "BEGIN:VEVENT\n"); - (void)fprintf (stream, "DTSTART:%s\n", ical_date); - (void)fprintf (stream, "SUMMARY:%s\n", ev->mesg); - (void)fprintf (stream, "END:VEVENT\n"); - } -} - -static void -pcal_export_events (FILE *stream) -{ - llist_item_t *i; - - (void)fprintf (stream, "\n# ======\n# Events\n# ======\n"); - LLIST_FOREACH (&eventlist, i) - { - struct event *ev = LLIST_TS_GET_DATA (i); - pcal_dump_event (stream, ev->day, 0, ev->mesg); - } - (void)fprintf (stream, "\n"); -} - -/* Export recurrent appointments. */ -static void -ical_export_recur_apoints (FILE *stream) -{ - llist_item_t *i, *j; - char ical_datetime[BUFSIZ]; - char ical_date[BUFSIZ]; - - LLIST_TS_LOCK (&recur_alist_p); - LLIST_TS_FOREACH (&recur_alist_p, i) - { - struct recur_apoint *rapt = LLIST_TS_GET_DATA (i); - - date_sec2date_fmt (rapt->start, ICALDATETIMEFMT, ical_datetime); - (void)fprintf (stream, "BEGIN:VEVENT\n"); - (void)fprintf (stream, "DTSTART:%s\n", ical_datetime); - (void)fprintf (stream, "DURATION:PT0H0M%ldS\n", rapt->dur); - (void)fprintf (stream, "RRULE:FREQ=%s;INTERVAL=%d", - ical_recur_type[rapt->rpt->type], rapt->rpt->freq); - - if (rapt->rpt->until != 0) - { - date_sec2date_fmt (rapt->rpt->until + HOURINSEC, ICALDATEFMT, - ical_date); - (void)fprintf (stream, ";UNTIL=%s\n", ical_date); - } - else - (void)fprintf (stream, "\n"); - - if (LLIST_FIRST (&rapt->exc)) - { - (void)fprintf (stream, "EXDATE:"); - LLIST_FOREACH (&rapt->exc, j) - { - struct excp *exc = LLIST_GET_DATA (j); - date_sec2date_fmt (exc->st, ICALDATEFMT, ical_date); - (void)fprintf (stream, "%s", ical_date); - if (LLIST_NEXT (j)) - (void)fprintf (stream, ","); - else - (void)fprintf (stream, "\n"); - } - } - - (void)fprintf (stream, "SUMMARY:%s\n", rapt->mesg); - if (rapt->state & APOINT_NOTIFY) - ical_export_valarm (stream); - (void)fprintf (stream, "END:VEVENT\n"); - } - LLIST_TS_UNLOCK (&recur_alist_p); -} - -static void -pcal_export_recur_apoints (FILE *stream) -{ - llist_item_t *i; - char pcal_date[BUFSIZ], pcal_beg[BUFSIZ], pcal_end[BUFSIZ]; - - (void)fprintf (stream, "\n# =============="); - (void)fprintf (stream, "\n# Recur. Apoints"); - (void)fprintf (stream, "\n# ==============\n"); - (void)fprintf (stream, - "# (pcal does not support from..until dates specification\n"); - - LLIST_TS_FOREACH (&recur_alist_p, i) - { - struct recur_apoint *rapt = LLIST_TS_GET_DATA (i); - - if (rapt->rpt->until == 0 && rapt->rpt->freq == 1) - { - date_sec2date_fmt (rapt->start, "%R", pcal_beg); - date_sec2date_fmt (rapt->start + rapt->dur, "%R", pcal_end); - switch (rapt->rpt->type) - { - case RECUR_DAILY: - date_sec2date_fmt (rapt->start, "%b %d", pcal_date); - (void)fprintf (stream, "all day on_or_after %s (%s -> %s) %s\n", - pcal_date, pcal_beg, pcal_end, rapt->mesg); - break; - case RECUR_WEEKLY: - date_sec2date_fmt (rapt->start, "%a", pcal_date); - (void)fprintf (stream, "all %s on_or_after ", pcal_date); - date_sec2date_fmt (rapt->start, "%b %d", pcal_date); - (void)fprintf (stream, "%s (%s -> %s) %s\n", pcal_date, - pcal_beg, pcal_end, rapt->mesg); - break; - case RECUR_MONTHLY: - date_sec2date_fmt (rapt->start, "%d", pcal_date); - (void)fprintf (stream, "day on all %s (%s -> %s) %s\n", - pcal_date, pcal_beg, pcal_end, rapt->mesg); - break; - case RECUR_YEARLY: - date_sec2date_fmt (rapt->start, "%b %d", pcal_date); - (void)fprintf (stream, "%s (%s -> %s) %s\n", pcal_date, - pcal_beg, pcal_end, rapt->mesg); - break; - default: - EXIT (_("incoherent repetition type")); - } - } - else - { - const long YEAR_START = calendar_start_of_year (); - const long YEAR_END = calendar_end_of_year (); - - if (rapt->start < YEAR_END && rapt->start > YEAR_START) - foreach_date_dump (YEAR_END, rapt->rpt, &rapt->exc, rapt->start, - rapt->dur, rapt->mesg, - (cb_dump_t)pcal_dump_apoint, stream); - } - } -} - -/* Export appointments. */ -static void -ical_export_apoints (FILE *stream) -{ - llist_item_t *i; - char ical_datetime[BUFSIZ]; - - LLIST_TS_LOCK (&alist_p); - LLIST_TS_FOREACH (&alist_p, i) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - date_sec2date_fmt (apt->start, ICALDATETIMEFMT, ical_datetime); - (void)fprintf (stream, "BEGIN:VEVENT\n"); - (void)fprintf (stream, "DTSTART:%s\n", ical_datetime); - (void)fprintf (stream, "DURATION:P%ldDT%ldH%ldM%ldS\n", - apt->dur / DAYINSEC, - (apt->dur / HOURINSEC) % 24, - (apt->dur / MININSEC) % 60, - apt->dur % MININSEC); - (void)fprintf (stream, "SUMMARY:%s\n", apt->mesg); - if (apt->state & APOINT_NOTIFY) - ical_export_valarm (stream); - (void)fprintf (stream, "END:VEVENT\n"); + snprintf(stream_name, BUFSIZ, "%s/calcurse.%s", get_tempdir(), + file_ext[type]); + + while (stream == NULL) { + status_mesg(question, ""); + cancel = updatestring(win[STA].p, &stream_name, 0, 1); + if (cancel) { + mem_free(stream_name); + return NULL; } - LLIST_TS_UNLOCK (&alist_p); -} - -static void -pcal_export_apoints (FILE *stream) -{ - llist_item_t *i; - - (void)fprintf (stream, "\n# ============\n# Appointments\n# ============\n"); - LLIST_TS_LOCK (&alist_p); - LLIST_TS_FOREACH (&alist_p, i) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - pcal_dump_apoint (stream, apt->start, apt->dur, apt->mesg); + stream = fopen(stream_name, "w"); + if (stream == NULL) { + status_mesg(wrong_name, press_enter); + wgetch(win[STA].p); } - LLIST_TS_UNLOCK (&alist_p); - (void)fprintf (stream, "\n"); -} - -/* Export todo items. */ -static void -ical_export_todo (FILE *stream) -{ - llist_item_t *i; - - LLIST_FOREACH (&todolist, i) - { - struct todo *todo = LLIST_TS_GET_DATA (i); - if (todo->id < 0) /* completed items */ - continue; + } + mem_free(stream_name); - (void)fprintf (stream, "BEGIN:VTODO\n"); - (void)fprintf (stream, "PRIORITY:%d\n", todo->id); - (void)fprintf (stream, "SUMMARY:%s\n", todo->mesg); - (void)fprintf (stream, "END:VTODO\n"); - } -} - -static void -pcal_export_todo (FILE *stream) -{ - llist_item_t *i; - - (void)fprintf (stream, "#\n# Todos\n#\n"); - LLIST_FOREACH (&todolist, i) - { - struct todo *todo = LLIST_TS_GET_DATA (i); - if (todo->id < 0) /* completed items */ - continue; - - (void)fprintf (stream, "note all "); - (void)fprintf (stream, "%d. %s\n", todo->id, todo->mesg); - } - (void)fprintf (stream, "\n"); + return stream; } /* Append a line to a file. */ -unsigned -io_fprintln (const char *fname, const char *fmt, ...) +unsigned io_fprintln(const char *fname, const char *fmt, ...) { FILE *fp; va_list ap; char buf[BUFSIZ]; int ret; - fp = fopen (fname, "a"); - RETVAL_IF (!fp, 0, _("Failed to open \"%s\", - %s\n"), - fname, strerror (errno)); + fp = fopen(fname, "a"); + RETVAL_IF(!fp, 0, _("Failed to open \"%s\", - %s\n"), fname, strerror(errno)); - va_start (ap, fmt); - ret = vsnprintf (buf, sizeof buf, fmt, ap); - RETVAL_IF (ret < 0, 0, _("Failed to build message\n")); - va_end (ap); + va_start(ap, fmt); + ret = vsnprintf(buf, sizeof buf, fmt, ap); + RETVAL_IF(ret < 0, 0, _("Failed to build message\n")); + va_end(ap); - ret = fprintf (fp, "%s", buf); - RETVAL_IF (ret < 0, 0, _("Failed to print message \"%s\"\n"), buf); + ret = fprintf(fp, "%s", buf); + RETVAL_IF(ret < 0, 0, _("Failed to print message \"%s\"\n"), buf); - ret = fclose (fp); - RETVAL_IF (ret != 0, 0, _("Failed to close \"%s\" - %s\n"), - fname, strerror (errno)); + ret = fclose(fp); + RETVAL_IF(ret != 0, 0, _("Failed to close \"%s\" - %s\n"), + fname, strerror(errno)); return 1; } @@ -723,383 +218,231 @@ io_fprintln (const char *fname, const char *fmt, ...) * is created. * The datadir argument can be use to specify an alternative data root dir. */ -void -io_init (char *cfile, char *datadir) +void io_init(const char *cfile, const char *datadir) { FILE *data_file; - char *home; + const char *home; char apts_file[BUFSIZ] = ""; int ch; - if (datadir != NULL) - { - home = datadir; - (void)snprintf (path_dir, BUFSIZ, "%s", home); - (void)snprintf (path_todo, BUFSIZ, "%s/" TODO_PATH_NAME, home); - (void)snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH_NAME, home); - (void)snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR_NAME, home); - (void)snprintf (path_apts, BUFSIZ, "%s/" APTS_PATH_NAME, home); - (void)snprintf (path_keys, BUFSIZ, "%s/" KEYS_PATH_NAME, home); - (void)snprintf (path_cpid, BUFSIZ, "%s/" CPID_PATH_NAME, home); - (void)snprintf (path_dpid, BUFSIZ, "%s/" DPID_PATH_NAME, home); - (void)snprintf (path_dmon_log, BUFSIZ, "%s/" DLOG_PATH_NAME, home); - } - else - { - home = getenv ("HOME"); - if (home == NULL) - { - home = "."; - } - (void)snprintf (path_dir, BUFSIZ, "%s/" DIR_NAME, home); - (void)snprintf (path_todo, BUFSIZ, "%s/" TODO_PATH, home); - (void)snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH, home); - (void)snprintf (path_keys, BUFSIZ, "%s/" KEYS_PATH, home); - (void)snprintf (path_cpid, BUFSIZ, "%s/" CPID_PATH, home); - (void)snprintf (path_dpid, BUFSIZ, "%s/" DPID_PATH, home); - (void)snprintf (path_dmon_log, BUFSIZ, "%s/" DLOG_PATH, home); - (void)snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR, home); - if (cfile == NULL) - { - (void)snprintf (path_apts, BUFSIZ, "%s/" APTS_PATH, home); - } - else - { - (void)snprintf (apts_file, BUFSIZ, "%s", cfile); - (void)strncpy (path_apts, apts_file, BUFSIZ); - /* check if the file exists, otherwise create it */ - data_file = fopen (path_apts, "r"); - if (data_file == NULL) - { - printf (_("%s does not exist, create it now [y or n] ? "), - path_apts); - ch = getchar (); - switch (ch) - { - case 'N': - case 'n': - printf (_("aborting...\n")); - exit_calcurse (EXIT_FAILURE); - break; - - case 'Y': - case 'y': - data_file = fopen (path_apts, "w"); - if (data_file == NULL) - { - perror (path_apts); - exit_calcurse (EXIT_FAILURE); - } - else - { - printf (_("%s successfully created\n"), path_apts); - printf (_("starting interactive mode...\n")); - } - break; - - default: - printf (_("aborting...\n")); - exit_calcurse (EXIT_FAILURE); - break; - } - } - file_close (data_file, __FILE_POS__); + if (datadir != NULL) { + home = datadir; + snprintf(path_dir, BUFSIZ, "%s", home); + snprintf(path_todo, BUFSIZ, "%s/" TODO_PATH_NAME, home); + snprintf(path_conf, BUFSIZ, "%s/" CONF_PATH_NAME, home); + snprintf(path_notes, BUFSIZ, "%s/" NOTES_DIR_NAME, home); + snprintf(path_apts, BUFSIZ, "%s/" APTS_PATH_NAME, home); + snprintf(path_keys, BUFSIZ, "%s/" KEYS_PATH_NAME, home); + snprintf(path_cpid, BUFSIZ, "%s/" CPID_PATH_NAME, home); + snprintf(path_dpid, BUFSIZ, "%s/" DPID_PATH_NAME, home); + snprintf(path_dmon_log, BUFSIZ, "%s/" DLOG_PATH_NAME, home); + } else { + home = getenv("HOME"); + if (home == NULL) { + home = "."; + } + snprintf(path_dir, BUFSIZ, "%s/" DIR_NAME, home); + snprintf(path_todo, BUFSIZ, "%s/" TODO_PATH, home); + snprintf(path_conf, BUFSIZ, "%s/" CONF_PATH, home); + snprintf(path_keys, BUFSIZ, "%s/" KEYS_PATH, home); + snprintf(path_cpid, BUFSIZ, "%s/" CPID_PATH, home); + snprintf(path_dpid, BUFSIZ, "%s/" DPID_PATH, home); + snprintf(path_dmon_log, BUFSIZ, "%s/" DLOG_PATH, home); + snprintf(path_notes, BUFSIZ, "%s/" NOTES_DIR, home); + if (cfile == NULL) { + snprintf(path_apts, BUFSIZ, "%s/" APTS_PATH, home); + } else { + snprintf(apts_file, BUFSIZ, "%s", cfile); + strncpy(path_apts, apts_file, BUFSIZ); + /* check if the file exists, otherwise create it */ + data_file = fopen(path_apts, "r"); + if (data_file == NULL) { + printf(_("%s does not exist, create it now [y or n] ? "), path_apts); + ch = getchar(); + switch (ch) { + case 'N': + case 'n': + puts(_("aborting...\n")); + exit_calcurse(EXIT_FAILURE); + break; + + case 'Y': + case 'y': + data_file = fopen(path_apts, "w"); + if (data_file == NULL) { + perror(path_apts); + exit_calcurse(EXIT_FAILURE); + } else { + printf(_("%s successfully created\n"), path_apts); + puts(_("starting interactive mode...\n")); + } + break; + + default: + puts(_("aborting...\n")); + exit_calcurse(EXIT_FAILURE); + break; } + } + file_close(data_file, __FILE_POS__); } + } } -void -io_extract_data (char *dst_data, const char *org, int len) +void io_extract_data(char *dst_data, const char *org, int len) { int i; - for (i = 0; i < len - 1; i++) - { - if (*org == '\n' || *org == '\0') - break; - *dst_data++ = *org++; - } + for (; *org == ' ' || *org == '\t'; org++) ; + for (i = 0; i < len - 1; i++) { + if (*org == '\n' || *org == '\0' || *org == '#') + break; + *dst_data++ = *org++; + } *dst_data = '\0'; } -void -display_mark (void) +static void display_mark(void) { const int DISPLAY_TIME = 1; WINDOW *mwin; - mwin = newwin (1, 2, 1, col - 3); + mwin = newwin(1, 2, 1, col - 3); - custom_apply_attr (mwin, ATTR_HIGHEST); - mvwprintw (mwin, 0, 0, "**"); - wins_wrefresh (mwin); - sleep (DISPLAY_TIME); - mvwprintw (mwin, 0, 0, " "); - wins_wrefresh (mwin); - delwin (mwin); - wins_doupdate (); + custom_apply_attr(mwin, ATTR_HIGHEST); + mvwprintw(mwin, 0, 0, "**"); + wins_wrefresh(mwin); + sleep(DISPLAY_TIME); + mvwprintw(mwin, 0, 0, " "); + wins_wrefresh(mwin); + delwin(mwin); + wins_doupdate(); } static pthread_mutex_t io_save_mutex = PTHREAD_MUTEX_INITIALIZER; -/* Save the user configuration. */ -unsigned -io_save_conf (struct conf *conf) -{ - char *config_txt = - "#\n" - "# Calcurse configuration file\n#\n" - "# This file sets the configuration options used by Calcurse. These\n" - "# options are usually set from within Calcurse. A line beginning with \n" - "# a space or tab is considered to be a continuation of the previous " - "line.\n" - "# For a variable to be unset its value must be blank.\n" - "# To set a variable to the empty string its value should be \"\".\n" - "# Lines beginning with \"#\" are comments, and ignored by Calcurse.\n"; - char theme_name[BUFSIZ]; - FILE *fp; - - if ((fp = fopen (path_conf, "w")) == NULL) - return 0; - - custom_color_theme_name (theme_name); - - (void)fprintf (fp, "%s\n", config_txt); - - (void)fprintf (fp, "# If this option is set to yes, " - "automatic save is done when quitting\n"); - (void)fprintf (fp, "auto_save=\n"); - (void)fprintf (fp, "%s\n", (conf->auto_save) ? "yes" : "no"); - - (void)fprintf (fp, "\n# If not null, perform automatic saves every " - "'periodic_save' minutes\n"); - (void)fprintf (fp, "periodic_save=\n"); - (void)fprintf (fp, "%d\n", conf->periodic_save); - - (void)fprintf (fp, "\n# If this option is set to yes, " - "confirmation is required before quitting\n"); - (void)fprintf (fp, "confirm_quit=\n"); - (void)fprintf (fp, "%s\n", (conf->confirm_quit) ? "yes" : "no"); - - (void)fprintf (fp, "\n# If this option is set to yes, " - "confirmation is required before deleting an event\n"); - (void)fprintf (fp, "confirm_delete=\n"); - (void)fprintf (fp, "%s\n", (conf->confirm_delete) ? "yes" : "no"); - - (void)fprintf (fp, "\n# If this option is set to yes, " - "messages about loaded and saved data will not be displayed\n"); - (void)fprintf (fp, "skip_system_dialogs=\n"); - (void)fprintf (fp, "%s\n", (conf->skip_system_dialogs) ? "yes" : "no"); - - (void)fprintf (fp, - "\n# If this option is set to yes, progress bar appearing " - "when saving data will not be displayed\n"); - (void)fprintf (fp, "skip_progress_bar=\n"); - (void)fprintf (fp, "%s\n", (conf->skip_progress_bar) ? "yes" : "no"); - - (void)fprintf (fp, "\n# Default calendar view (0)monthly (1)weekly:\n"); - (void)fprintf (fp, "calendar_default_view=\n"); - (void)fprintf (fp, "%d\n", calendar_get_view ()); - - (void)fprintf (fp, "\n# If this option is set to yes, " - "monday is the first day of the week, else it is sunday\n"); - (void)fprintf (fp, "week_begins_on_monday=\n"); - (void)fprintf (fp, "%s\n", - (calendar_week_begins_on_monday ())? "yes" : "no"); - - (void)fprintf (fp, "\n# This is the color theme used for menus :\n"); - (void)fprintf (fp, "color-theme=\n"); - (void)fprintf (fp, "%s\n", theme_name); - - (void)fprintf (fp, "\n# This is the layout of the calendar :\n"); - (void)fprintf (fp, "layout=\n"); - (void)fprintf (fp, "%d\n", wins_layout ()); - - (void)fprintf (fp, "\n# Width (in percentage, 0 being minimun width) " - "of the side bar :\n"); - (void)fprintf (fp, "side-bar_width=\n"); - (void)fprintf (fp, "%d\n", wins_sbar_wperc ()); - - if (ui_mode == UI_CURSES) - pthread_mutex_lock (&nbar.mutex); - (void)fprintf (fp, - "\n# If this option is set to yes, " - "notify-bar will be displayed :\n"); - (void)fprintf (fp, "notify-bar_show=\n"); - (void)fprintf (fp, "%s\n", (nbar.show) ? "yes" : "no"); - - (void)fprintf (fp, - "\n# Format of the date to be displayed inside notify-bar :\n"); - (void)fprintf (fp, "notify-bar_date=\n"); - (void)fprintf (fp, "%s\n", nbar.datefmt); - - (void)fprintf (fp, - "\n# Format of the time to be displayed inside notify-bar :\n"); - (void)fprintf (fp, "notify-bar_clock=\n"); - (void)fprintf (fp, "%s\n", nbar.timefmt); - - (void)fprintf (fp, - "\n# Warn user if he has an appointment within next " - "'notify-bar_warning' seconds :\n"); - (void)fprintf (fp, "notify-bar_warning=\n"); - (void)fprintf (fp, "%d\n", nbar.cntdwn); - - (void)fprintf (fp, "\n# Command used to notify user of " - "an upcoming appointment :\n"); - (void)fprintf (fp, "notify-bar_command=\n"); - (void)fprintf (fp, "%s\n", nbar.cmd); - - (void)fprintf (fp, "\n# Format of the date to be displayed " - "in non-interactive mode :\n"); - (void)fprintf (fp, "output_datefmt=\n"); - (void)fprintf (fp, "%s\n", conf->output_datefmt); - - (void)fprintf (fp, "\n# Format to be used when entering a date " - "(1)mm/dd/yyyy (2)dd/mm/yyyy (3)yyyy/mm/dd) " - "(4)yyyy-mm-dd:\n"); - (void)fprintf (fp, "input_datefmt=\n"); - (void)fprintf (fp, "%d\n", conf->input_datefmt); - - if (ui_mode == UI_CURSES) - pthread_mutex_unlock (&nbar.mutex); - - (void)fprintf (fp, "\n# If this option is set to yes, " - "calcurse will run in background to get notifications " - "after exiting\n"); - (void)fprintf (fp, "notify-daemon_enable=\n"); - (void)fprintf (fp, "%s\n", dmon.enable ? "yes" : "no"); - - (void)fprintf (fp, "\n# If this option is set to yes, " - "activity will be logged when running in background\n"); - (void)fprintf (fp, "notify-daemon_log=\n"); - (void)fprintf (fp, "%s\n", dmon.log ? "yes" : "no"); - - file_close (fp, __FILE_POS__); - - return 1; -} - /* * Save the apts data file, which contains the * appointments first, and then the events. * Recursive items are written first. */ -unsigned -io_save_apts (void) +unsigned io_save_apts(void) { llist_item_t *i; FILE *fp; - if ((fp = fopen (path_apts, "w")) == NULL) + if (read_only) + return 1; + + if ((fp = fopen(path_apts, "w")) == NULL) return 0; - recur_save_data (fp); + recur_save_data(fp); if (ui_mode == UI_CURSES) - LLIST_TS_LOCK (&alist_p); - LLIST_TS_FOREACH (&alist_p, i) - { - struct apoint *apt = LLIST_TS_GET_DATA (i); - apoint_write (apt, fp); - } + LLIST_TS_LOCK(&alist_p); + LLIST_TS_FOREACH(&alist_p, i) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + apoint_write(apt, fp); + } if (ui_mode == UI_CURSES) - LLIST_TS_UNLOCK (&alist_p); + LLIST_TS_UNLOCK(&alist_p); - LLIST_FOREACH (&eventlist, i) - { - struct event *ev = LLIST_TS_GET_DATA (i); - event_write (ev, fp); - } - file_close (fp, __FILE_POS__); + LLIST_FOREACH(&eventlist, i) { + struct event *ev = LLIST_TS_GET_DATA(i); + event_write(ev, fp); + } + file_close(fp, __FILE_POS__); return 1; } /* Save the todo data file. */ -unsigned -io_save_todo (void) +unsigned io_save_todo(void) { llist_item_t *i; FILE *fp; - if ((fp = fopen (path_todo, "w")) == NULL) + if (read_only) + return 1; + + if ((fp = fopen(path_todo, "w")) == NULL) return 0; - LLIST_FOREACH (&todolist, i) - { - struct todo *todo = LLIST_TS_GET_DATA (i); - if (todo->note) - (void)fprintf (fp, "[%d]>%s %s\n", todo->id, todo->note, todo->mesg); - else - (void)fprintf (fp, "[%d] %s\n", todo->id, todo->mesg); - } - file_close (fp, __FILE_POS__); + LLIST_FOREACH(&todolist, i) { + struct todo *todo = LLIST_TS_GET_DATA(i); + todo_write(todo, fp); + } + file_close(fp, __FILE_POS__); return 1; } /* Save user-defined keys */ -unsigned -io_save_keys (void) +unsigned io_save_keys(void) { FILE *fp; - if ((fp = fopen (path_keys, "w")) == NULL) + if (read_only) + return 1; + + if ((fp = fopen(path_keys, "w")) == NULL) return 0; - keys_save_bindings (fp); - file_close (fp, __FILE_POS__); + keys_save_bindings(fp); + file_close(fp, __FILE_POS__); return 1; } /* Save the calendar data */ -void -io_save_cal (struct conf *conf, enum save_display display) +void io_save_cal(enum save_display display) { - char *access_pb = _("Problems accessing data file ..."); - char *save_success = _("The data files were successfully saved"); - char *enter = _("Press [ENTER] to continue"); + const char *access_pb = _("Problems accessing data file ..."); + const char *save_success = _("The data files were successfully saved"); + const char *enter = _("Press [ENTER] to continue"); int show_bar; - pthread_mutex_lock (&io_save_mutex); + if (read_only) + return; + + pthread_mutex_lock(&io_save_mutex); show_bar = 0; if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_BAR - && !conf->skip_progress_bar) + && conf.progress_bar) show_bar = 1; else if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_MARK) - display_mark (); + display_mark(); if (show_bar) - progress_bar (PROGRESS_BAR_SAVE, PROGRESS_BAR_CONF); - if (!io_save_conf (conf)) - ERROR_MSG ("%s", access_pb); + progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_CONF); + if (!config_save()) + ERROR_MSG("%s", access_pb); if (show_bar) - progress_bar (PROGRESS_BAR_SAVE, PROGRESS_BAR_TODO); - if (!io_save_todo ()) - ERROR_MSG ("%s", access_pb); + progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_TODO); + if (!io_save_todo()) + ERROR_MSG("%s", access_pb); if (show_bar) - progress_bar (PROGRESS_BAR_SAVE, PROGRESS_BAR_APTS); - if (!io_save_apts ()) - ERROR_MSG ("%s", access_pb); + progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_APTS); + if (!io_save_apts()) + ERROR_MSG("%s", access_pb); if (show_bar) - progress_bar (PROGRESS_BAR_SAVE, PROGRESS_BAR_KEYS); - if (!io_save_keys ()) - ERROR_MSG ("%s", access_pb); + progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_KEYS); + if (!io_save_keys()) + ERROR_MSG("%s", access_pb); /* Print a message telling data were saved */ - if (ui_mode == UI_CURSES && !conf->skip_system_dialogs - && display != IO_SAVE_DISPLAY_MARK) - { - status_mesg (save_success, enter); - (void)wgetch (win[STA].p); - } + if (ui_mode == UI_CURSES && conf.system_dialogs + && display != IO_SAVE_DISPLAY_MARK) { + status_mesg(save_success, enter); + wgetch(win[STA].p); + } - pthread_mutex_unlock (&io_save_mutex); + pthread_mutex_unlock(&io_save_mutex); } /* @@ -1107,8 +450,7 @@ io_save_cal (struct conf *conf, enum save_display display) * and then load either: a new appointment, a new event, or a new * recursive item (which can also be either an event or an appointment). */ -void -io_load_app (void) +void io_load_app(void) { FILE *data_file; int c, is_appointment, is_event, is_recursive; @@ -1118,251 +460,206 @@ io_load_app (void) int id = 0; int freq; char type, state = 0L; - char note[NOTESIZ + 1], *notep; + char note[MAX_NOTESIZ + 1], *notep; - t = time (NULL); - lt = localtime (&t); + t = time(NULL); + lt = localtime(&t); start = end = until = *lt; - data_file = fopen (path_apts, "r"); - for (;;) - { - LLIST_INIT (&exc); - is_appointment = is_event = is_recursive = 0; - c = getc (data_file); - if (c == EOF) - break; - (void)ungetc (c, data_file); - - /* Read the date first: it is common to both events - * and appointments. - */ - if (fscanf (data_file, "%u / %u / %u ", - &start.tm_mon, &start.tm_mday, &start.tm_year) != 3) - { - EXIT (_("syntax error in the item date")); - } - - /* Read the next character : if it is an '@' then we have - * an appointment, else if it is an '[' we have en event. - */ - c = getc (data_file); - - if (c == '@') - is_appointment = 1; - else if (c == '[') - is_event = 1; - else - { - EXIT (_("no event nor appointment found")); - } - (void)ungetc (c, data_file); - - /* Read the remaining informations. */ - if (is_appointment) - { - fscanf (data_file, "@ %u : %u -> %u / %u / %u @ %u : %u ", - &start.tm_hour, &start.tm_min, - &end.tm_mon, &end.tm_mday, &end.tm_year, - &end.tm_hour, &end.tm_min); - } - else if (is_event) - { - fscanf (data_file, "[%d] ", &id); - } - else - { - EXIT (_("wrong format in the appointment or event")); - /* NOTREACHED */ - } + data_file = fopen(path_apts, "r"); + EXIT_IF(data_file == NULL, _("failed to open appointment file")); - /* Check if we have a recursive item. */ - c = getc (data_file); - - if (c == '{') - { - (void)ungetc (c, data_file); - is_recursive = 1; - fscanf (data_file, "{ %d%c ", &freq, &type); - - c = getc (data_file); - if (c == '}') - { /* endless recurrent item */ - (void)ungetc (c, data_file); - fscanf (data_file, "} "); - until.tm_year = 0; - } - else if (c == '-') - { - (void)ungetc (c, data_file); - fscanf (data_file, " -> %u / %u / %u ", - &until.tm_mon, &until.tm_mday, &until.tm_year); - c = getc (data_file); - if (c == '!') - { - (void)ungetc (c, data_file); - recur_exc_scan (&exc, data_file); - c = getc (data_file); - } - else - { - (void)ungetc (c, data_file); - fscanf (data_file, "} "); - } - } - else if (c == '!') - { // endless item with exceptions - (void)ungetc (c, data_file); - recur_exc_scan (&exc, data_file); - c = getc (data_file); - until.tm_year = 0; - } - else - { - EXIT (_("wrong format in the appointment or event")); - /* NOTREACHED */ - } - } - else - (void)ungetc (c, data_file); - - /* Check if a note is attached to the item. */ - c = getc (data_file); - if (c == '>') - { - (void)fgets (note, NOTESIZ + 1, data_file); - note[NOTESIZ] = '\0'; - notep = note; - getc (data_file); - } - else - { - notep = NULL; - (void)ungetc (c, data_file); - } + for (;;) { + LLIST_INIT(&exc); + is_appointment = is_event = is_recursive = 0; + c = getc(data_file); + if (c == EOF) + break; + ungetc(c, data_file); + + /* Read the date first: it is common to both events + * and appointments. + */ + if (fscanf(data_file, "%d / %d / %d ", + &start.tm_mon, &start.tm_mday, &start.tm_year) != 3) + EXIT(_("syntax error in the item date")); + + /* Read the next character : if it is an '@' then we have + * an appointment, else if it is an '[' we have en event. + */ + c = getc(data_file); + + if (c == '@') + is_appointment = 1; + else if (c == '[') + is_event = 1; + else + EXIT(_("no event nor appointment found")); + + /* Read the remaining informations. */ + if (is_appointment) { + if (fscanf(data_file, " %d : %d -> %d / %d / %d @ %d : %d ", + &start.tm_hour, &start.tm_min, + &end.tm_mon, &end.tm_mday, &end.tm_year, + &end.tm_hour, &end.tm_min) != 7) + EXIT(_("syntax error in item time or duration")); + } else if (is_event) { + if (fscanf(data_file, " %d ", &id) != 1 || getc(data_file) != ']') + EXIT(_("syntax error in item identifier")); + while ((c = getc(data_file)) == ' ') ; + ungetc(c, data_file); + } else { + EXIT(_("wrong format in the appointment or event")); + /* NOTREACHED */ + } - /* - * Last: read the item description and load it into its - * corresponding linked list, depending on the item type. - */ - if (is_appointment) - { - c = getc (data_file); - if (c == '!') - { - (void)ungetc (c, data_file); - fscanf (data_file, " ! "); - state |= APOINT_NOTIFY; - } - else - { - (void)ungetc (c, data_file); - fscanf (data_file, " | "); - state = 0L; - } - if (is_recursive) - { - recur_apoint_scan (data_file, start, end, - type, freq, until, notep, &exc, state); - } - else - { - 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, notep, &exc); - } - else - { - event_scan (data_file, start, id, notep); - } - } - else - { - EXIT (_("wrong format in the appointment or event")); - /* NOTREACHED */ - } + /* Check if we have a recursive item. */ + c = getc(data_file); + + if (c == '{') { + is_recursive = 1; + if (fscanf(data_file, " %d%c ", &freq, &type) != 2) + EXIT(_("syntax error in item repetition")); + + c = getc(data_file); + if (c == '}') { /* endless recurrent item */ + until.tm_year = 0; + while ((c = getc(data_file)) == ' ') ; + ungetc(c, data_file); + } else if (c == '-' && getc(data_file) == '>') { + if (fscanf(data_file, " %d / %d / %d ", &until.tm_mon, + &until.tm_mday, &until.tm_year) != 3) + EXIT(_("syntax error in item repetition")); + c = getc(data_file); + if (c == '!') { + ungetc(c, data_file); + recur_exc_scan(&exc, data_file); + c = getc(data_file); + } else if (c == '}') { + while ((c = getc(data_file)) == ' ') ; + ungetc(c, data_file); + } else + EXIT(_("syntax error in item repetition")); + } else if (c == '!') { /* endless item with exceptions */ + ungetc(c, data_file); + recur_exc_scan(&exc, data_file); + c = getc(data_file); + until.tm_year = 0; + } else { + EXIT(_("wrong format in the appointment or event")); + /* NOTREACHED */ + } + } else + ungetc(c, data_file); + + /* Check if a note is attached to the item. */ + c = getc(data_file); + if (c == '>') { + note_read(note, data_file); + notep = note; + } 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. + */ + if (is_appointment) { + c = getc(data_file); + if (c == '!') { + state |= APOINT_NOTIFY; + while ((c = getc(data_file)) == ' ') ; + ungetc(c, data_file); + } else if (c == '|') { + state = 0L; + while ((c = getc(data_file)) == ' ') ; + ungetc(c, data_file); + } else + EXIT(_("syntax error in item repetition")); + if (is_recursive) { + recur_apoint_scan(data_file, start, end, + type, freq, until, notep, &exc, state); + } else { + 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, notep, &exc); + } else { + event_scan(data_file, start, id, notep); + } + } else { + EXIT(_("wrong format in the appointment or event")); + /* NOTREACHED */ } - file_close (data_file, __FILE_POS__); + } + file_close(data_file, __FILE_POS__); } /* Load the todo data */ -void -io_load_todo (void) +void io_load_todo(void) { FILE *data_file; - char *mesg_line1 = _("Failed to open todo file"); - char *mesg_line2 = _("Press [ENTER] to continue"); char *newline; int nb_tod = 0; int c, id; - char buf[BUFSIZ], e_todo[BUFSIZ], note[NOTESIZ + 1]; + char buf[BUFSIZ], e_todo[BUFSIZ], note[MAX_NOTESIZ + 1]; - data_file = fopen (path_todo, "r"); - if (data_file == NULL) - { - status_mesg (mesg_line1, mesg_line2); - (void)wgetch (win[STA].p); - } - for (;;) - { - c = getc (data_file); - if (c == EOF) - { - break; - } - else if (c == '[') - { /* new style with id */ - fscanf (data_file, "%d]", &id); - } - else - { - id = 9; - (void)ungetc (c, data_file); - } - /* Now read the attached note, if any. */ - c = getc (data_file); - if (c == '>') - { - (void)fgets (note, NOTESIZ + 1, data_file); - note[NOTESIZ] = '\0'; - getc (data_file); - } - else - note[0] = '\0'; - /* Then read todo description. */ - (void)fgets (buf, sizeof buf, data_file); - newline = strchr (buf, '\n'); - if (newline) - *newline = '\0'; - io_extract_data (e_todo, buf, sizeof buf); - todo_add (e_todo, id, note); - ++nb_tod; - } - file_close (data_file, __FILE_POS__); - todo_set_nb (nb_tod); + data_file = fopen(path_todo, "r"); + EXIT_IF(data_file == NULL, _("failed to open todo file")); + + for (;;) { + c = getc(data_file); + if (c == EOF) + break; + else if (c == '[') { /* new style with id */ + if (fscanf(data_file, " %d ", &id) != 1 || getc(data_file) != ']') + EXIT(_("syntax error in item identifier")); + while ((c = getc(data_file)) == ' ') ; + ungetc(c, data_file); + } else { + id = 9; + ungetc(c, data_file); + } + /* Now read the attached note, if any. */ + c = getc(data_file); + if (c == '>') + note_read(note, data_file); + else { + note[0] = '\0'; + ungetc(c, data_file); + } + /* Then read todo description. */ + if (!fgets(buf, sizeof buf, data_file)) + buf[0] = '\0'; + newline = strchr(buf, '\n'); + if (newline) + *newline = '\0'; + io_extract_data(e_todo, buf, sizeof buf); + todo_add(e_todo, id, note); + ++nb_tod; + } + file_close(data_file, __FILE_POS__); + todo_set_nb(nb_tod); } static void -load_keys_ht_getkey (struct ht_keybindings_s *data, char **key, int *len) +load_keys_ht_getkey(struct ht_keybindings_s *data, const char **key, int *len) { *key = data->label; - *len = strlen (data->label); + *len = strlen(data->label); } static int -load_keys_ht_compare (struct ht_keybindings_s *data1, - struct ht_keybindings_s *data2) +load_keys_ht_compare(struct ht_keybindings_s *data1, + struct ht_keybindings_s *data2) { - const int KEYLEN = strlen (data1->label); + const int KEYLEN = strlen(data1->label); - if (strlen (data2->label) == KEYLEN - && !memcmp (data1->label, data2->label, KEYLEN)) + if (strlen(data2->label) == KEYLEN + && !memcmp(data1->label, data2->label, KEYLEN)) return 0; else return 1; @@ -1373,7 +670,7 @@ load_keys_ht_compare (struct ht_keybindings_s *data1, * visible in some specific cases. Thus replace it by the following is_blank() * function. */ -static int is_blank (int c) +static int is_blank(int c) { return c == ' ' || c == '\t'; } @@ -1385,8 +682,7 @@ static int is_blank (int c) * A log file is also built in case some errors were found in the key * configuration file. */ -void -io_load_keys (char *pager) +void io_load_keys(const char *pager) { struct ht_keybindings_s keys[NBKEYS]; FILE *keyfp; @@ -1395,187 +691,163 @@ io_load_keys (char *pager) int i, skipped, loaded, line; const int MAX_ERRORS = 5; - keys_init (); + keys_init(); -#define HSIZE 256 - HTABLE_HEAD (ht_keybindings, HSIZE, ht_keybindings_s) ht_keys = - HTABLE_INITIALIZER (&ht_keys); + struct ht_keybindings ht_keys = HTABLE_INITIALIZER(&ht_keys); - HTABLE_GENERATE (ht_keybindings, ht_keybindings_s, load_keys_ht_getkey, - load_keys_ht_compare); + for (i = 0; i < NBKEYS; i++) { + keys[i].key = (enum key)i; + keys[i].label = keys_get_label((enum key)i); + HTABLE_INSERT(ht_keybindings, &ht_keys, &keys[i]); + } - for (i = 0; i < NBKEYS; i++) - { - keys[i].key = (enum key)i; - keys[i].label = keys_get_label ((enum key)i); - HTABLE_INSERT (ht_keybindings, &ht_keys, &keys[i]); - } + keyfp = fopen(path_keys, "r"); + EXIT_IF(keyfp == NULL, _("failed to open key file")); - keyfp = fopen (path_keys, "r"); - EXIT_IF (keyfp == NULL, _("could not find any key file.")); - log = io_log_init (); + log = io_log_init(); skipped = loaded = line = 0; - while (fgets (buf, BUFSIZ, keyfp) != NULL) - { - char key_label[BUFSIZ], *p; - struct ht_keybindings_s *ht_elm, ht_entry; - const int AWAITED = 1; - int assigned; - - line++; - if (skipped > MAX_ERRORS) - { - char *too_many = - _("\nToo many errors while reading configuration file!\n" - "Please backup your keys file, remove it from directory, " - "and launch calcurse again.\n"); - - io_log_print (log, line, too_many); - break; - } - for (p = buf; is_blank ((int)*p); p++) - ; - if (p != buf) - memmove (buf, p, strlen (p)); - if (buf[0] == '#' || buf[0] == '\n') - continue; - - if (sscanf (buf, "%s", key_label) != AWAITED) - { - skipped++; - io_log_print (log, line, _("Could not read key label")); - continue; - } - ht_entry.label = key_label; - p = buf + strlen (key_label) + 1; - ht_elm = HTABLE_LOOKUP (ht_keybindings, &ht_keys, &ht_entry); - if (!ht_elm) - { + while (fgets(buf, BUFSIZ, keyfp) != NULL) { + char key_label[BUFSIZ], *p; + struct ht_keybindings_s *ht_elm, ht_entry; + const int AWAITED = 1; + int assigned; + + line++; + if (skipped > MAX_ERRORS) { + const char *too_many = + _("\nToo many errors while reading configuration file!\n" + "Please backup your keys file, remove it from directory, " + "and launch calcurse again.\n"); + + io_log_print(log, line, too_many); + break; + } + for (p = buf; is_blank((int)*p); p++) ; + if (p != buf) + memmove(buf, p, strlen(p)); + if (buf[0] == '#' || buf[0] == '\n') + continue; + + if (sscanf(buf, "%s", key_label) != AWAITED) { + skipped++; + io_log_print(log, line, _("Could not read key label")); + continue; + } + ht_entry.label = key_label; + p = buf + strlen(key_label) + 1; + ht_elm = HTABLE_LOOKUP(ht_keybindings, &ht_keys, &ht_entry); + if (!ht_elm) { + skipped++; + io_log_print(log, line, _("Key label not recognized")); + continue; + } + assigned = 0; + for (;;) { + char key_ch[BUFSIZ], tmpbuf[BUFSIZ]; + + while (*p == ' ') + p++; + (void)strncpy(tmpbuf, p, BUFSIZ); + if (sscanf(tmpbuf, "%s", key_ch) == AWAITED) { + int ch; + + if ((ch = keys_str2int(key_ch)) < 0) { + char unknown_key[BUFSIZ]; + skipped++; - io_log_print (log, line, _("Key label not recognized")); - continue; - } - assigned = 0; - for (;;) - { - char key_ch[BUFSIZ], tmpbuf[BUFSIZ]; - - while (*p == ' ') - p++; - (void)strncpy (tmpbuf, p, BUFSIZ); - if (sscanf (tmpbuf, "%s", key_ch) == AWAITED) - { - int ch; - - if ((ch = keys_str2int (key_ch)) < 0) - { - char unknown_key[BUFSIZ]; - - skipped++; - (void)snprintf (unknown_key, BUFSIZ, - _("Error reading key: \"%s\""), key_ch); - io_log_print (log, line, unknown_key); - } - else - { - int used; - - used = keys_assign_binding (ch, ht_elm->key); - if (used) - { - char already_assigned[BUFSIZ]; - - skipped++; - (void)snprintf (already_assigned, BUFSIZ, - _("\"%s\" assigned multiple times!"), key_ch); - io_log_print (log, line, already_assigned); - } - else - assigned++; - } - p += strlen (key_ch) + 1; - } - else - { - if (assigned) - loaded++; - break; - } - } + (void)snprintf(unknown_key, BUFSIZ, + _("Error reading key: \"%s\""), key_ch); + io_log_print(log, line, unknown_key); + } else { + int used; + + used = keys_assign_binding(ch, ht_elm->key); + if (used) { + char already_assigned[BUFSIZ]; + + skipped++; + (void)snprintf(already_assigned, BUFSIZ, + _("\"%s\" assigned multiple times!"), key_ch); + io_log_print(log, line, already_assigned); + } else + assigned++; + } + p += strlen(key_ch) + 1; + } else { + if (assigned) + loaded++; + break; + } } - file_close (keyfp, __FILE_POS__); - file_close (log->fd, __FILE_POS__); - if (skipped > 0) - { - char *view_log = + } + file_close(keyfp, __FILE_POS__); + file_close(log->fd, __FILE_POS__); + if (skipped > 0) { + const char *view_log = _("There were some errors when loading keys file, see log file ?"); - io_log_display (log, view_log, pager); - } - io_log_free (log); - EXIT_IF (skipped > MAX_ERRORS, - _("Too many errors while reading keys file, aborting...")); + io_log_display(log, view_log, pager); + } + io_log_free(log); + EXIT_IF(skipped > MAX_ERRORS, + _("Too many errors while reading keys file, aborting...")); if (loaded < NBKEYS) - keys_fill_missing (); - if (keys_check_missing_bindings ()) - WARN_MSG (_("Some actions do not have any associated key bindings!")); -#undef HSIZE + keys_fill_missing(); + if (keys_check_missing_bindings()) + WARN_MSG(_("Some actions do not have any associated key bindings!")); } -void -io_check_dir (char *dir, int *missing) +void io_check_dir(char *dir, int *missing) { + if (read_only) + return; + errno = 0; - if (mkdir (dir, 0700) != 0) - { - if (errno != EEXIST) - { - (void)fprintf (stderr, _("FATAL ERROR: could not create %s: %s\n"), - dir, strerror (errno)); - exit_calcurse (EXIT_FAILURE); - } - } - else - { - if (missing) - (*missing)++; + if (mkdir(dir, 0700) != 0) { + if (errno != EEXIST) { + fprintf(stderr, _("FATAL ERROR: could not create %s: %s\n"), dir, + strerror(errno)); + exit_calcurse(EXIT_FAILURE); } + } else { + if (missing) + (*missing)++; + } } -unsigned -io_file_exist (char *file) +unsigned io_file_exist(char *file) { FILE *fd; if (!file) return 0; - if ((fd = fopen (file, "r")) == NULL) + if ((fd = fopen(file, "r")) == NULL) return 0; - (void)fclose (fd); + fclose(fd); return 1; } -void -io_check_file (char *file, int *missing) +void io_check_file(char *file, int *missing) { + if (read_only) + return; + errno = 0; - if (!io_file_exist (file)) - { - FILE *fd; - - if (missing) - (*missing)++; - if ((fd = fopen (file, "w")) == NULL) - { - (void)fprintf (stderr, _("FATAL ERROR: could not create %s: %s\n"), - file, strerror (errno)); - exit_calcurse (EXIT_FAILURE); - } - file_close (fd, __FILE_POS__); + if (!io_file_exist(file)) { + FILE *fd; + + if (missing) + (*missing)++; + if ((fd = fopen(file, "w")) == NULL) { + fprintf(stderr, _("FATAL ERROR: could not create %s: %s\n"), file, + strerror(errno)); + exit_calcurse(EXIT_FAILURE); } + file_close(fd, __FILE_POS__); + } } /* @@ -1590,1121 +862,127 @@ io_check_file (char *file, int *missing) * |___ apts * |___ todo */ -int -io_check_data_files (void) +int io_check_data_files(void) { int missing, missing_keys; missing = missing_keys = 0; errno = 0; - io_check_dir (path_dir, &missing); - io_check_dir (path_notes, &missing); - io_check_file (path_todo, &missing); - io_check_file (path_apts, &missing); - io_check_file (path_conf, &missing); - io_check_file (path_keys, &missing_keys); - if (missing_keys) - { - missing++; - keys_dump_defaults (path_keys); - } + io_check_dir(path_dir, &missing); + io_check_dir(path_notes, &missing); + io_check_file(path_todo, &missing); + io_check_file(path_apts, &missing); + io_check_file(path_conf, &missing); + io_check_file(path_keys, &missing_keys); + if (missing_keys) { + missing++; + keys_dump_defaults(path_keys); + } return missing; } /* Draw the startup screen */ -void -io_startup_screen (unsigned skip_dialogs, int no_data_file) +void io_startup_screen(int no_data_file) { - char *welcome_mesg = - _("Welcome to Calcurse. Missing data files were created."); - char *data_mesg = _("Data files found. Data will be loaded now."); - char *enter = _("Press [ENTER] to continue"); - - if (no_data_file != 0) - { - status_mesg (welcome_mesg, enter); - (void)wgetch (win[STA].p); - } - else if (!skip_dialogs) - { - status_mesg (data_mesg, enter); - (void)wgetch (win[STA].p); - } + const char *enter = _("Press [ENTER] to continue"); + + if (no_data_file) + status_mesg(_("Data files found. Data will be loaded now."), enter); + else + status_mesg(_("Welcome to Calcurse. Missing data files were created."), + enter); + + wgetch(win[STA].p); } /* Export calcurse data. */ -void -io_export_data (enum export_type type, struct conf *conf) +void io_export_data(enum export_type type) { FILE *stream; - char *success = _("The data were successfully exported"); - char *enter = _("Press [ENTER] to continue"); + const char *success = _("The data were successfully exported"); + const char *enter = _("Press [ENTER] to continue"); if (type < IO_EXPORT_ICAL || type >= IO_EXPORT_NBTYPES) - EXIT (_("unknown export type")); + EXIT(_("unknown export type")); stream = 0; - switch (ui_mode) - { - case UI_CMDLINE: - stream = stdout; - break; - case UI_CURSES: - stream = get_export_stream (type); - break; - default: - EXIT (_("wrong export mode")); - /* NOTREACHED */ - } + switch (ui_mode) { + case UI_CMDLINE: + stream = stdout; + break; + case UI_CURSES: + stream = get_export_stream(type); + break; + default: + EXIT(_("wrong export mode")); + /* NOTREACHED */ + } if (stream == NULL) return; - cb_export_header[type] (stream); - - if (!conf->skip_progress_bar && ui_mode == UI_CURSES) - progress_bar (PROGRESS_BAR_EXPORT, PROGRESS_BAR_EXPORT_EVENTS); - cb_export_recur_events[type] (stream); - cb_export_events[type] (stream); - - if (!conf->skip_progress_bar && ui_mode == UI_CURSES) - progress_bar (PROGRESS_BAR_EXPORT, PROGRESS_BAR_EXPORT_APOINTS); - cb_export_recur_apoints[type] (stream); - cb_export_apoints[type] (stream); + if (type == IO_EXPORT_ICAL) + ical_export_data(stream); + else if (type == IO_EXPORT_PCAL) + pcal_export_data(stream); - if (!conf->skip_progress_bar && ui_mode == UI_CURSES) - progress_bar (PROGRESS_BAR_EXPORT, PROGRESS_BAR_EXPORT_TODO); - cb_export_todo[type] (stream); - - cb_export_footer[type] (stream); - - if (stream != stdout) - file_close (stream, __FILE_POS__); - - if (!conf->skip_system_dialogs && ui_mode == UI_CURSES) - { - status_mesg (success, enter); - (void)wgetch (win[STA].p); - } + if (conf.system_dialogs && ui_mode == UI_CURSES) { + status_mesg(success, enter); + wgetch(win[STA].p); + } } /* Draws the export format selection bar */ -void -io_export_bar (void) +void io_export_bar(void) { int smlspc, spc; smlspc = 2; spc = 15; - custom_apply_attr (win[STA].p, ATTR_HIGHEST); - mvwprintw (win[STA].p, 0, 2, "Q"); - mvwprintw (win[STA].p, 1, 2, "I"); - mvwprintw (win[STA].p, 0, 2 + spc, "P"); - custom_remove_attr (win[STA].p, ATTR_HIGHEST); - - mvwprintw (win[STA].p, 0, 2 + smlspc, _("Exit")); - mvwprintw (win[STA].p, 1, 2 + smlspc, _("Ical")); - mvwprintw (win[STA].p, 0, 2 + spc + smlspc, _("Pcal")); - - wnoutrefresh (win[STA].p); - wmove (win[STA].p, 0, 0); - wins_doupdate (); -} - -/* Print a header to describe import log report format. */ -static void -ical_log_init (FILE *log, float version) -{ - const char *header = - "+-------------------------------------------------------------------+\n" - "| Calcurse icalendar import log. |\n" - "| |\n" - "| Items imported from icalendar file, version %1.1f |\n" - "| Some items could not be imported, they are described hereafter. |\n" - "| The log line format is as follows: |\n" - "| |\n" - "| TYPE [LINE]: DESCRIPTION |\n" - "| |\n" - "| where: |\n" - "| * TYPE represents the item type ('VEVENT' or 'VTODO') |\n" - "| * LINE is the line in the input stream at which this item begins |\n" - "| * DESCRIPTION indicates why the item could not be imported |\n" - "+-------------------------------------------------------------------+\n\n"; - - if (log) - (void)fprintf (log, header, version); -} - -/* - * Used to build a report of the import process. - * The icalendar item for which a problem occurs is mentioned (by giving its - * first line inside the icalendar file), together with a message describing the - * problem. - */ -static void -ical_log (FILE *log, ical_types_e type, unsigned lineno, char *msg) -{ - const char *typestr[ICAL_TYPES] = {"VEVENT", "VTODO"}; - - RETURN_IF (type < 0 || type >= ICAL_TYPES, _("unknown ical type")); - if (log) - (void)fprintf (log, "%s [%d]: %s\n", typestr[type], lineno, msg); -} - -static void -ical_store_todo (int priority, char *mesg, char *note) -{ - todo_add (mesg, priority, note); - mem_free (mesg); - erase_note (¬e, ERASE_FORCE_KEEP_NOTE); -} - -static void -ical_store_event (char *mesg, char *note, long day, long end, ical_rpt_t *rpt, - llist_t *exc) -{ - const int EVENTID = 1; - - if (rpt) - { - recur_event_new (mesg, note, day, EVENTID, rpt->type, rpt->freq, - rpt->until, exc); - mem_free (rpt); - } - else if (end && end != day) - { - /* Here we have an event that spans over several days. */ - rpt = mem_malloc (sizeof (ical_rpt_t)); - rpt->type = RECUR_DAILY; - rpt->freq = 1; - rpt->count = 0; - rpt->until = end; - recur_event_new (mesg, note, day, EVENTID, rpt->type, rpt->freq, - rpt->until, exc); - mem_free (rpt); - } - else - { - event_new (mesg, note, day, EVENTID); - } - mem_free (mesg); - erase_note (¬e, ERASE_FORCE_KEEP_NOTE); -} - -static void -ical_store_apoint (char *mesg, char *note, long start, long dur, - ical_rpt_t *rpt, llist_t *exc, int has_alarm) -{ - char state = 0L; - - if (has_alarm) - state |= APOINT_NOTIFY; - if (rpt) - { - recur_apoint_new (mesg, note, start, dur, state, rpt->type, rpt->freq, - rpt->until, exc); - mem_free (rpt); - } - else - { - apoint_new (mesg, note, start, dur, state); - } - mem_free (mesg); - erase_note (¬e, ERASE_FORCE_KEEP_NOTE); -} - -/* - * Returns an allocated string representing the string given in argument once - * unformatted. - * - * Note: - * Even if the RFC2445 recommends not to have more than 75 octets on one line of - * text, I prefer not to restrict the parsing to this size, thus I use a buffer - * of size BUFSIZ. - * - * Extract from RFC2445: - * Lines of text SHOULD NOT be longer than 75 octets, excluding the line - * break. - */ -static char * -ical_unformat_line (char *line) -{ - char *p, uline[BUFSIZ]; - int len; - - if (strlen (line) >= BUFSIZ) - return NULL; - - bzero (uline, BUFSIZ); - for (len = 0, p = line; *p; p++) - { - switch (*p) - { - case '\\': - switch (*(p + 1)) - { - case 'n': - uline[len++] = '\n'; - p++; - break; - case 't': - uline[len++] = '\t'; - p++; - break; - case ';': - case ':': - case ',': - uline[len++] = *(p + 1); - p++; - break; - default: - uline[len++] = *p; - break; - } - break; - default: - uline[len++] = *p; - break; - } - } - - return mem_strdup (uline); -} - -static void -ical_readline_init (FILE *fdi, char *buf, char *lstore, unsigned *ln) -{ - char *eol; - - *buf = *lstore = '\0'; - fgets (lstore, BUFSIZ, fdi); - if ((eol = strchr(lstore, '\n')) != NULL) - *eol = '\0'; - (*ln)++; -} - -static int -ical_readline (FILE *fdi, char *buf, char *lstore, unsigned *ln) -{ - char *eol; - - strncpy (buf, lstore, BUFSIZ); - (*ln)++; - - while (fgets (lstore, BUFSIZ, fdi) != NULL) - { - if ((eol = strchr(lstore, '\n')) != NULL) - *eol = '\0'; - if (*lstore != SPACE && *lstore != TAB) - break; - strncat (buf, lstore + 1, BUFSIZ); - buf[BUFSIZ - 1] = '\0'; - (*ln)++; - } - - if (feof (fdi)) - { - *lstore = '\0'; - if (*buf == '\0') - return 0; - } - - return 1; -} - -static float -ical_chk_header (FILE *fd, char *buf, char *lstore, unsigned *lineno) -{ - const int HEADER_MALFORMED = -1; - const struct string icalheader = STRING_BUILD ("BEGIN:VCALENDAR"); - float version; - - if (!ical_readline (fd, buf, lstore, lineno)) - return HEADER_MALFORMED; - - str_toupper (buf); - if (strncmp (buf, icalheader.str, icalheader.len) != 0) - return HEADER_MALFORMED; - - while (!sscanf (buf, "VERSION:%f", &version)) - { - if (!ical_readline (fd, buf, lstore, lineno)) - return HEADER_MALFORMED; - } - return version; -} - -/* - * iCalendar date-time format is based on the ISO 8601 complete - * representation. It should be something like : DATE 'T' TIME - * where DATE is 'YYYYMMDD' and TIME is 'HHMMSS'. - * The time and 'T' separator are optional (in the case of an day-long event). - * - * Optionnaly, if the type pointer is given, specify if it is an event - * (no time is given, meaning it is an all-day event), or an appointment - * (time is given). - * - * The timezone is not yet handled by calcurse. - */ -static long -ical_datetime2long (char *datestr, ical_vevent_e *type) -{ - const int NOTFOUND = 0, FORMAT_DATE = 3, FORMAT_DATETIME = 5; - struct date date; - unsigned hour, min; - long datelong; - int format; - - format = sscanf (datestr, "%04u%02u%02uT%02u%02u", - &date.yyyy, &date.mm, &date.dd, &hour, &min); - if (format == FORMAT_DATE) - { - if (type) - *type = EVENT; - datelong = date2sec (date, 0, 0); - } - else if (format == FORMAT_DATETIME) - { - if (type) - *type = APPOINTMENT; - datelong = date2sec (date, hour, min); - } - else - { - datelong = NOTFOUND; - } - return datelong; -} - -static long -ical_durtime2long (char *timestr) -{ - long timelong; - char *p; - - if ((p = strchr (timestr, 'T')) == NULL) - timelong = 0; - else - { - int nbmatch; - struct { - unsigned hour, min, sec; - } time; - - p++; - bzero (&time, sizeof time); - nbmatch = sscanf (p, "%uH%uM%uS", &time.hour, &time.min, &time.sec); - if (nbmatch < 1 || nbmatch > 3) - timelong = 0; - else - timelong = time.hour * HOURINSEC + time.min * MININSEC + time.sec; - } - return timelong; -} - -/* - * Extract from RFC2445: - * - * Value Name: DURATION - * - * Purpose: This value type is used to identify properties that contain - * duration of time. - * - * Formal Definition: The value type is defined by the following - * notation: - * - * dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week) - * dur-date = dur-day [dur-time] - * dur-time = "T" (dur-hour / dur-minute / dur-second) - * dur-week = 1*DIGIT "W" - * dur-hour = 1*DIGIT "H" [dur-minute] - * dur-minute = 1*DIGIT "M" [dur-second] - * dur-second = 1*DIGIT "S" - * dur-day = 1*DIGIT "D" - * - * Example: A duration of 15 days, 5 hours and 20 seconds would be: - * P15DT5H0M20S - * A duration of 7 weeks would be: - * P7W - */ -static long -ical_dur2long (char *durstr) -{ - const int NOTFOUND = -1; - long durlong; - char *p; - struct { - unsigned week, day; - } date; - - bzero (&date, sizeof date); - if ((p = strchr (durstr, 'P')) == NULL) - durlong = NOTFOUND; - else - { - p++; - if (*p == '-') - return NOTFOUND; - else if (*p == '+') - p++; - - if (*p == 'T') /* dur-time */ - durlong = ical_durtime2long (p); - else if (strchr (p, 'W')) /* dur-week */ - { - if (sscanf (p, "%u", &date.week) == 1) - durlong = date.week * WEEKINDAYS * DAYINSEC; - else - durlong = NOTFOUND; - } - else - { - if (strchr (p, 'D')) /* dur-date */ - { - if (sscanf (p, "%uD", &date.day) == 1) - { - durlong = date.day * DAYINSEC; - durlong += ical_durtime2long (p); - } - else - durlong = NOTFOUND; - } - else - durlong = NOTFOUND; - } - } - return durlong; -} - -/* - * Compute the vevent repetition end date from the repetition count. - * - * Extract from RFC2445: - * The COUNT rule part defines the number of occurrences at which to - * range-bound the recurrence. The "DTSTART" property value, if specified, - * counts as the first occurrence. - */ -static long -ical_compute_rpt_until (long start, ical_rpt_t *rpt) -{ - long until; - - switch (rpt->type) - { - case RECUR_DAILY: - until = date_sec_change (start, 0, rpt->freq * (rpt->count - 1)); - break; - case RECUR_WEEKLY: - until = date_sec_change (start, 0, - rpt->freq * WEEKINDAYS * (rpt->count - 1)); - break; - case RECUR_MONTHLY: - until = date_sec_change (start, rpt->freq * (rpt->count - 1), 0); - break; - case RECUR_YEARLY: - until = date_sec_change (start, rpt->freq * 12 * (rpt->count - 1), 0); - break; - default: - until = 0; - break; - /* NOTREACHED */ - } - return until; -} - -/* - * Read a recurrence rule from an iCalendar RRULE string. - * - * Value Name: RECUR - * - * Purpose: This value type is used to identify properties that contain - * a recurrence rule specification. - * - * Formal Definition: The value type is defined by the following - * notation: - * - * recur = "FREQ"=freq *( - * - * ; either UNTIL or COUNT may appear in a 'recur', - * ; but UNTIL and COUNT MUST NOT occur in the same 'recur' - * - * ( ";" "UNTIL" "=" enddate ) / - * ( ";" "COUNT" "=" 1*DIGIT ) / - * - * ; the rest of these keywords are optional, - * ; but MUST NOT occur more than - * ; once - * - * ( ";" "INTERVAL" "=" 1*DIGIT ) / - * ( ";" "BYSECOND" "=" byseclist ) / - * ( ";" "BYMINUTE" "=" byminlist ) / - * ( ";" "BYHOUR" "=" byhrlist ) / - * ( ";" "BYDAY" "=" bywdaylist ) / - * ( ";" "BYMONTHDAY" "=" bymodaylist ) / - * ( ";" "BYYEARDAY" "=" byyrdaylist ) / - * ( ";" "BYWEEKNO" "=" bywknolist ) / - * ( ";" "BYMONTH" "=" bymolist ) / - * ( ";" "BYSETPOS" "=" bysplist ) / - * ( ";" "WKST" "=" weekday ) / - * ( ";" x-name "=" text ) - * ) -*/ -static ical_rpt_t * -ical_read_rrule (FILE *log, char *rrulestr, unsigned *noskipped, - const int itemline) -{ - const struct string daily = STRING_BUILD ("DAILY"); - const struct string weekly = STRING_BUILD ("WEEKLY"); - const struct string monthly = STRING_BUILD ("MONTHLY"); - const struct string yearly = STRING_BUILD ("YEARLY"); - const struct string count = STRING_BUILD ("COUNT="); - const struct string interv = STRING_BUILD ("INTERVAL="); - unsigned interval; - ical_rpt_t *rpt; - char *p; - - rpt = NULL; - if ((p = strchr (rrulestr, ':')) != NULL) - { - char freqstr[BUFSIZ]; - - p++; - rpt = mem_malloc (sizeof (ical_rpt_t)); - bzero (rpt, sizeof (ical_rpt_t)); - if (sscanf (p, "FREQ=%s", freqstr) != 1) - { - ical_log (log, ICAL_VEVENT, itemline, - _("recurrence frequence not found.")); - (*noskipped)++; - mem_free (rpt); - return NULL; - } - else - { - if (strncmp (freqstr, daily.str, daily.len) == 0) - rpt->type = RECUR_DAILY; - else if (strncmp (freqstr, weekly.str, weekly.len) == 0) - rpt->type = RECUR_WEEKLY; - else if (strncmp (freqstr, monthly.str, monthly.len) == 0) - rpt->type = RECUR_MONTHLY; - else if (strncmp (freqstr, yearly.str, yearly.len) == 0) - rpt->type = RECUR_YEARLY; - else - { - ical_log (log, ICAL_VEVENT, itemline, - _("recurrence frequence not recognized.")); - (*noskipped)++; - mem_free (rpt); - return NULL; - } - } - /* - The UNTIL rule part defines a date-time value which bounds the - recurrence rule in an inclusive manner. If not present, and the - COUNT rule part is also not present, the RRULE is considered to - repeat forever. - - The COUNT rule part defines the number of occurrences at which to - range-bound the recurrence. The "DTSTART" property value, if - specified, counts as the first occurrence. - */ - if ((p = strstr (rrulestr, "UNTIL")) != NULL) - { - char *untilstr; - - untilstr = strchr (p, '='); - rpt->until = ical_datetime2long (++untilstr, NULL); - } - else - { - unsigned cnt; - char *countstr; - - if ((countstr = strstr (rrulestr, count.str)) != NULL) - { - countstr += count.len; - if (sscanf (countstr, "%u", &cnt) != 1) - { - rpt->until = 0; - /* endless repetition */ - } - else - { - rpt->count = cnt; - } - } - else - rpt->until = 0; - } - - if ((p = strstr (rrulestr, interv.str)) != NULL) - { - p += interv.len; - if (sscanf (p, "%u", &interval) != 1) - { - rpt->freq = 1; - /* default frequence if none specified */ - } - else - { - rpt->freq = interval; - } - } - else - { - rpt->freq = 1; - } - } - else - { - ical_log (log, ICAL_VEVENT, itemline, _("recurrence rule malformed.")); - (*noskipped)++; - } - return rpt; -} + custom_apply_attr(win[STA].p, ATTR_HIGHEST); + mvwprintw(win[STA].p, 0, 2, "Q"); + mvwprintw(win[STA].p, 1, 2, "I"); + mvwprintw(win[STA].p, 0, 2 + spc, "P"); + custom_remove_attr(win[STA].p, ATTR_HIGHEST); -static void -ical_add_exc (llist_t *exc_head, long date) -{ - if (date != 0) - { - struct excp *exc = mem_malloc (sizeof (struct excp)); - exc->st = date; + mvwprintw(win[STA].p, 0, 2 + smlspc, _("Exit")); + mvwprintw(win[STA].p, 1, 2 + smlspc, _("Ical")); + mvwprintw(win[STA].p, 0, 2 + spc + smlspc, _("Pcal")); - LLIST_ADD (exc_head, exc); - } + wnoutrefresh(win[STA].p); + wmove(win[STA].p, 0, 0); + wins_doupdate(); } -/* - * This property defines the list of date/time exceptions for a - * recurring calendar component. - */ -void -ical_read_exdate (llist_t *exc, FILE *log, char *exstr, unsigned *noskipped, - const int itemline) -{ - char *p, *q; - long date; - - LLIST_INIT (exc); - if ((p = strchr (exstr, ':')) != NULL) - { - p++; - while ((q = strchr (p, ',')) != NULL) - { - char buf[BUFSIZ]; - const int buflen = q - p; - - (void)strncpy (buf, p, buflen); - buf[buflen] = '\0'; - date = ical_datetime2long (buf, NULL); - ical_add_exc (exc, date); - p = ++q; - } - date = ical_datetime2long (p, NULL); - ical_add_exc (exc, date); - } - else - { - ical_log (log, ICAL_VEVENT, itemline, - _("recurrence exception dates malformed.")); - (*noskipped)++; - } -} - -/* Return an allocated string containing the name of the newly created note. */ -static char * -ical_read_note (char *line, unsigned *noskipped, ical_vevent_e item_type, - const int itemline, FILE *log) -{ - char *p, *notestr, *notename, fullnotename[BUFSIZ]; - FILE *fdo; - - if ((p = strchr (line, ':')) != NULL) - { - notename = new_tempfile (path_notes, NOTESIZ); - EXIT_IF (notename == NULL, - _("Warning: could not create new note file to store " - "description. Aborting...\n")); - (void)snprintf (fullnotename, BUFSIZ, "%s%s", path_notes, notename); - fdo = fopen (fullnotename, "w"); - EXIT_IF (fdo == NULL, _("Warning: could not open %s, Aborting..."), - fullnotename); - p++; - notestr = ical_unformat_line (p); - if (notestr == NULL) - { - ical_log (log, item_type, itemline, - _("could not get entire item description.")); - file_close (fdo, __FILE_POS__); - erase_note (¬ename, ERASE_FORCE); - (*noskipped)++; - return NULL; - } - else if (strlen (notestr) == 0) - { - file_close (fdo, __FILE_POS__); - erase_note (¬ename, ERASE_FORCE); - mem_free (notestr); - return NULL; - } - else - { - (void)fprintf (fdo, "%s", notestr); - file_close (fdo, __FILE_POS__); - mem_free (notestr); - return notename; - } - } - else - { - ical_log (log, item_type, itemline, _("description malformed.")); - (*noskipped)++; - return NULL; - } -} - -/* Returns an allocated string containing the ical item summary. */ -static char * -ical_read_summary (char *line) -{ - char *p, *summary; - - if ((p = strchr (line, ':')) != NULL) - { - p++; - summary = ical_unformat_line (p); - return summary; - } - else - return NULL; -} - -static void -ical_read_event (FILE *fdi, FILE *log, unsigned *noevents, unsigned *noapoints, - unsigned *noskipped, char *buf, char *lstore, - unsigned *lineno) -{ - const int ITEMLINE = *lineno; - const struct string endevent = STRING_BUILD ("END:VEVENT"); - const struct string summary = STRING_BUILD ("SUMMARY"); - const struct string dtstart = STRING_BUILD ("DTSTART"); - const struct string dtend = STRING_BUILD ("DTEND"); - const struct string duration = STRING_BUILD ("DURATION"); - const struct string rrule = STRING_BUILD ("RRULE"); - const struct string exdate = STRING_BUILD ("EXDATE"); - const struct string alarm = STRING_BUILD ("BEGIN:VALARM"); - const struct string endalarm = STRING_BUILD ("END:VALARM"); - const struct string desc = STRING_BUILD ("DESCRIPTION"); - ical_vevent_e vevent_type; - char *p, buf_upper[BUFSIZ]; - struct { - llist_t exc; - ical_rpt_t *rpt; - char *mesg, *note; - long start, end, dur; - int has_alarm; - } vevent; - int skip_alarm; - - vevent_type = UNDEFINED; - bzero (&vevent, sizeof vevent); - skip_alarm = 0; - while (ical_readline (fdi, buf, lstore, lineno)) - { - strncpy (buf_upper, buf, BUFSIZ); - buf_upper[BUFSIZ - 1] = '\0'; - str_toupper (buf_upper); - - if (skip_alarm) - { - /* Need to skip VALARM properties because some keywords could - interfere, such as DURATION, SUMMARY,.. */ - if (strncmp (buf_upper, endalarm.str, endalarm.len) == 0) - skip_alarm = 0; - continue; - } - if (strncmp (buf_upper, endevent.str, endevent.len) == 0) - { - if (vevent.mesg) - { - if (vevent.rpt && vevent.rpt->count) - vevent.rpt->until = ical_compute_rpt_until (vevent.start, - vevent.rpt); - - switch (vevent_type) - { - case APPOINTMENT: - if (vevent.start == 0) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("appointment has no start time.")); - goto cleanup; - } - if (vevent.dur == 0) - { - if (vevent.end == 0) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("could not compute duration " - "(no end time).")); - goto cleanup; - } - else if (vevent.start == vevent.end) - { - vevent_type = EVENT; - vevent.end = 0L; - ical_store_event (vevent.mesg, vevent.note, - vevent.start, vevent.end, - vevent.rpt, &vevent.exc); - (*noevents)++; - return; - } - else - { - vevent.dur = vevent.end - vevent.start; - if (vevent.dur < 0) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("item has a negative duration.")); - goto cleanup; - } - } - } - ical_store_apoint (vevent.mesg, vevent.note, vevent.start, - vevent.dur, vevent.rpt, &vevent.exc, - vevent.has_alarm); - (*noapoints)++; - break; - case EVENT: - if (vevent.start == 0) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("event date is not defined.")); - goto cleanup; - } - ical_store_event (vevent.mesg, vevent.note, vevent.start, - vevent.end, vevent.rpt, &vevent.exc); - (*noevents)++; - break; - case UNDEFINED: - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("item could not be identified.")); - goto cleanup; - break; - } - } - else - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("could not retrieve item summary.")); - goto cleanup; - } - return; - } - else - { - if (strncmp (buf_upper, dtstart.str, dtstart.len) == 0) - { - if ((p = strchr (buf, ':')) != NULL) - vevent.start = ical_datetime2long (++p, &vevent_type); - if (!vevent.start) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("could not retrieve event start time.")); - goto cleanup; - } - } - else if (strncmp (buf_upper, dtend.str, dtend.len) == 0) - { - if ((p = strchr (buf, ':')) != NULL) - vevent.end = ical_datetime2long (++p, &vevent_type); - if (!vevent.end) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("could not retrieve event end time.")); - goto cleanup; - } - } - else if (strncmp (buf_upper, duration.str, duration.len) == 0) - { - if ((vevent.dur = ical_dur2long (buf)) <= 0) - { - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("item duration malformed.")); - goto cleanup; - } - } - else if (strncmp (buf_upper, rrule.str, rrule.len) == 0) - { - vevent.rpt = ical_read_rrule (log, buf, noskipped, ITEMLINE); - } - else if (strncmp (buf_upper, exdate.str, exdate.len) == 0) - { - ical_read_exdate (&vevent.exc, log, buf, noskipped, ITEMLINE); - } - else if (strncmp (buf_upper, summary.str, summary.len) == 0) - { - vevent.mesg = ical_read_summary (buf); - } - else if (strncmp (buf_upper, alarm.str, alarm.len) == 0) - { - skip_alarm = 1; - vevent.has_alarm = 1; - } - else if (strncmp (buf_upper, desc.str, desc.len) == 0) - { - vevent.note = ical_read_note (buf, noskipped, ICAL_VEVENT, - ITEMLINE, log); - } - } - } - ical_log (log, ICAL_VEVENT, ITEMLINE, - _("The ical file seems to be malformed. " - "The end of item was not found.")); - -cleanup: - - if (vevent.note) - mem_free (vevent.note); - if (vevent.mesg) - mem_free (vevent.mesg); - if (vevent.rpt) - mem_free (vevent.rpt); - LLIST_FREE (&vevent.exc); - (*noskipped)++; -} - -static void -ical_read_todo (FILE *fdi, FILE *log, unsigned *notodos, unsigned *noskipped, - char *buf, char *lstore, unsigned *lineno) -{ - const struct string endtodo = STRING_BUILD ("END:VTODO"); - const struct string summary = STRING_BUILD ("SUMMARY"); - const struct string alarm = STRING_BUILD ("BEGIN:VALARM"); - const struct string endalarm = STRING_BUILD ("END:VALARM"); - const struct string desc = STRING_BUILD ("DESCRIPTION"); - const int LOWEST = 9; - const int ITEMLINE = *lineno; - char buf_upper[BUFSIZ]; - struct { - char *mesg, *note; - int has_priority, priority; - } vtodo; - int skip_alarm; - - bzero (&vtodo, sizeof vtodo); - skip_alarm = 0; - while (ical_readline (fdi, buf, lstore, lineno)) - { - strncpy (buf_upper, buf, BUFSIZ); - buf_upper[BUFSIZ - 1] = '\0'; - str_toupper (buf_upper); - if (skip_alarm) - { - /* Need to skip VALARM properties because some keywords could - interfere, such as DURATION, SUMMARY,.. */ - if (strncmp (buf_upper, endalarm.str, endalarm.len) == 0) - skip_alarm = 0; - continue; - } - if (strncmp (buf_upper, endtodo.str, endtodo.len) == 0) - { - if (!vtodo.has_priority) - vtodo.priority = LOWEST; - if (vtodo.mesg) - { - ical_store_todo (vtodo.priority, vtodo.mesg, vtodo.note); - (*notodos)++; - } - else - { - ical_log (log, ICAL_VTODO, ITEMLINE, - _("could not retrieve item summary.")); - goto cleanup; - } - return; - } - else - { - int tmpint; - - if (sscanf (buf_upper, "PRIORITY:%d", &tmpint) == 1) - { - if (tmpint <= 9 && tmpint >= 1) - { - vtodo.priority = tmpint; - vtodo.has_priority = 1; - } - else - { - ical_log (log, ICAL_VTODO, ITEMLINE, - _("item priority is not acceptable " - "(must be between 1 and 9).")); - vtodo.priority = LOWEST; - } - } - else if (strncmp (buf_upper, summary.str, summary.len) == 0) - { - vtodo.mesg = ical_read_summary (buf); - } - else if (strncmp (buf_upper, alarm.str, alarm.len) == 0) - { - skip_alarm = 1; - } - else if (strncmp (buf_upper, desc.str, desc.len) == 0) - { - vtodo.note = ical_read_note (buf, noskipped, ICAL_VTODO, - ITEMLINE, log); - } - } - } - ical_log (log, ICAL_VTODO, ITEMLINE, - _("The ical file seems to be malformed. " - "The end of item was not found.")); - -cleanup: - - if (vtodo.note) - mem_free (vtodo.note); - if (vtodo.mesg) - mem_free (vtodo.mesg); - (*noskipped)++; -} - -static FILE * -get_import_stream (enum export_type type) +static FILE *get_import_stream(enum export_type type) { FILE *stream; char *stream_name; - char *ask_fname = _("Enter the file name to import data from:"); - char *wrong_file = - _("The file cannot be accessed, please enter another file name."); - char *press_enter = _("Press [ENTER] to continue."); + const char *ask_fname = _("Enter the file name to import data from:"); + const char *wrong_file = + _("The file cannot be accessed, please enter another file name."); + const char *press_enter = _("Press [ENTER] to continue."); int cancel; stream = NULL; - stream_name = mem_malloc (BUFSIZ); - bzero (stream_name, BUFSIZ); - while (stream == NULL) - { - status_mesg (ask_fname, ""); - cancel = updatestring (win[STA].p, &stream_name, 0, 1); - if (cancel) - { - mem_free (stream_name); - return NULL; - } - stream = fopen (stream_name, "r"); - if (stream == NULL) - { - status_mesg (wrong_file, press_enter); - (void)wgetch (win[STA].p); - } + stream_name = mem_malloc(BUFSIZ); + memset(stream_name, 0, BUFSIZ); + while (stream == NULL) { + status_mesg(ask_fname, ""); + cancel = updatestring(win[STA].p, &stream_name, 0, 1); + if (cancel) { + mem_free(stream_name); + return NULL; } - mem_free (stream_name); + stream = fopen(stream_name, "r"); + if (stream == NULL) { + status_mesg(wrong_file, press_enter); + wgetch(win[STA].p); + } + } + mem_free(stream_name); return stream; } @@ -2715,229 +993,182 @@ get_import_stream (enum export_type type) * A temporary log file is created in /tmp to store the import process report, * and is cleared at the end. */ -void -io_import_data (enum import_type type, struct conf *conf, char *stream_name) +void io_import_data(enum import_type type, const char *stream_name) { - const struct string vevent = STRING_BUILD ("BEGIN:VEVENT"); - const struct string vtodo = STRING_BUILD ("BEGIN:VTODO"); - char *proc_report = _("Import process report: %04d lines read "); - char *lines_stats = - _("%d apps / %d events / %d todos / %d skipped "); - char *lines_stats_interactive = - _("%d apps / %d events / %d todos / %d skipped ([ENTER] to continue)"); - char buf[BUFSIZ], lstore[BUFSIZ]; + const char *proc_report = _("Import process report: %04d lines read "); + char stats_str[4][BUFSIZ]; FILE *stream = NULL; struct io_file *log; - float ical_version; struct { unsigned events, apoints, todos, lines, skipped; } stats; - EXIT_IF (type < 0 || type >= IO_IMPORT_NBTYPES, _("unknown import type")); - switch (ui_mode) - { - case UI_CMDLINE: - stream = fopen (stream_name, "r"); - EXIT_IF (stream == NULL, - _("FATAL ERROR: the input file cannot be accessed, " - "Aborting...")); - break; - case UI_CURSES: - stream = get_import_stream (type); - break; - default: - EXIT (_("FATAL ERROR: wrong import mode")); - /* NOTREACHED */ - } + EXIT_IF(type < 0 || type >= IO_IMPORT_NBTYPES, _("unknown import type")); + switch (ui_mode) { + case UI_CMDLINE: + stream = fopen(stream_name, "r"); + EXIT_IF(stream == NULL, + _("FATAL ERROR: the input file cannot be accessed, " + "Aborting...")); + break; + case UI_CURSES: + stream = get_import_stream(type); + break; + default: + EXIT(_("FATAL ERROR: wrong import mode")); + /* NOTREACHED */ + } if (stream == NULL) return; - bzero (&stats, sizeof stats); - ical_readline_init (stream, buf, lstore, &stats.lines); - ical_version = ical_chk_header (stream, buf, lstore, &stats.lines); - RETURN_IF (ical_version < 0, - _("Warning: ical header malformed or wrong version number. " - "Aborting...")); - - log = io_log_init (); - if (log == NULL) - { - if (stream != stdin) - file_close (stream, __FILE_POS__); - return; - } - ical_log_init (log->fd, ical_version); - - while (ical_readline (stream, buf, lstore, &stats.lines)) - { - stats.lines++; - str_toupper (buf); - if (strncmp (buf, vevent.str, vevent.len) == 0) - { - ical_read_event (stream, log->fd, &stats.events, &stats.apoints, - &stats.skipped, buf, lstore, &stats.lines); - } - else if (strncmp (buf, vtodo.str, vtodo.len) == 0) - { - ical_read_todo (stream, log->fd, &stats.todos, &stats.skipped, - buf, lstore, &stats.lines); - } - } - if (stream != stdin) - file_close (stream, __FILE_POS__); + memset(&stats, 0, sizeof stats); - /* Update the number of todo items. */ - todo_set_nb (todo_nb () + stats.todos); + log = io_log_init(); + if (log == NULL) { + if (stream != stdin) + file_close(stream, __FILE_POS__); + return; + } - if (ui_mode == UI_CURSES && !conf->skip_system_dialogs) - { - char read[BUFSIZ], stat[BUFSIZ]; + if (type == IO_IMPORT_ICAL) + ical_import_data(stream, log->fd, &stats.events, &stats.apoints, + &stats.todos, &stats.lines, &stats.skipped); - (void)snprintf (read, BUFSIZ, proc_report, stats.lines); - (void)snprintf (stat, BUFSIZ, lines_stats_interactive, stats.apoints, - stats.events, stats.todos, stats.skipped); - status_mesg (read, stat); - (void)wgetch (win[STA].p); - } - else if (ui_mode == UI_CMDLINE) - { - printf (proc_report, stats.lines); - printf ("\n"); - printf (lines_stats, stats.apoints, stats.events, stats.todos, - stats.skipped); - printf ("\n"); - } + if (stream != stdin) + file_close(stream, __FILE_POS__); + + snprintf(stats_str[0], BUFSIZ, + ngettext("%d app", "%d apps", stats.apoints), stats.apoints); + snprintf(stats_str[1], BUFSIZ, + ngettext("%d event", "%d events", stats.events), stats.events); + snprintf(stats_str[2], BUFSIZ, + ngettext("%d todo", "%d todos", stats.todos), stats.todos); + snprintf(stats_str[3], BUFSIZ, _("%d skipped"), stats.skipped); + + /* Update the number of todo items. */ + todo_set_nb(todo_nb() + stats.todos); + + if (ui_mode == UI_CURSES && conf.system_dialogs) { + char read[BUFSIZ], stat[BUFSIZ]; + + snprintf(read, BUFSIZ, proc_report, stats.lines); + snprintf(stat, BUFSIZ, "%s / %s / %s / %s (%s)", stats_str[0], + stats_str[1], stats_str[2], stats_str[3], + _("Press [ENTER] to continue")); + status_mesg(read, stat); + wgetch(win[STA].p); + } else if (ui_mode == UI_CMDLINE) { + printf(proc_report, stats.lines); + printf("\n%s / %s / %s / %s\n", stats_str[0], stats_str[1], + stats_str[2], stats_str[3]); + } /* User has the choice to look at the log file if some items could not be imported. - */ - file_close (log->fd, __FILE_POS__); - if (stats.skipped > 0) - { - char *view_log = _("Some items could not be imported, see log file ?"); + */ + file_close(log->fd, __FILE_POS__); + if (stats.skipped > 0) { + const char *view_log = + _("Some items could not be imported, see log file ?"); - io_log_display (log, view_log, conf->pager); - } - io_log_free (log); + io_log_display(log, view_log, conf.pager); + } + io_log_free(log); } -struct io_file * -io_log_init (void) +struct io_file *io_log_init(void) { char logprefix[BUFSIZ]; char *logname; struct io_file *log; - snprintf (logprefix, BUFSIZ, "%s/calcurse_log.", get_tempdir ()); - logname = new_tempfile (logprefix, NOTESIZ); - RETVAL_IF (logname == NULL, 0, - _("Warning: could not create temporary log file, Aborting...")); - log = mem_malloc (sizeof (struct io_file)); - RETVAL_IF (log == NULL, 0, - _("Warning: could not open temporary log file, Aborting...")); - (void)snprintf (log->name, sizeof (log->name), "%s%s", logprefix, logname); - mem_free (logname); - log->fd = fopen (log->name, "w"); - if (log->fd == NULL) - { - ERROR_MSG (_("Warning: could not open temporary log file, Aborting...")); - mem_free (log); - return 0; - } + snprintf(logprefix, BUFSIZ, "%s/calcurse_log.", get_tempdir()); + logname = new_tempfile(logprefix, TMPEXTSIZ); + RETVAL_IF(logname == NULL, 0, + _("Warning: could not create temporary log file, Aborting...")); + log = mem_malloc(sizeof(struct io_file)); + RETVAL_IF(log == NULL, 0, + _("Warning: could not open temporary log file, Aborting...")); + snprintf(log->name, sizeof(log->name), "%s%s", logprefix, logname); + mem_free(logname); + log->fd = fopen(log->name, "w"); + if (log->fd == NULL) { + ERROR_MSG(_("Warning: could not open temporary log file, Aborting...")); + mem_free(log); + return 0; + } return log; } -void -io_log_print (struct io_file *log, int line, char *msg) +void io_log_print(struct io_file *log, int line, const char *msg) { if (log && log->fd) - (void)fprintf (log->fd, "line %d: %s\n", line, msg); + fprintf(log->fd, "line %d: %s\n", line, msg); } -void -io_log_display (struct io_file *log, char *msg, char *pager) +void io_log_display(struct io_file *log, const char *msg, const char *pager) { - char *choices = "[y/n] "; int ans; - RETURN_IF (log == NULL, _("No log file to display!")); - if (ui_mode == UI_CMDLINE) - { - printf ("\n%s %s", msg, choices); - ans = fgetc (stdin); - if (ans == 'y') - { - char cmd[BUFSIZ]; - - (void)snprintf (cmd, BUFSIZ, "%s %s", pager, log->name); - (void)system (cmd); - } - } - else - { - status_mesg (msg, choices); - do - { - ans = wgetch (win[STA].p); - if (ans == 'y') - { - wins_launch_external (log->name, pager); - } - } - while (ans != 'y' && ans != 'n'); - wins_erase_status_bar (); + RETURN_IF(log == NULL, _("No log file to display!")); + if (ui_mode == UI_CMDLINE) { + printf("\n%s [y/n] ", msg); + ans = fgetc(stdin); + if (ans == 'y') { + const char *arg[] = { pager, log->name, NULL }; + int pid; + + if ((pid = fork_exec(NULL, NULL, pager, arg))) + child_wait(NULL, NULL, pid); } + } else { + if (status_ask_bool(msg) == 1) + wins_launch_external(log->name, pager); + wins_erase_status_bar(); + } } -void -io_log_free (struct io_file *log) +void io_log_free(struct io_file *log) { if (!log) return; - EXIT_IF (unlink (log->name) != 0, - _("Warning: could not erase temporary log file %s, Aborting..."), - log->name); - mem_free (log); + EXIT_IF(unlink(log->name) != 0, + _("Warning: could not erase temporary log file %s, Aborting..."), + log->name); + mem_free(log); } static pthread_t io_t_psave; /* Thread used to periodically save data. */ -static void * -io_psave_thread (void *arg) +static void *io_psave_thread(void *arg) { - struct conf *config; int delay; - config = (struct conf *)arg; - delay = config->periodic_save; - EXIT_IF (delay < 0, _("Invalid delay")); + delay = conf.periodic_save; + EXIT_IF(delay < 0, _("Invalid delay")); - for (;;) - { - (void)sleep (delay * MININSEC); - io_save_cal (config, IO_SAVE_DISPLAY_MARK); - } + for (;;) { + sleep(delay * MININSEC); + io_save_cal(IO_SAVE_DISPLAY_MARK); + } } /* Launch the thread which handles periodic saves. */ -void -io_start_psave_thread (struct conf *conf) +void io_start_psave_thread(void) { - pthread_create (&io_t_psave, NULL, io_psave_thread, (void *)conf); + pthread_create(&io_t_psave, NULL, io_psave_thread, NULL); } /* Stop periodic data saves. */ -void -io_stop_psave_thread (void) +void io_stop_psave_thread(void) { - if (io_t_psave) - { - pthread_cancel (io_t_psave); - pthread_join (io_t_psave, NULL); - } + if (io_t_psave) { + pthread_cancel(io_t_psave); + pthread_join(io_t_psave, NULL); + } } /* @@ -2951,49 +1182,40 @@ io_stop_psave_thread (void) * Note: When creating the lock file, the interactive mode is not initialized * yet. */ -void -io_set_lock (void) +void io_set_lock(void) { - FILE *lock = fopen (path_cpid, "r"); + FILE *lock = fopen(path_cpid, "r"); int pid; - if (lock != NULL) - { - /* If there is a lock file, check whether the process exists. */ - if (fscanf(lock, "%d", &pid) == 1) - { - fclose(lock); - if (kill(pid, 0) != 0 && errno == ESRCH) - lock = NULL; - } - else - fclose(lock); - } - - if (lock != NULL) - { - (void)fprintf (stderr, - _("\nWARNING: it seems that another calcurse instance is " - "already running.\n" - "If this is not the case, please remove the following " - "lock file: \n\"%s\"\n" - "and restart calcurse.\n"), path_cpid); - exit (EXIT_FAILURE); - } - else - { - if (!io_dump_pid (path_cpid)) - EXIT (_("FATAL ERROR: could not create %s: %s\n"), - path_cpid, strerror (errno)); - } + if (lock != NULL) { + /* If there is a lock file, check whether the process exists. */ + if (fscanf(lock, "%d", &pid) == 1) { + fclose(lock); + if (kill(pid, 0) != 0 && errno == ESRCH) + lock = NULL; + } else + fclose(lock); + } + + if (lock != NULL) { + fprintf(stderr, + _("\nWARNING: it seems that another calcurse instance is " + "already running.\n" + "If this is not the case, please remove the following " + "lock file: \n\"%s\"\n" "and restart calcurse.\n"), path_cpid); + exit(EXIT_FAILURE); + } else { + if (!io_dump_pid(path_cpid)) + EXIT(_("FATAL ERROR: could not create %s: %s\n"), + path_cpid, strerror(errno)); + } } /* * Create a new file and write the process pid inside (used to create a simple * lock for example). Overwrite already existing files. */ -unsigned -io_dump_pid (char *file) +unsigned io_dump_pid(char *file) { pid_t pid; FILE *fp; @@ -3001,10 +1223,9 @@ io_dump_pid (char *file) if (!file) return 0; - pid = getpid (); - if (!(fp = fopen (file, "w")) - || fprintf (fp, "%ld\n", (long)pid) < 0 - || fclose (fp) != 0) + pid = getpid(); + if (!(fp = fopen(file, "w")) + || fprintf(fp, "%ld\n", (long)pid) < 0 || fclose(fp) != 0) return 0; return 1; @@ -3015,8 +1236,7 @@ io_dump_pid (char *file) * io_dump_pid (). * If no file was found, return 0. */ -unsigned -io_get_pid (char *file) +unsigned io_get_pid(char *file) { FILE *fp; unsigned pid; @@ -3024,13 +1244,13 @@ io_get_pid (char *file) if (!file) return 0; - if ((fp = fopen (file, "r")) == NULL) + if ((fp = fopen(file, "r")) == NULL) return 0; - if (fscanf (fp, "%u", &pid) != 1) + if (fscanf(fp, "%u", &pid) != 1) return 0; - (void)fclose (fp); + fclose(fp); return pid; } @@ -3038,24 +1258,48 @@ io_get_pid (char *file) /* * Check whether a file is empty. */ -int -io_file_is_empty (char *file) +int io_file_is_empty(char *file) { FILE *fp; - if (file && (fp = fopen (file, "r"))) - { - if ((fgetc (fp) == '\n' && fgetc (fp) == EOF) || feof (fp)) - { - fclose (fp); - return 1; - } - else - { - fclose (fp); - return 0; - } + if (file && (fp = fopen(file, "r"))) { + if ((fgetc(fp) == '\n' && fgetc(fp) == EOF) || feof(fp)) { + fclose(fp); + return 1; + } else { + fclose(fp); + return 0; } + } return -1; } + +/* + * Copy an existing file to a new location. + */ +int io_file_cp(const char *src, const char *dst) +{ + FILE *fp_src, *fp_dst; + char *buffer[BUFSIZ]; + unsigned int bytes_read; + + if (!(fp_src = fopen(src, "rb"))) + return 0; + if (!(fp_dst = fopen(dst, "wb"))) + return 0; + + while (!feof(fp_src)) { + bytes_read = fread(buffer, 1, BUFSIZ, fp_src); + if (bytes_read > 0) { + if (fwrite(buffer, 1, bytes_read, fp_dst) != bytes_read) + return 0; + } else + return 0; + } + + fclose(fp_dst); + fclose(fp_src); + + return 1; +} @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,20 +39,14 @@ #include "calcurse.h" -#define MAXKEYVAL KEY_MAX /* ncurses defines KEY_MAX as maximum key value */ +#define MAXKEYVAL KEY_MAX /* ncurses defines KEY_MAX as maximum key value */ struct keydef_s { - char *label; - char *binding; + const char *label; + const char *binding; }; -struct key_str_s { - char *str; - struct key_str_s *next; -}; - -static struct key_str_s *keys[NBKEYS]; - +static llist_t keys[NBKEYS]; static enum key actions[MAXKEYVAL]; static struct keydef_s keydef[NBKEYS] = { @@ -81,16 +75,17 @@ static struct keydef_s keydef[NBKEYS] = { {"generic-scroll-up", "C-p"}, {"generic-goto-today", "C-g"}, - {"move-right", "l L"}, - {"move-left", "h H"}, - {"move-down", "j J"}, - {"move-up", "k K"}, + {"move-right", "l L RGT"}, + {"move-left", "h H LFT"}, + {"move-down", "j J DWN"}, + {"move-up", "k K UP"}, {"start-of-week", "0"}, {"end-of-week", "$"}, {"add-item", "a A"}, {"del-item", "d D"}, {"edit-item", "e E"}, {"view-item", "v V"}, + {"pipe-item", "|"}, {"flag-item", "!"}, {"repeat", "r R"}, {"edit-note", "n N"}, @@ -99,92 +94,80 @@ static struct keydef_s keydef[NBKEYS] = { {"lower-priority", "-"}, }; -static void -dump_intro (FILE *fd) +static void dump_intro(FILE * fd) { - char *intro = - _("#\n" - "# Calcurse keys configuration file\n#\n" - "# This file sets the keybindings used by Calcurse.\n" - "# Lines beginning with \"#\" are comments, and ignored by Calcurse.\n" - "# To assign a keybinding to an action, this file must contain a line\n" - "# with the following syntax:\n#\n" - "# ACTION KEY1 KEY2 ... KEYn\n#\n" - "# Where ACTION is what will be performed when KEY1, KEY2, ..., or KEYn\n" - "# will be pressed.\n" - "#\n" - "# To define bindings which use the CONTROL key, prefix the key with " - "'C-'.\n" - "# The escape, space bar and horizontal Tab key can be specified using\n" - "# the 'ESC', 'SPC' and 'TAB' keyword, respectively.\n" - "# Arrow keys can also be specified with the UP, DWN, LFT, RGT keywords.\n" - "# Last, Home and End keys can be assigned using 'KEY_HOME' and 'KEY_END'\n" - "# keywords." - "\n#\n" - "# A description of what each ACTION keyword is used for is available\n" - "# from calcurse online configuration menu.\n"); - - (void)fprintf (fd, "%s\n", intro); + const char *intro = + _("#\n" + "# Calcurse keys configuration file\n#\n" + "# This file sets the keybindings used by Calcurse.\n" + "# Lines beginning with \"#\" are comments, and ignored by Calcurse.\n" + "# To assign a keybinding to an action, this file must contain a line\n" + "# with the following syntax:\n#\n" + "# ACTION KEY1 KEY2 ... KEYn\n#\n" + "# Where ACTION is what will be performed when KEY1, KEY2, ..., or KEYn\n" + "# will be pressed.\n" + "#\n" + "# To define bindings which use the CONTROL key, prefix the key with " + "'C-'.\n" + "# The escape, space bar and horizontal Tab key can be specified using\n" + "# the 'ESC', 'SPC' and 'TAB' keyword, respectively.\n" + "# Arrow keys can also be specified with the UP, DWN, LFT, RGT keywords.\n" + "# Last, Home and End keys can be assigned using 'KEY_HOME' and 'KEY_END'\n" + "# keywords." + "\n#\n" + "# A description of what each ACTION keyword is used for is available\n" + "# from calcurse online configuration menu.\n"); + + fprintf(fd, "%s\n", intro); } -void -keys_init (void) +void keys_init(void) { int i; for (i = 0; i < MAXKEYVAL; i++) actions[i] = KEY_UNDEF; - bzero (keys, NBKEYS); + for (i = 0; i < NBKEYS; i++) + LLIST_INIT(&keys[i]); } -void -keys_free (void) +static void key_free(char *s) { - struct key_str_s *o, **i; - int key; - - for (key = 0; key < NBKEYS; key++) - { - if (keys[key] == NULL) - continue; - - i = &keys[key]; - while (*i) - { - o = *i; - *i = o->next; - mem_free (o->str); - mem_free (o); - } - } + mem_free(s); } -void -keys_dump_defaults (char *file) +void keys_free(void) +{ + int i; + + for (i = 0; i < NBKEYS; i++) { + LLIST_FREE_INNER(&keys[i], key_free); + LLIST_FREE(&keys[i]); + } +} + +void keys_dump_defaults(char *file) { FILE *fd; int i; - fd = fopen (file, "w"); - EXIT_IF (fd == NULL, _("FATAL ERROR: could not create default keys file.")); + fd = fopen(file, "w"); + EXIT_IF(fd == NULL, _("FATAL ERROR: could not create default keys file.")); - dump_intro (fd); + dump_intro(fd); for (i = 0; i < NBKEYS; i++) - (void)fprintf (fd, "%s %s\n", keydef[i].label, keydef[i].binding); - file_close (fd, __FILE_POS__); + fprintf(fd, "%s %s\n", keydef[i].label, keydef[i].binding); + file_close(fd, __FILE_POS__); } -char * -keys_get_label (enum key key) +const char *keys_get_label(enum key key) { - EXIT_IF (key < 0 || key > NBKEYS, - _("FATAL ERROR: key value out of bounds")); + EXIT_IF(key < 0 || key > NBKEYS, _("FATAL ERROR: key value out of bounds")); return keydef[key].label; } -enum key -keys_get_action (int pressed) +enum key keys_get_action(int pressed) { if (pressed < 0 || pressed > MAXKEYVAL) return -1; @@ -192,461 +175,391 @@ keys_get_action (int pressed) return actions[pressed]; } -enum key -keys_getch (WINDOW *win) +enum key keys_getch(WINDOW * win, int *count) { - int ch; - - ch = wgetch (win); - switch (ch) - { - case KEY_RESIZE: - return KEY_RESIZE; - default: - return keys_get_action (ch); + int ch = '0'; + + if (count) { + *count = 0; + do { + *count = *count * 10 + ch - '0'; + ch = wgetch(win); } + while ((ch == '0' && *count > 0) || (ch >= '1' && ch <= '9')); + + if (*count == 0) + *count = 1; + } else + ch = wgetch(win); + + switch (ch) { + case KEY_RESIZE: + return KEY_RESIZE; + default: + return keys_get_action(ch); + } } -static void -add_key_str (enum key action, int key) +static void add_key_str(enum key action, int key) { - struct key_str_s *new, **i; - if (action < 0 || action > NBKEYS) return; - new = mem_malloc (sizeof (struct key_str_s)); - new->str = mem_strdup (keys_int2str (key)); - new->next = NULL; - i = &keys[action]; - for (;;) - { - if (*i == NULL) - { - *i = new; - break; - } - else if ((*i)->next == NULL) - { - (*i)->next = new; - break; - } - i = &(*i)->next; - } + LLIST_ADD(&keys[action], mem_strdup(keys_int2str(key))); } -int -keys_assign_binding (int key, enum key action) +int keys_assign_binding(int key, enum key action) { if (key < 0 || key > MAXKEYVAL || actions[key] != KEY_UNDEF) return 1; - else - { - actions[key] = action; - add_key_str (action, key); - } + else { + actions[key] = action; + add_key_str(action, key); + } return 0; } -static void -del_key_str (enum key action, int key) +static void del_key_str(enum key action, int key) { - struct key_str_s *old, **i; + llist_item_t *i; char oldstr[BUFSIZ]; if (action < 0 || action > NBKEYS) return; - (void)strncpy (oldstr, keys_int2str (key), BUFSIZ); - for (i = &keys[action]; *i; i = &(*i)->next) - { - if (!strcmp ((*i)->str, oldstr)) - { - old = *i; - *i = old->next; - mem_free (old->str); - mem_free (old); - break; - } + strncpy(oldstr, keys_int2str(key), BUFSIZ); + + LLIST_FOREACH(&keys[action], i) { + if (strcmp(LLIST_GET_DATA(i), oldstr) == 0) { + LLIST_REMOVE(&keys[action], i); + return; } + } } -void -keys_remove_binding (int key, enum key action) +void keys_remove_binding(int key, enum key action) { - if (key < 0 || key > MAXKEYVAL) - return; - else - { - actions[key] = KEY_UNDEF; - del_key_str (action, key); - } + if (key >= 0 && key <= MAXKEYVAL) { + actions[key] = KEY_UNDEF; + del_key_str(action, key); + } } -int -keys_str2int (char *key) +int keys_str2int(const char *key) { - const struct string CONTROL_KEY = STRING_BUILD ("C-"); - const struct string TAB_KEY = STRING_BUILD ("TAB"); - const struct string SPACE_KEY = STRING_BUILD ("SPC"); - const struct string ESCAPE_KEY = STRING_BUILD ("ESC"); - const struct string CURSES_KEY_UP = STRING_BUILD ("UP"); - const struct string CURSES_KEY_DOWN = STRING_BUILD ("DWN"); - const struct string CURSES_KEY_LEFT = STRING_BUILD ("LFT"); - const struct string CURSES_KEY_RIGHT = STRING_BUILD ("RGT"); - const struct string CURSES_KEY_HOME = STRING_BUILD ("KEY_HOME"); - const struct string CURSES_KEY_END = STRING_BUILD ("KEY_END"); + const char CONTROL_KEY[] = "C-"; + const char TAB_KEY[] = "TAB"; + const char SPACE_KEY[] = "SPC"; + const char ESCAPE_KEY[] = "ESC"; + const char CURSES_KEY_UP[] = "UP"; + const char CURSES_KEY_DOWN[] = "DWN"; + const char CURSES_KEY_LEFT[] = "LFT"; + const char CURSES_KEY_RIGHT[] = "RGT"; + const char CURSES_KEY_HOME[] = "KEY_HOME"; + const char CURSES_KEY_END[] = "KEY_END"; if (!key) return -1; - if (strlen (key) == 1) + if (strlen(key) == 1) return (int)key[0]; - else - { - if (key[0] == '^') - return CTRL ((int)key[1]); - else if (!strncmp (key, CONTROL_KEY.str, CONTROL_KEY.len)) - return CTRL ((int)key[CONTROL_KEY.len]); - else if (!strncmp (key, TAB_KEY.str, TAB_KEY.len)) - return TAB; - else if (!strncmp (key, ESCAPE_KEY.str, ESCAPE_KEY.len)) - return ESCAPE; - else if (!strncmp (key, SPACE_KEY.str, SPACE_KEY.len)) - return SPACE; - else if (!strncmp (key, CURSES_KEY_UP.str, CURSES_KEY_UP.len)) - return KEY_UP; - else if (!strncmp (key, CURSES_KEY_DOWN.str, CURSES_KEY_DOWN.len)) - return KEY_DOWN; - else if (!strncmp (key, CURSES_KEY_LEFT.str, CURSES_KEY_LEFT.len)) - return KEY_LEFT; - else if (!strncmp (key, CURSES_KEY_RIGHT.str, CURSES_KEY_RIGHT.len)) - return KEY_RIGHT; - else if (!strncmp (key, CURSES_KEY_HOME.str, CURSES_KEY_HOME.len)) - return KEY_HOME; - else if (!strncmp (key, CURSES_KEY_END.str, CURSES_KEY_END.len)) - return KEY_END; - else - return -1; - } + else { + if (key[0] == '^') + return CTRL((int)key[1]); + else if (!strncmp(key, CONTROL_KEY, sizeof(CONTROL_KEY) - 1)) + return CTRL((int)key[sizeof(CONTROL_KEY) - 1]); + else if (!strcmp(key, TAB_KEY)) + return TAB; + else if (!strcmp(key, ESCAPE_KEY)) + return ESCAPE; + else if (!strcmp(key, SPACE_KEY)) + return SPACE; + else if (!strcmp(key, CURSES_KEY_UP)) + return KEY_UP; + else if (!strcmp(key, CURSES_KEY_DOWN)) + return KEY_DOWN; + else if (!strcmp(key, CURSES_KEY_LEFT)) + return KEY_LEFT; + else if (!strcmp(key, CURSES_KEY_RIGHT)) + return KEY_RIGHT; + else if (!strcmp(key, CURSES_KEY_HOME)) + return KEY_HOME; + else if (!strcmp(key, CURSES_KEY_END)) + return KEY_END; + else + return -1; + } } -char * -keys_int2str (int key) +const char *keys_int2str(int key) { - switch (key) - { - case TAB: - return "TAB"; - case SPACE: - return "SPC"; - case ESCAPE: - return "ESC"; - case KEY_UP: - return "UP"; - case KEY_DOWN: - return "DWN"; - case KEY_LEFT: - return "LFT"; - case KEY_RIGHT: - return "RGT"; - case KEY_HOME: - return "KEY_HOME"; - case KEY_END: - return "KEY_END"; - default: - return (char *)keyname (key); - } + switch (key) { + case TAB: + return "TAB"; + case SPACE: + return "SPC"; + case ESCAPE: + return "ESC"; + case KEY_UP: + return "UP"; + case KEY_DOWN: + return "DWN"; + case KEY_LEFT: + return "LFT"; + case KEY_RIGHT: + return "RGT"; + case KEY_HOME: + return "KEY_HOME"; + case KEY_END: + return "KEY_END"; + default: + return (char *)keyname(key); + } } -int -keys_action_count_keys (enum key action) +int keys_action_count_keys(enum key action) { - struct key_str_s *key; - int i; + llist_item_t *i; + int n = 0; - i = 0; - for (key = keys[action]; key; key = key->next) - i++; + LLIST_FOREACH(&keys[action], i) + n++; - return i; + return n; } -char * -keys_action_firstkey (enum key action) +const char *keys_action_firstkey(enum key action) { - return (keys[action] != NULL) ? keys[action]->str : "XXX"; + const char *s = LLIST_GET_DATA(LLIST_FIRST(&keys[action])); + return (s != NULL) ? s : "XXX"; } -char * -keys_action_nkey (enum key action, int keynum) +const char *keys_action_nkey(enum key action, int keynum) { - struct key_str_s *key; - int i; - - i = 0; - for (key = keys[action]; key; key = key->next) - { - if (i == keynum) - return key->str; - i++; - } - return (char *)0; + return LLIST_GET_DATA(LLIST_NTH(&keys[action], keynum)); } -char * -keys_action_allkeys (enum key action) +char *keys_action_allkeys(enum key action) { + llist_item_t *i; static char keystr[BUFSIZ]; - struct key_str_s *i; const char *CHAR_SPACE = " "; - if (keys[action] == NULL) + if (!LLIST_FIRST(&keys[action])) return NULL; + keystr[0] = '\0'; - for (i = keys[action]; i; i = i->next) - { - const int MAXLEN = sizeof (keystr) - 1 - strlen (keystr); - (void)strncat (keystr, i->str, MAXLEN - 1); - (void)strncat (keystr, CHAR_SPACE, 1); - } + LLIST_FOREACH(&keys[action], i) { + const int MAXLEN = sizeof(keystr) - 1 - strlen(keystr); + strncat(keystr, LLIST_GET_DATA(i), MAXLEN - 1); + strncat(keystr, CHAR_SPACE, 1); + } return keystr; } /* Need this to display keys properly inside status bar. */ -static char * -keys_format_label (char *key, int keylen) +static char *keys_format_label(char *key, int keylen) { static char fmtkey[BUFSIZ]; - const int len = strlen (key); - char *dot = "."; + const int len = strlen(key); + const char dot = '.'; int i; if (keylen > BUFSIZ) - return (char *)0; + return NULL; - bzero (fmtkey, sizeof (fmtkey)); + memset(fmtkey, 0, sizeof(fmtkey)); if (len == 0) - (void)snprintf (fmtkey, sizeof (fmtkey), "?"); - else if (len <= keylen) - { - for (i = 0; i < keylen - len; i++) - fmtkey[i] = ' '; - (void)strncat (fmtkey, key, keylen); - } - else - { - for (i = 0; i < keylen - 1; i++) - fmtkey[i] = key[i]; - (void)strncat (fmtkey, dot, strlen (dot)); - } + strncpy(fmtkey, "?", sizeof(fmtkey)); + else if (len <= keylen) { + for (i = 0; i < keylen - len; i++) + fmtkey[i] = ' '; + strncat(fmtkey, key, keylen); + } else { + for (i = 0; i < keylen - 1; i++) + fmtkey[i] = key[i]; + fmtkey[keylen - 1] = dot; + } return fmtkey; } void -keys_display_bindings_bar (WINDOW *win, struct binding **binding, int first_key, - int last_key) +keys_display_bindings_bar(WINDOW * win, struct binding *bindings[], int count, + int page_base, int page_size, struct binding *more) { - int i, j, cmdlen, space_between_cmds; - - /* Total length of a command. */ - cmdlen = KEYS_KEYLEN + 1 + KEYS_LABELEN; - space_between_cmds = floor (col / KEYS_CMDS_PER_LINE - cmdlen); - cmdlen += space_between_cmds; - - j = 0; - wins_erase_status_bar (); - for (i = first_key; i < last_key; i += 2) - { - char key[KEYS_KEYLEN + 1], *fmtkey; - const int KEY_POS = j * cmdlen; - const int LABEL_POS = j * cmdlen + KEYS_KEYLEN + 1; - - (void)strncpy (key, keys_action_firstkey (binding[i]->action), - KEYS_KEYLEN); - fmtkey = keys_format_label (key, KEYS_KEYLEN); - custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, 0, KEY_POS, fmtkey); - if (i + 1 != last_key) - { - (void)strncpy (key, keys_action_firstkey (binding[i + 1]->action), - KEYS_KEYLEN); - key[KEYS_KEYLEN] = 0; - fmtkey = keys_format_label (key, KEYS_KEYLEN); - mvwprintw (win, 1, KEY_POS, fmtkey); - } - custom_remove_attr (win, ATTR_HIGHEST); - mvwprintw (win, 0, LABEL_POS, binding[i]->label); - if (i + 1 != last_key) - mvwprintw (win, 1, LABEL_POS, binding[i + 1]->label); - j++; - } - wnoutrefresh (win); + /* Padding between two key bindings. */ + const int padding = (col * 2) / page_size - (KEYS_KEYLEN + KEYS_LABELEN + 1); + /* Total length of a key binding (including padding). */ + const int cmd_len = KEYS_KEYLEN + KEYS_LABELEN + 1 + padding; + + int i; + + wins_erase_status_bar(); + for (i = 0; i < page_size && page_base + i < count; i++) { + /* Location of key and label. */ + const int key_pos_x = (i / 2) * cmd_len; + const int key_pos_y = i % 2; + const int label_pos_x = key_pos_x + KEYS_KEYLEN + 1; + const int label_pos_y = key_pos_y; + + struct binding *binding; + char key[KEYS_KEYLEN + 1], *fmtkey; + + if (!more || i < page_size - 1 || page_base + i == count - 1) + binding = bindings[page_base + i]; + else + binding = more; + + strncpy(key, keys_action_firstkey(binding->action), KEYS_KEYLEN); + key[KEYS_KEYLEN] = '\0'; + fmtkey = keys_format_label(key, KEYS_KEYLEN); + + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, key_pos_y, key_pos_x, fmtkey); + custom_remove_attr(win, ATTR_HIGHEST); + mvwprintw(win, label_pos_y, label_pos_x, binding->label); + } + wnoutrefresh(win); } /* * Display information about the given key. * (could not add the keys descriptions to keydef variable, because of i18n). */ -void -keys_popup_info (enum key key) +void keys_popup_info(enum key key) { char *info[NBKEYS]; WINDOW *infowin; - info[KEY_GENERIC_CANCEL] = - _("Cancel the ongoing action."); - info[KEY_GENERIC_SELECT] = - _("Select the highlighted item."); + info[KEY_GENERIC_CANCEL] = _("Cancel the ongoing action."); + info[KEY_GENERIC_SELECT] = _("Select the highlighted item."); info[KEY_GENERIC_CREDITS] = - _("Print general information about calcurse's authors, license, etc."); + _("Print general information about calcurse's authors, license, etc."); info[KEY_GENERIC_HELP] = - _("Display hints whenever some help screens are available."); - info[KEY_GENERIC_QUIT] = - _("Exit from the current menu, or quit calcurse."); - info[KEY_GENERIC_SAVE] = - _("Save calcurse data."); + _("Display hints whenever some help screens are available."); + info[KEY_GENERIC_QUIT] = _("Exit from the current menu, or quit calcurse."); + info[KEY_GENERIC_SAVE] = _("Save calcurse data."); + info[KEY_GENERIC_CUT] = _("Help for `generic-cut`."); + info[KEY_GENERIC_PASTE] = _("Help for `generic-paste`."); info[KEY_GENERIC_CHANGE_VIEW] = - _("Select next panel in calcurse main screen."); - info[KEY_GENERIC_IMPORT] = - _("Import data from an external file."); - info[KEY_GENERIC_EXPORT] = - _("Export data to a new file format."); - info[KEY_GENERIC_GOTO] = - _("Select the day to go to."); + _("Select next panel in calcurse main screen."); + info[KEY_GENERIC_IMPORT] = _("Import data from an external file."); + info[KEY_GENERIC_EXPORT] = _("Export data to a new file format."); + info[KEY_GENERIC_GOTO] = _("Select the day to go to."); info[KEY_GENERIC_OTHER_CMD] = - _("Show next possible actions inside status bar."); - info[KEY_GENERIC_CONFIG_MENU] = - _("Enter the configuration menu."); - info[KEY_GENERIC_REDRAW] = - _("Redraw calcurse's screen."); + _("Show next possible actions inside status bar."); + info[KEY_GENERIC_CONFIG_MENU] = _("Enter the configuration menu."); + info[KEY_GENERIC_REDRAW] = _("Redraw calcurse's screen."); info[KEY_GENERIC_ADD_APPT] = - _("Add an appointment, whichever panel is currently selected."); + _("Add an appointment, whichever panel is currently selected."); info[KEY_GENERIC_ADD_TODO] = - _("Add a todo item, whichever panel is currently selected."); + _("Add a todo item, whichever panel is currently selected."); info[KEY_GENERIC_NEXT_DAY] = - _("Move to next day in calendar, whichever panel is currently selected."); + _("Move to next day in calendar, whichever panel is currently selected."); info[KEY_GENERIC_PREV_DAY] = - _("Move to previous day in calendar, whichever panel is currently " - "selected."); + _("Move to previous day in calendar, whichever panel is currently " + "selected."); info[KEY_GENERIC_NEXT_WEEK] = - _("Move to next week in calendar, whichever panel is currently selected."); + _ + ("Move to next week in calendar, whichever panel is currently selected."); info[KEY_GENERIC_PREV_WEEK] = - _("Move to previous week in calendar, whichever panel is currently " - "selected"); + _("Move to previous week in calendar, whichever panel is currently " + "selected"); info[KEY_GENERIC_SCROLL_DOWN] = - _("Scroll window down (e.g. when displaying text inside a popup window)."); + _ + ("Scroll window down (e.g. when displaying text inside a popup window)."); info[KEY_GENERIC_SCROLL_UP] = - _("Scroll window up (e.g. when displaying text inside a popup window)."); - info[KEY_GENERIC_GOTO_TODAY] = - _("Go to today, whichever panel is selected."); - info[KEY_MOVE_RIGHT] = - _("Move to the right."); - info[KEY_MOVE_LEFT] = - _("Move to the left."); - info[KEY_MOVE_DOWN] = - _("Move down."); - info[KEY_MOVE_UP] = - _("Move up."); + _("Scroll window up (e.g. when displaying text inside a popup window)."); + info[KEY_GENERIC_GOTO_TODAY] = _("Go to today, whichever panel is selected."); + info[KEY_MOVE_RIGHT] = _("Move to the right."); + info[KEY_MOVE_LEFT] = _("Move to the left."); + info[KEY_MOVE_DOWN] = _("Move down."); + info[KEY_MOVE_UP] = _("Move up."); info[KEY_START_OF_WEEK] = - _("Select the first day of the current week when inside the calendar " - "panel."); + _("Select the first day of the current week when inside the calendar " + "panel."); info[KEY_END_OF_WEEK] = - _("Select the last day of the current week when inside the calendar " - "panel."); - info[KEY_ADD_ITEM] = - _("Add an item to the currently selected panel."); - info[KEY_DEL_ITEM] = - _("Delete the currently selected item."); - info[KEY_EDIT_ITEM] = - _("Edit the currently seleted item."); + _("Select the last day of the current week when inside the calendar " + "panel."); + info[KEY_ADD_ITEM] = _("Add an item to the currently selected panel."); + info[KEY_DEL_ITEM] = _("Delete the currently selected item."); + info[KEY_EDIT_ITEM] = _("Edit the currently seleted item."); info[KEY_VIEW_ITEM] = - _("Display the currently selected item inside a popup window."); - info[KEY_FLAG_ITEM] = - _("Flag the currently selected item as important."); - info[KEY_REPEAT_ITEM] = - _("Repeat an item"); + _("Display the currently selected item inside a popup window."); + info[KEY_FLAG_ITEM] = _("Flag the currently selected item as important."); + info[KEY_REPEAT_ITEM] = _("Repeat an item"); + info[KEY_PIPE_ITEM] = + _("Pipe the currently selected item to an external program."); info[KEY_EDIT_NOTE] = - _("Attach (or edit if one exists) a note to the currently selected item"); + _("Attach (or edit if one exists) a note to the currently selected item"); info[KEY_VIEW_NOTE] = - _("View the note attached to the currently selected item."); - info[KEY_RAISE_PRIORITY] = - _("Raise a task priority inside the todo panel."); - info[KEY_LOWER_PRIORITY] = - _("Lower a task priority inside the todo panel."); + _("View the note attached to the currently selected item."); + info[KEY_RAISE_PRIORITY] = _("Raise a task priority inside the todo panel."); + info[KEY_LOWER_PRIORITY] = _("Lower a task priority inside the todo panel."); if (key < 0 || key > NBKEYS) return; #define WINROW 10 #define WINCOL (col - 4) - infowin = popup (WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2, - keydef[key].label, info[key], 1); - (void)keys_getch (infowin); - delwin (infowin); + infowin = popup(WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2, + keydef[key].label, info[key], 1); + keys_getch(infowin, NULL); + delwin(infowin); #undef WINROW #undef WINCOL } -void -keys_save_bindings (FILE *fd) +void keys_save_bindings(FILE * fd) { int i; - EXIT_IF (fd == NULL, _("FATAL ERROR: null file pointer.")); - dump_intro (fd); + EXIT_IF(fd == NULL, _("FATAL ERROR: null file pointer.")); + dump_intro(fd); for (i = 0; i < NBKEYS; i++) - (void)fprintf (fd, "%s %s\n", keydef[i].label, keys_action_allkeys (i)); + fprintf(fd, "%s %s\n", keydef[i].label, keys_action_allkeys(i)); } -int -keys_check_missing_bindings (void) +int keys_check_missing_bindings(void) { int i; - for (i = 0; i < NBKEYS; i++) - { - if (keys[i] == NULL) - return 1; - } + for (i = 0; i < NBKEYS; i++) { + if (!LLIST_FIRST(&keys[i])) + return 1; + } return 0; } -void -keys_fill_missing (void) +void keys_fill_missing(void) { int i; - for (i = 0; i < NBKEYS; i++) - { - if (keys[i] == NULL) - { - 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) - WARN_MSG (_("When adding default key for \"%s\", " - "\"%s\" was already assigned!"), - keydef[i].label, key_ch); - p += strlen (key_ch) + 1; - } - else - break; - } - } + for (i = 0; i < NBKEYS; i++) { + if (!LLIST_FIRST(&keys[i])) { + char *p, tmpbuf[BUFSIZ]; + + 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) + WARN_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/llist.c b/src/llist.c index eeded6b..847b795 100644 --- a/src/llist.c +++ b/src/llist.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,52 +39,47 @@ /* * Initialize a list. */ -void -llist_init (llist_t *l) +void llist_init(llist_t * l) { l->head = NULL; + l->tail = NULL; } /* * Free a list, but not the contained data. */ -void -llist_free (llist_t *l) +void llist_free(llist_t * l) { llist_item_t *i, *t; - for (i = l->head; i; i = t) - { - t = i->next; - mem_free (i); - } + for (i = l->head; i; i = t) { + t = i->next; + mem_free(i); + } l->head = NULL; + l->tail = NULL; } /* * Free the data contained in a list. */ -void -llist_free_inner (llist_t *l, llist_fn_free_t fn_free) +void llist_free_inner(llist_t * l, llist_fn_free_t fn_free) { llist_item_t *i; - for (i = l->head; i; i = i->next) - { - if (i->data) - { - fn_free(i->data); - i->data = NULL; - } + for (i = l->head; i; i = i->next) { + if (i->data) { + fn_free(i->data); + i->data = NULL; } + } } /* * Get the first item of a list. */ -llist_item_t * -llist_first (llist_t *l) +llist_item_t *llist_first(llist_t * l) { return l->head; } @@ -92,12 +87,14 @@ llist_first (llist_t *l) /* * Get the nth item of a list. */ -llist_item_t * -llist_nth (llist_t *l, int n) +llist_item_t *llist_nth(llist_t * l, int n) { llist_item_t *i; - for (i = l->head; i && n > 0; n--) + if (n < 0) + return NULL; + + for (i = l->head; i && n != 0; n--) i = i->next; return i; @@ -106,17 +103,28 @@ llist_nth (llist_t *l, int n) /* * Get the successor of a list item. */ -llist_item_t * -llist_next (llist_item_t *i) +llist_item_t *llist_next(llist_item_t * i) { return i ? i->next : NULL; } /* + * Return the successor of a list item if it is matched by some filter + * callback. Return NULL otherwise. + */ +llist_item_t *llist_next_filter(llist_item_t * i, long data, + llist_fn_match_t fn_match) +{ + if (i && i->next && fn_match(i->next->data, data)) + return i->next; + else + return NULL; +} + +/* * Get the actual data of an item. */ -void * -llist_get_data (llist_item_t *i) +void *llist_get_data(llist_item_t * i) { return i ? i->data : NULL; } @@ -124,97 +132,88 @@ llist_get_data (llist_item_t *i) /* * Add an item at the end of a list. */ -void -llist_add (llist_t *l, void *data) +void llist_add(llist_t * l, void *data) { - llist_item_t *o = mem_malloc (sizeof (llist_item_t)); - llist_item_t *i; + llist_item_t *o = mem_malloc(sizeof(llist_item_t)); - if (o) - { - o->data = data; - o->next = NULL; - - if (!l->head) - l->head = o; - else - { - for (i = l->head; i->next; i = i->next) - ; - i->next = o; - } + if (o) { + o->data = data; + o->next = NULL; + + if (!l->head) + l->head = l->tail = o; + else { + l->tail->next = o; + l->tail = o; } + } } /* * Add an item to a sorted list. */ -void -llist_add_sorted (llist_t *l, void *data, llist_fn_cmp_t fn_cmp) +void llist_add_sorted(llist_t * l, void *data, llist_fn_cmp_t fn_cmp) { - llist_item_t *o = mem_malloc (sizeof (llist_item_t)); + llist_item_t *o = mem_malloc(sizeof(llist_item_t)); llist_item_t *i; - if (o) - { - o->data = data; - o->next = NULL; - - if (!l->head) - l->head = o; - else if (fn_cmp(o->data, l->head->data) < 0) - { - o->next = l->head; - l->head = o; - } - else - { - i = l->head; - while (i->next && fn_cmp(o->data, i->next->data) >= 0) - i = i->next; - o->next = i->next; - i->next = o; - } + if (o) { + o->data = data; + o->next = NULL; + + if (!l->head) + l->head = l->tail = o; + else if (fn_cmp(o->data, l->tail->data) >= 0) { + l->tail->next = o; + l->tail = o; + } else if (fn_cmp(o->data, l->head->data) < 0) { + o->next = l->head; + l->head = o; + } else { + i = l->head; + while (i->next && fn_cmp(o->data, i->next->data) >= 0) + i = i->next; + o->next = i->next; + i->next = o; } + } } /* * Remove an item from a list. */ -void -llist_remove (llist_t *l, llist_item_t *i) +void llist_remove(llist_t * l, llist_item_t * i) { llist_item_t *j = NULL; if (l->head && i == l->head) l->head = i->next; - else - { - for (j = l->head; j && j->next != i; j = j->next) - ; - } - - if (i) - { - if (j) - j->next = i->next; - mem_free (i); - } + else { + for (j = l->head; j && j->next != i; j = j->next) ; + } + + if (i) { + if (j) + j->next = i->next; + if (i == l->tail) + l->tail = j; + + mem_free(i); + } } /* * Find the first item matched by some filter callback. */ -llist_item_t * -llist_find_first (llist_t *l, long data, llist_fn_match_t fn_match) +llist_item_t *llist_find_first(llist_t * l, long data, + llist_fn_match_t fn_match) { llist_item_t *i; - for (i = l->head; i; i = i->next) - { - if (fn_match (i->data, data)) - return i; - } + for (i = l->head; i; i = i->next) { + if (fn_match(i->data, data)) + return i; + } return NULL; } @@ -222,18 +221,16 @@ llist_find_first (llist_t *l, long data, llist_fn_match_t fn_match) /* * Find the next item matched by some filter callback. */ -llist_item_t * -llist_find_next (llist_item_t *i, long data, llist_fn_match_t fn_match) +llist_item_t *llist_find_next(llist_item_t * i, long data, + llist_fn_match_t fn_match) { - if (i) - { - i = i->next; - for (; i; i = i->next) - { - if (fn_match (i->data, data)) - return i; - } + if (i) { + i = i->next; + for (; i; i = i->next) { + if (fn_match(i->data, data)) + return i; } + } return NULL; } @@ -241,16 +238,18 @@ llist_find_next (llist_item_t *i, long data, llist_fn_match_t fn_match) /* * Find the nth item matched by some filter callback. */ -llist_item_t * -llist_find_nth (llist_t *l, int n, long data, llist_fn_match_t fn_match) +llist_item_t *llist_find_nth(llist_t * l, int n, long data, + llist_fn_match_t fn_match) { llist_item_t *i; - for (i = l->head; i; i = i->next) - { - if (fn_match (i->data, data) && (n-- == 0)) - return i; - } + if (n < 0) + return NULL; + + for (i = l->head; i; i = i->next) { + if (fn_match(i->data, data) && (n-- == 0)) + return i; + } return NULL; } diff --git a/src/llist.h b/src/llist.h index d7e4249..c795f37 100644 --- a/src/llist.h +++ b/src/llist.h @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,12 +38,13 @@ typedef struct llist_item llist_item_t; struct llist_item { struct llist_item *next; - void *data; + void *data; }; typedef struct llist llist_t; struct llist { struct llist_item *head; + struct llist_item *tail; }; typedef int (*llist_fn_cmp_t) (void *, void *); @@ -51,9 +52,9 @@ typedef int (*llist_fn_match_t) (void *, long); typedef void (*llist_fn_free_t) (void *); /* Initialization and deallocation. */ -void llist_init (llist_t *); -void llist_free (llist_t *); -void llist_free_inner (llist_t *, llist_fn_free_t); +void llist_init(llist_t *); +void llist_free(llist_t *); +void llist_free_inner(llist_t *, llist_fn_free_t); #define LLIST_INIT(l) llist_init(l) #define LLIST_FREE(l) llist_free(l) @@ -61,16 +62,19 @@ void llist_free_inner (llist_t *, llist_fn_free_t); llist_free_inner(l, (llist_fn_free_t)fn_free) /* Retrieving list items. */ -llist_item_t *llist_first (llist_t *); -llist_item_t *llist_nth (llist_t *, int); -llist_item_t *llist_next (llist_item_t *); -llist_item_t *llist_find_first (llist_t *, long, llist_fn_match_t); -llist_item_t *llist_find_next (llist_item_t *, long, llist_fn_match_t); -llist_item_t *llist_find_nth (llist_t *, int, long, llist_fn_match_t); +llist_item_t *llist_first(llist_t *); +llist_item_t *llist_nth(llist_t *, int); +llist_item_t *llist_next(llist_item_t *); +llist_item_t *llist_next_filter(llist_item_t *, long, llist_fn_match_t); +llist_item_t *llist_find_first(llist_t *, long, llist_fn_match_t); +llist_item_t *llist_find_next(llist_item_t *, long, llist_fn_match_t); +llist_item_t *llist_find_nth(llist_t *, int, long, llist_fn_match_t); #define LLIST_FIRST(l) llist_first(l) #define LLIST_NTH(l, n) llist_nth(l, n) #define LLIST_NEXT(i) llist_next(i) +#define LLIST_NEXT_FILTER(i, data, fn_match) \ + llist_next_filter(i, data, (llist_fn_match_t)fn_match) #define LLIST_FIND_FIRST(l, data, fn_match) \ llist_find_first(l, data, (llist_fn_match_t)fn_match) #define LLIST_FIND_NEXT(i, data, fn_match) \ @@ -82,16 +86,19 @@ llist_item_t *llist_find_nth (llist_t *, int, long, llist_fn_match_t); #define LLIST_FIND_FOREACH(l, data, fn_match, i) \ for (i = LLIST_FIND_FIRST (l, data, fn_match); i; \ i = LLIST_FIND_NEXT (i, data, fn_match)) +#define LLIST_FIND_FOREACH_CONT(l, data, fn_match, i) \ + for (i = LLIST_FIND_FIRST (l, data, fn_match); i; \ + i = LLIST_NEXT_FILTER (i, data, fn_match)) /* Accessing list item data. */ -void *llist_get_data (llist_item_t *); +void *llist_get_data(llist_item_t *); #define LLIST_GET_DATA(i) llist_get_data(i) /* List manipulation. */ -void llist_add (llist_t *, void *); -void llist_add_sorted (llist_t *, void *, llist_fn_cmp_t); -void llist_remove (llist_t *, llist_item_t *); +void llist_add(llist_t *, void *); +void llist_add_sorted(llist_t *, void *, llist_fn_cmp_t); +void llist_remove(llist_t *, llist_item_t *); #define LLIST_ADD(l, data) llist_add(l, data) #define LLIST_ADD_SORTED(l, data, fn_cmp) \ diff --git a/src/llist_ts.h b/src/llist_ts.h index 0f90024..b452377 100644 --- a/src/llist_ts.h +++ b/src/llist_ts.h @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,8 +37,9 @@ /* Thread-safe linked lists. */ typedef struct llist_ts llist_ts_t; struct llist_ts { - llist_item_t *head; - pthread_mutex_t mutex; + llist_item_t *head; + llist_item_t *tail; + pthread_mutex_t mutex; }; /* Initialization and deallocation. */ @@ -63,6 +64,8 @@ struct llist_ts { #define LLIST_TS_FIRST(l_ts) llist_first ((llist_t *)l_ts) #define LLIST_TS_NTH(l_ts, n) llist_nth ((llist_t *)l_ts, n) #define LLIST_TS_NEXT(i) llist_next (i) +#define LLIST_TS_NEXT_FILTER(i, data, fn_match) \ + llist_next_filter (i, data, (llist_fn_match_t)fn_match) #define LLIST_TS_FIND_FIRST(l_ts, data, fn_match) \ llist_find_first ((llist_t *)l_ts, data, (llist_fn_match_t)fn_match) #define LLIST_TS_FIND_NEXT(i, data, fn_match) \ @@ -75,6 +78,9 @@ struct llist_ts { #define LLIST_TS_FIND_FOREACH(l_ts, data, fn_match, i) \ for (i = LLIST_TS_FIND_FIRST (l_ts, data, fn_match); i; \ i = LLIST_TS_FIND_NEXT (i, data, fn_match)) +#define LLIST_TS_FIND_FOREACH_CONT(l_ts, data, fn_match, i) \ + for (i = LLIST_TS_FIND_FIRST (l_ts, data, fn_match); i; \ + i = LLIST_TS_NEXT_FILTER (i, data, fn_match)) /* Accessing list item data. */ #define LLIST_TS_GET_DATA(i) llist_get_data (i) @@ -84,4 +90,3 @@ struct llist_ts { #define LLIST_TS_REMOVE(l_ts, i) llist_remove ((llist_t *)l_ts, i) #define LLIST_TS_ADD_SORTED(l_ts, data, fn_cmp) \ llist_add_sorted ((llist_t *)l_ts, data, (llist_fn_cmp_t)fn_cmp) - @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@ #include "calcurse.h" +#ifdef CALCURSE_MEMORY_DEBUG + enum { BLK_STATE, BLK_SIZE, @@ -67,252 +69,233 @@ struct mem_stats { static struct mem_stats mstats; +#endif /* CALCURSE_MEMORY_DEBUG */ -static unsigned -stats_add_blk (size_t size, const char *pos) -{ - struct mem_blk *o, **i; - - o = malloc (sizeof (*o)); - EXIT_IF (o == NULL, _("could not allocate memory to store block info")); - - mstats.ncall++; - - o->pos = pos; - o->size = (unsigned)size; - o->next = 0; - - for (i = &mstats.blk; *i; i = &(*i)->next) - ; - o->id = mstats.ncall; - *i = o; - - return o->id; -} - -static void -stats_del_blk (unsigned id) -{ - struct mem_blk *o, **i; - - i = &mstats.blk; - for (o = mstats.blk; o; o = o->next) - { - if (o->id == id) - { - *i = o->next; - free (o); - return; - } - i = &o->next; - } - - EXIT (_("Block not found")); - /* NOTREACHED */ -} - -void * -xmalloc (size_t size) +void *xmalloc(size_t size) { void *p; - EXIT_IF (size == 0, _("xmalloc: zero size")); - p = malloc (size); - EXIT_IF (p == NULL, _("xmalloc: out of memory")); + EXIT_IF(size == 0, _("xmalloc: zero size")); + p = malloc(size); + EXIT_IF(p == NULL, _("xmalloc: out of memory")); return p; } -void * -xcalloc (size_t nmemb, size_t size) +void *xcalloc(size_t nmemb, size_t size) { void *p; - EXIT_IF (nmemb == 0 || size == 0, _("xcalloc: zero size")); - EXIT_IF (SIZE_MAX / nmemb < size, _("xcalloc: overflow")); - p = calloc (nmemb, size); - EXIT_IF (p == NULL, _("xcalloc: out of memory")); + EXIT_IF(nmemb == 0 || size == 0, _("xcalloc: zero size")); + EXIT_IF(SIZE_MAX / nmemb < size, _("xcalloc: overflow")); + p = calloc(nmemb, size); + EXIT_IF(p == NULL, _("xcalloc: out of memory")); return p; } -void * -xrealloc (void *ptr, size_t nmemb, size_t size) +void *xrealloc(void *ptr, size_t nmemb, size_t size) { void *new_ptr; size_t new_size; new_size = nmemb * size; - EXIT_IF (new_size == 0, _("xrealloc: zero size")); - EXIT_IF (SIZE_MAX / nmemb < size, _("xrealloc: overflow")); - new_ptr = realloc (ptr, new_size); - EXIT_IF (new_ptr == NULL, _("xrealloc: out of memory")); + EXIT_IF(new_size == 0, _("xrealloc: zero size")); + EXIT_IF(SIZE_MAX / nmemb < size, _("xrealloc: overflow")); + new_ptr = realloc(ptr, new_size); + EXIT_IF(new_ptr == NULL, _("xrealloc: out of memory")); return new_ptr; } -char * -xstrdup (const char *str) +char *xstrdup(const char *str) { size_t len; char *cp; - len = strlen (str) + 1; - cp = xmalloc (len); + len = strlen(str) + 1; + cp = xmalloc(len); + + return strncpy(cp, str, len); +} + +void xfree(void *p) +{ + EXIT_IF(p == NULL, _("xfree: null pointer")); + free(p); +} + +#ifdef CALCURSE_MEMORY_DEBUG + +static unsigned stats_add_blk(size_t size, const char *pos) +{ + struct mem_blk *o, **i; + + o = malloc(sizeof(*o)); + EXIT_IF(o == NULL, _("could not allocate memory to store block info")); + + mstats.ncall++; + + o->pos = pos; + o->size = (unsigned)size; + o->next = 0; + + for (i = &mstats.blk; *i; i = &(*i)->next) ; + o->id = mstats.ncall; + *i = o; - return strncpy (cp, str, len); + return o->id; } -void -xfree (void *p) +static void stats_del_blk(unsigned id) { - EXIT_IF (p == NULL, _("xfree: null pointer")); - free (p); + struct mem_blk *o, **i; + + i = &mstats.blk; + for (o = mstats.blk; o; o = o->next) { + if (o->id == id) { + *i = o->next; + free(o); + return; + } + i = &o->next; + } + + EXIT(_("Block not found")); + /* NOTREACHED */ } -void * -dbg_malloc (size_t size, const char *pos) +void *dbg_malloc(size_t size, const char *pos) { unsigned *buf; - if (size == 0) - return (void *)0; + if (size == 0) + return NULL; - size = EXTRA_SPACE + (size + sizeof (unsigned) - 1) / sizeof (unsigned); - buf = xmalloc (size * sizeof (unsigned)); + size = EXTRA_SPACE + (size + sizeof(unsigned) - 1) / sizeof(unsigned); + buf = xmalloc(size * sizeof(unsigned)); - buf[BLK_STATE] = MAGIC_ALLOC; /* state of the block */ - buf[BLK_SIZE] = size; /* size of the block */ - buf[BLK_ID] = stats_add_blk (size, pos); /* identify a block by its id */ - buf[size - 1] = buf[BLK_ID]; /* mark at end of block */ + buf[BLK_STATE] = MAGIC_ALLOC; /* state of the block */ + buf[BLK_SIZE] = size; /* size of the block */ + buf[BLK_ID] = stats_add_blk(size, pos); /* identify a block by its id */ + buf[size - 1] = buf[BLK_ID]; /* mark at end of block */ mstats.nalloc += size; return (void *)(buf + EXTRA_SPACE_START); } -void * -dbg_calloc (size_t nmemb, size_t size, const char *pos) +void *dbg_calloc(size_t nmemb, size_t size, const char *pos) { void *buf; if (!nmemb || !size) - return (void *)0; + return NULL; - EXIT_IF (nmemb > SIZE_MAX / size, _("overflow at %s"), pos); + EXIT_IF(nmemb > SIZE_MAX / size, _("overflow at %s"), pos); size *= nmemb; - if ((buf = dbg_malloc (size, pos)) == NULL) - return (void *)0; + if ((buf = dbg_malloc(size, pos)) == NULL) + return NULL; - bzero (buf, size); + memset(buf, 0, size); return buf; } -void * -dbg_realloc (void *ptr, size_t nmemb, size_t size, const char *pos) +void *dbg_realloc(void *ptr, size_t nmemb, size_t size, const char *pos) { unsigned *buf, old_size, new_size, cpy_size; if (ptr == NULL) - return (void *)0; + return NULL; - new_size = nmemb *size; + new_size = nmemb * size; if (new_size == 0) - return (void *)0; + return NULL; - EXIT_IF (nmemb > SIZE_MAX / size, _("overflow at %s"), pos); + EXIT_IF(nmemb > SIZE_MAX / size, _("overflow at %s"), pos); - if ((buf = dbg_malloc (new_size, pos)) == NULL) - return (void *)0; + if ((buf = dbg_malloc(new_size, pos)) == NULL) + return NULL; old_size = *((unsigned *)ptr - EXTRA_SPACE_START + BLK_SIZE); cpy_size = (old_size > new_size) ? new_size : old_size; - bcopy (ptr, buf, cpy_size); + memmove(buf, ptr, cpy_size); - mem_free (ptr); + mem_free(ptr); return (void *)buf; } -char * -dbg_strdup (const char *s, const char *pos) +char *dbg_strdup(const char *s, const char *pos) { size_t size; char *buf; if (s == NULL) - return (char *)0; + return NULL; - size = strlen (s); - if ((buf = dbg_malloc (size + 1, pos)) == NULL) - return (char *)0; + size = strlen(s); + if ((buf = dbg_malloc(size + 1, pos)) == NULL) + return NULL; - return strncpy (buf, s, size + 1); + return strncpy(buf, s, size + 1); } -void -dbg_free (void *ptr, const char *pos) +void dbg_free(void *ptr, const char *pos) { unsigned *buf, size; - EXIT_IF (ptr == NULL, _("dbg_free: null pointer at %s"), pos); + EXIT_IF(ptr == NULL, _("dbg_free: null pointer at %s"), pos); buf = (unsigned *)ptr - EXTRA_SPACE_START; size = buf[BLK_SIZE]; - EXIT_IF (buf[BLK_STATE] == MAGIC_FREE, - _("block seems already freed at %s"), pos); - EXIT_IF (buf[BLK_STATE] != MAGIC_ALLOC, - _("corrupt block header at %s"), pos); - EXIT_IF (buf[size - 1] != buf[BLK_ID], - _("corrupt block end at %s, (end = %u, should be %d)"), pos, - buf[size - 1], buf[BLK_ID]); + EXIT_IF(buf[BLK_STATE] == MAGIC_FREE, + _("block seems already freed at %s"), pos); + EXIT_IF(buf[BLK_STATE] != MAGIC_ALLOC, _("corrupt block header at %s"), pos); + EXIT_IF(buf[size - 1] != buf[BLK_ID], + _("corrupt block end at %s, (end = %u, should be %d)"), pos, + buf[size - 1], buf[BLK_ID]); buf[0] = MAGIC_FREE; - stats_del_blk (buf[BLK_ID]); + stats_del_blk(buf[BLK_ID]); - free (buf); + free(buf); mstats.nfree += size; } - -#ifdef CALCURSE_MEMORY_DEBUG - -static void -dump_block_info (struct mem_blk *blk) +static void dump_block_info(struct mem_blk *blk) { if (blk == NULL) return; - printf (_("---==== MEMORY BLOCK ====----------------\n")); - printf (_(" id: %u\n"), blk->id); - printf (_(" size: %u\n"), blk->size); - printf (_(" allocated in: %s\n"), blk->pos); - printf (_("-----------------------------------------\n")); + puts(_("---==== MEMORY BLOCK ====----------------\n")); + printf(_(" id: %u\n"), blk->id); + printf(_(" size: %u\n"), blk->size); + printf(_(" allocated in: %s\n"), blk->pos); + puts(_("-----------------------------------------\n")); } -void -mem_stats (void) +void mem_stats(void) { - printf ("\n"); - printf (_("+------------------------------+\n")); - printf (_("| calcurse memory usage report |\n")); - printf (_("+------------------------------+\n")); - printf (_(" number of calls: %u\n"), mstats.ncall); - printf (_(" allocated blocks: %u\n"), mstats.nalloc); - printf (_(" unfreed blocks: %u\n"), mstats.nalloc - mstats.nfree); - printf ("\n"); - - if (mstats.nfree < mstats.nalloc) - { - struct mem_blk *blk; - - for (blk = mstats.blk; blk; blk = blk->next) - dump_block_info (blk); - } + putchar('\n'); + puts(_("+------------------------------+\n")); + puts(_("| calcurse memory usage report |\n")); + puts(_("+------------------------------+\n")); + printf(_(" number of calls: %u\n"), mstats.ncall); + printf(_(" allocated blocks: %u\n"), mstats.nalloc); + printf(_(" unfreed blocks: %u\n"), mstats.nalloc - mstats.nfree); + putchar('\n'); + + if (mstats.nfree < mstats.nalloc) { + struct mem_blk *blk; + + for (blk = mstats.blk; blk; blk = blk->next) + dump_block_info(blk); + } } #endif /* CALCURSE_MEMORY_DEBUG */ diff --git a/src/note.c b/src/note.c new file mode 100644 index 0000000..d2f7ab2 --- /dev/null +++ b/src/note.c @@ -0,0 +1,235 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#include <unistd.h> +#include <dirent.h> + +#include "calcurse.h" +#include "sha1.h" + +struct note_gc_hash { + char *hash; + char buf[MAX_NOTESIZ + 1]; + HTABLE_ENTRY(note_gc_hash); +}; + +static void note_gc_extract_key(struct note_gc_hash *, const char **, int *); +static int note_gc_cmp(struct note_gc_hash *, struct note_gc_hash *); + +HTABLE_HEAD(htp, NOTE_GC_HSIZE, note_gc_hash); +HTABLE_PROTOTYPE(htp, note_gc_hash) + HTABLE_GENERATE(htp, note_gc_hash, note_gc_extract_key, note_gc_cmp) + +/* Create note file from a string and return a newly allocated string that + * contains its name. */ +char *generate_note(const char *str) +{ + char *sha1 = mem_malloc(SHA1_DIGESTLEN * 2 + 1); + char notepath[BUFSIZ]; + FILE *fp; + + sha1_digest(str, sha1); + snprintf(notepath, BUFSIZ, "%s%s", path_notes, sha1); + fp = fopen(notepath, "w"); + EXIT_IF(fp == NULL, _("Warning: could not open %s, Aborting..."), notepath); + fputs(str, fp); + file_close(fp, __FILE_POS__); + + return sha1; +} + +/* Edit a note with an external editor. */ +void edit_note(char **note, const char *editor) +{ + char tmppath[BUFSIZ]; + char *tmpext; + char notepath[BUFSIZ]; + char *sha1 = mem_malloc(SHA1_DIGESTLEN * 2 + 1); + FILE *fp; + + strncpy(tmppath, get_tempdir(), BUFSIZ); + strncat(tmppath, "/calcurse-note.", BUFSIZ - strlen(tmppath) - 1); + if ((tmpext = new_tempfile(tmppath, TMPEXTSIZ)) == NULL) + return; + strncat(tmppath, tmpext, BUFSIZ - strlen(tmppath) - 1); + mem_free(tmpext); + + if (*note != NULL) { + snprintf(notepath, BUFSIZ, "%s%s", path_notes, *note); + io_file_cp(notepath, tmppath); + } + + wins_launch_external(tmppath, editor); + + if (io_file_is_empty(tmppath) > 0) + erase_note(note); + else if ((fp = fopen(tmppath, "r"))) { + sha1_stream(fp, sha1); + fclose(fp); + *note = sha1; + + snprintf(notepath, BUFSIZ, "%s%s", path_notes, *note); + io_file_cp(tmppath, notepath); + } + + unlink(tmppath); +} + +/* View a note in an external pager. */ +void view_note(const char *note, const char *pager) +{ + char fullname[BUFSIZ]; + + if (note == NULL) + return; + snprintf(fullname, BUFSIZ, "%s%s", path_notes, note); + wins_launch_external(fullname, pager); +} + +/* Erase a note previously attached to an item. */ +void erase_note(char **note) +{ + if (*note == NULL) + return; + mem_free(*note); + *note = NULL; +} + +/* Read a serialized note file name from a stream and deserialize it. */ +void note_read(char *buffer, FILE * fp) +{ + int i; + + for (i = 0; i < MAX_NOTESIZ; i++) { + buffer[i] = getc(fp); + if (buffer[i] == ' ') { + buffer[i] = '\0'; + return; + } + } + + while (getc(fp) != ' ') ; + buffer[MAX_NOTESIZ] = '\0'; +} + +static void +note_gc_extract_key(struct note_gc_hash *data, const char **key, int *len) +{ + *key = data->hash; + *len = strlen(data->hash); +} + +static int note_gc_cmp(struct note_gc_hash *a, struct note_gc_hash *b) +{ + return strcmp(a->hash, b->hash); +} + +/* Spot and unlink unused note files. */ +void note_gc(void) +{ + struct htp gc_htable = HTABLE_INITIALIZER(&gc_htable); + struct note_gc_hash *hp; + DIR *dirp; + struct dirent *dp; + llist_item_t *i; + struct note_gc_hash tmph; + char notepath[BUFSIZ]; + + if (!(dirp = opendir(path_notes))) + return; + + /* Insert all note file names into a hash table. */ + do { + if ((dp = readdir(dirp)) && *(dp->d_name) != '.') { + hp = mem_malloc(sizeof(struct note_gc_hash)); + + strncpy(hp->buf, dp->d_name, MAX_NOTESIZ + 1); + hp->hash = hp->buf; + + HTABLE_INSERT(htp, &gc_htable, hp); + } + } + while (dp); + + closedir(dirp); + + /* Remove hashes that are actually in use. */ + LLIST_TS_FOREACH(&alist_p, i) { + struct apoint *apt = LLIST_GET_DATA(i); + if (apt->note) { + tmph.hash = apt->note; + free(HTABLE_REMOVE(htp, &gc_htable, &tmph)); + } + } + + LLIST_FOREACH(&eventlist, i) { + struct event *ev = LLIST_GET_DATA(i); + if (ev->note) { + tmph.hash = ev->note; + free(HTABLE_REMOVE(htp, &gc_htable, &tmph)); + } + } + + LLIST_TS_FOREACH(&recur_alist_p, i) { + struct recur_apoint *rapt = LLIST_GET_DATA(i); + if (rapt->note) { + tmph.hash = rapt->note; + free(HTABLE_REMOVE(htp, &gc_htable, &tmph)); + } + } + + LLIST_FOREACH(&recur_elist, i) { + struct recur_event *rev = LLIST_GET_DATA(i); + if (rev->note) { + tmph.hash = rev->note; + free(HTABLE_REMOVE(htp, &gc_htable, &tmph)); + } + } + + LLIST_FOREACH(&todolist, i) { + struct todo *todo = LLIST_GET_DATA(i); + if (todo->note) { + tmph.hash = todo->note; + free(HTABLE_REMOVE(htp, &gc_htable, &tmph)); + } + } + + /* Unlink unused note files. */ + HTABLE_FOREACH(hp, htp, &gc_htable) { + snprintf(notepath, BUFSIZ, "%s%s", path_notes, hp->hash); + unlink(notepath); + } +} diff --git a/src/notify.c b/src/notify.c index 3ed53bf..c746f49 100644 --- a/src/notify.c +++ b/src/notify.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,22 +51,21 @@ struct notify_vars { pthread_mutex_t mutex; }; -static struct notify_vars notify; -static struct notify_app notify_app; -static pthread_attr_t detached_thread_attr; -static pthread_t notify_t_main; +static struct notify_vars notify; +static struct notify_app notify_app; +static pthread_attr_t detached_thread_attr; +static pthread_t notify_t_main; /* * Return the number of seconds before next appointment * (0 if no upcoming appointment). */ -int -notify_time_left (void) +int notify_time_left(void) { time_t ntimer; int left; - ntimer = time (NULL); + ntimer = time(NULL); left = notify_app.time - ntimer; return left > 0 ? left : 0; @@ -76,11 +75,11 @@ notify_time_left (void) * Return 1 if the reminder was not sent already for the upcoming * appointment. */ -unsigned -notify_needs_reminder (void) +unsigned notify_needs_reminder(void) { if (notify_app.got_app - && (notify_app.state & APOINT_NOTIFY) + && (((notify_app.state & APOINT_NOTIFY) && !nbar.notify_all) || + (!(notify_app.state & APOINT_NOTIFY) && nbar.notify_all)) && !(notify_app.state & APOINT_NOTIFIED)) return 1; return 0; @@ -91,66 +90,62 @@ notify_needs_reminder (void) * Note: the mutex associated with this structure must be locked by the * caller! */ -void -notify_update_app (long start, char state, char *msg) +void notify_update_app(long start, char state, char *msg) { - notify_free_app (); + notify_free_app(); notify_app.got_app = 1; notify_app.time = start; notify_app.state = state; - notify_app.txt = mem_strdup (msg); + notify_app.txt = mem_strdup(msg); } /* Return 1 if we need to display the notify-bar, else 0. */ -int -notify_bar (void) +int notify_bar(void) { int display_bar = 0; - pthread_mutex_lock (&nbar.mutex); + pthread_mutex_lock(&nbar.mutex); display_bar = (nbar.show) ? 1 : 0; - pthread_mutex_unlock (&nbar.mutex); + pthread_mutex_unlock(&nbar.mutex); - return (display_bar); + return display_bar; } /* Initialize the nbar variable used to store notification options. */ -void -notify_init_vars (void) +void notify_init_vars(void) { - char *time_format = "%T"; - char *date_format = "%a %F"; - char *cmd = "printf '\\a'"; + const char *time_format = "%T"; + const char *date_format = "%a %F"; + const char *cmd = "printf '\\a'"; - pthread_mutex_init (&nbar.mutex, NULL); + pthread_mutex_init(&nbar.mutex, NULL); nbar.show = 1; nbar.cntdwn = 300; - (void)strncpy (nbar.datefmt, date_format, strlen (date_format) + 1); - (void)strncpy (nbar.timefmt, time_format, strlen (time_format) + 1); - (void)strncpy (nbar.cmd, cmd, strlen (cmd) + 1); + strncpy(nbar.datefmt, date_format, strlen(date_format) + 1); + strncpy(nbar.timefmt, time_format, strlen(time_format) + 1); + strncpy(nbar.cmd, cmd, strlen(cmd) + 1); - if ((nbar.shell = getenv ("SHELL")) == NULL) + if ((nbar.shell = getenv("SHELL")) == NULL) nbar.shell = "/bin/sh"; - (void)pthread_attr_init (&detached_thread_attr); - (void)pthread_attr_setdetachstate (&detached_thread_attr, - PTHREAD_CREATE_DETACHED); + nbar.notify_all = 0; + + pthread_attr_init(&detached_thread_attr); + pthread_attr_setdetachstate(&detached_thread_attr, PTHREAD_CREATE_DETACHED); } /* Extract the appointment file name from the complete file path. */ -static void -extract_aptsfile (void) +static void extract_aptsfile(void) { char *file; - file = strrchr (path_apts, '/'); + file = strrchr(path_apts, '/'); if (!file) notify.apts_file = path_apts; - else - { - notify.apts_file = file; - notify.apts_file++; - } + else { + notify.apts_file = file; + notify.apts_file++; + } } /* @@ -158,56 +153,50 @@ extract_aptsfile (void) * creating the notification window (l is the number of lines, c the * number of columns, y and x are its coordinates). */ -void -notify_init_bar (void) +void notify_init_bar(void) { - pthread_mutex_init (¬ify.mutex, NULL); - pthread_mutex_init (¬ify_app.mutex, NULL); + pthread_mutex_init(¬ify.mutex, NULL); + pthread_mutex_init(¬ify_app.mutex, NULL); notify_app.got_app = 0; notify_app.txt = 0; - notify.win = newwin (win[NOT].h, win[NOT].w, win[NOT].y, win[NOT].x); - extract_aptsfile (); + notify.win = newwin(win[NOT].h, win[NOT].w, win[NOT].y, win[NOT].x); + extract_aptsfile(); } /* * Free memory associated with the notify_app structure. */ -void -notify_free_app (void) +void notify_free_app(void) { notify_app.time = 0; notify_app.got_app = 0; notify_app.state = APOINT_NULL; if (notify_app.txt) - mem_free (notify_app.txt); + mem_free(notify_app.txt); notify_app.txt = 0; } /* Stop the notify-bar main thread. */ -void -notify_stop_main_thread (void) +void notify_stop_main_thread(void) { - if (notify_t_main) - { - pthread_cancel (notify_t_main); - pthread_join (notify_t_main, NULL); - } + if (notify_t_main) { + pthread_cancel(notify_t_main); + pthread_join(notify_t_main, NULL); + } } /* * The calcurse window geometry has changed so we need to reset the * notification window. */ -void -notify_reinit_bar (void) +void notify_reinit_bar(void) { - delwin (notify.win); - notify.win = newwin (win[NOT].h, win[NOT].w, win[NOT].y, win[NOT].x); + delwin(notify.win); + notify.win = newwin(win[NOT].h, win[NOT].w, win[NOT].y, win[NOT].x); } /* Launch user defined command as a notification. */ -unsigned -notify_launch_cmd (void) +unsigned notify_launch_cmd(void) { int pid; @@ -216,23 +205,19 @@ notify_launch_cmd (void) notify_app.state |= APOINT_NOTIFIED; - pid = fork (); + pid = fork(); - if (pid < 0) - { - ERROR_MSG (_("error while launching command: could not fork")); - return 0; - } - else if (pid == 0) - { - /* Child: launch user defined command */ - if (execlp (nbar.shell, nbar.shell, "-c", nbar.cmd, (char *)0) < 0) - { - ERROR_MSG (_("error while launching command")); - _exit (1); - } - _exit (0); + if (pid < 0) { + ERROR_MSG(_("error while launching command: could not fork")); + return 0; + } else if (pid == 0) { + /* Child: launch user defined command */ + if (execlp(nbar.shell, nbar.shell, "-c", nbar.cmd, NULL) < 0) { + ERROR_MSG(_("error while launching command")); + _exit(1); } + _exit(0); + } return 1; } @@ -241,8 +226,7 @@ notify_launch_cmd (void) * Update the notification bar. This is useful when changing color theme * for example. */ -void -notify_update_bar (void) +void notify_update_bar(void) { const int space = 3; int file_pos, date_pos, app_pos, txt_max_len, too_long = 0; @@ -250,82 +234,77 @@ notify_update_bar (void) char buf[BUFSIZ]; date_pos = space; - pthread_mutex_lock (¬ify.mutex); + pthread_mutex_lock(¬ify.mutex); - file_pos = strlen (notify.date) + strlen (notify.time) + 7 + 2 * space; - app_pos = file_pos + strlen (notify.apts_file) + 2 + space; + file_pos = strlen(notify.date) + strlen(notify.time) + 7 + 2 * space; + app_pos = file_pos + strlen(notify.apts_file) + 2 + space; txt_max_len = col - (app_pos + 12 + space); - custom_apply_attr (notify.win, ATTR_HIGHEST); - wattron (notify.win, A_UNDERLINE | A_REVERSE); - mvwhline (notify.win, 0, 0, ACS_HLINE, col); - mvwprintw (notify.win, 0, date_pos, "[ %s | %s ]", - notify.date, notify.time); - mvwprintw (notify.win, 0, file_pos, "(%s)", notify.apts_file); + custom_apply_attr(notify.win, ATTR_HIGHEST); + wattron(notify.win, A_UNDERLINE | A_REVERSE); + mvwhline(notify.win, 0, 0, ACS_HLINE, col); + mvwprintw(notify.win, 0, date_pos, "[ %s | %s ]", notify.date, notify.time); + mvwprintw(notify.win, 0, file_pos, "(%s)", notify.apts_file); + + pthread_mutex_lock(¬ify_app.mutex); + if (notify_app.got_app) { + if (strlen(notify_app.txt) > txt_max_len) { + int shrink_len; + + too_long = 1; + shrink_len = txt_max_len > 3 ? txt_max_len - 3 : 1; + strncpy(buf, notify_app.txt, shrink_len); + buf[shrink_len] = '\0'; + } + time_left = notify_time_left(); + if (time_left > 0) { + int hours_left, minutes_left; + + hours_left = (time_left / HOURINSEC); + minutes_left = (time_left - hours_left * HOURINSEC) / MININSEC; + pthread_mutex_lock(&nbar.mutex); + + if (time_left < nbar.cntdwn && + (((notify_app.state & APOINT_NOTIFY) && !nbar.notify_all) || + (!(notify_app.state & APOINT_NOTIFY) && nbar.notify_all))) + blinking = 1; + else + blinking = 0; - pthread_mutex_lock (¬ify_app.mutex); - if (notify_app.got_app) - { - if (strlen (notify_app.txt) > txt_max_len) - { - int shrink_len; - - too_long = 1; - shrink_len = txt_max_len > 3 ? txt_max_len - 3 : 1; - (void)strncpy (buf, notify_app.txt, shrink_len); - buf[shrink_len] = '\0'; - } - time_left = notify_time_left (); - if (time_left > 0) - { - int hours_left, minutes_left; - - hours_left = (time_left / HOURINSEC); - minutes_left = (time_left - hours_left * HOURINSEC) / MININSEC; - pthread_mutex_lock (&nbar.mutex); - - if (time_left < nbar.cntdwn && (notify_app.state & APOINT_NOTIFY)) - blinking = 1; - else - blinking = 0; - - if (blinking) - wattron (notify.win, A_BLINK); - if (too_long) - mvwprintw (notify.win, 0, app_pos, "> %02d:%02d :: %s.. <", - hours_left, minutes_left, buf); - else - mvwprintw (notify.win, 0, app_pos, "> %02d:%02d :: %s <", - hours_left, minutes_left, notify_app.txt); - if (blinking) - wattroff (notify.win, A_BLINK); - - if (blinking) - (void)notify_launch_cmd (); - pthread_mutex_unlock (&nbar.mutex); - } + if (blinking) + wattron(notify.win, A_BLINK); + if (too_long) + mvwprintw(notify.win, 0, app_pos, "> %02d:%02d :: %s.. <", + hours_left, minutes_left, buf); else - { - notify_app.got_app = 0; - pthread_mutex_unlock (¬ify_app.mutex); - pthread_mutex_unlock (¬ify.mutex); - notify_check_next_app (0); - return; - } + mvwprintw(notify.win, 0, app_pos, "> %02d:%02d :: %s <", + hours_left, minutes_left, notify_app.txt); + if (blinking) + wattroff(notify.win, A_BLINK); + + if (blinking) + notify_launch_cmd(); + pthread_mutex_unlock(&nbar.mutex); + } else { + notify_app.got_app = 0; + pthread_mutex_unlock(¬ify_app.mutex); + pthread_mutex_unlock(¬ify.mutex); + notify_check_next_app(0); + return; } - pthread_mutex_unlock (¬ify_app.mutex); + } + pthread_mutex_unlock(¬ify_app.mutex); - wattroff (notify.win, A_UNDERLINE | A_REVERSE); - custom_remove_attr (notify.win, ATTR_HIGHEST); - wins_wrefresh (notify.win); + wattroff(notify.win, A_UNDERLINE | A_REVERSE); + custom_remove_attr(notify.win, ATTR_HIGHEST); + wins_wrefresh(notify.win); - pthread_mutex_unlock (¬ify.mutex); + pthread_mutex_unlock(¬ify.mutex); } /* Update the notication bar content */ /* ARGSUSED0 */ -static void * -notify_main_thread (void *arg) +static void *notify_main_thread(void *arg) { const unsigned thread_sleep = 1; const unsigned check_app = MININSEC; @@ -336,49 +315,46 @@ notify_main_thread (void *arg) elapse = 0; - for (;;) - { - ntimer = time (NULL); - ntime = localtime (&ntimer); - pthread_mutex_lock (¬ify.mutex); - pthread_mutex_lock (&nbar.mutex); - strftime (notify.time, NOTIFY_FIELD_LENGTH, nbar.timefmt, ntime); - strftime (notify.date, NOTIFY_FIELD_LENGTH, nbar.datefmt, ntime); - pthread_mutex_unlock (&nbar.mutex); - pthread_mutex_unlock (¬ify.mutex); - notify_update_bar (); - psleep (thread_sleep); - elapse += thread_sleep; - if (elapse >= check_app) - { - elapse = 0; - pthread_mutex_lock (¬ify_app.mutex); - got_app = notify_app.got_app; - pthread_mutex_unlock (¬ify_app.mutex); - if (!got_app) - notify_check_next_app (0); - } + for (;;) { + ntimer = time(NULL); + ntime = localtime(&ntimer); + pthread_mutex_lock(¬ify.mutex); + pthread_mutex_lock(&nbar.mutex); + strftime(notify.time, NOTIFY_FIELD_LENGTH, nbar.timefmt, ntime); + strftime(notify.date, NOTIFY_FIELD_LENGTH, nbar.datefmt, ntime); + pthread_mutex_unlock(&nbar.mutex); + pthread_mutex_unlock(¬ify.mutex); + notify_update_bar(); + psleep(thread_sleep); + elapse += thread_sleep; + if (elapse >= check_app) { + elapse = 0; + pthread_mutex_lock(¬ify_app.mutex); + got_app = notify_app.got_app; + pthread_mutex_unlock(¬ify_app.mutex); + if (!got_app) + notify_check_next_app(0); } - pthread_exit ((void *) 0); + } + pthread_exit(NULL); } /* Fill the given structure with information about next appointment. */ -unsigned -notify_get_next (struct notify_app *a) +unsigned notify_get_next(struct notify_app *a) { time_t current_time; if (!a) return 0; - current_time = time (NULL); + current_time = time(NULL); a->time = current_time + DAYINSEC; a->got_app = 0; a->state = 0; - a->txt = (char *)0; - (void)recur_apoint_check_next (a, current_time, get_today ()); - (void)apoint_check_next (a, current_time); + a->txt = NULL; + recur_apoint_check_next(a, current_time, get_today()); + apoint_check_next(a, current_time); return 1; } @@ -387,191 +363,162 @@ notify_get_next (struct notify_app *a) * This is used for the daemon to check if we have an upcoming appointment or * not. */ -unsigned -notify_get_next_bkgd (void) +unsigned notify_get_next_bkgd(void) { struct notify_app a; - a.txt = (char *)0; - if (!notify_get_next (&a)) + a.txt = NULL; + if (!notify_get_next(&a)) return 0; - if (!a.got_app) - { - /* No next appointment, reset the previous notified one. */ - notify_app.got_app = 0; - return 1; - } - else - { - if (!notify_same_item (a.time)) - notify_update_app (a.time, a.state, a.txt); - } + if (!a.got_app) { + /* No next appointment, reset the previous notified one. */ + notify_app.got_app = 0; + return 1; + } else { + if (!notify_same_item(a.time)) + notify_update_app(a.time, a.state, a.txt); + } if (a.txt) - mem_free (a.txt); + mem_free(a.txt); return 1; } /* Return the description of next appointment to be notified. */ -char * -notify_app_txt (void) +char *notify_app_txt(void) { if (notify_app.got_app) return notify_app.txt; else - return (char *)0; + return NULL; } /* Look for the next appointment within the next 24 hours. */ /* ARGSUSED0 */ -static void * -notify_thread_app (void *arg) +static void *notify_thread_app(void *arg) { struct notify_app tmp_app; int force = (arg ? 1 : 0); - if (!notify_get_next (&tmp_app)) - pthread_exit ((void *)0); - - if (!tmp_app.got_app) - { - pthread_mutex_lock (¬ify_app.mutex); - notify_free_app (); - pthread_mutex_unlock (¬ify_app.mutex); - } - else - { - if (force || !notify_same_item (tmp_app.time)) - { - pthread_mutex_lock (¬ify_app.mutex); - notify_update_app (tmp_app.time, tmp_app.state, tmp_app.txt); - pthread_mutex_unlock (¬ify_app.mutex); - } + if (!notify_get_next(&tmp_app)) + pthread_exit(NULL); + + if (!tmp_app.got_app) { + pthread_mutex_lock(¬ify_app.mutex); + notify_free_app(); + pthread_mutex_unlock(¬ify_app.mutex); + } else { + if (force || !notify_same_item(tmp_app.time)) { + pthread_mutex_lock(¬ify_app.mutex); + notify_update_app(tmp_app.time, tmp_app.state, tmp_app.txt); + pthread_mutex_unlock(¬ify_app.mutex); } + } if (tmp_app.txt) - mem_free (tmp_app.txt); - notify_update_bar (); + mem_free(tmp_app.txt); + notify_update_bar(); - pthread_exit ((void *) 0); + pthread_exit(NULL); } /* Launch the thread notify_thread_app to look for next appointment. */ -void -notify_check_next_app (int force) +void notify_check_next_app(int force) { pthread_t notify_t_app; - void *arg = (force ? (void *)1 : (void *)0); + void *arg = (force ? (void *)1 : NULL); - pthread_create (¬ify_t_app, &detached_thread_attr, notify_thread_app, - arg); + pthread_create(¬ify_t_app, &detached_thread_attr, notify_thread_app, arg); return; } /* Check if the newly created appointment is to be notified. */ -void -notify_check_added (char *mesg, long start, char state) +void notify_check_added(char *mesg, long start, char state) { time_t current_time; int update_notify = 0; long gap; - current_time = time (NULL); - pthread_mutex_lock (¬ify_app.mutex); - if (!notify_app.got_app) - { - gap = start - current_time; - if (gap >= 0 && gap <= DAYINSEC) - update_notify = 1; - } - else if (start < notify_app.time && start >= current_time) - { + current_time = time(NULL); + pthread_mutex_lock(¬ify_app.mutex); + if (!notify_app.got_app) { + gap = start - current_time; + if (gap >= 0 && gap <= DAYINSEC) update_notify = 1; - } - else if (start == notify_app.time && state != notify_app.state) + } else if (start < notify_app.time && start >= current_time) { + update_notify = 1; + } else if (start == notify_app.time && state != notify_app.state) update_notify = 1; - if (update_notify) - { - notify_update_app (start, state, mesg); - } - pthread_mutex_unlock (¬ify_app.mutex); - notify_update_bar (); + if (update_notify) { + notify_update_app(start, state, mesg); + } + pthread_mutex_unlock(¬ify_app.mutex); + notify_update_bar(); } /* Check if the newly repeated appointment is to be notified. */ -void -notify_check_repeated (struct recur_apoint *i) +void notify_check_repeated(struct recur_apoint *i) { - long real_app_time; + unsigned real_app_time; int update_notify = 0; time_t current_time; - current_time = time (NULL); - pthread_mutex_lock (¬ify_app.mutex); - if ((real_app_time = recur_item_inday (i->start, &i->exc, i->rpt->type, - i->rpt->freq, i->rpt->until, - get_today ()))) - { - if (!notify_app.got_app) - { - if (real_app_time - current_time <= DAYINSEC) - update_notify = 1; - } - else if (real_app_time < notify_app.time && - real_app_time >= current_time) - { - update_notify = 1; - } - else if (real_app_time == notify_app.time && - i->state != notify_app.state) + current_time = time(NULL); + pthread_mutex_lock(¬ify_app.mutex); + if (recur_item_find_occurrence(i->start, i->dur, &i->exc, i->rpt->type, + i->rpt->freq, i->rpt->until, get_today(), + &real_app_time)) { + if (!notify_app.got_app) { + if (real_app_time - current_time <= DAYINSEC) update_notify = 1; - } - if (update_notify) - { - notify_update_app (real_app_time, i->state, i->mesg); - } - pthread_mutex_unlock (¬ify_app.mutex); - notify_update_bar (); + } else if (real_app_time < notify_app.time && real_app_time >= current_time) { + update_notify = 1; + } else if (real_app_time == notify_app.time && i->state != notify_app.state) + update_notify = 1; + } + if (update_notify) { + notify_update_app(real_app_time, i->state, i->mesg); + } + pthread_mutex_unlock(¬ify_app.mutex); + notify_update_bar(); } -int -notify_same_item (long time) +int notify_same_item(long time) { int same = 0; - pthread_mutex_lock (&(notify_app.mutex)); + pthread_mutex_lock(&(notify_app.mutex)); if (notify_app.got_app && notify_app.time == time) same = 1; - pthread_mutex_unlock (&(notify_app.mutex)); + pthread_mutex_unlock(&(notify_app.mutex)); return same; } -int -notify_same_recur_item (struct recur_apoint *i) +int notify_same_recur_item(struct recur_apoint *i) { int same = 0; - long item_start = 0; + unsigned item_start = 0; - item_start = recur_item_inday (i->start, &i->exc, i->rpt->type, - i->rpt->freq, i->rpt->until, get_today ()); - pthread_mutex_lock (¬ify_app.mutex); + recur_item_find_occurrence(i->start, i->dur, &i->exc, i->rpt->type, + i->rpt->freq, i->rpt->until, get_today(), + &item_start); + pthread_mutex_lock(¬ify_app.mutex); if (notify_app.got_app && item_start == notify_app.time) same = 1; - pthread_mutex_unlock (&(notify_app.mutex)); + pthread_mutex_unlock(&(notify_app.mutex)); return same; } /* Launch the notify-bar main thread. */ -void -notify_start_main_thread (void) +void notify_start_main_thread(void) { - pthread_create (¬ify_t_main, NULL, notify_main_thread, NULL); - notify_check_next_app (0); + pthread_create(¬ify_t_main, NULL, notify_main_thread, NULL); + notify_check_next_app(0); } /* @@ -580,255 +527,248 @@ notify_start_main_thread (void) * (either YES or NO), or an option holding a string value. */ static void -print_option (WINDOW *win, unsigned x, unsigned y, char *name, - char *valstr, unsigned valbool, char *desc, unsigned num) +print_option(WINDOW * win, unsigned x, unsigned y, char *name, + char *valstr, unsigned valbool, char *desc, unsigned num) { const int XOFF = 4; const int MAXCOL = col - 3; int x_opt, len; - x_opt = x + XOFF + strlen (name); - mvwprintw (win, y, x, "[%u] %s", num, name); - erase_window_part (win, x_opt, y, MAXCOL, y); - if ((len = strlen (valstr)) != 0) - { - unsigned maxlen; - - maxlen = MAXCOL - x_opt - 2; - custom_apply_attr (win, ATTR_HIGHEST); - if (len < maxlen) - mvwprintw (win, y, x_opt, "%s", valstr); - else - { - char buf[BUFSIZ]; - - (void)strncpy (buf, valstr, maxlen - 1); - buf[maxlen - 1] = '\0'; - mvwprintw (win, y, x_opt, "%s...", buf); - } - custom_remove_attr (win, ATTR_HIGHEST); + x_opt = x + XOFF + strlen(name); + mvwprintw(win, y, x, "[%u] %s", num, name); + erase_window_part(win, x_opt, y, MAXCOL, y); + if ((len = strlen(valstr)) != 0) { + unsigned maxlen; + + maxlen = MAXCOL - x_opt - 2; + custom_apply_attr(win, ATTR_HIGHEST); + if (len < maxlen) + mvwprintw(win, y, x_opt, "%s", valstr); + else { + char buf[BUFSIZ]; + + strncpy(buf, valstr, maxlen - 1); + buf[maxlen - 1] = '\0'; + mvwprintw(win, y, x_opt, "%s...", buf); } - else - print_bool_option_incolor (win, valbool, y, x_opt); - mvwprintw (win, y + 1, x, desc); + custom_remove_attr(win, ATTR_HIGHEST); + } else + print_bool_option_incolor(win, valbool, y, x_opt); + mvwprintw(win, y + 1, x, desc); } /* Print options related to the notify-bar. */ -static unsigned -print_config_options (WINDOW *optwin) +static unsigned print_config_options(WINDOW * optwin) { const int XORIG = 3; const int YORIG = 0; - const int YOFF = 3; + const int YOFF = 3; - enum - { SHOW, DATE, CLOCK, WARN, CMD, DMON, DMON_LOG, NB_OPT }; + enum { SHOW, DATE, CLOCK, WARN, CMD, NOTIFY_ALL, DMON, DMON_LOG, NB_OPT }; - struct opt_s - { - char *name; - char *desc; - char valstr[BUFSIZ]; - unsigned valnum; + struct opt_s { + char *name; + char *desc; + char valstr[BUFSIZ]; + unsigned valnum; } opt[NB_OPT]; int i; - opt[SHOW].name = _("notify-bar_show = "); + opt[SHOW].name = _("appearance.notifybar = "); opt[SHOW].desc = _("(if set to YES, notify-bar will be displayed)"); - opt[DATE].name = _("notify-bar_date = "); + opt[DATE].name = _("format.notifydate = "); opt[DATE].desc = _("(Format of the date to be displayed inside notify-bar)"); - opt[CLOCK].name = _("notify-bar_clock = "); + opt[CLOCK].name = _("format.notifytime = "); opt[CLOCK].desc = _("(Format of the time to be displayed inside notify-bar)"); - opt[WARN].name = _("notify-bar_warning = "); + opt[WARN].name = _("notification.warning = "); opt[WARN].desc = _("(Warn user if an appointment is within next " "'notify-bar_warning' seconds)"); - opt[CMD].name = _("notify-bar_command = "); + opt[CMD].name = _("notification.command = "); opt[CMD].desc = _("(Command used to notify user of an upcoming appointment)"); - opt[DMON].name = _("notify-daemon_enable = "); + opt[NOTIFY_ALL].name = _("notification.notifyall = "); + opt[NOTIFY_ALL].desc = + _("(Notify all appointments instead of flagged ones only)"); + + opt[DMON].name = _("daemon.enable = "); opt[DMON].desc = _("(Run in background to get notifications after exiting)"); - opt[DMON_LOG].name = _("notify-daemon_log = "); + opt[DMON_LOG].name = _("daemon.log = "); opt[DMON_LOG].desc = _("(Log activity when running in background)"); - pthread_mutex_lock (&nbar.mutex); + pthread_mutex_lock(&nbar.mutex); /* String value options */ - (void)strncpy (opt[DATE].valstr, nbar.datefmt, BUFSIZ); - (void)strncpy (opt[CLOCK].valstr, nbar.timefmt, BUFSIZ); - (void)snprintf (opt[WARN].valstr, BUFSIZ, "%d", nbar.cntdwn); - (void)strncpy (opt[CMD].valstr, nbar.cmd, BUFSIZ); + strncpy(opt[DATE].valstr, nbar.datefmt, BUFSIZ); + strncpy(opt[CLOCK].valstr, nbar.timefmt, BUFSIZ); + snprintf(opt[WARN].valstr, BUFSIZ, "%d", nbar.cntdwn); + strncpy(opt[CMD].valstr, nbar.cmd, BUFSIZ); /* Boolean options */ opt[SHOW].valnum = nbar.show; - pthread_mutex_unlock (&nbar.mutex); + opt[NOTIFY_ALL].valnum = nbar.notify_all; + pthread_mutex_unlock(&nbar.mutex); opt[DMON].valnum = dmon.enable; opt[DMON_LOG].valnum = dmon.log; - opt[SHOW].valstr[0] = opt[DMON].valstr[0] = opt[DMON_LOG].valstr[0] = '\0'; + opt[SHOW].valstr[0] = opt[NOTIFY_ALL].valstr[0] = opt[DMON].valstr[0] = + opt[DMON_LOG].valstr[0] = '\0'; - for (i = 0; i < NB_OPT; i++) - { - int y; + for (i = 0; i < NB_OPT; i++) { + int y; - y = YORIG + i * YOFF; - print_option (optwin, XORIG, y, opt[i].name, opt[i].valstr, - opt[i].valnum, opt[i].desc, i + 1); - } + y = YORIG + i * YOFF; + print_option(optwin, XORIG, y, opt[i].name, opt[i].valstr, + opt[i].valnum, opt[i].desc, i + 1); + } return YORIG + NB_OPT * YOFF; } -static void -reinit_conf_win (struct scrollwin *win) +static void reinit_conf_win(struct scrollwin *win) { unsigned first_line; first_line = win->first_visible_line; - wins_scrollwin_delete (win); - custom_set_swsiz (win); - wins_scrollwin_init (win); - wins_show (win->win.p, win->label); + wins_scrollwin_delete(win); + custom_set_swsiz(win); + wins_scrollwin_init(win); + wins_show(win->win.p, win->label); win->first_visible_line = first_line; } /* Notify-bar configuration. */ -void -notify_config_bar (void) +void notify_config_bar(void) { struct scrollwin cwin; char *buf; - char *number_str = - _("Enter an option number to change its value"); - char *keys = - _("(Press '^P' or '^N' to move up or down, 'Q' to quit)"); - char *date_str = - _("Enter the date format (see 'man 3 strftime' for possible formats) "); - char *time_str = - _("Enter the time format (see 'man 3 strftime' for possible formats) "); - char *count_str = - _("Enter the number of seconds (0 not to be warned before an appointment)"); - char *cmd_str = _("Enter the notification command "); + const char *number_str = _("Enter an option number to change its value"); + const char *keys = _("(Press '^P' or '^N' to move up or down, 'Q' to quit)"); + const char *date_str = + _("Enter the date format (see 'man 3 strftime' for possible formats) "); + const char *time_str = + _("Enter the time format (see 'man 3 strftime' for possible formats) "); + const char *count_str = + _ + ("Enter the number of seconds (0 not to be warned before an appointment)"); + const char *cmd_str = _("Enter the notification command "); int ch; - clear (); - custom_set_swsiz (&cwin); - (void)snprintf (cwin.label, BUFSIZ, _("notification options")); - wins_scrollwin_init (&cwin); - wins_show (cwin.win.p, cwin.label); - status_mesg (number_str, keys); - cwin.total_lines = print_config_options (cwin.pad.p); - wins_scrollwin_display (&cwin); - - buf = mem_malloc (BUFSIZ); - while ((ch = wgetch (win[STA].p)) != 'q') - { - buf[0] = '\0'; - - switch (ch) - { - case CTRL ('N'): - wins_scrollwin_down (&cwin, 1); - break; - case CTRL ('P'): - wins_scrollwin_up (&cwin, 1); - break; - case '1': - pthread_mutex_lock (&nbar.mutex); - nbar.show = !nbar.show; - pthread_mutex_unlock (&nbar.mutex); - if (notify_bar ()) - notify_start_main_thread (); - else - notify_stop_main_thread (); - wins_scrollwin_delete (&cwin); - reinit_conf_win (&cwin); - break; - case '2': - status_mesg (date_str, ""); - pthread_mutex_lock (&nbar.mutex); - (void)strncpy (buf, nbar.datefmt, strlen (nbar.datefmt) + 1); - pthread_mutex_unlock (&nbar.mutex); - if (updatestring (win[STA].p, &buf, 0, 1) == 0) - { - pthread_mutex_lock (&nbar.mutex); - (void)strncpy (nbar.datefmt, buf, strlen (buf) + 1); - pthread_mutex_unlock (&nbar.mutex); - } - break; - case '3': - status_mesg (time_str, ""); - pthread_mutex_lock (&nbar.mutex); - (void)strncpy (buf, nbar.timefmt, strlen (nbar.timefmt) + 1); - pthread_mutex_unlock (&nbar.mutex); - if (updatestring (win[STA].p, &buf, 0, 1) == 0) - { - pthread_mutex_lock (&nbar.mutex); - (void)strncpy (nbar.timefmt, buf, strlen (buf) + 1); - pthread_mutex_unlock (&nbar.mutex); - } - break; - case '4': - status_mesg (count_str, ""); - pthread_mutex_lock (&nbar.mutex); - snprintf (buf, BUFSIZ, "%d", nbar.cntdwn); - pthread_mutex_unlock (&nbar.mutex); - if (updatestring (win[STA].p, &buf, 0, 1) == 0 && - is_all_digit (buf) && atoi (buf) >= 0 && atoi (buf) <= DAYINSEC) - { - pthread_mutex_lock (&nbar.mutex); - nbar.cntdwn = atoi (buf); - pthread_mutex_unlock (&nbar.mutex); - } - break; - case '5': - status_mesg (cmd_str, ""); - pthread_mutex_lock (&nbar.mutex); - (void)strncpy (buf, nbar.cmd, strlen (nbar.cmd) + 1); - pthread_mutex_unlock (&nbar.mutex); - if (updatestring (win[STA].p, &buf, 0, 1) == 0) - { - pthread_mutex_lock (&nbar.mutex); - (void)strncpy (nbar.cmd, buf, strlen (buf) + 1); - pthread_mutex_unlock (&nbar.mutex); - } - break; - case '6': - dmon.enable = !dmon.enable; - break; - case '7': - dmon.log = !dmon.log; - break; - } - - if (resize) - { - resize = 0; - wins_get_config (); - wins_reset (); - reinit_conf_win (&cwin); - delwin (win[STA].p); - win[STA].p = newwin (win[STA].h, win[STA].w, win[STA].y, - win[STA].x); - keypad (win[STA].p, TRUE); - if (notify_bar ()) - { - notify_reinit_bar (); - notify_update_bar (); - } - clearok (curscr, TRUE); - } - - status_mesg (number_str, keys); - cwin.total_lines = print_config_options (cwin.pad.p); - wins_scrollwin_display (&cwin); + clear(); + custom_set_swsiz(&cwin); + cwin.label = _("notification options"); + wins_scrollwin_init(&cwin); + wins_show(cwin.win.p, cwin.label); + status_mesg(number_str, keys); + cwin.total_lines = print_config_options(cwin.pad.p); + wins_scrollwin_display(&cwin); + + buf = mem_malloc(BUFSIZ); + while ((ch = wgetch(win[STA].p)) != 'q') { + buf[0] = '\0'; + + switch (ch) { + case CTRL('N'): + wins_scrollwin_down(&cwin, 1); + break; + case CTRL('P'): + wins_scrollwin_up(&cwin, 1); + break; + case '1': + pthread_mutex_lock(&nbar.mutex); + nbar.show = !nbar.show; + pthread_mutex_unlock(&nbar.mutex); + if (notify_bar()) + notify_start_main_thread(); + else + notify_stop_main_thread(); + wins_scrollwin_delete(&cwin); + reinit_conf_win(&cwin); + break; + case '2': + status_mesg(date_str, ""); + pthread_mutex_lock(&nbar.mutex); + strncpy(buf, nbar.datefmt, strlen(nbar.datefmt) + 1); + pthread_mutex_unlock(&nbar.mutex); + if (updatestring(win[STA].p, &buf, 0, 1) == 0) { + pthread_mutex_lock(&nbar.mutex); + strncpy(nbar.datefmt, buf, strlen(buf) + 1); + pthread_mutex_unlock(&nbar.mutex); + } + break; + case '3': + status_mesg(time_str, ""); + pthread_mutex_lock(&nbar.mutex); + strncpy(buf, nbar.timefmt, strlen(nbar.timefmt) + 1); + pthread_mutex_unlock(&nbar.mutex); + if (updatestring(win[STA].p, &buf, 0, 1) == 0) { + pthread_mutex_lock(&nbar.mutex); + strncpy(nbar.timefmt, buf, strlen(buf) + 1); + pthread_mutex_unlock(&nbar.mutex); + } + break; + case '4': + status_mesg(count_str, ""); + pthread_mutex_lock(&nbar.mutex); + snprintf(buf, BUFSIZ, "%d", nbar.cntdwn); + pthread_mutex_unlock(&nbar.mutex); + if (updatestring(win[STA].p, &buf, 0, 1) == 0 && + is_all_digit(buf) && atoi(buf) >= 0 && atoi(buf) <= DAYINSEC) { + pthread_mutex_lock(&nbar.mutex); + nbar.cntdwn = atoi(buf); + pthread_mutex_unlock(&nbar.mutex); + } + break; + case '5': + status_mesg(cmd_str, ""); + pthread_mutex_lock(&nbar.mutex); + strncpy(buf, nbar.cmd, strlen(nbar.cmd) + 1); + pthread_mutex_unlock(&nbar.mutex); + if (updatestring(win[STA].p, &buf, 0, 1) == 0) { + pthread_mutex_lock(&nbar.mutex); + strncpy(nbar.cmd, buf, strlen(buf) + 1); + pthread_mutex_unlock(&nbar.mutex); + } + break; + case '6': + pthread_mutex_lock(&nbar.mutex); + nbar.notify_all = !nbar.notify_all; + pthread_mutex_unlock(&nbar.mutex); + notify_check_next_app(1); + break; + case '7': + dmon.enable = !dmon.enable; + break; + case '8': + dmon.log = !dmon.log; + break; + } + + if (resize) { + resize = 0; + wins_get_config(); + wins_reset(); + reinit_conf_win(&cwin); + delwin(win[STA].p); + win[STA].p = newwin(win[STA].h, win[STA].w, win[STA].y, win[STA].x); + keypad(win[STA].p, TRUE); + if (notify_bar()) { + notify_reinit_bar(); + notify_update_bar(); + } + clearok(curscr, TRUE); } - mem_free (buf); - wins_scrollwin_delete (&cwin); + + status_mesg(number_str, keys); + cwin.total_lines = print_config_options(cwin.pad.p); + wins_scrollwin_display(&cwin); + } + mem_free(buf); + wins_scrollwin_delete(&cwin); } diff --git a/src/pcal.c b/src/pcal.c new file mode 100644 index 0000000..c4f731d --- /dev/null +++ b/src/pcal.c @@ -0,0 +1,291 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#include <sys/types.h> + +#include "calcurse.h" + +/* Static functions used to add export functionalities. */ +static void pcal_export_header(FILE *); +static void pcal_export_recur_events(FILE *); +static void pcal_export_events(FILE *); +static void pcal_export_recur_apoints(FILE *); +static void pcal_export_apoints(FILE *); +static void pcal_export_todo(FILE *); +static void pcal_export_footer(FILE *); + +/* Type definition for callbacks to export functions. */ +typedef void (*cb_dump_t) (FILE *, long, long, char *); + +/* + * Travel through each occurence of an item, and execute the given callback + * (mainly used to export data). + */ +static void +foreach_date_dump(const long date_end, struct rpt *rpt, llist_t * exc, + long item_first_date, long item_dur, char *item_mesg, + cb_dump_t cb_dump, FILE * stream) +{ + long date, item_time; + struct tm lt; + time_t t; + + t = item_first_date; + lt = *localtime(&t); + lt.tm_hour = lt.tm_min = lt.tm_sec = 0; + lt.tm_isdst = -1; + date = mktime(<); + item_time = item_first_date - date; + + while (date <= date_end && date <= rpt->until) { + if (recur_item_inday(item_first_date, item_dur, exc, rpt->type, + rpt->freq, rpt->until, date)) { + (*cb_dump) (stream, date + item_time, item_dur, item_mesg); + } + switch (rpt->type) { + case RECUR_DAILY: + date = date_sec_change(date, 0, rpt->freq); + break; + case RECUR_WEEKLY: + date = date_sec_change(date, 0, rpt->freq * WEEKINDAYS); + break; + case RECUR_MONTHLY: + date = date_sec_change(date, rpt->freq, 0); + break; + case RECUR_YEARLY: + date = date_sec_change(date, rpt->freq * 12, 0); + break; + default: + EXIT(_("incoherent repetition type")); + /* NOTREACHED */ + break; + } + } +} + +static void pcal_export_header(FILE * stream) +{ + fputs("# calcurse pcal export\n", stream); + fputs("\n# =======\n# options\n# =======\n", stream); + fprintf(stream, "opt -A -K -l -m -F %s\n", + calendar_week_begins_on_monday()? "Monday" : "Sunday"); + fputs("# Display week number (i.e. 1-52) on every Monday\n", stream); + fprintf(stream, "all monday in all week %%w\n"); + fputc('\n', stream); +} + +static void pcal_export_footer(FILE * stream) +{ +} + +/* Format and dump event data to a pcal formatted file. */ +static void +pcal_dump_event(FILE * stream, long event_date, long event_dur, + char *event_mesg) +{ + char pcal_date[BUFSIZ]; + + date_sec2date_fmt(event_date, "%b %d", pcal_date); + fprintf(stream, "%s %s\n", pcal_date, event_mesg); +} + +/* Format and dump appointment data to a pcal formatted file. */ +static void +pcal_dump_apoint(FILE * stream, long apoint_date, long apoint_dur, + char *apoint_mesg) +{ + char pcal_date[BUFSIZ], pcal_beg[BUFSIZ], pcal_end[BUFSIZ]; + + date_sec2date_fmt(apoint_date, "%b %d", pcal_date); + date_sec2date_fmt(apoint_date, "%R", pcal_beg); + date_sec2date_fmt(apoint_date + apoint_dur, "%R", pcal_end); + fprintf(stream, "%s ", pcal_date); + fprintf(stream, "(%s -> %s) %s\n", pcal_beg, pcal_end, apoint_mesg); +} + +static void pcal_export_recur_events(FILE * stream) +{ + llist_item_t *i; + char pcal_date[BUFSIZ]; + + fputs("\n# =============", stream); + fputs("\n# Recur. Events", stream); + fputs("\n# =============\n", stream); + fputs("# (pcal does not support from..until dates specification\n", stream); + + LLIST_FOREACH(&recur_elist, i) { + struct recur_event *rev = LLIST_GET_DATA(i); + if (rev->rpt->until == 0 && rev->rpt->freq == 1) { + switch (rev->rpt->type) { + case RECUR_DAILY: + date_sec2date_fmt(rev->day, "%b %d", pcal_date); + fprintf(stream, "all day on_or_after %s %s\n", pcal_date, rev->mesg); + break; + case RECUR_WEEKLY: + date_sec2date_fmt(rev->day, "%a", pcal_date); + fprintf(stream, "all %s on_or_after ", pcal_date); + date_sec2date_fmt(rev->day, "%b %d", pcal_date); + fprintf(stream, "%s %s\n", pcal_date, rev->mesg); + break; + case RECUR_MONTHLY: + date_sec2date_fmt(rev->day, "%d", pcal_date); + fprintf(stream, "day on all %s %s\n", pcal_date, rev->mesg); + break; + case RECUR_YEARLY: + date_sec2date_fmt(rev->day, "%b %d", pcal_date); + fprintf(stream, "%s %s\n", pcal_date, rev->mesg); + break; + default: + EXIT(_("incoherent repetition type")); + } + } else { + const long YEAR_START = calendar_start_of_year(); + const long YEAR_END = calendar_end_of_year(); + + if (rev->day < YEAR_END && rev->day > YEAR_START) + foreach_date_dump(YEAR_END, rev->rpt, &rev->exc, rev->day, 0, + rev->mesg, (cb_dump_t) pcal_dump_event, stream); + } + } +} + +static void pcal_export_events(FILE * stream) +{ + llist_item_t *i; + + fputs("\n# ======\n# Events\n# ======\n", stream); + LLIST_FOREACH(&eventlist, i) { + struct event *ev = LLIST_TS_GET_DATA(i); + pcal_dump_event(stream, ev->day, 0, ev->mesg); + } + fputc('\n', stream); +} + +static void pcal_export_recur_apoints(FILE * stream) +{ + llist_item_t *i; + char pcal_date[BUFSIZ], pcal_beg[BUFSIZ], pcal_end[BUFSIZ]; + + fputs("\n# ==============", stream); + fputs("\n# Recur. Apoints", stream); + fputs("\n# ==============\n", stream); + fputs("# (pcal does not support from..until dates specification\n", stream); + + LLIST_TS_FOREACH(&recur_alist_p, i) { + struct recur_apoint *rapt = LLIST_TS_GET_DATA(i); + + if (rapt->rpt->until == 0 && rapt->rpt->freq == 1) { + date_sec2date_fmt(rapt->start, "%R", pcal_beg); + date_sec2date_fmt(rapt->start + rapt->dur, "%R", pcal_end); + switch (rapt->rpt->type) { + case RECUR_DAILY: + date_sec2date_fmt(rapt->start, "%b %d", pcal_date); + fprintf(stream, "all day on_or_after %s (%s -> %s) %s\n", + pcal_date, pcal_beg, pcal_end, rapt->mesg); + break; + case RECUR_WEEKLY: + date_sec2date_fmt(rapt->start, "%a", pcal_date); + fprintf(stream, "all %s on_or_after ", pcal_date); + date_sec2date_fmt(rapt->start, "%b %d", pcal_date); + fprintf(stream, "%s (%s -> %s) %s\n", pcal_date, pcal_beg, + pcal_end, rapt->mesg); + break; + case RECUR_MONTHLY: + date_sec2date_fmt(rapt->start, "%d", pcal_date); + fprintf(stream, "day on all %s (%s -> %s) %s\n", pcal_date, + pcal_beg, pcal_end, rapt->mesg); + break; + case RECUR_YEARLY: + date_sec2date_fmt(rapt->start, "%b %d", pcal_date); + fprintf(stream, "%s (%s -> %s) %s\n", pcal_date, pcal_beg, + pcal_end, rapt->mesg); + break; + default: + EXIT(_("incoherent repetition type")); + } + } else { + const long YEAR_START = calendar_start_of_year(); + const long YEAR_END = calendar_end_of_year(); + + if (rapt->start < YEAR_END && rapt->start > YEAR_START) + foreach_date_dump(YEAR_END, rapt->rpt, &rapt->exc, rapt->start, + rapt->dur, rapt->mesg, + (cb_dump_t) pcal_dump_apoint, stream); + } + } +} + +static void pcal_export_apoints(FILE * stream) +{ + llist_item_t *i; + + fputs("\n# ============\n# Appointments\n# ============\n", stream); + LLIST_TS_LOCK(&alist_p); + LLIST_TS_FOREACH(&alist_p, i) { + struct apoint *apt = LLIST_TS_GET_DATA(i); + pcal_dump_apoint(stream, apt->start, apt->dur, apt->mesg); + } + LLIST_TS_UNLOCK(&alist_p); + fputc('\n', stream); +} + +static void pcal_export_todo(FILE * stream) +{ + llist_item_t *i; + + fputs("#\n# Todos\n#\n", stream); + LLIST_FOREACH(&todolist, i) { + struct todo *todo = LLIST_TS_GET_DATA(i); + if (todo->id < 0) /* completed items */ + continue; + + fputs("note all ", stream); + fprintf(stream, "%d. %s\n", todo->id, todo->mesg); + } + fputc('\n', stream); +} + +/* Export calcurse data. */ +void pcal_export_data(FILE * stream) +{ + pcal_export_header(stream); + pcal_export_recur_events(stream); + pcal_export_events(stream); + pcal_export_recur_apoints(stream); + pcal_export_apoints(stream); + pcal_export_todo(stream); + pcal_export_footer(stream); +} diff --git a/src/recur.c b/src/recur.c index caa5ec3..dad9c25 100644 --- a/src/recur.c +++ b/src/recur.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,242 +42,217 @@ #include "calcurse.h" -llist_ts_t recur_alist_p; -llist_t recur_elist; -static struct recur_event bkp_cut_recur_event; +llist_ts_t recur_alist_p; +llist_t recur_elist; +static struct recur_event bkp_cut_recur_event; static struct recur_apoint bkp_cut_recur_apoint; -static void -free_exc (struct excp *exc) +static void free_exc(struct excp *exc) { - mem_free (exc); + mem_free(exc); } -static void -free_exc_list (llist_t *exc) +static void free_exc_list(llist_t * exc) { - LLIST_FREE_INNER (exc, free_exc); - LLIST_FREE (exc); + LLIST_FREE_INNER(exc, free_exc); + LLIST_FREE(exc); } -static int -exc_cmp_day (struct excp *a, struct excp *b) +static int exc_cmp_day(struct excp *a, struct excp *b) { - return (a->st < b->st ? -1 : (a->st == b->st ? 0 : 1)); + return a->st < b->st ? -1 : (a->st == b->st ? 0 : 1); } -static void -recur_add_exc (llist_t *exc, long day) +static void recur_add_exc(llist_t * exc, long day) { - struct excp *o = mem_malloc (sizeof (struct excp)); + struct excp *o = mem_malloc(sizeof(struct excp)); o->st = day; - LLIST_ADD_SORTED (exc, o, exc_cmp_day); + LLIST_ADD_SORTED(exc, o, exc_cmp_day); } -static void -exc_dup (llist_t *in, llist_t *exc) +static void exc_dup(llist_t * in, llist_t * exc) { llist_item_t *i; - LLIST_INIT (in); + LLIST_INIT(in); - if (exc) - { - LLIST_FOREACH (exc, i) - { - struct excp *p = LLIST_GET_DATA (i); - recur_add_exc (in, p->st); - } + if (exc) { + LLIST_FOREACH(exc, i) { + struct excp *p = LLIST_GET_DATA(i); + recur_add_exc(in, p->st); } + } } -void -recur_event_free_bkp (enum eraseflg flag) +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.rpt) - { - mem_free (bkp_cut_recur_event.rpt); - bkp_cut_recur_event.rpt = 0; - } - free_exc_list (&bkp_cut_recur_event.exc); - erase_note (&bkp_cut_recur_event.note, flag); + if (bkp_cut_recur_event.mesg) { + mem_free(bkp_cut_recur_event.mesg); + bkp_cut_recur_event.mesg = 0; + } + if (bkp_cut_recur_event.rpt) { + mem_free(bkp_cut_recur_event.rpt); + bkp_cut_recur_event.rpt = 0; + } + free_exc_list(&bkp_cut_recur_event.exc); + erase_note(&bkp_cut_recur_event.note); } -void -recur_apoint_free_bkp (enum eraseflg flag) +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.rpt) - { - mem_free (bkp_cut_recur_apoint.rpt); - bkp_cut_recur_apoint.rpt = 0; - } - free_exc_list (&bkp_cut_recur_apoint.exc); - erase_note (&bkp_cut_recur_apoint.note, flag); + if (bkp_cut_recur_apoint.mesg) { + mem_free(bkp_cut_recur_apoint.mesg); + bkp_cut_recur_apoint.mesg = 0; + } + if (bkp_cut_recur_apoint.rpt) { + mem_free(bkp_cut_recur_apoint.rpt); + bkp_cut_recur_apoint.rpt = 0; + } + free_exc_list(&bkp_cut_recur_apoint.exc); + erase_note(&bkp_cut_recur_apoint.note); } -static void -recur_event_dup (struct recur_event *in, struct recur_event *bkp) +static void recur_event_dup(struct recur_event *in, struct recur_event *bkp) { - EXIT_IF (!in || !bkp, _("null pointer")); + EXIT_IF(!in || !bkp, _("null pointer")); bkp->id = in->id; bkp->day = in->day; - bkp->mesg = mem_strdup (in->mesg); + bkp->mesg = mem_strdup(in->mesg); - bkp->rpt = mem_malloc (sizeof (struct rpt)); + bkp->rpt = mem_malloc(sizeof(struct rpt)); bkp->rpt->type = in->rpt->type; bkp->rpt->freq = in->rpt->freq; bkp->rpt->until = in->rpt->until; - exc_dup (&bkp->exc, &in->exc); + exc_dup(&bkp->exc, &in->exc); if (in->note) - bkp->note = mem_strdup (in->note); + bkp->note = mem_strdup(in->note); } -static void -recur_apoint_dup (struct recur_apoint *in, struct recur_apoint *bkp) +static void recur_apoint_dup(struct recur_apoint *in, struct recur_apoint *bkp) { - EXIT_IF (!in || !bkp, _("null pointer")); + 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->mesg = mem_strdup(in->mesg); - bkp->rpt = mem_malloc (sizeof (struct rpt)); + bkp->rpt = mem_malloc(sizeof(struct rpt)); bkp->rpt->type = in->rpt->type; bkp->rpt->freq = in->rpt->freq; bkp->rpt->until = in->rpt->until; - exc_dup (&bkp->exc, &in->exc); + exc_dup(&bkp->exc, &in->exc); if (in->note) - bkp->note = mem_strdup (in->note); + bkp->note = mem_strdup(in->note); } -void -recur_apoint_llist_init (void) +void recur_apoint_llist_init(void) { - LLIST_TS_INIT (&recur_alist_p); + LLIST_TS_INIT(&recur_alist_p); } -static void -recur_apoint_free (struct recur_apoint *rapt) +static void recur_apoint_free(struct recur_apoint *rapt) { - mem_free (rapt->mesg); + mem_free(rapt->mesg); if (rapt->note) - mem_free (rapt->note); + mem_free(rapt->note); if (rapt->rpt) - mem_free (rapt->rpt); - free_exc_list (&rapt->exc); - mem_free (rapt); + mem_free(rapt->rpt); + free_exc_list(&rapt->exc); + mem_free(rapt); } -static void -recur_event_free (struct recur_event *rev) +static void recur_event_free(struct recur_event *rev) { - mem_free (rev->mesg); + mem_free(rev->mesg); if (rev->note) - mem_free (rev->note); + mem_free(rev->note); if (rev->rpt) - mem_free (rev->rpt); - free_exc_list (&rev->exc); - mem_free (rev); + mem_free(rev->rpt); + free_exc_list(&rev->exc); + mem_free(rev); } -void -recur_apoint_llist_free (void) +void recur_apoint_llist_free(void) { - LLIST_TS_FREE_INNER (&recur_alist_p, recur_apoint_free); - LLIST_TS_FREE (&recur_alist_p); + LLIST_TS_FREE_INNER(&recur_alist_p, recur_apoint_free); + LLIST_TS_FREE(&recur_alist_p); } -void -recur_event_llist_free (void) +void recur_event_llist_free(void) { - LLIST_FREE_INNER (&recur_elist, recur_event_free); - LLIST_FREE (&recur_elist); + LLIST_FREE_INNER(&recur_elist, recur_event_free); + LLIST_FREE(&recur_elist); } static int -recur_apoint_cmp_start (struct recur_apoint *a, struct recur_apoint *b) +recur_apoint_cmp_start(struct recur_apoint *a, struct recur_apoint *b) { - return (a->start < b->start ? -1 : (a->start == b->start ? 0 : 1)); + return a->start < b->start ? -1 : (a->start == b->start ? 0 : 1); } -static int -recur_event_cmp_day (struct recur_event *a, struct recur_event *b) +static int recur_event_cmp_day(struct recur_event *a, struct recur_event *b) { - return (a->day < b->day ? -1 : (a->day == b->day ? 0 : 1)); + return a->day < b->day ? -1 : (a->day == b->day ? 0 : 1); } /* Insert a new recursive appointment in the general linked list */ -struct recur_apoint * -recur_apoint_new (char *mesg, char *note, long start, long dur, char state, - int type, int freq, long until, llist_t *except) +struct recur_apoint *recur_apoint_new(char *mesg, char *note, long start, + long dur, char state, int type, int freq, + long until, llist_t * except) { - struct recur_apoint *rapt = mem_malloc (sizeof (struct recur_apoint)); + struct recur_apoint *rapt = mem_malloc(sizeof(struct recur_apoint)); - rapt->rpt = mem_malloc (sizeof (struct rpt)); - rapt->mesg = mem_strdup (mesg); - rapt->note = (note != NULL) ? mem_strdup (note) : 0; + rapt->rpt = mem_malloc(sizeof(struct rpt)); + rapt->mesg = mem_strdup(mesg); + rapt->note = (note != NULL) ? mem_strdup(note) : 0; rapt->start = start; rapt->state = state; rapt->dur = dur; rapt->rpt->type = type; rapt->rpt->freq = freq; rapt->rpt->until = until; - if (except) - { - exc_dup (&rapt->exc, except); - free_exc_list (except); - } - else - LLIST_INIT (&rapt->exc); + if (except) { + exc_dup(&rapt->exc, except); + free_exc_list(except); + } else + LLIST_INIT(&rapt->exc); - LLIST_TS_LOCK (&recur_alist_p); - LLIST_TS_ADD_SORTED (&recur_alist_p, rapt, recur_apoint_cmp_start); - LLIST_TS_UNLOCK (&recur_alist_p); + LLIST_TS_LOCK(&recur_alist_p); + LLIST_TS_ADD_SORTED(&recur_alist_p, rapt, recur_apoint_cmp_start); + LLIST_TS_UNLOCK(&recur_alist_p); return rapt; } /* Insert a new recursive event in the general linked list */ -struct recur_event * -recur_event_new (char *mesg, char *note, long day, int id, int type, int freq, - long until, llist_t *except) +struct recur_event *recur_event_new(char *mesg, char *note, long day, int id, + int type, int freq, long until, + llist_t * except) { - struct recur_event *rev = mem_malloc (sizeof (struct recur_event)); + struct recur_event *rev = mem_malloc(sizeof(struct recur_event)); - rev->rpt = mem_malloc (sizeof (struct rpt)); - rev->mesg = mem_strdup (mesg); - rev->note = (note != NULL) ? mem_strdup (note) : 0; + rev->rpt = mem_malloc(sizeof(struct rpt)); + rev->mesg = mem_strdup(mesg); + rev->note = (note != NULL) ? mem_strdup(note) : 0; rev->day = day; rev->id = id; rev->rpt->type = type; rev->rpt->freq = freq; rev->rpt->until = until; - if (except) - { - exc_dup (&rev->exc, except); - free_exc_list (except); - } - else - LLIST_INIT (&rev->exc); + if (except) { + exc_dup(&rev->exc, except); + free_exc_list(except); + } else + LLIST_INIT(&rev->exc); - LLIST_ADD_SORTED (&recur_elist, rev, recur_event_cmp_day); + LLIST_ADD_SORTED(&recur_elist, rev, recur_event_cmp_day); return rev; } @@ -286,214 +261,195 @@ recur_event_new (char *mesg, char *note, long day, int id, int type, int freq, * Correspondance between the defines on recursive type, * and the letter to be written in file. */ -char -recur_def2char (enum recur_type define) +char recur_def2char(enum recur_type define) { char recur_char; - switch (define) - { - case RECUR_DAILY: - recur_char = 'D'; - break; - case RECUR_WEEKLY: - recur_char = 'W'; - break; - case RECUR_MONTHLY: - recur_char = 'M'; - break; - case RECUR_YEARLY: - recur_char = 'Y'; - break; - default: - EXIT (_("unknown repetition type")); - return 0; - } + switch (define) { + case RECUR_DAILY: + recur_char = 'D'; + break; + case RECUR_WEEKLY: + recur_char = 'W'; + break; + case RECUR_MONTHLY: + recur_char = 'M'; + break; + case RECUR_YEARLY: + recur_char = 'Y'; + break; + default: + EXIT(_("unknown repetition type")); + return 0; + } - return (recur_char); + return recur_char; } /* * 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; - switch (type) - { - case 'D': - recur_def = RECUR_DAILY; - break; - case 'W': - recur_def = RECUR_WEEKLY; - break; - case 'M': - recur_def = RECUR_MONTHLY; - break; - case 'Y': - recur_def = RECUR_YEARLY; - break; - default: - EXIT (_("unknown character")); - return 0; - } - return (recur_def); + switch (type) { + case 'D': + recur_def = RECUR_DAILY; + break; + case 'W': + recur_def = RECUR_WEEKLY; + break; + case 'M': + recur_def = RECUR_MONTHLY; + break; + case 'Y': + recur_def = RECUR_YEARLY; + break; + default: + EXIT(_("unknown character")); + return 0; + } + return recur_def; } /* Write days for which recurrent items should not be repeated. */ -static void -recur_write_exc (llist_t *lexc, FILE *f) +static void recur_write_exc(llist_t * lexc, FILE * f) { llist_item_t *i; struct tm *lt; time_t t; int st_mon, st_day, st_year; - LLIST_FOREACH (lexc, i) - { - struct excp *exc = LLIST_GET_DATA (i); - t = exc->st; - lt = localtime (&t); - st_mon = lt->tm_mon + 1; - st_day = lt->tm_mday; - st_year = lt->tm_year + 1900; - (void)fprintf (f, " !%02u/%02u/%04u", st_mon, st_day, st_year); - } + LLIST_FOREACH(lexc, i) { + struct excp *exc = LLIST_GET_DATA(i); + t = exc->st; + lt = localtime(&t); + st_mon = lt->tm_mon + 1; + st_day = lt->tm_mday; + st_year = lt->tm_year + 1900; + fprintf(f, " !%02u/%02u/%04u", st_mon, st_day, st_year); + } } /* Load the recursive appointment description */ -struct recur_apoint * -recur_apoint_scan (FILE *f, struct tm start, struct tm end, char type, - int freq, struct tm until, char *note, llist_t *exc, - char state) +struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start, struct tm end, + char type, int freq, struct tm until, + char *note, llist_t * exc, char state) { char buf[BUFSIZ], *nl; time_t tstart, tend, tuntil; /* Read the appointment description */ - (void)fgets (buf, sizeof buf, f); - nl = strchr (buf, '\n'); - if (nl) - { - *nl = '\0'; - } + if (!fgets(buf, sizeof buf, f)) + return NULL; + + nl = strchr(buf, '\n'); + if (nl) { + *nl = '\0'; + } start.tm_sec = end.tm_sec = 0; start.tm_isdst = end.tm_isdst = -1; start.tm_year -= 1900; start.tm_mon--; end.tm_year -= 1900; end.tm_mon--; - tstart = mktime (&start); - tend = mktime (&end); - - if (until.tm_year != 0) - { - until.tm_hour = 23; - until.tm_min = 59; - until.tm_sec = 0; - until.tm_isdst = -1; - until.tm_year -= 1900; - until.tm_mon--; - tuntil = mktime (&until); - } - else - { - tuntil = 0; - } - EXIT_IF (tstart == -1 || tend == -1 || tstart > tend || tuntil == -1, - _("date error in appointment")); - - return (recur_apoint_new (buf, note, tstart, tend - tstart, state, - recur_char2def (type), freq, tuntil, exc)); + tstart = mktime(&start); + tend = mktime(&end); + + if (until.tm_year != 0) { + until.tm_hour = 23; + until.tm_min = 59; + until.tm_sec = 0; + until.tm_isdst = -1; + until.tm_year -= 1900; + until.tm_mon--; + tuntil = mktime(&until); + } else { + tuntil = 0; + } + EXIT_IF(tstart == -1 || tend == -1 || tstart > tend || tuntil == -1, + _("date error in appointment")); + + 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 * -recur_event_scan (FILE *f, struct tm start, int id, char type, int freq, - struct tm until, char *note, llist_t *exc) +struct recur_event *recur_event_scan(FILE * f, struct tm start, int id, + char type, int freq, struct tm until, + char *note, llist_t * exc) { char buf[BUFSIZ], *nl; time_t tstart, tuntil; /* Read the event description */ - (void)fgets (buf, sizeof buf, f); - nl = strchr (buf, '\n'); - if (nl) - { - *nl = '\0'; - } - start.tm_hour = until.tm_hour = 12; + if (!fgets(buf, sizeof buf, f)) + return NULL; + + nl = strchr(buf, '\n'); + if (nl) { + *nl = '\0'; + } + start.tm_hour = until.tm_hour = 0; start.tm_min = until.tm_min = 0; start.tm_sec = until.tm_sec = 0; start.tm_isdst = until.tm_isdst = -1; start.tm_year -= 1900; start.tm_mon--; - if (until.tm_year != 0) - { - until.tm_year -= 1900; - until.tm_mon--; - tuntil = mktime (&until); - } - else - { - tuntil = 0; - } - tstart = mktime (&start); - EXIT_IF (tstart == -1 || tuntil == -1, - _("date error in event")); - - return recur_event_new (buf, note, tstart, id, recur_char2def (type), - freq, tuntil, exc); + if (until.tm_year != 0) { + until.tm_year -= 1900; + until.tm_mon--; + tuntil = mktime(&until); + } else { + tuntil = 0; + } + tstart = mktime(&start); + EXIT_IF(tstart == -1 || tuntil == -1, _("date error in event")); + + return recur_event_new(buf, note, tstart, id, recur_char2def(type), freq, + tuntil, exc); } /* Writting of a recursive appointment into file. */ -static void -recur_apoint_write (struct recur_apoint *o, FILE *f) +void recur_apoint_write(struct recur_apoint *o, FILE * f) { struct tm *lt; time_t t; t = o->start; - lt = localtime (&t); - (void)fprintf (f, "%02u/%02u/%04u @ %02u:%02u", - lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, - lt->tm_hour, lt->tm_min); + lt = localtime(&t); + fprintf(f, "%02u/%02u/%04u @ %02u:%02u", lt->tm_mon + 1, lt->tm_mday, + 1900 + lt->tm_year, lt->tm_hour, lt->tm_min); t = o->start + o->dur; - lt = localtime (&t); - (void)fprintf (f, " -> %02u/%02u/%04u @ %02u:%02u", - lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, - lt->tm_hour, lt->tm_min); + lt = localtime(&t); + fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u", lt->tm_mon + 1, lt->tm_mday, + 1900 + lt->tm_year, lt->tm_hour, lt->tm_min); t = o->rpt->until; - if (t == 0) - { /* We have an endless recurrent appointment. */ - (void)fprintf (f, " {%d%c", o->rpt->freq, recur_def2char (o->rpt->type)); - } - else - { - lt = localtime (&t); - (void)fprintf (f, " {%d%c -> %02u/%02u/%04u", - o->rpt->freq, recur_def2char (o->rpt->type), - lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year); - } - recur_write_exc (&o->exc, f); - (void)fprintf (f, "} "); + if (t == 0) { /* We have an endless recurrent appointment. */ + fprintf(f, " {%d%c", o->rpt->freq, recur_def2char(o->rpt->type)); + } else { + lt = localtime(&t); + fprintf(f, " {%d%c -> %02u/%02u/%04u", o->rpt->freq, + recur_def2char(o->rpt->type), lt->tm_mon + 1, lt->tm_mday, + 1900 + lt->tm_year); + } + recur_write_exc(&o->exc, f); + fputs("} ", f); if (o->note != NULL) - (void)fprintf (f, ">%s ", o->note); + fprintf(f, ">%s ", o->note); if (o->state & APOINT_NOTIFY) - (void)fprintf (f, "!"); + fputc('!', f); else - (void)fprintf (f, "|"); - (void)fprintf (f, "%s\n", o->mesg); + fputc('|', f); + fprintf(f, "%s\n", o->mesg); } /* Writting of a recursive event into file. */ -static void -recur_event_write (struct recur_event *o, FILE *f) +void recur_event_write(struct recur_event *o, FILE * f) { struct tm *lt; time_t t; @@ -501,61 +457,52 @@ recur_event_write (struct recur_event *o, FILE *f) int end_mon, end_day, end_year; t = o->day; - lt = localtime (&t); + lt = localtime(&t); st_mon = lt->tm_mon + 1; st_day = lt->tm_mday; st_year = lt->tm_year + 1900; t = o->rpt->until; - if (t == 0) - { /* We have an endless recurrent event. */ - (void)fprintf (f, "%02u/%02u/%04u [%d] {%d%c", - st_mon, st_day, st_year, o->id, o->rpt->freq, - recur_def2char (o->rpt->type)); - } - else - { - lt = localtime (&t); - end_mon = lt->tm_mon + 1; - end_day = lt->tm_mday; - end_year = lt->tm_year + 1900; - (void)fprintf (f, "%02u/%02u/%04u [%d] {%d%c -> %02u/%02u/%04u", - st_mon, st_day, st_year, o->id, - o->rpt->freq, recur_def2char (o->rpt->type), - end_mon, end_day, end_year); - } - recur_write_exc (&o->exc, f); - (void)fprintf (f, "} "); + if (t == 0) { /* We have an endless recurrent event. */ + fprintf(f, "%02u/%02u/%04u [%d] {%d%c", st_mon, st_day, st_year, o->id, + o->rpt->freq, recur_def2char(o->rpt->type)); + } else { + lt = localtime(&t); + end_mon = lt->tm_mon + 1; + end_day = lt->tm_mday; + end_year = lt->tm_year + 1900; + fprintf(f, "%02u/%02u/%04u [%d] {%d%c -> %02u/%02u/%04u", st_mon, + st_day, st_year, o->id, o->rpt->freq, + recur_def2char(o->rpt->type), end_mon, end_day, end_year); + } + recur_write_exc(&o->exc, f); + fputs("} ", f); if (o->note != NULL) - (void)fprintf (f, ">%s ", o->note); - (void)fprintf (f, "%s\n", o->mesg); + 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) { llist_item_t *i; - LLIST_FOREACH (&recur_elist, i) - { - struct recur_event *rev = LLIST_GET_DATA (i); - recur_event_write (rev, f); - } - - LLIST_TS_LOCK (&recur_alist_p); - LLIST_TS_FOREACH (&recur_alist_p, i) - { - struct recur_apoint *rapt = LLIST_GET_DATA (i); - recur_apoint_write (rapt, f); - } - LLIST_TS_UNLOCK (&recur_alist_p); + LLIST_FOREACH(&recur_elist, i) { + struct recur_event *rev = LLIST_GET_DATA(i); + recur_event_write(rev, f); + } + + LLIST_TS_LOCK(&recur_alist_p); + LLIST_TS_FOREACH(&recur_alist_p, i) { + struct recur_apoint *rapt = LLIST_GET_DATA(i); + recur_apoint_write(rapt, f); + } + LLIST_TS_UNLOCK(&recur_alist_p); } - /* - * The two following defines together with the diff_days, diff_weeks, - * diff_months and diff_years functions were provided by Lukas Fleischer to - * correct the wrong calculation of recurrent dates after a turn of year. + * The two following defines together with the diff_days, diff_months and + * diff_years functions were provided by Lukas Fleischer to correct the wrong + * calculation of recurrent dates after a turn of year. */ #define BC(start, end, bs) \ (((end) - (start) + ((start) % bs) - ((end) % bs)) / bs \ @@ -564,10 +511,8 @@ recur_save_data (FILE *f) #define LEAPCOUNT(start, end) \ (BC(start, end, 4) - BC(start, end, 100) + BC(start, end, 400)) - /* Calculate the difference in days between two dates. */ -static long -diff_days (struct tm lt_start, struct tm lt_end) +static long diff_days(struct tm lt_start, struct tm lt_end) { long diff; @@ -576,26 +521,17 @@ diff_days (struct tm lt_start, struct tm lt_end) diff = lt_end.tm_yday - lt_start.tm_yday; - if (lt_end.tm_year > lt_start.tm_year) - { - diff += (lt_end.tm_year - lt_start.tm_year) * YEARINDAYS; - diff += LEAPCOUNT (lt_start.tm_year + TM_YEAR_BASE, - lt_end.tm_year + TM_YEAR_BASE - 1); - } + if (lt_end.tm_year > lt_start.tm_year) { + diff += (lt_end.tm_year - lt_start.tm_year) * YEARINDAYS; + diff += LEAPCOUNT(lt_start.tm_year + TM_YEAR_BASE, + lt_end.tm_year + TM_YEAR_BASE - 1); + } return diff; } -/* Calculate the difference in weeks between two dates. */ -static long -diff_weeks (struct tm lt_start, struct tm lt_end) -{ - return diff_days (lt_start, lt_end) / WEEKINDAYS; -} - /* Calculate the difference in months between two dates. */ -static long -diff_months (struct tm lt_start, struct tm lt_end) +static long diff_months(struct tm lt_start, struct tm lt_end) { long diff; @@ -609,21 +545,19 @@ diff_months (struct tm lt_start, struct tm lt_end) } /* Calculate the difference in years between two dates. */ -static long -diff_years (struct tm lt_start, struct tm lt_end) +static long diff_years(struct tm lt_start, struct tm lt_end) { return lt_end.tm_year - lt_start.tm_year; } -static int -exc_inday (struct excp *exc, long day_start) +static int exc_inday(struct excp *exc, long day_start) { return (exc->st >= day_start && exc->st < day_start + DAYINSEC); } /* - * Check if the recurrent item belongs to the selected day, - * and if yes, return the real start time. + * Check if the recurrent item belongs to the selected day, and if yes, store + * the start date of the occurrence that belongs to the day in a buffer. * * This function was improved thanks to Tony's patch. * Thanks also to youshe for reporting daylight saving time related problems. @@ -631,92 +565,129 @@ exc_inday (struct excp *exc, long day_start) * calculation of recurrent dates after a turn of years. */ unsigned -recur_item_inday (long item_start, llist_t *item_exc, int rpt_type, - int rpt_freq, long rpt_until, long day_start) +recur_item_find_occurrence(long item_start, long item_dur, llist_t * item_exc, + int rpt_type, int rpt_freq, long rpt_until, + long day_start, unsigned *occurrence) { struct date start_date; - long day_end, diff; - struct tm lt_item, lt_day; + long diff, span; + struct tm lt_day, lt_item, lt_item_day; time_t t; - day_end = day_start + DAYINSEC; + if (day_start < item_start - DAYINSEC + 1) + return 0; + + if (rpt_until != 0 && day_start >= rpt_until + item_dur) + return 0; + t = day_start; - lt_day = *localtime (&t); + lt_day = *localtime(&t); - if (LLIST_FIND_FIRST (item_exc, day_start, exc_inday)) + t = item_start; + lt_item = *localtime(&t); + + lt_item_day = lt_item; + lt_item_day.tm_sec = lt_item_day.tm_min = lt_item_day.tm_hour = 0; + + span = (item_start - mktime(<_item_day) + item_dur - 1) / DAYINSEC; + + switch (rpt_type) { + case RECUR_DAILY: + diff = diff_days(lt_item_day, lt_day) % rpt_freq; + lt_item_day.tm_mday = lt_day.tm_mday - diff; + lt_item_day.tm_mon = lt_day.tm_mon; + lt_item_day.tm_year = lt_day.tm_year; + break; + case RECUR_WEEKLY: + diff = diff_days(lt_item_day, lt_day) % (rpt_freq * WEEKINDAYS); + lt_item_day.tm_mday = lt_day.tm_mday - diff; + lt_item_day.tm_mon = lt_day.tm_mon; + lt_item_day.tm_year = lt_day.tm_year; + break; + case RECUR_MONTHLY: + diff = diff_months(lt_item_day, lt_day) % rpt_freq; + if (lt_day.tm_mday < lt_item_day.tm_mday) + diff++; + lt_item_day.tm_mon = lt_day.tm_mon - diff; + lt_item_day.tm_year = lt_day.tm_year; + break; + case RECUR_YEARLY: + diff = diff_years(lt_item_day, lt_day) % rpt_freq; + if (lt_day.tm_mon < lt_item_day.tm_mon || + (lt_day.tm_mon == lt_item_day.tm_mon && + lt_day.tm_mday < lt_item_day.tm_mday)) + diff++; + lt_item_day.tm_year = lt_day.tm_year - diff; + break; + default: + EXIT(_("unknown item type")); + } + + lt_item_day.tm_isdst = lt_day.tm_isdst; + t = mktime(<_item_day); + + if (LLIST_FIND_FIRST(item_exc, t, exc_inday)) return 0; - if (rpt_until == 0) /* we have an endless recurrent item */ - rpt_until = day_end; + if (rpt_until != 0 && t > rpt_until) + return 0; - if (item_start > day_end || rpt_until < day_start) - return (0); + lt_item_day = *localtime(&t); + diff = diff_days(lt_item_day, lt_day); - t = item_start; - lt_item = *localtime (&t); - - switch (rpt_type) - { - case RECUR_DAILY: - diff = diff_days (lt_item, lt_day); - if (diff % rpt_freq != 0) - return (0); - lt_item.tm_mday = lt_day.tm_mday; - lt_item.tm_mon = lt_day.tm_mon; - lt_item.tm_year = lt_day.tm_year; - break; - case RECUR_WEEKLY: - if (lt_item.tm_wday != lt_day.tm_wday) - return (0); - else - { - diff = diff_weeks (lt_item, lt_day); - if (diff % rpt_freq != 0) - return (0); - } - lt_item.tm_mday = lt_day.tm_mday; - lt_item.tm_mon = lt_day.tm_mon; - lt_item.tm_year = lt_day.tm_year; - break; - case RECUR_MONTHLY: - diff = diff_months (lt_item, lt_day); - if (diff % rpt_freq != 0) - return (0); - lt_item.tm_mon = lt_day.tm_mon; - lt_item.tm_year = lt_day.tm_year; - break; - case RECUR_YEARLY: - diff = diff_years (lt_item, lt_day); - if (diff % rpt_freq != 0) - return (0); - lt_item.tm_year = lt_day.tm_year; - break; - default: - EXIT (_("unknown item type")); + if (diff <= span) { + if (occurrence) { + start_date.dd = lt_item_day.tm_mday; + start_date.mm = lt_item_day.tm_mon + 1; + start_date.yyyy = lt_item_day.tm_year + 1900; + + *occurrence = date2sec(start_date, lt_item.tm_hour, lt_item.tm_min); } - start_date.dd = lt_item.tm_mday; - start_date.mm = lt_item.tm_mon + 1; - start_date.yyyy = lt_item.tm_year + 1900; - item_start = date2sec (start_date, lt_item.tm_hour, lt_item.tm_min); - if (item_start < day_end && item_start >= day_start) - return (item_start); - else - return (0); + return 1; + } else + return 0; +} + +unsigned +recur_apoint_find_occurrence(struct recur_apoint *rapt, long day_start, + unsigned *occurrence) +{ + return recur_item_find_occurrence(rapt->start, rapt->dur, &rapt->exc, + rapt->rpt->type, rapt->rpt->freq, + rapt->rpt->until, day_start, occurrence); } unsigned -recur_apoint_inday(struct recur_apoint *rapt, long day_start) +recur_event_find_occurrence(struct recur_event *rev, long day_start, + unsigned *occurrence) { - return recur_item_inday (rapt->start, &rapt->exc, rapt->rpt->type, - rapt->rpt->freq, rapt->rpt->until, day_start); + return recur_item_find_occurrence(rev->day, DAYINSEC, &rev->exc, + rev->rpt->type, rev->rpt->freq, + rev->rpt->until, day_start, occurrence); } +/* Check if a recurrent item belongs to the selected day. */ unsigned -recur_event_inday(struct recur_event *rev, long day_start) +recur_item_inday(long item_start, long item_dur, llist_t * item_exc, + int rpt_type, int rpt_freq, long rpt_until, long day_start) +{ + /* We do not need the (real) start time of the occurrence here, so just + * ignore the buffer. */ + return recur_item_find_occurrence(item_start, item_dur, item_exc, rpt_type, + rpt_freq, rpt_until, day_start, NULL); +} + +unsigned recur_apoint_inday(struct recur_apoint *rapt, long day_start) +{ + return recur_item_inday(rapt->start, rapt->dur, &rapt->exc, rapt->rpt->type, + rapt->rpt->freq, rapt->rpt->until, day_start); +} + +unsigned recur_event_inday(struct recur_event *rev, long day_start) { - return recur_item_inday (rev->day, &rev->exc, rev->rpt->type, rev->rpt->freq, - rev->rpt->until, day_start); + return recur_item_inday(rev->day, DAYINSEC, &rev->exc, rev->rpt->type, + rev->rpt->freq, rev->rpt->until, day_start); } /* @@ -724,46 +695,40 @@ recur_event_inday(struct recur_event *rev, long day_start) * or delete only one occurence of the recurrent event. */ void -recur_event_erase (long start, unsigned num, unsigned delete_whole, - enum eraseflg flag) +recur_event_erase(long start, unsigned num, unsigned delete_whole, + enum eraseflg flag) { llist_item_t *i; - i = LLIST_FIND_NTH (&recur_elist, num, start, recur_event_inday); + i = LLIST_FIND_NTH(&recur_elist, num, start, recur_event_inday); if (!i) - EXIT (_("event not found")); - struct recur_event *rev = LLIST_GET_DATA (i); - - if (delete_whole) - { - switch (flag) - { - case ERASE_FORCE_ONLY_NOTE: - erase_note (&rev->note, flag); - break; - case ERASE_CUT: - recur_event_free_bkp (ERASE_FORCE); - recur_event_dup (rev, &bkp_cut_recur_event); - erase_note (&rev->note, ERASE_FORCE_KEEP_NOTE); - /* FALLTHROUGH */ - default: - LLIST_REMOVE (&recur_elist, i); - mem_free (rev->mesg); - if (rev->rpt) - { - mem_free (rev->rpt); - rev->rpt = 0; - } - free_exc_list (&rev->exc); - if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT) - erase_note (&rev->note, flag); - mem_free (rev); - break; - } + EXIT(_("event not found")); + struct recur_event *rev = LLIST_GET_DATA(i); + + if (delete_whole) { + switch (flag) { + case ERASE_FORCE_ONLY_NOTE: + erase_note(&rev->note); + break; + case ERASE_CUT: + recur_event_free_bkp(); + recur_event_dup(rev, &bkp_cut_recur_event); + erase_note(&rev->note); + /* FALLTHROUGH */ + default: + LLIST_REMOVE(&recur_elist, i); + mem_free(rev->mesg); + if (rev->rpt) { + mem_free(rev->rpt); + rev->rpt = 0; + } + free_exc_list(&rev->exc); + mem_free(rev); + break; } - else - recur_add_exc (&rev->exc, start); + } else + recur_add_exc(&rev->exc, start); } /* @@ -771,57 +736,50 @@ recur_event_erase (long start, unsigned num, unsigned delete_whole, * or delete only one occurence of the recurrent appointment. */ void -recur_apoint_erase (long start, unsigned num, unsigned delete_whole, - enum eraseflg flag) +recur_apoint_erase(long start, unsigned num, unsigned delete_whole, + enum eraseflg flag) { llist_item_t *i; int need_check_notify = 0; - i = LLIST_TS_FIND_NTH (&recur_alist_p, num, start, recur_apoint_inday); + i = LLIST_TS_FIND_NTH(&recur_alist_p, num, start, recur_apoint_inday); if (!i) - EXIT (_("appointment not found")); - struct recur_apoint *rapt = LLIST_GET_DATA (i); - - LLIST_TS_LOCK (&recur_alist_p); - if (notify_bar () && flag != ERASE_FORCE_ONLY_NOTE) - need_check_notify = notify_same_recur_item (rapt); - if (delete_whole) - { - switch (flag) - { - case ERASE_FORCE_ONLY_NOTE: - erase_note (&rapt->note, flag); - break; - case ERASE_CUT: - recur_apoint_free_bkp (ERASE_FORCE); - recur_apoint_dup (rapt, &bkp_cut_recur_apoint); - erase_note (&rapt->note, ERASE_FORCE_KEEP_NOTE); - /* FALLTHROUGH */ - default: - LLIST_TS_REMOVE (&recur_alist_p, i); - mem_free (rapt->mesg); - if (rapt->rpt) - { - mem_free (rapt->rpt); - rapt->rpt = 0; - } - free_exc_list (&rapt->exc); - if (flag != ERASE_FORCE_KEEP_NOTE && flag != ERASE_CUT) - erase_note (&rapt->note, flag); - mem_free (rapt); - if (need_check_notify) - notify_check_next_app (0); - break; - } - } - else - { - recur_add_exc (&rapt->exc, start); + EXIT(_("appointment not found")); + struct recur_apoint *rapt = LLIST_GET_DATA(i); + + LLIST_TS_LOCK(&recur_alist_p); + if (notify_bar() && flag != ERASE_FORCE_ONLY_NOTE) + need_check_notify = notify_same_recur_item(rapt); + if (delete_whole) { + switch (flag) { + case ERASE_FORCE_ONLY_NOTE: + erase_note(&rapt->note); + break; + case ERASE_CUT: + recur_apoint_free_bkp(); + recur_apoint_dup(rapt, &bkp_cut_recur_apoint); + erase_note(&rapt->note); + /* FALLTHROUGH */ + default: + LLIST_TS_REMOVE(&recur_alist_p, i); + mem_free(rapt->mesg); + if (rapt->rpt) { + mem_free(rapt->rpt); + rapt->rpt = 0; + } + free_exc_list(&rapt->exc); + mem_free(rapt); if (need_check_notify) - notify_check_next_app (0); + notify_check_next_app(0); + break; } - LLIST_TS_UNLOCK (&recur_alist_p); + } else { + recur_add_exc(&rapt->exc, start); + if (need_check_notify) + notify_check_next_app(0); + } + LLIST_TS_UNLOCK(&recur_alist_p); } /* @@ -831,319 +789,289 @@ recur_apoint_erase (long start, unsigned num, unsigned delete_whole, * o repetition end date * and then delete the selected item to recreate it as a recurrent one */ -void -recur_repeat_item (struct conf *conf) +void recur_repeat_item(void) { struct tm *lt; time_t t; - int ch = 0; int date_entered = 0; int year = 0, month = 0, day = 0; struct date until_date; char outstr[BUFSIZ]; char user_input[BUFSIZ] = ""; - char *mesg_type_1 = - _("Enter the repetition type: (D)aily, (W)eekly, (M)onthly, (Y)early"); - char *mesg_type_2 = _("[D/W/M/Y] "); - char *mesg_freq_1 = _("Enter the repetition frequence:"); - char *mesg_wrong_freq = _("The frequence you entered is not valid."); - char *mesg_until_1 = - _("Enter the ending date: [%s] or '0' for an endless repetition"); - char *mesg_wrong_1 = _("The entered date is not valid."); - char *mesg_wrong_2 = - _("Possible formats are [%s] or '0' for an endless repetition"); - char *wrong_type_1 = _("This item is already a repeated one."); - char *wrong_type_2 = _("Press [ENTER] to continue."); - char *mesg_older = - _("Sorry, the date you entered is older than the item start time."); + const char *msg_rpt_prefix = _("Enter the repetition type:"); + const char *msg_rpt_daily = _("(d)aily"); + const char *msg_rpt_weekly = _("(w)eekly"); + const char *msg_rpt_monthly = _("(m)onthly"); + const char *msg_rpt_yearly = _("(y)early"); + const char *msg_type_choice = _("[dwmy]"); + const char *mesg_freq_1 = _("Enter the repetition frequence:"); + const char *mesg_wrong_freq = _("The frequence you entered is not valid."); + const char *mesg_until_1 = + _("Enter the ending date: [%s] or '0' for an endless repetition"); + const char *mesg_wrong_1 = _("The entered date is not valid."); + const char *mesg_wrong_2 = + _("Possible formats are [%s] or '0' for an endless repetition"); + const char *wrong_type_1 = _("This item is already a repeated one."); + const char *wrong_type_2 = _("Press [ENTER] to continue."); + const char *mesg_older = + _("Sorry, the date you entered is older than the item start time."); + + char msg_asktype[BUFSIZ]; + snprintf(msg_asktype, BUFSIZ, "%s %s, %s, %s, %s", + msg_rpt_prefix, + msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly, msg_rpt_yearly); + int type = 0, freq = 0; int item_nb; struct day_item *p; struct recur_apoint *ra; long until, date; - item_nb = apoint_hilt (); - p = day_get_item (item_nb); - if (p->type != APPT && p->type != EVNT) - { - status_mesg (wrong_type_1, wrong_type_2); - (void)wgetch (win[STA].p); - return; - } - - while ((ch != 'D') && (ch != 'W') && (ch != 'M') - && (ch != 'Y') && (ch != ESCAPE)) - { - status_mesg (mesg_type_1, mesg_type_2); - ch = wgetch (win[STA].p); - ch = toupper (ch); - } - if (ch == ESCAPE) - { + item_nb = apoint_hilt(); + p = day_get_item(item_nb); + if (p->type != APPT && p->type != EVNT) { + status_mesg(wrong_type_1, wrong_type_2); + wgetch(win[STA].p); + return; + } + + switch (status_ask_choice(msg_asktype, msg_type_choice, 4)) { + case 1: + type = RECUR_DAILY; + break; + case 2: + type = RECUR_WEEKLY; + break; + case 3: + type = RECUR_MONTHLY; + break; + case 4: + type = RECUR_YEARLY; + break; + default: + return; + } + + while (freq == 0) { + status_mesg(mesg_freq_1, ""); + if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_VALID) { + freq = atoi(user_input); + if (freq == 0) { + status_mesg(mesg_wrong_freq, wrong_type_2); + wgetch(win[STA].p); + } + user_input[0] = '\0'; + } else return; - } - else - { - type = recur_char2def (ch); - } - - while (freq == 0) - { - status_mesg (mesg_freq_1, ""); - if (getstring (win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_VALID) - { - freq = atoi (user_input); - if (freq == 0) - { - status_mesg (mesg_wrong_freq, wrong_type_2); - (void)wgetch (win[STA].p); - } - user_input[0] = '\0'; + } + + while (!date_entered) { + snprintf(outstr, BUFSIZ, mesg_until_1, DATEFMT_DESC(conf.input_datefmt)); + status_mesg(_(outstr), ""); + if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_VALID) { + if (strlen(user_input) == 1 && strcmp(user_input, "0") == 0) { + until = 0; + date_entered = 1; + } else { + if (parse_date(user_input, conf.input_datefmt, + &year, &month, &day, calendar_get_slctd_day())) { + t = p->start; + lt = localtime(&t); + until_date.dd = day; + until_date.mm = month; + until_date.yyyy = year; + until = date2sec(until_date, lt->tm_hour, lt->tm_min); + if (until < p->start) { + status_mesg(mesg_older, wrong_type_2); + wgetch(win[STA].p); + date_entered = 0; + } else { + date_entered = 1; + } + } else { + snprintf(outstr, BUFSIZ, mesg_wrong_2, + DATEFMT_DESC(conf.input_datefmt)); + status_mesg(mesg_wrong_1, _(outstr)); + wgetch(win[STA].p); + date_entered = 0; } - else - return; - } - - while (!date_entered) - { - (void)snprintf (outstr, BUFSIZ, mesg_until_1, - DATEFMT_DESC (conf->input_datefmt)); - status_mesg (_(outstr), ""); - if (getstring (win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_VALID) - { - if (strlen (user_input) == 1 && strncmp (user_input, "0", 1) == 0) - { - until = 0; - date_entered = 1; - } - else - { - if (parse_date (user_input, conf->input_datefmt, - &year, &month, &day, calendar_get_slctd_day ())) - { - t = p->start; - lt = localtime (&t); - until_date.dd = day; - until_date.mm = month; - until_date.yyyy = year; - until = date2sec (until_date, lt->tm_hour, lt->tm_min); - if (until < p->start) - { - status_mesg (mesg_older, wrong_type_2); - (void)wgetch (win[STA].p); - date_entered = 0; - } - else - { - date_entered = 1; - } - } - else - { - (void)snprintf (outstr, BUFSIZ, mesg_wrong_2, - DATEFMT_DESC (conf->input_datefmt)); - status_mesg (mesg_wrong_1, _(outstr)); - (void)wgetch (win[STA].p); - date_entered = 0; - } - } - } - else - return; - } - - date = calendar_get_slctd_day_sec (); - if (p->type == EVNT) - { - (void)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->note, p->start, p->appt_dur, - p->state, type, freq, until, NULL); - if (notify_bar ()) - notify_check_repeated (ra); - } - else - { - EXIT (_("wrong item type")); - /* NOTREACHED */ - } - day_erase_item (date, item_nb, ERASE_FORCE_KEEP_NOTE); + } + } else + return; + } + + date = calendar_get_slctd_day_sec(); + if (p->type == EVNT) { + 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->note, p->start, p->appt_dur, + p->state, type, freq, until, NULL); + if (notify_bar()) + notify_check_repeated(ra); + } else { + EXIT(_("wrong item type")); + /* NOTREACHED */ + } + day_erase_item(date, item_nb, ERASE_FORCE); } /* * Read days for which recurrent items must not be repeated * (such days are called exceptions). */ -void -recur_exc_scan (llist_t *lexc, FILE *data_file) +void recur_exc_scan(llist_t * lexc, FILE * data_file) { int c = 0; struct tm day; - LLIST_INIT (lexc); - while ((c = getc (data_file)) == '!') - { - (void)ungetc (c, data_file); - if (fscanf (data_file, "!%u / %u / %u ", - &day.tm_mon, &day.tm_mday, &day.tm_year) != 3) - { - EXIT (_("syntax error in item date")); - } - day.tm_hour = 12; - day.tm_min = day.tm_sec = 0; - day.tm_isdst = -1; - day.tm_year -= 1900; - day.tm_mon--; - struct excp *exc = mem_malloc (sizeof (struct excp)); - exc->st = mktime (&day); - LLIST_ADD (lexc, exc); + LLIST_INIT(lexc); + while ((c = getc(data_file)) == '!') { + ungetc(c, data_file); + if (fscanf(data_file, "!%d / %d / %d ", + &day.tm_mon, &day.tm_mday, &day.tm_year) != 3) { + EXIT(_("syntax error in item date")); } + day.tm_hour = 0; + day.tm_min = day.tm_sec = 0; + day.tm_isdst = -1; + day.tm_year -= 1900; + day.tm_mon--; + struct excp *exc = mem_malloc(sizeof(struct excp)); + exc->st = mktime(&day); + LLIST_ADD(lexc, exc); + } } -static int -recur_apoint_starts_before (struct recur_apoint *rapt, long time) +static int recur_apoint_starts_before(struct recur_apoint *rapt, long time) { - return (rapt->start < time); + return rapt->start < time; } /* * Look in the appointment list if we have an item which starts before the item * stored in the notify_app structure (which is the next item to be notified). */ -struct notify_app * -recur_apoint_check_next (struct notify_app *app, long start, long day) +struct notify_app *recur_apoint_check_next(struct notify_app *app, long start, + long day) { llist_item_t *i; - long real_recur_start_time; - - LLIST_TS_LOCK (&recur_alist_p); - LLIST_TS_FIND_FOREACH (&recur_alist_p, app->time, recur_apoint_starts_before, i) - { - struct recur_apoint *rapt = LLIST_TS_GET_DATA (i); - - real_recur_start_time = recur_apoint_inday(rapt, day); - if (real_recur_start_time > start) - { - app->time = real_recur_start_time; - app->txt = mem_strdup (rapt->mesg); - app->state = rapt->state; - app->got_app = 1; - } + unsigned real_recur_start_time; + + LLIST_TS_LOCK(&recur_alist_p); + LLIST_TS_FIND_FOREACH(&recur_alist_p, app->time, recur_apoint_starts_before, + i) { + struct recur_apoint *rapt = LLIST_TS_GET_DATA(i); + + if (recur_apoint_find_occurrence(rapt, day, &real_recur_start_time) && + real_recur_start_time > start) { + app->time = real_recur_start_time; + app->txt = mem_strdup(rapt->mesg); + app->state = rapt->state; + app->got_app = 1; } - LLIST_TS_UNLOCK (&recur_alist_p); + } + LLIST_TS_UNLOCK(&recur_alist_p); - return (app); + return app; } /* Returns a structure containing the selected recurrent appointment. */ -struct recur_apoint * -recur_get_apoint (long date, int num) +struct recur_apoint *recur_get_apoint(long date, int num) { - llist_item_t *i = LLIST_TS_FIND_NTH (&recur_alist_p, num, date, + llist_item_t *i = LLIST_TS_FIND_NTH(&recur_alist_p, num, date, recur_apoint_inday); if (i) - return LLIST_TS_GET_DATA (i); + return LLIST_TS_GET_DATA(i); - EXIT (_("item not found")); + EXIT(_("item not found")); /* NOTREACHED */ } /* Returns a structure containing the selected recurrent event. */ -struct recur_event * -recur_get_event (long date, int num) +struct recur_event *recur_get_event(long date, int num) { - llist_item_t *i = LLIST_FIND_NTH (&recur_elist, num, date, - recur_event_inday); + llist_item_t *i = LLIST_FIND_NTH(&recur_elist, num, date, + recur_event_inday); if (i) - return LLIST_GET_DATA (i); + return LLIST_GET_DATA(i); - EXIT (_("item not found")); + EXIT(_("item not found")); /* NOTREACHED */ } /* Switch recurrent item notification state. */ -void -recur_apoint_switch_notify (long date, int recur_nb) +void recur_apoint_switch_notify(long date, int recur_nb) { llist_item_t *i; - LLIST_TS_LOCK (&recur_alist_p); - i = LLIST_TS_FIND_NTH (&recur_alist_p, recur_nb, date, recur_apoint_inday); + LLIST_TS_LOCK(&recur_alist_p); + i = LLIST_TS_FIND_NTH(&recur_alist_p, recur_nb, date, recur_apoint_inday); if (!i) - EXIT (_("item not found")); - struct recur_apoint *rapt = LLIST_TS_GET_DATA (i); + EXIT(_("item not found")); + struct recur_apoint *rapt = LLIST_TS_GET_DATA(i); rapt->state ^= APOINT_NOTIFY; - if (notify_bar ()) - notify_check_repeated (rapt); + if (notify_bar()) + notify_check_repeated(rapt); - LLIST_TS_UNLOCK (&recur_alist_p); + LLIST_TS_UNLOCK(&recur_alist_p); } -void -recur_event_paste_item (void) +void recur_event_paste_item(void) { long new_start, time_shift; llist_item_t *i; - new_start = date2sec (*calendar_get_slctd_day (), 12, 0); + new_start = date2sec(*calendar_get_slctd_day(), 0, 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; - LLIST_FOREACH (&bkp_cut_recur_event.exc, i) - { - struct excp *exc = LLIST_GET_DATA (i); - 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 (ERASE_FORCE_KEEP_NOTE); + LLIST_FOREACH(&bkp_cut_recur_event.exc, i) { + struct excp *exc = LLIST_GET_DATA(i); + exc->st += time_shift; + } + + 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) +void recur_apoint_paste_item(void) { long new_start, time_shift; llist_item_t *i; - new_start = date2sec (*calendar_get_slctd_day (), - get_item_hour (bkp_cut_recur_apoint.start), - get_item_min (bkp_cut_recur_apoint.start)); + 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; - LLIST_FOREACH (&bkp_cut_recur_event.exc, i) - { - struct excp *exc = LLIST_GET_DATA (i); - exc->st += time_shift; - } + LLIST_FOREACH(&bkp_cut_recur_event.exc, i) { + struct excp *exc = LLIST_GET_DATA(i); + 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_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); - if (notify_bar ()) - notify_check_repeated (&bkp_cut_recur_apoint); + if (notify_bar()) + notify_check_repeated(&bkp_cut_recur_apoint); - recur_apoint_free_bkp (ERASE_FORCE_KEEP_NOTE); + recur_apoint_free_bkp(); } diff --git a/src/sha1.c b/src/sha1.c new file mode 100644 index 0000000..4fbf245 --- /dev/null +++ b/src/sha1.c @@ -0,0 +1,267 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + * This code is based on Steve Reid's public domain SHA1 implementation. + * + * The original version is available at: + * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c + * + */ + +#include <stdio.h> +#include <string.h> + +#include "sha1.h" + +#define rol(val, n) (((val) << (n)) | ((val) >> (32 - (n)))) + +#ifdef WORDS_BIGENDIAN +#define blk0(i) block->l[i] +#else +#define blk0(i) (block->l[i] = (rol (block->l[i], 24) & \ + (uint32_t)0xFF00FF00) | (rol (block->l[i], 8) & (uint32_t)0x00FF00FF)) +#endif + +#define blk(i) (block->l[i & 15] = rol (block->l[(i + 13) & 15] ^ \ + block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) + +#define R0(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + blk0 (i) + \ + 0x5A827999 + rol (v, 5); w = rol (w, 30); +#define R1(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + blk (i) + \ + 0x5A827999 + rol (v, 5); w = rol (w, 30); +#define R2(v, w, x, y, z, i) z += (w ^ x ^ y) + blk (i) + 0x6ED9EBA1 + \ + rol (v, 5); w = rol(w, 30); +#define R3(v, w, x, y, z, i) z += (((w | x) & y) | (w & x)) + blk (i) + \ + 0x8F1BBCDC + rol (v, 5); w = rol (w, 30); +#define R4(v, w, x, y, z, i) z += (w ^ x ^ y) + blk (i) + 0xCA62C1D6 + \ + rol (v, 5); w = rol (w, 30); + +static void sha1_transform(uint32_t state[5], const uint8_t buffer[64]) +{ + typedef union { + uint8_t c[64]; + uint32_t l[16]; + } b64_t; + + b64_t *block = (b64_t *) buffer; + uint32_t a = state[0]; + uint32_t b = state[1]; + uint32_t c = state[2]; + uint32_t d = state[3]; + uint32_t e = state[4]; + + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + a = b = c = d = e = 0; +} + +void sha1_init(sha1_ctx_t * ctx) +{ + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + ctx->count[0] = ctx->count[1] = 0; +} + +void sha1_update(sha1_ctx_t * ctx, const uint8_t * data, unsigned int len) +{ + unsigned int i, j; + + j = (ctx->count[0] >> 3) & 63; + if ((ctx->count[0] += len << 3) < (len << 3)) + ctx->count[1]++; + ctx->count[1] += (len >> 29); + + if (j + len > 63) { + memcpy(&ctx->buffer[j], data, (i = 64 - j)); + sha1_transform(ctx->state, ctx->buffer); + for (; i + 63 < len; i += 64) + sha1_transform(ctx->state, &data[i]); + j = 0; + } else + i = 0; + memcpy(&ctx->buffer[j], &data[i], len - i); +} + +void sha1_final(sha1_ctx_t * ctx, uint8_t digest[SHA1_DIGESTLEN]) +{ + uint32_t i, j; + uint8_t finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (uint8_t) ((ctx->count[(i >= 4 ? 0 : 1)] >> + ((3 - (i & 3)) * 8)) & 255); + } + + sha1_update(ctx, (uint8_t *) "\200", 1); + while ((ctx->count[0] & 504) != 448) + sha1_update(ctx, (uint8_t *) "\0", 1); + + sha1_update(ctx, finalcount, 8); + for (i = 0; i < SHA1_DIGESTLEN; i++) + digest[i] = (uint8_t) ((ctx->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + + i = j = 0; + memset(ctx->buffer, 0, SHA1_BLOCKLEN); + memset(ctx->state, 0, SHA1_DIGESTLEN); + memset(ctx->count, 0, 8); + memset(&finalcount, 0, 8); +} + +void sha1_digest(const char *data, char *buffer) +{ + sha1_ctx_t ctx; + uint8_t digest[SHA1_DIGESTLEN]; + int i; + + sha1_init(&ctx); + sha1_update(&ctx, (const uint8_t *)data, strlen(data)); + sha1_final(&ctx, (uint8_t *) digest); + + for (i = 0; i < SHA1_DIGESTLEN; i++) { + snprintf(buffer, 3, "%02x", digest[i]); + buffer += sizeof(char) * 2; + } +} + +void sha1_stream(FILE * fp, char *buffer) +{ + sha1_ctx_t ctx; + uint8_t data[BUFSIZ]; + size_t bytes_read; + uint8_t digest[SHA1_DIGESTLEN]; + int i; + + sha1_init(&ctx); + + while (!feof(fp)) { + bytes_read = fread(data, 1, BUFSIZ, fp); + sha1_update(&ctx, data, bytes_read); + } + + sha1_final(&ctx, (uint8_t *) digest); + + for (i = 0; i < SHA1_DIGESTLEN; i++) { + snprintf(buffer, 3, "%02x", digest[i]); + buffer += sizeof(char) * 2; + } +} diff --git a/src/sha1.h b/src/sha1.h new file mode 100644 index 0000000..8f90ff5 --- /dev/null +++ b/src/sha1.h @@ -0,0 +1,57 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + * This code is based on Steve Reid's public domain SHA1 implementation. + * + * The original version is available at: + * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c + * + */ + +#include <stdint.h> + +#define SHA1_BLOCKLEN 64 +#define SHA1_DIGESTLEN 20 + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + uint8_t buffer[SHA1_BLOCKLEN]; +} sha1_ctx_t; + +void sha1_init(sha1_ctx_t *); +void sha1_update(sha1_ctx_t *, const uint8_t *, unsigned int); +void sha1_final(sha1_ctx_t *, uint8_t *); +void sha1_digest(const char *, char *); +void sha1_stream(FILE *, char *); @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,63 +43,58 @@ #include "calcurse.h" +#ifndef WAIT_MYPGRP +#define WAIT_MYPGRP 0 +#endif + /* * General signal handling routine. * Catch return values from children (user-defined notification commands). * This is needed to avoid zombie processes running on system. * Also catch CTRL-C (SIGINT), and SIGWINCH to resize screen automatically. */ -static void -generic_hdlr (int sig) +static void generic_hdlr(int sig) { - switch (sig) - { - case SIGCHLD: - while (waitpid (WAIT_MYPGRP, NULL, WNOHANG) > 0) - ; - break; - case SIGWINCH: - resize = 1; - clearok (curscr, TRUE); - (void)ungetch (KEY_RESIZE); - break; - case SIGTERM: - if (unlink (path_cpid) != 0) - { - EXIT (_("Could not remove calcurse lock file: %s\n"), - strerror (errno)); - } - exit (EXIT_SUCCESS); - break; + switch (sig) { + case SIGCHLD: + while (waitpid(WAIT_MYPGRP, NULL, WNOHANG) > 0) ; + break; + case SIGWINCH: + resize = 1; + clearok(curscr, TRUE); + ungetch(KEY_RESIZE); + break; + case SIGTERM: + if (unlink(path_cpid) != 0) { + EXIT(_("Could not remove calcurse lock file: %s\n"), strerror(errno)); } + exit(EXIT_SUCCESS); + break; + } } -unsigned -sigs_set_hdlr (int sig, void (*handler)(int)) +unsigned sigs_set_hdlr(int sig, void (*handler) (int)) { struct sigaction sa; - memset (&sa, 0, sizeof sa); - sigemptyset (&sa.sa_mask); + memset(&sa, 0, sizeof sa); + sigemptyset(&sa.sa_mask); sa.sa_handler = handler; sa.sa_flags = 0; - if (sigaction (sig, &sa, (struct sigaction *)0) == -1) - { - ERROR_MSG (_("Error setting signal #%d : %s\n"), - sig, strerror (errno)); - return 0; - } + if (sigaction(sig, &sa, NULL) == -1) { + ERROR_MSG(_("Error setting signal #%d : %s\n"), sig, strerror(errno)); + return 0; + } return 1; } /* Signal handling init. */ -void -sigs_init () +void sigs_init() { - if (!sigs_set_hdlr (SIGCHLD, generic_hdlr) - || !sigs_set_hdlr (SIGWINCH, generic_hdlr) - || !sigs_set_hdlr (SIGTERM, generic_hdlr) - || !sigs_set_hdlr (SIGINT, SIG_IGN)) - exit_calcurse (1); + if (!sigs_set_hdlr(SIGCHLD, generic_hdlr) + || !sigs_set_hdlr(SIGWINCH, generic_hdlr) + || !sigs_set_hdlr(SIGTERM, generic_hdlr) + || !sigs_set_hdlr(SIGINT, SIG_IGN)) + exit_calcurse(1); } @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,171 +47,161 @@ static int first = 1; static char *msgsav; /* Returns a structure containing the selected item. */ -static struct todo * -todo_get_item (int item_number) +static struct todo *todo_get_item(int item_number) { - return LLIST_GET_DATA (LLIST_NTH (&todolist, item_number - 1)); + return LLIST_GET_DATA(LLIST_NTH(&todolist, item_number - 1)); } /* Sets which todo is highlighted. */ -void -todo_hilt_set (int highlighted) +void todo_hilt_set(int highlighted) { hilt = highlighted; } -void -todo_hilt_decrease (void) +void todo_hilt_decrease(int n) { - hilt--; + hilt -= n; } -void -todo_hilt_increase (void) +void todo_hilt_increase(int n) { - hilt++; + hilt += n; } /* Return which todo is highlighted. */ -int -todo_hilt (void) +int todo_hilt(void) { - return (hilt); + return hilt; } /* Return the number of todos. */ -int -todo_nb (void) +int todo_nb(void) { - return (todos); + return todos; } /* Set the number of todos. */ -void -todo_set_nb (int nb) +void todo_set_nb(int nb) { todos = nb; } /* Set which one is the first todo to be displayed. */ -void -todo_set_first (int nb) +void todo_set_first(int nb) { first = nb; } -void -todo_first_increase (void) +void todo_first_increase(int n) { - first++; + first += n; } -void -todo_first_decrease (void) +void todo_first_decrease(int n) { - first--; + first -= n; } /* * Return the position of the hilghlighted item, relative to the first one * displayed. */ -int -todo_hilt_pos (void) +int todo_hilt_pos(void) { - return (hilt - first); + return hilt - first; } /* Return the last visited todo. */ -char * -todo_saved_mesg (void) +char *todo_saved_mesg(void) { - return (msgsav); + return msgsav; } /* Request user to enter a new todo item. */ -void -todo_new_item (void) +void todo_new_item(void) { int ch = 0; - char *mesg = _("Enter the new ToDo item : "); - char *mesg_id = _("Enter the ToDo priority [1 (highest) - 9 (lowest)] :"); + const char *mesg = _("Enter the new ToDo item : "); + const char *mesg_id = + _("Enter the ToDo priority [1 (highest) - 9 (lowest)] :"); char todo_input[BUFSIZ] = ""; - status_mesg (mesg, ""); - if (getstring (win[STA].p, todo_input, BUFSIZ, 0, 1) == GETSTRING_VALID) - { - while ((ch < '1') || (ch > '9')) - { - status_mesg (mesg_id, ""); - ch = wgetch (win[STA].p); - } - todo_add (todo_input, ch - '0', NULL); - todos++; + status_mesg(mesg, ""); + if (getstring(win[STA].p, todo_input, BUFSIZ, 0, 1) == GETSTRING_VALID) { + while ((ch < '1') || (ch > '9')) { + status_mesg(mesg_id, ""); + ch = wgetch(win[STA].p); } + todo_add(todo_input, ch - '0', NULL); + todos++; + } } -static int -todo_cmp_id (struct todo *a, struct todo *b) +static int todo_cmp_id(struct todo *a, struct todo *b) { /* * As of version 2.6, todo items can have a negative id, which means they * were completed. To keep them sorted, we need to consider the absolute id * value. */ - int abs_a = abs (a->id); - int abs_b = abs (b->id); + int abs_a = abs(a->id); + int abs_b = abs(b->id); - return (abs_a < abs_b ? -1 : (abs_a == abs_b ? 0 : 1)); + return abs_a < abs_b ? -1 : (abs_a == abs_b ? 0 : 1); } /* * Add an item in the todo linked list. */ -struct todo * -todo_add (char *mesg, int id, char *note) +struct todo *todo_add(char *mesg, int id, char *note) { struct todo *todo; - todo = mem_malloc (sizeof (struct todo)); - todo->mesg = mem_strdup (mesg); + todo = mem_malloc(sizeof(struct todo)); + todo->mesg = mem_strdup(mesg); todo->id = id; - todo->note = (note != NULL && note[0] != '\0') ? mem_strdup (note) : NULL; + todo->note = (note != NULL && note[0] != '\0') ? mem_strdup(note) : NULL; - LLIST_ADD_SORTED (&todolist, todo, todo_cmp_id); + LLIST_ADD_SORTED(&todolist, todo, todo_cmp_id); return todo; } +void todo_write(struct todo *todo, FILE * f) +{ + if (todo->note) + fprintf(f, "[%d]>%s %s\n", todo->id, todo->note, todo->mesg); + else + fprintf(f, "[%d] %s\n", todo->id, todo->mesg); +} + /* Delete a note previously attached to a todo item. */ -static void -todo_delete_note_bynum (unsigned num) +static void todo_delete_note_bynum(unsigned num) { - llist_item_t *i = LLIST_NTH (&todolist, num); + llist_item_t *i = LLIST_NTH(&todolist, num); if (!i) - EXIT (_("no such todo")); - struct todo *todo = LLIST_TS_GET_DATA (i); + EXIT(_("no such todo")); + struct todo *todo = LLIST_TS_GET_DATA(i); if (!todo->note) - EXIT (_("no note attached")); - erase_note (&todo->note, ERASE_FORCE_ONLY_NOTE); + EXIT(_("no note attached")); + erase_note(&todo->note); } /* Delete an item from the todo linked list. */ -static void -todo_delete_bynum (unsigned num, enum eraseflg flag) +static void todo_delete_bynum(unsigned num) { - llist_item_t *i = LLIST_NTH (&todolist, num); + llist_item_t *i = LLIST_NTH(&todolist, num); if (!i) - EXIT (_("no such todo")); - struct todo *todo = LLIST_TS_GET_DATA (i); + EXIT(_("no such todo")); + struct todo *todo = LLIST_TS_GET_DATA(i); - LLIST_REMOVE (&todolist, i); - mem_free (todo->mesg); - erase_note (&todo->note, flag); - mem_free (todo); + LLIST_REMOVE(&todolist, i); + mem_free(todo->mesg); + erase_note(&todo->note); + mem_free(todo); } /* @@ -220,186 +210,164 @@ todo_delete_bynum (unsigned num, enum eraseflg flag) * This way, it is easy to retrive its original priority if the user decides * that in fact it was not completed. */ -void -todo_flag (void) +void todo_flag(void) { struct todo *t; - t = todo_get_item (hilt); + t = todo_get_item(hilt); t->id = -t->id; } /* Delete an item from the ToDo list. */ -void -todo_delete (struct conf *conf) +void todo_delete(void) { - char *choices = "[y/n] "; - char *del_todo_str = _("Do you really want to delete this task ?"); - char *erase_warning = + const char *del_todo_str = _("Do you really want to delete this task ?"); + const char *erase_warning = _("This item has a note attached to it. " "Delete (t)odo or just its (n)ote ?"); - char *erase_choice = _("[t/n] "); - unsigned go_for_todo_del = 0; - int answer, has_note; - - if (conf->confirm_delete) - { - status_mesg (del_todo_str, choices); - answer = wgetch (win[STA].p); - if ((answer == 'y') && (todos > 0)) - { - go_for_todo_del = 1; - } - else - { - wins_erase_status_bar (); - return; - } - } - else if (todos > 0) - go_for_todo_del = 1; - - if (go_for_todo_del == 0) - { - wins_erase_status_bar (); - return; - } - - answer = -1; - has_note = (todo_get_item (hilt)->note != NULL) ? 1 : 0; - if (has_note == 0) - answer = 't'; + const char *erase_choice = _("[tn]"); + const int nb_erase_choice = 2; + int answer; - while (answer != 't' && answer != 'n' && answer != KEY_GENERIC_CANCEL) - { - status_mesg (erase_warning, erase_choice); - answer = wgetch (win[STA].p); - } + if ((todos <= 0) || + (conf.confirm_delete && (status_ask_bool(del_todo_str) != 1))) { + wins_erase_status_bar(); + return; + } - switch (answer) - { - case 't': - todo_delete_bynum (hilt - 1, ERASE_FORCE); - todos--; - if (hilt > 1) - hilt--; - if (todos == 0) - hilt = 0; - if (hilt - first < 0) - first--; - break; - case 'n': - todo_delete_note_bynum (hilt - 1); - break; - default: - wins_erase_status_bar (); - return; - } + /* This todo item doesn't have any note associated. */ + if (todo_get_item(hilt)->note == NULL) + answer = 1; + else + answer = status_ask_choice(erase_warning, erase_choice, nb_erase_choice); + + switch (answer) { + case 1: + todo_delete_bynum(hilt - 1); + todos--; + if (hilt > 1) + hilt--; + if (todos == 0) + hilt = 0; + if (hilt - first < 0) + first--; + break; + case 2: + todo_delete_note_bynum(hilt - 1); + break; + default: + wins_erase_status_bar(); + return; + } } /* * Returns the position into the linked list corresponding to the * given todo item. */ -static int -todo_get_position (struct todo *needle) +static int todo_get_position(struct todo *needle) { llist_item_t *i; int n = 0; - LLIST_FOREACH (&todolist, i) - { - n++; - if (LLIST_TS_GET_DATA (i) == needle) - return n; - } + LLIST_FOREACH(&todolist, i) { + n++; + if (LLIST_TS_GET_DATA(i) == needle) + return n; + } - EXIT (_("todo not found")); - return -1; /* avoid compiler warnings */ + EXIT(_("todo not found")); + return -1; /* avoid compiler warnings */ } /* Change an item priority by pressing '+' or '-' inside TODO panel. */ -void -todo_chg_priority (int action) +void todo_chg_priority(int action) { struct todo *backup; char backup_mesg[BUFSIZ]; int backup_id; - char backup_note[NOTESIZ + 1]; - int do_chg = 1; + char backup_note[MAX_NOTESIZ + 1]; - backup = todo_get_item (hilt); - (void)strncpy (backup_mesg, backup->mesg, strlen (backup->mesg) + 1); + backup = todo_get_item(hilt); + strncpy(backup_mesg, backup->mesg, strlen(backup->mesg) + 1); backup_id = backup->id; if (backup->note) - (void)strncpy (backup_note, backup->note, NOTESIZ + 1); + strncpy(backup_note, backup->note, MAX_NOTESIZ + 1); else backup_note[0] = '\0'; - switch (action) - { - case KEY_RAISE_PRIORITY: - (backup_id > 1) ? backup_id-- : do_chg--; - break; - case KEY_LOWER_PRIORITY: - (backup_id > 0 && backup_id < 9) ? backup_id++ : do_chg--; - break; - default: - EXIT (_("no such action")); - /* NOTREACHED */ - } - if (do_chg) - { - todo_delete_bynum (hilt - 1, ERASE_FORCE_KEEP_NOTE); - backup = todo_add (backup_mesg, backup_id, backup_note); - hilt = todo_get_position (backup); - } + switch (action) { + case KEY_RAISE_PRIORITY: + if (backup_id > 1) + backup_id--; + else + return; + break; + case KEY_LOWER_PRIORITY: + if (backup_id > 0 && backup_id < 9) + backup_id++; + else + return; + break; + default: + EXIT(_("no such action")); + /* NOTREACHED */ + } + + todo_delete_bynum(hilt - 1); + backup = todo_add(backup_mesg, backup_id, backup_note); + hilt = todo_get_position(backup); } /* Edit the description of an already existing todo item. */ -void -todo_edit_item (void) +void todo_edit_item(void) { struct todo *i; - char *mesg = _("Enter the new ToDo description :"); + const char *mesg = _("Enter the new ToDo description :"); - status_mesg (mesg, ""); - i = todo_get_item (hilt); - updatestring (win[STA].p, &i->mesg, 0, 1); + status_mesg(mesg, ""); + i = todo_get_item(hilt); + updatestring(win[STA].p, &i->mesg, 0, 1); } /* Display todo items in the corresponding panel. */ static void -display_todo_item (int incolor, char *msg, int prio, int note, int len, int y, - int x) +display_todo_item(int incolor, char *msg, int prio, int note, int width, int y, + int x) { WINDOW *w; int ch_note; - char buf[len], priostr[2]; + char buf[width * UTF8_MAXLEN], priostr[2]; + int i; w = win[TOD].p; ch_note = (note) ? '>' : '.'; if (prio > 0) - snprintf (priostr, sizeof priostr, "%d", prio); + snprintf(priostr, sizeof priostr, "%d", prio); else - snprintf (priostr, sizeof priostr, "X"); + strncpy(priostr, "X", sizeof priostr); if (incolor == 0) - custom_apply_attr (w, ATTR_HIGHEST); - if (strlen (msg) < len) - mvwprintw (w, y, x, "%s%c %s", priostr, ch_note, msg); - else - { - (void)strncpy (buf, msg, len - 1); - buf[len - 1] = '\0'; - mvwprintw (w, y, x, "%s%c %s...", priostr, ch_note, buf); + custom_apply_attr(w, ATTR_HIGHEST); + if (utf8_strwidth(msg) < width) + mvwprintw(w, y, x, "%s%c %s", priostr, ch_note, msg); + else { + for (i = 0; msg[i] && width > 0; i++) { + if (!UTF8_ISCONT(msg[i])) + width -= utf8_width(&msg[i]); + buf[i] = msg[i]; } + if (i) + buf[i - 1] = 0; + else + buf[0] = 0; + mvwprintw(w, y, x, "%s%c %s...", priostr, ch_note, buf); + } if (incolor == 0) - custom_remove_attr (w, ATTR_HIGHEST); + custom_remove_attr(w, ATTR_HIGHEST); } /* Updates the ToDo panel. */ -void -todo_update_panel (int which_pan) +void todo_update_panel(int which_pan) { llist_item_t *i; int len = win[TOD].w - 8; @@ -412,97 +380,94 @@ todo_update_panel (int which_pan) int incolor = -1; /* Print todo item in the panel. */ - erase_window_part (win[TOD].p, 1, title_lines, win[TOD].w - 2, - win[TOD].h - 2); - LLIST_FOREACH (&todolist, i) - { - struct todo *todo = LLIST_TS_GET_DATA (i); - num_todo++; - t_realpos = num_todo - first; - incolor = num_todo - hilt; - if (incolor == 0) - msgsav = todo->mesg; - if (t_realpos >= 0 && t_realpos < max_items) - { - display_todo_item (incolor, todo->mesg, todo->id, - (todo->note != NULL) ? 1 : 0, len, y_offset, - x_offset); - y_offset = y_offset + todo_lines; - } + erase_window_part(win[TOD].p, 1, title_lines, win[TOD].w - 2, win[TOD].h - 2); + LLIST_FOREACH(&todolist, i) { + struct todo *todo = LLIST_TS_GET_DATA(i); + num_todo++; + t_realpos = num_todo - first; + incolor = (which_pan == TOD) ? num_todo - hilt : num_todo; + if (incolor == 0) + msgsav = todo->mesg; + if (t_realpos >= 0 && t_realpos < max_items) { + display_todo_item(incolor, todo->mesg, todo->id, + (todo->note != NULL) ? 1 : 0, len, y_offset, x_offset); + y_offset = y_offset + todo_lines; } + } /* Draw the scrollbar if necessary. */ - if (todos > max_items) - { - float ratio = ((float) max_items) / ((float) todos); - int sbar_length = (int) (ratio * (max_items + 1)); - int highend = (int) (ratio * first); - unsigned hilt_bar = (which_pan == TOD) ? 1 : 0; - int sbar_top = highend + title_lines; - - if ((sbar_top + sbar_length) > win[TOD].h - 1) - sbar_length = win[TOD].h - 1 - sbar_top; - draw_scrollbar (win[TOD].p, sbar_top, win[TOD].w - 2, - sbar_length, title_lines, win[TOD].h - 1, hilt_bar); - } - - wnoutrefresh (win[TOD].p); + if (todos > max_items) { + float ratio = ((float)max_items) / ((float)todos); + int sbar_length = (int)(ratio * (max_items + 1)); + int highend = (int)(ratio * first); + unsigned hilt_bar = (which_pan == TOD) ? 1 : 0; + int sbar_top = highend + title_lines; + + if ((sbar_top + sbar_length) > win[TOD].h - 1) + sbar_length = win[TOD].h - 1 - sbar_top; + draw_scrollbar(win[TOD].p, sbar_top, win[TOD].w - 2, + sbar_length, title_lines, win[TOD].h - 1, hilt_bar); + } + + wnoutrefresh(win[TOD].p); } /* Attach a note to a todo */ -void -todo_edit_note (char *editor) +void todo_edit_note(const char *editor) { - struct todo *i; - char fullname[BUFSIZ]; - char *filename; - - i = todo_get_item (hilt); - if (i->note == NULL) - { - if ((filename = new_tempfile (path_notes, NOTESIZ)) != NULL) - i->note = filename; - else - return; - } - (void)snprintf (fullname, BUFSIZ, "%s%s", path_notes, i->note); - wins_launch_external (fullname, editor); - - if (io_file_is_empty (fullname) > 0) - erase_note (&i->note, ERASE_FORCE); + struct todo *i = todo_get_item(hilt); + edit_note(&i->note, editor); } /* View a note previously attached to a todo */ -void -todo_view_note (char *pager) +void todo_view_note(const char *pager) { - struct todo *i; - char fullname[BUFSIZ]; + struct todo *i = todo_get_item(hilt); + view_note(i->note, pager); +} - i = todo_get_item (hilt); - if (i->note == NULL) +/* Pipe a todo item to an external program. */ +void todo_pipe_item(void) +{ + char cmd[BUFSIZ] = ""; + char const *arg[] = { cmd, NULL }; + int pout; + int pid; + FILE *fpout; + struct todo *todo; + + status_mesg(_("Pipe item to external command:"), ""); + if (getstring(win[STA].p, cmd, BUFSIZ, 0, 1) != GETSTRING_VALID) return; - (void)snprintf (fullname, BUFSIZ, "%s%s", path_notes, i->note); - wins_launch_external (fullname, pager); + + wins_prepare_external(); + if ((pid = shell_exec(NULL, &pout, *arg, arg))) { + fpout = fdopen(pout, "w"); + + todo = todo_get_item(hilt); + todo_write(todo, fpout); + + fclose(fpout); + child_wait(NULL, &pout, pid); + press_any_key(); + } + wins_unprepare_external(); } -void -todo_free (struct todo *todo) +static void todo_free(struct todo *todo) { - mem_free (todo->mesg); - erase_note (&todo->note, ERASE_FORCE_KEEP_NOTE); - mem_free (todo); + mem_free(todo->mesg); + erase_note(&todo->note); + mem_free(todo); } -void -todo_init_list (void) +void todo_init_list(void) { - LLIST_INIT (&todolist); + LLIST_INIT(&todolist); } -void -todo_free_list (void) +void todo_free_list(void) { - LLIST_FREE_INNER (&todolist, todo_free); - LLIST_FREE (&todolist); + LLIST_FREE_INNER(&todolist, todo_free); + LLIST_FREE(&todolist); } diff --git a/src/utf8.c b/src/utf8.c new file mode 100644 index 0000000..398b142 --- /dev/null +++ b/src/utf8.c @@ -0,0 +1,335 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#include "calcurse.h" + +struct utf8_range { + int min, max, width; +}; + +static const struct utf8_range utf8_widthtab[] = { + {0x00300, 0x0036f, 0}, + {0x00483, 0x00489, 0}, + {0x00591, 0x005bd, 0}, + {0x005bf, 0x005bf, 0}, + {0x005c1, 0x005c2, 0}, + {0x005c4, 0x005c5, 0}, + {0x005c7, 0x005c7, 0}, + {0x00610, 0x0061a, 0}, + {0x0064b, 0x0065e, 0}, + {0x00670, 0x00670, 0}, + {0x006d6, 0x006dc, 0}, + {0x006de, 0x006e4, 0}, + {0x006e7, 0x006e8, 0}, + {0x006ea, 0x006ed, 0}, + {0x00711, 0x00711, 0}, + {0x00730, 0x0074a, 0}, + {0x007a6, 0x007b0, 0}, + {0x007eb, 0x007f3, 0}, + {0x00816, 0x00819, 0}, + {0x0081b, 0x00823, 0}, + {0x00825, 0x00827, 0}, + {0x00829, 0x0082d, 0}, + {0x00900, 0x00903, 0}, + {0x0093c, 0x0093c, 0}, + {0x0093e, 0x0094e, 0}, + {0x00951, 0x00955, 0}, + {0x00962, 0x00963, 0}, + {0x00981, 0x00983, 0}, + {0x009bc, 0x009bc, 0}, + {0x009be, 0x009c4, 0}, + {0x009c7, 0x009c8, 0}, + {0x009cb, 0x009cd, 0}, + {0x009d7, 0x009d7, 0}, + {0x009e2, 0x009e3, 0}, + {0x00a01, 0x00a03, 0}, + {0x00a3c, 0x00a3c, 0}, + {0x00a3e, 0x00a42, 0}, + {0x00a47, 0x00a48, 0}, + {0x00a4b, 0x00a4d, 0}, + {0x00a51, 0x00a51, 0}, + {0x00a70, 0x00a71, 0}, + {0x00a75, 0x00a75, 0}, + {0x00a81, 0x00a83, 0}, + {0x00abc, 0x00abc, 0}, + {0x00abe, 0x00ac5, 0}, + {0x00ac7, 0x00ac9, 0}, + {0x00acb, 0x00acd, 0}, + {0x00ae2, 0x00ae3, 0}, + {0x00b01, 0x00b03, 0}, + {0x00b3c, 0x00b3c, 0}, + {0x00b3e, 0x00b44, 0}, + {0x00b47, 0x00b48, 0}, + {0x00b4b, 0x00b4d, 0}, + {0x00b56, 0x00b57, 0}, + {0x00b62, 0x00b63, 0}, + {0x00b82, 0x00b82, 0}, + {0x00bbe, 0x00bc2, 0}, + {0x00bc6, 0x00bc8, 0}, + {0x00bca, 0x00bcd, 0}, + {0x00bd7, 0x00bd7, 0}, + {0x00c01, 0x00c03, 0}, + {0x00c3e, 0x00c44, 0}, + {0x00c46, 0x00c48, 0}, + {0x00c4a, 0x00c4d, 0}, + {0x00c55, 0x00c56, 0}, + {0x00c62, 0x00c63, 0}, + {0x00c82, 0x00c83, 0}, + {0x00cbc, 0x00cbc, 0}, + {0x00cbe, 0x00cc4, 0}, + {0x00cc6, 0x00cc8, 0}, + {0x00cca, 0x00ccd, 0}, + {0x00cd5, 0x00cd6, 0}, + {0x00ce2, 0x00ce3, 0}, + {0x00d02, 0x00d03, 0}, + {0x00d3e, 0x00d44, 0}, + {0x00d46, 0x00d48, 0}, + {0x00d4a, 0x00d4d, 0}, + {0x00d57, 0x00d57, 0}, + {0x00d62, 0x00d63, 0}, + {0x00d82, 0x00d83, 0}, + {0x00dca, 0x00dca, 0}, + {0x00dcf, 0x00dd4, 0}, + {0x00dd6, 0x00dd6, 0}, + {0x00dd8, 0x00ddf, 0}, + {0x00df2, 0x00df3, 0}, + {0x00e31, 0x00e31, 0}, + {0x00e34, 0x00e3a, 0}, + {0x00e47, 0x00e4e, 0}, + {0x00eb1, 0x00eb1, 0}, + {0x00eb4, 0x00eb9, 0}, + {0x00ebb, 0x00ebc, 0}, + {0x00ec8, 0x00ecd, 0}, + {0x00f18, 0x00f19, 0}, + {0x00f35, 0x00f35, 0}, + {0x00f37, 0x00f37, 0}, + {0x00f39, 0x00f39, 0}, + {0x00f3e, 0x00f3f, 0}, + {0x00f71, 0x00f84, 0}, + {0x00f86, 0x00f87, 0}, + {0x00f90, 0x00f97, 0}, + {0x00f99, 0x00fbc, 0}, + {0x00fc6, 0x00fc6, 0}, + {0x0102b, 0x0103e, 0}, + {0x01056, 0x01059, 0}, + {0x0105e, 0x01060, 0}, + {0x01062, 0x01064, 0}, + {0x01067, 0x0106d, 0}, + {0x01071, 0x01074, 0}, + {0x01082, 0x0108d, 0}, + {0x0108f, 0x0108f, 0}, + {0x0109a, 0x0109d, 0}, + {0x01100, 0x0115f, 2}, + {0x011a3, 0x011a7, 2}, + {0x011fa, 0x011ff, 2}, + {0x0135f, 0x0135f, 0}, + {0x01712, 0x01714, 0}, + {0x01732, 0x01734, 0}, + {0x01752, 0x01753, 0}, + {0x01772, 0x01773, 0}, + {0x017b6, 0x017d3, 0}, + {0x017dd, 0x017dd, 0}, + {0x0180b, 0x0180d, 0}, + {0x018a9, 0x018a9, 0}, + {0x01920, 0x0192b, 0}, + {0x01930, 0x0193b, 0}, + {0x019b0, 0x019c0, 0}, + {0x019c8, 0x019c9, 0}, + {0x01a17, 0x01a1b, 0}, + {0x01a55, 0x01a5e, 0}, + {0x01a60, 0x01a7c, 0}, + {0x01a7f, 0x01a7f, 0}, + {0x01b00, 0x01b04, 0}, + {0x01b34, 0x01b44, 0}, + {0x01b6b, 0x01b73, 0}, + {0x01b80, 0x01b82, 0}, + {0x01ba1, 0x01baa, 0}, + {0x01c24, 0x01c37, 0}, + {0x01cd0, 0x01cd2, 0}, + {0x01cd4, 0x01ce8, 0}, + {0x01ced, 0x01ced, 0}, + {0x01cf2, 0x01cf2, 0}, + {0x01dc0, 0x01de6, 0}, + {0x01dfd, 0x01dff, 0}, + {0x020d0, 0x020f0, 0}, + {0x02329, 0x0232a, 2}, + {0x02cef, 0x02cf1, 0}, + {0x02de0, 0x02dff, 0}, + {0x02e80, 0x02e99, 2}, + {0x02e9b, 0x02ef3, 2}, + {0x02f00, 0x02fd5, 2}, + {0x02ff0, 0x02ffb, 2}, + {0x03000, 0x03029, 2}, + {0x0302a, 0x0302f, 0}, + {0x03030, 0x0303e, 2}, + {0x03041, 0x03096, 2}, + {0x03099, 0x0309a, 0}, + {0x0309b, 0x030ff, 2}, + {0x03105, 0x0312d, 2}, + {0x03131, 0x0318e, 2}, + {0x03190, 0x031b7, 2}, + {0x031c0, 0x031e3, 2}, + {0x031f0, 0x0321e, 2}, + {0x03220, 0x03247, 2}, + {0x03250, 0x032fe, 2}, + {0x03300, 0x04dbf, 2}, + {0x04e00, 0x0a48c, 2}, + {0x0a490, 0x0a4c6, 2}, + {0x0a66f, 0x0a672, 0}, + {0x0a67c, 0x0a67d, 0}, + {0x0a6f0, 0x0a6f1, 0}, + {0x0a802, 0x0a802, 0}, + {0x0a806, 0x0a806, 0}, + {0x0a80b, 0x0a80b, 0}, + {0x0a823, 0x0a827, 0}, + {0x0a880, 0x0a881, 0}, + {0x0a8b4, 0x0a8c4, 0}, + {0x0a8e0, 0x0a8f1, 0}, + {0x0a926, 0x0a92d, 0}, + {0x0a947, 0x0a953, 0}, + {0x0a960, 0x0a97c, 2}, + {0x0a980, 0x0a983, 0}, + {0x0a9b3, 0x0a9c0, 0}, + {0x0aa29, 0x0aa36, 0}, + {0x0aa43, 0x0aa43, 0}, + {0x0aa4c, 0x0aa4d, 0}, + {0x0aa7b, 0x0aa7b, 0}, + {0x0aab0, 0x0aab0, 0}, + {0x0aab2, 0x0aab4, 0}, + {0x0aab7, 0x0aab8, 0}, + {0x0aabe, 0x0aabf, 0}, + {0x0aac1, 0x0aac1, 0}, + {0x0abe3, 0x0abea, 0}, + {0x0abec, 0x0abed, 0}, + {0x0ac00, 0x0d7a3, 2}, + {0x0d7b0, 0x0d7c6, 2}, + {0x0d7cb, 0x0d7fb, 2}, + {0x0f900, 0x0faff, 2}, + {0x0fb1e, 0x0fb1e, 0}, + {0x0fe00, 0x0fe0f, 0}, + {0x0fe10, 0x0fe19, 2}, + {0x0fe20, 0x0fe26, 0}, + {0x0fe30, 0x0fe52, 2}, + {0x0fe54, 0x0fe66, 2}, + {0x0fe68, 0x0fe6b, 2}, + {0x0ff01, 0x0ff60, 2}, + {0x0ffe0, 0x0ffe6, 2}, + {0x101fd, 0x101fd, 0}, + {0x10a01, 0x10a03, 0}, + {0x10a05, 0x10a06, 0}, + {0x10a0c, 0x10a0f, 0}, + {0x10a38, 0x10a3a, 0}, + {0x10a3f, 0x10a3f, 0}, + {0x11080, 0x11082, 0}, + {0x110b0, 0x110ba, 0}, + {0x1d165, 0x1d169, 0}, + {0x1d16d, 0x1d172, 0}, + {0x1d17b, 0x1d182, 0}, + {0x1d185, 0x1d18b, 0}, + {0x1d1aa, 0x1d1ad, 0}, + {0x1d242, 0x1d244, 0}, + {0x1f200, 0x1f200, 2}, + {0x1f210, 0x1f231, 2}, + {0x1f240, 0x1f248, 2}, + {0x20000, 0x2fffd, 2}, + {0x30000, 0x3fffd, 2}, + {0xe0100, 0xe01ef, 0} +}; + +/* Get the width of a UTF-8 character. */ +int utf8_width(char *s) +{ + int val, low, high, cur; + + if (UTF8_ISCONT(*s)) + return 0; + + switch (UTF8_LENGTH(*s)) { + case 1: + val = s[0]; + break; + case 2: + val = (s[1] & 0x3f) | (s[0] & 0x1f) << 6; + break; + case 3: + val = ((s[2] & 0x3f) | (s[1] & 0x3f) << 6) | (s[0] & 0x0f) << 12; + break; + case 4: + val = (((s[3] & 0x3f) | (s[2] & 0x3f) << 6) | + (s[1] & 0x3f) << 12) | (s[0] & 0x3f) << 18; + break; + case 5: + val = ((((s[4] & 0x3f) | (s[3] & 0x3f) << 6) | + (s[2] & 0x3f) << 12) | (s[1] & 0x3f) << 18) | (s[0] & 0x3f) << 24; + break; + case 6: + val = (((((s[5] & 0x3f) | (s[4] & 0x3f) << 6) | + (s[3] & 0x3f) << 12) | (s[2] & 0x3f) << 18) | + (s[1] & 0x3f) << 24) | (s[0] & 0x3f) << 30; + break; + default: + return 0; + } + + low = 0; + high = sizeof(utf8_widthtab) / sizeof(utf8_widthtab[0]); + do { + cur = (low + high) / 2; + if (val >= utf8_widthtab[cur].min) { + if (val <= utf8_widthtab[cur].max) + return utf8_widthtab[cur].width; + else + low = cur + 1; + } else + high = cur - 1; + } + while (low <= high); + + return 1; +} + +/* Get the width of a UTF-8 string. */ +int utf8_strwidth(char *s) +{ + int width = 0; + + for (; s && *s; s++) { + if (!UTF8_ISCONT(*s)) + width += utf8_width(s); + } + + return width; +} diff --git a/src/utils.c b/src/utils.c index 0a01c2e..b3d9c71 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,69 +42,80 @@ #include <ctype.h> #include <sys/types.h> #include <errno.h> +#include <fcntl.h> +#include <sys/wait.h> +#include <termios.h> #include "calcurse.h" #define ISLEAP(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) +#define FS_EXT_MAXLEN 64 + +enum format_specifier { + FS_STARTDATE, + FS_DURATION, + FS_ENDDATE, + FS_MESSAGE, + FS_NOTE, + FS_NOTEFILE, + FS_PRIORITY, + FS_PSIGN, + FS_EOF, + FS_UNKNOWN +}; + /* General routine to exit calcurse properly. */ -void -exit_calcurse (int status) +void exit_calcurse(int status) { int was_interactive; - if (ui_mode == UI_CURSES) - { - notify_stop_main_thread (); - clear (); - wins_refresh (); - endwin (); - ui_mode = UI_CMDLINE; - was_interactive = 1; - } - else + if (ui_mode == UI_CURSES) { + notify_stop_main_thread(); + clear(); + wins_refresh(); + endwin(); + ui_mode = UI_CMDLINE; + was_interactive = 1; + } else was_interactive = 0; - calendar_stop_date_thread (); - io_stop_psave_thread (); - free_user_data (); - keys_free (); - mem_stats (); - if (was_interactive) - { - if (unlink (path_cpid) != 0) - EXIT (_("Could not remove calcurse lock file: %s\n"), - strerror (errno)); - if (dmon.enable) - dmon_start (status); - } + calendar_stop_date_thread(); + io_stop_psave_thread(); + free_user_data(); + keys_free(); + mem_stats(); + if (was_interactive) { + if (unlink(path_cpid) != 0) + EXIT(_("Could not remove calcurse lock file: %s\n"), strerror(errno)); + if (dmon.enable) + dmon_start(status); + } - exit (status); + exit(status); } -void -free_user_data (void) +void free_user_data(void) { - day_free_list (); - event_llist_free (); - event_free_bkp (ERASE_FORCE); - apoint_llist_free (); - apoint_free_bkp (ERASE_FORCE); - recur_apoint_llist_free (); - recur_event_llist_free (); - recur_apoint_free_bkp (ERASE_FORCE); - recur_event_free_bkp (ERASE_FORCE); - todo_free_list (); - notify_free_app (); + 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(); + notify_free_app(); } /* Function to exit on internal error. */ -void -fatalbox (const char *errmsg) +void fatalbox(const char *errmsg) { WINDOW *errwin; - char *label = _("/!\\ INTERNAL ERROR /!\\"); - char *reportmsg = _("Please report the following bug:"); + const char *label = _("/!\\ INTERNAL ERROR /!\\"); + const char *reportmsg = _("Please report the following bug:"); const int WINROW = 10; const int WINCOL = col - 2; const int MSGLEN = WINCOL - 2; @@ -113,25 +124,24 @@ fatalbox (const char *errmsg) if (errmsg == NULL) return; - (void)strncpy (msg, errmsg, MSGLEN); - errwin = newwin (WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2); - custom_apply_attr (errwin, ATTR_HIGHEST); - box (errwin, 0, 0); - wins_show (errwin, label); - mvwprintw (errwin, 3, 1, reportmsg); - mvwprintw (errwin, 5, (WINCOL - strlen (msg)) / 2, "%s", msg); - custom_remove_attr (errwin, ATTR_HIGHEST); - wins_wrefresh (errwin); - (void)wgetch (errwin); - delwin (errwin); - wins_doupdate (); + strncpy(msg, errmsg, MSGLEN); + errwin = newwin(WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2); + custom_apply_attr(errwin, ATTR_HIGHEST); + box(errwin, 0, 0); + wins_show(errwin, label); + mvwprintw(errwin, 3, 1, reportmsg); + mvwprintw(errwin, 5, (WINCOL - strlen(msg)) / 2, "%s", msg); + custom_remove_attr(errwin, ATTR_HIGHEST); + wins_wrefresh(errwin); + wgetch(errwin); + delwin(errwin); + wins_doupdate(); } -void -warnbox (const char *msg) +void warnbox(const char *msg) { WINDOW *warnwin; - char *label = "/!\\"; + const char *label = "/!\\"; const int WINROW = 10; const int WINCOL = col - 2; const int MSGLEN = WINCOL - 2; @@ -140,317 +150,208 @@ warnbox (const char *msg) if (msg == NULL) return; - (void)strncpy (displmsg, msg, MSGLEN); - warnwin = newwin (WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2); - custom_apply_attr (warnwin, ATTR_HIGHEST); - box (warnwin, 0, 0); - wins_show (warnwin, label); - mvwprintw (warnwin, 5, (WINCOL - strlen (displmsg)) / 2, "%s", displmsg); - custom_remove_attr (warnwin, ATTR_HIGHEST); - wins_wrefresh (warnwin); - (void)wgetch (warnwin); - delwin (warnwin); - wins_doupdate (); + strncpy(displmsg, msg, MSGLEN); + warnwin = newwin(WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2); + custom_apply_attr(warnwin, ATTR_HIGHEST); + box(warnwin, 0, 0); + wins_show(warnwin, label); + mvwprintw(warnwin, 5, (WINCOL - strlen(displmsg)) / 2, "%s", displmsg); + custom_remove_attr(warnwin, ATTR_HIGHEST); + wins_wrefresh(warnwin); + wgetch(warnwin); + delwin(warnwin); + wins_doupdate(); } /* * Print a message in the status bar. * Message texts for first line and second line are to be provided. */ -void -status_mesg (char *mesg_line1, char *mesg_line2) +void status_mesg(const char *msg1, const char *msg2) { - wins_erase_status_bar (); - custom_apply_attr (win[STA].p, ATTR_HIGHEST); - mvwprintw (win[STA].p, 0, 0, mesg_line1); - mvwprintw (win[STA].p, 1, 0, mesg_line2); - custom_remove_attr (win[STA].p, ATTR_HIGHEST); + wins_erase_status_bar(); + custom_apply_attr(win[STA].p, ATTR_HIGHEST); + mvwprintw(win[STA].p, 0, 0, msg1); + mvwprintw(win[STA].p, 1, 0, msg2); + custom_remove_attr(win[STA].p, ATTR_HIGHEST); +} + +/* + * Prompts the user to make a choice between named alternatives. + * + * The available choices are described by a string of the form + * "[ynp]". The first and last char are ignored (they are only here to + * make the translators' life easier), and every other char indicates + * a key the user is allowed to press. + * + * Returns the index of the key pressed by the user (starting from 1), + * or -1 if the user doesn't want to answer (e.g. by escaping). + */ +int status_ask_choice(const char *message, const char choice[], int nb_choice) +{ + int i, ch; + char tmp[BUFSIZ]; + /* "[4/2/f/t/w/.../Z] " */ + char avail_choice[2 * nb_choice + 3]; + + avail_choice[0] = '['; + avail_choice[1] = '\0'; + + for (i = 1; i <= nb_choice; i++) { + snprintf(tmp, BUFSIZ, (i == nb_choice) ? "%c] " : "%c/", choice[i]); + strcat(avail_choice, tmp); + } + + status_mesg(message, avail_choice); + + for (;;) { + ch = wgetch(win[STA].p); + for (i = 1; i <= nb_choice; i++) + if (ch == choice[i]) + return i; + if (ch == ESCAPE) + return (-1); + if (resize) { + resize = 0; + wins_reset(); + status_mesg(message, avail_choice); + } + } +} + +/* + * Prompts the user with a boolean question. + * + * Returns 1 if yes, 2 if no, and -1 otherwise + */ +int status_ask_bool(const char *msg) +{ + return (status_ask_choice(msg, _("[yn]"), 2)); +} + +/* + * Prompts the user to make a choice between a number of alternatives. + * + * Returns the option chosen by the user (starting from 1), or -1 if + * the user doesn't want to answer. + */ +int +status_ask_simplechoice(const char *prefix, const char *choice[], int nb_choice) +{ + int i; + char tmp[BUFSIZ]; + /* "(1) Choice1, (2) Choice2, (3) Choice3?" */ + char choicestr[BUFSIZ]; + /* Holds the characters to choose from ('1', '2', etc) */ + char char_choice[nb_choice + 2]; + + /* No need to initialize first and last char. */ + for (i = 1; i <= nb_choice; i++) + char_choice[i] = '0' + i; + + strcpy(choicestr, prefix); + + for (i = 0; i < nb_choice; i++) { + snprintf(tmp, BUFSIZ, ((i + 1) == nb_choice) ? "(%d) %s?" : "(%d) %s, ", + (i + 1), _(choice[i])); + strcat(choicestr, tmp); + } + + return (status_ask_choice(choicestr, char_choice, nb_choice)); } /* Erase part of a window. */ void -erase_window_part (WINDOW *win, int first_col, int first_row, int last_col, - int last_row) +erase_window_part(WINDOW * win, int first_col, int first_row, int last_col, + int last_row) { int c, r; - for (r = first_row; r <= last_row; r++) - { - for (c = first_col; c <= last_col; c++) - mvwprintw (win, r, c, " "); - } - - wnoutrefresh (win); + for (r = first_row; r <= last_row; r++) { + for (c = first_col; c <= last_col; c++) + mvwprintw(win, r, c, " "); + } } /* draws a popup window */ -WINDOW * -popup (int pop_row, int pop_col, int pop_y, int pop_x, char *title, char *msg, - int hint) +WINDOW *popup(int pop_row, int pop_col, int pop_y, int pop_x, const char *title, + const char *msg, int hint) { - char *any_key = _("Press any key to continue..."); + const char *any_key = _("Press any key to continue..."); char label[BUFSIZ]; WINDOW *popup_win; const int MSGXPOS = 5; - popup_win = newwin (pop_row, pop_col, pop_y, pop_x); - keypad (popup_win, TRUE); + popup_win = newwin(pop_row, pop_col, pop_y, pop_x); + keypad(popup_win, TRUE); if (msg) - mvwprintw (popup_win, MSGXPOS, (pop_col - strlen (msg)) / 2, "%s", msg); - custom_apply_attr (popup_win, ATTR_HIGHEST); - box (popup_win, 0, 0); - (void)snprintf (label, BUFSIZ, "%s", title); - wins_show (popup_win, label); + mvwprintw(popup_win, MSGXPOS, (pop_col - strlen(msg)) / 2, "%s", msg); + custom_apply_attr(popup_win, ATTR_HIGHEST); + box(popup_win, 0, 0); + snprintf(label, BUFSIZ, "%s", title); + wins_show(popup_win, label); if (hint) - mvwprintw (popup_win, pop_row - 2, pop_col - (strlen (any_key) + 1), "%s", - any_key); - custom_remove_attr (popup_win, ATTR_HIGHEST); - wins_wrefresh (popup_win); + mvwprintw(popup_win, pop_row - 2, pop_col - (strlen(any_key) + 1), "%s", + any_key); + custom_remove_attr(popup_win, ATTR_HIGHEST); + wins_wrefresh(popup_win); return popup_win; } /* prints in middle of a panel */ void -print_in_middle (WINDOW *win, int starty, int startx, int width, char *string) +print_in_middle(WINDOW * win, int starty, int startx, int width, + const char *string) { - int len = strlen (string); + int len = strlen(string); int x, y; win = win ? win : stdscr; - getyx (win, y, x); + getyx(win, y, x); x = startx ? startx : x; y = starty ? starty : y; width = width ? width : 80; x += (width - len) / 2; - custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, x, "%s", string); - custom_remove_attr (win, ATTR_HIGHEST); -} - -/* Print the string at the desired position. */ -static void -showstring (WINDOW *win, int x, int y, char *str, int len, int scroff, - int curpos) -{ - char c = 0; - - /* print string */ - mvwaddnstr (win, y, x, &str[scroff], -1); - wclrtoeol (win); - - /* print scrolling indicator */ - if (scroff > 0 && scroff < len - col) - c = '*'; - else if (scroff > 0) - c = '<'; - else if (scroff < len - col) - c = '>'; - mvwprintw (win, y, col - 1, "%c", c); - - /* print cursor */ - wmove (win, y, curpos - scroff); - - if (curpos >= len) - waddch (win, SPACE | A_REVERSE); - else - waddch (win, str[curpos] | A_REVERSE); -} - -/* Delete a character at the given position in string. */ -static void -del_char (int pos, char *str) -{ - str += pos; - memmove (str, str + 1, strlen (str) + 1); -} - -/* Add a character at the given position in string. */ -static void -ins_char (int pos, int ch, char *str) -{ - str += pos; - memmove (str + 1, str, strlen (str) + 1); - *str = ch; -} - -static void -bell (void) -{ - printf ("\a"); -} - -/* - * Getstring allows to get user input and to print it on a window, - * even if noecho() is on. This function is also used to modify an existing - * text (the variable string can be non-NULL). - * We need to do the echoing manually because of the multi-threading - * environment, otherwise the cursor would move from place to place without - * control. - */ -enum getstr -getstring (WINDOW *win, char *str, int l, int x, int y) -{ - const int pgsize = col / 3; - - int len = strlen (str); - int curpos = len; - int scroff = 0; - int ch; - - custom_apply_attr (win, ATTR_HIGHEST); - - for (;;) { - while (curpos < scroff) - scroff -= pgsize; - while (curpos >= scroff + col - 1) - scroff += pgsize; - - showstring (win, x, y, str, len, scroff, curpos); - wins_doupdate (); - - if ((ch = wgetch (win)) == '\n') break; - switch (ch) - { - case KEY_BACKSPACE: /* delete one character */ - case 330: - case 127: - case CTRL ('H'): - if (curpos > 0) - { - del_char ((--curpos), str); - len--; - } - else - bell (); - break; - case CTRL ('D'): /* delete next character */ - if (curpos < len) - { - del_char (curpos, str); - len--; - } - else - bell (); - break; - case CTRL ('W'): /* delete a word */ - if (curpos > 0) { - while (curpos && str[curpos - 1] == ' ') - { - del_char ((--curpos), str); - len--; - } - while (curpos && str[curpos - 1] != ' ') - { - del_char ((--curpos), str); - len--; - } - } - else - bell (); - break; - case CTRL ('K'): /* delete to end-of-line */ - str[curpos] = 0; - len = curpos; - break; - case CTRL ('A'): /* go to begginning of string */ - curpos = 0; - break; - case CTRL ('E'): /* go to end of string */ - curpos = len; - break; - case KEY_LEFT: /* move one char backward */ - case CTRL ('B'): - if (curpos > 0) curpos--; - break; - case KEY_RIGHT: /* move one char forward */ - case CTRL ('F'): - if (curpos < len) curpos++; - break; - case ESCAPE: /* cancel editing */ - return (GETSTRING_ESC); - break; - default: /* insert one character */ - if (len < l - 1) - { - ins_char ((curpos++), ch, str); - len++; - } - } - } - - custom_remove_attr (win, ATTR_HIGHEST); - - return (len == 0 ? GETSTRING_RET : GETSTRING_VALID); -} - -/* Update an already existing string. */ -int -updatestring (WINDOW *win, char **str, int x, int y) -{ - int len = strlen (*str); - char *buf; - enum getstr ret; - - EXIT_IF (len + 1 > BUFSIZ, _("Internal error: line too long")); - - buf = mem_malloc (BUFSIZ); - (void)memcpy (buf, *str, len + 1); - - ret = getstring (win, buf, BUFSIZ, x, y); - - if (ret == GETSTRING_VALID) - { - len = strlen (buf); - *str = mem_realloc (*str, len + 1, 1); - EXIT_IF (*str == NULL, _("out of memory")); - (void)memcpy (*str, buf, len + 1); - } - - mem_free (buf); - return ret; + custom_apply_attr(win, ATTR_HIGHEST); + mvwprintw(win, y, x, "%s", string); + custom_remove_attr(win, ATTR_HIGHEST); } /* checks if a string is only made of digits */ -int -is_all_digit (char *string) +int is_all_digit(const char *string) { - for (; *string; string++) - { - if (!isdigit ((int)*string)) - return 0; - } + for (; *string; string++) { + if (!isdigit((int)*string)) + return 0; + } return 1; } /* Given an item date expressed in seconds, return its start time in seconds. */ -long -get_item_time (long date) +long get_item_time(long date) { - return (long)(get_item_hour (date) * HOURINSEC + - get_item_min (date) * MININSEC); + return (long)(get_item_hour(date) * HOURINSEC + + get_item_min(date) * MININSEC); } -int -get_item_hour (long date) +int get_item_hour(long date) { - return (localtime ((time_t *)&date))->tm_hour; + return (localtime((time_t *) & date))->tm_hour; } -int -get_item_min (long date) +int get_item_min(long date) { - return (localtime ((time_t *)&date))->tm_min; + return (localtime((time_t *) & date))->tm_min; } -long -date2sec (struct date day, unsigned hour, unsigned min) +long date2sec(struct date day, unsigned hour, unsigned min) { - time_t t = now (); - struct tm start = *(localtime (&t)); + time_t t = now(); + struct tm start = *(localtime(&t)); start.tm_mon = day.mm - 1; start.tm_mday = day.dd; @@ -460,40 +361,37 @@ date2sec (struct date day, unsigned hour, unsigned min) start.tm_sec = 0; start.tm_isdst = -1; - t = mktime (&start); - EXIT_IF (t == -1, _("failure in mktime")); + t = mktime(&start); + EXIT_IF(t == -1, _("failure in mktime")); return t; } /* Return a string containing the date, given a date in seconds. */ -char * -date_sec2date_str (long sec, char *datefmt) +char *date_sec2date_str(long sec, const char *datefmt) { struct tm *lt; - char *datestr = (char *) mem_calloc (BUFSIZ, sizeof (char)); + char *datestr = (char *)mem_calloc(BUFSIZ, sizeof(char)); if (sec == 0) - (void)snprintf (datestr, BUFSIZ, "0"); - else - { - lt = localtime ((time_t *)&sec); - strftime (datestr, BUFSIZ, datefmt, lt); - } + strncpy(datestr, "0", BUFSIZ); + else { + lt = localtime((time_t *) & sec); + strftime(datestr, BUFSIZ, datefmt, lt); + } return datestr; } /* Generic function to format date. */ -void -date_sec2date_fmt (long sec, const char *fmt, char *datef) +void date_sec2date_fmt(long sec, const char *fmt, char *datef) { /* TODO: Find a better way to deal with localization and strftime(). */ char *locale_old = mem_strdup (setlocale (LC_ALL, NULL)); setlocale (LC_ALL, "C"); - struct tm *lt = localtime ((time_t *)&sec); - strftime (datef, BUFSIZ, fmt, lt); + struct tm *lt = localtime((time_t *)&sec); + strftime(datef, BUFSIZ, fmt, lt); setlocale (LC_ALL, locale_old); mem_free (locale_old); @@ -502,19 +400,18 @@ date_sec2date_fmt (long sec, const char *fmt, char *datef) /* * Used to change date by adding a certain amount of days or weeks. */ -long -date_sec_change (long date, int delta_month, int delta_day) +long date_sec_change(long date, int delta_month, int delta_day) { struct tm *lt; time_t t; t = date; - lt = localtime (&t); + lt = localtime(&t); lt->tm_mon += delta_month; lt->tm_mday += delta_day; lt->tm_isdst = -1; - t = mktime (lt); - EXIT_IF (t == -1, _("failure in mktime")); + t = mktime(lt); + EXIT_IF(t == -1, _("failure in mktime")); return t; } @@ -523,28 +420,26 @@ date_sec_change (long date, int delta_month, int delta_day) * Return a long containing the date which is updated taking into account * the new time and date entered by the user. */ -long -update_time_in_date (long date, unsigned hr, unsigned mn) +long update_time_in_date(long date, unsigned hr, unsigned mn) { struct tm *lt; time_t t, new_date; t = date; - lt = localtime (&t); + lt = localtime(&t); lt->tm_hour = hr; lt->tm_min = mn; - new_date = mktime (lt); - EXIT_IF (new_date == -1, _("error in mktime")); + new_date = mktime(lt); + EXIT_IF(new_date == -1, _("error in mktime")); - return (new_date); + return new_date; } /* * Returns the date in seconds from year 1900. * If no date is entered, current date is chosen. */ -long -get_sec_date (struct date date) +long get_sec_date(struct date date) { struct tm *ptrtime; time_t timer; @@ -553,56 +448,23 @@ get_sec_date (struct date date) char current_month[] = "mm "; char current_year[] = "yyyy "; - if (date.yyyy == 0 && date.mm == 0 && date.dd == 0) - { - timer = time (NULL); - ptrtime = localtime (&timer); - strftime (current_day, strlen (current_day), "%d", ptrtime); - strftime (current_month, strlen (current_month), "%m", ptrtime); - strftime (current_year, strlen (current_year), "%Y", ptrtime); - date.mm = atoi (current_month); - date.dd = atoi (current_day); - date.yyyy = atoi (current_year); - } - long_date = date2sec (date, 0, 0); - return (long_date); + if (date.yyyy == 0 && date.mm == 0 && date.dd == 0) { + timer = time(NULL); + ptrtime = localtime(&timer); + strftime(current_day, strlen(current_day), "%d", ptrtime); + strftime(current_month, strlen(current_month), "%m", ptrtime); + strftime(current_year, strlen(current_year), "%Y", ptrtime); + date.mm = atoi(current_month); + date.dd = atoi(current_day); + date.yyyy = atoi(current_year); + } + long_date = date2sec(date, 0, 0); + return long_date; } -long -min2sec (unsigned minutes) +long min2sec(unsigned minutes) { - return (minutes * MININSEC); -} - -/* - * Checks if a time has a good format. - * The format could be either HH:MM or H:MM or MM, and we should have: - * 0 <= HH <= 24 and 0 <= MM < 999. - * This function returns 1 if the entered time is correct and in - * [h:mm] or [hh:mm] format, and 2 if the entered time is correct and entered - * in [mm] format. - */ -int -check_time (char *string) -{ - char *s = mem_strdup(string); - char *hour = strtok(s, ":"); - char *min = strtok(NULL, ":"); - int h, m; - int ret = 0; - - if (min) - { - h = atoi (hour); - m = atoi (min); - if (h >= 0 && h < 24 && m >= 0 && m < MININSEC) - ret = 1; - } - else if (strlen(s) < 4 && is_all_digit(s) && atoi(s) > 0) - ret = 2; - - mem_free(s); - return ret; + return minutes * MININSEC; } /* @@ -610,17 +472,17 @@ check_time (char *string) * can not be displayed inside the corresponding panel. */ void -draw_scrollbar (WINDOW *win, int y, int x, int length, - int bar_top, int bar_bottom, unsigned hilt) +draw_scrollbar(WINDOW * win, int y, int x, int length, + int bar_top, int bar_bottom, unsigned hilt) { - mvwvline (win, bar_top, x, ACS_VLINE, bar_bottom - bar_top); + mvwvline(win, bar_top, x, ACS_VLINE, bar_bottom - bar_top); if (hilt) - custom_apply_attr (win, ATTR_HIGHEST); - wattron (win, A_REVERSE); - mvwvline (win, y, x, ' ', length); - wattroff (win, A_REVERSE); + custom_apply_attr(win, ATTR_HIGHEST); + wattron(win, A_REVERSE); + mvwvline(win, y, x, ' ', length); + wattroff(win, A_REVERSE); if (hilt) - custom_remove_attr (win, ATTR_HIGHEST); + custom_remove_attr(win, ATTR_HIGHEST); } /* @@ -629,121 +491,112 @@ draw_scrollbar (WINDOW *win, int y, int x, int length, * long to fit in its corresponding panel window. */ void -item_in_popup (char *saved_a_start, char *saved_a_end, char *msg, - char *pop_title) +item_in_popup(const char *saved_a_start, const char *saved_a_end, + const char *msg, const char *pop_title) { WINDOW *popup_win, *pad; const int margin_left = 4, margin_top = 4; const int winl = row - 5, winw = col - margin_left; const int padl = winl - 2, padw = winw - margin_left; - pad = newpad (padl, padw); - popup_win = popup (winl, winw, 1, 2, pop_title, (char *)0, 1); - if (strncmp (pop_title, _("Appointment"), 11) == 0) - { - mvwprintw (popup_win, margin_top, margin_left, "- %s -> %s", - saved_a_start, saved_a_end); - } - mvwprintw (pad, 0, margin_left, "%s", msg); - wmove (win[STA].p, 0, 0); - pnoutrefresh (pad, 0, 0, margin_top + 2, margin_left, padl, winw); - wins_doupdate (); - (void)wgetch (popup_win); - delwin (pad); - delwin (popup_win); + pad = newpad(padl, padw); + popup_win = popup(winl, winw, 1, 2, pop_title, NULL, 1); + if (strcmp(pop_title, _("Appointment")) == 0) { + mvwprintw(popup_win, margin_top, margin_left, "- %s -> %s", + saved_a_start, saved_a_end); + } + mvwprintw(pad, 0, margin_left, "%s", msg); + wmove(win[STA].p, 0, 0); + pnoutrefresh(pad, 0, 0, margin_top + 2, margin_left, padl, winw); + wins_doupdate(); + wgetch(popup_win); + delwin(pad); + delwin(popup_win); } /* Returns the beginning of current day in seconds from 1900. */ -long -get_today (void) +long get_today(void) { struct tm *lt; time_t current_time; long current_day; struct date day; - current_time = time (NULL); - lt = localtime (¤t_time); + current_time = time(NULL); + lt = localtime(¤t_time); day.mm = lt->tm_mon + 1; day.dd = lt->tm_mday; day.yyyy = lt->tm_year + 1900; - current_day = date2sec (day, 0, 0); + current_day = date2sec(day, 0, 0); - return (current_day); + return current_day; } /* Returns the current time in seconds. */ -long -now (void) +long now(void) { - return (long)time (NULL); + return (long)time(NULL); } -char * -nowstr (void) +char *nowstr(void) { static char buf[BUFSIZ]; - time_t t = now (); + time_t t = now(); - (void)strftime (buf, sizeof buf, "%a %b %d %T %Y", localtime (&t)); + strftime(buf, sizeof buf, "%a %b %d %T %Y", localtime(&t)); return buf; } -long -mystrtol (const char *str) +long mystrtol(const char *str) { char *ep; long lval; errno = 0; - lval = strtol (str, &ep, 10); + lval = strtol(str, &ep, 10); if (str[0] == '\0' || *ep != '\0') - EXIT (_("could not convert string")); + EXIT(_("could not convert string")); if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) - EXIT (_("out of range")); + EXIT(_("out of range")); - return (lval); + return lval; } /* Print the given option value with appropriate color. */ void -print_bool_option_incolor (WINDOW *win, unsigned option, int pos_y, int pos_x) +print_bool_option_incolor(WINDOW * win, unsigned option, int pos_y, int pos_x) { int color = 0; - char option_value[BUFSIZ] = ""; - - if (option == 1) - { - color = ATTR_TRUE; - strncpy (option_value, _("yes"), BUFSIZ); - } - else if (option == 0) - { - color = ATTR_FALSE; - strncpy (option_value, _("no"), BUFSIZ); - } - else - EXIT (_("option not defined")); - - custom_apply_attr (win, color); - mvwprintw (win, pos_y, pos_x, "%s", option_value); - custom_remove_attr (win, color); - wnoutrefresh (win); - wins_doupdate (); + const char *option_value; + + if (option == 1) { + color = ATTR_TRUE; + option_value = _("yes"); + } else if (option == 0) { + color = ATTR_FALSE; + option_value = _("no"); + } else + EXIT(_("option not defined")); + + custom_apply_attr(win, color); + mvwprintw(win, pos_y, pos_x, "%s", option_value); + custom_remove_attr(win, color); + wnoutrefresh(win); + wins_doupdate(); } - /* * Get the name of the default directory for temporary files. */ -const char * -get_tempdir (void) +const char *get_tempdir(void) { - if (getenv ("TMPDIR")) - return getenv ("TMPDIR"); + if (getenv("TMPDIR")) + return getenv("TMPDIR"); +#ifdef P_tmpdir else if (P_tmpdir) return P_tmpdir; +#endif else return "/tmp"; } @@ -752,53 +605,32 @@ get_tempdir (void) * Create a new unique file, and return a newly allocated string which contains * the random part of the file name. */ -char * -new_tempfile (const char *prefix, int trailing_len) +char *new_tempfile(const char *prefix, int trailing_len) { char fullname[BUFSIZ]; int prefix_len, fd; FILE *file; if (prefix == NULL) - return (NULL); + return NULL; - prefix_len = strlen (prefix); + prefix_len = strlen(prefix); if (prefix_len + trailing_len >= BUFSIZ) - return (NULL); - memcpy (fullname, prefix, prefix_len); - (void)memset (fullname + prefix_len, 'X', trailing_len); + return NULL; + memcpy(fullname, prefix, prefix_len); + memset(fullname + prefix_len, 'X', trailing_len); fullname[prefix_len + trailing_len] = '\0'; - if ((fd = mkstemp (fullname)) == -1 || (file = fdopen (fd, "w+")) == NULL) - { - if (fd != -1) - { - unlink (fullname); - close (fd); - } - ERROR_MSG (_("temporary file \"%s\" could not be created"), fullname); - return (char *)0; + if ((fd = mkstemp(fullname)) == -1 || (file = fdopen(fd, "w+")) == NULL) { + if (fd != -1) { + unlink(fullname); + close(fd); } - fclose (file); - - return mem_strdup (fullname + prefix_len); -} - -/* Erase a note previously attached to a todo, event or appointment. */ -void -erase_note (char **note, enum eraseflg flag) -{ - char fullname[BUFSIZ]; + ERROR_MSG(_("temporary file \"%s\" could not be created"), fullname); + return NULL; + } + fclose(file); - if (*note == NULL) - return; - if (flag != ERASE_FORCE_KEEP_NOTE) - { - (void)snprintf (fullname, BUFSIZ, "%s%s", path_notes, *note); - if (unlink (fullname) != 0) - EXIT (_("could not remove note")); - } - mem_free (*note); - *note = NULL; + return mem_strdup(fullname + prefix_len); } /* @@ -814,75 +646,68 @@ erase_note (char **note, enum eraseflg flag) * Returns 1 if sucessfully converted or 0 if the string is an invalid date. */ int -parse_date (char *date_string, enum datefmt datefmt, int *year, int *month, - int *day, struct date *slctd_date) +parse_date(const char *date_string, enum datefmt datefmt, int *year, + int *month, int *day, struct date *slctd_date) { - char sep = (datefmt == DATEFMT_ISO) ? '-' : '/'; - char *p; - int in[3] = {0, 0, 0}, n = 0; + const char sep = (datefmt == DATEFMT_ISO) ? '-' : '/'; + const char *p; + int in[3] = { 0, 0, 0 }, n = 0; int d, m, y; if (!date_string) return 0; /* parse string into in[], read up to three integers */ - for (p = date_string; *p; p++) - { - if (*p == sep) - { - if ((++n) > 2) - return 0; - } - else if ((*p >= '0') && (*p <= '9')) - in[n] = in[n] * 10 + (int)(*p - '0'); - else + for (p = date_string; *p; p++) { + if (*p == sep) { + if ((++n) > 2) return 0; - } + } else if ((*p >= '0') && (*p <= '9')) + in[n] = in[n] * 10 + (int)(*p - '0'); + else + return 0; + } if ((!slctd_date && n < 2) || in[n] == 0) return 0; /* convert into day, month and year, depending on the date format */ - switch (datefmt) - { - case DATEFMT_MMDDYYYY: - m = (n >= 1) ? in[0] : 0; - d = (n >= 1) ? in[1] : in[0]; - y = in[2]; - break; - case DATEFMT_DDMMYYYY: - d = in[0]; - m = in[1]; - y = in[2]; - break; - case DATEFMT_YYYYMMDD: - case DATEFMT_ISO: - y = (n >= 2) ? in[n - 2] : 0; - m = (n >= 1) ? in[n - 1] : 0; - d = in[n]; - break; - default: - return 0; - } + switch (datefmt) { + case DATEFMT_MMDDYYYY: + m = (n >= 1) ? in[0] : 0; + d = (n >= 1) ? in[1] : in[0]; + y = in[2]; + break; + case DATEFMT_DDMMYYYY: + d = in[0]; + m = in[1]; + y = in[2]; + break; + case DATEFMT_YYYYMMDD: + case DATEFMT_ISO: + y = (n >= 2) ? in[n - 2] : 0; + m = (n >= 1) ? in[n - 1] : 0; + d = in[n]; + break; + default: + return 0; + } - if (slctd_date) - { - if (y > 0 && y < 100) - { - /* convert "YY" format into "YYYY" */ - y += slctd_date->yyyy - slctd_date->yyyy % 100; - } - else if (n < 2) - { - /* set year and, optionally, month if short from is used */ - y = slctd_date->yyyy; - if (n < 1) m = slctd_date->mm; - } + if (slctd_date) { + if (y > 0 && y < 100) { + /* convert "YY" format into "YYYY" */ + y += slctd_date->yyyy - slctd_date->yyyy % 100; + } else if (n < 2) { + /* set year and, optionally, month if short from is used */ + y = slctd_date->yyyy; + if (n < 1) + m = slctd_date->mm; } + } /* check if date is valid, take leap years into account */ if (y < 1902 || y > 2037 || m < 1 || m > 12 || d < 1 || - d > days[m - 1] + (m == 2 && ISLEAP (y)) ? 1 : 0) + d > days[m - 1] + (m == 2 && ISLEAP(y)) ? 1 : 0) return 0; if (year) @@ -895,19 +720,142 @@ parse_date (char *date_string, enum datefmt datefmt, int *year, int *month, return 1; } -void -str_toupper (char *s) +/* + * Converts a time string into hours and minutes. Short forms like "23:" + * (23:00) or ":45" (0:45) are allowed. + * + * Returns 1 on success and 0 on failure. + */ +int parse_time(const char *string, unsigned *hour, unsigned *minute) +{ + const char *p; + unsigned in[2] = { 0, 0 }, n = 0; + + if (!string) + return 0; + + /* parse string into in[], read up to two integers */ + for (p = string; *p; p++) { + if (*p == ':') { + if ((++n) > 1) + return 0; + } else if ((*p >= '0') && (*p <= '9')) + in[n] = in[n] * 10 + (int)(*p - '0'); + else + return 0; + } + + if (n != 1 || in[0] >= DAYINHOURS || in[1] >= HOURINMIN) + return 0; + + *hour = in[0]; + *minute = in[1]; + return 1; +} + +/* + * Converts a duration string into minutes. + * + * Allowed formats (noted as regular expressions): + * + * - \d*:\d* + * - (\d*m|\d*h(|\d*m)|\d*d(|\d*m|\d*h(|\d*m))) + * - \d+ + * + * "\d" is used as a placeholder for "(0|1|2|3|4|5|6|7|8|9)". + * + * Returns 1 on success and 0 on failure. + */ +int parse_duration(const char *string, unsigned *duration) +{ + enum { + STATE_INITIAL, + STATE_HHMM_MM, + STATE_DDHHMM_HH, + STATE_DDHHMM_MM, + STATE_DONE + } state = STATE_INITIAL; + + const char *p; + unsigned in = 0; + unsigned dur = 0; + + if (!string || *string == '\0') + return 0; + + /* parse string using a simple state machine */ + for (p = string; *p; p++) { + if ((*p >= '0') && (*p <= '9')) { + if (state == STATE_DONE) + return 0; + else + in = in * 10 + (int)(*p - '0'); + } else { + switch (state) { + case STATE_INITIAL: + if (*p == ':') { + dur += in * HOURINMIN; + state = STATE_HHMM_MM; + } else if (*p == 'd') { + dur += in * DAYINMIN; + state = STATE_DDHHMM_HH; + } else if (*p == 'h') { + dur += in * HOURINMIN; + state = STATE_DDHHMM_MM; + } else if (*p == 'm') { + dur += in; + state = STATE_DONE; + } else + return 0; + break; + case STATE_DDHHMM_HH: + if (*p == 'h') { + dur += in * HOURINMIN; + state = STATE_DDHHMM_MM; + } else if (*p == 'm') { + dur += in; + state = STATE_DONE; + } else + return 0; + break; + case STATE_DDHHMM_MM: + if (*p == 'm') { + dur += in; + state = STATE_DONE; + } else + return 0; + break; + case STATE_HHMM_MM: + case STATE_DONE: + return 0; + break; + } + + in = 0; + } + } + + if ((state == STATE_HHMM_MM && in >= HOURINMIN) || + ((state == STATE_DDHHMM_HH || state == STATE_DDHHMM_MM) && in > 0)) + return 0; + + dur += in; + *duration = dur; + + return 1; +} + +void str_toupper(char *s) { if (!s) return; for (; *s; s++) - *s = toupper (*s); + *s = toupper(*s); } -void -file_close (FILE *f, const char *pos) +void file_close(FILE * f, const char *pos) { - EXIT_IF ((fclose (f)) != 0, _("Error when closing file at %s"), pos); + EXIT_IF((fclose(f)) != 0, _("Error when closing file at %s"), pos); } /* @@ -915,11 +863,482 @@ file_close (FILE *f, const char *pos) * (hence the 'p') in a way that even if a signal is caught during the sleep * process, this function will return to sleep afterwards. */ -void -psleep (unsigned secs) +void psleep(unsigned secs) { unsigned unslept; - for (unslept = sleep (secs); unslept; unslept = sleep (unslept)) - ; + for (unslept = sleep(secs); unslept; unslept = sleep(unslept)) ; +} + +/* + * Fork and execute an external process. + * + * If pfdin and/or pfdout point to a valid address, a pipe is created and the + * appropriate file descriptors are written to pfdin/pfdout. + */ +int fork_exec(int *pfdin, int *pfdout, const char *path, const char *const *arg) +{ + int pin[2], pout[2]; + int pid; + + if (pfdin && (pipe(pin) == -1)) + return 0; + if (pfdout && (pipe(pout) == -1)) + return 0; + + if ((pid = fork()) == 0) { + if (pfdout) { + if (dup2(pout[0], STDIN_FILENO) < 0) + _exit(127); + close(pout[0]); + close(pout[1]); + } + + if (pfdin) { + if (dup2(pin[1], STDOUT_FILENO) < 0) + _exit(127); + close(pin[0]); + close(pin[1]); + } + + execvp(path, (char *const *)arg); + _exit(127); + } else { + if (pfdin) + close(pin[1]); + if (pfdout) + close(pout[0]); + + if (pid > 0) { + if (pfdin) { + fcntl(pin[0], F_SETFD, FD_CLOEXEC); + *pfdin = pin[0]; + } + if (pfdout) { + fcntl(pout[1], F_SETFD, FD_CLOEXEC); + *pfdout = pout[1]; + } + } else { + if (pfdin) + close(pin[0]); + if (pfdout) + close(pout[1]); + return 0; + } + } + return pid; +} + +/* Execute an external program in a shell. */ +int +shell_exec(int *pfdin, int *pfdout, const char *path, const char *const *arg) +{ + int argc, i; + const char **narg; + char *arg0 = NULL; + int ret; + + for (argc = 0; arg[argc]; argc++) ; + + if (argc < 1) + return -1; + + narg = mem_calloc(argc + 4, sizeof(const char *)); + + narg[0] = "sh"; + narg[1] = "-c"; + + if (argc > 1) { + arg0 = mem_malloc(strlen(path) + 6); + sprintf(arg0, "%s \"$@\"", path); + narg[2] = arg0; + + for (i = 0; i < argc; i++) + narg[i + 3] = arg[i]; + narg[argc + 3] = NULL; + } else { + narg[2] = path; + narg[3] = NULL; + } + + ret = fork_exec(pfdin, pfdout, *narg, narg); + + if (arg0) + mem_free(arg0); + mem_free(narg); + + return ret; +} + +/* Wait for a child process to terminate. */ +int child_wait(int *pfdin, int *pfdout, int pid) +{ + int stat; + + if (pfdin) + close(*pfdin); + if (pfdout) + close(*pfdout); + + waitpid(pid, &stat, 0); + return stat; +} + +/* Display "Press any key to continue..." and wait for a key press. */ +void press_any_key(void) +{ + struct termios t_attr_old, t_attr; + + tcgetattr(STDIN_FILENO, &t_attr_old); + memcpy(&t_attr, &t_attr_old, sizeof(struct termios)); + t_attr.c_lflag &= ~(ICANON | ECHO | ECHONL); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_attr); + + fflush(stdout); + fputs(_("Press any key to continue..."), stdout); + fflush(stdout); + fgetc(stdin); + fflush(stdin); + fputs("\r\n", stdout); + + tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_attr_old); +} + +/* + * Display note contents if one is asociated with the currently displayed item + * (to be used together with the '-a' or '-t' flag in non-interactive mode). + * Each line begins with nbtab tabs. + * Print "No note file found", if the notefile does not exists. + * + * (patch submitted by Erik Saule). + */ +static void print_notefile(FILE * out, const char *filename, int nbtab) +{ + char path_to_notefile[BUFSIZ]; + FILE *notefile; + char linestarter[BUFSIZ]; + char buffer[BUFSIZ]; + int i; + int printlinestarter = 1; + + if (nbtab < BUFSIZ) { + for (i = 0; i < nbtab; i++) + linestarter[i] = '\t'; + linestarter[nbtab] = '\0'; + } else + linestarter[0] = '\0'; + + snprintf(path_to_notefile, BUFSIZ, "%s/%s", path_notes, filename); + notefile = fopen(path_to_notefile, "r"); + if (notefile) { + while (fgets(buffer, BUFSIZ, notefile) != 0) { + if (printlinestarter) { + fputs(linestarter, out); + printlinestarter = 0; + } + fputs(buffer, out); + if (buffer[strlen(buffer) - 1] == '\n') + printlinestarter = 1; + } + fputs("\n", out); + file_close(notefile, __FILE_POS__); + } else { + fputs(linestarter, out); + fputs(_("No note file found\n"), out); + } +} + +/* Print an escape sequence and return its length. */ +static int print_escape(const char *s) +{ + switch (*(s + 1)) { + case 'a': + putchar('\a'); + return 1; + case 'b': + putchar('\b'); + return 1; + case 'f': + putchar('\f'); + return 1; + case 'n': + putchar('\n'); + return 1; + case 'r': + putchar('\r'); + return 1; + case 't': + putchar('\t'); + return 1; + case 'v': + putchar('\v'); + return 1; + case '0': + putchar('\0'); + return 1; + case '\'': + putchar('\''); + return 1; + case '"': + putchar('"'); + return 1; + case '\?': + putchar('?'); + return 1; + case '\\': + putchar('\\'); + return 1; + case '\0': + return 0; + default: + return 1; + } +} + +/* Parse a format specifier. */ +static enum format_specifier parse_fs(const char **s, char *extformat) +{ + char buf[FS_EXT_MAXLEN]; + int i; + + extformat[0] = '\0'; + + switch (**s) { + case 's': + strcpy(extformat, "epoch"); + return FS_STARTDATE; + case 'S': + return FS_STARTDATE; + case 'd': + return FS_DURATION; + case 'e': + strcpy(extformat, "epoch"); + return FS_ENDDATE; + case 'E': + return FS_ENDDATE; + case 'm': + return FS_MESSAGE; + case 'n': + return FS_NOTE; + case 'N': + return FS_NOTEFILE; + case 'p': + return FS_PRIORITY; + case '(': + /* Long format specifier. */ + for ((*s)++, i = 0; **s != ':' && **s != ')'; (*s)++, i++) { + if (**s == '\0') + return FS_EOF; + + if (i < FS_EXT_MAXLEN) + buf[i] = **s; + } + + buf[(i < FS_EXT_MAXLEN) ? i : FS_EXT_MAXLEN - 1] = '\0'; + + if (**s == ':') { + for ((*s)++, i = 0; **s != ')'; (*s)++, i++) { + if (**s == '\0') + return FS_EOF; + + if (i < FS_EXT_MAXLEN) + extformat[i] = **s; + } + + extformat[(i < FS_EXT_MAXLEN) ? i : FS_EXT_MAXLEN - 1] = '\0'; + } + + if (!strcmp(buf, "start")) + return FS_STARTDATE; + else if (!strcmp(buf, "duration")) + return FS_DURATION; + else if (!strcmp(buf, "end")) + return FS_ENDDATE; + else if (!strcmp(buf, "message")) + return FS_MESSAGE; + else if (!strcmp(buf, "noteid")) + return FS_NOTE; + else if (!strcmp(buf, "note")) + return FS_NOTEFILE; + else if (!strcmp(buf, "priority")) + return FS_PRIORITY; + else + return FS_UNKNOWN; + case '%': + return FS_PSIGN; + case '\0': + return FS_EOF; + default: + return FS_UNKNOWN; + } +} + +/* Print a formatted date to stdout. */ +static void print_date(long date, long day, const char *extformat) +{ + char buf[BUFSIZ]; + + if (!strcmp(extformat, "epoch")) + printf("%ld", date); + else { + time_t t = date; + struct tm *lt = localtime((time_t *) & t); + + if (extformat[0] == '\0' || !strcmp(extformat, "default")) { + if (date >= day && date <= day + DAYINSEC) + strftime(buf, BUFSIZ, "%H:%M", lt); + else + strftime(buf, BUFSIZ, "..:..", lt); + } else { + strftime(buf, BUFSIZ, extformat, lt); + } + + printf("%s", buf); + } +} + +/* Print a formatted appointment to stdout. */ +void print_apoint(const char *format, long day, struct apoint *apt) +{ + const char *p; + char extformat[FS_EXT_MAXLEN]; + + for (p = format; *p; p++) { + if (*p == '%') { + p++; + switch (parse_fs(&p, extformat)) { + case FS_STARTDATE: + print_date(apt->start, day, extformat); + break; + case FS_DURATION: + printf("%ld", apt->dur); + break; + case FS_ENDDATE: + print_date(apt->start + apt->dur, day, extformat); + break; + case FS_MESSAGE: + printf("%s", apt->mesg); + break; + case FS_NOTE: + printf("%s", apt->note); + break; + case FS_NOTEFILE: + print_notefile(stdout, apt->note, 1); + break; + case FS_PSIGN: + putchar('%'); + break; + case FS_EOF: + return; + break; + default: + putchar('?'); + break; + } + } else if (*p == '\\') + p += print_escape(p); + else + putchar(*p); + } +} + +/* Print a formatted event to stdout. */ +void print_event(const char *format, long day, struct event *ev) +{ + const char *p; + char extformat[FS_EXT_MAXLEN]; + + for (p = format; *p; p++) { + if (*p == '%') { + p++; + switch (parse_fs(&p, extformat)) { + case FS_MESSAGE: + printf("%s", ev->mesg); + break; + case FS_NOTE: + printf("%s", ev->note); + break; + case FS_NOTEFILE: + print_notefile(stdout, ev->note, 1); + break; + case FS_PSIGN: + putchar('%'); + break; + case FS_EOF: + return; + break; + default: + putchar('?'); + break; + } + } else if (*p == '\\') + p += print_escape(p); + else + putchar(*p); + } +} + +/* Print a formatted recurrent appointment to stdout. */ +void +print_recur_apoint(const char *format, long day, unsigned occurrence, + struct recur_apoint *rapt) +{ + struct apoint apt; + + apt.start = occurrence; + apt.dur = rapt->dur; + apt.mesg = rapt->mesg; + apt.note = rapt->note; + + print_apoint(format, day, &apt); +} + +/* Print a formatted recurrent event to stdout. */ +void print_recur_event(const char *format, long day, struct recur_event *rev) +{ + struct event ev; + + ev.mesg = rev->mesg; + ev.note = rev->note; + + print_event(format, day, &ev); +} + +/* Print a formatted todo item to stdout. */ +void print_todo(const char *format, struct todo *todo) +{ + const char *p; + char extformat[FS_EXT_MAXLEN]; + + for (p = format; *p; p++) { + if (*p == '%') { + p++; + switch (parse_fs(&p, extformat)) { + case FS_PRIORITY: + printf("%d", abs(todo->id)); + break; + case FS_MESSAGE: + printf("%s", todo->mesg); + break; + case FS_NOTE: + printf("%s", todo->note); + break; + case FS_NOTEFILE: + print_notefile(stdout, todo->note, 1); + break; + case FS_PSIGN: + putchar('%'); + break; + case FS_EOF: + return; + break; + default: + putchar('?'); + break; + } + } else if (*p == '\\') + p += print_escape(p); + else + putchar(*p); + } } @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,9 @@ int resize = 0; /* variable to tell if the terminal supports color */ unsigned colorize = 0; +/* Default background and foreground colors. */ +int foreground, background; + /* * To tell if curses interface was launched already or not (in that case * calcurse is running in command-line mode). @@ -55,11 +58,15 @@ unsigned colorize = 0; */ enum ui_mode ui_mode = UI_CMDLINE; +/* Don't save anything if this is set. */ +int read_only = 0; + /* * variables to store calendar names */ int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -char *monthnames[12] = { + +const char *monthnames[12] = { N_("January"), N_("February"), N_("March"), @@ -74,7 +81,7 @@ char *monthnames[12] = { N_("December") }; -char *daynames[8] = { +const char *daynames[8] = { N_("Sun"), N_("Mon"), N_("Tue"), @@ -99,6 +106,9 @@ char path_cpid[] = ""; char path_dpid[] = ""; char path_dmon_log[] = ""; +/* Variable to store global configuration. */ +struct conf conf; + /* Variable to handle pads. */ struct pad apad; @@ -111,45 +121,45 @@ struct dmon_conf dmon; /* * Variables init */ -void -vars_init (struct conf *conf) +void vars_init(void) { - char *ed, *pg; + const char *ed, *pg; /* Variables for user configuration */ - conf->confirm_quit = 1; - conf->confirm_delete = 1; - conf->auto_save = 1; - conf->periodic_save = 0; - conf->skip_system_dialogs = 0; - conf->skip_progress_bar = 0; - (void)strncpy (conf->output_datefmt, "%D", 3); - conf->input_datefmt = 1; + conf.confirm_quit = 1; + conf.confirm_delete = 1; + conf.auto_save = 1; + conf.auto_gc = 0; + conf.periodic_save = 0; + conf.system_dialogs = 1; + conf.progress_bar = 1; + strncpy(conf.output_datefmt, "%D", 3); + conf.input_datefmt = 1; /* Default external editor and pager */ - ed = getenv ("VISUAL"); + ed = getenv("VISUAL"); if (ed == NULL || ed[0] == '\0') - ed = getenv ("EDITOR"); + ed = getenv("EDITOR"); if (ed == NULL || ed[0] == '\0') ed = DEFAULT_EDITOR; - conf->editor = ed; + conf.editor = ed; - pg = getenv ("PAGER"); + pg = getenv("PAGER"); if (pg == NULL || pg[0] == '\0') pg = DEFAULT_PAGER; - conf->pager = pg; + conf.pager = pg; - wins_set_layout (1); + wins_set_layout(1); - calendar_set_first_day_of_week (MONDAY); + calendar_set_first_day_of_week(MONDAY); /* Pad structure to scroll text inside the appointment panel */ apad.length = 1; apad.first_onscreen = 0; /* Attribute definitions for color and non-color terminals */ - custom_init_attr (); + custom_init_attr(); /* Start at the current date */ - calendar_init_slctd_day (); + calendar_init_slctd_day(); } @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2011 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2012 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ struct window win[NBWINS]; /* User-configurable side bar width. */ -static unsigned sbarwidth; +static unsigned sbarwidth_perc; static enum win slctd_win; static int layout; @@ -63,93 +63,85 @@ static int layout; */ static pthread_mutex_t screen_mutex = PTHREAD_MUTEX_INITIALIZER; -static unsigned -screen_acquire (void) +static unsigned screen_acquire(void) { - if (pthread_mutex_lock (&screen_mutex) != 0) + if (pthread_mutex_lock(&screen_mutex) != 0) return 0; else return 1; } -static void -screen_release (void) +static void screen_release(void) { - (void)pthread_mutex_unlock (&screen_mutex); + pthread_mutex_unlock(&screen_mutex); } -int -wins_refresh (void) +int wins_refresh(void) { int rc; - if (!screen_acquire ()) + if (!screen_acquire()) return ERR; - rc = refresh (); - screen_release (); + rc = refresh(); + screen_release(); return rc; } -int -wins_wrefresh (WINDOW *win) +int wins_wrefresh(WINDOW * win) { int rc; - if (!win || !screen_acquire ()) + if (!win || !screen_acquire()) return ERR; - rc = wrefresh (win); - screen_release (); + rc = wrefresh(win); + screen_release(); return rc; } -int -wins_doupdate (void) +int wins_doupdate(void) { int rc; - if (!screen_acquire ()) + if (!screen_acquire()) return ERR; - rc = doupdate (); - screen_release (); + rc = doupdate(); + screen_release(); return rc; } /* Get the current layout. */ -int -wins_layout (void) +int wins_layout(void) { return layout; } /* Set the current layout. */ -void -wins_set_layout (int nb) +void wins_set_layout(int nb) { layout = nb; } /* Get the current side bar width. */ -unsigned -wins_sbar_width (void) +unsigned wins_sbar_width(void) { - return sbarwidth ? sbarwidth : SBARMINWIDTH; + if (sbarwidth_perc > SBARMAXWIDTHPERC) + return col * SBARMAXWIDTHPERC / 100; + else { + unsigned sbarwidth = (unsigned)(col * sbarwidth_perc / 100); + return (sbarwidth < SBARMINWIDTH) ? SBARMINWIDTH : sbarwidth; + } } /* * Return the side bar width in percentage of the total number of columns * available in calcurse's screen. */ -unsigned -wins_sbar_wperc (void) +unsigned wins_sbar_wperc(void) { - unsigned perc; - - perc = col ? (unsigned)(100 * sbarwidth / col + 1): 0; - - return perc > SBARMAXWIDTHPERC ? SBARMAXWIDTHPERC : perc; + return sbarwidth_perc > SBARMAXWIDTHPERC ? SBARMAXWIDTHPERC : sbarwidth_perc; } /* @@ -158,62 +150,44 @@ wins_sbar_wperc (void) * The side bar could not have a width representing more than 50% of the screen, * and could not be less than SBARMINWIDTH characters. */ -void -wins_set_sbar_width (unsigned perc) +void wins_set_sbar_width(unsigned perc) { - if (perc > SBARMAXWIDTHPERC) - sbarwidth = col * SBARMAXWIDTHPERC / 100; - else if (perc <= 0) - sbarwidth = SBARMINWIDTH; - else - { - sbarwidth = (unsigned)(col * perc / 100); - if (sbarwidth < SBARMINWIDTH) - sbarwidth = SBARMINWIDTH; - } + sbarwidth_perc = perc; } /* Change the width of the side bar within acceptable boundaries. */ -void -wins_sbar_winc (void) +void wins_sbar_winc(void) { - if (sbarwidth < SBARMINWIDTH) - sbarwidth = SBARMINWIDTH + 1; - else if (sbarwidth < SBARMAXWIDTHPERC * col / 100) - sbarwidth++; + if (sbarwidth_perc < SBARMAXWIDTHPERC) + sbarwidth_perc++; } -void -wins_sbar_wdec (void) +void wins_sbar_wdec(void) { - if (sbarwidth > SBARMINWIDTH) - sbarwidth--; + if (sbarwidth_perc > 0) + sbarwidth_perc--; } /* Initialize the selected window in calcurse's interface. */ -void -wins_slctd_init (void) +void wins_slctd_init(void) { - wins_slctd_set (CAL); + wins_slctd_set(CAL); } /* Returns an enum which corresponds to the window which is selected. */ -enum win -wins_slctd (void) +enum win wins_slctd(void) { - return (slctd_win); + return slctd_win; } /* Sets the selected window. */ -void -wins_slctd_set (enum win window) +void wins_slctd_set(enum win window) { slctd_win = window; } /* TAB key was hit in the interface, need to select next window. */ -void -wins_slctd_next (void) +void wins_slctd_next(void) { if (slctd_win == TOD) slctd_win = CAL; @@ -221,39 +195,32 @@ wins_slctd_next (void) slctd_win++; } -static void -wins_init_panels (void) +static void wins_init_panels(void) { - char label[BUFSIZ]; - - win[CAL].p = newwin (CALHEIGHT, wins_sbar_width (), win[CAL].y, win[CAL].x); - (void)snprintf (label, BUFSIZ, _("Calendar")); - wins_show (win[CAL].p, label); + win[CAL].p = newwin(CALHEIGHT, wins_sbar_width(), win[CAL].y, win[CAL].x); + wins_show(win[CAL].p, _("Calendar")); - win[APP].p = newwin (win[APP].h, win[APP].w, win[APP].y, win[APP].x); - (void)snprintf (label, BUFSIZ, _("Appointments")); - wins_show (win[APP].p, label); + win[APP].p = newwin(win[APP].h, win[APP].w, win[APP].y, win[APP].x); + wins_show(win[APP].p, _("Appointments")); apad.width = win[APP].w - 3; - apad.ptrwin = newpad (apad.length, apad.width); + apad.ptrwin = newpad(apad.length, apad.width); - win[TOD].p = newwin (win[TOD].h, win[TOD].w, win[TOD].y, win[TOD].x); - (void)snprintf (label, BUFSIZ, _("ToDo")); - wins_show (win[TOD].p, label); + win[TOD].p = newwin(win[TOD].h, win[TOD].w, win[TOD].y, win[TOD].x); + wins_show(win[TOD].p, _("ToDo")); /* Enable function keys (i.e. arrow keys) in those windows */ - keypad (win[CAL].p, TRUE); - keypad (win[APP].p, TRUE); - keypad (win[TOD].p, TRUE); + keypad(win[CAL].p, TRUE); + keypad(win[APP].p, TRUE); + keypad(win[TOD].p, TRUE); } /* Create all the windows. */ -void -wins_init (void) +void wins_init(void) { - wins_init_panels (); - win[STA].p = newwin (win[STA].h, win[STA].w, win[STA].y, win[STA].x); + wins_init_panels(); + win[STA].p = newwin(win[STA].h, win[STA].w, win[STA].y, win[STA].x); - keypad (win[STA].p, TRUE); + keypad(win[STA].p, TRUE); /* Notify that the curses mode is now launched. */ ui_mode = UI_CURSES; @@ -263,116 +230,105 @@ wins_init (void) * Create a new window and its associated pad, which is used to make the * scrolling faster. */ -void -wins_scrollwin_init (struct scrollwin *sw) +void wins_scrollwin_init(struct scrollwin *sw) { - EXIT_IF (sw == NULL, "null pointer"); - sw->win.p = newwin (sw->win.h, sw->win.w, sw->win.y, sw->win.x); - sw->pad.p = newpad (sw->pad.h, sw->pad.w); + EXIT_IF(sw == NULL, "null pointer"); + sw->win.p = newwin(sw->win.h, sw->win.w, sw->win.y, sw->win.x); + sw->pad.p = newpad(sw->pad.h, sw->pad.w); sw->first_visible_line = 0; sw->total_lines = 0; } /* Free an already created scrollwin. */ -void -wins_scrollwin_delete (struct scrollwin *sw) +void wins_scrollwin_delete(struct scrollwin *sw) { - EXIT_IF (sw == NULL, "null pointer"); + EXIT_IF(sw == NULL, "null pointer"); delwin(sw->win.p); delwin(sw->pad.p); } /* Display a scrolling window. */ -void -wins_scrollwin_display (struct scrollwin *sw) +void wins_scrollwin_display(struct scrollwin *sw) { const int visible_lines = sw->win.h - sw->pad.y - 1; - if (sw->total_lines > visible_lines) - { - float ratio = ((float) visible_lines) / ((float) sw->total_lines); - int sbar_length = (int) (ratio * visible_lines); - int highend = (int) (ratio * sw->first_visible_line); - int sbar_top = highend + sw->pad.y + 1; + if (sw->total_lines > visible_lines) { + float ratio = ((float)visible_lines) / ((float)sw->total_lines); + int sbar_length = (int)(ratio * visible_lines); + int highend = (int)(ratio * sw->first_visible_line); + int sbar_top = highend + sw->pad.y + 1; - if ((sbar_top + sbar_length) > sw->win.h - 1) - sbar_length = sw->win.h - sbar_top; - draw_scrollbar (sw->win.p, sbar_top, sw->win.w + sw->win.x - 2, - sbar_length, sw->pad.y + 1, sw->win.h - 1, 1); - } - wmove (win[STA].p, 0, 0); - wnoutrefresh (sw->win.p); - pnoutrefresh (sw->pad.p, sw->first_visible_line, 0, sw->pad.y, sw->pad.x, - sw->win.h - sw->pad.y + 1, sw->win.w - sw->win.x); - wins_doupdate (); + if ((sbar_top + sbar_length) > sw->win.h - 1) + sbar_length = sw->win.h - sbar_top; + draw_scrollbar(sw->win.p, sbar_top, sw->win.w + sw->win.x - 2, + sbar_length, sw->pad.y + 1, sw->win.h - 1, 1); + } + wmove(win[STA].p, 0, 0); + wnoutrefresh(sw->win.p); + pnoutrefresh(sw->pad.p, sw->first_visible_line, 0, sw->pad.y, sw->pad.x, + sw->win.h - sw->pad.y + 1, sw->win.w - sw->win.x); + wins_doupdate(); } -void -wins_scrollwin_up (struct scrollwin *sw, int amount) +void wins_scrollwin_up(struct scrollwin *sw, int amount) { if (sw->first_visible_line > 0) sw->first_visible_line -= amount; } -void -wins_scrollwin_down (struct scrollwin *sw, int amount) +void wins_scrollwin_down(struct scrollwin *sw, int amount) { - if (sw->total_lines - > (sw->first_visible_line + sw->win.h - sw->pad.y - 1)) + if (sw->total_lines > (sw->first_visible_line + sw->win.h - sw->pad.y - 1)) sw->first_visible_line += amount; } -void -wins_reinit_panels (void) +void wins_reinit_panels(void) { - delwin (win[CAL].p); - delwin (win[APP].p); - delwin (apad.ptrwin); - delwin (win[TOD].p); - wins_get_config (); - wins_init_panels (); + delwin(win[CAL].p); + delwin(win[APP].p); + delwin(apad.ptrwin); + delwin(win[TOD].p); + wins_get_config(); + wins_init_panels(); } /* * Delete the existing windows and recreate them with their new * size and placement. */ -void -wins_reinit (void) +void wins_reinit(void) { - delwin (win[CAL].p); - delwin (win[APP].p); - delwin (apad.ptrwin); - delwin (win[TOD].p); - delwin (win[STA].p); - wins_get_config (); - wins_init (); - if (notify_bar ()) - notify_reinit_bar (); + delwin(win[CAL].p); + delwin(win[APP].p); + delwin(apad.ptrwin); + delwin(win[TOD].p); + delwin(win[STA].p); + wins_get_config(); + wins_init(); + if (notify_bar()) + notify_reinit_bar(); } /* Show the window with a border and a label. */ -void -wins_show (WINDOW *win, char *label) +void wins_show(WINDOW * win, const char *label) { - int width = getmaxx (win); + int width = getmaxx(win); - box (win, 0, 0); - mvwaddch (win, 2, 0, ACS_LTEE); - mvwhline (win, 2, 1, ACS_HLINE, width - 2); - mvwaddch (win, 2, width - 1, ACS_RTEE); + box(win, 0, 0); + mvwaddch(win, 2, 0, ACS_LTEE); + mvwhline(win, 2, 1, ACS_HLINE, width - 2); + mvwaddch(win, 2, width - 1, ACS_RTEE); - print_in_middle (win, 1, 0, width, label); + print_in_middle(win, 1, 0, width, label); } /* * Get the screen size and recalculate the windows configurations. */ -void -wins_get_config (void) +void wins_get_config(void) { /* Get the screen configuration */ - getmaxyx (stdscr, row, col); + getmaxyx(stdscr, row, col); /* fixed values for status, notification bars and calendar */ win[STA].h = STATUSHEIGHT; @@ -380,267 +336,243 @@ wins_get_config (void) win[STA].y = row - win[STA].h; win[STA].x = 0; - if (notify_bar ()) - { - win[NOT].h = 1; - win[NOT].w = col; - win[NOT].y = win[STA].y - 1; - win[NOT].x = 0; - } - else - { - win[NOT].h = 0; - win[NOT].w = 0; - win[NOT].y = 0; - win[NOT].x = 0; - } - - win[CAL].w = wins_sbar_width (); + if (notify_bar()) { + win[NOT].h = 1; + win[NOT].w = col; + win[NOT].y = win[STA].y - 1; + win[NOT].x = 0; + } else { + win[NOT].h = 0; + win[NOT].w = 0; + win[NOT].y = 0; + win[NOT].x = 0; + } + + win[CAL].w = wins_sbar_width(); win[CAL].h = CALHEIGHT; - if (layout <= 4) - { /* APPOINTMENT is the biggest panel */ - win[APP].w = col - win[CAL].w; - win[APP].h = row - (win[STA].h + win[NOT].h); - win[TOD].w = win[CAL].w; - win[TOD].h = row - (win[CAL].h + win[STA].h + win[NOT].h); - } - else - { /* TODO is the biggest panel */ - win[TOD].w = col - win[CAL].w; - win[TOD].h = row - (win[STA].h + win[NOT].h); - win[APP].w = win[CAL].w; - win[APP].h = row - (win[CAL].h + win[STA].h + win[NOT].h); - } + if (layout <= 4) { /* APPOINTMENT is the biggest panel */ + win[APP].w = col - win[CAL].w; + win[APP].h = row - (win[STA].h + win[NOT].h); + win[TOD].w = win[CAL].w; + win[TOD].h = row - (win[CAL].h + win[STA].h + win[NOT].h); + } else { /* TODO is the biggest panel */ + win[TOD].w = col - win[CAL].w; + win[TOD].h = row - (win[STA].h + win[NOT].h); + win[APP].w = win[CAL].w; + win[APP].h = row - (win[CAL].h + win[STA].h + win[NOT].h); + } /* defining the layout */ - switch (layout) - { - case 1: - win[APP].y = 0; - win[APP].x = 0; - win[CAL].y = 0; - win[TOD].x = win[APP].w; - win[TOD].y = win[CAL].h; - win[CAL].x = win[APP].w; - break; - case 2: - win[APP].y = 0; - win[APP].x = 0; - win[TOD].y = 0; - win[TOD].x = win[APP].w; - win[CAL].x = win[APP].w; - win[CAL].y = win[TOD].h; - break; - case 3: - win[APP].y = 0; - win[TOD].x = 0; - win[CAL].x = 0; - win[CAL].y = 0; - win[APP].x = win[CAL].w; - win[TOD].y = win[CAL].h; - break; - case 4: - win[APP].y = 0; - win[TOD].x = 0; - win[TOD].y = 0; - win[CAL].x = 0; - win[APP].x = win[CAL].w; - win[CAL].y = win[TOD].h; - break; - case 5: - win[TOD].y = 0; - win[TOD].x = 0; - win[CAL].y = 0; - win[APP].y = win[CAL].h; - win[APP].x = win[TOD].w; - win[CAL].x = win[TOD].w; - break; - case 6: - win[TOD].y = 0; - win[TOD].x = 0; - win[APP].y = 0; - win[APP].x = win[TOD].w; - win[CAL].x = win[TOD].w; - win[CAL].y = win[APP].h; - break; - case 7: - win[TOD].y = 0; - win[APP].x = 0; - win[CAL].x = 0; - win[CAL].y = 0; - win[TOD].x = win[CAL].w; - win[APP].y = win[CAL].h; - break; - case 8: - win[TOD].y = 0; - win[APP].x = 0; - win[CAL].x = 0; - win[APP].y = 0; - win[TOD].x = win[CAL].w; - win[CAL].y = win[APP].h; - break; - } + switch (layout) { + case 1: + win[APP].y = 0; + win[APP].x = 0; + win[CAL].y = 0; + win[TOD].x = win[APP].w; + win[TOD].y = win[CAL].h; + win[CAL].x = win[APP].w; + break; + case 2: + win[APP].y = 0; + win[APP].x = 0; + win[TOD].y = 0; + win[TOD].x = win[APP].w; + win[CAL].x = win[APP].w; + win[CAL].y = win[TOD].h; + break; + case 3: + win[APP].y = 0; + win[TOD].x = 0; + win[CAL].x = 0; + win[CAL].y = 0; + win[APP].x = win[CAL].w; + win[TOD].y = win[CAL].h; + break; + case 4: + win[APP].y = 0; + win[TOD].x = 0; + win[TOD].y = 0; + win[CAL].x = 0; + win[APP].x = win[CAL].w; + win[CAL].y = win[TOD].h; + break; + case 5: + win[TOD].y = 0; + win[TOD].x = 0; + win[CAL].y = 0; + win[APP].y = win[CAL].h; + win[APP].x = win[TOD].w; + win[CAL].x = win[TOD].w; + break; + case 6: + win[TOD].y = 0; + win[TOD].x = 0; + win[APP].y = 0; + win[APP].x = win[TOD].w; + win[CAL].x = win[TOD].w; + win[CAL].y = win[APP].h; + break; + case 7: + win[TOD].y = 0; + win[APP].x = 0; + win[CAL].x = 0; + win[CAL].y = 0; + win[TOD].x = win[CAL].w; + win[APP].y = win[CAL].h; + break; + case 8: + win[TOD].y = 0; + win[APP].x = 0; + win[CAL].x = 0; + win[APP].y = 0; + win[TOD].x = win[CAL].w; + win[CAL].y = win[APP].h; + break; + } } /* draw panel border in color */ -static void -border_color (WINDOW *window) +static void border_color(WINDOW * window) { int color_attr = A_BOLD; int no_color_attr = A_BOLD; - if (colorize) - { - wattron (window, color_attr | COLOR_PAIR (COLR_CUSTOM)); - box (window, 0, 0); - } - else - { - wattron (window, no_color_attr); - box (window, 0, 0); - } - if (colorize) - { - wattroff (window, color_attr | COLOR_PAIR (COLR_CUSTOM)); - } - else - { - wattroff (window, no_color_attr); - } - wnoutrefresh (window); + if (colorize) { + wattron(window, color_attr | COLOR_PAIR(COLR_CUSTOM)); + box(window, 0, 0); + } else { + wattron(window, no_color_attr); + box(window, 0, 0); + } + if (colorize) { + wattroff(window, color_attr | COLOR_PAIR(COLR_CUSTOM)); + } else { + wattroff(window, no_color_attr); + } + wnoutrefresh(window); } /* draw panel border without any color */ -static void -border_nocolor (WINDOW *window) +static void border_nocolor(WINDOW * window) { int color_attr = A_BOLD; int no_color_attr = A_DIM; - if (colorize) - { - wattron (window, color_attr | COLOR_PAIR (COLR_DEFAULT)); - } - else - { - wattron (window, no_color_attr); - } - box (window, 0, 0); - if (colorize) - { - wattroff (window, color_attr | COLOR_PAIR (COLR_DEFAULT)); - } - else - { - wattroff (window, no_color_attr); - } - wnoutrefresh (window); -} - -void -wins_update_border (void) -{ - switch (slctd_win) - { - case CAL: - border_color (win[CAL].p); - border_nocolor (win[APP].p); - border_nocolor (win[TOD].p); - break; - case APP: - border_color (win[APP].p); - border_nocolor (win[CAL].p); - border_nocolor (win[TOD].p); - break; - case TOD: - border_color (win[TOD].p); - border_nocolor (win[APP].p); - border_nocolor (win[CAL].p); - break; - default: - EXIT (_("no window selected")); - /* NOTREACHED */ - } -} - -void -wins_update_panels (void) -{ - apoint_update_panel (slctd_win); - todo_update_panel (slctd_win); - calendar_update_panel (&win[CAL]); + if (colorize) { + wattron(window, color_attr | COLOR_PAIR(COLR_DEFAULT)); + } else { + wattron(window, no_color_attr); + } + box(window, 0, 0); + if (colorize) { + wattroff(window, color_attr | COLOR_PAIR(COLR_DEFAULT)); + } else { + wattroff(window, no_color_attr); + } + wnoutrefresh(window); +} + +void wins_update_border(int flags) +{ + if (flags & FLAG_CAL) { + if (slctd_win == CAL) + border_color(win[CAL].p); + else + border_nocolor(win[CAL].p); + } + if (flags & FLAG_APP) { + if (slctd_win == APP) + border_color(win[APP].p); + else + border_nocolor(win[APP].p); + } + if (flags & FLAG_TOD) { + if (slctd_win == TOD) + border_color(win[TOD].p); + else + border_nocolor(win[TOD].p); + } +} + +void wins_update_panels(int flags) +{ + if (flags & FLAG_APP) + apoint_update_panel(slctd_win); + if (flags & FLAG_TOD) + todo_update_panel(slctd_win); + if (flags & FLAG_CAL) + calendar_update_panel(&win[CAL]); } /* * Update all of the three windows and put a border around the * selected window. */ -void -wins_update (void) +void wins_update(int flags) { - wins_update_border (); - wins_update_panels (); - wins_status_bar (); - if (notify_bar ()) - notify_update_bar (); - wmove (win[STA].p, 0, 0); - wins_doupdate (); + wins_update_border(flags); + wins_update_panels(flags); + if (flags & FLAG_STA) + wins_status_bar(); + if ((flags & FLAG_NOT) && notify_bar()) + notify_update_bar(); + wmove(win[STA].p, 0, 0); + wins_doupdate(); } /* Reset the screen, needed when resizing terminal for example. */ -void -wins_reset (void) +void wins_reset(void) { - endwin (); - wins_refresh (); - curs_set (0); - wins_reinit (); - wins_update (); + endwin(); + wins_refresh(); + curs_set(0); + wins_reinit(); + wins_update(FLAG_ALL); +} + +/* Prepare windows for the execution of an external command. */ +void wins_prepare_external(void) +{ + if (notify_bar()) + notify_stop_main_thread(); + def_prog_mode(); + ui_mode = UI_CMDLINE; + clear(); + wins_refresh(); + endwin(); +} + +/* Restore windows when returning from an external command. */ +void wins_unprepare_external(void) +{ + reset_prog_mode(); + clearok(curscr, TRUE); + curs_set(0); + ui_mode = UI_CURSES; + wins_refresh(); + if (notify_bar()) + notify_start_main_thread(); } /* * While inside interactive mode, launch the external command cmd on the given * file. */ -void -wins_launch_external (const char *file, const char *cmd) -{ - char *p; - int len; - - /* Beware of space between cmd and file. */ - len = strlen (file) + strlen (cmd) + 2; - - p = (char *) mem_calloc (len, sizeof (char)); - if (snprintf (p, len, "%s %s", cmd, file) == -1) - { - mem_free (p); - return; - } - if (notify_bar ()) - notify_stop_main_thread (); - def_prog_mode (); - endwin (); - ui_mode = UI_CMDLINE; - clear (); - wins_refresh (); - (void)system (p); - reset_prog_mode (); - clearok (curscr, TRUE); - curs_set (0); - ui_mode = UI_CURSES; - wins_refresh (); - if (notify_bar ()) - notify_start_main_thread (); - mem_free (p); +void wins_launch_external(const char *file, const char *cmd) +{ + const char *arg[] = { cmd, file, NULL }; + int pid; + + wins_prepare_external(); + if ((pid = shell_exec(NULL, NULL, *arg, arg))) + child_wait(NULL, NULL, pid); + wins_unprepare_external(); } -#define NB_CAL_CMDS 27 /* number of commands while in cal view */ -#define NB_APP_CMDS 31 /* same thing while in appointment view */ -#define NB_TOD_CMDS 30 /* 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 */ +#define NB_CAL_CMDS 27 /* number of commands while in cal view */ +#define NB_APP_CMDS 32 /* same thing while in appointment view */ +#define NB_TOD_CMDS 31 /* same thing while in todo view */ static unsigned status_page; @@ -650,114 +582,124 @@ static unsigned status_page; * table, and update the NB_CAL_CMDS, NB_APP_CMDS or NB_TOD_CMDS defines, * depending on which panel the added keybind is assigned to. */ -void -wins_status_bar (void) -{ -#define NB_PANELS 3 /* 3 panels: CALENDAR, APPOINTMENT, TODO */ - enum win which_pan; - int start, end; - const int pos[NB_PANELS + 1] = - { 0, NB_CAL_CMDS, NB_CAL_CMDS + NB_APP_CMDS, TOTAL_CMDS }; - - struct binding help = {_("Help"), KEY_GENERIC_HELP}; - struct binding quit = {_("Quit"), KEY_GENERIC_QUIT}; - struct binding save = {_("Save"), KEY_GENERIC_SAVE}; - struct binding cut = {_("Cut"), KEY_GENERIC_CUT}; - struct binding paste = {_("Paste"), KEY_GENERIC_PASTE}; - struct binding chgvu = {_("Chg Win"), KEY_GENERIC_CHANGE_VIEW}; - struct binding import = {_("Import"), KEY_GENERIC_IMPORT}; - struct binding export = {_("Export"), KEY_GENERIC_EXPORT}; - struct binding togo = {_("Go to"), KEY_GENERIC_GOTO}; - struct binding othr = {_("OtherCmd"), KEY_GENERIC_OTHER_CMD}; - struct binding conf = {_("Config"), KEY_GENERIC_CONFIG_MENU}; - struct binding draw = {_("Redraw"), KEY_GENERIC_REDRAW}; - struct binding appt = {_("Add Appt"), KEY_GENERIC_ADD_APPT}; - struct binding todo = {_("Add Todo"), KEY_GENERIC_ADD_TODO}; - struct binding gnday = {_("+1 Day"), KEY_GENERIC_NEXT_DAY}; - struct binding gpday = {_("-1 Day"), KEY_GENERIC_PREV_DAY}; - struct binding gnweek = {_("+1 Week"), KEY_GENERIC_NEXT_WEEK}; - struct binding gpweek = {_("-1 Week"), KEY_GENERIC_PREV_WEEK}; - struct binding today = {_("Today"), KEY_GENERIC_GOTO_TODAY}; - struct binding nview = {_("Nxt View"), KEY_GENERIC_SCROLL_DOWN}; - struct binding pview = {_("Prv View"), KEY_GENERIC_SCROLL_UP}; - struct binding up = {_("Up"), KEY_MOVE_UP}; - struct binding down = {_("Down"), KEY_MOVE_DOWN}; - struct binding left = {_("Left"), KEY_MOVE_LEFT}; - struct binding right = {_("Right"), KEY_MOVE_RIGHT}; - struct binding weekb = {_("beg Week"), KEY_START_OF_WEEK}; - struct binding weeke = {_("end Week"), KEY_END_OF_WEEK}; - struct binding add = {_("Add Item"), KEY_ADD_ITEM}; - struct binding del = {_("Del Item"), KEY_DEL_ITEM}; - struct binding edit = {_("Edit Itm"), KEY_EDIT_ITEM}; - struct binding view = {_("View"), KEY_VIEW_ITEM}; - struct binding flag = {_("Flag Itm"), KEY_FLAG_ITEM}; - struct binding rept = {_("Repeat"), KEY_REPEAT_ITEM}; - struct binding enote = {_("EditNote"), KEY_EDIT_NOTE}; - struct binding vnote = {_("ViewNote"), KEY_VIEW_NOTE}; - struct binding rprio = {_("Prio.+"), KEY_RAISE_PRIORITY}; - struct binding lprio = {_("Prio.-"), KEY_LOWER_PRIORITY}; - - struct binding *binding[TOTAL_CMDS] = { - /* calendar keys */ +void wins_status_bar(void) +{ + struct binding help = { _("Help"), KEY_GENERIC_HELP }; + struct binding quit = { _("Quit"), KEY_GENERIC_QUIT }; + struct binding save = { _("Save"), KEY_GENERIC_SAVE }; + struct binding cut = { _("Cut"), KEY_GENERIC_CUT }; + struct binding paste = { _("Paste"), KEY_GENERIC_PASTE }; + struct binding chgvu = { _("Chg Win"), KEY_GENERIC_CHANGE_VIEW }; + struct binding import = { _("Import"), KEY_GENERIC_IMPORT }; + struct binding export = { _("Export"), KEY_GENERIC_EXPORT }; + struct binding togo = { _("Go to"), KEY_GENERIC_GOTO }; + struct binding conf = { _("Config"), KEY_GENERIC_CONFIG_MENU }; + struct binding draw = { _("Redraw"), KEY_GENERIC_REDRAW }; + struct binding appt = { _("Add Appt"), KEY_GENERIC_ADD_APPT }; + struct binding todo = { _("Add Todo"), KEY_GENERIC_ADD_TODO }; + struct binding gnday = { _("+1 Day"), KEY_GENERIC_NEXT_DAY }; + struct binding gpday = { _("-1 Day"), KEY_GENERIC_PREV_DAY }; + struct binding gnweek = { _("+1 Week"), KEY_GENERIC_NEXT_WEEK }; + struct binding gpweek = { _("-1 Week"), KEY_GENERIC_PREV_WEEK }; + struct binding today = { _("Today"), KEY_GENERIC_GOTO_TODAY }; + struct binding nview = { _("Nxt View"), KEY_GENERIC_SCROLL_DOWN }; + struct binding pview = { _("Prv View"), KEY_GENERIC_SCROLL_UP }; + struct binding up = { _("Up"), KEY_MOVE_UP }; + struct binding down = { _("Down"), KEY_MOVE_DOWN }; + struct binding left = { _("Left"), KEY_MOVE_LEFT }; + struct binding right = { _("Right"), KEY_MOVE_RIGHT }; + struct binding weekb = { _("beg Week"), KEY_START_OF_WEEK }; + struct binding weeke = { _("end Week"), KEY_END_OF_WEEK }; + struct binding add = { _("Add Item"), KEY_ADD_ITEM }; + struct binding del = { _("Del Item"), KEY_DEL_ITEM }; + struct binding edit = { _("Edit Itm"), KEY_EDIT_ITEM }; + struct binding view = { _("View"), KEY_VIEW_ITEM }; + struct binding pipe = { _("Pipe"), KEY_PIPE_ITEM }; + struct binding flag = { _("Flag Itm"), KEY_FLAG_ITEM }; + struct binding rept = { _("Repeat"), KEY_REPEAT_ITEM }; + struct binding enote = { _("EditNote"), KEY_EDIT_NOTE }; + struct binding vnote = { _("ViewNote"), KEY_VIEW_NOTE }; + struct binding rprio = { _("Prio.+"), KEY_RAISE_PRIORITY }; + struct binding lprio = { _("Prio.-"), KEY_LOWER_PRIORITY }; + struct binding othr = { _("OtherCmd"), KEY_GENERIC_OTHER_CMD }; + + struct binding *bindings_cal[] = { &help, &quit, &save, &chgvu, &nview, &pview, &up, &down, &left, &right, - &togo, &othr, &import, &export, &weekb, &weeke, &appt, &todo, - &gnday, &gpday, &gnweek, &gpweek, &draw, &othr, &today, &conf, &othr, - /* appointment keys */ + &togo, &import, &export, &weekb, &weeke, &appt, &todo, &gnday, &gpday, + &gnweek, &gpweek, &draw, &today, &conf + }; + + struct binding *bindings_apoint[] = { &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, &cut, &paste, - &othr, - /* todo keys */ + &pipe, &draw, &rept, &flag, &enote, &vnote, &up, &down, &gnday, &gpday, + &gnweek, &gpweek, &togo, &today, &conf, &appt, &todo, &cut, &paste + }; + + struct binding *bindings_todo[] = { &help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view, - &flag, &othr, &rprio, &lprio, &enote, &vnote, &up, &down, &gnday, &gpday, - &gnweek, &gpweek, &togo, &othr, &today, &conf, &appt, &todo, &draw, &othr + &pipe, &flag, &rprio, &lprio, &enote, &vnote, &up, &down, &gnday, &gpday, + &gnweek, &gpweek, &togo, &today, &conf, &appt, &todo, &draw }; - /* Drawing the keybinding with attribute and label without. */ - which_pan = wins_slctd (); - start = pos[which_pan] + 2 * KEYS_CMDS_PER_LINE * (status_page - 1); - end = MIN (start + 2 * KEYS_CMDS_PER_LINE, pos[which_pan + 1]); - keys_display_bindings_bar (win[STA].p, binding, start, end); + enum win active_panel = wins_slctd(); + + struct binding **bindings; + int bindings_size; + + switch (active_panel) { + case CAL: + bindings = bindings_cal; + bindings_size = sizeof(bindings_cal) / sizeof(bindings_cal[0]); + break; + case APP: + bindings = bindings_apoint; + bindings_size = sizeof(bindings_apoint) / sizeof(bindings_apoint[0]); + break; + case TOD: + bindings = bindings_todo; + bindings_size = sizeof(bindings_todo) / sizeof(bindings_todo[0]); + break; + default: + EXIT(_("unknown panel")); + /* NOTREACHED */ + } + + keys_display_bindings_bar(win[STA].p, bindings, bindings_size, + (KEYS_CMDS_PER_LINE * 2 - 1) * (status_page - 1), + KEYS_CMDS_PER_LINE * 2, &othr); } /* Erase status bar. */ -void -wins_erase_status_bar (void) +void wins_erase_status_bar(void) { - erase_window_part (win[STA].p, 0, 0, col, STATUSHEIGHT); + erase_window_part(win[STA].p, 0, 0, col, STATUSHEIGHT); } /* Update the status bar page number to display other commands. */ -void -wins_other_status_page (int panel) +void wins_other_status_page(int panel) { int nb_item, max_page; - switch (panel) - { - case CAL: - nb_item = NB_CAL_CMDS; - break; - case APP: - nb_item = NB_APP_CMDS; - break; - case TOD: - nb_item = NB_TOD_CMDS; - break; - default: - EXIT (_("unknown panel")); - /* NOTREACHED */ - } - max_page = ceil (nb_item / (2 * CMDS_PER_LINE + 1)) + 1; - if (status_page < max_page) - status_page++; - else - status_page = 1; + switch (panel) { + case CAL: + nb_item = NB_CAL_CMDS; + break; + case APP: + nb_item = NB_APP_CMDS; + break; + case TOD: + nb_item = NB_TOD_CMDS; + break; + default: + EXIT(_("unknown panel")); + /* NOTREACHED */ + } + max_page = nb_item / (KEYS_CMDS_PER_LINE * 2 - 1) + 1; + status_page = (status_page % max_page) + 1; } /* Reset the status bar page. */ -void -wins_reset_status_page (void) +void wins_reset_status_page(void) { status_page = 1; } @@ -765,5 +707,3 @@ wins_reset_status_page (void) #undef NB_CAL_CMDS #undef NB_APP_CMDS #undef NB_TOD_CMDS -#undef TOTAL_CMDS -#undef CMDS_PER_LINE |