diff options
Diffstat (limited to 'src/recur.c')
-rwxr-xr-x | src/recur.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/src/recur.c b/src/recur.c new file mode 100755 index 0000000..d0629aa --- /dev/null +++ b/src/recur.c @@ -0,0 +1,355 @@ +/* $calcurse: recur.c,v 1.1 2006/07/31 21:00:03 culot Exp $ */ + +/* + * Calcurse - text-based organizer + * Copyright (c) 2004-2006 Frederic Culot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Send your feedback or comments to : calcurse@culot.org + * Calcurse home page : http://culot.org/calcurse + * + */ + +#include <ncurses.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <time.h> + +#include "i18n.h" +#include "utils.h" +#include "apoint.h" +#include "event.h" +#include "recur.h" + +struct recur_apoint_s *recur_alist; +struct recur_event_s *recur_elist; + +/* Insert a new recursive appointment in the general linked list */ +struct recur_apoint_s *recur_apoint_new(char *mesg, long start, long dur, + int type, int freq, long until) +{ + struct recur_apoint_s *o, **i; + o = (struct recur_apoint_s *) malloc(sizeof(struct recur_apoint_s)); + o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s)); + o->exc = (struct days_s *) malloc(sizeof(struct days_s)); + o->mesg = (char *) malloc(strlen(mesg) + 1); + strcpy(o->mesg, mesg); + o->start = start; + o->dur = dur; + o->rpt->type = type; + o->rpt->freq = freq; + o->rpt->until = until; + i = &recur_alist; + for (;;) { + if (*i == 0 || (*i)->start > start) { + o->next = *i; + *i = o; + break; + } + i = &(*i)->next; + } + return o; +} + +/* Insert a new recursive event in the general linked list */ +struct recur_event_s *recur_event_new(char *mesg, long day, int id, + int type, int freq, long until) +{ + struct recur_event_s *o, **i; + o = (struct recur_event_s *) malloc(sizeof(struct recur_event_s)); + o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s)); + o->exc = (struct days_s *) malloc(sizeof(struct days_s)); + o->mesg = (char *) malloc(strlen(mesg) + 1); + strcpy(o->mesg, mesg); + o->day = day; + o->id = id; + o->rpt->type = type; + o->rpt->freq = freq; + o->rpt->until = until; + i = &recur_elist; + for (;;) { + if (*i == 0 || (*i)->day > day) { + o->next = *i; + *i = o; + break; + } + i = &(*i)->next; + } + return o; +} + +/* + * Correspondance between the defines on recursive type, + * and the letter to be written in file. + */ +char recur_def2char(int define){ + char recur_char; + + switch (define) { + case 1: + recur_char = 'D'; + break; + case 2: + recur_char = 'W'; + break; + case 3: + recur_char = 'M'; + break; + case 4: + recur_char = 'Y'; + break; + } + return recur_char; +} + +/* + * Correspondance between the letters written in file and the defines + * concerning the recursive 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; + } + return recur_def; +} + +/* Writting of a recursive appointment into file. */ +void recur_apoint_write(struct recur_apoint_s *o, FILE *f) +{ + struct tm *lt; + time_t t; + + t = o->start; + 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); + 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. */ + fprintf(f, " {%d%c} |%s\n", o->rpt->freq, + recur_def2char(o->rpt->type), o->mesg); + } else { + lt = localtime(&t); + fprintf(f, " {%d%c -> %02u/%02u/%04u} |%s\n", + o->rpt->freq, recur_def2char(o->rpt->type), + lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, + o->mesg); + } +} + +/* Writting of a recursive event into file. */ +void recur_event_write(struct recur_event_s *o, FILE *f) +{ + struct tm *lt; + time_t t; + int st_mon, st_day, st_year; + int end_mon, end_day, end_year; + + t = o->day; + 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. */ + fprintf(f, "%02u/%02u/%04u [%d] {%d%c} %s\n", + st_mon, st_day, st_year, o->id, o->rpt->freq, + recur_def2char(o->rpt->type), o->mesg); + } 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} %s\n", + st_mon, st_day, st_year, o->id, + o->rpt->freq, recur_def2char(o->rpt->type), + end_mon, end_day, end_year, o->mesg); + } +} + +/* Load the recursive appointment description */ +struct recur_apoint_s *recur_apoint_scan(FILE * f, struct tm start, + struct tm end, char type, int freq, struct tm until) +{ + struct tm *lt; + char buf[MESG_MAXSIZE], *nl; + time_t tstart, tend, t, tuntil; + + t = time(NULL); + lt = localtime(&t); + + /* Read the appointment description */ + fgets(buf, MESG_MAXSIZE, f); + 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 = 12; + until.tm_min = 0; + until.tm_sec = 0; + until.tm_isdst = -1; + until.tm_year -= 1900; + until.tm_mon--; + tuntil = mktime(&until); + } else { + tuntil = 0; + } + + if (tstart == -1 || tend == -1 || tstart > tend || tuntil == -1) { + fputs(_("FATAL ERROR in apoint_scan: date error in the appointment\n"), stderr); + exit(EXIT_FAILURE); + } + + return recur_apoint_new(buf, tstart, tend - tstart, + recur_char2def(type), freq, tuntil); +} + +/* Load the recursive events from file */ +struct recur_event_s *recur_event_scan(FILE * f, struct tm start, int id, + char type, int freq, struct tm until) +{ + struct tm *lt; + char buf[MESG_MAXSIZE], *nl; + time_t tstart, t, tuntil; + + t = time(NULL); + lt = localtime(&t); + + /* Read the event description */ + fgets(buf, MESG_MAXSIZE, f); + nl = strchr(buf, '\n'); + if (nl) { + *nl = '\0'; + } + + start.tm_hour = until.tm_hour = 12; + 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); + if ( (tstart == -1) || (tuntil == -1) ) { + fputs(_("FATAL ERROR in recur_event_scan: date error in the event\n"), stderr); + exit(EXIT_FAILURE); + } + + return recur_event_new(buf, tstart, id, recur_char2def(type), freq, tuntil); +} + +/* Write recursive items to file. */ +void recur_save_data(FILE *f) +{ + struct recur_event_s *re; + struct recur_apoint_s *ra; + + for (re = recur_elist; re != 0; re = re->next) + recur_event_write(re, f); + for (ra = recur_alist; ra != 0; ra = ra->next) + recur_apoint_write(ra, f); +} + +/* Check if the recurrent item belongs to the selected day. */ +unsigned recur_item_inday(long item_start, int rpt_type, int rpt_freq, + long rpt_until, long day_start) +{ + const int DAYINSEC = 86400; + long day_end = day_start + DAYINSEC; + int inday = 0; + struct tm *lt; + time_t t; + char *error = + _("FATAL ERROR in recur_item_inday: unknown item type\n"); + + if (rpt_until == 0) /* we have an endless recurrent item */ + rpt_until = day_end; + while (item_start <= day_end && item_start <= rpt_until) { + if (item_start < day_end && item_start >= day_start) { + inday = 1; + break; + } + t = item_start; + lt = localtime(&t); + if (rpt_type == RECUR_DAILY) { + lt->tm_mday += rpt_freq; + } else if (rpt_type == RECUR_WEEKLY) { + lt->tm_mday += rpt_freq * 7; + } else if (rpt_type == RECUR_MONTHLY) { + lt->tm_mon += rpt_freq; + } else if (rpt_type == RECUR_YEARLY) { + lt->tm_year += rpt_freq; + } else { /* NOT REACHED */ + fputs(error, stderr); + exit(EXIT_FAILURE); + } + item_start = date2sec(lt->tm_year + 1900, lt->tm_mon + 1, + lt->tm_mday, 0, 0); + } + return inday; +} + +/* Returns a structure of type apoint_s given a structure of type recur_apoint_s */ +struct apoint_s *recur_apoint_s2apoint_s(struct recur_apoint_s *p) +{ + struct apoint_s *a; + + a = (struct apoint_s *) malloc(sizeof(struct apoint_s)); + a->mesg = (char *) malloc(strlen(p->mesg) + 1); + a->start = p->start; + a->dur = p->dur; + a->mesg = p->mesg; + return a; +} |