From: jan@ECHO.CANBERRA.EDU.AU (Jan Newmarch)
Newsgroups: comp.windows.x.motif
Subject: Frequently Asked Questions about Motif (Part 2 of 4)
Keywords: FAQ question answer
Date: 9 Apr 92 00:06:24 GMT
Expires: 8 Jun 92 15:51:30 GMT
Reply-To: jan@echo.canberra.edu.au (Jan Newmarch)
Followup-To: comp.windows.x.motif
Distribution: inet
Organization: The Internet

Archive-name: motif-faq-2
Last-modified: Wed Apr 8 1992
Version: 2.4


-------------------------------------------------------------------------------
Subject: 42) TOPIC: LIST WIDGET

-------------------------------------------------------------------------------
Subject: 43) How do I best put a new set of items into a list?

Answer: Set the new list count and list by XtSetArgs and install them by
XtSetValues.

    XmString list[SIZE];
    int list_size;

    XtSetArg (args[n], XmNitemCount, list_size); n++;
    XtSetArg (args[n], XmNitems, list); n++;
    XtSetValues (w, args, n);

Each time the list is reset by this the old contents are freed by the widget and
the new supplied list is copied.  Do *not* free the old list of items yourself
as this would result in the space being freed twice.  It is not necessary to
remove the items one at a time, nor to "zero" out the list first.

-------------------------------------------------------------------------------
Subject: 44)  Can I have strings with different fonts in a list?

Answer: Yes. The strings are XmStrings. Each one can be created using a
different character set using a different font.


-------------------------------------------------------------------------------
Subject: 45) Can I get a bitmap to show in a list item like I can in a Label?  I
want to place a bitmap along with some normal text in my list items.

Answer: No. The list contains XmStrings, and these only allow text in various
character sets. The workaround is to define your font containing the icons you
want. Then you can create a fontlist containing your icon font and the font you
want the text in, and then make your items multi-segment XmStrings where the
first segment contains the code of the icon you want with a charset that matches
the icon font in your fontlist and the second segment with a charset matching
the text font.


-------------------------------------------------------------------------------
Subject: 46) Can I have items with different colours in a list?

Answer: No.  The list contains XmStrings, and these only allow text in various
character sets. Since the items are XmStrings, you can already change the font
of an item by replacing it with an item with the same text and a different
charset tag.  Adding support for color would require modification of the
internal data structure in XmList as well as modification to the drawing
routines.  A possible workaround is to use a rowcolumn of buttons which can be
individually set.  However, you would have to do all list functionality
yourself.


-------------------------------------------------------------------------------
Subject: 47) Can I grey out an item in a list?  I want to make insensitive items
in a list so that they cannot be selected.

Answer:

From W. Scott Meeks of OSF:

Unfortunately, you can't do it directly since the list items aren't individual
widgets.  We've had other requests for this technology, but it didn't make the
cut for 1.2; it should be in some future release.

However, you can probably fake it in your application with some difficulty.
First, a list item is an XmString, so you can specify a different charset for
the item than for other items in the list and then specify a font in the list's
fontlist that matches the charset and gives you the visual you want.  The next
problem is making the item unselectable.  One idea would be to have the
application keep track of the insensitive items and the items currently
selected.  Then you would set up a selection callback that when called would
check the item selected against the list of insensitive items and if the
selected item matched would deselect that item and reselect the previously
selected items.  Otherwise it would just update the application's list of
selected items.  The major drawback with this approach is that you'll get
flashing whenever the list selects an item and your application immediately de-
selects.  Unfortunately I can't think of a way around this without mucking with
the list internals.

Another alternative suggested is to use instead a column of say read only text
widgets which you can make insensitive.

-------------------------------------------------------------------------------
Subject: 48) TOPIC: FILE SELECTION BOX WIDGET

-------------------------------------------------------------------------------
Subject: 49)* What is libPW.a and do I need it?  My manual says I need to link
in libPW.a to use the File Selection Box.  I can't find it on my system.

