From: ksall@cen.com (Ken Sall)
Newsgroups: comp.windows.x.motif,comp.answers,news.answers
Subject: Motif FAQ (Part 9 of 9)
Date: 7 May 1995 12:28:53 GMT
Organization: none
Approved: news-answers-request@MIT.EDU
Expires: 20 Jun 1995 12:27:35 GMT
Message-ID: <motif-faq/part9_799849655@rtfm.mit.edu>
Reply-To: ksall@cen.com (Ken Sall)
Keywords: FAQ question answer

Archive-name: motif-faq/part9
Last-modified: MAY 05, 1995
Posting-Frequency: monthly
Organization: Century Computing, Inc. <URL:http://www.cen.com/>
Version: 4.4




-----------------------------------------------------------------------------
Subject: 208)  TOPIC: MISCELLANEOUS

-----------------------------------------------------------------------------
Subject: 209)  How can an application be informed of signals?

Answer: blackman@hodgkin.med.upenn.edu (David Blackman) writes:

According to comp.windows.x FAQ, you shouldn't make Xt/Xlib calls from a Unix
signal handler:

    "You can work around the problem by setting a flag in the
    interrupt handler and later checking it with a work procedure
    or a timer event which has previously been added."

Kaleb KEITHLEY (fedora.x.org!kaleb) adds:

Xt is not reentrant and it is not safe to call any Xt functions from a signal
handler...  I think [the signaling] technique is covered in the [X] FAQ. On
most POSIX-type systems write(2) is guaranteed to be reentrant and atomic. If
you establish a simple pipe with the pipe(2) system call, and add it as an
XtInput with XtAppAddInput(), then you can write to the pipe in the signal
handler. Xt will notice that input is available and call the input-handler
proc. This technique is inherently better than setting the flag because the
write to the pipe will result in XtAppNextEvent returning immediately without
the latency you observe in using the flag technique.  In R6 you can use the
XtAppAddSignal function.

Ken Sall (ksall@cen.com) adds: See the "Signal Handling" chapter of "Motif
Programming Manual" by Heller and Ferguson, listed in the BOOKS topic.

Paul Davey (pd@uit.co.uk) adds: The write and XtAppAddInput input method is
often the best - but be warned it does not work on some SVR3 based Unixes,
where a pipe may not be selected on. SCO Unix exhibits this behaviour so here
the external flag method should be used.

-----------------------------------------------------------------------------
Subject: 210)  How do I control the repeat rate on a SUN keyboard?

Answer:

     [...]

     -ar1 milliseconds
             This option specifies amount of time in milliseconds
             before   which   a   pressed  key  should  begin  to
             autorepeat.

     -ar2 milliseconds
             This option specifies the interval  in  milliseconds
             between autorepeats of pressed keys.

Of course this presumes you're using a server based on the MIT sample server.

Thanks to kaleb@x.org (Kaleb Keithley)

-----------------------------------------------------------------------------
Subject: 211)  How can I identify the children of a manager widget?

Answer: Use XtGetValues() on XmNchildren (array of widget IDs) and
XmNnumChildren (number of widgets in array).

-----------------------------------------------------------------------------
Subject: 212)  What functions can an application use to change the size or
position of a widget?

Answer: Applications should set the values of the XmNx, XmNy, XmNwidth, and
XmNheight resources.

Note that many manager widgets ignore the XmNx and XmNy resources of their
children, relying instead on their internal layout algorithms.  If you really
want specific positions, you must use a manager widget that allows them, e.g.,
XmBulletinBoard.

Also note that some manager widgets reject size change requests from their
children when certain resources are set (e.g., XmNresizable on XmForm).
Others allow the the children to resize, but clip the results (e.g.,
XmNallowShellResize on shell widgets).  Make sure you have these resources set
to the policy you want.

Due to bugs, some widgets (third party widgets) do not respond to changes in
their width and height.  Sometimes, you can get them to respond correctly by
unmanaging them, setting the resources, then managing them again.

Under no circumstances should applications use routines like
XtConfigureWidget() or XtResizeWidget().  These routines are reserved for
widget internals and will seriously confuse many widgets.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 213)  What widgets give the look of push buttons, but behavior of
toggle buttons?

Answer: Use the XmToggleButton widget, setting XmNindicatorOn to False and
XmNshadowThickness to 2.

Thanks to Ken Lee, kenton@rahul.net

Also set XmNfillOnSelect to True. Otherwise, the background color of the
button will not stay in the "armed" state.

thanks to Glenn McMillen, mcmillen@meadow.mdso.vf.ge.com

In Motif 1.2 (and later), if you specify a XmNselectColor and set
XmNindicatorOn to False, then you need to set XmNfillOnSelect to True.
XmNfillOnSelect is not necessary if you are not setting a XmNselectColor.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 214)  Can I use XtAddTimeOut, XtAddWorkProc, and XtAddInput with
XtAppMainLoop?

Answer: On many systems, the obsolete XtAdd*() functions are not compatible
with the XtAppMainLoop().  Instead, you should use newer XtAppAddTimeOut(),
XtAppAddWorkProc(), and XtAppAddInput() functions with XtAppMainLoop()

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 215)  Why does XtGetValues for XmNx and XmNwidth return extremely
large values?

Answer: You must use the 16 bit "Dimension" and "Position" data types for your
arguments.  If you use 32 bit integers, some implementations will fill the
remaining 16 bits with invalid data, causing incorrect return values.  The
*Motif Programmer's Manual* and the widget man pages specify the correct data
type for each resource.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 216)  Can I use XmGetPixmap() with widgets that have non-default
visual types?

Answer: XmGetPixmap() assumes that you are using the default screen depth.  If
you're using a different depth, use XmGetPixmapByDepth() instead.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 217)  How can I determine the item selected in a option menu or a
RadioBox?

Answer: The value of the XmNmenuHistory resource of the XmRowColumn parent is
the widget ID of the last selected item.  It works the same way for all menus
and radio boxes.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 218)  What is the matter with Frame in Motif 1.2?

[Last modified: November 92]

Answer: This announcement has been made by OSF:

"IMPORTANT NOTICE

We have discovered two problems in the new 1.2 child alignment resources in
XmFrame. Because some vendors may have committed, or are soon to commit to
field releases of Motif 1.2 and 1.2.1, OSF's options for fixing them are
limited. We are trying to deal with these in a way that does not cause
hardship for application developers who will develop applications against
various point versions of Motif. OSF's future actions for correction are
summarized.

WHAT YOU SHOULD DO AND KNOW

1. Mark the following change in your documentation.

