From 45fdeb790bdedab65bb864c32a9f7a483c27d27e Mon Sep 17 00:00:00 2001 From: Steve Murphy Date: Sat, 3 Apr 1999 23:57:14 +0000 Subject: Added this routine so Monthly recurrences use the weekday field as a 1999-04-01 Steve Murphy * calobj.c (weekdaynum): Added this routine so Monthly recurrences use the weekday field as a simple integer for a single weekday. * calobj.c (load_recur_monthly_pos): Call weekdaynum instead of weekdaylist. The interface only lets the user input a single value anyway. * calobj.c (ical_object_to_vobject): instead of code to output day names from a bit array, use instead the value as an int and output a single dayname. * calobj.c (ical_object_generate_events): first_week_day gets the day int instead of the first entry in the bit field. I inserted a fair chunk of code to avoid calling generate if the day is out of range for a month. It may be unneccessary, because mktime will turn the extra days into a valid date the next month. But not all mktimes are equal, I fear. * eventedit.c (ee_store_recur_rule_to_ical): For case 3, (Monthly), I added code to set the interval slot of the recur struct; without this value, selecting a monthly recursing, by date, would lead to an infinite loop broken only by a failure to alloc more memory. Also, in the "by position" case, both u.month_pos and u.month_day were being assigned values. This is a mistake, as they are both part of an union, and the same thing. The weekday field should get the recur_rr_month_weekday value. * eventedit.c (ee_rp_init_rule): set default day from the weekday field instead of the u.month_day field, which is really the month_pos value. * gnome-cal.c (gnome_calendar_tag_calendar): Month days start with 1, not 0; thus, setting tm.tm_mday = 0, and then calling mktime will generate a time corresponding to the end of the previous month, which may have a mday anywhere from 28 to 31. The end time just adds 1 to the month, so your end time may not cover the last few days of this month, depending on what the biggest mday of last month was. I changed it so tm_mday is set to 1 instead. 1999-03-30 Federico Mena Quintero svn path=/trunk/; revision=792 --- calendar/ChangeLog | 42 ++++++++++++++++++++ calendar/cal-util/calobj.c | 95 +++++++++++++++++++++++++++++++++++++++++----- calendar/calobj.c | 95 +++++++++++++++++++++++++++++++++++++++++----- calendar/eventedit.c | 4 +- calendar/gnome-cal.c | 3 +- calendar/gui/eventedit.c | 4 +- calendar/gui/gnome-cal.c | 3 +- calendar/pcs/calobj.c | 95 +++++++++++++++++++++++++++++++++++++++++----- 8 files changed, 308 insertions(+), 33 deletions(-) diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 6f338a09b2..121dd41dcd 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,45 @@ +1999-04-01 Steve Murphy + + * calobj.c (weekdaynum): Added this routine so Monthly recurrences + use the weekday field as a simple integer for a single weekday. + + * calobj.c (load_recur_monthly_pos): Call weekdaynum instead of + weekdaylist. The interface only lets the user input a single value + anyway. + + * calobj.c (ical_object_to_vobject): instead of code to output day + names from a bit array, use instead the value as an int and output + a single dayname. + + * calobj.c (ical_object_generate_events): first_week_day gets the + day int instead of the first entry in the bit field. I inserted a + fair chunk of code to avoid calling generate if the day is out of + range for a month. It may be unneccessary, because mktime will + turn the extra days into a valid date the next month. But not all + mktimes are equal, I fear. + + * eventedit.c (ee_store_recur_rule_to_ical): For case 3, + (Monthly), I added code to set the interval slot of the recur + struct; without this value, selecting a monthly recursing, by + date, would lead to an infinite loop broken only by a failure to + alloc more memory. Also, in the "by position" case, both + u.month_pos and u.month_day were being assigned values. This is a + mistake, as they are both part of an union, and the same + thing. The weekday field should get the recur_rr_month_weekday + value. + + * eventedit.c (ee_rp_init_rule): set default day from the weekday + field instead of the u.month_day field, which is really the + month_pos value. + + * gnome-cal.c (gnome_calendar_tag_calendar): Month days start with + 1, not 0; thus, setting tm.tm_mday = 0, and then calling mktime + will generate a time corresponding to the end of the previous + month, which may have a mday anywhere from 28 to 31. The end time + just adds 1 to the month, so your end time may not cover the last + few days of this month, depending on what the biggest mday of last + month was. I changed it so tm_mday is set to 1 instead. + 1999-03-30 Federico Mena Quintero * gncal-todo.c (convert_time_t_to_char): Made static. Make it use diff --git a/calendar/cal-util/calobj.c b/calendar/cal-util/calobj.c index 30d9b5f8ed..d4a17c8859 100644 --- a/calendar/cal-util/calobj.c +++ b/calendar/cal-util/calobj.c @@ -205,6 +205,36 @@ weekdaylist (iCalObject *o, char **str) } } +static void +weekdaynum (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 = i; + *str += 2; + if (**str == ' ') + (*str)++; + } + } + } while (isalpha (**str)); +} + static void ocurrencelist (iCalObject *o, char **str) { @@ -287,7 +317,7 @@ static void load_recur_monthly_pos (iCalObject *o, char **str) { ocurrencelist (o, str); - weekdaylist (o, str); + weekdaynum (o, str); } static void @@ -947,12 +977,9 @@ ical_object_to_vobject (iCalObject *ical) sprintf (buffer, "%d%s ", nega ? -ical->recur->u.month_pos : ical->recur->u.month_pos, nega ? "-" : "+"); strcat (result, buffer); - for (i = 0; i < 7; i++){ - if (ical->recur->weekday & (1 << i)){ - sprintf (buffer, "%s ", recur_day_list [i]); - strcat (result, buffer); - } - } + /* the gui is set up for a single day, not a set here in this case */ + sprintf (buffer, "%s ", recur_day_list [ical->recur->weekday]); + strcat (result, buffer); } break; @@ -1173,7 +1200,8 @@ ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendar if (ico->recur->u.month_pos == 0) return; - first_week_day = ical_object_get_first_weekday (ico->recur->weekday); + first_week_day = /* ical_object_get_first_weekday (ico->recur->weekday); */ + ico->recur->weekday; /* the i/f only lets you choose a single day of the week! */ /* This should not happen, but take it into account */ if (first_week_day == -1) { @@ -1194,7 +1222,56 @@ ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendar tm.tm_mday = (7 * (ico->recur->u.month_pos - ((week_day_start <= first_week_day ) ? 1 : 0)) - (week_day_start - first_week_day) + 1); - + if( tm.tm_mday > 31 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + + switch( tm.tm_mon ) + { + case 3: + case 5: + case 8: + case 10: + if( tm.tm_mday > 30 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + break; + case 1: + if( ((tm.tm_year+1900)%4) == 0 + && ((tm.tm_year+1900)%400) != 100 + && ((tm.tm_year+1900)%400) != 200 + && ((tm.tm_year+1900)%400) != 300 ) + { + + if( tm.tm_mday > 29 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + } + else + { + if( tm.tm_mday > 28 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + } + break; + } + t = mktime (&tm); if (time_in_range (t, start, end) && recur_in_range (current, ico->recur)) diff --git a/calendar/calobj.c b/calendar/calobj.c index 30d9b5f8ed..d4a17c8859 100644 --- a/calendar/calobj.c +++ b/calendar/calobj.c @@ -205,6 +205,36 @@ weekdaylist (iCalObject *o, char **str) } } +static void +weekdaynum (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 = i; + *str += 2; + if (**str == ' ') + (*str)++; + } + } + } while (isalpha (**str)); +} + static void ocurrencelist (iCalObject *o, char **str) { @@ -287,7 +317,7 @@ static void load_recur_monthly_pos (iCalObject *o, char **str) { ocurrencelist (o, str); - weekdaylist (o, str); + weekdaynum (o, str); } static void @@ -947,12 +977,9 @@ ical_object_to_vobject (iCalObject *ical) sprintf (buffer, "%d%s ", nega ? -ical->recur->u.month_pos : ical->recur->u.month_pos, nega ? "-" : "+"); strcat (result, buffer); - for (i = 0; i < 7; i++){ - if (ical->recur->weekday & (1 << i)){ - sprintf (buffer, "%s ", recur_day_list [i]); - strcat (result, buffer); - } - } + /* the gui is set up for a single day, not a set here in this case */ + sprintf (buffer, "%s ", recur_day_list [ical->recur->weekday]); + strcat (result, buffer); } break; @@ -1173,7 +1200,8 @@ ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendar if (ico->recur->u.month_pos == 0) return; - first_week_day = ical_object_get_first_weekday (ico->recur->weekday); + first_week_day = /* ical_object_get_first_weekday (ico->recur->weekday); */ + ico->recur->weekday; /* the i/f only lets you choose a single day of the week! */ /* This should not happen, but take it into account */ if (first_week_day == -1) { @@ -1194,7 +1222,56 @@ ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendar tm.tm_mday = (7 * (ico->recur->u.month_pos - ((week_day_start <= first_week_day ) ? 1 : 0)) - (week_day_start - first_week_day) + 1); - + if( tm.tm_mday > 31 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + + switch( tm.tm_mon ) + { + case 3: + case 5: + case 8: + case 10: + if( tm.tm_mday > 30 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + break; + case 1: + if( ((tm.tm_year+1900)%4) == 0 + && ((tm.tm_year+1900)%400) != 100 + && ((tm.tm_year+1900)%400) != 200 + && ((tm.tm_year+1900)%400) != 300 ) + { + + if( tm.tm_mday > 29 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + } + else + { + if( tm.tm_mday > 28 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + } + break; + } + t = mktime (&tm); if (time_in_range (t, start, end) && recur_in_range (current, ico->recur)) diff --git a/calendar/eventedit.c b/calendar/eventedit.c index abd7670e8a..e97e39e8a2 100644 --- a/calendar/eventedit.c +++ b/calendar/eventedit.c @@ -580,7 +580,7 @@ ee_store_recur_rule_to_ical (EventEditor *ee) ical->recur->u.month_pos = option_menu_active_number (ee->recur_rr_month_day); - ical->recur->u.month_day = + ical->recur->weekday = option_menu_active_number (ee->recur_rr_month_weekday); ical->recur->interval = gtk_spin_button_get_value_as_int ( @@ -1014,7 +1014,7 @@ ee_rp_init_rule (EventEditor *ee) page = 3; month_period = interval; def_pos = ee->ical->recur->u.month_pos; - default_day = ee->ical->recur->u.month_day; + default_day = ee->ical->recur->weekday; /* you can't use u.month_pos and u.month_day-- it's a union... */ break; case RECUR_MONTHLY_BY_DAY: diff --git a/calendar/gnome-cal.c b/calendar/gnome-cal.c index f589d0fe28..89d6998e3e 100644 --- a/calendar/gnome-cal.c +++ b/calendar/gnome-cal.c @@ -442,7 +442,8 @@ gnome_calendar_tag_calendar (GnomeCalendar *cal, GtkCalendar *gtk_cal) tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; - tm.tm_mday = 0; + tm.tm_mday = 1; /* setting this to zero is a no-no; it will set mktime back to the end of the + previous month, which may be 28,29,30; this may chop some days from the calendar */ tm.tm_mon = gtk_cal->month; tm.tm_year = gtk_cal->year - 1900; tm.tm_isdst= -1; diff --git a/calendar/gui/eventedit.c b/calendar/gui/eventedit.c index abd7670e8a..e97e39e8a2 100644 --- a/calendar/gui/eventedit.c +++ b/calendar/gui/eventedit.c @@ -580,7 +580,7 @@ ee_store_recur_rule_to_ical (EventEditor *ee) ical->recur->u.month_pos = option_menu_active_number (ee->recur_rr_month_day); - ical->recur->u.month_day = + ical->recur->weekday = option_menu_active_number (ee->recur_rr_month_weekday); ical->recur->interval = gtk_spin_button_get_value_as_int ( @@ -1014,7 +1014,7 @@ ee_rp_init_rule (EventEditor *ee) page = 3; month_period = interval; def_pos = ee->ical->recur->u.month_pos; - default_day = ee->ical->recur->u.month_day; + default_day = ee->ical->recur->weekday; /* you can't use u.month_pos and u.month_day-- it's a union... */ break; case RECUR_MONTHLY_BY_DAY: diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index f589d0fe28..89d6998e3e 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -442,7 +442,8 @@ gnome_calendar_tag_calendar (GnomeCalendar *cal, GtkCalendar *gtk_cal) tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; - tm.tm_mday = 0; + tm.tm_mday = 1; /* setting this to zero is a no-no; it will set mktime back to the end of the + previous month, which may be 28,29,30; this may chop some days from the calendar */ tm.tm_mon = gtk_cal->month; tm.tm_year = gtk_cal->year - 1900; tm.tm_isdst= -1; diff --git a/calendar/pcs/calobj.c b/calendar/pcs/calobj.c index 30d9b5f8ed..d4a17c8859 100644 --- a/calendar/pcs/calobj.c +++ b/calendar/pcs/calobj.c @@ -205,6 +205,36 @@ weekdaylist (iCalObject *o, char **str) } } +static void +weekdaynum (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 = i; + *str += 2; + if (**str == ' ') + (*str)++; + } + } + } while (isalpha (**str)); +} + static void ocurrencelist (iCalObject *o, char **str) { @@ -287,7 +317,7 @@ static void load_recur_monthly_pos (iCalObject *o, char **str) { ocurrencelist (o, str); - weekdaylist (o, str); + weekdaynum (o, str); } static void @@ -947,12 +977,9 @@ ical_object_to_vobject (iCalObject *ical) sprintf (buffer, "%d%s ", nega ? -ical->recur->u.month_pos : ical->recur->u.month_pos, nega ? "-" : "+"); strcat (result, buffer); - for (i = 0; i < 7; i++){ - if (ical->recur->weekday & (1 << i)){ - sprintf (buffer, "%s ", recur_day_list [i]); - strcat (result, buffer); - } - } + /* the gui is set up for a single day, not a set here in this case */ + sprintf (buffer, "%s ", recur_day_list [ical->recur->weekday]); + strcat (result, buffer); } break; @@ -1173,7 +1200,8 @@ ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendar if (ico->recur->u.month_pos == 0) return; - first_week_day = ical_object_get_first_weekday (ico->recur->weekday); + first_week_day = /* ical_object_get_first_weekday (ico->recur->weekday); */ + ico->recur->weekday; /* the i/f only lets you choose a single day of the week! */ /* This should not happen, but take it into account */ if (first_week_day == -1) { @@ -1194,7 +1222,56 @@ ical_object_generate_events (iCalObject *ico, time_t start, time_t end, calendar tm.tm_mday = (7 * (ico->recur->u.month_pos - ((week_day_start <= first_week_day ) ? 1 : 0)) - (week_day_start - first_week_day) + 1); - + if( tm.tm_mday > 31 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + + switch( tm.tm_mon ) + { + case 3: + case 5: + case 8: + case 10: + if( tm.tm_mday > 30 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + break; + case 1: + if( ((tm.tm_year+1900)%4) == 0 + && ((tm.tm_year+1900)%400) != 100 + && ((tm.tm_year+1900)%400) != 200 + && ((tm.tm_year+1900)%400) != 300 ) + { + + if( tm.tm_mday > 29 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + } + else + { + if( tm.tm_mday > 28 ) + { + tm.tm_mday = 1; + tm.tm_mon += ico->recur->interval; + current = mktime (&tm); + continue; + } + } + break; + } + t = mktime (&tm); if (time_in_range (t, start, end) && recur_in_range (current, ico->recur)) -- cgit v1.2.3