diff options
Diffstat (limited to 'src/pcal.c')
-rw-r--r-- | src/pcal.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/src/pcal.c b/src/pcal.c new file mode 100644 index 0000000..0046739 --- /dev/null +++ b/src/pcal.c @@ -0,0 +1,317 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2011 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 %s %%w\n", _("Week")); + 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); +} + |