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

📄 addresstransfer.c

📁 我的Palm OS 5 SDK zhCN_PIMApps代码。 使用codewarrior 开发环境
💻 C
📖 第 1 页 / 共 4 页
字号:
 * FUNCTION: TransferImportVCard
 *
 * DESCRIPTION: Import a VCard 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
 *			----	----		-----------
 *			rsf		4/24/97		Initial Revision
 *			bhall	8/12/99		moved category beaming code from gromit codeline
 *          ABa     6/20/00  	Integrate Pdi library
 *
 *************************************************************/


Boolean TransferImportVCard(DmOpenRef dbP, UInt16 pdiRefNum, PdiReaderType* reader, Boolean obeyUniqueIDs, Boolean beginAlreadyRead)
{
	volatile AddrDBRecordType 	newRecord;
	AddressPhoneLabels 			phoneLabel;
	UInt16						phoneField;
	UInt16 						indexNew;
	UInt16 						indexOld;
	UInt32 						uid;
	Err 						err;
	UInt32 						uniqueID;
	volatile Err 				error = 0;
	UInt16						property;
	Char* 						addressBufferP = NULL;
	Char* 						nameBufferP = NULL;
	UInt16						i;
	UInt16						categoryID;
	char 						categoryName[dmCategoryLength];


	// if we have ExgManager socket
	if (reader->appData != NULL)
	{
		categoryID = ((ExgSocketPtr)(reader->appData))->appData;
	}

	// Initialize a new record
	for (i=0; i < addrNumFields; i++)
		newRecord.fields[i] = NULL;	// clear the record

	newRecord.options.phones.phone1 = 0;	// Work
	newRecord.options.phones.phone2 = 1;	// Home
	newRecord.options.phones.phone3 = 2;	// Fax
	newRecord.options.phones.phone4 = 7;	// Other
	newRecord.options.phones.phone5 = 3;	// Email
	newRecord.options.phones.displayPhoneForList = phone1 - firstPhoneField;

	uid = 0;

	ErrTry
	{
		TraceOutput(TL(appErrorClass, __FILE__ ":TransferImportVCard:%d", __LINE__));

		phoneField = firstPhoneField;

		if (!beginAlreadyRead)
		{
			PdiReadProperty(pdiRefNum, reader);
			beginAlreadyRead = reader->property == kPdiPRN_BEGIN_VCARD;
		}
		
		// if not "BEGIN:VCARD"
		if (!beginAlreadyRead)
			ErrThrow(exgErrBadData);
			
		PdiEnterObject(pdiRefNum, reader);
		PdiDefineResizing(pdiRefNum, reader, 16, tableMaxTextItemSize);

		TraceOutput(TL(appErrorClass, __FILE__ ":TransferImportVCard:%d", __LINE__));
		while (PdiReadProperty(pdiRefNum, reader) == 0 && (property = reader->property) != kPdiPRN_END_VCARD)
		{
			TraceOutput(TL(appErrorClass, "TransferImportVCard (PdiReadProperty): property = %s", reader->propertyName));
			switch(property)
			{
			case kPdiPRN_N:
				PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[name], kPdiResizableBuffer, kPdiDefaultFields);
				PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[firstName], kPdiResizableBuffer, kPdiDefaultFields);
				break;

			case kPdiPRN_ADR:
				{
					UInt8 n = 0;
					UInt16 totalSize;
					Char* addressPostOfficeP = NULL;
					Char* addressExtendedP = NULL;
					Char* strings[3];

					PdiReadPropertyField(pdiRefNum, reader, &addressPostOfficeP, kPdiResizableBuffer, kPdiDefaultFields);
					PdiReadPropertyField(pdiRefNum, reader, &addressExtendedP, kPdiResizableBuffer, kPdiDefaultFields);
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[address], kPdiResizableBuffer, kPdiDefaultFields);
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[city], kPdiResizableBuffer, kPdiDefaultFields);
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[state], kPdiResizableBuffer, kPdiDefaultFields);
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[zipCode], kPdiResizableBuffer, kPdiDefaultFields);
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[country], kPdiResizableBuffer, kPdiDefaultFields);

					if (newRecord.fields[address] != NULL)
					{
						strings[n++] = newRecord.fields[address];
						totalSize += StrLen(newRecord.fields[address]);
					}
					if (addressPostOfficeP != NULL)
					{
						strings[n++] = addressPostOfficeP;
						totalSize += StrLen(addressPostOfficeP);
					}
					if (addressExtendedP != NULL)
					{
						strings[n++] = addressExtendedP;
						totalSize += StrLen(addressExtendedP);
					}

					if (addressPostOfficeP != NULL || addressExtendedP != NULL)
					{
						Char* result = NULL;

						totalSize += (n - 1) * (sizeOf7BitChar(linefeedChr) + sizeOf7BitChar(spaceChr)) + sizeOf7BitChar(nullChr);
						if (totalSize > tableMaxTextItemSize)
						{
							totalSize = tableMaxTextItemSize;
						}
						result = MemHandleLock(MemHandleNew(totalSize));
						if (result != NULL)
						{
							*result = 0;
							while (n > 0)
							{
								n--;
								StrNCat(result, strings[n], totalSize);
								if (n != 0)
								{
									StrNCat(result, "\n ", totalSize);
								}
							}
						}
						if (addressPostOfficeP != NULL)
						{
							MemPtrFree(addressPostOfficeP);
						}
						if (addressExtendedP != NULL)
						{
							MemPtrFree(addressExtendedP);
						}
						if (newRecord.fields[address] != NULL && result != NULL)
						{
							MemPtrFree(newRecord.fields[address]);
						}
						if (result != NULL)
						{
							newRecord.fields[address] = result;
						}
					}
				}
				break;

			case kPdiPRN_FN:
				// Take care of FN iff no name nor first name.
				if (newRecord.fields[name] == NULL && newRecord.fields[firstName] == NULL)
				{
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[name], kPdiResizableBuffer, kPdiDefaultFields);
				}
				break;

			case kPdiPRN_NICKNAME:
				// Take care of nickname iff no first name.
				if (newRecord.fields[firstName] == NULL)
				{
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[firstName], kPdiResizableBuffer, kPdiDefaultFields);
				}
				break;

			case kPdiPRN_ORG:
				PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[company], kPdiResizableBuffer, kPdiConvertSemicolon);
				break;

			case kPdiPRN_TITLE:
				PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[title], kPdiResizableBuffer, kPdiConvertSemicolon);
				break;

			case kPdiPRN_NOTE:
				PdiDefineResizing(pdiRefNum, reader, 16, noteViewMaxLength);
				PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[note], kPdiResizableBuffer, kPdiNoFields);
				PdiDefineResizing(pdiRefNum, reader, 16, tableMaxTextItemSize);
				break;

			case kPdiPRN_X_PALM_CATEGORY:
				{
					Char* categoryStringP = NULL;
					PdiReadPropertyField(pdiRefNum, reader, &categoryStringP, kPdiResizableBuffer, kPdiNoFields);
					if (categoryStringP != NULL)
					{
						// Make a copy
						StrNCopy(categoryName, categoryStringP, dmCategoryLength - 1);
						categoryName[dmCategoryLength - 1] = 0;
						// Free the string (Imc routines allocate the space)
						MemPtrFree(categoryStringP);
						// If we ever decide to use vCard 3.0 CATEGORIES, we would need to skip additional ones here
					}
				}
				break;

			case kPdiPRN_TEL:
			case kPdiPRN_EMAIL:
				if (phoneField <= lastPhoneField)
				{
					if (reader->property == kPdiPRN_EMAIL)
					{
						phoneLabel = emailLabel;
					}
					else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_FAX))
					{
						phoneLabel = faxLabel;
					}
					else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_PAGER))
					{
						phoneLabel = pagerLabel;
					}
					else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_CAR) || PdiParameterPairTest(reader, kPdiPAV_TYPE_CELL))
					{
						phoneLabel = mobileLabel;
					}
					else if (PdiParameterPairTest(reader, kPdiPAV_X_X_PALM_MAIN))
					{
						phoneLabel = mainLabel;
					}
					else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_HOME))
					{
						phoneLabel = homeLabel;
					}
					else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_WORK))
					{
						phoneLabel = workLabel;
					}
					else
					{
						phoneLabel = otherLabel;
					}
					SetPhoneLabel(&newRecord, phoneField, phoneLabel);
					if (PdiParameterPairTest(reader, kPdiPAV_TYPE_PREF))
					{
						newRecord.options.phones.displayPhoneForList = phoneField - firstPhoneField;
					}
					PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[phoneField], kPdiResizableBuffer, kPdiNoFields);
					if (newRecord.fields[phoneField] != NULL)
					{
						phoneField++;
					}
				}
				break;

			case kPdiPRN_X_PALM_CUSTOM:
				ErrNonFatalDisplayIf(reader->customFieldNumber >= (lastRenameableLabel - firstRenameableLabel + 1),
									 "Invalid Custom Field");
				PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[custom1 + reader->customFieldNumber],
									 kPdiResizableBuffer, kPdiNoFields);
				break;

			case kPdiPRN_BEGIN_VCARD:
				TransferImportVCard(dbP, pdiRefNum, reader, obeyUniqueIDs, true);
				break;

			}
		} // end while

		// We don't have to search for the pref phone, because we are sure it is not null
		// (or it is but there was no TEL or EMAIL property in the vcard and so the
		// displayList is firstPhoneField)

		// if the company and name fields are identical, assume company only
		if (newRecord.fields[name] != NULL
			&& newRecord.fields[company] != NULL
			&& newRecord.fields[firstName] == NULL
			&& StrCompare(newRecord.fields[name], newRecord.fields[company]) == 0)
		{
			MemPtrFree(newRecord.fields[name]);
			newRecord.fields[name] = NULL;
		}

		// Before adding the record verify that one field at least in non NULL
		for (i = 0; i < addrNumFields; i++)
		{
			if (newRecord.fields[i] != NULL)
				goto addRecord;
		}
		
		// All fields are NULL: not really an error but we must not add the record
		ErrThrow(errNone);

addRecord:
		err = AddrDBNewRecord(dbP, (AddrDBRecordType*)&newRecord, &indexNew);

		// Memory error ? 
		if (err)
			ErrThrow(exgMemError);

#ifdef VCARD_CATEGORIES
		// If a category was included, try to use it
		if (categoryName[0])
		{
			UInt16	categoryID;
			UInt16	attr;
			Err		err;

			// 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);
				}
			}

			// Set the category for the record
			if (categoryID != dmAllCategories)
			{
				// Get the attributes
				err = DmRecordInfo(dbP, indexNew, &attr, NULL, NULL);

				// Set them to include the category, and mark the record dirty
				if ((attr & dmRecAttrCategoryMask) != categoryID)
				{
					attr &= ~dmRecAttrCategoryMask;
					attr |= categoryID | dmRecAttrDirty;
					err = DmSetRecordInfo(dbP, indexNew, &attr, NULL);
				}
			}
		}
#endif
		// Set the category for the record
		if (categoryID)
		{
			UInt16	attr;
			Err		err;

			// Get the attributes
			err = DmRecordInfo(dbP, indexNew, &attr, NULL, NULL);

			// Set them to include the category, and mark the record dirty
			if ((attr & dmRecAttrCategoryMask) != categoryID)
			{
				attr &= ~dmRecAttrCategoryMask;
				attr |= categoryID | dmRecAttrDirty;
				err = DmSetRecordInfo(dbP, indexNew, &attr, NULL);
			}
		}

		// 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);
			}
		}


		// Store the information necessary to navigate to the record inserted.
		DmRecordInfo(dbP, indexNew, NULL, &uniqueID, NULL);
		// DOLATER ABa: About the goto code if think I will remove this hack
		// and add a thing like;
		// if (I'm sure data is comming from exchange manager) then
		// 		PrvTransferSetGoToParams.
		// Why not a ExgSocketPtr in reader ?
		//   != NULL <=> I'm sure data is comming from exchange manager
		// Or removing this call (and last one) from Import and storing indexNew
		// in the reader structure (userdata). This will save time when importing a whole category
