📄 datetransfer.c
字号:
// Extract position and sign
MatchDayPositionToken(identifier, &position,
&fromEndOfMonth);
// Validate occurrence
if (position < 1)
position = 1;
else if (position > 31)
position = 31;
if (fromEndOfMonth)
{
// This wont be accurate, since not all months
// have 31 days. Datebook doesnt support it anyway
repeatInfoP->repeatOn = 31 - position;
}
else
{
// It's an exact day from the start of the month
repeatInfoP->repeatOn = position;
}
}
#endif
}
}
}
}
break;
default:
// Bad monthly sub-type
ErrNonFatalDisplay("Bad monthly rule");
MemHandleFree(repeatInfoH);
repeatInfoP = NULL;
break;
}
}
break;
case 'y':
{
// Yearly
repeatInfoP->repeatType = repeatYearly;
// Has no meaning for this case
repeatInfoP->repeatFrequency = StrAToI(&identifier[2]);
// Determine if yearly by day or by month
switch (identifier[1])
{
case 'm':
{
// By month
// Read remaining tokens: months, duration, end date
while (fieldP != NULL)
{
// Read a token
fieldP = GetToken(fieldP, identifier);
// Determine token type
if (identifier[0] == '#')
{
// It's a duration. Extract it.
UInt32 duration = StrAToI(&identifier[1]);
// If duration is not zero
if (duration != 0)
{
// Compute end-date from available data and duration
}
}
else if (TxtCharIsDigit(identifier[0]))
{
// It's a month occurrence or an end-date. Judge by length
if (StrLen(identifier) > 2)
{
// It should be an end-date
MatchDateTimeToken(identifier, &repeatInfoP->repeatEndDate, NULL);
}
else
{
#if 1
// Datebook doesnt support monthly repeats on a date which isnt
// the same as the start day. Thus, occurrences are not used and
// this value should be zero
repeatInfoP->repeatOn = 0;
#else
// It should be a monthly occurrence
UInt32 month;
// Extract month
month = StrAToI(identifier);
// Validate month
if (month < 1)
month = 1;
else if (month > december)
month = december;
// Do something with month here
#endif
}
}
}
}
break;
case 'd':
{
// By day
// Read remaining tokens: days, duration, end date
while (fieldP != NULL)
{
// Read a token
fieldP = GetToken(fieldP, identifier);
// Determine token type
if (identifier[0] == '#')
{
// It's a duration. Extract it.
UInt32 duration = StrAToI(&identifier[1]);
// If duration is not zero
if (duration != 0)
{
// Compute end-date from available data and duration
}
}
else if (TxtCharIsDigit(identifier[0]))
{
// It's a day occurrence or an end-date. Judge by length
if (StrLen(identifier) > 3)
{
// It should be an end-date
MatchDateTimeToken(identifier, &repeatInfoP->repeatEndDate, NULL);
}
else
{
#if 1
// Datebook doesnt support daily repeats on a days which arent
// the same as the start day. Thus, occurrences are not used and
// this value should be zero
repeatInfoP->repeatOn = 0;
#else
// It should be a daily occurrence
UInt32 day;
// Extract day
day = StrAToI(identifier);
// Validate day
if (day < 1)
day = 1;
else if (day > 31)
day = 31;
// Do something with day here
#endif
}
}
}
}
break;
default:
// Bad yearly sub-type
ErrNonFatalDisplay("Bad yearly rule");
MemHandleFree(repeatInfoH);
repeatInfoP = NULL;
break;
}
}
break;
default:
// Unknown rule
ErrNonFatalDisplay("Bad repeat rule");
MemHandleFree(repeatInfoH);
repeatInfoP = NULL;
break;
}
// ABa release in ImportVCal
// Free entire repeat rule string
// MemPtrFree(ruleTextP);
}
return repeatInfoP;
}
#pragma mark ----------------------------
/************************************************************
*
* FUNCTION: DateImportVEvent
*
* DESCRIPTION: Import a VCal record of type vEvent
*
* PARAMETERS:
* dbP - pointer to the database to add the record to
* inputStream - pointer to where to import the record from
* inputFunc - function to get input from the stream
* obeyUniqueIDs - true to obey any unique ids if possible
* beginAlreadyRead - whether the begin statement has been read
*
* RETURNS: true if the input was read
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* djk 8/9/97 Created
* art 10/17/97 Added parameter to return unique id
* art 2/2/98 Handle yearly events better (but not great).
* tlw 2/9/98 Use UInt16 for yearly (monthly repeatFrequency) so its not truncated.
* peter 3/29/00 Deal with events whose start and end times fall on different days,
* as occurs when events expressed in universal time are shifted.
*
*************************************************************/
static Boolean
DateImportVEvent(DmOpenRef dbP, UInt16 pdiRefNum, PdiReaderType* reader,
Boolean obeyUniqueIDs, Boolean beginAlreadyRead, UInt32 * uniqueIDP)
{
UInt16 indexNew;
UInt16 indexOld;
UInt32 uid;
/*volatile*/ ApptDBRecordType newDateRecord;
Char * volatile newAttachment;
ApptDateTimeType nWhen;
UInt32 alarmDTinSec = 0; // ASSUMPTION: Alarm is not set for 1/1/1904 at 00:00:00
char *tempP;
volatile Err error = 0;
Boolean datedEvent = false; // Aba: true iff a date was found in the event
TraceOutput(TL(appErrorClass, "DateImportVEvent: BEGIN"));
// Read in the vEvent entry
if (!beginAlreadyRead)
{
PdiReadProperty(pdiRefNum, reader);
beginAlreadyRead = reader->property == kPdiPRN_BEGIN_VEVENT;
}
if (!beginAlreadyRead)
return false;
PdiEnterObject(pdiRefNum, reader);
// Initialize the record to NULL
newDateRecord.when = &nWhen;
newDateRecord.alarm = NULL;
newDateRecord.repeat = NULL;
newDateRecord.exceptions = NULL;
newDateRecord.description = NULL;
newDateRecord.note = NULL;
newAttachment = NULL;
tempP = NULL;
// An error happens usually due to no memory. It's easier just to
// catch the error. If an error happens, we remove the last record.
// Then we throw a second time so the caller receives it and displays a message.
ErrTry
{
while (PdiReadProperty(pdiRefNum, reader) == 0 && reader->property != kPdiPRN_END_VEVENT)
{
TraceOutput(TL(appErrorClass, "DateImportVEvent: property = %s", reader->propertyName));
switch(reader->property)
{
case kPdiPRN_DTSTART:
// Handle Start tag
// ASSUMPTION: we will use the date from the start time, not the end time
// NOTE: This function will break if the DTSTART value is truncated
// beyond the day
PdiReadPropertyField(pdiRefNum, reader, &tempP, kPdiResizableBuffer, kPdiDefaultFields);
if (tempP != NULL)
{
// Extract start date & time
MatchDateTimeToken(tempP, &newDateRecord.when->date,
&newDateRecord.when->startTime);
// Assume end time same as start time for now...
newDateRecord.when->endTime = newDateRecord.when->startTime;
datedEvent = true;
}
break;
case kPdiPRN_DTEND:
// Read in the end time
// ASSUMPTION: It is possible to send an end date that is different from
// the start date, this would cause a problem for us, since we
// assume that the end time has the same date as the start time. This can
// happen even if the event starts and ends on the same day if the sending
// device uses universal time format and is in a different time zone than
// the receiving device.
PdiReadPropertyField(pdiRefNum, reader, &tempP, kPdiResizableBuffer, kPdiDefaultFields);
if (tempP != NULL)
{
DateType endDate;
// Extract end time
MatchDateTimeToken(tempP, &endDate, &newDateRecord.when->endTime);
if (DateToDays(endDate) != DateToDays(newDateRecord.when->date))
{
ErrNonFatalDisplayIf(DateToDays(endDate) < DateToDays(newDateRecord.when->date),
"Event ends on an earlier date than it starts");
// Force event end time to be on same day as start time, reducing
// event duration as necessary.
if (DateToDays(endDate) > DateToDays(newDateRecord.when->date))
{// Set end time to 11:55 PM.
newDateRecord.when->endTime.hours = hoursPerDay - 1;
newDateRecord.when->endTime.minutes = hoursInMinutes - 5;
}
}
}
break;
// Read Repeat info
case kPdiPRN_RRULE:
PdiReadPropertyField(pdiRefNum, reader, &tempP, kPdiResizableBuffer, kPdiDefaultFields);
newDateRecord.repeat = DateImportRepeatingRule(tempP);
// aro - Fix bug #51567 - handle the case where no days of week is set
// for weekly event.
// Assume the starting day of the event is the repeating day
if ((newDateRecord.repeat)
&& (newDateRecord.repeat->repeatType == repeatWeekly)
&& (newDateRecord.repeat->repeatOn == 0))
{
// Assume that start date is known and set it as the repeat day
SetBitMacro(newDateRecord.repeat->repeatOn,
DayOfWeek(newDateRecord.when->date.month, newDateRecord.when->date.day, newDateRecord.when->date.year + firstYear));
}
break;
// Read Repeat exceptions
case kPdiPRN_EXDATE:
{
MemHandle exceptionListH;
ExceptionsListType* exceptionListP;
DateType* exceptionP;
UInt16 exceptionCount = 0;
Err err;
// Allocate exception list handle to hold at least the first exception
exceptionListH = MemHandleNew(sizeof(ExceptionsListType));
// Debug check
ErrFatalDisplayIf(exceptionListH == NULL, "Memory full");
// Read each exception
while (PdiReadPropertyField(pdiRefNum, reader, &tempP, kPdiResizableBuffer, kPdiSemicolonFields) == 0)
{
// Resize handle to hold exception
err = MemHandleResize(exceptionListH, sizeof(ExceptionsListType) +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -