📄 todotransfer.c
字号:
Boolean obeyUniqueIDs, Boolean beginAlreadyRead, UInt32 * uniqueIDP)
{
UInt16 indexNew;
UInt16 indexOld;
UInt32 uid;
volatile ToDoItemType newToDo;
int nv;
char * fieldP;
Boolean firstLoop = true;
volatile Err error = 0;
char categoryName[dmCategoryLength];
UInt16 categoryID = dmUnfiledCategory;
Boolean oneProperty = false; // Aba: true iff one property was found in the note
*uniqueIDP = 0;
categoryName[0] = 0;
TraceOutput(TL(appErrorClass, "ToDoImportVToDo: BEGIN"));
// Read in the vEvent entry
if (!beginAlreadyRead)
{
PdiReadProperty(pdiRefNum, reader);
beginAlreadyRead = reader->property == kPdiPRN_BEGIN_VTODO;
}
if (!beginAlreadyRead)
return false;
// Ennter the object
PdiEnterObject(pdiRefNum, reader);
// Initialize the record to default values
*((UInt16 *) &newToDo.dueDate) = toDoNoDueDate;
newToDo.priority = defaultPriority;
newToDo.priority &= incompleteFlag;
newToDo.description = NULL;
newToDo.note = NULL;
fieldP = NULL;
uid = 0;
// 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_VTODO)
{
TraceOutput(TL(appErrorClass, "ToDoImportVToDo: property = %s", reader->propertyName));
switch(reader->property)
{
// Handle Priority tag
case kPdiPRN_PRIORITY:
PdiReadPropertyField(pdiRefNum, reader, &fieldP, kPdiResizableBuffer, kPdiDefaultFields);
if (fieldP != NULL)
{
nv = StrAToI(fieldP);
nv = min(nv, toDoMaxPriority);
newToDo.priority = nv | (newToDo.priority & completeFlag);
}
oneProperty = true;
break;
// Handle the due date.
case kPdiPRN_DUE:
PdiReadPropertyField(pdiRefNum, reader, &fieldP, kPdiResizableBuffer, kPdiDefaultFields);
if (fieldP != NULL)
{
// Extract due date
MatchDateToken(fieldP, (DateType*)&newToDo.dueDate);
}
oneProperty = true;
break;
// Handle the two cases that indicate completed
//the Status:completed property
case kPdiPRN_STATUS:
PdiReadPropertyField(pdiRefNum, reader, &fieldP, kPdiResizableBuffer, kPdiDefaultFields);
if (fieldP != NULL)
{
if (StrCaselessCompare(fieldP, "COMPLETED") == 0)
{
newToDo.priority |= completeFlag;
}
}
oneProperty = true;
break;
// and the date/time completed property
case kPdiPRN_COMPLETED:
newToDo.priority |= completeFlag;
oneProperty = true;
break;
// Handle the description
case kPdiPRN_DESCRIPTION:
PdiReadPropertyField(pdiRefNum, reader, (Char**) &newToDo.description, kPdiResizableBuffer, kPdiDefaultFields);
oneProperty = true;
break;
// Treat attachments as notes
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
PdiReadPropertyField(pdiRefNum, reader, (Char**) &newToDo.note, kPdiResizableBuffer, kPdiDefaultFields);
oneProperty = true;
break;
// read in the category
case kPdiPRN_CATEGORIES:
PdiReadPropertyField(pdiRefNum, reader, &fieldP, kPdiResizableBuffer, kPdiDefaultFields);
if (fieldP != NULL)
{
char *spot = fieldP;
// If the category was not a predefined vCal catval,
// we need to skip the leading special category name mark ("X-")
if (spot[0] == 'X' && spot[1] == '-')
{
spot += 2;
}
// Make a copy, leaving room for the terminator, cropping if necessary.
StrNCopy(categoryName, spot, dmCategoryLength - 1);
// Make sure it is null terminated.
categoryName[dmCategoryLength - 1] = 0;
}
oneProperty = true;
break;
// read in the unique identifier
case kPdiPRN_UID:
PdiReadPropertyField(pdiRefNum, reader, &fieldP, kPdiResizableBuffer, kPdiDefaultFields);
if (fieldP != NULL)
{
uid = StrAToI(fieldP);
// Check the uid for reasonableness.
if (uid < (dmRecordIDReservedRange << 12))
uid = 0;
}
oneProperty = true;
break;
}
}
if (fieldP != NULL)
MemPtrFree(fieldP);
// Non syntax error but empty object: don't create it
if (oneProperty == false)
ErrThrow(errNone);
// Make sure that there are values for description and note
if (newToDo.description == NULL)
{
newToDo.description = (Char *) MemPtrNew(sizeOf7BitChar('\0'));
*newToDo.description = '\0' ;
}
if (newToDo.note == NULL)
{
// Need to add bound checking here so we don't read in
// more chars than the max note size
newToDo.note = (Char *) MemPtrNew(sizeOf7BitChar('\0'));
*newToDo.note = '\0' ;
}
// Set the category for the record (we saved category ID in appData field)
if (((ExgSocketPtr)(reader->appData))->appData)
{
categoryID = ((ExgSocketPtr)(reader->appData))->appData & dmRecAttrCategoryMask;
}
// we really need to recognize the vCal category specified, our category picker needs to somehow
// know the default category. Without that support, we need to always put things into unfiled by
// default because that is what we show the user. This logic really needs to run before the ask dialog
// comes up, but we have not yet parsed the data then... Hmmmm
#ifdef OLD_CATEGORY_TRANSPORT
// If a category was included, try to use it
else if (categoryName[0]) {
// Get the category ID
categoryID = CategoryFind(dbP, categoryName);
// If it doesn't exist, and we have room, create it
if (categoryID == dmAllCategories) {
// Find the first unused category
categoryID = CategoryFind(dbP, "");
// If there is a slot, fill it with the name we were given
if (categoryID != dmAllCategories) {
CategorySetName(dbP, categoryID, categoryName);
}
else
cateoryID = dmUnfiledCategory; // reset to default
}
}
#endif // OLD_CATEGORY_TRANSPORT
// Write the actual record
TraceOutput(TL(appErrorClass, "Add the record"));
if (ToDoNewRecord(dbP, (ToDoItemType*)&newToDo, categoryID, &indexNew))
ErrThrow(exgMemError);
// 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)
{
// Throw the error after the memory is cleaned winUp.
error = inErr;
} ErrEndCatch
// Free any temporary buffers used to store the incoming data.
if (newToDo.note) MemPtrFree(newToDo.note);
if (newToDo.description) MemPtrFree(newToDo.description);
if (error)
ErrThrow(error);
return ((reader->events & kPdiEOFEventMask) == 0);
}
/************************************************************
*
* FUNCTION: ToDoImportVCal
*
* DESCRIPTION: Import a VCal record of type vEvent and vToDo
*
* The Datebook handles vCalendar records. Any vToDo records
* are sent to the ToDo app for importing.
*
* This routine doesn't exist for the device since the Datebook
* is sent vCal data. The Datebook will To Do any vToDo records
* via an action code. This routine is only for the simulator
* because the Datebook can't run at the same time.
*
* 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
* vToDoFunc - function to import vToDo records
* on the device this is a function to call ToDo to read
* for the shell command this is an empty function
*
* RETURNS: true if the input was read
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* djk 8/9/97 Created
* roger 9/12/97 Modified to work on the device
* ABa 06/21/00 Integrate Pdi library
*
*************************************************************/
extern Boolean ToDoImportVCal(DmOpenRef dbP, UInt16 pdiRefNum, PdiReaderType* reader,
Boolean obeyUniqueIDs, Boolean beginAlreadyRead, ImportVEventF vEventFunc)
{
UInt32 uid;
UInt32 uniqueID = 0;
Err error = 0;
uid = 0;
TraceOutput(TL(appErrorClass, "ToDoImportVCal: BEGIN"));
// Read in the vEvent entry
if (!beginAlreadyRead)
{
PdiReadProperty(pdiRefNum, reader);
beginAlreadyRead = reader->property == kPdiPRN_BEGIN_VCALENDAR;
}
if (!beginAlreadyRead)
return false;
// Read in the vcard entry
if (beginAlreadyRead)
{
PdiEnterObject(pdiRefNum, reader);
while (PdiReadProperty(pdiRefNum, reader) == 0 && reader->property != kPdiPRN_END_VCALENDAR)
{
// Hand it off to the correct sub-routine
// Note: here VCalEventRead is a dummy routine that just runs until it finds an end
if (reader->property == kPdiPRN_BEGIN_VTODO)
{
ToDoImportVToDo(dbP, pdiRefNum, reader, obeyUniqueIDs, true, &uniqueID);
ToDoSetGoToParams (dbP, reader->appData, uniqueID);
}
else if (reader->property == kPdiPRN_BEGIN_VEVENT)
{
error = vEventFunc(dbP, pdiRefNum, reader, obeyUniqueIDs, true, &uniqueID);
if (error)
ErrThrow(error);
}
}
}
return ((reader->events & kPdiEOFEventMask) == 0);
}
/************************************************************
*
* FUNCTION: ToDoExportVCal
*
* DESCRIPTION: Export a VCALENDAR record.
*
* 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
*
*************************************************************/
extern void ToDoExportVCal(DmOpenRef dbP, Int16 index, ToDoDBRecordPtr recordP,
UInt16 pdiRefNum, PdiWriterType* writer, Boolean writeUniqueIDs)
{
Char * note; // b/c the note doesnt have its own pointer in the record
UInt32 uid;
Char tempString[tempStringLengthMax];
UInt16 attr;
ErrNonFatalDisplayIf (dmCategoryLength > tempStringLengthMax,
"ToDoExportVCal: tempString too Int16");
PdiWriteBeginObject(pdiRefNum, writer, kPdiPRN_BEGIN_VTODO);
// Emit the Category
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_CATEGORIES);
DmRecordInfo (dbP, index, &attr, NULL, NULL);
CategoryGetName(dbP, (attr & dmRecAttrCategoryMask), tempString + 2);
// Check to see if the category is a predefined vCal catval
if((StrCaselessCompare(tempString, "Personal") != 0) &&
(StrCaselessCompare(tempString, "Business") != 0))
{
tempString[0] = 'X';
tempString[1] = '-';
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteText);
}
else
{
PdiWritePropertyValue(pdiRefNum, writer, tempString + 2, kPdiWriteText);
}
// Emit the Due date
if (DateToInt(recordP->dueDate) != toDoNoDueDate)
{
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_DUE);
// NOTE: since we don't keep a time for ToDo due dates,
// we will truncate the ISO 8601 date/time to an ISO 8601 date
// as allowed by the standard
StrPrintF(tempString, "%d%02d%02d", firstYear + recordP->dueDate.year,
recordP->dueDate.month, recordP->dueDate.day);
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteData);
}
// Emit the completed flag
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_STATUS);
if (recordP->priority & completeFlag)
{
PdiWritePropertyValue(pdiRefNum, writer, (Char*) "COMPLETED", kPdiWriteData);
}
else
{
PdiWritePropertyValue(pdiRefNum, writer, (Char*) "NEEDS ACTION", kPdiWriteData);
}
// Emit the Priority Level
if ((recordP->priority & priorityOnly) != 0)
{
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_PRIORITY);
StrPrintF(tempString, "%d", recordP->priority & priorityOnly);
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteData);
}
// Emit the Decsription Text
if(recordP->description != '\0')
{
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_DESCRIPTION);
PdiWritePropertyValue(pdiRefNum, writer, &recordP->description, kPdiWriteText);
}
// Get the pointer to the note
note = (&recordP->description) + StrLen(&recordP->description) + 1;
// Emit the note
if(*note != '\0')
{
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_ATTACH);
PdiWritePropertyValue(pdiRefNum, writer, note, kPdiWriteText);
}
// Emit an unique id
if (writeUniqueIDs)
{
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_UID);
// Get the record's unique id and append to the string.
DmRecordInfo(dbP, index, NULL, &uid, NULL);
StrIToA(tempString, uid);
PdiWritePropertyValue(pdiRefNum, writer, tempString, kPdiWriteData);
}
PdiWriteEndObject(pdiRefNum, writer, kPdiPRN_END_VTODO);
if (writer->error)
ErrThrow(writer->error);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -