Motif widget class such as XmPushButton or XmForm in a callback declaration. Finally, you can indicate that an
argument is expected, but not restrict its type, by specifying the special type−name any. If you use the any specifier,
you should take extra care to ensure that references to the procedure elsewhere in the UIL module do not pass values
to the callback that might crash your application. This problem has been fixed as of Motif Release 1.2.3.
The UIL compiler makes sure that the use of a callback is consistent with its declaration. If you declare a callback as
taking no arguments, you cannot pass an argument to the callback when you use it. Likewise, when a callback does
take an argument, you must provide one when you use the routine, and the argument must match the type in the
declaration. You can pass an argument whose type does not match the declaration if the UIL automatic type
conversions described earlier provide for it. For example, you can pass a string to a callback that is declared as
taking a compound_string. If the use of a callback does not agree with its declaration, the UIL compiler generates
an error, and the module is not compiled successfully. The following code fragment shows how you might use the
print and quit callbacks:
object close : XmPushButton {
callbacks {
XmNarmCallback = procedure print ("Armed!");
XmNactivateCallback = procedure quit();
};
};
When a callback specified in a UIL module is invoked at run−time, the argument, if any, is passed to the callback as
the client_data parameter. In this example, the string "Armed!" is passed to the print() callback when the
PushButton is armed. The callback simply prints the argument that is passed to it. This routine is shown in the
following code fragment:
void
print (w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
char *message = (char *) client_data;
puts (message);
}
You should always cast the client_data argument to the appropriate type before using it, as this fragment
illustrates. The argument type depends on the UIL value passed to a callback. contains a complete listing of the UIL
data types and the corresponding C types. In particular, you should note that the integer, float, and boolean
numeric types are passed as pointers to the values, not the values themselves.
25.5 Using Lists
A UIL list is a group of widget children, resource settings, callback settings, or callback procedures. Although we
didn't mention it earlier, the controls, arguments, and callbacks subsections of a widget definition are all
in−line lists. The procedures syntax for specifying multiple callbacks is also an in−line list. You can also define a
list outside of a widget definition and name it, so that you can use the list later in a widget definition or in another list.
You define named lists in a list section of a UIL module, which begins with the list keyword. A list definition
consists of the name of the list, followed by a colon, the type of the list, and its contents. Unlike variable and widget
definitions, list definitions are always private to a module, so you cannot export them. If you want to use a list in more
than one module, you should place its definition in a UIL include file. The list name is a programmer−specified
identifier; the list type is one of controls, arguments, callbacks, or procedures. The content of a list
25 Creating a User Interface With UIL 25.5 Using Lists
692
depends on its type.
Lists of controls, arguments, and callbacks, like the widget subsections by the same name, contain widget
children, resource settings, and callback settings, respectively. The format of each of these lists is the same as the
format of the corresponding subsection of a widget definition. A procedures list is used to specify multiple
callback routines for a particular callback reason, as we explained earlier. Once you define a named list, you can use it
in a widget definition. the source code shows a UIL module that uses all four types of lists.
/* simple_lst.uil −− simple example of lists */
module simple_lst
procedure
quit();
print (string);
list buttons : controls {
XmPushButton OK;
XmPushButton Help;
};
list size : arguments {
XmNwidth = 50;
XmNheight = 50;
};
list funcs : callbacks {
XmNactivateCallback = procedure print ("Help!");
XmNhelpCallback = procedure print ("Help!");
};
list ok_cbs : procedures {
print ("Okee−dokee");
quit();
};
object OK : XmPushButton {
arguments size;
callbacks {
XmNactivateCallback = procedures ok_cbs;
};
};
object Help : XmPushButton {
arguments size;
callbacks funcs;
};
object root : XmRowColumn {
controls buttons;
};
end module;
As with the object definition, we use the convention of placing each list definition in its own list section, even
though it is not necessary for consecutive definitions. This example defines the buttons, size, funcs, and
ok_cbs lists, and then uses the lists in defining the widget hierarchy. To use a list in a widget definition, you specify
the subsection followed by the name of a list. The named list replaces the in−line list definition that you have seen
25 Creating a User Interface With UIL 25.5 Using Lists
693
previously. The UIL compiler makes sure that the type of each named list matches the name of the subsection, which
means that you cannot specify a named controls list for an arguments subsection, for example.
A named list definition lets you separate the contents of each list type from a widget definition. One advantage of
this approach is that you can abstract commonly−used settings and define them in one place. However, the ability to
factor out duplicate widget subsections and procedure lists is not that big of an advantage. The feature of lists that
makes them more useful is the ability to reference other lists of the same type. You include one list in another by
including an entry that consists of the type of the included list, followed by the name of the list to include.
Each reference to a list includes a copy of that list, which has different results depending on the type of the list. When
you include a controls or procedures list in another list, the widgets or callbacks in the included list are added
to the existing list, even if the same widget or callback is already there. Therefore, you can create multiple instances of
the same widget or call the same callback multiple times. When you include an arguments or callbacks list in
another list, the resources or callback settings in the included list are added to the existing list, but any duplicate
setting supersedes the earlier setting. The advantage of this behavior is that you can selectively override resource or
callback settings that have already been specified. When you override a resource or callback setting, the UIL compiler
generates an informational message. You can turn off these messages with the −w compiler option, but you should be
careful to do so only if you know that a module does not generate any other warnings. the source code illustrates the
use of nested lists.
/* station.uil −− Example of using lists in lists */
module dialog
list basic_buttons : controls {
OK : XmPushButton { };
Cancel : XmPushButton { };
};
list extended_buttons : controls {
controls basic_buttons;
Help : XmPushButton { };
};
list attach_all : arguments {
XmNtopAttachment = XmATTACH_FORM;
XmNbottomAttachment = XmATTACH_FORM;
XmNleftAttachment = XmATTACH_FORM;
XmNrightAttachment = XmATTACH_FORM;
};
object stations : XmRadioBox {
controls {
WAQY : XmToggleButton { }; KLBJ : XmToggleButton { };
WPLR : XmToggleButton { }; KRCK : XmToggleButton { };
WHCN : XmToggleButton { }; KPEZ : XmToggleButton { };
};
arguments {
XmNorientation = XmHORIZONTAL;
XmNnumColumns = 3;
XmNmarginWidth = 20;
arguments attach_all;
XmNbottomAttachment = XmATTACH_NONE;
};
};
25 Creating a User Interface With UIL 25.5 Using Lists
694
object panel : XmRowColumn {
controls extended_buttons;
arguments {
XmNorientation = XmHORIZONTAL;
XmNentryAlignment = XmALIGNMENT_CENTER;
XmNpacking = XmPACK_COLUMN;
arguments attach_all;
XmNtopAttachment = XmATTACH_WIDGET;
XmNtopWidget = stations;
};
};
object root : XmFormDialog {
controls {
XmRadioBox stations;
XmRowColumn panel;
};
arguments {
XmNdialogTitle = "Station Chooser";
};
};
end module;
This module describes a simple user interface that uses two different types of lists. The output of the module is shown
in the figure.
The basic_buttons list is a controls list that consists of two PushButtons: OK and Cancel. The
extended_buttons list builds on the first list by adding a Help PushButton. This list is used as part of the dialog
later in the module. The attach_all list is an arguments list that contains several Form attachment resource
settings. We reference this list in the definition of both the RadioBox and the RowColumn, instead of reproducing the
same settings in both widget definitions. In both cases, we override one of the resource settings from the list in the
widget definition. This section only covers the basic use of lists in a UIL module. For more information on using lists,
see Section #suiladvlist in Chapter 26, Advanced UIL Programming.
User interface of station.uil
25 Creating a User Interface With UIL 25.5 Using Lists
695

Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.