You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1417 lines
38 KiB
C++

// XTPCalendarRecurrencePattern.cpp: implementation of the CXTPCalendarRecurrencePattern class.
//
// This file is a part of the XTREME CALENDAR MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPPropExchange.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPVC80Helpers.h"
#include "XTPCalendarDefines.h"
#include "XTPCalendarUtils.h"
#include "XTPCalendarEvents.h"
#include "XTPCalendarEvent.h"
#include "XTPCalendarData.h"
#include "XTPCalendarRecurrencePattern.h"
#include "XTPCalendarCustomProperties.h"
static LPCTSTR cszRPatt_PatternID = _T("PatternID");
static LPCTSTR cszRPatt_StartTime = _T("StartTime");
static LPCTSTR cszRPatt_DurationMinutes = _T("DurationMinutes");
static LPCTSTR cszRPatt_RecurrenceType = _T("RecurrenceType");
static LPCTSTR cszRPatt_RecurrenceOpt_Data1 = _T("RecurrenceOpt_Data1");
static LPCTSTR cszRPatt_RecurrenceOpt_Data2 = _T("RecurrenceOpt_Data2");
static LPCTSTR cszRPatt_RecurrenceOpt_Data3 = _T("RecurrenceOpt_Data3");
static LPCTSTR cszRPatt_PatternStartDate = _T("PatternStartDate");
static LPCTSTR cszRPatt_UseEndMethod = _T("UseEndMethod");
static LPCTSTR cszRPatt_PatternEndDate = _T("PatternEndDate");
static LPCTSTR cszRPatt_EndAfterOccurrences = _T("EndAfterOccurrences");
static LPCTSTR cszRPatt_MasterEventID = _T("MasterEventID");
//===========================================================================
static const LPCTSTR cszOccRMD_Count = _T("*xtp*OccRMD_Count");
static const LPCTSTR cszOccRMD_StartTime = _T("*xtp*OccRMD_Start");
static const LPCTSTR cszOccRMD_EndTime = _T("*xtp*OccRMD_End");
static const LPCTSTR cszOccRMD_IsReminder = _T("*xtp*OccRMD_IsReminder");
static const LPCTSTR cszOccRMD_NextReminderTime_Snoozed = _T("*xtp*OccRMD_NextReminderTime_Snoozed");
//===========================================================================
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////////
#define XTP_RECPATT_PROP_SET_DATA_VER 1
////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CXTPCalendarRecurrencePattern, CCmdTarget)
/////////////////////////////////////////////////////////////////////////////
CXTPCalendarRecurrencePattern::CXTPCalendarRecurrencePattern(CXTPCalendarData* pDataProvider)
{
ASSERT(pDataProvider);
m_ptrDataProvider = pDataProvider;
CMDTARGET_ADDREF(m_ptrDataProvider);
m_dwPatternID = XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID;
m_dwMasterEventID = XTP_CALENDAR_UNKNOWN_EVENT_ID;
m_dtStartTime = (DATE)0; //.SetStatus(COleDateTime::null);
m_nDurationMinutes = 0;
m_Options.m_nRecurrenceType = xtpCalendarRecurrenceUnknown;
m_dtPatternStartDate = (DATE)0; //.SetStatus(COleDateTime::null);
m_pCustomProperties = new CXTPCalendarCustomProperties;
m_parExceptionEvents = new CXTPCalendarEvents();
}
CXTPCalendarRecurrencePattern::~CXTPCalendarRecurrencePattern()
{
CMDTARGET_RELEASE(m_ptrDataProvider);
CMDTARGET_RELEASE(m_pCustomProperties);
CMDTARGET_RELEASE(m_parExceptionEvents);
}
COleDateTime CXTPCalendarRecurrencePattern::GetStartOccurrenceTime(COleDateTime dtOccurrenceStartDate) const
{
COleDateTime dtStartOcc = GetStartTime();
dtStartOcc = CXTPCalendarUtils::UpdateDate(dtStartOcc, dtOccurrenceStartDate);
return dtStartOcc;
}
COleDateTime CXTPCalendarRecurrencePattern::GetEndOccurrenceTime(COleDateTime dtOccurrenceStartDate) const
{
COleDateTimeSpan spDuration = GetDuration();
COleDateTime dtEndOcc = GetStartOccurrenceTime(dtOccurrenceStartDate);
dtEndOcc += spDuration;
return dtEndOcc;
}
void CXTPCalendarRecurrencePattern::_GetOccurrenceStartEnd(const COleDateTime& dtOccStartDate, COleDateTime& rdtOccStart, COleDateTime& rdtOccEnd) const
{
rdtOccStart = GetStartTime();
rdtOccStart = CXTPCalendarUtils::UpdateDate(rdtOccStart, dtOccStartDate);
COleDateTimeSpan spDuration = GetDuration();
rdtOccEnd = rdtOccStart + spDuration;
}
void CXTPCalendarRecurrencePattern::SetPatternStartDate(COleDateTime dtStart)
{
m_dtPatternStartDate = CXTPCalendarUtils::ResetTime(dtStart);
if (m_dtPatternStartDate.GetStatus() == COleDateTime::valid &&
m_PatternEnd.m_dtPatternEndDate.GetStatus() == COleDateTime::valid &&
m_dtPatternStartDate > m_PatternEnd.m_dtPatternEndDate)
{
m_PatternEnd.m_dtPatternEndDate = m_dtPatternStartDate;
}
}
void CXTPCalendarRecurrencePattern::SetPatternEndDate(COleDateTime dtEnd)
{
m_PatternEnd.m_dtPatternEndDate = CXTPCalendarUtils::ResetTime(dtEnd);
m_PatternEnd.m_nUseEnd = xtpCalendarPatternEndDate;
if (m_dtPatternStartDate.GetStatus() == COleDateTime::valid &&
m_PatternEnd.m_dtPatternEndDate.GetStatus() == COleDateTime::valid &&
m_PatternEnd.m_dtPatternEndDate < m_dtPatternStartDate)
{
m_dtPatternStartDate = m_PatternEnd.m_dtPatternEndDate;
}
}
BOOL CXTPCalendarRecurrencePattern::GetOccurrences(CXTPCalendarEvents* pEventsArray,
COleDateTime dtStart, COleDateTime dtEnd,
CXTPCalendarEvent* pMasterEvent)
{
if (!pMasterEvent || !pEventsArray)
{
ASSERT(FALSE);
return FALSE;
}
COleDateTime dtStartOcc, dtEndOcc;
_GetOccurrenceStartEnd(dtStart, dtStartOcc, dtEndOcc);
int nOccDays = CXTPCalendarUtils::GetEventPeriodDays(dtStartOcc, dtEndOcc);
ASSERT(nOccDays > 0);
nOccDays = max(1, nOccDays);
COleDateTime dtStartCheckOcc = dtStart;
if (dtStart == dtEnd)
{
//- check for previous multiday occurrences ---
if (nOccDays > 1)
{
COleDateTimeSpan spCheckMDOcc(nOccDays - 1, 0, 0, 0);
dtStartCheckOcc = dtStart - spCheckMDOcc;
}
}
CXTPCalendarDatesArray arDates;
GetOccurrencesDates(arDates, dtStartCheckOcc, dtEnd);
COleDateTime dtI;
int nCount = (int) arDates.GetSize();
for (int i = 0; i < nCount; i++)
{
dtI = arDates[i];
_GetOccurrenceStartEnd(dtI, dtStartOcc, dtEndOcc);
ASSERT(!(CXTPCalendarUtils::ResetTime(dtEndOcc) < CXTPCalendarUtils::ResetTime(dtStart) ||
CXTPCalendarUtils::ResetTime(dtStartOcc) > CXTPCalendarUtils::ResetTime(dtEnd)));
CXTPCalendarEventPtr ptrOccurrenceEvent(FindException(dtStartOcc, dtEndOcc), TRUE);
if (ptrOccurrenceEvent)
{
continue;
}
else
{
ptrOccurrenceEvent = pMasterEvent->CloneForOccurrence(dtStartOcc, dtEndOcc);
if (ptrOccurrenceEvent && ptrOccurrenceEvent->GetStartTime() <
pMasterEvent->GetLastModificationTime())
{
ptrOccurrenceEvent->SetReminder(FALSE);
}
}
if (ptrOccurrenceEvent)
{
m_arOccReminders.UpdateOccIfNeed(ptrOccurrenceEvent, this);
pEventsArray->Add(ptrOccurrenceEvent);
}
}
FindExceptions(pEventsArray, dtStart, dtEnd);
return TRUE;
}
void CXTPCalendarRecurrencePattern::GetOccurrencesDates(CXTPCalendarDatesArray& rArDates,
COleDateTime dtStart, COleDateTime dtEnd) const
{
COleDateTime dtStart0 = CXTPCalendarUtils::ResetTime(dtStart);
COleDateTime dtEnd0 = CXTPCalendarUtils::SetTime_235959(dtEnd);
int nMaxOccCount = INT_MAX;
int nOccCount = 0;
COleDateTime dtI;
COleDateTime dtE1(9999, 1, 1, 0, 0, 0);
COleDateTime dtS1 = max(dtStart0, m_dtPatternStartDate);
CString s;
switch (m_PatternEnd.m_nUseEnd)
{
case xtpCalendarPatternEndDate:
dtE1 = min(m_PatternEnd.m_dtPatternEndDate, dtEnd0);
break;
case xtpCalendarPatternEndAfterOccurrences:
nMaxOccCount = m_PatternEnd.m_nEndAfterOccurrences;
dtE1 = dtEnd0;
break;
case xtpCalendarPatternEndNoDate:
dtE1 = dtEnd0;
break;
default:
ASSERT(FALSE);
return;
}
switch (m_Options.m_nRecurrenceType)
{
case xtpCalendarRecurrenceDaily:
{
//------------------------------------------------------
// 1. Every N days:
// m_nInterval = N,
// m_nDayOfWeekMask = xtpCalendarDayAllWeek
//------------------------------------------------------
// 2. Every week day (Mo-Fr):
// m_nInterval = 1,
// m_nDayOfWeekMask = xtpCalendarDayMo_Fr
//------------------------------------------------------
int nDays = m_Options.m_Daily.nIntervalDays;
if (m_Options.m_Daily.bEveryWeekDayOnly)
{
ASSERT(nDays == 1);
nDays = 1;
}
COleDateTimeSpan spStep(nDays, 0, 0, 0);
if (m_dtPatternStartDate < dtStart0)
{
//--- shift start date --------------
COleDateTimeSpan spDiff = dtStart0 - m_dtPatternStartDate;
int nDiff_Days = (int)CXTPCalendarUtils::GetTotalDays(spDiff);
ASSERT(nDiff_Days >= 1);
int nJump_Days = (nDiff_Days / nDays) * nDays;
spDiff.SetDateTimeSpan(nJump_Days, 0, 0, 0);
dtS1 = m_dtPatternStartDate + spDiff;
if (dtS1 < dtStart0)
{
dtS1 += spStep;
}
//--- calculate occurrences ----------
if (nMaxOccCount != INT_MAX)
{
nOccCount = nDiff_Days / nDays;
if (m_Options.m_Daily.bEveryWeekDayOnly)
{
int nWDstart = m_dtPatternStartDate.GetDayOfWeek();
int nBasis1_days = (nDiff_Days - (7 - nWDstart));
int nSatDays = nBasis1_days / 7 + ((nBasis1_days % 7) ? 1 : 0);
int nBasis6_days = (nDiff_Days - (6 - nWDstart));
int nSunDays = nBasis6_days / 7 + ((nBasis6_days % 7) ? 1 : 0);
nOccCount -= nSatDays + nSunDays;
}
}
}
else
{
dtS1 = m_dtPatternStartDate;
}
for (dtI = dtS1; dtI <= dtE1 && nOccCount < nMaxOccCount; dtI += spStep)
{
if (m_Options.m_Daily.bEveryWeekDayOnly)
{
int nWD = dtI.GetDayOfWeek(); // 1-Sunday, 2 - Monday, ...
if (nWD == 1 || nWD == 7)
{
continue;
}
}
ASSERT(dtI >= dtStart0 && dtI <= dtE1);
rArDates.Add(dtI);
nOccCount++;
}
}
break;
case xtpCalendarRecurrenceWeekly:
{
//------------------------------------------------------
// 1. Every N weeks:
// m_nInterval = N,
// m_nDayOfWeekMask = <*MASK*>
//------------------------------------------------------
int nWeeksStep = m_Options.m_Weekly.nIntervalWeeks;
if (nWeeksStep <= 0)
{
ASSERT(FALSE);
nWeeksStep = 1;
}
COleDateTimeSpan spStep(1, 0, 0, 0);
COleDateTimeSpan spStepWeeks((nWeeksStep)*7, 0, 0, 0);
int nFirstDayOfWeekIndex = 2; // Always Monday (as in MS Outlook)
COleDateTimeSpan spWeek(7, 0, 0, 0);
COleDateTime dtPatSW = CXTPCalendarUtils::ShiftDateToWeekBegin(m_dtPatternStartDate, nFirstDayOfWeekIndex);
dtPatSW = CXTPCalendarUtils::ResetTime(dtPatSW);
COleDateTime dtOccFrame1 = dtPatSW;
COleDateTime dtOccFrame2 = dtOccFrame1 + spWeek;
if (m_dtPatternStartDate < dtStart0)
{
int nPatDW = m_dtPatternStartDate.GetDayOfWeek();
int nMask = CXTPCalendarUtils::MakeDaysOfWeekMask_Mo_(nPatDW);
COleDateTime dtStart0SW = CXTPCalendarUtils::ShiftDateToWeekBegin(dtStart0, nFirstDayOfWeekIndex);
COleDateTimeSpan spDiff = dtStart0SW - dtPatSW;
int nDiff_Weeks = (int)spDiff.GetTotalDays() / 7;
ASSERT((int)spDiff.GetTotalDays() % 7 == 0);
int nJump_Weeks = (nDiff_Weeks / nWeeksStep) * nWeeksStep;
spDiff.SetDateTimeSpan(nJump_Weeks * 7, 0, 0, 0);
dtOccFrame1 = dtPatSW + spDiff;
dtOccFrame2 = dtOccFrame1 + spWeek;
//s.Format(_T("nOccCount=%d nMaxOccCount=%d nDiff_Weeks=%d nJump_Weeks=%d nPatDW=%d nMask=%d\n"), nOccCount, nMaxOccCount, nDiff_Weeks, nJump_Weeks, nPatDW, nMask);
//TRACE(s);
//BOOL a[7];
//for (int i = 1; i <= 7; i++)
//{
// int nTestMask = 1 << (i - 1);
// if (nTestMask & m_Options.m_Weekly.nDayOfWeekMask)
// a[i - 1] = TRUE;
// else
// a[i - 1] = FALSE;
//}
int nDW = CXTPCalendarUtils::GetDayOfWeekCount(m_Options.m_Weekly.nDayOfWeekMask);
if (nMask)
{
nOccCount = nDW;
nOccCount *= nJump_Weeks / nWeeksStep;
}
int nSkippedMask = CXTPCalendarUtils::MakeDaysOfWeekMask_Mo_(m_dtPatternStartDate.GetDayOfWeek());
nOccCount -= CXTPCalendarUtils::GetDayOfWeekCount(nSkippedMask & m_Options.m_Weekly.nDayOfWeekMask);
int nAddedMask = CXTPCalendarUtils::MakeDaysOfWeekMask_Mo_(dtS1.GetDayOfWeek());
nOccCount += CXTPCalendarUtils::GetDayOfWeekCount(nAddedMask & m_Options.m_Weekly.nDayOfWeekMask);
}
for (dtI = dtS1; dtI <= dtE1 && nOccCount < nMaxOccCount; dtI += spStep)
{
if (nWeeksStep > 1 && !(dtOccFrame1 <= dtI && dtI < dtOccFrame2))
{
dtOccFrame1 += spStepWeeks;
dtOccFrame2 = dtOccFrame1 + spWeek;
dtI = dtOccFrame1 - spStep;
continue;
}
int nWD = dtI.GetDayOfWeek(); // 1-Sunday, 2 - Monday, ...
int nWDMask = CXTPCalendarUtils::GetDayOfWeekMask(nWD);
if (m_Options.m_Weekly.nDayOfWeekMask & nWDMask)
{
ASSERT(dtI >= dtStart0 && dtI <= dtE1);
rArDates.Add(dtI);
nOccCount++;
}
}
}
break;
case xtpCalendarRecurrenceMonthly:
{
//------------------------------------------------------
// 1. Day N of every M month(s):
// m_nDayOfMonth = N,
// m_nInterval = M
//------------------------------------------------------
int nMInterval = m_Options.m_Monthly.nIntervalMonths;
if (nMInterval <= 0)
{
ASSERT(FALSE);
nMInterval = 1;
}
COleDateTime dtOccFrame1 = CXTPCalendarUtils::ResetTime(m_dtPatternStartDate);
CXTPCalendarUtils::UpdateMonthDay(dtOccFrame1, 1);
if (m_dtPatternStartDate < dtStart0)
{
int nPS_Year = m_dtPatternStartDate.GetYear();
int nPS_Month = m_dtPatternStartDate.GetMonth();
int nPS_GlobalMonth = nPS_Year * 12 + nPS_Month;
int nS0_Year = dtStart0.GetYear();
int nS0_Month = dtStart0.GetMonth();
int nS0_GlobalMonth = nS0_Year * 12 + nS0_Month;
int nMonthDiff = nS0_GlobalMonth - nPS_GlobalMonth;
int nJump_Month = (nMonthDiff / nMInterval) * nMInterval;
CXTPCalendarUtils::ShiftDate_Month(dtOccFrame1, nJump_Month, 1);
nOccCount = nJump_Month / nMInterval;
if (m_dtPatternStartDate.GetDay() > m_Options.m_Monthly.nDayOfMonth)
nOccCount--;
if (dtS1.GetDay() > m_Options.m_Monthly.nDayOfMonth)
nOccCount++;
}
COleDateTime dtOcc(dtOccFrame1);
VERIFY(CXTPCalendarUtils::UpdateMonthDay(dtOcc, m_Options.m_Monthly.nDayOfMonth));
if (dtOcc >= dtS1)
{
dtS1 = dtOcc;
}
else
{
dtS1 = dtOcc;
CXTPCalendarUtils::ShiftDate_Month(dtS1, m_Options.m_Monthly.nIntervalMonths,
m_Options.m_Monthly.nDayOfMonth);
}
for (dtI = dtS1; dtI <= dtE1 && nOccCount < nMaxOccCount;)
{
ASSERT(dtI >= dtStart0 && dtI <= dtE1);
rArDates.Add(dtI);
nOccCount++;
CXTPCalendarUtils::ShiftDate_Month(dtI, m_Options.m_Monthly.nIntervalMonths,
m_Options.m_Monthly.nDayOfMonth);
}
}
break;
case xtpCalendarRecurrenceMonthNth:
{
//------------------------------------------------------
//~ The I:{First, second, ..., Last>
//~ W:{Day, WeekDay, WeekEndDay, Su, Mo, ...}
//~ of every M month(s):
//------------------------------------------------------
int nMInterval = m_Options.m_MonthNth.nIntervalMonths;
if (nMInterval <= 0)
{
ASSERT(FALSE);
nMInterval = 1;
}
COleDateTime dtOccFrame1 = CXTPCalendarUtils::ResetTime(m_dtPatternStartDate);
CXTPCalendarUtils::UpdateMonthDay(dtOccFrame1, 1);
if (m_dtPatternStartDate < dtStart0)
{
int nPS_Year = m_dtPatternStartDate.GetYear();
int nPS_Month = m_dtPatternStartDate.GetMonth();
int nPS_GlobalMonth = nPS_Year * 12 + nPS_Month;
int nS0_Year = dtStart0.GetYear();
int nS0_Month = dtStart0.GetMonth();
int nS0_GlobalMonth = nS0_Year * 12 + nS0_Month;
int nMonthDiff = nS0_GlobalMonth - nPS_GlobalMonth;
int nJump_Month = (nMonthDiff / nMInterval) * nMInterval;
CXTPCalendarUtils::ShiftDate_Month(dtOccFrame1, nJump_Month, 1);
nOccCount = nJump_Month / nMInterval;
COleDateTime dtTestMD(m_dtPatternStartDate);
CXTPCalendarUtils::CalcDayOfMonth(dtTestMD,
m_Options.m_MonthNth.nWhichDay,
m_Options.m_MonthNth.nWhichDayMask);
if (m_dtPatternStartDate.GetDay() > dtTestMD.GetDay())
{
nOccCount--;
}
dtTestMD = dtS1;
CXTPCalendarUtils::CalcDayOfMonth(dtTestMD,
m_Options.m_MonthNth.nWhichDay,
m_Options.m_MonthNth.nWhichDayMask);
if (dtS1.GetDay() > dtTestMD.GetDay())
{
nOccCount++;
}
}
COleDateTime dtOcc(dtOccFrame1);
BOOL bRes = CXTPCalendarUtils::CalcDayOfMonth(dtOcc, m_Options.m_MonthNth.nWhichDay,
m_Options.m_MonthNth.nWhichDayMask);
if (!bRes)
{
return;
}
if (dtOcc >= dtS1)
{
dtS1 = dtOcc;
}
else
{
dtS1 = dtOcc;
CXTPCalendarUtils::ShiftDate_Month(dtS1, nMInterval);
bRes = CXTPCalendarUtils::CalcDayOfMonth(dtS1, m_Options.m_MonthNth.nWhichDay,
m_Options.m_MonthNth.nWhichDayMask);
if (!bRes)
{
return;
}
}
for (dtI = dtS1; dtI <= dtE1 && nOccCount < nMaxOccCount;)
//for (dtI = dtS1; dtI >= dtStart0 && dtI <= dtE1 && nOccCount < nMaxOccCount;)
{
ASSERT(dtI >= dtStart0 && dtI <= dtE1);
rArDates.Add(dtI);
nOccCount++;
CXTPCalendarUtils::ShiftDate_Month(dtI, nMInterval);
bRes = CXTPCalendarUtils::CalcDayOfMonth(dtI,
m_Options.m_MonthNth.nWhichDay,
m_Options.m_MonthNth.nWhichDayMask);
if (!bRes)
{
ASSERT(FALSE);
break;
}
}
}
break;
case xtpCalendarRecurrenceYearly:
{
//------------------------------------------------------
// Every M:{month} D:{Day}
// m_nMonthOfYear = M
// m_nDayOfMonth = D
//------------------------------------------------------
COleDateTime dtOcc(dtS1.GetYear(), m_Options.m_Yearly.nMonthOfYear,
1, 0, 0, 0);
CXTPCalendarUtils::UpdateMonthDay(dtOcc, m_Options.m_Yearly.nDayOfMonth);
if (dtOcc >= dtS1)
{
dtS1 = dtOcc;
}
else
{
dtS1 = dtOcc;
CXTPCalendarUtils::ShiftDate_Year(dtS1, 1, m_Options.m_Yearly.nDayOfMonth);
}
for (dtI = dtS1; dtI <= dtE1 && nOccCount < nMaxOccCount;
CXTPCalendarUtils::ShiftDate_Year(dtI, 1, m_Options.m_Yearly.nDayOfMonth))
{
ASSERT(dtI >= dtStart0 && dtI <= dtE1);
rArDates.Add(dtI);
nOccCount++;
}
}
break;
case xtpCalendarRecurrenceYearNth:
{
//------------------------------------------------------
//~ The I:{First, second, ..., Last>
//~ W:{Day, WeekDay, WeekEndDay, Su, Mo, ...}
//~ of M:{month}
//------------------------------------------------------
COleDateTime dtOcc(dtS1.GetYear(), m_Options.m_YearNth.nMonthOfYear,
1, 0, 0, 0);
BOOL bRes = CXTPCalendarUtils::CalcDayOfMonth(dtOcc,
m_Options.m_YearNth.nWhichDay,
m_Options.m_YearNth.nWhichDayMask);
if (!bRes)
{
return;
}
if (dtOcc >= dtS1)
{
dtS1 = dtOcc;
}
else
{
dtS1 = dtOcc;
CXTPCalendarUtils::ShiftDate_Year(dtS1, 1);
bRes = CXTPCalendarUtils::CalcDayOfMonth(dtS1, m_Options.m_YearNth.nWhichDay,
m_Options.m_YearNth.nWhichDayMask);
if (!bRes)
{
return;
}
}
for (dtI = dtS1; dtI <= dtE1 && nOccCount < nMaxOccCount;)
{
ASSERT(dtI >= dtStart0 && dtI <= dtE1);
rArDates.Add(dtI);
nOccCount++;
CXTPCalendarUtils::ShiftDate_Year(dtI, 1);
bRes = CXTPCalendarUtils::CalcDayOfMonth(dtI, m_Options.m_YearNth.nWhichDay,
m_Options.m_YearNth.nWhichDayMask);
if (!bRes)
{
ASSERT(FALSE);
break;
}
}
}
}
}
void CXTPCalendarRecurrencePattern::SetRecurrenceOptions(const XTP_CALENDAR_RECURRENCE_OPTIONS& Options)
{
m_Options = Options;
if (m_Options.m_nRecurrenceType == xtpCalendarRecurrenceDaily &&
m_Options.m_Daily.bEveryWeekDayOnly)
{
m_Options.m_Daily.nIntervalDays = 1;
}
//Prevent wrong user entry (e.g. infinite loop for nIntervalDays = 0 case)
if (m_Options.m_nRecurrenceType == xtpCalendarRecurrenceDaily)
{
m_Options.m_Daily.nIntervalDays = min(max(m_Options.m_Daily.nIntervalDays,1), 999);
}
if (m_Options.m_nRecurrenceType == xtpCalendarRecurrenceWeekly)
{
m_Options.m_Weekly.nIntervalWeeks = min(max(m_Options.m_Weekly.nIntervalWeeks,1), 999);
}
if (m_Options.m_nRecurrenceType == xtpCalendarRecurrenceMonthly)
{
m_Options.m_Monthly.nIntervalMonths = min(max(m_Options.m_Monthly.nIntervalMonths,1), 999);
m_Options.m_Monthly.nDayOfMonth = min(max(m_Options.m_Monthly.nDayOfMonth,1), 31);
}
if (m_Options.m_nRecurrenceType == xtpCalendarRecurrenceYearly)
{
m_Options.m_Yearly.nDayOfMonth = min(max(m_Options.m_Yearly.nDayOfMonth,1), 31);
}
}
void CXTPCalendarRecurrencePattern::SetPatternEnd(const XTP_CALENDAR_PATTERN_END& patternEnd)
{
m_PatternEnd = patternEnd;
if (m_PatternEnd.m_nUseEnd == xtpCalendarPatternEndDate)
{
m_PatternEnd.m_dtPatternEndDate = CXTPCalendarUtils::ResetTime(m_PatternEnd.m_dtPatternEndDate);
if (m_dtPatternStartDate.GetStatus() == COleDateTime::valid &&
m_PatternEnd.m_dtPatternEndDate.GetStatus() == COleDateTime::valid &&
m_PatternEnd.m_dtPatternEndDate < m_dtPatternStartDate)
{
m_dtPatternStartDate = m_PatternEnd.m_dtPatternEndDate;
}
}
}
CXTPCalendarRecurrencePatternPtr CXTPCalendarRecurrencePattern::ClonePattern()
{
if (!m_ptrDataProvider)
{
ASSERT(FALSE);
return NULL;
}
DWORD dwPatternID = GetPatternID();
DWORD dwMasterID = GetMasterEventID();
CXTPCalendarRecurrencePatternPtr ptrNew = m_ptrDataProvider->CreateNewRecurrencePattern();
if (!ptrNew)
{
ASSERT(FALSE);
return NULL;
}
ptrNew->SetPatternID(dwPatternID);
ptrNew->SetMasterEventID(dwMasterID);
if (!ptrNew->Update(this))
{
ASSERT(FALSE);
return NULL;
}
return ptrNew;
}
BOOL CXTPCalendarRecurrencePattern::Update(CXTPCalendarRecurrencePattern* pNewData)
{
if (pNewData == this)
{
return TRUE;
}
COleDateTime dtTmp = pNewData->GetStartTime();
SetStartTime(dtTmp);
int nTmp = pNewData->GetDurationMinutes();
SetDurationMinutes(nTmp);
const XTP_CALENDAR_RECURRENCE_OPTIONS& rOpt = pNewData->GetRecurrenceOptions();
SetRecurrenceOptions(rOpt);
dtTmp = pNewData->GetPatternStartDate();
SetPatternStartDate(dtTmp);
const XTP_CALENDAR_PATTERN_END& rPatternEnd = pNewData->GetPatternEnd();
SetPatternEnd(rPatternEnd);
RemoveAllExceptions();
CXTPCalendarEventsPtr ptrExceptions = pNewData->GetExceptions();
int nCount = XTP_SAFE_GET1(ptrExceptions, GetCount(), 0);
for (int i = 0; i < nCount; i++)
{
CXTPCalendarEvent* pException = ptrExceptions->GetAt(i, FALSE);
if (pException)
{
if (!SetException(pException))
{
ASSERT(FALSE);
}
}
}
ASSERT(pNewData->GetCustomProperties());
pNewData->GetCustomProperties()->CopyTo(m_pCustomProperties);
m_arOccReminders.RemoveAll();
m_arOccReminders.Append(pNewData->m_arOccReminders);
return TRUE;
}
BOOL CXTPCalendarRecurrencePattern::SetException(CXTPCalendarEvent* pException, CXTPCalendarEvent* pMasterEventToUpdate)
{
if (!pException)
{
ASSERT(FALSE);
return FALSE;
}
DWORD dwExcID = pException->GetEventID();
CXTPCalendarEvent* pExc = m_parExceptionEvents->FindEvent(dwExcID);
if (!pExc)
{
COleDateTime dtStartOcc = pException->GetRException_StartTimeOrig();
COleDateTime dtEndOcc = pException->GetRException_EndTimeOrig();
pExc = FindException(dtStartOcc, dtEndOcc);
}
BOOL bRes = TRUE;
if (pExc)
{
pExc->SetEventID(pException->GetEventID());
bRes = pExc->Update(pException);
ASSERT(bRes);
}
else
{
CXTPCalendarEventPtr ptrExc = pException->CloneEvent();
m_parExceptionEvents->Add(ptrExc);
pExc = ptrExc;
}
pExc->SetRecurrencePatternID(m_dwPatternID);
if (pMasterEventToUpdate)
{
pMasterEventToUpdate->UpdateStartEndDatesFromPatternExceptions();
}
return bRes;
}
BOOL CXTPCalendarRecurrencePattern::RemoveException(CXTPCalendarEvent* pException,
CXTPCalendarEvent* pMasterEventToUpdate)
{
if (!pException)
{
ASSERT(FALSE);
return FALSE;
}
int nRState = pException->GetRecurrenceState();
ASSERT(nRState == xtpCalendarRecurrenceOccurrence || nRState == xtpCalendarRecurrenceException);
COleDateTime dtStartOcc, dtEndOcc;
if (nRState == xtpCalendarRecurrenceOccurrence)
{
dtStartOcc = pException->GetStartTime();
dtEndOcc = pException->GetEndTime();
}
else
{
if (nRState == xtpCalendarRecurrenceException)
{
dtStartOcc = pException->GetRException_StartTimeOrig();
dtEndOcc = pException->GetRException_EndTimeOrig();
}
else
{
return FALSE;
}
}
int nCount = m_parExceptionEvents->GetCount();
int nFExcIdx = FindExceptionIndex(dtStartOcc, dtEndOcc);
if (nFExcIdx >= 0 && nFExcIdx < nCount)
{
m_parExceptionEvents->RemoveAt(nFExcIdx);
if (pMasterEventToUpdate)
{
pMasterEventToUpdate->UpdateStartEndDatesFromPatternExceptions();
}
return TRUE;
}
return FALSE;
}
void CXTPCalendarRecurrencePattern::RemoveAllExceptions()
{
m_parExceptionEvents->RemoveAll();
m_arOccReminders.RemoveAll();
}
CXTPCalendarEvent* CXTPCalendarRecurrencePattern::FindException(COleDateTime dtStartOrig, COleDateTime dtEndOrig) const
{
int nCount = m_parExceptionEvents->GetCount();
int nFExcIdx = FindExceptionIndex(dtStartOrig, dtEndOrig);
if (nFExcIdx >= 0 && nFExcIdx < nCount)
{
CXTPCalendarEvent* pEvent = m_parExceptionEvents->GetAt(nFExcIdx, FALSE);
return pEvent;
}
return NULL;
}
int CXTPCalendarRecurrencePattern::FindExceptionIndex(COleDateTime dtStartOrig, COleDateTime dtEndOrig) const
{
COleDateTime dtTmpS, dtTmpE;
int nCount = m_parExceptionEvents->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarEvent* pEvent = m_parExceptionEvents->GetAt(i, FALSE);
ASSERT(pEvent->GetRecurrenceState() == xtpCalendarRecurrenceException);
dtTmpS = pEvent->GetRException_StartTimeOrig();
dtTmpE = pEvent->GetRException_EndTimeOrig();
if (CXTPCalendarUtils::IsEqual(dtTmpS, dtStartOrig) &&
CXTPCalendarUtils::IsEqual(dtTmpE, dtEndOrig))
{
return i;
}
}
return -1;
}
BOOL CXTPCalendarRecurrencePattern::FindExceptions(CXTPCalendarEvents* pEvents,
COleDateTime dtStart, COleDateTime dtEnd) const
{
dtStart = CXTPCalendarUtils::ResetTime(dtStart);
dtEnd = CXTPCalendarUtils::ResetTime(dtEnd);
COleDateTime dtTmpS, dtTmpE;
int nCount = m_parExceptionEvents->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarEvent* pEvent = m_parExceptionEvents->GetAt(i, FALSE);
ASSERT(pEvent->GetRecurrenceState() == xtpCalendarRecurrenceException);
dtTmpS = CXTPCalendarUtils::ResetTime(pEvent->GetStartTime());
dtTmpE = CXTPCalendarUtils::ResetTime(pEvent->GetEndTime());
if (dtStart <= dtTmpS && dtTmpS <= dtEnd ||
dtStart <= dtTmpE && dtTmpE <= dtEnd ||
dtTmpS <= dtStart && dtStart <= dtTmpE ||
dtTmpS <= dtEnd && dtEnd <= dtTmpE)
{
if (!pEvent->IsRExceptionDeleted())
{
pEvents->Add(pEvent);
}
}
}
return TRUE;
}
CXTPCalendarEventsPtr CXTPCalendarRecurrencePattern::GetExceptions()
{
CXTPCalendarEventsPtr ptrExceptions = new CXTPCalendarEvents();
if (!ptrExceptions)
{
return NULL;
}
int nCount = m_parExceptionEvents->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarEvent* pEvent = m_parExceptionEvents->GetAt(i, FALSE);
ASSERT(pEvent);
CXTPCalendarEventPtr ptrEventCopy = pEvent ? pEvent->CloneEvent() : NULL;
if (ptrEventCopy)
{
ptrExceptions->Add(ptrEventCopy);
}
}
return ptrExceptions;
}
CXTPCalendarEventPtr CXTPCalendarRecurrencePattern::GetMasterEvent() const
{
if (!m_ptrDataProvider)
{
ASSERT(FALSE);
return NULL;
}
CXTPCalendarEventPtr ptrMEvent = m_ptrDataProvider->GetEvent(m_dwMasterEventID);
ASSERT(ptrMEvent);
return ptrMEvent;
}
void CXTPCalendarRecurrencePattern::SetPatternID(DWORD dwID)
{
m_dwPatternID = dwID;
int nCount = m_parExceptionEvents->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPCalendarEvent* pEvent = m_parExceptionEvents->GetAt(i, FALSE);
ASSERT(pEvent);
if (pEvent)
{
pEvent->SetRecurrencePatternID(m_dwPatternID);
}
}
}
void CXTPCalendarRecurrencePattern::DoPropExchange(CXTPPropExchange* pPX)
{
long nVersion = XTP_RECPATT_PROP_SET_DATA_VER;
PX_Long(pPX, _T("Version"), nVersion, XTP_RECPATT_PROP_SET_DATA_VER);
PX_DWord(pPX, cszRPatt_PatternID, m_dwPatternID, XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID);
PX_DateTime(pPX, cszRPatt_StartTime, m_dtStartTime);
PX_Int(pPX, cszRPatt_DurationMinutes, m_nDurationMinutes, 0);
PX_Enum(pPX, cszRPatt_RecurrenceType, m_Options.m_nRecurrenceType, xtpCalendarRecurrenceUnknown);
PX_Int(pPX, cszRPatt_RecurrenceOpt_Data1, m_Options.m_YearNth.nWhichDay, 0);
PX_Int(pPX, cszRPatt_RecurrenceOpt_Data2, m_Options.m_YearNth.nWhichDayMask, 0);
PX_Int(pPX, cszRPatt_RecurrenceOpt_Data3, m_Options.m_YearNth.nMonthOfYear, 0);
PX_DateTime(pPX, cszRPatt_PatternStartDate, m_dtPatternStartDate);
PX_Enum(pPX, cszRPatt_UseEndMethod, m_PatternEnd.m_nUseEnd, xtpCalendarPatternEndNoDate);
if (m_PatternEnd.m_nUseEnd == xtpCalendarPatternEndDate)
{
PX_DateTime(pPX, cszRPatt_PatternEndDate, m_PatternEnd.m_dtPatternEndDate);
}
else if (m_PatternEnd.m_nUseEnd == xtpCalendarPatternEndAfterOccurrences)
{
PX_Int(pPX, cszRPatt_EndAfterOccurrences, m_PatternEnd.m_nEndAfterOccurrences, 1);
}
PX_DWord(pPX, cszRPatt_MasterEventID, m_dwMasterEventID, XTP_CALENDAR_UNKNOWN_EVENT_ID);
//------------------------------------------------------------------------
if (pPX->IsStoring())
{
VERIFY( m_arOccReminders.Save(m_pCustomProperties, this) );
}
//-------------------------------------------
m_pCustomProperties->DoPropExchange(pPX);
//-------------------------------------------
if (pPX->IsLoading())
{
VERIFY( m_arOccReminders.Load(m_pCustomProperties) );
}
m_arOccReminders.ClearProperties(m_pCustomProperties);
}
void CXTPCalendarRecurrencePattern::SetOccReminder(
CXTPCalendarEvent* pOccEvent,
int nbIsReminder,
DATE dtNextReminderTime_Snoozed)
{
ASSERT(pOccEvent);
if (!pOccEvent)
{
return;
}
int nIndex = m_arOccReminders.Find(pOccEvent);
if (nIndex < 0)
{
CXTPCalendarReminderForOccurrence tmpData;
tmpData.m_dtOccurrenceStartTime = pOccEvent->GetStartTime();
tmpData.m_dtOccurrenceEndTime = pOccEvent->GetEndTime();
nIndex = (int)m_arOccReminders.Add(tmpData);
}
CXTPCalendarReminderForOccurrence* pOccRmdData;
pOccRmdData = &m_arOccReminders[nIndex];
if (nbIsReminder != xtpCalendarRmdPrm_DontChange)
{
pOccRmdData->m_nbIsReminder = nbIsReminder;
}
if (dtNextReminderTime_Snoozed != xtpCalendarRmdPrm_DontChange)
{
pOccRmdData->m_dtNextReminderTime_Snoozed = dtNextReminderTime_Snoozed;
}
m_arOccReminders.UpdateOccIfNeedEx(pOccEvent, pOccRmdData, this);
if (pOccRmdData->m_nbIsReminder == xtpCalendarRmdPrm_Default &&
pOccRmdData->m_dtNextReminderTime_Snoozed == xtpCalendarRmdPrm_Default)
{
m_arOccReminders.RemoveAt(nIndex);
}
}
////////////////////////////////////////////////////////////////////////////
CXTPCalendarReminderForOccurrence::CXTPCalendarReminderForOccurrence()
{
m_dtOccurrenceStartTime = 0;
m_dtOccurrenceEndTime = 0;
m_nbIsReminder = xtpCalendarRmdPrm_Default;
m_dtNextReminderTime_Snoozed = (DATE)xtpCalendarRmdPrm_Default;
}
CXTPCalendarReminderForOccurrence::~CXTPCalendarReminderForOccurrence()
{
}
const CXTPCalendarReminderForOccurrence& CXTPCalendarReminderForOccurrence::operator=(
const CXTPCalendarReminderForOccurrence& rSrc)
{
m_dtOccurrenceStartTime = rSrc.m_dtOccurrenceStartTime;
m_dtOccurrenceEndTime = rSrc.m_dtOccurrenceEndTime;
m_nbIsReminder = rSrc.m_nbIsReminder;
m_dtNextReminderTime_Snoozed = rSrc.m_dtNextReminderTime_Snoozed;
return *this;
}
//===========================================================================
CXTPCalendarReminderForOccurrenceArray::CXTPCalendarReminderForOccurrenceArray()
{
}
CXTPCalendarReminderForOccurrenceArray::~CXTPCalendarReminderForOccurrenceArray()
{
}
int CXTPCalendarReminderForOccurrenceArray::Find(CXTPCalendarEvent* pOccEvent) const
{
ASSERT(pOccEvent);
if (!pOccEvent)
{
return -1;
}
ASSERT(pOccEvent->GetRecurrenceState() == xtpCalendarRecurrenceOccurrence);
DATE dtOcctartTime = pOccEvent->GetStartTime();
DATE dtOccEndTime = pOccEvent->GetEndTime();
int nFIndex = Find(dtOcctartTime, dtOccEndTime);
return nFIndex;
}
int CXTPCalendarReminderForOccurrenceArray::Find(DATE dtOccStartTime, DATE dtOccEndTime) const
{
int nCount = (int)GetSize();
for (int i = 0; i < nCount; i++)
{
const CXTPCalendarReminderForOccurrence& rData = m_pData[i];
if (CXTPCalendarUtils::IsEqual(dtOccStartTime, rData.m_dtOccurrenceStartTime) &&
CXTPCalendarUtils::IsEqual(dtOccEndTime, rData.m_dtOccurrenceEndTime))
{
return i;
}
}
return -1;
}
int CXTPCalendarReminderForOccurrenceArray::UpdateOccIfNeed(
CXTPCalendarEvent* pOccEvent,
CXTPCalendarRecurrencePattern* pPattern)
{
if (!pOccEvent || !pPattern)
{
ASSERT(FALSE);
return 0;
}
int nFIndex = Find(pOccEvent);
if (nFIndex < 0)
{
return 0;
}
CXTPCalendarReminderForOccurrence* pOccRmdData;
pOccRmdData = &ElementAt(nFIndex);
int nRes = UpdateOccIfNeedEx(pOccEvent, pOccRmdData, pPattern);
return nRes;
}
int CXTPCalendarReminderForOccurrenceArray::UpdateOccIfNeedEx(
CXTPCalendarEvent* pOccEvent,
const CXTPCalendarReminderForOccurrence* pOccRmdData,
CXTPCalendarRecurrencePattern* pPattern)
{
if (!pOccEvent || !pOccRmdData || !pPattern)
{
ASSERT(FALSE);
return 0;
}
// IsReminder
if (pOccRmdData->m_nbIsReminder == xtpCalendarRmdPrm_Default)
{
CXTPCalendarEventPtr ptrMasterEvent = pPattern->GetMasterEvent();
if (!ptrMasterEvent)
{
ASSERT(FALSE);
return 0;
}
pOccEvent->SetReminder(ptrMasterEvent->IsReminder());
}
else if (pOccRmdData->m_nbIsReminder != xtpCalendarRmdPrm_DontChange)
{
pOccEvent->SetReminder(pOccRmdData->m_nbIsReminder != 0);
}
// MinutesBeforeStart_Snoozed
if (pOccRmdData->m_dtNextReminderTime_Snoozed == xtpCalendarRmdPrm_Default)
{
pOccEvent->GetCustomProperties()->RemoveProperty(cszEventCustProp_NextReminderTime_Snoozed);
}
else if (pOccRmdData->m_dtNextReminderTime_Snoozed != xtpCalendarRmdPrm_DontChange)
{
VERIFY( pOccEvent->GetCustomProperties()->SetProperty(
cszEventCustProp_NextReminderTime_Snoozed,
pOccRmdData->m_dtNextReminderTime_Snoozed) );
}
return 1;
}
BOOL CXTPCalendarReminderForOccurrenceArray::Load(CXTPCalendarCustomProperties* pProps)
{
ASSERT(pProps);
if (!pProps)
{
return FALSE;
}
RemoveAll();
COleVariant varCount;
BOOL bExists = pProps->GetProperty(cszOccRMD_Count, varCount);
if (!bExists)
{
return TRUE;
}
COleVariant varValue;
CString strPropNameI;
int nCount = (int)(long)_variant_t(varCount);
for (int i = 0; i < nCount; i++)
{
CXTPCalendarReminderForOccurrence rmdData;
_PropName(cszOccRMD_StartTime, i, strPropNameI);
if (pProps->GetProperty(strPropNameI, varValue))
{
rmdData.m_dtOccurrenceStartTime = (DATE)_variant_t(varValue);
}
_PropName(cszOccRMD_EndTime, i, strPropNameI);
if (pProps->GetProperty(strPropNameI, varValue))
{
rmdData.m_dtOccurrenceEndTime = (DATE)_variant_t(varValue);
}
_PropName(cszOccRMD_IsReminder, i, strPropNameI);
if (pProps->GetProperty(strPropNameI, varValue))
{
rmdData.m_nbIsReminder = (long)_variant_t(varValue);
}
_PropName(cszOccRMD_NextReminderTime_Snoozed, i, strPropNameI);
if (pProps->GetProperty(strPropNameI, varValue))
{
rmdData.m_dtNextReminderTime_Snoozed = (DATE)_variant_t(varValue);
}
Add(rmdData);
}
return TRUE;
}
BOOL CXTPCalendarReminderForOccurrenceArray::Save(CXTPCalendarCustomProperties* pProps,
CXTPCalendarRecurrencePattern* pPattern)
{
ASSERT(pProps);
if (!pProps)
{
return FALSE;
}
ClearProperties(pProps);
CString strPropNameI;
int nCount = (int)GetSize();
int i;
//===========================================================================
if (pPattern)
{
for (i = nCount-1; i >= 0; i--)
{
const CXTPCalendarReminderForOccurrence& rData = ElementAt(i);
int nFExcIdx = pPattern->FindExceptionIndex(rData.m_dtOccurrenceStartTime,
rData.m_dtOccurrenceEndTime);
if (nFExcIdx >= 0)
{
RemoveAt(i);
}
}
}
//===========================================================================
nCount = (int)GetSize();
for (i = 0; i < nCount; i++)
{
const CXTPCalendarReminderForOccurrence& rData = ElementAt(i);
_PropName(cszOccRMD_StartTime, i, strPropNameI);
VERIFY( pProps->SetProperty(strPropNameI, COleDateTime(rData.m_dtOccurrenceStartTime)) );
_PropName(cszOccRMD_EndTime, i, strPropNameI);
VERIFY( pProps->SetProperty(strPropNameI, COleDateTime(rData.m_dtOccurrenceEndTime)) );
_PropName(cszOccRMD_IsReminder, i, strPropNameI);
VERIFY( pProps->SetProperty(strPropNameI, (long)rData.m_nbIsReminder) );
if (rData.m_dtNextReminderTime_Snoozed != xtpCalendarRmdPrm_Default)
{
ASSERT(rData.m_dtNextReminderTime_Snoozed >= xtpCalendarDateTime_min && rData.m_dtNextReminderTime_Snoozed <= xtpCalendarDateTime_max);
_PropName(cszOccRMD_NextReminderTime_Snoozed, i, strPropNameI);
VERIFY( pProps->SetProperty(strPropNameI, COleDateTime(rData.m_dtNextReminderTime_Snoozed)) );
}
}
BOOL bRes = pProps->SetProperty(cszOccRMD_Count, (long)nCount);
ASSERT(bRes);
return bRes;
}
void CXTPCalendarReminderForOccurrenceArray::ClearProperties(CXTPCalendarCustomProperties* pProps)
{
ASSERT(pProps);
if (!pProps)
{
return;
}
COleVariant varCount;
BOOL bExists = pProps->GetProperty(cszOccRMD_Count, varCount);
if (!bExists)
{
return;
}
CString strPropNameI;
int nCount = (int)(long)_variant_t(varCount);
for (int i = 0; i < nCount; i++)
{
_PropName(cszOccRMD_StartTime, i, strPropNameI);
pProps->RemoveProperty(strPropNameI);
_PropName(cszOccRMD_EndTime, i, strPropNameI);
pProps->RemoveProperty(strPropNameI);
_PropName(cszOccRMD_IsReminder, i, strPropNameI);
pProps->RemoveProperty(strPropNameI);
_PropName(cszOccRMD_NextReminderTime_Snoozed, i, strPropNameI);
pProps->RemoveProperty(strPropNameI);
}
pProps->RemoveProperty(cszOccRMD_Count);
}
void CXTPCalendarReminderForOccurrenceArray::_PropName(LPCTSTR pcszProp, int nIndex, CString& rstrPropNameI)
{
TCHAR szIndex[64];
ITOT_S(nIndex, szIndex, 64, 10);
rstrPropNameI = pcszProp;
rstrPropNameI += _T("[");
rstrPropNameI += szIndex;
rstrPropNameI += _T("]");
}
COleDateTimeSpan CXTPCalendarRecurrencePattern::GetDuration() const
{
return CXTPCalendarUtils::Minutes2Span(m_nDurationMinutes);
}