📄 addressautofill.c
字号:
/******************************************************************************
*
* Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
*
* File: AddressAutoFill.c
*
* Release: Palm OS 5 SDK (68K) R3.
*
* Description:
* This module contains routines that support the auto-fill feature
* of the address application. (Started from ExpLookup.c from Expense)
*
*****************************************************************************/
#include "AddrTools.h"
#include "AddrDefines.h"
#include "AddressAutoFill.h"
#include <ErrorMgr.h>
#include <StringMgr.h>
#include <TimeMgr.h>
#include <UIResources.h>
#include <PalmUtils.h>
/***********************************************************************
*
* Defines
*
***********************************************************************/
#define maxLookupEntries 100 // max number of entries per lookup database
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
static Boolean PrvAutoFillLookupStringInList (ListPtr lst, Char *key, UInt16 *indexP, Boolean *uniqueP);
static Int16 PrvAutoFillPartialCaselessCompare (Char * s1, Char * s2);
static Int16 PrvAutoFillLookupCompareRecords (Char * str, LookupRecordPtr r2, Int16 /* dummy */, SortRecordInfoPtr /* info1 */, SortRecordInfoPtr /* info2 */, MemHandle /* appInfoH */);
static Int16 PrvAutoFillSortCompareRecords (LookupRecordPtr r1, LookupRecordPtr r2, Int16 /* dummy */, SortRecordInfoPtr /* info1 */, SortRecordInfoPtr /* info2 */, MemHandle /* appInfoH */);
/***********************************************************************
*
* FUNCTION: AutoFillInitDB
*
* DESCRIPTION: This routine initializes a lookup database from a
* resource. Each string in the resource becomes a record
* in the database. The strings in the resouce are delimited
* by the '|' character.
*
* PARAMETERS: type - database type
* creator - database creator type
* name - name given to the database
* initRscID - reosource used to initialize the database
*
* RETURNED: error code, 0 if successful
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 1/12/96 Initial Revision
* grant 4/7/99 Set backup bit on new databases.
* bhall 11/1/99 now handles case where init string not present
* also sorts the db in case initial values out of order
* bhall 11/8/99 Fixed prob where records not properly sorted
* Fixed prob where last record of init string skipped
***********************************************************************/
Err AutoFillInitDB (UInt32 type, UInt32 creator, const Char * name,
UInt16 initRscID)
{
Char zero=0;
UInt16 error = 0;
UInt16 index;
UInt32 strLen;
UInt32 time;
Char * endP;
Char * resP;
MemHandle resH;
MemHandle rH;
DmOpenRef dbP = 0;
LookupRecordPtr rP;
LookupRecordPtr nilP = 0;
Boolean done;
dbP = DmOpenDatabaseByTypeCreator (type, creator, dmModeReadWrite);
if (dbP) goto exit;
// If the description datebase does not exist, create it.
error = DmCreateDatabase (0, name, creator, type, false);
if (error) return (error);
// Then open it
dbP = DmOpenDatabaseByTypeCreator (type, creator, dmModeReadWrite);
if (! dbP) return DmGetLastErr();
// Set the backup bit. This is to aid syncs with non-Palm software.
// Also set hidden bit so launcher info doesn't give confusing record counts.
ToolsSetDBAttrBits(dbP, dmHdrAttrBackup | dmHdrAttrHidden);
// We will need the time for default records we may create
time = TimGetSeconds();
// Attempt to initialize the description datebase from a resource that contains strings
// delimited by "|" characters.
resH = DmGetResource(strRsc, initRscID);
if (resH) {
// Lock down the init string
resP = MemHandleLock(resH);
// Parse it and add records as we go
index = 0;
done = false;
while (!done) {
// Find the next one to add
endP = StrChr(resP, '|');
if (endP) {
strLen = (UInt16) (endP - resP);
} else {
strLen = StrLen(resP);
done = true;
}
// If we don't find one, stop
if (strLen == 0) break;
// Create a new record
rH = DmNewRecord(dbP, &index, sizeof (LookupRecordType) + strLen);
rP = MemHandleLock(rH);
// Write out the data
DmWrite (rP, OffsetOf(LookupRecordType, time), &time, sizeof (UInt32));
DmWrite (rP, OffsetOf(LookupRecordType, text), resP, strLen);
DmWrite (rP, OffsetOf(LookupRecordType, text) + strLen, &zero, 1); // null-terminate
MemPtrUnlock(rP);
// Release it, dirty
DmReleaseRecord(dbP, index, true);
// Move to the next
resP += strLen + 1;
index++;
}
// Done with the init string - release it
MemHandleUnlock(resH);
DmReleaseResource(resH);
// Now sort the database - required for proper operation
error = DmQuickSort(dbP, (DmComparF *)PrvAutoFillSortCompareRecords, 0);
}
exit:
// If we had the database open, close it
if (dbP) DmCloseDatabase(dbP);
return (0);
}
/***********************************************************************
*
* FUNCTION: AutoFillLookupStringInDatabase
*
* DESCRIPTION: This routine seatches a database for a the string passed.
*
* PARAMETERS: dpb - description database
* key - string to lookup record with
* indexP - to contain the record found
*
* RETURNED: true if a unique match was found.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 1/4/96 Initial Revision
*
***********************************************************************/
Boolean AutoFillLookupStringInDatabase (DmOpenRef dbP, Char * key, UInt16 * indexP)
{
Int16 result;
Int16 numOfRecords;
UInt16 kmin, probe, i;
MemHandle rH;
Boolean match = false;
LookupRecordPtr rP;
Boolean unique;
unique = false;
if ((! key) || (! *key) ) return false;
numOfRecords = DmNumRecords(dbP);
if (numOfRecords == 0) return false;
result = 0;
kmin = probe = 0;
while (numOfRecords > 0)
{
i = numOfRecords / 2;
probe = kmin + i;
// Compare the two records. Treat deleted records as greater.
// If the records are equal look at the following position.
rH = DmQueryRecord (dbP, probe);
if (rH == 0)
{
result = -1; // Delete record is greater
}
else
{
rP = MemHandleLock(rH);
result = PrvAutoFillPartialCaselessCompare (key, &rP->text);
MemHandleUnlock(rH);
}
// If the date passed is less than the probe's date , keep searching.
if (result < 0)
numOfRecords = i;
// If the date passed is greater than the probe's date, keep searching.
else if (result > 0)
{
kmin = probe + 1;
numOfRecords = numOfRecords - i - 1;
}
// If equal stop here! Make sure the match is unique by checking
// the records before and after the probe, if either matches then
// we don't have a unique match.
else
{
// Start by assuming we have a unique match.
match = true;
unique = true;
*indexP = probe;
// If we not have a unique match, we want to return the
// index one the first item that matches the key.
while (probe)
{
rH = DmQueryRecord (dbP, probe-1);
rP = MemHandleLock(rH);
result = PrvAutoFillPartialCaselessCompare (key, &rP->text);
MemHandleUnlock(rH);
if (result != 0) break;
unique = false;
*indexP = probe-1;
probe--;
}
if (! unique) break;
if (probe + 1 < DmNumRecords(dbP))
{
rH = DmQueryRecord (dbP, probe+1);
if (rH)
{
rP = MemHandleLock(rH);
result = PrvAutoFillPartialCaselessCompare (key, &rP->text);
MemHandleUnlock(rH);
if (result == 0)
unique = false;
}
}
break;
}
}
return (match);
}
/***********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -