Large number of updates. Recurrence basically works now in most of its

Large number of updates.  Recurrence basically works now in most
of its forms (daily, weekly, month-by-position).

Miguel.

svn path=/trunk/; revision=148
This commit is contained in:
Arturo Espinosa
1998-04-17 19:35:43 +00:00
parent ad0347d16b
commit 55f88f14fe
20 changed files with 807 additions and 192 deletions

View File

@ -12,6 +12,8 @@
#include "timeutil.h"
#include "versit/vcc.h"
static void ical_object_compute_end (iCalObject *ico);
iCalObject *
ical_object_new (void)
{
@ -35,7 +37,6 @@ default_alarm (iCalObject *ical, CalendarAlarm *alarm, char *def_mail, enum Alar
alarm->count = 15;
alarm->units = ALARM_MINUTES;
} else {
printf ("uno!\n");
alarm->count = 1;
alarm->units = ALARM_DAYS;
}
@ -140,7 +141,7 @@ static void
ignore_space(char **str)
{
while (**str && isspace (**str))
str++;
(*str)++;
}
static void
@ -183,6 +184,12 @@ weekdaylist (iCalObject *o, char **str)
}
}
} while (isalpha (**str));
if (o->recur->weekday == 0){
struct tm *tm = localtime (&o->dtstart);
o->recur->weekday = 1 << tm->tm_wday;
}
}
static void
@ -223,11 +230,11 @@ daynumber (iCalObject *o, char **str)
while (**str && isdigit (**str)){
val = val * 10 + (**str - '0');
str++;
(*str)++;
}
if (**str == '+')
str++;
(*str)++;
if (**str == '-')
val *= -1;
@ -245,8 +252,10 @@ daynumberlist (iCalObject *o, char **str)
while (**str){
if (!isdigit (**str))
return;
while (**str && isdigit (**str))
while (**str && isdigit (**str)){
val = 10 * val + (**str - '0');
(*str)++;
}
if (!first){
o->recur->u.month_day = val;
first = 1;
@ -300,10 +309,12 @@ duration (iCalObject *o, char **str)
ignore_space (str);
if (**str != '#')
return;
while (**str && isdigit (**str))
(*str)++;
while (**str && isdigit (**str)){
duration = duration * 10 + (**str - '0');
o->recur->temp_duration = duration;
(*str)++;
}
o->recur->duration = duration;
}
static void
@ -311,7 +322,7 @@ enddate (iCalObject *o, char **str)
{
ignore_space (str);
if (isdigit (**str)){
o->recur->enddate = time_from_isodate (*str);
o->recur->_enddate = time_from_isodate (*str);
*str += 16;
}
}
@ -335,7 +346,7 @@ load_recurrence (iCalObject *o, char *str)
case 'M':
if (*str == 'P')
type = RECUR_MONTHLY_BY_POS;
else if (*str == 'D')
else if (*str == 'D')
type = RECUR_MONTHLY_BY_DAY;
str++;
break;
@ -356,13 +367,18 @@ load_recurrence (iCalObject *o, char *str)
ignore_space (&str);
/* Get the interval */
while (*str && isdigit (*str))
for (;*str && isdigit (*str);str++)
interval = interval * 10 + (*str-'0');
o->recur->interval = interval;
/* this is the default per the spec */
o->recur->duration = 2;
ignore_space (&str);
switch (type){
case RECUR_DAILY:
break;
case RECUR_WEEKLY:
load_recur_weekly (o, &str);
break;
@ -385,6 +401,17 @@ load_recurrence (iCalObject *o, char *str)
duration (o, &str);
enddate (o, &str);
/* Compute the enddate */
if (o->recur->_enddate == 0){
printf ("ENDDATE es 0, d=%d\n", o->recur->duration);
if (o->recur->duration != 0){
ical_object_compute_end (o);
} else
o->recur->enddate = 0;
} else {
printf ("El evento termina\n");
o->recur->enddate = o->recur->_enddate;
}
return 1;
}
@ -689,14 +716,173 @@ ical_foreach (GList *events, calendarfn fn, void *closure)
}
}
static int
generate (iCalObject *ico, time_t reference, calendarfn cb, void *closure)
{
struct tm dt_start, dt_end, ref;
time_t s_t, e_t;
dt_start = *localtime (&ico->dtstart);
dt_end = *localtime (&ico->dtend);
ref = *localtime (&reference);
dt_start.tm_mday = ref.tm_mday;
dt_start.tm_mon = ref.tm_mon;
dt_start.tm_year = ref.tm_year;
dt_end.tm_mday = ref.tm_mday;
dt_end.tm_mon = ref.tm_mon;
dt_end.tm_year = ref.tm_year;
s_t = mktime (&dt_start);
e_t = mktime (&dt_end);
if (s_t == -1 || e_t == -1){
g_warning ("Produced invalid dates!\n");
return 0;
}
return (*cb)(ico, s_t, e_t, closure);
}
#define time_in_range(x,a,b) ((x >= a) && (b ? x <= b : 1))
/*
* Generate every possible event. Invokes the callback routine for
* every occurrence of the event in the [START, END] time interval.
*
* If END is zero, the event is generated forever.
* The callback routine is expected to return 0 when no further event
* generation is requested.
*/
void
ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendarfn cb, void *closure)
{
Recurrence *recur = ico->recur;
time_t current;
if (!ico->recur){
if ((start <= ico->dtstart) && (ico->dtend <= end))
(*cb)(ico, ico->dtstart, ico->dtend, closure);
if (time_in_range (ico->dtstart, start, end) ||
time_in_range (ico->dtend, start, end)){
time_t ev_s, ev_e;
ev_s = ico->dtstart < start ? start : ico->dtstart;
ev_e = ico->dtend > end ? end : ico->dtend;
(*cb)(ico, ev_s, ev_e, closure);
}
return;
}
/* The event has a recurrence rule */
if (end != 0){
if (ico->dtstart > end)
return;
if (!IS_INFINITE (ico->recur) && recur->enddate < start)
return;
}
current = ico->dtstart;
switch (recur->type){
case RECUR_DAILY:
do {
if (time_in_range (current, start, end)){
if (!generate (ico, current, cb, closure))
return;
}
/* Advance */
current = time_add_day (current, recur->interval);
if (current == -1){
g_warning ("RECUR_DAILY: mktime error\n");
return;
}
} while (current < end || (end == 0));
break;
case RECUR_WEEKLY:
do {
struct tm *tm = localtime (&current);
if (time_in_range (current, start, end)){
if (recur->weekday & (1 << tm->tm_wday))
if (!generate (ico, current, cb, closure))
return;
}
/* Advance by day for scanning the week or by interval at week end */
if (tm->tm_wday == 6)
current = time_add_day (current, recur->interval);
else
current = time_add_day (current, 1);
if (current == -1){
g_warning ("RECUR_WEEKLY: mktime error\n");
return;
}
} while (current < end || (end == 0));
break;
case RECUR_MONTHLY_BY_POS:
g_warning ("We still do not handle MONTHLY_BY_POS\n");
break;
case RECUR_MONTHLY_BY_DAY:
do {
struct tm *tm = localtime (&current);
time_t t;
int p;
p = tm->tm_mday;
tm->tm_mday = recur->u.month_day;
t = mktime (tm);
if (time_in_range (t, start, end))
if (!generate (ico, t, cb, closure))
return;
/* Advance a month */
tm->tm_mday = p;
tm->tm_mon += recur->interval;
current = mktime (tm);
if (current == -1){
g_warning ("RECUR_MONTHLY_BY_DAY: mktime error\n");
return;
}
} while (current < end || (end == 0));
case RECUR_YEARLY_BY_MONTH:
case RECUR_YEARLY_BY_DAY:
do {
if (time_in_range (current, start, end))
if (!generate (ico, current, cb, closure))
return;
/* Advance */
current = time_add_year (current, recur->interval);
} while (current < end || (end == 0));
}
}
static int
duration_callback (iCalObject *ico, time_t start, time_t end, void *closure)
{
int *count = closure;
(*count)++;
if (ico->recur->duration == *count){
ico->recur->enddate = end;
return 0;
}
return 1;
}
/* Computes ico->recur->enddate from ico->recur->duration */
void
ical_object_compute_end (iCalObject *ico)
{
int count = 0;
g_return_if_fail (ico->recur != NULL);
ical_object_generate_events (ico, ico->dtstart, 0, duration_callback, &count);
}

