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

📄 addressdb.c

📁 我的Palm OS 5 SDK zhCN_PIMApps代码。 使用codewarrior 开发环境
💻 C
📖 第 1 页 / 共 4 页
字号:
					matches1 = 0;
				else
					matches1 = PrvAddrDBStrCmpMatches(key, recordKey);

				MemHandleUnlock(rH);

				if (matches1 == matches2)
					*recordP = probe2;
				else
					break;
			}

			*completeMatch = (matches2 == StrLen(key));
		}

	return true;
}


/************************************************************
 *
 *  FUNCTION:    AddrDBLookupLookupString
 *
 *  DESCRIPTION: Return which record contains the most of
 *      the string passed.  If no string is passed or there
 *  aren't any records then false is returned.
 *
 *  PARAMETERS: address record
 *                key - string to lookup record with
 *                sortByCompany - how the db is sorted
 *                vars -  Lookup variables
 *                recordP - to contain the record found
 *                phoneP - to contain the phone found
 *                completeMatch -  true if a record contains all
 *                                 of the key
 *
 *  RETURNS: the record in recordP or false
 *             completeMatch -  true if a record contains all
 *                              of the key
 *
 * RETURNED:    false is return if a displayable record was not found.
 *
 * REVISION HISTORY:
 *         Name   Date      Description
 *         ----   ----      -----------
 *         Roger   7/19/96   Initial Revision
 *
 *************************************************************/
Boolean AddrDBLookupLookupString(DmOpenRef dbP, Char * key, Boolean sortByCompany, AddressLookupFields field1, AddressLookupFields field2, UInt16 * recordP, Int16 * phoneP, AddressFields lookupFieldMap[], Boolean *completeMatch, Boolean *uniqueMatch)
{
	Int16                   numOfRecords;
	MemHandle                rH;
	PrvAddrPackedDBRecord*   r;
	//   UInt16                  kmin, i;                     // all positions in the database.
	UInt16                  probe, probe2         ;      // all positions in the database.
	Int16                  phoneProbe, phoneProbe2;
	//   Int16                   result;                     // result of comparing two records
	UInt16                   whichKey;
	char*                  recordKey;
	UInt16                   matches1, matches2;
	AddressFields         searchField;
	AddrDBRecordFlags      searchFieldFlag;


	*uniqueMatch = false;
	*completeMatch = false;

	// If there isn't a key to search with stop the with the first record.
	if (key == NULL || *key == '\0')
	{
		*completeMatch = true;
		return false;
	}

	numOfRecords = DmNumRecords(dbP);
	if (numOfRecords == 0)
		return false;

	// Performing a lookup on the sort field allows the use a binary search which
	// takes advantage of the ordered field.
	if (field1 == addrLookupSortField)
	{
		// Perform the standard lookup on the sort fields looking at all categories.
		if (!AddrDBLookupString(dbP, key, sortByCompany, dmAllCategories,
							  recordP, completeMatch, false))
			return false;   // nothing matched


		// At this point probe is the position where the string could be
		// inserted.  It is in between two entries.  Neither the record
		// before or after may have ANY letters in common, especially after
		// those records in other catergories are skipped.  Go with the
		// record that has the most letters in common.


		// Make sure the record returned is of the same category.
		// If not return the first prior record of the same category.
		probe2 = probe = *recordP;
		phoneProbe2 = phoneProbe = 0;
		if (AddrDBLookupSeekRecord (dbP, &probe, &phoneProbe, 0, dmSeekForward,
								  field1, field2, lookupFieldMap))
		{
			// Now count the number of matching characters in probe
			rH = DmQueryRecord(dbP, probe);      // No deleted record possible
			r = (PrvAddrPackedDBRecord *) MemHandleLock(rH);
			ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
			whichKey = 1;
			PrvAddrDBFindKey(r, &recordKey, &whichKey, sortByCompany);
			if (recordKey == NULL)
				matches1 = 0;
			else
				matches1 = PrvAddrDBStrCmpMatches(key, recordKey);

			MemHandleUnlock(rH);
		}
		else
		{
			// No record in this category was found or probe is past all
			// records in this category.  Either way there aren't any matching
			// letters.
			matches1 = 0;
		}


		*uniqueMatch = true;


		// Sometimes the record before has more matching letters. Check it.
		// Passing DmSeekRecordInCategory an offset of 1 doesn't work
		// when probe is at the end of the database and there isn't at least
		// one record to skip.
		probe2 = probe - 1;
		if (probe == 0 ||
			!AddrDBLookupSeekRecord (dbP, &probe2, &phoneProbe2, 0, dmSeekBackward,
								   field1, field2, lookupFieldMap))
		{
			// There isn't an earlier record.  Try to find a following record.
			probe2 = probe + 1;
			phoneProbe2 = phoneProbe;
			if (!AddrDBLookupSeekRecord (dbP, &probe2, &phoneProbe2, 0, dmSeekForward,
									   field1, field2, lookupFieldMap))
			{
				// There isn't a following record.  Try to use the probe.
				if (matches1 > 0)
				{
					// Go with probe because they have at least some letters in common.
					*recordP = probe;   //
					*phoneP = phoneProbe;
					*completeMatch = (matches1 == StrLen(key));
					return true;
				}
				else
				{
					// probe has no letters in common and nothing earlier in this category
					// was found so this is a failed lookup.
					*completeMatch = false;
					return false;
				}
			}
		}


		// Now count the number of matching characters in probe2
		rH = DmQueryRecord(dbP, probe2);      // No deleted record possible
		r = (PrvAddrPackedDBRecord *) MemHandleLock(rH);
		ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
		whichKey = 1;
		PrvAddrDBFindKey(r, &recordKey, &whichKey, sortByCompany);
		if (recordKey == NULL)
			matches2 = 0;
		else
			matches2 = PrvAddrDBStrCmpMatches(key, recordKey);
		MemHandleUnlock(rH);


		// Now, return the probe which has the most letters in common.
		if (matches1 > matches2)
		{
			*completeMatch = (matches1 == StrLen(key));
			*recordP = probe;
			*phoneP = phoneProbe;

			// If the next item has the same number of
			// matching letters then the match is not unique.
			probe2 = probe;
			phoneProbe2 = phoneProbe;
			if (AddrDBLookupSeekRecord (dbP, &probe2, &phoneProbe2, 1, dmSeekForward,
									  field1, field2, lookupFieldMap))
			{
				rH = DmQueryRecord(dbP, probe2);
				r = (PrvAddrPackedDBRecord *) MemHandleLock(rH);
				ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");

				// Compare the string to the first sort key only
				whichKey = 1;
				PrvAddrDBFindKey(r, &recordKey, &whichKey, sortByCompany);

				if (recordKey == NULL)
					matches2 = 0;
				else
					matches2 = PrvAddrDBStrCmpMatches(key, recordKey);

				MemHandleUnlock(rH);

				if (matches1 <= matches2)
				{
					*uniqueMatch = false;
				}
			}
		}
		else
			if (matches1 == 0 && matches2 == 0)
			{
				*completeMatch = false;
				*uniqueMatch = false;
				return false;            // no item with same first letter found
			}
			else
			{
				// The first item matches as much or more as the second item
				*recordP = probe2;
				*phoneP = phoneProbe2;

				// If the prior item in the category has the same number of
				// matching letters use it instead.  Repeat to find the
				// earliest such match.
				while (AddrDBLookupSeekRecord (dbP, &probe2, &phoneProbe2, 1, dmSeekBackward,
											 field1, field2, lookupFieldMap))
				{
					rH = DmQueryRecord(dbP, probe2);
					r = (PrvAddrPackedDBRecord *) MemHandleLock(rH);
					ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");

					// Compare the string to the first sort key only
					whichKey = 1;
					PrvAddrDBFindKey(r, &recordKey, &whichKey, sortByCompany);

					if (recordKey == NULL)
						matches1 = 0;
					else
						matches1 = PrvAddrDBStrCmpMatches(key, recordKey);

					MemHandleUnlock(rH);

					if (matches1 == matches2)
					{
						*recordP = probe2;
						*phoneP = phoneProbe2;
					}
					else
						break;
				}

				*completeMatch = (matches2 == StrLen(key));
				*uniqueMatch = false;
			}

		return true;

	}
	else
	{
		// Peform a lookup based on unordered data.  This gets real slow with lots of data
		// Because to check for uniqueness we must search every record.  This means on average
		// this lookup is twice as slow as it would be it it could stop with the first match.
		AddrDBRecordType record;


		*completeMatch = false;

		matches1 = 0;         // treat this as the most matches

		// cache these values
		searchField = lookupFieldMap[field1];
		searchFieldFlag.allBits = BitAtPosition(field1);

		// Start with the first record and look at each record until there are no more.
		// Look for the record with the most number of matching records.  Even if we found
		// a record containing all the record we are searching for we must still look
		// for one more complete match to confirm or deny uniqueness of the match.
		probe2 = 0;
		phoneProbe2 = 0;
		while (AddrDBLookupSeekRecord (dbP, &probe2, &phoneProbe2, 1, dmSeekForward,
									 field1, field2, lookupFieldMap))
		{
			rH = DmQueryRecord(dbP, probe2);
			r = (PrvAddrPackedDBRecord *) MemHandleLock(rH);
			ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");

			// Compare the string to the search field
			if (r->flags.allBits & searchFieldFlag.allBits)
			{
				PrvAddrDBUnpack(r, &record);
				recordKey = record.fields[searchField];

				if (recordKey == NULL)
					matches2 = 0;
				else
					matches2 = PrvAddrDBStrCmpMatches(key, recordKey);
			}
			else
			{
				matches2 = 0;
			}

			MemHandleUnlock(rH);

			if (matches2 > matches1)
			{
				matches1 = matches2;      // the most matches so far

				*recordP = probe2;      // return the best record
				*phoneP = phoneProbe2;

				*completeMatch = (matches2 == StrLen(key));
			}
			// Did we find another record which is a complete match?
			else if (matches2 > 0 &&
					 matches1 == matches2 &&
					 *completeMatch)
			{
				*uniqueMatch = false;
				return true;
			}
			else
			{
				// The record is a matching failure.  Since AddrLookupSeekRecord is going
				// to return this record again for every phone field we cheat by specifying
				// the last phone field to skip all other entries.
				//            phoneProbe2 = numPhoneFields - 1;
			}
		}


		// Was at least one record found with at least one matching character?
		if (matches1 > 0)
		{
			// At this point every record was searched and no other match was found.
			*uniqueMatch = true;

			return true;
		}
	}

	return false;
}


/***********************************************************************
 *
 * FUNCTION:     AddrDBGetDatabase
 *
 * DESCRIPTION:  Get the application's database.  Open the database if it
 * exists, create it if neccessary.
 *
 * PARAMETERS:   *dbPP - pointer to a database ref (DmOpenRef) to be set
 *					  mode - how to open the database (dmModeReadWrite)
 *
 * RETURNED:     Err - zero if no error, else the error
 *
 * REVISION HISTORY:
 *			Name		Date		Description
 *			----		----		-----------
 *			jmp		10/01/99	Initial Revision
 *
 ***********************************************************************/
Err AddrDBGetDatabase (DmOpenRef *dbPP, UInt16 mode)
{
	Err error = 0;
	DmOpenRef dbP;
	UInt16 cardNo;
	LocalID dbID;

	*dbPP = NULL;

	// Find the application's data file.  If it doesn't exist create it.
	dbP = DmOpenDatabaseByTypeCreator (addrDBType, sysFileCAddress, mode);
	if (!dbP)
	{
		error = DmCreateDatabase (0, addrDBName, sysFileCAddress, addrDBType, false);
		if (error)
			return error;

		dbP = DmOpenDatabaseByTypeCreator(addrDBType, sysFileCAddress, mode);
		if (!dbP)
			return (1);

		// Set the backup bit.  This is to aid syncs with non Palm software.
		ToolsSetDBAttrBits(dbP, dmHdrAttrBackup);

		error = AddrDBAppInfoInit (dbP);
		if (error)
		{
			DmOpenDatabaseInfo(dbP, &dbID, NULL, NULL, &cardNo, NULL);
			DmCloseDatabase(dbP);
			DmDeleteDatabase(cardNo, dbID);
			return error;
		}
	}

	*dbPP = dbP;
	return 0;
}

#pragma mark -

/************************************************************
 *
 *  FUNCTION: PrvAddrDBLocalizeAppInfo
 *
 *  DESCRIPTION: Look for localize app info strings and copy
 *  them into the app info block.
 *
 *  PARAMETERS: application info ptr
 *
 *  RETURNS: nothing
 *
 *  CREATED: 12/13/95
 *
 *  BY: Roger Flores
 *
 *  MODIFICATIONS:
 *      10/22/96   roger      Set flags when field modified
 *************************************************************/
void PrvAddrDBLocalizeAppInfo(AddrAppInfoPtr appInfoP)
{
	MemHandle       localizedAppInfoH;
	Char *          localizedAppInfoP;
	AddrAppInfoPtr   nilP = 0;
	MemHandle       stringsH;
	Char *         *stringsP;
	int             i;
	UInt16            localRenamedCategories;
	UInt32            localDirtyFieldLabels;


	localizedAppInfoH = DmGetResource(appInfoStringsRsc, LocalizedAppInfoStr);
	if (!localizedAppInfoH)
		return;
	localizedAppInfoP = MemHandleLock(localizedAppInfoH);
	stringsH = SysFormPointerArrayToStrings(localizedAppInfoP,
											dmRecNumCategories + addrNumFields + numPhoneLabelsStoredSecond);
	stringsP = MemHandleLock(stringsH);


	// Copy each category
	localRenamedCategories = appInfoP->renamedCategories;
	for (i = 0; i < dmRecNumCategories; i++)
	{
		if (stringsP[i][0] != '\0')
		{
			DmStrCopy(appInfoP, (Int32) nilP->categoryLabels[i], stringsP[i]);
			SetBitMacro(localRenamedCategories, i);
		}
	}
	DmWrite(appInfoP, (Int32) &nilP->renamedCategories, &localRenamedCategories,
			sizeof(localRenamedCategories));


	// Copy each field label
	localDirtyFieldLabels = appInfoP->dirtyFieldLabels.allBits;
	for (i = 0; i < (addrNumFields + numPhoneLabelsStoredSecond); i++)
	{
		if (stringsP[i + dmRecNumCategories][0] != '\0')
		{
			DmStrCopy(appInfoP, (Int32) nilP->fieldLabels[i],
					  stringsP[i + dmRecNumCategories]);
			SetBitMacro(localDirtyFieldLabels, i);
		}
	}
	DmWrite(appInfoP, (Int32) &nilP->dirtyFieldLabels.allBits, &localDirtyFieldLabels,
			sizeof(localDirtyFieldLabels));


	MemPtrFree(stringsP);
	MemPtrUnlock(localizedAppInfoP);
	DmReleaseResource(localizedAppInfoH);
}


/************************************************************
 *
 *  FUNCTION: PrvAddrDBFindKey
 *
 *  DESCRIPTION: Return the next valid key
 *
 *  PARAMETERS: database packed record
 *            <-> key to use (ptr to string or NULL for uniq ID)
 *            <-> which key (incremented for use again, starts at 1)
 *            -> sortByCompany
 *
 *  RETURNS:
 *
 *  CREATED: 1/16/95
 *
 *  BY: Roger Flores
 *
 *   COMMENTS:   Returns the key which is asked for if possible and
 *   advances whichKey.  If the key is not available the key advances
 *   to the next one.  The order of keys is:
 *

⌨️ 快捷键说明

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