Document revision date: 30 March 2001
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

Guide to the DEC Text Processing Utility


Previous Contents Index

5.2.4 Using Callbacks

This section presents background information on the DECwindows concept of callbacks and explains how DECwindows DECTPU implements this concept.

5.2.4.1 Background on DECwindows Callbacks

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.

5.2.4.2 Internally Defined DECTPU Callback Routines and Application-Level Callback Action Routines

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.

5.2.4.3 Internally Defined DECTPU Callback Routines with UIL

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.

5.2.4.4 Internally Defined DECTPU Callback Routines with Widgets Not Defined by UIL

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 a callback.

5.2.4.5 Application-Level Callback Action Routines

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.

5.2.4.6 Callable Interface-Level Callback Routines

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.

5.2.5 Using Closures

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.

5.2.6 Specifying Values for Widget Resources in DECwindows DECTPU

This section discusses techniques for specifying values for widget resources.

5.2.6.1 DECTPU Data Types for Specifying Resource Values

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.

Table 5-1 Relationship Between DECTPU Data Types and DECwindows Argument Data Types
DECwindows Argument Data Type DECTPU Data Type
Array of strings Array of strings
Boolean Integer
Callback Integer (0)
Compound string String
Compound string table Array of strings
Dimension Integer
Integer Integer
Position Integer
Short Integer
String String
Unsigned character Integer

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.

5.2.6.2 Specifying a List as a Resource Value

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.

Setting Resources

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:


line_feed := ASCII (10); 
resource_array {"items" + line_feed + "itemsCount"}:=list_array;     
 

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.

Getting Resources

To get resource values from a widget, use the following statement:


GET_INFO (widget, "WIDGET_INFO", array) 

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:


items<line-feed>items_count 

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:


"items" + ASCII(10) + "itemsCount" 

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.

5.3 Writing Code Compatible with DECwindows EVE

This section provides information useful for programmers who extend DECwindows EVE or layer applications on DECwindows EVE.

5.3.1 Select Ranges in 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 selection, 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.

5.3.1.1 Dynamic Selection

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:


r1 := EVE$SELECTION (TRUE, TRUE, TRUE, TRUE, FALSE) 

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.

5.3.1.2 Static Selection

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.

5.3.1.3 Found Range Selection

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.

5.3.1.4 Relation of EVE Selection to DECwindows Global Selection

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.

5.4 Compiling DECTPU Programs

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.

In EVE, you can use the LINE command. For example, the command LINE 42 moves the editing point and the cursor to line 42.

To see DECTPU messages while in EVE, use the BUFFER MESSAGES command. To return to the original buffer or another buffer of your choice, use the BUFFER name_of_buffer command.

There are two ways to compile a program in DECTPU: on the command line of EVE or in a DECTPU buffer.

5.4.1 Compiling on the EVE Command Line

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.

5.4.2 Compiling in a DECTPU Buffer

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:


TPU Statement: COMPILE (CURRENT_BUFFER); 

The program associated with SHOW (VARIABLES) is not executed until you enter the following statement:


TPU Statement: EXECUTE (CURRENT_BUFFER); 

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:


new_program := COMPILE (CURRENT_BUFFER); 

If no error messages are issued while you compile the current buffer, you can then execute the program new_program with the following statement:


EXECUTE (new_program); 

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.


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
6018PRO_011.HTML