⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 addresstransfer.c

📁 我的Palm OS 5 SDK zhCN_PIMApps代码。 使用codewarrior 开发环境
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
 *
 * Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
 *
 * File: AddressTransfer.c
 *
 * Release: Palm OS 5 SDK (68K) R3.
 *
 * Description:
 *      Address Book routines to transfer records.
 *
 *****************************************************************************/

#include "Address.h"
#include "AddressTransfer.h"
#include "AddressRsc.h"
#include "AddrDefines.h"
#include "AddrTools.h"

#include <TraceMgr.h>
#include <PdiLib.h>
#include <UDAMgr.h>
#include <ErrorMgr.h>
#include <UIResources.h>
#include <StringMgr.h>
#include <Category.h>
#include <PalmLocale.h>

/***********************************************************************
 *
 *   Defines
 *
 ***********************************************************************/

#define identifierLengthMax			40
#define addrFilenameExtension		"vcf"
#define addrFilenameExtensionLength	3
#define addrMIMEType				"text/x-vCard"

// Aba: internal version of vCalendar. Must be updated
// the export side of the vCalendar code evoluate

#define kVObjectVersion						"5.3"

/***********************************************************************
 *
 *	Internal Functions
 *
 ***********************************************************************/

static Err	PrvTransferPdiLibLoad(UInt16* refNum, Boolean *loadedP);
static void	PrvTransferPdiLibUnload(UInt16 refNum, Boolean loaded);
static Err	PrvTransferSendRecordTryCatch (DmOpenRef dbP, Int16 recordNum, AddrDBRecordPtr recordP, UDAWriterType* media);
static void	PrvTransferCleanFileName(Char* ioFileName);
static Err	PrvTransferSendCategoryTryCatch (DmOpenRef dbP, UInt16 categoryNum, UDAWriterType*  media, UInt16 index);
static void PrvTransferSetGoToParams (DmOpenRef dbP, ExgSocketPtr exgSocketP, UInt32 uniqueID);

static MemHandle PrvTransferGetFullName (AddrDBRecordPtr r, Int16 useCompany);
static Boolean PrvTransferAlternateFieldExists(AddrDBRecordPtr recordP);

/***********************************************************************
 *
 * FUNCTION:		TransferRegisterData
 *
 * DESCRIPTION:		Register with the exchange manager to receive data
 * with a certain name extension.
 *
 * PARAMETERS:		nothing
 *
 * RETURNED:		nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			rsf		12/2/97		Created
 *
 ***********************************************************************/
void TransferRegisterData (void)
{
	MemHandle resH = DmGetResource(strRsc, ExgDescriptionStr);
	void *desc = MemHandleLock(resH);

	ExgRegisterDatatype(sysFileCAddress, exgRegExtensionID, addrFilenameExtension, desc, 0);
	ExgRegisterDatatype(sysFileCAddress, exgRegTypeID, addrMIMEType, desc, 0);
	MemHandleUnlock(resH);
	DmReleaseResource(resH);
}

/***********************************************************************
 *
 * FUNCTION:    TransferSendRecord
 *
 * DESCRIPTION: Send a record.
 *
 * PARAMETERS:	dbP - pointer to the database to add the record to
 * 				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
 *         dje     4/24/00  Don't specify target creator ID
 *         ABa     6/20/00  Integrate Pdi library
 *		   vsm 	   12/5/02  Use PrvTransferGetFullName to lay out the name fields
 *							in the appropriate order.
 *
 ***********************************************************************/
