[ Previous | Next | Contents | Glossary | Home | Search ]
Motif 2.1 Programmer's Guide



Structure of a Program Using MRM

The following sections describe the structural elements of an application program that uses the Motif Resource Manager.

Including Header Files

An application that uses MRM must include all the header files it would need if it did not use MRM. These include <Xm/Xm.h>, header files specific to each widget the program uses, and any header files needed by Motif routines. In addition, the application must include the file <Mrm/MrmPublic.h>. This file contains definitions that the MRM routines need.

Following is an example of including header files for an application that uses only a Text widget and MRM:

#include <Mrm/MrmPublic.h>
#include <Xm/Xm.h>
#include <Xm/Text.h>

Initializing the Intrinsics

An application initializes the Intrinsics as in any other program, usually by calling XtAppInitialize. The application must call XtDisplayInitialize either directly or indirectly before opening any UID files.

Initializing MRM

An application that uses MRM must initialize MRM by calling MrmInitialize before fetching any widgets from UID files. It is a good idea to call MrmInitialize before using any other MRM routines.

Opening UID Files

After initializing MRM and the Intrinsics, an application uses MrmOpenHierarchyPerDisplay to find and open one or more UID files that contain the widget definitions and other information to be loaded.

Note:

The UID format is portable only across same-size architecture machines.

MrmOpenHierarchyPerDisplay uses search paths in much the same way XtDisplayInitialize uses them to build the initial resource database. One argument to MrmOpenHierarchyPerDisplay is a list of UID filenames, each of which represents either a full pathname or a name to be substituted in a file search path. The search path comes from the UIDPATH environment variable or, if UIDPATH is not set, from a series of default paths. MrmOpenHierarchyPerDisplay calls XtResolvePathname to search these paths. When it uses a search path, MrmOpenHierarchyPerDisplay looks for files first by using a suffix of .uid and then by using a NULL suffix.

As with the initial resource database, UID files can reside in different directories depending on the language environment. The search paths can include these substitutions, as well as others recognized by XtResolvePathname:

  1. %N is replaced by the class name of the application.

  2. %L is replaced by the display's language specification.

  3. %l is replaced by the language part of the language specification.

  4. %U is replaced by the current filename from the list of filenames passed as an argument to MrmOpenHierarchyPerDisplay.

    MrmOpenHierarchyPerDisplay returns an ID that identifies the list of open UID files for subsequent calls to routines that load data from the files. On each request to load data, MRM searches the list of files in order. This ordered list of open files is the UID hierarchy. The program can retrieve data from the hierarchy until it calls MrmCloseHierarchy.

    Following is an example of a call to MrmOpenHierarchyPerDisplay. The example initializes MRM and the Intrinsics, opens a UID hierarchy, and closes the hierarchy.

    int main(int argc, char **argv)
    {
        Widget         app_shell;
        XtAppContext   app;
        static String  file_names[] = { "app_1", "app_2" };
        MrmHierarchy   hierarchy_id;
     
        app_shell = XtAppInitialize(&app, "Example",
            (XrmOptionDescList) NULL, 0, (Cardinal *) &argc, argv,
            (String *) NULL, (ArgList) NULL, 0);
        MrmInitialize();
        switch (MrmOpenHierarchyPerDisplay(XtDisplay(app_shell),
                 (MrmCount) XtNumber(file_names), file_names,
                 (MrmOsOpenParamPtr *) NULL, &hierarchy_id)) {
        case MrmSUCCESS:
            if (MrmCloseHierarchy(hierarchy_id) == MrmSUCCESS) {
                exit 0;
            } else {
                fprintf(stderr,
                         "Unable to close UID hierarchy.\n");
                exit 1;
            }
        case MrmNOT_FOUND:
            fprintf(stderr, "Unable to open UID files.\n");
            exit 1;
        default:
            fprintf(stderr, "Unable to open UID hierarchy.\n");
            exit 1;
        }
    }

  5. Registering Callbacks and Identifiers

    The application must register the names of all callback procedures and identifiers defined in the UIL files. Registering the names associates the symbolic names in the UIL files with procedures and data defined in the program. MrmRegisterNames and MrmRegisterNamesInHierarchy accomplish this task. Names registered by MrmRegisterNames are global to all UID hierarchies, whereas names registered by MrmRegisterNamesInHierarchy are local to a particular hierarchy. When MRM looks up the program-defined value associated with a name in a given hierarchy, it searches first for an association local to the hierarchy and then for a global association.

    Following is an example using MrmRegisterNames:

    void PBActivateCB_1(Widget pb, XtPointer app_data,
        XtPointer widget_data);
    void PBActivateCB_2(Widget pb, XtPointer app_data,
        XtPointer widget_data);
    void PBArmCB(Widget pb, XtPointer app_data,
        XtPointer widget_data);
     
    static MrmRegisterArg cb_list[] = {
        { "pb_ac_proc_1",   (XtPointer) PBActivateCB_1 },
        { "pb_ac_proc_2",   (XtPointer) PBActivateCB_2 },
        { "pb_arm_proc",    (XtPointer) PBArmCB }
    };
     
        if (MrmRegisterNames(cb_list,
                             (MrmCount) XtNumber(cb_list))
             == MrmSUCCESS) {
            ...
        } else {
            ...
        }

    Fetching Information from UID Files

    MRM can fetch the following information from UID files:

    1. Named widgets, defined by object clauses, and their descendants. Use MrmFetchWidget or MrmFetchWidgetOverride.

    2. Named color literals, defined by color or rbg functions and appearing in value clauses. Use MrmFetchColorLiteral.

    3. Named icon literals, defined by icon functions and appearing in value clauses. Use MrmFetchIconLiteral.

    4. Other named literals appearing in value clauses. Use MrmFetchLiteral or MrmFetchSetValues.

      MRM can fetch literals appearing in value clauses only if they are defined as exported.

      After creating a top-level shell, using XtAppInitialize or XtAppCreateShell, the application can use MrmFetchWidget to fetch the child of the top-level shell and its descendants. For each widget in the tree, MrmFetchWidget does the following:

      1. Calls the appropriate widget creation routine, passing it the initial resource values defined in the arguments specification in the object clause

      2. Adds the callback routines defined in the callbacks specification of the object clause

      3. Calls any MrmNcreateCallback callbacks

      4. Manages all child widgets unless they are defined to be unmanaged

        The application does not have to fetch all widgets at the beginning of the program. To create widgets such as menus and dialogs as needed, the application can call MrmFetchWidget at any time.

        The application can fetch the same widget definition more than once. MRM creates a new widget each time, essentially using the UIL definition as a template. MrmFetchWidgetOverride is useful here, as it allows the application to override the initial resource values specified in the UIL file.

        Following is a simple example using MrmFetchWidget to create the main widget hierarchy for an application:

        int main(int argc, char **argv)
        {
            Widget         app_shell, top_level;
            XtAppContext   app;
            static String  file_names[] = { "app_1", "app_2" };
            MrmHierarchy   hierarchy_id;
            MrmType        top_level_class;
         
            MrmInitialize();
            app_shell = XtAppInitialize(&app, "Example",
                (XrmOptionDescList) NULL, 0, (Cardinal *) &argc, argv,
                (String *) NULL, (ArgList) NULL, 0);
            switch (MrmOpenHierarchyPerDisplay(XtDisplay(app_shell),
                     (MrmCount) XtNumber(file_names), file_names,
                     (MrmOsOpenParamPtr *) NULL, &hierarchy_id)) {
            case MrmSUCCESS:
                if (MrmFetchWidget(hierarchy_id, "top_level",
                      app_shell, &top_level, &top_level_class)
                                                    != MrmSUCCESS) {
                    fprintf(stderr,
                              "Unable to fetch top-level widget.\n");
                }
                if (MrmCloseHierarchy(hierarchy_id) == MrmSUCCESS) {
                    exit 0;
                } else {
                    fprintf(stderr,
                              "Unable to close UID hierarchy.\n");
                    exit 1;
                }
            case MrmNOT_FOUND:
                fprintf(stderr, "Unable to open UID files.\n");
                exit 1;
            default:
                fprintf(stderr, "Unable to open UID hierarchy.\n");
                exit 1;
            }
        }

      5. Closing the UID File

        MrmCloseHierarchy closes all files in the specified UID hierarchy. The application can close and reopen a hierarchy, but usually it does not close a hierarchy until it is finished reading data from the UID files. When the application uses multiple hierarchies, operating system limits on the number of open files may make it necessary to close one hierarchy before opening another.

        Defining Callback Procedures

        An application that uses MRM defines callback procedures in the same way as an application that uses only the toolkit. For callbacks delared in UIL files, the application must use MrmRegisterNames or MrmRegisterNamesInHierarchy to associate the UIL callback procedure names with the actual procedures defined in the program.

        An application can create widgets, such as dialogs and PopupMenus, as the program needs them. If these widgets are defined in UIL files, a callback procedure can call MrmFetchWidget to fetch them from UID files.

        Making Widgets Visible

        MrmFetchWidget never manages the widget the application is fetching. It does manage all other widgets in the tree whose root is the widget being fetched, except for widgets declared unmanaged in the UIL file. MrmFetchWidget does not realize any widgets in the tree.

        The application must manage any unmanaged widgets created by MrmFetchWidget, and it must realize all widgets it wants to make visible. In the simple case where the application fetches the entire widget hierarchy at the beginning of the program, it typically manages the widget it fetches and then realizes the top-level shell:

        int main(int argc, char **argv)
        {
         Widget         app_shell, top_level;
         XtAppContext   app;
         static String  file_names[] = { "app_1", "app_2" };
         MrmHierarchy   hierarchy_id;
         MrmType        top_level_class;
         
            MrmInitialize();
            app_shell = XtAppInitialize(&app, "Example",
                (XrmOptionDescList) NULL, 0, (Cardinal *) &argc, argv,
                (String *) NULL, (ArgList) NULL, 0);
            switch (MrmOpenHierarchyPerDisplay(XtDisplay(app_shell),
                     (MrmCount) XtNumber(file_names), file_names,
                     (MrmOsOpenParamPtr *) NULL, &hierarchy_id)) {
            case MrmSUCCESS:
                if (MrmFetchWidget(hierarchy_id, "top_level", app_shell,
                      &top_level, &top_level_class) == MrmSUCCESS) {
                    XtManageChild(top_level);
                    XtRealizeWidget(app_shell);
                } else {
                    fprintf(stderr,
                             "Unable to fetch top-level widget.\n");
                }
                if (MrmCloseHierarchy(hierarchy_id) == MrmSUCCESS) {
                    exit 0;
                } else {
                    fprintf(stderr,
                              "Unable to close UID hierarchy.\n");
                    exit 1;
                }
            case MrmNOT_FOUND:
                fprintf(stderr, "Unable to open UID files.\n");
                exit 1;
            default:
                fprintf(stderr, "Unable to open UID hierarchy.\n");
                exit 1;
            }
        }

        Entering the Event Loop

        As with toolkit applications that do not use MRM, a program using MRM typically calls XtAppMainLoop to enter the event loop after realizing the top-level shell.


        [ Previous | Next | Contents | Glossary | Home | Search ]