Requirements and considerations for UI Toolkit programs

This topic includes the following sections:

 

When writing your program, remember to do the following:

We also recommend that you use event-style programming when using UI Toolkit. This topic discuss these and other issues you should keep in mind when creating UI Toolkit applications.

tools.def

To use UI Toolkit, your program must include tools.def, which contains definitions of keywords required by Toolkit, as well as external function declarations and global status fields. Use the .INCLUDE statement to include this file in your program. Tools.def is in the directory for your UI Toolkit distribution, so you can use the WND environment variable:

.include "WND:tools.def"

If you want to include only part of tools.def in your application, define D_DEFINES_ONLY or D_NO_GLOBAL_DATA (i.e., use one of these in a .DEFINE statement):

For example, you could define D_DEFINES_ONLY and include tools.def before the first routine in the file, and then you would need to include tools.def only in routines that need access to the global data or the function declarations.

D_NO_GLOBAL_DATA can be especially helpful when modularizing your code to be used with xfServerPlus. For example, the following code suppresses the inclusion of global data.

.define D_NO_GLOBAL_DATA
.include "WND:tools.def"

See the comments in tools.def form more information on this file, and see Customizing configuration fields for information on customizing UI Toolkit with tools.def.

Reserved global data section and common field names

All Toolkit global data section names begin with “DTK_”. UI Toolkit also uses names that begin with “GLST_” for common field names. Therefore, to avoid potential conflicts, avoid using names beginning with “DTK_” or “GLST_” for common fields or global data sections.

Channel usage

The UI Toolkit subroutines use variables for all channels. In the past, most programs “hard-coded” their channel numbers by using decimal literals (1, 15, 32, and so forth). However, hard-coding can get you into trouble—for example, you might inadvertently use a channel that is already in use. Enabling the development environment to manage the I/O channels eliminates this problem, since Toolkit assigns the channels and maintains a database so channels don’t get re-used inappropriately.

UI Toolkit uses three types of channels: system channels, global channels, and local channels.

A system channel is reserved for use by the system. That is, you may not manipulate it with U_OPEN, U_CLOSE, U_GBLCHN, and so forth. The terminal channel opened by U_START is a system channel, and so are all channels that have been excluded from Toolkit use, such as those before or after the first_channel through last_channel range passed to U_START. These channels may be accessed through non-Toolkit calls, but we do not recommend it.

UI Toolkit uses the default terminal channel, which is opened automatically when the program starts. When an OPEN(chn, i, “TT:”) or OPEN(chn, o, “TT:”) is performed, that channel number is mapped to the default terminal channel. When the channel is closed, the mapping is removed. The default terminal channel is closed only when the program exits.

Important

On OpenVMS, the default terminal channel opens SYS$INPUT and SYS$OUTPUT for input and output. When running a Toolkit program from a command file, if you want to get input from the terminal device instead of the command file, add the line

$ define/process sys$input sys$command

before the command line where you run your Toolkit program.

A global channel is a channel that you can open or close. You can either open it as a global channel or promote it to global later. You cannot automatically close a global channel with an E_EXIT from the environment in which it was opened; however, you can close it using a U_CLOSE at any time.

You can also open a local channel, but it will be closed automatically (with purge) when the environment in which it was opened is exited. Unlike local windows, a local channel may also be closed using U_CLOSE at any environment level.

For information about opening and closing channels, see U_OPEN and U_CLOSE.

Event-driven programming

Programming with UI Toolkit is most effective if you use event-driven (or event-style) programming. Toolkit uses black-box processing, and event-driven programming takes full advantage of this feature. For more information, see Black-box processing.

In event-driven programming, control of your program is turned over to UI Toolkit by calling a Toolkit routine. When the Toolkit routine completes its processing, it returns control to your program. Your program tests an exit flag for the “event” that caused the routine to exit. Based on the result of this test, your program performs the appropriate function.

The UI Toolkit event loop

UI Toolkit is designed so this event-driven technique works best in a loop (REPEAT, DO UNTIL, and so forth). We call this the “Toolkit event loop.” It works for any of the UI Toolkit functions: input processing, menu processing, text editing or viewing, or list processing.

At the top of your loop, you call a Toolkit routine. For example, you may call a routine to do input processing. UI Toolkit will start input processing, and any input from the user will be processed by Toolkit.

When Toolkit determines that the user has input something that meets its criteria for termination of input processing, a flag (or flags) will be set, the input routine will exit, and control will be returned to your program.

Immediately following the call to the input processing routine, your program will perform a test, or series of tests, to determine the reason input processing exited. Using the test results, you can have your program call another routine, look up a record in a file, validate data, exit the input processing loop, or anything else that can be done with Synergy DBL.

When your program has done what it needs to do, it returns to the top of the loop and calls the input processing routine to get more input.

The complete steps for using event-driven programming are as follows:

1. Remove any unnecessary menu columns from the menu bar.
2. Place necessary menu columns on the menu bar.
3. Set up the following loop:

Throughout this manual, you will be exposed to the UI Toolkit event loop. We encourage you to study this sample code, and better still, try writing some small programs using this technique. Once you become comfortable with this programming style, you will be well on your way to becoming a productive Toolkit developer.

Error processing

Synergy DBL runtime errors (with the exception of most window errors) can be trapped with calls to the FATAL subroutine, with ONERROR statements, and with TRY-CATCH blocks.

When a Toolkit error or a window error is generated, the error is automatically sent to U_ABORT, unless the error is returned in an argument for a Toolkit routine, such as the error argument for L_CREATE. (If this happens, the error number is returned in the argument, and you can use %U_GETWNDERR to get the error text.) If an error is sent to U_ABORT, it will either perform a STOP and display a fatal error message (the default), or it will throw an error that can be trapped by an ONERROR statement. For more information, see U_ABORT and %U_GETWNDERR.

Bounds checking

Bounds checking detects memory access errors (buffer overruns), where a reference exceeds the calling routine’s data space, including such failures as data being overwritten and segmentation violations. There are several ways to use bounds checking with Toolkit applications:

Note that if g_dtkbounds is set to 2, you can use DTK_BOUNDS_LOG to log nonfatal errors to a file.

In traditional Synergy on Windows, the default Toolkit library (tklib.elb) is built with one of the Synergy compiler options for bounds checking (-qstrict) by default. If you want more thorough checking, you can use tklib_qcheck.elb, which is a version of the Toolkit library built with the -qcheck Synergy compiler option. To use this library, link against it (WND:tklib_qcheck.elb) and build your entire application using -qcheck. Note, however, that -qcheck is not generally recommended for production builds.

In Synergy .NET, all applications use bounds checking that is automatically provided by the Synergy .NET compiler. The -qstrict and -qcheck compiler options don’t apply to Synergy .NET, but you can use g_dtkbounds/DTK_BOUNDS and DTK_BOUNDS_LOG. Compiler and runtime checks will generally preclude g_dtkbounds/DTK_BOUNDS checking, but in some cases this checking may detect additional issues.

Callbacks

A callback is a call to a Toolkit program from a routine that is not part of the Toolkit program—i.e., a callback routine. On UNIX and OpenVMS, all callbacks are synchronous. On Windows, a callback can be synchronous (e.g., a call to EUTILS_METHOD) or asynchronous (e.g., a call to click method). Most are asynchronous. Note the following:

Resizing the application

You can resize a UI Toolkit application by using U_RESIZE to specify the number of rows and columns for the application.

With traditional Synergy on Windows, you can also scale an application. That is, you can increase or decrease the size of the display screen, the windows for the application, and the text in those windows.

You can also instruct Toolkit to perform special processing when an application is resized with %EAPPSTATE_METHOD.

Monitor scaling and resolution on Windows

Although we improved support for high-DPI monitors with Synergy/DE version 11, support is limited due to Windows limitations. Note the following: