[Xfce4-commits] r29985 - in xfcalendar/trunk: src tz_convert

Juha Kautto juha at xfce.org
Thu May 28 15:50:28 CEST 2009


Author: juha
Date: 2009-05-28 13:50:28 +0000 (Thu, 28 May 2009)
New Revision: 29985

Modified:
   xfcalendar/trunk/src/ical-code.c
   xfcalendar/trunk/tz_convert/tz_convert.c
Log:
several bugs fixed in tz_convert. 
New timezone data visible in selection.


Modified: xfcalendar/trunk/src/ical-code.c
===================================================================
--- xfcalendar/trunk/src/ical-code.c	2009-05-26 05:24:53 UTC (rev 29984)
+++ xfcalendar/trunk/src/ical-code.c	2009-05-28 13:50:28 UTC (rev 29985)
@@ -70,6 +70,15 @@
 #define ORAGE_DEBUG 1
 */
 
+/** This is the toplevel directory where the timezone data is installed in. */
+#define ZONEINFO_DIRECTORY  PACKAGE_DATA_DIR "/zoneinfo"
+
+/** This is the filename of the file containing the city names and
+ *     coordinates of all the builtin timezones. */
+#define ZONES_TAB_FILENAME  "zones.tab"
+
+#define ORAGE_ZONES_TAB  ZONEINFO_DIRECTORY "/" ZONES_TAB_FILENAME
+
 typedef struct
 {
     struct icaltimetype stime; /* start time */
@@ -83,6 +92,8 @@
 {
     int    count;     /* how many timezones we have */
     char **city;      /* pointer to timezone location name strings */
+    int  *utc_offset; /* pointer to int array holding utc offsets */
+    int  *dst;        /* pointer to int array holding dst settings */
 } xfical_timezone_array;
 
 static icalset *fical = NULL;
@@ -502,15 +513,49 @@
     N_("Pacific/Yap"),
 };
 
-static xfical_timezone_array xfical_get_timezones()
+static struct icaltimetype ical_get_current_local_time()
 {
 #undef P_N
+#define P_N "ical_get_current_local_time: "
+    struct tm *tm;
+    struct icaltimetype ctime;
+
+#ifdef ORAGE_DEBUG
+    orage_message(-300, P_N);
+#endif
+    if (g_par.local_timezone_utc)
+        ctime = icaltime_current_time_with_zone(utc_icaltimezone);
+    else if ((g_par.local_timezone)
+        &&   (strcmp(g_par.local_timezone, "floating") != 0))
+        ctime = icaltime_current_time_with_zone(local_icaltimezone);
+    else { /* use floating time */
+        ctime.is_utc      = 0;
+        ctime.is_date     = 0;
+        ctime.is_daylight = 0;
+        ctime.zone        = NULL;
+    }
+    /* and at the end we need to change the clock to be correct */
+    tm = orage_localtime();
+    ctime.year        = tm->tm_year+1900;
+    ctime.month       = tm->tm_mon+1;
+    ctime.day         = tm->tm_mday;
+    ctime.hour        = tm->tm_hour;
+    ctime.minute      = tm->tm_min;
+    ctime.second      = tm->tm_sec;
+
+    return(ctime);
+}
+static xfical_timezone_array get_ical_timezones()
+{
+#undef P_N
 #define P_N "xfical_timezone_array: "
-    static xfical_timezone_array tz={0, NULL};
+    static xfical_timezone_array tz={0, NULL, NULL};
     static char tz_utc[]="UTC";
     static char tz_floating[]="floating";
     icalarray *tz_array;
     icaltimezone *l_tz;
+    int dst; /* daylight saving time = summer time */
+    struct icaltimetype ctime;
 
 #ifdef ORAGE_DEBUG
     orage_message(-100, P_N);
@@ -518,13 +563,28 @@
     if (tz.count == 0) {
         tz_array = icaltimezone_get_builtin_timezones();
         tz.city = (char **)g_malloc(sizeof(char *)*(2+tz_array->num_elements));
+        tz.utc_offset = (int *)g_malloc(sizeof(int)*(2+tz_array->num_elements));
+        tz.dst = (int *)g_malloc(sizeof(int)*(2+tz_array->num_elements));
+        ctime = ical_get_current_local_time();
         for (tz.count = 0; tz.count <  tz_array->num_elements; tz.count++) {
             l_tz = (icaltimezone *)icalarray_element_at(tz_array, tz.count);
             /* ical timezones are static so this is safe although not
              * exactly pretty */
             tz.city[tz.count] = icaltimezone_get_location(l_tz);
+            /*
+            g_print(P_N "before %d %s\n", tz.count, tz.city[tz.count]);
+            */
+            tz.utc_offset[tz.count] = icaltimezone_get_utc_offset(
+                    l_tz, &ctime, &tz.dst[tz.count]);
+            /*
+            g_print(P_N "after %d %s offset:%d dst: %d\n", tz.count, tz.city[tz.count], tz.utc_offset[tz.count], tz.dst[tz.count]);
+            */
         }
+        tz.utc_offset[tz.count] = 0;
+        tz.dst[tz.count] = 0;
         tz.city[tz.count++] = tz_utc;
+        tz.utc_offset[tz.count] = 0;
+        tz.dst[tz.count] = 0;
         tz.city[tz.count++] = tz_floating;
     }
     return (tz);
@@ -862,39 +922,6 @@
 }
 #endif
 
-static struct icaltimetype ical_get_current_local_time()
-{
-#undef P_N
-#define P_N "ical_get_current_local_time: "
-    struct tm *tm;
-    struct icaltimetype ctime;
-
-#ifdef ORAGE_DEBUG
-    orage_message(-300, P_N);
-#endif
-    if (g_par.local_timezone_utc)
-        ctime = icaltime_current_time_with_zone(utc_icaltimezone);
-    else if ((g_par.local_timezone)
-        &&   (strcmp(g_par.local_timezone, "floating") != 0))
-        ctime = icaltime_current_time_with_zone(local_icaltimezone);
-    else { /* use floating time */
-        ctime.is_utc      = 0;
-        ctime.is_date     = 0;
-        ctime.is_daylight = 0;
-        ctime.zone        = NULL;
-    }
-    /* and at the end we need to change the clock to be correct */
-    tm = orage_localtime();
-    ctime.year        = tm->tm_year+1900;
-    ctime.month       = tm->tm_mon+1;
-    ctime.day         = tm->tm_mday;
-    ctime.hour        = tm->tm_hour;
-    ctime.minute      = tm->tm_min;
-    ctime.second      = tm->tm_sec;
-
-    return(ctime);
-}
-
 static char *get_char_timezone(icalproperty *p)
 {
 #undef  P_N 
@@ -5000,20 +5027,240 @@
     }
 }
 
+static GtkTreeStore *tz_button_create_store(void)
+{
+#undef P_N
+#define P_N "tz_button_create_store: "
+#define MAX_AREA_LENGTH 100
+
+enum {
+    LOCATION,
+    LOCATION_ENG,
+    OFFSET,
+    N_COLUMNS
+};
+
+    GtkTreeStore *store;
+    GtkTreeIter iter1, iter2, main;
+    gboolean main_created = FALSE;
+    xfical_timezone_array tz_a;
+    char area_old[MAX_AREA_LENGTH+2]; /*+2 = / + null */
+    char s_offset[100];
+    gint i, j, offs_hour, offs_min;
+
+    store = gtk_tree_store_new(N_COLUMNS
+            , G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    strcpy(area_old, "S T a R T"); /* this never matches */
+    tz_a = get_ical_timezones();
+    g_print(P_N "number of timezones %d\n", tz_a.count);
+    g_print(P_N "name of zone file full location %s\n", ORAGE_ZONES_TAB);
+    /* Create special "area" for first level timezones, which do not have
+     * any real area */
+    gtk_tree_store_append(store, &iter1, NULL);
+    gtk_tree_store_set(store, &iter1
+            , LOCATION, _("Other")
+            , LOCATION_ENG, "Other"
+            , OFFSET, " "
+            , -1);
+    main = iter1; /* need to remember that */
+
+    for (i=0; i < tz_a.count-2; i++) {
+        /* first check area */
+        if (! g_str_has_prefix(tz_a.city[i], area_old)) {
+            /* we have new area, let's add it */
+            for (j=0; tz_a.city[i][j] && tz_a.city[i][j] != '/' 
+                      && j < MAX_AREA_LENGTH; j++) {
+                area_old[j] = tz_a.city[i][j];
+            }
+        /* now tz_a.city[i][j] is either / or 0 which means not found / */
+            if (!tz_a.city[i][j]) { /* end of name = no are code */
+                iter1 = main;
+            }
+            else if (j < MAX_AREA_LENGTH) { /* new area, let's add it */
+                area_old[j] = 0;
+                gtk_tree_store_append(store, &iter1, NULL);
+                gtk_tree_store_set(store, &iter1
+                        , LOCATION, _(area_old)
+                        , LOCATION_ENG, area_old
+                        , OFFSET, " "
+                        , -1);
+                /* let's make sure we do not match accidentally to those 
+                 * plain names on main level. We do this by adding / */
+                area_old[j++] = '/'; 
+                area_old[j] = 0;
+            }
+            else {
+                orage_message(310, P_N "too long line in zones.tab %s", tz_a.city[i]);
+            }
+
+        }
+        /* then city translated and in base form used internally */
+        gtk_tree_store_append(store, &iter2, &iter1);
+        offs_hour = tz_a.utc_offset[i] / (60*60);
+        offs_min = abs((tz_a.utc_offset[i] - offs_hour * (60*60)) / 60);
+        /*
+        offs_min = ((abs(tz_a.utc_offset[i]) / 36) % 100) / 60;
+        if (offs_min)
+            g_print(P_N " %s offset main bef %d offset minutes %d\n", tz_a.city[i], offs_hour, offs_min);
+        if (offs_min)
+            switch (offs_min) {
+                case 25:
+                    offs_min = 15;
+                    break;
+                case 50:
+                    offs_min = 30;
+                    break;
+                case 75:
+                    offs_min = 45;
+                    break;
+                default:
+                    orage_message(10, P_N "strange offset %d in zones.tab %s"
+                            , tz_a.utc_offset[i], tz_a.city[i]);
+                    break;
+            }
+            */
+        if (offs_min)
+            g_print(P_N " %s offset %d hour %d minutes %d\n", tz_a.city[i], tz_a.utc_offset[i], offs_hour, offs_min);
+        g_sprintf(s_offset, "%+03d:%02d %s", offs_hour, offs_min
+                , (tz_a.dst[i]) ? "dst" : "std");
+        gtk_tree_store_set(store, &iter2
+                , LOCATION, _(tz_a.city[i])
+                , LOCATION_ENG, tz_a.city[i]
+                , OFFSET, s_offset
+                , -1);
+    }
+    return(store);
+}
+
 gboolean xfical_timezone_button_clicked(GtkButton *button, GtkWindow *parent
         , gchar **tz)
 {
 #undef P_N
 #define P_N "xfical_timezone_button_clicked: "
-#define MAX_AREA_LENGTH 20
 
 enum {
     LOCATION,
     LOCATION_ENG,
+    OFFSET,
     N_COLUMNS
 };
 
     GtkTreeStore *store;
+    GtkWidget *tree;
+    GtkCellRenderer *rend;
+    GtkTreeViewColumn *col;
+    GtkWidget *window;
+    GtkWidget *sw;
+    int result;
+    char *loc, *loc_eng;
+    GtkTreeSelection *sel;
+    GtkTreeModel     *model;
+    GtkTreeIter       iter;
+    gboolean    changed = FALSE;
+
+#ifdef ORAGE_DEBUG
+    orage_message(-100, P_N);
+#endif
+    /* enter data */
+    store = tz_button_create_store();
+
+    /* create view */
+    tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+    rend = gtk_cell_renderer_text_new();
+    col  = gtk_tree_view_column_new_with_attributes(_("Location")
+                , rend, "text", LOCATION, 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(_("Location")
+                , rend, "text", LOCATION_ENG, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
+    gtk_tree_view_column_set_visible(col, FALSE);
+
+    rend = gtk_cell_renderer_text_new();
+    col  = gtk_tree_view_column_new_with_attributes(_("GMT Offset")
+                , rend, "text", OFFSET, NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col);
+
+    /* show it */
+    window =  gtk_dialog_new_with_buttons(_("Pick timezone")
+            , parent
+            , GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+            , _("UTC"), 1
+            , _("floating"), 2
+            , _(g_par.local_timezone), 3
+            , GTK_STOCK_OK, GTK_RESPONSE_ACCEPT
+            , NULL);
+    sw = gtk_scrolled_window_new(NULL, NULL);
+    gtk_container_add(GTK_CONTAINER(sw), tree);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), sw, TRUE, TRUE, 0);
+    /*
+    gtk_window_set_default_size(GTK_WINDOW(window), 300, 500);
+    */
+
+    gtk_widget_show_all(window);
+    do {
+        result = gtk_dialog_run(GTK_DIALOG(window));
+        switch (result) {
+            case GTK_RESPONSE_ACCEPT:
+                sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
+                if (gtk_tree_selection_get_selected(sel, &model, &iter))
+                    if (gtk_tree_model_iter_has_child(model, &iter))
+                        result = 0;
+                    else {
+                        gtk_tree_model_get(model, &iter, LOCATION, &loc, -1);
+                        gtk_tree_model_get(model, &iter, LOCATION_ENG, &loc_eng
+                                , -1);                     }
+                else {
+                    loc = g_strdup(_(*tz));
+                    loc_eng = g_strdup(*tz);
+                }
+                break;
+            case 1:
+                loc = g_strdup(_("UTC"));
+                loc_eng = g_strdup("UTC");
+                break;
+            case 2:
+                loc = g_strdup(_("floating"));
+                loc_eng = g_strdup("floating");
+                break;
+            case 3:
+                loc = g_strdup(_(g_par.local_timezone));
+                loc_eng = g_strdup(g_par.local_timezone);
+                break;
+            default:
+                loc = g_strdup(_(*tz));
+                loc_eng = g_strdup(*tz);
+                break;
+        }
+    } while (result == 0);
+    if (g_ascii_strcasecmp(loc, (gchar *)gtk_button_get_label(button)) != 0)
+        changed = TRUE;
+    gtk_button_set_label(button, loc);
+
+    if (*tz)
+        g_free(*tz);
+    *tz = g_strdup(loc_eng);
+    g_free(loc);
+    g_free(loc_eng);
+    gtk_widget_destroy(window);
+    return(changed);
+}
+
+gboolean xfical_timezone_button_clicked2(GtkButton *button, GtkWindow *parent
+        , gchar **tz)
+{
+#undef P_N
+#define P_N "xfical_timezone_button_clicked: "
+#define MAX_AREA_LENGTH 100
+
+enum {
+    LOCATION,
+    LOCATION_ENG,
+    N_COLUMNS
+};
+
+    GtkTreeStore *store;
     GtkTreeIter iter1, iter2;
     GtkWidget *tree;
     GtkCellRenderer *rend;
@@ -5034,17 +5281,23 @@
     /* enter data */
     store = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
     strcpy(area_old, "S T a R T");
-    tz_a = xfical_get_timezones();
+    tz_a = get_ical_timezones();
+    g_print(P_N "number of timezones %d\n", tz_a.count);
     for (i=0; i < tz_a.count-2; i++) {
         /* first area */
         if (! g_str_has_prefix(tz_a.city[i], area_old)) {
-            for (j=0; tz_a.city[i][j] != '/' && j < MAX_AREA_LENGTH; j++) {
+            for (j=0; tz_a.city[i][j] && tz_a.city[i][j] != '/' && j < MAX_AREA_LENGTH; j++) {
                 area_old[j] = tz_a.city[i][j];
             }
-            if (j < MAX_AREA_LENGTH)
+            if (!tz_a.city[i][j]) { /* end of name = no are code */
+                strcpy(area_old, tz_a.city[i]);
+                orage_message(10, P_N "no / found in name %s", tz_a.city[i]);
+            }
+            else if (j < MAX_AREA_LENGTH)
                 area_old[j] = 0;
-            else
+            else {
                 orage_message(310, P_N "too long line in zones.tab %s", tz_a.city[i]);
+            }
 
             gtk_tree_store_append(store, &iter1, NULL);
             gtk_tree_store_set(store, &iter1

Modified: xfcalendar/trunk/tz_convert/tz_convert.c
===================================================================
--- xfcalendar/trunk/tz_convert/tz_convert.c	2009-05-26 05:24:53 UTC (rev 29984)
+++ xfcalendar/trunk/tz_convert/tz_convert.c	2009-05-28 13:50:28 UTC (rev 29985)
@@ -58,7 +58,7 @@
 #define DEFAULT_ZONETAB_FILE        "/usr/share/zoneinfo/zone.tab"
 
 int debug = 1; /* bigger number => more output */
-char version[] = "1.0.0";
+char version[] = "1.4.3";
 int file_cnt = 0; /* number of processed files */
 
 unsigned char *in_buf, *in_head, *in_tail;
@@ -68,6 +68,7 @@
 int in_file_is_dir = 0;
 int only_one_level = 0;
 int excl_dir_cnt = 5;
+int no_rrule = 0;
 char **excl_dir = NULL;
 
 FILE *ical_file;
@@ -301,7 +302,7 @@
 int process_file(const char *file_name)
 {
     if (debug > 1)
-        printf("process_file: start\n");
+        printf("\n\nprocess_file: start\n");
     if (process_header(file_name)) {
         printf("File (%s) does not look like tz file. Skipping it.\n"
                 , file_name);
@@ -315,7 +316,8 @@
     process_std_table();
     process_gmt_table();
     if (debug > 1)
-        printf("process_file: end\n");
+        printf("\nprocess_file: end\n\n\n");
+    return(0); /* ok */
 }
 
 void create_backup_file(char *out_file)
@@ -447,7 +449,7 @@
         }
     }
     if (debug > 1)
-        printf("create_ical_file: end\n");
+        printf("create_ical_file: end\n\n");
     return(0);
 }
 
@@ -498,7 +500,11 @@
     in_head += 6*tct_i;
     data.gmt_offset = (int)get_long();
     data.gmt_offset_hh = data.gmt_offset / (60*60);
+    /*
     data.gmt_offset_mm = (data.gmt_offset - data.gmt_offset_hh * (60*60)) / 60;
+    */
+    data.gmt_offset_mm = abs((data.gmt_offset - data.gmt_offset_hh * (60*60)) 
+            / 60);
     data.is_dst = in_head[0];
     abbr_i =  in_head[1];
 
@@ -521,18 +527,26 @@
     return(data);
 }
 
-int wit_get_rrule(struct ical_timezone_data *prev
+/* Check if we can use repeat rules. We can use them if entries are 
+ * similar enough. Possible values to return:
+ * RRULE < 10 (We only check if the time happens in same weekday on same week:)
+ *          (-1 == last week, 1 == first week, 2 == second week, 3 == 3rd week)
+ * RDATE == 100
+ * no repeat possible == 0
+ * */
+int wit_get_repeat_rule(struct ical_timezone_data *prev
         , struct ical_timezone_data *cur) {
     int monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-    int rrule_day_cnt;
-    int leap_year = 0, prev_leap_year = 0;
+    int repeat_rule;
+    int cur_leap_year = 0, prev_leap_year = 0;
 
     if (cur->gmt_offset == prev->gmt_offset
     &&  !strcmp(cur->tz, prev->tz)) {
         /* 2) check if we can use RRULE. 
          * We only check yearly same month and same week day changing
          * rules (which should cover most real world cases). */
-        if (cur->start_time.tm_year == prev->start_time.tm_year + 1
+        if (!no_rrule
+        &&  cur->start_time.tm_year == prev->start_time.tm_year + 1
         &&  cur->start_time.tm_mon  == prev->start_time.tm_mon
         &&  cur->start_time.tm_wday == prev->start_time.tm_wday
         &&  cur->start_time.tm_hour == prev->start_time.tm_hour
@@ -540,6 +554,12 @@
         &&  cur->start_time.tm_sec  == prev->start_time.tm_sec) {
             /* so far so good, now check that our weekdays are on
              * the same week */
+            if (cur->start_time.tm_mon == 1) {
+                if (((cur->start_time.tm_year%4) == 0)
+                && (((cur->start_time.tm_year%100) != 0) 
+                    || ((cur->start_time.tm_year%400) == 0)))
+                    cur_leap_year = 1; /* leap year, february has 29 days */
+            }
             if (prev->start_time.tm_mon == 1) {
                 if (((prev->start_time.tm_year%4) == 0)
                 && (((prev->start_time.tm_year%100) != 0) 
@@ -548,17 +568,17 @@
             }
             /* most often these change on the last week day
              * (and on sunday, but that does not matter now) */
-            if ((monthdays[cur->start_time.tm_mon] + leap_year - 
+            if ((monthdays[cur->start_time.tm_mon] + cur_leap_year - 
                     cur->start_time.tm_mday) < 7
             &&  (monthdays[prev->start_time.tm_mon] + prev_leap_year - 
                     prev->start_time.tm_mday) < 7) {
                 /* yep, it is last */
-                rrule_day_cnt = -1;
+                repeat_rule = -1;
             }
             else if (cur->start_time.tm_mday < 8
                  &&  prev->start_time.tm_mday < 8) {
                 /* ok, it is first */
-                rrule_day_cnt = 1;
+                repeat_rule = 1;
             }
             else if (cur->start_time.tm_mday < 15
                  &&  prev->start_time.tm_mday < 15
@@ -566,7 +586,7 @@
                  &&  cur->start_time.tm_mday >= 8 
                  &&  prev->start_time.tm_mday >= 8) {
                 /* fine, it is second */
-                rrule_day_cnt = 2;
+                repeat_rule = 2;
             }
             else if (cur->start_time.tm_mday < 22
                  &&  prev->start_time.tm_mday < 22
@@ -574,64 +594,83 @@
                  &&  cur->start_time.tm_mday >= 15 
                  &&  prev->start_time.tm_mday >= 15) {
                 /* must be the third then */
-                rrule_day_cnt = 3;
+                repeat_rule = 3;
             }
             else { 
                 /* give up, it did not work after all.
                  * It is quite possible that rule changed, but
                  * in that case we need to write this out anyway */
-                rrule_day_cnt = 100; /* RDATE is still possible */
+                repeat_rule = 100; /* RDATE is still possible */
             }
         }
         else { /* 2) failed, need to use RDATE */
-            rrule_day_cnt = 100;
+            repeat_rule = 100;
         }
     }
     else { /* 1) not possible to use RRULE nor RDATE, need new entry */
-        rrule_day_cnt = 0;
+        repeat_rule = 0;
     }
-    return(rrule_day_cnt);
+    return(repeat_rule);
 }
 
-void wit_write_data(int rrule_day_cnt, struct rdate_prev_data *rdate
-        , struct ical_timezone_data *first
-        , struct ical_timezone_data *prev)
+void wit_write_data(int repeat_rule, struct rdate_prev_data **rdate
+        , struct ical_timezone_data *first, struct ical_timezone_data *prev
+        , struct ical_timezone_data *ical_data)
 {
-    char str[100];
-    int len;
+    char str[100], until_date[20];
+    int len, until_day;
     char *dst_begin="BEGIN:DAYLIGHT\n";
     char *dst_end="END:DAYLIGHT\n";
     char *std_begin="BEGIN:STANDARD\n";
     char *std_end="END:STANDARD\n";
     char *day[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA" };
+    int monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
     struct rdate_prev_data *tmp_data = NULL, *tmp_data2;
     struct ical_timezone_data tmp_prev;
+    struct tm until_time;
 
     if (debug > 3)
         printf("\tWriting data (%s) %s"
                 , first->is_dst ? "dst" : "std"
                 , asctime(&first->start_time));
 
-    /****** First Check that we really need to write this record *****/
-    if (rrule_day_cnt == 100) { /* RDATE rule */
-        if (rdate == NULL) {
-        /* we actually have nothing to print. This happens seldom, but
-         * is possible if we found RDATE rule, but after that we actually
-         * found that it is the first RRULE element and we did not push
-         * anything into the rdate store */
-            if (debug > 3)
-                printf("\tWrite aborted. RDATE rule changed to RRULE\n");
-            return;
+    /****** First check that we really need to write this record *****/
+    /* when we have last write (ical_data == NULL), we always need to write */
+    if (ical_data) { /* not last, check if write can be omitted */
+        if (repeat_rule == 100) { /* RDATE rule */
+            for (tmp_data = *rdate; tmp_data ; ) {
+                tmp_prev = tmp_data->data;
+                if ((tmp_prev.start_time.tm_year + 1900) <= ignore_older) {
+                    tmp_data2 = tmp_data;
+                    tmp_data = tmp_data->next;
+                    *rdate = tmp_data; /* new start */
+                    free(tmp_data2);
+                    if (debug > 3)
+                        printf("\tWrite skipped. Too old RDATE row\n");
+                }
+                else { /* rows are in order, so we are done */
+                    tmp_data = tmp_data->next;
+                    if (debug > 3)
+                        printf("\tWrite kept. Fresh RDATE row\n");
+                }
+            }
+            if (*rdate == NULL) {
+            /* we actually have nothing left to print. */
+                if (debug > 2)
+                    printf("\tWrite skipped. Too old RDATE entry\n");
+                return;
+            }
         }
-    }
-    else if (rrule_day_cnt == 0) { /* non repeating rule */
-        if ((prev->start_time.tm_year + 1900) <= ignore_older) {
-        /* We again have nothing to print. We got non repeating case, which
-         * happens before our limit year */
-            if (debug > 3)
-                printf("\tWrite aborted. Too old non repeating year\n");
-            return;
+        else if (repeat_rule == 0) { /* non repeating rule */
+            if ((prev->start_time.tm_year + 1900) <= ignore_older) {
+            /* We have nothing to print. We got non repeating case, which
+             * happens before our limit year */
+                if (debug > 2)
+                    printf("\tWrite skipped. Too old non repeating year\n");
+                return;
+            }
         }
+        /* FIXME: adjust DTSTART with RDATE but also with RRULE */
     }
 
     /****** Write the data ******/
@@ -660,20 +699,45 @@
             , first->start_time.tm_sec);
     fwrite(str, 1, len, ical_file);
 
-    if (rrule_day_cnt) { /* we had repeating appointment */
-        if (rrule_day_cnt < 10) { /* RRULE */
+    if (repeat_rule) { /* we had repeating appointment */
+        if (repeat_rule < 10) { /* RRULE */
             if (debug > 3)
                 printf("\t\t...RRULE\n");
-            len = snprintf(str, 50, "RRULE:FREQ=YEARLY;BYMONTH=%d;BYDAY=%d%s\n"
+            /* All RRULE ends. We invent end time to be close after last 
+             * included date = prev */
+            until_time = prev->start_time;
+            if (until_time.tm_mday > 28 && until_time.tm_mon == 1) {
+                /* we are in february, which is special */
+                if (((until_time.tm_year%4) == 0)
+                && (((until_time.tm_year%100) != 0) 
+                    || ((until_time.tm_year%400) == 0)))
+                    ++monthdays[1]; /* leap year, february has 29 days */
+            }
+            /* goto next day. Note that all our RRULE are yearly, so this
+             * is very safe. (We set time also to the end of the day.) */
+            if (++until_time.tm_mday > monthdays[until_time.tm_mon]) {
+                if (++until_time.tm_mon > 11) {
+                    ++until_time.tm_year;
+                    until_time.tm_mon = 0;
+                }
+                until_time.tm_mday = 1;
+            }
+            len = snprintf(until_date, 30, "%04d%02d%02dT235959Z"
+                    , until_time.tm_year + 1900
+                    , until_time.tm_mon  + 1
+                    , until_time.tm_mday);
+            len = snprintf(str, 80
+                    , "RRULE:FREQ=YEARLY;BYMONTH=%d;BYDAY=%d%s;UNTIL=%s\n"
                     , first->start_time.tm_mon + 1
-                    , rrule_day_cnt
-                    , day[first->start_time.tm_wday]);
+                    , repeat_rule
+                    , day[first->start_time.tm_wday]
+                    , until_date);
             fwrite(str, 1, len, ical_file);
         }
         else { /* RDATE */
             if (debug > 3)
                 printf("\t\t...RDATE\n");
-            for (tmp_data = rdate; tmp_data ; ) {
+            for (tmp_data = *rdate; tmp_data ; ) {
                 tmp_prev = tmp_data->data;
                 len = snprintf(str, 30, "RDATE:%04d%02d%02dT%02d%02d%02d\n"
                         , tmp_prev.start_time.tm_year + 1900
@@ -693,14 +757,7 @@
     else {
         if (debug > 3)
             printf("\t\t...single\n");
-        len = snprintf(str, 30, "RDATE:%04d%02d%02dT%02d%02d%02d\n"
-                , prev->start_time.tm_year + 1900
-                , prev->start_time.tm_mon  + 1
-                , prev->start_time.tm_mday
-                , prev->start_time.tm_hour
-                , prev->start_time.tm_min
-                , prev->start_time.tm_sec);
-        fwrite(str, 1, len, ical_file);
+        /* dtstart tells the first time */
     }
 
     if (prev->is_dst)
@@ -709,9 +766,40 @@
         write_ical_str(std_end);
 }
 
+wit_push_to_rdate_queue(struct rdate_prev_data **p_rdate_data
+        , struct ical_timezone_data *p_data_prev)
+{
+    struct rdate_prev_data *tmp_data = NULL, *tmp_data2 = NULL;
+
+    for (tmp_data = *p_rdate_data; tmp_data ; ) {
+        /* find the last one, which is still empty */
+        tmp_data2 = tmp_data;
+        tmp_data  = tmp_data->next;
+    }
+    tmp_data = malloc(sizeof(struct rdate_prev_data));
+    tmp_data->data = *p_data_prev;
+    tmp_data->next = NULL; /* last */
+    if (!*p_rdate_data) {
+        *p_rdate_data = tmp_data;
+    }
+    else {
+        tmp_data2->next = tmp_data;
+    }
+}
+
 void write_ical_timezones()
 {
     int i;
+    /* ical_data        contains the just read new record being processed
+     * ical_data_prev   is previous record (needed when getting next data)
+     * data_prev_std    is previous std (standard time) record
+     * data_prev_dst    is previous dst (daylight saving time) record
+     * data_first_std   is first std record before within repeating group.
+     * data_first_dst   is first dst record before within repeating group
+     *                  DTSTART is based on "first", so it is needed always,
+     *                  but it stops incrementing with RRULE and RDATE. For non 
+     *                  repeating groups, it is actually the same than prev.
+     *                  */
     struct ical_timezone_data ical_data
         , ical_data_prev = { {0, 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, NULL}
         , data_prev_std = { {0, 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, NULL}
@@ -725,16 +813,15 @@
 
     int std_init_done = 0;
     int dst_init_done = 0;
-    int rrule_day_cnt_std = 0, rrule_day_cnt_std_prev = 0;
-    int rrule_day_cnt_dst = 0, rrule_day_cnt_dst_prev = 0;
-        /* pointers either to rrule_day_cnt_std and rrule_day_cnt_std_prev
-         * or to rrule_day_cnt_dst and rrule_day_cnt_dst_prev. 
+    int repeat_rule_std_cur = 0, repeat_rule_std_prev = 0;
+    int repeat_rule_dst_cur = 0, repeat_rule_dst_prev = 0;
+        /* pointers either to repeat_rule_std_cur and repeat_rule_std_prev
+         * or to repeat_rule_dst_cur and repeat_rule_dst_prev. 
          * These avoid having separate code paths for std and dst */
-    int *p_rrule_day_cnt = 0, *p_rrule_day_cnt_prev = 0;
-    struct rdate_prev_data *prev_dst_data = NULL, *prev_std_data = NULL
-        /* points either to prev_dst_data or to prev_std_data */
-        , **p_prev_data 
-        , *tmp_data = NULL, *tmp_data2 = NULL;
+    int *p_repeat_rule_cur = NULL, *p_repeat_rule_prev = NULL;
+    /* lists to maintain repeating RDATE group actual dates */
+    struct rdate_prev_data *rdate_data_dst = NULL, *rdate_data_std = NULL
+        , **p_rdate_data; /* points to rdate_data_dst or to rdate_data_std */
 
     /* we are processing "in_timezone_name" so we know it exists in this 
      * system and it is then safe to use that in the localtime conversion */
@@ -756,16 +843,19 @@
                 data_prev_dst  = ical_data;
                 dst_init_done  = 1;
                 if (debug > 2)
-                    printf("init %d = (%s) %s", i
-                            , ical_data.is_dst ? "dst" : "std"
+                    printf("init time change %d: (%s) from %02d:%02d to %02d:%02d (%s) %s"
+                            , i, ical_data.is_dst ? "dst" : "std"
+                            , ical_data.prev_gmt_offset_hh, ical_data.prev_gmt_offset_mm
+                            , ical_data.gmt_offset_hh, ical_data.gmt_offset_mm
+                            , ical_data.tz
                             , asctime(&ical_data.start_time));
-                continue; /* we never write the first record */
-            }
+                        continue; /* we never write the first record */
+                    }
             p_data_first = &data_first_dst;
             p_data_prev = &data_prev_dst;
-            p_rrule_day_cnt = &rrule_day_cnt_dst;
-            p_rrule_day_cnt_prev = &rrule_day_cnt_dst_prev;
-            p_prev_data = &prev_dst_data;
+            p_repeat_rule_cur = &repeat_rule_dst_cur;
+            p_repeat_rule_prev = &repeat_rule_dst_prev;
+            p_rdate_data = &rdate_data_dst;
         }
         else { /* !dst == std */
             if (!std_init_done) {
@@ -773,147 +863,192 @@
                 data_prev_std  = ical_data;
                 std_init_done  = 1;
                 if (debug > 2)
-                    printf("init %d = (%s) %s", i
-                            , ical_data.is_dst ? "dst" : "std"
+                    printf("int time change %d: (%s) from %02d:%02d to %02d:%02d (%s) %s"
+                            , i, ical_data.is_dst ? "dst" : "std"
+                            , ical_data.prev_gmt_offset_hh, ical_data.prev_gmt_offset_mm
+                            , ical_data.gmt_offset_hh, ical_data.gmt_offset_mm
+                            , ical_data.tz
                             , asctime(&ical_data.start_time));
                 continue; /* we never write the first record */
             }
             p_data_first = &data_first_std;
             p_data_prev = &data_prev_std;
-            p_rrule_day_cnt = &rrule_day_cnt_std;
-            p_rrule_day_cnt_prev = &rrule_day_cnt_std_prev;
-            p_prev_data = &prev_std_data;
+            p_repeat_rule_cur = &repeat_rule_std_cur;
+            p_repeat_rule_prev = &repeat_rule_std_prev;
+            p_rdate_data = &rdate_data_std;
         }
 
-    /***** check if we need this data *****/
-        /* we only take newer than threshold values */
-        if (ical_data.start_time.tm_year + 1900 <= ignore_older) {
-            if (debug > 2)
-                printf("skip %d = (%s) %s", i
-                        , ical_data.is_dst ? "dst" : "std"
-                        , asctime(&ical_data.start_time));
-            ical_data_prev = ical_data;
-            *p_data_first = ical_data;
-            *p_data_prev = ical_data;
-            *p_rrule_day_cnt_prev = *p_rrule_day_cnt;
-            *p_rrule_day_cnt = wit_get_rrule(p_data_prev, &ical_data);
-            /* without p_ variables this looked like:
-            if (ical_data.is_dst) {
-                data_first_dst = ical_data;
-                data_prev_dst  = ical_data;
-                rrule_day_cnt_dst_prev = rrule_day_cnt_dst;
-                rrule_day_cnt_dst = wit_get_rrule(&data_prev_dst, &ical_data);
-            }
-            else {
-                data_first_std = ical_data;
-                data_prev_std  = ical_data;
-                rrule_day_cnt_std_prev = rrule_day_cnt_std;
-                rrule_day_cnt_std = wit_get_rrule(&data_prev_std, &ical_data);
-            }
-            */
-            continue;
-        }
+
         if (debug > 2)
-            printf("process %d: (%s) from %02d:%02d to %02d:%02d (%s) %s", i
-                    , ical_data.is_dst ? "dst" : "std"
-                    , ical_data.prev_gmt_offset_hh,ical_data.prev_gmt_offset_mm
+            printf("time change %d: (%s) from %02d:%02d to %02d:%02d (%s) %s"
+                    , i, ical_data.is_dst ? "dst" : "std"
+                    , ical_data.prev_gmt_offset_hh, ical_data.prev_gmt_offset_mm
                     , ical_data.gmt_offset_hh, ical_data.gmt_offset_mm
                     , ical_data.tz
                     , asctime(&ical_data.start_time));
+
     /***** check if we can shortcut the entry with RRULE or RDATE *****/
-        /* 1) check if it is similar to the previous values */
-        *p_rrule_day_cnt_prev = *p_rrule_day_cnt;
-        *p_rrule_day_cnt = wit_get_rrule(p_data_prev, &ical_data);
-        if (*p_rrule_day_cnt
-        && (*p_rrule_day_cnt == *p_rrule_day_cnt_prev
-            && *p_rrule_day_cnt_prev)) {
-            /* we continue with either real RRULE or RDATE */
-            if (*p_rrule_day_cnt < 10) {
-                /* we found RRULE, so we do not have to do anything 
-                 * since this just continues. */
+        /* We have the following possibilities shown by p_repeat_rule_prev/cur:
+         *      RRULE == < 10    RDATE == 100     NONE == 0
+         *      remember to check first == 0 as RRULE matches that, too
+         * (We also know that those pointers always have a value, so null check
+         *  is not needed)
+         * prev     cur     action
+         * RRULE    RRULE   => a) same rule => continue
+         *                     b) different rule => write, init new RRULE
+         *                          (not possible now as we do not have 
+         *                          overlappin rules)
+         * RDATE    RRULE   => write, end RDATE, init RRULE
+         * NONE     RRULE   => init RRULE
+         * RRULE    RDATE   => write, init RDATE
+         * RDATE    RDATE   => push RDATE to queue, continue
+         * NONE     RDATE   => init RDATE
+         * RRULE    NONE    => write
+         * RDATE    NONE    => write
+         * NONE     NONE    => write
+         * */
+        *p_repeat_rule_prev = *p_repeat_rule_cur;
+        *p_repeat_rule_cur = wit_get_repeat_rule(p_data_prev, &ical_data);
+        if (debug > 3)
+            printf("\t\t\t***** repeating values prev:%d cur:%d\n"
+                    , *p_repeat_rule_prev, *p_repeat_rule_cur);
+
+        if (*p_repeat_rule_cur == 0) {
+        /***** NONE begin *****/
+            if (*p_repeat_rule_prev == 0) { /* also previously NONE */
+                wit_write_data(*p_repeat_rule_prev, p_rdate_data
+                        , p_data_first, p_data_prev, &ical_data);
+                *p_data_first = ical_data;
+                *p_data_prev  = ical_data;
                 if (debug > 3)
-                    printf("\tRRULE value found\n");
-                *p_data_prev = ical_data;
+                    printf("\tNONE -> NONE\n");
+            } /* end-ef NONE */
+            else if (*p_repeat_rule_prev < 10) { /* previously RRULE */
+                wit_write_data(*p_repeat_rule_prev, p_rdate_data
+                        , p_data_first, p_data_prev, &ical_data);
+                *p_data_first = ical_data;
+                *p_data_prev  = ical_data;
+                if (debug > 3)
+                    printf("\tRRULE -> NONE\n");
+            } /* end-of RRULE */
+            else if (*p_repeat_rule_prev == 100) { /* previously RDATE */
+                /* need to push the last RDATE and write them all. 
+                   If we had only one RDATE, it is not mandatory to push it,
+                   but it works equally well, so not worth special check */
+                wit_push_to_rdate_queue(p_rdate_data, p_data_prev);
+                wit_write_data(*p_repeat_rule_prev, p_rdate_data
+                        , p_data_first, p_data_prev, &ical_data);
+                /* wit_write_data freed rdate memory already */
+                *p_rdate_data = NULL;
+                *p_data_first = ical_data;
+                *p_data_prev  = ical_data;
+                if (debug > 3)
+                    printf("\tRDATE -> NONE\n");
+            } /* end-of RDATE */
+            else { /* error, unknown value */
+                perror("***** Unknown value in repeating rule *****");
             }
-            else { /* we actually found RDATE */
+        /***** NONE end *****/
+        } 
+        else if (*p_repeat_rule_cur < 10 ) {  
+        /***** RRULE begin *****/
+            if (*p_repeat_rule_prev == 0) { /* previously NONE */
+                /* do not write the previous, use it as first RRULE element */
+                *p_data_first = *p_data_prev;
+                *p_data_prev  = ical_data;
                 if (debug > 3)
-                    printf("\tRDATE value found\n");
-                if (p_data_prev->start_time.tm_year + 1900 <= ignore_older) {
-                    /* do not push old values into queue, ignore them */
-                    if (debug > 3)
-                        printf("\tAborted push to RRULE queue, too old (%s) %s"
-                                , p_data_prev->is_dst ? "dst" : "std"
-                                , asctime(&p_data_prev->start_time));
+                    printf("\tNONE -> RRULE\n");
+            } /* end-ef NONE */
+            else if (*p_repeat_rule_prev < 10) { /* also previously RRULE */
+                if (*p_repeat_rule_prev == *p_repeat_rule_cur) {
+                /* we had same RRULE previously, so we do not have to do 
+                 * anything since this just continues. */
+                    *p_data_prev = ical_data;
                 }
-                else {
-                    if (debug > 3)
-                        printf("\tpushed to RRULE queue (%s) %s"
-                                , p_data_prev->is_dst ? "dst" : "std"
-                                , asctime(&p_data_prev->start_time));
-                    for (tmp_data = *p_prev_data; tmp_data ; ) {
-                        /* find the last one, which is still empty */
-                        tmp_data2 = tmp_data;
-                        tmp_data  = tmp_data->next;
-                    }
-                    tmp_data = malloc(sizeof(struct rdate_prev_data));
-                    tmp_data->data = *p_data_prev;
-                    tmp_data->next = NULL; /* last */
-                    if (!*p_prev_data) {
-                        *p_prev_data = tmp_data;
-                    }
-                    else {
-                        tmp_data2->next = tmp_data;
-                    }
+                else { /* different RRULE (not possible now as we do
+                          not have overlapping rules) */
+                    printf("\t***** ERROR: change from RRULE to different RRULE \n");
+                    wit_write_data(*p_repeat_rule_prev, p_rdate_data
+                            , p_data_first, p_data_prev, &ical_data);
+                    *p_data_first = ical_data;
+                    *p_data_prev  = ical_data;
                 }
-                *p_data_prev = ical_data;
+                if (debug > 3)
+                    printf("\tRULE -> RRULE\n");
+            } /* end-of RRULE */
+            else if (*p_repeat_rule_prev == 100) { /* previously RDATE */
+                /* Note that we have not pushed the previous RDATE into the 
+                 * rdate queue yet. As we now see that it fist our RRULE, 
+                 * we will steal it and use in RRULE.
+                 * We do not have to write anything if we only had this one
+                 * RDATE */
+                if (*p_rdate_data != NULL) {
+                    /* we had more than one rdate, need to write those */
+                    wit_write_data(*p_repeat_rule_prev, p_rdate_data
+                            , p_data_first, p_data_prev, &ical_data);
+                }
+                /* wit_write_data freed rdate memory already */
+                *p_rdate_data = NULL;
+                *p_data_first = *p_data_prev;
+                *p_data_prev  = ical_data;
+                if (debug > 3)
+                    printf("\tRDATE -> RRULE\n");
+            } /* end-of RDATE */
+            else { /* error, unknown value */
+                perror("***** Unknown value in repeating rule *****");
             }
+        /***** RRULE end *****/
         }
-        else { /* not RRULE or we changed to/from RRULE from/to RDATE, 
-                * so write previous and init new round */
-            if (debug > 3)
-                printf("\tnon repeating value found\n");
-            wit_write_data(*p_rrule_day_cnt_prev, *p_prev_data
-                    , p_data_first, p_data_prev);
-            if (*p_rrule_day_cnt_prev > 10 && *p_rrule_day_cnt < 10) {
-                /* we had RDATE and now we found RRULE */
-                /* so this was actually the first RRULE */
+        else if (*p_repeat_rule_cur == 100) {  
+        /***** RDATE begin *****/
+            if (*p_repeat_rule_prev == 0) { /* previously NONE */
+                /* do not write the previous, use it as first RDATE element */
+                wit_push_to_rdate_queue(p_rdate_data, p_data_prev);
+                *p_data_first = *p_data_prev;
+                *p_data_prev  = ical_data;
                 if (debug > 3)
-                    printf("\tchanged from RDATE to RRULE\n");
-                if (p_data_prev->start_time.tm_year + 1900 <= ignore_older) {
-                    /* we ignore too old record and take current as first */
-                    if (debug > 3) {
-                        printf("\tIgnoring too old (%s) %s"
-                                , p_data_prev->is_dst ? "dst" : "std"
-                                , asctime(&p_data_prev->start_time));
-                        printf("\tUsing RRULE (%s) %s"
-                                , ical_data.is_dst ? "dst" : "std"
-                                , asctime(&ical_data.start_time));
-                    }
-                    *p_data_first = ical_data; 
-                }
-                else {
-                    if (debug > 3)
-                        printf("\tUsing RRULE (%s) %s"
-                                , p_data_prev->is_dst ? "dst" : "std"
-                                , asctime(&p_data_prev->start_time));
-                    *p_data_first = *p_data_prev; 
-                }
-            }
-            else {
+                    printf("\tNONE -> RDATE\n");
+            } /* end-ef NONE */
+            else if (*p_repeat_rule_prev < 10) { /* previously RRULE */
+                /* write old RRULE as we rather use it than RDATE, but do not 
+                 * push this new value to rdate queue as it is now our first 
+                 * rdate and we may not get more. */
+                wit_write_data(*p_repeat_rule_prev, p_rdate_data
+                        , p_data_first, p_data_prev, &ical_data);
                 *p_data_first = ical_data;
+                *p_data_prev  = ical_data;
+                if (debug > 3)
+                    printf("\tRRULE -> RDATE\n");
+            } /* end-of RRULE */
+            else if (*p_repeat_rule_prev == 100) { /* also previously RDATE */
+                /* we only add prev data into the queue and that is it */
+                wit_push_to_rdate_queue(p_rdate_data, p_data_prev);
+                *p_data_prev  = ical_data;
+                if (debug > 3)
+                    printf("\tRDATE -> RDATE\n");
+            } /* end-of RDATE */
+            else { /* error, unknown value */
+                perror("***** Unknown value in repeating rule *****");
             }
-            *p_data_prev  = ical_data;
-            *p_prev_data  = NULL;
-        } 
+        /***** RDATE end *****/
+        }
         ical_data_prev = ical_data;
     } /* for (i = 0; i < timecnt; i++) */
+
     /* need to write the last one also */
     if (debug > 3)
         printf("writing last values:\n");
-    wit_write_data(rrule_day_cnt_std_prev, prev_std_data
-            , &data_first_std, &data_prev_std);
-    wit_write_data(rrule_day_cnt_dst_prev, prev_dst_data
-            , &data_first_dst, &data_prev_dst);
+    if (std_init_done)
+        wit_write_data(repeat_rule_std_prev, &rdate_data_std
+                , &data_first_std, &data_prev_std, NULL);
+    else if (debug > 3)
+        printf("\tskipping last std write as std init has not been done:\n");
+
+    if (dst_init_done)
+        wit_write_data(repeat_rule_dst_prev, &rdate_data_dst
+                , &data_first_dst, &data_prev_dst, NULL);
+    else if (debug > 3)
+        printf("\tskipping last dst write as dst init has not been done:\n");
 }
 
 void write_ical_ending()
@@ -928,7 +1063,7 @@
 int write_ical_file(const char *in_file_name, const struct stat *in_file_stat)
 {
     if (debug > 1)
-        printf("write_ical_file: start\n");
+        printf("***** write_ical_file: start *****\n\n");
     if (create_ical_file(in_file_name))
         return(1);
     write_ical_header();
@@ -936,7 +1071,7 @@
     write_ical_ending();
     fclose(ical_file);
     if (debug > 1)
-        printf("write_ical_file: end\n");
+        printf("\n***** write_ical_file: end *****\n\n\n");
     return(0);
 }
 
@@ -999,7 +1134,7 @@
               " 0 is least and 10 is highest (1=default)."
             , "level"},
         {"limit", 'l', POPT_ARG_INT, &ignore_older, 6
-            , "limit proocessing to newer than this year."
+            , "limit processing to newer than this year."
             , "year"},
         {"timezone", 't', POPT_ARG_STRING, &tmp_str, 7
             , "timezone name. For example Europe/Helsinki"
@@ -1019,6 +1154,13 @@
               " By default directories right and posix are excluded, but if"
               " you use this parameter, you have to specify those also."
             , "directory"},
+        {"norrule", 'u', POPT_ARG_INT, &no_rrule, 11
+            , "do not use RRULE ical repeating rule, but use RDATE instead."
+              " Not all calendars are able to understand RDATE correctly"
+              " with timezones. "
+              " (Orage should work fine with RRULE)"
+              " 0 = use RRULE  1 = do not use RRULE (0=default)."
+            , "level"},
         POPT_AUTOHELP
         {NULL, '\0', POPT_ARG_NONE, NULL, 0, NULL, NULL}
     };
@@ -1083,6 +1225,12 @@
                     res = val;
                 }
                 break;
+            case 11:
+                if (no_rrule)
+                    printf("Not using RRULE (using RDATE instead)\n");
+                else
+                    printf("Using RRULE when possible\n");
+                break;
             default:
                 res = val;
                 printf("unknown parameter\n");
@@ -1216,7 +1364,7 @@
         printf("file_call: start\n");
     file_cnt++;
     /* we are only interested about files and directories we can access */
-    if (flags == FTW_F) {
+    if (flags == FTW_F) { /* we got file */
         if (debug > 0)
             printf("\t\tfile_call: processing file=(%s)\n", file_name);
         if (only_one_level && (f->level > 1)) {
@@ -1227,16 +1375,20 @@
             return(FTW_CONTINUE);
         }
         read_file(file_name, sb);
-        process_file(file_name);
+        if (process_file(file_name)) { /* we skipped this file */
+            free(in_buf);
+            return(FTW_CONTINUE);
+        }
         write_ical_file(file_name, sb);
         add_zone_tabs();
+
         free(in_buf);
         free(out_file);
         out_file = NULL;
         free(in_timezone_name);
         free(timezone_name);
     }
-    else if (flags == FTW_D) {
+    else if (flags == FTW_D) { /* this is directory */
         if (debug > 0)
             printf("\tfile_call: processing directory=(%s)\n", file_name);
         if (only_one_level && f->level > 0) {
@@ -1361,6 +1513,8 @@
         for (i = 0; (i <= excl_dir_cnt) && excl_dir[i];i++)
             printf("\t\texclude directory %d: (%s)\n"
                     , i, excl_dir[i]);
+        printf("\tusing rrule: %s\n"
+                , no_rrule ? "NO" : "YES");
         printf("***** Parameters *****\n\n");
     }
     if (debug > 1)




More information about the Xfce4-commits mailing list