argument count at this point and issue an error message if any spurious arguments are found. The seventh argument is
the start of a NULL−terminated list of fallback resources for the top−level shell widget created by the initialization
call. Fallback resources provide a kind of "belt and suspenders" protection against the possibility that an app−defaults
file is not installed. They are ignored if the app−defaults file or any other explicit resource settings are found. When
no fallback resources are specified, the seventh argument should be NULL.
It is generally a good idea to provide fallbacks for resources that are essential to the operation of your application. An
example of how fallback resources can be used by an application is shown in the following code fragment:
String fallbacks[] = {
"Demos*background: grey",
"Demos*XmList.fontList: −*−courier−medium−r−*−−12−*",
"Demos*XmText.fontList: −*−courier−medium−r−*−−12−*",
/* list the rest of the app−defaults resources here ... */
NULL
};
...
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, fallbacks, NULL);
...
Fallback resources protect your application against a missing app−defaults file, but they do not guard against one that
is modified incorrectly or otherwise corrupted, since they are not used if the app−defaults file is present in any form.
A better fallback mechanism would provide protection against these types of problems. Fortunately, X11 Release 5
introduces a new function, XrmCombineDatabases(), that allows you to provide real fallbacks in case the user or
the system administrator misconfigures the app−defaults file. The eighth parameter is the start of a NULL−terminated
list of resource/value pairs that are applied to the top−level widget returned by XtVaAppInitialize(). If there
are no resource settings, which is often the case for this function, you can pass NULL as the eighth parameter. If you
do pass any parameters, it should be done just as we describe for XtVaCreateWidget() later in this chapter. All
of the functions whose names begin with XtVa support the same type of varargs−style (variadic) argument lists.
The X11 Release 4 implementation of XtVaAppInitialize() and other varargs functions may not work entirely
as expected for some non−ANSI−C compilers due to a bug in the way that Xt declares variadic functions. This
problem only arises for some compilers that do not understand function prototypes. The problem is rare since it is
compiler−dependent and it only happens on older compilers. It is not a compiler error but an Xt error, since functions
are not supposed to mix fixed parameter declarations with variadic declarations. XtVaAppInitialize() mixes
these declarations; the first seven parameters are fixed while the eighth through nth arguments are variadic. ANSI−C
allows, and even requires, this type of specification.
If you experience problems such as segmentation faults or bus errors as a result of using XtVaAppInitialize(),
you can try passing an extra NULL parameter after the final NULL. Another option is to use XtAppInitialize(),
which is identical to XtVa-AppInitialize(), but does not contain a variable argument list of resource/values
pairs. Instead, it uses the old−style args and num_args method of specifying resource values, which we describe
later in this chapter.
3.3.4 Creating Widgets
There is a convenience function for creating every class of widget and gadget supported by the Motif toolkit. For
example, to create a PushButton widget, you can use the function XmCreatePushButton(). To create the
corresponding gadget, you can use XmCreatePushButtonGadget(). In addition, there are convenience
functions for creating compound objects. A compound object is a collection of widgets that is treated like a single
object. For example, a ScrolledList object is really a List widget inside a ScrolledWindow widget.
3 The Motif Programming Model 3.3.4 Creating Widgets
30
XmCreateScrolledList() creates the compound object consisting of both widgets.
The convenience functions for creating all of the different types of widgets are described in Volume Six B, Motif
Reference Manual. In the examples in this book, however, we -typically use the Xt functions
XtVaCreateWidget() and XtVaCreateManagedWidget() for creating simple widgets. These functions
allow you to decide whether to create a widget as managed or unmanaged, while the Motif convenience functions
always create unmanaged widgets. The Xt routines also allow you to set resources for a widget using the varargs
interface, which is more convenient than the args and num_args method used by the Motif creation routines.
X nests windows using a parent−child model. A display screen is defined as the root window; every application has a
top−level window that is a child of the root window. A top−level window in turn has subwindows, which overlay it
but cannot extend beyond its boundaries. If a window extends beyond the boundaries of its parent, it is clipped.
Because every widget has its own X window, widgets follow a similar parent−child model. Whenever a widget is
created, it is created as the child of another widget. The shell widget returned by the call to
XtVaAppInitialize() is the top−level widget of an application. It is usually overlaid with a special class of
widget called a manager widget, which implements rules for controlling the size and placement of widget children.
For example, the Motif RowColumn widget is a manager that allows widgets to be laid out in regular rows and
columns, while the Form widget is a manager that allows widgets to be placed at precise positions relative to one
another. A manager widget can contain other manager widgets as well as primitive widgets, which are used to
implement actual user−interface controls. Managers also support gadgets. A gadget is a lighter−weight object that is
identical to its corresponding widget in appearance, but does not have its own window.
In the source code the button was created as a child of the top−level shell window. This simple application contains
only one visible widget, so it does not use a manager. Actually, shells are extremely simple managers. A shell can
only have one child; the shell makes itself exactly the same size as the child so the shell remains invisible behind the
child. Here's the call we used to create the button:
button = XtVaCreateManagedWidget ("pushme",
xmPushButtonWidgetClass, toplevel,
XmNlabelString, label,
NULL);
The first argument is a string that is used as the name of the widget in the resource database. If a user wants to specify
the color of the button label for the application, he can use the following specification in a resource file:
hello.pushme.foreground: blue
The name is different from the variable name that is used to refer to the widget in application code. The following
resource specification is not correct:
hello.button.foreground: blue
The resource name does not need to be identical to the variable name given to the widget inside the program, though
to minimize confusion, many programmers make the two names the same. If you want users to be able to configure
widget resources, be sure to include the names of the widgets in your documentation.
The second argument is the class of the widget to be created. This name is defined in the public header file for the
widget. The widget reference pages in Volume Six B list the widget class name for each Motif and Xt widget class.
The third argument is the parent of the widget, which must be a manager widget that has already been created. In this
example, the parent of the PushButton widget is toplevel, the shell widget returned by the call to
3 The Motif Programming Model 3.3.4 Creating Widgets
31

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

O’Reilly members experience live online training, plus books, videos, and digital content from nearly 200 publishers.