View File

@ -86,7 +86,14 @@ typedef struct {
enum RecurType type;
int interval;
time_t enddate;
/* Used for recur computation */
time_t enddate; /* If the value is zero, it is an infinite event
* otherwise, it is either the _enddate value (if
* this is what got specified) or it is our computed
* ending date (computed from the duration item).
*/
int weekday;
union {
@ -94,8 +101,11 @@ typedef struct {
int month_day;
} u;
int temp_duration; /* Used temporarly, we compute enddate */
int duration;
time_t _enddate; /* As found on the vCalendar file */
int __count;
} Recurrence;
#define IS_INFINITE(r) (r->duration == 0)
/* Flags to indicate what has changed in an object */
typedef enum {
@ -157,7 +167,7 @@ typedef struct {
} iCalObject;
/* The callback for the recurrence generator */
typedef void (*calendarfn)(iCalObject *, time_t, time_t, void *);
typedef int (*calendarfn)(iCalObject *, time_t, time_t, void *);
iCalObject *ical_new (char *comment, char *organizer, char *summary);
iCalObject *ical_object_new (void);

View File

@ -207,21 +207,25 @@ calendar_load_from_vobject (Calendar *cal, VObject *vcal)
}
/* Loads a calendar from a file */
void
char *
calendar_load (Calendar *cal, char *fname)
{
VObject *vcal;
if (cal->filename){
g_warning ("Calendar load called again\n");
return;
return "Internal error";
}
cal->filename = g_strdup (fname);
vcal = Parse_MIME_FromFileName (fname);
if (!vcal)
return "Could not load the calendar";
calendar_load_from_vobject (cal, vcal);
cleanVObject (vcal);
cleanStrTbl ();
return NULL;
}
void
@ -250,7 +254,7 @@ calendar_save (Calendar *cal, char *fname)
cleanStrTbl ();
}
static void
static gint
calendar_object_compare_by_start (gpointer a, gpointer b)
{
CalendarObject *ca = a;
@ -261,7 +265,7 @@ calendar_object_compare_by_start (gpointer a, gpointer b)
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
static void
static int
assemble_event_list (iCalObject *obj, time_t start, time_t end, void *c)
{
CalendarObject *co;
@ -272,6 +276,8 @@ assemble_event_list (iCalObject *obj, time_t start, time_t end, void *c)
co->ev_end = end;
co->ico = obj;
*l = g_list_insert_sorted (*l, co, calendar_object_compare_by_start);
return 1;
}
void
@ -280,7 +286,7 @@ calendar_destroy_event_list (GList *l)
GList *p;
for (p = l; p; p = p->next)
g_free (l->data);
g_free (p->data);
g_list_free (l);
}

View File

@ -38,7 +38,7 @@ typedef struct {
} CalendarObject;
Calendar *calendar_new (char *title);
void calendar_load (Calendar *cal, char *fname);
char *calendar_load (Calendar *cal, char *fname);
void calendar_add_object (Calendar *cal, iCalObject *obj);
void calendar_remove_object (Calendar *cal, iCalObject *obj);
void calendar_destroy (Calendar *cal);

