You can display a list of places on the map as the user enters the name, using CartoType's incremental searching support.
Create a full-text index
The first step is to create your CTM1 (map data) file using the makemap command-line option /textindex=full. That way, all phrases within text attributes are indexed, as well as the whole string.
Searching as the user types
Here's what you need to do in your find dialog.
As the user types, every time the text changes, and if the text is not empty, you need to find a list of places starting with that text. Here's an example of how to do that using the C++ API. The same functionality is available in the other APIs (.NET, Android and iOS).
Set up the parameters to the Find function
CartoType::TFindParam find_param; find_param.iMaxObjectCount = 32; CString attrib; attrib.Set("$,name:*,alt_name,int_name,addr:housename,addr::housenumber"); find_param.iAttributes = &attrib; find_param.iStringMatchMethod = CartoType::TStringMatchMethod(CartoType::EStringMatchPrefixFlag | CartoType::EStringMatchFoldAccentsFlag | CartoType::EStringMatchFoldCaseFlag | CartoType::EStringMatchIgnoreNonAlphanumericsFlag | CartoType::EStringMatchFastFlag);
In this example a relatively free match is used, ignoring accents, case, and non-alphanumerics (spaces, punctuation, etc.). You can make the matching rules more restrictive if you like, but it's important to set the 'prefix' and 'fast' flags (CartoType::EStringMatchPrefixFlag and CartoType::EStringMatchFastFlag). The first gets all strings for which the search text is a prefix or a full match, and the second makes the search work fast enough for good response time while the user types, by getting only the first 'iMaxObjectCount' matches rather than getting a large number of matches and selecting the most relevant.
This example uses a list of attribute names ("$,name:*,alt_name,int_name,addr:housename,addr::housenumber") to confine the search to those attributes most useful to a place-name search: the main name (given as '$'), all attributes starting with 'name:', the alternative and internal names, and the house name and number.
Call the Find function
Set the find text.
CString text; //+ to do: copy what the user has typed into 'text' find_param.iText = &text;
where 'text' is the text the user has typed.
Now call the Find function.
CartoType::CPointerArray<CartoType::CBaseMapObject> object_array; framework.Find(object_array,find_param);
where 'framework' is the CartoType::Framework object owned by your application.
You can now clear your list box and populate it using the objects in object_array: there will be up to 32 of them (or whatever number you choose) as set in find_param.iMaxObjectCount.
Choosing the text to put in the list box
Often, the text that's actually matched by the Find function isn't the main name of the map object, but some other attribute like an alternative name, house number, or a building name. You can find exactly what was matched using the function CBaseMapObject::GetMatch, like this, for each object:
CartoType::CBaseMapObject* cur_object = object_array[i]; CartoType::CBaseMapObject::CMatch match; CartoType::TResult error = cur_object->GetMatch(match,text,find_param.iStringMatchMethod,&attrib);
The 'match' object now contains the key and value of the matched attribute if any, and the starting and ending index of the matched text.
You might choose to create a string containing some or all of the attributes of the map object and making the matched text bold.