Kenton Lee

X Toolkit and Xlib Application Resources

by Kenton Lee

August, 1995

Copyright © 1995 Kenton Lee, All Rights Reserved.


X Toolkit resources are the primary programming interface to X Toolkit widgets. As I've discussed in previous articles, widget resources allow both the programmer and the end user to easily configure the widget user interface.[1,2,3]

The usefulness of X resources, however, is not limited to widgets. In this month's Advanced Application Development column, I'll discuss ways to use resources that are not associated with widgets. Non-widget resources can be very useful to application programmers. For example, you could use them to:

While non-widget resources do not provide quite as much functionality as widget resources, they do allow you to:

In this column, we'll cover two non-widget resource mechanisms. One uses the X Toolkit and takes advantage of the X Toolkit's automatic resource handling features. The other is based on Xlib and provides a little more flexibility in some cases.

X Toolkit Application Resources

The X Toolkit supports non-widget resources through its application resource feature. You may be familiar with built-in application resources such as XtNselectionTimeout and XtNsynchronous. These resources allow end users to configure the X Toolkit's non-widget functionality through the normal command line or resource file mechanisms. You can use the same feature to define and use your own application resources.

For example, when developing your program you may want to implement a special debug mode or be able specify configuration information. Since you want to be able to change these options quickly, traditional techniques such as conditional compilation flags aren't very attractive. Application resources make these options easy.

There are three required and one optional steps to defining and using application resources:

  1. specify a data structure to contain the retrieved resource values
  2. define the resource names, classes, types, and default values with an XtResource list
  3. use XtGetApplicationResources() to fill in the data structure
  4. (optional) if you wish, you may add your application resources to your command-line resource parser

The first step is to define and declare a data structure to hold the resource values. In a C language program, this is usually a simple struct. In C++, it may also be a class. For example, this structure holds three variables (of varying types).

    /* application resources data structure */
    typedef struct {
        Boolean debug;
        Cardinal numButtons;
        String baseName;
    } AppResourcesRec;
    AppResourcesRec appRes;

The next step is to define the resources themselves, including their names, types, and default values. X Toolkit resources, whether for application resources or for widget resources, are defined using an XtResource list. For our three resources, the list looks like this:

    /* application resources specification */
    XtResource appResourcesSpec[] = {
        { "debug", "Debug", XtRBoolean, sizeof(Boolean),
            XtOffsetOf(AppResourcesRec, debug),
            XtRImmediate, (XtPointer)False },
        { "numButtons", "NumButtons", XtRInt, sizeof(int),
            XtOffsetOf(AppResourcesRec, numButtons),
            XtRImmediate, (XtPointer)3 }
        { "baseName", "BaseName", XtRString, sizeof(String),
            XtOffsetOf(AppResourcesRec, baseName),
            XtRString, (XtPointer)"base" },
    };

Each element of this the above list defines one resource. In case you haven't seen a resource definition before, let's review the fields of the first resource definition line.

Now that we've specified the resources and the data structure to hold them, we must add a line of code to parse the resources at run time:

    XtGetApplicationResources(widget, (XtPointer) &appRes, 
        appResourcesSpec, XtNumber(appResourcesSpec), NULL, 0);

The first argument to this function is a widget within your application. As you know, X Toolkit resources are defined in hierarchical fashion, with the hierarchy matching the widget instance hierarchy. The widget in this example specifies how your application resources are to be retrieved with respect to your resource hierarchy. In most cases, you should just use your application shell widget, since it has the same name and class as your application. The next three arguments to XtGetApplicationResources() are just the structures we defined above. The last two arguments allow you to programmatically set application resources, though, in practice, this feature is usually disabled by specifying NULL values.

Figure 1 presents a complete example program using the X Toolkit application resources feature, including command-line processing. This program creates a number of push button widgets, with the number and names of the widgets controlled by the application resources. The program uses two Motif widget, but these could be replaced with equivalent widgets from any other widget set.



/* X Toolkit application resources example program */
#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <stdio.h>

/* application resources data structure */
typedef struct {
Boolean debug;
Cardinal numButtons;
String baseName;
} AppResourcesRec;
static AppResourcesRec appRes;

/* application resources specification */
static XtResource appResourcesSpec[] = {
{ "debug", "Debug", XtRBoolean, sizeof(Boolean),
XtOffsetOf(AppResourcesRec, debug),
XtRImmediate, (XtPointer)False },
{ "numButtons", "NumButtons", XtRInt, sizeof(int),
XtOffsetOf(AppResourcesRec, numButtons),
XtRImmediate, (XtPointer)3 },
{ "baseName", "BaseName", XtRString, sizeof(String),
XtOffsetOf(AppResourcesRec, baseName),
XtRString, (XtPointer)"base" }
};

/* command line options specification */
static XrmOptionDescRec optionsSpec[] =
{
{ "-debug", "*debug", XrmoptionNoArg, "True" },
{ "-buttons", "*numButtons", XrmoptionSepArg, 0 },
{ "-base", "*baseName", XrmoptionSepArg, 0 }
};