View File

@ -12,6 +12,8 @@
#include "timeutil.h"
#include "versit/vcc.h"
static void ical_object_compute_end (iCalObject *ico);
iCalObject *
ical_object_new (void)
{
@ -35,7 +37,6 @@ default_alarm (iCalObject *ical, CalendarAlarm *alarm, char *def_mail, enum Alar
alarm->count = 15;
alarm->units = ALARM_MINUTES;
} else {
printf ("uno!\n");
alarm->count = 1;
alarm->units = ALARM_DAYS;
}
@ -140,7 +141,7 @@ static void
ignore_space(char **str)
{
while (**str && isspace (**str))
str++;
(*str)++;
}
static void
@ -183,6 +184,12 @@ weekdaylist (iCalObject *o, char **str)
}
}
} while (isalpha (**str));
if (o->recur->weekday == 0){
struct tm *tm = localtime (&o->dtstart);
o->recur->weekday = 1 << tm->tm_wday;
}
}
static void
@ -223,11 +230,11 @@ daynumber (iCalObject *o, char **str)
while (**str && isdigit (**str)){
val = val * 10 + (**str - '0');
str++;
(*str)++;
}
if (**str == '+')
str++;
(*str)++;
if (**str == '-')
val *= -1;
@ -245,8 +252,10 @@ daynumberlist (iCalObject *o, char **str)
while (**str){
if (!isdigit (**str))
return;
while (**str && isdigit (**str))
while (**str && isdigit (**str)){
val = 10 * val + (**str - '0');
(*str)++;
}
if (!first){
o->recur->u.month_day = val;
first = 1;
@ -300,10 +309,12 @@ duration (iCalObject *o, char **str)
ignore_space (str);
if (**str != '#')
return;
while (**str && isdigit (**str))
(*str)++;
while (**str && isdigit (**str)){
duration = duration * 10 + (**str - '0');
o->recur->temp_duration = duration;
(*str)++;
}
o->recur->duration = duration;
}
static void
@ -311,7 +322,7 @@ enddate (iCalObject *o, char **str)
{
ignore_space (str);
if (isdigit (**str)){
o->recur->enddate = time_from_isodate (*str);
o->recur->_enddate = time_from_isodate (*str);
*str += 16;
}
}
@ -335,7 +346,7 @@ load_recurrence (iCalObject *o, char *str)
case 'M':
if (*str == 'P')
type = RECUR_MONTHLY_BY_POS;
else if (*str == 'D')
else if (*str == 'D')
type = RECUR_MONTHLY_BY_DAY;
str++;
break;
@ -356,13 +367,18 @@ load_recurrence (iCalObject *o, char *str)
ignore_space (&str);
/* Get the interval */
while (*str && isdigit (*str))
for (;*str && isdigit (*str);str++)
interval = interval * 10 + (*str-'0');
o->recur->interval = interval;
/* this is the default per the spec */
o->recur->duration = 2;
ignore_space (&str);
switch (type){
case RECUR_DAILY:
break;
case RECUR_WEEKLY:
load_recur_weekly (o, &str);
break;
@ -385,6 +401,17 @@ load_recurrence (iCalObject *o, char *str)
duration (o, &str);
enddate (o, &str);
/* Compute the enddate */
if (o->recur->_enddate == 0){
printf ("ENDDATE es 0, d=%d\n", o->recur->duration);
if (o->recur->duration != 0){
ical_object_compute_end (o);
} else
o->recur->enddate = 0;
} else {
printf ("El evento termina\n");
o->recur->enddate = o->recur->_enddate;
}
return 1;
}
@ -689,14 +716,173 @@ ical_foreach (GList *events, calendarfn fn, void *closure)
}
}
static int
generate (iCalObject *ico, time_t reference, calendarfn cb, void *closure)
{
struct tm dt_start, dt_end, ref;
time_t s_t, e_t;
dt_start = *localtime (&ico->dtstart);
dt_end = *localtime (&ico->dtend);
ref = *localtime (&reference);
dt_start.tm_mday = ref.tm_mday;
dt_start.tm_mon = ref.tm_mon;
dt_start.tm_year = ref.tm_year;
dt_end.tm_mday = ref.tm_mday;
dt_end.tm_mon = ref.tm_mon;
dt_end.tm_year = ref.tm_year;
s_t = mktime (&dt_start);
e_t = mktime (&dt_end);
if (s_t == -1 || e_t == -1){
g_warning ("Produced invalid dates!\n");
return 0;
}
return (*cb)(ico, s_t, e_t, closure);
}
#define time_in_range(x,a,b) ((x >= a) && (b ? x <= b : 1))
/*
* Generate every possible event. Invokes the callback routine for
* every occurrence of the event in the [START, END] time interval.
*
* If END is zero, the event is generated forever.
* The callback routine is expected to return 0 when no further event
* generation is requested.
*/
void
ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendarfn cb, void *closure)
{
Recurrence *recur = ico->recur;
time_t current;
if (!ico->recur){
if ((start <= ico->dtstart) && (ico->dtend <= end))
(*cb)(ico, ico->dtstart, ico->dtend, closure);
if (time_in_range (ico->dtstart, start, end) ||
time_in_range (ico->dtend, start, end)){
time_t ev_s, ev_e;
ev_s = ico->dtstart < start ? start : ico->dtstart;
ev_e = ico->dtend > end ? end : ico->dtend;
(*cb)(ico, ev_s, ev_e, closure);
}
return;
}
/* The event has a recurrence rule */
if (end != 0){
if (ico->dtstart > end)
return;
if (!IS_INFINITE (ico->recur) && recur->enddate < start)
return;
}
current = ico->dtstart;
switch (recur->type){
case RECUR_DAILY:
do {
if (time_in_range (current, start, end)){
if (!generate (ico, current, cb, closure))
return;
}
/* Advance */
current = time_add_day (current, recur->interval);
if (current == -1){
g_warning ("RECUR_DAILY: mktime error\n");
return;
}
} while (current < end || (end == 0));
break;
case RECUR_WEEKLY:
do {
struct tm *tm = localtime (&current);
if (time_in_range (current, start, end)){
if (recur->weekday & (1 << tm->tm_wday))
if (!generate (ico, current, cb, closure))
return;
}
/* Advance by day for scanning the week or by interval at week end */
if (tm->tm_wday == 6)
current = time_add_day (current, recur->interval);
else
current = time_add_day (current, 1);
if (current == -1){
g_warning ("RECUR_WEEKLY: mktime error\n");
return;
}
} while (current < end || (end == 0));
break;
case RECUR_MONTHLY_BY_POS:
g_warning ("We still do not handle MONTHLY_BY_POS\n");
break;
case RECUR_MONTHLY_BY_DAY:
do {
struct tm *tm = localtime (&current);
time_t t;
int p;
p = tm->tm_mday;
tm->tm_mday = recur->u.month_day;
t = mktime (tm);
if (time_in_range (t, start, end))
if (!generate (ico, t, cb, closure))
return;
/* Advance a month */
tm->tm_mday = p;
tm->tm_mon += recur->interval;
current = mktime (tm);
if (current == -1){
g_warning ("RECUR_MONTHLY_BY_DAY: mktime error\n");
return;
}
} while (current < end || (end == 0));
case RECUR_YEARLY_BY_MONTH:
case RECUR_YEARLY_BY_DAY:
do {
if (time_in_range (current, start, end))
if (!generate (ico, current, cb, closure))
return;
/* Advance */
current = time_add_year (current, recur->interval);
} while (current < end || (end == 0));
}
}
static int
duration_callback (iCalObject *ico, time_t start, time_t end, void *closure)
{
int *count = closure;
(*count)++;
if (ico->recur->duration == *count){
ico->recur->enddate = end;
return 0;
}
return 1;
}
/* Computes ico->recur->enddate from ico->recur->duration */
void
ical_object_compute_end (iCalObject *ico)
{
int count = 0;
g_return_if_fail (ico->recur != NULL);
ical_object_generate_events (ico, ico->dtstart, 0, duration_callback, &count);
}

