ContactMatchName(), ContactEnsureField()
Perhaps you're writing a special-purpose application that communicates with just one contact. Perhaps a carry-out restaurant chain has contracted you to write an application that the user can use to place an order over the phone. The program would only need to make contact with one place: the local restaurant's GSM phone number.
In this case, you wouldn't want to provide UI for choosing a contact--your program is only interested in one dedicated contact. Still, it's worthwhile to store the contact in the Contact database--if the restaurant's phone number changes, the user can enter the corrected number using the Contact Manager built-in application.
To find the Contact record for a particular contact, you will need to make sure that your .gp file contains the following lines:
library contdb library foamdb
Finding the "Stuckey's Snack Shack" Contact, below, shows how you could find a dedicated contact in a Contact database and extract the phone number associated with that contact.
To locate a dedicated contact and extract its phone number, carry out the following steps:
RecordID
of the contact's
record, call ContactMatchName()
. This routine takes a
search string (pass the contact's name), a ContdbFieldType
(pass CFT_NAME, since we're searching by name), a flag (pass a non-zero
value to specify that you're only interested in one matching record),
a pointer to a FieldID
buffer to fill in and a pointer to
a word value to fill in. It returns the RecordID
of the
contact (or -1 if the contact wasn't found). It also fills in the
FieldID
buffer with the contact's name field
FieldID
and fills in the word value with the number of
matches found; neither of these values is important to our purpose.If you're searching multiple databases and the current database doesn't contain the record, go on to the next database.
ContactGetDBHandle()
. This routine takes no arguments
and returns the database's handle.FoamDBGetRecordFromID()
.
This routine takes the Contact database's handle and the record's
RecordID
. It returns the record's memory handle.FieldID
of the record's GSM phone number field. In
the example below, we assume that the record has only one phone number
field, and that this is the field we want. For a more rigorous approach,
we could examine each field to make sure it was named
"Tel (GSM)". For an example of how one might examine all the
fields of a record, see To Get More Info on a Contact.For our shortcut, we use the ContactEnsureField()
function. This function takes as arguments a record handle, a field
name string (in our example, we pass a null optr to specify that
we should use the default field name, and the ContdbFieldType
of the field to find ( pass CFT_PHONE). The function returns a
FieldID
.
FoamDBGetFieldData()
.
Pass the database handle, the record handle, the FieldID
, a
buffer to write the name to, and the size of that buffer. The function
fills in the buffer with the phone number string, and returns the length
of that string. The returned string might not be null-terminated; thus
you will either need to keep track of the returned string length, or
else terminate the string.FoamDBDiscardRecord()
. This routine takes the Contact's
database handle and the record's handle as arguments.ContactReleaseDBHandle()
.If the contact is not found, there are a couple of approaches the application can take:
Code Display: Finding the "Stuckey's Snack Shack" Contact
@method ContactProcessClass, MSG_CONTACT_PROCESS_SEND_TO_STUCKEYS { TCHAR nameStr[] = "Stuckey's Snack Shack"; TCHAR numStr[] = "+1-800-788-2539"; VMFileHandle hCDB; RecordID recordID; FieldID fieldID; word numMatches; dword recordIndex; word len; MemHandle hRecord; int dbOverride = TRUE; FileLongName dbName; int numDBs; int dbNumber; word oldOverride; /* * Check the database on the device and the databases in the memory card. */ /* * First try the db on the device. */ oldOverride = ContactSetOverrideDB(CONTACT_DEVICE_DB_NAME); hCDB = ContactGetDBHandle(); /* device DB */ recordID = ContactMatchName( nameStr, CFT_NAME, TRUE, &fieldID, &numMatches ); ContactReleaseDBHandle(); /* device DB */ if ( recordID == LECI_INVALID_CONTACT_ID) { /* * Now try each db on the memory card. */ numDBs = ContactGetNumDBsOnMemoryCard(); for (dbNumber = 0 ; dbNumber < numDBs; dbNumber++) { ContactGetDBName(dbNumber, dbName); ContactSetOverrideDB(dbName); hCDB = ContactGetDBHandle(); recordID = ContactMatchName( nameStr, CFT_NAME, TRUE, &fieldID, &numMatches ); ContactReleaseDBHandle(); if ( recordID != LECI_INVALID_CONTACT_ID) { break; } /* We didn't find it, loop up and try again. */ } if ( recordID == LECI_INVALID_CONTACT_ID) { ContactRestoreOverrideDB(oldOverride); dbOverride = FALSE; } } hCDB = ContactGetDBHandle(); if ( LECI_INVALID_CONTACT_ID == recordID ) { /* No such record in contact database -- let's add it. */ dbOverride = FALSE; hRecord = ContactCreateRecordFromTemplate(); fieldID = ContactEnsureField( hRecord, NullOptr, CFT_NAME ); FoamDBSetFieldData( hCDB, hRecord, fieldID, nameStr, strlen( nameStr ) ); fieldID = ContactEnsureField( hRecord, @TelGSMStr, CFT_PHONE ); FoamDBSetFieldData( hCDB, hRecord, fieldID, numStr, strlen( numStr ) ); recordIndex = ContactSaveRecord( hRecord ); hRecord = FoamDBGetVisibleRecord( hCDB, recordIndex ); } else { /* Contact exists: get record from ID. */ hRecord = FoamDBGetRecordFromID( hCDB, recordID ); } /* Record was either found or created: get the GSM phone number. */ fieldID = ContactEnsureField( hRecord, @TelGSMStr, CFT_PHONE ); len = FoamDBGetFieldData( hCDB, hRecord, fieldID, numStr, MAX_NUMBER_FIELD_DATA_LEN ); numStr[len] = '\0'; /* * Here, the application can do something with the contact's data... */ ContactReleaseDBHandle(); if (dbOverride ) { ContactRestoreOverrideDB(oldOverride); } } /* MSG_CONTACT_PROCESS_SEND_TO_STUCKEYS */
To allow the user to edit the contact information for this single
contact, use a ContactEdit
object. To specify the
contact that the user will work with, you will need its handle.
Pass the handle as an argument to the MSG_CONTACT_EDIT_DISPLAY_RECORD
message. (Don't call ContactSaveRecord()
,
FoamDBDeleteRecord()
, or FoamDBDiscardRecord()
when done with this handle; the controller will do so.)