[evolution-patches] Evolution Multi Calendar patch !



Hello...

According to previous emails, We're on our way to make the evolution
compatible with multi calendar systems.
FIRST stable patch is ready now.

It'll take 2 more patches to achieve a multi calendar evolution.

Here, some notes about the patch(s) :

   * Since, the evolution doesn't use a single backend to get date/time
(GDATE, icaltimetype, tm, time_t, etc) we were forced to change all time
layers and modules, in order to make them work with multi calendar
systems.

   * We named the new function set, IMcal...IMprovedcal. New functions
are accessible from
'/evolution-data-server/calendar/libical/src/libical/'. Added routines
start with 'imcaltime*' prefix

   * All added routines have a similar prototype to the original libical
functions, except that we add them a additional argument, which is a
'imcaltimeobj'. This type is used to improve flexibility of the new time
routines and contains some function pointers to time/date calculating
routines, according to IN-USE calendar system (like Gregorian, Jalali,
Hijri etc) which is declared in the structure. for more info on
'imcaltimeobj' see 'imcaltime.h'.

   * Using 'imcaltimeobj' we're able to use calendar systems in two
order:
     1) As a module, which is loaded with some shared library loading
library like libdl (Requires some fixes on Makefile).
     2) As a Internal part of code. 
     
   * Currently there are two available calendars which is made as
module:
     0) Gregorian : Default.
     1) Jalali : Used in Iran.
     2) Hijri : Mostly used in Arabic countries.

   * We'll change the evolution with 3 different patches:
     1)Patch on "libical", which contains our major multi calendar
routines. (data-server)
     2)Next patch will be the "libecal". Uses independent, or libical
dependent routines. (data-server)
     3)Finally, 3rd path is for the evolution client. (client)

Note: since, we've added some new files to data-server, we have NOT use
'cvs diff' to make the patch. The attached patch is created with
ordinary 'diff'.




diff -u -p -N evolution-data-server/calendar/libical/src/libical/Makefile.am evolution-data-server-wd/calendar/libical/src/libical/Makefile.am
--- evolution-data-server/calendar/libical/src/libical/Makefile.am	2005-07-05 19:24:13.000000000 +0430
+++ evolution-data-server-wd/calendar/libical/src/libical/Makefile.am	2005-07-05 20:09:37.000000000 +0430
@@ -53,6 +53,16 @@ libical_evolution_la_LDFLAGS = -version-
 
 libical_evolution_la_SOURCES =		\
 	$(BUILT_SOURCES)	\
+	imcaltime.c 		\
+	imcaltime.h		\
+	imcaltimeobj_gregorian.c \
+	imcaltimeobj_gregorian.h \
+	imcaltimeobj_hijri.c	\
+	imcaltimeobj_hijri.h	\
+	imcaltimeobj_jalali.c	\
+	imcaltimeobj_jalali.h	\
+	imcaltimezone.c		\
+	imcaltimezone.h		\
 	icalarray.c		\
 	icalarray.h		\
 	icalattach.h		\
@@ -118,31 +128,37 @@ endif
 libical_evolutionincludedir = $(privincludedir)/libical
 
 libical_evolutioninclude_HEADERS = \