View File

@ -86,7 +86,14 @@ typedef struct {
enum RecurType type;
int interval;
time_t enddate;
/* Used for recur computation */
time_t enddate; /* If the value is zero, it is an infinite event
* otherwise, it is either the _enddate value (if
* this is what got specified) or it is our computed
* ending date (computed from the duration item).
*/
int weekday;
union {
@ -94,8 +101,11 @@ typedef struct {
int month_day;
} u;
int temp_duration; /* Used temporarly, we compute enddate */
int duration;
time_t _enddate; /* As found on the vCalendar file */
int __count;
} Recurrence;
#define IS_INFINITE(r) (r->duration == 0)
/* Flags to indicate what has changed in an object */
typedef enum {
@ -157,7 +167,7 @@ typedef struct {
} iCalObject;
/* The callback for the recurrence generator */
typedef void (*calendarfn)(iCalObject *, time_t, time_t, void *);
typedef int (*calendarfn)(iCalObject *, time_t, time_t, void *);
iCalObject *ical_new (char *comment, char *organizer, char *summary);
iCalObject *ical_object_new (void);

View File

@ -1447,7 +1447,7 @@ button_1 (GncalFullDay *fullday, GdkEventButton *event)
child = find_child_by_window (fullday, event->window, &on_text);
if (!child || on_text)
if (!child || on_text || child->ico->recur)
return FALSE;
/* Prepare for drag */
@ -1647,8 +1647,8 @@ update_from_drag_info (GncalFullDay *fullday)
widget = GTK_WIDGET (fullday);
get_time_from_rows (fullday, di->child_start_row, di->child_rows_used,
&di->child->start,
&di->child->end);
&di->child->ico->dtstart,
&di->child->ico->dtend);
child_range_changed (fullday, di->child);
@ -1878,7 +1878,7 @@ child_compare_by_start (gpointer a, gpointer b)
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
static void
static int
fullday_add_children (iCalObject *obj, time_t start, time_t end, void *c)
{
GncalFullDay *fullday = c;
@ -1886,6 +1886,8 @@ fullday_add_children (iCalObject *obj, time_t start, time_t end, void *c)
child = child_new (fullday, start, end, obj);
fullday->children = g_list_insert_sorted (fullday->children, child, child_compare_by_start);
return 1;
}
void

View File

@ -198,7 +198,12 @@ gnome_calendar_update_all (GnomeCalendar *cal, iCalObject *object, int flags)
void
gnome_calendar_load (GnomeCalendar *gcal, char *file)
{
calendar_load (gcal->cal, file);
char *r;
if ((r = calendar_load (gcal->cal, file)) != NULL){
printf ("Error loading calendar: %s\n", r);
return;
}
gnome_calendar_update_all (gcal, NULL, 0);
}

View File

@ -207,21 +207,25 @@ calendar_load_from_vobject (Calendar *cal, VObject *vcal)
}
/* Loads a calendar from a file */
void
char *
calendar_load (Calendar *cal, char *fname)
{
VObject *vcal;
if (cal->filename){
g_warning ("Calendar load called again\n");
return;
return "Internal error";
}
cal->filename = g_strdup (fname);
vcal = Parse_MIME_FromFileName (fname);
if (!vcal)
return "Could not load the calendar";
calendar_load_from_vobject (cal, vcal);
cleanVObject (vcal);
cleanStrTbl ();
return NULL;
}
void
@ -250,7 +254,7 @@ calendar_save (Calendar *cal, char *fname)
cleanStrTbl ();
}
static void
static gint
calendar_object_compare_by_start (gpointer a, gpointer b)
{
CalendarObject *ca = a;
@ -261,7 +265,7 @@ calendar_object_compare_by_start (gpointer a, gpointer b)
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
static void
static int
assemble_event_list (iCalObject *obj, time_t start, time_t end, void *c)
{
CalendarObject *co;
@ -272,6 +276,8 @@ assemble_event_list (iCalObject *obj, time_t start, time_t end, void *c)
co->ev_end = end;
co->ico = obj;
*l = g_list_insert_sorted (*l, co, calendar_object_compare_by_start);
return 1;
}
void
@ -280,7 +286,7 @@ calendar_destroy_event_list (GList *l)
GList *p;
for (p = l; p; p = p->next)
g_free (l->data);
g_free (p->data);
g_list_free (l);
}

