The Sample FEP Kit provides a Sample FEP shared library to help you get started with creating your own FEP. The Sample FEP Kit also includes a test application that will help you debug and test your FEP.
This chapter discusses the following topics:
- The Sample FEP
- Text Services Manager Server
- Event Flow in a FEP
- FEP Type and Creator ID
- Modifying the Sample FEP
- Debugging and Testing the FEP
The Sample FEP
The Sample FEP shipped with this document is a simple acronym converter: it takes an acronym as input and converts it to the spelled-out English version. PalmSource provides this sample code as a starting place for creating your own FEP. The following sections describe the basic structure of the Sample FEP project.
Sample FEP File List
The files that you will use with the Sample FEP project are described in the following table. All paths below (except the first one) are relative to the sample FEP directory: \PDK\samples\SampleFep
Table 3.1 Sample FEP File List
Header file that contains most of the function declarations required to implement the FEP API. This header is available in the PDK \headers directory. For those developers without access to the PDK, see Appendix A for the contents of this header file. |
|
Sample dictionary for use with the Sample FEP. It contains a list of acronyms and their spelled-out English equivalents. Warning: The Sample FEP will not run without this dictionary installed. |
|
Public header file for the FEP. This file contains the custom defines and function declarations that are specific to a particular FEP. For example, this is where the FEP name is defined. |
|
An XML resource description file that contains the sample FEP icon name and bitmap references. Bitmaps are stored in the |
|
Header file that defines a structure typedef that is used to pass FEP state (global and session-specific) to all functions. |
|
Header file that contains the private FEP declarations which are used by multiple source files. For example, the FEP internal state structure uses some of these declarations. |
|
Source file for functions that are not top-level. These include functions called by top-level functions in |
|
The other files in this directory are Palm OS Developer Suite project files. |
The TestSampleFep Application
The TestSampleFep application is also included in the Sample FEP Kit in SampleFep\Test. This application lets you switch between the default FEP and your new FEP for testing purposes. The application contains a text field and buttons that represent the input area buttons that you normally see on a handheld that uses a FEP: "Convert," "Confirm," "On/Off", and "Activate/Deactivate".
The TestSampleFep application requires that the FEP you are testing have the creator 'sfep'
.
The section, "Debugging and Testing the FEP," describes this application in more detail.
FEP Code Structure
The FEP code is structured into three layers:
-
SampleFep.cpp
implements all of the top-level FEP functions described in Chapter 5, "Text Services FEP Reference." - Below this level are
SampleFepEvents.cpp
andSampleFepOptions.cpp
, which implement the FEP user interface. - The user interface depends on the FEP engine, which is implemented by functions in the
SampleFepEngine.cpp
file.
Text Services Manager Server
The Text Services Manager has a server component that globally maintains the current FEP and current FEP mode across all processes and threads.
There can be only one current FEP in the system and one global FEP mode, even though there may be more than one user interface context that is using a FEP. In such a case, each would be using the same FEP, but the server maintains separate state objects for each client so it's always clear which is the active client.
There can be multiple clients running in different threads, so a FEP client must get its current mode from the server and not attempt to maintain its own mode. This is because the mode could be changed by a client in another thread. Use the function TsmGetFepMode()
to get the FEP mode and TsmSetFepMode()
to set the FEP mode. These functions interact with the server to get and set the mode.
When a FEP session starts or becomes the active session after having been inactive, the server calls the TsmLibFepReset()
function in the FEP library. This gives the FEP a chance to start with a clean slate; any internal globals it may have been maintaining for another session should get cleaned up here. It also alerts the FEP that the global FEP mode may have changed and it should check the mode and set it if necessary.
If you want to use globals in your FEP, ensure that they are thread safe. You can put them in the FEP instance record (TsmFepStatusType
), or always reset them when the FEP receives the TsmLibFepReset()
call.
Event Flow in a FEP
This section describes how Palm OS interacts with a FEP, including how events get passed to a FEP.
Initialization Sequence
The following sequence of calls is used to load the correct FEP when a new user interface context is created:
- The Text Services Manager is initialized. It calls
TsmGetSystemFepCreator()
to determine the creator code of the system FEP. It then callsTsmLibGetFepInfo()
for this FEP to find out whether or not the FEP should be loaded. If the FEP version number is invalid, the FEP will not be loaded. For more information about the FEP version number, read about theTsmFepInfoType
data structure. - If the FEP should be loaded, then the Text Manager calls
TsmLibFepOpen()
. If that call succeeds, then the FEP is set as the current FEP.
The FEP should maintain some sort of reference counting in order to be aware if it is being called to be loaded more than once. In such a case all it needs to do is set up its globals and does not need to allocate a new set, since only once FEP session will be active at any time.
You can see how the Sample FEP uses the gFepOpenCount
global to maintain reference counting.
System Events
The following event processing takes place above the level of field editing of text:
- Whenever
SysHandleEvent()
is called, it calls the Text Manager. If the event is a Text Services Manager virtualkeyDownEvent
(for example, one of the four Text Services Manager input area buttons, or a mode change virtual character), then the event gets re-posted as atsmFepButtonEvent
ortsmFepModeEvent
. Otherwise,TsmLibFepMapEvent()
is called. This lets the FEP remap certain events when appropriate. For example, the "space"keyDownEvent
gets remapped to a Text Services Manager button "convert" event if there is an active inline session which contains text. - Whenever
FrmHandleEvent()
is called with akeyDownEvent
,tsmFepButtonEvent
, ortsmFepModeEvent
, and there is no active field, then it callsTsmLibFepHandleEvent()
. This lets the user turn the FEP on and off, for example, even when the current form has no text field.
Field-Level Events
The following events occur when a user is editing text in a field:
Whenever FldHandleEvent()
is called, it calls TsmLibFepHandleEvent()
. If the FEP handles the event, then it returns true
, and FldHandleEvent()
skips its event processing. Based on the results returned in the status and action structures passed to TsmLibFepHandleEvent()
, the field code will update text, redraw the field, and update the selection range or insertion point as appropriate.
For example, suppose the field gets a keyDownEvent
. The FEP determines whether it is active ("on") or inactive ("off"). If the FEP handles the event, TsmLibFepHandleEvent()
returns information that tells the field code what to do (for example, "move the insertion point one character to the right").
When FldHandleEvent()
has finished processing the structures returned by TsmLibFepHandleEvent()
, it calls TsmLibFepCommitAction()
). This lets the FEP do things like unlock/deallocate the buffers it uses to pass back inline text to the field code.
Whenever the field loses the focus (for example, the user tapped elsewhere on the screen or the form was closed), TsmLibFepTerminate()
is called. This lets the FEP reset its state; it can also return information to the field about how things need to be updated (for example, if partially entered Hiragana characters need to be deleted).
At various times the field code will call TsmLibFepReset()
to put the FEP into a known, safe state. The FEP should treat this like a call to TsmLibFepTerminate()
, but without returning any action information.
Notes About Event Handling
When the user has written some text and confirmed it, the FEP has the option of posting a tsmConfirmEvent
event. Eventually, this event reaches the top of the event queue. If the form is gone and another form is current, the new form receives the event, but that form was not the form that generated the event. To avoid this problem, the application must verify that the form ID contained in the event matches the current form ID.
FEP Type and Creator ID
The FEP creator ID must be unique, and should be assigned like any other creator ID by registering at http://dev.palmos.com/creatorid/. The FEP's type must be sysFileTFep
('libt'
).
The name can be anything you like.
Modifying the Sample FEP
This section talks about how to handle various issues involved with writing FEPs.
- Changing the Locale
- Handling Text Services Manager Button Events
- Handling Other Events
- Handling the Mode Indicator
- Handling Auto-Yomi Events (Japanese only)
- Auto-Extending the Maximum Size of a Field
- Adding User Dictionary Functions
Changing the Locale
The Sample FEP uses a Latin character set. If you want to design a FEP for a different language, you must have access to a version of Palm OS that supports that language and its character set. You must select an appropriate prefix file for your target locale.
Handling Text Services Manager Button Events
As described in Chapter 2, "The FEP User Interface," a typical FEP receives input from three or four special Text Services Manager buttons in the input area. Tapping one of these buttons generates a keyDownEvent
with one of the following characters: vchrTsm1
, vchrTsm2
, vchrTsm3
, or vchrTsm4
. When SysHandleEvent()
passes these events to TsmLibFepMapEvent()
, a corresponding Text Services Manager button event gets posted. This event eventually gets passed to the FEP through the form or field code.
One of the hardest user interface events to handle properly in a FEP is when the user selects text and then taps on the "Convert" button. For instance, if the FEP can't process all of the text at once, the FEP needs to be able to tell the caller that it took only part of the text.
Look at the HandleButtonEvent
function in SampleFepEvents.cpp
for an example, because this shifting of text can be difficult to get right. FEP buffer size is limited, and it can be difficult to communicate back to the field code when this limitation becomes an issue.
Handling Other Events
Some regular keyDownEvents
(for example, space and linefeed) are given special meaning by the FEP. As with the FEP buttons, these get converted into Text Services Manager button events by TsmLibFepMapEvent()
when appropriate (for example, if there is no current conversion session, then the space and linefeed characters are given no special meaning by the FEP).
Handling the Mode Indicator
The FEP is given a chance to draw its own mode indicator in the space normally occupied by the handwriting recognition system's shift mode indicator. If the FEP is off, then the regular mode indicator is in effect.
Handling Auto-Yomi Events (Japanese only)
In the Japanese language, some words (especially names) may have pronunciations that differ from the usual pronunciation for that sequence of characters. The characters that represent the pronunciation are called yomi. The standard PalmSource Japanese Address Book contains corresponding yomi text fields for the Last Name, First Name, and Company Name fields.
Whenever the FEP dumps converted text, either as a result of a call to TsmLibFepHandleEvent()
or TsmLibFepTerminate()
, it also posts an "auto-yomi" event through tsmConfirmEvent
. This event contains pointers to the yomi text and the resulting converted text. This event is used by the Japanese Address Book to automatically fill in the pronunciation field when the user is editing the Last Name, First Name, and Company Name fields.
In most cases, the auto-yomi event causes the yomi field to be filled in with the same characters used in the regular text field. The user can then change the yomi text manually if the pronunciation should be different.
If a specific name always has the same pronunciation, you can add an entry to the FEP User Dictionary through the FEP Panel. Then, when the user enters that name, the corresponding yomi text will always appear in the yomi text field.
Auto-Extending the Maximum Size of a Field
The Category Manager and the Keyboard application use features set up by the Text Services Manager with information provided by the FEP (by TsmLibGetFepInfo()
). These features mainly involve auto-extending the maximum size (in bytes) of a field so that the user can temporarily enter more text (for example, in a transitional character set such as Japanese Hiragana). This expanded text will later get converted into fewer bytes of the final character set (for example, Japanese Kanji).
Adding User Dictionary Functions
Data found in a front-end processor's user dictionary is typically used by the FEP engine during conversion and is viewed or edited in a FEP Panel, whose user interface must be supplied by the FEP. The sample FEP code shows an example of how to do this.
The format of the user dictionary is proprietary to each vendor; the Palm OS does not have a standard format. Currently there is no public API to get entries from the user dictionary or to add entries to the user dictionary.
When the user selects the "Add Word" command from the Edit menu, the sysAppLaunchCmdFepPanelAddWord
command launches the FEP Panel that has the same creator ID as the FEP and the type 'panl'
.
The system passes the FepPanelAddWordParamsType
structure to the FEP Panel with the sysAppLaunchCmdFepPanelAddWord
launch code. This structure contains information about the new word to be added to the user dictionary.
Debugging and Testing the FEP
The TestSampleFep application makes it easy to test your FEP in the Palm OS Simulator. It lets you activate and deactivate your FEP. It also provides a text field so that you can enter and convert text.
The test application requires that your FEP have the creator 'sfep'
.
- Run Palm OS Simulator using a compatible ROM.
- Install the FEP's conversion dictionary, if it is not embedded in the PRC file. (For the Sample FEP, install
SampleFep-Med.pdb
.) - Debug the application.
- In Palm OS Simulator, tap the Activate button to make your FEP the current FEP. Until you deactivate the FEP or reset the handheld, all FEP calls will be handled by your FEP. The button should now say, "Deactivate."
- To deactivate your FEP, launch the TestSampleFep application. Tap the Deactivate button to make the system FEP the current FEP. You can now safely delete or update your sample FEP.