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

📄 addressdb.c

📁 palm os 上的中文伴侣源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 *
 * Copyright (c) 1995-2002 PalmSource, Inc. All rights reserved.
 *
 * File: AddressDB.c
 *
 * Release: Palm OS 5 SDK (68K) R3.
 *
 * Description:
 *      Address Manager routines
 *
 *****************************************************************************/

#include "AddressDB.h"
#include "AddrDefines.h"

#include <UIResources.h>
#include <SysUtils.h>
#include <ErrorMgr.h>
#include <StringMgr.h>
#include <TextMgr.h>
#include <PalmUtils.h>

#include <FeatureMgr.h>
#include <AddressSortLib.h>

#define sortKeyFieldBits   (BitAtPosition(name) | BitAtPosition(firstName) | BitAtPosition(company))

// The following structure doesn't really exist.  The first field
// varies depending on the data present.  However, it is convient
// (and less error prone) to use when accessing the other information.

typedef struct {
	AddrOptionsType		options;            // Display by company or by name
	AddrDBRecordFlags	flags;
	UInt8				companyFieldOffset; // Offset from firstField
	char				firstField;
} PrvAddrPackedDBRecord;


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

static void		PrvAddrDBFindKey(PrvAddrPackedDBRecord *r, char **key, UInt16 *whichKey, Int16 sortByCompany);
static Int16	PrvAddrDBComparePackedRecords(PrvAddrPackedDBRecord *r1, PrvAddrPackedDBRecord *r2, Int16 sortByCompany, SortRecordInfoPtr /*info1*/, SortRecordInfoPtr /*info2*/, MemHandle /*appInfoH*/);
static Int16	PrvAddrDBUnpackedSize(AddrDBRecordPtr r);
static void		PrvAddrDBPack(AddrDBRecordPtr s, void * recordP);
static void		PrvAddrDBUnpack(PrvAddrPackedDBRecord *src, AddrDBRecordPtr dest);
static UInt16	PrvAddrDBFindSortPosition(DmOpenRef dbP, PrvAddrPackedDBRecord *newRecord);

AddrAppInfoPtr   AddrDBAppInfoGetPtr(DmOpenRef dbP)
{
	UInt16     cardNo;
	LocalID    dbID;
	LocalID    appInfoID;

	if (DmOpenDatabaseInfo(dbP, &dbID, NULL, NULL, &cardNo, NULL))
		return NULL;
	if (DmDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &appInfoID, NULL, NULL, NULL))
		return NULL;

	if (appInfoID == 0)
		return NULL;
	else
		return ((AddrAppInfoType*) MemLocalIDToLockedPtr(appInfoID, cardNo));

}

Err AddrDBNewRecord(DmOpenRef dbP, AddrDBRecordPtr r, UInt16 *index)
{
	MemHandle               recordH;
	Err                   	err;
	PrvAddrPackedDBRecord*  recordP;
	UInt16                  newIndex;

	// 1) and 2) (make a new chunk with the correct size)
	recordH = DmNewHandle(dbP, (Int32) PrvAddrDBUnpackedSize(r));
	if (recordH == NULL)
		return dmErrMemError;

	// 3) Copy the data from the unpacked record to the packed one.
	recordP = (PrvAddrPackedDBRecord*) MemHandleLock(recordH);
	PrvAddrDBPack(r, recordP);

	// Get the index
	newIndex = PrvAddrDBFindSortPosition(dbP, recordP);
	MemPtrUnlock(recordP);

	// 4) attach in place
	err = DmAttachRecord(dbP, &newIndex, recordH, 0);
	if (err)
		MemHandleFree(recordH);
	else
		*index = newIndex;

	return err;
}

Err AddrDBChangeRecord(DmOpenRef dbP, UInt16 *index, AddrDBRecordPtr r, AddrDBRecordFlags changedFields, UInt16 blobDirty)
{
	AddrDBRecordType   		src;
	MemHandle          		srcH;
	Err            			result;
	MemHandle          		recordH=0;
	MemHandle          		oldH;
	Int16              		i;
	AddrDBRecordFlags		changes;
	Int16              		sortByCompany;
	AddrAppInfoPtr   		appInfoPtr;
	Boolean          		dontMove;
	UInt16             		attributes;      // to contain the deleted flag

	PrvAddrPackedDBRecord* 	cmpP;
	PrvAddrPackedDBRecord* 	recordP;
	UInt16				    Counter = 0;
	
	MemHandle packedH;
	
	MemMove(&changes, &changedFields, sizeof(changedFields));

	// We do not assume that r is completely valid so we get a valid
	// AddrDBRecordPtr...
	if ((result = AddrDBGetRecord(dbP, *index, &src, &srcH)) != 0)
		return result;
	
	// Get handle to packed record, we need to figure out if there is blob data
	packedH = DmQueryRecord(dbP, *index);
	
	// And we apply the changes to it.
	MemMove(&(src.options), (&r->options), sizeof(AddrOptionsType));
	
	for (i = firstAddressField; i < addrNumStringFields; i++)
	{
		// If the flag is set, point to the string else NULL
		if (GetBitMacro(changes, i) != 0)
		{
			src.fields[i] = r->fields[i];
			RemoveBitMacro(changes, i);
		}
		
		if ((changes.allBits == 0) && (changes.allBits2 == 0))
			break;  // no more changes
	}
	
	// Fill in birthday info only if the birth date is present.
	if(GetBitMacro(changes, birthdayDate))
	{
		src.birthdayInfo.birthdayDate = r->birthdayInfo.birthdayDate;
		RemoveBitMacro(changes, birthdayDate);
	}
	
	if(GetBitMacro(changes, birthdayMask))
	{
		src.birthdayInfo.birthdayMask = r->birthdayInfo.birthdayMask;
		RemoveBitMacro(changes, birthdayMask);
	}
	
	if(GetBitMacro(changes, birthdayPreset))
	{
		src.birthdayInfo.birthdayPreset = r->birthdayInfo.birthdayPreset;
		RemoveBitMacro(changes, birthdayPreset);
	}
	
	if(r->pictureInfo.pictureDirty)
	{
		src.pictureInfo.pictureDirty = 1;
		src.pictureInfo.pictureSize = r->pictureInfo.pictureSize;
		src.pictureInfo.pictureData = r->pictureInfo.pictureData;		
	}

	if(blobDirty)
	{
		for(Counter = 0;Counter< r->numBlobs  ;Counter++)
		{
			src.blobs[Counter] = r->blobs[Counter]; 
		} 
		src.numBlobs = r->numBlobs;
	}

	// 1) and 2) (make a new chunk with the correct size)
	recordH = DmNewHandle(dbP, PrvAddrDBUnpackedSize(&src));
	if (recordH == NULL)
	{
		MemHandleUnlock(srcH);  // undo lock from AddrGetRecord above
		return dmErrMemError;
	}
	recordP = (PrvAddrPackedDBRecord*) MemHandleLock(recordH);

	// 3) Copy the data from the unpacked record to the packed one.
	PrvAddrDBPack(&src, recordP);

	// The original record is copied and no longer needed.
	MemHandleUnlock(srcH);

	// 4) If the sort position changes...
	// Check if any of the key fields have changed
	if ((changedFields.allBits & sortKeyFieldBits) == 0)
		goto attachRecord;

	// Make sure *index-1 < *index < *index+1, if so it's in sorted
	// order.  Leave it there.
	appInfoPtr = (AddrAppInfoPtr) AddrDBAppInfoGetPtr(dbP);
	sortByCompany = appInfoPtr->misc.sortByCompany;
	MemPtrUnlock(appInfoPtr);

	if (*index > 0)
	{
		// This record wasn't deleted and deleted records are at the end of the
		// database so the prior record may not be deleted!
		cmpP = (PrvAddrPackedDBRecord*) MemHandleLock(DmQueryRecord(dbP, *index-1));
		dontMove = (PrvAddrDBComparePackedRecords (cmpP,  recordP, sortByCompany,
							NULL, NULL, 0) == -1);
		MemPtrUnlock(cmpP);
	}
	else
		dontMove = true;


	if (*index+1 < DmNumRecords (dbP))
	{
		DmRecordInfo(dbP, *index+1, &attributes, NULL, NULL);
		if (attributes & dmRecAttrDelete)
			;      // don't move it after the deleted record!
		else {
			cmpP = (PrvAddrPackedDBRecord*) MemHandleLock(DmQueryRecord(dbP, *index+1));
			dontMove = dontMove && (PrvAddrDBComparePackedRecords (recordP, cmpP, sortByCompany,
									NULL, NULL, 0) == -1);
			MemPtrUnlock(cmpP);
		}
	}

	if (dontMove)
		goto attachRecord;

	// The record isn't in the right position.  Move it.
	i = PrvAddrDBFindSortPosition(dbP, recordP);
	DmMoveRecord(dbP, *index, i);
	if (i > *index) i--;
	*index = i; // return new position

	// Attach the new record to the old index, the preserves the
	// category and record id.
attachRecord:

	result = DmAttachRecord(dbP, index, recordH, &oldH);
	MemPtrUnlock(recordP);
	if (result) return result;

	MemHandleFree(oldH);
	return 0;
}

Err AddrDBGetRecord(DmOpenRef dbP, UInt16 index, AddrDBRecordPtr recordP,
				  MemHandle *recordH)
{
	PrvAddrPackedDBRecord *src;

	*recordH = DmQueryRecord(dbP, index);
	
	if (*recordH == NULL)
		return dmErrIndexOutOfRange;
		
	src = (PrvAddrPackedDBRecord *) MemHandleLock(*recordH);
	if (src == NULL)
		return dmErrIndexOutOfRange;

	PrvAddrDBUnpack(src, recordP);

	return 0;
}

Int16 PrvAddrDBUnpackedSize(AddrDBRecordPtr r)
{
	Int16 size;
	Int16   index;

	size = sizeof (PrvAddrPackedDBRecord) - sizeof (char);   // correct
	for (index = firstAddressField; index < addrNumStringFields; index++)
	{
		 if (r->fields[index] != NULL)
			size += StrLen(r->fields[index]) + 1;
	}
	
	//calculate length for birthday info
	if(r->birthdayInfo.birthdayDate.month && r->birthdayInfo.birthdayDate.day)
	{
		size += sizeof(DateType);
		size += sizeof(AddressDBBirthdayFlags);
		if(r->birthdayInfo.birthdayMask.alarm)
		{
			size += sizeof(UInt8); //preset			
		}
	}
	if(r->pictureInfo.pictureSize && r->pictureInfo.pictureData)
	{
		size += sizeof(UInt32); //blob id
		size+=sizeof(r->pictureInfo.pictureSize); //blob size, same as sizeof(picture size)
		size+= sizeof(r->pictureInfo.pictureDirty);  		
		size+= r->pictureInfo.pictureSize;
	}

	for (index = 0; index < r->numBlobs; index++)
 	{
 		size += sizeof(r->blobs[index].creatorID);
 		size += sizeof(r->blobs[index].size);
 		size += r->blobs[index].size;
 	}
	return size;
}

void PrvAddrDBPack(AddrDBRecordPtr s, void * recordP)
{
	Int32                offset;
	AddrDBRecordFlags    flags;
	Int16                index;
	PrvAddrPackedDBRecord*  d=0;
	UInt16                len;
	void *               srcP;
	UInt8                companyFieldOffset;
	UInt16				blobCount = 0;
 	UInt16				size = 0;

	flags.allBits = 0;
	flags.allBits2 = 0;

	DmWrite(recordP, (Int32)&d->options, &s->options, sizeof(s->options));
	offset = (Int32)&d->firstField;

	for (index = firstAddressField; index < addrNumStringFields; index++) {
		if (s->fields[index] != NULL)
			/*         if (s->fields[index][0] == '\0')
			 {
			 // so set the companyFieldOffset or clear it code doesn't fail
			 s->fields[index] = NULL;
			 }
			 else
			 */
		{
			//ErrFatalDisplayIf(s->fields[index][0] == '\0' && index != P1ctnote,
			//				  "Empty field being added");
			
			// Skip fields with empty strings
			if ((s->fields[index][0] != '\0') || (index == note))
			{
				srcP = s->fields[index];
				len = StrLen((Char*)srcP) + 1;
				DmWrite(recordP, offset, srcP, len);
				offset += len;
				SetBitMacro(flags, index);
			}

⌨️ 快捷键说明

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