On page 1-512 of the OSF/Motif Programmer's Reference, change the descriptions
under XmNchildVerticalAlignment as follows (what follows is the CORRECT
wording to match the current implementation):

XmALIGNMENT_WIDGET_TOP
        Causes the BOTTOM edge of the title area to align
        vertically with the top shadow of the Frame.

XmALIGNMENT_WIDGET_BOTTOM
        Causes the TOP edge of the title area to align
        vertically with the top shadow of the Frame.

2. Note the following limitation on resource converters for Motif 1.2 and
1.2.1 implementations.

The rep types for XmFrame's XmNentryVerticalAlignment resource were
incorrected implemented, which means that converters will not work properly.
The following resource settings will not work from a resource file in 1.2 and
1.2.1:

        *childVerticalAlignment: alignment_baseline_bottom
        *childVerticalAlignment: alignment_baseline_top
        *childVerticalAlignment: alignment_widget_bottom
        *childVerticalAlignment: alignment_widget_top

If you wish to set these values for these resources (note they are new
constraint resources in XmFrame) you will have to set them directly in C or
via uil.

WHAT WE WILL DO

The problem described in note #1 above will not be fixed in the OSF/Motif
implementation until the next MAJOR release of Motif.  At that time we will
correct the documentation and modify the code to match those new descriptions,
but we will preserve the existing enumerated values and their behavior for
backward compatibility for that release.

The fix for the problem described in note #2 will be shipped by OSF in Motif
1.2.2.

SUMMARY

We are sorry for any difficulty this causes Motif users.  If you have any
questions or flames (I suppose I deserve it) please send them directly to me.
We sincerely hope this proactive response is better for our customers than you
having to figure it out yourselves!

Libby


-----------------------------------------------------------------------------
Subject: 219)  What is IMUG and how do I join it?

Answer: IMUG is the International Motif User Group founded by Quest Windows
Corporation and co-sponsored by FedUNIX.  IMUG is a non-profit organization
working to keep users informed on technical and standards issues, to
strengthen user groups on a local level, to increase communication among users
internationally, and to promote the use of an international conference as a
forum for sharing and learning more about Motif.  You can join it by

 1.  Pay the annual membership fee of $20 USD directly to IMUG.  Contact

     IMUG
     5200 Great America Parkway
     Santa Clara,  CA  95054
     (408) 496-1900
     imug@quest.com

 2.  Register at the International Motif User Conference, and automatically
     become an IMUG member.

 3.  Donate a pd widget, widget tool or widget builder to the IMUG Widget
     Depository and receive a free one year IMUG membership.


-----------------------------------------------------------------------------
Subject: 220)  How do I set the title of a top level window?

[Last modified: September 92]

Answer: Set XmNtitle (and optionally XmNtitleEncoding) for TopLevelShells.
(Note that this is of type String rather than XmStrin.) Ypu can also set
XmNiconName if you want its icon to show this title.  For XmDialogShells, set
the XmNdialogTitle of its immediate child, assuming it's a BulletinBoard
subclass.  These can also be set in resource files.


-----------------------------------------------------------------------------
Subject: 221)  Can I use editres with Motif?

[Last modified: Sept 94]

Answer: Editres, part of the MIT delivery, is a powerful widget tree analysis
tool and is highly recommended.  There's negligible overhead in making editres
available to an application and many projects keep the editres "hook" active
even for operational programs.

It isn't built in to Motif (at 1.2.0), but you can do this in your application

    extern void _XEditResCheckMessages();
    ...
    XtAddEventHandler(shell_widget, (EventMask)0, True,
                        _XEditResCheckMessages, NULL);

once for each shell widget that you want to react to the "click to select
client" protocol.  Then link your client with the R5 libXmu.

David Brooks, OSF

Marc Quinton (quinton@stna7.stna7.stna.dgac.fr) wrote:

With X11R4 see the Editres package which is a port of the X11R5 Editres
protocol and client. You can find it at :

 ftp.stna7.stna.dgac.fr(143.196.9.83):/pub/dist/Editres.tar.Z

-----------------------------------------------------------------------------
Subject: 222)  Where is the editres protocol documented?

[Last modified: Apr 95]

Answer: In /usr/include/X11/Xmu/EditresP.h.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 223)  Why does an augment translation appear to act as replace for
some widgets?  When I use either augment or override translations in
.Xdefaults it seems to act as replace in both Motif 1.0 and 1.1

Answer: By default, the translation table is NULL.  If there is nothing
specified (either in resource file, or in args), the widget's Initialize
finds: Oh, there is NULL in translations, lets use our default ones.  If,
however, the translations have become non-NULL, the default translations are
NOT used at all. Thus, using #augment, #override or a new table has identical
effect: defines the new translations. The only way you can augment/override
Motif's default translations is AFTER Initialize, using XtSetValues.  Note,
however, that Motif managers do play with translation tables as well ... so
that results are not always easy to predict.

OSF wrote: A number of people have complained about not being able to
augment/override translations from the .Xdefaults.  This is due to the
complexity of the menu system/keyboard traversal and the necessary
translations changes required to support the Motif Style Guide in menus.  It
cannot be fixed in a simple way. Fixing it requires re-design of the
menus/buttons and it is planned to be fixed in 1.2.

-----------------------------------------------------------------------------
Subject: 224)  How do you "grey" out a widget so that it cannot be activated?

Answer: Use XtSetSensitive(widget, False). Do not set the XmNsensitive
resource directly yourself (by XtSetValues) since the widget may need to talk
to parents first.

-----------------------------------------------------------------------------
Subject: 225)* Why doesn't the Help callback work on some widgets?

[Last modified: May 95]

Answer: If you press the help key the help callback of the widget with the
keyboard focus is called (not the one containing the mouse).  You can't get
the help callback of a non-keyboard-selectable widget called. To get `context
sensitive' help on these, you have to find the mouse, associate its position
with a widget and then do the help.

 The X Resource, Issue 6, has an article on implementing context help in
 Motif in this manner, that is, using the mouse position to indicate the
 widget for which context help is desired, as well as using resources to
 specify the help.  Example source code is available at

        ftp://ftp.ora.com/pub/examples/xresource/issue6/helpdemo.tar.Z

 The demo program lets you toggle between using the method described in
 the article and XmTrackingLocate() for comparision purposes.

Contributed by: Jay Schmidgall  jay@vnet.ibm.com (author of the article
mentioned above).  Thanks to chen@adi.com (Franklin Chen) for correcting the
URL.

--

-----------------------------------------------------------------------------
Subject: 226)  Can I specify a widget in a resource file?

Answer: This answer, which uses the Xmu library, is due to David Elliott.  If
the converter is added, then the name of a widget (a string) can be used in
resource files, and will be converted to the appropriate widget.

This code, which was basically stolen from the Athena Form widget, adds a
String to Widget converter.  I wrote it as a general routine that I call at
the beginning of all of my programs, and made it so I could add other
converters as needed (like String to Unit Type ;-).

        #include <X11/Intrinsic.h>
        #include <X11/StringDefs.h>
        #include <Xm/Xm.h>
        #include <X11/Xmu/Converters.h>
        #include <X11/IntrinsicP.h>
        #include <X11/CoreP.h>

        void
        setupConverters()
        {
                static XtConvertArgRec parentCvtArgs[] = {
                        {XtBaseOffset, (caddr_t)XtOffset(Widget, core.parent),
                                sizeof(Widget)}
                };

                XtAddConverter(XmRString, XmRWindow, XmuCvtStringToWidget,
                        parentCvtArgs, XtNumber(parentCvtArgs));
        }


-----------------------------------------------------------------------------
Subject: 227)  Why are only some of my translations are being installed?  I
have a translation table like the following, but only the first ones are
getting installed and the rest are ignored.

 *Text.translations:    #override \
     Ctrl<Key>a:    beginning-of-line() \n\
     Ctrl<Key>e:    end-of-line() \n\
     Ctrl<Key>f:    forward-character() \n\


Answer: Most likely, you have a space at the end of one of the lines (the
first in this case).

     Ctrl<Key>a:    beginning-of-line() \n\
                                           ^ space here

The second backslash in each line is there to protect the real newline
character and so you must not follow it with anything other than the newline
itself. Otherwise it acts as the end of the resource definition and the
remaining lines are not added.


-----------------------------------------------------------------------------
Subject: 228)  Where can I get the PanHandler code?

Answer: It is available by email from Chuck Ocheret:  chuck@IMSI.COM.

-----------------------------------------------------------------------------
Subject: 229)  What are these passive grab warnings?  When I destroy certain
widgets I get a stream of messages

    Warning: Attempt to remove non-existant passive grab


Answer: They are meaningless, and you want to ignore them.  Do this (from Kee
Hinckley) by installing an XtWarning handler that explicitly looks for them
and discards them:

        static void xtWarnCB(String message) {
           if (asi_strstr(message, "non-existant passive grab", TRUE)) return;
           ...

They come from Xt, and (W. Scott Meeks): "it's something that the designers of
Xt decided the toolkit should do. Unfortunately, Motif winds up putting
passive grabs all over the place for the menu system.  On the one hand, we
want to remove all these grabs when menus get destroyed so that they don't
leak memory; on the other hand, it's almost impossible to keep track of all
the grabs, so we have a conservative strategy of ungrabbing any place where a
grab could have been made and we don't explicitly know that there is no grab.
The unfortunate side effect is the little passive grab warning messages.
We're trying to clean these up where possible, but there are some new places
where the warning is generated.  Until we get this completely cleaned up (1.2
maybe), your best bet is probably to use a warning handler."

-----------------------------------------------------------------------------
Subject: 230)  How do I have more buttons than three in a MessageBox?  I want
to have something like a MessageBox (or other widget) with more than three
buttons, but with the same nice appearance.

[Last modified: Feb 95]

Answer: The Motif 1.2 MessageBox widget allows extra buttons to be added after
the OK button. Just create the extra buttons as children of the MessageBox.
Similarly with the SelectionBox.

Pre-Motif 1.2, you have to do one of the following methods.

A SelectionBox is created with four buttons, but the fourth (the Apply button)
is unmanaged. To manage it get its widget ID via
XmSelectionBoxGetChild(parent, XmDIALOG_APPLY_BUTTON) and then XtManage it.
Unmanage all of the other bits in the SelectionBox that you don't want.  If
you want more than four buttons, try two SelectionBoxes (or similar) together
in a container, where all of the unwanted parts of the widgets are unmanaged.

Alternatively, build your own dialog:

/* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warranty expressed or implied.
 * This program is -not- in the public domain.  This program is
 * taken from the Motif Programming Manual, O'Reilly Volume 6.
 */

/* action_area.c -- demonstrate how CreateActionArea() can be used
 * in a real application.  Create what would otherwise be identified
 * as a PromptDialog, only this is of our own creation.  As such,
 * we provide a TextField widget for input.  When the user presses
 * Return, the Ok button is activated.
 */
#include <Xm/DialogS.h>
#include <Xm/PushBG.h>
#include <Xm/PushB.h>
#include <Xm/LabelG.h>
#include <Xm/PanedW.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/TextF.h>

typedef struct {
    char *label;
    void (*callback)();
    caddr_t data;
} ActionAreaItem;

static void
    do_dialog(), close_dialog(), activate_cb(),
    ok_pushed(), cancel_pushed(), help();

main(argc, argv)
int argc;
char *argv[];
{
    Widget toplevel, button;
    XtAppContext app;

    toplevel = XtVaAppInitialize(&app, "Demos",
        NULL, 0, &argc, argv, NULL, NULL);

    button = XtVaCreateManagedWidget("Push Me",
        xmPushButtonWidgetClass, toplevel, NULL);
    XtAddCallback(button, XmNactivateCallback, do_dialog, NULL);

    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
}

/* callback routine for "Push Me" button.  Actually, this represents
 * a function that could be invoked by any arbitrary callback.  Here,
 * we demonstrate how one can build a standard customized dialog box.
 * The control area is created here and the action area is created in
 * a separate, generic routine: CreateActionArea().
 */
static void
do_dialog(w, file)
Widget w; /* will act as dialog's parent */
char *file;
{
    Widget dialog, pane, rc, label, text_w, action_a;
    XmString string;
    extern Widget CreateActionArea();
    Arg args[10];
    static ActionAreaItem action_items[] = {
        { "Ok",     ok_pushed,     NULL          },
        { "Cancel", cancel_pushed, NULL          },
        { "Close",  close_dialog,  NULL          },
        { "Help",   help,          "Help Button" },
    };

    /* The DialogShell is the Shell for this dialog.  Set it up so
     * that the "Close" button in the window manager's system menu
     * destroys the shell (it only unmaps it by default).
     */
    dialog = XtVaCreatePopupShell("dialog",
        xmDialogShellWidgetClass, XtParent(w),
        XmNtitle,  "Dialog Shell",     /* give arbitrary title in wm */
        XmNdeleteResponse, XmDESTROY,  /* system menu "Close" action */
        NULL);

    /* now that the dialog is created, set the Close button's
     * client data, so close_dialog() will know what to destroy.
     */
    action_items[2].data = (caddr_t)dialog;

    /* Create the paned window as a child of the dialog.  This will
     * contain the control area (a Form widget) and the action area
     * (created by CreateActionArea() using the action_items above).
     */
    pane = XtVaCreateWidget("pane", xmPanedWindowWidgetClass, dialog,
        XmNsashWidth,  1,
        XmNsashHeight, 1,
        NULL);

    /* create the control area (Form) which contains a
     * Label gadget and a List widget.
     */
    rc = XtVaCreateWidget("control_area", xmRowColumnWidgetClass, pane, NULL);
    string = XmStringCreateLocalized("Type Something:");
    XtVaCreateManagedWidget("label", xmLabelGadgetClass, rc,
        XmNlabelString,    string,
        XmNleftAttachment, XmATTACH_FORM,
        XmNtopAttachment,  XmATTACH_FORM,
        NULL);
    XmStringFree(string);

    text_w = XtVaCreateManagedWidget("text-field",
        xmTextFieldWidgetClass, rc, NULL);

    /* RowColumn is full -- now manage */
    XtManageChild(rc);

    /* Set the client data "Ok" and "Cancel" button's callbacks. */
    action_items[0].data = (caddr_t)text_w;
    action_items[1].data = (caddr_t)text_w;

    /* Create the action area -- we don't need the widget it returns. */
    action_a = CreateActionArea(pane, action_items, XtNumber(action_items));

    /* callback for Return in TextField.  Use action_a as client data */
    XtAddCallback(text_w, XmNactivateCallback, activate_cb, action_a);

    XtManageChild(pane);
    XtPopup(dialog, XtGrabNone);
}

/*--------------*/
/* The next four functions are the callback routines for the buttons
 * in the action area for the dialog created above.  Again, they are
 * simple examples, yet they demonstrate the fundamental design approach.
 */
static void
close_dialog(w, shell)
Widget w, shell;
{
    XtDestroyWidget(shell);
}

/* The "ok" button was pushed or the user pressed Return */
static void
ok_pushed(w, text_w, cbs)
Widget w, text_w;         /* the text widget is the client data */
XmAnyCallbackStruct *cbs;
{
    char *text = XmTextFieldGetString(text_w);

    printf("String = %s0, text);
    XtFree(text);
}

static void
cancel_pushed(w, text_w, cbs)
Widget w, text_w;         /* the text field is the client data */
XmAnyCallbackStruct *cbs;
{
    /* cancel the whole operation; reset to NULL. */
    XmTextFieldSetString(text_w, "");
}

static void
help(w, string)
Widget w;
String string;
{
    puts(string);
}
/*--------------*/

/* When Return is pressed in TextField widget, respond by getting
 * the designated "default button" in the action area and activate
 * it as if the user had selected it.
 */
static void
activate_cb(text_w, client_data, cbs)
Widget text_w;              /* user pressed Return in this widget */
XtPointer client_data;        /* action_area passed as client data */
XmAnyCallbackStruct *cbs;   /* borrow the "event" field from this */
{
    Widget dflt, action_area = (Widget)client_data;

    XtVaGetValues(action_area, XmNdefaultButton, &dflt, NULL);
    if (dflt) /* sanity check -- this better work */
        /* make the default button think it got pushed.  This causes
         * "ok_pushed" to be called, but XtCallActionProc() causes
         * the button appear to be activated as if the user selected it.
         */
        XtCallActionProc(dflt, "ArmAndActivate", cbs->event, NULL, 0);
}

#define TIGHTNESS 20

Widget
CreateActionArea(parent, actions, num_actions)
Widget parent;
ActionAreaItem *actions;
int num_actions;
{
    Widget action_area, widget;
    int i;

    action_area = XtVaCreateWidget("action_area", xmFormWidgetClass, parent,
        XmNfractionBase, TIGHTNESS*num_actions - 1,
        XmNleftOffset,   10,
        XmNrightOffset,  10,
        NULL);

    for (i = 0; i < num_actions; i++) {
        widget = XtVaCreateManagedWidget(actions[i].label,
            xmPushButtonWidgetClass, action_area,
            XmNleftAttachment,       i? XmATTACH_POSITION : XmATTACH_FORM,
            XmNleftPosition,         TIGHTNESS*i,
            XmNtopAttachment,        XmATTACH_FORM,
            XmNbottomAttachment,     XmATTACH_FORM,
            XmNrightAttachment,
                    i != num_actions-1? XmATTACH_POSITION : XmATTACH_FORM,
            XmNrightPosition,        TIGHTNESS*i + (TIGHTNESS-1),
            XmNshowAsDefault,        i == 0,
            XmNdefaultButtonShadowThickness, 1,
            NULL);
        if (actions[i].callback)
            XtAddCallback(widget, XmNactivateCallback,
                actions[i].callback, actions[i].data);
        if (i == 0) {
            /* Set the action_area's default button to the first widget
             * created (or, make the index a parameter to the function
             * or have it be part of the data structure). Also, set the
             * pane window constraint for max and min heights so this
             * particular pane in the PanedWindow is not resizable.
             */
            Dimension height, h;
            XtVaGetValues(action_area, XmNmarginHeight, &h, NULL);
            XtVaGetValues(widget, XmNheight, &height, NULL);
            height += 2 * h;
            XtVaSetValues(action_area,
                XmNdefaultButton, widget,
                XmNpaneMaximum,   height,
                XmNpaneMinimum,   height,
                NULL);
        }
    }

    XtManageChild(action_area);

    return action_area;
}


-----------------------------------------------------------------------------
Subject: 231)  How do I create a "busy working cursor"?

[Last modified: Feb 95]

Answer: - in Baudouin's code (following), the idea is to keep in an array an
up-to-date list of all shells used in the application, and set for all of them
the cursor to a watch or to the default cursor, with the 2 functions provided.

- in Dan Heller's code (later), the idea is to turn on the watch cursor for
the top-level shell only, popup a working window to possibly abort the
callback, and manage some expose events during the callback.

- in the FAQ for comp.windows.x, the idea is to bring a large window on top of
the application, hide all windows below it, and turn on the watch cursor on
this large window. Unmapping the large window resets the default cursor,


                                    - 10 -


mapping it turns on the watch cursor.

Baudouin Raoult (mab@ecmwf.co.uk) wrote:

void my_SetWatchCursor(w)
Widget w;
{
        static Cursor watch = NULL;

        if(!watch)
                watch = XCreateFontCursor(XtDisplay(w),XC_watch);

        XDefineCursor(XtDisplay(w),XtWindow(w),watch);
        XmUpdateDisplay(w);
}

void my_ResetCursor(w)
Widget w;
{
        XUndefineCursor(XtDisplay(w),XtWindow(w));
        XmUpdateDisplay(w);
}


Answer: A solution with lots of bells and whistles is

/* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warrantee expressed or implied.
 * This program is -not- in the public domain.
 */

/* busy.c -- demonstrate how to use a WorkingDialog and to process
 * only "important" events.  e.g., those that may interrupt the
 * task or to repaint widgets for exposure.  Set up a simple shell
 * and a widget that, when pressed, immediately goes into its own
 * loop.  First, "lock" the shell so that a timeout cursor is set on
 * the shell and pop up a WorkingDialog.  Then enter loop ... sleep
 * for one second ten times, checking between each interval to see
 * if the user clicked the Stop button or if any widgets need to be
 * refreshed.  Ignore all other events.
 *
 * main() and get_busy() are stubs that would be replaced by a real
 * application; all other functions can be used "as is."
 */
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <X11/cursorfont.h>

Widget shell;
void TimeoutCursors();
Boolean CheckForInterrupt();

main(argc, argv)
int argc;
char *argv[];
{
    XtAppContext app;
    Widget button;
    XmString label;
    void get_busy();

    shell = XtVaAppInitialize(&app, "Demos",
        NULL, 0, &argc, argv, NULL, NULL);

    label = XmStringCreateLocalized(
        "Boy, is *this* going to take a long time.");
    button = XtVaCreateManagedWidget("button",
        xmPushButtonWidgetClass, shell,
        XmNlabelString,          label,
        NULL);
    XmStringFree(label);
    XtAddCallback(button, XmNactivateCallback, get_busy, argv[1]);

    XtRealizeWidget(shell);
    XtAppMainLoop(app);
}

void
get_busy(widget)
Widget widget;
{
    int n;

    TimeoutCursors(True, True);
    for (n = 0; n < 10; n++) {
        sleep(1);
        if (CheckForInterrupt()) {
            puts("Interrupt!");
            break;
        }
    }
    if (n == 10)
        puts("done.");
    TimeoutCursors(False, NULL);
}

/* The interesting part of the program -- extract and use at will */
static Boolean stopped;  /* True when user wants to stop processing */
static Widget dialog;    /* WorkingDialog displayed when timed out */

/* timeout_cursors() turns on the "watch" cursor over the application
 * to provide feedback for the user that he's going to be waiting
 * a while before he can interact with the appliation again.
 */
void
TimeoutCursors(on, interruptable)
int on, interruptable;
{
    static int locked;
    static Cursor cursor;
    extern Widget shell;
    XSetWindowAttributes attrs;
    Display *dpy = XtDisplay(shell);
    XEvent event;
    Arg args[1];
    XmString str;
    extern void stop();

    /* "locked" keeps track if we've already called the function.
     * This allows recursion and is necessary for most situations.
     */
    on? locked++ : locked--;
    if (locked > 1 || locked == 1 && on == 0)
        return; /* already locked and we're not unlocking */

    stopped = False; /* doesn't matter at this point; initialize */
    if (!cursor) /* make sure the timeout cursor is initialized */
        cursor = XCreateFontCursor(dpy, XC_watch);

    /* if "on" is true, then turn on watch cursor, otherwise, return
     * the shell's cursor to normal.
     */
    attrs.cursor = on? cursor : None;

    /* change the main application shell's cursor to be the timeout
     * cursor (or to reset it to normal).  If other shells exist in
     * this application, they will have to be listed here in order
     * for them to have timeout cursors too.
     */
    XChangeWindowAttributes(dpy, XtWindow(shell), CWCursor, &attrs);

    XFlush(dpy);

    if (on) {
        /* we're timing out, put up a WorkingDialog.  If the process
         * is interruptable, allow a "Stop" button.  Otherwise, remove
         * all actions so the user can't stop the processing.
         */
        str = XmStringCreateLocalized("Busy.  Please Wait.");
        XtSetArg(args[0], XmNmessageString, str);
        dialog = XmCreateWorkingDialog(shell, "Busy", args, 1);
        XmStringFree(str);
        XtUnmanageChild(
            XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON));
        if (interruptable) {
            str = XmStringCreateLocalized("Stop");
            XtVaSetValues(dialog, XmNcancelLabelString, str, NULL);
            XmStringFree(str);
            XtAddCallback(dialog, XmNcancelCallback, stop, NULL);
        } else
            XtUnmanageChild(
                XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
        XtUnmanageChild(
            XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
        XtManageChild(dialog);
    } else {
        /* get rid of all button and keyboard events that occured
         * during the time out.  The user shouldn't have done anything
         * during this time, so flush for button and keypress events.
         * KeyRelease events are not discarded because accelerators
         * require the corresponding release event before normal input
         * can continue.
         */
        while (XCheckMaskEvent(dpy,
                ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
                | PointerMotionMask | KeyPressMask, &event)) {
            /* do nothing */;
        }
        XtDestroyWidget(dialog);
    }
}

/* User Pressed the "Stop" button in dialog. */
void
stop(dialog)
Widget dialog;
{
    stopped = True;
}

Boolean
CheckForInterrupt()
{
    extern Widget shell;
    Display *dpy = XtDisplay(shell);
    Window win = XtWindow(dialog);
    XEvent event;

    /* Make sure all our requests get to the server */
    XFlush(dpy);

    /* Let motif process all pending exposure events for us. */
    XmUpdateDisplay(shell);

    /* Check the event loop for events in the dialog ("Stop"?) */
    while (XCheckMaskEvent(dpy,
            ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
            PointerMotionMask | KeyPressMask | KeyReleaseMask,
            &event)) {
        /* got an "interesting" event. */
        if (event.xany.window == win)
            XtDispatchEvent(&event); /* it's in our dialog.. */
        else /* uninteresting event--throw it away and sound bell */
            XBell(dpy, 50);
    }
    return stopped;
}


-----------------------------------------------------------------------------
Subject: 232)  Can I use the hourglass that mwm uses?

[Last modified: March 93]

Answer: The hourglass used by mwm is hard-coded into code that is subject to
OSF copyright. In Motif 1.2 though, the bitmaps for this and other things
(information, no_enter, question, warning, working) were made available.  The
install process will probably add them to /usr/include/X11/bitmaps.
Otherwise, just use the watch cursor XC_watch of the previous question,
because that has the same semantics.


-----------------------------------------------------------------------------
Subject: 233)  What order should the libraries be linked in?

[Last modified: August 92]

Answer: At link time, use the library order  -lXm -lXt -lX11. There are two
reasons for this (dbrooks@osf.org):

On most systems, the order matters because the linker won't re-scan a library
once it is done with it.  Thus any references to Xlib calls from Xm will
probably be unresolved.

The [other] problem is that there are two VendorShell widgets. A dummy is
provided in the Xt library, but a widget set will rely on its own being
referenced.  If you mention Xt first, the linker will choose the wrong one.

Motif code will wrongly assume the Motif VendorShell has been class-
initialized [and will probably crash].
 Xaw has a similar problem, but a softer landing; it only complains about
unregistered converters.


-----------------------------------------------------------------------------
Subject: 234)  How do I use xmkmf for Motif clients?

[Last modified: October 1992]

Answer: This advice comes from dbrooks@osf.org:

There are a number of intractable problems with using X configuration files
and xmkmf, while trying to make it easy to build Motif.  Not the least of
these, but one I've never heard mentioned yet, is that the rules for
contructing the names of shared library macros are machine-dependent, and in
the various xxxLib.tmpl files.  Do we edit all those files to add definitions
for XMLIB, DEPXMLIB, etc., or do we put a maze of #ifdefs into the Motif.tmpl
file?

Please note that, if you install Motif, it overwrites your installed
Imake.tmpl with one that includes Motif.tmpl and Motif.rules.

With those caveats, I think the following guidelines will help.

David Brooks OSF

Clients in the X11R5 release use the xmkmf command to build Makefiles.  In
general, the xmkmf command cannot be used for Motif clients, because of the
need to consider the UseInstalledMotif flag separately.  Since xmkmf is a
simple script that calls imake, it is easy to construct the proper call to
imake using the following rules.

In the following, replace {MTOP} by the toplevel directory with the Motif
source tree, and {XTOP} by the toplevel ("mit") directory with the X source.
It is assumed that the directory containing your installed imake is in your
PATH.

When needed, the imake variables XTop and MTop are normally set in your
site.def (to {XTOP} amd {MTOP} respectively); however they may also be set
with additional -D arguments to imake.

1. With both X and Motif in their source trees, ensure the imake variables
   XTop and MTop are set, and use:

        ${XTOP}/config/imake -I{MTOP}/config

2. With Motif in its source tree, and X installed, ensure MTop is set, and
   use:

        imake -I{MTOP}/config -DUseInstalled

3. With both Motif and X installed, and a nonstandard ProjectRoot (see
   site.def for an explanation of this), use:

        imake -DUseInstalled -DUseInstalledMotif -I{ProjectRoot}/lib/X11/config

   or, if the configuration files are in /usr/lib/X11/config:

        imake -DUseInstalled -DUseInstalledMotif


To build a simple Imakefile, remember to include lines like this:

        LOCAL_LIBRARIES = XmClientLibs
                DEPLIBS = XmClientDepLibs

Or, for a client that uses uil/mrm, replace these by MrmClientLibs and
MrmClientDepLibs, and also use:

        MSimpleUilTarget(program)

to build the client and uid file.  Look at the demos for more examples.


And Paul Howell <grue@engin.umich.edu> added:

i did this, calling the new script "xmmkmf".  It passes both -DUseInstalled
and -DUseInstalledMotif.

and i modified the stock R5 Imake.tmpl to do this:

#include <Project.tmpl>
#ifdef UseInstalledMotif
#include <Motif.tmpl>
#endif

#include <Imake.rules>
#ifdef UseInstalledMotif
#include <Motif.rules>
#endif

the result was something that does both athena and motif rules.  and it really
works, just that easy!


-----------------------------------------------------------------------------
Subject: 235)  How do I make context sensitive help?  The Motif Style Guide
says that an application must initiate context-sensitive help by changing the
shape of the pointer to the question pointer. When the user moves the pointer
to the component help is wanted on and presses BSelect, any available context
sensitive help for the component must be presented, and the pointer reverts
from the question pointer.
[Last modified: August 92]

Answer: A widget that gives context sensitive help would place this help in
the XmNhelpCallback function. To trigger this function: (from Martin G C
Davies, mgcd@se.alcbel.be)

I use the following callback that is called when the "On Context" help
pulldown menu is selected. It does the arrow bit and calls the help callbacks
for the widget. It also zips up the widget tree looking for help if needs be.
I don't restrict the arrows motion so I can get help on dialog boxes. No
prizes for guessing what "popup_message" does.


static void ContextHelp(
    Widget              w ,
    Opaque              * tag ,
    XmAnyCallbackStruct * callback_struct
)
{
    static Cursor   context_cursor = NULL ;
    Widget          context_widget ;

    if ( context_cursor == NULL )
        context_cursor = XCreateFontCursor( display, XC_question_arrow ) ;

    context_widget = XmTrackingLocate( top_level_widget,
                                context_cursor, FALSE ) ;

    if ( context_widget != NULL ) /* otherwise its not a widget */
    {
        XmAnyCallbackStruct cb ;

        cb.reason = XmCR_HELP ;
        cb.event = callback_struct->event ;

        /*
         * If there's no help at this widget we'll track back
           up the hierarchy trying to find some.
         */

        do
        {
            if ( ( XtHasCallbacks( context_widget, XmNhelpCallback ) ==
                                                XtCallbackHasSome ) )
            {
                XtCallCallbacks( context_widget, XmNhelpCallback, & cb ) ;
                return ;
            }
            else
                context_widget = XtParent( context_widget ) ;
        } while ( context_widget != NULL ) ;
    }

    popup_message( "No context-sensitive help found\n\
for the selected object." ) ;
}


Dave Bonnett suggested, to use the following translations for XmText (and
XmTextField) widgets to get the same help with key strokes, and to provide an
accelerator label in the Context help menu entry.

MyApp*XmText*translations: #override\n\
                                <Key>F1:    Help()

MyApp*Help_menu*Contextual Help.acceleratorText:   F1

MyApp*defaultVirtualBindings:           osfBackSpace : <Key>Delete\n\
                                        osfRight : <Key>Right\n\
                                        osfLeft  : <Key>Left\n\
                                        osfUp    : <Key>Up\n\
                                        osfHelp  : <Key>F1\n\
                                        osfDown  : <Key>Down


-----------------------------------------------------------------------------
Subject: 236)  How do I debug a modal interaction?

When an application crashes in a modal section (such as in a modal dialog, a
menu or when a drag and drop is in action), I cannot access the debugger.

[Last modified: January 1993]

Answer: Run the debugger on one display while the application writes to
another display.

-----------------------------------------------------------------------------
Subject: 237)  How can I disable Drag and Drop in my Motif 1.2 client ?

[Last modified: Oct 94]

Answer: Several people have reported that for complex hierarchies of widgets,
drag and drop can slow down an application considerably. If you do not need
drag and drop's significant power, you can disable it in your application.

Set the XmDisplay drag-protocol resources to XmDRAG_NONE.  The following code
fragment demonstrates this:

#include <Xm/Display.h>


    dw = XmGetXmDisplay(XtDisplay(shell));
    /* where "shell" is your client's top-level shell. */

    XtVaSetValues(dw, XmNdragInitiatorProtocolStyle, XmDRAG_NONE, NULL);
    XtVaSetValues(dw, XmNdragReceiverProtocolStyle,  XmDRAG_NONE, NULL);


Thanks to Lance Purple (purple@austin.ibm.com)

Ken Lee (kenton@rahul.net) and Christoph Widmer
(widmer@einsteinium.SLCS.SLB.COM) describe how to disable drag and drop from a
resource file:

        *dragInitiatorProtocolStyle: XmDRAG_NONE
        *dragReceiverProtocolStyle:  XmDRAG_NONE

Ken Lee also notes that as of Motif 1.2, the "Xm" prefix is required for all
token constants in resource files. (Which is why specifying "DRAG_NONE" won't
work but "XmDRAG_NONE" will.)

-----------------------------------------------------------------------------
Subject: 238)  Where can I find info and examples of the Motif drag and drop
protocol?

[Last modified: Apr 95]

Answer: The drag and drop protocol implemented by OSF is not stable, so they
have not published it yet. The API should remain stable though.  The OSF
protocol is not compatable with the OpenLook protocol.  OSF and Sun are
working on a joint protocol for publication.

For programming examples on Motif drag and drop, see the Motif 1.2 Programmers
Guide.

For a third alternative, try Roger Reynolds drag and drop protocol, available
from netcom.com in /pub/rogerr.

Ken Lee, kenton@rahul.net, writes: OSF's "Motif Programmers Guide" includes
complete source code for several drag and drop demos.  Chapter 15 has several
simple examples demonstrating the basic behaviour.  Appendix B has a lengthy
example covering all possible options.  (I think the source code for some of
the demos also appears on the OSF tape.)


-----------------------------------------------------------------------------
Subject: 239)  Why can't I install my own colormap using XInstallColormap?

[Last modified: Sept 94]

Answer: You shouldn't install the colormap yourself using XInstallColormap.
See the ICCCM document for all the reasons.  Instead put the colormap as an
argument on the Shell widget and the window manager will take care of this.

When the colormap is installed,  unless you have a display with multiple
colormaps, the other windows will go "technicolor" and there is no way around
this problem.

Thanks to Doug Rand <drand@sgi.com>

-----------------------------------------------------------------------------
Subject: 240)  How do I get correct shadow colors to match other color
changes?

[Last modified: Sept 94]

Answer:

Thanks to Craig MacFarlane (craigm@chateau-rouge.ICS.UCI.EDU) for the
following explanation and code:

You have to make a call to calculate the new shadow colors.  The trick is
actually getting a value of type Pixel when all you have is the string "Blue".
I use the XtConvertAndStore() function to convert from a char * to a Pixel.
For example:


  char *color = "blue";
  XrmValue color_value, pixel_value;
  Pixel background;

  color_value.size = strlen(color);
  color_value.addr = (XtPointer) color;
  pixel_value.size = sizeof(Pixel);
  pixel_value.addr = (XtPointer) 0;

  result = XtConvertAndStore(widget,
                             XtRString, &color_value,
                             XtRPixel, &pixel_value);

  background = (*(Pixel *)pixel_value.addr);


You can then use the pixel value obtained by XtConvertAndStore() in the
XmGetColors call.  XmGetColors calculates appropriate foreground, topshadow,
bottomshadow, and select colors for the given background. e.g.


  XmGetColors(screen,
              DefaultColormap(display_id, DefaultScreen(display_id)),
              background,
              &foreground, &topshadow, &bottomshadow, &select);


Then it's trivial to set the shadow colors at the same time you set the
foreground and background colors.  For example:


  XtVaSetValues(widget,
                XmNforeground, foreground,
                XmNbackground, background,
                XmNarmColor, select,
                XmNtopShadowColor, topshadow,
                XmNbottomShadowColor, bottomshadow,
                NULL);


You'll get asthetically pleasing colors every time. :)

-----------------------------------------------------------------------------
Subject: 241)  What color algorithm does Motif use?  I am told that Motif uses
some sort of algorithm that will take a single color that is defined for the
"background" and scale it so that the widget remains discriminable from the
background, etc.  What is the algorithm?

[Last modified: Oct 94]

Answer: Chris Flatters (cflatter@nrao.edu) writes: Shiz Kobara's book "Visual
Design with OSF/Motif", Addison Wesley,  1991, ISBN 0-201-56320-7) is a good
source for information of this sort.  I haven't seen it in bookshops for a
while so it may have gone out of print (which would be a pity).  In essence
each widget has 4 colours which, to first order, are

        background
        select          (background * 85%)
        top shadow      (background * 150%)
        bottom shadow   (background * 50%)

An additional correction may be applied to the hues of the calculated colours
if any of the RGB values saturates.  The algorithm works best if the brightest
of the RGB components lies in the range 155-175 (on a scale of 0-255).  The
top shadow becomes darker than the background for light background colours
which does not lead to a particularly pleasing effect.

-----------------------------------------------------------------------------
Subject: 242)  How can you access the superclass widget from which Motif
convenience dialogs are subclassed?

[Last modified: Oct 94]

Answer: Kim Frei (uunet!ask.uniras.dk!kimf) wrote: If you are using Motif 1.2,
read about XmTemplateDialog.

-----------------------------------------------------------------------------
Subject: 243)* Can the Notebook widget display non-rectangular "file tabs"?
Is it possible to use the Shape extension to fiddle with the shape of the
major tabs (XmPushButtons right now) to get non-rectangular buttons, going for
that "file tab" look?

[Last modified: May 95]

Answer: Vania Joloboff <uunet!gr.osf.org!vania> wrote:

On the Motif 2.0* CD-ROM, in the demos directory, there is a library of
additional widgets lib/Exm.  Among the widgets, there is a ExmTabButton
especially designed to fit within a Notebook. It has a smooth shape like real
tabs in folders.

It also a good example on how to use the new traits and the Xme API for widget
writers.

(Thanks to Ken Lee, kenton@rahul.net, for a correction here.)

-----------------------------------------------------------------------------
Subject: 244)  How does the clipboard mechanism work?

[Last modified: Dec 94]

A.  Doug Rand <drand@sgi.com> writes:

Basically there are two selections CLIPBOARD_MANAGER and CLIPBOARD which are
used.  The Motif clipboard is not a clipboard manager, but xclipboard,  or a
more functional clipboard client would be.  The newest ICCCM (2.0) spells this
out.

The basic process is that the clipboard manager:

1) Check to see if CLIPBOARD_MANAGER is owned by anyone,  abort if it is.

2) Assert ownership of CLIPBOARD_MANAGER and CLIPBOARD

3) When the CLIPBOARD selection is lost,  query new owner for data and then
retake ownership of CLIPBOARD

#3 is done until the application exists.  What you do with the data is up to
the application.

-----------------------------------------------------------------------------
Subject: 245)  Why does the xyz application core dump when I cut and paste?

Answer: Application crashes when text is cut and pasted into an XmText widget
may occur with statically linked executables linked with X11R5 libraries under
SunOS. For example, a Netscape README file says:

    The SunOS 4.1 [Netscape 0.94] distribution also includes a directory
    called "nls".  This directory is a standard part of the MIT X11R5
    distribution, but is not included with OpenWindows 3.0 or earlier.  We
    have linked Netscape against the MIT R5 libraries because they are
    less buggy in general; however, they have one rather serious bug,
    which is that if this "nls" directory does not exist, the program will
    dump core any time you try to paste into a text field!

    So, if you don't have the "nls" directory on your system, you will
    need to install it first.  The usual place is /usr/lib/X11/nls,
    but you can put it anywhere: just point the $XNLSPATH environment
    variable at it.

    Some sites don't have their X libraries installed in /usr/lib/X11/.
    This doesn't matter.  You either need to put the nls directory in
    /usr/lib/X11/, or every user will need to set this environment
    variable.

So, for example, we do:

       setenv XNLSPATH /usr/local/x11r5/lib/X11/nls

since our X11R5 is not installed in the default location.

-----------------------------------------------------------------------------
Subject: 246)  Why doesn't XtNameToWidget (widget, "MyName") work?

[Last modified: Apr 95]

Answer: The second argument must be a qualified specification (like a resource
specification).  In most cases, you'll use something like "*MyName".  The
leading '*' is required.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 247)  Why does my structure contain incorrect data when the callback
is called?  I created a structure and used a pointer to it as callback client
data.

[Last modified: Apr 95]

Answer: If your structure is declared as automatic, the callback will probably
not be executed within the structure's scope, so the pointer to the structure
will become invalid.  You can avoid this problem by declaring your structure
external or by allocating with malloc or (in C++) new.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 248)+ How can an application manage events on multiple displays?

[Last modified: May 95]

Answer: Just put multiple display pointers into one application context.  (You
normally specify which application context as an argument to XtOpenDisplay()).
XtAppNextEvent() and XtAppMainLoop() automatically poll all displays in the
application context.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 249)+ Why do I get "Error: attempt to add non-widget child "dsm" to
parent"?

[Last modified: May 95]

Answer: You're linking your libraries in the wrong order.  You must link -lXm
*before* -lXt.

Thanks to Ken Lee, kenton@rahul.net

Ken Sall (ksall@cen.com) adds: This same error occurs if you combine Motif and
Athena widgets in the same application. If you link with "-lXaw" before "-
lXm", you get the runtime error. However, if you switch the order of the two
libraries, there is no problem. For example:

        cc mothena.c -o mothena -lXm -lXaw -lXt -lXmu -lX11


-----------------------------------------------------------------------------
Subject: 250)+ Why do I get link errors about "XShape" symbols?

[Last modified: May 95]

Answer: You must link with the Extensions library, -lXext, after any widget
libraries.  For example,

        cc -o myapp myapp.o -lXm  -lXt -lXext -lX11

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 251)+ Why does my X11R6 program crash with undefined symbol
"LowerCase"?

[Last modified: May 95]

Answer: If you are using Motif version 1.1.[123], then the problem may be a
failure to set MotifBC to YES in your site.def.

Thanks to Geoffrey Leach, geoff@netcom.com

-----------------------------------------------------------------------------

Subject: 252)  TOPIC: HISTORY and ACKNOWLEDGEMENTS

[Last modified: Apr 95]

Answer:

History:
-------
November 89 to July 93: FAQ was maintained by Jan Newmarch
                        (jan@ise.canberra.edu.au)

July 93 to August 94:   FAQ was maintained by Brian Dealy
                        (dealy@c3i.saic.com)

Acknowledgments:
----------------
This list was compiled using questions and answers posed to
comp.windows.x.motif and motif-talk. Some information was excerpted from the
comp.windows.x FAQ.  To all who contributed one way or the other, thanks! We
try to give individual references, but you may recognize something uncredited
as your contribution. If we've mangled the words (or, heaven forbid, the code)
too much, let the current maintainer know.

NOTE: If you are a two-or-more-time contributor to this FAQ and you have a WWW
personal home page which you'd like to have listed, see the subject: "Which X
and Motif developers have their own home page URLs?"


  Jan Newmarch, Information Science and Engineering,
  University of Canberra, PO Box 1, Belconnen, Act 2616
  Australia. Tel: (Aust) 6-2522422. Fax: (Aust) 6-2522999

  ACSnet: jan@ise.canberra.edu.au
  ARPA:   jan%ise.canberra.edu.au@uunet.uu.net
  UUCP:   {uunet,ukc}!munnari!ise.canberra.edu.au!jan
  JANET:  jan%au.edu.canberra.ise@EAN-RELAY


Jan Newmarch maintained this FAQ for a long time and has really helped a great
many of us by providing this valuable service.  He deserves a big round of
applause for his efforts.  I use this resource all the time and it has saved
me countless hours with manuals and source code trying to relearn what others
have already discovered.  Jan`s efforts are gratefully acknowledged here.


  Brian Dealy, SAIC
  dealy@c3i.saic.com


Likewise, Brian Dealy of SAIC did an admirable job taking over the Motif FAQ
from Jan. A considerable amount of information was added during his tenure and
we greatly appreciate Brian's work on the FAQ, as well as his efforts in
maintaining the comp.windows.x.motif newsgroup reflector, for the good of all
Motif-dom.


  Ken Sall
  ksall@cen.com
  Tel: (301) 953-3330  FAX: (301) 953-2368
  Century Computing, Inc.
  http://www.cen.com/


