if (status != MrmSUCCESS)
error ("Unable to open hello_world.uid file.");
status = MrmRegisterNames (callback_list, XtNumber (callback_list));
if (status != MrmSUCCESS)
error ("Unable to register callback functions with Mrm.");
status = MrmFetchWidget (hierarchy, /* hierarchy to search */
"hello_main", /* object name */
toplevel, /* parent */
&hello_main, /* widget created */
&class_code); /* widget's class code */
if (status != MrmSUCCESS)
error ("Unable to create interface from UID file");
MrmCloseHierarchy (hierarchy);
XtManageChild (hello_main);
XtRealizeWidget (toplevel);
XtAppMainLoop (app_context);
}
Compiling this program is similar to any other Motif application−−we just need to add the Mrm library to the link
line. Because the program consists of a single file, we can use the following command to compile it on most UNIX
systems:
cc −o hello_world hello_world.c −lMrm −lXm −lXt −lX11
You should note that this program, like any program that uses Mrm, includes the file <Mrm/MrmAppl.h>. This file
contains the function prototypes and constant definitions necessary to use Mrm. It also includes the <Xm/Xm.h> file,
which contains the necessary declarations and definitions for the Motif library. When you use Mrm, there's no need to
include a header file for each type of widget in the interface because the interface is not created directly in C.
However, if your application uses any widget convenience functions, you do need to include the appropriate widget
header file(s).
23.5.1 Initializing the Application
The first step for any Motif application is the initialization of the library components. The addition of Mrm doesn't
change this−−the initialization process is just a little more involved. As you can see in the figure, initialization is the
most involved step in an Mrm application. Before initializing any of the libraries, the hello_world.c program calls
XtSetLanguageProc(). This function sets the default procedure used to establish the run−time language
environment. In X11R5 you should be sure to include this call before any other X−related initialization since other
libraries depend on the language setting.
Next, we initialize the Mrm library by calling MrmInitialize(). This routine sets up internal data structures that
Mrm needs to create widgets and should be called prior to initializing Xt. You should call this function only once,
preferably when your application is starting up. Unlike the other Mrm functions, MrmInitialize() does not
return a status value.
You may run across some code that initializes Mrm after Xt. While the order doesn't matter currently, the OSF
documentation specifically states that you should initialize Mrm before Xt, so you should probably follow their
advice. After initializing Mrm, we're ready to initialize Xt with the following call:
23 Introduction to UIL 23.5.1 Initializing the Application
643
toplevel =
XtVaAppInitialize (&app_context, /* application context */
"Hello", /* application class name */
NULL, 0, /* command line options */
&argc, argv, /* argc and argv */
NULL, /* fallback resources */
NULL); /* arg list */
This convenience function initializes the toolkit, creates an application context, opens the display, and creates the
top−level ApplicationShell. This call is used by most Xt and Motif applications. Once both Mrm and Xt are
initialized, we must open the UID files. We use the MrmOpenHierarchyPerDisplay() function to do this. The
form of this function is: The Motif 1.2 MrmOpenHierarchyPerDisplay() function supersedes the Motif 1.1
MrmOpenHierarchy() function that you may encounter in older applications. Motif 1.2 still supports the older
version to remain backwards compatible, but you shouldn't use it.
Cardinal
MrmOpenHierarchyPerDisplay(display, num_files, file_list, os_data,
hierarchy)
Display *display;
MrmCount num_files;
String file_list[];
MrmOsOpenParmPtr os_data[];
MrmHierarchy hierarchy;
The first argument is the Display; the second and third are the number of UID files and an array of filenames to
open; the fourth is an operating system−dependent structure that should always be NULL (it is used internally by the
UIL compiler); and the fifth is the address of an MrmHierarchy value that is filled in by the routine. Here's the call
used by the "Hello, World" application to open its UID file:
String uid_file_list[] = { "hello_world" };
...
status =
MrmOpenHierarchyPerDisplay (XtDisplay (toplevel), /* display */
XtNumber (uid_file_list), /* num files */
uid_file_list, /* file list */
NULL, /* OS data */
&hierarchy); /* hierarchy */
Although we need to open only one UID file in this situation, we use the XtNumber() macro so that we can easily
add filenames to the uid_file_list array. While the "Hello World" interface is described in a single UID file, the
interface of a more complex application is often broken into multiple UID files for organizational and
internationalization purposes. (See Section #suilorg for a discussion on UIL module organization.)
Note that the hello_world filename is missing the .uid extension. We don't need to add it because Mrm supplies the
extension by default. The filenames you pass to this function may be either full pathnames that begins with a slash or
partial pathnames. Full pathnames are opened directly, while partial names like hello_world are located using a search
path. Mrm gets the path from the UIDPATH environment variable if it is set. Otherwise, the following default path is
used: /usr/lib/X11 and /usr/include/X11 are vendor specific and may therefore differ in some implementations.
%U%S
$XAPPLRESDIR/%L/uid/%N/%U%S
$XAPPLRESDIR/%l/uid/%N/%U%S
$XAPPLRESDIR/uid/%N/%U%S
$XAPPLRESDIR/%L/uid/%U%S
$XAPPLRESDIR/%l/uid/%U%S
23 Introduction to UIL 23.5.1 Initializing the Application
644
$XAPPLRESDIR/uid/%U%S
$HOME/uid/%U%S
$HOME/%U%S
/usr/lib/X11/%L/uid/%N/%U%S
/usr/lib/X11/%l/uid/%N/%U%S
/usr/lib/X11/uid/%N/%U%S
/usr/lib/X11/%L/uid/%U%S
/usr/lib/X11/%l/uid/%U%S
/usr/lib/X11/uid/%U%S
/usr/include/X11/uid/%U%S
If XAPPLRESDIR is not set, Mrm uses HOME instead in the default search path. You might recognize some of the
substitution characters in the default path, as they are also used in Xt resource file paths like XFILESEARCHPATH.
In the path above, %L represents the LANG environment variable, %N represents the application class name, %U
represents the UID filename in question, %S represents the filename suffix .uid, and %l represents the language part
LANG. You can find a complete listing of substitutions in the XtResolvePathname() reference in Volume Five,
X Toolkit Intrinsics Reference Manual.
Mrm may actually search the UID path twice for each partial pathname that you specify in the file_list. If Mrm
cannot find the file with the suffix (%S) set to .uid, it tries again with no suffix, which is why we did not need to use
the .uid suffix in our file list.
If MrmOpenHierarchyPerDisplay() successfully opens the specified files, it returns an MrmHierarchy
value in the hierarchy argument and returns the status MrmSUCCESS. The hierarchy value, which is
analogous to a FILE pointer, is used as an argument to other Mrm routines that read information from UID files. If
Mrm fails to open a UID file, it prints an error message with XtAppWarning() and returns one of the following:
MrmNOT_FOUND, if the file cannot be opened
MrmNOT_VALID, if the file version is incorrect
MrmDISPLAY_NOT_OPENED, if the display argument is NULL and the display has not been opened
MrmFAILED, for any other failure
When a failure occurs, none of the UID files remain open and a valid hierarchy is not returned. If our example
application detects an error, it simply prints an error message and exits.
We suggest that you always check the status value returned by MrmOpenHierarchyPerDisplay() and the other
Mrm functions against MrmSUCCESS, as opposed to checking against one or more error values. By using this
approach, you avoid the possibility of accidentally forgetting to check for one or more errors. If necessary, you can
check for a specific error status value after checking against MrmSUCCESS. Recall that we set the
XmNactivateCallback of the PushButton to quit() in the UIL module. The UIL compiler stores the name
quit in the compiled UID file, but Mrm needs the address of the quit() procedure to add the callback to the
widget at run−time. This raises the question, "Why not store the procedure's address in the UID file, instead of its
name?" While this sounds like a reasonable solution, it would impose two undesirable restrictions. First, the UIL
module would need to be recompiled any time we relink the application, and second, the compiled UID file would be
usable only with that specific application on that particular host architecture.
By calling MrmRegisterNames(), the application provides Mrm with the information it needs to map the
procedure names stored in the UID files to procedure addresses. Here is the call and associated data from the source
code
static MrmRegisterArg callback_list[] = {
23 Introduction to UIL 23.5.1 Initializing the Application
645

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.