HP OpenVMS Systems Documentation
Guide to the DEC Text Processing Utility
5.2.4 Using Callbacks
This section presents background information on the DECwindows concept
of callbacks and explains how DECwindows DECTPU implements this concept.
A callback is a mechanism used by a DECwindows widget to notify an application that the widget has been modified in some way. DECwindows applications have one or more callback routines that define what the application does in response to the callback.
For more information about the use of callbacks and callback routines
in DECwindows programs, see the OpenVMS documentation overview.
DECTPU implements the DECwindows concept of callback routines by providing internally defined routines that deliver the information obtained from a widget's callback to a layered application. These routines are referred to as "internally defined DECTPU callback routines."
When a widget calls back to DECTPU, DECTPU packages the callback information, adds the information to its input queue, and returns to the widget. DECTPU may not process the callback packet on its input queue until later. As a result, the information about the widget that DECTPU gets from the callback may not match the information returned by the GET_INFO (widget_variable, "widget_info") built-in procedure.
When DECTPU processes the callback packet, it uses the CREATE_WIDGET built-in or the SET (WIDGET_CALLBACK) built-in to execute the program or learn sequence that was associated with the widget. This program or learn sequence controls what the application does in response to the callback information passed by the DECTPU callback routines. An application's callback routines are referred to as "application-level callback action routines."
The following sections present information on internally defined DECTPU
callback routines and on application-level callback action routines.
DECTPU declares two internally defined callback routines to the X Resource Manager to handle incoming callbacks and dispatch them to the layered application:
Although DECwindows lets you specify a different callback routine for each reason that a widget can call back, DECwindows DECTPU does not support this capability. Instead, it provides only the two callback routines mentioned.
Use these callback routines only if you are specifying a widget's
callback resources in a User Interface Language (UIL) file. When a
widget is part of an X Resource Manager hierarchy, do not include
callback resource names or values in the array you pass to SET
(WIDGET). Instead, specify one of the two internally defined callback
routines in the UIL file.
Although the SET (WIDGET) built-in procedure lets you specify values
for various resources of a widget, there are restrictions on specifying
values for callback resources of widgets. When a widget is not part of
an X Resource Manager hierarchy, specify the names of the callback
resources in the array you pass to SET (WIDGET), and specify 0 as the
value of each such callback resource. DECTPU automatically substitutes
its common callback entry point for the 0 value. A widget calls back
only for those reasons specified in the widget's argument list. If a
reason is omitted from the list, the corresponding event does not cause
When DECTPU receives a widget callback, it identifies and executes the
layered application procedure or learn sequence that has been
designated as the callback action routine. You can designate a
procedure or learn sequence as a callback action routine either when
the widget is created, by using the CREATE_WIDGET built-in procedure,
or at some later time, by using the SET (WIDGET_CALLBACK) built-in
procedure. When you specify an application-level callback program or
learn sequence with CREATE_WIDGET or SET (WIDGET_CALLBACK), all widgets
in the same X Resource Manager hierarchy have the same callback program
or learn sequence. Therefore, the callback program or learn sequence
must have a mechanism for handling all possible callback reasons.
If you are layering an application on DECTPU or on EVE, you can specify callable interface-level callback routines only if you are specifying a widget's callback resources in a User Interface Language (UIL) file.
Callbacks can pass values known as closures. Closures are strings or integers whose function depends on the application you are writing. (DECwindows documentation refers to closures as tags.) For more information about what closures are and how to use them, see Section 5.2.5.
You use the DECTPU callable interface routine TPU$WIDGET_INTEGER_CALLBACK as the callback routine for all callbacks that have an integer closure. You use the DECTPU routine TPU$WIDGET_STRING_CALLBACK for all callbacks that have a string closure.
When a widget is part of an X Resource Manager hierarchy, do not
include callback resource names or values in the array you pass to SET
(WIDGET). Instead, specify the callback routine in the UIL file. When a
widget is not part of an X Resource Manager hierarchy, specify the
names of the callback resources in the array you pass to SET (WIDGET),
and specify 0 as the value of each such callback resource. DECTPU
automatically substitutes its common callback entry point for the 0
value. A widget calls back only for those reasons specified in the
widget's argument list. If a reason is omitted from the list, the
corresponding event does not cause a callback.
With DECwindows, you can specify a closure value for a widget. (DECwindows documentation refers to closures as tags.) DECwindows does not define what a closure value is; a closure is simply a value that DECwindows understands how to recognize and manipulate so that a DECwindows application programmer can use the value if needed in the application. For general information about using closures in DECwindows, see the OpenVMS documentation overview.
When a widget calls back to the DECwindows application, the callback parameters include the closure value assigned to the widget. DECwindows allows the application to define the significance and possible values of the closure.
DECTPU supports closure values of type string and integer. Closure values are optional for widgets used by applications layered on DECTPU. If you do not specify a closure value, the GET_INFO (WIDGET, "callback_parameters", array) built-in procedure returns unspecified in the "closure" array element. If you create a widget without using a UIL file, the GET_INFO (WIDGET, "callback_parameters", array) built-in procedure returns the closure you specified as a parameter to CREATE_WIDGET. If you create a widget by using a UIL file, the GET_INFO (WIDGET, "callback_parameters", array) built-in procedure returns the closure value (if any) defined in the X Resource Manager. If none is defined, the built-in returns unspecified.
DECTPU leaves it to the layered application to use the closure in any way the application programmer wishes. DECTPU passes through to the application any closure value received as part of a callback.
DECwindows EVE provides an example of how an application can use closure values. DECwindows EVE assigns a unique closure value to every widget instance that can be created during an EVE editing session. Each closure value corresponds to something that EVE must do in response to the activation of that particular widget. When an event causes DECTPU to execute EVE's main callback program, the GET_INFO (WIDGET, "callback_parameters", array) built-in procedure returns the widget activated, the reason code (the reason the widget is calling back), and the closure associated with the particular widget instance.
EVE's main callback program contains an array that is indexed with values identical to the widget closure values. Each array element contains a pointer to the EVE code to be executed in response to the corresponding widget's callback. EVE's callback program uses the closure value to locate the appropriate array index so the correct EVE routine can be executed in response to the callback.
If your layered application does not use EVE's callback program, then
its callback program or learn sequence must have a mechanism for
determining which widget is calling back and which application code
should be executed as a result.
This section discusses techniques for specifying values for widget
DECTPU supports the following data types with which to specify values for widget resources:
DECTPU converts the value you specify into the data type appropriate for the widget resource you are setting. Table 5-1 shows the relationship between DECTPU data types for widget resources and DECwindows data types for widget resources.
DECTPU does not support setting values for resources (such as pixmap, color map, font, icon, widget, and so on) whose data types are not listed in this table.
When you pass an array that specifies values for a widget's resources
by using CREATE_WIDGET or SET (WIDGET), DECTPU verifies that each array
index is a string that corresponds to a valid resource name for the
specified widget. DECTPU also verifies that the data type of the value
you specify is valid for the specified resource.
List box and file selection widgets manipulate lists. For example, the file selection widget manipulates a list of files. The widget resource that stores such a list is specified to DECTPU by using an array.
To handle an array that passes a list to a widget, DECwindows must know how many elements the array contains. For example, if you set the value of the "items" resource of a list box widget to point to a given array, DECwindows does not handle the array successfully unless the list box widget's "itemsCount" resource contains the number of elements in the array.
However, you do not necessarily know how many elements the array has at a given moment. To help you pass arrays, DECTPU has a convention for referring to widget resources. If you follow the convention, DECTPU will handle the resource that stores the number of array elements.
The following paragraphs discuss the naming convention in more detail.
When you use the SET (WIDGET) built-in procedure to pass a list to a widget, you must specify both the list name and the list count resource in the same array index, separated by a line feed (ASCII (10)). The array element should be the array that is to be passed. For example, to specify the "items" resource to the list box widget, use code similar to the following:
The line-feed character, ASCII (10), is a delimiter that separates two resource names.
DECTPU automatically generates two resource entries. The first is the array of strings that specifies the data to the list box for the "items" resource. The second is the count of elements in the array for the "itemsCount" resource.
To get resource values from a widget, use the following statement:
The indices of the array parameter are strings or string constants that name the resources whose values you want. (The initial values in the array are unimportant.) The GET_INFO statement directs DECTPU to fetch the specified resource values of the specified widget and put the values in the array.
For list box widgets or file selection widgets, one element of the array receives another array that contains the list manipulated by the widget. The indices of this array are of type integer. The lowest index has the value 0, and each subsequent index is incremented by 1. The contents of the array elements are of type string.
When you create the index of the element that receives the widget's list, you must observe the same naming convention as for setting resources so that DECTPU can handle both the list itself and the resource value that specifies the length of the list. Give the index the following format:
For example, if you used GET_INFO (widget, "WIDGET_INFO", array) to get resource values from a list box widget, you could specify the index for the element storing the widget's list as follows:
The element for the widget's list does not actually contain an array until after execution of the GET_INFO statement. When DECTPU encounters the GET_INFO statement, it parses the indices of the specified array. When DECTPU parses the index of the element for the widget's list, it fetches both the list itself and the length of the list. Using the resource specifying the length, DECTPU creates an array of the correct size to hold the widget's list.
See the DEC Text Processing Utility Reference Manual for
sample uses of DECwindows DECTPU built-ins.
This section provides information useful for programmers who extend
DECwindows EVE or layer applications on DECwindows EVE.
This section is intended for programmers who are extending EVE or layering an application on EVE.
There are four possible types of selection:
EVE can use only one type of selection at a time. The ways in which these selections differ are explained in the following sections.
EVE has a routine called EVE$SELECTION that returns the current
regardless of whether the selection is dynamic, static, formed from a
found range, or the primary global selection. You can use the
SELECT_RANGE built-in procedure to get the current selection if the
selection is a dynamic selection. However, Compaq recommends that you
use EVE$SELECTION to get the current selection because this routine
returns the current selection regardless of how it was created. To see
how the EVE$SELECTION routine works and what parameters it takes, see
the code for this routine in SYS$EXAMPLES:EVE$CORE.TPU.
When you press the Select key or invoke the SELECT command, EVE creates a dynamic selection. A dynamic selection expands and contracts as you move the text cursor. Moving the text cursor away from the text already selected does not cancel the selection. If you use the mouse to start a selection while a dynamic selection is active, the dynamic selection is canceled.
If EVE's current selection is a dynamic selection, the routine EVE$SELECTION returns the selected range and terminates the selection. If, for some reason, you want to use a statement that returns the current dynamic selection but does not terminate it, you can use a statement whose format is similar to the following:
The last parameter directs EVE$SELECTION not to terminate the
selection. For more information on how to use these parameters, see the
EVE$SELECTION routine in SYS$EXAMPLES:EVE$CORE.TPU.
EVE creates a static selection if you do any of the following:
EVE implements a static selection by creating a range upon which you can perform EVE commands such as STORE TEXT or REMOVE. However, EVE does not use the DECTPU SELECT built-in procedure to start this range. Thus, if you use the SELECT_RANGE built-in while a static selection is active, DECTPU returns the message "No select active."
If you move the text cursor off the text in the static selection, the
selection is canceled.
When EVE positions to the beginning of a range as the result of the FIND command, the WILDCARD FIND command, or pressing the Find key, EVE creates a found range that contains the text EVE found as a match for your search string. If no other selection is active, EVE treats the found range as the current selection.
EVE implements a found range selection by creating a range upon which you can perform EVE commands such as STORE TEXT or REMOVE. However, EVE does not use the DECTPU SELECT built-in procedure to start this range. Thus, if you use the SELECT_RANGE built-in while a found range selection is active, DECTPU returns the message "No select active."
If you move the text cursor off the text in the found range selection,
the selection is canceled.
If EVE has a dynamic selection or a static selection active, that selection is automatically designated as the primary global selection. A found range selection is not designated as the primary global selection.
You can use the routine EVE$SELECTION to get the text of the primary
global selection when an application other than DECTPU owns the
selection. To do so, the call to EVE$SELECTION must be in code bound to
a mouse button other than MB1. The value returned is a string that
contains the text of the primary global selection.
Before compiling programs in DECTPU, you should enable the display of informational messages to help you locate errors. EVE automatically enables the display of informational messages for you when you use the EXTEND EVE command. For more information on displaying messages, see the description of the SET (INFORMATIONAL) built-in procedure in the DEC Text Processing Utility Reference Manual.
The DECTPU compiler numbers the lines of code it compiles. The line numbers begin with 1. For a string, all DECTPU statements are considered to be on line 1. For a range, line 1 is the first line of the range, regardless of where in the buffer the range begins. Buffers are numbered starting at the first line. When a compilation error occurs, DECTPU tells you the approximate line number where the error occurred. To move to the line at which the error occurred, use the POSITION (integer) built-in procedure.
There are two ways to compile a program in DECTPU: on the command line
of EVE or in a DECTPU buffer.
You can compile a simple DECTPU program by entering it on the EVE
command line. For example, if you use the TPU command and then enter
the SHOW (SUMMARY) statement, DECTPU compiles and executes the program
associated with the SHOW (SUMMARY) statement.
DECTPU programs are usually compiled by entering DECTPU procedures and statements in a buffer and then compiling the buffer. If you are using EVE, you can enter the SHOW (VARIABLES) command in a buffer and compile the buffer by using the TPU command and entering the following statement after the prompt:
The program associated with SHOW (VARIABLES) is not executed until you enter the following statement:
If you use a buffer, a range, or a string as the parameter for the EXECUTE built-in procedure, DECTPU first compiles and then executes the buffer, range, or string. See the description of EXECUTE in the DEC Text Processing Utility Reference Manual.
The COMPILE built-in procedure optionally returns a program data type. If you want to use the program that you are compiling later in your session, you can assign the program that is returned to a variable. The following example shows how to make this assignment:
If no error messages are issued while you compile the current buffer, you can then execute the program new_program with the following statement:
You can use the COMPILE built-in procedure to compile certain parts of a buffer rather than a whole buffer. To do so, create a range that includes the statements within the buffer that you want compiled, and then specify the range as the parameter for COMPILE.