📄 datetransfer.c
字号:
sizeof(DateType) * exceptionCount);
ErrFatalDisplayIf(err != 0, "Memory full");
// Lock exception handle
exceptionListP = MemHandleLock(exceptionListH);
// Calc exception ptr
exceptionP = (DateType*)((UInt32)exceptionListP + (UInt32)sizeof(UInt16) +
(UInt32)(sizeof(DateType) * exceptionCount));
// Store exception into exception handle
MatchDateTimeToken(tempP, exceptionP, NULL);
// Increase exception count
exceptionCount++;
// Unlock exceptions list handle
MemHandleUnlock(exceptionListH);
}
// Lock exception handle
exceptionListP = MemHandleLock(exceptionListH);
// Store final exception count
exceptionListP->numExceptions = exceptionCount;
// Save exception list into datebook record
newDateRecord.exceptions = exceptionListP;
}
break;
// Read in Alarm info
case kPdiPRN_AALARM:
case kPdiPRN_DALARM:
{
DateTimeType alarmDT;
DateType alarmDate;
TimeType alarmTime;
PdiReadPropertyField(pdiRefNum, reader, &tempP, kPdiResizableBuffer, kPdiDefaultFields);
if (tempP != NULL)
{
// Extract alarm date & time
MatchDateTimeToken(tempP, &alarmDate, &alarmTime);
// Copy values to DateTimeType struct
alarmDT.year = alarmDate.year + firstYear;
alarmDT.month = alarmDate.month;
alarmDT.day = alarmDate.day;
alarmDT.hour = alarmTime.hours;
alarmDT.minute = alarmTime.minutes;
alarmDT.second = 0;
alarmDTinSec = TimDateTimeToSeconds(&alarmDT);
}
}
break;
// Read in Summary
case kPdiPRN_SUMMARY:
PdiDefineResizing(pdiRefNum, reader, kPdiDefaultBufferDeltaSize, tableMaxTextItemSize);
PdiReadPropertyField(pdiRefNum, reader, (Char**) &newDateRecord.description, kPdiResizableBuffer, kPdiDefaultFields);
PdiDefineResizing(pdiRefNum, reader, kPdiDefaultBufferDeltaSize, kPdiDefaultBufferMaxSize);
break;
// Read in Description
case kPdiPRN_DESCRIPTION:
PdiDefineResizing(pdiRefNum, reader, kPdiDefaultBufferDeltaSize, tableMaxTextItemSize);
PdiReadPropertyField(pdiRefNum, reader, (Char**) &newDateRecord.note, kPdiResizableBuffer, kPdiDefaultFields);
PdiDefineResizing(pdiRefNum, reader, kPdiDefaultBufferDeltaSize, kPdiDefaultBufferMaxSize);
TraceOutput(TL(appErrorClass, "newDateRecord.note = %p", newDateRecord.note));
break;
// Read in attachments. At the end we place the attachment into the record.
case kPdiPRN_ATTACH:
// Note: vCal permits attachments of types other than text, specifically
// URLs and Content ID's. At the moment, wee will just treat both of these
// as text strings
PdiDefineResizing(pdiRefNum, reader, kPdiDefaultBufferDeltaSize, noteViewMaxLength);
PdiReadPropertyField(pdiRefNum, reader, (Char**) &newAttachment, kPdiResizableBuffer, kPdiDefaultFields);
PdiDefineResizing(pdiRefNum, reader, kPdiDefaultBufferDeltaSize, kPdiDefaultBufferMaxSize);
break;
// read in the unique identifier
case kPdiPRN_UID:
{
Char* uniqueIDStringP = NULL;
PdiReadPropertyField(pdiRefNum, reader, &uniqueIDStringP, kPdiResizableBuffer, kPdiDefaultFields);
if (uniqueIDStringP != NULL)
{
uid = StrAToI(uniqueIDStringP);
MemPtrFree(uniqueIDStringP);
// Check the uid for reasonableness.
if (uid < (dmRecordIDReservedRange << 12))
uid = 0;
}
}
break;
}
TraceOutput(TL(appErrorClass, "DateImportVEvent: (in the while) tempP = %p", tempP));
TraceOutput(TL(appErrorClass, "DateImportVEvent: (in the while) tempP = %s", tempP));
TraceOutput(TL(appErrorClass, "DateImportVEvent: (in the while) newDateRecord.note = %p", newDateRecord.note));
}
TraceOutput(TL(appErrorClass, "DateImportVEvent (end while): property = %s", reader->propertyName));
TraceOutput(TL(appErrorClass, "DateImportVEvent: tempP = %p", tempP));
if (tempP)
MemPtrFree(tempP);
// If we go out the loop and last property is not an END:VEVENT => bad data
if (reader->property != kPdiPRN_END_VEVENT)
ErrThrow(exgErrBadData);
// If no date: no syntax error but data can't be accepted
if (datedEvent == false)
ErrThrow(errNone);
TraceOutput(TL(appErrorClass, "(.)"));
// if an alarm was read in, translate it appropriately
// ASSUMPTION: alarm is before start time
if (alarmDTinSec != 0)
{
TraceOutput(TL(appErrorClass, "*** newDateRecord.note = %s", newDateRecord.note));
TranslateAlarm((ApptDBRecordType*)&newDateRecord, alarmDTinSec);
TraceOutput(TL(appErrorClass, "*** newDateRecord.note = %s", newDateRecord.note));
}
TraceOutput(TL(appErrorClass, "(.)"));
// PalmIII stored descriptions as DESCRIPTION and notes as ATTACH.
// vCal spec stores considers them to be SUMMARY and DESCRIPTION.
// For now we write records in the old terminology but here we
// handle both.
if (newDateRecord.description == NULL)
{
newDateRecord.description = newDateRecord.note;
newDateRecord.note = newAttachment;
newAttachment = NULL;
}
TraceOutput(TL(appErrorClass, "(.)"));
// Some vCal implementations send duplicate SUMMARY and DESCRIPTION fields.
if (newDateRecord.description != NULL && newDateRecord.note != NULL &&
StrCompare(newDateRecord.description, newDateRecord.note) == 0)
{
// Delete the duplicate note.
MemPtrFree(newDateRecord.note);
newDateRecord.note = NULL;
}
// Write the actual record
TraceOutput(TL(appErrorClass, "newDateRecord.note = %p", newDateRecord.note));
TraceOutput(TL(appErrorClass, "newDateRecord.description = %p", newDateRecord.description));
TraceOutput(TL(appErrorClass, "DateImportVEvent (before ApptNewRecord): description = %s", newDateRecord.description));
TraceOutput(TL(appErrorClass, "(.)"));
if (ApptNewRecord(dbP, (ApptDBRecordType*)&newDateRecord, & indexNew))
ErrThrow(exgMemError);
TraceOutput(TL(appErrorClass, "(.)"));
// If uid was set then a unique id was passed to be used.
if (uid != 0 && obeyUniqueIDs)
{
// We can't simply remove any old record using the unique id and
// then add the new record because removing the old record could
// move the new one. So, we find any old record, change the new
// record, and then remove the old one.
indexOld = indexNew;
// Find any record with this uid. indexOld changes only if
// such a record is found.
DmFindRecordByID (dbP, uid, &indexOld);
// Change this record to this uid. The dirty bit is set from
// newly making this record.
DmSetRecordInfo(dbP, indexNew, NULL, &uid);
// Now remove any old record.
if (indexOld != indexNew)
{
DmRemoveRecord(dbP, indexOld);
}
}
// Return the unique id of the record inserted.
DmRecordInfo(dbP, indexNew, NULL, uniqueIDP, NULL);
}
ErrCatch(inErr)
{
error = inErr;
} ErrEndCatch
// Free any temporary buffers used to store the incoming data.
if (newAttachment)
MemPtrFree(newAttachment);
if (newDateRecord.note)
MemPtrFree(newDateRecord.note);
if (newDateRecord.description)
MemPtrFree(newDateRecord.description);
if (newDateRecord.alarm)
MemPtrFree(newDateRecord.alarm);
if (newDateRecord.repeat)
MemPtrFree(newDateRecord.repeat);
if (newDateRecord.exceptions)
MemPtrFree(newDateRecord.exceptions);
if (error)
ErrThrow(error);
return true; // ABa: never tested by DateImportVCal
}
/************************************************************
*
* FUNCTION: DateExportVCal
*
* DESCRIPTION: Export a VCALENDAR record.
*
* PARAMETERS:
* dbP - pointer to the database to export the records from
* index - the record number to export
* recordP - whether the begin statement has been read
* outputStream - pointer to where to export the record to
* outputFunc - function to send output to the stream
* writeUniqueIDs - true to write the record's unique id
*
* RETURNS: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* djk 8/9/97 Created
* CS 05/16/00 Use DayOfMonthType instead of DayOfWeekType.
*
*************************************************************/
extern void DateExportVCal(DmOpenRef dbP, Int16 index, ApptDBRecordPtr recordP,
UInt16 pdiRefNum, PdiWriterType* writer, Boolean writeUniqueIDs)
{
UInt32 uid;
Char tempString[RRULEStringLengthMax];
PdiWriteBeginObject(pdiRefNum, writer, kPdiPRN_BEGIN_VEVENT);
// Handle When
// ASSUMPTION: To represent non-timed events, we will use a
// DTSTART propert with a date value (instead of a date/time value)
// and _no_ DTEND proprty. This is permitted by ISO 8601.
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_DTSTART);
if (TimeToInt(recordP->when->startTime) != apptNoTime)
{
GenerateDateTimeToken(tempString, &recordP->when->date, &recordP->when->startTime);
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteData);
// End Time/Date
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_DTEND);
GenerateDateTimeToken(tempString, &recordP->when->date, &recordP->when->endTime);
}
else
// Handle a non-timed event -- see note above for convention
{
StrPrintF(tempString, "%d%02d%02d", firstYear + recordP->when->date.year,
recordP->when->date.month, recordP->when->date.day);
}
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteData);
// Handle Alarm
if (recordP->alarm != NULL &&
recordP->alarm->advance != apptNoAlarm)
{
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_AALARM);
// Because we cannot access DateBook globals due to our simple second code segment scheme, we
// can't access AlarmSoundRepeatInterval or AlarmSoundRepeatCount. When we switch to a
// smarter multisegment scheme or a large segment scheme, resume using the globals.
// TimSecondsToDateTime(ApptGetAlarmTimeVCalForm(recordP), &alrmDT);
// StrPrintF(tempString, "%d%02d%02dT%02d%02d00;PT%uM;%u" , alrmDT.year, alrmDT.month, alrmDT.day,
// alrmDT.hour, alrmDT.minute, AlarmSoundRepeatInterval / minutesInSeconds, AlarmSoundRepeatCount);
GenerateDateTimeTokenForSeconds(tempString, ApptGetAlarmTimeVCalForm(recordP));
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteData);
}
// Handle Repeating Events
if (recordP->repeat && (recordP->repeat->repeatType != repeatNone))
{
Char* writePtr = tempString;
Char* prepareString;
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_RRULE);
// Set the rule type
switch(recordP->repeat->repeatType)
{
case repeatDaily:
prepareString = (Char*) "D";
break;
case repeatWeekly:
prepareString = (Char*) "W";
break;
// One small oddity is that our repeatMonthlyByDay is equivelent
// to vCal's by-postion and our repeatMonthlyByDate is equivelent
// to vCal's by-Day rule
case repeatMonthlyByDay:
prepareString = (Char*) "MP";
break;
case repeatMonthlyByDate:
case repeatYearly:
// vCal's years rule uses days by number, which creates problems in leap years
// so instead we will use the month by-Day rule (equiv to our month by date rule)
// and multiply by monthsInYear
prepareString = (Char*) "MD";
break;
}
// Set the freqency
if (recordP->repeat->repeatType == repeatYearly)
writePtr += StrPrintF(writePtr, "%s%d ", prepareString, monthsInYear * (UInt16) recordP->repeat->repeatFrequency);
else
writePtr += StrPrintF(writePtr, "%s%d ", prepareString, (UInt16) recordP->repeat->repeatFrequency);
// if the repeat type is repeatWeekly, emit which days the event is on
if (recordP->repeat->repeatType == repeatWeekly)
{
int dayIndex;
for (dayIndex = 0; dayIndex < daysInWeek; dayIndex++)
{
if (GetBitMacro(recordP->repeat->repeatOn, dayIndex))
{
switch(dayIndex)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -