[Xfce4-commits] <orage:master> 4.7.4.6 Fixed BUG 5090 Recurring event does not adapt to DST changes

Juha Kautto noreply at xfce.org
Mon Sep 21 16:12:01 CEST 2009


Updating branch refs/heads/master
         to a4ced8555b79a359f4b2e704ad96f9458d9ac71f (commit)
       from 6ef448c9ba421280e94f82bf1efc692992288882 (commit)

commit a4ced8555b79a359f4b2e704ad96f9458d9ac71f
Author: Juha Kautto <juha at xfce.org>
Date:   Mon Sep 21 17:04:58 2009 +0300

    4.7.4.6 Fixed BUG 5090  Recurring event does not adapt to DST changes
    
    - Alarms converted times too early to local timezone. Conversion needs
      to happen last after all comparisons.
    - Enhanced timezone selection a little by reading also the previous
      time change time.
    - Fixed a small error in timezone selection when reading country names:
      Need to check the 2-char country code is in correct place as some of them
      appear in the file also in other places.

 configure.in.in          |    2 +-
 src/ical-archive.c       |    4 +-
 src/ical-code.c          |   52 +++++++++++++++++++++++++++------------------
 src/timezone_selection.c |   32 +++++++++++++++++++++-------
 src/tz_zoneinfo_read.c   |   45 +++++++++++++++++++++++++++++++--------
 src/tz_zoneinfo_read.h   |    1 +
 6 files changed, 95 insertions(+), 41 deletions(-)

diff --git a/configure.in.in b/configure.in.in
index b75fbbb..ac28494 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -9,7 +9,7 @@ dnl Written for Xfce by Juha Kautto <juha at xfce.org>
 dnl
 
 dnl Version information
-m4_define([orage_version], [4.7.4.5-test])
+m4_define([orage_version], [4.7.4.6-test])
 
 m4_define([gtk_minimum_version], [2.10.0])
 m4_define([xfce_minimum_version], [4.6.0])
diff --git a/src/ical-archive.c b/src/ical-archive.c
index 3390247..100be99 100644
--- a/src/ical-archive.c
+++ b/src/ical-archive.c
@@ -85,7 +85,7 @@ typedef struct
 char *ic_get_char_timezone(icalproperty *p);
 struct icaltimetype ic_convert_to_timezone(struct icaltimetype t
         , icalproperty *p);
-xfical_period ic_get_period(icalcomponent *c) ;
+xfical_period ic_get_period(icalcomponent *c, gboolean local);
 gboolean ic_internal_file_open(icalcomponent **p_ical
         , icalset **p_fical, gchar *file_icalpath, gboolean test);
 
@@ -388,7 +388,7 @@ gboolean xfical_archive(void)
             edate = sdate;
         }
         */
