The Nokia 9000i Communicator has a Contact database which acts as a central repository of "address book" information. Every time the user enters information about how a place may be reached by phone, fax, or e-mail that information is stored in the Contact database.
Whenever you prompt the user for information about where to send something, you'll probably use the Contact database. This will allow the user to choose which of their contacts should receive.
There are two libraries which exist to keep track of the Contact database and provide an API for the applications which share access to it.
The Contact database is a Foam database, and some operations upon the database will make use of Foam database commands. We will not explore the meanings of these commands closely here, but will show how they are used in the context of the Contact database.
Before reading this chapter, you should be familiar with controllers, Object-Oriented Programming, and the GEOS messaging system. It helps if you try out the "Contacts" built-in application, which demonstrates much of the functionality we'll discuss here.
Most programmers first encounter the ContDB and ContLog libraries when they need to intercept a message associated with a
ContactList
or perhaps a
RecentContactsControl
object. These object classes provide the user with a standard way to choose a contact.
There are other controllers which allow the user to choose an SMS contact.
SMAddressControlClass
allows the user to choose a recipient for a SMS message. This class should cover some applications' needs when it comes to allowing the user to choose a contact. However, if you need a custom control, you may wish to use a
ContactList
and/or a
RecentContactsSMSControl
.
A
ContactList
presents the user with a list of known contacts. The user may choose a name from the list. In Setting up a Contact List
, we show how to set up such an object and get the phone number of the contact the user selects.
The
RecentContactsSMSControl
presents the user with a list containing names and numbers associated with contacts that have recently had SMS transactions with the user. The user may choose a name or number from the list. In Choosing Contacts From a Log
, we show how to set up such an object and get the phone number of the contact the user selects.
1 Setting up a Contact List
1.1 Multiple-Selection ContactLists
1.2 Remembering the Search
1.3 Detecting Unknown Phone Numbers
1.4 Alternate Messages
2 Choosing Contacts From a Log
3 Using a Dedicated Contact
4 Logging Calls
5 To Get More Info on a Contact
6 The User's Own Data
ContactListClass, CONTACT_LIST_NOTIFY_CONTACT_SELECTED_MSG, ContactGetDBHandle(), FoamDBGetRecordFromID(), FoamDBGetFieldData(), FoamDBDiscardRecord(), ContactReleaseDBHandle()
To present the user with a list of Contacts, do the following:
Make sure that your .gp file contains lines requiring the foamdb and contdb libraries:
library contdb library foamdb
In your source code, create a
ContactList
object. The following
ContactList
object declaration allows the user to pick a contact. If the contact has more than one GSM phone number, the controller will make the user choose one of the fields.
ContactList
's
GCI_output
and ATTR_CONTACT_LIST_NOTIFY_CONTACT_SELECTED_MSG specify the object and message. In the example below, the application's process object will handle a message. We will discuss the message in more detail below.
ContactList
SMS-specific, set its ATTR_CONTACT_LIST_CALL_TYPE to CCT_SMS as shown below; also, set the CLF_SELECT_CONTACT_NUMBER feature flag in ATTR_GEN_CONTROL_REQUIRE_UI.
ContactList
's Search bar, set the CLF_SEARCH feature flag in ATTR_GEN_CONTROL_REQUIRE_UI; to exclude the Search bar, exclude the UI.
ContactList
a
ComplexMoniker
and setting its
CMI_iconBitmap
field to CMB_CONTACT_LIST.Putting this together, we end up with the following:
@object ContactListClass MyContactList = {
GI_visMoniker = "I want to talk to...";
GCI_output = (TO_PROCESS);
ATTR_CONTACT_LIST_CALL_TYPE = CCT_SMS;
ATTR_GEN_CONTROL_REQUIRE_UI = CLF_SEARCH |
CLF_SELECT_CONTACT_NUMBER ;
HINT_EXPAND_HEIGHT_TO_FIT_PARENT;
ATTR_CONTACT_LIST_NOTIFY_CONTACT_SELECTED_MSG =
MSG_MYPROCESS_SEND_MESSAGE ;
}
With this configuration, the
ContactList
will send a
MSG_MYPROCESS_SEND_MESSAGE
message to your process object when the user chooses a contact. A sample handler for this message is shown below ( Handling the ContactList's "Selected" Message
). The message will conform to the prototype:
@prototype void
CONTACT_LIST_NOTIFY_CONTACT_SELECTED_MSG(
dword recordID,
word fieldID);
The message handler should carry out the following steps:
ContactGetDBHandle()
. This routine takes no arguments, and returns the Contact database's handle.
FoamDBGetRecordFromID()
. This routine takes the Contact's database handle and the record's
RecordID
value. It allocates a block of memory to hold the record's data and returns the record's handle.
FoamDBGetFieldData()
. Pass the database handle, the record handle, the
FieldID
associated with the GSM number field (this number is supplied by the
ContactList
when it sends this message), 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()
.The example below shows a way of carrying out the above set of steps.
Code Display 4-1 Handling the ContactList's "Selected" Message
@class MyProcessClass, GenProcessClass; @message (CONTACT_LIST_NOTIFY_CONTACT_SELECTED_MSG) MSG_MYPROCESS_SEND_MESSAGE; @endc
@method MyProcessClass, MSG_MYPROCESS_SEND_MESSAGE {
TCHAR theNumber[31];
TCHAR theName[MAX_NAME_DATA_LEN+1];
word numLen;
VMFileHandle CDBHandle;
MemHandle theRecord;
/* Get the Contact database's handle */ CDBHandle = ContactGetDBHandle();
/* Get the handle to the record we're interested in */ theRecord = FoamDBGetRecordFromID( CDBHandle, recordID );
/* Get the GSM phone number string; null-terminate it. */ FoamDBGetFieldData( CDBHandle, theRecord, fieldID, theNumber, 30); theNumber[numLen] = `\000'; /* add null terminator */
/* We'll copy the name to theName buffer. */ ContactGetName(theRecord, theName); /* If you need more information about the contact * (e.g., business name, job title), this is a good place * to retrieve it. */ /* Do what you like with theNumber and theName */
/* We're done with this record. */ FoamDBDiscardRecord(CDBHandle, theRecord );
/* We're done with the database. */ ContactReleaseDBHandle(); }
Multiple-Selection ContactLists
Detecting Unknown Phone Numbers
Recent versions of the ContDB library support ContactLists which allow the user to select more than one contact at a time. This feature is available on devices with version numbers "Responder Build 4...." and higher. See Software Version Number for information about finding out the software version of the user's device.)
To create such a ContactList, give it the hint HINT_CONTACT_LIST_NON_EXCLUSIVE_LIST. The field ATTR_CONTACT_LIST_NUM_ITEMS will then store the number of selected contacts.
There are two methods which may be used to obtain the list of currently selected contacts:
MSG_CONTACT_LIST_GET_IDS_OF_SELECTED_RECORDS, using the size of this buffer (in bytes) as the input parameter. The message will fill the buffer with the selected ContactListSelectedEntrys.
CLF_SELECT_CONTACT_NUMBER in ATTR_GEN_CONTROL_REQUIRE_UI, and set ATTR_CONTACT_LIST_NOTIFY_MULTIPLE_CONTACTS_SELECTED_MSG to the message which will be sent whenever two or more contacts are selected from the contact list. This message must be of the prototype:
@prototype void
CONTACT_LIST_NOTIFY_MULTIPLE_CONTACTS_SELECTED_MSG(
MemHandle block = cx,
word num = dx);
The passed memory handle block will contain the set of ContactListSelectedEntrys, and num will contain the number of these entries. Your message must free the passed memory block.
Normally, a ContactList will lose track of the user's current search if the focus moves to another object. To force the list to remember the current search, send it a MSG_CONTACT_LIST_PRESERVE_SEARCH_ON_NEXT_LOST_FOCUS before it loses the focus. (This message is available on devices with version numbers "Responder Build 4...." and higher. See Software Version Number for information about finding out the software version of the user's device.)
If the user enters a valid phone number in the search box of a ContactList, but that number is not found, an application may request that the ContactList send out a notification using a variable data field. (This variable data field is available on devices with version numbers "Responder Build 4...." and higher. See Software Version Number for information about finding out the software version of the user's device.)
Give the ContactList a ATTR_CONTACT_LIST_NOTIFY_NUMBER_ENTERED_MSG variable data field. This field's data is a message.
The message should have parameters:
void MSG_MY_CL_NOTIFY( MemHandle phNumber = cx);
The passed block contains the phone number string. The message's recipient is responsible for freeing the passed block.
Builds 4.3.7 or newer of the Responder (see versions for more information about software versions) support two different methods for selecting contacts from a CCT_PHONE type of contact controller list. If the user quickly presses the "Select" trigger (F1 on the PC emulator), then, depending on the circumstances, the message specified by ATTR_CONTACT_LIST_NOTIFY_CONTACT_SELECTED_MSG, ATTR_CONTACT_LIST_NOTIFY_NUMBER_ENTERED_MSG, or
ATTR_CONTACT_LIST_NOTIFY_MULTIPLE_CONTACTS_SELECTED_MSG is sent. If the user holds the "Select" trigger for a longer time period, an alternate type of message analogous to the normal selection message is sent. These alternate messages include:
ATTR_CONTACT_LIST_ALTERNATE_NOTIFY_CONTACT_SELECTED_MSG
@prototype void CONTACT_LIST_ALTERNATE_NOTIFY_CONTACT_SELECTED_MSG(
dword recordID = cx:dx,
word fieldID = bp);
fieldID is the ID of the field containing the selected GSM phone number of the record with the ID recordID.
ATTR_CONTACT_LIST_ALTERNATE_NOTIFY_NUMBER_ENTERED_MSG CLF_SELECT_CONTACT_NUMBER must be set. The message must follow the prototype:
@prototype void CONTACT_LIST_ALTERNATE_NOTIFY_NUMBER_ENTERED_MSG(
MemHandle block = cx);
block will contain the null-terminated phone number.
ATTR_CONTACT_LIST_ALTERNATE_NOTIFY_MULTIPLE_CONTACTS_SELECTED_MSG CLF_SELECT_CONTACT_NUMBER and HINT_NON_EXCLUSIVE_LIST must be present for multiple selection contact lists. This message must follow the prototype:
@prototype void CONTACT_LIST_ALTERNATE_NOTIFY_MULTIPLE_CONTACTS_SELECTED_MSG(
MemHandle block = cx,
word num = dx);
block will contain the num ContactListSelectedEntry selected items.
RecentContactsSMSControlClass, CONTACTS_CONTROL_NOTIFY_ENTRY_SELECTED_MSG
For a list of recent SMS contacts, use a
RecentContactsSMSController
. You will need the following line in your
.gp
file:
library contlog
The following setup would allow the user to pick a phone number from a list of recently called SMS numbers, sending a
MSG_MYPROCESS_SEND_RECENT
message to the application's process object:
@object RecentContactsSMSControlClass MyLog = {
GCI_output = ( TO_PROCESS );
ATTR_RECENT_CONTACTS_CONTROL_NOTIFY_ENTRY_SELECTED_MSG =
MSG_MYPROCESS_SEND_RECENT;
}
With this setup, when the user chooses a phone number from the log, a
MSG_MYPROCESS_SEND_RECENT
message will be sent to the process object, which should handle the message. The message should conform to the CONTACTS_CONTROL_NOTIFY_ENTRY_SELECTED_MSG prototype.
@prototype void
CONTACTS_CONTROL_NOTIFY_ENTRY_SELECTED_MSG(
RecentContactsData *data)
typedef struct {
dword RCD_contactID;
NameOrNumber RCD_number;
} RecentContactsData;
The data argument's
RCD_number
field contains the GSM phone number of the selected contact. The code example below shows handler that extract's the name associated with the selected contact. It makes use of functions described in Setting up a Contact List
.
Code Display 4-2 Handling the RecentContacts "Selected" Message
@class MyProcessClass, GenProcessClass; @message (CONTACTS_CONTROL_NOTIFY_ENTRY_SELECTED_MSG) MSG_MYPROCESS_SEND_RECENT; @endc
@method MyProcessClass, MSG_MYPROCESS_SEND_RECENT {
/* Note: all of the code in this example is only useful if you need * the contact's name. If all you need is the GSM phone number, * none of this code is necessary. The phone number string is in * data->RCD_number. * * If you do need the following code, you will need to make sure * that your .gp file includes the lines library contdb library foamdb */
TCHAR theName[MAX_NAME_DATA_LEN+1]; VMFileHandle CDBHandle; MemHandle theRecord;
/* If the user chose a phone number that doesn't have a contact
* associated with it, the contact's RecordID value is -1,
* signalling an invalid contact. */
if ( data->RCD_contactID != LECI_INVALID_CONTACT_ID) {
CDBHandle = ContactGetDBHandle();
theRecord = FoamDBGetRecordFromID( CDBHandle, data->RCD_contactID );
ContactGetName(theRecord, theName); /* If you need more information about the contact * (e.g., business name, job title), this is a good place * to retrieve it. */ FoamDBDiscardRecord(CDBHandle, theRecord ); ContactReleaseDBHandle(); } /* do something clever with data->RCD_number and theName */ }
Recent versions of the Nokia 9000i Communicator allow fax and SMS contact lists to support multiple selections. Set the RCFCF_MULTIPLE_SELECTION or RCMCF_MULTIPLE_SELECTION bit to enable multiple selection for, respectively, a fax or SMS recent contact list and specify the message ATTR_RECENT_CONTACTS_CONTROL_NOTIFY_ENTRY_SELECTED_MSG which will be sent when the user chooses an item from the list.
ContactMatchName(), ContactEnsureField()
Perhaps you're writing a special-purpose application that is supposed to communicate 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 any gadgetry 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 an example of how you could find a dedicated contact in the 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.
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
.
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()
.Code Display 4-3 Finding the "Stuckey's Snack Shack" Contact
TCHAR theName[]= "Stuckey's Snack Shack"; TCHAR gsmNum[MAX_NUMBER_FIELD_DATA_LEN] = "1.800.788.2539" word gsmNumLen; FieldID theField; word dummyNumMatches; RecordID theRecordID; Memhandle theRecord; VMFileHandle CDBHandle;
theRecordID = ContactMatchName(theName, CFT_NAME,1, &theField, &dummnyNumMatches);
if ( theRecordID == LECI_INVALID_CONTACT_ID) { /* If we didn't find the record...*/
theRecord = ContactCreateRecordFromTemplate(); /* ... then we create it */
/* Fill in the name field; here @TelGSMStr is a chunk holding the string
* "Tel(GSM)" */
theField = ContactEnsureField( theRecord, NullOptr, CFT_NAME );
CDBHandle = ContactGetDBHandle();
FoamDBSetFieldData( CDBHandle, theRecord,theField, theName, sizeof(theName)-1 );
/* Fill in the fax field of new record with default GSM number string */
/* Fill in the name field; here @TelGSMStr is a chunk holding the string
* "Tel(GSM)" */
theField = ContactEnsureField( theRecord, @TelGSMStr, CFT_PHONE );
FoamDBSetFieldData( CDBHandle, theRecord, theField, gsmNum, 14 );
ContactReleaseDBHandle();
/* Save the newly created record to the Contact DB */
theRecordIIndex = ContactSaveRecord( theRecord );
theRecord = FoamDBGetVisibleRecord( CDBHandle, theRecordIndex );
}
else { /* If we successfully found the record, then get its handle */
CDBHandle = ContactGetDBHandle();
theRecord = FoamDBGetRecordFromID( CDBHandle, theRecordID);
}
/* Whether we found the record or just now created it, we now have * its handle and can extract the information that we want. */ /* Fill in the name field; here @TelGSMStr is a chunk holding the string * "Tel(GSM)" */ theField = ContactEnsureField( theRecord, @TelGSMStr, CFT_PHONE ); /* Copy the fax number into our buffer */ gsmNumLen = FoamDBGetFieldData( CDBHandle, theRecord, theField, gsmNum, MAX_NUMBER_FIELD_DATA_LEN); gsmNum[gsmNumLen]= `\000`
/* If we need more information about the contact (e.g., street address, * fax number, etc.) this would be a good place to get it. */
FoamDBDiscardRecord( CDBHandle, theRecord ); ContactReleaseHandle(); /* Do something clever with theName and gsmNum */
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.)
LogAddEntry()
If you wish to log incoming or outgoing messages, you will use the
LogAddEntry()
function, provided by the
contlog
library. Make sure that you your
.gp
file contains the line
library contlog
When it comes time to make the call that you want to log, carry out the following steps:
LogEntry
structure and call
LogAddEntry()
. The code shown in Logging an SMS Call
would be appropriate for logging an outgoing message; to log an incoming message, substitute LED_RECEIVED for LED_SENT.
LogAddEntry()
again, passing the same
LogEntry
structure as before, after writing the duration (in seconds) in the
LogEntry
's
LE_duration
field. (The previous invokation of
LogAddEntry()
will have filled in the
LogEntry
's
LE_flags
field with correct values.)Code Display 4-4 Logging an SMS Call
LogEntry MyEntry ; dword duration; TimerDateAndTime tdat; TimerGetDateAndTime(&tdat); duration = TimerGetCount();
strcpy( MyEntry->LE_number, theNumber); MyEntry.LE_contactID = recordID; MyEntry.LE_type = LET_SMS; MyEntry.LE_direction = LED_SENT; MyEntry.LE_duration = 1; MyEntry.LE_dateTime.DAT_year = tdat.TDAT_year; MyEntry.LE_datetime.DAT_month = tdat.TDAT_month; MyEntry.LE_datetime.DAT_day = tdat.TDAT_day; MyEntry.LE_datetime.DAT_hour = tdat.TDAT_hours; MyEntry.LE_datetime.DAT_minute = tdat.TDAT_minutes;
LogAddEntry( &MyEntry );
/* Send the message, and when done...*/
MyEntry.LE_duration = TimerGetCount() - duration;
LogAddEntry( &MyEntry );
When using the Contact Log library to log a contact, if you don't know the phone number, you can pass LEF_WILDCARD_NUMBER to
LogAddEntry()
to specify that this call's number should match any phone number. This is only allowed on devices with version numbers "Responder Build 4...." and higher. See Software Version Number
for information about finding out the software version of the user's device.
FoamDBFieldEnum(), FoamDBGetFieldType(), FoamDBGetFieldName()
In the examples above, we've shown how to get a selected contact's name and GSM phone number. It is possible to get more information about a contact given its
RecordID
number.
In the examples shown in Handling the ContactList's "Selected" Message , Handling the RecentContacts "Selected" Message , and Finding the "Stuckey's Snack Shack" Contact there is a comment noting a good place to get more information about a contact. If, for some reason, you need to find out information about a Contact in a context other than shown in one of those examples,
RecordID
number. Presumedly, you've stored away this number after using code like that shown in one of the examples shown above.
ContactList
object for the
RecordID
of its selected record, use the
MSG_CONTACT_LIST_GET_ID_OF_SELECTED_RECORD
message. This message takes no arguments, and returns a
RecordID
.
ContactGetDBHandle()
, storing the returned handle.
FoamDBGetRecordFromID()
. This returns the record's handle.
FoamDBDiscardRecord()
to free the handle.
ContactReleaseDBHandle()
to signal you're done with the database. You shouldn't keep the handle around for long; doing so prevents the file from being closed.
To find out any other sort of information about the contact, you'll need to access one of the fields of the record. Fields within a Foam DB record (the Contact DB is a Foam DB) are identified by a
FieldID
number.
The
FoamDBFieldEnum()
function provides a way to scan all the fields of a record. The following code snippet shows how you might use
FoamDBFieldEnum()
to search for all of a contact's voice phone numbers.
FoamDBFieldEnum()
calls a callback routine for each of the record's fields.
FoamDBFieldEnum()
takes as arguments a record handle, a pointer to a data buffer (this pointer will be passed to the callback routine; it gives you a way to pass data to the callback; in our example, we pass the record handle in the buffer), and a pointer to a callback function. The callback function is passed a
FieldHeader
structure and a pointer to the data buffer that was passed to
FoamDBFieldEnum()
. From the FieldHeader, it can get the
FieldID
from the
FieldHeader
's
FH_id
field. To get information about each field, use the
FoamDBGetFieldType()
,
FoamDBGetFieldName()
, and/or
FoamDBGetFieldData()
routines. Each of these routines takes the contact database handle, a record handle, a
FieldID
, and a pointer to a buffer to fill with a return value.
Code Display 4-5 Checking All Fields of a Contact
In this example, we check all fields of a contact, and build up an array with the names and data for those fields that correspond to voice phone numbers.
In this example, all we know at the start is the record's RecordID number.
void BuildNumberList( RecordID recordID ) {
/* Scan all fields of the Contact record */
/* For each one that corresponds to a voice phone number, store
* the field's name (e.g., "Phone") and data (e.g., "555-1212") in
* the global Data array. */
VMFileHandle CDBHandle;
MemHandle curRecord;
CDBHandle = ContactGetDBHandle(); curRecord = FoamDBGetRecordFromID( CDBHandle, recordID ); NumberOfNumbers = 0 /* Global variable: number of elements in Data array*/ FoamDBFieldEnum( curRecord, &curRecord, &BuildNumberListCallback ); FoamDBDiscardRecord( CDBhandle, curRecord) ; /* Done with the record */ ContactReleaseDBHandle(); /* Done with the Contact DB for now */ }
Boolean _pascal BuildNumberListCallback( FieldHeader *field, void *enumData ) {
VMFileHandle CDBHandle;
byte fieldType;
MemHandle curRecord = *((MemHandle *) enumData );
CDBandle = ContactGetDBHandle();
FoamDBGetFieldType( CDBHandle, curRecord, field->FH_id, &fieldType);
if (fieldType == CFT_PHONE ) { /* For each voice phone number */
/* To look for something other than a phone
* number, we would use a different
* ContdbFieldType value. */
/* Grab the field name */
FoamDBGetFieldName( CDBHandle, curRecord, field->FH_id,
Data[NumberOfNumbers].fName, MAX_FIELD_LABEL_LEN);
/* Grab the field data */
/* If the data has zero length, func will
* return zero. */
if (FoamDBGetFieldData( CDBHandle, curRecord, field->FH_id,
Data[NumberOfNumbers].fData, MAX_FIELD_NUMBER_DATA_LEN)) {
/* If the data was not of zero length
* (wasn't just a blank field), then
* up our NumberOfNumbers. */
NumberOfNumbers++;
}
}
ContactReleaseDBHandle(); /* We're done with the database */
/* if we return non-zero, we'll stop Enum'ing
* through the fields. Since we only have room
* for 10 fields in our array... */
return( NumberOfNumbers > 10) ;
}
As shown above, to get the field data and field name associate with a field, use the
FoamDBGetFieldData()
and
FoamDBFGetFieldName()
functions. Many users will leave blank fields in their contact records; to test for a blank field, check
FoamDBGetFieldData()
's return value; if it's zero, then the user has not filled in that field of the contact information.
ContactGetUserDataName(), ContactGetUserDataID()
Recent versions of the ContDB library provide routines which access the user's own contact information. These routines are only available on devices with version numbers "Responder Build 4...." and higher. See Software Version Number for information about finding out the software version of the user's device.
The ContDB library provides two routines useful for accessing the contact information the user has specified for themself. The
ContactGetUserDataName()
routine returns the user's name string.
ContactGetUserDataID()
returns the record ID number of a record which contains the user's contact information.