📄 dateday.c
字号:
MemHandleUnlock(recordH);
return (0);
}
// If the change is to be applied to the selected occurrence only
// an exception will be created and the specified date and time
// will be applied.
else if (alertButton == RangeCurrentButton)
exception = true;
// If the change is to be applied to the current and future
// events, the current record will need to be split, and the
// specified date and time will be applied.
else if (alertButton == RangeFutureButton)
splitEvent = true;
// If the change is to be applied to the all occurrences of the event
// the code below will do one of two things. If the user only changed
// the time of the event, the original start date will be maintained and only
// the time change will be applied. If the user changes both the time and date,
// the specified date and time will be applied.
else if (alertButton == RangeAllButton)
{
applyToAll = true;
if (timeChangeOnly)
date = apptRec.when->date;
}
}
// if there is an alarm associated with the item, remove it from
// the attention manager queue before changing the event
if (apptRec.alarm)
{
hasAlarm = true;
DeleteAlarmIfPosted(*recordNumP);
}
MemHandleUnlock (recordH);
// Add an exception to the current record, and create a new record
// at the new time.
if (exception)
{
err = ApptAddException (ApptDB, recordNumP, Date);
if (err) goto Exit;
ApptGetRecord (ApptDB, *recordNumP, &apptRec, &recordH);
when.startTime = startTime;
when.endTime = endTime;
when.date = date;
MemSet (&newRec, sizeof (newRec), 0);
newRec.description = apptRec.description;
newRec.note = apptRec.note;
newRec.when = &when;
newRec.alarm = apptRec.alarm;
err = CreateException (&newRec, recordNumP);
MemHandleUnlock (recordH);
if (err) goto Exit;
}
// Change the time of the current record.
else
{
MemSet (&changedFields, sizeof (changedFields), 0);
MemSet (&newRec, sizeof (newRec), 0);
if (isRepeating)
{
if (splitEvent)
{
err = SplitRepeatingEvent (recordNumP);
if (err) goto Exit;
}
ApptGetRecord (ApptDB, *recordNumP, &apptRec, &recordH);
// When changing the entire range of event, reset the start date by calculating
// the number of days the user moved the event and apply the delta to the event's
// start date, maintain the duration and clear the exceptions list.
repeat = *apptRec.repeat;
newRec.repeat = &repeat;
// Maintain the duration of the event.
if ((DateToInt (apptRec.repeat->repeatEndDate) != apptNoEndDate) && !(splitEvent))
{
adjust = (Int32) DateToDays (date) -
(Int32) DateToDays (apptRec.when->date);
DateAdjust (&repeat.repeatEndDate, adjust);
changedFields.repeat = true;
}
// If the repeat type is weekly and the start date of the event
// has been changed, update the 'repeat on' field, which contains
// the days of the week the event repeats on, such that the
// event occurs on the start date.
if (apptRec.repeat->repeatType == repeatWeekly)
{
dayOfWeek = DayOfWeek (apptRec.when->date.month,
apptRec.when->date.day,
apptRec.when->date.year+firstYear);
repeat.repeatOn &= ~(1 << dayOfWeek);
dayOfWeek = DayOfWeek (date.month,
date.day,
date.year+firstYear);
repeat.repeatOn |= (1 << dayOfWeek);
changedFields.repeat = true;
}
// If the repeat type is monthly by day, get the day of the month (ex:
// first Friday) of the start date of the event.
else if (apptRec.repeat->repeatType == repeatMonthlyByDay)
{
repeat.repeatOn = DayOfMonth (date.month, date.day, date.year + firstYear);
changedFields.repeat = true;
// If we're in the fourth week, and the fourth week is also the last
// week, ask the user which week the event repeats in (fourth or last).
if ( ((repeat.repeatOn / daysInWeek) == 3) &&
(date.day + daysInWeek > DaysInMonth (date.month, date.year + firstYear)))
{
alert = FrmInitForm (MonthlyRepeatDialog);
// Set the 4th / last push button.
if (apptRec.repeat->repeatOn > dom4thSat)
id = MonthlyRepeatLastButton;
else
id = MonthlyRepeatFourthButton;
FrmSetControlGroupSelection (alert, MonthlyRepeatWeekGroup,id);
alertButton = FrmDoDialog (alert);
if (FrmGetObjectIndex (alert, MonthlyRepeatLastButton) ==
FrmGetControlGroupSelection (alert, MonthlyRepeatWeekGroup))
repeat.repeatOn += daysInWeek;
FrmDeleteForm (alert);
if (alertButton == MonthlyRepeatCancel)
{
MemHandleUnlock (recordH);
return (0);
}
}
}
// If the record is a repeating appointment, and the start date has changed,
// then clear the exceptions list.
if ( !(applyToAll && timeChangeOnly) )
{
newRec.exceptions = NULL;
changedFields.exceptions = true;
}
MemHandleUnlock (recordH);
}
when.date = date;
when.startTime = startTime;
when.endTime = endTime;
newRec.when = &when;
changedFields.when = true;
err = ApptChangeRecord (ApptDB, recordNumP, &newRec, changedFields);
if (err) goto Exit;
}
// If the appointment has an alarm, reschedule the next alarm.
if (hasAlarm)
RescheduleAlarms (ApptDB);
*moved = true;
return (0);
Exit:
FrmAlert (DeviceFullAlert);
return (err);
}
/***********************************************************************
*
* FUNCTION: PurgeRecords
*
* DESCRIPTION: This routine deletes appointments that are before the
* user specified date.
*
* PARAMETERS: nothing
*
* RETURNED: true if the current view may need to be redrawn.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 8/1/95 Initial Revision
* gap 8/1/00 add attention manager support
*
***********************************************************************/
static Boolean PurgeRecords (void)
{
Int32 adjust;
UInt16 index;
UInt16 ctlIndex;
UInt16 numRecord;
UInt16 buttonHit;
UInt16 rangeItem;
ListPtr lst;
FormPtr alert;
MemHandle recordH;
Boolean purge;
Boolean archive = false;
DateType purgeDate;
DateTimeType dateTime;
ApptDBRecordType apptRec;
Boolean hasAlarm;
// Display an alert to comfirm the operation.
alert = FrmInitForm (PurgeDialog);
ctlIndex = FrmGetObjectIndex (alert, PurgeSaveBackup);
FrmSetControlValue (alert, ctlIndex, SaveBackup);
buttonHit = FrmDoDialog (alert);
archive = FrmGetControlValue (alert, ctlIndex);
lst = FrmGetObjectPtr (alert, FrmGetObjectIndex (alert, PurgeRangeList));
rangeItem = LstGetSelection (lst);
FrmDeleteForm (alert);
if (buttonHit == PurgeCancel)
return (false);
SaveBackup = archive;
// Compute the purge date.
TimSecondsToDateTime (TimGetSeconds (), &dateTime);
// One, two, or three weeks
if (rangeItem < 3)
adjust = ((rangeItem + 1) * daysInWeek);
// One month
else if (dateTime.month > january)
adjust = DaysInMonth (dateTime.month-1, dateTime.year);
else
adjust = DaysInMonth (december, dateTime.year-1);
purgeDate.year = dateTime.year - firstYear;
purgeDate.month = dateTime.month;
purgeDate.day = dateTime.day;
DateAdjust (&purgeDate, -adjust);
// Delete records.
numRecord = DmNumRecords (ApptDB);
if (! numRecord) return (false);
for (index = numRecord-1; (Int16) index >= 0; index--)
{
recordH = DmGetRecord (ApptDB, index);
if (recordH == 0) continue;
ApptGetRecord (ApptDB, index, &apptRec, &recordH);
if (apptRec.repeat)
purge = (DateToInt(apptRec.repeat->repeatEndDate) <= DateToInt(purgeDate));
else
purge = (DateToInt(apptRec.when->date) <= DateToInt(purgeDate));
hasAlarm = (apptRec.alarm != NULL);
MemHandleUnlock (recordH);
DmReleaseRecord (ApptDB, index, false);
if (purge)
{
// if the event to be delete had an alarm, be sure to remove it
// from the posted alarm queue before the event is deleted.
if (hasAlarm)
DeleteAlarmIfPosted(index);
if (archive)
DmArchiveRecord (ApptDB, index);
else
DmDeleteRecord (ApptDB, index);
// Move deleted record to the end of the index so that the
// quick sort routine will work.
DmMoveRecord (ApptDB, index, numRecord);
}
}
// Schedule the next alarm.
RescheduleAlarms (ApptDB);
return (true);
}
/***********************************************************************
*
* FUNCTION: DatebookDayOfWeek
*
* DESCRIPTION: This routine returns the day-of-the-week, adjusted by the
* preference setting that specifies the first day-of-
* the-week. If the date passed is a Tuesday and the
* start day of week is Monday, this routine will return
* a value of one.
*
* PARAMETERS: month - month (1-12)
* day - day (1-31)
* year - year (1904-2031)
*
* RETURNED: day of the week (0-first, 1-second)
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/27/95 Initial Revision
*
***********************************************************************/
static UInt16 DatebookDayOfWeek (UInt16 month, UInt16 day, UInt16 year)
{
return ((DayOfWeek (month, day, year) - StartDayOfWeek + daysInWeek)
% daysInWeek);
}
/***********************************************************************
*
* FUNCTION: SubstituteStr
*
* DESCRIPTION: This routine substitutes the occurrence a token, within
* a string, with another string.
*
* PARAMETERS: str - string containing token string
* token - the string to be replaced
* sub - the string to substitute for the token
* subLen - length of the substitute string.
*
* RETURNED: pointer to the string
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 7/6/95 Initial Revision
*
***********************************************************************/
static Char* SubstituteStr (Char* str, const Char* token, Char* sub, UInt16 subLen)
{
int charsToMove;
UInt16 tokenLen;
UInt16 strLen;
UInt16 blockSize;
Char* ptr;
MemHandle strH;
// Find the start of the token string, if it doesn't exist, exit.
ptr = StrStr(str, token);
if (ptr == NULL) return (str);
tokenLen = StrLen (token);
charsToMove = subLen - tokenLen;
// Resize the string if necessary.
strH = MemPtrRecoverHandle (str);
strLen = StrLen (str);
blockSize = MemHandleSize (strH);
if (strLen + charsToMove + 1 >= blockSize)
{
MemHandleUnlock (strH);
MemHandleResize (strH, strLen + charsToMove + 1);
str = MemHandleLock (strH);
ptr = StrStr (str, token);
ErrNonFatalDisplayIf(ptr == NULL, "Msg missing token");
}
// Make room for the substitute string.
if (charsToMove)
MemMove (ptr + subLen, ptr + tokenLen, StrLen (ptr + tokenLen)+1);
// Replace the token with the substitute string.
MemMove (ptr, sub, subLen);
return (str);
}
/***********************************************************************
*
* FUNCTION: SelectFont
*
* DESCRIPTION: This routine handles selection of a font in the List
* View.
*
* PARAMETERS: currFontID - id of current font
*
* RETURNED: id of new font
*
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 9/10/97 Initial Revision
*
***********************************************************************/
static FontID SelectFont (FontID currFontID)
{
UInt16 formID;
FontID fontID;
formID = (FrmGetFormId (FrmGetActiveForm ()));
// Call the OS font selector to get the id of a font.
fontID = FontSelect (currFontID);
if (fontID != currFontID)
FrmUpdateForm (formID, updateFontChanged);
return (fontID);
}
#pragma mark -
/***********************************************************************
*
* FUNCTION: RepeatSetDateTrigger
*
* DESCRIPTION: This routine sets the label of the trigger that displays
* the end date of a repeating appointment.
*
* PARAMETERS: endDate - date or -1 if no end date
*
* RETURNED: nothing
*
* NOTES:
* This routine assumes that the memory allocated for the label of
* the due date trigger is large enough to hold the lagest posible
* label. This label's memory is reserved by initializing the label
* in the resource file.
*
* REVISION HISTORY:
* Name Date Description
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -