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

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




-----------------------------------------------------------------------------
Subject: 89)  TOPIC: LIST WIDGET

-----------------------------------------------------------------------------
Subject: 90)  Should I create an XmList widget as a child of automatic
XmScrolledWindow or use the XmCreateScrolledList() convenience function?

Answer: With most implementations, the convenience function use internal hooks
to give somewhat better scrolling performance.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 91)  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);


or similarly with XtVaSetValues:


    XtVaSetValues (w,
       XmNitemCount, list_size,
       XmNitems, list,
       NULL);


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: 92)  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: 93)  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: 94)  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: 95)  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:

W. Scott Meeks of OSF wrote:

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: 96)  Can I have multi-line items in a list?
[Last modified: August 92]

Answer: Motif 1.0 and 1.1 both have problems with multi-line items in a list.
They should work okay in Motif 1.2.

-----------------------------------------------------------------------------
Subject: 97)  How can I tell the position of selected items in a list?

[Last modified: Oct 92]

Answer: W. Scott Meeks wrote:

1) All XmList selection callbacks get an XmListCallbackStruct which includes
the item selected and its position.  In addition, the multiple and extended
selection callbacks also get a list of the selected items.  This approach
requires that your application saves this information if you need it outside
of the immediate callback.

2) At any time you can XtGetValues the XmNselectedItems and
XmNselectedItemCount resources.  The problem with this approach is that
identical items may or may not show up in multiple times in this list and the
position in the selectedItems list may not relate directly to the position in
the items list.

3) You can call XmListGetSelectedPos on the list widget.  This will return a
list of the positions of all selected items.

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

-----------------------------------------------------------------------------
Subject: 99)  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.

[Last modified: Sept 94]

Answer: The libPW.a is the Programmers 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.


Casper H.S. Dik (asper@fwi.uva.nl), Faculty of Mathematics & Computer Science,
University of Amsterdam, sent this update for Solaris 2.x users:

The regex and regcmp function are part of libgen in SVR4.  Motif applications
should be linked with -lgen. (However, some SVR4 implementations, especially
those of vendors that once shipped SVR3 still contain libPW.)

On Solaris 2.x system, you'll need libgen which is located in /usr/ccs/lib.

-----------------------------------------------------------------------------
Subject: 100)  What are these compile errors: Undefined symbol _regcmp and
_regex?

[Last modified: Sept 94]

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


-----------------------------------------------------------------------------
Subject: 101)  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 regular 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: 102)  What's wrong with the FileSelectionBox under Solaris?

[Last modified: Apr 95]

Answer: Jim Guyton (guyton@burton.cs.colorado.edu) writes:

While not strictly a Motif problem, this one had me confused for [awhile].

If under Solaris the entries in a FileSelectionBox look strange and seem to be
missing the first two characters of many filenames, then be sure you're
linking -lc before -lucb.

If on the other hand, the filenames look strange and seem to have two garbage
characters in front of every filename, be sure to link -lucb before -lc.

There are two versions of readdir().  The one in -lucb returns a structure
that has the filename at an offset of 8 bytes (which matches
/usr/ucbinclude/sys/dir.h).

But the version in -lc returns the filename at an offset of 10 bytes (which
matches /usr/include/dirent.h).

So depending on how Motif was built for your Solaris, vs. how you link your
application, your filenames could be two bytes off in either direction.

-----------------------------------------------------------------------------
Subject: 103)  TOPIC: FORM WIDGET


-----------------------------------------------------------------------------
Subject: 104)  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.

db@sunbim.be (Danny Backx) wrote:

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: 105)  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 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.
      */

     /* 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: 106)  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 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.
 */

/* 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 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.
 */

/* 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: 107)  TOPIC: PUSHBUTTON WIDGET

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

[Last modified: Sept 94]

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.  one workaround suggested 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. Another method is described below
and was contributed by Harald Albrecht of Institute of Geometry and Practical
Mathematics Rhine Westphalia Technical University Aachen (RWTH Aachen),
Germany


albrecht@igpm.rwth-aachen.de wrote (Jul 8, 1993):

NOTE: Pointers to a more recent solution by the same author follow this code
sample.

My work-around of this problem looks like this: (I've written that code for a
Motif Object Library in C++ so please forgive me for being object orientated!)
The hack consists of a rewritten message loop which checks for keypresses
<MAlt>+<key>. If MessageLoop() finds such a keypress HandleAcc() ist called
and the widget tree is searched for a suitable widget with the right mnemonic.


// --------------------------------------------------------------------------
// traverse the widget tree starting with the given widget.
//
BOOL TraverseWidgetTree(Widget w, char *pMnemonic, XKeyEvent *KeyEvent)
{
    Widget               wChild;
    WidgetList           ChildList;
    int                  NumChilds, Child;
    KeySym               LabelMnemonic;
    char                 *pMnemonicString;

// Check if the widget is a subclass of label -- then it may have an
// accelerator attached...
    if ( XtIsSubclass(w, xmLabelWidgetClass) ) {
// ok. Now: get the widget's mnemonic, convert it to ASCII and compare
// it with the Key we're looking for.
        XtVaGetValues(w, XmNmnemonic, &LabelMnemonic, NULL);
        pMnemonicString = XKeysymToString(LabelMnemonic);
        if ( pMnemonicString &&
             (strcasecmp(pMnemonicString, pMnemonic) == 0) ) {
            // stimulate the keypress
            XmProcessTraversal((Widget)w, XmTRAVERSE_CURRENT);
            KeyEvent->type      = KeyPress;
            KeyEvent->window    = XtWindow(w);
            KeyEvent->subwindow = XtWindow(w);
            KeyEvent->state     = 0;
            KeyEvent->keycode   =
                XKeysymToKeycode(XtDisplay(w), XK_space);
            XSendEvent(XtDisplay(w), XtWindow(w),
                       True,
                       ButtonPressMask, (XEvent*) KeyEvent);
            KeyEvent->type      = KeyRelease;
            XSendEvent(XtDisplay(w), XtWindow(w),
                       True,
                       ButtonReleaseMask, (XEvent*) KeyEvent);
            return True;
        }
    }
// if this widget is a subclass of Composite check all the widget's
// childs.
    if ( XtIsSubclass(w, compositeWidgetClass) ) {
// if we're in a menu (or something like that) forget this leaf of the
// widget tree!
        if ( XtIsSubclass(w, xmRowColumnWidgetClass) ) {
            unsigned char RowColumnType;
            XtVaGetValues(w, XmNrowColumnType, &RowColumnType, NULL);
            if ( RowColumnType != XmWORK_AREA ) return False;
        }
        XtVaGetValues(w, XmNchildren, &ChildList,
                         XmNnumChildren, &NumChilds, NULL);
        for ( Child = 0; Child < NumChilds; ++Child ) {
            wChild = ChildList[Child];
            if ( TraverseWidgetTree(wChild, pMnemonic, KeyEvent) )
                return True;
        }
    }
    return False;
} // TraverseWidgetTree
// --------------------------------------------------------------------------
// handle accelerators (keypress MAlt + key)
//
#define MAX_MAPPING 10
BOOL HandleAcc(Widget w, XEvent *event)
{
           Widget         widget, OldWidget;
    static char           keybuffer[MAX_MAPPING];
           int            CharCount;
    static XComposeStatus composeStatus;

// convert KeyPress to ASCII
    CharCount = XLookupString((XKeyEvent*) event,
                              keybuffer, sizeof(keybuffer),
                              NULL, &composeStatus);
    keybuffer[CharCount] = 0;
// Only one char is alright -- then search the widget tree for a widget
// with the right mnemonic
    if ( CharCount == 1 ) {
        keybuffer[0] = tolower(keybuffer[0]);
        widget = w;
        while ( (widget != NULL) &&
                !XtIsSubclass(widget, shellWidgetClass) ) {
            OldWidget = widget; widget = XtParent(widget);
        }
        if ( !widget ) widget = OldWidget;
        return TraverseWidgetTree(widget,
                                  keybuffer, (XKeyEvent*) event);
    }
    return False; // no-one found.
} // HandleAcc
// --------------------------------------------------------------------------
// modified message loop
// loops until the Boolean pFlag points to is set to False
void MessageLoop(Boolean *pFlag)
{
    XEvent nextEvent;

    while ( *pFlag ) {
        if ( XtAppPending(AppContext) ) {
            XtAppNextEvent(AppContext, &nextEvent);
            if ( nextEvent.type == KeyPress ) {
// Falls es ein Tastendruck ist, bei dem auch noch die ALT-Taste
// (=Modifier 1) gedrueckt ist, koennte es ein Accelerator sein!
                if ( nextEvent.xkey.state & Mod1Mask )
                    if ( HandleAcc(XtWindowToWidget(nextEvent.xkey.display,
                                                    nextEvent.xkey.window),
                                   &nextEvent) )
                        continue; // Mitteilung konnte ausgeliefert werden
                                  // und darf daher nicht den ueblichen
                                  // Weg gehen!
            }
            XtDispatchEvent(&nextEvent);
        }
    }
} // TApplication::MessageLoop


Harald Albrecht albrecht@igpm.rwth-aachen.de Institute of Geometry and
Practical Mathematics Rhine Westphalia Technical University Aachen (RWTH
Aachen), Germany

NOTE: Harald Albrecht has re-designed his solution so that you can assign
hotkeys to *every* widget by placing a label near that widget. Get the code
from:

  ftp.informatik.rwth-aachen.de (137.226.112.172)
  in: /pub/packages/Mnemonic/Mnemonic.tar.gz

or from the WWW:

   file://134.130.161.30/arc/pub/unix/html/motifcorner.html

-----------------------------------------------------------------------------
Subject: 109)  TOPIC: ICON WIDGET

-----------------------------------------------------------------------------
Subject: 110)  How can I add multi-colored icons to my application?

[Last modified: Sept 94]

Answer: Get the Xpm (X PixMap file format) widgets.  There is a tutorial in
the directory ftp.x.org:/contrib/docs/xpm_tut and source code in the directory
ftp.x.org:/contrib/libraries.  Documentation is part of the tar file found in
/contrib/libraries.  The /contrib/libraries directory also contains xpm.FAQ.

There is also a mailing list: xpm-talk@sophia.inria.fr.

-----------------------------------------------------------------------------
Subject: 111)  How can I convert a Sun/GIF/TIFF image to a pixmap?

[Last modified: Oct 94]

Answer: An application called "xv" (interactive image display for the X Window
System) is useful for displaying and converting many image formats. From the
man page:

     xv is an X11 program that displays images in the GIF,  JPEG,
     TIFF,  PBM, PGM, PPM, X11 bitmap, PDS/VICAR, Sun Rasterfile,
     and PM formats on 1-, 2-, 4-, 6-, 8-, 16-, 24-, and 32-bit X
     displays.   xv  will also read compress-ed versions of these
     files.

You can get "xv" (shareware by John Bradley et al) from:

        ftp://ftp.cis.upenn.edu/pub/xv
or:
        ftp://ftp.x.org/R5contrib/xv-3.01.tar.gz

Another useful conversion package is "pbm" (portable bitmap file format) by
Jef Poskanzer et al, available from:

        ftp://ftp.x.org/R5contrib/netpbm-1mar1994.tar.gz
or:
        ftp://ftp.x.org/R5contrib/pbmplus10dec91.tar.Z (much older :-)

You might also want to check the X11 FAQ for additional conversion options:

        ftp://ftp.x.org/contrib/faqs/FAQ

-----------------------------------------------------------------------------
Subject: 112)  TOPIC: SCALE WIDGET

-----------------------------------------------------------------------------
Subject: 113)  Can the XmScale widget have arrows or tick marks in Motif 2.0?

Answer: Daniel Dardailler (daniel@x.org) (http://www.x.org/people/daniel)
writes:

In 2.0, Scale gets arrows (on both sides or same side), thermometer look,
thumb slider option, tick marks, and editable resource. For a picture, see:

    http://www.osf.org:8001:/motif/Motif20.html

-----------------------------------------------------------------------------
Subject: 114)+ How can I set the color of a XmScale widget's trough?

[Last modified: May 95]

Answer: Ken Lee, kenton@rahul.net, wrote: There is no direct API for setting
this, but you can set it through resource files with "*XmScale*troughColor:
red".

Ken Sall, ksall@cen.com, adds: If you need to do this at runtime, you can use
XtGetValues to get the scale's children, find the scrollbar, and set the
XmNtroughColor:

#include <Xm/ScrollBar.h>  // for XmIsScrollBar

        Pixel selectColor; // assume this is set to the desired color
        WidgetList *kids;
        int nkids;
        Arg argList[1], tmpargs[2];
        int i, s, t ;

        i = 0;
        XtSetArg ( argList[i], XmNtroughColor, selectColor ); i++;

        // Unfortunately, scale does not have a direct way
        // to get its scrollbar widget, so use Composite resources
        s = 0;
        XtSetArg (tmpargs[s], XmNnumChildren, &nkids ); s++ ;
        XtSetArg (tmpargs[s], XmNchildren, &kids ); s++ ;
        XtGetValues ( widgetId, tmpargs, s );
        for ( t = 0; t < nkids; t++ )
            {
            if ( XmIsScrollBar ( (Widget) kids[t]) ) // from ScrollBar.h
                {
                XtSetValues ( (Widget) kids[t], argList, i );
                }
            }


-----------------------------------------------------------------------------
Subject: 115)  TOPIC: LABEL WIDGET

-----------------------------------------------------------------------------
Subject: 116)  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: 117)  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: 118)  How can I set a multiline label?

[Last modified: Feb 95]

Answer: In .Xdefaults

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

This method does not seem to work in some of the older Motif 1.0 versions.

In code,

      char buf[128];
      XmString msg;
      sprintf(buf, "Here\nis\nthe\nLabel");
      msg = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNlabelString, msg);

Gives a four line label, using the escape sequence \n for a newline.  Here's
another approach from Jean-Philippe Martin-Flatin <syj@ecmwf.co.uk>

#include <Xm/Xm.h>
#include <string.h>

/*-----------------------------------------------------
    Create a new XmString from a char*

    This function can deal with embedded 'newline' and
    is equivalent to XmStringCreateLtoR,
    except it does not use non AES compliant charset
    XmSTRING_DEFAULT_CHARSET
----------------------------------------------------*/
XmString xec_NewString(char *s)
{
    XmString xms1;
    XmString xms2;
    XmString line;
    XmString separator;
    char     *p;
    char     *t = XtNewString(s);   /* Make a copy for strtok not to */
                                    /* damage the original string    */


    separator = XmStringSeparatorCreate();
    p         = strtok(t,"\n");
    xms1      = XmStringCreateLocalized(p);

    while (p = strtok(NULL,"\n"))
    {
        line = XmStringCreateLocalized(p);
        xms2 = XmStringConcat(xms1,separator);
        XmStringFree(xms1);
        xms1 = XmStringConcat(xms2,line);
        XmStringFree(xms2);
        XmStringFree(line);
    }

    XmStringFree(separator);
    XtFree(t);
    return xms1;
}


Do not use XmStringCreateLocalized() - it does not process the newline
character in the way you want. [TBD - Does anyone know if this statement is
true? Originally, this was in reference to the obsolete XmStringCreateSimple
function....ksall@cen.com]

-----------------------------------------------------------------------------
Subject: 119)  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: 120)  How can I have a Pixmap in a Label?

Answer: Bob Hays (bobhays@spss.com) wrote:

    Pixmap px_disarm, px_disarm_insens;

    Widget Label1;
    Pixel   foreground, background;
    Arg     args[4];
    Arg     arg[] = {
                { XmNforeground, &foreground },
                { XmNbackground, &background }
    };

    Label1 = XmCreateLabel ( Shell1, "Label1",
                                       (Arg *) NULL, (Cardinal) 0 );
    XtGetValues ( Label1, arg, XtNumber ( arg ) );
    px_disarm =
      XCreatePixmapFromBitmapData(display,
                                DefaultRootWindow(display),
                                mtn_bits, mtn_width, mtn_height,
                                foreground,
                                background,
                                DefaultDepth(display,DefaultScreen(display)));
    px_disarm_insens =
      XCreatePixmapFromBitmapData(display,
                                DefaultRootWindow(display),
                                mtn_ins_bits, mtn_ins_width, mtn_ins_height,
                                foreground,
                                background,
                                DefaultDepth(display,DefaultScreen(display)));

    n = 0;
    XtSetArg(args[n], XmNlabelType, XmPIXMAP);  n++;
    XtSetArg(args[n], XmNlabelPixmap, px_disarm);  n++;
    XtSetArg(args[n], XmNlabelInsensitivePixmap, px_disarm_insens ); n++;
    XtSetValues ( Label1, args, n );
    XtManageChild(Label1);

That will cause the foreground and background of your pixmap to be inherited
from the one that would be used by OSF/Motif when the label is displayed.  The
advantage is that this will utilize any resource values the user may have
requested without looking explicitly into the resource database.  And, you
will have a pixmap handy if the application insensitizes the label (without an
XmNlabelInsensitivePixmap your label will go empty if made insensitive).

[Bob's original code was for a PushButton. Just change all Label to PushButton
for them.]

-----------------------------------------------------------------------------
Subject: 121)+ Why doesn't the XmLabel widget obey the XmNwith and XmNheight
that I give it?

[Last modified: May 95]

Answer: By default, XmLabel ignores these resources and instead computes a
size based on the size of the label string or pixmap.  You can change this
behavior by setting XmNrecomputeSize to False.  (Note that setting
XmNrecomputeSize to False can dramatically improve performance if you have
alot of labels or change them frequently.)

Thanks to Ken Lee, kenton@rahul.net

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

-----------------------------------------------------------------------------
Subject: 123)  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: 124)  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: 125)  How can I create a drawing area widget with a non-default
visual type?

[Last modified: Apr 95]

Answer: The standard Motif drawing area does not support this.  You can,
however, easily create a subclass with a new Realize class method.  In SGI's
Motif, such a widget is called SgVisualDrawingArea.  Other Motif
implementations may have similar widgets.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 126)+ TOPIC: SCROLLED WINDOW WIDGET

-----------------------------------------------------------------------------
Subject: 127)  How do I tell if a scrolled window's scrollbars are visible?

Answer: Use XtGetValues() to get the scrollbar widget ID's, then use
XtIsManaged() to see if they are managed (visible).

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 128)  How can I programatically scroll a XmScrolledWindow in
XmAUTOMATIC mode?

Answer: In Motif 1.2, use XmScrollVisible().  If you're using a scrolled text
or scrolled list combination widget, use XmTextScroll() or XmListSet*()
instead.

The Motif manuals specifically forbid manipulating the scrollbars directly,
but some people have reported success with XmScrollBarSetValues, with the
"notify" parameter set to "True".

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 129)+ What widget does the XmScrolledWindow use for its clip window?

[Last modified: May 95]

Answer: If the XmScrolledWindow is using the XmAUTOMATIC scrolling policy, it
automatically creates an XmDrawingArea widget as its clip window.  If you
wish, you can retrieve the XmDrawingArea's widget ID by using XtGetValues on
the XmNclipWindow resource and then set resources on that widget.  Some useful
resources are XmNbackground and XmNresizeCallback.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
END OF PART FOUR