void TransferSendRecord (DmOpenRef dbP, Int16 recordNum, const Char * const prefix, UInt16 noDataAlertID)
{
	AddrDBRecordType record;
	MemHandle recordH;
	MemHandle descriptionH;
	UInt16 descriptionSize = 0;
	Int16 descriptionWidth;
	Boolean descriptionFit;
	UInt16 newDescriptionSize;
	MemHandle nameH;
	MemHandle resourceH;
	Char *resourceP;
	Err error;
	ExgSocketType exgSocket;
	UDAWriterType* media;
	UInt8 schemeLength;

	TraceInit();
	TraceOutput(TL(appErrorClass, "Pdi Version"));

	// 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.
	error = AddrDBGetRecord (dbP, recordNum, &record, &recordH);
	ErrNonFatalDisplayIf(error, "Can't get record");

	if (AddrDBRecordContainsData(&record))
	{
		descriptionH = PrvTransferGetFullName (&record, SortByCompany);
		if (descriptionH)
		{
			exgSocket.description = MemHandleLock(descriptionH);
			descriptionSize = StrLen(exgSocket.description);
		}


		// Truncate the description if too long
		if (descriptionSize > 0)
		{
			// Make sure the description isn't too long.
			newDescriptionSize = descriptionSize;
			WinGetDisplayExtent(&descriptionWidth, NULL);
			FntCharsInWidth (exgSocket.description, &descriptionWidth, (Int16 *)&newDescriptionSize, &descriptionFit);

			if (newDescriptionSize > 0)
			{
				if (newDescriptionSize != descriptionSize)
				{
					exgSocket.description[newDescriptionSize] = nullChr;
					MemHandleUnlock(descriptionH);
					MemHandleResize(descriptionH, newDescriptionSize + sizeOf7BitChar('\0'));
					exgSocket.description = MemHandleLock(descriptionH);
				}
			}
			else
			{
				MemHandleFree(descriptionH);
				descriptionH = NULL;
			}
			descriptionSize = newDescriptionSize;
		}

		// Make a filename
		schemeLength = StrLen(prefix);
		if (descriptionSize > 0)
		{
			// Now make a filename from the description
			nameH = MemHandleNew(schemeLength + imcFilenameLength);
			exgSocket.name = MemHandleLock(nameH);
			StrCopy(exgSocket.name, prefix);
			StrNCat(exgSocket.name, exgSocket.description,
					schemeLength + imcFilenameLength - addrFilenameExtensionLength - sizeOf7BitChar('.'));
			StrCat(exgSocket.name, ".");
			StrCat(exgSocket.name, addrFilenameExtension);
		}
		else
		{
			// A description is needed.  Either there never was one or the first line wasn't usable.
			if (descriptionH)
				MemHandleFree(descriptionH);
			
			descriptionH = DmGetResource(strRsc, BeamDescriptionStr);
			exgSocket.description = MemHandleLock(descriptionH);

			resourceH = DmGetResource(strRsc, BeamFilenameStr);
			resourceP = MemHandleLock(resourceH);
			nameH = MemHandleNew(schemeLength + StrLen(resourceP) + 1);
			exgSocket.name = MemHandleLock(nameH);
			StrCopy(exgSocket.name, prefix);
			StrCat(exgSocket.name, resourceP);
			MemHandleUnlock(resourceH);
			DmReleaseResource(resourceH);
		}

		//ABa: remove superfluous '.' characters
		PrvTransferCleanFileName(exgSocket.name);
		exgSocket.length = MemHandleSize(recordH) + 100;		// rough guess
		//exgSocket.target = sysFileCAddress;		// commented out 4/24/00 dje
		exgSocket.type = (Char *)addrMIMEType;
		error = ExgPut(&exgSocket);   // put data to destination


		TraceOutput(TL(appErrorClass, "TransferSendRecord: description = %s, name = %s", exgSocket.description, exgSocket.name));
		// ABa: Changes to use new streaming mechanism
		media = UDAExchangeWriterNew(&exgSocket,  512);
		if (!error)
		{
			if (media)
				error = PrvTransferSendRecordTryCatch(dbP, recordNum, &record, media);
			else
				error = exgMemError;
				
			ExgDisconnect(&exgSocket, error);
		}
		
		if (media)
			UDADelete(media);

		// Clean up
		if (descriptionH)
		{
			MemHandleUnlock (descriptionH);
			if (MemHandleDataStorage (descriptionH))
				DmReleaseResource(descriptionH);
			else
				MemHandleFree(descriptionH);
		}
		if (nameH)
		{
			MemHandleUnlock (nameH);
			if (MemHandleDataStorage (nameH))
				DmReleaseResource(nameH);
			else
				MemHandleFree(nameH);
		}
	}
	else
		FrmAlert(noDataAlertID);


	MemHandleUnlock(recordH);
	
	// No need to release the record because AddrDBGetRecord didn't mark it busy.
	//DmReleaseRecord(dbP, recordNum, false);
	
	TraceClose();
	return;
}




/***********************************************************************
 *
 * FUNCTION:    TransferSendCategory
 *
 * DESCRIPTION: Send all visible records in a category.
 *
 * PARAMETERS:	dbP - pointer to the database to add the record to
 * 				categoryNum - the category of records to send
 *				prefix - the scheme with ":" suffix and optional "?" prefix
 *				noDataAlertID - alert to put up if there is nothing to send
 *
 * RETURNED:    true if any records are found and sent
 *
 * REVISION HISTORY:
 *         Name   Date      Description
 *         ----   ----      -----------
 *         roger   5/9/97   Initial Revision
 *         dje     4/24/00  Don't specify target creator ID
 *
 ***********************************************************************/
void TransferSendCategory (DmOpenRef dbP, UInt16 categoryNum, const Char * const prefix, UInt16 noDataAlertID)
{
	Err error;
	Char description[dmCategoryLength];
	UInt16 index;
	Boolean foundAtLeastOneRecord;
	ExgSocketType exgSocket;
	UInt16 mode;
	LocalID dbID;
	UInt16 cardNo;
	Boolean databaseReopened;
	UDAWriterType* media;

	TraceInit();
	// If the database was opened to show secret records, reopen it to not see
	// secret records.  The idea is that secret records are not sent when a
	// category is sent.  They must be explicitly sent one by one.
	DmOpenDatabaseInfo(dbP, &dbID, NULL, &mode, &cardNo, NULL);
	if (mode & dmModeShowSecret)
	{
		dbP = DmOpenDatabase(cardNo, dbID, dmModeReadOnly);
		databaseReopened = true;
	}
	else
		databaseReopened = false;


	// important to init structure to zeros...
	MemSet(&exgSocket, sizeof(exgSocket), 0);


	// Make sure there is at least one record in the category.
	index = 0;
	foundAtLeastOneRecord = false;
	while (true)
	{
		if (DmSeekRecordInCategory(dbP, &index, 0, dmSeekForward, categoryNum) != 0)
			break;

		foundAtLeastOneRecord = DmQueryRecord(dbP, index) != 0;
		if (foundAtLeastOneRecord)
			break;


		index++;
	}


	// We should send the category because there's at least one record to send.
	if (foundAtLeastOneRecord)
	{
		// Form a description of what's being sent.  This will be displayed
		// by the system send dialog on the sending and receiving devices.
		CategoryGetName (dbP, categoryNum, description);
		exgSocket.description = description;

		// Now form a file name
		exgSocket.name = MemPtrNew(StrLen(prefix) + StrLen(description) + sizeOf7BitChar('.') + StrLen(addrFilenameExtension) + sizeOf7BitChar('\0'));
		if (exgSocket.name)
		{
			StrCopy(exgSocket.name, prefix);
			StrCat(exgSocket.name, description);
			StrCat(exgSocket.name, ".");
			StrCat(exgSocket.name, addrFilenameExtension);
		}
		// ABa: remove superfluous '.' chars
		PrvTransferCleanFileName(exgSocket.name);
		exgSocket.length = 0;		// rough guess
		//exgSocket.target = sysFileCAddress;		// commented out 4/24/00 dje
		exgSocket.type = (Char *)addrMIMEType;
		error = ExgPut(&exgSocket);   // put data to destination
		media = UDAExchangeWriterNew(&exgSocket, 512);
		if (!error)
		{
			if (media)
				error = PrvTransferSendCategoryTryCatch (dbP, categoryNum, media, index);
			else
				error = exgMemError;
				
			ExgDisconnect(&exgSocket, error);
		}

		// Release file name
		if (exgSocket.name)
			MemPtrFree(exgSocket.name);

		if (media)
			UDADelete(media);
	}
	else
		FrmAlert(noDataAlertID);

	if (databaseReopened)
		DmCloseDatabase(dbP);

	TraceClose();
	return;
}


/***********************************************************************
 *
 * FUNCTION:		ReceiveData
 *
 * DESCRIPTION:		Receives data into the output field using the Exg API
 *
 * PARAMETERS:		exgSocketP, socket from the app code
 *						 sysAppLaunchCmdExgReceiveData
 *
 * RETURNED:		error code or zero for no error.
 *
 * REVISION HISTORY:
 *         Name   Date      Description
 *         ----   ----      -----------
 *         ABa     6/20/00  Integrate Pdi library
 *
 ***********************************************************************/
Err TransferReceiveData(DmOpenRef dbP, ExgSocketPtr exgSocketP)
{
	volatile Err err;
	UInt16 pdiRefNum = sysInvalidRefNum;
	PdiReaderType* reader = NULL;
	UDAReaderType* stream = NULL;
	Boolean loaded;

	// accept will open a progress dialog and wait for your receive commands
	if ((err = ExgAccept(exgSocketP)) != 0)
		return err;

	TraceInit();

	if ((err = PrvTransferPdiLibLoad(&pdiRefNum, &loaded)))
	{
		pdiRefNum = sysInvalidRefNum;
		goto errorDisconnect;
	}	
		
	if ((stream = UDAExchangeReaderNew(exgSocketP)) == NULL)
	{
		err = exgMemError;
		goto errorDisconnect;
	}
		
	if ((reader = PdiReaderNew(pdiRefNum, stream, kPdiOpenParser)) == NULL)
	{
		err = exgMemError;
		goto errorDisconnect;
	}
	
	reader->appData = exgSocketP;
	
	ErrTry
	{
		// Keep importing records until it can't
		while(TransferImportVCard(dbP, pdiRefNum, reader, false, false)){};
	}
	ErrCatch(inErr)
	{
		err = inErr;
	} ErrEndCatch

	// Aba: A record has been added in the Database iff the GoTo
	// uniqueID parameter != 0.
	// In the case no record is added, return an error
	if (err == errNone && exgSocketP->goToParams.uniqueID == 0)
		err = exgErrBadData;
	
errorDisconnect:
	if (reader)
		PdiReaderDelete(pdiRefNum, &reader);

	if (stream)
		UDADelete(stream);
	
	if (pdiRefNum != sysInvalidRefNum)
		PrvTransferPdiLibUnload(pdiRefNum, loaded);
		
	ExgDisconnect(exgSocketP, err); // closes transfer dialog
	err = errNone;	// error was reported, so don't return it

	TraceClose();
	
	return err;
}


/************************************************************
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -