pimappsupport/vcardandvcal/src/VRECUR.CPP
changeset 0 f979ecb2b13e
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15  
       
    16 #include <vrecur.h>
       
    17 #include "verror.h"
       
    18 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    19 #include "versit_internal.h"
       
    20 #endif
       
    21 //
       
    22 // CWeekDayArray
       
    23 //
       
    24 
       
    25 EXPORT_C CWeekDayArray::CWeekDayArray()
       
    26 : iArray(NULL)
       
    27 /** Constructs an array of the days in the week. */
       
    28 	{}
       
    29 
       
    30 EXPORT_C CWeekDayArray::~CWeekDayArray()
       
    31 /** Frees all resources owned by the object, prior to its destruction. */
       
    32 	{
       
    33 	delete iArray;
       
    34 	}
       
    35 
       
    36 EXPORT_C void CWeekDayArray::ExternalizeL(RWriteStream& aStream)
       
    37 /** Externalises the array of days in the week to a write stream.
       
    38 
       
    39 Writes the first two characters of each day name, for instance "MO TU WE".
       
    40 
       
    41 The presence of this function means that the standard templated operator<<() 
       
    42 (defined in s32strm.h) is available to externalise objects of this class.
       
    43 
       
    44 @param aStream Stream to which the array is to be externalised. */
       
    45 	{
       
    46 	if (iArray)
       
    47 		{
       
    48 		TInt count=iArray->Count();
       
    49 		for (TInt ii=0; ii<count; ii++)
       
    50 			{
       
    51 			switch ((*iArray)[ii])
       
    52 				{
       
    53 			case EMonday:
       
    54 				aStream.WriteL(KVersitRecurrenceMonday8);
       
    55 				break;
       
    56 			case ETuesday:
       
    57 				aStream.WriteL(KVersitRecurrenceTuesday8);
       
    58 				break;
       
    59 			case EWednesday:
       
    60 				aStream.WriteL(KVersitRecurrenceWednesday8);
       
    61 				break;
       
    62 			case EThursday:
       
    63 				aStream.WriteL(KVersitRecurrenceThursday8);
       
    64 				break;
       
    65 			case EFriday:
       
    66 				aStream.WriteL(KVersitRecurrenceFriday8);
       
    67 				break;
       
    68 			case ESaturday:
       
    69 				aStream.WriteL(KVersitRecurrenceSaturday8);
       
    70 				break;
       
    71 			case ESunday:
       
    72 				aStream.WriteL(KVersitRecurrenceSunday8);
       
    73 				break;
       
    74 			default:
       
    75 				Panic(ENoWeekdayFound);
       
    76 				break;
       
    77 				};
       
    78 			aStream.WriteL(KVersitTokenSpace);
       
    79 			}
       
    80 		}
       
    81 	}
       
    82 
       
    83 //
       
    84 // CVersitRecurrence
       
    85 //
       
    86 EXPORT_C CVersitRecurrence::CVersitRecurrence(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate)
       
    87 : iInterval(aInterval),iDuration(aDuration),iEndDate(aEndDate)
       
    88 /** Constructs the CVersitRecurrence object.
       
    89 
       
    90 Initialises the interval (iInterval), duration (iDuration) and optionally, the end 
       
    91 date (iEndDate).
       
    92 
       
    93 This is invoked by the constructor of a derived class.
       
    94 
       
    95 @param aInterval The interval between repeats.
       
    96 @param aDuration The duration for the recurrence.
       
    97 @param aEndDate A pointer to the end date. The object takes ownership of this 
       
    98 pointer. */
       
    99 	{}
       
   100 
       
   101 EXPORT_C CVersitRecurrence::~CVersitRecurrence()
       
   102 /** Frees all resources owned by the CVersitRecurrence object, prior to its destruction. */
       
   103 	{
       
   104 	delete iEndDate;
       
   105 	}
       
   106 
       
   107 //
       
   108 // CVersitRecurrenceDaily
       
   109 //
       
   110 EXPORT_C CVersitRecurrenceDaily::CVersitRecurrenceDaily(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate)
       
   111 : CVersitRecurrence(aInterval,aDuration,aEndDate)
       
   112 /** Constructs the CVersitRecurrenceDaily object.
       
   113 
       
   114 Sets the interval, the duration and, optionally, an end date for the repeat. 
       
   115 The repeat type is set to EDaily.
       
   116 
       
   117 If a duration and an end date are both specified, the end date takes precedence.
       
   118 
       
   119 @param aInterval The number of days between repeats. 
       
   120 @param aDuration The duration, in days, for which the event should continue 
       
   121 recurring. A value of zero indicates the repeat should continue forever.
       
   122 @param aEndDate Pointer to the end date for the repeat. The object takes ownership 
       
   123 of this pointer. */
       
   124 	{
       
   125 	iRepeatType=EDaily;
       
   126 	}
       
   127 
       
   128 EXPORT_C void CVersitRecurrenceDaily::ExternalizeOccurrenceListsL(RWriteStream& /*aStream*/) const
       
   129 /** This function is empty because an occurrence list is not applicable to a daily recurrence type. 
       
   130 
       
   131 @param aStream Not used.*/
       
   132 	{}
       
   133 
       
   134 //
       
   135 //	CVersitRecurrenceWeekly
       
   136 //
       
   137 EXPORT_C CVersitRecurrenceWeekly::CVersitRecurrenceWeekly(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CWeekDayArray* aArrayOfWeekdayOccurrences)
       
   138 : CVersitRecurrence(aInterval,aDuration,aEndDate)
       
   139 , iArrayOfWeekDayOccurrences(aArrayOfWeekdayOccurrences)
       
   140 /** Constructs the CVersitRecurrenceWeekly object.
       
   141 
       
   142 Initialises the interval, the duration, optionally, an end date for the repeat and, 
       
   143 optionally, a pointer to an array of the days of the week on which the repeat 
       
   144 event occurs. Sets the repeat type to EWeekly. 
       
   145 
       
   146 @param aInterval The number of weeks between repeats.
       
   147 @param aDuration The duration, in weeks, for which the event should recur.
       
   148 A value of zero indicates the repeat should continue forever.
       
   149 @param aEndDate Pointer to the end date for the repeat. The object takes 
       
   150 ownership of this pointer.
       
   151 @param aArrayOfWeekdayOccurrences Array of the days of the week on which 
       
   152 the repeat event occurs. The object takes ownership of this pointer. */
       
   153 	{
       
   154 	iRepeatType=EWeekly;
       
   155 	}
       
   156 
       
   157 EXPORT_C CVersitRecurrenceWeekly::~CVersitRecurrenceWeekly()
       
   158 /** Frees all resources owned by the object, prior to its destruction. */
       
   159 	{
       
   160 	delete iArrayOfWeekDayOccurrences;
       
   161 	}
       
   162 
       
   163 EXPORT_C void CVersitRecurrenceWeekly::ExternalizeOccurrenceListsL(RWriteStream& aStream) const
       
   164 /** Writes the codes for the days of the week on which the event occurs (e.g. "TU 
       
   165 TH") to the outgoing stream, aStream.
       
   166 
       
   167 @param aStream The stream to which the occurrence list is to be written. */
       
   168 	{
       
   169 	if (iArrayOfWeekDayOccurrences)
       
   170 		iArrayOfWeekDayOccurrences->ExternalizeL(aStream);
       
   171 	}
       
   172 
       
   173 //
       
   174 // CVersitRecurrenceMonthlyByPos
       
   175 //
       
   176 
       
   177 EXPORT_C CVersitRecurrenceMonthlyByPos::CVersitRecurrenceMonthlyByPos(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CArrayPtrFlat<CMonthPosition>* aMonthPositions)
       
   178 : CVersitRecurrence(aInterval,aDuration,aEndDate)
       
   179 ,iMonthPositions(aMonthPositions)
       
   180 /** Constructs the CVersitRecurrenceMonthlyByPos object.
       
   181 
       
   182 Sets the interval, the duration, optionally, an end date for the repeat and 
       
   183 a pointer to an array of 'month positions', which specify when the event occurs. 
       
   184 Also sets the repeat type to EMonthlyByPos.
       
   185 
       
   186 If a duration and an end date are both specified, the end date takes precedence.
       
   187 
       
   188 @param aInterval The number of months between repeats. 
       
   189 @param aDuration The duration, in months, for which the event should recur. 
       
   190 A value of zero indicates the repeat should continue forever.
       
   191 @param aEndDate Pointer to the end date for the repeat event. The object takes 
       
   192 ownership of this pointer. 
       
   193 @param aMonthPositions Pointer to an array of the positions of days within 
       
   194 the month. The object takes ownership of this pointer. */
       
   195 	{
       
   196 	iRepeatType=EMonthlyByPos;
       
   197 	}
       
   198 
       
   199 EXPORT_C CVersitRecurrenceMonthlyByPos::~CVersitRecurrenceMonthlyByPos()
       
   200 /** Frees all resources owned by the object, prior to its destruction. */
       
   201 	{
       
   202 	if (iMonthPositions)
       
   203 		{
       
   204 		iMonthPositions->ResetAndDestroy();
       
   205 		delete iMonthPositions;
       
   206 		}
       
   207 	}
       
   208 
       
   209 EXPORT_C void CVersitRecurrenceMonthlyByPos::ExternalizeOccurrenceListsL(RWriteStream& aStream) const
       
   210 /** Writes the days of the month on which the event occurs to the output stream, 
       
   211 aStream.
       
   212 
       
   213 If an event occurs on Monday and Tuesday of the first week and the second to last week 
       
   214 of a month, the string written to aStream would be "1+ MO TU 2- MO TU ", with 
       
   215 the plus sign indicating that the week is counted from the start of the month 
       
   216 and the minus sign indicating that the week is counted from the end of the 
       
   217 month.
       
   218 
       
   219 @param aStream The stream to which the occurrence list is to be written. */
       
   220 	{
       
   221 	if (iMonthPositions)
       
   222 		{
       
   223 		const TInt count = iMonthPositions->Count();
       
   224 		CMonthPosition* monthPos;
       
   225 		TBuf8<1> weekNo;
       
   226 		for (TInt ii = 0; ii < count; ii++)
       
   227 			{
       
   228 			monthPos = (*iMonthPositions)[ii];
       
   229 			__ASSERT_DEBUG((monthPos->iWeekNo < 10), Panic(EWeekNoOverTen));
       
   230 			weekNo.Num(monthPos->iWeekNo);
       
   231 			aStream.WriteL(weekNo);
       
   232 			if (monthPos->iSign == CMonthPosition::EWeeksFromEndOfMonth)
       
   233 				aStream.WriteL(KVersitTokenMinus);
       
   234 			else
       
   235 				aStream.WriteL(KVersitTokenPlus);
       
   236 			aStream.WriteL(KVersitTokenSpace);
       
   237 			if (monthPos->iArrayOfWeekDays)
       
   238 				monthPos->iArrayOfWeekDays->ExternalizeL(aStream);
       
   239 			}
       
   240 		}
       
   241 	}
       
   242 
       
   243 EXPORT_C CVersitRecurrenceMonthlyByPos::CMonthPosition::~CMonthPosition()
       
   244 /** Frees all resources owned by the object, prior to its destruction. */
       
   245 	{
       
   246 	delete iArrayOfWeekDays;
       
   247 	}
       
   248 
       
   249 //
       
   250 // CVersitRecurrenceMonthlyByDay
       
   251 //
       
   252 EXPORT_C CVersitRecurrenceMonthlyByDay::CVersitRecurrenceMonthlyByDay(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,	CArrayFix<TInt>* aArrayOfOccurrencesInDaysFromStartOfMonth
       
   253 		,CArrayFix<TInt>* aArrayOfOccurrencesInDaysFromEndOfMonth,TBool aLastDay)
       
   254 : CVersitRecurrence(aInterval,aDuration,aEndDate)
       
   255 ,iArrayOfOccurrencesInDaysFromStartOfMonth(aArrayOfOccurrencesInDaysFromStartOfMonth)
       
   256 ,iArrayOfOccurrencesInDaysFromEndOfMonth(aArrayOfOccurrencesInDaysFromEndOfMonth)
       
   257 ,iLastDay(aLastDay)
       
   258 /** Constructs the CVersitRecurrenceMonthlyByDay object.
       
   259 
       
   260 Sets the repeat type to CVersitRecurrence::EMonthlyByDay. Note: if a duration and an end 
       
   261 date are both specified, the end date takes precedence.
       
   262 
       
   263 @param aInterval The number of months between repeats.
       
   264 @param aDuration The duration, in months, for which the event should recur. 
       
   265 A value of zero indicates the repeat should continue forever.
       
   266 @param aEndDate Optional pointer to the end date for the repeat event. The object 
       
   267 takes ownership of this pointer.
       
   268 @param aArrayOfOccurencesInDaysFromStartOfMonth Optional pointer to an array of 
       
   269 numbers, each of which can have a value between 1 and 31 inclusive, which identify 
       
   270 the days, counting from the start of the month, on which the repeat event occurs. The 
       
   271 object takes ownership of this pointer.
       
   272 @param aArrayOfOccurrencesInDaysFromEndOfMonth Optional pointer to an array of numbers, 
       
   273 each of which can have a value between 1 and 31 inclusive, which identify the days, 
       
   274 counting from the end of the month, on which the repeat event occurs. (The last day of 
       
   275 the month is represented by 1). The object takes ownership of this pointer.
       
   276 @param aLastDay Optional - ETrue if the event occurs on the last day of the month. This 
       
   277 day can then be represented in the output stream using the LD recurrence value. EFalse if not. */
       
   278 	{
       
   279 	iRepeatType=EMonthlyByDay;
       
   280 	}
       
   281 
       
   282 EXPORT_C CVersitRecurrenceMonthlyByDay::~CVersitRecurrenceMonthlyByDay()
       
   283 /** Frees all resources owned by the object, prior to its destruction. */
       
   284 	{
       
   285 	delete iArrayOfOccurrencesInDaysFromStartOfMonth;
       
   286 	delete iArrayOfOccurrencesInDaysFromEndOfMonth;
       
   287 	}
       
   288 
       
   289 EXPORT_C void CVersitRecurrenceMonthlyByDay::ExternalizeOccurrenceListsL(RWriteStream& aStream) const
       
   290 /** Writes the days of the month on which the event occurs to the output stream, 
       
   291 aStream.
       
   292 
       
   293 For days counted from the beginning of the month, the string written to aStream 
       
   294 might be "1+ 2+ 16+ 17+ ", with the plus sign indicating that the day is counted 
       
   295 from the start of the month.
       
   296 
       
   297 For days counted from the end of the month, the string written to aStream 
       
   298 might be "1- 3- 4- LD ", with "LD" signifying that the event occurs on the 
       
   299 last day of the month. 
       
   300 
       
   301 @param aStream The stream to which the occurrence list is to be written. */
       
   302 	{
       
   303 	if (iArrayOfOccurrencesInDaysFromStartOfMonth)
       
   304 		{
       
   305 		TInt count = iArrayOfOccurrencesInDaysFromStartOfMonth->Count();
       
   306 		TInt occurrence;
       
   307 		TBuf8<KVersitDefaultBufferSize> temp;
       
   308 		for (TInt ii = 0; ii < count; ii++)
       
   309 			{
       
   310 			occurrence = (*iArrayOfOccurrencesInDaysFromStartOfMonth)[ii];
       
   311 			if ((occurrence < 32) && (occurrence > 0)) //day in month
       
   312 				{
       
   313 				temp.Num(occurrence);
       
   314 				aStream.WriteL(temp);
       
   315 				aStream.WriteL(KVersitTokenPlus);
       
   316 				aStream.WriteL(KVersitTokenSpace);
       
   317 				}
       
   318 			}
       
   319 		}
       
   320 	if (iArrayOfOccurrencesInDaysFromEndOfMonth)
       
   321 		{
       
   322 		TInt count = iArrayOfOccurrencesInDaysFromEndOfMonth->Count();
       
   323 		TInt occurrence;
       
   324 		TBuf8<KVersitDefaultBufferSize> temp;
       
   325 		for (TInt ii = 0; ii < count; ii++)
       
   326 			{
       
   327 			occurrence = (*iArrayOfOccurrencesInDaysFromEndOfMonth)[ii];
       
   328 			if ((occurrence < 32) && (occurrence > 0)) //day in month
       
   329 				{
       
   330 				temp.Num(occurrence);
       
   331 				aStream.WriteL(temp);
       
   332 				aStream.WriteL(KVersitTokenMinus);
       
   333 				aStream.WriteL(KVersitTokenSpace);
       
   334 				}
       
   335 			}
       
   336 		}
       
   337 	if (iLastDay)
       
   338 		{
       
   339 		aStream.WriteL(KVersitRecurrenceLastDay);
       
   340 		aStream.WriteL(KVersitTokenSpace);
       
   341 		}
       
   342 	}
       
   343 
       
   344 //
       
   345 // CVersitRecurrenceYearlyByMonth
       
   346 //
       
   347 
       
   348 EXPORT_C CVersitRecurrenceYearlyByMonth::CVersitRecurrenceYearlyByMonth(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CArrayFix<TMonth>* aArrayOfMonthsInYearOccurrences)
       
   349 : CVersitRecurrence(aInterval,aDuration,aEndDate)
       
   350 , iArrayOfMonthsInYearOccurrences(aArrayOfMonthsInYearOccurrences)
       
   351 /** Constructs the CVersitRecurrenceYearlyByMonth object.
       
   352 
       
   353 Sets the repeat type to CVersitRecurrence::EYearlyByMonth.
       
   354 
       
   355 If a duration and an end date are both specified, the end date takes precedence.
       
   356 
       
   357 @param aInterval The number of years between repeats. 
       
   358 @param aDuration The duration, in years, for which the event should recur. 
       
   359 A value of zero indicates the repeat should continue forever. 
       
   360 @param aEndDate Optional pointer to the end date for the repeat event. The object takes 
       
   361 ownership of this pointer. 
       
   362 @param aArrayOfMonthsInYearOccurrences Pointer to an array of month values. 
       
   363 The object takes ownership of this pointer. */
       
   364 	{
       
   365 	iRepeatType=EYearlyByMonth;	
       
   366 	}
       
   367 
       
   368 EXPORT_C CVersitRecurrenceYearlyByMonth::~CVersitRecurrenceYearlyByMonth()
       
   369 /** Frees all resources owned by the object, prior to its destruction. */
       
   370 	{
       
   371 	delete iArrayOfMonthsInYearOccurrences;
       
   372 	}
       
   373 
       
   374 EXPORT_C void CVersitRecurrenceYearlyByMonth::ExternalizeOccurrenceListsL(RWriteStream& aStream) const
       
   375 /** Writes the months of the year, as month numbers, in which the event occurs to 
       
   376 the output stream.
       
   377 
       
   378 For example, if the event occurs from September to December inclusive, the 
       
   379 string written to aStream would be "9 10 11 12 ".
       
   380 
       
   381 @param aStream The stream to which the occurrence list is to be written. */
       
   382 	{
       
   383 	if (iArrayOfMonthsInYearOccurrences)
       
   384 		{
       
   385 		TInt count = iArrayOfMonthsInYearOccurrences->Count();
       
   386 		TBuf8<KVersitDefaultBufferSize> temp;
       
   387 		for (TInt ii = 0; ii < count; ii++)
       
   388 			{
       
   389 			temp.Num((*iArrayOfMonthsInYearOccurrences)[ii] + 1); // Add 1 since EJanuary = 0, not 1
       
   390 			aStream.WriteL(temp);
       
   391 			aStream.WriteL(KVersitTokenSpace);
       
   392 			}
       
   393 		}
       
   394 	}
       
   395 
       
   396 //
       
   397 // CVersitRecurrenceYearlyByDay
       
   398 //
       
   399 EXPORT_C CVersitRecurrenceYearlyByDay::CVersitRecurrenceYearlyByDay(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CArrayFix<TInt>* aArrayOfDaysInYearOccurrences)
       
   400 : CVersitRecurrence(aInterval,aDuration,aEndDate)
       
   401 ,iArrayOfDaysInYearOccurrences(aArrayOfDaysInYearOccurrences)
       
   402 /** Constructs the CVersitRecurrenceYearlyByDay object.
       
   403 
       
   404 Sets the repeat type to EYearlyByDay.
       
   405 
       
   406 If a duration and an end date are both specified, the end date takes precedence.
       
   407 
       
   408 @param aInterval The number of years between repeats. 
       
   409 @param aDuration The duration, in years, for which the event should 
       
   410 recur. A value of zero indicates the repeat should continue forever. 
       
   411 @param aEndDate Optional pointer to the end date for the repeat event. The object takes 
       
   412 ownership of this pointer. 
       
   413 @param aArrayOfDaysInYearOccurrences Pointer to an array of integers between 
       
   414 1 and 366 inclusive. Each integer represents a day on which the repeat event 
       
   415 occurs. The object takes ownership of this pointer. */
       
   416 	{
       
   417 	iRepeatType=EYearlyByDay;
       
   418 	}
       
   419 
       
   420 EXPORT_C CVersitRecurrenceYearlyByDay::~CVersitRecurrenceYearlyByDay()
       
   421 /** Frees all resources owned by the object, prior to its destruction. */
       
   422 	{
       
   423 	delete iArrayOfDaysInYearOccurrences;
       
   424 	}
       
   425 
       
   426 EXPORT_C void CVersitRecurrenceYearlyByDay::ExternalizeOccurrenceListsL(RWriteStream& aStream) const
       
   427 /** Writes the days of the year on which the event occurs to the output stream, 
       
   428 aStream.
       
   429 
       
   430 For example, the function might write the string "10 11 12 13 14 15 ".
       
   431 
       
   432 @param aStream The stream to which the occurrence list is to be written. */
       
   433 	{
       
   434 	if (iArrayOfDaysInYearOccurrences)
       
   435 		{
       
   436 		TInt count=iArrayOfDaysInYearOccurrences->Count();
       
   437 		TInt occurrence;
       
   438 		TBuf8<KVersitDefaultBufferSize> temp;
       
   439 		for (TInt ii = 0; ii < count; ii++)
       
   440 			{
       
   441 			occurrence = (*iArrayOfDaysInYearOccurrences)[ii];
       
   442 			temp.Num(occurrence);
       
   443 			if ((occurrence < 366) && (occurrence > 0)) //day in year
       
   444 				{
       
   445 				aStream.WriteL(temp);
       
   446 				aStream.WriteL(KVersitTokenSpace);
       
   447 				}
       
   448 			}
       
   449 		}
       
   450 	}
       
   451 
       
   452 //
       
   453 // CParserPropertyValueRecurrence
       
   454 //
       
   455 EXPORT_C CParserPropertyValueRecurrence::CParserPropertyValueRecurrence(CVersitRecurrence* aValue)
       
   456 : CParserTimePropertyValue(TUid::Uid(KVCalPropertyRecurrenceUid))
       
   457 , iValue(aValue)
       
   458 /** Constructs a recurrence property value. 
       
   459 
       
   460 Sets the property value's UID to KVCalPropertyRecurrenceUid.
       
   461 
       
   462 @param aValue A pointer to the recurrence value to assign to the property 
       
   463 value parser. The property value parser takes ownership of the pointer. */
       
   464 	{}
       
   465 
       
   466 EXPORT_C CParserPropertyValueRecurrence::~CParserPropertyValueRecurrence()
       
   467 /** Frees all resources owned by the property value, prior to its destruction. */
       
   468 	{
       
   469 	delete iValue;
       
   470 	}
       
   471 
       
   472 EXPORT_C void CParserPropertyValueRecurrence::ConvertAllDateTimesToUTCL(const TTimeIntervalSeconds& /*aIncrement*/,const CVersitDaylight* /*aDaylight*/)
       
   473 /** Converts the end time of the recurrence value into universal time.
       
   474 
       
   475 The date/time is checked against the daylight saving information provided 
       
   476 in aDaylight. If it falls inside the daylight saving period then the daylight 
       
   477 saving offset is subtracted from the time to convert it to universal time. 
       
   478 Otherwise the time is modified by aIncrement to convert it to universal time.
       
   479 
       
   480 Note that the daylight savings offset will adjust the time both for the daylight 
       
   481 saving and for the time zone.
       
   482 
       
   483 The function has no effect if the value is already stored in universal time.
       
   484 
       
   485 If aDaylight is a NULL pointer then aIncrement is used.
       
   486 
       
   487 @param aIncrement A time interval in seconds which represents the negative 
       
   488 of the time zone of the originating machine. For instance, if the time zone 
       
   489 is +04:30 (that is 4hr 30mins ahead of UTC), aIncrement should be set to minus 
       
   490 the number of seconds in 4hr 30mins..
       
   491 @param aDaylight Pointer to the specification for daylight saving. If the date/time 
       
   492 value is within the period for daylight saving, the value is modified by the 
       
   493 daylight saving offset (which accounts for both the time zone and daylight 
       
   494 saving rule). 
       
   495 @deprecated since 9.1
       
   496 */
       
   497 	{
       
   498 	}
       
   499 
       
   500 EXPORT_C void CParserPropertyValueRecurrence::ConvertAllUTCDateTimesToMachineLocalL(const TTimeIntervalSeconds& /*aIncrement*/)
       
   501 /** Converts the end time of the recurrence value into machine-local time. 
       
   502 
       
   503 This process involves adjusting the date/time value by the offset in aIncrement.
       
   504 
       
   505 The function has no effect if the value is already stored in machine-local 
       
   506 time.
       
   507 
       
   508 @param aIncrement A time interval which represents the number of seconds which 
       
   509 is to be added to the date/time value. This should normally be the universal 
       
   510 time offset for the machine's locale. 
       
   511 @deprecated since 9.1
       
   512 */
       
   513 	{
       
   514 	}
       
   515 
       
   516 EXPORT_C void CParserPropertyValueRecurrence::ExternalizeL(RWriteStream& aStream,const Versit::TEncodingAndCharset& /*aEncodingCharset*/
       
   517 																																,TInt /*aLengthOutput*/)
       
   518 /** Externalises the recurrence property value into aStream.
       
   519 
       
   520 The property is written to the stream in the following order:
       
   521 
       
   522 - Repeat type, e.g. "D" is written for a daily repeat (see KVersitRecurrenceDaily).
       
   523 
       
   524 - Repeat interval, e.g. "2" for a weekly repeat type that occurs fortnightly.
       
   525 
       
   526 - Occurrence list (optional), e.g. the string "MO TH" is written for a weekly repeat type that recurs 
       
   527 on Mondays and Thursdays.
       
   528 
       
   529 - End date (optional) - the date on which the event should stop recurring.
       
   530 
       
   531 - Duration, e.g. "#10" for a weekly repeat type that should last for 10 weeks.
       
   532 
       
   533 For example, "W2 TU TH #10", means a repeat every second Tuesday and Thursday for 10 weeks
       
   534 
       
   535 @param aStream Stream to which the value is to be externalised.
       
   536 @param aEncodingCharset Specifies character set and encoding information. This is not 
       
   537 used by this function since the recurrence rule value is in ASCII.
       
   538 @param aLengthOutput The amount of text that has been output so far on the line. This is not used by 
       
   539 this function since the line wrapping is not a general case for recurrence values. */
       
   540 	{
       
   541 	if (!iValue)
       
   542 		return;
       
   543 	switch(iValue->iRepeatType)
       
   544 		{
       
   545 	case CVersitRecurrence::EDaily:
       
   546 		aStream.WriteL(KVersitRecurrenceDaily);
       
   547 		break;
       
   548 	case CVersitRecurrence::EWeekly:
       
   549 		aStream.WriteL(KVersitRecurrenceWeekly);
       
   550 		break;
       
   551 	case CVersitRecurrence::EMonthlyByPos:
       
   552 		aStream.WriteL(KVersitRecurrenceMonthlyByPos8);
       
   553 		break;
       
   554 	case CVersitRecurrence::EMonthlyByDay:
       
   555 		aStream.WriteL(KVersitRecurrenceMonthlyByDay8);
       
   556 		break;
       
   557 	case CVersitRecurrence::EYearlyByMonth:
       
   558 		aStream.WriteL(KVersitRecurrenceYearlyByMonth8);
       
   559 		break;
       
   560 	case CVersitRecurrence::EYearlyByDay:
       
   561 		aStream.WriteL(KVersitRecurrenceYearlyByDay8);
       
   562 		break;
       
   563 	default:
       
   564 		Panic(ENoRecognizedRepeatType);
       
   565 		break;
       
   566 		};
       
   567 	TBuf8<KVersitDefaultBufferSize> temp;
       
   568 	temp.Num(iValue->iInterval);
       
   569 	aStream.WriteL(temp);
       
   570 	aStream.WriteL(KVersitTokenSpace);
       
   571 	iValue->ExternalizeOccurrenceListsL(aStream);
       
   572 	if (iValue->iEndDate)
       
   573 		{
       
   574 		TBuf8<KVersitMaxDateTimeLength> buf;
       
   575 		EncodeVersitDateTimeL(buf,*iValue->iEndDate);
       
   576 		aStream.WriteL(buf);
       
   577 		}
       
   578 	else 
       
   579 		{
       
   580 		aStream.WriteL(KVersitRecurrenceNumberOf);
       
   581 		temp.Num(iValue->iDuration);
       
   582 		aStream.WriteL(temp);
       
   583 		}
       
   584 	}
       
   585 
       
   586 //
       
   587 // CRecurrenceParser
       
   588 //
       
   589 EXPORT_C CRecurrenceParser::CRecurrenceParser(TBool aHasVersion)
       
   590 	: CVersitParser(aHasVersion)		//(aHasVersion? ESupportsVersion:ENoVersionProperty)	
       
   591 /** Constructs a recurrence parser.
       
   592 
       
   593 @param aHasVersion CVersitParser::ESupportsVersion if a version property is needed; 
       
   594 ENoVersionProperty otherwise. */
       
   595 	{}
       
   596 
       
   597 EXPORT_C CParserPropertyValue* CRecurrenceParser::MakePropertyValueRecurrenceL(TDes& aRecurringEntity)
       
   598 /** Internalises a recurrence property value in descriptor form.
       
   599 
       
   600 Creates a recurrence parser using the recurrence information provided in aRecurringEntity 
       
   601 (which has the format described in CParserPropertyValueRecurrence::ExternalizeL()).
       
   602 
       
   603 @param aRecurringEntity A recurring entity in descriptor form. */
       
   604 	{
       
   605 	aRecurringEntity.TrimAll();
       
   606 	if(aRecurringEntity.Length()==0)
       
   607 		{
       
   608 		CParserPropertyValue* value = new(ELeave) CParserPropertyValueRecurrence(NULL);
       
   609 		return value;
       
   610 		}
       
   611 		
       
   612 	// if there is no space between Event's interval (e.g. D1) and occurrence (e.g. #2), 
       
   613 	// i.e. for e.g. D1#2 then leave 
       
   614 	TInt posSpace=aRecurringEntity.Locate(ESpace);
       
   615 	TInt posNumSign=aRecurringEntity.Locate(KVersitRecurrenceNumberOfVal);
       
   616 	if(posSpace==KErrNotFound && posNumSign!=KErrNotFound)
       
   617 		{
       
   618 		User::Leave(KVersitErrBadRepeatValue);
       
   619 		}
       
   620 	//Extract the first part - Recurrence Type	
       
   621 	TPtrC recurrEntity(aRecurringEntity);
       
   622 	TPtrC recurrenceType;
       
   623 	if(posSpace==KErrNotFound)
       
   624 		{
       
   625 		recurrenceType.Set(recurrEntity.Left(aRecurringEntity.Length()));
       
   626 		}
       
   627 	else
       
   628 		{
       
   629 		recurrenceType.Set(recurrEntity.Left(posSpace));
       
   630 		}
       
   631 
       
   632 	if(recurrenceType.Length()<2)
       
   633 		{
       
   634 		// Only one letter for iRecurrenceType is not acceptable.
       
   635 		User::Leave(KVersitErrBadRepeatValue);
       
   636 		}
       
   637 
       
   638 	// if occurrence is not specified i.e. only D<n> specified, not D<n> #<n>
       
   639 	// then by vcal specification default occurrence value should be 2
       
   640 	TInt len=aRecurringEntity.Length()-posSpace-1;
       
   641 	_LIT(KVersitRecurrenceDefVal, "#2");
       
   642 	TPtr restString((TPtr &)KVersitRecurrenceDefVal);
       
   643 
       
   644 	//if occurrence is specified the extract from Recurring Rule
       
   645 	if(posSpace!=KErrNotFound) 
       
   646 		{
       
   647 		restString.Set(&aRecurringEntity[posSpace+1],len,len);
       
   648 		}
       
   649 
       
   650 	posSpace=restString.LocateReverse(ESpace);
       
   651 	TBool dateTimeAtEnd=EFalse;
       
   652 	TBool numCurrenceAtEnd=EFalse;
       
   653 	TBool thereIsADateList=ETrue;
       
   654 	len=restString.Length()-posSpace-1;
       
   655 	TPtr dateTime(&restString[posSpace+1],len,len);
       
   656 	if(dateTime.Length()>14)
       
   657 		{
       
   658 		dateTimeAtEnd=ETrue;
       
   659 		if (posSpace==KErrNotFound)
       
   660 			restString.Set(NULL,0,0);
       
   661 		else
       
   662 			restString.Set(&restString[0],posSpace,posSpace);
       
   663 		}
       
   664 	else 
       
   665 		{
       
   666 		//Ensure that dateTime is a time parameter, and not a weekday.
       
   667 		//This is true if the sequence length is greater than two
       
   668 		//characters, and the sequence begins with 'T'
       
   669 		TInt posTimeDelimeter=dateTime.Locate(KVersitTimePeriodTimeVal);
       
   670 		if(posTimeDelimeter == 0 && dateTime.Length() > 2)
       
   671 			{
       
   672 			//we want to strip off this date from 
       
   673 			if(posSpace==KErrNotFound)
       
   674 				restString.Set(NULL,0,0);
       
   675 			else
       
   676 				restString.Set(&restString[0],posSpace,posSpace);
       
   677 			}
       
   678 		}
       
   679 	TPtrC numCurrence;
       
   680 	TPtrC dateList;//use null string
       
   681 	if (restString.Length()>0)
       
   682 		{
       
   683 		posSpace=restString.Locate(KVersitRecurrenceNumberOfVal);
       
   684 		if(posSpace >= 0)
       
   685 			{
       
   686 			numCurrenceAtEnd=ETrue;
       
   687 			if(posSpace>restString.Length()-2)
       
   688 				User::Leave(KVersitErrBadRepeatValue);
       
   689 			numCurrence.Set(restString.Mid(posSpace+1));
       
   690 			}
       
   691 		if(posSpace > 1)
       
   692 			{
       
   693 			len=posSpace-1;
       
   694 			restString.Set(&restString[0],len,len);//there is space before '#'
       
   695 			}
       
   696 		else
       
   697 			thereIsADateList=(posSpace==KErrNotFound);
       
   698 		}
       
   699 	else
       
   700 		thereIsADateList=EFalse;
       
   701 	if(thereIsADateList)
       
   702 		{
       
   703 		dateList.Set(restString);
       
   704 		}
       
   705 	CVersitRecurrence::TType repeatType;
       
   706 	TInt interval;
       
   707 	GetFrequencyAndIntervalL(repeatType,interval,recurrenceType);//parse first part, such as W2,D1,YM1...
       
   708 	CVersitRecurrence* recurrence = GetFrequencyModifiersL(repeatType,interval,dateList/*dateListConcatenated*/);//parse the second part such as "1TH TU 2 WE"
       
   709 	CleanupStack::PushL(recurrence);
       
   710 	
       
   711 	// set duration and enddate values
       
   712 	if(numCurrenceAtEnd)
       
   713 		{
       
   714 		TInt numChar;
       
   715 		recurrence->iDuration = GetNumberL(numCurrence,numChar);
       
   716 		}
       
   717 	if(dateTimeAtEnd)
       
   718 		// Coverity doesn't acknowledge member assignment as leave safe
       
   719 		// coverity[alloc_fn] coverity[assign]
       
   720 		recurrence->iEndDate=DecodeDateTimeL(dateTime);
       
   721 
       
   722 	// no duration (#n) and no end date implies duration = #2
       
   723 	if ( !(numCurrenceAtEnd || dateTimeAtEnd) )
       
   724 		{
       
   725 		recurrence->iDuration = 2; 
       
   726 		}
       
   727 
       
   728 	// coverity[leave_without_push]
       
   729 	CParserPropertyValue* value = new(ELeave) CParserPropertyValueRecurrence(recurrence);
       
   730 	CleanupStack::Pop(recurrence);
       
   731 	return value;
       
   732 	}
       
   733 
       
   734 void CRecurrenceParser::ResetAndDestroyArrayOfMonthPositions(TAny* aObject)	
       
   735 	{
       
   736 	CArrayPtr<CVersitRecurrenceMonthlyByPos::CMonthPosition>* array=REINTERPRET_CAST(CArrayPtr<CVersitRecurrenceMonthlyByPos::CMonthPosition>*,aObject);
       
   737 	if (array)
       
   738 		array->ResetAndDestroy();
       
   739 	delete array;
       
   740 	}
       
   741 
       
   742 // For interoperability with Nokia 9110's incorrectly specified
       
   743 // vCalendar repeat rules a check is made after matching a 'M' or 'Y'
       
   744 // character that the next character isn't the repeat interval.  See
       
   745 // defects EDNCDUG-4FXPKP and EDNCDUG-4FXRAA (Symbian defect tracking v3)
       
   746 // for more detail.
       
   747 //
       
   748 void CRecurrenceParser::GetFrequencyAndIntervalL(CVersitRecurrence::TType& aFrequency,TInt& aInterval, const TDesC& aRecurrenceType)
       
   749 	{
       
   750 	TInt position = 0;
       
   751 	const TUint type = aRecurrenceType[position];
       
   752 	TPtrC recMonthlyByPos(KVersitRecurrenceMonthlyByPos);//MP
       
   753 	TPtrC recYearlyByDay(KVersitRecurrenceYearlyByDay);//YD
       
   754 	if (type == KVersitRecurrenceDailyVal)
       
   755 		{
       
   756 		position++;
       
   757 		aFrequency = CVersitRecurrence::EDaily;
       
   758 		}
       
   759 	else if (type == KVersitRecurrenceWeeklyVal)
       
   760 		{
       
   761 		position++;
       
   762 		aFrequency = CVersitRecurrence::EWeekly;
       
   763 		}
       
   764 	else if (type == recMonthlyByPos[0])
       
   765 		{
       
   766 		position++;
       
   767 		if (aRecurrenceType[position] == recMonthlyByPos[position])
       
   768 			aFrequency = CVersitRecurrence::EMonthlyByPos;
       
   769 		else
       
   770 			aFrequency = CVersitRecurrence::EMonthlyByDay;
       
   771 		TChar nextChar = aRecurrenceType[position];
       
   772 		if (!nextChar.IsDigit())
       
   773 			position++;
       
   774 		}
       
   775 	else if (type == recYearlyByDay[0])
       
   776 		{
       
   777 		position++;
       
   778 		if (aRecurrenceType[position] == recYearlyByDay[position])
       
   779 			aFrequency = CVersitRecurrence::EYearlyByDay;
       
   780 		else
       
   781 			aFrequency = CVersitRecurrence::EYearlyByMonth;
       
   782 		TChar nextChar = aRecurrenceType[position];
       
   783 		if (!nextChar.IsDigit())
       
   784 			position++;
       
   785 		}
       
   786 	else
       
   787 		User::Leave(KVersitErrRepeatTypeNotHandled);
       
   788 	TInt numChars;
       
   789 	aInterval = GetNumberL(aRecurrenceType.Mid(position),numChars);
       
   790 	}
       
   791 
       
   792 CVersitRecurrence* CRecurrenceParser::GetFrequencyModifiersL(const CVersitRecurrence::TType& aRepeatType,TInt aInterval, const TDesC& aListDates)
       
   793 	{
       
   794 	CVersitRecurrence* recurrence = NULL;
       
   795 	switch (aRepeatType)
       
   796 		{
       
   797 		case CVersitRecurrence::EDaily:
       
   798 			recurrence = new(ELeave)CVersitRecurrenceDaily(aInterval, 0, 0);
       
   799 			break;
       
   800 		case CVersitRecurrence::EWeekly:
       
   801 			{
       
   802 			CWeekDayArray* weekDays=GetListOfWeekDayOccurrencesL(aListDates);
       
   803 			CleanupStack::PushL(weekDays);
       
   804 			recurrence = new(ELeave)CVersitRecurrenceWeekly(aInterval, 0, 0, weekDays);
       
   805 			CleanupStack::Pop(weekDays);
       
   806 			}
       
   807 			break;
       
   808 		case CVersitRecurrence::EMonthlyByPos:
       
   809 			{
       
   810 			CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>* monthPositions
       
   811 				= new(ELeave) CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>(5);
       
   812 			CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfMonthPositions, monthPositions));
       
   813 			CPtrCArray* array =new(ELeave)CPtrC16Array(5);//each of them is something like "1 TH TU"
       
   814 			CleanupStack::PushL(array);//
       
   815 			TInt i;
       
   816 			TInt lastDigitPos=0;
       
   817 			TInt length=aListDates.Length();
       
   818 			if (length>0)
       
   819 				{
       
   820 				for(i=1;i<length;i++)
       
   821 					{//the first digit is not we after, eg. "1+ MO 2+ TU 3+ WE #10", the first digit we are looking for is "2" and the first element of the array is "1+ MO"
       
   822 					if(((TChar)aListDates[i]).IsDigit())
       
   823 						{
       
   824 						if(i-lastDigitPos==1)
       
   825 							User::Leave(KVersitErrBadRepeatValue);
       
   826 						array->AppendL(aListDates.Mid(lastDigitPos,i-lastDigitPos));
       
   827 						lastDigitPos=i;
       
   828 						}
       
   829 					}
       
   830 				if(lastDigitPos!=length-1)
       
   831 					array->AppendL(aListDates.Mid(lastDigitPos));
       
   832 				}
       
   833 			TInt count=array->Count();
       
   834 			for(i=0;i<count;i++)
       
   835 				{
       
   836 				CVersitRecurrenceMonthlyByPos::CMonthPosition* newMonthPosition=new(ELeave)CVersitRecurrenceMonthlyByPos::CMonthPosition;
       
   837 				CleanupStack::PushL(newMonthPosition);//
       
   838 				TInt posSpace=((*array)[i].Locate(ESpace));
       
   839 				TPtrC weekNo((*array)[i]);
       
   840 				TPtrC dayList;
       
   841 				if(posSpace!=KErrNotFound)
       
   842 					{
       
   843 					weekNo.Set((*array)[i].Left(posSpace));
       
   844 					if(posSpace!=(*array)[i].Length()-1)//space is not the last char
       
   845 						{
       
   846 						dayList.Set((*array)[i].Mid(posSpace+1));
       
   847 						}
       
   848 					}
       
   849 				else
       
   850 					User::Leave(KVersitErrBadRepeatValue);
       
   851 				if ((TChar)weekNo[weekNo.Length()-1]==KVersitTokenMinusVal)
       
   852 					newMonthPosition->iSign=CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromEndOfMonth;
       
   853 				else
       
   854 					newMonthPosition->iSign=CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromStartOfMonth;
       
   855 				TInt numChars;
       
   856 				newMonthPosition->iWeekNo=GetNumberL((*array)[i],numChars); //1-5
       
   857 				if ((newMonthPosition->iWeekNo<6)&&(newMonthPosition->iWeekNo>0))
       
   858 					{
       
   859 					newMonthPosition->iArrayOfWeekDays=GetListOfWeekDayOccurrencesL(dayList);
       
   860 					if(newMonthPosition->iArrayOfWeekDays)
       
   861 						{
       
   862 						monthPositions->AppendL(newMonthPosition);
       
   863 						CleanupStack::Pop(newMonthPosition); //
       
   864 						}
       
   865 					else
       
   866 						CleanupStack::PopAndDestroy(newMonthPosition);
       
   867 					}
       
   868 				else
       
   869 					CleanupStack::PopAndDestroy(newMonthPosition); //
       
   870 
       
   871 				}
       
   872 			CleanupStack::PopAndDestroy(array);//
       
   873 			recurrence=new(ELeave)CVersitRecurrenceMonthlyByPos(aInterval,0,0,monthPositions);
       
   874 			CleanupStack::Pop(monthPositions); // 
       
   875 			break;
       
   876 			}
       
   877 		case CVersitRecurrence::EMonthlyByDay:
       
   878 			{
       
   879 			CArrayFix<TInt>* arrayOfOccurrencesInDaysFromStartOfMonth=new(ELeave)CArrayFixFlat<TInt>(3);
       
   880 			CleanupStack::PushL(arrayOfOccurrencesInDaysFromStartOfMonth);
       
   881 			CArrayFix<TInt>* arrayOfOccurrencesInDaysFromEndOfMonth=new(ELeave)CArrayFixFlat<TInt>(3);
       
   882 			CleanupStack::PushL(arrayOfOccurrencesInDaysFromEndOfMonth);
       
   883 			TBool lastDay=EFalse;
       
   884 
       
   885 			TPtrC restdates(aListDates);
       
   886 			TPtrC date(aListDates);
       
   887 			TInt posSpace=0;
       
   888 			TInt i=0;
       
   889 			TInt length=aListDates.Length();
       
   890 
       
   891 			while(i<length&&(posSpace!=KErrNotFound))
       
   892 				{
       
   893 				i++;
       
   894 				posSpace=restdates.Locate(ESpace);
       
   895 				if(posSpace>0)
       
   896 					{
       
   897 					date.Set(restdates.Left(posSpace));
       
   898 					if(posSpace<restdates.Length()-1)
       
   899 						restdates.Set(restdates.Mid(posSpace+1));
       
   900 					else
       
   901 						posSpace=KErrNotFound;
       
   902 					}
       
   903 				else
       
   904 					{
       
   905 					date.Set(restdates);
       
   906 					posSpace=KErrNotFound;
       
   907 					}
       
   908 
       
   909 				if(TChar(date[0]).IsDigit())
       
   910 					{
       
   911 					TInt numChar;
       
   912 					if (aListDates[date.Length()-1]==KVersitTokenMinusVal)
       
   913 						arrayOfOccurrencesInDaysFromEndOfMonth->AppendL(GetNumberL(date,numChar));
       
   914 					else
       
   915 						arrayOfOccurrencesInDaysFromStartOfMonth->AppendL(GetNumberL(date,numChar));
       
   916 					}
       
   917 				else if (date.CompareC(KVersitRecurrenceLastDay))//LD
       
   918 					lastDay=ETrue;
       
   919 				}
       
   920 
       
   921 			if (arrayOfOccurrencesInDaysFromStartOfMonth->Count())
       
   922 				{
       
   923 				if (arrayOfOccurrencesInDaysFromEndOfMonth->Count())
       
   924 					{
       
   925 					recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, arrayOfOccurrencesInDaysFromStartOfMonth, arrayOfOccurrencesInDaysFromEndOfMonth, lastDay);
       
   926 					CleanupStack::Pop(2,arrayOfOccurrencesInDaysFromStartOfMonth); // 
       
   927 					}
       
   928 				else
       
   929 					{
       
   930 					recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, arrayOfOccurrencesInDaysFromStartOfMonth, NULL, lastDay);
       
   931 					CleanupStack::PopAndDestroy(); // 
       
   932 					arrayOfOccurrencesInDaysFromEndOfMonth = NULL;
       
   933 					CleanupStack::Pop(arrayOfOccurrencesInDaysFromStartOfMonth); // 
       
   934 					}
       
   935 				}
       
   936 			else
       
   937 				{
       
   938 				if (arrayOfOccurrencesInDaysFromEndOfMonth->Count())
       
   939 					{
       
   940 					recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, NULL, arrayOfOccurrencesInDaysFromEndOfMonth, lastDay);
       
   941 					CleanupStack::Pop(arrayOfOccurrencesInDaysFromEndOfMonth); // 
       
   942 					}
       
   943 				else										
       
   944 					{
       
   945 					recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, NULL, NULL, lastDay);
       
   946 					CleanupStack::PopAndDestroy(arrayOfOccurrencesInDaysFromEndOfMonth); // 
       
   947 					arrayOfOccurrencesInDaysFromEndOfMonth = NULL;
       
   948 					}
       
   949 				CleanupStack::PopAndDestroy(arrayOfOccurrencesInDaysFromStartOfMonth); // 
       
   950 				arrayOfOccurrencesInDaysFromStartOfMonth = NULL;
       
   951 				}			
       
   952 			break;
       
   953 			}
       
   954 		case CVersitRecurrence::EYearlyByMonth:
       
   955 			{
       
   956 			CArrayFix<TMonth>* arrayOfMonthInYearOccurrences=new(ELeave)CArrayFixFlat<TMonth>(3);
       
   957 			CleanupStack::PushL(arrayOfMonthInYearOccurrences);
       
   958 			TInt month;
       
   959 			TInt length=aListDates.Length();
       
   960 			TPtrC restdates(aListDates);
       
   961 			TPtrC date(aListDates);
       
   962 			TInt posSpace=0;
       
   963 			TInt i=0;
       
   964 			while(i<length&&(posSpace!=KErrNotFound))
       
   965 				{
       
   966 				i++;
       
   967 				posSpace=restdates.Locate(ESpace);
       
   968 				if(posSpace>0)
       
   969 					{
       
   970 					date.Set(restdates.Left(posSpace));
       
   971 					if(posSpace<restdates.Length()-1)
       
   972 						restdates.Set(restdates.Mid(posSpace+1));
       
   973 					else
       
   974 						posSpace=KErrNotFound;
       
   975 					}
       
   976 				else
       
   977 					{
       
   978 					date.Set(restdates);
       
   979 					posSpace=KErrNotFound;
       
   980 					}
       
   981 				if(TChar(date[0]).IsDigit())
       
   982 					{
       
   983 					TInt numChars;
       
   984 					month = GetNumberL(date,numChars);
       
   985 					if ((month > 0) && (month < 13))
       
   986 						arrayOfMonthInYearOccurrences->AppendL(TMonth(month - 1));
       
   987 					}
       
   988 				}
       
   989 
       
   990 			if (arrayOfMonthInYearOccurrences->Count())
       
   991 				{
       
   992 				recurrence = new(ELeave)CVersitRecurrenceYearlyByMonth(aInterval, 0, 0, arrayOfMonthInYearOccurrences);
       
   993 				CleanupStack::Pop(arrayOfMonthInYearOccurrences); //
       
   994 				}
       
   995 			else
       
   996 				{
       
   997 				recurrence = new(ELeave)CVersitRecurrenceYearlyByMonth(aInterval, 0, 0, NULL);
       
   998 				CleanupStack::PopAndDestroy(arrayOfMonthInYearOccurrences); //
       
   999 				arrayOfMonthInYearOccurrences = NULL;
       
  1000 				}
       
  1001 			break;
       
  1002 			}
       
  1003 		case CVersitRecurrence::EYearlyByDay:
       
  1004 			{
       
  1005 			CArrayFix<TInt>* arrayOfDayInYearOccurrences=new(ELeave)CArrayFixFlat<TInt>(3);
       
  1006 			CleanupStack::PushL(arrayOfDayInYearOccurrences);
       
  1007 			TInt day;
       
  1008 			TInt length=aListDates.Length();
       
  1009 			TPtrC restdates(aListDates);
       
  1010 			TPtrC date(aListDates);
       
  1011 			TInt posSpace=0;
       
  1012 			TInt i=0;
       
  1013 			while(i<length&&(posSpace!=KErrNotFound))
       
  1014 				{
       
  1015 				i++;
       
  1016 				posSpace=restdates.Locate(ESpace);
       
  1017 				if(posSpace>0)
       
  1018 					{
       
  1019 					date.Set(restdates.Left(posSpace));
       
  1020 					if(posSpace<restdates.Length()-1)
       
  1021 						restdates.Set(restdates.Mid(posSpace+1));
       
  1022 					else
       
  1023 						posSpace=KErrNotFound;
       
  1024 					}
       
  1025 				else
       
  1026 					{
       
  1027 					date.Set(restdates);
       
  1028 					posSpace=KErrNotFound;
       
  1029 					}
       
  1030 				if(TChar(date[0]).IsDigit())
       
  1031 					{
       
  1032 					TInt numChars;
       
  1033 					day = GetNumberL(date,numChars);
       
  1034 					if ((day > 0) && (day < 366))
       
  1035 						arrayOfDayInYearOccurrences->AppendL(day);
       
  1036 					}
       
  1037 				}
       
  1038 			if (arrayOfDayInYearOccurrences->Count())
       
  1039 				{
       
  1040 				recurrence = new(ELeave)CVersitRecurrenceYearlyByDay(aInterval, 0, 0, arrayOfDayInYearOccurrences);
       
  1041 				CleanupStack::Pop(arrayOfDayInYearOccurrences); //arrayOfDayInYearOccurrences
       
  1042 				}
       
  1043 			else
       
  1044 				{
       
  1045 				recurrence = new(ELeave)CVersitRecurrenceYearlyByDay(aInterval, 0, 0, NULL);
       
  1046 				CleanupStack::PopAndDestroy(arrayOfDayInYearOccurrences); //arrayOfDayInYearOccurrences
       
  1047 				arrayOfDayInYearOccurrences = NULL;
       
  1048 				}
       
  1049 			break;
       
  1050 			}
       
  1051 		};
       
  1052 	return recurrence;
       
  1053 	}
       
  1054 
       
  1055 CWeekDayArray* CRecurrenceParser::GetListOfWeekDayOccurrencesL(const TDesC& aListDays)
       
  1056 	{
       
  1057 	if (aListDays.Length()==0)
       
  1058 		return NULL;
       
  1059 	CWeekDayArray* arrayOfWeekDayOccurrences = new(ELeave)CWeekDayArray;
       
  1060 	CleanupStack::PushL(arrayOfWeekDayOccurrences);
       
  1061 	arrayOfWeekDayOccurrences->iArray = new(ELeave)CArrayFixFlat<TDay>(3);
       
  1062 	TPtrC restdays(aListDays);
       
  1063 	TPtrC day(aListDays);
       
  1064 	TInt posSpace=0;
       
  1065 	while(posSpace!=KErrNotFound)
       
  1066 		{
       
  1067 		posSpace=restdays.Locate(ESpace);
       
  1068 		if(posSpace>0)
       
  1069 			{
       
  1070 			day.Set(restdays.Left(posSpace));
       
  1071 			if(posSpace<restdays.Length()-1)
       
  1072 				restdays.Set(restdays.Mid(posSpace+1));
       
  1073 			else
       
  1074 				posSpace=KErrNotFound;
       
  1075 			}
       
  1076 		else
       
  1077 			{
       
  1078 			day.Set(restdays);
       
  1079 			posSpace=KErrNotFound;
       
  1080 			}
       
  1081 		((TChar)day[0]).UpperCase();
       
  1082 		switch ((TChar)day[0])
       
  1083 			{
       
  1084 			case 'F':
       
  1085 				if (!day.CompareC(KVersitRecurrenceFriday))
       
  1086 					arrayOfWeekDayOccurrences->iArray->AppendL(EFriday);
       
  1087 				break;
       
  1088 			case 'M':
       
  1089 				if (!day.CompareC(KVersitRecurrenceMonday))
       
  1090 					arrayOfWeekDayOccurrences->iArray->AppendL(EMonday);
       
  1091 				break;
       
  1092 			case 'S':
       
  1093 				if (!day.CompareC(KVersitRecurrenceSaturday()))
       
  1094 					arrayOfWeekDayOccurrences->iArray->AppendL(ESaturday);
       
  1095 				else if (!day.CompareF(KVersitRecurrenceSunday))
       
  1096 					arrayOfWeekDayOccurrences->iArray->AppendL(ESunday);
       
  1097 				break;
       
  1098 			case 'T':
       
  1099 				if (!day.CompareC(KVersitRecurrenceTuesday))
       
  1100 					arrayOfWeekDayOccurrences->iArray->AppendL(ETuesday);
       
  1101 				else if (!day.CompareF(KVersitRecurrenceThursday))
       
  1102 					arrayOfWeekDayOccurrences->iArray->AppendL(EThursday);
       
  1103 				break;
       
  1104 			case 'W':
       
  1105 				if (!day.CompareC(KVersitRecurrenceWednesday))
       
  1106 					arrayOfWeekDayOccurrences->iArray->AppendL(EWednesday);
       
  1107 				break;
       
  1108 			default:
       
  1109 				User::Leave(KVersitErrBadRepeatValue);
       
  1110 			}
       
  1111 		}
       
  1112 	CleanupStack::Pop(arrayOfWeekDayOccurrences);
       
  1113 	if (arrayOfWeekDayOccurrences->iArray->Count())
       
  1114 		return arrayOfWeekDayOccurrences;
       
  1115 	delete arrayOfWeekDayOccurrences;
       
  1116 	return NULL;
       
  1117 	}
       
  1118 
       
  1119 EXPORT_C void CRecurrenceParser::Reserved1()
       
  1120 	{}
       
  1121 
       
  1122 EXPORT_C void CRecurrenceParser::Reserved2()
       
  1123 	{}