This chapter describes user interface elements that display text or that assist in the display of text. It covers:
Text Fields
Labels
Form Titles
Fonts
See the book Exploring Palm OS: Text and Localization for information about manipulating the text strings that are stored in these elements.
Text Fields
A text field displays one or more lines of text. Figure 5.1 shows a form whose main element is an underlined, left-justified, multi-line field containing data.

The text field supports these features:
- Proportional bitmapped fonts (only one font per field)
- Drag-selection
- Scrolling for multiline fields
- Cut, copy, and paste
- Left and right text justification
- Tab stops
- Insertion point positioning with pen (the insertion point is positioned by touching the pen between characters)
- Double-tap to select a word
The text field does not support overstrike input mode; horizontal scrolling; numeric formatting; or special keys for page up, page down, left word, right word, home, end, left margin, or right margin.
Events in fields are handled by FldHandleEvent()
. Table 5.1 provides an overview of how F
ldHandleEvent() deals with the different events
Table 5.1 Event flow for fields
|
||
|
Sets the insertion point position to the position of the pen and tracks the pen without blocking until it is released. Responds to the |
|
Double-tapping in a field selects the word at that location, and triple-tapping selects the line. |
||
|
Nothing happens; a field remains selected until another field is selected or the form that contains the field is closed. |
|
|
Character added to field's text string. If there is an active FEP, keys are passed to it first so that it has a chance to convert characters. |
|
Moves insertion point down a line; the insertion point doesn't move beyond the last line that contains text. |
||
Moves insertion point one character position to the left. When the left margin is reached, move to the end of the previous line. |
||
Moves insertion point one character position to the right. When the right margin is reached, move to the start of the next line. |
||
Depending on the attributes you set when you create the field resource, a field may be either editable or noneditable and either single-line or multi-line. The following sections describe each type of field.
Editable Text Fields
An editable text field has an underline to indicate where the user can tap to enter text. If the field has the focus, it displays a blinking insertion point. If you create an editable text field, you should include the following elements in your form:
- An Edit menu so that the user can cut, copy, and paste.
- A shift indicator to indicate the current input mode on displays with static input areas. See Exploring Palm OS: Input Services for more information. Be sure to set the text field's auto-shift attribute so that the first word of a sentence is automatically capitalized.
The editable attribute affects how you retrieve or change the text and how the memory associated with the text field is freed. A text field stores two types of information about the text string that it displays:
The text handle is used for editable text strings because the field must resize the string while the user edits it and the string may move in memory as a result of the resizing.
Use FldGetTextHandle()
to retrieve the text of an editable text field. If you want to change the text, use any of the following functions:
-
FldInsert()
andFldDelete()
for small changes. -
FldSetTextHandle()
for larger changes.
Before you use FldSetTextHandle()
to change the text, you must remove the association between the handle and the text field. If you change the text while it is being used by a field, the field's internal structures specifying the text length, allocated size, and word wrapping information can become out of sync. To avoid this problem, remove the text handle from the field, change the text, and then set the field's text handle again. See Listing 5.1.
Listing 5.1 Editing text with FldSetTextHandle()
static void SetFieldText(FieldType *fieldP, char *string) { MemHandle textH; char *textP; // Get handle to field's text and remove associate between // field and text. textH = FldGetTextHandle(fieldP); FldSetTextHandle(fieldP, NULL); // Lock the handle and change the text. This code assumes // that textP is large enough to handle the string. textP = (char *)MemHandleLock(textH); strcpy(textP, string); // Reassociate the text with the field. MemHandleUnlock(textH); FldSetTextHandle(fieldP, textH); }
Editable text fields also support an edit in-place feature. With edit in-place, you can point the text field at a string within a non-schema database record or a column within a schema database row. As the user edits the text field, the database record is automatically updated. Use FldSetText()
for non-schema database records and FldSetTextColumn()
for schema database rows.
NOTE:
FldSetTextColumn()
locks the entire database row, not just the column it displays. If you need to make a change to a value in another column, release the lock using FldReleaseStorage()
and then use FldReturnStorage()
to reassociate the field with the data it displays.
When the form is closed, all memory associated with all of the user interface elements on the form, including the text field and its text string, is freed. However, if the text field is pointing to a string in a database record, the string is not freed. If a text field is pointing to a string in the dynamic heap and you want to preserve the string after the form is closed, remove the association between the text handle and the text field before the field is freed. Do so by calling FldSetTextHandle()
with NULL
for the text handle in response to the frmCloseEvent
.
Noneditable Text Fields
Noneditable text fields are not underlined and do not display a blinking insertion point. They are generally used to display complicated labels or labels that might change at run time.
As explained in the previous section, the text field contains both a handle and a pointer to the text string. Noneditable text fields often just use the pointer to the string and leave the handle as NULL
because the memory resizing issues do not apply.
Use FldGetTextPtr()
to retrieve the text of a non-editable text field and FldSetTextPtr()
to set it. When you use FldSetTextPtr()
to change the text, there is no association between the text handle and the text string pointer stored in the field. Because of this, the field does not free the string. If the string is in the dynamic heap, you must free it yourself. See Listing 5.2.
Listing 5.2 Freeing the string set by FldSetTextPtr()
case frmCloseEvent: strP = FldGetTextPtr(fldP); // Set the field text to NULL before freeing the string // to ensure that it is not being displayed when you // free it. FldSetTextPtr(fldP, NULL); MemPtrFree(strP);
Single-line Text Fields
Single-line text fields do not wrap when the text exceeds the width of the field. Instead, the field displays as many characters as possible. Use single-line text fields only for fields likely to contain very small amounts of information, such as a monetary figure.
Multi-line Text Fields
Multi-line text fields display more than one line of text. Text fields handle all word wrapping for you.
You can also set a multi-line text field to be dynamically sized. If you do this, the number of lines of text that the field displays can grow as the user adds more text to the field. Depending on the form layout, it might be advantageous to only display a single line of text initially, but to set the dynamic size attribute instead of the single line attribute. If you do, the field can grow to display extra lines when the text exceeds the bounds of the field (see Figure 5.2). Dynamically sized fields send fldHeightChangedEvent
when they need to be resized. Respond to this event to resize the field and, if necessary, reposition the rest of the elements on the form.
Figure 5.2 Dynamically sized field

Note that the fldHeightChangedEvent
is completely independent of the winResizedEvent
. The winResizedEvent
is sent when the entire form is being resized. fldHeightChangedEvent
is sent when only the dynamically sized field is being resized.
If the text field contains a large amount of text, attach a scroll bar to it. Palm OS® displays the scroll bar only when the text field contains more text than it displays, and Palm OS scrolls the field for you. Your application is responsible for updating the display of the scroll bar, however. See "Scroll Bars."
Labels
Most resource editors allow you to create a label resource. Labels are ideal for small, static amounts of text that you need to display to identify other elements on the form.
You generally don't interact with a label as a programmatic entity. However, if you need to do so, use the following functions:
-
FrmGetLabel()
retrieves the label. -
FrmGetLabelFont()
retrieves the bitmapped font used for a label. -
FrmSetLabelFont()
sets the bitmapped font used for a label. -
FrmCopyLabel()
changes the label. You may only pass a string that is the same size or shorter than the string initially allocated in the resource. If the new string is shorter, hide the label usingFrmHideObject()
before callingFrmCopyLabel()
and then display it afterwards usingFrmShowObject()
.
If you need to change the label frequently, you may find it more convenient to use a noneditable text field rather than a label. See "Noneditable Text Fields."
Form Titles
The title displayed in the form is not a separate resource. It is an attribute that you specify when you create the form. If you need to change the form title at runtime, use the following functions:
-
FrmGetTitle()
retrieves the form's title. -
FrmSetTitle()
sets the title of the form. This function does not copy the string that you pass to it, so you must ensure that it exists for as long as the form is displayed. -
FrmCopyTitle()
copies the string into the form's title. If you use this function, you must set the initial form title in the resource file to the largest string you might display in the title. If the new string is shorter, hide the label usingFrmHideObject()
before callingFrmCopyTitle()
and then display it afterwards usingFrmShowObject()
.
Fonts
Palm OS supports both bitmapped and scalable TrueType fonts. A bitmapped font is one that provides a separate bitmap for each glyph in each size and style. The Palm OS UI library, including all form controls, use bitmapped fonts for labels and other text.
A scalable font defines the shape of each glyph but not the size. Given a typeface definition, a scalable-font system can produce glyphs at any size. Scalable fonts are used only through the graphics context GcDrawTextAt()
call. See Chapter 8, "Drawing," for more information on drawing with the graphics context.
Scalable font support begins in Palm OS Cobalt; however, it is optional. A given Palm OS Cobalt device might not include the scalable font engine in its ROM. If so, the functions used to access scalable fonts still work, but they return the bitmapped fonts.
Each font is associated with a particular character encoding. The font contains glyphs that define how to draw each character in the encoding. A bitmapped font provides a separate bitmap for each glyph in each size and style. A scalable font provides a font family that specifies how the glyphs look. Each font family supports one or more font styles or faces such as regular or bold. The font engine determines how to scale these fonts to different heights.
This section covers the following information about both bitmapped and scalable fonts:
- About Font Resources
- Built-in Fonts
- Setting the Font Programmatically
- Selecting Which Font to Use
- Obtaining Font Dimensions
- Creating and Using Custom Bitmapped Fonts
- Creating and Using Custom Scalable Fonts
- How Palm OS Displays Bitmapped Fonts
About Font Resources
For bitmapped fonts, Palm OS supports two types of resources: a single-density font resource 'NFNT'
and an extended font resource ('nfnt'
) that supports multiple display densities. Both of these resources are the same 68K-based resources defined in all versions of Palm OS. ARM-based versions of these resources are not supported in Palm OS Cobalt. See "Bitmapped Font Resources" for the exact layout of these resources.
The built-in bitmapped fonts provided with the system use extended font resources, meaning that they contain a separate set of glyphs for each screen density. Thus, the single-density versions of the glyphs are used on standard 160 X 160 displays, the double-density versions of the glyphs are used for 320 X 320 displays, and so on.
You access any bitmapped font resource, whether 'NFNT'
or 'nfnt'
, using a FontID
constant. This constant is essentially an index into the system's list of bitmapped fonts.
Scalable font resources are 'fttf'
resources. This type of resource creates a wrapper around a TrueType font specification. Because TrueType fonts are scalable by their nature, they already support multiple display densities.
Scalable fonts are accessed by creating a font handle using an HTML Cascading Style Sheet (CSS) style font specification string or a font family name. See the description of the GcCreateFont()
function for an example of a CSS-style font specification string.
Built-in Fonts
There are several bitmapped and scalable fonts built into Palm OS.
The Font.h
file defines constants that can be used to access the built-in bitmapped fonts programmatically. These constants are defined on all versions of Palm OS no matter what language or character code; however, they may point to different fonts. For example, stdFont
on a Japanese system may be quite different from stdFont
on a Latin system.
Table 5.2 lists and describes the built-in bitmapped fonts that may be used to display text.
Table 5.2 Built-in text bitmapped fonts
Figure 5.3 shows what each of the fonts in Table 5.2 looks like.
Figure 5.3 Built-in text fonts

Palm OS also defines the bitmapped fonts listed in Table 5.3. These fonts do not contain most letters of the alphabet. They are used only for special purposes.
Table 5.3 Built-in symbol bitmapped fonts
The system may also contain system-defined scalable fonts, which are accessed by passing a standard name to the function GcCreateFont()
. Table 5.4 lists the strings that you can use. Note that these are not constants; they are strings that can be included as part of the CSS-style font specification you pass to GcCreateFont()
. (CSS is an HTML term that stands for Cascading Style Sheet.)
Table 5.4 Built-in scalable fonts
Figure 5.4 shows what each of the fonts in Table 5.4 looks like.
Figure 5.4 System-defined scalable text fonts

Note that if a device supports scalable fonts, these strings return TrueType fonts. They do not return the same fonts as the constants listed in Table 5.2. However, if a Palm OS Cobalt device does not support scalable fonts, these strings do return the same bitmapped fonts as the font constants listed in Table 5.2.
The fonts listed in Table 5.4 are all variations on a single font family. There may be other font families installed in the device. To obtain a full list, use code like that shown in Listing 5.3.
Listing 5.3 Iterating through all scalable fonts
int32_t numFamily, curFamily; int32_t numStyle, curStyle; FontFamily family; FontStyle style; numFamily = GcCountFontFamilies(); for (curFamily = 0; curFamily < numFamily; curFamily++) { GcGetFontFammily(curFamily, &family); numStyle = GcCountFontStyles(family); for (curStyle = 0; curStyle < numStyle; curStyle++) { GcGetFontStyle(family, curStyle, &style); } }
Setting the Font Programmatically
To set the font that a user interface element uses for its label or for its textual contents, you use different functions depending on the element. Table 5.5 shows which functions set fonts for which user interface elements. Note that user interface elements only support bitmapped fonts.
If you are drawing text directly to the screen, perform the following steps:
- Call one of the following functions to create a handle to a specific font:
-
GcCreateFont()
creates a font out of one of the strings in Table 5.4 or out of a CSS-style font specification. -
GcCreateFontFromFamily()
creates a font using a specified family. You can then set the size and style later. -
GcCreateFontFromID()
creates a font handle for a bitmapped font. Use this function to have your text more closely match the built-in system fonts.
-
IMPORTANT: It's best to create a font handle before you receive the
frmUpdateEvent
. Creating a font handle can be slow.
- Obtain a handle to the current graphics context using
GcGetCurrentContext()
. - Use the
GcSetFont()
function to set the draw state's font to the handle of the font you created. - Draw the text using
GcDrawTextAt()
. - When you are finished drawing release the graphics context to free memory associated with it.
- When you are finished with the font, call
GcReleaseFont()
to free the memory associated with the font handle.
Listing 5.4 shows drawing a text string in the stdFont
.
Listing 5.4 Setting a font for custom-drawn text
// Make this call outside of the event loop, probably // in your AppStart() function. GcHandle gcStdFontH = GcCreateFontFromID(stdFont); // In the EventLoop, do the following: GcContext gcH; char *string = "Hi, Mom!" case frmUpdateEvent: gcH = GcGetCurrentContext(); if (gcH) { GcSetCoordinateSystem(gcH, kCoordinatesNative); GcSetFont(gcH, gcStdFontH); GcDrawTextAt(gcH, 160, 100, string, strlen(string)); GcReleaseContext(gcH); } break; // Release the font when you are done with it. Possibly, in // the AppStop() function. GcReleaseFont(gcStdFontH);
Selecting Which Font to Use
The default fonts used to display normal text and bold text vary based on the handheld's character encoding. Devices with the Palm OS Latin encoding typically use stdFont
and boldFont
, while Japanese devices use largeFont
and largeBoldFont
as the default. When your application starts up for the first time, it should respect the system defaults. Use the FntGetDefaultFontID()
function to determine what the default fonts are (see Listing 5.5).
Listing 5.5 Determining the default system fonts
FontID textFont = FntGetDefaultFontID(defaultSystemFont); FontID labelFont = FntGetDefaultFontID(defaultBoldFont);
In general, where users can enter text, you should allow them to select the font through the Select Font dialog (see Figure 5.5).

The FontSelect()
function displays the Select Font dialog. This function takes as an argument a FontID
, which specifies the value that is initially selected in the dialog. It returns the FontID
that the user selected.
newFontID = FontSelect(textFont);
Because the default fonts vary based on the character encoding, the font size choices displayed in the Font Select dialog also vary based on character encoding. For this reason, you must call FntGetDefaultFontID()
to obtain the default system font and pass the returned value to FontSelect()
when you call it for the first time. On subsequent calls to FontSelect()
, you can pass the user's current font choice.
If you are displaying text in a scalable font and want to respect the system default font, you can use the scalable font counterpart to the default system font. See Listing 5.6.
Listing 5.6 Setting a default scalable font
GcFontHandle gcLabelFontH; FontID labelFont = FntGetDefaultFontID(defaultBoldFont); switch (labelFont) { case stdFont: gcLabelFontH = GcCreateFont("palmos-plain"); break; case boldFont: gcLabelFontH = GcCreateFont("palmos-bold"); break; case largeFont: gcLabelFontH = GcCreateFont("palmos-large-plain"); break; case largeBoldFont: gcLabelFontH = GcCreateFont("palmos-large-bold"); break; default: gcLabelFontH = GcCreateFont("palmos-plain"); break; }
Obtaining Font Dimensions
Use functions in the Font Manager to obtain information about a bitmapped font and how it is drawn to the screen. Figure 5.6 shows graphically the characteristics of a font. Table 5.6 describes the types of information that can be retrieved with the Font Manager.
Figure 5.6 Font characteristics

Table 5.6 Obtaining bitmapped font information
NOTE: All dimensions are given in terms of the active coordinate system. Note also that because Palm OS does not support kerning of bitmapped fonts,
FntAverageCharWidth()
actually returns the maximum width of any character in the font.
The functions listed in Table 5.6 all work on the current font, that is, the font listed in the Window Manager draw state. To change the current font, use FntSetFont()
. For example, to determine the line height of the font used for text in a field, do the following:
Listing 5.7 Obtaining characteristics of a field font
FieldType *fieldP; FontID oldFont; int16_t lineHeight; oldFont = FntSetFont(FldGetFont(fieldP)); lineHeight = FntLineHeight(); FntSetFont(oldFont);
With a scalable font, all of the information about the font's dimensions is dependent on the current size you've set for the font. Table 5.7 shows the functions that retrieve information about a scalable font.
Table 5.7 Obtaining scalable font information
|
|
|
|
|
|
Creating and Using Custom Bitmapped Fonts
You can create your own bitmapped font ('NFNT'
) or extended font ('nfnt'
) resource and use it only within your application.
Both the font and extended font resources are only large enough to support a font for the Palm Latin character encoding (256 characters). Defining a custom font for larger character sets is not supported.
Once you have defined a custom font in a resource file, you must assign it a font ID before you can use the font in your application. The font ID is different from the font's resource ID. It's a number between 0 and 255. The font ID you use must be greater than or equal to fntAppFontCustomBase
. All IDs less than that are reserved for system use. The function FntDefineFont()
assigns a font ID to a font resource. The font resource must be locked for the entire time that the font is in use. It's a good idea to load the font resource, lock it, and assign a font ID in your application's AppStart()
function. Unlock and release the font resource in the AppStop()
function.
Listing 5.8 shows code that loads a font resource, assigns a font ID to that resource, and then draws characters to the screen using the new font.
Listing 5.8 Loading and using a custom font
#define customFontID ((FontID) fntAppFontCustomBase) MemHandle customFontH; FontType *customFontP; Err AppStart(void) { ... // Load the font resource and assign it a font ID. customFontH = DmGetResource(globalResDBPtr, fontRscType, MyCoolFontRscID); customFontP = (FontType *)MemHandleLock(customFontH); FntDefineFont(customFontID, customFontP); ... } void AppStop(void) { ... //Release the font resource when app quits. MemHandleUnlock(customFontH); DmReleaseResource(customFontH); ... } void DrawCharsInNewFont(void) { FontID oldFont = FntSetFont(customFontID); char *msg = "Look, Mom. It's a new font!"); WinDrawChars(msg, strlen(msg), 28, 0); FntSetFont(oldFont); }
To use a extended font, you use essentially the same code as above, except that you must change the resource type used in the DmGetResource()
call to fontExtRscType
:
customFontH = DmGetResource(globalResDBPtr, fontExtRscType, MyCoolExtFontRscID); // rest as shown above.
Note that you still use a pointer to a FontType
structure to access the extended font.
It's possible to create an extended font resource that contains only double-density glyphs and not low-density glyphs. You could define an 'NFNT'
resource for the low-density glyphs and an extended font resource with just the double-density glyphs. Then you could load and use the 'NFNT'
resource on all devices with low-density screens and load and use the extended font resource when the display is not low-density. If you do this, you must carefully check the display density before deciding which resource to load (see Listing 5.9).
Listing 5.9 Conditionally loading a font resource
#define customFontID ((FontID) fntAppFontCustomBase) MemHandle fontH = NULL; FontType *fontP; uint16_t winVersion; Err error; error = FtrGet(sysFtrCreator, sysFtrNumWinVersion, &winVersion); // If winVersion is >= 4, the high-density feature set // is present. Check what type of display we are on // and load the appropriate font resource. if (!error && (winVersion >= 4)) { uint32_t density; error = WinScreenGetAttribute(winScreenDensity, &density); if (!error && (density != kDensityLow)) { // load and use the extended font resource. fontH = DmGetResource(globalResDBPtr, fontExtRscType, MyNewFontRscID); fontP = MemHandleLock(fontH); } } if (!fontH) { // Either the feature set is not present or we're on a // low-density screen. Load and use the 'NFNT' resource. fontH = DmGetResource(globalResDBPtr, fontRscType, MyOldFontRscID); fontP = (FontType *)MemHandleLock(fontH); } FntDefineFont(customFontID, fontP);
Creating and Using Custom Scalable Fonts
You can also create your own scalable fonts resources. Unlike bitmapped fonts, custom scalable fonts are available system-wide. Create a database of type 'ofnt'
. The XRD file that defines the database's resources should contain resource definitions like that shown in Listing 5.10.
Listing 5.10 Scalable font resource definition
<RAW_RESOURCE RESOURCE_ID="2000"> <RES_TYPE> 'fttf' </RES_TYPE> <DATA_FILE> "../MyNewTrueTypeFont.ttf" </DATA_FILE> </RAW_RESOURCE>
When Palm OS boots, the font engine searches for and loads all databases of type 'ofnt'
that it finds in the system; therefore, installing a new font database requires rebooting before you can access the fonts in it.
Because the font database is already loaded, you simply access your new fonts in the same manner as the fonts that came with the device. See "Selecting Which Font to Use."
How Palm OS Displays Bitmapped Fonts
To support multiple display densities, Palm OS uses an extended bitmapped font resource. An extended font resource contains a separate set of glyphs for each supported density. At runtime, Palm OS determines the current display density and then draws text using the glyphs that match the display density. On a double-density display, text is drawn using the double-density glyphs. On a low-density display, text is drawn using the low-density glyphs.
Palm OS uses extended font resources for each of the built-in fonts. If your application uses only these fonts, your text is drawn by default using high-density glyphs on high-density displays. You do not have to make any changes to your code for this to occur.
You only need to be concerned about the font density if you need to display more text than normal on a single-density screen or if you use custom fonts:
- When creating a custom bitmapped font, you'll want to create an extended font resource. See "Creating and Using Custom Bitmapped Fonts."
- If an extended font resource is not available or does not contain glyphs that match the screen density, Palm OS uses the following selection algorithm when selecting the font, from high to low priority:
- When drawing text in a custom font to an off-screen window, you must take care. Off-screen windows also have a display density. If you create a low-density off-screen window and draw text to it, use a low-density font or an extended font with low-density glyphs. If the resource contains only high-density glyphs, the rendering system shrinks the high-density font bitmaps. This results in poor quality text when the off-screen bitmap is subsequently transferred, and pixel-doubled, to a high-density display. If a low-density font is available, the rendering system substitutes a low-density font when drawing text to the window in an attempt to produce the best possible aesthetic result.
Because Palm OS includes glyphs for each supported density for each of the built-in fonts, this is only a potential problem if you are using a custom font.
The font scaling behavior can be overridden to allow your application to display more text at one time; WinSetScalingMode()
can force the rendering system to use the low-density font, unscaled, for subsequent text drawing.
To draw text using high-density coordinates, set the high-density coordinate system by calling WinSetCoordinateSystem()
before using the Font Manager functions to position text or extract font metrics.
Summary of Text Display Functions
|
|
|
|