📄 todotransfer.c
字号:
/******************************************************************************
*
* Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
*
* File: ToDoTransfer.c
*
* Release: Palm OS 5 SDK (68K) R3.
*
* Description:
* To Do routines to transfer records.
*
*****************************************************************************/
#include <PalmOS.h>
#include <PdiLib.h>
#include <UDAMgr.h>
#include <TraceMgr.h>
#include <PalmUtils.h>
#include "ToDo.h"
#include "ToDoRsc.h"
#define identifierLengthMax 40
#define tempStringLengthMax 20
#define defaultPriority 1
#define incompleteFlag 0x7F
#define todoSuffix ".vcs"
#define todoMIMEType "text/x-vCalendar"
// Aba: internal version of vCalendar. Must be updated
// the export side of the vCalendar code evoluate
#define kVObjectVersion "5.3"
extern Char * GetToDoNotePtr (ToDoDBRecordPtr recordP); // needed to see if ToDo empty
/***********************************************************************
*
* FUNCTION: PrvPdiLibLoad
*
* DESCRIPTION: Load Pdi library
* PARAMETERS: a pointer to an integer: the refNum of the libary
* return whether the library had to be loaded (and therefore
* needs to be unloaded)
*
* RETURNED: An error if library is not found
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* ABa 4/10/00 Created
*
***********************************************************************/
static Err PrvPdiLibLoad(UInt16* refNum, Boolean *loadedP)
{
Err error;
// Load the Pdi library
// Check if the library was pre-loaded (this is useful if we can
// be called from another app via an action code and want to use an existing
// instance of the library in case our caller has already loaded it)
*loadedP = false;
error = SysLibFind(kPdiLibName, refNum);
if (error != 0)
{
error = SysLibLoad(sysResTLibrary, sysFileCPdiLib, refNum);
TraceOutput(TL(appErrorClass, "Loading Pdi library."));
if (! error)
*loadedP = true;
}
if (error)
{
// We're here because the Pdi library failed to load.
// Inform the user or do something else defensive here.
ErrNonFatalDisplay(kPdiLibName " not found");
return error;
}
error = PdiLibOpen(*refNum);
return error;
}
/***********************************************************************
*
* FUNCTION: PrvPdiLibUnload
*
* DESCRIPTION: Unload Pdi library
* PARAMETERS: The refnum of the pdi library
* Whether the library was loaded (and therefore needs to be unloaded)
*
* RETURNED: NONE
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* ABa 4/10/00 Created
*
***********************************************************************/
static void PrvPdiLibUnload(UInt16 refNum, Boolean loaded)
{
if (PdiLibClose(refNum) == 0)
{
TraceOutput(TL(appErrorClass, "Unloading Pdi library."));
if (loaded)
SysLibRemove(refNum);
}
}
/***********************************************************************
*
* FUNCTION: PrvTransferCleanFileName
*
* DESCRIPTION: Remove dot characters in file name but not the least
* PARAMETERS: a pointer to a string
*
* RETURNED: String parameter doesn't contains superfluous dot characters
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* ABa 7/28/00 Created
*
***********************************************************************/
static void PrvTransferCleanFileName(Char* ioFileName)
{
Char* mayBeLastDotP;
Char* lastDotP;
UInt32 chrFullStopSize = TxtCharSize(chrFullStop);
// prevent NULL & empty string
if (ioFileName == NULL || *ioFileName == 0)
return;
// remove dot but not the last one
mayBeLastDotP = StrChr(ioFileName, chrFullStop);
while ((lastDotP = StrChr(mayBeLastDotP + chrFullStopSize, chrFullStop)))
{
// remove the dot
StrCopy(mayBeLastDotP, mayBeLastDotP + chrFullStopSize);
mayBeLastDotP = lastDotP - chrFullStopSize;
}
}
/************************************************************
*
* FUNCTION: MatchDateToken
*
* DESCRIPTION: Extract date from the given string
*
* PARAMETERS:
* tokenP - string ptr from which to extract
* dateP - ptr where to store date (optional)
*
* RETURNS: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* djk 2/2/98 Copied code from Date Book
*
*************************************************************/
static void MatchDateToken (const char* tokenP, DateType * dateP)
{
char identifier[identifierLengthMax];
int nv;
// Use identifier[] as a temp buffer to copy parts of the vCal DateTime
// so we can convert them to correct form. This date portion
// is 4 chars (date) + 2 chars (month) + 2 chars (day) = 8 chars long
// Read the Year
StrNCopy(identifier, tokenP, 4);
identifier[4] = nullChr;
nv = StrAToI(identifier);
// Validate the number and use it.
if (nv < firstYear || lastYear < nv)
nv = firstYear;
dateP->year = nv - firstYear;
tokenP += StrLen(identifier) * sizeof(Char);
// Read the Month
StrNCopy(identifier, tokenP, 2);
identifier[2] = nullChr;
nv = StrAToI(identifier);
// Validate the number and use it.
if (nv < 1 || monthsInYear < nv)
nv = 1;
dateP->month = nv;
tokenP += StrLen(identifier) * sizeof(Char);
// Read the Day
StrNCopy(identifier, tokenP, 2);
identifier[2] = nullChr;
nv = StrAToI(identifier);
// Validate the number and use it.
if (nv < 1 || 31 < nv)
nv = 1;
dateP->day = nv;
tokenP += StrLen(identifier) * sizeof(Char);
}
/***********************************************************************
*
* FUNCTION: SetDescriptionAndFilename
*
* DESCRIPTION: Derive and allocate a decription and filename from some text.
*
* PARAMETERS: textP - the text string to derive the names from
* descriptionPP - pointer to set to the allocated description
* descriptionHP - MemHandle to set to the allocated description
* filenamePP - pointer to set to the allocated filename
* filenameHP - MemHandle to set to the allocated description
* prefix - the scheme with ":" suffix and optional "?" prefix
*
* RETURNED: a description and filename are allocated and the pointers are set
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 11/4/97 Initial Revision
*
***********************************************************************/
static void SetDescriptionAndFilename(Char * textP, Char **descriptionPP,
MemHandle *descriptionHP, Char **filenamePP, MemHandle *filenameHP,
const Char * const prefix)
{
Char * descriptionP;
Int16 descriptionSize;
Int16 descriptionWidth;
Boolean descriptionFit;
Char * spaceP;
Char * filenameP;
MemHandle resourceH;
Char * resourceP;
UInt8 filenameLength;
UInt8 schemeLength;
Coord unused;
descriptionSize = StrLen(textP);
WinGetDisplayExtent(&descriptionWidth, &unused);
FntCharsInWidth (textP, &descriptionWidth, &descriptionSize, &descriptionFit);
if (descriptionSize > 0)
{
*descriptionHP = MemHandleNew(descriptionSize+sizeOf7BitChar('\0'));
if (*descriptionHP)
{
descriptionP = MemHandleLock(*descriptionHP);
MemMove(descriptionP, textP, descriptionSize);
descriptionP[descriptionSize] = nullChr;
}
}
else
{
*descriptionHP = DmGetResource(strRsc, BeamDescriptionStr);
descriptionP = MemHandleLock(*descriptionHP);
DmReleaseResource(*descriptionHP);
*descriptionHP = NULL; // so the resource isn't freed
}
if (descriptionSize > 0)
{
// Now form a file name. Use only the first word or two.
spaceP = StrChr(descriptionP, spaceChr);
if (spaceP)
// Check for a second space
spaceP = StrChr(spaceP + sizeOf7BitChar(spaceChr), spaceChr);
// If at least two spaces were found then use only that much of the description.
// If less than two spaces were found then use all of the description.
if (spaceP)
filenameLength = spaceP - descriptionP;
else
filenameLength = StrLen(descriptionP);
// Allocate space and form the filename
schemeLength = StrLen(prefix);
*filenameHP = MemHandleNew(schemeLength + filenameLength + StrLen(todoSuffix) + sizeOf7BitChar('\0'));
filenameP = MemHandleLock(*filenameHP);
if (filenameP)
{
StrCopy(filenameP, prefix);
MemMove(&filenameP[schemeLength], descriptionP, filenameLength);
MemMove(&filenameP[schemeLength + filenameLength], todoSuffix,
StrLen(todoSuffix) + sizeOf7BitChar('\0'));
}
}
else
{
resourceH = DmGetResource(strRsc, BeamFilenameStr);
resourceP = MemHandleLock(resourceH);
// Allocate space and form the filename
filenameLength = StrLen(resourceP);
schemeLength = StrLen(prefix);
*filenameHP = MemHandleNew(schemeLength + filenameLength + sizeOf7BitChar('\0'));
filenameP = MemHandleLock(*filenameHP);
if (filenameP)
{
StrCopy(filenameP, prefix);
StrCat(filenameP, resourceP);
}
MemHandleUnlock(resourceH);
DmReleaseResource(resourceH);
}
*descriptionPP = descriptionP;
*filenamePP = filenameP;
}
/***********************************************************************
*
* FUNCTION: ToDoSendRecordTryCatch
*
* DESCRIPTION: Send a record.
*
* PARAMETERS: dbP - pointer to the database to add the record to
* recordNum - the record number to send
* recordP - pointer to the record to send
* exgSocketP - the exchange socket used to send
*
* RETURNED: 0 if there's no error
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 12/11/97 Initial Revision
*
***********************************************************************/
static Err ToDoSendRecordTryCatch (DmOpenRef dbP, Int16 recordNum,
ToDoDBRecordPtr recordP, UDAWriterType* media)
{
volatile Err error = 0;
UInt16 pdiRefNum;
PdiWriterType* writer;
Boolean loaded;
if ((error = PrvPdiLibLoad(&pdiRefNum, &loaded)))
return error;
writer = PdiWriterNew(pdiRefNum, media, kPdiPalmCompatibility);
if (writer)
{
// An error can happen anywhere during the send process. It's easier just to
// catch the error. If an error happens, we must pass it into ExgDisconnect.
// It will then cancel the send and display appropriate ui.
ErrTry
{
PdiWriteBeginObject(pdiRefNum, writer, kPdiPRN_BEGIN_VCALENDAR);
PdiWriteProperty(pdiRefNum, writer, kPdiPRN_VERSION);
PdiWritePropertyValue(pdiRefNum, writer, (Char*)"1.0", kPdiWriteData);
PdiWritePropertyStr(pdiRefNum, writer, "X-PALM", kPdiNoFields, 1);
PdiWritePropertyValue(pdiRefNum, writer, (Char*) kVObjectVersion, kPdiWriteData);
ToDoExportVCal(dbP, recordNum, recordP, pdiRefNum, writer, true);
PdiWriteEndObject(pdiRefNum, writer, kPdiPRN_END_VCALENDAR);
error = UDAWriterFlush(media);
}
ErrCatch(inErr)
{
error = inErr;
} ErrEndCatch
PdiWriterDelete(pdiRefNum, &writer);
}
else
{
error = exgMemError;
}
PrvPdiLibUnload(pdiRefNum, loaded);
return error;
}
/***********************************************************************
*
* FUNCTION: ToDoSendRecord
*
* DESCRIPTION: Send a record.
*
* PARAMETERS: dbP - pointer to the database
* recordNum - the record to send
* prefix - the scheme with ":" suffix and optional "?" prefix
* noDataAlertID - alert to put up if there is nothing to send
*
* RETURNED: true if the record is found and sent
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 5/9/97 Initial Revision
*
***********************************************************************/
extern void ToDoSendRecord (DmOpenRef dbP, Int16 recordNum, const Char * const prefix, UInt16 noDataAlertID)
{
ToDoDBRecordPtr recordP;
MemHandle recordH;
MemHandle descriptionH = NULL;
Err error;
ExgSocketType exgSocket;
MemHandle nameH = NULL;
Boolean empty;
UDAWriterType* media;
// important to init structure to zeros...
MemSet(&exgSocket, sizeof(exgSocket), 0);
// Form a description of what's being sent. This will be displayed
// by the system send dialog on the sending and receiving devices.
recordH = (MemHandle) DmGetRecord(dbP, recordNum);
recordP = (ToDoDBRecordPtr) MemHandleLock(recordH);
// If the description field is empty and the note field is empty,
// consider the record empty.
empty = (! recordP->description) && (! *GetToDoNotePtr(recordP));
if (!empty)
{
// Set the exg description to the record's description.
SetDescriptionAndFilename(&recordP->description, &exgSocket.description,
&descriptionH, &exgSocket.name, &nameH, prefix);
//ABa: remove superfluous '.' characters
PrvTransferCleanFileName(exgSocket.name);
TraceOutput(TL(appErrorClass, "ToDoSendRecord: description = %s, name = %s", exgSocket.description, exgSocket.name));
exgSocket.length = MemHandleSize(recordH) + 100; // rough guess
// Note, a hack in exgmgr will remap this to datebook
// NOTE: ABa To test that the DateBook sublaunches the ToDo app
// when parsing VTODO, just comment out the next line
// And do the same in ToDoSendCategory
exgSocket.target = sysFileCToDo; // include target since todo and date book share an extension
exgSocket.type = (Char *)todoMIMEType;
error = ExgPut(&exgSocket); // put data to destination
// ABa: Changes to use new streaming mechanism
media = UDAExchangeWriterNew(&exgSocket, 512);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -