📄 datedb.c
字号:
case repeatMonthlyByDate:
// Compute the number of months
months = ((end.year - start.year) * monthsInYear) + (end.month - start.month);
// if the end day is too early in the last month, don't include that month
if (end.day < start.day)
months--;
daysTotal = months / freq + 1; // repeats once every freq months
break;
// Yearly repeating appointment.
case repeatYearly:
years = end.year - start.year;
// if the end day is too early in the last year, don't include that year
if (end.month < start.month
|| (end.month == start.month && end.day < start.day))
years--;
daysTotal = years / freq + 1; // repeats once every freq years
break;
default:
daysTotal = 1;
break;
}
ErrNonFatalDisplayIf(daysTotal == 0, "event repeats on 0 days");
ErrNonFatalDisplayIf(daysTotal < 0, "event repeats on negative days");
if (daysTotal <= 0) daysTotal = 1;
return (daysTotal);
}
/***********************************************************************
*
* FUNCTION: ApptHasMultipleOccurences
*
* DESCRIPTION: Does the given appointment occur more than once?
*
* This function compares the repeat info and the exception list for
* an appointment to determine if it has more than one visible (non-excepted)
* occurence.
* The decision is based solely on the number of times the appointment
* repeats versus the number of exceptions.
*
* PARAMETERS: ApptDBRecordPtr apptRecP - the appointment to examine
*
* RETURNED: true if the appointment occurs more than once
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* grant 3/2/99 Initial Revision
*
***********************************************************************/
Boolean ApptHasMultipleOccurences(ApptDBRecordPtr apptRecP)
{
Int32 totalRepeats;
Int32 numExceptions;
ErrFatalDisplayIf(apptRecP == NULL, "no appointment");
// if the appointment does not repeat, then it can't occur more than once
if (!apptRecP->repeat) return false;
totalRepeats = CountTotalRepeats(apptRecP);
if (apptRecP->exceptions)
numExceptions = apptRecP->exceptions->numExceptions;
else
numExceptions = 0;
if (totalRepeats == apptNoEndDate) return true;
if ((totalRepeats - numExceptions) > 1) return true;
return false;
}
/***********************************************************************
*
* FUNCTION: ApptListCompare
*
* DESCRIPTION: This routine compares two entries in the appointment list,
* it's called by ApptGetAppointments via the quick sort
* routine.
*
* PARAMETERS: a - a pointer to an entry in the appointment list
* b - a pointer to an entry in the appointment list
* extra - extra data passed to quick sort - not used
*
* RETURNED: if a1 > a2 returns a positive int
* if a1 < a2 returns a negative int
* if a1 = a2 returns zero
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/15/95 Initial Revision
*
***********************************************************************/
static Int16 ApptListCompare (ApptInfoPtr a1, ApptInfoPtr a2, Int32 extra)
{
#pragma unused (extra)
Int16 result;
result = TimeCompare (a1->startTime, a2->startTime);
if (result == 0)
{
result = TimeCompare (a1->endTime, a2->endTime);
}
return result;
}
/***********************************************************************
*
* FUNCTION: ApptGetAppointments
*
* DESCRIPTION: This routine returns a list of appointments that are on
* the date specified
*
* PARAMETERS: dbP - pointer to the database
* date - date to search for
* countP - number of appointments on the specified
* day (returned value)
*
* RETURNED: handle of the appointment list (ApptInfoType)
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/15/95 Initial Revision
*
***********************************************************************/
#if 0
VoidHand ApptGetAppointments (DmOpenRef dbP, DateType date, UInt16* countP)
{
Err error;
Int16 result;
Int16 count = 0;
UInt16 recordNum;
Boolean repeats;
MemHandle recordH;
MemHandle apptListH;
ApptInfoPtr apptList;
ApptDBRecordType apptRec;
ApptPackedDBRecordPtr r;
// Allocated a block to hold the appointment list.
apptListH = MemHandleNew (sizeof (ApptInfoType) * apptMaxPerDay);
ErrFatalDisplayIf(!apptListH, "Out of memory");
if (! apptListH) return (0);
apptList = MemHandleLock (apptListH);
// Find the first non-repeating appointment of the day.
if (ApptFindFirst (dbP, date, &recordNum))
{
while (count < apptMaxPerDay)
{
// Check if the appointment is on the date passed, if it is
// add it to the appointment list.
recordH = DmQueryRecord (dbP, recordNum);
r = MemHandleLock (recordH);
result = DateCompare (r->when.date, date);
if (result == 0)
{
// Add the record to the appoitment list.
apptList[count].startTime = r->when.startTime;
apptList[count].endTime = r->when.endTime;
apptList[count].recordNum = recordNum;
count++;
}
MemHandleUnlock (recordH);
if (result != 0) break;
// Get the next record.
error = DmSeekRecordInCategory (dbP, &recordNum, 1, dmSeekForward, dmAllCategories);
if (error == dmErrSeekFailed) break;
}
}
// Add the repeating appointments to the list. Repeating appointments
// are stored at the beginning of the database.
recordNum = 0;
while (count < apptMaxPerDay)
{
recordH = DmQueryNextInCategory (dbP, &recordNum, dmAllCategories);
if (! recordH) break;
r = (ApptPackedDBRecordPtr) MemHandleLock (recordH);
repeats = (r->flags.repeat != 0);
if (repeats)
{
ApptUnpack (r, &apptRec);
if (ApptRepeatsOnDate (&apptRec, date))
{
// Add the record to the appoitment list.
apptList[count].startTime = r->when.startTime;
apptList[count].endTime = r->when.endTime;
apptList[count].recordNum = recordNum;
count++;
}
}
MemHandleUnlock (recordH);
// If the record has no repeating info we've reached the end of the
// repeating appointments.
if (! repeats) break;
recordNum++;
}
// Sort the list by start time.
SysInsertionSort (apptList, count, sizeof (ApptInfoType), ApptListCompare, 0L);
// If there are no appointments on the specified day, free the appointment
// list.
if (count == 0)
{
MemPtrFree (apptList);
apptListH = 0;
}
// Resize the appointment list block to release any unused space.
else
{
MemHandleUnlock (apptListH);
MemHandleResize (apptListH, count * sizeof (ApptInfoType));
}
*countP = count;
return (apptListH);
}
#endif
/***********************************************************************
*
* FUNCTION: ApptGetAlarmTime
*
* DESCRIPTION: This routine determines the date and time of an alarm for
* the event passed. Depending on the search direction specified,
* it will return either the time of the next occurrence of the alarm
* to fire, or the time of the most recently triggered alarm.
*
* PARAMETERS: apptRec - pointer to an appointment record
* currentTime - current date and time in seconds
* searchForward - designates whether to find the next (true) or
* most recent (false) occurrence of an event.
*
* RETURNED: date and time of the alarm, in seconds, or zero if there
* is no alarm
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/20/95 Initial Revision
* gap 9/25/00 Add capability to search backwards for the most
* recent occurrence of the event (needed for attention
* manager support)
* gap 10/17/00 small optimization - removed advance calculation
* out of while loop as we only need to do this once.
* also, add advance to current time in order to
* correctly position the start of a backward search in
* order to take into account the advance time.
*
***********************************************************************/
UInt32 ApptGetAlarmTime (ApptDBRecordPtr apptRec, UInt32 currentTime, Boolean searchForward)
{
UInt32 advance;
UInt32 alarmTime;
DateType repeatDate;
DateTimeType curDateTime;
DateTimeType apptDateTime;
if (!apptRec->alarm)
return apptNoTime;
// Non-repeating appointment?
if (! apptRec->repeat)
{
// An alarm on an untimed event triggers at midnight.
if (TimeToInt (apptRec->when->startTime) == apptNoTime)
{
apptDateTime.minute = 0;
apptDateTime.hour = 0;
}
else
{
apptDateTime.minute = apptRec->when->startTime.minutes;
apptDateTime.hour = apptRec->when->startTime.hours;
}
apptDateTime.second = 0;
apptDateTime.day = apptRec->when->date.day;
apptDateTime.month = apptRec->when->date.month;
apptDateTime.year = apptRec->when->date.year + firstYear;
// Compute the time of the alarm by adjusting the date and time
// of the appointment by the length of the advance notice.
advance = apptRec->alarm->advance;
switch (apptRec->alarm->advanceUnit)
{
case aauMinutes:
advance *= minutesInSeconds;
break;
case aauHours:
advance *= hoursInSeconds;
break;
case aauDays:
advance *= daysInSeconds;
break;
}
alarmTime = TimDateTimeToSeconds (&apptDateTime) - advance;
if (searchForward)
{
if (alarmTime >= currentTime)
return (alarmTime);
else
return (0);
}
else
{
if (alarmTime <= currentTime)
return (alarmTime);
else
return (0);
}
}
// Repeating appointment.
// calculate the appointment alarm advance time.
switch (apptRec->alarm->advanceUnit)
{
case aauMinutes:
advance = (UInt32) apptRec->alarm->advance * minutesInSeconds;
break;
case aauHours:
advance = (UInt32) apptRec->alarm->advance * hoursInSeconds;
break;
case aauDays:
advance = (UInt32) apptRec->alarm->advance * daysInSeconds;
break;
}
// if searchin backwards, adjust the start point of
// the search to account for the alarm advance time.
if (!searchForward)
TimSecondsToDateTime (currentTime+advance, &curDateTime);
else
TimSecondsToDateTime (currentTime, &curDateTime);
repeatDate.year = curDateTime.year - firstYear;
repeatDate.month = curDateTime.month;
repeatDate.day = curDateTime.day;
while (ApptNextRepeat (apptRec, &repeatDate, searchForward))
{
// An alarm on an untimed event triggers at midnight.
if (TimeToInt (apptRec->when->startTime) == apptNoTime)
{
apptDateTime.minute = 0;
apptDateTime.hour = 0;
}
else
{
apptDateTime.minute = apptRec->when->startTime.minutes;
apptDateTime.hour = apptRec->when->startTime.hours;
}
apptDateTime.second = 0;
apptDateTime.day = repeatDate.day;
apptDateTime.month = repeatDate.month;
apptDateTime.year = repeatDate.year + firstYear;
// Compute the time of the alarm by adjusting the date and time
// of the appointment by the length of the advance notice.
alarmTime = TimDateTimeToSeconds (&apptDateTime) - advance;
if (searchForward)
{
if (alarmTime >= currentTime)
return (alarmTime);
DateAdjust (&repeatDate, 1);
}
else
{
if (alarmTime <= currentTime)
return (alarmTime);
DateAdjust (&repeatDate, -1);
}
}
return (0);
}
/***********************************************************************
*
* FUNCTION: ApptAlarmMunge
*
* DESCRIPTION: Helper routine for ApptAlarmMunger. Process one appointment.
*
* PARAMETERS: inDbR - reference to open database
* inPackedRecordP - pointer to packed record in storage heap
* inAlarmStart - first valid alarm time
* inAlarmStop - last valid alarm time
* inOutEarliestAlarmP - ???
* outAudibleP - true if alarm sound should play, nil is ok
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* peter 3/22/00 Initial Revision. Based on existing code from
* ApptAlarmMunger.
* gap 06/06/00 Only increment the alarm counter variable (numAlarms)
* when a new alarm is added to the alarms as opposed to
* every time an alarm is processed. Can result in a
* Fatal Alert "Error Querying Record" if count does not
* match the number of alarms in list and just the right
* value happens to reside in the memory following the
* actual list contents.
*
***********************************************************************/
static void ApptAlarmMunge (
ApptPackedDBRecordPtr inPackedRecordP,
UInt16 inRecordNum,
UInt32 inAlarmStart,
UInt32 inAlarmStop,
AlarmPostingDataPtr inPostingAlarmData,
UInt32 * inOutEarliestAlarmP)
{
ApptDBRecordType apptRec;
UInt32 alarmTime;
UInt32 uniqueID;
AttnLevelType attnLevel;
AttnFlagsType attnFlags;
if ( inPackedRecordP->flags.alarm )
{
ApptUnpack (inPackedRecordP, &apptRec);
// Get the first alarm on or after inAlarmStart
alarmTime = ApptGetAlarmTime (&apptRec, inAlarmStart, true);
// If in range, add the alarm to the output
if ( alar
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -