home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / progect-src-0.20.tar.gz / progect-src-0.20.tar / progect-0.20 / AddressDB.c < prev    next >
C/C++ Source or Header  |  2000-10-26  |  62KB  |  1,934 lines

  1. /******************************************************************************
  2.  *
  3.  * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
  4.  * All rights reserved.
  5.  *
  6.  * File: AddressDB.c
  7.  *
  8.  * Description:
  9.  *      Address Manager routines
  10.  *
  11.  * History:
  12.  *            1/9/95    rsf - Created
  13.  *            7/22/96    rsf - Added the Address Lookup routines.  These calls
  14.  *                         perform the data searching needed by the app to
  15.  *                         support the lookup launch notification.
  16.  *            10/01/99    jmp - Added AddrGetDataBase() routine.
  17.  *
  18.  *****************************************************************************/
  19.  
  20. // Set this to get to private database defines
  21. #define __ADDRMGR_PRIVATE__
  22.  
  23. #include <PalmOS.h>
  24. #include "Address.h"
  25. #include "AddressDB.h"
  26. #include "progect.h"
  27. #include "progectRsc.h"
  28. //#include "AddressRsc.h"
  29.  
  30. // Max length of a field name found in the FieldNamesStrList string list.
  31. #define maxFieldName    31
  32.  
  33. // Indexes into FieldNamesStrList string list.
  34. enum {
  35.     fieldNameStrListCity = 0,
  36.     fieldNameStrListState,
  37.     fieldNameStrListZip
  38. };
  39.  
  40. // Extract the bit at position index from bitfield.  0 is the high bit.
  41. #define BitAtPosition(pos)                  ((UInt32)1 << (pos))
  42. #define GetBitMacro(bitfield, index)      ((bitfield) & BitAtPosition(index))
  43. #define SetBitMacro(bitfield, index)      ((bitfield) |= BitAtPosition(index))
  44. #define RemoveBitMacro(bitfield, index)   ((bitfield) &= ~BitAtPosition(index))
  45.  
  46.  
  47.  
  48. #define sortKeyFieldBits   (BitAtPosition(name) | BitAtPosition(firstName) | BitAtPosition(company))
  49. //0x70000         // Update this if the sort fields 
  50.                                  // change positions
  51.  
  52. // The following structure doesn't really exist.  The first field
  53. // varies depending on the data present.  However, it is convient
  54. // (and less error prone) to use when accessing the other information.
  55. typedef struct {
  56.       AddrOptionsType      options;        // Display by company or by name
  57.       AddrDBRecordFlags    flags;
  58.       UInt8                    companyFieldOffset;   // Offset from firstField
  59.       char                 firstField;
  60. } AddrPackedDBRecord;
  61.  
  62.  
  63. /************************************************************
  64.  * Private routines used only in this module
  65.  *************************************************************/
  66.  
  67. Boolean PrvSeekVisibleRecordInCategory (DmOpenRef dbR, UInt16 * indexP, UInt16 offset,
  68.     Int16 direction, UInt16 category, Boolean masked);
  69.  
  70.  
  71. /************************************************************
  72.  *
  73.  *  FUNCTION: AddrAppInfoGetPtr
  74.  *
  75.  *  DESCRIPTION: Return a locked pointer to the AddrAppInfo or NULL
  76.  *
  77.  *  PARAMETERS: dbP - open database pointer
  78.  *
  79.  *  RETURNS: locked ptr to the AddrAppInfo or NULL
  80.  *
  81.  *  CREATED: 6/13/95 
  82.  *
  83.  *  BY: Roger Flores
  84.  *
  85.  *************************************************************/
  86. //AddrAppInfoPtr   AddrAppInfoGetPtr(DmOpenRef dbP)
  87. //{
  88. //   UInt16     cardNo;
  89. //   LocalID    dbID;
  90. //   LocalID    appInfoID;
  91. //   
  92. //   if (DmOpenDatabaseInfo(dbP, &dbID, NULL, NULL, &cardNo, NULL))
  93. //      return NULL;
  94. //   if (DmDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &appInfoID, NULL, NULL, NULL))
  95. //      return NULL;
  96. //
  97. //   if (appInfoID == NULL)
  98. //      return NULL;
  99. //   else
  100. //      return MemLocalIDToLockedPtr(appInfoID, cardNo);
  101. //   
  102. //}   
  103.  
  104.  
  105. /************************************************************
  106.  *
  107.  *  FUNCTION: AddrChangeCountry
  108.  *
  109.  *  DESCRIPTION: Set the field labels to those appropriate
  110.  *  to the current country (based on system preferences).
  111.  *
  112.  *  PARAMETERS: application info ptr
  113.  *
  114.  *  RETURNS: nothing
  115.  *
  116.  * HISTORY:
  117.  *        07/24/95    rsf    Created by Roger Flores
  118.  *        07/29/99    kwk    Load field names from string list resource.
  119.  *
  120.  *************************************************************/
  121. //void AddrChangeCountry(AddrAppInfoPtr appInfoP)
  122. //{
  123. //   CountryType countryCurrent;
  124. //   AddrAppInfoPtr   nilP = NULL;
  125. //    MemHandle textH;
  126. //    UInt16 strListID;
  127. //    Char fieldName[maxFieldName + sizeOf7BitChar(chrNull)];
  128. //
  129. //   // Localize the field labels to the current country
  130. //   countryCurrent = (CountryType) PrefGetPreference(prefCountry);
  131. //   strListID = (UInt16)countryCurrent + FieldNamesStrList;
  132. //   
  133. //   textH = DmGetResource(strListRscType, strListID);
  134. //   if (textH != NULL)
  135. //       {
  136. //        AddrDBRecordFlags dirtyFieldLabels;
  137. //
  138. //      DmStrCopy(appInfoP, (Int32) nilP->fieldLabels[city],
  139. //          SysStringByIndex(strListID, fieldNameStrListCity, fieldName, maxFieldName));
  140. //      DmStrCopy(appInfoP, (Int32) nilP->fieldLabels[state],
  141. //          SysStringByIndex(strListID, fieldNameStrListState, fieldName, maxFieldName));
  142. //      DmStrCopy(appInfoP, (Int32) nilP->fieldLabels[zipCode],
  143. //          SysStringByIndex(strListID, fieldNameStrListZip, fieldName, maxFieldName));
  144. //      
  145. //      dirtyFieldLabels.allBits = (appInfoP->dirtyFieldLabels.allBits) | 
  146. //         BitAtPosition(city) | BitAtPosition(state) | BitAtPosition(zipCode);
  147. //      
  148. //      DmWrite(appInfoP, (Int32) &nilP->dirtyFieldLabels, &dirtyFieldLabels, sizeof dirtyFieldLabels);
  149. //       }
  150. //   
  151. //   // Record the country.
  152. //   DmWrite(appInfoP, (Int32) &nilP->country, &countryCurrent, sizeof(countryCurrent));
  153. //}
  154.  
  155.  
  156. /************************************************************
  157.  *
  158.  *  FUNCTION: AddrLocalizeAppInfo
  159.  *
  160.  *  DESCRIPTION: Look for localize app info strings and copy
  161.  *  them into the app info block.
  162.  *
  163.  *  PARAMETERS: application info ptr
  164.  *
  165.  *  RETURNS: nothing
  166.  *
  167.  *  CREATED: 12/13/95 
  168.  *
  169.  *  BY: Roger Flores
  170.  *
  171.  *  MODIFICATIONS:
  172.  *      10/22/96   roger      Set flags when field modified 
  173.  *************************************************************/
  174. //static void AddrLocalizeAppInfo(AddrAppInfoPtr appInfoP)
  175. //{
  176. //   MemHandle       localizedAppInfoH;
  177. //   Char *          localizedAppInfoP;
  178. //   AddrAppInfoPtr   nilP = 0;
  179. //   MemHandle       stringsH;
  180. //   Char *         *stringsP;
  181. //   int             i;
  182. //   UInt16            localRenamedCategories;
  183. //   UInt32            localDirtyFieldLabels;
  184. //
  185. //
  186. //   localizedAppInfoH = DmGetResource(appInfoStringsRsc, LocalizedAppInfoStr);
  187. //   if (!localizedAppInfoH)
  188. //      return;
  189. //   localizedAppInfoP = MemHandleLock(localizedAppInfoH);
  190. //   stringsH = SysFormPointerArrayToStrings(localizedAppInfoP, 
  191. //      dmRecNumCategories + addrNumFields + numPhoneLabelsStoredSecond);
  192. //   stringsP = MemHandleLock(stringsH);
  193. //   
  194. //   
  195. //   // Copy each category
  196. //   localRenamedCategories = appInfoP->renamedCategories;
  197. //   for (i = 0; i < dmRecNumCategories; i++)
  198. //      {
  199. //      if (stringsP[i][0] != '\0')
  200. //         {
  201. //         DmStrCopy(appInfoP, (Int32) nilP->categoryLabels[i], stringsP[i]);
  202. //         SetBitMacro(localRenamedCategories, i);
  203. //         }
  204. //      }
  205. //   DmWrite(appInfoP, (Int32) &nilP->renamedCategories, &localRenamedCategories,  
  206. //      sizeof(localRenamedCategories));
  207. //   
  208. //   
  209. //   // Copy each field label
  210. //   localDirtyFieldLabels = appInfoP->dirtyFieldLabels.allBits;
  211. //   for (i = 0; i < (addrNumFields + numPhoneLabelsStoredSecond); i++)
  212. //      {
  213. //      if (stringsP[i + dmRecNumCategories][0] != '\0')
  214. //         {
  215. //         DmStrCopy(appInfoP, (Int32) nilP->fieldLabels[i], 
  216. //            stringsP[i + dmRecNumCategories]);
  217. //         SetBitMacro(localDirtyFieldLabels, i);
  218. //         }
  219. //      }
  220. //   DmWrite(appInfoP, (Int32) &nilP->dirtyFieldLabels.allBits, &localDirtyFieldLabels,  
  221. //      sizeof(localDirtyFieldLabels));
  222. //   
  223. //   
  224. //   MemPtrFree(stringsP);
  225. //   MemPtrUnlock(localizedAppInfoP);
  226. //   DmReleaseResource(localizedAppInfoH);
  227. //}
  228.  
  229.  
  230. /************************************************************
  231.  *
  232.  *  FUNCTION: AddrAppInfoInit
  233.  *
  234.  *  DESCRIPTION: Create an app info chunk if missing.  Set
  235.  *      the strings to a default.
  236.  *
  237.  *  PARAMETERS: dbP - open database pointer
  238.  *
  239.  *  RETURNS: 0 if successful, errorcode if not
  240.  *
  241.  *  CREATED: 1/3/95 
  242.  *
  243.  *  BY: Roger Flores
  244.  *
  245.  *  MODIFICATIONS:
  246.  *      10/22/96   roger      Change to init data via code and resources to 
  247.  *                        remove global var use which wasn't always available.
  248.  *************************************************************/
  249. //Err   AddrAppInfoInit(DmOpenRef dbP)
  250. //{
  251. //   UInt16         cardNo;
  252. //   LocalID        dbID;
  253. //   LocalID        appInfoID;
  254. //   MemHandle         h;
  255. //   AddrAppInfoPtr appInfoP;
  256. //   AddrAppInfoPtr defaultAddrApplicationInfoP;
  257. //   UInt8          i;
  258. //   
  259. //   
  260. //   appInfoP = AddrAppInfoGetPtr(dbP);
  261. //
  262. //   // If there isn't an AddrApplicationInfo make space for one
  263. //   if (appInfoP == NULL)
  264. //      {
  265. //      if (DmOpenDatabaseInfo(dbP, &dbID, NULL, NULL, &cardNo, NULL))
  266. //         return dmErrInvalidParam;
  267. //      if (DmDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &appInfoID, NULL, NULL, NULL))
  268. //         return dmErrInvalidParam;
  269. //
  270. //      h = DmNewHandle(dbP, sizeof(AddrAppInfoType));
  271. //      if (!h) return dmErrMemError;
  272. //      
  273. //      appInfoID = MemHandleToLocalID( h);
  274. //      DmSetDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &appInfoID, NULL, NULL, NULL);
  275. //
  276. //      appInfoP = MemHandleLock(h);
  277. //      }
  278. //   
  279. //   
  280. //   // Allocate & Clear the app info
  281. //   defaultAddrApplicationInfoP = MemPtrNew(sizeof(AddrAppInfoType));
  282. //   if (defaultAddrApplicationInfoP == NULL)
  283. //      {
  284. //      ErrDisplay("Unable to init AddressDB");
  285. //      return 1;
  286. //      }
  287. //   
  288. //   MemSet(defaultAddrApplicationInfoP, sizeof(AddrAppInfoType), 0);
  289. //   
  290. //   // Init the categories
  291. //   for (i = 0; i < dmRecNumCategories; i++)
  292. //      {
  293. //      defaultAddrApplicationInfoP->categoryUniqIDs[i] = i;
  294. //      }
  295. //   defaultAddrApplicationInfoP->lastUniqID = dmRecNumCategories - 1;
  296. //   
  297. //   // Set to sort by name
  298. //   defaultAddrApplicationInfoP->misc.sortByCompany = false;
  299. //   
  300. //
  301. //   // copy in the defaults and free the default app info
  302. //   DmWrite(appInfoP, 0, defaultAddrApplicationInfoP,  sizeof(AddrAppInfoType));
  303. //   MemPtrFree(defaultAddrApplicationInfoP);
  304. //   
  305. //   
  306. //   // Try to use localized app info block strings.
  307. //   AddrLocalizeAppInfo(appInfoP);
  308. //
  309. //   // Localize the field labels to the current country
  310. //   AddrChangeCountry(appInfoP);
  311. //      
  312. //   
  313. //   // Unlock
  314. //   MemPtrUnlock(appInfoP);
  315. //   
  316. //   return 0;
  317. //}
  318.  
  319.  
  320. /************************************************************
  321.  *
  322.  *  FUNCTION: AddrSetFieldLabel
  323.  *
  324.  *  DESCRIPTION: Set a field's label and mark it dirty.
  325.  *
  326.  *  PARAMETERS: dbP - open database pointer
  327.  *                fieldNum - field label to change
  328.  *                fieldLabel - new field label to use
  329.  *
  330.  *  RETURNS: 0 if successful, errorcode if not
  331.  *
  332.  *  CREATED: 6/28/95 
  333.  *
  334.  *  BY: Roger Flores
  335.  *
  336.  *************************************************************/
  337. //void AddrSetFieldLabel(DmOpenRef dbP, UInt16 fieldNum, Char * fieldLabel)
  338. //{
  339. //   AddrAppInfoPtr    appInfoP;
  340. //   AddrAppInfoType   copy;
  341. //
  342. //
  343. //   ErrFatalDisplayIf(fieldNum >= lastLabel, 
  344. //      "fieldNum out of range");   
  345. //   
  346. //   // Get a copy of the app info
  347. //   appInfoP = AddrAppInfoGetPtr(dbP);
  348. //   ErrFatalDisplayIf(appInfoP == NULL, 
  349. //      "Bad database (invalid or no app info block)");
  350. //   MemMove(©, appInfoP, sizeof(copy));
  351. //   
  352. //   // Make the changes
  353. //   StrCopy(copy.fieldLabels[fieldNum], fieldLabel); //lint !e661 
  354. //   SetBitMacro(copy.dirtyFieldLabels.allBits, fieldNum);
  355. //   
  356. //   // Write changes to record
  357. //   DmWrite(appInfoP, 0, ©, sizeof(copy));
  358. //   
  359. //   // Unlock app info
  360. //   MemPtrUnlock(appInfoP);
  361. //}
  362.    
  363.  
  364.  
  365. /************************************************************
  366.  *
  367.  *  FUNCTION: AddrFindKey
  368.  *
  369.  *  DESCRIPTION: Return the next valid key
  370.  *
  371.  *  PARAMETERS: database packed record
  372.  *            <-> key to use (ptr to string or NULL for uniq ID)
  373.  *            <-> which key (incremented for use again, starts at 1)
  374.  *            -> sortByCompany
  375.  *
  376.  *  RETURNS: 
  377.  *
  378.  *  CREATED: 1/16/95 
  379.  *
  380.  *  BY: Roger Flores
  381.  *
  382.  *   COMMENTS:   Returns the key which is asked for if possible and 
  383.  *   advances whichKey.  If the key is not available the key advances
  384.  *   to the next one.  The order of keys is:
  385.  *
  386.  * if sortByCompany:
  387.  *      companyKey, nameKey, firstNameKey, uniq ID
  388.  *
  389.  * if !sortByCompany:
  390.  *      nameKey, firstNameKey, companyKey (if no name or first name), uniq ID
  391.  *
  392.  *
  393.  *************************************************************/
  394.  
  395. //static void AddrFindKey(AddrPackedDBRecord *r, char **key, UInt16 *whichKey, 
  396. //   Int16 sortByCompany)
  397. //{
  398. //   AddrDBRecordFlags fieldFlags;
  399. //   
  400. //   fieldFlags.allBits = r->flags.allBits;
  401. //
  402. //   ErrFatalDisplayIf(*whichKey == 0 || *whichKey == 5, "Bad addr key");
  403. //
  404. //   if (sortByCompany)
  405. //      {
  406. //      if (*whichKey == 1 && fieldFlags.bits.company)
  407. //         {
  408. //         *whichKey = 2;
  409. //         goto returnCompanyKey;
  410. //         }
  411. //      
  412. //      if (*whichKey <= 2 && fieldFlags.bits.name)
  413. //         {
  414. //         *whichKey = 3;
  415. //         goto returnNameKey;
  416. //         }
  417. //      
  418. //      if (*whichKey <= 3 && fieldFlags.bits.firstName)
  419. //         {
  420. //         *whichKey = 4;
  421. //         goto returnFirstNameKey;
  422. //         }
  423. //      }
  424. //   else
  425. //      {
  426. //      if (*whichKey == 1 && fieldFlags.bits.name)
  427. //         {
  428. //         *whichKey = 2;
  429. //         goto returnNameKey;
  430. //         }
  431. //      
  432. //      if (*whichKey <= 2 && fieldFlags.bits.firstName)
  433. //         {
  434. //         *whichKey = 3;
  435. //         goto returnFirstNameKey;
  436. //         }
  437. //
  438. //      // For now don't consider company name when sorting by person name
  439. //      // unless there isn't a name or firstName
  440. //      if (*whichKey <= 3 && fieldFlags.bits.company &&
  441. //          !(fieldFlags.bits.name || fieldFlags.bits.firstName))
  442. //         {
  443. //         *whichKey = 4;
  444. //         goto returnCompanyKey;
  445. //         }
  446. //
  447. //      }
  448. //   
  449. //   // All possible fields have been tried so return NULL so that
  450. //   // the uniq ID is compared.
  451. //   *whichKey = 5;
  452. //   *key = NULL;
  453. //   return;
  454. //
  455. //
  456. //
  457. //returnCompanyKey:
  458. //   *key = (char *) &r->companyFieldOffset + r->companyFieldOffset;
  459. //   return;
  460. //   
  461. //   
  462. //returnNameKey:
  463. //   *key = &r->firstField;
  464. //   return;
  465. //   
  466. //   
  467. //returnFirstNameKey:
  468. //   *key = &r->firstField;
  469. //   if (r->flags.bits.name)
  470. //      {
  471. //      *key += StrLen(*key) + 1;
  472. //      }
  473. //   return;
  474. //   
  475. //}
  476.  
  477.  
  478. /************************************************************
  479.  *
  480.  *  FUNCTION: AddrComparePackedRecords
  481.  *
  482.  *  DESCRIPTION: Compare two packed records.
  483.  *
  484.  *  PARAMETERS: address record 1
  485.  *            address record 2
  486.  *
  487.  *  RETURNS: -1 if record one is less
  488.  *           1 if record two is less
  489.  *
  490.  *  CREATED: 1/14/95 
  491.  *
  492.  *  BY: Roger Flores
  493.  *
  494.  *   COMMENTS:   Compare the two records key by key until
  495.  *   there is a difference.  Return -1 if r1 is less or 1 if r2
  496.  *   is less.  A zero may be returned if two records
  497.  *   seem identical.
  498.  * NULL fields are considered less than others.
  499.  *
  500.  *************************************************************/
  501.  
  502. //static Int16 AddrComparePackedRecords(AddrPackedDBRecord *r1, AddrPackedDBRecord *r2, 
  503. //   Int16 sortByCompany, SortRecordInfoPtr /*info1*/, SortRecordInfoPtr /*info2*/, 
  504. //   MemHandle /*appInfoH*/)
  505. //{
  506. //   UInt16 whichKey1, whichKey2;
  507. //   char *key1, *key2;
  508. //   Int16 result;
  509. //
  510. //   whichKey1 = 1;
  511. //   whichKey2 = 1;
  512. //   
  513. //   do {
  514. //      AddrFindKey(r1, &key1, &whichKey1, sortByCompany);
  515. //      AddrFindKey(r2, &key2, &whichKey2, sortByCompany);
  516. //      
  517. //      // A key with NULL loses the StrCompare.
  518. //      if (key1 == NULL)
  519. //         {
  520. //         // If both are NULL then return them as equal
  521. //         if (key2 == NULL)
  522. //            {
  523. //            result = 0;
  524. //            return result;
  525. //            }
  526. //         else
  527. //            result = -1;
  528. //         }
  529. //      else
  530. //      if (key2 == NULL)
  531. //         result = 1;
  532. //      else
  533. //         {
  534. //         result = StrCaselessCompare(key1, key2);
  535. //         if (result == 0)
  536. //            result = StrCompare(key1, key2);
  537. //         }
  538. //
  539. //   } while (!result);
  540. //   
  541. //   
  542. //   return result;
  543. //}
  544.  
  545.  
  546. /************************************************************
  547.  *
  548.  *  FUNCTION: AddrUnpackedSize
  549.  *
  550.  *  DESCRIPTION: Return the size of an AddrDBRecordType
  551.  *
  552.  *  PARAMETERS: address record
  553.  *
  554.  *  RETURNS: the size in bytes
  555.  *
  556.  *  CREATED: 1/10/95 
  557.  *
  558.  *  BY: Roger Flores
  559.  *
  560.  *************************************************************/
  561. //static Int16 AddrUnpackedSize(AddrDBRecordPtr r)
  562. //{
  563. //   Int16 size;
  564. //   Int16   index;
  565. //   
  566. //   size = sizeof (AddrPackedDBRecord) - sizeof (char);   // correct
  567. //   for (index = firstAddressField; index < addressFieldsCount; index++)
  568. //      {
  569. //      if (r->fields[index] != NULL)
  570. //         size += StrLen(r->fields[index]) + 1;
  571. //      }
  572. //   return size;
  573. //}
  574.  
  575.  
  576. /************************************************************
  577.  *
  578.  *  FUNCTION: AddrPack
  579.  *
  580.  *  DESCRIPTION: Pack an AddrDBRecordType.  Doesn't pack empty strings.
  581.  *
  582.  *  PARAMETERS: address record to pack
  583.  *                address record to pack into
  584.  *
  585.  *  RETURNS: the AddrPackedDBRecord is packed
  586.  *
  587.  *  CREATED: 1/10/95 
  588.  *
  589.  *  BY: Roger Flores
  590.  *
  591.  *************************************************************/
  592. //static void AddrPack(AddrDBRecordPtr s, void * recordP)
  593. //{
  594. //   Int32                offset;
  595. //   AddrDBRecordFlags    flags;
  596. //   Int16                index;
  597. //   AddrPackedDBRecord*  d=0;
  598. //   Int16                len;
  599. //   void *               srcP;
  600. //   UInt8                companyFieldOffset;
  601. //   
  602. //   flags.allBits = 0;
  603. //
  604. //   DmWrite(recordP, (Int32)&d->options, &s->options, sizeof(s->options));
  605. //   offset = (Int32)&d->firstField;
  606. //   
  607. //   for (index = firstAddressField; index < addressFieldsCount; index++) {
  608. //      if (s->fields[index] != NULL)
  609. ///*         if (s->fields[index][0] == '\0')
  610. //            {
  611. //            // so set the companyFieldOffset or clear it code doesn't fail
  612. //            s->fields[index] = NULL;   
  613. //            }
  614. //         else
  615. //*/
  616. //            {
  617. //         ErrFatalDisplayIf(s->fields[index][0] == '\0' && index != note, 
  618. //            "Empty field being added");
  619. //         srcP = s->fields[index];
  620. //         len = StrLen(srcP) + 1;
  621. //         DmWrite(recordP, offset, srcP, len);
  622. //         offset += len;
  623. //         SetBitMacro(flags.allBits, index);
  624. //         }
  625. //      }
  626. //
  627. //   // Set the flags indicating which fields are used   
  628. //   DmWrite(recordP, (Int32)&d->flags.allBits, &flags.allBits, sizeof(flags.allBits));
  629. //
  630. //   // Set the companyFieldOffset or clear it
  631. //   if (s->fields[company] == NULL)
  632. //      companyFieldOffset = 0;
  633. //   else {
  634. //      index = 1;
  635. //      if (s->fields[name] != NULL)
  636. //         index += StrLen(s->fields[name]) + 1;
  637. //      if (s->fields[firstName] != NULL)
  638. //         index += StrLen(s->fields[firstName]) + 1;
  639. //      companyFieldOffset = (UInt8) index;
  640. //      }
  641. //   DmWrite(recordP, (Int32)(&d->companyFieldOffset), &companyFieldOffset, sizeof(companyFieldOffset));
  642. //}
  643.  
  644.  
  645. /************************************************************
  646.  *
  647.  *  FUNCTION: AddrUnpack
  648.  *
  649.  *  DESCRIPTION: Fills in the AddrDBRecord structure
  650.  *
  651.  *  PARAMETERS: address record to unpack
  652.  *                the address record to unpack into
  653.  *
  654.  *  RETURNS: the record unpacked
  655.  *
  656.  *  CREATED: 1/14/95 
  657.  *
  658.  *  BY: Roger Flores
  659.  *
  660.  *************************************************************/
  661. static void AddrUnpack(AddrPackedDBRecord *src, AddrDBRecordPtr dest)
  662. {
  663.    Int16   index;
  664.    UInt32 flags;
  665.    char *p;
  666.  
  667.    
  668.    dest->options = src->options;
  669.    flags = src->flags.allBits;
  670.    p = &src->firstField;
  671.  
  672.          
  673.    for (index = firstAddressField; index < addressFieldsCount; index++)
  674.       {
  675.       // If the flag is set point to the string else NULL
  676.       if (GetBitMacro(flags, index) != 0)
  677.          {
  678.          dest->fields[index] = p;
  679.          p += StrLen(p) + 1;
  680.          }
  681.       else
  682.          dest->fields[index] = NULL;
  683.       }
  684. }
  685.  
  686.  
  687. /************************************************************
  688.  *
  689.  *  FUNCTION: AddrFindSortPosition
  690.  *
  691.  *  DESCRIPTION: Return where a record is or should be
  692.  *      Useful to find or find where to insert a record.
  693.  *
  694.  *  PARAMETERS: address record
  695.  *
  696.  *  RETURNS: the size in bytes
  697.  *
  698.  *  CREATED: 1/11/95 
  699.  *
  700.  *  BY: Roger Flores
  701.  *
  702.  *************************************************************/
  703. //static UInt16 AddrFindSortPosition(DmOpenRef dbP, AddrPackedDBRecord *newRecord)
  704. //{
  705. //   Int16 sortByCompany;
  706. //   AddrAppInfoPtr appInfoPtr;
  707. //
  708. //   
  709. //   appInfoPtr = (AddrAppInfoPtr) AddrAppInfoGetPtr(dbP);
  710. //   sortByCompany = appInfoPtr->misc.sortByCompany;
  711. //   MemPtrUnlock(appInfoPtr);
  712. //         
  713. //   return DmFindSortPosition(dbP, (void *) newRecord, NULL, (DmComparF *) 
  714. //      AddrComparePackedRecords, (Int16) sortByCompany);
  715. //}
  716.  
  717.  
  718.  
  719. /************************************************************
  720.  *
  721.  *  FUNCTION: StrCmpMatches
  722.  *
  723.  *  DESCRIPTION: Compares two strings and reports the number
  724.  *  of matching bytes from the start of <s1>.
  725.  *
  726.  *  PARAMETERS: 2 string pointers
  727.  *
  728.  *  RETURNS: number of matching bytes from <s1>.
  729.  *
  730.  *  CREATED: 6/15/95 
  731.  *
  732.  *  BY: Roger Flores
  733.  *
  734.  * REVISION HISTORY:
  735.  *             Name  Date       Description
  736.  *              ----  ----       -----------
  737.  *             Roger    06/15/95    Initial Revision
  738.  *             kwk    05/16/99    Use TxtCaselessCompare routine.
  739.  *
  740.  *************************************************************/
  741. //static UInt16 StrCmpMatches(const Char* s1, const Char* s2)
  742. //{
  743. //   UInt16 matches;
  744. //
  745. //   ErrFatalDisplayIf ( s1 == NULL, "Error NULL string parameter"); 
  746. //   ErrFatalDisplayIf ( s2 == NULL, "Error NULL string parameter");
  747. //
  748. //    TxtCaselessCompare(s1, StrLen(s1), &matches, s2, StrLen(s2), NULL);
  749. //    return (matches);
  750. //}
  751.  
  752.  
  753. /************************************************************
  754.  *
  755.  *  FUNCTION: AddrNewRecord
  756.  *
  757.  *  DESCRIPTION: Create a new packed record in sorted position
  758.  *
  759.  *  PARAMETERS: database pointer - open db pointer
  760.  *            address record   - pointer to a record to copy into the DB
  761.  *            record index      - to be set to the new record's index
  762.  *
  763.  *  RETURNS: ##0 if successful, errorcode if not
  764.  *             index set if a new record is created.
  765.  *
  766.  *  CREATED: 1/10/95 
  767.  *
  768.  *  BY: Roger Flores
  769.  *
  770.  *************************************************************/
  771. //Err AddrNewRecord(DmOpenRef dbP, AddrDBRecordPtr r, UInt16 *index)
  772. //{
  773. //   MemHandle               recordH;
  774. //   Err                   err;
  775. //   AddrPackedDBRecord*   recordP;
  776. //   UInt16                   newIndex;
  777. //   
  778. //
  779. //   // 1) and 2) (make a new chunk with the correct size)
  780. //   recordH = DmNewHandle(dbP, (Int32) AddrUnpackedSize(r));
  781. //   if (recordH == NULL)
  782. //      return dmErrMemError;
  783. //
  784. //      
  785. //   // 3) Copy the data from the unpacked record to the packed one.
  786. //   recordP = MemHandleLock(recordH);
  787. //   AddrPack(r, recordP);
  788. //
  789. //   // Get the index
  790. //   newIndex = AddrFindSortPosition(dbP, recordP);
  791. //   MemPtrUnlock(recordP);
  792. //
  793. //
  794. //   // 4) attach in place
  795. //   err = DmAttachRecord(dbP, &newIndex, recordH, 0);
  796. //   if (err) 
  797. //      MemHandleFree(recordH);
  798. //   else
  799. //      *index = newIndex;
  800. //      
  801. //   return err;
  802. //}
  803.  
  804.  
  805. /************************************************************
  806.  *
  807.  *  FUNCTION: AddrChangeRecord
  808.  *
  809.  *  DESCRIPTION: Change a record in the Address Database
  810.  *
  811.  *  PARAMETERS: dbP - open database pointer
  812.  *            database index
  813.  *            address record
  814.  *            changed fields
  815.  *
  816.  *  RETURNS: ##0 if successful, errorcode if not
  817.  *
  818.  *  CREATED: 1/14/95 
  819.  *
  820.  *  BY: Roger Flores
  821.  *
  822.  *   COMMENTS:   Records are not stored with extra padding - they
  823.  *   are always resized to their exact storage space.  This avoids
  824.  *   a database compression issue.  The code works as follows:
  825.  *   
  826.  *   1)   get the size of the new record
  827.  *   2)   make the new record
  828.  *   3)   pack the packed record plus the changes into the new record
  829.  *   4)   if the sort position is changes move to the new position
  830.  *   5)   attach in position
  831.  *
  832.  * The MemHandle to the record passed doesn't need to be unlocked 
  833.  * since that chunk is freed by this routine.  It should be discarded.
  834.  *
  835.  *************************************************************/
  836. //Err AddrChangeRecord(DmOpenRef dbP, UInt16 *index, AddrDBRecordPtr r, 
  837. //   AddrDBRecordFlags changedFields)
  838. //{
  839. //   AddrDBRecordType    src;
  840. //   MemHandle             srcH;
  841. //   Err                result;
  842. //   MemHandle             recordH=0;
  843. //   MemHandle             oldH;
  844. //   Int16                i;
  845. //   UInt32             changes = changedFields.allBits;
  846. //   Int16                sortByCompany;
  847. //   AddrAppInfoPtr    appInfoPtr;
  848. //   Boolean            dontMove;
  849. //   UInt16                attributes;      // to contain the deleted flag
  850. //   
  851. //   AddrPackedDBRecord*   cmpP;
  852. //   AddrPackedDBRecord*   recordP;
  853. //
  854. //   
  855. //   // We do not assume that r is completely valid so we get a valid
  856. //   // AddrDBRecordPtr...
  857. //   if ((result = AddrGetRecord(dbP, *index, &src, &srcH)) != 0)
  858. //      return result;
  859. //   
  860. //   // and we apply the changes to it.
  861. //   src.options = r->options;         // copy the phone info
  862. //   for (i = firstAddressField; i < addressFieldsCount; i++) 
  863. //      {
  864. //      // If the flag is set point to the string else NULL
  865. //      if (GetBitMacro(changes, i) != 0)
  866. //         {
  867. //         src.fields[i] = r->fields[i];
  868. //         RemoveBitMacro(changes, i);
  869. //         }
  870. //      if (changes == 0)
  871. //         break;      // no more changes
  872. //      }
  873. //
  874. //
  875. //   // 1) and 2) (make a new chunk with the correct size)
  876. //   recordH = DmNewHandle(dbP, AddrUnpackedSize(&src));
  877. //   if (recordH == NULL)
  878. //      {
  879. //      MemHandleUnlock(srcH);      // undo lock from AddrGetRecord above
  880. //      return dmErrMemError;
  881. //      }
  882. //   recordP = MemHandleLock(recordH);
  883. //
  884. //      
  885. //   // 3) Copy the data from the unpacked record to the packed one.
  886. //   AddrPack(&src, recordP);
  887. //
  888. //   // The original record is copied and no longer needed.
  889. //   MemHandleUnlock(srcH);
  890. //   
  891. //
  892. //   // 4) if the sort position changes...
  893. //   // Check if any of the key fields have changed
  894. //   if ((changedFields.allBits & sortKeyFieldBits) == 0) 
  895. //      goto attachRecord;
  896. //   
  897. //   
  898. //   // Make sure *index-1 < *index < *index+1, if so it's in sorted 
  899. //   // order.  Leave it there.   
  900. //   appInfoPtr = (AddrAppInfoPtr) AddrAppInfoGetPtr(dbP);
  901. //   sortByCompany = appInfoPtr->misc.sortByCompany;
  902. //   MemPtrUnlock(appInfoPtr);
  903. //
  904. //   if (*index > 0)
  905. //      {
  906. //      // This record wasn't deleted and deleted records are at the end of the
  907. //      // database so the prior record may not be deleted!
  908. //      cmpP = MemHandleLock(DmQueryRecord(dbP, *index-1));
  909. //      dontMove = (AddrComparePackedRecords (cmpP,  recordP, sortByCompany,
  910. //                     NULL, NULL, 0) == -1);
  911. //      MemPtrUnlock(cmpP);
  912. //      }
  913. //   else 
  914. //      dontMove = true;
  915. //
  916. //
  917. //   if (*index+1 < DmNumRecords (dbP))
  918. //      {
  919. //      DmRecordInfo(dbP, *index+1, &attributes, NULL, NULL);
  920. //      if (attributes & dmRecAttrDelete)
  921. //         ;      // don't move it after the deleted record!
  922. //      else {
  923. //         cmpP = MemHandleLock(DmQueryRecord(dbP, *index+1));
  924. //         dontMove = dontMove && (AddrComparePackedRecords (recordP, cmpP, 
  925. //                     sortByCompany, NULL, NULL, 0) == -1);
  926. //         MemPtrUnlock(cmpP);
  927. //         }
  928. //      }
  929. //
  930. //      
  931. //   if (dontMove) 
  932. //      goto attachRecord;
  933. //
  934. //   
  935. //   
  936. //   // The record isn't in the right position.  Move it.
  937. //   i = AddrFindSortPosition(dbP, recordP);
  938. //   DmMoveRecord(dbP, *index, i);
  939. //   if (i > *index) i--;
  940. //   *index = i;                  // return new position
  941. //
  942. //
  943. //   // Attach the new record to the old index,  the preserves the 
  944. //   // category and record id.
  945. //attachRecord:
  946. //
  947. //   result = DmAttachRecord(dbP, index, recordH, &oldH);
  948. //   MemPtrUnlock(recordP);
  949. //   if (result) return result;
  950. //
  951. //   MemHandleFree(oldH);
  952. //   return 0;
  953. //}
  954.  
  955.  
  956.  
  957. /************************************************************
  958.  *
  959.  *  FUNCTION: AddrGetRecord
  960.  *
  961.  *  DESCRIPTION: Get a record from the Address Database
  962.  *
  963.  *  PARAMETERS: database pointer - open db pointer
  964.  *            database index - index of record to lock
  965.  *            address record pointer - pointer address structure
  966.  *            address record - MemHandle to unlock when done
  967.  *
  968.  *  RETURNS: ##0 if successful, errorcode if not
  969.  *    The record's MemHandle is locked so that the pointer to 
  970.  *  strings within the record remain pointing to valid chunk
  971.  *  versus the record randomly moving.  Unlock the MemHandle when
  972.  *  AddrDBRecord is destroyed.
  973.  *
  974.  *  CREATED: 1/14/95 
  975.  *
  976.  *  BY: Roger Flores
  977.  *
  978.  *************************************************************/
  979. Err AddrGetRecord(DmOpenRef dbP, UInt16 index, AddrDBRecordPtr recordP, 
  980.    MemHandle *recordH)
  981. {
  982.    AddrPackedDBRecord *src;
  983.  
  984.    *recordH = DmQueryRecord(dbP, index);
  985.    src = (AddrPackedDBRecord *) MemHandleLock(*recordH);
  986.    if (src == NULL)
  987.       return dmErrIndexOutOfRange;
  988.    
  989.    AddrUnpack(src, recordP);
  990.    
  991.    return 0;
  992. }
  993.  
  994.  
  995. /***********************************************************************
  996.  *
  997.  * FUNCTION:    RecordContainsData
  998.  *
  999.  * DESCRIPTION: Checks the record returns true if it contains any data.
  1000.  *
  1001.  * PARAMETERS:  recordP  - a pointer to an address record
  1002.  *
  1003.  * RETURNED:    true if one of the fields has data
  1004.  *
  1005.  * REVISION HISTORY:
  1006.  *         Name   Date      Description
  1007.  *         ----   ----      -----------
  1008.  *         rsf   12/3/97   Initial Revision
  1009.  *
  1010.  ***********************************************************************/
  1011. Boolean RecordContainsData (AddrDBRecordPtr recordP)
  1012. {
  1013.    UInt16 i;
  1014.    
  1015.    
  1016.     // Look for a field which isn't empty
  1017.     for (i = firstAddressField; i < addressFieldsCount; i++)
  1018.         {
  1019.         if (recordP->fields[i] != NULL)
  1020.            return true;
  1021.         }
  1022.     
  1023.     return false;
  1024. }
  1025.  
  1026.  
  1027. /***********************************************************************
  1028.  *
  1029.  * FUNCTION:    RecordContainsField
  1030.  *
  1031.  * DESCRIPTION: Check if a packed record contains a desired field.           
  1032.  *
  1033.  * PARAMETERS:  recordP  - pointer to the record to search
  1034.  *              field - type of field to find.
  1035.  *
  1036.  * RETURNED:    true if the record contains the field.
  1037.  *
  1038.  * REVISION HISTORY:
  1039.  *         Name   Date      Description
  1040.  *         ----   ----      -----------
  1041.  *         Roger   7/9/96   Initial Revision
  1042.  *
  1043.  ***********************************************************************/
  1044. //static Boolean RecordContainsField(AddrPackedDBRecord *packedRecordP, 
  1045. //   AddressLookupFields field, Int16 * phoneP, Int16 direction,
  1046. //   AddressFields lookupFieldMap[])
  1047. //{
  1048. //   int index;
  1049. //   int stopIndex;
  1050. //   int phoneType;
  1051. //   
  1052. //   
  1053. //   switch (field)
  1054. //       {
  1055. //      case addrLookupSortField:
  1056. //         return packedRecordP->flags.allBits & sortKeyFieldBits;
  1057. //      
  1058. //      case addrLookupListPhone:
  1059. //         return GetBitMacro(packedRecordP->flags.allBits, firstPhoneField + 
  1060. //            packedRecordP->options.phones.displayPhoneForList);
  1061. //      
  1062. //      case addrLookupNoField:
  1063. //         return true;
  1064. //      
  1065. //      default:
  1066. //            if (!IsPhoneLookupField(field))
  1067. //                return GetBitMacro(packedRecordP->flags.allBits, lookupFieldMap[field]) != 0;
  1068. //         
  1069. //            phoneType = field - addrLookupWork;
  1070. //            index = firstPhoneField + *phoneP;
  1071. //            if (direction == dmSeekForward)
  1072. //                stopIndex = lastPhoneField + direction;
  1073. //            else
  1074. //                stopIndex = firstPhoneField + direction;
  1075. //            
  1076. //         while (index != stopIndex)
  1077. //             {
  1078. //            // If the phone field is the type requested and it's not empty 
  1079. //            // return it.
  1080. //            if (GetPhoneLabel(packedRecordP, index) == phoneType &&
  1081. //                GetBitMacro(packedRecordP->flags.allBits, index))
  1082. //                {
  1083. //               *phoneP = index - firstPhoneField;
  1084. //               return true;
  1085. //                 }
  1086. //              index += direction;
  1087. //             }
  1088. //          
  1089. //         // The phone type wasn't used.
  1090. //         if (direction == dmSeekForward)
  1091. //             *phoneP = 0;                              // Reset for the next record
  1092. //         else
  1093. //            *phoneP = numPhoneFields - 1;      // Reset for the next record
  1094. //          
  1095. //         return false;
  1096. //        }
  1097. //}
  1098.  
  1099.  
  1100. /************************************************************
  1101.  *
  1102.  *  FUNCTION: AddrChangeSortOrder
  1103.  *
  1104.  *  DESCRIPTION: Change the Address Database's sort order
  1105.  *
  1106.  *  PARAMETERS: dbP - open database pointer
  1107.  *            TRUE if sort by company
  1108.  *
  1109.  *  RETURNS: nothing
  1110.  *
  1111.  *  CREATED: 1/17/95 
  1112.  *
  1113.  *  BY: Roger Flores
  1114.  *
  1115.  *************************************************************/
  1116. //Err AddrChangeSortOrder(DmOpenRef dbP, Boolean sortByCompany)
  1117. //{
  1118. //   AddrAppInfoPtr appInfoPtr;
  1119. //   AddrAppInfoPtr   nilP=0;
  1120. //   AddrDBMisc      misc;
  1121. //
  1122. //   
  1123. //   appInfoPtr = (AddrAppInfoPtr) AddrAppInfoGetPtr(dbP);
  1124. //   misc = appInfoPtr->misc;
  1125. //   misc.sortByCompany = sortByCompany;
  1126. //   DmWrite(appInfoPtr, (Int32) &nilP->misc, &misc, sizeof(misc));
  1127. //   MemPtrUnlock(appInfoPtr);
  1128. //   
  1129. //   DmQuickSort(dbP, (DmComparF *) AddrComparePackedRecords, (Int16) sortByCompany);
  1130. //   return 0;
  1131. //}
  1132.  
  1133.  
  1134. /***********************************************************************
  1135.  *
  1136.  * FUNCTION:    AddrLookupSeekRecord
  1137.  *
  1138.  * DESCRIPTION: Given the index of a record, scan 
  1139.  *              forewards or backwards for displayable records.           
  1140.  *
  1141.  * PARAMETERS:  indexP  - pointer to the index of a record to start from;
  1142.  *                        the index of the record sought is returned in
  1143.  *                        this parameter.
  1144.  *
  1145.  *              offset  - number of records to skip:   
  1146.  *                           0 - mean seek from the current record to the
  1147.  *                             next display record, if the current record is
  1148.  *                             a display record, its index is retuned.
  1149.  *                         1 - mean seek foreward, skipping one displayable 
  1150.  *                             record
  1151.  *                        -1 - means seek backwards, skipping one 
  1152.  *                             displayable record
  1153.  *                             
  1154.  *
  1155.  * RETURNED:    true if a displayable record was found.
  1156.  *
  1157.  * REVISION HISTORY:
  1158.  *         Name   Date      Description
  1159.  *         ----   ----      -----------
  1160.  *         Roger   7/9/96   Initial Revision
  1161.  *
  1162.  ***********************************************************************/
  1163. //extern Boolean AddrLookupSeekRecord (DmOpenRef dbP, UInt16 * indexP, 
  1164. //   Int16 * phoneP, Int16 offset, Int16 direction, 
  1165. //   AddressLookupFields field1, AddressLookupFields field2, 
  1166. //   AddressFields lookupFieldMap[])
  1167. //{
  1168. //   UInt16 index;
  1169. //   UInt16 oldIndex;
  1170. //   UInt16 count;
  1171. //   UInt16 numRecords;
  1172. //   MemHandle recordH;
  1173. //   Boolean match;
  1174. //   Int16 phone;
  1175. //   Boolean searchPhones;
  1176. //   AddrPackedDBRecord *packedRecordP;
  1177. //   
  1178. //
  1179. //   ErrFatalDisplayIf ( (direction != dmSeekForward) && (direction != dmSeekBackward), 
  1180. //      "Bad Param");
  1181. //
  1182. //   ErrFatalDisplayIf ( (offset < 0), "Bad param"); 
  1183. //   
  1184. //
  1185. //   index = *indexP;
  1186. //   phone = *phoneP;
  1187. //   
  1188. //   searchPhones = IsPhoneLookupField(field1) || IsPhoneLookupField(field2);
  1189. //
  1190. //   numRecords = DmNumRecords(dbP);
  1191. //   
  1192. //   if (index >= numRecords)
  1193. //       {
  1194. //      if (direction == dmSeekForward)
  1195. //         return false;
  1196. //      else
  1197. //         index = numRecords - 1;
  1198. //      }
  1199. //   
  1200. //   
  1201. //   // Moving forward?
  1202. //   if (direction == dmSeekForward )
  1203. //      count = numRecords - index;
  1204. //   else
  1205. //      count = index + 1;
  1206. //      
  1207. //   // Loop through the records
  1208. //   while (count--) {
  1209. //   
  1210. //      // Make sure the current record isn't hidden.  If so skip it and find the
  1211. //      // next non hidden record.  Decrease the record count to search by the number
  1212. //      // of records skipped.
  1213. //      oldIndex = index;
  1214. //      if (DmSeekRecordInCategory (dbP, &index, 0, direction, dmAllCategories))
  1215. //         {
  1216. //         // There are no more records.
  1217. //         break;
  1218. //         }
  1219. //      if (index != oldIndex)
  1220. //         {
  1221. //         if (direction == dmSeekForward)
  1222. //            count -= index - oldIndex;
  1223. //         else
  1224. //            count -= oldIndex - index;
  1225. //         }
  1226. //      
  1227. //      recordH = DmQueryRecord(dbP, index);
  1228. //      
  1229. //      // If we have found a deleted record stop the search.
  1230. //      if (!recordH)
  1231. //         break;
  1232. //      
  1233. //      packedRecordP = MemHandleLock(recordH);
  1234. //      if (!packedRecordP)
  1235. //         goto Exit;
  1236. //
  1237. //      match = RecordContainsField(packedRecordP, field1, &phone, direction, lookupFieldMap) &&
  1238. //         RecordContainsField(packedRecordP, field2, &phone, direction, lookupFieldMap);
  1239. //      
  1240. //      MemHandleUnlock(recordH);
  1241. //      
  1242. //      if (match) 
  1243. //         {
  1244. //         *indexP = index;
  1245. //         *phoneP = phone;
  1246. //         if (offset == 0) return true;
  1247. //         offset--;
  1248. //         }
  1249. //      
  1250. //      // Look for another phone in this record if one was found or
  1251. //      // else look at the next record.
  1252. //      if (searchPhones && match)
  1253. //         {
  1254. //         phone += direction;
  1255. //         // We their are no more phones to search so advance to next record
  1256. //         if (phone == -1 || numPhoneFields <= phone)
  1257. //            {
  1258. //            if (direction == dmSeekForward)
  1259. //               phone = 0;
  1260. //            else
  1261. //               phone = numPhoneFields - 1;
  1262. //
  1263. //            index += direction;
  1264. //            }
  1265. //         else
  1266. //            {
  1267. //            // Since we are going to search this record again bump the count up
  1268. //            // by one.  This loop is supposed to loop once per record to search.
  1269. //            count++;
  1270. //            }
  1271. //         }
  1272. //      else
  1273. //         index += direction;
  1274. //         
  1275. //      }
  1276. //   
  1277. //   return false;
  1278. //
  1279. //Exit:
  1280. //   ErrDisplay("Err seeking rec");
  1281. //
  1282. //   return false;
  1283. //}
  1284.  
  1285. /************************************************************
  1286.  *
  1287.  *  FUNCTION: PrvSeekVisibleRecordInCategory
  1288.  *
  1289.  *  DESCRIPTION: Like DmSeekRecordInCategory, but if masked is true
  1290.  *                        also explicitly skips past private records
  1291.  *
  1292.  *  PARAMETERS: masked - indicates that database is opened in show secret mode
  1293.  *                            but should be hide secret.
  1294.  *
  1295.  *  RETURNS: as DmSeekRecordInCategory
  1296.  *
  1297.  *  CREATED: 6/15/99
  1298.  *
  1299.  *  BY: Jameson Quinn
  1300.  *
  1301.  *************************************************************/
  1302. //Boolean PrvSeekVisibleRecordInCategory (DmOpenRef dbR, UInt16 * indexP, UInt16 offset,
  1303. //    Int16 direction, UInt16 category, Boolean masked)
  1304. //{
  1305. //    UInt16        attr;
  1306. //    Boolean result;
  1307. //    
  1308. //    result = DmSeekRecordInCategory(dbR,indexP,offset,direction,category);
  1309. //    
  1310. //    if (result != errNone)
  1311. //        {
  1312. //        goto Exit;
  1313. //        }
  1314. //    
  1315. //    DmRecordInfo (dbR, *indexP, &attr, NULL, NULL);
  1316. //    
  1317. //    while (masked && (attr & dmRecAttrSecret))
  1318. //        {
  1319. //        result = DmSeekRecordInCategory(dbR,indexP,1,direction,category);
  1320. //        
  1321. //        if (result != errNone)
  1322. //            {
  1323. //            goto Exit;
  1324. //            }
  1325. //            
  1326. //        DmRecordInfo (dbR, *indexP, &attr, NULL, NULL);
  1327. //        }
  1328. //
  1329. //Exit:
  1330. //    return result;
  1331. //}
  1332.  
  1333. /************************************************************
  1334.  *
  1335.  *  FUNCTION: AddrLookupString
  1336.  *
  1337.  *  DESCRIPTION: Return which record contains the most of
  1338.  *      the string passed.  If no string is passed or there
  1339.  *  aren't any records then false is returned.
  1340.  *
  1341.  *  PARAMETERS: address record
  1342.  *                key - string to lookup record with
  1343.  *                sortByCompany - how the db is sorted
  1344.  *                category -  the category to search in
  1345.  *                recordP - to contain the record found
  1346.  *                completeMatch -  true if a record contains all 
  1347.  *                                 of the key
  1348.  *
  1349.  *  RETURNS: the record in recordP or false
  1350.  *             completeMatch -  true if a record contains all 
  1351.  *                              of the key
  1352.  *
  1353.  *  CREATED: 6/15/95 
  1354.  *
  1355.  *  BY: Roger Flores
  1356.  *
  1357.  *************************************************************/
  1358. //Boolean AddrLookupString(DmOpenRef dbP, Char * key, 
  1359. //   Boolean sortByCompany, UInt16 category, UInt16 * recordP, Boolean *completeMatch,
  1360. //   Boolean masked)
  1361. //{
  1362. //   Int16                   numOfRecords;
  1363. //   MemHandle                rH;
  1364. //   AddrPackedDBRecord*   r;
  1365. //   UInt16                  kmin, probe, probe2, i;      // all positions in the database.
  1366. //   Int16                   result;                     // result of comparing two records
  1367. //   UInt16                   whichKey;
  1368. //   char*                  recordKey;
  1369. //   UInt16                   matches1, matches2;
  1370. //
  1371. //   
  1372. //   // If there isn't a key to search with stop the with the first record.
  1373. //   if (key == NULL || *key == '\0')
  1374. //      {
  1375. //      *completeMatch = true;
  1376. //      return false;
  1377. //      }
  1378. //      
  1379. //   numOfRecords = DmNumRecords(dbP);
  1380. //   if (numOfRecords == 0)
  1381. //      return false;
  1382. //   
  1383. //   result = 0;
  1384. //   kmin = probe = 0;
  1385. //   rH = 0;
  1386. //   
  1387. //   
  1388. //   while (numOfRecords > 0)
  1389. //      {
  1390. //      i = numOfRecords / 2;
  1391. //      probe = kmin + i;
  1392. //
  1393. //
  1394. //      // Compare the two records.  Treat deleted records as greater.
  1395. //      // If the records are equal look at the following position.
  1396. //      if (rH) 
  1397. //         MemHandleUnlock(rH);
  1398. //      rH = DmQueryRecord(dbP, probe);
  1399. //      if (rH == 0)
  1400. //         {
  1401. //         result = -1;      // Delete record is greater
  1402. //         }
  1403. //      else
  1404. //         {
  1405. //         r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1406. //         ErrFatalDisplayIf(r == 0, "Addr bsearch: data somehow missing");
  1407. //            
  1408. //            
  1409. //         // Compare the string to the first sort key only
  1410. //         whichKey = 1;
  1411. //         AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1412. //      
  1413. //         if (recordKey == NULL)
  1414. //            result = 1;
  1415. //         else
  1416. //            result = StrCaselessCompare(key, recordKey);
  1417. //
  1418. //
  1419. //         // If equal stop here!  We don't want the position after.
  1420. //         if (result == 0)
  1421. //            goto findRecordInCategory;
  1422. //         }
  1423. //
  1424. //
  1425. //      ErrFatalDisplayIf(result == 0, "Impossible bsearch state");
  1426. //      
  1427. //      // More likely than < 0 because of deleted records
  1428. //      if (result < 0)
  1429. //         numOfRecords = i;
  1430. //      else
  1431. //         {
  1432. //         kmin = probe + 1;
  1433. //         numOfRecords = numOfRecords - i - 1;
  1434. //         }
  1435. //      }
  1436. //
  1437. //   if (result >= 0)
  1438. //      probe++;
  1439. //      
  1440. //findRecordInCategory:
  1441. //   if (rH)
  1442. //      MemHandleUnlock(rH);
  1443. //   
  1444. //   // At this point probe is the position where the string could be
  1445. //   // inserted.  It is in between two entries.  Neither the record
  1446. //   // before or after may have ANY letters in common, especially after
  1447. //   // those records in other catergories are skipped.  Go with the
  1448. //   // record that has the most letters in common.
  1449. //   
  1450. //   
  1451. //   // Make sure the record returned is of the same category.
  1452. //   // If not return the first prior record of the same category.
  1453. //   probe2 = probe;
  1454. //   if (!PrvSeekVisibleRecordInCategory (dbP, &probe, 0, dmSeekForward, category, masked))
  1455. //      {
  1456. //      // Now count the number of matching characters in probe
  1457. //      rH = DmQueryRecord(dbP, probe);      // No deleted record possible
  1458. //      r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1459. //      ErrFatalDisplayIf(r == 0, "Addr bsearch: data somehow missing");
  1460. //      whichKey = 1;
  1461. //      AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1462. //      if (recordKey == NULL)
  1463. //         matches1 = 0;
  1464. //      else
  1465. //         matches1 = StrCmpMatches(key, recordKey);
  1466. //      
  1467. //      MemHandleUnlock(rH);
  1468. //      }
  1469. //   else
  1470. //      {
  1471. //      // No record in this category was found or probe is past all
  1472. //      // records in this category.  Either way there aren't any matching
  1473. //      // letters.
  1474. //      matches1 = 0;
  1475. //      }
  1476. //   
  1477. //
  1478. //
  1479. //   // Sometimes the record before has more matching letters. Check it.
  1480. //   // Passing DmSeekRecordInCategory an offset of 1 doesn't work
  1481. //   // when probe is at the end of the database and there isn't at least
  1482. //   // one record to skip.
  1483. //   probe2 = probe - 1;
  1484. //   if (probe == 0 ||
  1485. //      PrvSeekVisibleRecordInCategory (dbP, &probe2, 0, dmSeekBackward, category, masked))
  1486. //      {
  1487. //      if (matches1 > 0)
  1488. //         {
  1489. //         // Go with probe because they have at least some letters in common.
  1490. //         *recordP = probe;   //
  1491. //         *completeMatch = (matches1 == StrLen(key));
  1492. //         return true;
  1493. //         }
  1494. //      else
  1495. //         {
  1496. //         // probe has no letters in common and nothing earlier in this category
  1497. //         // was found so this is a failed lookup.
  1498. //         *completeMatch = false;
  1499. //         return false;
  1500. //         }
  1501. //      }
  1502. //   
  1503. //   
  1504. //   // Now count the number of matching characters in probe2
  1505. //   rH = DmQueryRecord(dbP, probe2);      // No deleted record possible
  1506. //   r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1507. //   ErrFatalDisplayIf(r == 0, "Addr bsearch: data somehow missing");
  1508. //   whichKey = 1;
  1509. //   AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1510. //   if (recordKey == NULL)
  1511. //      matches2 = 0;
  1512. //   else
  1513. //      matches2 = StrCmpMatches(key, recordKey);
  1514. //   MemHandleUnlock(rH);
  1515. //
  1516. //
  1517. //   // Now, return the probe which has the most letters in common.
  1518. //   if (matches1 > matches2)
  1519. //      {
  1520. //      *completeMatch = (matches1 == StrLen(key));
  1521. //      *recordP = probe;
  1522. //      }
  1523. //   else
  1524. //   if (matches1 == 0 && matches2 == 0)
  1525. //      {
  1526. //      *completeMatch = false;
  1527. //      return false;            // no item with same first letter found
  1528. //      }
  1529. //   else
  1530. //      {
  1531. //      // The first item matches as much or more as the second item
  1532. //      *recordP = probe2;
  1533. //      
  1534. //      // If the prior item in the category has the same number of
  1535. //      // matching letters use it instead.  Repeat to find the
  1536. //      // earliest such match.
  1537. //      while (!PrvSeekVisibleRecordInCategory (dbP, &probe2, 1, dmSeekBackward, category, masked))
  1538. //         {
  1539. //         rH = DmQueryRecord(dbP, probe2);
  1540. //         r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1541. //         ErrFatalDisplayIf(r == 0, "Addr bsearch: data somehow missing");
  1542. //
  1543. //         // Compare the string to the first sort key only
  1544. //         whichKey = 1;
  1545. //         AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1546. //      
  1547. //         if (recordKey == NULL)
  1548. //            matches1 = 0;
  1549. //         else
  1550. //            matches1 = StrCmpMatches(key, recordKey);
  1551. //               
  1552. //         MemHandleUnlock(rH);
  1553. //
  1554. //         if (matches1 == matches2)
  1555. //            *recordP = probe2;
  1556. //         else
  1557. //            break;
  1558. //         }
  1559. //         
  1560. //      *completeMatch = (matches2 == StrLen(key));
  1561. //      }      
  1562. //
  1563. //   return true;
  1564. //}
  1565.  
  1566.  
  1567. /************************************************************
  1568.  *
  1569.  *  FUNCTION:    AddrLookupLookupString
  1570.  *
  1571.  *  DESCRIPTION: Return which record contains the most of
  1572.  *      the string passed.  If no string is passed or there
  1573.  *  aren't any records then false is returned.
  1574.  *
  1575.  *  PARAMETERS: address record
  1576.  *                key - string to lookup record with
  1577.  *                sortByCompany - how the db is sorted
  1578.  *                vars -  Lookup variables
  1579.  *                recordP - to contain the record found
  1580.  *                phoneP - to contain the phone found
  1581.  *                completeMatch -  true if a record contains all 
  1582.  *                                 of the key
  1583.  *
  1584.  *  RETURNS: the record in recordP or false
  1585.  *             completeMatch -  true if a record contains all 
  1586.  *                              of the key
  1587.  *
  1588.  * RETURNED:    false is return if a displayable record was not found.
  1589.  *
  1590.  * REVISION HISTORY:
  1591.  *         Name   Date      Description
  1592.  *         ----   ----      -----------
  1593.  *         Roger   7/19/96   Initial Revision
  1594.  *
  1595.  *************************************************************/
  1596. //extern Boolean AddrLookupLookupString(DmOpenRef dbP, Char * key, 
  1597. //   Boolean sortByCompany, AddressLookupFields field1, 
  1598. //   AddressLookupFields field2, UInt16 * recordP, Int16 * phoneP, 
  1599. //   AddressFields lookupFieldMap[], Boolean *completeMatch, 
  1600. //   Boolean *uniqueMatch)
  1601. //{
  1602. //   Int16                   numOfRecords;
  1603. //   MemHandle                rH;
  1604. //   AddrPackedDBRecord*   r;
  1605. ////   UInt16                  kmin, i;                     // all positions in the database.
  1606. //   UInt16                  probe, probe2         ;      // all positions in the database.
  1607. //   Int16                  phoneProbe, phoneProbe2;
  1608. ////   Int16                   result;                     // result of comparing two records
  1609. //   UInt16                   whichKey;
  1610. //   char*                  recordKey;
  1611. //   UInt16                   matches1, matches2;
  1612. //   AddressFields         searchField;
  1613. //   AddrDBRecordFlags      searchFieldFlag;
  1614. //
  1615. //   
  1616. //   *uniqueMatch = false;
  1617. //   // If there isn't a key to search with stop the with the first record.
  1618. //   if (key == NULL || *key == '\0')
  1619. //      {
  1620. //      *completeMatch = true;
  1621. //      return false;
  1622. //      }
  1623. //      
  1624. //   numOfRecords = DmNumRecords(dbP);
  1625. //   if (numOfRecords == 0)
  1626. //      return false;
  1627. //   
  1628. //   // Performing a lookup on the sort field allows the use a binary search which
  1629. //   // takes advantage of the ordered field.
  1630. //   if (field1 == addrLookupSortField)
  1631. //      {
  1632. //      // Perform the standard lookup on the sort fields looking at all categories.
  1633. //      if (!AddrLookupString(dbP, key, sortByCompany, dmAllCategories, 
  1634. //         recordP, completeMatch, false))
  1635. //         return false;   // nothing matched
  1636. //      
  1637. //      
  1638. //      // At this point probe is the position where the string could be
  1639. //      // inserted.  It is in between two entries.  Neither the record
  1640. //      // before or after may have ANY letters in common, especially after
  1641. //      // those records in other catergories are skipped.  Go with the
  1642. //      // record that has the most letters in common.
  1643. //      
  1644. //      
  1645. //      // Make sure the record returned is of the same category.
  1646. //      // If not return the first prior record of the same category.
  1647. //      probe2 = probe = *recordP;
  1648. //      phoneProbe2 = phoneProbe = 0;
  1649. //      if (AddrLookupSeekRecord (dbP, &probe, &phoneProbe, 0, dmSeekForward, 
  1650. //         field1, field2, lookupFieldMap))
  1651. //         {
  1652. //         // Now count the number of matching characters in probe
  1653. //         rH = DmQueryRecord(dbP, probe);      // No deleted record possible
  1654. //         r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1655. //         ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
  1656. //         whichKey = 1;
  1657. //         AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1658. //         if (recordKey == NULL)
  1659. //            matches1 = 0;
  1660. //         else
  1661. //            matches1 = StrCmpMatches(key, recordKey);
  1662. //         
  1663. //         MemHandleUnlock(rH);
  1664. //         }
  1665. //      else
  1666. //         {
  1667. //         // No record in this category was found or probe is past all
  1668. //         // records in this category.  Either way there aren't any matching
  1669. //         // letters.
  1670. //         matches1 = 0;
  1671. //         }
  1672. //      
  1673. //
  1674. //      *uniqueMatch = true;
  1675. //
  1676. //
  1677. //      // Sometimes the record before has more matching letters. Check it.
  1678. //      // Passing DmSeekRecordInCategory an offset of 1 doesn't work
  1679. //      // when probe is at the end of the database and there isn't at least
  1680. //      // one record to skip.
  1681. //      probe2 = probe - 1;
  1682. //      if (probe == 0 ||
  1683. //         !AddrLookupSeekRecord (dbP, &probe2, &phoneProbe2, 0, dmSeekBackward, 
  1684. //            field1, field2, lookupFieldMap))
  1685. //         {
  1686. //         // There isn't an earlier record.  Try to find a following record.
  1687. //         probe2 = probe + 1;
  1688. //         phoneProbe2 = phoneProbe;
  1689. //         if (!AddrLookupSeekRecord (dbP, &probe2, &phoneProbe2, 0, dmSeekForward, 
  1690. //            field1, field2, lookupFieldMap))
  1691. //            {
  1692. //            // There isn't a following record.  Try to use the probe.
  1693. //            if (matches1 > 0)
  1694. //               {
  1695. //               // Go with probe because they have at least some letters in common.
  1696. //               *recordP = probe;   //
  1697. //               *phoneP = phoneProbe;
  1698. //               *completeMatch = (matches1 == StrLen(key));
  1699. //               return true;
  1700. //               }
  1701. //            else
  1702. //               {
  1703. //               // probe has no letters in common and nothing earlier in this category
  1704. //               // was found so this is a failed lookup.
  1705. //               *completeMatch = false;
  1706. //               return false;
  1707. //               }
  1708. //            }
  1709. //         }
  1710. //      
  1711. //      
  1712. //      // Now count the number of matching characters in probe2
  1713. //      rH = DmQueryRecord(dbP, probe2);      // No deleted record possible
  1714. //      r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1715. //      ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
  1716. //      whichKey = 1;
  1717. //      AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1718. //      if (recordKey == NULL)
  1719. //         matches2 = 0;
  1720. //      else
  1721. //         matches2 = StrCmpMatches(key, recordKey);
  1722. //      MemHandleUnlock(rH);
  1723. //
  1724. //
  1725. //      // Now, return the probe which has the most letters in common.
  1726. //      if (matches1 > matches2)
  1727. //         {
  1728. //         *completeMatch = (matches1 == StrLen(key));
  1729. //         *recordP = probe;
  1730. //         *phoneP = phoneProbe;
  1731. //         
  1732. //         // If the next item has the same number of
  1733. //         // matching letters then the match is not unique.
  1734. //         probe2 = probe;
  1735. //         phoneProbe2 = phoneProbe;
  1736. //         if (AddrLookupSeekRecord (dbP, &probe2, &phoneProbe2, 1, dmSeekForward, 
  1737. //            field1, field2, lookupFieldMap))
  1738. //            {
  1739. //            rH = DmQueryRecord(dbP, probe2);
  1740. //            r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1741. //            ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
  1742. //
  1743. //            // Compare the string to the first sort key only
  1744. //            whichKey = 1;
  1745. //            AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1746. //         
  1747. //            if (recordKey == NULL)
  1748. //               matches2 = 0;
  1749. //            else
  1750. //               matches2 = StrCmpMatches(key, recordKey);
  1751. //                  
  1752. //            MemHandleUnlock(rH);
  1753. //
  1754. //            if (matches1 <= matches2)
  1755. //               {
  1756. //               *uniqueMatch = false;
  1757. //               }
  1758. //            }
  1759. //         }
  1760. //      else
  1761. //      if (matches1 == 0 && matches2 == 0)
  1762. //         {
  1763. //         *completeMatch = false;
  1764. //         *uniqueMatch = false;
  1765. //         return false;            // no item with same first letter found
  1766. //         }
  1767. //      else
  1768. //         {
  1769. //         // The first item matches as much or more as the second item
  1770. //         *recordP = probe2;
  1771. //         *phoneP = phoneProbe2;
  1772. //         
  1773. //         // If the prior item in the category has the same number of
  1774. //         // matching letters use it instead.  Repeat to find the
  1775. //         // earliest such match.
  1776. //         while (AddrLookupSeekRecord (dbP, &probe2, &phoneProbe2, 1, dmSeekBackward, 
  1777. //            field1, field2, lookupFieldMap))
  1778. //            {
  1779. //            rH = DmQueryRecord(dbP, probe2);
  1780. //            r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1781. //            ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
  1782. //
  1783. //            // Compare the string to the first sort key only
  1784. //            whichKey = 1;
  1785. //            AddrFindKey(r, &recordKey, &whichKey, sortByCompany);
  1786. //         
  1787. //            if (recordKey == NULL)
  1788. //               matches1 = 0;
  1789. //            else
  1790. //               matches1 = StrCmpMatches(key, recordKey);
  1791. //                  
  1792. //            MemHandleUnlock(rH);
  1793. //
  1794. //            if (matches1 == matches2)
  1795. //               {
  1796. //               *recordP = probe2;
  1797. //               *phoneP = phoneProbe2;
  1798. //               }
  1799. //            else
  1800. //               break;
  1801. //            }
  1802. //            
  1803. //         *completeMatch = (matches2 == StrLen(key));
  1804. //         *uniqueMatch = false;
  1805. //         }      
  1806. //
  1807. //      return true;
  1808. //         
  1809. //      }
  1810. //   else
  1811. //      {
  1812. //      // Peform a lookup based on unordered data.  This gets real slow with lots of data
  1813. //      // Because to check for uniqueness we must search every record.  This means on average
  1814. //      // this lookup is twice as slow as it would be it it could stop with the first match.
  1815. //      AddrDBRecordType record;
  1816. //      
  1817. //      
  1818. //      *completeMatch = false;
  1819. //      
  1820. //      matches1 = 0;         // treat this as the most matches
  1821. //
  1822. //      // cache these values      
  1823. //      searchField = lookupFieldMap[field1];
  1824. //      searchFieldFlag.allBits = BitAtPosition(field1);
  1825. //      
  1826. //      // Start with the first record and look at each record until there are no more.
  1827. //      // Look for the record with the most number of matching records.  Even if we found
  1828. //      // a record containing all the record we are searching for we must still look
  1829. //      // for one more complete match to confirm or deny uniqueness of the match.
  1830. //      probe2 = 0;
  1831. //      phoneProbe2 = 0;
  1832. //      while (AddrLookupSeekRecord (dbP, &probe2, &phoneProbe2, 1, dmSeekForward, 
  1833. //         field1, field2, lookupFieldMap))
  1834. //         {
  1835. //         rH = DmQueryRecord(dbP, probe2);
  1836. //         r = (AddrPackedDBRecord *) MemHandleLock(rH);
  1837. //         ErrFatalDisplayIf(r == 0, "AddrLookup bsearch: data somehow missing");
  1838. //
  1839. //         // Compare the string to the search field
  1840. //         if (r->flags.allBits & searchFieldFlag.allBits)
  1841. //            {
  1842. //            AddrUnpack(r, &record);
  1843. //            recordKey = record.fields[searchField];
  1844. //         
  1845. //            if (recordKey == NULL)
  1846. //               matches2 = 0;
  1847. //            else
  1848. //               matches2 = StrCmpMatches(key, recordKey);
  1849. //            }
  1850. //         else
  1851. //            {
  1852. //            matches2 = 0;
  1853. //            }
  1854. //               
  1855. //         MemHandleUnlock(rH);
  1856. //         
  1857. //         if (matches2 > matches1)
  1858. //            {
  1859. //            matches1 = matches2;      // the most matches so far
  1860. //            
  1861. //            *recordP = probe2;      // return the best record
  1862. //            *phoneP = phoneProbe2;
  1863. //            
  1864. //            *completeMatch = (matches2 == StrLen(key));
  1865. //            }
  1866. //         // Did we find another record which is a complete match?
  1867. //         else if (matches2 > 0 &&
  1868. //            matches1 == matches2 &&
  1869. //            *completeMatch)
  1870. //            {
  1871. //            *uniqueMatch = false;
  1872. //            return true;
  1873. //            }
  1874. //         else
  1875. //            {
  1876. //            // The record is a matching failure.  Since AddrLookupSeekRecord is going
  1877. //            // to return this record again for every phone field we cheat by specifying
  1878. //            // the last phone field to skip all other entries.
  1879. ////            phoneProbe2 = numPhoneFields - 1;
  1880. //            }
  1881. //         }
  1882. //      
  1883. //      
  1884. //      // Was at least one record found with at least one matching character?
  1885. //      if (matches1 > 0)
  1886. //         {
  1887. //         // At this point every record was searched and no other match was found.
  1888. //         *uniqueMatch = true;
  1889. //         
  1890. //         return true;
  1891. //         }
  1892. //      }
  1893. //   
  1894. //   return false;
  1895. //}
  1896.  
  1897.  
  1898. /***********************************************************************
  1899.  *
  1900.  * FUNCTION:     AddrGetDatabase
  1901.  *
  1902.  * DESCRIPTION:  Get the application's database.  Open the database if it
  1903.  * exists, create it if neccessary.
  1904.  *
  1905.  * PARAMETERS:   *dbPP - pointer to a database ref (DmOpenRef) to be set
  1906.  *                      mode - how to open the database (dmModeReadWrite)
  1907.  *
  1908.  * RETURNED:     Err - zero if no error, else the error
  1909.  *
  1910.  * REVISION HISTORY:
  1911.  *            Name        Date        Description
  1912.  *            ----        ----        -----------
  1913.  *            jmp        10/01/99    Initial Revision
  1914.  *
  1915.  ***********************************************************************/
  1916. Err AddrGetDatabase (DmOpenRef *dbPP, UInt16 mode)
  1917. {
  1918.     DmOpenRef dbP;
  1919.  
  1920.     *dbPP = NULL;
  1921.   
  1922.   // Find the application's data file.  If it doesn't exist create it.
  1923.     dbP = DmOpenDatabaseByTypeCreator (addrDBType, sysFileCAddress, mode);
  1924.     if (!dbP)
  1925.         {
  1926.             DEBUG1("Can't open address database");
  1927.             return 1;
  1928.         }
  1929.     
  1930.     *dbPP = dbP;
  1931.     return 0;
  1932. }
  1933.  
  1934.