pimappservices/calendar/client/src/calrrule.cpp
changeset 0 f979ecb2b13e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pimappservices/calendar/client/src/calrrule.cpp	Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,635 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <calrrule.h>
+
+#include "agmutil.h"
+#include "calcommonimpl.h"
+
+/** Constructor for the weekday within a month data structure.
+
+@param aDay The weekday to set.
+@param aWeekInMonth The week to set. 
+
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C TCalRRule::TDayOfMonth::TDayOfMonth(TDay aDay, TInt8 aWeekInMonth) :
+	iDay(aDay), iWeekInMonth(aWeekInMonth)
+	{
+	}
+
+/** Get the weekday.
+@return The weekday.
+
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TDay TCalRRule::TDayOfMonth::Day() const
+	{
+	return iDay;
+	}
+
+/** Get the week within the month.
+@return The week within the month.
+
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TInt8 TCalRRule::TDayOfMonth::WeekInMonth() const
+	{
+	return iWeekInMonth;
+	}
+
+// Some bits are used internally to differentiate between rule types:
+//  if bit 63 is set on a monthly rule, then it is week-of-month format, e.g. 3rd Wed
+//  if bit 63 is not set on a monthly rule, then it is date-of-month format, e.g. 10th
+const TUint KMonthlyByWeek = 63;
+
+//  if bit 62 is set on a yearly rule, then it is week-of-month-of-year format, e.g. 3rd Wed of June
+//  if bit 62 is not set on a yearly rule, then it is date-of-year format, e.g. 10th June
+const TUint KYearlyByWeek = 62;
+
+// Provides a mapping between the numbers 0 to 63 to bit fields.
+// 0 maps to EBit1
+// 1 maps to EBit2
+// ...etc
+TBool TCalRRule::GetNthBit(TUint aNum) const
+	{
+	TUint64 bit(EBit1);
+	
+	if (aNum >= 64)
+		{
+		CalUtils::Panic(ERepeatRuleBitFailure);
+		}
+	
+	bit = bit << aNum;
+	
+	if (iBuffer & bit)
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+void TCalRRule::SetNthBit(TUint aNum)
+	{
+	TUint64 bit(EBit1);
+	
+	if (aNum >= 64)
+		{
+		CalUtils::Panic(ERepeatRuleBitFailure);
+		}
+	
+	bit = bit << aNum;
+	
+	iBuffer |= bit;
+	}
+
+/** Constructor for the iCal repeat rule type.
+This does not set the type. All data is reset.
+ 
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C TCalRRule::TCalRRule()
+	{
+	iType = EInvalid;
+	InitialiseData();
+	}
+
+/** Constructor for the iCal repeat rule type.
+All data is reset.
+
+@leave KErrNotSupported If an invalid repeat rule type is passed in.
+
+@param aType The type of repeat rule. One of: EDaily, EWeekly, EMonthly, EYearly. 
+
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C TCalRRule::TCalRRule(TCalRRule::TType aType)
+	{
+	__ASSERT_ALWAYS(aType == EDaily || aType == EWeekly || aType == EMonthly || aType == EYearly, 
+						Panic(EAgmErrBadRepeat));
+	iType = aType;
+	InitialiseData();
+	}
+
+void TCalRRule::InitialiseData()
+	{
+	iBuffer = 0;
+	iCount = 0;
+	iUntil.SetTimeUtcL(Time::NullTTime()); // this can't leave
+	iInterval = 1;
+	TLocale locale;
+	iWkSt = locale.StartOfWeek();
+	iReserved = 0;
+	iReserved2 = 0;
+	}
+
+/** Sets the repeat definition's type.
+
+This will be one of: daily, weekly, monthly or yearly. If the type is weekly,
+it must have at least one weekday set by calling SetByDay().
+
+The type may only be set once, from either the constructor or from the SetType function. 
+@leave KErrNotSupported If an invalid type is passed in.
+@panic CalInterimAPI 15 The repeat rule type has already been set.
+@param aType The repeat definition's type. 
+@see SetByDay()
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::SetType(TCalRRule::TType aType)
+	{
+	__ASSERT_ALWAYS(iType == EInvalid, CalUtils::Panic(ERepeatRuleTypeAlreadySet)); // type must not be set already
+	__ASSERT_ALWAYS(aType == EDaily || aType == EWeekly || aType == EMonthly || aType == EYearly, 
+			User::Leave(KErrNotSupported)); // aType must be a meaningful type	
+	iType = aType;
+	}
+
+/** Gets the repeat definition's type. 
+
+This will be one of: daily, weekly, monthly or yearly.
+
+@return The repeat definition's type. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TCalRRule::TType TCalRRule::Type() const
+	{
+	return iType;
+	}
+
+/** Sets the repeat's start date.
+
+The repeat rule's start date should match the entry's start date. If it does
+not then it will be modified to match the entry's start date (or end date for Todos)
+when the rule is applied to the entry using CCalEntry::SetRRuleL.
+
+@param aStartDate The start date, as a TCalTime so it may be accessed in utc or system local time. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::SetDtStart(const TCalTime& aStartDate)
+	{
+	iDtStart = aStartDate;
+	}
+	
+/** Gets the date on which this repeat rule starts.
+
+@return The start date, as a TCalTime so it may be accessed in utc or system local time. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TCalTime TCalRRule::DtStart() const
+	{ 	
+	return iDtStart; 
+	}
+
+/** Sets the repeat's end date. 
+
+Only one of the until or count parameters may be set. Setting the until date will reset the count parameter.
+If the until date is set to TCalTime::MaxTime() the rule will repeat forever.
+
+@param aEndDate The end date, as a TCalTime so it may be accessed in utc or system local time. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::SetUntil(const TCalTime& aEndDate)
+	{
+	//"-1" means only until time has been set 
+	iCount = -1;	
+
+
+	if (aEndDate.TimeUtcL() == TCalTime::MaxTime() || aEndDate.TimeLocalL() == TCalTime::MaxTime())
+		{
+		iCount = 0;	
+		}
+
+	iUntil = aEndDate;
+	}
+	
+/** Gets the date on which this repeat rule finishes.
+
+@return The end date, as a TCalTime so it may be accessed in utc or system local time. If 
+the until value has not been set this will return Time::NullTTime.
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TCalTime TCalRRule::Until() const
+	{
+	return iUntil; 
+	}
+
+/** Sets the repeat interval. 
+
+This is a number of days for a daily repeat, a number of weeks for a 
+weekly repeat, etc. 
+
+@param aInterval The interval. Any parameter that is greater than 255 or less than 1 will be ignored.
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::SetInterval(TInt aInterval)
+	{
+	if (aInterval > 0 && aInterval < 256)
+		{
+		iInterval = aInterval;
+		}
+	}
+
+/** Gets the repeat interval.
+
+This is a number of days for a daily repeat, a number of weeks for a 
+weekly repeat, etc. 
+
+@return The interval. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TInt TCalRRule::Interval() const
+	{
+	return iInterval;
+	}
+
+/** Sets the number of instances that this repeat rule will contain. Setting the count
+ 	will reset the until time to Time::NullTTime.
+
+@param aCount The number of instances. Any non-positive parameter will be ignored.
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::SetCount(TUint aCount)
+	{
+	if (aCount > 0)
+		{
+		iCount = aCount;
+		
+		if(iUntil.TimeLocalL() != Time::NullTTime())
+			{
+			iUntil.SetTimeLocalL(Time::NullTTime());
+			}	
+		}
+	}
+
+/** Gets the number of instances that this repeat rule will contain.
+
+@return The number of instances. It will return:
+
+>0 - Indicate how many occurrences of a repeating rule.
+ 0 - Repeating forever. Note that it is the default value if there is neither Until time nor Count has been set. 
+<0 - A Until time has been set but not the count. 
+
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TUint TCalRRule::Count() const
+	{
+	return iCount;
+	}
+	
+/** Set all weekdays on which this rule is repeated.
+
+@leave KErrNotSupported if not called on a weekly repeat rule.
+@param aDays Array containing all weekdays that are to be set. Any weekdays not included 
+in this array will not be set. Any weekdays not in the TDay enum will be ignored. 
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C void TCalRRule::SetByDay(const RArray<TDay>& aDays)
+	{
+	__ASSERT_ALWAYS(iType == EWeekly, User::Leave(KErrNotSupported));
+	
+	iBuffer = 0;
+	
+	TInt daysCount = aDays.Count();
+	for (TInt i = 0; i < daysCount; ++i)
+		{
+		TDay day(aDays[i]);
+		if (day >= EMonday && day <= ESunday)
+			{
+			// if this day is valid then set this bit
+			SetNthBit(static_cast<TUint>(day));
+			}
+		}
+	}
+
+/** Gets all weekdays on which this rule is repeated.
+
+@param aDays On return this array contains all weekdays that are to be set. 
+This function will do nothing if this is not a weekly repeat rule. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::GetByDayL(RArray<TDay>& aDays) const
+	{
+	if (iType == EWeekly)
+		{
+		aDays.Reset();
+		TDay day = EMonday;
+		while(day <= ESunday)
+			{
+			if (GetNthBit(static_cast<TUint>(day)))
+				{
+				aDays.AppendL(day);
+				}
+			day = static_cast<TDay>((static_cast<TInt>(day) + 1));
+			}
+		}
+	}
+
+/** Set all weekdays in the month on which this rule is repeated.
+
+@leave KErrNotSupported If it is called on a repeat rule which is not monthly or yearly.
+
+@param aDays Array containing all days in the month that are to be set. Any days in the month
+not included in this array will not be set. For a yearly rule, only the first item in the array 
+will be used. Any invalid data will be ignored. 
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C void TCalRRule::SetByDay(const RArray<TDayOfMonth>& aDays)
+	{
+	__ASSERT_ALWAYS(iType == EMonthly || iType == EYearly, User::Leave(KErrNotSupported));
+		
+	if (iType == EMonthly)
+		{
+		iBuffer = 0;
+		TInt daysCount = aDays.Count();
+		for (TInt i = 0; i < daysCount; ++i)
+			{
+			TDayOfMonth dayOfMonth = aDays[i];
+			TDay weekDay = dayOfMonth.Day();
+			if (weekDay >= EMonday && weekDay <= ESunday)
+				{
+				TInt byteToSet = dayOfMonth.WeekInMonth();
+				// if this day and week are valid then set this bit
+				if (byteToSet == -1 || (byteToSet >= 1 && byteToSet <= 4))
+					{
+					if (byteToSet == -1)
+						{
+						byteToSet = 0;
+						}
+					
+					// first 7 bits represent which weekdays are set on the last week of the month - (week = -1)
+					// next 7 bits represent which weekdays are set on the 1st week of the month - (week = 1)
+					// next 7 bits represent which weekdays are set on the 2nd week of the month - (week = 2)
+					// next 7 bits represent which weekdays are set on the 3rd week of the month - (week = 3)
+					// next 7 bits represent which weekdays are set on the 4th week of the month - (week = 4)
+					TUint bitToSet = weekDay + 7 * byteToSet;
+					SetNthBit(bitToSet);
+					}
+				}
+			}
+		SetNthBit(KMonthlyByWeek);
+		}
+	else if (iType == EYearly)
+		{
+		if (!GetNthBit(KYearlyByWeek))
+			{
+			iBuffer = 0;
+			SetNthBit(KYearlyByWeek);
+			}
+			
+		if (aDays.Count() >= 1)
+			{
+			TDay theDay = aDays[0].Day();
+			TInt8 theWeek = aDays[0].WeekInMonth();
+			
+			if (theDay >= EMonday && theDay <= ESunday && 
+				(theWeek == -1 || (theWeek >= 1 && theWeek <= 4)) )
+				{
+				TUint8* bufferPtr = (TUint8*)&iBuffer; // convert the iBuffer store to three TUint8s
+				// EMonday=0 so store it as 1, this allows us to tell if any days have been set
+				bufferPtr[0] = (TUint8)theDay+1;
+				bufferPtr[1] = (TUint8)theWeek;
+				}
+			}
+		}
+	}
+
+/** Gets all days in the month on which this rule is repeated.
+
+@param aDays On return this array contains all days in the month that are to be set. 
+This function will do nothing if this is not a monthly or yearly repeat rule. 
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::GetByDayL(RArray<TDayOfMonth>& aDays) const
+	{
+	if (iType == EMonthly)
+		{
+		aDays.Reset();
+		if (GetNthBit(KMonthlyByWeek))
+			{
+			// if i == 35, then weekNum = 5 below which is too high
+			for (TUint i = 0; i < 35; ++i)
+				{
+				if (GetNthBit(i))
+					{
+					// This is the reverse of the algorithm in TCalRRule::SetByDay(const RArray<TDayOfMonth>& aDays)
+					TDay day = static_cast<TDay>(i % 7);
+					TInt weekNum = i / 7;
+					if (weekNum == 0)
+						{
+						weekNum = -1;
+						}
+					TDayOfMonth dayOfMonth(day, weekNum);
+					aDays.AppendL(dayOfMonth);
+					}
+				}
+			}
+		}
+	else if (iType == EYearly)
+		{
+		aDays.Reset();
+		if (GetNthBit(KYearlyByWeek))
+			{
+			TUint8* bufferPtr = (TUint8*)&iBuffer; // convert the iBuffer store to three TUint8s
+			TDay theDay = TDay(bufferPtr[0]-1); // -1 because EMonday is stored as +1
+			TInt8 theWeek = TInt8(bufferPtr[1]);
+			
+			if (theDay >= EMonday && theDay <= ESunday)
+				{
+				TDayOfMonth dayOfMonth(theDay, theWeek);
+				aDays.AppendL(dayOfMonth);
+				}
+			}
+		}
+	}
+	
+/** Sets all dates of the month on which this rule is repeated.
+
+@leave KErrNotSupported If it is not a monthly repeat rule.
+
+@param aMonthDays Array containing all month dates that are to be set. Any month dates
+not included in this array will not be set. Any out of range dates will be ignored. 
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C void TCalRRule::SetByMonthDay(const RArray<TInt>& aMonthDays)
+	{
+	__ASSERT_ALWAYS(iType == EMonthly, User::Leave(KErrNotSupported));
+	
+	iBuffer = 0;
+	TInt daysCount = aMonthDays.Count();
+	for (TInt i = 0; i < daysCount; ++i)
+		{
+		TInt bit = aMonthDays[i];
+		
+		// check this date is valid
+		if (bit >= 0 && bit <= 30)
+			{
+			SetNthBit(bit);
+			}
+		}
+	}
+
+/** Gets all dates of the month on which this rule is repeated.
+
+@param aMonthDays On return, this array contains all month dates that are to be set.
+This function will do nothing if this is not a monthly repeat rule. 
+Note that 0 represents 1st of the month, 1 represents 2nd, etc.
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::GetByMonthDayL(RArray<TInt>& aMonthDays) const
+	{
+	if (iType == EMonthly)
+		{
+		aMonthDays.Reset();
+		if (!GetNthBit(KMonthlyByWeek))
+			{			
+			// check first 31 bits of iBuffer to see which dates have been set
+			for (TInt i = 0; i <= 30; ++i)
+				{
+				if (GetNthBit(i))
+					{
+					aMonthDays.AppendL(i);
+					}
+				}
+			}
+		}
+	}
+
+/** Sets the month of the year for this repeat rule.
+
+@leave KErrNotSupported If it is not on a yearly repeat rule 
+@param aMonths Array of months on which to repeat. Only the first month in the array is used.
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C void TCalRRule::SetByMonth(const RArray<TMonth> aMonths)
+	{
+	__ASSERT_ALWAYS(iType == EYearly, User::Leave(KErrNotSupported));
+	
+	if (aMonths.Count() >= 1)
+		{
+		TMonth month = aMonths[0];
+		if (month >= EJanuary && month <= EDecember)
+			{
+			if (!GetNthBit(KYearlyByWeek))
+				{
+				iBuffer = 0;
+				SetNthBit(KYearlyByWeek);
+				}
+			
+			TUint8* bufferPtr = (TUint8*)&iBuffer; // convert the iBuffer store to three TUint8s
+			// EJanuary=0 so store it as 1, this allows us to tell if any months have been set
+			bufferPtr[2] = (TUint8)month+1;
+			}
+		}
+	}
+
+/** Gets the month of the year for this repeat rule.
+This function will do nothing if this is not a yearly repeat rule
+@param aMonths On return, the months on which to repeat.
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C void TCalRRule::GetByMonthL(RArray<TMonth>& aMonths) const
+	{
+	if (iType == EYearly)
+		{
+		aMonths.Reset();
+		if (GetNthBit(KYearlyByWeek))
+			{
+			TUint8* bufferPtr = (TUint8*)&iBuffer; // convert the iBuffer store to three TUint8s
+			TMonth theMonth = TMonth(bufferPtr[2]-1); // -1 because EJanuary stored as 1
+			if (theMonth >= EJanuary && theMonth <= EDecember)
+				{
+				aMonths.AppendL(theMonth);
+				}
+			}
+		}
+	}
+
+/** Sets the first day of the week for this repeat rule.
+
+@param aDay The weekday to be the first. Any invalid parameter will be ignored. 
+@publishedAll
+@released
+@capability None
+*/
+EXPORT_C void TCalRRule::SetWkSt(TDay aDay)
+	{
+	if (aDay >= EMonday && aDay <= ESunday)
+		{
+		iWkSt = aDay;
+		}
+	}
+	
+/** Gets the first day of the week for this repeat rule.
+
+@return The weekday to be the first.
+@publishedAll
+@released 
+@capability None
+*/
+EXPORT_C TDay TCalRRule::WkSt() const
+	{
+	return iWkSt;
+	}
+
+void TCalRRule::SetUntilAndCount(const TCalTime& aTime, TUint aCount)
+	{
+	iUntil = aTime;
+	iCount = aCount;
+	}