#if EMULATION_LEVEL != EMULATION_NONE
		// Don't call PrvTransferSetGoToParams for shell commands.  Do this by seeing which
		// input function is passed - the one for shell commands or the local one for exchange.
		if (reader->appData != NULL)
#endif
			PrvTransferSetGoToParams (dbP, (ExgSocketPtr)(reader->appData), uniqueID);
		;
		TraceOutput(TL(appErrorClass, __FILE__ ":TransferImportVCard:%d", __LINE__));
	} //end of ErrTry


	ErrCatch(inErr)
	{
		// Throw the error after the memory is cleaned up.
		error = inErr;
	} ErrEndCatch

	// Free any temporary buffers used to store the incoming data.
	for (i=0; i < addrNumFields; i++)
	{
		if (newRecord.fields[i] != NULL)
		{
			MemPtrFree(newRecord.fields[i]);
			newRecord.fields[i] = NULL;	// clear the record
		}
	}

	// misformed vCard (no BEGIN:xxx): we must stop the import
	if (error == exgErrBadData)
		return false;

	// in other case (typically a memory error) we must throw up the error
	if (error != errNone)
		ErrThrow(error);

	// if no error we must inform caller to continue iff not EOF
	return ((reader->events & kPdiEOFEventMask) == 0);


}

/************************************************************
 *
 * FUNCTION: TransferExportVCard
 *
 * DESCRIPTION: Export a record as a Imc VCard 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
 *
 *	HISTORY:
 *		08/06/97	rsf	Created by Roger Flores
 *		06/09/99	grant	Ensure that phone numbers labeled "other" aren't
 *							tagged as ";WORK" or ";HOME".
 *		08/12/99	bhall	moved category beaming code from gromit codeline
 *		10/30/99	kwk	Use TxtGetChar before calling TxtCharIsDigit.
 *         ABa     6/20/00  Integrate Pdi library
 *
 *************************************************************/
void TransferExportVCard(DmOpenRef dbP, Int16 index, AddrDBRecordType *recordP,
    UInt16 pdiRefNum, PdiWriterType* writer, Boolean writeUniqueIDs)
{
	int			i;
	UInt32			uid;
	AddrAppInfoPtr appInfoP= NULL;
	Char uidString[12];
	Boolean personOnlyAtHome = false;

⌨️ 快捷键说明

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