-        per =  ic_get_period(c);
+        per =  ic_get_period(c, TRUE);
         uid = (char *)icalcomponent_get_uid(c);
         /* Items with endate before threshold => archived.
          * Recurring events are marked in the main file by adding special
diff --git a/src/ical-code.c b/src/ical-code.c
index 5c213d1..ff30e67 100644
--- a/src/ical-code.c
+++ b/src/ical-code.c
@@ -580,7 +580,7 @@ static struct icaltimetype convert_to_local_timezone(struct icaltimetype t
     return (tl);
 }
 
-xfical_period ic_get_period(icalcomponent *c) 
+xfical_period ic_get_period(icalcomponent *c, gboolean local) 
 {
 #undef  P_N 
 #define P_N "ic_get_period: "
@@ -596,7 +596,10 @@ xfical_period ic_get_period(icalcomponent *c)
     p = icalcomponent_get_first_property(c, ICAL_DTSTART_PROPERTY);
     if (p != NULL) {
         per.stime = icalproperty_get_dtstart(p);
-        per.stime = convert_to_local_timezone(per.stime, p);
+        if (local)
+            per.stime = convert_to_local_timezone(per.stime, p);
+        else
+            per.stime = ic_convert_to_timezone(per.stime, p);
     }
     else {
         per.stime = icaltime_null_time();
@@ -625,7 +628,10 @@ xfical_period ic_get_period(icalcomponent *c)
             per.etime = icalproperty_get_dtend(p);
         else if (per.ikind == ICAL_VTODO_COMPONENT)
             per.etime = icalproperty_get_due(p);
-        per.etime = convert_to_local_timezone(per.etime, p);
+        if (local)
+            per.etime = convert_to_local_timezone(per.etime, p);
+        else
+            per.etime = ic_convert_to_timezone(per.etime, p);
         per.duration = icaltime_subtract(per.etime, per.stime);
         if (icaltime_is_date(per.stime) 
             && icaldurationtype_as_int(per.duration) != 0) {
@@ -653,7 +659,10 @@ xfical_period ic_get_period(icalcomponent *c)
 
     if (p2 != NULL) {
         per.ctime = icalproperty_get_completed(p2);
-        per.ctime = convert_to_local_timezone(per.ctime, p2);
+        if (local)
+            per.ctime = convert_to_local_timezone(per.ctime, p2);
+        else
+            per.ctime = ic_convert_to_timezone(per.ctime, p);
     }
     else
         per.ctime = icaltime_null_time();
@@ -2517,6 +2526,7 @@ static void set_todo_times(icalcomponent *c, xfical_period *per)
     }
 }
 
+/* this works in UTC times */
 struct icaltimetype count_alarm_time(xfical_period per
         , struct icaltimetype cur_time
         , struct icaldurationtype dur
@@ -2529,18 +2539,18 @@ struct icaltimetype count_alarm_time(xfical_period per
  * when counting alarm time. */
         if (rel == ICAL_RELATED_START) {
             per.stime.is_date       = 0;
-            per.stime.is_utc        = cur_time.is_utc;
-            per.stime.is_daylight   = cur_time.is_daylight;
-            per.stime.zone          = cur_time.zone;
+            per.stime.is_utc        = 1;
+            per.stime.is_daylight   = 0;
+            per.stime.zone          = utc_icaltimezone;
             per.stime.hour          = 0;
             per.stime.minute        = 0;
             per.stime.second        = 0;
         }
         else {
             per.etime.is_date       = 0;
-            per.etime.is_utc        = cur_time.is_utc;
-            per.etime.is_daylight   = cur_time.is_daylight;
-            per.etime.zone          = cur_time.zone;
+            per.etime.is_utc        = 1;
+            per.etime.is_daylight   = 0;
+            per.etime.zone          = utc_icaltimezone;
             per.etime.hour          = 0;
             per.etime.minute        = 0;
             per.etime.second        = 0;
@@ -2558,7 +2568,7 @@ struct icaltimetype count_alarm_time(xfical_period per
  * FIXME: We assume all alarms have similar trigger, which 
  * may not be true for other than Orage appointments
  */
-static  alarm_struct *process_alarm_trigger(icalcomponent *c
+alarm_struct *process_alarm_trigger(icalcomponent *c
         , icalcomponent *ca, struct icaltimetype cur_time, int *cnt_repeat)
 { /* c == main component; ca == alarm component */
 #undef P_N
@@ -2592,7 +2602,7 @@ static  alarm_struct *process_alarm_trigger(icalcomponent *c
         rel = icalparameter_get_related(trg_related_par);
     else
         rel = ICAL_RELATED_START;
-    per = ic_get_period(c);
+    per = ic_get_period(c, FALSE);
     next_alarm_time = count_alarm_time(per, cur_time, trg.duration, rel);
     alarm_start_diff = icaltime_subtract(per.stime, next_alarm_time);
     /* we only have ctime for TODOs and only if todo has been completed.
@@ -2600,7 +2610,7 @@ static  alarm_struct *process_alarm_trigger(icalcomponent *c
      * current date */
     if (per.ikind == ICAL_VTODO_COMPONENT) {
         if (icaltime_is_null_time(per.ctime)
-        || local_compare(per.ctime, per.stime) < 0) {
+        || icaltime_compare(per.ctime, per.stime) < 0) {
         /* VTODO is never completed  */
         /* or it has completed before start, so
          * this one is not done and needs to be counted */
@@ -2625,9 +2635,9 @@ static  alarm_struct *process_alarm_trigger(icalcomponent *c
              next_start_time = icaltime_add(next_alarm_time, alarm_start_diff);
              !icaltime_is_null_time(next_alarm_time)
              && ((per.ikind == ICAL_VTODO_COMPONENT
-                  && local_compare(next_start_time, per.ctime) <= 0)
+                  && icaltime_compare(next_start_time, per.ctime) <= 0)
                  || (per.ikind != ICAL_VTODO_COMPONENT 
-                     && local_compare(next_alarm_time, cur_time) <= 0)
+                     && icaltime_compare(next_alarm_time, cur_time) <= 0)
                  || icalproperty_recurrence_is_excluded(c
                          , &per.stime, &next_start_time));
             next_alarm_time = icalrecur_iterator_next(ri),
@@ -2677,6 +2687,7 @@ static  alarm_struct *process_alarm_trigger(icalcomponent *c
             continue;
 
         /* it has same timezone than startdate, convert to local time */
+        /* FIXME: this should not convert, but just set the timezone */
         if (icaltime_is_utc(next_start_time)) {
             /* FIXME: tarkista että convert_to_local_timezone toimii oikein
              * UTC:llä. se ei toimi kuten tässä */
@@ -2716,6 +2727,7 @@ static  alarm_struct *process_alarm_trigger(icalcomponent *c
 
     if (trg_active) {
         new_alarm = g_new0(alarm_struct, 1);
+        next_alarm_time = icaltime_convert_to_zone(next_alarm_time, local_icaltimezone);
         new_alarm->alarm_time = g_strdup(icaltime_as_ical_string(next_alarm_time));
         return(new_alarm);
     }
@@ -2873,7 +2885,8 @@ static void xfical_alarm_build_list_internal_real(gboolean first_list_today
 #ifdef ORAGE_DEBUG
     orage_message(-200, P_N);
 #endif
-    cur_time = ical_get_current_local_time();
+    /* cur_time = ical_get_current_local_time(); */
+    cur_time = icaltime_current_time_with_zone(utc_icaltimezone);
 
     for (c = icalcomponent_get_first_component(base, ICAL_ANY_COMPONENT);
             c != 0;
@@ -2914,9 +2927,6 @@ static void xfical_alarm_build_list_internal_real(gboolean first_list_today
                         (char *)icalcomponent_get_description(c));
             g_par.alarm_list = g_list_prepend(g_par.alarm_list, new_alarm);
             cnt_alarm_add++;
-            /*
-            g_print(P_N "added alarm (%s) at (%s)\n", new_alarm->title, new_alarm->alarm_time);
-            */
         }
     }  /* COMPONENT */
     if (first_list_today) {
@@ -3027,7 +3037,7 @@ static xfical_appt *xfical_appt_get_next_on_day_internal(char *a_day
          icalcompiter_next(&ci)) {
         /* next appointment loop. check if it is ok */
         c = icalcompiter_deref(&ci);
-        per = ic_get_period(c);
+        per = ic_get_period(c, TRUE);
         if (type == XFICAL_TYPE_TODO) {
             if (icaltime_is_null_time(per.ctime)
             || local_compare(per.ctime, per.stime) <= 0)
@@ -3323,7 +3333,7 @@ static void xfical_mark_calendar_from_component(GtkCalendar *gtkcal
     */
     } /* ICAL_VEVENT_COMPONENT */
     else if (kind == ICAL_VTODO_COMPONENT) {
-        per = ic_get_period(c);
+        per = ic_get_period(c, TRUE);
         marked = FALSE;
         if (icaltime_is_null_time(per.ctime)
         || (local_compare(per.ctime, per.stime) < 0)) {
diff --git a/src/timezone_selection.c b/src/timezone_selection.c
index baeae91..e5eafa7 100644
--- a/src/timezone_selection.c
+++ b/src/timezone_selection.c
@@ -67,6 +67,7 @@ enum {
     LOCATION_ENG,
     OFFSET,
     COUNTRY,
+    PREV_CHANGE,
     NEXT_CHANGE,
     N_COLUMNS
 };
@@ -81,12 +82,12 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
     GtkTreeIter iter1, iter2, main;
     orage_timezone_array tz_a;
     char area_old[MAX_AREA_LENGTH+2]; /*+2 = / + null */
-    char s_offset[100], s_country[100], s_next[100];
+    char s_offset[100], s_country[100], s_next[100], s_prev[100];
     gint i, j, offs_hour, offs_min;
 
     store = gtk_tree_store_new(N_COLUMNS
             , G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING
-            , G_TYPE_STRING, G_TYPE_STRING);
+            , G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
     strcpy(area_old, "S T a R T"); /* this never matches */
     tz_a = get_orage_timezones(details, 1);
     /*
@@ -100,6 +101,7 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
             , LOCATION_ENG, " Other"
             , OFFSET, " "
             , COUNTRY, " "
+            , PREV_CHANGE, " "
             , NEXT_CHANGE, " "
             , -1);
     main = iter1; /* need to remember that */
@@ -124,6 +126,7 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
                         , LOCATION_ENG, area_old
                         , OFFSET, " "
                         , COUNTRY, " "
+                        , PREV_CHANGE, " "
                         , NEXT_CHANGE, " "
                         , -1);
                 /* let's make sure we do not match accidentally to those 
@@ -147,21 +150,29 @@ static GtkTreeStore *tz_button_create_store(gboolean details)
                 , offs_hour, offs_min
                 , (tz_a.dst[i]) ? "dst" : "std"
                 , (tz_a.tz[i]) ? tz_a.tz[i] : "-");
-        if (details && tz_a.country[i] && tz_a.cc[i])
-            g_snprintf(s_country, 100, "%s (%s)", tz_a.country[i], tz_a.cc[i]);
-        else
-            strcpy(s_country, " ");
-        if (details)
+        if (details) {
+            if (tz_a.country[i] && tz_a.cc[i])
+                g_snprintf(s_country, 100, "%s (%s)"
+                        , tz_a.country[i], tz_a.cc[i]);
+            else 
+                strcpy(s_country, " ");
+            g_snprintf(s_prev, 100, "%s"
+                    , (tz_a.prev[i]) ? tz_a.prev[i] : _("not changed"));
             g_snprintf(s_next, 100, "%s"
                     , (tz_a.next[i]) ? tz_a.next[i] : _("not changing"));
-        else
+        }
+        else {
+            strcpy(s_country, " ");
+            strcpy(s_prev, " ");
             strcpy(s_next, " ");
+        }
 
         gtk_tree_store_set(store, &iter2
                 , LOCATION, _(tz_a.city[i])
                 , LOCATION_ENG, tz_a.city[i]
                 , OFFSET, s_offset
                 , COUNTRY, s_country
+                , PREV_CHANGE, s_prev
                 , NEXT_CHANGE, s_next
                 , -1);
     }
@@ -224,6 +235,11 @@ GtkWidget *tz_button_create_view(gboolean details, GtkTreeStore *store)
         gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
 
         rend = gtk_cell_renderer_text_new();
+        col  = gtk_tree_view_column_new_with_attributes(_("Previous Change")
+                , rend, "text", PREV_CHANGE, NULL);
+        gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
+
+        rend = gtk_cell_renderer_text_new();
         col  = gtk_tree_view_column_new_with_attributes(_("Next Change")
                 , rend, "text", NEXT_CHANGE, NULL);
         gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
diff --git a/src/tz_zoneinfo_read.c b/src/tz_zoneinfo_read.c
index a97a8eb..8a48d02 100644
--- a/src/tz_zoneinfo_read.c
+++ b/src/tz_zoneinfo_read.c
@@ -333,7 +333,7 @@ static int process_file(const char *file_name)
 static void get_country()
 { /* tz_array.city[tz_array.count] contains the city name.
      We will find corresponding country and fill it to the table */
-    char *str, *str_nl;
+    char *str, *str_nl, cc[4];
 
     if (!(str = strstr(zone_tab_buf, tz_array.city[tz_array.count])))
         return; /* not found */
@@ -350,12 +350,19 @@ static void get_country()
     strncpy(tz_array.cc[tz_array.count], ++str_nl, 2);
     tz_array.cc[tz_array.count][2] = '\0';
 
-    /* then search the country */
-    if (!(str = strstr(country_buf, tz_array.cc[tz_array.count])))
+    /********** then search the country **********/
+    /* Need to search line, which starts with country code.
+     * Note that it is not enough to search any country coed, but it really
+     * needs to be the first two chars in the line */
+    cc[0] = '\n'; 
+    cc[1] = tz_array.cc[tz_array.count][0];
+    cc[2] = tz_array.cc[tz_array.count][1];
+    cc[3] = '\0';
+    if (!(str = strstr(country_buf, cc)))
         return; /* not found */
     /* country name is after the country code and a single tab */
     str += 3;
-    /* but w still need to find how long it is.
+    /* but we still need to find how long it is.
      * It ends in the line end. 
      * (There is a line end at the end of the file also.) */
     for (str_nl = str; str_nl[0] != '\n'; str_nl++)
@@ -385,8 +392,8 @@ static int write_ical_file(const char *in_file_name
     unsigned int tct_i, abbr_i;
     struct tm cur_gm_time;
     time_t tt_now = time(NULL);
-    long tc_time = 0; /* TimeChange time */
-    char s_next[101];
+    long tc_time = 0, prev_tc_time; /* TimeChange times */
+    char s_next[101], s_prev[101];
 
     if (debug > 1)
         printf("***** write_ical_file: start *****\n\n");
@@ -403,6 +410,7 @@ static int write_ical_file(const char *in_file_name
         /* search for current time setting.
          * timecnt tells how many changes we have in the tz file.
          * i points to the next value to read. */
+        prev_tc_time = tc_time;
         tc_time = get_long(); /* start time of this timechange */
     }
     /* i points to the next value to be read, so need to -- */
@@ -412,6 +420,7 @@ static int write_ical_file(const char *in_file_name
         tz_array.utc_offset[tz_array.count] = 0;
         tz_array.dst[tz_array.count] = 0;
         tz_array.tz[tz_array.count] = "UTC";
+        tz_array.prev[tz_array.count] = NULL;
         tz_array.next[tz_array.count] = NULL;
         tz_array.count++;
         return(1); /* done */
@@ -420,16 +429,29 @@ static int write_ical_file(const char *in_file_name
         /* we found previous and next value */
         /* tc_time has the next change time */
         if (details) {
+            localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
+            strftime(s_prev, 100, "%c", &cur_gm_time);
+            tz_array.prev[tz_array.count] = strdup(s_prev);
             localtime_r((const time_t *)&tc_time, &cur_gm_time);
             strftime(s_next, 100, "%c", &cur_gm_time);
             tz_array.next[tz_array.count] = strdup(s_next);
         }
-        else 
+        else {
             tz_array.next[tz_array.count] = NULL;
+            tz_array.prev[tz_array.count] = NULL;
+        }
         i--; /* we need to take the previous value */
     }
-    else 
+    else { /* no next value, but previous may exist */
         tz_array.next[tz_array.count] = NULL;
+        if (details && prev_tc_time) {
+            localtime_r((const time_t *)&prev_tc_time, &cur_gm_time);
+            strftime(s_prev, 100, "%c", &cur_gm_time);
+            tz_array.prev[tz_array.count] = strdup(s_prev);
+        }
+        else
+            tz_array.prev[tz_array.count] = NULL;
+    }
 
     /* i now points to latest time change and shows current time.
      * So we found our result and can start collecting real data: */
@@ -476,7 +498,6 @@ static int file_call(const char *file_name, const struct stat *sb, int flags
                 + strlen("zoneinfo/")]);
         timezone_name = strdup(in_timezone_name);
         if (check_ical && !timezone_exists_in_ical()) {
-            printf("\t\tfile_call: skipped file=(%s)\n", file_name);
             free(in_timezone_name);
             free(timezone_name);
             return(FTW_CONTINUE);
@@ -807,6 +828,7 @@ orage_timezone_array get_orage_timezones(int show_details, int ical)
         tz_array.utc_offset = (int *)malloc(sizeof(int)*(tz_array_size+2));
         tz_array.dst = (int *)malloc(sizeof(int)*(tz_array_size+2));
         tz_array.tz = (char **)malloc(sizeof(char *)*(tz_array_size+2));
+        tz_array.prev = (char **)malloc(sizeof(char *)*(tz_array_size+2));
         tz_array.next = (char **)malloc(sizeof(char *)*(tz_array_size+2));
         tz_array.country = (char **)malloc(sizeof(char *)*(tz_array_size+2));
         tz_array.cc = (char **)malloc(sizeof(char *)*(tz_array_size+2));
@@ -832,6 +854,7 @@ orage_timezone_array get_orage_timezones(int show_details, int ical)
         tz_array.utc_offset[tz_array.count] = 0;
         tz_array.dst[tz_array.count] = 0;
         tz_array.tz[tz_array.count] = strdup("UTC");
+        tz_array.prev[tz_array.count] = NULL;
         tz_array.next[tz_array.count] = NULL;
         tz_array.country[tz_array.count] = NULL;
         tz_array.cc[tz_array.count] = NULL;
@@ -840,6 +863,7 @@ orage_timezone_array get_orage_timezones(int show_details, int ical)
         tz_array.utc_offset[tz_array.count] = 0;
         tz_array.dst[tz_array.count] = 0;
         tz_array.tz[tz_array.count] = NULL;
+        tz_array.prev[tz_array.count] = NULL;
         tz_array.next[tz_array.count] = NULL;
         tz_array.country[tz_array.count] = NULL;
         tz_array.cc[tz_array.count] = NULL;
@@ -857,6 +881,8 @@ void free_orage_timezones(int show_details)
             free(tz_array.city[i]);
         if (tz_array.tz[i])
             free(tz_array.tz[i]);
+        if (tz_array.prev[i])
+            free(tz_array.prev[i]);
         if (tz_array.next[i])
             free(tz_array.next[i]);
         if (tz_array.country[i])
@@ -868,6 +894,7 @@ void free_orage_timezones(int show_details)
     free(tz_array.utc_offset);
     free(tz_array.dst);
     free(tz_array.tz);
+    free(tz_array.prev);
     free(tz_array.next);
     free(tz_array.country);
     free(tz_array.cc);
diff --git a/src/tz_zoneinfo_read.h b/src/tz_zoneinfo_read.h
index 8e05e1b..1f70f73 100644
--- a/src/tz_zoneinfo_read.h
+++ b/src/tz_zoneinfo_read.h
@@ -25,6 +25,7 @@ typedef struct _orage_timezone_array
     int  *utc_offset; /* pointer to int array holding utc offsets */
     int  *dst;        /* pointer to int array holding dst settings */
     char **tz;        /* pointer to timezone name strings */
+    char **prev;      /* pointer to previous time change strings */
     char **next;      /* pointer to next time change strings */
     char **country;   /* pointer to country name strings */
     char **cc;        /* pointer to country code strings */



More information about the Xfce4-commits mailing list