View File

@ -38,7 +38,7 @@ typedef struct {
} CalendarObject;
Calendar *calendar_new (char *title);
void calendar_load (Calendar *cal, char *fname);
char *calendar_load (Calendar *cal, char *fname);
void calendar_add_object (Calendar *cal, iCalObject *obj);
void calendar_remove_object (Calendar *cal, iCalObject *obj);
void calendar_destroy (Calendar *cal);

View File

@ -1447,7 +1447,7 @@ button_1 (GncalFullDay *fullday, GdkEventButton *event)
child = find_child_by_window (fullday, event->window, &on_text);
if (!child || on_text)
if (!child || on_text || child->ico->recur)
return FALSE;
/* Prepare for drag */
@ -1647,8 +1647,8 @@ update_from_drag_info (GncalFullDay *fullday)
widget = GTK_WIDGET (fullday);
get_time_from_rows (fullday, di->child_start_row, di->child_rows_used,
&di->child->start,
&di->child->end);
&di->child->ico->dtstart,
&di->child->ico->dtend);
child_range_changed (fullday, di->child);
@ -1878,7 +1878,7 @@ child_compare_by_start (gpointer a, gpointer b)
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
static void
static int
fullday_add_children (iCalObject *obj, time_t start, time_t end, void *c)
{
GncalFullDay *fullday = c;
@ -1886,6 +1886,8 @@ fullday_add_children (iCalObject *obj, time_t start, time_t end, void *c)
child = child_new (fullday, start, end, obj);
fullday->children = g_list_insert_sorted (fullday->children, child, child_compare_by_start);
return 1;
}
void

View File

@ -198,7 +198,12 @@ gnome_calendar_update_all (GnomeCalendar *cal, iCalObject *object, int flags)
void
gnome_calendar_load (GnomeCalendar *gcal, char *file)
{
calendar_load (gcal->cal, file);
char *r;
if ((r = calendar_load (gcal->cal, file)) != NULL){
printf ("Error loading calendar: %s\n", r);
return;
}
gnome_calendar_update_all (gcal, NULL, 0);
}

View File

@ -8,34 +8,19 @@ DCREATED:19980402T023552
UID:KOrganizer - 1804289383
SEQUENCE:1
LAST-MODIFIED:19980330T225948
DTSTART:19980415T003000
DTEND:19980415T010000
SUMMARY:asdfasdfasfasdfasdf
DTSTART:19980415T116000
DTEND:19980415T119000
SUMMARY:Mensual, el 15, durante 4 semanas
STATUS:NEEDS ACTION
CLASS:PUBLIC
PRIORITY:0
TRANSP:0
RRULE:MD1 15 #4
RELATED-TO:0
X-PILOTID:0
X-PILOTSTAT:0
END:VEVENT
BEGIN:VEVENT
DCREATED:19980402T023558
UID:KOrganizer - 846930886
SEQUENCE:1
LAST-MODIFIED:19980402T023558
DTSTART:19980415T140000
DTEND:19980415T160000
SUMMARY:asdfasfdasfasdfasfd
STATUS:NEEDS ACTION
CLASS:PUBLIC
PRIORITY:0
TRANSP:0
RELATED-TO:0
X-PILOTID:0
X-PILOTSTAT:0
END:VEVENT
END:VCALENDAR

View File

@ -136,23 +136,6 @@ gncal_year_view_new (GnomeCalendar *calendar, time_t date)
return GTK_WIDGET (yview);
}
void gncal_year_view_set (GncalYearView *yview, time_t date)
{
int i;
char buff[10];
struct tm *tmptm;
tmptm = localtime(&date);
yview->year = tmptm->tm_year;
snprintf(buff, 10, "%d", yview->year + 1900);
gtk_label_set(GTK_LABEL(yview->year_label), buff);
for (i = 0; i < 12; i++) {
gtk_calendar_select_month (GTK_CALENDAR(yview->calendar[i]), i, yview->year);
}
}
static void
year_view_mark_day (iCalObject *ical, time_t start, time_t end, void *closure)
{
@ -174,6 +157,47 @@ year_view_mark_day (iCalObject *ical, time_t start, time_t end, void *closure)
}
}
static void
gncal_year_view_set_year (GncalYearView *yview, int year)
{
time_t year_begin, year_end;
char buff[20];
GList *l;
int i;
if (!yview->gcal->cal)
return;
snprintf(buff, 20, "%d", yview->year + 1900);
gtk_label_set(GTK_LABEL(yview->year_label), buff);
for (i = 0; i < 12; i++) {
gtk_calendar_select_month (GTK_CALENDAR(yview->calendar[i]), i, yview->year);
}
year_begin = time_year_begin (yview->year);
year_end = time_year_end (yview->year);
l = calendar_get_events_in_range (yview->gcal->cal, year_begin, year_end);
for (; l; l = l->next){
CalendarObject *co = l->data;
year_view_mark_day (co->ico, co->ev_start, co->ev_end, yview);
}
calendar_destroy_event_list (l);
}
void
gncal_year_view_set (GncalYearView *yview, time_t date)
{
struct tm *tmptm;
tmptm = localtime(&date);
yview->year = tmptm->tm_year;
gncal_year_view_set_year (yview, yview->year);
}
void
gncal_year_view_update (GncalYearView *yview, iCalObject *ico, int flags)
{
@ -184,19 +208,7 @@ gncal_year_view_update (GncalYearView *yview, iCalObject *ico, int flags)
if ((flags & CHANGE_SUMMARY) == flags)
return;
if (flags & CHANGE_NEW){
time_t year_begin, year_end;
GList *l, *nl;
year_begin = time_year_begin (yview->year);
year_end = time_year_end (yview->year);
l = g_list_append (NULL, ico);
nl = calendar_get_objects_in_range (l, year_begin, year_end, NULL);
if (nl){
ical_foreach (nl, year_view_mark_day, yview);
g_list_free (nl);
}
g_list_free (l);
}
printf ("MARCANDO!\n");
if (flags & CHANGE_NEW)
gncal_year_view_set_year (yview, yview->year);
}

View File

@ -12,6 +12,8 @@
#include "timeutil.h"
#include "versit/vcc.h"
static void ical_object_compute_end (iCalObject *ico);
iCalObject *
ical_object_new (void)
{
@ -35,7 +37,6 @@ default_alarm (iCalObject *ical, CalendarAlarm *alarm, char *def_mail, enum Alar
alarm->count = 15;
alarm->units = ALARM_MINUTES;
} else {
printf ("uno!\n");
alarm->count = 1;
alarm->units = ALARM_DAYS;
}
@ -140,7 +141,7 @@ static void
ignore_space(char **str)
{
while (**str && isspace (**str))
str++;
(*str)++;
}
static void
@ -183,6 +184,12 @@ weekdaylist (iCalObject *o, char **str)
}
}
} while (isalpha (**str));
if (o->recur->weekday == 0){
struct tm *tm = localtime (&o->dtstart);
o->recur->weekday = 1 << tm->tm_wday;
}
}
static void
@ -223,11 +230,11 @@ daynumber (iCalObject *o, char **str)
while (**str && isdigit (**str)){
val = val * 10 + (**str - '0');
str++;
(*str)++;
}
if (**str == '+')
str++;
(*str)++;
if (**str == '-')
val *= -1;
@ -245,8 +252,10 @@ daynumberlist (iCalObject *o, char **str)
while (**str){
if (!isdigit (**str))
return;
while (**str && isdigit (**str))
while (**str && isdigit (**str)){
val = 10 * val + (**str - '0');
(*str)++;
}
if (!first){
o->recur->u.month_day = val;
first = 1;
@ -300,10 +309,12 @@ duration (iCalObject *o, char **str)
ignore_space (str);
if (**str != '#')
return;
while (**str && isdigit (**str))
(*str)++;
while (**str && isdigit (**str)){
duration = duration * 10 + (**str - '0');
o->recur->temp_duration = duration;
(*str)++;
}
o->recur->duration = duration;
}
static void
@ -311,7 +322,7 @@ enddate (iCalObject *o, char **str)
{
ignore_space (str);
if (isdigit (**str)){
o->recur->enddate = time_from_isodate (*str);
o->recur->_enddate = time_from_isodate (*str);
*str += 16;
}
}
@ -335,7 +346,7 @@ load_recurrence (iCalObject *o, char *str)
case 'M':
if (*str == 'P')
type = RECUR_MONTHLY_BY_POS;
else if (*str == 'D')
else if (*str == 'D')
type = RECUR_MONTHLY_BY_DAY;
str++;
break;
@ -356,13 +367,18 @@ load_recurrence (iCalObject *o, char *str)
ignore_space (&str);
/* Get the interval */
while (*str && isdigit (*str))
for (;*str && isdigit (*str);str++)
interval = interval * 10 + (*str-'0');
o->recur->interval = interval;
/* this is the default per the spec */
o->recur->duration = 2;
ignore_space (&str);
switch (type){
case RECUR_DAILY:
break;
case RECUR_WEEKLY:
load_recur_weekly (o, &str);
break;
@ -385,6 +401,17 @@ load_recurrence (iCalObject *o, char *str)
duration (o, &str);
enddate (o, &str);
/* Compute the enddate */
if (o->recur->_enddate == 0){
printf ("ENDDATE es 0, d=%d\n", o->recur->duration);
if (o->recur->duration != 0){
ical_object_compute_end (o);
} else
o->recur->enddate = 0;
} else {
printf ("El evento termina\n");
o->recur->enddate = o->recur->_enddate;
}
return 1;
}
@ -689,14 +716,173 @@ ical_foreach (GList *events, calendarfn fn, void *closure)
}
}
static int
generate (iCalObject *ico, time_t reference, calendarfn cb, void *closure)
{
struct tm dt_start, dt_end, ref;
time_t s_t, e_t;
dt_start = *localtime (&ico->dtstart);
dt_end = *localtime (&ico->dtend);
ref = *localtime (&reference);
dt_start.tm_mday = ref.tm_mday;
dt_start.tm_mon = ref.tm_mon;
dt_start.tm_year = ref.tm_year;
dt_end.tm_mday = ref.tm_mday;
dt_end.tm_mon = ref.tm_mon;
dt_end.tm_year = ref.tm_year;
s_t = mktime (&dt_start);
e_t = mktime (&dt_end);
if (s_t == -1 || e_t == -1){
g_warning ("Produced invalid dates!\n");
return 0;
}
return (*cb)(ico, s_t, e_t, closure);
}
#define time_in_range(x,a,b) ((x >= a) && (b ? x <= b : 1))
/*
* Generate every possible event. Invokes the callback routine for
* every occurrence of the event in the [START, END] time interval.
*
* If END is zero, the event is generated forever.
* The callback routine is expected to return 0 when no further event
* generation is requested.
*/
void
ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendarfn cb, void *closure)
{
Recurrence *recur = ico->recur;
time_t current;
if (!ico->recur){
if ((start <= ico->dtstart) && (ico->dtend <= end))
(*cb)(ico, ico->dtstart, ico->dtend, closure);
if (time_in_range (ico->dtstart, start, end) ||
time_in_range (ico->dtend, start, end)){
time_t ev_s, ev_e;
ev_s = ico->dtstart < start ? start : ico->dtstart;
ev_e = ico->dtend > end ? end : ico->dtend;
(*cb)(ico, ev_s, ev_e, closure);
}
return;
}
/* The event has a recurrence rule */
if (end != 0){
if (ico->dtstart > end)
return;
if (!IS_INFINITE (ico->recur) && recur->enddate < start)
return;
}
current = ico->dtstart;
switch (recur->type){
case RECUR_DAILY:
do {
if (time_in_range (current, start, end)){
if (!generate (ico, current, cb, closure))
return;
}
/* Advance */
current = time_add_day (current, recur->interval);
if (current == -1){
g_warning ("RECUR_DAILY: mktime error\n");
return;
}
} while (current < end || (end == 0));
break;
case RECUR_WEEKLY:
do {
struct tm *tm = localtime (&current);
if (time_in_range (current, start, end)){
if (recur->weekday & (1 << tm->tm_wday))
if (!generate (ico, current, cb, closure))
return;
}
/* Advance by day for scanning the week or by interval at week end */
if (tm->tm_wday == 6)
current = time_add_day (current, recur->interval);
else
current = time_add_day (current, 1);
if (current == -1){
g_warning ("RECUR_WEEKLY: mktime error\n");
return;
}
} while (current < end || (end == 0));
break;
case RECUR_MONTHLY_BY_POS:
g_warning ("We still do not handle MONTHLY_BY_POS\n");
break;
case RECUR_MONTHLY_BY_DAY:
do {
struct tm *tm = localtime (&current);
time_t t;
int p;
p = tm->tm_mday;
tm->tm_mday = recur->u.month_day;
t = mktime (tm);
if (time_in_range (t, start, end))
if (!generate (ico, t, cb, closure))
return;
/* Advance a month */
tm->tm_mday = p;
tm->tm_mon += recur->interval;
current = mktime (tm);
if (current == -1){
g_warning ("RECUR_MONTHLY_BY_DAY: mktime error\n");
return;
}
} while (current < end || (end == 0));
case RECUR_YEARLY_BY_MONTH:
case RECUR_YEARLY_BY_DAY:
do {
if (time_in_range (current, start, end))
if (!generate (ico, current, cb, closure))
return;
/* Advance */
current = time_add_year (current, recur->interval);
} while (current < end || (end == 0));
}
}
static int
duration_callback (iCalObject *ico, time_t start, time_t end, void *closure)
{
int *count = closure;
(*count)++;
if (ico->recur->duration == *count){
ico->recur->enddate = end;
return 0;
}
return 1;
}
/* Computes ico->recur->enddate from ico->recur->duration */
void
ical_object_compute_end (iCalObject *ico)
{
int count = 0;
g_return_if_fail (ico->recur != NULL);
ical_object_generate_events (ico, ico->dtstart, 0, duration_callback, &count);
}