void main(int argc, char **argv) {
Cardinal n;
XtAppContext app;
Widget wTop, wRC;

/* initialize Xt, including command line options */
wTop = XtAppInitialize(&app, "Res",
optionsSpec, XtNumber(optionsSpec),
&argc, argv, NULL, NULL, 0);

/* load application resources */
XtGetApplicationResources(wTop, (XtPointer)&appRes,
appResourcesSpec, XtNumber(appResourcesSpec), NULL, 0);

wRC = XtCreateManagedWidget("rc", xmRowColumnWidgetClass, wTop,
NULL, 0);

/* create widgets, using values from application resources */
for (n = 0; n < appRes.numButtons; n++) {
char name[100];
sprintf(name, "%s_%d", appRes.baseName, n);
XtCreateManagedWidget(name, xmPushButtonWidgetClass, wRC,
NULL, 0);
if (appRes.debug)
printf("creating button %s\n", name);
}

XtRealizeWidget(wTop);
XtAppMainLoop(app);
}

Figure 1: X Toolkit Application Resources Example


See what happens when you run the program as:

    prog -base foobar -buttons 5 -debug

Application resources are the intended way for application programmers to implement application-level X Toolkit resources. In some cases, however, you may want to create a special resource name hierarchy for your application resources. In these cases, you can use XtGetSubResources() in place of XtGetApplicationResources(). XtGetSubResources() is intended for internal widget use only, but it also works at the application level.[5] The syntax and semantics of the two functions are almost the same, except that XtGetSubResources() allows you to specify an additional resource part name and class.

Note that application resources and widget subresources don't provide all the functionality of widget resources. In particular, there is no way for widget oriented programs like editres[3] to retrieve application resources.

For more information on the X Toolkit's application resources, widget subresources, or command line parsing features, please see an X Toolkit tutorial book, such as X Window System Toolkit[4].

Xlib Resource Manager

While X Toolkit application resources are very powerful, giving you access to the X Toolkit's command line parser and resource converter features, application programmers sometimes prefer using a simpler database mechanism. For those cases, Xlib's resource manager Xrm might be more appropriate.

The X Toolkit resource mechanism is based on Xrm and both use the same resource file syntax. If, at some later point in time, you wish to change your resource handling API from Xrm to X Toolkit application resources (or vice versa), you can easily do so while maintaining file format compatibility.

One advantage of the Xrm API is that it allows you to easily create and manage multiple independent resource databases and named resource files. You may, for example, want to create a set of configuration options that can be modified via your application program's user interface. When the user changes the configuration, you may want to save these to a specified file so that you may restore them the next time the user runs your program. An easy way to manage these resources is put them in a private resource database that your program maintains separately from the main X Toolkit resource database.

Xrm provides functions to read resources from specified resource files into private resource databases and also to write databases out to files. Xrm also provides functions to get and set the values of resources in private databases.

Figure 2 is a simple example of the basic Xrm functions. It creates a resource database from a resource file, gets a string resource "myResource" (class "MyResource"), prints out its value, changes the value, and writes the changed database back to the file.


/* Xrm example program */
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <stdio.h>
#include <string.h>

main(int argc, char **argv)
{
    XrmValue xrmv;
    char *type, *value;
    int status;
    XrmDatabase db;

    /* initialize Xrm and load our database */
    XrmInitialize();
    db = XrmGetFileDatabase(".myrc");

    /* retrieve our resource and print out the value */
    status = XrmGetResource(db, "myResource",
        "MyResource", &type, &xrmv);
    if (status && (strcmp(type, "String") == 0)) {
        value = (char *) xrmv.addr;
        printf("resource was %s\n", value);
    } else
        printf("resource does not exist\n");

    /* change the value of the resource */
    XrmPutLineResource(&db, "myResource: newValue");

    /* write database back to file */
    XrmPutFileDatabase(db, ".myrc");

    /* free the database from memory */
    XrmDestroyDatabase(db);
}

Figure 2: Simple Xrm Example


There are many more Xrm functions and the Xlib manual[6] does a good job of documenting them. Only those used above, however, are really necessary for simple resource databases. Here are some hints that you may find helpful when using Xrm:


Conclusion

X Toolkit widget resources are a simple, but powerful programming and configuration mechanism. Application programmers can take advantage of this functionality in non-widget contexts as well.

This month's column discusses two non-widget resource features. The X Toolkit's application resource mechanism provides almost all of the functionality of widget resources. Xlib's resource manager provides a simpler mechanism that may be appropriate in certain applications.

I've used both features extensively in my application programs, with good success.


References
  1. Kenton Lee, " `Indirect' Motif Widget Resources," The X Journal, March, 1995.
  2. Kenton Lee, " Widget Resource Syntax Errors," The X Journal, May, 1995.
  3. Kenton Lee, " Debugging Widget Resources with Editres," The X Journal, November, 1994.
  4. Paul Asente and Ralph Swick, X Window System Toolkit, Digital Press, 1990.
  5. Douglas Young, Object-Oriented Programming with C++ and OSF/Motif, Prentice-Hall, 1992.
  6. Robert Scheifler and James Gettys, X Window System (third edition), Digital Press, 1992.


Ken Lee is an independent software consultant specializing in X Window System application software. He has been developing UNIX graphical user interface software since 1981. Ken may be reached by Internet electronic mail at kenton @ rahul.net or on the World Wide Web at http://www.rahul.net/kenton/.

Ken has published over two dozen technical papers on X software development. Most are available over the World Wide Web at http://www.rahul.net/kenton/bib.html.