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:
@ -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 (¤t);
|
||||
|
||||
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 (¤t);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,16 +86,26 @@ 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 {
|
||||
int month_pos;
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 (¤t);
|
||||
|
||||
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 (¤t);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,16 +86,26 @@ 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 {
|
||||
int month_pos;
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 (¤t);
|
||||
|
||||
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 (¤t);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,16 +86,26 @@ 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 {
|
||||
int month_pos;
|
||||
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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user