home *** CD-ROM | disk | FTP | other *** search
/ Danny Amor's Online Library / Danny Amor's Online Library - Volume 1.iso / html / faqs / faq / motif-faq / part3 < prev    next >
Encoding:
Text File  |  1995-07-25  |  60.8 KB  |  1,585 lines

  1. Subject: Motif FAQ (Part 3 of 6)
  2. Newsgroups: comp.windows.x.motif,comp.answers,news.answers
  3. From: ksall@cen.com (Ken Sall)
  4. Date: 11 Oct 1994 07:52:00 GMT
  5.  
  6. Archive-name: motif-faq/part3
  7. Last-modified: OCT 10, 1994
  8. Posting-Frequency: monthly
  9. Organization: Century Computing, Inc.
  10. Version: 3.8
  11.  
  12.  
  13.  
  14. -----------------------------------------------------------------------------
  15. Subject: 59)  How can I replace characters typed with say a `*'?  I want to
  16. replace input for password entry.
  17.  
  18. [Last modified: April 93]
  19.  
  20. Answer: In Motif 1.1 Use the modifyVerifyCallback to tell when input is
  21. received.  Set text->ptr in the callback structure to '*'. This does not work
  22. under 1.0 because of an oversight in which changes to this are ignored.  In
  23. Motif 1.0, what you can do is set the doit flag to 'false' so the text is not
  24. displayed. Then set a static boolean to True to prevent re-entrance.  Next
  25. call XmTextReplace() to display your '*'.  then reset your re-entrance flag to
  26. False.  XmTextReplace() will call the XmNmodifyVerify callback.  To prevent
  27. getting into an infinite loop, you need the re-entrance flag.
  28.  
  29. The following program from Dan Heller illustrates this:
  30.  
  31.  
  32. --------------
  33. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  34.  * This program is freely distributable without licensing fees and
  35.  * is provided without guarantee or warranty expressed or implied.
  36.  * This program is -not- in the public domain.  This program appears
  37.  * in the Motif Programming Manual, O'Reilly Volume 6.
  38.  */
  39.  
  40. /* passwd.c -- prompt for a passwd.  Meaning, all input looks like
  41.  * a series of *'s.  Store the actual data typed by the user in
  42.  * an internal variable.  Don't allow paste operations.  Handle
  43.  * backspacing by deleting all text from insertion point to the
  44.  * end of text.
  45.  */
  46. #include <Xm/Text.h>
  47. #include <Xm/LabelG.h>
  48. #include <Xm/RowColumn.h>
  49. #include <ctype.h>
  50.  
  51. void check_passwd();
  52. char *passwd; /* store user-typed passwd here. */
  53.  
  54. main(argc, argv)
  55. int argc;
  56. char *argv[];
  57. {
  58.     Widget        toplevel, text_w, rowcol;
  59.     XtAppContext  app;
  60.  
  61.     toplevel = XtVaAppInitialize(&app, "Demos",
  62.         NULL, 0, &argc, argv, NULL, NULL);
  63.  
  64.     rowcol = XtVaCreateWidget("rowcol",
  65.         xmRowColumnWidgetClass, toplevel,
  66.         XmNorientation, XmHORIZONTAL,
  67.         NULL);
  68.  
  69.     XtVaCreateManagedWidget("Password:",
  70.         xmLabelGadgetClass, rowcol, NULL);
  71.     text_w = XtVaCreateManagedWidget("text_w",
  72.         xmTextWidgetClass, rowcol, NULL);
  73.  
  74.     XtAddCallback(text_w, XmNmodifyVerifyCallback, check_passwd, NULL);
  75.     XtAddCallback(text_w, XmNactivateCallback, check_passwd, NULL);
  76.  
  77.     XtManageChild(rowcol);
  78.     XtRealizeWidget(toplevel);
  79.     XtAppMainLoop(app);
  80. }
  81.  
  82. void
  83. check_passwd(text_w, unused, cbs)
  84. Widget        text_w;
  85. XtPointer     unused;
  86. XmTextVerifyCallbackStruct *cbs;
  87. {
  88.     char *new;
  89.     int len;
  90.  
  91.     if (cbs->reason == XmCR_ACTIVATE) {
  92.         printf("Password: %s\n", passwd);
  93.         return;
  94.     }
  95.  
  96.     if (cbs->text->ptr == NULL) { /* backspace */
  97.         cbs->endPos = strlen(passwd); /* delete from here to end */
  98.         if (cbs->endPos <= 0) return; /* catch null passwd - Mark Scoville */
  99.         passwd[cbs->startPos] = 0; /* backspace--terminate */
  100.         return;
  101.     }
  102.  
  103.     if (cbs->text->length > 1) {
  104.         cbs->doit = False; /* don't allow "paste" operations */
  105.         return; /* make the user *type* the password! */
  106.     }
  107.  
  108.     new = XtMalloc(cbs->endPos + 2); /* new char + NULL terminator */
  109.     if (passwd) {
  110.         strcpy(new, passwd);
  111.         XtFree(passwd);
  112.     } else
  113.         new[0] = NULL;
  114.     passwd = new;
  115.     strncat(passwd, cbs->text->ptr, cbs->text->length);
  116.     passwd[cbs->endPos + cbs->text->length] = 0;
  117.  
  118.     for (len = 0; len < cbs->text->length; len++)
  119.         cbs->text->ptr[len] = '*';
  120. }
  121.  
  122.  
  123. -----------------------------------------------------------------------------
  124. Subject: 60)  How can I best add a large piece of text to a scrolled text
  125. widget?
  126.  
  127. [Last modified: Sept 94]
  128.  
  129. [NOTE: This problem is probably only relevant for Motif 1.0 which probably no
  130. one is using anymore. If you know this to still be a problem, send mail to
  131. ksall@cen.com. I'll probably remove this question otherwise.]
  132.  
  133. In some versions of Motif 1.0 even using XmTextSetString, it insists on adding
  134. the text one line at a time, adjusting the scroll bar each time. It looks
  135. awful and is slow.
  136.  
  137. Answer: If you don't have this problem, use XmTextSetString to set all of the
  138. text in the widget.  If you do have this slowdown problem even using
  139. XmTextSetString, unmanage the widget, add the text and then manage it again.
  140. This may cause the window to blink, but you have to put up with that or switch
  141. to a different version of Motif.
  142.  
  143. -----------------------------------------------------------------------------
  144. Subject: 61)  How can I highlight text in the Text widget?
  145.  
  146. Answer: From: argv@zipcode.com (Dan Heller)
  147.  
  148. If you don't need font or color changes, you can do all this using a Text
  149. widget very easily [in Motif 1.1, anyway].
  150.  
  151.         loop() {
  152.             pos = offset_of_pattern_in_text_widget(pattern, text_w);
  153.             search_len = strlen(pattern);
  154.             XmTextSetHighlight(text_w, pos, pos+search_len,
  155.                         XmHIGHLIGHT_SELECTED);
  156.         }
  157.  
  158.  
  159. There are two choices for highlighting: reverse video (HIGHLIGHT_SELECTED) and
  160. underlined (HIGHLIGHT_SECONDARY_SELECTED).  Be careful that your users won't
  161. confuse your highlights with actual selections!
  162.  
  163. -----------------------------------------------------------------------------
  164. Subject: 62)  How can I select all of the text in a widget programmatically?
  165. So that some initial text is displayed, but anything typed replaces it.
  166.  
  167. Answer: XmTextSetSelection(Text1, 0, XmTextGetLastPosition(Text1), event-
  168. >xbutton.time);
  169.  
  170. where Text1 is the widget in question (obviously) and event is some event that
  171. triggered this call.  You can use XtLastTimestampProcessed( display) instead
  172. of xbutton.time if you don't happen to have an event pointer handy.
  173.  
  174.  
  175. -----------------------------------------------------------------------------
  176. Subject: 63)  How can I change colours of text in the Text widget?  I want
  177. some of the text in one colour, some in another.
  178.  
  179. Answer: You can't.  Text stores an ordinary string, and points where
  180. `highlights' of various types begin and end.  These highlights are all the
  181. control you have over components of the text.  See the previous question.
  182.  
  183.  
  184. -----------------------------------------------------------------------------
  185. Subject: 64)  How can I change the font of text in the Text widget?  I want
  186. some of the text in one font, some in another.
  187.  
  188. [Last modified: Sept 94]
  189.  
  190. Answer: You can't in Text (see the previous question).  If you wanted readonly
  191. text, you could do it by using a label instead.  Label uses XmStrings, which
  192. can contain multiple character sets in the one string.
  193.  
  194. If you are using Motif 2.0, however, XmStrings are now permitted in XmText
  195. widgets, which solves this particular problem.
  196.  
  197. -----------------------------------------------------------------------------
  198. Subject: 65)  Is there an emacs binding for the text widget?
  199.  
  200. Answer: This set is due to Kee Hinckley (nazgul@utopia.com):
  201.  
  202. *XmText.translations: #override\n\
  203.         Ctrl <Key>b:            backward-character()\n\
  204.         Alt <Key>b:             backward-word()\n\
  205.         Meta <Key>b:            backward-word()\n\
  206.         Shift Alt <Key>b:       backward-word(extend)\n\
  207.         Shift Meta <Key>b:      backward-word(extend)\n\
  208.         Alt <Key>[:             backward-paragraph()\n\
  209.         Meta <Key>[:            backward-paragraph()\n\
  210.         Shift Alt <Key>[:       backward-paragraph(extend)\n\
  211.         Shift Meta <Key>[:      backward-paragraph(extend)\n\
  212.         Alt <Key><:             beginning-of-file()\n\
  213.         Meta <Key><:            beginning-of-file()\n\
  214.         Ctrl <Key>a:            beginning-of-line()\n\
  215.         Shift Ctrl <Key>a:      beginning-of-line(extend)\n\
  216.         Ctrl <Key>osfInsert:    copy-clipboard()\n\
  217.         Shift <Key>osfDelete:   cut-clipboard()\n\
  218.         Shift <Key>osfInsert:   paste-clipboard()\n\
  219.         Alt <Key>>:             end-of-file()\n\
  220.         Meta <Key>>:            end-of-file()\n\
  221.         Ctrl <Key>e:            end-of-line()\n\
  222.         Shift Ctrl <Key>e:      end-of-line(extend)\n\
  223.         Ctrl <Key>f:            forward-character()\n\
  224.         Alt <Key>]:             forward-paragraph()\n\
  225.         Meta <Key>]:            forward-paragraph()\n\
  226.         Shift Alt <Key>]:       forward-paragraph(extend)\n\
  227.         Shift Meta <Key>]:      forward-paragraph(extend)\n\
  228.         Ctrl Alt <Key>f:        forward-word()\n\
  229.         Ctrl Meta <Key>f:       forward-word()\n\
  230.         Ctrl <Key>d:            kill-next-character()\n\
  231.         Alt <Key>BackSpace:     kill-previous-word()\n\
  232.         Meta <Key>BackSpace:    kill-previous-word()\n\
  233.         Ctrl <Key>w:            key-select() kill-selection()\n\
  234.         Ctrl <Key>y:            unkill()\n\
  235.         Ctrl <Key>k:            kill-to-end-of-line()\n\
  236.         Alt <Key>Delete:        kill-to-start-of-line()\n\
  237.         Meta <Key>Delete:       kill-to-start-of-line()\n\
  238.         Ctrl <Key>o:            newline-and-backup()\n\
  239.         Ctrl <Key>j:            newline-and-indent()\n\
  240.         Ctrl <Key>n:            next-line()\n\
  241.         Ctrl <Key>osfLeft:      page-left()\n\
  242.         Ctrl <Key>osfRight:     page-right()\n\
  243.         Ctrl <Key>p:            previous-line()\n\
  244.         Ctrl <Key>g:            process-cancel()\n\
  245.         Ctrl <Key>l:            redraw-display()\n\
  246.         Ctrl <Key>osfDown:      next-page()\n\
  247.         Ctrl <Key>osfUp:        previous-page()\n\
  248.         Ctrl <Key>space:        set-anchor()\n
  249.  
  250.  
  251. ! If you'd like the Delete key to work like backspace instead of deleting
  252. ! backwards, add the following definition to the lines above.
  253. !       <Key>osfDelete: delete-previous-character()\n\
  254.  
  255. ! These aren't included because they could intefere with
  256. | menu accelerators (or vice versa)
  257. !       Alt <Key>p:             backward-paragraph()\n\
  258. !       Meta <Key>p:            backward-paragraph()\n\
  259. !       Shift Alt<Key>p:        backward-paragraph(extend)\n\
  260. !       Shift Meta<Key>p:       backward-paragraph(extend)\n\
  261. !       Alt <Key>w:             copy-clipboard()\n\
  262. !       Meta <Key>w:            copy-clipboard()\n\
  263. !       Ctrl Alt <Key>w:        cut-clipboard()\n\
  264. !       Ctrl Meta <Key>w:       cut-clipboard()\n\
  265. !       Alt <Key>y:             paste-clipboard()\n\
  266. !       Meta <Key>y:            paste-clipboard()\n\
  267. !       Alt <Key>f:             forward-word()\n\
  268. !       Meta <Key>f:            forward-word()\n\
  269. !       Alt <Key>n:             forward-paragraph()\n\
  270. !       Meta <Key>n:            forward-paragraph()\n\
  271. !       Shift Alt <Key>n:       forward-paragraph(extend)\n\
  272. !       Shift Meta <Key>n:      forward-paragraph(extend)\n\
  273. !       Shift Alt <Key>f:       forward-word(extend)\n\
  274. !       Shift Meta <Key>f:      forward-word(extend)\n\
  275. !       Alt <Key>d:             kill-next-word()\n\
  276. !       Meta <Key>d:            kill-next-word()\n\
  277. !       Alt <Key>h:             select-all()\n\
  278. !       Meta <Key>h:            select-all()\n\
  279.  
  280. Similar sets of translations have been suggested by others.
  281.  
  282. -----------------------------------------------------------------------------
  283. Subject: 66)  How can I use a file as the text source for a Text widget?
  284.  
  285. Answer: You can't do it directly like you can with the Athena Text widget.
  286. Instead, read the text from the file into a string (all of it!) and then use
  287. XmTextSetString.  Alternatively, read blocks of characters and add them at the
  288. end of the text using XmTextInsertString.  The following is an excerpt from
  289. Dan Heller's "file_browser.c":
  290.  
  291.     /* file_browser.c -- use a ScrolledText object to view the
  292.      * contents of arbitrary files chosen by the user from a
  293.      * FileSelectionDialog or from a single-line text widget.
  294.      */
  295.  
  296.     ...
  297.     struct stat statb;
  298.  
  299.     /* make sure the file is a regular text file and open it */
  300.     if (stat(filename, &statb) == -1 ||
  301.             (statb.st_mode & S_IFMT) != S_IFREG ||
  302.             !(fp = fopen(filename, "r"))) {
  303.         if ((statb.st_mode & S_IFMT) == S_IFREG)
  304.             perror(filename); /* send to stderr why we can't read it */
  305.         else
  306.             fprintf(stderr, "%s: not a regular file0, filename);
  307.         XtFree(filename);
  308.         return;
  309.     }
  310.  
  311.     /* put the contents of the file in the Text widget by allocating
  312.      * enough space for the entire file, reading the file into the
  313.      * allocated space, and using XmTextFieldSetString() to show the file.
  314.      */
  315.     if (!(text = XtMalloc((unsigned)(statb.st_size+1)))) {
  316.         fprintf(stderr, "Can't alloc enough space for %s", filename);
  317.         XtFree(filename);
  318.         fclose(fp);
  319.         return;
  320.     }
  321.  
  322.     if (!fread(text, sizeof(char), statb.st_size+1, fp))
  323.         fprintf(stderr, "Warning: may not have read entire file!0);
  324.  
  325.     text[statb.st_size] = 0; /* be sure to NULL-terminate */
  326.  
  327.     /* insert file contents in Text widget */
  328.     XmTextSetString(text_w, text);
  329.  
  330.  
  331. -----------------------------------------------------------------------------
  332. Subject: 67)  How can put Text in overstrike mode instead of insert?
  333.  
  334. [Last modified: Sept 94]
  335.  
  336. Answer: There is no direct way. This was posted by Edmond Pitt
  337. (ejp@bohra.cpg.oz) The correct answer to the question is to put the following
  338. in a modifyVerify callback, where 'mvcb' is the XmTextVerifyCallbackStruct,
  339. and 'overstriking' is defined by you:
  340.  
  341.     if (overstriking && mvcb->text->length == 1)
  342.     {
  343.         _XmTextDisableRedisplay(w,FALSE);
  344.         XtCallActionProc(w,"delete-next-character",mvcb->event,0);
  345.         _XmTextEnableRedisplay(w);
  346.     }
  347.  
  348. _XmText{Dis,En}ableRedisplay() are XmText{Dis,En}ableRedisplay() in 1.0, but
  349. X11R3 has no XtCallActionProc() anyway. For this environment you need my 1.0.3
  350. Text widget patches posted last year & available on request.
  351.  
  352. An update was provided by Ingeborg (inca@osf.org):
  353.  
  354. In 1.2 and later releases, there is an action function toggle-overstrike()
  355. which will toggle between overstrike and insert mode. Before 1.2.3, there is
  356. no visual difference, and at most one character will get overstruck. In 1.2.3,
  357. a block cursor was added as a visual cue to that the widget is in overstrike
  358. mode, and the code was fixed to overstrike the actual number of characters
  359. input (this makes a difference if you have preediting - for example in
  360. japanese).
  361.  
  362. There is no default binding in 1.2, but the recommended key is osfInsert
  363. without modifiers.  No resource exists.
  364.  
  365.  
  366. -----------------------------------------------------------------------------
  367. Subject: 68)* How can I make the Delete key do a Backspace?  Related question:
  368. How can I swap Delete and Backspace?
  369.  
  370. [Last modified: Oct 94]
  371.  
  372. Answer: Put this in your .Xdefaults
  373.  
  374.     *XmText.translations: #override <Key>osfDelete: delete-previous-character()
  375.  
  376.  
  377. Additional information from David Kaelbling <drk@x.org>:
  378.  
  379. You can also supply an arbitrary file name to xmbind (so you can conditionally
  380. run xmbind from your .xinitrc file based on the hostname, architecture,
  381. xdpyinfo output, or whatever).
  382.  
  383. Some people prefer to use xmodmap to swap the keysyms for all applications,
  384. but what you're doing will work fine if you specify all of the virtual key
  385. bindings.  The current bindings are stored on the root window -- use "xprop
  386. -root" and look for a _MOTIF_BINDINGS or _MOTIF_DEFAULT_BINDINGS property.
  387. OSF/Motif is also distributed with a "bindings" directory containing all the
  388. fallback virtkey binding files.
  389.  
  390. There are several ways to do display-specific customization: make
  391.  
  392. -----------------------------------------------------------------------------
  393. Subject: 69)  TOPIC: LIST WIDGET
  394.  
  395. -----------------------------------------------------------------------------
  396. Subject: 70)  Should I create an XmList widget as a child of automatic
  397. XmScrolledWindow or use the XmCreateScrolledList() convenience function?
  398.  
  399. Answer: With most implementations, the convenience function use internal hooks
  400. to give somewhat better scrolling performance.
  401.  
  402. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  403.  
  404. -----------------------------------------------------------------------------
  405. Subject: 71)  How do I best put a new set of items into a list?
  406.  
  407. Answer: Set the new list count and list by XtSetArgs and install them by
  408. XtSetValues.
  409.  
  410.     XmString list[SIZE];
  411.     int list_size;
  412.  
  413.     XtSetArg (args[n], XmNitemCount, list_size); n++;
  414.     XtSetArg (args[n], XmNitems, list); n++;
  415.     XtSetValues (w, args, n);
  416.  
  417.  
  418. or similarly with XtVaSetValues:
  419.  
  420.  
  421.     XtVaSetValues (w,
  422.        XmNitemCount, list_size,
  423.        XmNitems, list,
  424.        NULL);
  425.  
  426.  
  427. Each time the list is reset by this the old contents are freed by the widget
  428. and the new supplied list is copied.  Do *not* free the old list of items
  429. yourself as this would result in the space being freed twice.  It is not
  430. necessary to remove the items one at a time, nor to "zero" out the list first.
  431.  
  432. -----------------------------------------------------------------------------
  433. Subject: 72)  Can I have strings with different fonts in a list?
  434.  
  435. Answer: Yes. The strings are XmStrings. Each one can be created using a
  436. different character set using a different font.
  437.  
  438.  
  439. -----------------------------------------------------------------------------
  440. Subject: 73)  Can I get a bitmap to show in a list item like I can in a Label?
  441. I want to place a bitmap along with some normal text in my list items.
  442.  
  443. Answer: No. The list contains XmStrings, and these only allow text in various
  444. character sets. The workaround is to define your font containing the icons you
  445. want. Then you can create a fontlist containing your icon font and the font
  446. you want the text in, and then make your items multi-segment XmStrings where
  447. the first segment contains the code of the icon you want with a charset that
  448. matches the icon font in your fontlist and the second segment with a charset
  449. matching the text font.
  450.  
  451.  
  452. -----------------------------------------------------------------------------
  453. Subject: 74)  Can I have items with different colours in a list?
  454.  
  455. Answer: No.  The list contains XmStrings, and these only allow text in various
  456. character sets. Since the items are XmStrings, you can already change the font
  457. of an item by replacing it with an item with the same text and a different
  458. charset tag.  Adding support for color would require modification of the
  459. internal data structure in XmList as well as modification to the drawing
  460. routines.  A possible workaround is to use a rowcolumn of buttons which can be
  461. individually set.  However, you would have to do all list functionality
  462. yourself.
  463.  
  464.  
  465. -----------------------------------------------------------------------------
  466. Subject: 75)  Can I grey out an item in a list?  I want to make insensitive
  467. items in a list so that they cannot be selected.
  468.  
  469. Answer:
  470.  
  471. From W. Scott Meeks of OSF:
  472.  
  473. Unfortunately, you can't do it directly since the list items aren't individual
  474. widgets.  We've had other requests for this technology, but it didn't make the
  475. cut for 1.2; it should be in some future release.
  476.  
  477. However, you can probably fake it in your application with some difficulty.
  478. First, a list item is an XmString, so you can specify a different charset for
  479. the item than for other items in the list and then specify a font in the
  480. list's fontlist that matches the charset and gives you the visual you want.
  481. The next problem is making the item unselectable.  One idea would be to have
  482. the application keep track of the insensitive items and the items currently
  483. selected.  Then you would set up a selection callback that when called would
  484. check the item selected against the list of insensitive items and if the
  485. selected item matched would deselect that item and reselect the previously
  486. selected items.  Otherwise it would just update the application's list of
  487. selected items.  The major drawback with this approach is that you'll get
  488. flashing whenever the list selects an item and your application immediately
  489. de-selects.  Unfortunately I can't think of a way around this without mucking
  490. with the list internals.
  491.  
  492. Another alternative suggested is to use instead a column of say read only text
  493. widgets which you can make insensitive.
  494.  
  495. -----------------------------------------------------------------------------
  496. Subject: 76)  Can I have multi-line items in a list?
  497. [Last modified: August 92]
  498.  
  499. Answer: Motif 1.0 and 1.1 both have problems with multi-line items in a list.
  500. They should work okay in Motif 1.2.
  501.  
  502. -----------------------------------------------------------------------------
  503. Subject: 77)  How can I tell the position of selected items in a list?
  504.  
  505. [Last modified: Oct 92]
  506.  
  507. Answer: From  W. Scott Meeks:
  508.  
  509. 1) All XmList selection callbacks get an XmListCallbackStruct which includes
  510. the item selected and its position.  In addition, the multiple and extended
  511. selection callbacks also get a list of the selected items.  This approach
  512. requires that your application saves this information if you need it outside
  513. of the immediate callback.
  514.  
  515. 2) At any time you can XtGetValues the XmNselectedItems and
  516. XmNselectedItemCount resources.  The problem with this approach is that
  517. identical items may or may not show up in multiple times in this list and the
  518. position in the selectedItems list may not relate directly to the position in
  519. the items list.
  520.  
  521. 3) You can call XmListGetSelectedPos on the list widget.  This will return a
  522. list of the positions of all selected items.
  523.  
  524. -----------------------------------------------------------------------------
  525. Subject: 78)  TOPIC: FILE SELECTION BOX WIDGET
  526.  
  527. -----------------------------------------------------------------------------
  528. Subject: 79)  What is libPW.a and do I need it?  My manual says I need to link
  529. in libPW.a to use the File Selection Box.  I can't find it on my system.
  530.  
  531. [Last modified: Sept 94]
  532.  
  533. Answer: The libPW.a is the Programmers Workbench library which is an ATT
  534. product not included in Berkeley based systems, hence it is not found in SunOS
  535. or Ultrix, but is found on HP-UX (a Berkeley/ATT hybrid which chose ATT in
  536. this case).  It contains the regex(3) routines (regcmp, regex).  Some systems
  537. which don't have these in the libc.a need to link with -lPW.  Some systems
  538. which have the regex(3) routines in there also have the libPW.a.  If you have
  539. regex(3) in libc, and it works, don't link with libPW.  If you don't have
  540. regex(3) in libc, and you don't have a libPW, then check some sites on the net
  541. for public domain replacements (several exist), or call your vendor.
  542.  
  543. In most versions of Motif (see the doco), you can compile FileSB.c with
  544. -DNO_REGEX if you don't have it.
  545.  
  546.  
  547. Casper H.S. Dik (asper@fwi.uva.nl), Faculty of Mathematics & Computer Science,
  548. University of Amsterdam, sent this update for Solaris 2.x users:
  549.  
  550. The regex and regcmp function are part of libgen in SVR4.  Motif applications
  551. should be linked with -lgen. (However, some SVR4 implementations, especially
  552. those of vendors that once shipped SVR3 still contain libPW.)
  553.  
  554. On Solaris 2.x system, you'll need libgen which is located in /usr/ccs/lib.
  555.  
  556. -----------------------------------------------------------------------------
  557. Subject: 80)  What are these compile errors: Undefined symbol _regcmp and
  558. _regex?
  559.  
  560. [Last modified: Sept 94]
  561.  
  562. Answer: You need to link in the libPW or libgen library - see previous
  563. question.
  564.  
  565.  
  566. -----------------------------------------------------------------------------
  567. Subject: 81)  What's wrong with the Motif 1.0 File Selection Box?  I can't set
  568. the directory, change the directory or get the file mask to work.
  569.  
  570. Answer: The 1.0 File Selection Box is broken, and these don't work.  They
  571. weren't fixed until Motif 1.04.  Use these later versions of 1.0 or switch to
  572. Motif 1.1 where it changed a lot.
  573.  
  574. Joe Hildebrand has a work-around for some of this: Before popping up an
  575. XmFileSelectionDialog, change to the directory you want.  When a file is
  576. selected, check if it is a directory, so that we can change to it.  i.e.
  577.  
  578. static void show_file_box_CB(w, client_data, call_data)
  579.    Widget               w;
  580.    Widget               client_data;
  581.    XmAnyCallbackStruct  *call_data;
  582. {
  583.    chdir("/users/hildjj/files");
  584.    XtManageChild(client_data);
  585. }
  586.  
  587. static void val_save(w, client_data, call_data)
  588.    Widget       w;
  589.    Widget       client_data;
  590.    XmSelectionBoxCallbackStruct *call_data;
  591. {
  592.    struct stat buf;  /* struct stat is defined in stat.h */
  593.    char *filename;
  594.  
  595.    /* get the file name from the FileSelectionBox */
  596.    filename = SmX(call_data->value);
  597.  
  598.    /* get the status of the file named filename, and put it into buf */
  599.    if (!stat(filename, &buf))
  600.    {
  601.       /* if it's a directory */
  602.       /* if it's a directory */
  603.       if(S_ISDIR(buf.st_mode))
  604.       {
  605.          /* change to that directory, and update the FileSelectionBox */
  606.         chdir(filename);
  607.         XmFileSelectionDoSearch(w, NULL);
  608.       }
  609.       else
  610.          /* if it's a regular file */
  611.          if(S_ISREG(buf.st_mode))
  612.             /* ask if it should be overwritten */
  613.             XtManageChild(valbox);
  614.          else
  615.             /* it's another kind of file.  What type, i can't think of,
  616.                but it might happen */
  617.             pop_up_error_box(client_data, "Error saving file");
  618.    }
  619.    else  /* we couldn't get the file status */
  620.    {
  621.       /* if it's because the file doesn't exist, we're golden */
  622.       if (errno == ENOENT)
  623.          save_file();
  624.       else   /* there is some other problem getting the status.
  625.                 e.g. bad path */
  626.          pop_up_error_box(client_data, "Error saving file");
  627.    }
  628. }
  629.  
  630. this still doesn't implement the file masking stuff.
  631.  
  632.  
  633. -----------------------------------------------------------------------------
  634. Subject: 82)  TOPIC: FORM WIDGET
  635.  
  636.  
  637. -----------------------------------------------------------------------------
  638. Subject: 83)  Why don't labels in a Form resize when the label is changed?
  639. I've got some labels in a form. The labels don't resize whenever the label
  640. string resource is changed. As a result, the operator has to resize the window
  641. to see the new label contents. I am using Motif 1.1.
  642.  
  643. Answer: This problem may happen to any widget inside a Form widget. The
  644. problem was that the Form will resize itself when it gets geometry requests
  645. from its children. If its preferred size is not allowed, the Form will
  646. disallow all geometry requests from its children. The workaround is that you
  647. should set any ancestor of the Form to be resizable. For the shell which
  648. contains the Form you should set the shell resource XmNallowShellResize to be
  649. True (by default, it is set to FALSE).  There is currently an inconsistency on
  650. how resizing is being done, and it may get fixed in Motif 1.2.
  651.  
  652. From db@sunbim.be (Danny Backx)
  653.  
  654. Basically what you have to do is set the XmNresizePolicy on the Form to
  655. XmRESIZE_NONE.  The facts seem to be that XmRESIZE_NONE does NOT mean "do not
  656. allow resizes".  You may also have to set XmNresizable on the form to True.
  657.  
  658. -----------------------------------------------------------------------------
  659. Subject: 84)  How can I center a widget in a form?
  660.  
  661. Answer: One of Motif's trickier questions.  The problems are that: Form gives
  662. no support for centering, only for edge attachments, and the widget must stay
  663. in the center if the form or the widget is resized.  Just looking at
  664. horizontal centering (vertical is similar) some solutions are:
  665.  
  666.  a.  Use the table widget instead of Form.
  667.  
  668.  b.  A hack free solution is from Dan Heller:
  669.  
  670.      /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  671.       * This program is freely distributable without licensing fees and
  672.       * is provided without guarantee or warranty expressed or implied.
  673.       * This program is -not- in the public domain.  This program is
  674.       * taken from the Motif Programming Manual, O'Reilly Volume 6.
  675.       */
  676.  
  677.      /* corners.c -- demonstrate widget layout management for a
  678.       * BulletinBoard widget.  There are four widgets each labeled
  679.       * top-left, top-right, bottom-left and bottom-right.  Their
  680.       * positions in the bulletin board correspond to their names.
  681.       * Only when the widget is resized does the geometry management
  682.       * kick in and position the children in their correct locations.
  683.       */
  684.      #include <Xm/BulletinB.h>
  685.      #include <Xm/PushBG.h>
  686.  
  687.      char *corners[] = {
  688.          "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right",
  689.      };
  690.  
  691.      static void resize();
  692.  
  693.      main(argc, argv)
  694.      int argc;
  695.      char *argv[];
  696.      {
  697.          Widget toplevel, bboard;
  698.          XtAppContext app;
  699.          XtActionsRec rec;
  700.          int i;
  701.  
  702.          /* Initialize toolkit and create toplevel shell */
  703.          toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
  704.              &argc, argv, NULL, NULL);
  705.  
  706.          /* Create your standard BulletinBoard widget */
  707.          bboard = XtVaCreateManagedWidget("bboard",
  708.              xmBulletinBoardWidgetClass, toplevel, NULL);
  709.  
  710.          /* Set up a translation table that captures "Resize" events
  711.           * (also called ConfigureNotify or Configure events).  If the
  712.           * event is generated, call the function resize().
  713.           */
  714.          rec.string = "resize";
  715.          rec.proc = resize;
  716.          XtAppAddActions(app, &rec, 1);
  717.          XtOverrideTranslations(bboard,
  718.              XtParseTranslationTable("<Configure>: resize()"));
  719.  
  720.          /* Create children of the dialog -- a PushButton in each corner. */
  721.          for (i = 0; i < XtNumber(corners); i++)
  722.              XtVaCreateManagedWidget(corners[i],
  723.                  xmPushButtonGadgetClass, bboard, NULL);
  724.  
  725.          XtRealizeWidget(toplevel);
  726.          XtAppMainLoop(app);
  727.      }
  728.  
  729.      /* resize(), the routine that is automatically called by Xt upon the
  730.       * delivery of a Configure event.  This happens whenever the widget
  731.       * gets resized.
  732.       */
  733.      static void
  734.      resize(w, event, args, num_args)
  735.      CompositeWidget w;   /* The widget (BulletinBoard) that got resized */
  736.      XConfigureEvent *event;  /* The event struct associated with the event */
  737.      String args[]; /* unused */
  738.      int *num_args; /* unused */
  739.      {
  740.          WidgetList children;
  741.          int width = event->width;
  742.          int height = event->height;
  743.          Dimension w_width, w_height;
  744.          short margin_w, margin_h;
  745.  
  746.          /* get handle to BulletinBoard's children and marginal spacing */
  747.          XtVaGetValues(w,
  748.              XmNchildren, &children,
  749.              XmNmarginWidth, &margin_w,
  750.              XmNmarginHeight, &margin_h,
  751.              NULL);
  752.  
  753.          /* place the top left widget */
  754.          XtVaSetValues(children[0],
  755.              XmNx, margin_w,
  756.  
  757.              XmNy, margin_h,
  758.              NULL);
  759.  
  760.          /* top right */
  761.          XtVaGetValues(children[1], XmNwidth, &w_width, NULL);
  762.  
  763.          /* To Center a widget in the middle of the BulletinBoard (or Form),
  764.           * simply call:
  765.           *   XtVaSetValues(widget,
  766.                XmNx,    (width - w_width)/2,
  767.                XmNy,    (height - w_height)/2,
  768.                NULL);
  769.           * and return.
  770.           */
  771.          XtVaSetValues(children[1],
  772.              XmNx, width - margin_w - w_width,
  773.              XmNy, margin_h,
  774.              NULL);
  775.          /* bottom left */
  776.          XtVaGetValues(children[2], XmNheight, &w_height, NULL);
  777.          XtVaSetValues(children[2],
  778.  
  779.              XmNx, margin_w,
  780.              XmNy, height - margin_h - w_height,
  781.              NULL);
  782.          /* bottom right */
  783.          XtVaGetValues(children[3],
  784.              XmNheight, &w_height,
  785.              XmNwidth, &w_width,
  786.              NULL);
  787.          XtVaSetValues(children[3],
  788.              XmNx, width - margin_w - w_width,
  789.              XmNy, height - margin_h - w_height,
  790.              NULL);
  791.      }
  792.  
  793.  c.  No uil solution has been suggested, because of the widget size problem
  794.  
  795. -----------------------------------------------------------------------------
  796. Subject: 85)  How do I line up two columns of widgets of different types?  I
  797. have a column of say label widgets, and a column of text widgets and I want to
  798. have them lined up horizontally. The problem is that they are of different
  799. heights. Just putting them in a form or rowcolumn doesn't line them up
  800. properly because the label and text widgets are of different height.
  801.  
  802. If you want the geometry to look like this
  803.  
  804.           -------------------------------------
  805.          |          -------------------------- |
  806.          |a label  |Some text                 ||
  807.          |          -------------------------- |
  808.                            ------------------- |
  809.          |a longer label  |Some more text     ||
  810.          |                 ------------------- |
  811.          |                    ---------------- |
  812.          |a very long label  |Even more text  ||
  813.          |                    ---------------- |
  814.           -------------------------------------
  815.  
  816. try
  817.  
  818. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  819.  * This program is freely distributable without licensing fees and
  820.  * is provided without guarantee or warranty expressed or implied.
  821.  * This program is -not- in the public domain.  This program is
  822.  * taken from the Motif Programming Manual, O'Reilly Volume 6.
  823.  */
  824.  
  825. /* text_form.c -- demonstrate how attachments work in Form widgets.
  826.  * by creating a text-entry form type application.
  827.  */
  828.  
  829. #include <Xm/PushB.h>
  830. #include <Xm/PushBG.h>
  831. #include <Xm/LabelG.h>
  832. #include <Xm/Text.h>
  833. #include <Xm/Form.h>
  834.  
  835. char *prompts[] = {
  836.     "Name:", "Phone:", "Address:",
  837.     "City:", "State:", "Zip:",
  838. };
  839.  
  840. main(argc, argv)
  841. int argc;
  842. char *argv[];
  843. {
  844.     Widget toplevel, mainform, subform, label, text;
  845.     XtAppContext app;
  846.     char buf[32];
  847.     int i;
  848.  
  849.     toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
  850.         &argc, argv, NULL, NULL);
  851.  
  852.     mainform = XtVaCreateWidget("mainform",
  853.         xmFormWidgetClass, toplevel,
  854.         NULL);
  855.  
  856.     for (i = 0; i < XtNumber(prompts); i++) {
  857.         subform = XtVaCreateWidget("subform",
  858.             xmFormWidgetClass,   mainform,
  859.             /* first one should be attached for form */
  860.             XmNtopAttachment,    i? XmATTACH_WIDGET : XmATTACH_FORM,
  861.             /* others are attached to the previous subform */
  862.             XmNtopWidget,        subform,
  863.             XmNleftAttachment,   XmATTACH_FORM,
  864.             XmNrightAttachment,  XmATTACH_FORM,
  865.             NULL);
  866.         label = XtVaCreateManagedWidget(prompts[i],
  867.             xmLabelGadgetClass,  subform,
  868.             XmNtopAttachment,    XmATTACH_FORM,
  869.             XmNbottomAttachment, XmATTACH_FORM,
  870.             XmNleftAttachment,   XmATTACH_FORM,
  871.             XmNalignment,        XmALIGNMENT_BEGINNING,
  872.             NULL);
  873.         sprintf(buf, "text_%d", i);
  874.         text = XtVaCreateManagedWidget(buf,
  875.             xmTextWidgetClass,   subform,
  876.             XmNtopAttachment,    XmATTACH_FORM,
  877.             XmNbottomAttachment, XmATTACH_FORM,
  878.             XmNrightAttachment,  XmATTACH_FORM,
  879.             XmNleftAttachment,   XmATTACH_WIDGET,
  880.             XmNleftWidget,       label,
  881.             NULL);
  882.         XtManageChild(subform);
  883.     }
  884.     /* Now that all the forms are added, manage the main form */
  885.     XtManageChild(mainform);
  886.  
  887.     XtRealizeWidget(toplevel);
  888.     XtAppMainLoop(app);
  889. }
  890.  
  891. If you resize horizontally it stretches the text widgets.  If you resize
  892. vertically it leaves space under the bottom (if you don't resize, this is not
  893. problem).
  894.  
  895. If you want the text widgets to be lined up on the left, as in
  896.  
  897.           ----------------------------------------
  898.          |                    ------------------- |
  899.          |          a label  |Some text          ||
  900.          |                    ------------------- |
  901.                               ------------------- |
  902.          |   a longer label  |Some more text     ||
  903.          |                    ------------------- |
  904.          |                    ------------------- |
  905.          |a very long label  |Even more text     ||
  906.          |                    ------------------- |
  907.           ----------------------------------------
  908.  
  909. try this
  910.  
  911.  
  912. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  913.  * This program is freely distributable without licensing fees and
  914.  * is provided without guarantee or warranty expressed or implied.
  915.  * This program is -not- in the public domain.  This program is
  916.  * taken from the Motif Programming Manual, O'Reilly Volume 6.
  917.  */
  918.  
  919. /* text_entry.c -- This demo shows how the RowColumn widget can be
  920.  * configured to build a text entry form.  It displays a table of
  921.  * right-justified Labels and Text widgets that extend to the right
  922.  * edge of the Form.
  923.  */
  924. #include <Xm/LabelG.h>
  925. #include <Xm/RowColumn.h>
  926. #include <Xm/Text.h>
  927.  
  928. char *text_labels[] = {
  929.     "Name:", "Phone:", "Address:", "City:", "State:", "Zip:",
  930. };
  931.  
  932. main(argc, argv)
  933. int argc;
  934. char *argv[];
  935. {
  936.     Widget toplevel, rowcol;
  937.     XtAppContext app;
  938.     char buf[8];
  939.     int i;
  940.  
  941.     toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
  942.         &argc, argv, NULL, NULL);
  943.  
  944.     rowcol = XtVaCreateWidget("rowcolumn",
  945.         xmRowColumnWidgetClass, toplevel,
  946.         XmNpacking,        XmPACK_COLUMN,
  947.         XmNnumColumns,     XtNumber(text_labels),
  948.         XmNorientation,    XmHORIZONTAL,
  949.         XmNisAligned,      True,
  950.         XmNentryAlignment, XmALIGNMENT_END,
  951.         NULL);
  952.  
  953.     /* simply loop thru the strings creating a widget for each one */
  954.     for (i = 0; i < XtNumber(text_labels); i++) {
  955.         XtVaCreateManagedWidget(text_labels[i],
  956.             xmLabelGadgetClass, rowcol,
  957.             NULL);
  958.         sprintf(buf, "text_%d", i);
  959.         XtVaCreateManagedWidget(buf,
  960.             xmTextWidgetClass, rowcol,
  961.             NULL);
  962.     }
  963.  
  964.     XtManageChild(rowcol);
  965.     XtRealizeWidget(toplevel);
  966.     XtAppMainLoop(app);
  967. }
  968.  
  969. This makes all objects exactly the same size.  It does not resize in nice
  970. ways.
  971.  
  972. If you want the text widgets lined up on the left, and the labels to be the
  973. size of the longest string, resizing nicely both horizontally and vertically,
  974. as in
  975.  
  976.          -------------------------------------
  977.         |                    ---------------- |
  978.         |          a label  |Some text       ||
  979.         |                    ---------------- |
  980.                              ---------------- |
  981.         |   a longer label  |Some more text  ||
  982.         |                    ---------------- |
  983.         |                    ---------------- |
  984.         |a very long label  |Even more text  ||
  985.         |                    ---------------- |
  986.          -------------------------------------
  987.  
  988.  
  989. Answer: Do this: to get the widgets lined up horizontally, use a form but
  990. place the widgets using XmATTACH_POSITION.  In the example, attach the top of
  991. the first label to the form, the bottomPosition to 33 (33% of the height).
  992. Attach the topPosition of the second label to 33 and the bottomPosition to 66.
  993. Attach the topPosition of the third label to 66 and the bottom of the label to
  994. the form.  Do the same with the text widgets.
  995.  
  996. To get the label widgets lined up vertically, use the right attachment of
  997. XmATTACH_OPPOSITE_WIDGET: starting from the one with the longest label, attach
  998. widgets on the right to each other. In the example, attach the 2nd label to
  999. the third, and the first to the second.  To get the text widgets lined up,
  1000. just attach them on the left to the labels.  To get the text in the labels
  1001. aligned correctly, use XmALIGNMENT_END for the XmNalignment resource.
  1002.  
  1003.         /* geometry for label 2
  1004.         */
  1005.         n = 0;
  1006.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  1007.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1008.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1009.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  1010.         XtSetArg (args[n], XmNtopPosition, 66); n++;
  1011.         XtSetValues (label[2], args, n);
  1012.  
  1013.         /* geometry for label 1
  1014.         */
  1015.         n = 0;
  1016.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  1017.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  1018.         XtSetArg (args[n], XmNbottomPosition, 66); n++;
  1019.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  1020.         XtSetArg (args[n], XmNtopPosition, 33); n++;
  1021.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1022.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  1023.         XtSetArg (args[n], XmNrightWidget, label[2]); n++;
  1024.         XtSetValues (label[1], args, n);
  1025.  
  1026.         /* geometry for label 0
  1027.         */
  1028.         n = 0;
  1029.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  1030.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  1031.         XtSetArg (args[n], XmNbottomPosition, 33); n++;
  1032.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1033.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1034.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  1035.         XtSetArg (args[n], XmNrightWidget, label[1]); n++;
  1036.         XtSetValues (label[0], args, n);
  1037.  
  1038.         /* geometry for text 0
  1039.         */
  1040.         n = 0;
  1041.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1042.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  1043.         XtSetArg (args[n], XmNbottomPosition, 33); n++;
  1044.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1045.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1046.         XtSetArg (args[n], XmNleftWidget, label[0]); n++;
  1047.         XtSetValues (text[0], args, n);
  1048.  
  1049.         /* geometry for text 1
  1050.         */
  1051.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  1052.         XtSetArg (args[n], XmNtopPosition, 33); n++;
  1053.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  1054.         XtSetArg (args[n], XmNbottomPosition, 66); n++;
  1055.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1056.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1057.         XtSetArg (args[n], XmNleftWidget, label[1]); n++;
  1058.         XtSetValues (text[1], args, n);
  1059.  
  1060.         /* geometry for text 2
  1061.         */
  1062.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  1063.         XtSetArg (args[n], XmNtopPosition, 66); n++;
  1064.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1065.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1066.         XtSetArg (args[n], XmNleftWidget, label[2]); n++;
  1067.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1068.         XtSetValues (text[2], args, n);
  1069.  
  1070.  
  1071. -----------------------------------------------------------------------------
  1072. Subject: 86)  TOPIC: PUSHBUTTON WIDGET
  1073.  
  1074. -----------------------------------------------------------------------------
  1075. Subject: 87)  Why can't I use accelerators on buttons not in a menu?
  1076.  
  1077. [Last modified: Sept 94]
  1078.  
  1079. Answer:
  1080.  
  1081. It is apparently a difficult feature to implement, but OSF are considering
  1082. this for the future. It is problematic trying to use the Xt accelerators since
  1083. the Motif method interferes with this.  one workaround suggested is to
  1084. duplicate your non-menu button by a button in a menu somewhere, which does
  1085. have a menu-accelerator installed.  When the user invokes what they think is
  1086. the accelerator for the button they can see Motif actually invokes the button
  1087. on the menu that they can't see at the time. Another method is described below
  1088. and was contributed by Harald Albrecht of Institute of Geometry and Practical
  1089. Mathematics Rhine Westphalia Technical University Aachen (RWTH Aachen),
  1090. Germany
  1091.  
  1092.  
  1093. From albrecht@igpm.rwth-aachen.de Thu Jul  8 11:44:21 1993
  1094.  
  1095. NOTE: Pointers to a more recent solution by the same author follow this code
  1096. sample.
  1097.  
  1098. My work-around of this problem looks like this: (I've written that code for a
  1099. Motif Object Library in C++ so please forgive me for being object orientated!)
  1100. The hack consists of a rewritten message loop which checks for keypresses
  1101. <MAlt>+<key>. If MessageLoop() finds such a keypress HandleAcc() ist called
  1102. and the widget tree is searched for a suitable widget with the right mnemonic.
  1103.  
  1104.  
  1105. // --------------------------------------------------------------------------
  1106. // traverse the widget tree starting with the given widget.
  1107. //
  1108. BOOL TraverseWidgetTree(Widget w, char *pMnemonic, XKeyEvent *KeyEvent)
  1109. {
  1110.     Widget               wChild;
  1111.     WidgetList           ChildList;
  1112.     int                  NumChilds, Child;
  1113.     KeySym               LabelMnemonic;
  1114.     char                 *pMnemonicString;
  1115.  
  1116. // Check if the widget is a subclass of label -- then it may have an
  1117. // accelerator attached...
  1118.     if ( XtIsSubclass(w, xmLabelWidgetClass) ) {
  1119. // ok. Now: get the widget's mnemonic, convert it to ASCII and compare
  1120. // it with the Key we're looking for.
  1121.         XtVaGetValues(w, XmNmnemonic, &LabelMnemonic, NULL);
  1122.         pMnemonicString = XKeysymToString(LabelMnemonic);
  1123.         if ( pMnemonicString &&
  1124.              (strcasecmp(pMnemonicString, pMnemonic) == 0) ) {
  1125.             // stimulate the keypress
  1126.             XmProcessTraversal((Widget)w, XmTRAVERSE_CURRENT);
  1127.             KeyEvent->type      = KeyPress;
  1128.             KeyEvent->window    = XtWindow(w);
  1129.             KeyEvent->subwindow = XtWindow(w);
  1130.             KeyEvent->state     = 0;
  1131.             KeyEvent->keycode   =
  1132.                 XKeysymToKeycode(XtDisplay(w), XK_space);
  1133.             XSendEvent(XtDisplay(w), XtWindow(w),
  1134.                        True,
  1135.                        ButtonPressMask, (XEvent*) KeyEvent);
  1136.             KeyEvent->type      = KeyRelease;
  1137.             XSendEvent(XtDisplay(w), XtWindow(w),
  1138.                        True,
  1139.                        ButtonReleaseMask, (XEvent*) KeyEvent);
  1140.             return True;
  1141.         }
  1142.     }
  1143. // if this widget is a subclass of Composite check all the widget's
  1144. // childs.
  1145.     if ( XtIsSubclass(w, compositeWidgetClass) ) {
  1146. // if we're in a menu (or something like that) forget this leaf of the
  1147. // widget tree!
  1148.         if ( XtIsSubclass(w, xmRowColumnWidgetClass) ) {
  1149.             unsigned char RowColumnType;
  1150.             XtVaGetValues(w, XmNrowColumnType, &RowColumnType, NULL);
  1151.             if ( RowColumnType != XmWORK_AREA ) return False;
  1152.         }
  1153.         XtVaGetValues(w, XmNchildren, &ChildList,
  1154.                          XmNnumChildren, &NumChilds, NULL);
  1155.         for ( Child = 0; Child < NumChilds; ++Child ) {
  1156.             wChild = ChildList[Child];
  1157.             if ( TraverseWidgetTree(wChild, pMnemonic, KeyEvent) )
  1158.                 return True;
  1159.         }
  1160.     }
  1161.     return False;
  1162. } // TraverseWidgetTree
  1163. // --------------------------------------------------------------------------
  1164. // handle accelerators (keypress MAlt + key)
  1165. //
  1166. #define MAX_MAPPING 10
  1167. BOOL HandleAcc(Widget w, XEvent *event)
  1168. {
  1169.            Widget         widget, OldWidget;
  1170.     static char           keybuffer[MAX_MAPPING];
  1171.            int            CharCount;
  1172.     static XComposeStatus composeStatus;
  1173.  
  1174. // convert KeyPress to ASCII
  1175.     CharCount = XLookupString((XKeyEvent*) event,
  1176.                               keybuffer, sizeof(keybuffer),
  1177.                               NULL, &composeStatus);
  1178.     keybuffer[CharCount] = 0;
  1179. // Only one char is alright -- then search the widget tree for a widget
  1180. // with the right mnemonic
  1181.     if ( CharCount == 1 ) {
  1182.         keybuffer[0] = tolower(keybuffer[0]);
  1183.         widget = w;
  1184.         while ( (widget != NULL) &&
  1185.                 !XtIsSubclass(widget, shellWidgetClass) ) {
  1186.             OldWidget = widget; widget = XtParent(widget);
  1187.         }
  1188.         if ( !widget ) widget = OldWidget;
  1189.         return TraverseWidgetTree(widget,
  1190.                                   keybuffer, (XKeyEvent*) event);
  1191.     }
  1192.     return False; // no-one found.
  1193. } // HandleAcc
  1194. // --------------------------------------------------------------------------
  1195. // modified message loop
  1196. // loops until the Boolean pFlag points to is set to False
  1197. void MessageLoop(Boolean *pFlag)
  1198. {
  1199.     XEvent nextEvent;
  1200.  
  1201.     while ( *pFlag ) {
  1202.         if ( XtAppPending(AppContext) ) {
  1203.             XtAppNextEvent(AppContext, &nextEvent);
  1204.             if ( nextEvent.type == KeyPress ) {
  1205. // Falls es ein Tastendruck ist, bei dem auch noch die ALT-Taste
  1206. // (=Modifier 1) gedrueckt ist, koennte es ein Accelerator sein!
  1207.                 if ( nextEvent.xkey.state & Mod1Mask )
  1208.                     if ( HandleAcc(XtWindowToWidget(nextEvent.xkey.display,
  1209.                                                     nextEvent.xkey.window),
  1210.                                    &nextEvent) )
  1211.                         continue; // Mitteilung konnte ausgeliefert werden
  1212.                                   // und darf daher nicht den ueblichen
  1213.                                   // Weg gehen!
  1214.             }
  1215.             XtDispatchEvent(&nextEvent);
  1216.         }
  1217.     }
  1218. } // TApplication::MessageLoop
  1219.  
  1220.  
  1221. Harald Albrecht albrecht@igpm.rwth-aachen.de Institute of Geometry and
  1222. Practical Mathematics Rhine Westphalia Technical University Aachen (RWTH
  1223. Aachen), Germany
  1224.  
  1225. NOTE: Harald Albrecht has re-designed his solution so that you can assign
  1226. hotkeys to *every* widget by placing a label near that widget. Get the code
  1227. from:
  1228.  
  1229.   ftp.informatik.rwth-aachen.de (137.226.112.172)
  1230.   in: /pub/packages/Mnemonic/Mnemonic.tar.gz
  1231.  
  1232. or from the WWW:
  1233.  
  1234.    file://134.130.161.30/arc/pub/unix/html/motifcorner.html
  1235.  
  1236. -----------------------------------------------------------------------------
  1237. Subject: 88)  TOPIC: ICON WIDGET
  1238.  
  1239. -----------------------------------------------------------------------------
  1240. Subject: 89)  How can I add multi-colored icons to my application?
  1241.  
  1242. [Last modified: Sept 94]
  1243.  
  1244. Answer: Get the Xpm (X PixMap file format) widgets.  There is a tutorial in
  1245. the directory ftp.x.org:/contrib/docs/xpm_tut and source code in the directory
  1246. ftp.x.org:/contrib/libraries.  Documentation is part of the tar file found in
  1247. /contrib/libraries.  The /contrib/libraries directory also contains xpm.FAQ.
  1248.  
  1249. There is also a mailing list: xpm-talk@sophia.inria.fr.
  1250.  
  1251. -----------------------------------------------------------------------------
  1252. Subject: 90)+ How can I convert a Sun/GIF/TIFF image to a pixmap?
  1253.  
  1254. [Last modified: Oct 94]
  1255.  
  1256. Answer: An application called "xv" (interactive image display for the X Window
  1257. System) is useful for displaying and converting many image formats. From the
  1258. man page:
  1259.  
  1260.      xv is an X11 program that displays images in the GIF,  JPEG,
  1261.      TIFF,  PBM, PGM, PPM, X11 bitmap, PDS/VICAR, Sun Rasterfile,
  1262.      and PM formats on 1-, 2-, 4-, 6-, 8-, 16-, 24-, and 32-bit X
  1263.      displays.   xv  will also read compress-ed versions of these
  1264.      files.
  1265.  
  1266. You can get "xv" (shareware by John Bradley et al) from:
  1267.  
  1268.         ftp://ftp.cis.upenn.edu/pub/xv
  1269. or:
  1270.         ftp://ftp.x.org/R5contrib/xv-3.01.tar.gz
  1271.  
  1272. Another useful conversion package is "pbm" (portable bitmap file format) by
  1273. Jef Poskanzer et al, available from:
  1274.  
  1275.         ftp://ftp.x.org/R5contrib/netpbm-1mar1994.tar.gz
  1276. or:
  1277.         ftp://ftp.x.org/R5contrib/pbmplus10dec91.tar.Z (much older :-)
  1278.  
  1279. You might also want to check the X11 FAQ for additional conversion options:
  1280.  
  1281.         ftp://ftp.x.org/contrib/faqs/FAQ
  1282.  
  1283. -----------------------------------------------------------------------------
  1284. Subject: 91)  TOPIC: LABEL WIDGET
  1285.  
  1286. -----------------------------------------------------------------------------
  1287. Subject: 92)  How can I align the text in a label (button, etc) widget?
  1288.  
  1289. Answer: The alignment for the label widget is controlled by the resource
  1290. XmNalignment, and the default centers the text. Use this resource to change it
  1291. to left or right alignment.  However, when the label (or any descendant) is in
  1292. a row column, and XmNisAligned is True (the default), the row column aligns
  1293. text using its resource XmNentryAlignment. If you want simultaneous control
  1294. over all widgets use this, but otherwise turn XmNisAligned off and do it
  1295. individually.
  1296.  
  1297.  
  1298. -----------------------------------------------------------------------------
  1299. Subject: 93)  Why doesn't label alignment work in a RowColumn?
  1300.  
  1301. Answer: RowColumn has a  resource XmNisAligned (default True) and and
  1302. XmNentryAlignment (default XmALIGNMENT_BEGINNING).  These control alignment of
  1303. the labelString in Labels and descendants. Set XmNisAligned to False to turn
  1304. this off.
  1305.  
  1306. -----------------------------------------------------------------------------
  1307. Subject: 94)  How can I set a multiline label?
  1308.  
  1309. [Last modified: September 92]
  1310.  
  1311. Answer: In .Xdefaults
  1312.  
  1313.       *XmLabel*labelString:             Here\nis\nthe\nLabel
  1314.  
  1315. This method does not seem to work in some of the older Motif 1.0 versions.
  1316.  
  1317. In code,
  1318.  
  1319.       char buf[128];
  1320.       XmString msg;
  1321.       sprintf(buf, "Here\nis\nthe\nLabel");
  1322.       msg = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
  1323.       XtSetArg (args[n], XmNlabelString, msg);
  1324.  
  1325. Gives a four line label, using the escape sequence \n for a newline.  However,
  1326. XmStringCreateLtoR() is obsoleted from version 1.1 on, and may disappear.
  1327. This is because it it is only in the AES as "trial-use" and has been proposed
  1328. for removal from the AES. Realistically, it will probably not be removed from
  1329. any backward compatible versions of Motif, but the potential is there.  If it
  1330. does disappear (or if you want to avoid using the non-AES compliant
  1331. XmSTRING_DEFAULT_CHARSET), try this from Jean-Philippe Martin-Flatin
  1332. <syj@ecmwf.co.uk>
  1333.  
  1334. #include <Xm/Xm.h>
  1335. #include <string.h>
  1336.  
  1337. /*-----------------------------------------------------
  1338.     Create a new XmString from a char*
  1339.  
  1340.     This function can deal with embedded 'newline' and
  1341.     is equivalent to the obsolete XmStringCreateLtoR,
  1342.     except it does not use non AES compliant charset
  1343.     XmSTRING_DEFAULT_CHARSET
  1344. ----------------------------------------------------*/
  1345. XmString xec_NewString(char *s)
  1346. {
  1347.     XmString xms1;
  1348.     XmString xms2;
  1349.     XmString line;
  1350.     XmString separator;
  1351.     char     *p;
  1352.     char     *t = XtNewString(s);   /* Make a copy for strtok not to */
  1353.                                     /* damage the original string    */
  1354.  
  1355.  
  1356.     separator = XmStringSeparatorCreate();
  1357.     p         = strtok(t,"\n");
  1358.     xms1      = XmStringCreateSimple(p);
  1359.  
  1360.     while (p = strtok(NULL,"\n"))
  1361.     {
  1362.         line = XmStringCreateSimple(p);
  1363.         xms2 = XmStringConcat(xms1,separator);
  1364.         XmStringFree(xms1);
  1365.         xms1 = XmStringConcat(xms2,line);
  1366.         XmStringFree(xms2);
  1367.         XmStringFree(line);
  1368.     }
  1369.  
  1370.     XmStringFree(separator);
  1371.     XtFree(t);
  1372.     return xms1;
  1373. }
  1374.  
  1375.  
  1376. Do not use XmStringCreateSimple() - it does not process the newline character
  1377. in the way you want.
  1378.  
  1379. -----------------------------------------------------------------------------
  1380. Subject: 95)  How can I have a vertical label?
  1381.  
  1382. Answer: Make a multiline label with one character per line, as in the last
  1383. question. There is no way to make the text rotated by 90 degrees though.
  1384.  
  1385.  
  1386. -----------------------------------------------------------------------------
  1387. Subject: 96)  How can I have a Pixmap in a Label?
  1388.  
  1389. Answer: From Bob Hays (bobhays@spss.com)
  1390.  
  1391.     Pixmap px_disarm, px_disarm_insens;
  1392.  
  1393.     Widget Label1;
  1394.     Pixel   foreground, background;
  1395.     Arg     args[4];
  1396.     Arg     arg[] = {
  1397.                 { XmNforeground, &foreground },
  1398.                 { XmNbackground, &background }
  1399.     };
  1400.  
  1401.     Label1 = XmCreateLabel ( Shell1, "Label1",
  1402.                                        (Arg *) NULL, (Cardinal) 0 );
  1403.     XtGetValues ( Label1, arg, XtNumber ( arg ) );
  1404.     px_disarm =
  1405.       XCreatePixmapFromBitmapData(display,
  1406.                                 DefaultRootWindow(display),
  1407.                                 mtn_bits, mtn_width, mtn_height,
  1408.                                 foreground,
  1409.                                 background,
  1410.                                 DefaultDepth(display,DefaultScreen(display)));
  1411.     px_disarm_insens =
  1412.       XCreatePixmapFromBitmapData(display,
  1413.                                 DefaultRootWindow(display),
  1414.                                 mtn_ins_bits, mtn_ins_width, mtn_ins_height,
  1415.                                 foreground,
  1416.                                 background,
  1417.                                 DefaultDepth(display,DefaultScreen(display)));
  1418.  
  1419.     n = 0;
  1420.     XtSetArg(args[n], XmNlabelType, XmPIXMAP);  n++;
  1421.     XtSetArg(args[n], XmNlabelPixmap, px_disarm);  n++;
  1422.     XtSetArg(args[n], XmNlabelInsensitivePixmap, px_disarm_insens ); n++;
  1423.     XtSetValues ( Label1, args, n );
  1424.     XtManageChild(Label1);
  1425.  
  1426. That will cause the foreground and background of your pixmap to be inherited
  1427. from the one that would be used by OSF/Motif when the label is displayed.  The
  1428. advantage is that this will utilize any resource values the user may have
  1429. requested without looking explicitly into the resource database.  And, you
  1430. will have a pixmap handy if the application insensitizes the label (without an
  1431. XmNlabelInsensitivePixmap your label will go empty if made insensitive).
  1432.  
  1433. [Bob's original code was for a PushButton. Just change all Label to PushButton
  1434. for them.]
  1435.  
  1436. -----------------------------------------------------------------------------
  1437. Subject: 97)  TOPIC: DRAWING AREA WIDGET
  1438.  
  1439. -----------------------------------------------------------------------------
  1440. Subject: 98)  How can I send an expose event to a Drawing Area widget?  (or
  1441. any other, come to that). I want to send an expose event so that it will
  1442. redraw itself.
  1443.  
  1444. Answer: Use the Xlib call
  1445.  
  1446.         XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True)
  1447.  
  1448. This clears the widget's window and generates an expose event in doing so.
  1449. The widgets expose action will then redraw it.  This uses a round trip
  1450. request.  An alternative, without the round trip is
  1451.  
  1452. from orca!mesa!rthomson@uunet.uu.net  (Rich Thomson):
  1453.  
  1454.     Widget da;
  1455.     XmDrawingAreaCallbackStruct da_struct;
  1456.  
  1457.     da_struct.reason = XmCR_EXPOSE;
  1458.     da_struct.event = (XEvent *) NULL;
  1459.     da_struct.window = XtWindow(da);
  1460.  
  1461.     XtCallCallbacks(da, XmNexposeCallback, (XtPointer) da_struct);
  1462.  
  1463.  
  1464. -----------------------------------------------------------------------------
  1465. Subject: 99)  How can I know when a DrawingArea has been resized?  It
  1466. generates an expose event whn it is enlarged, but not when it is shrunk.
  1467.  
  1468. Answer: Use the resize callback.
  1469.  
  1470. -----------------------------------------------------------------------------
  1471. Subject: 100)  TOPIC: MENUS
  1472.  
  1473. -----------------------------------------------------------------------------
  1474. Subject: 101)  How do I set the current choice in a radio box or an option
  1475. menu?
  1476.  
  1477. [Last modified: Sept 94]
  1478.  
  1479. Answer: Set the XmNmenuHistory resource on its RowColumn parent.
  1480.  
  1481. Thanks to Ken Lee, kenton@esd.sgi.com
  1482.  
  1483. -----------------------------------------------------------------------------
  1484. Subject: 102)  How do I make a menu choice insensitive if it was created with
  1485. XmVaCreateSimplePulldownMenu?
  1486.  
  1487. [Last modified: Sept 94]
  1488.  
  1489. Answer: According to the Motif manual, the buttons are named "button_n", where
  1490. "n" is an integer starting from 0.  You can use XtNameToWidget() to convert
  1491. these names to widget ID's.
  1492.  
  1493. Thanks to Ken Lee, kenton@esd.sgi.com
  1494.  
  1495. -----------------------------------------------------------------------------
  1496. Subject: 103)  What can I put inside a menu bar?
  1497.  
  1498. Answer: You can only put cascade buttons in menu bars. No pushbuttons, toggle
  1499. buttons or gadgets are allowed. When you create a pulldown menu with parent a
  1500. menu bar, its real parent is a shell widget.
  1501.  
  1502. -----------------------------------------------------------------------------
  1503. Subject: 104)  Can I have a cascade button without a submenu in a pulldown
  1504. menu?
  1505.  
  1506. Answer: Yes you can. A cascade button has an activate callback which is called
  1507. when you click on it and it doesn't have a submenu. It can have a mnemonic,
  1508. but keyboard traversal using the arrow keys in the menu will skip over it.
  1509.  
  1510. -----------------------------------------------------------------------------
  1511. Subject: 105)  Should I have a cascade button without a submenu in a pulldown
  1512. menu?
  1513.  
  1514. Answer: No. This is forbidden by the style guide. Technically you can do it
  1515. (see previous question) but if you do it will not be Motif style compliant.
  1516. This is unlikely to change - if a "button" is important enough to be in a
  1517. pulldown menu bar with no pulldown, it should be a button elsewhere.  (Mind
  1518. you, you won't be able to put accelerators on it elsewhere though.)
  1519.  
  1520. -----------------------------------------------------------------------------
  1521. Subject: 106)  What is the best way to create popup menus?
  1522.  
  1523. [Last modified: August 92]
  1524.  
  1525. Susan Murdock Thompson (from OSF): In general, create a popupMenu as the child
  1526. from which you will be posting it from (ie: if you have a bulletinBoard with a
  1527. PushButton in it and want MB2 on the pushButton to post the popupMenu, create
  1528. the popupMenu as a child of the pushButton).  [This parent-child relationship
  1529. seems to make a big difference in the behavior of the popups.]  Add an event
  1530. handler to handle buttonPress events.  You'll need to check for the correct
  1531. button (what you've specified menuPost to be) before posting the menu.
  1532.  
  1533. To create a popup that can be accessible from within an entire client window,
  1534. create it as the child of the top-most widget (but not the shell) and add
  1535. event handlers for the top-most widget and children widgets.
  1536.  
  1537. ie:
  1538.  
  1539. {
  1540.   ....
  1541.  
  1542.   XtManageChild(rc=XmCreateRowColumn(Shell1, "rc", NULL, 0));
  1543.   XtManageChild(label = XmCreateLabel(rc, "label", NULL, 0));
  1544.   XtManageChild(text = XmCreateText(rc, "text", NULL, 0));
  1545.   XtManageChild(pushbutton = XmCreatePushButton(rc, "pushbutton", NULL, 0));
  1546.  
  1547.   n = 0;
  1548.   XtSetArg(args[n], XmNmenuPost, "<Btn3Down>"); n++;
  1549.   popup = XmCreatePopupMenu(rc, "popup", args, n);
  1550.  
  1551.   XtAddEventHandler(rc, ButtonPressMask, False, PostMenu3, popup);
  1552.   XtAddEventHandler(text, ButtonPressMask, False, PostMenu3, popup);
  1553.   XtAddEventHandler(label, ButtonPressMask, False, PostMenu3, popup);
  1554.   XtAddEventHandler(pushbutton, ButtonPressMask, False, PostMenu3, popup);
  1555.  
  1556.   XtManageChild(m1 = XmCreatePushButton(popup, "m1", NULL, 0));
  1557.   XtManageChild(m2 = XmCreatePushButton(popup, "m2", NULL, 0));
  1558.   XtManageChild(m3 = XmCreatePushButton(popup, "m3", NULL, 0));
  1559.  
  1560.   XtAddCallback(m1, XmNactivateCallback, SayCB, "button M1");
  1561.   XtAddCallback(m2, XmNactivateCallback, SayCB, "button M2");
  1562.   XtAddCallback(m3, XmNactivateCallback, SayCB, "button M3");
  1563.   ...
  1564. }
  1565.  
  1566. /* where PostMenu3 is ... */
  1567.  
  1568. PostMenu3 (w, popup, event)
  1569. Widget w;
  1570. Widget popup;
  1571. XButtonEvent * event;
  1572. {
  1573.   printf("menuPost = 3, button %d0, event->button);
  1574.  
  1575.   if (event->button != Button3)
  1576.     return;
  1577.   XmMenuPosition(popup, event);
  1578.   XtManageChild(popup);
  1579. }
  1580.  
  1581.  
  1582. -----------------------------------------------------------------------------
  1583. END OF PART THREE
  1584.  
  1585.