Load recurrence rules; Paint the recurrence screen according to the rules.
Load recurrence rules; Paint the recurrence screen according to the rules. -miguel svn path=/trunk/; revision=133
This commit is contained in:
@ -115,10 +115,270 @@ set_list (char *str, char *sc)
|
||||
return list;
|
||||
}
|
||||
|
||||
static GList *
|
||||
set_date_list (char *str)
|
||||
{
|
||||
GList *list = 0;
|
||||
char *s;
|
||||
|
||||
for (s = strtok (str, ";"); s; s = strtok (NULL, ";")){
|
||||
time_t *t = g_new (time_t, 1);
|
||||
|
||||
*t = time_from_isodate (s);
|
||||
list = g_list_prepend (list, t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static void
|
||||
ignore_space(char **str)
|
||||
{
|
||||
while (**str && isspace (**str))
|
||||
*str++;
|
||||
}
|
||||
|
||||
static void
|
||||
skip_numbers (char **str)
|
||||
{
|
||||
while (**str){
|
||||
ignore_space (str);
|
||||
if (!isdigit (**str))
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
weekdaylist (iCalObject *o, char **str)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
char first_letter, second_letter;
|
||||
int index;
|
||||
} days [] = {
|
||||
{ 'S', 'U', 0 },
|
||||
{ 'M', 'O', 1 },
|
||||
{ 'T', 'U', 2 },
|
||||
{ 'W', 'E', 3 },
|
||||
{ 'T', 'H', 4 },
|
||||
{ 'F', 'R', 5 },
|
||||
{ 'S', 'A', 6 }
|
||||
};
|
||||
|
||||
ignore_space (str);
|
||||
do {
|
||||
for (i = 0; i < 7; i++){
|
||||
if (**str == days [i].first_letter && *(*str+1) == days [i].second_letter){
|
||||
o->recur->weekday |= 1 << i;
|
||||
*str += 2;
|
||||
if (**str == ' ')
|
||||
(*str)++;
|
||||
}
|
||||
}
|
||||
} while (isalpha (**str));
|
||||
}
|
||||
|
||||
static void
|
||||
ocurrencelist (iCalObject *o, char **str)
|
||||
{
|
||||
char *p, *q;
|
||||
int value = 0;
|
||||
|
||||
ignore_space (str);
|
||||
p = *str;
|
||||
if (!isdigit (*str))
|
||||
return;
|
||||
|
||||
if (!(*p >= '1' && *p <= '5'))
|
||||
return;
|
||||
|
||||
if (!(*(p+1) == '+' || *(p+1) == '-'))
|
||||
return;
|
||||
|
||||
o->recur->u.month_pos = (*p-'0') * (*(p+1) == '+' ? 1 : -1);
|
||||
*str += 2;
|
||||
}
|
||||
|
||||
static void
|
||||
daynumber (iCalObject *o, char **str)
|
||||
{
|
||||
int val = 0;
|
||||
char *p = *str;
|
||||
|
||||
ignore_space (str);
|
||||
if (strcmp (p, "LD")){
|
||||
o->recur->u.month_day = DAY_LASTDAY;
|
||||
*str += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(isdigit (*p)))
|
||||
return;
|
||||
|
||||
while (**str && isdigit (**str)){
|
||||
val = val * 10 + (**str - '0');
|
||||
*str++;
|
||||
}
|
||||
|
||||
if (**str == '+')
|
||||
*str++;
|
||||
|
||||
if (**str == '-')
|
||||
val *= -1;
|
||||
o->recur->u.month_day = val;
|
||||
}
|
||||
|
||||
static void
|
||||
daynumberlist (iCalObject *o, char **str)
|
||||
{
|
||||
int first = 0;
|
||||
int val = 0;
|
||||
|
||||
ignore_space (str);
|
||||
|
||||
while (**str){
|
||||
if (!isdigit (**str))
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
val = 10 * val + (**str - '0');
|
||||
if (!first){
|
||||
o->recur->u.month_day = val;
|
||||
first = 1;
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_weekly (iCalObject *o, char **str)
|
||||
{
|
||||
weekdaylist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_monthly_pos (iCalObject *o, char **str)
|
||||
{
|
||||
ocurrencelist (o, str);
|
||||
weekdaylist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_monthly_day (iCalObject *o, char **str)
|
||||
{
|
||||
daynumberlist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_yearly_month (iCalObject *o, char **str)
|
||||
{
|
||||
/* Skip as we do not support multiple months and we do expect
|
||||
* the dtstart to agree with the value on this field
|
||||
*/
|
||||
skip_numbers (str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_yearly_day (iCalObject *o, char **str)
|
||||
{
|
||||
/* Skip as we do not support multiple days and we do expect
|
||||
* the dtstart to agree with the value on this field
|
||||
*/
|
||||
skip_numbers (str);
|
||||
}
|
||||
|
||||
static void
|
||||
duration (iCalObject *o, char **str)
|
||||
{
|
||||
int duration = 0;
|
||||
|
||||
ignore_space (str);
|
||||
if (**str != '#')
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
duration = duration * 10 + (**str - '0');
|
||||
|
||||
o->recur->temp_duration = duration;
|
||||
}
|
||||
|
||||
static void
|
||||
enddate (iCalObject *o, char **str)
|
||||
{
|
||||
ignore_space (str);
|
||||
if (isdigit (**str)){
|
||||
o->recur->enddate = time_from_isodate (*str);
|
||||
*str += 16;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
load_recurrence (iCalObject *o, char *str)
|
||||
{
|
||||
char c;
|
||||
enum RecurType type;
|
||||
int interval = 0;
|
||||
|
||||
type = -1;
|
||||
switch (*str++){
|
||||
case 'D':
|
||||
type = RECUR_DAILY;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
type = RECUR_WEEKLY;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (*str == 'P')
|
||||
type = RECUR_MONTHLY_BY_POS;
|
||||
else if (*str == 'D')
|
||||
type = RECUR_MONTHLY_BY_DAY;
|
||||
str++;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (*str == 'M')
|
||||
type = RECUR_YEARLY_BY_MONTH;
|
||||
else if (*str == 'D')
|
||||
type = RECUR_YEARLY_BY_DAY;
|
||||
str++;
|
||||
break;
|
||||
}
|
||||
if (type == -1)
|
||||
return 0;
|
||||
|
||||
o->recur = g_new0 (Recurrence, 1);
|
||||
o->recur->type = type;
|
||||
ignore_space (&str);
|
||||
|
||||
/* Get the interval */
|
||||
while (*str && isdigit (*str))
|
||||
interval = interval * 10 + (*str-'0');
|
||||
o->recur->interval = interval;
|
||||
|
||||
ignore_space (&str);
|
||||
|
||||
switch (type){
|
||||
case RECUR_WEEKLY:
|
||||
load_recur_weekly (o, &str);
|
||||
break;
|
||||
case RECUR_MONTHLY_BY_POS:
|
||||
load_recur_monthly_pos (o, &str);
|
||||
break;
|
||||
case RECUR_MONTHLY_BY_DAY:
|
||||
load_recur_monthly_day (o, &str);
|
||||
break;
|
||||
case RECUR_YEARLY_BY_MONTH:
|
||||
load_recur_yearly_month (o, &str);
|
||||
break;
|
||||
case RECUR_YEARLY_BY_DAY:
|
||||
load_recur_yearly_day (o, &str);
|
||||
break;
|
||||
}
|
||||
duration (o, &str);
|
||||
enddate (o, &str);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define is_a_prop_of(obj,prop) isAPropertyOf (obj,prop)
|
||||
@ -133,6 +393,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
iCalObject *ical;
|
||||
VObject *vo;
|
||||
VObjectIterator i;
|
||||
int syntax_error;
|
||||
|
||||
ical = g_new0 (iCalObject, 1);
|
||||
|
||||
@ -181,7 +442,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
|
||||
/* exdate */
|
||||
if (has (o, VCExpDateProp))
|
||||
ical->exdate = set_list (str_val (vo), ",");
|
||||
ical->exdate = set_date_list (str_val (vo));
|
||||
|
||||
/* description/comment */
|
||||
if (has (o, VCDescriptionProp))
|
||||
@ -254,7 +515,12 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
|
||||
/* FIXME: rrule */
|
||||
if (has (o, VCRRuleProp))
|
||||
load_recurrence (ical, str_val (vo));
|
||||
syntax_error = load_recurrence (ical, str_val (vo)) == 0;
|
||||
|
||||
if (syntax_error){
|
||||
ical_object_destroy (ical);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ical;
|
||||
}
|
||||
|
@ -79,10 +79,21 @@ enum RecurType {
|
||||
RECUR_YEARLY_BY_DAY,
|
||||
};
|
||||
|
||||
#define DAY_LASTDAY 10000
|
||||
|
||||
typedef struct {
|
||||
enum RecurType type;
|
||||
|
||||
int frequency;
|
||||
int interval;
|
||||
time_t enddate;
|
||||
int weekday;
|
||||
|
||||
union {
|
||||
int month_pos;
|
||||
int month_day;
|
||||
} u;
|
||||
|
||||
int temp_duration; /* Used temporarly, we compute enddate */
|
||||
} Recurrence;
|
||||
|
||||
/* Flags to indicate what has changed in an object */
|
||||
|
@ -115,10 +115,270 @@ set_list (char *str, char *sc)
|
||||
return list;
|
||||
}
|
||||
|
||||
static GList *
|
||||
set_date_list (char *str)
|
||||
{
|
||||
GList *list = 0;
|
||||
char *s;
|
||||
|
||||
for (s = strtok (str, ";"); s; s = strtok (NULL, ";")){
|
||||
time_t *t = g_new (time_t, 1);
|
||||
|
||||
*t = time_from_isodate (s);
|
||||
list = g_list_prepend (list, t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static void
|
||||
ignore_space(char **str)
|
||||
{
|
||||
while (**str && isspace (**str))
|
||||
*str++;
|
||||
}
|
||||
|
||||
static void
|
||||
skip_numbers (char **str)
|
||||
{
|
||||
while (**str){
|
||||
ignore_space (str);
|
||||
if (!isdigit (**str))
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
weekdaylist (iCalObject *o, char **str)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
char first_letter, second_letter;
|
||||
int index;
|
||||
} days [] = {
|
||||
{ 'S', 'U', 0 },
|
||||
{ 'M', 'O', 1 },
|
||||
{ 'T', 'U', 2 },
|
||||
{ 'W', 'E', 3 },
|
||||
{ 'T', 'H', 4 },
|
||||
{ 'F', 'R', 5 },
|
||||
{ 'S', 'A', 6 }
|
||||
};
|
||||
|
||||
ignore_space (str);
|
||||
do {
|
||||
for (i = 0; i < 7; i++){
|
||||
if (**str == days [i].first_letter && *(*str+1) == days [i].second_letter){
|
||||
o->recur->weekday |= 1 << i;
|
||||
*str += 2;
|
||||
if (**str == ' ')
|
||||
(*str)++;
|
||||
}
|
||||
}
|
||||
} while (isalpha (**str));
|
||||
}
|
||||
|
||||
static void
|
||||
ocurrencelist (iCalObject *o, char **str)
|
||||
{
|
||||
char *p, *q;
|
||||
int value = 0;
|
||||
|
||||
ignore_space (str);
|
||||
p = *str;
|
||||
if (!isdigit (*str))
|
||||
return;
|
||||
|
||||
if (!(*p >= '1' && *p <= '5'))
|
||||
return;
|
||||
|
||||
if (!(*(p+1) == '+' || *(p+1) == '-'))
|
||||
return;
|
||||
|
||||
o->recur->u.month_pos = (*p-'0') * (*(p+1) == '+' ? 1 : -1);
|
||||
*str += 2;
|
||||
}
|
||||
|
||||
static void
|
||||
daynumber (iCalObject *o, char **str)
|
||||
{
|
||||
int val = 0;
|
||||
char *p = *str;
|
||||
|
||||
ignore_space (str);
|
||||
if (strcmp (p, "LD")){
|
||||
o->recur->u.month_day = DAY_LASTDAY;
|
||||
*str += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(isdigit (*p)))
|
||||
return;
|
||||
|
||||
while (**str && isdigit (**str)){
|
||||
val = val * 10 + (**str - '0');
|
||||
*str++;
|
||||
}
|
||||
|
||||
if (**str == '+')
|
||||
*str++;
|
||||
|
||||
if (**str == '-')
|
||||
val *= -1;
|
||||
o->recur->u.month_day = val;
|
||||
}
|
||||
|
||||
static void
|
||||
daynumberlist (iCalObject *o, char **str)
|
||||
{
|
||||
int first = 0;
|
||||
int val = 0;
|
||||
|
||||
ignore_space (str);
|
||||
|
||||
while (**str){
|
||||
if (!isdigit (**str))
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
val = 10 * val + (**str - '0');
|
||||
if (!first){
|
||||
o->recur->u.month_day = val;
|
||||
first = 1;
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_weekly (iCalObject *o, char **str)
|
||||
{
|
||||
weekdaylist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_monthly_pos (iCalObject *o, char **str)
|
||||
{
|
||||
ocurrencelist (o, str);
|
||||
weekdaylist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_monthly_day (iCalObject *o, char **str)
|
||||
{
|
||||
daynumberlist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_yearly_month (iCalObject *o, char **str)
|
||||
{
|
||||
/* Skip as we do not support multiple months and we do expect
|
||||
* the dtstart to agree with the value on this field
|
||||
*/
|
||||
skip_numbers (str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_yearly_day (iCalObject *o, char **str)
|
||||
{
|
||||
/* Skip as we do not support multiple days and we do expect
|
||||
* the dtstart to agree with the value on this field
|
||||
*/
|
||||
skip_numbers (str);
|
||||
}
|
||||
|
||||
static void
|
||||
duration (iCalObject *o, char **str)
|
||||
{
|
||||
int duration = 0;
|
||||
|
||||
ignore_space (str);
|
||||
if (**str != '#')
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
duration = duration * 10 + (**str - '0');
|
||||
|
||||
o->recur->temp_duration = duration;
|
||||
}
|
||||
|
||||
static void
|
||||
enddate (iCalObject *o, char **str)
|
||||
{
|
||||
ignore_space (str);
|
||||
if (isdigit (**str)){
|
||||
o->recur->enddate = time_from_isodate (*str);
|
||||
*str += 16;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
load_recurrence (iCalObject *o, char *str)
|
||||
{
|
||||
char c;
|
||||
enum RecurType type;
|
||||
int interval = 0;
|
||||
|
||||
type = -1;
|
||||
switch (*str++){
|
||||
case 'D':
|
||||
type = RECUR_DAILY;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
type = RECUR_WEEKLY;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (*str == 'P')
|
||||
type = RECUR_MONTHLY_BY_POS;
|
||||
else if (*str == 'D')
|
||||
type = RECUR_MONTHLY_BY_DAY;
|
||||
str++;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (*str == 'M')
|
||||
type = RECUR_YEARLY_BY_MONTH;
|
||||
else if (*str == 'D')
|
||||
type = RECUR_YEARLY_BY_DAY;
|
||||
str++;
|
||||
break;
|
||||
}
|
||||
if (type == -1)
|
||||
return 0;
|
||||
|
||||
o->recur = g_new0 (Recurrence, 1);
|
||||
o->recur->type = type;
|
||||
ignore_space (&str);
|
||||
|
||||
/* Get the interval */
|
||||
while (*str && isdigit (*str))
|
||||
interval = interval * 10 + (*str-'0');
|
||||
o->recur->interval = interval;
|
||||
|
||||
ignore_space (&str);
|
||||
|
||||
switch (type){
|
||||
case RECUR_WEEKLY:
|
||||
load_recur_weekly (o, &str);
|
||||
break;
|
||||
case RECUR_MONTHLY_BY_POS:
|
||||
load_recur_monthly_pos (o, &str);
|
||||
break;
|
||||
case RECUR_MONTHLY_BY_DAY:
|
||||
load_recur_monthly_day (o, &str);
|
||||
break;
|
||||
case RECUR_YEARLY_BY_MONTH:
|
||||
load_recur_yearly_month (o, &str);
|
||||
break;
|
||||
case RECUR_YEARLY_BY_DAY:
|
||||
load_recur_yearly_day (o, &str);
|
||||
break;
|
||||
}
|
||||
duration (o, &str);
|
||||
enddate (o, &str);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define is_a_prop_of(obj,prop) isAPropertyOf (obj,prop)
|
||||
@ -133,6 +393,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
iCalObject *ical;
|
||||
VObject *vo;
|
||||
VObjectIterator i;
|
||||
int syntax_error;
|
||||
|
||||
ical = g_new0 (iCalObject, 1);
|
||||
|
||||
@ -181,7 +442,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
|
||||
/* exdate */
|
||||
if (has (o, VCExpDateProp))
|
||||
ical->exdate = set_list (str_val (vo), ",");
|
||||
ical->exdate = set_date_list (str_val (vo));
|
||||
|
||||
/* description/comment */
|
||||
if (has (o, VCDescriptionProp))
|
||||
@ -254,7 +515,12 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
|
||||
/* FIXME: rrule */
|
||||
if (has (o, VCRRuleProp))
|
||||
load_recurrence (ical, str_val (vo));
|
||||
syntax_error = load_recurrence (ical, str_val (vo)) == 0;
|
||||
|
||||
if (syntax_error){
|
||||
ical_object_destroy (ical);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ical;
|
||||
}
|
||||
|
@ -79,10 +79,21 @@ enum RecurType {
|
||||
RECUR_YEARLY_BY_DAY,
|
||||
};
|
||||
|
||||
#define DAY_LASTDAY 10000
|
||||
|
||||
typedef struct {
|
||||
enum RecurType type;
|
||||
|
||||
int frequency;
|
||||
int interval;
|
||||
time_t enddate;
|
||||
int weekday;
|
||||
|
||||
union {
|
||||
int month_pos;
|
||||
int month_day;
|
||||
} u;
|
||||
|
||||
int temp_duration; /* Used temporarly, we compute enddate */
|
||||
} Recurrence;
|
||||
|
||||
/* Flags to indicate what has changed in an object */
|
||||
|
@ -621,7 +621,7 @@ static char *weekday_names [] = {
|
||||
};
|
||||
|
||||
static GtkWidget *
|
||||
make_day_list_widget (char **array)
|
||||
make_day_list_widget (char **array, int sel)
|
||||
{
|
||||
GtkWidget *option_menu, *menu;
|
||||
int i;
|
||||
@ -636,6 +636,7 @@ make_day_list_widget (char **array)
|
||||
gtk_widget_show (item);
|
||||
}
|
||||
gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
|
||||
gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), sel);
|
||||
return option_menu;
|
||||
}
|
||||
|
||||
@ -663,6 +664,12 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
GtkNotebook *notebook;
|
||||
GSList *group;
|
||||
int i, page, day_period, week_period, month_period, year_period;
|
||||
int week_vector, default_day, def_pos, def_off;
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
|
||||
now = time (NULL);
|
||||
tm = localtime (&now);
|
||||
|
||||
f = gtk_frame_new (_("Frequency"));
|
||||
vbox = gtk_vbox_new (0, 0);
|
||||
@ -680,18 +687,50 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
month_period = 1;
|
||||
year_period = 1;
|
||||
|
||||
/* Default to today */
|
||||
week_vector = 1 << tm->tm_wday;
|
||||
default_day = tm->tm_mday - 1;
|
||||
def_pos = 0;
|
||||
def_off = 0;
|
||||
|
||||
/* Determine which should be the default selection */
|
||||
if (ee->ical->recur){
|
||||
enum RecurType type = ee->ical->recur->type;
|
||||
int freq = ee->ical->recur->frequency;
|
||||
int interval = ee->ical->recur->interval;
|
||||
|
||||
switch (type){
|
||||
case RECUR_DAILY: page = 0; day_period = freq; break;
|
||||
case RECUR_WEEKLY: page = 1; week_period = freq; break;
|
||||
case RECUR_MONTHLY_BY_POS: page = 2; month_period = freq; break;
|
||||
case RECUR_MONTHLY_BY_DAY: page = 2; month_period = freq; break;
|
||||
case RECUR_YEARLY_BY_MONTH: page = 3; year_period = freq; break;
|
||||
case RECUR_YEARLY_BY_DAY: page = 4; year_period = freq; break;
|
||||
case RECUR_DAILY:
|
||||
page = 0;
|
||||
day_period = interval;
|
||||
break;
|
||||
|
||||
case RECUR_WEEKLY:
|
||||
page = 1;
|
||||
week_period = interval;
|
||||
week_vector = ee->ical->recur->weekday;
|
||||
break;
|
||||
|
||||
case RECUR_MONTHLY_BY_POS:
|
||||
page = 2;
|
||||
month_period = interval;
|
||||
def_pos = ee->ical->recur->u.month_pos;
|
||||
break;
|
||||
|
||||
case RECUR_MONTHLY_BY_DAY:
|
||||
page = 2;
|
||||
month_period = interval;
|
||||
default_day = ee->ical->recur->u.month_day;
|
||||
break;
|
||||
|
||||
case RECUR_YEARLY_BY_MONTH:
|
||||
page = 3;
|
||||
year_period = interval;
|
||||
break;
|
||||
|
||||
case RECUR_YEARLY_BY_DAY:
|
||||
page = 4;
|
||||
year_period = interval;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
page = 0;
|
||||
@ -731,6 +770,8 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
for (i = 0; i < 7; i++){
|
||||
ee->recur_week_days [i] = gtk_check_button_new_with_label (_(day_names [i]));
|
||||
gtk_box_pack_start (GTK_BOX (week_day), ee->recur_week_days [i], 1, 1, 5);
|
||||
if (week_vector & (1 << i))
|
||||
gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (ee->recur_week_days [i]));
|
||||
}
|
||||
gtk_box_pack_start (GTK_BOX (weekly), week_day, 1, 1, 0);
|
||||
|
||||
@ -738,7 +779,7 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
/* 3. The monthly recurrence */
|
||||
monthly = gtk_table_new (0, 0, 0);
|
||||
re = gtk_radio_button_new_with_label (NULL, _("Recur on the"));
|
||||
ee->recur_month_date = make_day_list_widget (numeral_day_names);
|
||||
ee->recur_month_date = make_day_list_widget (numeral_day_names, default_day);
|
||||
w = gtk_label_new (_("day"));
|
||||
gtk_table_attach (GTK_TABLE (monthly), re,
|
||||
0, 1, 0, 1, 0, 0, 0, 0);
|
||||
@ -748,9 +789,9 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
2, 3, 0, 1, 0, 0, 0, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (re), "toggled", GTK_SIGNAL_FUNC (recur_month_enable_date), ee);
|
||||
|
||||
r1 = gtk_radio_button_new_with_label (gtk_radio_button_group (GTK_RADIO_BUTTON (r)), _("Recur on the"));
|
||||
ee->recur_month_day = make_day_list_widget (numeral_day_names);
|
||||
ee->recur_month_weekday = make_day_list_widget (weekday_names);
|
||||
r1 = gtk_radio_button_new_with_label (gtk_radio_button_group (GTK_RADIO_BUTTON (re)), _("Recur on the"));
|
||||
ee->recur_month_day = make_day_list_widget (numeral_day_names, 0);
|
||||
ee->recur_month_weekday = make_day_list_widget (weekday_names, def_pos);
|
||||
gtk_table_attach (GTK_TABLE (monthly), r1,
|
||||
0, 1, 1, 2, 0, 0, 0, 0);
|
||||
gtk_table_attach (GTK_TABLE (monthly), ee->recur_month_day,
|
||||
@ -764,6 +805,13 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
4, 5, 0, 2, 0, 0, 5, 0);
|
||||
gtk_table_attach (GTK_TABLE (monthly), gtk_label_new (_("month(s)")),
|
||||
5, 6, 0, 2, 0, 0, 0, 0);
|
||||
if (ee->ical->recur){
|
||||
if (ee->ical->recur->type == RECUR_MONTHLY_BY_POS)
|
||||
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (r1), 1);
|
||||
} else {
|
||||
recur_month_enable_date ((re), ee);
|
||||
}
|
||||
|
||||
/* 4. The yearly recurrence */
|
||||
yearly = gtk_hbox_new (0, 0);
|
||||
ee->recur_year_period = small_entry (year_period);
|
||||
|
@ -621,7 +621,7 @@ static char *weekday_names [] = {
|
||||
};
|
||||
|
||||
static GtkWidget *
|
||||
make_day_list_widget (char **array)
|
||||
make_day_list_widget (char **array, int sel)
|
||||
{
|
||||
GtkWidget *option_menu, *menu;
|
||||
int i;
|
||||
@ -636,6 +636,7 @@ make_day_list_widget (char **array)
|
||||
gtk_widget_show (item);
|
||||
}
|
||||
gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
|
||||
gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), sel);
|
||||
return option_menu;
|
||||
}
|
||||
|
||||
@ -663,6 +664,12 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
GtkNotebook *notebook;
|
||||
GSList *group;
|
||||
int i, page, day_period, week_period, month_period, year_period;
|
||||
int week_vector, default_day, def_pos, def_off;
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
|
||||
now = time (NULL);
|
||||
tm = localtime (&now);
|
||||
|
||||
f = gtk_frame_new (_("Frequency"));
|
||||
vbox = gtk_vbox_new (0, 0);
|
||||
@ -680,18 +687,50 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
month_period = 1;
|
||||
year_period = 1;
|
||||
|
||||
/* Default to today */
|
||||
week_vector = 1 << tm->tm_wday;
|
||||
default_day = tm->tm_mday - 1;
|
||||
def_pos = 0;
|
||||
def_off = 0;
|
||||
|
||||
/* Determine which should be the default selection */
|
||||
if (ee->ical->recur){
|
||||
enum RecurType type = ee->ical->recur->type;
|
||||
int freq = ee->ical->recur->frequency;
|
||||
int interval = ee->ical->recur->interval;
|
||||
|
||||
switch (type){
|
||||
case RECUR_DAILY: page = 0; day_period = freq; break;
|
||||
case RECUR_WEEKLY: page = 1; week_period = freq; break;
|
||||
case RECUR_MONTHLY_BY_POS: page = 2; month_period = freq; break;
|
||||
case RECUR_MONTHLY_BY_DAY: page = 2; month_period = freq; break;
|
||||
case RECUR_YEARLY_BY_MONTH: page = 3; year_period = freq; break;
|
||||
case RECUR_YEARLY_BY_DAY: page = 4; year_period = freq; break;
|
||||
case RECUR_DAILY:
|
||||
page = 0;
|
||||
day_period = interval;
|
||||
break;
|
||||
|
||||
case RECUR_WEEKLY:
|
||||
page = 1;
|
||||
week_period = interval;
|
||||
week_vector = ee->ical->recur->weekday;
|
||||
break;
|
||||
|
||||
case RECUR_MONTHLY_BY_POS:
|
||||
page = 2;
|
||||
month_period = interval;
|
||||
def_pos = ee->ical->recur->u.month_pos;
|
||||
break;
|
||||
|
||||
case RECUR_MONTHLY_BY_DAY:
|
||||
page = 2;
|
||||
month_period = interval;
|
||||
default_day = ee->ical->recur->u.month_day;
|
||||
break;
|
||||
|
||||
case RECUR_YEARLY_BY_MONTH:
|
||||
page = 3;
|
||||
year_period = interval;
|
||||
break;
|
||||
|
||||
case RECUR_YEARLY_BY_DAY:
|
||||
page = 4;
|
||||
year_period = interval;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
page = 0;
|
||||
@ -731,6 +770,8 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
for (i = 0; i < 7; i++){
|
||||
ee->recur_week_days [i] = gtk_check_button_new_with_label (_(day_names [i]));
|
||||
gtk_box_pack_start (GTK_BOX (week_day), ee->recur_week_days [i], 1, 1, 5);
|
||||
if (week_vector & (1 << i))
|
||||
gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (ee->recur_week_days [i]));
|
||||
}
|
||||
gtk_box_pack_start (GTK_BOX (weekly), week_day, 1, 1, 0);
|
||||
|
||||
@ -738,7 +779,7 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
/* 3. The monthly recurrence */
|
||||
monthly = gtk_table_new (0, 0, 0);
|
||||
re = gtk_radio_button_new_with_label (NULL, _("Recur on the"));
|
||||
ee->recur_month_date = make_day_list_widget (numeral_day_names);
|
||||
ee->recur_month_date = make_day_list_widget (numeral_day_names, default_day);
|
||||
w = gtk_label_new (_("day"));
|
||||
gtk_table_attach (GTK_TABLE (monthly), re,
|
||||
0, 1, 0, 1, 0, 0, 0, 0);
|
||||
@ -748,9 +789,9 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
2, 3, 0, 1, 0, 0, 0, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (re), "toggled", GTK_SIGNAL_FUNC (recur_month_enable_date), ee);
|
||||
|
||||
r1 = gtk_radio_button_new_with_label (gtk_radio_button_group (GTK_RADIO_BUTTON (r)), _("Recur on the"));
|
||||
ee->recur_month_day = make_day_list_widget (numeral_day_names);
|
||||
ee->recur_month_weekday = make_day_list_widget (weekday_names);
|
||||
r1 = gtk_radio_button_new_with_label (gtk_radio_button_group (GTK_RADIO_BUTTON (re)), _("Recur on the"));
|
||||
ee->recur_month_day = make_day_list_widget (numeral_day_names, 0);
|
||||
ee->recur_month_weekday = make_day_list_widget (weekday_names, def_pos);
|
||||
gtk_table_attach (GTK_TABLE (monthly), r1,
|
||||
0, 1, 1, 2, 0, 0, 0, 0);
|
||||
gtk_table_attach (GTK_TABLE (monthly), ee->recur_month_day,
|
||||
@ -764,6 +805,13 @@ ee_rp_init_frequency (EventEditor *ee)
|
||||
4, 5, 0, 2, 0, 0, 5, 0);
|
||||
gtk_table_attach (GTK_TABLE (monthly), gtk_label_new (_("month(s)")),
|
||||
5, 6, 0, 2, 0, 0, 0, 0);
|
||||
if (ee->ical->recur){
|
||||
if (ee->ical->recur->type == RECUR_MONTHLY_BY_POS)
|
||||
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (r1), 1);
|
||||
} else {
|
||||
recur_month_enable_date ((re), ee);
|
||||
}
|
||||
|
||||
/* 4. The yearly recurrence */
|
||||
yearly = gtk_hbox_new (0, 0);
|
||||
ee->recur_year_period = small_entry (year_period);
|
||||
|
@ -115,10 +115,270 @@ set_list (char *str, char *sc)
|
||||
return list;
|
||||
}
|
||||
|
||||
static GList *
|
||||
set_date_list (char *str)
|
||||
{
|
||||
GList *list = 0;
|
||||
char *s;
|
||||
|
||||
for (s = strtok (str, ";"); s; s = strtok (NULL, ";")){
|
||||
time_t *t = g_new (time_t, 1);
|
||||
|
||||
*t = time_from_isodate (s);
|
||||
list = g_list_prepend (list, t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static void
|
||||
ignore_space(char **str)
|
||||
{
|
||||
while (**str && isspace (**str))
|
||||
*str++;
|
||||
}
|
||||
|
||||
static void
|
||||
skip_numbers (char **str)
|
||||
{
|
||||
while (**str){
|
||||
ignore_space (str);
|
||||
if (!isdigit (**str))
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
weekdaylist (iCalObject *o, char **str)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
char first_letter, second_letter;
|
||||
int index;
|
||||
} days [] = {
|
||||
{ 'S', 'U', 0 },
|
||||
{ 'M', 'O', 1 },
|
||||
{ 'T', 'U', 2 },
|
||||
{ 'W', 'E', 3 },
|
||||
{ 'T', 'H', 4 },
|
||||
{ 'F', 'R', 5 },
|
||||
{ 'S', 'A', 6 }
|
||||
};
|
||||
|
||||
ignore_space (str);
|
||||
do {
|
||||
for (i = 0; i < 7; i++){
|
||||
if (**str == days [i].first_letter && *(*str+1) == days [i].second_letter){
|
||||
o->recur->weekday |= 1 << i;
|
||||
*str += 2;
|
||||
if (**str == ' ')
|
||||
(*str)++;
|
||||
}
|
||||
}
|
||||
} while (isalpha (**str));
|
||||
}
|
||||
|
||||
static void
|
||||
ocurrencelist (iCalObject *o, char **str)
|
||||
{
|
||||
char *p, *q;
|
||||
int value = 0;
|
||||
|
||||
ignore_space (str);
|
||||
p = *str;
|
||||
if (!isdigit (*str))
|
||||
return;
|
||||
|
||||
if (!(*p >= '1' && *p <= '5'))
|
||||
return;
|
||||
|
||||
if (!(*(p+1) == '+' || *(p+1) == '-'))
|
||||
return;
|
||||
|
||||
o->recur->u.month_pos = (*p-'0') * (*(p+1) == '+' ? 1 : -1);
|
||||
*str += 2;
|
||||
}
|
||||
|
||||
static void
|
||||
daynumber (iCalObject *o, char **str)
|
||||
{
|
||||
int val = 0;
|
||||
char *p = *str;
|
||||
|
||||
ignore_space (str);
|
||||
if (strcmp (p, "LD")){
|
||||
o->recur->u.month_day = DAY_LASTDAY;
|
||||
*str += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(isdigit (*p)))
|
||||
return;
|
||||
|
||||
while (**str && isdigit (**str)){
|
||||
val = val * 10 + (**str - '0');
|
||||
*str++;
|
||||
}
|
||||
|
||||
if (**str == '+')
|
||||
*str++;
|
||||
|
||||
if (**str == '-')
|
||||
val *= -1;
|
||||
o->recur->u.month_day = val;
|
||||
}
|
||||
|
||||
static void
|
||||
daynumberlist (iCalObject *o, char **str)
|
||||
{
|
||||
int first = 0;
|
||||
int val = 0;
|
||||
|
||||
ignore_space (str);
|
||||
|
||||
while (**str){
|
||||
if (!isdigit (**str))
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
val = 10 * val + (**str - '0');
|
||||
if (!first){
|
||||
o->recur->u.month_day = val;
|
||||
first = 1;
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_weekly (iCalObject *o, char **str)
|
||||
{
|
||||
weekdaylist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_monthly_pos (iCalObject *o, char **str)
|
||||
{
|
||||
ocurrencelist (o, str);
|
||||
weekdaylist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_monthly_day (iCalObject *o, char **str)
|
||||
{
|
||||
daynumberlist (o, str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_yearly_month (iCalObject *o, char **str)
|
||||
{
|
||||
/* Skip as we do not support multiple months and we do expect
|
||||
* the dtstart to agree with the value on this field
|
||||
*/
|
||||
skip_numbers (str);
|
||||
}
|
||||
|
||||
static void
|
||||
load_recur_yearly_day (iCalObject *o, char **str)
|
||||
{
|
||||
/* Skip as we do not support multiple days and we do expect
|
||||
* the dtstart to agree with the value on this field
|
||||
*/
|
||||
skip_numbers (str);
|
||||
}
|
||||
|
||||
static void
|
||||
duration (iCalObject *o, char **str)
|
||||
{
|
||||
int duration = 0;
|
||||
|
||||
ignore_space (str);
|
||||
if (**str != '#')
|
||||
return;
|
||||
while (**str && isdigit (**str))
|
||||
duration = duration * 10 + (**str - '0');
|
||||
|
||||
o->recur->temp_duration = duration;
|
||||
}
|
||||
|
||||
static void
|
||||
enddate (iCalObject *o, char **str)
|
||||
{
|
||||
ignore_space (str);
|
||||
if (isdigit (**str)){
|
||||
o->recur->enddate = time_from_isodate (*str);
|
||||
*str += 16;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
load_recurrence (iCalObject *o, char *str)
|
||||
{
|
||||
char c;
|
||||
enum RecurType type;
|
||||
int interval = 0;
|
||||
|
||||
type = -1;
|
||||
switch (*str++){
|
||||
case 'D':
|
||||
type = RECUR_DAILY;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
type = RECUR_WEEKLY;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (*str == 'P')
|
||||
type = RECUR_MONTHLY_BY_POS;
|
||||
else if (*str == 'D')
|
||||
type = RECUR_MONTHLY_BY_DAY;
|
||||
str++;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (*str == 'M')
|
||||
type = RECUR_YEARLY_BY_MONTH;
|
||||
else if (*str == 'D')
|
||||
type = RECUR_YEARLY_BY_DAY;
|
||||
str++;
|
||||
break;
|
||||
}
|
||||
if (type == -1)
|
||||
return 0;
|
||||
|
||||
o->recur = g_new0 (Recurrence, 1);
|
||||
o->recur->type = type;
|
||||
ignore_space (&str);
|
||||
|
||||
/* Get the interval */
|
||||
while (*str && isdigit (*str))
|
||||
interval = interval * 10 + (*str-'0');
|
||||
o->recur->interval = interval;
|
||||
|
||||
ignore_space (&str);
|
||||
|
||||
switch (type){
|
||||
case RECUR_WEEKLY:
|
||||
load_recur_weekly (o, &str);
|
||||
break;
|
||||
case RECUR_MONTHLY_BY_POS:
|
||||
load_recur_monthly_pos (o, &str);
|
||||
break;
|
||||
case RECUR_MONTHLY_BY_DAY:
|
||||
load_recur_monthly_day (o, &str);
|
||||
break;
|
||||
case RECUR_YEARLY_BY_MONTH:
|
||||
load_recur_yearly_month (o, &str);
|
||||
break;
|
||||
case RECUR_YEARLY_BY_DAY:
|
||||
load_recur_yearly_day (o, &str);
|
||||
break;
|
||||
}
|
||||
duration (o, &str);
|
||||
enddate (o, &str);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define is_a_prop_of(obj,prop) isAPropertyOf (obj,prop)
|
||||
@ -133,6 +393,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
iCalObject *ical;
|
||||
VObject *vo;
|
||||
VObjectIterator i;
|
||||
int syntax_error;
|
||||
|
||||
ical = g_new0 (iCalObject, 1);
|
||||
|
||||
@ -181,7 +442,7 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
|
||||
/* exdate */
|
||||
if (has (o, VCExpDateProp))
|
||||
ical->exdate = set_list (str_val (vo), ",");
|
||||
ical->exdate = set_date_list (str_val (vo));
|
||||
|
||||
/* description/comment */
|
||||
if (has (o, VCDescriptionProp))
|
||||
@ -254,7 +515,12 @@ ical_object_create_from_vobject (VObject *o, const char *object_name)
|
||||
|
||||
/* FIXME: rrule */
|
||||
if (has (o, VCRRuleProp))
|
||||
load_recurrence (ical, str_val (vo));
|
||||
syntax_error = load_recurrence (ical, str_val (vo)) == 0;
|
||||
|
||||
if (syntax_error){
|
||||
ical_object_destroy (ical);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ical;
|
||||
}
|
||||
|
@ -79,10 +79,21 @@ enum RecurType {
|
||||
RECUR_YEARLY_BY_DAY,
|
||||
};
|
||||
|
||||
#define DAY_LASTDAY 10000
|
||||
|
||||
typedef struct {
|
||||
enum RecurType type;
|
||||
|
||||
int frequency;
|
||||
int interval;
|
||||
time_t enddate;
|
||||
int weekday;
|
||||
|
||||
union {
|
||||
int month_pos;
|
||||
int month_day;
|
||||
} u;
|
||||
|
||||
int temp_duration; /* Used temporarly, we compute enddate */
|
||||
} Recurrence;
|
||||
|
||||
/* Flags to indicate what has changed in an object */
|
||||
|
Reference in New Issue
Block a user