Panther lets you access and manipulate most widgets at runtime, get and modify their data and properties, ascertain the current selection within a radio button group or list box, and determine whether data has changed or passed validation. Panther differentiates between data entry widgets that can be thus accessed and manipulated, and other widgets that are static in nature, like lines, boxes, and static labels.
In order to access widgets, you must know how widgets are identified; for information on widget naming and array/occurrence numbering, refer to Chapter 14, "Identifying Screen Widgets."
Functions described in this section are documented in the Programming Guide; refer to that manual for the syntax and specific behavior of each function.
Changing Widget Display
Widget display is determined by the setting for the Hidden property. By default, this property is set to No. You can change the setting to:
For tab decks, the
topmost_card runtime property sets the topmost card in the deck or returns the object id of the card that is topmost in the tab deck.
For tab decks, the
You can control what type of input in allowed for the widget by setting the widget's properties in the screen editor and, if necessary, changing those properties at runtime.
The Keystroke Filter property sets the criteria for data entry: the keys that can be used (numbers, letters, or a combination) and the format of the entered data.
For example, the following entry in the Edit Mask subproperty would force the user to enter three digits followed by six letters:
ID# and the hyphen are only display characters. Display characters are stripped before sending the value to a database or copying the value with sm_getfield
§. For more information, refer to "Edit Masks" in Using the Editors.
The Regular Expression property can also enforce a specific pattern of letters or numbers, and in addition, it can restrict the range of characters available. For example, the following expression defines a code of three digits ranging from 1-5, followed by a hyphen and minimum of three letters, but no more than six.
For more information, refer to "Regular Expressions" in Using the Editors.
If you want to suggest a format pattern and have that format pattern saved to the database, you can use the Keystroke Filter property in combination with the Initial Text property. For example, an initial text entry of - - in combination with a setting of Numeric in the Keystroke Filter property would allow the user to enter groups of numbers separated by hyphens.
Other properties in the Input category determine if entry in the widget is required and if data in the widget is protected. For more information, refer to Chapter 14, "Data Entry Widgets," in Using the Editors.
Under Format/Display, properties determine if a widget's contents are right or left justified, a password, a date format, or a currency format. You can also specify the date or currency format which will be used to enter data. For a description of properties in the Format/Display category, refer to Chapter 10, "Controlling the Way Things Look," in Using the Editors.
You can traverse widgets on the screen using the mouse or the
Panther provides a set of library functions that enable you to traverse the contents of a given container objectscreen (including one used as an
LDB), grid widget, box widget, selection group, synchronized scrolling group, tab deck, tab card, or table view widget. Follow these steps:
sm_list_objects_startthrough repeated calls to sm_list_objects_next. This function, when first called, on a given list returns the object ID of the first widget in the list; each subsequent call returns the object ID of the next widget in the list.
When the list is completely traversed, the function returns
PR_E_ERROR. You can use this error code to test whether a list is fully traversed; or use sm_list_objects_count to set a counter within a for loop.
For example, the following procedure creates an objects contents list for all members in a grid and traverses the list:
proc traverse_grid( grid_name )
vars grid_list, ct, member_ct, member_id
// create list of all members in grid
grid_list = sm_list_objects_start( sm_prop_id( grid_name ) )
if grid_list > 0
// get count of listed object IDs
member_ct = sm_list_objects_count( grid_list )
for ct = 1 while ct <= member_ct
// traverse list
member_id = sm_list_objects_next( grid_list )
// use member's object ID to perform some action on it
call sm_list_objects_end( grid_list )
The following example hides a box widget and the widgets positioned within its borders:
proc hide_box (name)
vars box_list, count, i, item_id
@widget(name)->hidden = PV_YES
box_list = sm_list_objects_start ( sm_prop_id (name) )
if box_list >0
count = sm_list_objects_count ( box_list )
for i = 1 while i <= count
item_id = sm_list_objects_next ( box_list )
// don't try to hide static labels
if @id(item_id)->widget_type != PV_STATIC_LABEL
// don't try to hide always-hidden widgets
if @id(item_id)->hidden != PV_ALWAYS
@id(item_id)->hidden = PV_YES
call sm_list_objects_end (box_list)
In JPL, the member property can be used to find the members of a container. The following example cycles through the cards in the specified tab deck:
for i = 1 while i <= my_deck->number_of_cards
a = my_deck->member[i]
//some JPL programming
Getting Widget Data
Panther library functions let you obtain the data in a widget or its occurrences; they also let you ascertain the widget's current property settings.
The following functions copy data from widgets and arrays:
sm_getfieldcopies data from the specified widget or occurrence to the supplied parameter. Panther strips leading or trailing blanks.
You can also get information about the data in a widget with these functions:
You can also get information about the data in a widget with these functions:
sm_dlengthreturns the length of the data in the specified widget or occurrence of a widget. The length includes any data that is shifted offscreen and therefore out of view. The length excludes leading blanks in right-justified widgets, and trailing blanks in left-justified widgets.
sm_null lets you test whether a widget's value is null or not. This function checks whether a widget's Null Field property is set to Yes; if it is,
sm_null gets the widget's null indicator and compares it to the widget's value.
You can access all widget properties at runtime through JPL or the property functions: For more information about getting and setting widget properties in JPL, refer to Chapter 19, "Programming in JPL."
sm_prop_id. For example, this JPL if statement conditionally unhides a widget at runtime by changing its hidden property to
if (login == "super")
emp_salary ->hidden = PV_NO
You can access all widget properties at runtime through JPL or the property functions:
For more information about getting and setting widget properties in JPL, refer to Chapter 19, "Programming in JPL."
Changing Widget Data
The following library functions let you move data directly into widgets:
sm_putfieldmoves the supplied string into the specified widget. If the string is too long, Panther truncates it without warning. If the string is shorter than the destination widget, Panther blank fills it according to the widget's justification. If the data is a null string, Panther clears the field. This refreshes date and time fields that take system values.
sm_ww_write wraps at the end of words and leaves a space at the end of each line. If a word is equal to or longer than the length of the widget,
sm_ww_write breaks the word one character before the end of the field, appends a space, and wraps the rest of the word on the next line.
sm_dtofield converts a real number value to user-readable format as specified by format. It then moves this value into the specified widget with a call to
sm_amt_format. If the format string is empty, Panther determines the number of decimal places from the widget's C Type property specification, or from its
numeric_type property specification. If neither exists, it uses two decimal places.
sm_upd_select updates the contents of an option menu or combo box with data from another screen. The widget must be defined to accept data from an external screen; otherwise, the function returns an error.
To clear widget data:
Clearing Widget Data
To clear widget data:
FERAlogical key to clear a widget's data.
sm_cl_unprot erases onscreen and offscreen data from all widgets that are unprotected from clearing (
CPROTECT). Date and time fields that take system values are reinitialized. Widgets with the null edit are reset to their null indicator values.
sm_n_clear_array also clear arrays synchronized with the array unless they are protected from clearing. Variants
sm_n_1clear_array only clear the specified array.
You can insert rows in using the logical key Two functions let you delete and insert occurrences from arrays:
Inserting and Deleting Occurrences
INSL and delete rows using
You can insert rows in using the logical key
Two functions let you delete and insert occurrences from arrays:
sm_doccurremoves one or more occurrences, starting with the specified occurrence.
If other arrays are synchronized with the one specified, Both functions ignore the target array's Clearing Protect setting.
sm_ioccur perform the same operation on them, provided their Clearing Protect property is set to No. If a synchronized array is protected from clearing, Panther leaves it unchanged. Thus, you can synchronize a protected array that contains an unchanging sequence of numbers with an adjoining unprotected array whose data grows and shrinks.
If other arrays are synchronized with the one specified,
Both functions ignore the target array's Clearing Protect setting.
Making Widget Selections
Panther has a set of functions that let you check the current selection or selections within a selection group, and change the selections.
sm_getfield, let you determine whether a selection has been made within a selection group and what those selections are.sm_isselected checks whether a selection has been made in a selection group. The selection is referenced by the group name and occurrence number.
If you call
sm_n_getfield on a radio button group that allows one selection, the buffer that you pass into this function gets the group occurrence number of the selected item. For example, the radio button group rating has the third occurrence, PG-13, selected:
Given this selection, the following call to
sm_n_getfield puts the string "3" into the string buffer pointed to by
sm_n_getfield (buffer, "rating");
If you call
sm_n_getfield on a group of widget types that allows multiple selections, for example, a check box group. Panther puts the numbers of the selected occurrences into
buffer. For example, the
genre check box group has occurrences 1, 3, and 4 selected:
If you call
buffer gets the string 1 3 4.
Panther sees a group's value as an array whose elements contain the offsets of the selected items. Thus, Panther stores the value of
genre as follows:
genre = "1"
genre = "3"
genre = "4
genre = " "
sm_i_getfield gets the specified selection in the group. For example, this call gets the second-selected item in
genre and puts its value, 3, into
retvar = sm_i_getfield (buffer, "genre", 2);
sm_select lets you select an occurrence within a selection widget group. If the group's # of Selections property allows no more than one selection, Panther first deselects the current selection before it selects the specified group occurrence. For more information about selection widgets, refer to Chapter 20, "Selection Widgets," in Using the Editors.
To deselect an occurrence, call
The selected runtime property specifies whether a selection-type widget is selected.
For grid widgets, the
grid_current_occ runtime property contains the grid widget's current (or selected) occurrence. The following JPL procedure uses this property to delete the selected row.
vars grid_name occ
grid_name = @widget(fld)->grid
occ = @widget(grid_name)->grid_current_occ
call sm_i_doccur(fld, occ, 1)
Inside a list box, you can select multiple occurrences or change the application behavior to only allow a single choice. The
LISTBOX_SELECTION behavior variable determines the behavior of list boxes in your application with its settings of
EXTENDED_SELECTION (default). The value for
LISTBOX_SELECTION must remain constant during the running of the application.
For extended list boxes, the Listbox Type property must be set to Select Any. If it belongs to a selection group, the # of Selections property must also be set to Any. Extended selections pertain to selections within the list box, not the selection group. Therefore, if you have two list boxes in the group, the selection within one list box will have no effect on the other.
One of the field function arguments,
K_EXTEND, can determine if the widget is an extended list box. Another field function argument,
K_EXTEND_LAST, can determine if the cursor is in the last item of an extended selection list box.
ADDM logical key toggles in and out of add mode within the list box.
Accessing Tab Controls
A tab control, available for Windows and Motif applications, consists of a tab deck and its associated cards. The tab deck is like a box; any widget within its boundaries is assigned to one of its cards. The
number_of_cards read-only property gets the number of cards in the deck, including hidden ones.
Each tab card can have widgets which can be grouped as needed. The card property of each widget appearing on a tab card is set to the object ID of that card.
Tab cards are numbered sequentially within the tab deck. The Card Number property (
card_number) determines the sequence of the cards. You can move to another card by clicking on its index tab or with the
PCARD logical keys.
The tab card currently on display in the screen is the topmost card. At runtime, you can set which card is topmost using the tab deck's
topmost_card property. The following JPL statement set a new topmost card:
// my_deck has three cards named card1, card2, and card3.
// This call sets the second card as topmost card.
Accessing ActiveX Controls
Active X controls, available for Windows and Web applications, are considered separately since the ActiveX control itself is not a Panther' widget, only the ActiveX container is. However, Panther can access the ActiveX control's properties, events, and methods. This allows you to manipulate the ActiveX control at runtime.
The Active X container's
CLSID property (
clsid) determines which ActiveX control is located inside the container. If the ActiveX control specified in that
CLSID property is registered on your system, the control will be displayed in the screen editor and the Properties window will display the control's property names and settings.
To get and set property values at runtime:
ax_prependedto the Active X control's property name. The ax_
prefixinsures that there are no conflicts between Panther properties and ActiveX control properties.
The author of an ActiveX control specifies what methods can be used to access the control, the arguments needed for those methods, and the events that are applicable to the control. Those methods can then be called in Windows applications using For more information and an example of an ActiveX control, refer to Chapter 18, "ActiveX Controls," in Using the Editors.
sm_com_set_handler in Windows applications and VBScript functions in Web applications.
The author of an ActiveX control specifies what methods can be used to access the control, the arguments needed for those methods, and the events that are applicable to the control. Those methods can then be called in Windows applications using
For more information and an example of an ActiveX control, refer to Chapter 18, "ActiveX Controls," in Using the Editors.
Panther maintains two runtime properties that can be checked to determine the validation and modification status of a widget or group:
PV_YES—the widget has passed validation.
The valided property is initially set to During field validation, Panther tests a field's data against a number of formatting and input property settings. Refer to Table 17-1 for a list of these properties.
In order to allow users to move freely within a GUI application screen, validation is typically suppressed until they explicitly submit the screen data, for example, by pressing a Save push button. Field validation does not typically occur when the user uses a cursor key to move out of the widget, or mouse clicks into another widget. To force validation also to occur on these events, set the application behavior variable For information on validating widgets during screen exit processing, refer to "Screen Exit Processing."
PV_NO when a screen is displayed. It is reset to
PV_NO each time the content of the widget is changed. It is set to
PV_YES each time the widget passes its validation tests; for example when
sm_fval forces validation processing on the widget. You can also explicitly set a widget's valided property to
The valided property is initially set to
During field validation, Panther tests a field's data against a number of formatting and input property settings. Refer to Table 17-1 for a list of these properties.
In order to allow users to move freely within a GUI application screen, validation is typically suppressed until they explicitly submit the screen data, for example, by pressing a Save push button. Field validation does not typically occur when the user uses a cursor key to move out of the widget, or mouse clicks into another widget. To force validation also to occur on these events, set the application behavior variable
For information on validating widgets during screen exit processing, refer to "Screen Exit Processing."
PV_YES—the data is changed.
The mdt property is initially set to Panther performs validation on a widget no matter how its valided property is set. If a widget's validation requires significant processing such as a database lookup, you can avoid redundant validation and significant overhead by setting its
PV_NO after the screen's entry function is called and is set
PV_YES when the content of the widget or group changes. Once set to
PV_NO, a widget's mdt property remains unchanged while the screen is displayed; however, you can explicitly reset it to
no_validation property to
PV_YES and test the state of its data only when necessary, for example, through the widget's own exit function. The following JPL code tests the mdt property of widget
cust_id, to determine whether to force validation processing through
sm_fval. Because this widget has validation initially disabled (no_validation =
PV_YES), its no_validation property must be reset before the call to
/* If the data has changed, force-validate the widget */
if cust_id->mdt == PV_YES
/* reenable validation */
cust_id->no_validation = PV_NO
/* validate widget data */
if ( sm_n_fval( "cust_id" ) == 0 )
cust_id->mdt = PV_NO /* reset mdt flag */
cust_id->no_validation = PV_YES /* disable validation */
mdt properties for all widgets:
sm_cl_all_mdts resets the mdt property of all widgets and occurrences to
The mdt property is initially set to
Panther performs validation on a widget no matter how its valided property is set. If a widget's validation requires significant processing such as a database lookup, you can avoid redundant validation and significant overhead by setting its
sm_tst_all_mdts tests the mdt property of all on- and offscreen occurrences of all widgets on the current screen. If it finds an occurrence with its
mdt bit set to
PV_YES, the function returns with the base field and occurrence number. Use this function to ascertain whether any occurrence has been modified on the screen since the screen was displayed or its mdt was last cleared by
sm_cl_all_mdts or by resetting the