Answer: The libPW.a is the Programers Workbench library which is an ATT product
not included in Berkeley based systems, hence it is not found in SunOS or
Ultrix, but is found on HP-UX (a Berkeley/ATT hybrid which chose ATT in this
case).  It contains the regex(3) routines (regcmp, regex).  Some systems which
don't have these in the libc.a need to link with -lPW.  Some systems which have
the regex(3) routines in there also have the libPW.a.  If you have regex(3) in
libc, and it works, don't link with libPW.  If you don't have regex(3) in libc,
and you don't have a libPW, then check some sites on the net for public domain
replacements (several exist), or call your vendor.

In most versions of Motif (see the doco), you can compile FileSB.c with
-DNO_REGEX if you don't have it.

-------------------------------------------------------------------------------
Subject: 50)+ What are these compile errors: Undefined symbol _regcmp?

Answer: You need to link in the libPW library - see previous question.


-------------------------------------------------------------------------------
Subject: 51) What's wrong with the Motif 1.0 File Selection Box?  I can't set
the directory, change the directory or get the file mask to work.

Answer: The 1.0 File Selection Box is broken, and these don't work.  They
weren't fixed until Motif 1.04.  Use these later versions of 1.0 or switch to
Motif 1.1 where it changed a lot.

Joe Hildebrand has a work-around for some of this: Before popping up an
XmFileSelectionDialog, change to the directory you want.  When a file is
selected, check if it is a directory, so that we can change to it.  i.e.

static void show_file_box_CB(w, client_data, call_data)
   Widget               w;
   Widget               client_data;
   XmAnyCallbackStruct  *call_data;
{
   chdir("/users/hildjj/files");
   XtManageChild(client_data);
}

static void val_save(w, client_data, call_data)
   Widget       w;
   Widget       client_data;
   XmSelectionBoxCallbackStruct *call_data;
{
   struct stat buf;  /* struct stat is defined in stat.h */
   char *filename;

   /* get the file name from the FileSelectionBox */
   filename = SmX(call_data->value);

   /* get the status of the file named filename, and put it into buf */
   if (!stat(filename, &buf))
   {
      /* if it's a directory */
      /* if it's a directory */
      if(S_ISDIR(buf.st_mode))
      {
         /* change to that directory, and update the FileSelectionBox */
        chdir(filename);
        XmFileSelectionDoSearch(w, NULL);
      }
      else
         /* if it's a regualr file */
         if(S_ISREG(buf.st_mode))
            /* ask if it should be overwritten */
            XtManageChild(valbox);
         else
            /* it's another kind of file.  What type, i can't think of,
               but it might happen */
            pop_up_error_box(client_data, "Error saving file");
   }
   else  /* we couldn't get the file status */
   {
      /* if it's because the file doesn't exist, we're golden */
      if (errno == ENOENT)
         save_file();
      else   /* there is some other problem getting the status.
                e.g. bad path */
         pop_up_error_box(client_data, "Error saving file");
   }
}

this still doesn't implement the file masking stuff.


-------------------------------------------------------------------------------
Subject: 52) TOPIC: FORM WIDGET


-------------------------------------------------------------------------------
Subject: 53)* Why don't labels in a Form resize when the label is changed?  I've
got some labels in a form. The labels don't resize whenever the label string
resource is changed. As a result, the operator has to resize the window to see
the new label contents. I am using Motif 1.1.

Answer: This problem may happen to any widget inside a Form widget. The problem
was that the Form will resize itself when it gets geometry requests from its
children. If its preferred size is not allowed, the Form will disallow all
geometry requests from its children. The workaround is that you should set any
ancestor of the Form to be resizable. For the shell which contains the Form you
should set the shell resource XmNallowShellResize to be True (by default, it is
set to FALSE).  There is currently an inconsistency on how resizing is being
done, and it may get fixed in Motif 1.2.

From db@sunbim.be (Danny Backx)

Basically what you have to do is set the XmNresizePolicy on the Form to
XmRESIZE_NONE.  The facts seem to be that XmRESIZE_NONE does NOT mean "do not
allow resizes".  You may also have to set XmNresizable on the form to True.