View File

@ -86,7 +86,14 @@ typedef struct {
enum RecurType type;
int interval;
time_t enddate;
/* Used for recur computation */
time_t enddate; /* If the value is zero, it is an infinite event
* otherwise, it is either the _enddate value (if
* this is what got specified) or it is our computed
* ending date (computed from the duration item).
*/
int weekday;
union {
@ -94,8 +101,11 @@ typedef struct {
int month_day;
} u;
int temp_duration; /* Used temporarly, we compute enddate */
int duration;
time_t _enddate; /* As found on the vCalendar file */
int __count;
} Recurrence;
#define IS_INFINITE(r) (r->duration == 0)
/* Flags to indicate what has changed in an object */
typedef enum {
@ -157,7 +167,7 @@ typedef struct {
} iCalObject;
/* The callback for the recurrence generator */
typedef void (*calendarfn)(iCalObject *, time_t, time_t, void *);
typedef int (*calendarfn)(iCalObject *, time_t, time_t, void *);
iCalObject *ical_new (char *comment, char *organizer, char *summary);
iCalObject *ical_object_new (void);

View File

@ -8,34 +8,19 @@ DCREATED:19980402T023552
UID:KOrganizer - 1804289383
SEQUENCE:1
LAST-MODIFIED:19980330T225948
DTSTART:19980415T003000
DTEND:19980415T010000
SUMMARY:asdfasdfasfasdfasdf
DTSTART:19980415T116000
DTEND:19980415T119000
SUMMARY:Mensual, el 15, durante 4 semanas
STATUS:NEEDS ACTION
CLASS:PUBLIC
PRIORITY:0
TRANSP:0
RRULE:MD1 15 #4
RELATED-TO:0
X-PILOTID:0
X-PILOTSTAT:0
END:VEVENT
BEGIN:VEVENT
DCREATED:19980402T023558
UID:KOrganizer - 846930886
SEQUENCE:1
LAST-MODIFIED:19980402T023558
DTSTART:19980415T140000
DTEND:19980415T160000
SUMMARY:asdfasfdasfasdfasfd
STATUS:NEEDS ACTION
CLASS:PUBLIC
PRIORITY:0
TRANSP:0
RELATED-TO:0
X-PILOTID:0
X-PILOTSTAT:0
END:VEVENT
END:VCALENDAR

View File

@ -122,15 +122,13 @@ time_t
time_day_hour (time_t t, int hour)
{
struct tm tm;
time_t retval;
tm = *localtime (&t);
tm.tm_hour = hour;
tm.tm_min = 0;
tm.tm_sec = 0;
retval = mktime (&tm);
return retval;
return mktime (&tm);
}
@ -138,22 +136,19 @@ time_t
time_start_of_day (time_t t)
{
struct tm tm;
time_t retval;
tm = *localtime (&t);
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
retval = mktime (&tm);
return retval;
return mktime (&tm);
}
time_t
time_end_of_day (time_t t)
{
struct tm tm;
time_t retval;
tm = *localtime (&t);
tm.tm_hour = 0;
@ -161,8 +156,7 @@ time_end_of_day (time_t t)
tm.tm_sec = 0;
tm.tm_mday++;
retval = mktime (&tm);
return retval;
return mktime (&tm);
}
time_t
@ -187,7 +181,6 @@ time_t
time_year_end (int year)
{
struct tm tm;
time_t retval;
tm.tm_hour = 23;
tm.tm_min = 59;
@ -197,6 +190,17 @@ time_year_end (int year)
tm.tm_mday = 31;
tm.tm_isdst = -1;
retval = mktime (&tm);
return retval;
return mktime (&tm);
}
time_t
time_week_begin (time_t t)
{
struct tm tm;
time_t retval;
tm = *localtime (&t);
tm.tm_mday -= tm.tm_wday;
return mktime (&tm);
}

View File

@ -19,9 +19,10 @@ char *isodate_from_time_t (time_t t);
int get_time_t_hour (time_t t);
time_t time_add_week (time_t time, int weeks);
time_t time_add_day (time_t time, int weeks);
time_t time_add_day (time_t time, int days);
time_t time_add_year (time_t time, int years);
/* Returns pointer to a statically-allocated buffer with a string of the form
* 3am, 4am, 12pm, 08h, 17h, etc.
* The string is internationalized, hopefully correctly.
@ -29,10 +30,12 @@ time_t time_add_year (time_t time, int years);
char *format_simple_hour (int hour, int use_am_pm);
time_t time_start_of_day (time_t t);
time_t time_end_of_day (time_t t);
time_t time_day_hour (time_t t, int hour);
time_t time_year_begin (int year);
time_t time_year_end (int year);
time_t time_end_of_day (time_t t);
time_t time_day_hour (time_t t, int hour);
time_t time_year_begin (int year);
time_t time_year_end (int year);
time_t time_week_begin (time_t t);
void print_time_t (time_t t);
#endif

View File

@ -136,23 +136,6 @@ gncal_year_view_new (GnomeCalendar *calendar, time_t date)
return GTK_WIDGET (yview);
}
void gncal_year_view_set (GncalYearView *yview, time_t date)
{
int i;
char buff[10];
struct tm *tmptm;
tmptm = localtime(&date);
yview->year = tmptm->tm_year;
snprintf(buff, 10, "%d", yview->year + 1900);
gtk_label_set(GTK_LABEL(yview->year_label), buff);
for (i = 0; i < 12; i++) {
gtk_calendar_select_month (GTK_CALENDAR(yview->calendar[i]), i, yview->year);
}
}
static void
year_view_mark_day (iCalObject *ical, time_t start, time_t end, void *closure)
{
@ -174,6 +157,47 @@ year_view_mark_day (iCalObject *ical, time_t start, time_t end, void *closure)
}
}
static void
gncal_year_view_set_year (GncalYearView *yview, int year)
{
time_t year_begin, year_end;
char buff[20];
GList *l;
int i;
if (!yview->gcal->cal)
return;
snprintf(buff, 20, "%d", yview->year + 1900);
gtk_label_set(GTK_LABEL(yview->year_label), buff);
for (i = 0; i < 12; i++) {
gtk_calendar_select_month (GTK_CALENDAR(yview->calendar[i]), i, yview->year);
}
year_begin = time_year_begin (yview->year);
year_end = time_year_end (yview->year);
l = calendar_get_events_in_range (yview->gcal->cal, year_begin, year_end);
for (; l; l = l->next){
CalendarObject *co = l->data;
year_view_mark_day (co->ico, co->ev_start, co->ev_end, yview);
}
calendar_destroy_event_list (l);
}
void
gncal_year_view_set (GncalYearView *yview, time_t date)
{
struct tm *tmptm;
tmptm = localtime(&date);
yview->year = tmptm->tm_year;
gncal_year_view_set_year (yview, yview->year);
}
void
gncal_year_view_update (GncalYearView *yview, iCalObject *ico, int flags)
{
@ -184,19 +208,7 @@ gncal_year_view_update (GncalYearView *yview, iCalObject *ico, int flags)
if ((flags & CHANGE_SUMMARY) == flags)
return;
if (flags & CHANGE_NEW){
time_t year_begin, year_end;
GList *l, *nl;
year_begin = time_year_begin (yview->year);
year_end = time_year_end (yview->year);
l = g_list_append (NULL, ico);
nl = calendar_get_objects_in_range (l, year_begin, year_end, NULL);
if (nl){
ical_foreach (nl, year_view_mark_day, yview);
g_list_free (nl);
}
g_list_free (l);
}
printf ("MARCANDO!\n");
if (flags & CHANGE_NEW)
gncal_year_view_set_year (yview, yview->year);
}