diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/client/src/calrrule.cpp --- /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 + +#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& 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(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& aDays) const + { + if (iType == EWeekly) + { + aDays.Reset(); + TDay day = EMonday; + while(day <= ESunday) + { + if (GetNthBit(static_cast(day))) + { + aDays.AppendL(day); + } + day = static_cast((static_cast(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& 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& 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& aDays) + TDay day = static_cast(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& 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& 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 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& 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; + }