-------------------------------------------------------------------------------
Subject: 54)* How can I center a widget in a form?

Answer: One of Motif's trickier questions.  The problems are that: Form gives no
support for centering, only for edge attachments, and the widget must stay in
the center if the form or the widget is resized.  Just looking at horizontal
centering (vertical is similar) some solutions are:

 a.  Use the table widget instead of Form.

 b.  A hack free solution is from Dan Heller:

     /* 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.  This program is
      * taken from the Motif Programming Manual, O'Reilly Volume 6.
      */

     /* corners.c -- demonstrate widget layout management for a
      * BulletinBoard widget.  There are four widgets each labeled
      * top-left, top-right, bottom-left and bottom-right.  Their
      * positions in the bulletin board correspond to their names.
      * Only when the widget is resized does the geometry management
      * kick in and position the children in their correct locations.
      */
     #include <Xm/BulletinB.h>
     #include <Xm/PushBG.h>

     char *corners[] = {
         "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right",
     };

     static void resize();

     main(argc, argv)
     int argc;
     char *argv[];
     {
         Widget toplevel, bboard;
         XtAppContext app;
         XtActionsRec rec;
         int i;

         /* Initialize toolkit and create toplevel shell */
         toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
             &argc, argv, NULL, NULL);

         /* Create your standard BulletinBoard widget */
         bboard = XtVaCreateManagedWidget("bboard",
             xmBulletinBoardWidgetClass, toplevel, NULL);

         /* Set up a translation table that captures "Resize" events
          * (also called ConfigureNotify or Configure events).  If the
          * event is generated, call the function resize().
          */
         rec.string = "resize";
         rec.proc = resize;
         XtAppAddActions(app, &rec, 1);
         XtOverrideTranslations(bboard,
             XtParseTranslationTable("<Configure>: resize()"));

         /* Create children of the dialog -- a PushButton in each corner. */
         for (i = 0; i < XtNumber(corners); i++)
             XtVaCreateManagedWidget(corners[i],
                 xmPushButtonGadgetClass, bboard, NULL);

         XtRealizeWidget(toplevel);
         XtAppMainLoop(app);
     }

     /* resize(), the routine that is automatically called by Xt upon the
      * delivery of a Configure event.  This happens whenever the widget
      * gets resized.
      */
     static void
     resize(w, event, args, num_args)
     CompositeWidget w;   /* The widget (BulletinBoard) that got resized */
     XConfigureEvent *event;  /* The event struct associated with the event */
     String args[]; /* unused */
     int *num_args; /* unused */
     {
         WidgetList children;
         int width = event->width;
         int height = event->height;
         Dimension w_width, w_height;
         short margin_w, margin_h;

         /* get handle to BulletinBoard's children and marginal spacing */
         XtVaGetValues(w,
             XmNchildren, &children,
             XmNmarginWidth, &margin_w,
             XmNmarginHeight, &margin_h,
             NULL);

         /* place the top left widget */
         XtVaSetValues(children[0],
             XmNx, margin_w,

             XmNy, margin_h,
             NULL);

         /* top right */
         XtVaGetValues(children[1], XmNwidth, &w_width, NULL);

         /* To Center a widget in the middle of the BulletinBoard (or Form),
          * simply call:
          *   XtVaSetValues(widget,
               XmNx,    (width - w_width)/2,
               XmNy,    (height - w_height)/2,
               NULL);
          * and return.
          */
         XtVaSetValues(children[1],
             XmNx, width - margin_w - w_width,
             XmNy, margin_h,
             NULL);
         /* bottom left */
         XtVaGetValues(children[2], XmNheight, &w_height, NULL);
         XtVaSetValues(children[2],

             XmNx, margin_w,
             XmNy, height - margin_h - w_height,
             NULL);
         /* bottom right */
         XtVaGetValues(children[3],
             XmNheight, &w_height,
             XmNwidth, &w_width,
             NULL);
         XtVaSetValues(children[3],
             XmNx, width - margin_w - w_width,
             XmNy, height - margin_h - w_height,
             NULL);
     }

 c.  No uil solution has been suggested, because of the widget size problem