-	ical.h			\
-	icalarray.h		\
-	icalattach.h		\
-	icalcomponent.h		\
-	icalderivedparameter.h	\
-	icalderivedproperty.h	\
-	icalderivedvalue.h	\
-	icalduration.h		\
-	icalenums.h		\
-	icalerror.h		\
-	icallangbind.h		\
-	icalmemory.h		\
-	icalmime.h		\
-	icalparameter.h		\
-	icalparser.h		\
-	icalperiod.h		\
-	icalproperty.h		\
-	icalrecur.h		\
-	icalrestriction.h	\
-	icaltime.h		\
-	icaltimezone.h		\
-	icaltypes.h		\
-	icalvalue.h		\
-	pvl.h			\
-	sspm.h			\
+	ical.h				\
+	icalarray.h			\
+	icalattach.h			\
+	icalcomponent.h			\
+	icalderivedparameter.h		\
+	icalderivedproperty.h		\
+	icalderivedvalue.h		\
+	icalduration.h			\
+	icalenums.h			\
+	icalerror.h			\
+	icallangbind.h			\
+	icalmemory.h			\
+	icalmime.h			\
+	icalparameter.h			\
+	icalparser.h			\
+	icalperiod.h			\
+	icalproperty.h			\
+	icalrecur.h			\
+	icalrestriction.h		\
+	icaltime.h			\
+	icaltimezone.h			\
+	icaltypes.h			\
+	icalvalue.h			\
+	imcaltime.c			\
+	imcaltime.h			\
+	imcaltimeobj_gregorian.h	\
+	imcaltimeobj_hijri.h		\
+	imcaltimeobj_jalali.h		\
+	imcaltimezone.h			\
+	pvl.h				\
+	sspm.h				\
 	$(cxx_headers)
 
 # ORDERING OF HEADERS IS SIGNIFICANT. Don't change this ordering. It
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltime.c evolution-data-server-wd/calendar/libical/src/libical/imcaltime.c
--- evolution-data-server/calendar/libical/src/libical/imcaltime.c	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltime.c	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,1187 @@
+/* -*- Mode: C -*-
+  ======================================================================
+  FILE: imcaltime.c
+  CREATOR: eric 02 June 2000
+  
+  $Id: icaltime.c,v 1.34 2004/12/22 11:54:39 rodrigo Exp $
+  $Locker:  $
+  
+  MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+             Arash Yadegarnia		arash bluehome net  
+	     
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+  
+ ======================================================================*/
+ /***********************************************************************
+  * @file imcaltime.c                                                   *
+  *                                                                     *
+  * @This file contains some modified libical routines, which has been  *
+  * added, in order to make it compatible with multi calendar purposes. *
+  ***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imcaltime.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "astime.h"		/* Julian data handling routines */
+
+#include "icalerror.h"
+#include "icalmemory.h"
+
+#include "imcaltimezone.h"
+#include "icalvalue.h"
+
+#ifdef WIN32
+#include <Windows.h>
+
+#define snprintf      _snprintf
+#define strcasecmp    stricmp
+#endif
+
+/*
+ *  Function to convert a struct tm time specification
+ *  to an ANSI time_t using the specified time zone.
+ *  This is different from the standard mktime() function
+ *  in that we dont want the automatic adjustments for
+ *  local daylight savings time applied to the result.
+ *  This function expects well-formed input.
+ */
+static time_t make_time(struct tm *tm, int tzm)
+{
+  time_t tim;
+  static int days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
+  
+  /* check that year specification within range */
+
+  if (tm->tm_year < 70 || tm->tm_year > 138)
+    return((time_t) -1);
+
+  /* check that month specification within range */
+
+  if (tm->tm_mon < 0 || tm->tm_mon > 11)
+    return((time_t) -1);
+
+  /* check for upper bound of Jan 17, 2038 (to avoid possibility of
+     32-bit arithmetic overflow) */
+  
+  if (tm->tm_year == 138) {
+    if (tm->tm_mon > 0)
+      return((time_t) -1);
+    else if (tm->tm_mday > 17)
+      return((time_t) -1);
+  }
+
+  /*
+   *  calculate elapsed days since start of the epoch (midnight Jan
+   *  1st, 1970 UTC) 17 = number of leap years between 1900 and 1970
+   *  (number of leap days to subtract)
+   */
+
+  tim = (tm->tm_year - 70) * 365 + ((tm->tm_year - 1) / 4) - 17;
+
+  /* add number of days elapsed in the current year */
+    tim += days[tm->tm_mon];
+
+  /* check and adjust for leap years (the leap year check only valid
+     during the 32-bit era */
+
+  if ((tm->tm_year & 3) == 0 && tm->tm_mon > 1)
+    tim += 1;
+
+  /* elapsed days to current date */
+
+  tim += tm->tm_mday;
+
+
+  /* calculate elapsed hours since start of the epoch */
+
+  tim = tim * 24 + tm->tm_hour;
+
+  /* calculate elapsed minutes since start of the epoch */
+
+  tim = tim * 60 + tm->tm_min;
+  
+  /* adjust per time zone specification */
+  
+  tim -= tzm;
+  
+  /* calculate elapsed seconds since start of the epoch */
+  
+  tim = tim * 60 + tm->tm_sec;
+  
+  /* return number of seconds since start of the epoch */
+  
+  return(tim);
+}
+
+/**	@brief Constructor (deprecated).
+ *
+ * Convert seconds past UNIX epoch to a timetype.
+ *
+ * @deprecated This constructor is deprecated and shouldn't be used in
+ *   new software.  Use imcaltime_from_timet_with_zone(time_t, int,
+ *   imcaltimezone *) instead.  In the meantime, calls to this method
+ *   return a floating time, which can always be converted to a local
+ *   time with an appropriate call to imcaltime_convert_to_zone().
+ */
+
+struct icaltimetype 
+imcaltime_from_timet(const time_t tm, const int is_date, 
+                    const struct imcaltimeobj *cal)
+{
+#ifndef NO_WARN_DEPRECATED
+	icalerror_warn("imcaltime_from_timet() is DEPRECATED, use imcaltime_from_timet_with_zone() instead");
+#endif
+
+	return imcaltime_from_timet_with_zone(tm, is_date, 0, cal);
+}
+
+
+/**	@brief Constructor.
+ *
+ *	@param tm The time
+ *	@param is_date Boolean: 1 means we should treat tm as a DATE
+ *	@param zone The timezone tm is in, NULL means to treat tm as a
+ *		floating time
+ *
+ *	Return a new imcaltime instance, initialized to the given time
+ *	expressed as seconds past UNIX epoch, optionally using the given
+ *	timezone.
+ *
+ *	If the caller specifies the is_date param as TRUE, the returned
+ *	object is of DATE type, otherwise the input is meant to be of
+ *	DATE-TIME type.
+ *	If the zone is not specified (NULL zone param) the time is taken
+ *	to be floating, that is, valid in any timezone. Note that, in
+ *	addition to the uses specified in [RFC2445], this can be used
+ *	when doing simple math on couples of times.
+ *	If the zone is specified (UTC or otherwise), it's stored in the
+ *	object and it's used as the native timezone for this object.
+ *	This means that the caller can convert this time to a different
+ *	target timezone with no need to store the source timezone.
+ *
+ */
+struct icaltimetype 
+imcaltime_from_timet_with_zone(const time_t tm, const int is_date,
+                              const imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+    struct icaltimetype tt;
+    struct tm t;
+    imcaltimezone *utc_zone;
+    struct imcaldatetype dt;
+    utc_zone = imcaltimezone_get_utc_timezone ();
+
+    /* Convert the time_t to a struct tm in UTC time. We can trust gmtime
+       for this. */
+    t = *(gmtime(&tm));
+   
+    /* IF NOT GREGORIAN , ... */
+    if ( NULL != cal->convert_to_cal_type ){ 
+      dt = cal->convert_to_cal_type(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
+     
+      tt.year    = dt.year;
+      tt.month   = dt.month;
+      tt.day     = dt.day;
+    }
+    else{
+    	tt.year    = t.tm_year + 1900;  
+    	tt.month   = t.tm_mon + 1;
+   	tt.day     = t.tm_mday;
+    }
+    
+    tt.hour    = t.tm_hour;
+    tt.minute  = t.tm_min;
+    tt.second  = t.tm_sec;
+    tt.is_date = 0; 
+    tt.is_utc  = (zone == utc_zone) ? 1 : 0;
+    tt.zone    = NULL;
+    tt.is_daylight = 0;
+
+    /* Use our timezone functions to convert to the required timezone. */
+    imcaltimezone_convert_time (&tt, utc_zone, zone, cal);
+
+    tt.is_date = is_date; 
+
+    /* If it is a DATE value, make sure hour, minute & second are 0. */
+    if (is_date) { 
+	tt.hour   = 0;
+	tt.minute = 0;
+	tt.second = 0;
+    }
+
+    return tt;
+}
+
+/**	@brief Constructor.
+ * 
+ * Returns an icaltimetype representing the current time in the given timezone.
+ */
+struct icaltimetype imcaltime_current_time_with_zone(const imcaltimezone *zone,
+                                                    const struct imcaltimeobj *cal)
+{
+    return imcaltime_from_timet_with_zone (time (NULL), 0, zone, cal);
+}
+
+/**	@brief Constructor.
+ * 
+ * Returns an icaltimetype representing the current day.
+ */
+struct icaltimetype imcaltime_today(const struct imcaltimeobj *cal)
+{
+    return imcaltime_from_timet_with_zone (time (NULL), 1, NULL, cal);
+}
+
+/**	@brief	Return the time as seconds past the UNIX epoch
+ *
+ *	While this function is not currently deprecated, it probably won't do
+ *	what you expect, unless you know what you're doing. In particular, you
+ *	should only pass an imcaltime in UTC, since no conversion is done. Even
+ *	in that case, it's probably better to just use
+ *	imcaltime_as_timet_with_zone().
+ */
+time_t imcaltime_as_timet(const struct icaltimetype tt, const struct imcaltimeobj *cal)
+{
+    struct tm stm;
+    time_t t;
+    struct imcaldatetype dt;
+
+    /* If the time is the special null time, return 0. */
+    if (imcaltime_is_null_time(tt)) {
+	return 0;
+    }
+
+    /* Copy the icaltimetype to a struct tm. */
+    memset (&stm, 0, sizeof (struct tm));
+
+    if (imcaltime_is_date(tt)) {
+	stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
+    } else {
+	stm.tm_sec  = tt.second;
+	stm.tm_min  = tt.minute;
+	stm.tm_hour = tt.hour;
+    }
+
+    if( NULL != cal -> convert_to_gregorian ){
+      dt = cal->convert_to_gregorian(tt.year, tt.month, tt.day);
+
+      stm.tm_mday  = dt.day;
+      stm.tm_mon   = dt.month-1;
+      stm.tm_year  = dt.year-1900;
+    }
+    else{
+      stm.tm_mday  = tt.day;
+      stm.tm_mon   = tt.month-1;
+      stm.tm_year  = tt.year-1900;
+    }
+
+    stm.tm_isdst = -1;
+
+    t = make_time(&stm, 0);
+
+    return t;
+
+}
+
+
+time_t imcaltime_as_timet_with_zone(const struct icaltimetype tt,
+	const imcaltimezone *zone, const struct imcaltimeobj *cal)
+{
+    imcaltimezone *utc_zone;
+    struct tm stm;
+    time_t t;
+    char *old_tz;
+    struct icaltimetype local_tt;
+    struct imcaldatetype dt;
+    
+    utc_zone = imcaltimezone_get_utc_timezone ();
+
+    /* If the time is the special null time, return 0. */
+    if (imcaltime_is_null_time(tt)) {
+	return 0;
+    }
+
+    local_tt = tt;
+    
+    /* Clear the is_date flag, so we can convert the time. */
+    local_tt.is_date = 0;
+
+    /* Use our timezone functions to convert to UTC. */
+    imcaltimezone_convert_time (&local_tt, zone, utc_zone, cal);
+
+    /* Copy the icaltimetype to a struct tm. */
+    memset (&stm, 0, sizeof (struct tm));
+
+    if( NULL != cal->convert_to_gregorian ){
+      dt = cal->convert_to_gregorian(local_tt.year, local_tt.month, local_tt.day);
+
+      local_tt.year  = dt.year;
+      local_tt.month = dt.month;
+      local_tt.day   = dt.day;
+    }
+    
+    stm.tm_sec   = local_tt.second;
+    stm.tm_min   = local_tt.minute;
+    stm.tm_hour  = local_tt.hour;
+    stm.tm_mday  = local_tt.day;
+    stm.tm_mon   = local_tt.month-1;
+    stm.tm_year  = local_tt.year-1900;
+    stm.tm_isdst = -1;
+
+    /* Set TZ to UTC and use mktime to convert to a time_t. */
+    old_tz = set_tz ("UTC");
+    t = mktime (&stm);
+    unset_tz (old_tz);
+
+    return t;
+}
+
+/**
+ * Return a string represention of the time, in RFC2445 format. The
+ * string is owned by libical
+ */
+const char* imcaltime_as_ical_string(const struct icaltimetype tt)
+{
+    size_t size = 17;
+    char* buf = icalmemory_new_buffer(size);
+
+    if(tt.is_date){
+	snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
+    } else {
+	char* fmt;
+	if(tt.is_utc){
+	    fmt = "%04d%02d%02dT%02d%02d%02dZ";
+	} else {
+	    fmt = "%04d%02d%02dT%02d%02d%02d";
+	}
+	snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
+		 tt.hour,tt.minute,tt.second);
+    }
+    
+    icalmemory_add_tmp_buffer(buf);
+
+    return buf;
+
+}
+
+/**
+ *	Reset all of the time components to be in their normal ranges. For
+ *	instance, given a time with minutes=70, the minutes will be reduces
+ *	to 10, and the hour incremented. This allows the caller to do
+ *	arithmetic on times without worrying about overflow or
+ *	underflow.
+ *
+ *	Implementation note: we call imcaltime_adjust() with no adjustment.
+ */
+struct icaltimetype imcaltime_normalize(const struct icaltimetype tt, const struct imcaltimeobj *cal)
+{
+	struct icaltimetype ret = tt;
+	imcaltime_adjust(&ret, 0, 0, 0, 0, cal);
+	return ret;
+}
+
+
+
+/**	@brief Contructor.
+ * 
+ * Create a time from an ISO format string.
+ *
+ * @todo If the given string specifies a DATE-TIME not in UTC, there
+ *       is no way to know if this is a floating time or really refers to a
+ *       timezone. We should probably add a new constructor:
+ *       imcaltime_from_string_with_zone()
+ */
+struct icaltimetype imcaltime_from_string(const char* str)
+{
+    struct icaltimetype tt = imcaltime_null_time();
+    int size;
+
+    icalerror_check_arg_re(str!=0,"str",imcaltime_null_time());
+
+    size = strlen(str);
+    
+    if ((size == 15) || (size == 19)) { /* floating time with/without separators*/
+	tt.is_utc = 0;
+	tt.is_date = 0;
+    } else if ((size == 16) || (size == 20)) { /* UTC time, ends in 'Z'*/
+	if ((str[15] != 'Z') && (str[19] != 'Z'))
+	    goto FAIL;
+
+	tt.is_utc = 1;
+	tt.zone = imcaltimezone_get_utc_timezone();
+	tt.is_date = 0;
+    } else if ((size == 8) || (size == 10)) { /* A DATE */
+	tt.is_utc = 0;
+	tt.is_date = 1;
+    } else { /* error */
+	goto FAIL;
+    }
+
+    if (tt.is_date == 1){
+        if (size == 10) {
+            char dsep1, dsep2;    
+            if (sscanf(str,"%04d%c%02d%c%02d",&tt.year,&dsep1,&tt.month,&dsep2,&tt.day) < 5)
+                goto FAIL;
+            if ((dsep1 != '-') || (dsep2 != '-'))
+                goto FAIL;
+        } else if (sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day) < 3) {
+	    goto FAIL;
+        }    
+    } else {
+       if (size > 16 ) {
+         char dsep1, dsep2, tsep, tsep1, tsep2;      
+         if (sscanf(str,"%04d%c%02d%c%02d%c%02d%c%02d%c%02d",&tt.year,&dsep1,&tt.month,&dsep2,
+                &tt.day,&tsep,&tt.hour,&tsep1,&tt.minute,&tsep2,&tt.second) < 11)
+	    goto FAIL;
+
+	if((tsep != 'T') || (dsep1 != '-') || (dsep2 != '-') || (tsep1 != ':') || (tsep2 != ':'))
+	    goto FAIL;
+
+       } else {        
+	char tsep;
+	if (sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
+	       &tsep,&tt.hour,&tt.minute,&tt.second) < 7)
+	    goto FAIL;
+
+	if(tsep != 'T')
+	    goto FAIL;
+       }
+    }
+
+    return tt;    
+
+FAIL:
+    icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+    return imcaltime_null_time();
+}
+
+
+/* Returns whether the specified year is a leap year. Year is the normal year,
+   e.g. 2001. */
+int
+imcaltime_is_leap_year (const int year, const struct imcaltimeobj *cal)
+{
+
+/*    if (year <= 1752)
+        return (year % 4 == 0);
+    else
+        return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);*/
+	
+	return cal->is_leap_year(year);
+}
+
+int imcaltime_days_in_month(const int month, const int year,const struct imcaltimeobj *cal)
+{
+
+    assert(month > 0);
+    assert(month <= 12);
+
+    return cal->days_in_month(month, year);
+}
+
+/* 1-> Sunday, 7->Saturday */
+/* TODO commnet */
+
+int imcaltime_day_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal){
+/*	UTinstant jt;
+
+	memset(&jt,0,sizeof(UTinstant));
+
+	jt.year = t.year;
+	jt.month = t.month;
+	jt.day = t.day;
+	jt.i_hour = 0;
+	jt.i_minute = 0;
+	jt.i_second = 0;
+
+	juldat(&jt);
+	
+	return jt.weekday + 1;*/
+	return cal->day_of_week(t.year, t.month, t.day) + 1;
+}
+
+/** Day of the year that the first day of the week (Sunday) is on.
+ */
+int imcaltime_start_doy_week(const struct icaltimetype t, int fdow, 
+                            const struct imcaltimeobj *cal){
+	/*UTinstant jt;
+	int delta;
+
+	memset(&jt,0,sizeof(UTinstant));
+
+	jt.year = t.year;
+	jt.month = t.month;
+	jt.day = t.day;
+	jt.i_hour = 0;
+	jt.i_minute = 0;
+	jt.i_second = 0;
+
+	juldat(&jt);
+	caldat(&jt);
+
+	delta = jt.weekday - (fdow - 1);
+	if (delta < 0) delta += 7;
+	return jt.day_of_year - delta;*/
+	int delta;
+	
+	delta = imcaltime_day_of_week(t, cal) - (fdow + 1);
+	if (delta < 0) delta += 7;
+	return imcaltime_day_of_year(t, cal) - delta;
+}
+
+/** Day of the year that the first day of the week (Sunday) is on.
+ * 
+ *  @deprecated Doesn't take into account different week start days. 
+ */
+int imcaltime_start_doy_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal){
+
+#ifndef NO_WARN_DEPRECATED
+    icalerror_warn("imcaltime_start_doy_of_week() is DEPRECATED, use\
+	imcaltime_start_doy_week() instead");
+#endif
+
+    return imcaltime_start_doy_week(t, 1, cal);
+}
+
+/** 
+ * @todo Doesn't take into account the start day of the
+ * week. strftime assumes that weeks start on Monday. 
+ */
+int imcaltime_week_number(const struct icaltimetype ictt, const struct imcaltimeobj *cal)
+{
+	/*UTinstant jt;
+
+	memset(&jt,0,sizeof(UTinstant));
+
+	jt.year  = ictt.year;
+	jt.month = ictt.month;
+	jt.day   = ictt.day;
+	jt.i_hour   = 0;
+	jt.i_minute = 0;
+	jt.i_second = 0;
+
+	juldat(&jt, cal);
+	caldat(&jt, cal);
+		
+	return (jt.day_of_year - jt.weekday) / 7;*/
+	
+	return (( imcaltime_day_of_year(ictt, cal) - imcaltime_day_of_week(ictt, cal) ) / 7) + 1;
+}
+
+/**
+ *	Returns the day of the year, counting from 1 (Jan 1st).
+ *	FIXME handel UTC
+ */
+int imcaltime_day_of_year(const struct icaltimetype t, const struct imcaltimeobj *cal)
+{
+
+  return cal->day_of_year(t.year, t.month, t.day);
+}
+
+/**	@brief Contructor.
+ *
+ *	Create a new time, given a day of year and a year.
+ */
+/* Jan 1 is day #1, not 0 */
+struct icaltimetype imcaltime_from_day_of_year(const int _doy, const int _year,
+                                              const struct imcaltimeobj *cal)
+{
+    struct icaltimetype tt = imcaltime_null_date();
+    int is_leap;
+    int month;
+    int doy = _doy;
+    int year = _year;
+
+    is_leap = imcaltime_is_leap_year(year, cal);
+
+    /* Zero and neg numbers represent days  of the previous year */
+    if(doy <1){
+        year--;
+        is_leap = imcaltime_is_leap_year(year, cal);
+        doy    += cal->day_of_year(year, 12, 0);
+    } else if(doy > cal->day_of_year(year, 12, 0)){
+        /* Move on to the next year*/
+        is_leap = imcaltime_is_leap_year(year, cal);
+        doy    -= cal->day_of_year(year, 12, 0);
+        year++;
+    }
+
+    tt.year = year;
+
+    for (month = 11; month >= 0; month--) {
+      if (doy > cal->day_of_year(year, month, 0)) {
+	tt.month = month + 1;
+	tt.day   = doy - cal->day_of_year(year, month, 0);
+	break;
+      }
+    }
+
+    return tt;
+}
+
+/**	@brief Constructor.
+ *
+ *	Return a null time, which is guaranteed not to be equal to any other time.
+ */
+struct icaltimetype imcaltime_null_time(void)
+{
+    struct icaltimetype t;
+    memset(&t,0,sizeof(struct icaltimetype));
+
+    return t;
+}
+
+/**	@brief Constructor.
+ *
+ *	Return a null date.
+ */
+struct icaltimetype imcaltime_null_date(void)
+{
+    struct icaltimetype t;
+    memset(&t,0,sizeof(struct icaltimetype));
+
+    t.is_date = 1;
+
+    /*
+     * Init to -1 to match what icalyacc.y used to do.
+     * Does anything depend on this?
+     */
+    t.hour = -1;
+    t.minute = -1;
+    t.second = -1;
+
+    return t;
+}
+
+
+/**
+ *	Returns false if the time is clearly invalid, but is not null. This
+ *	is usually the result of creating a new time type buy not clearing
+ *	it, or setting one of the flags to an illegal value.
+ */
+int imcaltime_is_valid_time(const struct icaltimetype t){
+    if(t.is_utc > 1 || t.is_utc < 0 ||
+       t.year < 0 || t.year > 3000 ||
+       t.is_date > 1 || t.is_date < 0){
+	return 0;
+    } else {
+	return 1;
+    }
+
+}
+
+/**	@brief Returns true if time is a DATE
+ */
+int imcaltime_is_date(const struct icaltimetype t) {
+
+	return t.is_date;
+}
+
+/**	@brief Returns true if time is relative to UTC zone
+ *
+ *	@todo  We should only check the zone
+ */
+int imcaltime_is_utc(const struct icaltimetype t) {
+
+	return t.is_utc;
+}
+
+/**
+ *	Return true if the time is null.
+ */
+int imcaltime_is_null_time(const struct icaltimetype t)
+{
+    if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
+	return 1;
+    }
+
+    return 0;
+
+}
+
+/**
+ *	Return -1, 0, or 1 to indicate that a<b, a==b, or a>b.
+ * 	This calls imcaltime_compare function after converting them to the utc
+ * 	timezone.
+ */
+
+int imcaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in, 
+		const struct imcaltimeobj *cal) 
+{
+    int retval = 0;
+    struct icaltimetype a, b;
+
+    a = imcaltime_convert_to_zone(a_in, imcaltimezone_get_utc_timezone(), cal);
+    b = imcaltime_convert_to_zone(b_in, imcaltimezone_get_utc_timezone(), cal);
+
+    if (a.year > b.year)
+	retval = 1;
+    else if (a.year < b.year)
+	retval = -1;
+
+    else if (a.month > b.month)
+	retval = 1;
+    else if (a.month < b.month)
+	retval = -1;
+
+    else if (a.day > b.day)
+	retval = 1;
+    else if (a.day < b.day)
+	retval = -1;
+
+    /* if both are dates, we are done */
+    if (a.is_date && b.is_date)
+	return retval;
+
+    /* else, if we already found a difference, we are done */
+    else if (retval != 0)
+	return retval;
+
+    /* else, if only one is a date (and we already know the date part is equal),
+       then the other is greater */
+    else if (b.is_date)
+	retval = 1;
+    else if (a.is_date)
+	retval = -1;
+
+    else if (a.hour > b.hour)
+	retval = 1;
+    else if (a.hour < b.hour)
+	retval = -1;
+
+    else if (a.minute > b.minute)
+	retval = 1;
+    else if (a.minute < b.minute)
+	retval = -1;
+
+    else if (a.second > b.second)
+	retval = 1;
+    else if (a.second < b.second)
+	retval = -1;
+
+    return retval;
+}
+
+/**
+ *	like imcaltime_compare, but only use the date parts.
+ */
+
+int
+imcaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in, 
+		const struct imcaltimeobj *cal)
+{
+    int retval;
+    struct icaltimetype a, b;
+
+    a = imcaltime_convert_to_zone(a_in, imcaltimezone_get_utc_timezone(), cal);
+    b = imcaltime_convert_to_zone(b_in, imcaltimezone_get_utc_timezone(), cal);
+
+    if (a.year > b.year)
+	retval = 1;
+    else if (a.year < b.year)
+	retval = -1;
+
+    else if (a.month > b.month)
+	retval = 1;
+    else if (a.month < b.month)
+	retval = -1;
+
+    else if (a.day > b.day)
+	retval = 1;
+    else if (a.day < b.day)
+	retval = -1;
+
+    else
+	retval = 0;
+
+    return retval;
+}
+
+/* These are defined in icalduration.c:
+struct icaltimetype  imcaltime_add(struct icaltimetype t,
+				  struct icaldurationtype  d)
+struct icaldurationtype  imcaltime_subtract(struct icaltimetype t1,
+					   struct icaltimetype t2)
+*/
+
+
+
+/**	@brief Internal, shouldn't be part of the public API
+ *
+ *	Adds (or subtracts) a time from a icaltimetype.
+ *	NOTE: This function is exactly the same as imcaltimezone_adjust_change()
+ *	except for the type of the first parameter.
+ */
+void
+imcaltime_adjust(struct icaltimetype *tt, const int days, const int hours,
+	const int minutes, const int seconds, const struct imcaltimeobj *cal) {
+
+    int second, minute, hour, day;
+    int minutes_overflow, hours_overflow, days_overflow = 0, years_overflow;
+    int days_in_month;
+
+    /* If we are passed a date make sure to ignore hour minute and second */
+    if (tt->is_date)
+	goto IS_DATE;
+
+    /* Add on the seconds. */
+    second = tt->second + seconds;
+    tt->second = second % 60;
+    minutes_overflow = second / 60;
+    if (tt->second < 0) {
+	tt->second += 60;
+	minutes_overflow--;
+    }
+
+    /* Add on the minutes. */
+    minute = tt->minute + minutes + minutes_overflow;
+    tt->minute = minute % 60;
+    hours_overflow = minute / 60;
+    if (tt->minute < 0) {
+	tt->minute += 60;
+	hours_overflow--;
+    }
+
+    /* Add on the hours. */
+    hour = tt->hour + hours + hours_overflow;
+    tt->hour = hour % 24;
+    days_overflow = hour / 24;
+    if (tt->hour < 0) {
+	tt->hour += 24;
+	days_overflow--;
+    }
+
+IS_DATE:
+    /* Normalize the month. We do this before handling the day since we may
+       need to know what month it is to get the number of days in it.
+       Note that months are 1 to 12, so we have to be a bit careful. */
+    if (tt->month >= 13) {
+	years_overflow = (tt->month - 1) / 12;
+	tt->year += years_overflow;
+	tt->month -= years_overflow * 12;
+    } else if (tt->month <= 0) {
+	/* 0 to -11 is -1 year out, -12 to -23 is -2 years. */
+	years_overflow = (tt->month / 12) - 1;
+	tt->year += years_overflow;
+	tt->month -= years_overflow * 12;
+    }
+
+    /* Add on the days. */
+    day = tt->day + days + days_overflow;
+    if (day > 0) {
+	for (;;) {
+	    days_in_month = imcaltime_days_in_month (tt->month, tt->year, cal);
+	    if (day <= days_in_month)
+		break;
+
+	    tt->month++;
+	    if (tt->month >= 13) {
+		tt->year++;
+		tt->month = 1;
+	    }
+
+	    day -= days_in_month;
+	}
+    } else {
+	while (day <= 0) {
+	    if (tt->month == 1) {
+		tt->year--;
+		tt->month = 12;
+	    } else {
+		tt->month--;
+	    }
+
+	    day += imcaltime_days_in_month (tt->month, tt->year, cal);
+	}
+    }
+    tt->day = day;
+}
+
+/**	@brief Convert time to a given timezone
+ *
+ *	Convert a time from its native timezone to a given timezone.
+ *
+ *	If tt is a date, the returned time is an exact
+ *	copy of the input. If it's a floating time, the returned object
+ *	represents the same time translated to the given timezone.
+ *	Otherwise the time will be converted to the new
+ *	time zone, and its native timezone set to the right timezone.
+ */
+struct icaltimetype imcaltime_convert_to_zone(const struct icaltimetype tt,
+	imcaltimezone *zone,
+	const struct imcaltimeobj *cal) {
+
+	struct icaltimetype ret = tt;
+
+	/* If it's a date do nothing */
+	if (tt.is_date) {
+		return ret;
+	}
+
+	if (tt.zone == zone) {
+		return ret;
+	}
+
+	/* If it's a floating time we don't want to adjust the time */
+	if (tt.zone != NULL) {
+		imcaltimezone_convert_time(&ret, tt.zone, zone, cal);
+	}
+
+	ret.zone = zone;
+	if (zone == imcaltimezone_get_utc_timezone()) {
+		ret.is_utc = 1;
+	} else {
+		ret.is_utc = 0;
+	}
+
+	return ret;
+}
+
+const imcaltimezone *
+imcaltime_get_timezone(const struct icaltimetype t) {
+
+	return t.zone;
+}
+
+char *
+imcaltime_get_tzid(const struct icaltimetype t, const struct imcaltimeobj *cal) {
+
+	if (t.zone != NULL) {
+		return imcaltimezone_get_tzid(t.zone, cal);
+	} else {
+		return NULL;
+	}
+}
+
+/**	@brief Set the timezone
+ *
+ *	Force the imcaltime to be interpreted relative to another timezone.
+ *	If you need to do timezone conversion, applying offset adjustments,
+ *	then you should use imcaltime_convert_to_timezone instead.
+ */
+struct icaltimetype
+imcaltime_set_timezone(struct icaltimetype *t, const imcaltimezone *zone) {
+
+	/* If it's a date do nothing */
+	if (t->is_date) {
+		return *t;
+	}
+
+	if (t->zone == zone) {
+		return *t;
+	}
+
+	t->zone = zone;
+	if (zone == imcaltimezone_get_utc_timezone()) {
+		t->is_utc = 1;
+	} else {
+		t->is_utc = 0;
+	}
+
+	return *t;
+}
+
+
+/**
+ *  @brief builds an imcaltimespan given a start time, end time and busy value.
+ *
+ *  @param dtstart   The beginning time of the span, can be a date-time
+ *                   or just a date.
+ *  @param dtend     The end time of the span.
+ *  @param is_busy   A boolean value, 0/1.
+ *  @return          A span using the supplied values.
+ *
+ *  returned span contains times specified in UTC.
+ */
+
+imcaltime_span imcaltime_span_new(struct icaltimetype dtstart,
+				       struct icaltimetype dtend,
+				       int    is_busy,
+                                       const struct imcaltimeobj *cal)
+{
+  imcaltime_span span;
+
+  span.is_busy = is_busy;
+
+  span.start   = imcaltime_as_timet_with_zone(dtstart,
+					     imcaltimezone_get_utc_timezone(),
+	                                     cal);
+
+  if (imcaltime_is_null_time(dtend)) {
+    if (!imcaltime_is_date(dtstart)) {
+      /* If dtstart is a DATE-TIME and there is no DTEND nor DURATION
+	 it takes no time */
+      span.end = span.start;
+      return span;
+    } else {
+      dtend = dtstart;
+    }
+  }
+
+  span.end = imcaltime_as_timet_with_zone(dtend, imcaltimezone_get_utc_timezone(), cal);
+  
+  if (imcaltime_is_date(dtstart)) {
+    /* no time specified, go until the end of the day..*/
+    span.end += 60*60*24 - 1;
+  }
+  return span;
+}
+
+
+/** @brief Returns true if the two spans overlap
+ *
+ *  @param s1         1st span to test
+ *  @param s2         2nd span to test
+ *  @return           boolean value
+ *
+ *  The result is calculated by testing if the start time of s1 is contained
+ *  by the s2 span, or if the end time of s1 is contained by the s2 span.
+ *
+ *  Also returns true if the spans are equal.
+ *
+ *  Note, this will return false if the spans are adjacent.
+ */
+
+int imcaltime_span_overlaps(imcaltime_span *s1, 
+			   imcaltime_span *s2)
+{
+  /* s1->start in s2 */
+  if (s1->start > s2->start && s1->start < s2->end)
+    return 1;
+
+  /* s1->end in s2 */
+  if (s1->end > s2->start && s1->end < s2->end)
+    return 1;
+
+  /* s2->start in s1 */
+  if (s2->start > s1->start && s2->start < s1->end)
+    return 1;
+
+  /* s2->end in s1 */
+  if (s2->end > s1->start && s2->end < s1->end)
+    return 1;
+
+  if (s1->start == s2->start && s1->end == s2->end)
+    return 1;
+  
+  return 0;
+}
+
+/** @brief Returns true if the span is totally within the containing
+ *  span
+ *
+ *  @param s          The span to test for.
+ *  @param container  The span to test against.
+ *  @return           boolean value.
+ *
+ */
+
+int imcaltime_span_contains(imcaltime_span *s,
+			   imcaltime_span *container)
+{
+
+  if ((s->start >= container->start && s->start < container->end) &&
+      (s->end   <= container->end   && s->end   > container->start))
+    return 1;
+  
+  return 0;
+}
+
+/* Gets a pointer to imcaltimeobj, and then set callbacks in two order:
+ *
+ * 	#ifdef MODULE then :
+ * 		loads the 'cal_type'.so in currnet directory.
+ * 	#else
+ * 		calls corespondent functions internally:
+ * 			jalali_loader() OR hijri_loader OR gregorian_loader
+ *
+ * 	NOTE: Addition of some other calendar types, is possible,
+ * 	      by creating a object file containing whole callbacks in icaltimeobj structure.
+ * 	      for a instance of a such file see, "imcaltimeobj_jalali.c"
+ *
+ */
+int imcaltime_init(const char *cal_type, const struct imcaltimeobj *cal)
+{
+	char *module_path;
+	char  path[] = ".";
+	char *error;
+	void *handle;
+        void (*loader)(void *);
+
+#ifdef MODULES	
+	
+	if( strcmp(GREGORIAN ,cal_type) ){
+		/* allocates memory for name of the module */
+		module_path = (char *) icalmemory_new_buffer(strlen(path) + strlen(cal_type) + 5)
+		snprintf(module_path,strlen (module_path), "%s/%s.so", path, cal_type);
+
+		handle = dlopen (module_path, RTLD_LAZY);
+		if (!handle) {
+			fprintf (stderr, "%s\n", dlerror());
+			return (1);
+		}
+	
+		icalmemory_free_buffer((void*) module_path)	/* frees the allocated buffer */
+		dlerror();    /* Clear any existing error */
+
+		
+	        strncpy(cal  -> cal_type, cal_type, MAX_CAL_NAME); 
+
+		cal -> convert_to_cal_type  = dlsym(handle, "convert_to_cal_type" );
+		cal -> convert_to_gregorian = dlsym(handle, "convert_to_gregorian");
+		cal -> day_in_the_year      = dlsym(handle, "day_in_the_year");   
+		cal -> day_of_week          = dlsym(handle, "day_of_week");   
+		cal -> day_in_the_month     = dlsym(handle, "day_in_the_month");  
+		cal -> is_leap_year         = dlsym(handle, "is_leap_year");     
+				
+		if ((error = dlerror()) != NULL)  {
+			fprintf (stderr, "%s\n", error);
+			return (1);
+		}
+	}else{
+		strncpy(cal  -> cal_type, cal_type, MAX_CAL_NAME);
+		cal -> convert_to_cal_type  = NULL; 
+		cal -> convert_to_gregorian = NULL;
+		cal -> day_in_the_year      = gregorian_day_in_year;
+		cal -> day_in_the_month     = gregorian_day_in_month;
+		cal -> is_leap_year         = gregorian_is_leap_year;
+				
+	}
+											  
+#else
+	if( !strcmp(JALALI, cal_type) )
+		jalaly_loader(cal);
+	
+	else if( !strcmp(GREGORIAN, cal_type) )
+		gregorian_loader(cal);
+	
+	else if( !strcmp(HIJRI, cal_type) )
+		hijri_loader(cal);	
+
+#endif
+}
+
+void * icaltimetype_to_icaltimetype(struct icaltimetype *src, struct icaltimetype *dest){
+	return memcpy(dest, src, sizeof(struct icaltimetype));
+}
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltime.h evolution-data-server-wd/calendar/libical/src/libical/imcaltime.h
--- evolution-data-server/calendar/libical/src/libical/imcaltime.h	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltime.h	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,325 @@
+
+/* -*- Mode: C -*-
+  ======================================================================
+  FILE: imcaltime.c
+  CREATOR: eric 02 June 2000
+  
+  $Id: icaltime.c,v 1.34 2004/12/22 11:54:39 rodrigo Exp $
+  $Locker:  $
+  
+  MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+             Arash Yadegarnia		arash bluehome net  
+	     
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+  
+ ======================================================================*/
+/**	@file imcaltime.h
+ *	@brief struct icaltimetype is a pseudo-object that abstracts time
+ *	handling.
+ *
+ *	It can represent either a DATE or a DATE-TIME (floating, UTC or in a
+ *	given timezone), and it keeps track internally of its native timezone.
+ *
+ *	The typical usage is to call the correct constructor specifying the
+ *	desired timezone. If this is not known until a later time, the
+ *	correct behavior is to specify a NULL timezone and call
+ *	imcaltime_convert_to_zone() at a later time.
+ *
+ *	There are several ways to create a new icaltimetype:
+ *
+ *	- imcaltime_null_time()
+ *	- imcaltime_null_date()
+ *	- imcaltime_current_time_with_zone()
+ *	- imcaltime_today()
+ *	- imcaltime_from_timet_with_zone
+ * 	- imcaltime_from_string_with_zone
+ *	- imcaltime_from_day_of_year
+ *	- imcaltime_from_week_number
+ *
+ *	italtimetype objects can be converted to different formats:
+ *
+ *	- imcaltime_as_timet
+ *	- imcaltime_as_timet_with_zone
+ *	- imcaltime_as_ical_string
+ *
+ *	Accessor methods include:
+ *
+ *	- imcaltime_get_timezone
+ *	- imcaltime_get_tzid
+ *	- imcaltime_set_timezone
+ *	- imcaltime_day_of_year
+ *	- imcaltime_day_of_week
+ *	- imcaltime_start_doy_week
+ *	- imcaltime_week_number
+ *
+ *	Query methods include:
+ *
+ *	- imcaltime_is_null_time
+ *	- imcaltime_is_valid_time
+ *	- imcaltime_is_date
+ *	- imcaltime_is_utc
+ *	- imcaltime_is_floating
+ *
+ *	Modify, compare and utility methods include:
+ *
+ *	- imcaltime_add
+ *	- imcaltime_subtract
+ *      - imcaltime_compare_with_zone
+ *	- imcaltime_compare
+ *	- imcaltime_compare_date_only
+ *	- imcaltime_adjust
+ *	- imcaltime_normalize
+ *	- imcaltime_convert_to_zone
+ */
+
+#ifndef imcaltime_H
+#define imcaltime_H
+
+#include <time.h>
+#include "icaltime.h"
+
+/* An opaque struct representing a timezone. We declare this here to avoid
+   a circular dependancy. */
+#ifndef imcaltimeZONE_DEFINED
+#define imcaltimeZONE_DEFINED
+typedef struct _imcaltimezone		imcaltimezone;
+#endif
+
+
+#include <dlfcn.h>	/* for module handling routins */
+
+#ifndef JALALI
+	#define JALALI "jalali"	/* Iranian calendar system */
+#endif
+#ifndef HIJRI
+	#define HIJRI "hijri"	/* Mostly used in Arabic countries */
+#endif
+#ifndef GREGORIAN
+	#define GREGORIAN "gregorian"	/* The Julian calendar */
+
+/*  NOTICE :  we use gregorian routines (instead of libical internal routines)
+ *            temporarly. In near future we'll make it work with the main
+ *            functions. :D 
+ */
+
+#endif
+#define MAX_CAL_NAME 16	/* MAXIMUM LENGHT OF CALENDAR NAME WE USE */
+
+/** imcaltime_span is returned by icalcomponent_get_span() */
+struct imcaltime_span {
+	time_t start;   /**< in UTC */
+	time_t end;     /**< in UTC */
+	int is_busy;    /**< 1->busy time, 0-> free time */
+};
+
+typedef struct imcaltime_span imcaltime_span;
+
+/*
+ *	FIXME
+ *
+ *	is_utc is redundant, and might be considered a minor optimization.
+ *	It might be deprecated, so you should use imcaltime_is_utc() instead.
+ */
+
+/* Return type of our date convertor routines */
+struct imcaldatetype{
+	int year;
+	int month;
+	int day;
+};
+
+typedef struct imcaldatetype imcaldatetype;
+
+/* Main object used in imcaltime routines, to handle multi calendar systems. 
+ *
+ * cal_type:             Holds preferd calendar type. 
+ *
+ * convert_to_cal_type:  Gets year, month and day in gregorian,
+ *                       and convert them to preferd calendar
+ *                       system, according to cal_type.
+ *                      
+ * convert_to_gregorian: gets year, month and day (non-gregorian),
+ *                       and convert them to gregorian.
+ *
+ * days_in_month:        Returns days in a given month (handles leap years internally).
+ *
+ * day_of_year:          Returns day of the year, using given year, month and day,
+ *                       which handles leap years automatically.
+ *
+ * day_of_week:          Returns day of week.
+ *
+ * is_leap_year:         True, if we're on a leap year!
+ */
+ 
+struct imcaltimeobj{
+	const char cal_type[16];
+	
+	imcaldatetype (* convert_to_cal_type )(int year, int month, int day);
+	imcaldatetype (* convert_to_gregorian)(int year, int month, int day);
+	
+	int (* days_in_month)(const int year, const int month);
+	int (* day_of_year  )(const int year, const int month, const int day);
+	int (* day_of_week  )(const int year, const int month, const int day);
+	int (* is_leap_year )(const int year);
+};
+
+typedef struct imcaltimeobj imcaltimeobj;
+
+/** Gets a pointer to imcaltimeobj, and then set callbacks. */
+int imcaltime_init(const char *cal_type, const struct imcaltimeobj *cal);
+
+/** Return a null time, which indicates no time has been set. 
+    This time represent the beginning of the epoch */
+struct icaltimetype imcaltime_null_time(void);
+
+/** Return a null date */
+struct icaltimetype imcaltime_null_date(void);
+
+/** Returns the current time in the given timezone, as an icaltimetype. */
+struct icaltimetype imcaltime_current_time_with_zone(const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Returns the current day as an icaltimetype, with is_date set. */
+struct icaltimetype imcaltime_today(const struct imcaltimeobj *cal);
+
+/** Convert seconds past UNIX epoch to a timetype*/
+struct icaltimetype imcaltime_from_timet(const time_t v, const int is_date,const struct imcaltimeobj *cal);
+
+/** Convert seconds past UNIX epoch to a timetype, using timezones. */
+struct icaltimetype imcaltime_from_timet_with_zone(const time_t tm,
+	const int is_date, const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** create a time from an ISO format string */
+struct icaltimetype imcaltime_from_string(const char* str);
+
+/** create a time from an ISO format string */
+struct icaltimetype imcaltime_from_string_with_zone(const char* str,
+	const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Create a new time, given a day of year and a year. */
+struct icaltimetype imcaltime_from_day_of_year(const int doy,
+	const int year,const  struct imcaltimeobj *cal);
+
+/**	@brief Contructor (TODO).
+ * Create a new time from a weeknumber and a year. */
+struct icaltimetype imcaltime_from_week_number(const int week_number,
+	const int year);
+
+/** Return the time as seconds past the UNIX epoch */
+time_t imcaltime_as_timet(const struct icaltimetype, const struct imcaltimeobj *cal);
+
+/** Return the time as seconds past the UNIX epoch, using timezones. */
+time_t imcaltime_as_timet_with_zone(const struct icaltimetype tt,
+	const imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Return a string represention of the time, in RFC2445 format. The
+   string is owned by libical */
+const char* imcaltime_as_ical_string(const struct icaltimetype tt);
+
+/** @brief Return the timezone */
+const imcaltimezone *imcaltime_get_timezone(const struct icaltimetype t);
+
+/** @brief Return the tzid, or NULL for a floating time */
+char *imcaltime_get_tzid(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** @brief Set the timezone */
+struct icaltimetype imcaltime_set_timezone(struct icaltimetype *t,
+	const imcaltimezone *zone);
+
+/** Return the day of the year of the given time */
+int imcaltime_day_of_year(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return the day of the week of the given time. Sunday is 1 */
+int imcaltime_day_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return the day of the year for the Sunday of the week that the
+   given time is within. */
+int imcaltime_start_doy_of_week(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return the day of the year for the first day of the week that the
+   given time is within. */
+int imcaltime_start_doy_week(const struct icaltimetype t, int fdow, const struct imcaltimeobj *cal);
+
+/** Return the week number for the week the given time is within */
+int imcaltime_week_number(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** Return true of the time is null. */
+int imcaltime_is_null_time(const struct icaltimetype t);
+
+/** Returns false if the time is clearly invalid, but is not null. This
+   is usually the result of creating a new time type buy not clearing
+   it, or setting one of the flags to an illegal value. */
+int imcaltime_is_valid_time(const struct icaltimetype t);
+
+/** @brief Returns true if time is of DATE type, false if DATE-TIME */
+int imcaltime_is_date(const struct icaltimetype t);
+
+/** @brief Returns true if time is relative to UTC zone */
+int imcaltime_is_utc(const struct icaltimetype t);
+
+/** @brief Returns true if time is a floating time */
+int imcaltime_is_floating(const struct icaltimetype t);
+
+/** Return -1, 0, or 1 to indicate that a<b, a==b or a>b */
+int imcaltime_compare_with_zone(const struct icaltimetype a,
+        const struct icaltimetype b);
+
+/** Return -1, 0, or 1 to indicate that a<b, a==b or a>b */
+int imcaltime_compare(const struct icaltimetype a,
+	const struct icaltimetype b, const struct imcaltimeobj *cal);
+
+/** like imcaltime_compare, but only use the date parts. */
+int imcaltime_compare_date_only(const struct icaltimetype a,
+	const struct icaltimetype b, const struct imcaltimeobj *cal);
+
+/** Adds or subtracts a number of days, hours, minutes and seconds. */
+void  imcaltime_adjust(struct icaltimetype *tt, const int days,
+	const int hours, const int minutes, const int seconds, const struct imcaltimeobj *cal);
+
+/** Normalize the imcaltime, so that all fields are within the normal range. */
+struct icaltimetype imcaltime_normalize(const struct icaltimetype t, const struct imcaltimeobj *cal);
+
+/** convert tt, of timezone tzid, into a utc time. Does nothing if the
+   time is already UTC.  */
+struct icaltimetype imcaltime_convert_to_zone(const struct icaltimetype tt,
+	imcaltimezone *zone, const struct imcaltimeobj *cal);
+
+/** Return the number of days in the given month */
+int imcaltime_days_in_month(const int month, const int year, const struct imcaltimeobj *cal);
+
+
+/** @brief calculate an imcaltimespan given a start and end time. */
+struct imcaltime_span imcaltime_span_new(struct icaltimetype dtstart,
+				       struct icaltimetype dtend,
+				       int is_busy,
+				       const struct imcaltimeobj *cal);
+
+/** @brief Returns true if the two spans overlap **/
+int imcaltime_span_overlaps(imcaltime_span *s1, 
+			   imcaltime_span *s2);
+
+/** @brief Returns true if the span is totally within the containing
+ *  span 
+ */
+int imcaltime_span_contains(imcaltime_span *s,
+			   imcaltime_span *container);
+
+
+
+#endif /* !imcaltime_H */
+
+
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.c	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.c	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,190 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_gregorian.c
+ CREATOR: Bagher Fathi                  fathi yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2001, Damon Chaplin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+
+======================================================================*/
+
+#include "imcaltimeobj_gregorian.h"
+#include "imcaltime.h"
+#include "astime.h"
+#include "assert.h"
+
+
+struct imcaldatetype gregorianDate (long gregorianDaysNo) 
+{
+  
+	int gregorianMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+	struct imcaldatetype h;
+	int gregorianYear, gregorianMonth, gregorianDay;
+	int leap;
+	int i;
+
+	gregorianYear = 1600 + 400 *  (div ((int) gregorianDaysNo, (int) 146097).quot);
+	gregorianDaysNo = gregorianDaysNo % 146097;
+  
+	if (gregorianDaysNo >= 36524)
+	{
+		gregorianYear += 100 * (div ((int) gregorianDaysNo, (int) 36524).quot);
+		gregorianDaysNo = gregorianDaysNo % 36524;
+	}
+  
+	gregorianYear += 4 * (div ((int) gregorianDaysNo, (int) 1461).quot);
+	gregorianDaysNo %= 1461;
+	leap = 0;
+  
+	if (gregorianDaysNo <= 365 && gregorianDaysNo != 0)
+	{
+		leap = 1;
+	}
+  
+	else if (gregorianDaysNo == 0)
+	{
+		gregorianYear -= 1;
+		gregorianDaysNo = 365;
+	}
+  
+	else
+	{
+		gregorianDaysNo--;
+		gregorianYear += (div ((int) gregorianDaysNo, (int) 365).quot);
+		gregorianDaysNo = gregorianDaysNo % 365;
+      
+		if (gregorianDaysNo == 0)
+		{
+			gregorianYear -= 1;
+			gregorianDaysNo = 365;
+		}
+	}
+  
+
+	for (i = 0; gregorianDaysNo > (gregorianMonthDays[i] + (i == 1 && leap)); i++)
+		gregorianDaysNo -= gregorianMonthDays[i] + (i == 1 && leap);
+  
+	gregorianMonth = i + 1;
+	gregorianDay = gregorianDaysNo;
+	h.year = gregorianYear;
+	h.month = gregorianMonth;
+	h.day = gregorianDay;
+	gregorianYear -= 1600;
+  
+	return (h);
+}
+
+long
+gregorianDays (long gregorianYear, long gregorianMonth, long gregorianDay) 
+{
+  
+	int gregorianMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+	int gregorianDaysNo;
+	int i;
+  
+	gregorianYear  -= 1600;
+	gregorianMonth -= 1;
+	gregorianDaysNo = 365 * gregorianYear + (div ((int) (gregorianYear + 3), (int) 4).quot) - 
+	                  (div ((int) (gregorianYear + 99), (int) 100).quot) + (div ((int) (gregorianYear + 399), (int) 400).quot);
+  
+	for (i = 0; i < gregorianMonth; ++i)
+		gregorianDaysNo += gregorianMonthDays[i];
+  
+	if (gregorianMonth > 1 && ((gregorianYear % 4 == 0 && gregorianYear % 100 != 0) || (gregorianYear % 400 == 0)))
+		gregorianDaysNo++;
+  
+	gregorianDaysNo += gregorianDay;
+  
+	return gregorianDaysNo;
+}
+
+#ifdef MODULE
+int day_of_week (int year, int month, int day)
+#else
+int gregorian_day_of_week (int year, int month, int day)
+#endif
+{
+	UTinstant jt;
+
+	memset(&jt,0,sizeof(UTinstant));
+	jt.year = year;
+	jt.month = month;
+	jt.day = day;
+	jt.i_hour = 0;
+	jt.i_minute = 0;
+	jt.i_second = 0;
+	juldat(&jt);
+	
+	return jt.weekday + 1;
+}
+
+#ifdef MODULE
+int is_leap_year (int year)
+#else
+int gregorian_is_leap_year (int year)
+#endif
+{	
+	if (year <= 1752)
+		return (year % 4 == 0);
+	else
+		return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
+}
+
+#ifdef MODULE
+int days_in_month (int month, int year)
+#else
+int gregorian_days_in_month (int month, int year)
+#endif
+{
+	int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+	
+	assert (month > 0);
+	assert (month <= 12);
+
+	if ( year == 12 )
+		return days[month] = gregorian_is_leap_year(year);
+
+	return days[month];
+}
+
+#ifdef MODULE
+int day_of_year (int year, int month, int day)
+#else
+int gregorian_day_of_year (int year, int month, int day)
+#endif
+{
+	int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+	if ( month == 12 )
+		return days[month - 1] + gregorian_is_leap_year(year) + day;
+	
+	return days[month - 1] + day;
+}
+
+#ifndef MODULES
+
+void gregorian_loader(imcaltimeobj *cal){
+        strncpy((char*) cal -> cal_type, GREGORIAN, MAX_CAL_NAME);
+        cal -> convert_to_cal_type  = NULL;
+        cal -> convert_to_gregorian = NULL;
+	cal -> days_in_month        = &gregorian_days_in_month;
+	cal -> day_of_year          = &gregorian_day_of_year;
+	cal -> day_of_week          = &gregorian_day_of_week;	
+	cal -> is_leap_year         = &gregorian_is_leap_year;
+}
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_gregorian.h	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_gregorian.h	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_gregorian.h
+ CREATOR: Bagher Fathi                  fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef _imcaltime_OBJ_GREGORIAN_
+        #define _imcaltime_OBJ_GREGORIAN_
+
+#include <stdlib.h>
+
+struct imcaldatetype gregorianDate (long gregorianDaysNo);
+long int gregorianDays (long gregorianYear, long gregorianMonth, long gregorianDay);
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.c	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.c	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,312 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_hijri.c
+ CREATOR: Bagher Fathi                  fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#include "imcaltimeobj_hijri.h"
+#include "imcaltime.h"
+#include "assert.h"
+
+
+long
+hijriDays (int hijriYear, int hijriMonth, int hijriDay) 
+{
+	int hijriMonthDays[] = { 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29 };
+	long int hijriDaysNo;
+	struct  imcaldatetype h;
+	int i;
+  
+	hijriYear -=1009;
+	hijriMonth -=1;
+  
+	if (hijriYear >= 12)
+	{
+		hijriDaysNo = 4252;
+		hijriYear = hijriYear - 12;
+	}
+  
+	else
+		hijriDaysNo = 0;
+  
+	hijriDaysNo += 10631 * (div ((int) hijriYear, (int) 30).quot);
+	hijriYear = hijriYear % 30;
+  
+	for (i = 1; i <= hijriYear; i++)
+	{
+		if (i == 2  || i == 5  || i == 7  || i == 10 || i == 13 || i == 15 || 
+		    i == 18 || i == 21 || i == 24 || i == 26 || i == 29)
+			hijriDaysNo += 355;
+		else
+			hijriDaysNo += 354;
+	}
+  
+	for (i = 0; i < hijriMonth; i++)
+		hijriDaysNo += hijriMonthDays[i];
+  
+	hijriDaysNo += hijriDay;
+  
+	return hijriDaysNo;
+}
+
+/* FIXME Remove fopen */
+struct imcaldatetype hijriToGregorian (hijriYear, hijriMonth, hijriDay) 
+{
+  
+	FILE * fp;
+	struct imcaldatetype h;
+	struct imcaldatetype hd;
+       	struct imcaldatetype gd;
+	long int hijriDaysNo, gregorianDaysNo;
+  
+	hijriDaysNo = hijriDays (hijriYear, hijriMonth, hijriDay);
+  
+	if ((fp = fopen ("dateExep.txt", "r")) != NULL)
+	{
+		while (fscanf(fp, "%d %d %d %d %d %d ", &gd.year, &gd.month, &gd.day, 
+	                                        &hd.year, &hd.month, &hd.day) != EOF)
+		{
+			if (hijriDays (hijriYear, hijriMonth, hijriDay) >= 
+			               hijriDays (hd.year, hd.month, hd.day))
+			{
+	      
+				if (hijriDays (hijriYear, hijriMonth, hijriDay) ==
+				    hijriDays (hd.year, hd.month, hd.day))
+				
+				if (hijriMonth > hd.month)
+				{
+					h = gregorianDate (gregorianDays (gd.year, gd.month, gd.day) + 1);
+		    
+					return (h);
+				}
+	      
+				else if (hijriMonth == hd.month)
+		  		{
+					h = gregorianDate (gregorianDays (gd.year, gd.month, gd.day));
+		    
+					return (h);
+				}
+	      
+				if (hd.day == 30)
+					hijriDaysNo++;
+	      
+				if (hd.day == 1)
+					hijriDaysNo--;
+	    
+			}
+		}
+		fclose (fp);
+	}
+  
+	gregorianDaysNo = hijriDaysNo + 194;
+	h = gregorianDate (gregorianDaysNo);
+  
+	return (h);
+}
+
+struct imcaldatetype hijriDate (long hijriDaysNo) 
+{
+  
+	int hijriMonthDays[] = { 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29 };
+	int  hijriYear, hijriMonth, hijriDay;
+	struct imcaldatetype h;
+	int temp1, temp2,i;
+  
+	if (hijriDaysNo >= 4252)
+	{
+		temp2 = 12;
+		hijriDaysNo -= 4252;
+	}
+  
+	else
+		temp2 = 0;
+  
+
+	temp1 = (div ((int) hijriDaysNo, (int) 10631).quot);
+	hijriDaysNo = hijriDaysNo % 10631;
+
+	hijriYear = temp2 + 1009 + 30 * temp1;
+  
+	for (i = 1; i <= 30; i++)
+	{
+		if (i == 2  || i == 5  || i == 7  || i == 10 || i == 13 || i == 15 || 
+		    i == 18 || i == 21 || i == 24 || i == 26 || i == 29)
+		{
+			if (hijriDaysNo >= 355)
+			{
+				hijriDaysNo -= 355;
+				hijriYear += 1;
+			}
+	  
+			else
+				i = 30;
+		}
+      
+		else
+		{
+			if (hijriDaysNo >= 354)
+			{
+				hijriDaysNo -= 354;
+				hijriYear += 1;
+			}
+			
+			else
+				i = 30;
+		}
+	}
+  
+	if (hijriDaysNo == 0)
+	{
+		i = (hijriYear - 1) % 30;
+      
+		if (i == 2  || i == 5  || i == 7  || i == 10 || i == 13 || i == 15 || 
+		    i == 18 || i == 21 || i == 24 || i == 26 || i == 29)
+		{
+			hijriYear -= 1;
+			hijriDaysNo = 355;
+		}
+      
+		else
+		{
+			hijriYear -= 1;
+			hijriDaysNo = 354;
+		}
+	}
+  
+	for (i = 0; i < 11 && hijriDaysNo > hijriMonthDays[i]; i++)
+		hijriDaysNo -= hijriMonthDays[i];
+  
+	hijriMonth = i + 1;
+	hijriDay = hijriDaysNo;
+	h.year = hijriYear;
+	h.month = hijriMonth;
+	h.day = hijriDay;
+  
+	return (h);
+}
+
+
+
+struct imcaldatetype gregorianToHijri (int gregorianYear, int gregorianMonth, int gregorianDay) 
+{
+	FILE * fp;
+	long int gregorianDaysNo;
+	struct imcaldatetype h, hd, gd;
+  
+	gregorianDaysNo = gregorianDays (gregorianYear, gregorianMonth, gregorianDay);
+  
+	if ((fp = fopen ("dateExep.txt", "r")) != NULL)
+	{
+		while (fscanf(fp, "%d %d %d %d %d %d ", &gd.year, &gd.month, &gd.day, 
+		                                        &hd.year, &hd.month, &hd.day) != EOF)
+		{
+			if (gregorianDays (gregorianYear, gregorianMonth, gregorianDay) >= 
+			    gregorianDays (gd.year, gd.month, gd.day))
+			{
+				if (gregorianDays (gregorianYear, gregorianMonth, gregorianDay) ==
+				    gregorianDays (gd.year, gd.month, gd.day))
+				{
+					h.day = hd.day;
+					h.month = hd.month;
+					h.year = hd.year;
+		  
+					return (h);
+				}
+	      
+				if (hd.day == 30)
+					gregorianDaysNo--;
+	      
+				if (hd.day == 1)
+					gregorianDaysNo++;
+			}
+		}
+		fclose (fp);
+    
+	}
+  
+	gregorianDaysNo = gregorianDaysNo - 194;
+	h = hijriDate (gregorianDaysNo);
+  
+	return (h);
+}
+
+#ifdef MODULES
+int day_of_week (int year, int month, int day)
+#else
+int hijri_day_of_week (int year, int month, int day)
+#endif
+{
+	return gregorian_day_of_week(year, month, day);
+}
+
+#ifdef MODULES
+int is_leap_year (int year)
+#else
+int hijri_is_leap_year (int year)
+#endif
+{	
+	/* TODO Add support for non-gregorian calendar systems. */	
+	return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
+}
+
+#ifdef MODULES
+int days_in_month (int month, int year)
+#else
+int hijri_days_in_month (int month, int year)
+#endif
+{
+	int days[] = { 0, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29 };
+	
+	assert (month > 0);
+	assert (month <= 12);
+
+	if ( year == 12 )
+		return days[month] = hijri_is_leap_year(year);
+
+	return days[month];
+}
+
+#ifdef MODULES
+int day_of_year (int year, int month, int day)
+#else
+int hijri_day_of_year (int year, int month, int day)
+#endif
+{
+	int days[] = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 354};
+
+	if ( month == 12 )
+		return days[month - 1] + hijri_is_leap_year(year) + day;
+	
+	return days[month - 1] + day;
+}
+
+#ifndef MODULES
+
+void hijri_loader(imcaltimeobj *cal){
+        strncpy((char*) cal -> cal_type, HIJRI, MAX_CAL_NAME);
+        cal -> convert_to_cal_type  = &gregorianToHijri;
+        cal -> convert_to_gregorian = &hijriToGregorian;
+	cal -> days_in_month        = &hijri_days_in_month;
+	cal -> day_of_year          = &hijri_day_of_year;
+	cal -> day_of_week          = &hijri_day_of_week;	
+	cal -> is_leap_year         = &hijri_is_leap_year;
+}
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_hijri.h	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_hijri.h	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_jalali.c
+ CREATOR: Bagher Fathi                  fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef _imcaltime_OBJ_HIJRI_
+	#define _imcaltime_OBJ_HIJRI_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct imcaldatetype  hijriToGregorian (int hijriYear, int hijriMonth, int hijriDay);
+struct imcaldatetype  gregorianToHijri (int gregorianYear, int gregorianMonth, int gregorianDay);
+struct imcaldatetype  gregorianDate (long gregorianDaysNo);
+long int hijriDays (int hijriYear, int hijriMonth, int hijriDay);
+int jalali_day_of_week (int year, int month, int day);
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.c	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.c	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_jalali.c
+ CREATOR: Bagher Fathi                  fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#include "imcaltimeobj_jalali.h"
+#include "imcaltime.h"
+#include "assert.h"
+
+
+long int
+jalalyDays (int jalalyYear, int jalalyMonth, int jalalyDay) 
+{
+  
+	int jalalyMonthDays[] = { 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 };
+	long int jalalyDaysNo;
+	int i;
+
+  
+	jalalyYear -= 979;
+	jalalyMonth -= 1;
+  
+	if (jalalyYear >= 8){
+		jalalyDaysNo = 2922;
+		jalalyYear -= 8;
+	}
+  
+	else
+		jalalyDaysNo = 0;
+  
+	jalalyDaysNo += 46751 * (div ((int) jalalyYear, (int) 128).quot);
+	jalalyYear %=128;
+  
+	if (jalalyYear >= 29){
+		jalalyDaysNo += 10592;
+		jalalyYear -=29;
+	}
+  
+	jalalyDaysNo += 12053 * (div ((int) jalalyYear, (int) 33).quot);
+	jalalyYear %=33;
+  
+	if (jalalyYear >= 5)
+	{
+		jalalyDaysNo += 1826;
+		jalalyYear -=5;
+	}
+  
+	else if (jalalyYear == 4)
+	{
+		jalalyDaysNo += 1460;
+		jalalyYear -=4;
+	}
+  
+	jalalyDaysNo += 1461 * (div ((int) jalalyYear, (int) 4).quot);
+	jalalyYear %= 4;
+	jalalyDaysNo += 365 * jalalyYear;
+  
+	for (i = 0; i < jalalyMonth; i++)
+		jalalyDaysNo += jalalyMonthDays[i];
+  
+	jalalyDaysNo += jalalyDay;
+  
+	return jalalyDaysNo;
+}
+
+#ifdef MODULE
+struct imcaldatetype convert_to_Gregorian (jalalyYear, jalalyMonth, jalalyDay)
+#else 
+struct imcaldatetype jalaliToGregorian (jalalyYear, jalalyMonth, jalalyDay)
+#endif
+{
+	struct imcaldatetype h;
+	long int jalalyDaysNo, gregorianDaysNo;
+  
+	jalalyDaysNo = jalalyDays (jalalyYear, jalalyMonth, jalalyDay);
+	gregorianDaysNo = jalalyDaysNo + 80;
+	h = gregorianDate (gregorianDaysNo);
+  
+	return (h);
+}
+
+struct imcaldatetype jalalyDate (long jalalyDaysNo) 
+{
+  
+	int jalalyMonthDays[] = { 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29 };
+	struct imcaldatetype h;
+	int jalayYear, jalalyMonth, jalalyDay;
+	int temp1, temp2, temp3, temp4,i;
+  
+	if (jalalyDaysNo >= 2922)
+	{
+		temp3 = 8;
+		jalalyDaysNo -= 2922;
+	}
+  
+	else
+		temp3 = 0;
+  
+	temp1 = (div ((int) jalalyDaysNo, (int) 46751).quot);
+	jalalyDaysNo = jalalyDaysNo % 46751;
+
+	if (jalalyDaysNo >= 10592)
+	{
+		jalayYear = 29;
+		jalalyDaysNo -= 10592;
+	}
+  
+	else
+		jalayYear = 0;
+  
+	temp2 = (div ((int) jalalyDaysNo, (int) 12053).quot);
+	jalalyDaysNo = jalalyDaysNo % 12053;
+  
+	if (jalalyDaysNo >= 1826)
+	{
+		temp4 = 5;
+		jalalyDaysNo -= 1826;
+	}
+  
+	else
+		if (jalalyDaysNo > 1095)
+		{
+			temp4 = 3;
+			jalalyDaysNo -= 1095;
+		}
+	else
+		temp4 = 0;
+  
+	jalayYear += temp4 + temp3 + 979 + 128 * temp1 + 33 * temp2 + 4 * (div ((int) jalalyDaysNo, (int) 1461).quot);
+	jalalyDaysNo %= 1461;
+  
+	if (jalalyDaysNo == 0)
+	{
+		jalayYear -= 1;
+		jalalyDaysNo = 366;
+	}
+  
+	else
+	{
+		jalayYear += (div ((int) jalalyDaysNo, (int) 365).quot);
+		jalalyDaysNo = jalalyDaysNo % 365;
+      
+		if (jalalyDaysNo == 0)
+		{
+			jalayYear -= 1;
+			jalalyDaysNo = 365;
+		}
+	}
+  
+	for (i = 0; i < 11 && jalalyDaysNo > jalalyMonthDays[i]; ++i)
+		jalalyDaysNo -= jalalyMonthDays[i];
+  
+	jalalyMonth = i + 1;
+	jalalyDay = jalalyDaysNo;
+	h.day = jalalyDay;
+	h.month = jalalyMonth;
+	h.year = jalayYear;
+  
+	return (h);
+
+}
+
+#ifdef MODULES
+struct imcaldatetype gregorian_to_cal_type (gregorianYear, gregorianMonth, gregorianDay) 
+#else
+struct imcaldatetype gregorianToJalali (gregorianYear, gregorianMonth, gregorianDay) 
+#endif
+{
+	int gregorianDaysNo, jalalyDaysNo;
+	struct imcaldatetype h;
+  
+	gregorianDaysNo = gregorianDays (gregorianYear, gregorianMonth, gregorianDay);
+	jalalyDaysNo = gregorianDaysNo - 80;
+	h = jalalyDate (jalalyDaysNo);
+  
+	return (h);
+}
+
+#ifdef MODULES
+int day_of_week (int year, int month, int day)
+#else
+int jalali_day_of_week (int year, int month, int day)
+#endif
+{
+	struct imcaldatetype dt = jalaliToGregorian(year, month, day);
+	
+	return gregorian_day_of_week(dt.year, dt.month, dt.day);
+}
+
+#ifdef MODULES
+int is_leap_year (int year)
+#else
+int jalali_is_leap_year (int year)
+#endif
+{	
+	/* TODO Add support for non-gregorian calendar systems. */	
+	return ( (year % 4==0) && (year % 100 !=0 )) || (year % 400 == 0);
+}
+
+#ifdef MODULES
+int days_in_month (int month, int year)
+#else
+int jalali_days_in_month (int month, int year)
+#endif
+{
+	int days[13] = {0, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};
+	
+	assert (month > 0);
+	assert (month <= 12);
+
+	if ( year == 12 )
+		return days[month] = jalali_is_leap_year(year);
+
+	return days[month];
+}	
+
+#ifdef MODULES
+int day_of_year (int year, int month, int day)
+#else
+int jalali_day_of_year (int year, int month, int day)
+#endif
+{
+	int days[12] = {0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 365};
+
+	if ( month == 12 )
+		return days[month - 1] + jalali_is_leap_year(year) + day;
+	
+	return days[month - 1] + day;
+}
+
+#ifndef MODULES
+
+void jalaly_loader(imcaltimeobj *cal){
+        strncpy((char*) cal -> cal_type, JALALI, MAX_CAL_NAME);
+        cal -> convert_to_cal_type  = &gregorianToJalali;
+        cal -> convert_to_gregorian = &jalaliToGregorian;
+	cal -> days_in_month        = &jalali_days_in_month;
+	cal -> day_of_year          = &jalali_day_of_year;
+	cal -> day_of_week          = &jalali_day_of_week;	
+	cal -> is_leap_year         = &jalali_is_leap_year;
+}
+
+#endif
+
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimeobj_jalali.h	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimeobj_jalali.h	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimeobj_jalali.h
+ CREATOR: Bagher Fathi                  fathi_gohardani yahoo com
+
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2004, ARP Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef _imcaltime_OBJ_JALALI_
+	#define _imcaltime_OBJ_JALALI_
+
+#include <stdlib.h>
+
+struct imcaldatetype  jalalyDate (long jalalyDaysNo);
+struct imcaldatetype  jalaliToGregorian (int jalalyYear, int jalalyMonth, int jalalyDay);
+struct imcaldatetype  gregorianDate (long gregorianDaysNo);
+struct imcaldatetype  gregorianToJalali(int,int,int);
+long int jalalyDays (int jalalyYear, int jalalyMonth, int jalalyDay);
+int jalali_day_of_week (int year, int month, int day);
+
+#endif
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimezone.c evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.c
--- evolution-data-server/calendar/libical/src/libical/imcaltimezone.c	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.c	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,1716 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: icaltimezone.c
+ CREATOR: Damon Chaplin 15 March 2001
+
+ $Id: icaltimezone.c,v 1.22 2003/10/21 18:28:27 ettore Exp $
+ $Locker:  $
+
+  MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+             Arash Yadegarnia		arash bluehome net  
+	     
+ (C) COPYRIGHT 2001, Damon Chaplin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+
+======================================================================*/
+
+ /***********************************************************************
+  * @file imcaltimezone.c                                               *
+  *                                                                     *
+  * @This file prepares some timezone handling routines which supports  *
+  * multi calendar                                                      *
+  ***********************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "icalproperty.h"
+#include "icalarray.h"
+#include "icalerror.h"
+#include "icalparser.h"
+#include "imcaltimezone.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#define PACKAGE_DATA_DIR "/Projects/libical"
+#endif
+
+/** This is the toplevel directory where the timezone data is installed in. */
+#define ZONEINFO_DIRECTORY	PACKAGE_DATA_DIR "/zoneinfo"
+
+/** The prefix we use to uniquely identify TZIDs. */
+#define TZID_PREFIX		"/softwarestudio.org/"
+#define TZID_PREFIX_LEN		20
+
+/** This is the filename of the file containing the city names and
+    coordinates of all the builtin timezones. */
+#define ZONES_TAB_FILENAME	"zones.tab"
+
+/** This is the number of years of extra coverage we do when expanding
+    the timezone changes. */
+#define imcaltimeZONE_EXTRA_COVERAGE	5
+
+/** This is the maximum year we will expand to. time_t values only go up to
+    somewhere around 2037. */
+#define imcaltimeZONE_MAX_YEAR		2035
+
+struct _imcaltimezone {
+    char		*tzid;
+    /**< The unique ID of this timezone,
+       e.g. "/softwarestudio.org/Olson_20010601_1/Africa/Banjul".
+       This should only be used to identify a VTIMEZONE. It is not
+       meant to be displayed to the user in any form. */
+
+    char		*location;
+    /**< The location for the timezone, e.g. "Africa/Accra" for the
+       Olson database. We look for this in the "LOCATION" or
+       "X-LIC-LOCATION" properties of the VTIMEZONE component. It
+       isn't a standard property yet. This will be NULL if no location
+       is found in the VTIMEZONE. */
+
+    char		*tznames;
+    /**< This will be set to a combination of the TZNAME properties
+       from the last STANDARD and DAYLIGHT components in the
+       VTIMEZONE, e.g. "EST/EDT".  If they both use the same TZNAME,
+       or only one type of component is found, then only one TZNAME
+       will appear, e.g. "AZOT". If no TZNAME is found this will be
+       NULL. */
+
+    double		 latitude;
+    double		 longitude;
+    /**< The coordinates of the city, in degrees. */
+
+    icalcomponent	*component;
+    /**< The toplevel VTIMEZONE component loaded from the .ics file for this
+         timezone. If we need to regenerate the changes data we need this. */
+
+    imcaltimezone	*builtin_timezone;
+    /**< If this is not NULL it points to the builtin imcaltimezone
+       that the above TZID refers to. This imcaltimezone should be used
+       instead when accessing the timezone changes data, so that the
+       expanded timezone changes data is shared between calendar
+       components. */
+
+    int			 end_year;
+    /**< This is the last year for which we have expanded the data to.
+       If we need to calculate a date past this we need to expand the
+       timezone component data from scratch. */
+
+    icalarray		*changes;
+    /**< A dynamically-allocated array of time zone changes, sorted by the
+       time of the change in local time. So we can do fast binary-searches
+       to convert from local time to UTC. */
+};
+
+typedef struct _imcaltimezonechange	imcaltimezonechange;
+
+struct _imcaltimezonechange {
+    int		 utc_offset;
+    /**< The offset to add to UTC to get local time, in seconds. */
+
+    int		 prev_utc_offset;
+    /**< The offset to add to UTC, before this change, in seconds. */
+
+    int		 year;		/**< Actual year, e.g. 2001. */
+    int		 month;		/**< 1 (Jan) to 12 (Dec). */
+    int		 day;
+    int		 hour;
+    int		 minute;
+    int		 second;
+    /**< The time that the change came into effect, in UTC.
+       Note that the prev_utc_offset applies to this local time,
+       since we haven't changed to the new offset yet. */
+
+    int		 is_daylight;
+    /**< Whether this is STANDARD or DAYLIGHT time. */
+};
+
+
+/** An array of imcaltimezones for the builtin timezones. */
+static icalarray *builtin_timezones = NULL;
+
+/** This is the special UTC timezone, which isn't in builtin_timezones. */
+static imcaltimezone utc_timezone = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static char* zone_files_directory = NULL;
+
+static void  imcaltimezone_reset			(imcaltimezone   *zone);
+static char* imcaltimezone_get_location_from_vtimezone (icalcomponent *component);
+static char* imcaltimezone_get_tznames_from_vtimezone (icalcomponent *component, const struct imcaltimeobj *cal);
+static void  imcaltimezone_expand_changes	(imcaltimezone	*zone,
+						 int		 end_year,
+						 const struct imcaltimeobj *cal);
+static void  imcaltimezone_expand_vtimezone	(icalcomponent	*comp,
+						 int		 end_year,
+						 icalarray	*changes, const struct imcaltimeobj *cal);
+static int   imcaltimezone_compare_change_fn	(const void	*elem1,
+						 const void	*elem2);
+
+static int   imcaltimezone_find_nearby_change	(imcaltimezone	*zone,
+						 imcaltimezonechange *change);
+
+static void  imcaltimezone_adjust_change		(imcaltimezonechange *tt,
+						 int		 days,
+						 int		 hours,
+						 int		 minutes,
+						 int		 seconds,
+						 const struct imcaltimeobj *cal);
+
+static void  imcaltimezone_init			(imcaltimezone	*zone);
+
+/** Gets the TZID, LOCATION/X-LIC-LOCATION, and TZNAME properties from the
+   VTIMEZONE component and places them in the imcaltimezone. It returns 1 on
+   success, or 0 if the TZID can't be found. */
+static int   imcaltimezone_get_vtimezone_properties (imcaltimezone  *zone,
+						    icalcomponent *component,
+						    const struct imcaltimeobj *cal);
+
+
+static void  imcaltimezone_load_builtin_timezone	(imcaltimezone	*zone,
+                                                         const struct imcaltimeobj *cal);
+
+static void  imcaltimezone_ensure_coverage	(imcaltimezone	*zone,
+						 int		 end_year,
+						 const struct imcaltimeobj *cal);
+
+
+static void  imcaltimezone_init_builtin_timezones(void);
+
+static void  imcaltimezone_parse_zone_tab	(void);
+
+static char* imcaltimezone_load_get_line_fn	(char		*s,
+						 size_t		 size,
+						 void		*data);
+
+static void  format_utc_offset			(int		 utc_offset,
+						 char		*buffer);
+
+static char* get_zone_directory(void);
+
+
+/** Creates a new imcaltimezone. */
+imcaltimezone*
+imcaltimezone_new			(void)
+{
+    imcaltimezone *zone;
+
+    zone = (imcaltimezone*) malloc (sizeof (imcaltimezone));
+    if (!zone) {
+	icalerror_set_errno (ICAL_NEWFAILED_ERROR);
+	return NULL;
+    }
+
+    imcaltimezone_init (zone);
+
+    return zone;
+}
+
+
+/** Frees all memory used for the imcaltimezone. */
+void
+imcaltimezone_free			(imcaltimezone *zone,
+					 int	       free_struct)
+{
+    imcaltimezone_reset (zone);
+    if (free_struct)
+	free (zone);
+}
+
+
+/** Resets the imcaltimezone to the initial state, freeing most of the fields. */
+static void
+imcaltimezone_reset			(imcaltimezone *zone)
+{
+    if (zone->tzid)
+		free (zone->tzid);
+    if (zone->location)
+		free (zone->location);
+    if (zone->tznames)
+		free (zone->tznames);
+    if (zone->component)
+		icalcomponent_free (zone->component);
+    if (zone->changes)
+		icalarray_free (zone->changes);
+	
+    imcaltimezone_init (zone);
+}
+
+
+/** Initializes an imcaltimezone. */
+static void
+imcaltimezone_init			(imcaltimezone	*zone)
+{
+    zone->tzid = NULL;
+    zone->location = NULL;
+    zone->tznames = NULL;
+    zone->latitude = 0.0;
+    zone->longitude = 0.0;
+    zone->component = NULL;
+    zone->builtin_timezone = NULL;
+    zone->end_year = 0;
+    zone->changes = NULL;
+}
+
+
+/** Gets the TZID, LOCATION/X-LIC-LOCATION and TZNAME properties of
+   the VTIMEZONE component and stores them in the imcaltimezone.  It
+   returns 1 on success, or 0 if the TZID can't be found.  Note that
+   it expects the zone to be initialized or reset - it doesn't free
+   any old values. */
+static int
+imcaltimezone_get_vtimezone_properties	(imcaltimezone	*zone,
+					 icalcomponent	*component,
+					 const struct imcaltimeobj *cal)
+{
+    icalproperty *prop;
+    const char *tzid;
+ 
+    prop = icalcomponent_get_first_property (component, ICAL_TZID_PROPERTY);
+    if (!prop)
+	return 0;
+
+    /* A VTIMEZONE MUST have a TZID, or a lot of our code won't work. */
+    tzid = icalproperty_get_tzid (prop);
+    if (!tzid)
+	return 0;
+
+    zone->tzid = strdup (tzid);
+    zone->component = component;
+	if ( zone->location != 0 ) free ( zone->location );
+    zone->location = imcaltimezone_get_location_from_vtimezone (component)	;
+    zone->tznames = imcaltimezone_get_tznames_from_vtimezone (component, cal);
+
+    return 1;
+}
+
+/** Gets the LOCATION or X-LIC-LOCATION property from a VTIMEZONE. */
+static char*
+imcaltimezone_get_location_from_vtimezone (icalcomponent *component)
+{
+    icalproperty *prop;
+    const char *location;
+    const char *name;
+
+    prop = icalcomponent_get_first_property (component,
+					     ICAL_LOCATION_PROPERTY);
+    if (prop) {
+	location = icalproperty_get_location (prop);
+	if (location)
+	    return strdup (location);
+    }
+
+    prop = icalcomponent_get_first_property (component, ICAL_X_PROPERTY);
+    while (prop) {
+	name = icalproperty_get_x_name (prop);
+	if (name && !strcmp (name, "X-LIC-LOCATION")) {
+	    location = icalproperty_get_x (prop);
+	    if (location)
+		return strdup (location);
+	}
+	prop = icalcomponent_get_next_property (component,
+						ICAL_X_PROPERTY);
+    }
+
+    return NULL;
+}
+
+
+/** Gets the TZNAMEs used for the last STANDARD & DAYLIGHT components
+   in a VTIMEZONE. If both STANDARD and DAYLIGHT components use the
+   same TZNAME, it returns that. If they use different TZNAMEs, it
+   formats them like "EST/EDT". The returned string should be freed by
+   the caller. */
+static char*
+imcaltimezone_get_tznames_from_vtimezone (icalcomponent *component, const struct imcaltimeobj *cal)
+{
+    icalcomponent *comp;
+    icalcomponent_kind type;
+    icalproperty *prop;
+    struct icaltimetype dtstart;
+    struct icaldatetimeperiodtype rdate;
+    const char *current_tzname;
+    const char *standard_tzname = NULL, *daylight_tzname = NULL;
+    struct icaltimetype standard_max_date, daylight_max_date;
+    struct icaltimetype current_max_date;
+
+    standard_max_date = imcaltime_null_time();
+    daylight_max_date = imcaltime_null_time();
+
+    /* Step through the STANDARD & DAYLIGHT subcomponents. */
+    comp = icalcomponent_get_first_component (component, ICAL_ANY_COMPONENT);
+    while (comp) {
+	type = icalcomponent_isa (comp);
+	if (type == ICAL_XSTANDARD_COMPONENT
+	    || type == ICAL_XDAYLIGHT_COMPONENT) {
+	    current_max_date = imcaltime_null_time ();
+	    current_tzname = NULL;
+
+	    /* Step through the properties. We want to find the TZNAME, and
+	       the largest DTSTART or RDATE. */
+	    prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+	    while (prop) {
+		switch (icalproperty_isa (prop)) {
+		case ICAL_TZNAME_PROPERTY:
+		    current_tzname = icalproperty_get_tzname (prop);
+		    break;
+
+		case ICAL_DTSTART_PROPERTY:
+		    dtstart =  icalproperty_get_dtstart (prop);
+		    if (imcaltime_compare (dtstart, current_max_date, cal) > 0)
+			current_max_date = dtstart;
+
+		    break;
+
+		case ICAL_RDATE_PROPERTY:
+		    rdate = icalproperty_get_rdate (prop);
+		    if (imcaltime_compare (rdate.time, current_max_date, cal) > 0)
+			current_max_date = rdate.time;
+
+		    break;
+
+		default:
+		    break;
+		}
+
+		prop = icalcomponent_get_next_property (comp,
+							ICAL_ANY_PROPERTY);
+	    }
+
+	    if (current_tzname) {
+		if (type == ICAL_XSTANDARD_COMPONENT) {
+		    if (!standard_tzname
+			|| imcaltime_compare (current_max_date,
+					     standard_max_date, cal) > 0) {
+			standard_max_date = current_max_date;
+			standard_tzname = current_tzname;
+		    }
+		} else {
+		    if (!daylight_tzname
+			|| imcaltime_compare (current_max_date,
+					     daylight_max_date, cal) > 0) {
+			daylight_max_date = current_max_date;
+			daylight_tzname = current_tzname;
+		    }
+		}
+	    }
+	}
+
+        comp = icalcomponent_get_next_component (component,
+						 ICAL_ANY_COMPONENT);
+    }
+
+    /* Outlook (2000) places "Standard Time" and "Daylight Time" in the TZNAME
+       strings, which is totally useless. So we return NULL in that case. */
+    if (standard_tzname && !strcmp (standard_tzname, "Standard Time"))
+	return NULL;
+
+    /* If both standard and daylight TZNAMEs were found, if they are the same
+       we return just one, else we format them like "EST/EDT". */
+    if (standard_tzname && daylight_tzname) {
+	unsigned int standard_len, daylight_len;
+	char *tznames;
+
+	if (!strcmp (standard_tzname, daylight_tzname))
+	    return strdup (standard_tzname);
+
+	standard_len = strlen (standard_tzname);
+	daylight_len = strlen (daylight_tzname);
+	tznames = malloc (standard_len + daylight_len + 2);
+	strcpy (tznames, standard_tzname);
+	tznames[standard_len] = '/';
+	strcpy (tznames + standard_len + 1, daylight_tzname);
+	return tznames;
+    } else {
+	const char *tznames;
+
+	/* If either of the TZNAMEs was found just return that, else NULL. */
+	tznames = standard_tzname ? standard_tzname : daylight_tzname;
+	return tznames ? strdup (tznames) : NULL;
+    }
+}
+
+
+static void
+imcaltimezone_ensure_coverage		(imcaltimezone	*zone,
+					 int		 end_year,
+					 const struct imcaltimeobj *cal)
+{
+    /* When we expand timezone changes we always expand at least up to this
+       year, plus imcaltimeZONE_EXTRA_COVERAGE. */
+    static int imcaltimezone_minimum_expansion_year = -1;
+
+    int changes_end_year;
+
+    if (!zone->component)
+	imcaltimezone_load_builtin_timezone (zone, cal);
+
+    if (imcaltimezone_minimum_expansion_year == -1) {
+	struct icaltimetype today = imcaltime_today(cal);
+	imcaltimezone_minimum_expansion_year = today.year;
+    }
+
+    changes_end_year = end_year;
+    if (changes_end_year < imcaltimezone_minimum_expansion_year)
+	changes_end_year = imcaltimezone_minimum_expansion_year;
+
+    changes_end_year += imcaltimeZONE_EXTRA_COVERAGE;
+
+    if (changes_end_year > imcaltimeZONE_MAX_YEAR)
+	changes_end_year = imcaltimeZONE_MAX_YEAR;
+
+    if (!zone->changes || zone->end_year < end_year)
+	imcaltimezone_expand_changes (zone, changes_end_year, cal);
+}
+
+
+static void
+imcaltimezone_expand_changes		(imcaltimezone	*zone,
+					 int		 end_year,
+					 const struct imcaltimeobj *cal)
+{
+    icalarray *changes;
+    icalcomponent *comp;
+
+#if 0
+    printf ("\nExpanding changes for: %s to year: %i\n", zone->tzid, end_year);
+#endif
+
+    changes = icalarray_new (sizeof (imcaltimezonechange), 32);
+    if (!changes)
+	return;
+
+    /* Scan the STANDARD and DAYLIGHT subcomponents. */
+    comp = icalcomponent_get_first_component (zone->component,
+					      ICAL_ANY_COMPONENT);
+    while (comp) {
+	imcaltimezone_expand_vtimezone (comp, end_year, changes, cal);
+	comp = icalcomponent_get_next_component (zone->component,
+						 ICAL_ANY_COMPONENT);
+    }
+
+    /* Sort the changes. We may have duplicates but I don't think it will
+       matter. */
+    icalarray_sort (changes, imcaltimezone_compare_change_fn);
+
+    if (zone->changes)
+	icalarray_free (zone->changes);
+
+    zone->changes = changes;
+    zone->end_year = end_year;
+}
+
+
+static void
+imcaltimezone_expand_vtimezone		(icalcomponent	*comp,
+					 int		 end_year,
+					 icalarray	*changes,
+					 const struct imcaltimeobj *cal)
+{
+    imcaltimezonechange change;
+    icalproperty *prop;
+    struct icaltimetype dtstart, occ;
+    struct icalrecurrencetype rrule;
+    icalrecur_iterator* rrule_iterator;
+    struct icaldatetimeperiodtype rdate;
+    int found_dtstart = 0, found_tzoffsetto = 0, found_tzoffsetfrom = 0;
+    int has_recurrence = 0;
+
+    /* First we check if it is a STANDARD or DAYLIGHT component, and
+       just return if it isn't. */
+    if (icalcomponent_isa (comp) == ICAL_XSTANDARD_COMPONENT)
+	change.is_daylight = 0;
+    else if (icalcomponent_isa (comp) == ICAL_XDAYLIGHT_COMPONENT)
+	change.is_daylight = 1;
+    else 
+	return;
+
+    /* Step through each of the properties to find the DTSTART,
+       TZOFFSETFROM and TZOFFSETTO. We can't expand recurrences here
+       since we need these properties before we can do that. */
+    prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+    while (prop) {
+	switch (icalproperty_isa (prop)) {
+	case ICAL_DTSTART_PROPERTY:
+	    dtstart = icalproperty_get_dtstart (prop);
+	    found_dtstart = 1;
+	    break;
+	case ICAL_TZOFFSETTO_PROPERTY:
+	    change.utc_offset = icalproperty_get_tzoffsetto (prop);
+	    /*printf ("Found TZOFFSETTO: %i\n", change.utc_offset);*/
+	    found_tzoffsetto = 1;
+	    break;
+	case ICAL_TZOFFSETFROM_PROPERTY:
+	    change.prev_utc_offset = icalproperty_get_tzoffsetfrom (prop);
+	    /*printf ("Found TZOFFSETFROM: %i\n", change.prev_utc_offset);*/
+	    found_tzoffsetfrom = 1;
+	    break;
+	case ICAL_RDATE_PROPERTY:
+	case ICAL_RRULE_PROPERTY:
+	    has_recurrence = 1;
+	    break;
+	default:
+	    /* Just ignore any other properties. */
+	    break;
+	}
+
+	prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY);
+    }
+
+    /* If we didn't find a DTSTART, TZOFFSETTO and TZOFFSETFROM we have to
+       ignore the component. FIXME: Add an error property? */
+    if (!found_dtstart || !found_tzoffsetto || !found_tzoffsetfrom)
+	return;
+
+#if 0
+    printf ("\n Expanding component DTSTART (Y/M/D): %i/%i/%i %i:%02i:%02i\n",
+	    dtstart.year, dtstart.month, dtstart.day,
+	    dtstart.hour, dtstart.minute, dtstart.second);
+#endif
+
+    /* If the STANDARD/DAYLIGHT component has no recurrence data, we just add
+       a single change for the DTSTART. */
+    if (!has_recurrence) {
+	change.year   = dtstart.year;
+	change.month  = dtstart.month;
+	change.day    = dtstart.day;
+	change.hour   = dtstart.hour;
+	change.minute = dtstart.minute;
+	change.second = dtstart.second;
+
+	/* Convert to UTC. */
+	imcaltimezone_adjust_change (&change, 0, 0, 0, -change.prev_utc_offset, cal);
+
+#if 0
+	printf ("  Appending single DTSTART (Y/M/D): %i/%02i/%02i %i:%02i:%02i\n",
+		change.year, change.month, change.day,
+		change.hour, change.minute, change.second);
+#endif
+
+	/* Add the change to the array. */
+	icalarray_append (changes, &change);
+	return;
+    }
+
+    /* The component has recurrence data, so we expand that now. */
+    prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+    while (prop) {
+#if 0
+	printf ("Expanding property...\n");
+#endif
+	switch (icalproperty_isa (prop)) {
+	case ICAL_RDATE_PROPERTY:
+	    rdate = icalproperty_get_rdate (prop);
+	    change.year   = rdate.time.year;
+	    change.month  = rdate.time.month;
+	    change.day    = rdate.time.day;
+	    /* RDATEs with a DATE value inherit the time from
+	       the DTSTART. */
+	    if (imcaltime_is_date(rdate.time)) {
+		change.hour   = dtstart.hour;
+		change.minute = dtstart.minute;
+		change.second = dtstart.second;
+	    } else {
+		change.hour   = rdate.time.hour;
+		change.minute = rdate.time.minute;
+		change.second = rdate.time.second;
+
+		/* The spec was a bit vague about whether RDATEs were in local
+		   time or UTC so we support both to be safe. So if it is in
+		   UTC we have to add the UTC offset to get a local time. */
+		if (!imcaltime_is_utc(rdate.time))
+		    imcaltimezone_adjust_change (&change, 0, 0, 0,
+						-change.prev_utc_offset, cal);
+	    }
+
+#if 0
+	    printf ("  Appending RDATE element (Y/M/D): %i/%02i/%02i %i:%02i:%02i\n",
+		    change.year, change.month, change.day,
+		    change.hour, change.minute, change.second);
+#endif
+
+	    icalarray_append (changes, &change);
+	    break;
+	case ICAL_RRULE_PROPERTY:
+	    rrule = icalproperty_get_rrule (prop);
+
+	    /* If the rrule UNTIL value is set and is in UTC, we convert it to
+	       a local time, since the recurrence code has no way to convert
+	       it itself. */
+	    if (!imcaltime_is_null_time (rrule.until) && rrule.until.is_utc) {
+#if 0
+		printf ("  Found RRULE UNTIL in UTC.\n");
+#endif
+
+		/* To convert from UTC to a local time, we use the TZOFFSETFROM
+		   since that is the offset from UTC that will be in effect
+		   when each of the RRULE occurrences happens. */
+		imcaltime_adjust (&rrule.until, 0, 0, 0,
+				 change.prev_utc_offset, cal);
+		rrule.until.is_utc = 0;
+	    }
+
+	    rrule_iterator = icalrecur_iterator_new (rrule, dtstart);
+	    for (;;) {
+		occ = icalrecur_iterator_next (rrule_iterator);
+		if (occ.year > end_year || imcaltime_is_null_time (occ))
+		    break;
+
+		change.year   = occ.year;
+		change.month  = occ.month;
+		change.day    = occ.day;
+		change.hour   = occ.hour;
+		change.minute = occ.minute;
+		change.second = occ.second;
+
+#if 0
+		printf ("  Appending RRULE element (Y/M/D): %i/%02i/%02i %i:%02i:%02i\n",
+			change.year, change.month, change.day,
+			change.hour, change.minute, change.second);
+#endif
+
+		imcaltimezone_adjust_change (&change, 0, 0, 0,
+					    -change.prev_utc_offset, cal);
+
+		icalarray_append (changes, &change);
+	    }
+
+	    icalrecur_iterator_free (rrule_iterator);
+	    break;
+	default:
+	    break;
+	}
+
+	prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY);
+    }
+}
+
+
+/** A function to compare 2 imcaltimezonechange elements, used for qsort(). */
+static int
+imcaltimezone_compare_change_fn		(const void	*elem1,
+					 const void	*elem2)
+{
+    const imcaltimezonechange *change1, *change2;
+    int retval;
+
+    change1 = elem1;
+    change2 = elem2;
+
+    if (change1->year < change2->year)
+	retval = -1;
+    else if (change1->year > change2->year)
+	retval = 1;
+
+    else if (change1->month < change2->month)
+	retval = -1;
+    else if (change1->month > change2->month)
+	retval = 1;
+
+    else if (change1->day < change2->day)
+	retval = -1;
+    else if (change1->day > change2->day)
+	retval = 1;
+
+    else if (change1->hour < change2->hour)
+	retval = -1;
+    else if (change1->hour > change2->hour)
+	retval = 1;
+
+    else if (change1->minute < change2->minute)
+	retval = -1;
+    else if (change1->minute > change2->minute)
+	retval = 1;
+
+    else if (change1->second < change2->second)
+	retval = -1;
+    else if (change1->second > change2->second)
+	retval = 1;
+
+    else
+	retval = 0;
+
+    return retval;
+}
+
+
+
+void
+imcaltimezone_convert_time		(struct icaltimetype *tt,
+					 imcaltimezone	*from_zone,
+					 imcaltimezone	*to_zone,
+					 const struct imcaltimeobj *cal)
+{
+    int utc_offset, is_daylight;
+
+    /* If the time is a DATE value or both timezones are the same, or we are
+       converting a floating time, we don't need to do anything. */
+    if (imcaltime_is_date(*tt) || from_zone == to_zone || from_zone == NULL)
+	return;
+
+    /* Convert the time to UTC by getting the UTC offset and subtracting it. */
+    utc_offset = imcaltimezone_get_utc_offset (from_zone, tt, NULL, cal);
+    imcaltime_adjust (tt, 0, 0, 0, -utc_offset, cal);
+
+    /* Now we convert the time to the new timezone by getting the UTC offset
+       of our UTC time and adding it. */       
+    utc_offset = imcaltimezone_get_utc_offset_of_utc_time (to_zone, tt,
+							  &is_daylight, cal);
+    tt->is_daylight = is_daylight;
+    imcaltime_adjust (tt, 0, 0, 0, utc_offset, cal);
+}
+
+
+
+
+/** @deprecated This API wasn't updated when we changed icaltimetype to contain its own
+    timezone. Also, this takes a pointer instead of the struct. */
+/* Calculates the UTC offset of a given local time in the given
+   timezone.  It is the number of seconds to add to UTC to get local
+   time.  The is_daylight flag is set to 1 if the time is in
+   daylight-savings time. */
+int
+imcaltimezone_get_utc_offset		(imcaltimezone	*zone,
+					 struct icaltimetype	*tt,
+					 int		*is_daylight,
+					 const struct imcaltimeobj *cal)
+{
+    imcaltimezonechange *zone_change, *prev_zone_change, tt_change, tmp_change;
+    int change_num, step, utc_offset_change, cmp;
+    int change_num_to_use;
+    int want_daylight;
+
+    if (tt == NULL)
+	return 0;
+
+    if (is_daylight)
+	*is_daylight = 0;
+
+    /* For local times and UTC return 0. */
+    if (zone == NULL || zone == &utc_timezone)
+	return 0;
+
+    /* Use the builtin imcaltimezone if possible. */
+    if (zone->builtin_timezone)
+	zone = zone->builtin_timezone;
+
+    /* Make sure the changes array is expanded up to the given time. */
+    imcaltimezone_ensure_coverage (zone, tt->year, cal);
+
+    if (!zone->changes || zone->changes->num_elements == 0)
+	return 0;
+
+    /* Copy the time parts of the icaltimetype to an imcaltimezonechange so we
+       can use our comparison function on it. */
+    tt_change.year   = tt->year;
+    tt_change.month  = tt->month;
+    tt_change.day    = tt->day;
+    tt_change.hour   = tt->hour;
+    tt_change.minute = tt->minute;
+    tt_change.second = tt->second;
+
+    /* This should find a change close to the time, either the change before
+       it or the change after it. */
+    change_num = imcaltimezone_find_nearby_change (zone, &tt_change);
+
+    /* Sanity check. */
+    icalerror_assert (change_num >= 0,
+		      "Negative timezone change index");
+    icalerror_assert (change_num < zone->changes->num_elements,
+		      "Timezone change index out of bounds");
+
+    /* Now move backwards or forwards to find the timezone change that applies
+       to tt. It should only have to do 1 or 2 steps. */
+    zone_change = icalarray_element_at (zone->changes, change_num);
+    step = 1;
+    change_num_to_use = -1;
+    for (;;) {
+	/* Copy the change, so we can adjust it. */
+	tmp_change = *zone_change;
+
+	/* If the clock is going backward, check if it is in the region of time
+	   that is used twice. If it is, use the change with the daylight
+	   setting which matches tt, or use standard if we don't know. */
+	if (tmp_change.utc_offset < tmp_change.prev_utc_offset) {
+	    /* If the time change is at 2:00AM local time and the clock is
+	       going back to 1:00AM we adjust the change to 1:00AM. We may
+	       have the wrong change but we'll figure that out later. */
+	    imcaltimezone_adjust_change (&tmp_change, 0, 0, 0,
+					tmp_change.utc_offset, cal);
+	} else {
+	    imcaltimezone_adjust_change (&tmp_change, 0, 0, 0,
+					tmp_change.prev_utc_offset, cal);
+	}
+
+	cmp = imcaltimezone_compare_change_fn (&tt_change, &tmp_change);
+
+	/* If the given time is on or after this change, then this change may
+	   apply, but we continue as a later change may be the right one.
+	   If the given time is before this change, then if we have already
+	   found a change which applies we can use that, else we need to step
+	   backwards. */
+	if (cmp >= 0)
+	    change_num_to_use = change_num;
+	else
+	    step = -1;
+
+	/* If we are stepping backwards through the changes and we have found
+	   a change that applies, then we know this is the change to use so
+	   we exit the loop. */
+	if (step == -1 && change_num_to_use != -1)
+	    break;
+
+	change_num += step;
+
+	/* If we go past the start of the changes array, then we have no data
+	   for this time so we return a UTC offset of 0. */
+	if (change_num < 0)
+	    return 0;
+
+	if (change_num >= zone->changes->num_elements)
+	    break;
+
+	zone_change = icalarray_element_at (zone->changes, change_num);
+    }
+
+    /* If we didn't find a change to use, then we have a bug! */
+    icalerror_assert (change_num_to_use != -1,
+		      "No applicable timezone change found");
+
+    /* Now we just need to check if the time is in the overlapped region of
+       time when clocks go back. */
+    zone_change = icalarray_element_at (zone->changes, change_num_to_use);
+
+    utc_offset_change = zone_change->utc_offset - zone_change->prev_utc_offset;
+    if (utc_offset_change < 0 && change_num_to_use > 0) {
+	tmp_change = *zone_change;
+	imcaltimezone_adjust_change (&tmp_change, 0, 0, 0,
+				    tmp_change.prev_utc_offset, cal);
+
+	if (imcaltimezone_compare_change_fn (&tt_change, &tmp_change) < 0) {
+	    /* The time is in the overlapped region, so we may need to use
+	       either the current zone_change or the previous one. If the
+	       time has the is_daylight field set we use the matching change,
+	       else we use the change with standard time. */
+	    prev_zone_change = icalarray_element_at (zone->changes,
+						     change_num_to_use - 1);
+
+	    /* I was going to add an is_daylight flag to struct icaltimetype,
+	       but iCalendar doesn't let us distinguish between standard and
+	       daylight time anyway, so there's no point. So we just use the
+	       standard time instead. */
+	    want_daylight = (tt->is_daylight == 1) ? 1 : 0;
+
+#if 0
+	    if (zone_change->is_daylight == prev_zone_change->is_daylight)
+		printf (" **** Same is_daylight setting\n");
+#endif
+
+	    if (zone_change->is_daylight != want_daylight
+		&& prev_zone_change->is_daylight == want_daylight)
+		zone_change = prev_zone_change;
+	}
+    }
+
+    /* Now we know exactly which timezone change applies to the time, so
+       we can return the UTC offset and whether it is a daylight time. */
+    if (is_daylight)
+	*is_daylight = zone_change->is_daylight;
+    return zone_change->utc_offset;
+}
+
+
+/** @deprecated This API wasn't updated when we changed icaltimetype to contain its own
+    timezone. Also, this takes a pointer instead of the struct. */
+/** Calculates the UTC offset of a given UTC time in the given
+   timezone.  It is the number of seconds to add to UTC to get local
+   time.  The is_daylight flag is set to 1 if the time is in
+   daylight-savings time. */
+int
+imcaltimezone_get_utc_offset_of_utc_time	(imcaltimezone	*zone,
+					 struct icaltimetype	*tt,
+					 int		*is_daylight, 
+					 const struct imcaltimeobj *cal)
+{
+    imcaltimezonechange *zone_change, tt_change, tmp_change;
+    int change_num, step, change_num_to_use;
+
+    if (is_daylight)
+	*is_daylight = 0;
+
+    /* For local times and UTC return 0. */
+    if (zone == NULL || zone == &utc_timezone)
+	return 0;
+
+    /* Use the builtin imcaltimezone if possible. */
+    if (zone->builtin_timezone)
+	zone = zone->builtin_timezone;
+
+    /* Make sure the changes array is expanded up to the given time. */
+    imcaltimezone_ensure_coverage (zone, tt->year, cal);
+
+    if (!zone->changes || zone->changes->num_elements == 0)
+	return 0;
+
+    /* Copy the time parts of the icaltimetype to an imcaltimezonechange so we
+       can use our comparison function on it. */
+    tt_change.year   = tt->year;
+    tt_change.month  = tt->month;
+    tt_change.day    = tt->day;
+    tt_change.hour   = tt->hour;
+    tt_change.minute = tt->minute;
+    tt_change.second = tt->second;
+
+    /* This should find a change close to the time, either the change before
+       it or the change after it. */
+    change_num = imcaltimezone_find_nearby_change (zone, &tt_change);
+
+    /* Sanity check. */
+    icalerror_assert (change_num >= 0,
+		      "Negative timezone change index");
+    icalerror_assert (change_num < zone->changes->num_elements,
+		      "Timezone change index out of bounds");
+
+    /* Now move backwards or forwards to find the timezone change that applies
+       to tt. It should only have to do 1 or 2 steps. */
+    zone_change = icalarray_element_at (zone->changes, change_num);
+    step = 1;
+    change_num_to_use = -1;
+    for (;;) {
+	/* Copy the change and adjust it to UTC. */
+	tmp_change = *zone_change;
+
+	/* If the given time is on or after this change, then this change may
+	   apply, but we continue as a later change may be the right one.
+	   If the given time is before this change, then if we have already
+	   found a change which applies we can use that, else we need to step
+	   backwards. */
+	if (imcaltimezone_compare_change_fn (&tt_change, &tmp_change) >= 0)
+	    change_num_to_use = change_num;
+	else
+	    step = -1;
+
+	/* If we are stepping backwards through the changes and we have found
+	   a change that applies, then we know this is the change to use so
+	   we exit the loop. */
+	if (step == -1 && change_num_to_use != -1)
+	    break;
+
+	change_num += step;
+
+	/* If we go past the start of the changes array, then we have no data
+	   for this time so we return a UTC offset of 0. */
+	if (change_num < 0)
+	    return 0;
+
+	if (change_num >= zone->changes->num_elements)
+	    break;
+
+	zone_change = icalarray_element_at (zone->changes, change_num);
+    }
+
+    /* If we didn't find a change to use, then we have a bug! */
+    icalerror_assert (change_num_to_use != -1,
+		      "No applicable timezone change found");
+
+    /* Now we know exactly which timezone change applies to the time, so
+       we can return the UTC offset and whether it is a daylight time. */
+    zone_change = icalarray_element_at (zone->changes, change_num_to_use);
+    if (is_daylight)
+	*is_daylight = zone_change->is_daylight;
+
+    return zone_change->utc_offset;
+}
+
+
+/** Returns the index of a timezone change which is close to the time
+   given in change. */
+static int
+imcaltimezone_find_nearby_change		(imcaltimezone		*zone,
+					 imcaltimezonechange	*change)
+{
+    imcaltimezonechange *zone_change;
+    int lower, upper, middle, cmp;
+					 
+    /* Do a simple binary search. */
+    lower = middle = 0;
+    upper = zone->changes->num_elements;
+
+    while (lower < upper) {
+	middle = (lower + upper) / 2;
+	zone_change = icalarray_element_at (zone->changes, middle);
+	cmp = imcaltimezone_compare_change_fn (change, zone_change);
+	if (cmp == 0)
+	    break;
+	else if (cmp < 0)
+	    upper = middle;
+	else
+	    lower = middle + 1;
+    }
+
+    return middle;
+}
+
+
+
+
+/** Adds (or subtracts) a time from a imcaltimezonechange.  NOTE: This
+   function is exactly the same as imcaltime_adjust() except for the
+   type of the first parameter. */
+static void
+imcaltimezone_adjust_change		(imcaltimezonechange *tt,
+					 int		 days,
+					 int		 hours,
+					 int		 minutes,
+					 int		 seconds,
+					 const struct imcaltimeobj *cal)
+{
+    int second, minute, hour, day;
+    int minutes_overflow, hours_overflow, days_overflow;
+    int days_in_month;
+
+    /* Add on the seconds. */
+    second = tt->second + seconds;
+    tt->second = second % 60;
+    minutes_overflow = second / 60;
+    if (tt->second < 0) {
+	tt->second += 60;
+	minutes_overflow--;
+    }
+
+    /* Add on the minutes. */
+    minute = tt->minute + minutes + minutes_overflow;
+    tt->minute = minute % 60;
+    hours_overflow = minute / 60;
+    if (tt->minute < 0) {
+	tt->minute += 60;
+	hours_overflow--;
+    }
+
+    /* Add on the hours. */
+    hour = tt->hour + hours + hours_overflow;
+    tt->hour = hour % 24;
+    days_overflow = hour / 24;
+    if (tt->hour < 0) {
+	tt->hour += 24;
+	days_overflow--;
+    }
+
+    /* Add on the days. */
+    day = tt->day + days + days_overflow;
+    if (day > 0) {
+	for (;;) {
+	    days_in_month = imcaltime_days_in_month (tt->month, tt->year, cal);
+	    if (day <= days_in_month)
+		break;
+
+	    tt->month++;
+	    if (tt->month >= 13) {
+		tt->year++;
+		tt->month = 1;
+	    }
+
+	    day -= days_in_month;
+	}
+    } else {
+	while (day <= 0) {
+	    if (tt->month == 1) {
+		tt->year--;
+		tt->month = 12;
+	    } else {
+		tt->month--;
+	    }
+
+	    day += imcaltime_days_in_month (tt->month, tt->year, cal);
+	}
+    }
+    tt->day = day;
+}
+
+
+char*
+imcaltimezone_get_tzid			(imcaltimezone	*zone, const struct imcaltimeobj *cal)
+{
+    /* If this is a floating time, without a timezone, return NULL. */
+    if (!zone)
+	return NULL;
+
+    if (!zone->tzid)
+	imcaltimezone_load_builtin_timezone (zone, cal);
+
+    return zone->tzid;
+}
+
+
+char*
+imcaltimezone_get_location		(imcaltimezone	*zone)
+{
+    /* If this is a floating time, without a timezone, return NULL. */
+    if (!zone)
+	return NULL;
+
+    /* Note that for builtin timezones this comes from zones.tab so we don't
+       need to check the timezone is loaded here. */
+    return zone->location;
+}
+
+
+char*
+imcaltimezone_get_tznames		(imcaltimezone	*zone, const struct imcaltimeobj *cal)
+{
+    /* If this is a floating time, without a timezone, return NULL. */
+    if (!zone)
+	return NULL;
+
+    if (!zone->component)
+	imcaltimezone_load_builtin_timezone (zone, cal);
+
+    return zone->tznames;
+}
+
+
+/** Returns the latitude of a builtin timezone. */
+double
+imcaltimezone_get_latitude		(imcaltimezone	*zone)
+{
+    /* If this is a floating time, without a timezone, return 0. */
+    if (!zone)
+	return 0.0;
+
+    /* Note that for builtin timezones this comes from zones.tab so we don't
+       need to check the timezone is loaded here. */
+    return zone->latitude;
+}
+
+
+/** Returns the longitude of a builtin timezone. */
+double
+imcaltimezone_get_longitude		(imcaltimezone	*zone)
+{
+    /* If this is a floating time, without a timezone, return 0. */
+    if (!zone)
+	return 0.0;
+
+    /* Note that for builtin timezones this comes from zones.tab so we don't
+       need to check the timezone is loaded here. */
+    return zone->longitude;
+}
+
+
+/** Returns the VTIMEZONE component of a timezone. */
+icalcomponent*
+imcaltimezone_get_component		(imcaltimezone	*zone, const struct imcaltimeobj *cal)
+{
+    /* If this is a floating time, without a timezone, return NULL. */
+    if (!zone)
+	return NULL;
+
+    if (!zone->component)
+	imcaltimezone_load_builtin_timezone (zone, cal);
+
+    return zone->component;
+}
+
+
+/** Sets the VTIMEZONE component of an imcaltimezone, initializing the
+   tzid, location & tzname fields. It returns 1 on success or 0 on
+   failure, i.e.  no TZID was found. */
+int
+imcaltimezone_set_component		(imcaltimezone	*zone,
+					 icalcomponent	*comp,
+					 const struct imcaltimeobj *cal)
+{
+    imcaltimezone_reset (zone);
+    return imcaltimezone_get_vtimezone_properties (zone, comp, cal);
+}
+
+
+/* Returns the timezone name to display to the user. We prefer to use the
+   Olson city name, but fall back on the TZNAME, or finally the TZID. We don't
+   want to use "" as it may be wrongly interpreted as a floating time.
+   Do not free the returned string. */
+char*
+imcaltimezone_get_display_name		(imcaltimezone	*zone,
+                                         const struct imcaltimeobj *cal)
+{
+	char *display_name;
+
+	display_name = imcaltimezone_get_location (zone);
+	if (!display_name)
+		display_name = imcaltimezone_get_tznames (zone, cal);
+	if (!display_name) {
+		display_name = imcaltimezone_get_tzid (zone, cal);
+		/* Outlook will strip out X-LIC-LOCATION property and so all
+		   we get back in the iTIP replies is the TZID. So we see if
+		   this is one of our TZIDs and if so we jump to the city name
+		   at the end of it. */
+		if (display_name
+		    && !strncmp (display_name, TZID_PREFIX, TZID_PREFIX_LEN)) {
+		    /* Get the location, which is after the 3rd '/' char. */
+		    char *p;
+		    int num_slashes = 0;
+		    for (p = display_name; *p; p++) {
+			if (*p == '/') {
+			    num_slashes++;
+			    if (num_slashes == 3)
+				return p + 1;
+			}
+		    }
+		}
+	}
+
+	return display_name;
+}
+
+
+icalarray*
+imcaltimezone_array_new			(void)
+{
+    return icalarray_new (sizeof (imcaltimezone), 16);
+}
+
+
+void
+imcaltimezone_array_append_from_vtimezone (icalarray	*timezones,
+					  icalcomponent	*child, const struct imcaltimeobj *cal)
+{
+    imcaltimezone zone;
+
+    imcaltimezone_init (&zone);
+    if (imcaltimezone_get_vtimezone_properties (&zone, child, cal))
+	icalarray_append (timezones, &zone);
+}
+
+
+void
+imcaltimezone_array_free			(icalarray	*timezones)
+{
+    imcaltimezone *zone;
+    int i;
+
+	if ( timezones )
+	{
+		for (i = 0; i < timezones->num_elements; i++) {
+		zone = icalarray_element_at (timezones, i);
+		imcaltimezone_free (zone, 0);
+		}
+
+		icalarray_free (timezones);
+	}
+}
+
+
+/*
+ * BUILTIN TIMEZONE HANDLING
+ */
+
+
+/** Returns an icalarray of imcaltimezone structs, one for each builtin
+   timezone.  This will load and parse the zones.tab file to get the
+   timezone names and their coordinates. It will not load the
+   VTIMEZONE data for any timezones. */
+icalarray*
+imcaltimezone_get_builtin_timezones	(void)
+{
+    if (!builtin_timezones)
+	imcaltimezone_init_builtin_timezones ();
+
+    return builtin_timezones;
+}
+
+/** Release builtin timezone memory */
+void
+imcaltimezone_free_builtin_timezones(void)
+{
+	imcaltimezone_array_free(builtin_timezones);
+}
+
+
+/** Returns a single builtin timezone, given its Olson city name. */
+imcaltimezone*
+imcaltimezone_get_builtin_timezone	(const char *location)
+{
+    imcaltimezone *zone;
+    int lower, upper, middle, cmp;
+    char *zone_location;
+
+    if (!location || !location[0])
+	return NULL;
+
+    if (!strcmp (location, "UTC"))
+	return &utc_timezone;
+
+    if (!builtin_timezones)
+	imcaltimezone_init_builtin_timezones ();
+
+    /* Do a simple binary search. */
+    lower = middle = 0;
+    upper = builtin_timezones->num_elements;
+
+    while (lower < upper) {
+	middle = (lower + upper) / 2;
+	zone = icalarray_element_at (builtin_timezones, middle);
+	zone_location = imcaltimezone_get_location (zone);
+	cmp = strcmp (location, zone_location);
+	if (cmp == 0)
+	    return zone;
+	else if (cmp < 0)
+	    upper = middle;
+	else
+	    lower = middle + 1;
+    }
+
+    return NULL;
+}
+
+
+/** Returns a single builtin timezone, given its TZID. */
+imcaltimezone*
+imcaltimezone_get_builtin_timezone_from_tzid (const char *tzid, const struct imcaltimeobj *cal)
+{
+    int num_slashes = 0;
+    const char *p, *zone_tzid;
+    imcaltimezone *zone;
+
+    if (!tzid || !tzid[0])
+	return NULL;
+
+    /* Check that the TZID starts with our unique prefix. */
+    if (strncmp (tzid, TZID_PREFIX, TZID_PREFIX_LEN))
+	return NULL;
+
+    /* Get the location, which is after the 3rd '/' character. */
+    p = tzid;
+    for (p = tzid; *p; p++) {
+	if (*p == '/') {
+	    num_slashes++;
+	    if (num_slashes == 3)
+		break;
+	}
+    }
+
+    if (num_slashes != 3)
+	return NULL;
+
+    p++;
+
+    /* Now we can use the function to get the builtin timezone from the
+       location string. */
+    zone = imcaltimezone_get_builtin_timezone (p);
+    if (!zone)
+	return NULL;
+
+    /* Check that the builtin TZID matches exactly. We don't want to return
+       a different version of the VTIMEZONE. */
+    zone_tzid = imcaltimezone_get_tzid (zone, cal);
+    if (!strcmp (zone_tzid, tzid))
+	return zone;
+    else
+	return NULL;
+}
+
+
+/** Returns the special UTC timezone. */
+imcaltimezone*
+imcaltimezone_get_utc_timezone		(void)
+{
+    if (!builtin_timezones)
+	imcaltimezone_init_builtin_timezones ();
+
+    return &utc_timezone;
+}
+
+
+
+/** This initializes the builtin timezone data, i.e. the
+   builtin_timezones array and the special UTC timezone. It should be
+   called before any code that uses the timezone functions. */
+static void
+imcaltimezone_init_builtin_timezones	(void)
+{
+    /* Initialize the special UTC timezone. */
+    utc_timezone.tzid = "UTC";
+
+    imcaltimezone_parse_zone_tab ();
+}
+
+
+/** This parses the zones.tab file containing the names and locations
+   of the builtin timezones. It creates the builtin_timezones array
+   which is an icalarray of imcaltimezone structs. It only fills in the
+   location, latitude and longtude fields; the rest are left
+   blank. The VTIMEZONE component is loaded later if it is needed. The
+   timezones in the zones.tab file are sorted by their name, which is
+   useful for binary searches. */
+static void
+imcaltimezone_parse_zone_tab		(void)
+{
+    char *filename;
+    FILE *fp;
+    char buf[1024];  /* Used to store each line of zones.tab as it is read. */
+    char location[1024]; /* Stores the city name when parsing buf. */
+    unsigned int filename_len;
+    int latitude_degrees, latitude_minutes, latitude_seconds;
+    int longitude_degrees, longitude_minutes, longitude_seconds;
+    imcaltimezone zone;
+
+    icalerror_assert (builtin_timezones == NULL,
+		      "Parsing zones.tab file multiple times");
+
+    builtin_timezones = icalarray_new (sizeof (imcaltimezone), 32);
+
+    filename_len = strlen (get_zone_directory()) + strlen (ZONES_TAB_FILENAME)
+	+ 2;
+
+    filename = (char*) malloc (filename_len);
+    if (!filename) {
+	icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+	return;
+    }
+
+    snprintf (filename, filename_len, "%s/%s", get_zone_directory(),
+	      ZONES_TAB_FILENAME);
+
+    fp = fopen (filename, "r");
+    free (filename);
+    if (!fp) {
+	icalerror_set_errno(ICAL_FILE_ERROR);
+	return;
+    }
+
+    while (fgets (buf, sizeof(buf), fp)) {
+	if (*buf == '#') continue;
+
+	/* The format of each line is: "latitude longitude location". */
+	if (sscanf (buf, "%4d%2d%2d %4d%2d%2d %s",
+		    &latitude_degrees, &latitude_minutes,
+		    &latitude_seconds,
+		    &longitude_degrees, &longitude_minutes,
+		    &longitude_seconds,
+		    location) != 7) {
+	    fprintf (stderr, "Invalid timezone description line: %s\n", buf);
+	    continue;
+	}
+
+	imcaltimezone_init (&zone);
+	zone.location = strdup (location);
+
+	if (latitude_degrees >= 0)
+	    zone.latitude = (double) latitude_degrees
+		+ (double) latitude_minutes / 60
+		+ (double) latitude_seconds / 3600;
+	else
+	    zone.latitude = (double) latitude_degrees
+		- (double) latitude_minutes / 60
+		- (double) latitude_seconds / 3600;
+
+	if (longitude_degrees >= 0)
+	    zone.longitude = (double) longitude_degrees
+		+ (double) longitude_minutes / 60
+		+ (double) longitude_seconds / 3600;
+	else
+	    zone.longitude = (double) longitude_degrees
+		- (double) longitude_minutes / 60
+		- (double) longitude_seconds / 3600;
+
+	icalarray_append (builtin_timezones, &zone);
+
+#if 0
+	printf ("Found zone: %s %f %f\n",
+		location, zone.latitude, zone.longitude);
+#endif
+    }
+
+    fclose (fp);
+}
+
+
+/** Loads the builtin VTIMEZONE data for the given timezone. */
+static void
+imcaltimezone_load_builtin_timezone	(imcaltimezone	*zone, const struct imcaltimeobj *cal)
+{
+    char *filename;
+    unsigned int filename_len;
+    FILE *fp;
+    icalparser *parser;
+    icalcomponent *comp, *subcomp;
+
+	    /* If the location isn't set, it isn't a builtin timezone. */
+    if (!zone->location || !zone->location[0])
+	return;
+
+    filename_len = strlen (get_zone_directory()) + strlen (zone->location) + 6;
+
+    filename = (char*) malloc (filename_len);
+    if (!filename) {
+	icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+	return;
+    }
+
+    snprintf (filename, filename_len, "%s/%s.ics", get_zone_directory(),
+	      zone->location);
+
+    fp = fopen (filename, "r");
+    free (filename);
+    if (!fp) {
+	icalerror_set_errno(ICAL_FILE_ERROR);
+	return;
+    }
+
+	
+	/* ##### B.# Sun, 11 Nov 2001 04:04:29 +1100 
+	this is where the MALFORMEDDATA error is being set, after the call to 'icalparser_parse'
+	fprintf(stderr, "** WARNING ** %s: %d %s\n", __FILE__, __LINE__, icalerror_strerror(icalerrno));
+	*/
+
+    parser = icalparser_new ();
+	icalparser_set_gen_data (parser, fp);
+	comp = icalparser_parse (parser, imcaltimezone_load_get_line_fn);
+    icalparser_free (parser);
+	fclose (fp);
+
+	
+	
+    /* Find the VTIMEZONE component inside the VCALENDAR. There should be 1. */
+    subcomp = icalcomponent_get_first_component (comp,
+						 ICAL_VTIMEZONE_COMPONENT);
+    if (!subcomp) {
+	icalerror_set_errno(ICAL_PARSE_ERROR);
+	return;
+    }
+
+    imcaltimezone_get_vtimezone_properties (zone, subcomp, cal);
+
+	icalcomponent_remove_component(comp,subcomp);
+
+	icalcomponent_free(comp);
+
+}
+
+
+/** Callback used from icalparser_parse() */
+static char *
+imcaltimezone_load_get_line_fn		(char		*s,
+					 size_t		 size,
+					 void		*data)
+{
+    return fgets (s, size, (FILE*) data);
+}
+
+
+
+
+/*
+ * DEBUGGING
+ */
+
+/**
+ * This outputs a list of timezone changes for the given timezone to the
+ * given file, up to the maximum year given. We compare this output with the
+ * output from 'vzic --dump-changes' to make sure that we are consistent.
+ * (vzic is the Olson timezone database to VTIMEZONE converter.)
+ * 
+ * The output format is:
+ *
+ *	Zone-Name [tab] Date [tab] Time [tab] UTC-Offset
+ *
+ * The Date and Time fields specify the time change in UTC.
+ *
+ * The UTC Offset is for local (wall-clock) time. It is the amount of time
+ * to add to UTC to get local time.
+ */
+int
+imcaltimezone_dump_changes		(imcaltimezone	*zone,
+					 int		 max_year,
+					 FILE		*fp,
+					 const struct imcaltimeobj *cal)
+{
+    static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+			      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+    imcaltimezonechange *zone_change;
+    int change_num;
+    char buffer[8];
+
+    /* Make sure the changes array is expanded up to the given time. */
+    imcaltimezone_ensure_coverage (zone, max_year, cal);
+
+#if 0
+    printf ("Num changes: %i\n", zone->changes->num_elements);
+#endif
+
+    change_num = 0;
+    for (change_num = 0; change_num < zone->changes->num_elements; change_num++) {
+	zone_change = icalarray_element_at (zone->changes, change_num);
+
+	if (zone_change->year > max_year)
+	    break;
+
+	fprintf (fp, "%s\t%2i %s %04i\t%2i:%02i:%02i",
+		zone->location,
+		zone_change->day, months[zone_change->month - 1],
+		zone_change->year,
+		zone_change->hour, zone_change->minute, zone_change->second);
+
+	/* Wall Clock Time offset from UTC. */
+	format_utc_offset (zone_change->utc_offset, buffer);
+	fprintf (fp, "\t%s", buffer);
+
+	fprintf (fp, "\n");
+    }
+	return 1;
+}
+
+
+/** This formats a UTC offset as "+HHMM" or "+HHMMSS".
+   buffer should have space for 8 characters. */
+static void
+format_utc_offset			(int		 utc_offset,
+					 char		*buffer)
+{
+  char *sign = "+";
+  int hours, minutes, seconds;
+
+  if (utc_offset < 0) {
+    utc_offset = -utc_offset;
+    sign = "-";
+  }
+
+  hours = utc_offset / 3600;
+  minutes = (utc_offset % 3600) / 60;
+  seconds = utc_offset % 60;
+
+  /* Sanity check. Standard timezone offsets shouldn't be much more than 12
+     hours, and daylight saving shouldn't change it by more than a few hours.
+     (The maximum offset is 15 hours 56 minutes at present.) */
+  if (hours < 0 || hours >= 24 || minutes < 0 || minutes >= 60
+      || seconds < 0 || seconds >= 60) {
+    fprintf (stderr, "Warning: Strange timezone offset: H:%i M:%i S:%i\n",
+	     hours, minutes, seconds);
+  }
+
+  if (seconds == 0)
+    sprintf (buffer, "%s%02i%02i", sign, hours, minutes);
+  else
+    sprintf (buffer, "%s%02i%02i%02i", sign, hours, minutes, seconds);
+}
+
+static char* get_zone_directory(void)
+{
+	return zone_files_directory == NULL ? ZONEINFO_DIRECTORY : zone_files_directory;
+}
+
diff -u -p -N evolution-data-server/calendar/libical/src/libical/imcaltimezone.h evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.h
--- evolution-data-server/calendar/libical/src/libical/imcaltimezone.h	1970-01-01 03:30:00.000000000 +0330
+++ evolution-data-server-wd/calendar/libical/src/libical/imcaltimezone.h	2005-07-05 19:43:36.000000000 +0430
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*======================================================================
+ FILE: imcaltimezone.h
+ CREATOR: Damon Chaplin 15 March 2001
+
+ $Id: imcaltimezone.h,v 1.8 2003/10/21 18:28:27 ettore Exp $
+ $Locker:  $
+  
+ MODIFIED : Mohammad R. Ghorbani	ghorbani bluehome net
+            Arash Yadegarnia		arash bluehome net  
+
+ (C) COPYRIGHT 2001, Damon Chaplin
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either: 
+
+    The LGPL as published by the Free Software Foundation, version
+    2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+  Or:
+
+    The Mozilla Public License Version 1.0. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+
+======================================================================*/
+/**
+ * @file imcaltimezone.h
+ * @brief timezone handling routines
+ */
+
+#ifndef imcaltimeZONE_H
+#define imcaltimeZONE_H
+
+#include <stdio.h> /* For FILE* */
+#include "imcaltime.h"
+#include "icalarray.h"
+#include "icalcomponent.h"
+
+
+#ifndef imcaltimeZONE_DEFINED
+#define imcaltimeZONE_DEFINED
+/** @brief An opaque struct representing a timezone.  
+ * We declare this here to avoid a circular dependancy. 
+ */
+typedef struct _imcaltimezone		imcaltimezone;
+#endif
+
+/**
+ * @par Creating/Destroying individual imcaltimezones.
+ */
+
+/** Creates a new imcaltimezone. */
+imcaltimezone *imcaltimezone_new			(void);
+
+/** Frees all memory used for the imcaltimezone. Set free_struct to free the
+   imcaltimezone struct as well. */
+void imcaltimezone_free				(imcaltimezone *zone,
+						 int free_struct);
+
+/**
+ * @par Accessing timezones.
+ */
+
+/** Free any builtin timezone information **/
+void imcaltimezone_free_builtin_timezones(void);
+
+/** Returns the array of builtin imcaltimezones. */
+icalarray* imcaltimezone_get_builtin_timezones	(void);
+
+/** Returns a single builtin timezone, given its Olson city name. */
+imcaltimezone* imcaltimezone_get_builtin_timezone	(const char *location);
+
+/** Returns a single builtin timezone, given its TZID. */
+imcaltimezone* imcaltimezone_get_builtin_timezone_from_tzid (const char *tzid,
+		 const struct imcaltimeobj * cal);
+
+/** Returns the UTC timezone. */
+imcaltimezone* imcaltimezone_get_utc_timezone	(void);
+
+/** Returns the TZID of a timezone. */
+char*	imcaltimezone_get_tzid			(imcaltimezone	*zone,
+		const struct imcaltimeobj * cal);
+
+/** Returns the city name of a timezone. */
+char*	imcaltimezone_get_location		(imcaltimezone	*zone);
+
+/** Returns the TZNAME properties used in the latest STANDARD and DAYLIGHT
+   components. If they are the same it will return just one, e.g. "LMT".
+   If they are different it will format them like "EST/EDT". Note that this
+   may also return NULL. */
+char*	imcaltimezone_get_tznames		(imcaltimezone	*zone, const struct imcaltimeobj *);
+
+/** Returns the latitude of a builtin timezone. */
+double	imcaltimezone_get_latitude		(imcaltimezone	*zone);
+
+/** Returns the longitude of a builtin timezone. */
+double	imcaltimezone_get_longitude		(imcaltimezone	*zone);
+
+/** Returns the VTIMEZONE component of a timezone. */
+icalcomponent*	imcaltimezone_get_component	(imcaltimezone	*zone, const struct imcaltimeobj *);
+
+/** Sets the VTIMEZONE component of an imcaltimezone, initializing the tzid,
+   location & tzname fields. It returns 1 on success or 0 on failure, i.e.
+   no TZID was found. */
+int	imcaltimezone_set_component		(imcaltimezone	*zone,
+						 icalcomponent	*comp,
+						 const struct imcaltimeobj * cal);
+
+char*   imcaltimezone_get_display_name           (imcaltimezone   *zone,
+		 const struct imcaltimeobj * cal);
+
+/**
+ * @par Converting times between timezones.
+ */
+
+void	imcaltimezone_convert_time		(struct icaltimetype *tt,
+						 imcaltimezone	*from_zone,
+						 imcaltimezone	*to_zone,
+						 const struct imcaltimeobj * cal);
+
+
+/**
+ * @par Getting offsets from UTC.
+ */
+
+/** Calculates the UTC offset of a given local time in the given
+   timezone.  It is the number of seconds to add to UTC to get local
+   time.  The is_daylight flag is set to 1 if the time is in
+   daylight-savings time. */
+int	imcaltimezone_get_utc_offset		(imcaltimezone	*zone,
+						 struct icaltimetype *tt,
+						 int		*is_daylight,
+						 const struct imcaltimeobj * cal);
+
+/** Calculates the UTC offset of a given UTC time in the given
+   timezone.  It is the number of seconds to add to UTC to get local
+   time.  The is_daylight flag is set to 1 if the time is in
+   daylight-savings time. */
+int	imcaltimezone_get_utc_offset_of_utc_time	(imcaltimezone	*zone,
+						 struct icaltimetype *tt,
+						 int		*is_daylight,
+						 const struct imcaltimeobj * cal);
+
+
+
+/*
+ * Handling arrays of timezones. Mainly for internal use.
+ */
+icalarray*  imcaltimezone_array_new		(void);
+
+void	    imcaltimezone_array_append_from_vtimezone (icalarray	    *timezones,
+						      icalcomponent *child,
+						      const struct imcaltimeobj * cal);
+
+void	    imcaltimezone_array_free		(icalarray	*timezones);
+
+
+/*
+ * @par Handling the default location the timezone files
+ */
+
+/** Set the directory to look for the zonefiles */
+void set_zone_directory(char *path);
+
+/** Free memory dedicated to the zonefile directory */
+void free_zone_directory(void);
+
+/*
+ * @par Debugging Output.
+ */
+
+/** Dumps information about changes in the timezone up to and including
+   max_year. */
+int	imcaltimezone_dump_changes		(imcaltimezone	*zone,
+						 int		 max_year,
+						 FILE		*fp,
+						  const struct imcaltimeobj * cal);
+
+#endif /* imcaltimeZONE_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]