📄 addressdb.c
字号:
/******************************************************************************
*
* 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 + -