-------------------------------------------------------------------------------
Subject: 55)* How do I line up two columns of widgets of different types?  I
have a column of say label widgets, and a column of text widgets and I want to
have them lined up horizontally. The problem is that they are of different
heights. Just putting them in a form or rowcolumn doesn't line them up properly
because the label and text widgets are of different height.

If you want the geometry to look like this

          -------------------------------------
         |          -------------------------- |
         |a label  |Some text                 ||
         |          -------------------------- |
                           ------------------- |
         |a longer label  |Some more text     ||
         |                 ------------------- |
         |                    ---------------- |
         |a very long label  |Even more text  ||
         |                    ---------------- |
          -------------------------------------

try

/* 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.  This program is
 * taken from the Motif Programming Manual, O'Reilly Volume 6.
 */

/* text_form.c -- demonstrate how attachments work in Form widgets.
 * by creating a text-entry form type application.
 */

#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/LabelG.h>
#include <Xm/Text.h>
#include <Xm/Form.h>

char *prompts[] = {
    "Name:", "Phone:", "Address:",
    "City:", "State:", "Zip:",
};

main(argc, argv)
int argc;
char *argv[];
{
    Widget toplevel, mainform, subform, label, text;
    XtAppContext app;
    char buf[32];
    int i;

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

    mainform = XtVaCreateWidget("mainform",
        xmFormWidgetClass, toplevel,
        NULL);

    for (i = 0; i < XtNumber(prompts); i++) {
        subform = XtVaCreateWidget("subform",
            xmFormWidgetClass,   mainform,
            /* first one should be attached for form */
            XmNtopAttachment,    i? XmATTACH_WIDGET : XmATTACH_FORM,
            /* others are attached to the previous subform */
            XmNtopWidget,        subform,
            XmNleftAttachment,   XmATTACH_FORM,
            XmNrightAttachment,  XmATTACH_FORM,
            NULL);
        label = XtVaCreateManagedWidget(prompts[i],
            xmLabelGadgetClass,  subform,
            XmNtopAttachment,    XmATTACH_FORM,
            XmNbottomAttachment, XmATTACH_FORM,
            XmNleftAttachment,   XmATTACH_FORM,
            XmNalignment,        XmALIGNMENT_BEGINNING,
            NULL);
        sprintf(buf, "text_%d", i);
        text = XtVaCreateManagedWidget(buf,
            xmTextWidgetClass,   subform,
            XmNtopAttachment,    XmATTACH_FORM,
            XmNbottomAttachment, XmATTACH_FORM,
            XmNrightAttachment,  XmATTACH_FORM,
            XmNleftAttachment,   XmATTACH_WIDGET,
            XmNleftWidget,       label,
            NULL);
        XtManageChild(subform);
    }
    /* Now that all the forms are added, manage the main form */
    XtManageChild(mainform);

    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
}

If you resize horizontally it stretches the text widgets.  If you resize
vertically it leaves space under the bottom (if you don't resize, this is not
problem).

If you want the text widgets to be lined up on the left, as in

          ----------------------------------------
         |                    ------------------- |
         |          a label  |Some text          ||
         |                    ------------------- |
                              ------------------- |
         |   a longer label  |Some more text     ||
         |                    ------------------- |
         |                    ------------------- |
         |a very long label  |Even more text     ||
         |                    ------------------- |
          ----------------------------------------

try this

/* 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.  This program is
 * taken from the Motif Programming Manual, O'Reilly Volume 6.
 */

/* text_entry.c -- This demo shows how the RowColumn widget can be
 * configured to build a text entry form.  It displays a table of
 * right-justified Labels and Text widgets that extend to the right
 * edge of the Form.
 */
#include <Xm/LabelG.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>

char *text_labels[] = {
    "Name:", "Phone:", "Address:", "City:", "State:", "Zip:",
};

main(argc, argv)
int argc;
char *argv[];
{
    Widget toplevel, rowcol;
    XtAppContext app;
    char buf[8];
    int i;

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

    rowcol = XtVaCreateWidget("rowcolumn",
        xmRowColumnWidgetClass, toplevel,
        XmNpacking,        XmPACK_COLUMN,
        XmNnumColumns,     XtNumber(text_labels),
        XmNorientation,    XmHORIZONTAL,
        XmNisAligned,      True,
        XmNentryAlignment, XmALIGNMENT_END,
        NULL);

    /* simply loop thru the strings creating a widget for each one */
    for (i = 0; i < XtNumber(text_labels); i++) {
        XtVaCreateManagedWidget(text_labels[i],
            xmLabelGadgetClass, rowcol,
            NULL);
        sprintf(buf, "text_%d", i);
        XtVaCreateManagedWidget(buf,
            xmTextWidgetClass, rowcol,
            NULL);
    }

    XtManageChild(rowcol);
    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
}

This makes all objects exactly the same size.  It does not resize in nice ways.

If you want the text widgets lined up on the left, and the labels to be the size
of the longest string, resizing nicely both horizontally and vertically, as in

         -------------------------------------
        |                    ---------------- |
        |          a label  |Some text       ||
        |                    ---------------- |
                             ---------------- |
        |   a longer label  |Some more text  ||
        |                    ---------------- |
        |                    ---------------- |
        |a very long label  |Even more text  ||
        |                    ---------------- |
         -------------------------------------



Answer: Do this: to get the widgets lined up horizontally, use a form but place
the widgets using XmATTACH_POSITION.  In the example, attach the top of the
first label to the form, the bottomPosition to 33 (33% of the height).  Attach
the topPosition of the second label to 33 and the bottomPosition to 66.  Attach
the topPosition of the third label to 66 and the bottom of the label to the
form.  Do the same with the text widgets.

To get the label widgets lined up vertically, use the right attachment of
XmATTACH_OPPOSITE_WIDGET: starting from the one with the longest label, attach
widgets on the right to each other. In the example, attach the 2nd label to the
third, and the first to the second.  To get the text widgets lined up, just
attach them on the left to the labels.  To get the text in the labels aligned
correctly, use XmALIGNMENT_END for the XmNalignment resource.

        /* geometry for label 2
        */
        n = 0;
        XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
        XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNtopPosition, 66); n++;
        XtSetValues (label[2], args, n);

        /* geometry for label 1
        */
        n = 0;
        XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNbottomPosition, 66); n++;
        XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNtopPosition, 33); n++;
        XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
        XtSetArg (args[n], XmNrightWidget, label[2]); n++;
        XtSetValues (label[1], args, n);

        /* geometry for label 0
        */
        n = 0;
        XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNbottomPosition, 33); n++;
        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
        XtSetArg (args[n], XmNrightWidget, label[1]); n++;
        XtSetValues (label[0], args, n);

        /* geometry for text 0
        */
        n = 0;
        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNbottomPosition, 33); n++;
        XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
        XtSetArg (args[n], XmNleftWidget, label[0]); n++;
        XtSetValues (text[0], args, n);

        /* geometry for text 1
        */
        XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNtopPosition, 33); n++;
        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNbottomPosition, 66); n++;
        XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
        XtSetArg (args[n], XmNleftWidget, label[1]); n++;
        XtSetValues (text[1], args, n);

        /* geometry for text 2
        */
        XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
        XtSetArg (args[n], XmNtopPosition, 66); n++;
        XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
        XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
        XtSetArg (args[n], XmNleftWidget, label[2]); n++;
        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
        XtSetValues (text[2], args, n);


-------------------------------------------------------------------------------
Subject: 56) TOPIC: PUSHBUTTON WIDGET

-------------------------------------------------------------------------------
Subject: 57) Why can't I use accelerators on buttons not in a menu?

Answer: It is apparently a difficult feature to implement, but OSF are
considering this for the future. It is problematic trying to use the Xt
accelerators since the Motif method interferes with this.  The workaround
suggested so far is to duplicate your non-menu button by a button in a menu
somewhere, which does have a menu-accelerator installed.  When the user invokes
what they think is the accelerator for the button they can see Motif actually
invokes the button on the menu that they can't see at the time.


-------------------------------------------------------------------------------
Subject: 58) TOPIC: LABEL WIDGET

-------------------------------------------------------------------------------
Subject: 59) How can I align the text in a label (button, etc) widget?

Answer: The alignment for the label widget is controlled by the resource
XmNalignment, and the default centers the text. Use this resource to change it
to left or right alignment.  However, when the label (or any descendant) is in a
row column, and XmNisAligned is True (the default), the row column aligns text
using its resource XmNentryAlignment. If you want simultaneous control over all
widgets use this, but otherwise turn XmNisAligned off and do it individually.



-------------------------------------------------------------------------------
Subject: 60) Why doesn't label alignment work in a RowColumn?

Answer: RowColumn has a  resource XmNisAligned (default True) and and
XmNentryAlignment (default XmALIGNMENT_BEGINNING).  These control alignment of
the labelString in Labels and descendants. Set XmNisAligned to False to turn
this off.

-------------------------------------------------------------------------------
Subject: 61)* How can I set a multiline label?

Answer: In .Xdefaults

      *Label*labelString:             Here\nis\nthe\nLabel

In code,

      char buf[128];
      XmString msg;
      sprintf(buf, "Here\nis\nthe\nLabel");
#if XmVersion == 1000    /* Motif 1.0 */
      msg = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
#else                    /* other Motif versions */
      msg = XmStringCreateSimple(buf);
#endif
      XtSetArg (args[n], XmNlabelString, msg);

Gives a four line label, using the escape sequence \n for a newline.
XmStringCreateLtoR() is obsoleted from version 1.1 on, and may disappear.
XmStringCreateSimple() is not available in Motif 1.0.

-------------------------------------------------------------------------------
Subject: 62)  How can I have a vertical label?

Answer: Make a multiline label with one character per line, as in the last
question. There is no way to make the text rotated by 90 degrees though.


-------------------------------------------------------------------------------
Subject: 63) TOPIC: DRAWING AREA WIDGET

-------------------------------------------------------------------------------
Subject: 64) How can I send an expose event to a Drawing Area widget?  (or any
other, come to that). I want to send an expose event so that it will redraw
itself.

Answer: Use the Xlib call

        XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True)

This clears the widget's window and generates an expose event in doing so.  The
widgets expose action will then redraw it.  This uses a round trip request.  An
alternative, without the round trip is

from orca!mesa!rthomson@uunet.uu.net  (Rich Thomson):

    Widget da;
    XmDrawingAreaCallbackStruct da_struct;

    da_struct.reason = XmCR_EXPOSE;
    da_struct.event = (XEvent *) NULL;
    da_struct.window = XtWindow(da);

    XtCallCallbacks(da, XmNexposeCallback, (XtPointer) da_struct);


-------------------------------------------------------------------------------
Subject: 65)+ How can I know when a DrawingArea has been resized?  It generates
an expose event whn it is enlarged, but not when it is shrunk.

Answer: Use the resize callback.

-------------------------------------------------------------------------------
Subject: 66) TOPIC: MENUS

-------------------------------------------------------------------------------
Subject: 67) What can I put inside a menu bar?

Answer: You can only put cascade buttons in menu bars. No pushbuttons, toggle
buttons or gadgets are allowed. When you create a pulldown menu with parent a
menu bar, its real parent is a shell widget.

-------------------------------------------------------------------------------
Subject: 68) Can I have a cascade button without a submenu in a pulldown menu?

Answer: Yes you can. A cascade button has an activate callback which is called
when you click on it and it doesn't have a submenu. It can have a mnemonic, but
keyboard traversal using the arrow keys in the menu will skip over it.

-------------------------------------------------------------------------------
Subject: 69) Should I have a cascade button without a submenu in a pulldown
menu?

Answer: No. This is forbidden by the style guide. Technically you can do it (see
previous question) but if you do it will not be Motif style compliant. This is
unlikely to change - if a "button" is important enough to be in a pulldown menu
bar with no pulldown, it should be a button elsewhere.  (Mind you, you won't be
able to put accelerators on it elsewhere though.)