Single-line text
PtWidget → PtBasic → PtLabel → PtText
For more information, see the diagram of the widget hierarchy.
<photon/PtText.h>
The Photon text widgets let you type textual information into a text-entry box. The widgets provide basic editing features, so you can alter text that's entered. They also support a point-and-click model of editing, so that you can operate on blocks of text as a unit.
Photon provides two different text widgets:
The text that you enter in the text widget is either inserted into or overwrites the existing text, depending on the insertion mode. The location where text is inserted or replaced is visually represented by a cursor.
In insert mode, the cursor appears as a vertical bar or pipe (|) between two characters. When you enter a character, it appears at the cursor location, and the cursor is moved to the right of that character.
In replace mode, the cursor appears as an underline (_) beneath a character. When you enter a new character, it replaces the character at the cursor location, and the cursor is moved to the next character in the text.
Clicking the mouse button once changes the cursor location to the character position nearest the pointer location. Double-clicking selects the text under the pointer, using space characters as the selection delimiter. Dragging the pointer with the button pressed selects a range of text as the object of a subsequent operation. The selected range of text, which begins at the cursor position and ends at the pointer location, is highlighted by inverting the foreground and background colors used to display the text. Releasing the button completes the range selection.
You can extend the range of text selected by dragging with the Shift key pressed. The selected range of text is changed to the text between the current cursor position and the pointer location. The extension of the range of text is completed when the button is released. Alternately, you can extend the range by Shift-clicking at a new position.
Any character you type after selecting a range of text replaces the selected range. Your application can also specify a string to replace the selected range.
You can delete selected text by pressing Delete or Backspace. Pressing Ctrl-Backspace deletes all the text to the left of the cursor up to the first space character. Ctrl-Delete deletes the text to the right of the cursor up to the first space character.
To modify the text widget's contents within a program, you must be able to access the text widget's internal storage. The primary means of access to this text is through the Pt_ARG_TEXT_STRING resource (inherited from PtLabel).
When you set the widget's text using Pt_ARG_TEXT_STRING, you must give a null-terminated C string as a value.
The following short program creates a text widget whose initial contents are the string “hello, world...”:
#include <Pt.h> PhArea_t area = { {0, 0}, {200,40} }; main(int argc, char *argv[]) { PtAppContext_t app; int nargs = 0; PtArg_t args[4]; PtWidget_t *window; if (PtInit(NULL) == -1) PtExit(EXIT_FAILURE); PtSetArg(&args[nargs++], Pt_ARG_POS, &area.pos, 0); PtSetArg(&args[nargs++], Pt_ARG_DIM, &area.size, 0); PtSetArg(&args[nargs++], Pt_ARG_WINDOW_TITLE, "hello", 0); if ((window = PtCreateWidget(PtWindow, Pt_NO_PARENT, nargs, args)) == NULL) PtExit(EXIT_FAILURE); nargs = 0; area.pos.y = 15; PtSetArg(&args[nargs++], Pt_ARG_POS, &area.pos, 0); PtSetArg(&args[nargs++], Pt_ARG_DIM, &area.size, 0); PtSetArg(&args[nargs++], Pt_ARG_TEXT_STRING, "hello, world...", 0); PtCreateWidget(PtText, window, nargs, args); PtRealizeWidget(window); PtMainLoop(); }
You can retrieve the widget's text as a null-terminated C string by getting the value of the Pt_ARG_TEXT_STRING resource with the PtGetResources() function.
For more information, see “Getting resources” in the Manipulating Resources in Application Code chapter of the Photon Programmer's Guide.
You can obtain the range of characters in the current selection by using the PtTextGetSelection() function. This function takes the widget as the first parameter and returns the start and end position in the remaining two parameters. You can pass the range to other convenience functions to modify the selected text.
Your application can change any block of text in the widget by calling PtTextModifyText(). The arguments are:
Your application can monitor and control changes made to the widget's text using the text-modification callbacks. These callbacks are invoked when you type new text. If the widget has the Pt_CALLBACKS_ACTIVE bit set in its Pt_ARG_FLAGS resource, these callbacks are also invoked when your application changes the text is changed by calling PtSetResource(), PtSetResources(), or a convenience function such as PtTextModifyText(). The text-modification callbacks are:
The Pt_CB_MODIFY_VERIFY callback is useful for validating changes before they're made to the widget. You can use this callback to alter the text modification or prevent it entirely.
This callback can manipulate the text modification via the cbdata member of the PtCallbackInfo_t structure passed to it. The cbdata member is a pointer to a text-callback structure. This is a PtTextCallback_t structure if the widget is a PtText, and a PtMultiTextCallback_t structure if the widget is a PtMultiText widget.
The following example shows how the text member of the above structure can be modified to alter the text inserted into the widget. The example uses the allcaps() callback function to convert any lowercase characters to uppercase before they're inserted into the widget.
#include <Pt.h> #include <stdlib.h> #include <ctype.h> int allcaps(PtWidget_t *, void *, PtCallbackInfo_t *); main(int argc, char *argv[]) { PtAppContext_t app; PhRect_t extent; PhPoint_t pos; PhPoint_t dim; PtArg_t args[6]; int nargs; PtWidget_t *window, *text, *label; if (PtInit(NULL) == -1) PtExit(EXIT_FAILURE); /* Labels work with UTF-8 (multibyte character) strings. International characters can be entered only from an editor that supports UTF-8 */ nargs = 0; PtSetArg(&args[nargs], Pt_ARG_MARGIN_HEIGHT, 4, 0); nargs++; if ((window = PtCreateWidget(PtWindow, Pt_NO_PARENT, nargs, args)) == NULL) PtExit(EXIT_FAILURE); nargs = 0; PtSetArg(&args[nargs], Pt_ARG_TEXT_STRING, "Enter Text:", 0); nargs++; label = PtCreateWidget(PtLabel, window, nargs, args); PtExtentWidget(label); PtWidgetExtent(label, &extent); pos.x = extent.lr.x + 4; pos.y = 0; nargs = 0; PtSetArg(&args[nargs], Pt_ARG_COLUMNS, 20, 0); nargs++; PtSetArg(&args[nargs], Pt_ARG_POS, &pos, 0); nargs++; text = PtCreateWidget(PtText, window, nargs, args); PtAddCallback(text, Pt_CB_MODIFY_VERIFY, allcaps, NULL); PtRealizeWidget(window); PtMainLoop(); } int allcaps( PtWidget_t *w, void *client_data, PtCallbackInfo_t *info) { int len; PtTextCallback_t *cbs = (PtTextCallback_t *)info->cbdata; if (cbs->text == NULL) return Pt_CONTINUE; for ( len = 0; len < cbs->length; len++ ) if (islower(cbs->text[len])) cbs->text[len] = toupper(cbs->text[len]); return Pt_CONTINUE; }
You can prevent the text from being added to the widget by setting the doit member of the PtTextCallback_t structure to zero or by setting the length member to zero.
Setting the length to 0 stops the widget from inserting the text; it doesn't prevent any deletion included in the modification. |
You can determine if a modification is replacing or deleting a block of text by checking start_pos and end_pos. If these values differ, then a block of text is being removed from the widget and may potentially be replaced by new text contained in the text member.
Be sure to handle backspaces correctly. As well as checking for a different start and end position, an application can determine which of Backspace or Delete was pressed by checking the length, cur_insert, and new_insert:
The following simple example of accepting a password as input illustrates how to handle all editing operations (including pasting) correctly:
/* This program creates two text widgets for entering a password: - one offscreen to collect the password - one onscreen in which to type. All characters are displayed as stars in the onscreen widget but are saved in the offscreen widget. This is done by making the displayed widget's callbacks manipulate the offscreen widget's text. */ #include <Pt.h> #include <stdio.h> #include <stdlib.h> int check_passwd(PtWidget_t *, void *, PtCallbackInfo_t *); int update_passwd(PtWidget_t *, void *, PtCallbackInfo_t *); PtWidget_t *displayed_text, *offscreen_text; main(int argc, char *argv[]) { PhRect_t extent; PhPoint_t pos; PtArg_t args[2]; int nargs; PtWidget_t *window, *label; if (PtInit(NULL) == -1) PtExit(EXIT_FAILURE); nargs = 0; PtSetArg(&args[nargs++], Pt_ARG_MARGIN_HEIGHT, 4, 0); if ((window = PtCreateWidget(PtWindow, Pt_NO_PARENT, nargs, args)) == NULL) PtExit(EXIT_FAILURE); nargs = 0; PtSetArg( &args[nargs++], Pt_ARG_TEXT_STRING, "Enter Text:", 0); label = PtCreateWidget( PtLabel, Pt_DEFAULT_PARENT, nargs, args); PtExtentWidget(label); PtWidgetExtent(label, &extent); pos = extent.lr; pos.x += 4; pos.y = 0; /* Create the displayed text widget: */ nargs = 0; PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); PtSetArg(&args[nargs++], Pt_ARG_COLUMNS, 20, 0); displayed_text = PtCreateWidget( PtText, Pt_DEFAULT_PARENT, nargs, args); PtAddCallback(displayed_text, Pt_CB_MODIFY_VERIFY, update_passwd, NULL); PtAddCallback(displayed_text, Pt_CB_ACTIVATE, check_passwd, NULL); /* Create an offscreen text widget: */ pos.x = -1000; nargs = 0; PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); offscreen_text = PtCreateWidget( PtText, Pt_DEFAULT_PARENT, nargs, args); PtRealizeWidget(window); PtMainLoop(); } int check_passwd( PtWidget_t *widget, void *client_data, PtCallbackInfo_t *info ) { /* This callback gets the password out of the offscreen widget. It's invoked when you activate the displayed widget (e.g. by pressing Enter). */ PtTextCallback_t *cbs = (PtTextCallback_t *)info->cbdata; char *passwd; PtGetResource( offscreen_text, Pt_ARG_TEXT_STRING, &passwd, 0 ); if (info->reason_subtype == Pt_EDIT_ACTIVATE) printf("Password: %s\n", passwd); return Pt_CONTINUE; } int update_passwd( PtWidget_t *widget, void *client_data, PtCallbackInfo_t *info ) { /* This callback is invoked when you type in the displayed widget, but it passes the typing to the offscreen widget. The characters are replaced by the same number of stars in the displayed widget. You need as many stars in the string below as characters that you allow in the password. */ PtTextCallback_t *tcb = (PtTextCallback_t *)info->cbdata; static const char stars[] = "********************"; PtSetResource( offscreen_text, Pt_ARG_TEXT_SUBSTRING, tcb, 0 ); tcb->text = stars; return Pt_CONTINUE; }
After you've entered the new text into the widget, the Pt_CB_TEXT_CHANGED or Pt_CB_MODIFY_NOTIFY callback list is invoked. You can use this callback to keep track of changes after they've been made. This is useful in form-filling applications and text editors to determine if the contents of the text buffer are “dirty” (i.e. the user modified them).
This callback uses the same text-modification callback structure as the Pt_CB_MODIFY_VERIFY callback. The text member of this structure contains a UTF-8 string indicating the current contents of the text widget (i.e. the entire text buffer).
As an example, you can use this callback in form-filling applications to provide a visual cue to indicate that one or more fields within the form have changed. The user then knows that the pending changes won't take effect until they're applied, usually by pressing an Apply or OK button.
To use this callback in this way:
Another possibility is to create a check button beside each field in the form when the user alters the field's contents. Activating the check button causes the new value to take effect.
The text widget inherits callbacks from PtBasic that tell your application either that the text widget has gained or lost focus.
The text widget gains focus when the user either clicks on the text widget or presses the Tab key to move from another widget into this one.
When the text widget obtains the focus by either of these two means, any callbacks defined in its Pt_CB_GOT_FOCUS callback list are called. This is useful if your application wishes to alter the appearance of a text widget that the user is entering text into, or to trigger the update of a status field providing hints to a user using a “novice” mode of the interface.
The Pt_CB_LOST_FOCUS callback is invoked any time the user switches focus away from the text widget, either by tabbing to or clicking within another widget. You can use this callback to undo any change in the text widget's appearance that the application made to indicate that the widget had focus. The callback can also be useful in checking any syntax in the fields within a form.
You can track changes to the text cursor position representing the current insertion point by adding a cursor movement callback to the Pt_CB_MOTION_VERIFY callback list. The callback is invoked every time:
Or:
Or:
The reason member given in the callback info for this callback is Pt_CB_MOTION_VERIFY. The event member indicates the type of action that caused the callback to be invoked.
You can determine the type of action that caused the callback to be invoked by making a comparison on the event member. If it's set to NULL, the callback was invoked as a result of an application function call. Otherwise, the callback was invoked as a result of a user action (such as a pointer button press or keypress event).
The event member is a pointer to a PhEvent_t structure (see the Photon Library Reference) that describes the user's action. To differentiate between a pointer event and a keypress event, look at the type of that event.
The cbdata member of info is a pointer to the same type of text-modification callback structure used by the other text widget callbacks. This callback uses the cur_insert, new_insert, and doit members of the structure. Your application can set the doit member to zero to prevent the cursor movement from taking place.
The PtText widget inherits an activate callback from PtBasic, Pt_CB_ACTIVATE, that's invoked when one of the following occurs:
The reason_subtype in the callback information is Pt_EDIT_ACTIVATE. The callback data is a pointer to the same text-modification callback structure as used by the text-modification callbacks. The text member of that structure contains a UTF-8 string indicating the contents of the buffer.
The reason_subtype in the callback information is Pt_CHANGE_ACTIVATE. The callback data is a pointer to the same text-modification callback structure as used by the text-modification callbacks. The text member of that structure contains a UTF-8 string indicating the contents of the buffer.
The reason code in the callback information is always Pt_CB_ACTIVATE.
When only one text field is contained within a container widget (e.g. a dialog), the activate callback is often chained to the activate action on the dialog. In other words, for a prompt dialog, typing a new value in the text field and pressing the Enter key has the same effect as pressing the dialog's OK button after entering the new value.
The PtText widget provides an edit mask that lets you specify a pattern for the text entered into the text field. Any characters that you type must conform to this pattern or they're rejected.
Edit masks can be difficult to use and aren't very flexible; use a Pt_CB_MODIFY_VERIFY callback instead. |
The string entered into a data-entry field often conforms to some format. The text widget can use an edit mask to ensure that the information is in the correct format.
You can provide a single edit mask for the text widget by setting the Pt_ARG_EDIT_MASK resource. This resource is a null-terminated text string that acts as a template for text entered in the text field. Each character that you type must match the corresponding character in the edit mask.
Here are the characters that you can specify in the edit mask, along with the characters they match:
This character: | Matches: |
---|---|
# | Any single numeric digit |
X | Any character (don't care) |
A | Any alphabetic character (the letters A-Z) |
n | Any alphanumeric character (the letters A-Z or any numeric digit). All alphabetic characters are converted to lowercase. |
N | Any alphanumeric character (the letters A-Z or any numeric digit). All alphabetic characters are converted to uppercase. |
c | Any alphabetic character (the letters A-Z). All characters are converted to lowercase. |
C | Any alphabetic character (the letters A-Z). All characters are converted to uppercase. |
d | Any alphanumeric character (the letters A-Z or any numeric digit), but without case conversion. |
Any other character that appears in the edit mask is assumed to be a constant character that must appear at that position in the text field. When you've typed enough characters to reach that position, the character is automatically inserted. After that, you can't delete or alter it.
As an example, Canadian postal codes must consist of uppercase alphabetic characters and numbers in the following order: character, digit, character, space, digit, character, digit. For example, QNX Software System's postal code is K2M 1W8. So, a text field for entering a postal code might specify C#C #C# as the edit mask. The text field widget enforces the constraints on the characters you type and automatically adds the space character.
If you: | The widget: |
---|---|
Press the mouse button | Gets input focus |
Press the mouse button and drag the mouse | Extends the text selection |
Release the mouse button | Ends the text selection |
If you press: | The widget: |
---|---|
Any character | Inserts the typed character |
→ | Moves the cursor to the right |
← | Moves the cursor to the left |
Home | Moves the cursor to the beginning of the line |
End | Moves the cursor to the end of the line |
Shift-→ | Extends the text selection to the right |
Shift-← | Extends the text selection to the left |
Shift-Home | Extends the text selection to the beginning of the line |
Shift-End | Extends the text selection to the end of the line |
Backspace | Deletes the previous character |
Delete | Deletes the current character |
Enter | Processes the text |
Tab | Moves the cursor to the next text field |
Shift-Tab | Moves the cursor to the previous text field |
Ctrl-→ | Moves the cursor to the next word |
Ctrl-← | Moves the cursor to the previous word |
Ins | Toggles between insert and replace modes |
If you select some text and hold down the Ctrl key, you can drag the selected text to a PtText, PtMultiText, PtTerminal, or PtTty widget.
Resource | C type | Pt type | Default |
---|---|---|---|
Pt_ARG_COLUMNS | short | Scalar | 0 |
Pt_ARG_CURSOR_POSITION | int | Scalar | -1 |
Pt_ARG_EDIT_MASK | char * | String | NULL |
Pt_ARG_MAX_LENGTH | signed int | Scalar | SHRT_MAX |
Pt_ARG_SELECTION_RANGE | See below | Complex | See below |
Pt_ARG_TEXT_CURSOR_WIDTH | char | Scalar | 1 |
Pt_ARG_TEXT_FLAGS | unsigned long | Flag | Pt_CURSOR_VISIBLE | Pt_EDITABLE | Pt_INSERT_MODE | Pt_TEXT_BLINKING_CURSOR |
Pt_ARG_TEXT_HIGHLIGHT_BACKGROUND_COLOR | PgColor_t | Scalar | Pt_DEFAULT_COLOR |
Pt_ARG_TEXT_HIGHLIGHT_TEXT_COLOR | PgColor_t | Scalar | Pt_DEFAULT_COLOR |
Pt_ARG_TEXT_SUBSTRING | See below | Complex | See below |
Pt_CB_MODIFY_NOTIFY | PtCallback_t * | Link | NULL |
Pt_CB_MODIFY_VERIFY | PtCallback_t * | Link | NULL |
Pt_CB_MOTION_NOTIFY | PtCallback_t * | Link | NULL |
Pt_CB_MOTION_VERIFY | PtCallback_t * | Link | NULL |
Pt_CB_TEXT_CHANGED | PtCallback_t * | Link | NULL |
C type | Pt type | Default |
---|---|---|
short | Scalar | 0 |
The number of “M” characters that fit in the field horizontally. The widget uses this resource only if the width component of the Pt_ARG_DIM resource is 0.
C type | Pt type | Default |
---|---|---|
int | Scalar | -1 |
The cursor position. A value of 0 indicates that the cursor is placed before the first character, 1 before the second character, and so on.
C type | Pt type | Default |
---|---|---|
char * | String | NULL |
A string that serves as an input filter for the text field. Each character in the string determines the acceptable input for the corresponding character position in the text field. The edit mask can contain the following:
See “Edit masks,” above.
Edit masks can be difficult to use and aren't very flexible; use a Pt_CB_MODIFY_VERIFY callback instead. |
C type | Pt type | Default |
---|---|---|
signed int | Scalar | SHRT_MAX |
The maximum text length that the widget accepts.
C type | Pt type | Default |
---|---|---|
See below | Complex | See below |
You can use this resource to select a range of text or determine what text is currently selected. This resource is complex, and requires special handling:
The len isn't used when setting or getting this resource.
You can call PtTextGetSelection() or PtTextSetSelection() instead of using this resource.
C type | Pt type | Default |
---|---|---|
char | Scalar | 1 |
The width, in pixels, of the cursor.
C type | Pt type | Default |
---|---|---|
unsigned long | Flag | Pt_CURSOR_VISIBLE | Pt_EDITABLE | Pt_INSERT_MODE | Pt_TEXT_BLINKING_CURSOR |
Valid flags:
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pt_DEFAULT_COLOR |
The background color for highlighting. See PgColor_t in the Photon Library Reference.
If you set this resource to Pt_DEFAULT_COLOR, the widget uses the default background color.
C type | Pt type | Default |
---|---|---|
PgColor_t | Scalar | Pt_DEFAULT_COLOR |
The text color for highlighting. See PgColor_t in the Photon Library Reference.
If you set this resource to Pt_DEFAULT_COLOR, the widget uses the default text color.
C type | Pt type | Default |
---|---|---|
See below | Complex | See below |
You can use this resource to get or set a substring of the widget's text. It's a complex resource, so it needs special handling:
Instead of setting this resource, you can call PtTextModifyText().
You don't use the len argument to PtSetArg() when setting or getting this resource.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks that the widget invokes after the value of the text string changes.
It doesn't matter which name you use for this resource. |
If you've set the Pt_CALLBACKS_ACTIVE bit in the widget's Pt_ARG_FLAGS resource, these callbacks are also invoked when your application changes the text is changed by calling PtSetResource(), PtSetResources(), or a convenience function such as PtTextModifyText().
Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
For more information, see “Text-modification callbacks,” above.
These callbacks should return Pt_CONTINUE.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks that the widget invokes before the value of the text string changes. To alter the input to the widget, you can modify the members of the callback structure.
If you've set the Pt_CALLBACKS_ACTIVE bit set in the widget's Pt_ARG_FLAGS resource, these callbacks are also invoked when your application changes the text is changed by calling PtSetResource(), PtSetResources(), or a convenience function such as PtTextModifyText().
Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
For more information, see PtTextModifyText().
These callbacks should return Pt_CONTINUE.
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks that the widget invokes after it repositions the cursor.
If you've set the Pt_CALLBACKS_ACTIVE bit set in the widget's Pt_ARG_FLAGS resource, these callbacks are also invoked when your application repositions the cursor by calling PtSetResource() or PtSetResources().
Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
C type | Pt type | Default |
---|---|---|
PtCallback_t * | Link | NULL |
A list of PtCallback_t structures that define the callbacks that the widget invokes before it repositions the cursor. You can use this callback resource to modify or even disallow cursor repositioning.
If you've set the Pt_CALLBACKS_ACTIVE bit set in the widget's Pt_ARG_FLAGS resource, these callbacks are also invoked when your application repositions the cursor by calling PtSetResource() or PtSetResources().
Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
These callbacks should return Pt_CONTINUE.
If the widget modifies an inherited resource, the “Default override” column indicates the new value. This modification affects any subclasses of the widget.
Pt_CB_ACTIVATE is inherited from PtBasic, but its behavior is different for a PtText widget. Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
If reason_subtype is Pt_EDIT_ACTIVATE or Pt_CHANGE_ACTIVATE, cbdata points to a PtTextCallback_t structure that contains at least the following members:
These callbacks should return Pt_CONTINUE.
Pt_CB_GOT_FOCUS and Pt_CB_LOST_FOCUS are inherited from PtBasic, but the callback data is different for a PtText widget. Each callback is passed a PtCallbackInfo_t structure that contains at least the following members:
The Pt_CB_GOT_FOCUS callbacks should return Pt_CONTINUE.
The Pt_CB_LOST_FOCUS callbacks should return:
Or:
The PtText widget defines the following convenience functions and data structures that make it easier to use the widget once it's been created: