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 / part6 < prev   
Encoding:
Text File  |  1995-07-25  |  59.1 KB  |  1,653 lines

  1. Subject: Motif FAQ (Part 6 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:13 GMT
  5.  
  6. Archive-name: motif-faq/part6
  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: 173)  TOPIC: MISCELLANEOUS
  16.  
  17. -----------------------------------------------------------------------------
  18. Subject: 174)* How can an application be informed of signals?
  19.  
  20. Answer: blackman@hodgkin.med.upenn.edu (David Blackman) writes:
  21.  
  22. According to comp.windows.x FAQ, you shouldn't make Xt/Xlib calls from a Unix
  23. signal handler:
  24.  
  25.     "You can work around the problem by setting a flag in the
  26.     interrupt handler and later checking it with a work procedure
  27.     or a timer event which has previously been added."
  28.  
  29. Kaleb KEITHLEY (fedora.x.org!kaleb) adds:
  30.  
  31. Xt is not reentrant and it is not safe to call any Xt functions from a signal
  32. handler...  I think [the signaling] technique is covered in the [X] FAQ. On
  33. most POSIX-type systems write(2) is guaranteed to be reentrant and atomic. If
  34. you establish a simple pipe with the pipe(2) system call, and add it as an
  35. XtInput with XtAppAddInput(), then you can write to the pipe in the signal
  36. handler. Xt will notice that input is available and call the input-handler
  37. proc. This technique is inherently better than setting the flag because the
  38. write to the pipe will result in XtAppNextEvent returning immediately without
  39. the latency you observe in using the flag technique.  In R6 you can use the
  40. XtAppAddSignal function.
  41.  
  42. Ken Sall (ksall@cen.com) adds: See the "Signal Handling" chapter of "Motif
  43. Programming Manual" by Heller and Ferguson, listed in the BOOKS topic.
  44.  
  45. Paul Davey (pd@uit.co.uk) adds: The write and XtAppAddInput input method is
  46. often the best - but be warned it does not work on some SVR3 based Unixes,
  47. where a pipe may not be selected on. SCO Unix exhibits this behaviour so here
  48. the external flag method should be used.
  49.  
  50. -----------------------------------------------------------------------------
  51. Subject: 175)  How do I control the repeat rate on a SUN keyboard ??
  52.  
  53.  
  54. Answer:
  55.  
  56.      [...]
  57.  
  58.      -ar1 milliseconds
  59.              This option specifies amount of time in milliseconds
  60.              before   which   a   pressed  key  should  begin  to
  61.              autorepeat.
  62.  
  63.      -ar2 milliseconds
  64.              This option specifies the interval  in  milliseconds
  65.              between autorepeats of pressed keys.
  66.  
  67. Of course this presumes you're using a server based on the MIT sample server.
  68.  
  69. Thanks to kaleb@x.org (Kaleb Keithley)
  70.  
  71. -----------------------------------------------------------------------------
  72. Subject: 176)  How can I identify the children of a manager widget?
  73.  
  74. Answer: XmNnumChildren (number of widgets in array).
  75.  
  76. -----------------------------------------------------------------------------
  77. Subject: 177)  How do I tell if a scrolled window's scrollbars are visible?
  78.  
  79. Answer: Use XtGetValues() to get the scrollbar widget ID's, then use
  80. XtIsManaged() to see if they are managed (visible).
  81.  
  82. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  83.  
  84. -----------------------------------------------------------------------------
  85. Subject: 178)  How can I programatically scroll a XmScrolledWindow in
  86. XmAUTOMATIC mode?
  87.  
  88. Answer: In Motif 1.2, use XmScrollVisible().  If you're using a scrolled text
  89. or scrolled list combination widget, use XmTextScroll() or XmListSet*()
  90. instead.
  91.  
  92. The Motif manuals specifically forbid manipulating the scrollbars directly,
  93. but some people have reported success with XmScrollBarSetValues, with the
  94. "notify" parameter set to "True".
  95.  
  96. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  97.  
  98. -----------------------------------------------------------------------------
  99. Subject: 179)  What functions can an application use to change the size or
  100. position of a widget?
  101.  
  102. Answer: Applications should set the values of the XmNx, XmNy, XmNwidth, and
  103. XmNheight resources.
  104.  
  105. Note that many manager widgets ignore the XmNx and XmNy resources of their
  106. children, relying instead on their internal layout algorithms.  If you really
  107. want specific positions, you must use a manager widget that allows them, e.g.,
  108. XmBulletinBoard.
  109.  
  110. Also note that some manager widgets reject size change requests from their
  111. children when certain resources are set (e.g., XmNresizable on XmForm).
  112. Others allow the the children to resize, but clip the results (e.g.,
  113. XmNallowShellResize on shell widgets).  Make sure you have these resources set
  114. to the policy you want.
  115.  
  116. Due to bugs, some widgets (third party widgets) do not respond to changes in
  117. their width and height.  Sometimes, you can get them to respond correctly by
  118. unmanaging them, setting the resources, then managing them again.
  119.  
  120. Under no circumstances should applications use routines like
  121. XtConfigureWidget() or XtResizeWidget().  These routines are reserved for
  122. widget internals and will seriously confuse many widgets.
  123.  
  124. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  125.  
  126. -----------------------------------------------------------------------------
  127. Subject: 180)  What widgets give the look of push buttons, but behavior of
  128. toggle buttons?
  129.  
  130. Answer: Use the XmToggleButton widget, setting XmNindicatorOn to False and
  131. XmNshadowThickness to 2.
  132.  
  133. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  134.  
  135. Also set XmNfillOnSelect to True. Otherwise, the background color of the
  136. button will not stay in the "armed" state.
  137.  
  138. thanks to Glenn McMillen, mcmillen@meadow.mdso.vf.ge.com
  139.  
  140. In Motif 1.2 (and later), if you specify a XmNselectColor and set
  141. XmNindicatorOn to False, then you need to set XmNfillOnSelect to True.
  142. XmNfillOnSelect is not necessary if you are not setting a XmNselectColor.
  143.  
  144. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  145.  
  146.  
  147. -----------------------------------------------------------------------------
  148. Subject: 181)  How do I obtain the size of a unmanaged shell widget?
  149.  
  150. Answer: In the code below, use getsize() for widgets which have been managed,
  151. and getsize2() for newly created shell widgets which have not yet been
  152. managed.
  153.  
  154. getsize2() takes two widget parameters because popup dialogs etc.  _consist_
  155. of two separate widgets - the parent shell and the child bulletin board, form,
  156. whatever.  This important distinction (somewhat glossed over in the Motif
  157. manuals) is the cause of a large number of queries in comp.windows.x.motif.
  158. XmCreate...Dialog() functions return the (bulletin board, form, whatever)
  159. _child_ of the pair, not the parent shell.
  160.  
  161. getsize2() takes the _shell_ widget as it's first parameter, and the shell's
  162. _child_ (the bulletin board, form, whatever) as it's second.  Thus, if you are
  163. using code like widget = XmCreate...Dialog() to create your popup dialogs, use
  164. code like getsize2(XtParent(widget),widget,&width,&height) to get the width
  165. and height. If you use e.g. XmCreateDialogShell() or XtCreatePopupShell(),
  166. then you are creating the the shell widget and it's child explicitly, and can
  167. just pass them into getsize2() with no problem.
  168.  
  169. Note: getsize2() calls getsize().
  170.  
  171. /* getsize(widget,width,height);
  172.  * Widget widget;
  173.  * int *width,*height;
  174.  *
  175.  * returns the width and height of a managed widget */
  176.  
  177.  
  178. void getsize(l,w,h) Widget l; int *w,*h; { Dimension w_,h_,b_;
  179.  
  180. static Arg size_args[] =
  181.   {
  182.   { XmNwidth,0 },
  183.   { XmNheight,0 },
  184.   { XmNborderWidth,0 },
  185.   };
  186.  
  187. size_args[0].value = (XtArgVal)&w_; size_args[1].value = (XtArgVal)&h_;
  188. size_args[2].value = (XtArgVal)&b_;
  189.  
  190. XtGetValues(l,size_args,3);
  191.  
  192. if (w) *w = w_ + b_; if (h) *h = h_ + b_; } /*
  193. getsize2(shell,child,width,height);
  194.  * Widget shell,child;
  195.  * int *width,*height;
  196.  *
  197.  * returns the width, height of an unmanaged shell widget */
  198.  
  199. void getsize2(p,c,w,h) Widget p,c; int *w,*h; { XtSetMappedWhenManaged(p,0);
  200.  
  201. XtManageChild(c);
  202.  
  203. getsize(p,w,h);
  204.  
  205. XtUnmanageChild(c);
  206.  
  207. XtSetMappedWhenManaged(p,-1); } submitted by: [ Huw Rogers  Communications
  208. Software Engineer, NEC Corporation, Tokyo, Japan ] [ Email:
  209. rogersh@ccs.mt.nec.co.jp  Fax: +81-3-5476-1005  Tel: +81-3-5476-1096 ]
  210.  
  211. -----------------------------------------------------------------------------
  212. Subject: 182)  Can I use XtAddTimeOut, XtAddWorkProc, and XtAddInput with
  213. XtAppMainLoop?
  214.  
  215. Answer: On many systems, the obsolete XtAdd*() functions are not compatible
  216. with the XtAppMainLoop().  Instead, you should use newer XtAppAddTimeOut(),
  217. XtAppAddWorkProc(), and XtAppAddInput() functions with XtAppMainLoop()
  218.  
  219. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  220.  
  221. -----------------------------------------------------------------------------
  222. Subject: 183)  Why does XtGetValues for XmNx and XmNwidth return extremely
  223. large values?
  224.  
  225. Answer: You must use the 16 bit "Dimension" and "Position" data types for your
  226. arguments.  If you use 32 bit integers, some implementations will fill the
  227. remaining 16 bits with invalid data, causing incorrect return values.  The
  228. *Motif Programmer's Manual* and the widget man pages specify the correct data
  229. type for each resource.
  230.  
  231. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  232.  
  233. -----------------------------------------------------------------------------
  234. Subject: 184)  XtGetValues() on XmNx and XmNy of my top level shell don't
  235. return the correct root window coordinates.  How do I compute these?
  236.  
  237. Answer: XmNx and XmNy are the coordinates relative to your shell's parent
  238. window, which is usually a window manager's frame window.  To translate to the
  239. root coordinate space, use XtTranslateCoords() or XTranslateCoordinates().
  240.  
  241. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  242.  
  243. -----------------------------------------------------------------------------
  244. Subject: 185)  Can I use XmGetPixmap() with widgets that have non-default
  245. visual types?
  246.  
  247. Answer: If you're using a different depth, use XmGetPixmapByDepth() instead.
  248.  
  249. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  250.  
  251. -----------------------------------------------------------------------------
  252. Subject: 186)  How can I determine the item selected in a option menu or a
  253. RadioBox?
  254.  
  255. Answer: The value of the XmNmenuHistory resource of the XmRowColumn parent is
  256. the widget ID of the last selected item.  It works the same way for all menus
  257. and radio boxes.
  258.  
  259. Thanks to Ken Lee, kenton@allegro.esd.sgi.com
  260.  
  261. -----------------------------------------------------------------------------
  262. Subject: 187)  What is the matter with Frame in Motif 1.2?
  263.  
  264. [Last modified: November 92]
  265.  
  266. Answer: This announcement has been made by OSF:
  267.  
  268. "IMPORTANT NOTICE
  269.  
  270. We have discovered two problems in the new 1.2 child alignment resources in
  271. XmFrame. Because some vendors may have committed, or are soon to commit to
  272. field releases of Motif 1.2 and 1.2.1, OSF's options for fixing them are
  273. limited. We are trying to deal with these in a way that does not cause
  274. hardship for application developers who will develop applications against
  275. various point versions of Motif. OSF's future actions for correction are
  276. summarized.
  277.  
  278. WHAT YOU SHOULD DO AND KNOW
  279.  
  280. 1. Mark the following change in your documentation.
  281.  
  282. On page 1-512 of the OSF/Motif Programmer's Reference, change the descriptions
  283. under XmNchildVerticalAlignment as follows (what follows is the CORRECT
  284. wording to match the current implementation):
  285.  
  286. XmALIGNMENT_WIDGET_TOP
  287.         Causes the BOTTOM edge of the title area to align
  288.         vertically with the top shadow of the Frame.
  289.  
  290. XmALIGNMENT_WIDGET_BOTTOM
  291.         Causes the TOP edge of the title area to align
  292.         vertically with the top shadow of the Frame.
  293.  
  294. 2. Note the following limitation on resource converters for Motif 1.2 and
  295. 1.2.1 implementations.
  296.  
  297. The rep types for XmFrame's XmNentryVerticalAlignment resource were
  298. incorrected implemented, which means that converters will not work properly.
  299. The following resource settings will not work from a resource file in 1.2 and
  300. 1.2.1:
  301.  
  302.         *childVerticalAlignment: alignment_baseline_bottom
  303.         *childVerticalAlignment: alignment_baseline_top
  304.         *childVerticalAlignment: alignment_widget_bottom
  305.         *childVerticalAlignment: alignment_widget_top
  306.  
  307. If you wish to set these values for these resources (note they are new
  308. constraint resources in XmFrame) you will have to set them directly in C or
  309. via uil.
  310.  
  311. WHAT WE WILL DO
  312.  
  313. The problem described in note #1 above will not be fixed in the OSF/Motif
  314. implementation until the next MAJOR release of Motif.  At that time we will
  315. correct the documentation and modify the code to match those new descriptions,
  316. but we will preserve the existing enumerated values and their behavior for
  317. backward compatibility for that release.
  318.  
  319. The fix for the problem described in note #2 will be shipped by OSF in Motif
  320. 1.2.2.
  321.  
  322. SUMMARY
  323.  
  324. We are sorry for any difficulty this causes Motif users.  If you have any
  325. questions or flames (I suppose I deserve it) please send them directly to me.
  326. We sincerely hope this proactive response is better for our customers than you
  327. having to figure it out yourselves!
  328.  
  329. Libby
  330.  
  331.  
  332. -----------------------------------------------------------------------------
  333. Subject: 188)  What is IMUG and how do I join it?
  334.  
  335. Answer: IMUG is the International Motif User Group founded by Quest Windows
  336. Corporation and co-sponsored by FedUNIX.  IMUG is a non-profit organization
  337. working to keep users informed on technical and standards issues, to
  338. strengthen user groups on a local level, to increase communication among users
  339. internationally, and to promote the use of an international conference as a
  340. forum for sharing and learning more about Motif.  You can join it by
  341.  
  342.  1.  Pay the annual membership fee of $20 USD directly to IMUG.  Contact
  343.  
  344.      IMUG
  345.      5200 Great America Parkway
  346.      Santa Clara,  CA  95054
  347.      (408) 496-1900
  348.      imug@quest.com
  349.  
  350.  2.  Register at the International Motif User Conference, and automatically
  351.      become an IMUG member.
  352.  
  353.  3.  Donate a pd widget, widget tool or widget builder to the IMUG Widget
  354.      Depository and receive a free one year IMUG membership.
  355.  
  356.  
  357. -----------------------------------------------------------------------------
  358. Subject: 189)  How do I set the title of a top level window?
  359.  
  360. [Last modified: September 92]
  361.  
  362. Answer: Set XmNtitle (and optionally XmNtitleEncoding) for TopLevelShells.
  363. (Note that this is of type String rather than XmStrin.) Ypu can also set
  364. XmNiconName if you want its icon to show this title.  For XmDialogShells, set
  365. the XmNdialogTitle of its immediate child, assuming it's a BulletinBoard
  366. subclass.  These can also be set in resource files.
  367.  
  368.  
  369. -----------------------------------------------------------------------------
  370. Subject: 190)  Can I use editres with Motif?
  371.  
  372. [Last modified: Sept 94]
  373.  
  374. Answer: Editres, part of the MIT delivery, is a powerful widget tree analysis
  375. tool and is highly recommended.  There's negligible overhead in making editres
  376. available to an application and many projects keep the editres "hook" active
  377. even for operational programs.
  378.  
  379. It isn't built in to Motif (at 1.2.0), but you can do this in your application
  380.  
  381.     extern void _XEditResCheckMessages();
  382.     ...
  383.     XtAddEventHandler(shell_widget, (EventMask)0, True,
  384.                         _XEditResCheckMessages, NULL);
  385.  
  386. once for each shell widget that you want to react to the "click to select
  387. client" protocol.  Then link your client with the R5 libXmu.
  388.  
  389. David Brooks, OSF
  390.  
  391. From Marc Quinton (quinton@stna7.stna7.stna.dgac.fr):
  392.  
  393. With X11R4 see the Editres package which is a port of the X11R5 Editres
  394. protocol and client. You can find it at :
  395.  
  396.  ftp.stna7.stna.dgac.fr(143.196.9.83):/pub/dist/Editres.tar.Z
  397.  
  398. -----------------------------------------------------------------------------
  399. Subject: 191)  How can I put decorations on transient windows using olwm?
  400.  
  401. Answer: From Jean-Philippe Martin-Flatin <syj@ecmwf.co.uk>
  402.  
  403. /**********************************************************************
  404. ** WindowDecorations.c
  405. **
  406. ** Manages window decorations under the OpenLook window manager (OLWM).
  407. **
  408. ** Adapted from a C++ program posted to comp.windows.x.motif by:
  409. **
  410. **    +--------------------------------------------------------------+
  411. **    | Ron Edmark                          User Interface Group     |
  412. **    | Tel:        (408) 980-1500 x282     Integrated Systems, Inc. |
  413. **    | Internet:   edmark@isi.com          3260 Jay St.             |
  414. **    | Voice mail: (408) 980-1590 x282     Santa Clara, CA 95054    |
  415. **    +--------------------------------------------------------------+
  416. ***********************************************************************/
  417.  
  418. #include <X11/X.h>
  419. #include <X11/Xlib.h>
  420. #include <X11/Xatom.h>
  421. #include <X11/Intrinsic.h>
  422. #include <X11/StringDefs.h>
  423. #include <X11/Protocols.h>
  424. #include <Xm/Xm.h>
  425. #include <Xm/AtomMgr.h>
  426.  
  427. /*
  428. ** Decorations for OpenLook:
  429. ** The caller can OR different mask options to change the frame decoration.
  430. */
  431. #define OLWM_Header     (long)(1<<0)
  432. #define OLWM_Resize     (long)(1<<1)
  433. #define OLWM_Close      (long)(1<<2)
  434.  
  435. /*
  436. ** Prototypes
  437. */
  438. static void InstallOLWMAtoms  (Widget w);
  439. static void AddOLWMDialogFrame(Widget widget, long decorationMask);
  440.  
  441.  
  442. /*
  443. ** Global variables
  444. */
  445. static Atom AtomWinAttr;
  446. static Atom AtomWTOther;
  447. static Atom AtomDecor;
  448. static Atom AtomResize;
  449. static Atom AtomHeader;
  450. static Atom AtomClose;
  451. static int  not_installed_yet = TRUE;
  452.  
  453.  
  454. static void InstallOLWMAtoms(Widget w)
  455. {
  456.         AtomWinAttr = XInternAtom(XtDisplay(w), "_OL_WIN_ATTR" ,    FALSE);
  457.         AtomWTOther = XInternAtom(XtDisplay(w), "_OL_WT_OTHER",     FALSE);
  458.         AtomDecor   = XInternAtom(XtDisplay(w), "_OL_DECOR_ADD",    FALSE);
  459.         AtomResize  = XInternAtom(XtDisplay(w), "_OL_DECOR_RESIZE", FALSE);
  460.         AtomHeader  = XInternAtom(XtDisplay(w), "_OL_DECOR_HEADER", FALSE);
  461.         AtomClose   = XInternAtom(XtDisplay(w), "_OL_DECOR_CLOSE",  FALSE);
  462.  
  463.         not_installed_yet = FALSE;
  464. }
  465.  
  466. static void AddOLWMDialogFrame(Widget widget, long decorationMask)
  467. {
  468.         Atom   winAttrs[2];
  469.         Atom   winDecor[3];
  470.         Widget shell = widget;
  471.         Window win;
  472.         int    numberOfDecorations = 0;
  473.  
  474.         /*
  475.         ** Make sure atoms for OpenLook are installed only once
  476.         */
  477.         if (not_installed_yet) InstallOLWMAtoms(widget);
  478.  
  479.         while (!XtIsShell(shell)) shell = XtParent(shell);
  480.  
  481.         win = XtWindow(shell);
  482.  
  483.         /*
  484.         ** Tell Open Look that our window is not one of the standard OLWM window        ** types. See OLIT Widget Set Programmer's Guide pp.70-73.
  485.         */
  486.  
  487.         winAttrs[0] = AtomWTOther;
  488.  
  489.         XChangeProperty(XtDisplay(shell),
  490.                         win,
  491.                         AtomWinAttr,
  492.                         XA_ATOM,
  493.                         32,
  494.                         PropModeReplace,
  495.                         (unsigned char*)winAttrs,
  496.                         1);
  497.  
  498.         /*
  499.         ** Tell Open Look to add some decorations to our window
  500.         */
  501.         numberOfDecorations = 0;
  502.         if (decorationMask & OLWM_Header)
  503.                 winDecor[numberOfDecorations++] = AtomHeader;
  504.         if (decorationMask & OLWM_Resize)
  505.                 winDecor[numberOfDecorations++] = AtomResize;
  506.         if (decorationMask & OLWM_Close)
  507.         {
  508.                 winDecor[numberOfDecorations++] = AtomClose;
  509.  
  510.                 /*
  511.                 ** If the close button is specified, the header must be
  512.                 ** specified. If the header bit is not set, set it.
  513.                 */
  514.                 if (!(decorationMask & OLWM_Header))
  515.                         winDecor[numberOfDecorations++] = AtomHeader;
  516.         }
  517.  
  518.         XChangeProperty(XtDisplay(shell),
  519.                         win,
  520.                         AtomDecor,
  521.                         XA_ATOM,
  522.                         32,
  523.                         PropModeReplace,
  524.                         (unsigned char*)winDecor,
  525.                         numberOfDecorations);
  526. }
  527.  
  528.  
  529. /*
  530. ** Example of use of AddOLWMDialogFrame, with a bit of extra stuff
  531. */
  532. void register_dialog_to_WM(Widget shell, XtCallbackProc Cbk_func)
  533. {
  534.         Atom atom;
  535.  
  536.         /*
  537.         ** Alias the "Close" item in system menu attached to dialog shell
  538.         ** to the activate callback of "Exit" in the menubar
  539.         */
  540.         if (Cbk_func)
  541.         {
  542.             atom = XmInternAtom(XtDisplay(shell),"WM_DELETE_WINDOW",TRUE);
  543.             XmAddWMProtocolCallback(shell,atom, Cbk_func,NULL);
  544.         }
  545.  
  546.         /*
  547.         ** If Motif is the window manager, skip OpenLook specific stuff
  548.         */
  549.         if (XmIsMotifWMRunning(shell)) return;
  550.  
  551.         /*
  552.         ** Register dialog shell to OpenLook.
  553.         **
  554.         ** WARNING: on some systems, adding the "Close" button allows the title
  555.         ** to be properly centered in the title bar. On others, activating
  556.         ** "Close" crashes OpenLook. The reason is not clear yet, but it seems
  557.         ** the first case occurs with OpenWindows 2 while the second occurs with
  558.         ** Openwindows 3. Thus, comment out one of the two following lines as
  559.         ** suitable for your site, and send e-mail to syj@ecmwf.co.uk if you
  560.         ** find out what is going on !
  561.         */
  562.         AddOLWMDialogFrame(shell,(OLWM_Header | OLWM_Resize));
  563. /*      AddOLWMDialogFrame(shell,(OLWM_Header | OLWM_Resize | OLWM_Close)); */
  564. }
  565.  
  566.  
  567. -----------------------------------------------------------------------------
  568. Subject: 192)  Why does an augment translation appear to act as replace for
  569. some widgets?  When I use either augment or override translations in
  570. .Xdefaults it seems to act as replace in both Motif 1.0 and 1.1
  571.  
  572. Answer: By default, the translation table is NULL.  If there is nothing
  573. specified (either in resource file, or in args), the widget's Initialize
  574. finds: Oh, there is NULL in translations, lets use our default ones.  If,
  575. however, the translations have become non-NULL, the default translations are
  576. NOT used at all. Thus, using #augment, #override or a new table has identical
  577. effect: defines the new translations. The only way you can augment/override
  578. Motif's default translations is AFTER Initialize, using XtSetValues.  Note,
  579. however, that Motif managers do play with translation tables as well ... so
  580. that results are not always easy to predict.
  581.  
  582. From OSF: A number of people have complained about not being able to
  583. augment/override translations from the .Xdefaults.  This is due to the
  584. complexity of the menu system/keyboard traversal and the necessary
  585. translations changes required to support the Motif Style Guide in menus.  It
  586. cannot be fixed in a simple way. Fixing it requires re-design of the
  587. menus/buttons and it is planned to be fixed in 1.2.
  588.  
  589. -----------------------------------------------------------------------------
  590. Subject: 193)  How do you "grey" out a widget so that it cannot be activated?
  591.  
  592. Answer: Use XtSetSensitive(widget, False). Do not set the XmNsensitive
  593. resource directly yourself (by XtSetValues) since the widget may need to talk
  594. to parents first.
  595.  
  596. -----------------------------------------------------------------------------
  597. Subject: 194)* Why doesn't the Help callback work on some widgets?
  598.  
  599. [Last modified: Oct 94]
  600.  
  601. Answer: If you press the help key the help callback of the widget with the
  602. keyboard focus is called (not the one containing the mouse).  You can't get
  603. the help callback of a non-keyboard-selectable widget called. To get `context
  604. sensitive' help on these, you have to find the mouse, associate its position
  605. with a widget and then do the help.
  606.  
  607.  The X Resource, Issue 6, has an article on implementing context help in
  608.  Motif in this manner, that is, using the mouse position to indicate the
  609.  widget for which context help is desired, as well as using resources to
  610.  specify the help.  Example source code is available at
  611.  
  612.         ftp://ora.com/pub/examples/xresource/issue6/helpdemo.tar.Z
  613.  
  614.  The demo program lets you toggle between using the method described in
  615.  the article and XmTrackingLocate() for comparision purposes.
  616.  
  617. contributed by: Jay Schmidgall  jay@vnet.ibm.com (author of the article
  618. mentioned above) --
  619.  
  620. -----------------------------------------------------------------------------
  621. Subject: 195)  Can I specify a widget in a resource file?
  622.  
  623. Answer: This answer, which uses the Xmu library, is due to David Elliott.  If
  624. the converter is added, then the name of a widget (a string) can be used in
  625. resource files, and will be converted to the appropriate widget.
  626.  
  627. This code, which was basically stolen from the Athena Form widget, adds a
  628. String to Widget converter.  I wrote it as a general routine that I call at
  629. the beginning of all of my programs, and made it so I could add other
  630. converters as needed (like String to Unit Type ;-).
  631.  
  632.         #include <X11/Intrinsic.h>
  633.         #include <X11/StringDefs.h>
  634.         #include <Xm/Xm.h>
  635.         #include <X11/Xmu/Converters.h>
  636.         #include <X11/IntrinsicP.h>
  637.         #include <X11/CoreP.h>
  638.  
  639.         void
  640.         setupConverters()
  641.         {
  642.                 static XtConvertArgRec parentCvtArgs[] = {
  643.                         {XtBaseOffset, (caddr_t)XtOffset(Widget, core.parent),
  644.                                 sizeof(Widget)}
  645.                 };
  646.  
  647.                 XtAddConverter(XmRString, XmRWindow, XmuCvtStringToWidget,
  648.                         parentCvtArgs, XtNumber(parentCvtArgs));
  649.         }
  650.  
  651.  
  652. -----------------------------------------------------------------------------
  653. Subject: 196)  Why are only some of my translations are being installed?  I
  654. have a translation table like the following, but only the first ones are
  655. getting installed and the rest are ignored.
  656.  
  657.  *Text.translations:    #override \
  658.      Ctrl<Key>a:    beginning-of-line() \n\
  659.      Ctrl<Key>e:    end-of-line() \n\
  660.      Ctrl<Key>f:    forward-character() \n\
  661.  
  662.  
  663. Answer: Most likely, you have a space at the end of one of the lines (the
  664. first in this case).
  665.  
  666.      Ctrl<Key>a:    beginning-of-line() \n\
  667.                                            ^ space here
  668.  
  669. The second backslash in each line is there to protect the real newline
  670. character and so you must not follow it with anything other than the newline
  671. itself. Otherwise it acts as the end of the resource definition and the
  672. remaining lines are not added.
  673.  
  674.  
  675. -----------------------------------------------------------------------------
  676. Subject: 197)  Where can I get the PanHandler code?
  677.  
  678. Answer: It is available by email from Chuck Ocheret:  chuck@IMSI.COM.
  679.  
  680. -----------------------------------------------------------------------------
  681. Subject: 198)  What are these passive grab warnings?  When I destroy certain
  682. widgets I get a stream of messages
  683.  
  684.     Warning: Attempt to remove non-existant passive grab
  685.  
  686.  
  687. Answer: They are meaningless, and you want to ignore them.  Do this (from Kee
  688. Hinckley) by installing an XtWarning handler that explicitly looks for them
  689. and discards them:
  690.  
  691.         static void xtWarnCB(String message) {
  692.            if (asi_strstr(message, "non-existant passive grab", TRUE)) return;
  693.            ...
  694.  
  695. They come from Xt, and (W. Scott Meeks): "it's something that the designers of
  696. Xt decided the toolkit should do. Unfortunately, Motif winds up putting
  697. passive grabs all over the place for the menu system.  On the one hand, we
  698. want to remove all these grabs when menus get destroyed so that they don't
  699. leak memory; on the other hand, it's almost impossible to keep track of all
  700. the grabs, so we have a conservative strategy of ungrabbing any place where a
  701. grab could have been made and we don't explicitly know that there is no grab.
  702. The unfortunate side effect is the little passive grab warning messages.
  703. We're trying to clean these up where possible, but there are some new places
  704. where the warning is generated.  Until we get this completely cleaned up (1.2
  705. maybe), your best bet is probably to use a warning handler."
  706.  
  707. -----------------------------------------------------------------------------
  708. Subject: 199)  How do I have more buttons than three in a box?  I want to have
  709. something like a MessageBox (or other widget) with more than three buttons,
  710. but with the same nice appearance.
  711.  
  712. [Last modified: May 93]
  713.  
  714. Answer: The Motif 1.2 MessageBox widget allows extra buttons to be added after
  715. the OK button. Just create the extra buttons as children of the MessageBox.
  716. Similarly with the SelectionBox.
  717.  
  718. Pre-Motif 1.2, you have to do one of the following methods.
  719.  
  720. A SelectionBox is created with four buttons, but the fourth (the Apply button)
  721. is unmanaged. To manage it get its widget ID via
  722. XmSelectionBoxGetChild(parent, XmDIALOG_APPLY_BUTTON) and then XtManage it.
  723. Unmanage all of the other bits in the SelectionBox that you don't want.  If
  724. you want more than four buttons, try two SelectionBoxes (or similar) together
  725. in a container, where all of the unwanted parts of the widgets are unmanaged.
  726.  
  727. Alternatively, build your own dialog:
  728.  
  729. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  730.  * This program is freely distributable without licensing fees and
  731.  * is provided without guarantee or warranty expressed or implied.
  732.  * This program is -not- in the public domain.  This program is
  733.  * taken from the Motif Programming Manual, O'Reilly Volume 6.
  734.  */
  735.  
  736. /* action_area.c -- demonstrate how CreateActionArea() can be used
  737.  * in a real application.  Create what would otherwise be identified
  738.  * as a PromptDialog, only this is of our own creation.  As such,
  739.  * we provide a TextField widget for input.  When the user presses
  740.  * Return, the Ok button is activated.
  741.  */
  742. #include <Xm/DialogS.h>
  743. #include <Xm/PushBG.h>
  744. #include <Xm/PushB.h>
  745. #include <Xm/LabelG.h>
  746. #include <Xm/PanedW.h>
  747. #include <Xm/Form.h>
  748. #include <Xm/RowColumn.h>
  749. #include <Xm/TextF.h>
  750.  
  751. typedef struct {
  752.     char *label;
  753.     void (*callback)();
  754.     caddr_t data;
  755. } ActionAreaItem;
  756.  
  757. static void
  758.     do_dialog(), close_dialog(), activate_cb(),
  759.     ok_pushed(), cancel_pushed(), help();
  760.  
  761. main(argc, argv)
  762. int argc;
  763. char *argv[];
  764. {
  765.     Widget toplevel, button;
  766.     XtAppContext app;
  767.  
  768.     toplevel = XtVaAppInitialize(&app, "Demos",
  769.         NULL, 0, &argc, argv, NULL, NULL);
  770.  
  771.     button = XtVaCreateManagedWidget("Push Me",
  772.         xmPushButtonWidgetClass, toplevel, NULL);
  773.     XtAddCallback(button, XmNactivateCallback, do_dialog, NULL);
  774.  
  775.     XtRealizeWidget(toplevel);
  776.     XtAppMainLoop(app);
  777. }
  778.  
  779. /* callback routine for "Push Me" button.  Actually, this represents
  780.  * a function that could be invoked by any arbitrary callback.  Here,
  781.  * we demonstrate how one can build a standard customized dialog box.
  782.  * The control area is created here and the action area is created in
  783.  * a separate, generic routine: CreateActionArea().
  784.  */
  785. static void
  786. do_dialog(w, file)
  787. Widget w; /* will act as dialog's parent */
  788. char *file;
  789. {
  790.     Widget dialog, pane, rc, label, text_w, action_a;
  791.     XmString string;
  792.     extern Widget CreateActionArea();
  793.     Arg args[10];
  794.     static ActionAreaItem action_items[] = {
  795.         { "Ok",     ok_pushed,     NULL          },
  796.         { "Cancel", cancel_pushed, NULL          },
  797.         { "Close",  close_dialog,  NULL          },
  798.         { "Help",   help,          "Help Button" },
  799.     };
  800.  
  801.     /* The DialogShell is the Shell for this dialog.  Set it up so
  802.      * that the "Close" button in the window manager's system menu
  803.      * destroys the shell (it only unmaps it by default).
  804.      */
  805.     dialog = XtVaCreatePopupShell("dialog",
  806.         xmDialogShellWidgetClass, XtParent(w),
  807.         XmNtitle,  "Dialog Shell",     /* give arbitrary title in wm */
  808.         XmNdeleteResponse, XmDESTROY,  /* system menu "Close" action */
  809.         NULL);
  810.  
  811.     /* now that the dialog is created, set the Close button's
  812.      * client data, so close_dialog() will know what to destroy.
  813.      */
  814.     action_items[2].data = (caddr_t)dialog;
  815.  
  816.     /* Create the paned window as a child of the dialog.  This will
  817.      * contain the control area (a Form widget) and the action area
  818.      * (created by CreateActionArea() using the action_items above).
  819.      */
  820.     pane = XtVaCreateWidget("pane", xmPanedWindowWidgetClass, dialog,
  821.         XmNsashWidth,  1,
  822.         XmNsashHeight, 1,
  823.         NULL);
  824.  
  825.     /* create the control area (Form) which contains a
  826.      * Label gadget and a List widget.
  827.      */
  828.     rc = XtVaCreateWidget("control_area", xmRowColumnWidgetClass, pane, NULL);
  829.     string = XmStringCreateSimple("Type Something:");
  830.     XtVaCreateManagedWidget("label", xmLabelGadgetClass, rc,
  831.         XmNlabelString,    string,
  832.         XmNleftAttachment, XmATTACH_FORM,
  833.         XmNtopAttachment,  XmATTACH_FORM,
  834.         NULL);
  835.     XmStringFree(string);
  836.  
  837.     text_w = XtVaCreateManagedWidget("text-field",
  838.         xmTextFieldWidgetClass, rc, NULL);
  839.  
  840.     /* RowColumn is full -- now manage */
  841.     XtManageChild(rc);
  842.  
  843.     /* Set the client data "Ok" and "Cancel" button's callbacks. */
  844.     action_items[0].data = (caddr_t)text_w;
  845.     action_items[1].data = (caddr_t)text_w;
  846.  
  847.     /* Create the action area -- we don't need the widget it returns. */
  848.     action_a = CreateActionArea(pane, action_items, XtNumber(action_items));
  849.  
  850.     /* callback for Return in TextField.  Use action_a as client data */
  851.     XtAddCallback(text_w, XmNactivateCallback, activate_cb, action_a);
  852.  
  853.     XtManageChild(pane);
  854.     XtPopup(dialog, XtGrabNone);
  855. }
  856.  
  857. /*--------------*/
  858. /* The next four functions are the callback routines for the buttons
  859.  * in the action area for the dialog created above.  Again, they are
  860.  * simple examples, yet they demonstrate the fundamental design approach.
  861.  */
  862. static void
  863. close_dialog(w, shell)
  864. Widget w, shell;
  865. {
  866.     XtDestroyWidget(shell);
  867. }
  868.  
  869. /* The "ok" button was pushed or the user pressed Return */
  870. static void
  871. ok_pushed(w, text_w, cbs)
  872. Widget w, text_w;         /* the text widget is the client data */
  873. XmAnyCallbackStruct *cbs;
  874. {
  875.     char *text = XmTextFieldGetString(text_w);
  876.  
  877.     printf("String = %s0, text);
  878.     XtFree(text);
  879. }
  880.  
  881. static void
  882. cancel_pushed(w, text_w, cbs)
  883. Widget w, text_w;         /* the text field is the client data */
  884. XmAnyCallbackStruct *cbs;
  885. {
  886.     /* cancel the whole operation; reset to NULL. */
  887.     XmTextFieldSetString(text_w, "");
  888. }
  889.  
  890. static void
  891. help(w, string)
  892. Widget w;
  893. String string;
  894. {
  895.     puts(string);
  896. }
  897. /*--------------*/
  898.  
  899. /* When Return is pressed in TextField widget, respond by getting
  900.  * the designated "default button" in the action area and activate
  901.  * it as if the user had selected it.
  902.  */
  903. static void
  904. activate_cb(text_w, client_data, cbs)
  905. Widget text_w;              /* user pressed Return in this widget */
  906. XtPointer client_data;        /* action_area passed as client data */
  907. XmAnyCallbackStruct *cbs;   /* borrow the "event" field from this */
  908. {
  909.     Widget dflt, action_area = (Widget)client_data;
  910.  
  911.     XtVaGetValues(action_area, XmNdefaultButton, &dflt, NULL);
  912.     if (dflt) /* sanity check -- this better work */
  913.         /* make the default button think it got pushed.  This causes
  914.          * "ok_pushed" to be called, but XtCallActionProc() causes
  915.          * the button appear to be activated as if the user selected it.
  916.          */
  917.         XtCallActionProc(dflt, "ArmAndActivate", cbs->event, NULL, 0);
  918. }
  919.  
  920. #define TIGHTNESS 20
  921.  
  922. Widget
  923. CreateActionArea(parent, actions, num_actions)
  924. Widget parent;
  925. ActionAreaItem *actions;
  926. int num_actions;
  927. {
  928.     Widget action_area, widget;
  929.     int i;
  930.  
  931.     action_area = XtVaCreateWidget("action_area", xmFormWidgetClass, parent,
  932.         XmNfractionBase, TIGHTNESS*num_actions - 1,
  933.         XmNleftOffset,   10,
  934.         XmNrightOffset,  10,
  935.         NULL);
  936.  
  937.     for (i = 0; i < num_actions; i++) {
  938.         widget = XtVaCreateManagedWidget(actions[i].label,
  939.             xmPushButtonWidgetClass, action_area,
  940.             XmNleftAttachment,       i? XmATTACH_POSITION : XmATTACH_FORM,
  941.             XmNleftPosition,         TIGHTNESS*i,
  942.             XmNtopAttachment,        XmATTACH_FORM,
  943.             XmNbottomAttachment,     XmATTACH_FORM,
  944.             XmNrightAttachment,
  945.                     i != num_actions-1? XmATTACH_POSITION : XmATTACH_FORM,
  946.             XmNrightPosition,        TIGHTNESS*i + (TIGHTNESS-1),
  947.             XmNshowAsDefault,        i == 0,
  948.             XmNdefaultButtonShadowThickness, 1,
  949.             NULL);
  950.         if (actions[i].callback)
  951.             XtAddCallback(widget, XmNactivateCallback,
  952.                 actions[i].callback, actions[i].data);
  953.         if (i == 0) {
  954.             /* Set the action_area's default button to the first widget
  955.              * created (or, make the index a parameter to the function
  956.              * or have it be part of the data structure). Also, set the
  957.              * pane window constraint for max and min heights so this
  958.              * particular pane in the PanedWindow is not resizable.
  959.              */
  960.             Dimension height, h;
  961.             XtVaGetValues(action_area, XmNmarginHeight, &h, NULL);
  962.             XtVaGetValues(widget, XmNheight, &height, NULL);
  963.             height += 2 * h;
  964.             XtVaSetValues(action_area,
  965.                 XmNdefaultButton, widget,
  966.                 XmNpaneMaximum,   height,
  967.                 XmNpaneMinimum,   height,
  968.                 NULL);
  969.         }
  970.     }
  971.  
  972.     XtManageChild(action_area);
  973.  
  974.     return action_area;
  975. }
  976.  
  977.  
  978. -----------------------------------------------------------------------------
  979. Subject: 200)  How do I create a "busy working cursor"?
  980.  
  981. Answer: - in Baudouin's code (following), the idea is to keep in an array an
  982. up-to-date list of all shells used in the application, and set for all of them
  983. the cursor to a watch or to the default cursor, with the 2 functions provided.
  984.  
  985. - in Dan Heller's code (later), the idea is to turn on the watch cursor for
  986. the top-level shell only, popup a working window to possibly abort the
  987. callback, and manage some expose events during the callback.
  988.  
  989. - in the FAQ for comp.windows.x (#113), the idea is to bring a large window on
  990. top of the application, hide all windows below it, and turn on the watch
  991. cursor on this large window. Unmapping the large window resets the default
  992. cursor, mapping it turns on the watch cursor.
  993.  
  994. From Baudouin Raoult (mab@ecmwf.co.uk)
  995.  
  996. void my_SetWatchCursor(w)
  997. Widget w;
  998. {
  999.         static Cursor watch = NULL;
  1000.  
  1001.         if(!watch)
  1002.                 watch = XCreateFontCursor(XtDisplay(w),XC_watch);
  1003.  
  1004.         XDefineCursor(XtDisplay(w),XtWindow(w),watch);
  1005.         XmUpdateDisplay(w);
  1006. }
  1007.  
  1008. void my_ResetCursor(w)
  1009. Widget w;
  1010. {
  1011.         XUndefineCursor(XtDisplay(w),XtWindow(w));
  1012.         XmUpdateDisplay(w);
  1013. }
  1014.  
  1015.  
  1016. Answer: A solution with lots of bells and whistles is
  1017.  
  1018.  
  1019. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  1020.  * This program is freely distributable without licensing fees and
  1021.  * is provided without guarantee or warrantee expressed or implied.
  1022.  * This program is -not- in the public domain.
  1023.  */
  1024.  
  1025. /* busy.c -- demonstrate how to use a WorkingDialog and to process
  1026.  * only "important" events.  e.g., those that may interrupt the
  1027.  * task or to repaint widgets for exposure.  Set up a simple shell
  1028.  * and a widget that, when pressed, immediately goes into its own
  1029.  * loop.  First, "lock" the shell so that a timeout cursor is set on
  1030.  * the shell and pop up a WorkingDialog.  Then enter loop ... sleep
  1031.  * for one second ten times, checking between each interval to see
  1032.  * if the user clicked the Stop button or if any widgets need to be
  1033.  * refreshed.  Ignore all other events.
  1034.  *
  1035.  * main() and get_busy() are stubs that would be replaced by a real
  1036.  * application; all other functions can be used "as is."
  1037.  */
  1038. #include <Xm/MessageB.h>
  1039. #include <Xm/PushB.h>
  1040. #include <X11/cursorfont.h>
  1041.  
  1042. Widget shell;
  1043. void TimeoutCursors();
  1044. Boolean CheckForInterrupt();
  1045.  
  1046. main(argc, argv)
  1047. int argc;
  1048. char *argv[];
  1049. {
  1050.     XtAppContext app;
  1051.     Widget button;
  1052.     XmString label;
  1053.     void get_busy();
  1054.  
  1055.     shell = XtVaAppInitialize(&app, "Demos",
  1056.         NULL, 0, &argc, argv, NULL, NULL);
  1057.  
  1058.     label = XmStringCreateSimple(
  1059.         "Boy, is *this* going to take a long time.");
  1060.     button = XtVaCreateManagedWidget("button",
  1061.         xmPushButtonWidgetClass, shell,
  1062.         XmNlabelString,          label,
  1063.         NULL);
  1064.     XmStringFree(label);
  1065.     XtAddCallback(button, XmNactivateCallback, get_busy, argv[1]);
  1066.  
  1067.     XtRealizeWidget(shell);
  1068.     XtAppMainLoop(app);
  1069. }
  1070.  
  1071. void
  1072. get_busy(widget)
  1073. Widget widget;
  1074. {
  1075.     int n;
  1076.  
  1077.     TimeoutCursors(True, True);
  1078.     for (n = 0; n < 10; n++) {
  1079.         sleep(1);
  1080.         if (CheckForInterrupt()) {
  1081.             puts("Interrupt!");
  1082.             break;
  1083.         }
  1084.     }
  1085.     if (n == 10)
  1086.         puts("done.");
  1087.     TimeoutCursors(False, NULL);
  1088. }
  1089.  
  1090. /* The interesting part of the program -- extract and use at will */
  1091. static Boolean stopped;  /* True when user wants to stop processing */
  1092. static Widget dialog;    /* WorkingDialog displayed when timed out */
  1093.  
  1094. /* timeout_cursors() turns on the "watch" cursor over the application
  1095.  * to provide feedback for the user that he's going to be waiting
  1096.  * a while before he can interact with the appliation again.
  1097.  */
  1098. void
  1099. TimeoutCursors(on, interruptable)
  1100. int on, interruptable;
  1101. {
  1102.     static int locked;
  1103.     static Cursor cursor;
  1104.     extern Widget shell;
  1105.     XSetWindowAttributes attrs;
  1106.     Display *dpy = XtDisplay(shell);
  1107.     XEvent event;
  1108.     Arg args[1];
  1109.     XmString str;
  1110.     extern void stop();
  1111.  
  1112.     /* "locked" keeps track if we've already called the function.
  1113.      * This allows recursion and is necessary for most situations.
  1114.      */
  1115.     on? locked++ : locked--;
  1116.     if (locked > 1 || locked == 1 && on == 0)
  1117.         return; /* already locked and we're not unlocking */
  1118.  
  1119.     stopped = False; /* doesn't matter at this point; initialize */
  1120.     if (!cursor) /* make sure the timeout cursor is initialized */
  1121.         cursor = XCreateFontCursor(dpy, XC_watch);
  1122.  
  1123.     /* if "on" is true, then turn on watch cursor, otherwise, return
  1124.      * the shell's cursor to normal.
  1125.      */
  1126.     attrs.cursor = on? cursor : None;
  1127.  
  1128.     /* change the main application shell's cursor to be the timeout
  1129.      * cursor (or to reset it to normal).  If other shells exist in
  1130.      * this application, they will have to be listed here in order
  1131.      * for them to have timeout cursors too.
  1132.      */
  1133.     XChangeWindowAttributes(dpy, XtWindow(shell), CWCursor, &attrs);
  1134.  
  1135.     XFlush(dpy);
  1136.  
  1137.     if (on) {
  1138.         /* we're timing out, put up a WorkingDialog.  If the process
  1139.          * is interruptable, allow a "Stop" button.  Otherwise, remove
  1140.          * all actions so the user can't stop the processing.
  1141.          */
  1142.         str = XmStringCreateSimple("Busy.  Please Wait.");
  1143.         XtSetArg(args[0], XmNmessageString, str);
  1144.         dialog = XmCreateWorkingDialog(shell, "Busy", args, 1);
  1145.         XmStringFree(str);
  1146.         XtUnmanageChild(
  1147.             XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON));
  1148.         if (interruptable) {
  1149.             str = XmStringCreateSimple("Stop");
  1150.             XtVaSetValues(dialog, XmNcancelLabelString, str, NULL);
  1151.             XmStringFree(str);
  1152.             XtAddCallback(dialog, XmNcancelCallback, stop, NULL);
  1153.         } else
  1154.             XtUnmanageChild(
  1155.                 XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
  1156.         XtUnmanageChild(
  1157.             XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
  1158.         XtManageChild(dialog);
  1159.     } else {
  1160.         /* get rid of all button and keyboard events that occured
  1161.          * during the time out.  The user shouldn't have done anything
  1162.          * during this time, so flush for button and keypress events.
  1163.          * KeyRelease events are not discarded because accelerators
  1164.          * require the corresponding release event before normal input
  1165.          * can continue.
  1166.          */
  1167.         while (XCheckMaskEvent(dpy,
  1168.                 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
  1169.                 | PointerMotionMask | KeyPressMask, &event)) {
  1170.             /* do nothing */;
  1171.         }
  1172.         XtDestroyWidget(dialog);
  1173.     }
  1174. }
  1175.  
  1176. /* User Pressed the "Stop" button in dialog. */
  1177. void
  1178. stop(dialog)
  1179. Widget dialog;
  1180. {
  1181.     stopped = True;
  1182. }
  1183.  
  1184. Boolean
  1185. CheckForInterrupt()
  1186. {
  1187.     extern Widget shell;
  1188.     Display *dpy = XtDisplay(shell);
  1189.     Window win = XtWindow(dialog);
  1190.     XEvent event;
  1191.  
  1192.     /* Make sure all our requests get to the server */
  1193.     XFlush(dpy);
  1194.  
  1195.     /* Let motif process all pending exposure events for us. */
  1196.     XmUpdateDisplay(shell);
  1197.  
  1198.     /* Check the event loop for events in the dialog ("Stop"?) */
  1199.     while (XCheckMaskEvent(dpy,
  1200.             ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
  1201.             PointerMotionMask | KeyPressMask | KeyReleaseMask,
  1202.             &event)) {
  1203.         /* got an "interesting" event. */
  1204.         if (event.xany.window == win)
  1205.             XtDispatchEvent(&event); /* it's in our dialog.. */
  1206.         else /* uninteresting event--throw it away and sound bell */
  1207.             XBell(dpy, 50);
  1208.     }
  1209.     return stopped;
  1210. }
  1211.  
  1212.  
  1213. -----------------------------------------------------------------------------
  1214. Subject: 201)  Can I use the hourglass that mwm uses?
  1215.  
  1216. [Last modified: March 93]
  1217.  
  1218. Answer: The hourglass used by mwm is hard-coded into code that is subject to
  1219. OSF copyright. In Motif 1.2 though, the bitmaps for this and other things
  1220. (information, no_enter, question, warning, working) were made available.  The
  1221. install process will probably add them to /usr/include/X11/bitmaps.
  1222. Otherwise, just use the watch cursor XC_watch of the previous question,
  1223. because that has the same semantics.
  1224.  
  1225.  
  1226. -----------------------------------------------------------------------------
  1227. Subject: 202)  What order should the libraries be linked in?
  1228.  
  1229. [Last modified: August 92]
  1230.  
  1231. Answer: At link time, use the library order  -lXm -lXt -lX11. There are two
  1232. reasons for this (dbrooks@osf.org):
  1233.  
  1234. On most systems, the order matters because the linker won't re-scan a library
  1235. once it is done with it.  Thus any references to Xlib calls from Xm will
  1236. probably be unresolved.
  1237.  
  1238. The [other] problem is that there are two VendorShell widgets. A dummy is
  1239. provided in the Xt library, but a widget set will rely on its own being
  1240. referenced.  If you mention Xt first, the linker will choose the wrong one.
  1241.  
  1242. Motif code will wrongly assume the Motif VendorShell has been class-
  1243. initialized [and will probably crash].
  1244.  Xaw has a similar problem, but a softer landing; it only complains about
  1245. unregistered converters.
  1246.  
  1247.  
  1248. -----------------------------------------------------------------------------
  1249. Subject: 203)  How do I use xmkmf for Motif clients?
  1250.  
  1251. [Last modified: October 1992]
  1252.  
  1253. Answer: This advice comes from dbrooks@osf.org:
  1254.  
  1255. There are a number of intractable problems with using X configuration files
  1256. and xmkmf, while trying to make it easy to build Motif.  Not the least of
  1257. these, but one I've never heard mentioned yet, is that the rules for
  1258. contructing the names of shared library macros are machine-dependent, and in
  1259. the various xxxLib.tmpl files.  Do we edit all those files to add definitions
  1260. for XMLIB, DEPXMLIB, etc., or do we put a maze of #ifdefs into the Motif.tmpl
  1261. file?
  1262.  
  1263. Please note that, if you install Motif, it overwrites your installed
  1264. Imake.tmpl with one that includes Motif.tmpl and Motif.rules.
  1265.  
  1266. With those caveats, I think the following guidelines will help.
  1267.  
  1268. David Brooks OSF
  1269.  
  1270. Clients in the X11R5 release use the xmkmf command to build Makefiles.  In
  1271. general, the xmkmf command cannot be used for Motif clients, because of the
  1272. need to consider the UseInstalledMotif flag separately.  Since xmkmf is a
  1273. simple script that calls imake, it is easy to construct the proper call to
  1274. imake using the following rules.
  1275.  
  1276. In the following, replace {MTOP} by the toplevel directory with the Motif
  1277. source tree, and {XTOP} by the toplevel ("mit") directory with the X source.
  1278. It is assumed that the directory containing your installed imake is in your
  1279. PATH.
  1280.  
  1281. When needed, the imake variables XTop and MTop are normally set in your
  1282. site.def (to {XTOP} amd {MTOP} respectively); however they may also be set
  1283. with additional -D arguments to imake.
  1284.  
  1285. 1. With both X and Motif in their source trees, ensure the imake variables
  1286.    XTop and MTop are set, and use:
  1287.  
  1288.         ${XTOP}/config/imake -I{MTOP}/config
  1289.  
  1290. 2. With Motif in its source tree, and X installed, ensure MTop is set, and
  1291.    use:
  1292.  
  1293.         imake -I{MTOP}/config -DUseInstalled
  1294.  
  1295. 3. With both Motif and X installed, and a nonstandard ProjectRoot (see
  1296.    site.def for an explanation of this), use:
  1297.  
  1298.         imake -DUseInstalled -DUseInstalledMotif -I{ProjectRoot}/lib/X11/config
  1299.  
  1300.    or, if the configuration files are in /usr/lib/X11/config:
  1301.  
  1302.         imake -DUseInstalled -DUseInstalledMotif
  1303.  
  1304.  
  1305. To build a simple Imakefile, remember to include lines like this:
  1306.  
  1307.         LOCAL_LIBRARIES = XmClientLibs
  1308.                 DEPLIBS = XmClientDepLibs
  1309.  
  1310. Or, for a client that uses uil/mrm, replace these by MrmClientLibs and
  1311. MrmClientDepLibs, and also use:
  1312.  
  1313.         MSimpleUilTarget(program)
  1314.  
  1315. to build the client and uid file.  Look at the demos for more examples.
  1316.  
  1317.  
  1318. And Paul Howell <grue@engin.umich.edu> added:
  1319.  
  1320. i did this, calling the new script "xmmkmf".  It passes both -DUseInstalled
  1321. and -DUseInstalledMotif.
  1322.  
  1323. and i modified the stock R5 Imake.tmpl to do this:
  1324.  
  1325. #include <Project.tmpl>
  1326. #ifdef UseInstalledMotif
  1327. #include <Motif.tmpl>
  1328. #endif
  1329.  
  1330. #include <Imake.rules>
  1331. #ifdef UseInstalledMotif
  1332. #include <Motif.rules>
  1333. #endif
  1334.  
  1335. the result was something that does both athena and motif rules.  and it really
  1336. works, just that easy!
  1337.  
  1338.  
  1339. -----------------------------------------------------------------------------
  1340. Subject: 204)  How do I make context sensitive help?  The Motif Style Guide
  1341. says that an application must initiate context-sensitive help by changing the
  1342. shape of the pointer to the question pointer. When the user moves the pointer
  1343. to the component help is wanted on and presses BSelect, any available context
  1344. sensitive help for the component must be presented, and the pointer reverts
  1345. from the question pointer.
  1346. [Last modified: August 92]
  1347.  
  1348. Answer: A widget that gives context sensitive help would place this help in
  1349. the XmNhelpCallback function. To trigger this function: (from Martin G C
  1350. Davies, mgcd@se.alcbel.be)
  1351.  
  1352. I use the following callback that is called when the "On Context" help
  1353. pulldown menu is selected. It does the arrow bit and calls the help callbacks
  1354. for the widget. It also zips up the widget tree looking for help if needs be.
  1355. I don't restrict the arrows motion so I can get help on dialog boxes. No
  1356. prizes for guessing what "popup_message" does.
  1357.  
  1358.  
  1359. static void ContextHelp(
  1360.     Widget              w ,
  1361.     Opaque              * tag ,
  1362.     XmAnyCallbackStruct * callback_struct
  1363. )
  1364. {
  1365.     static Cursor   context_cursor = NULL ;
  1366.     Widget          context_widget ;
  1367.  
  1368.     if ( context_cursor == NULL )
  1369.         context_cursor = XCreateFontCursor( display, XC_question_arrow ) ;
  1370.  
  1371.     context_widget = XmTrackingLocate( top_level_widget,
  1372.                                 context_cursor, FALSE ) ;
  1373.  
  1374.     if ( context_widget != NULL ) /* otherwise its not a widget */
  1375.     {
  1376.         XmAnyCallbackStruct cb ;
  1377.  
  1378.         cb.reason = XmCR_HELP ;
  1379.         cb.event = callback_struct->event ;
  1380.  
  1381.         /*
  1382.          * If there's no help at this widget we'll track back
  1383.            up the hierarchy trying to find some.
  1384.          */
  1385.  
  1386.         do
  1387.         {
  1388.             if ( ( XtHasCallbacks( context_widget, XmNhelpCallback ) ==
  1389.                                                 XtCallbackHasSome ) )
  1390.             {
  1391.                 XtCallCallbacks( context_widget, XmNhelpCallback, & cb ) ;
  1392.                 return ;
  1393.             }
  1394.             else
  1395.                 context_widget = XtParent( context_widget ) ;
  1396.         } while ( context_widget != NULL ) ;
  1397.     }
  1398.  
  1399.     popup_message( "No context-sensitive help found\n\
  1400. for the selected object." ) ;
  1401. }
  1402.  
  1403.  
  1404. Dave Bonnett suggested, to use the following translations for XmText (and
  1405. XmTextField) widgets to get the same help with key strokes, and to provide an
  1406. accelerator label in the Context help menu entry.
  1407.  
  1408. MyApp*XmText*translations: #override\n\
  1409.                                 <Key>F1:    Help()
  1410.  
  1411. MyApp*Help_menu*Contextual Help.acceleratorText:   F1
  1412.  
  1413. MyApp*defaultVirtualBindings:           osfBackSpace : <Key>Delete\n\
  1414.                                         osfRight : <Key>Right\n\
  1415.                                         osfLeft  : <Key>Left\n\
  1416.                                         osfUp    : <Key>Up\n\
  1417.                                         osfHelp  : <Key>F1\n\
  1418.                                         osfDown  : <Key>Down
  1419.  
  1420.  
  1421. -----------------------------------------------------------------------------
  1422. Subject: 205)  How do I debug a modal interaction?
  1423.  
  1424. When an application crashes in a modal section (such as in a modal dialog, a
  1425. menu or when a drag and drop is in action), I cannot access the debugger.
  1426.  
  1427. [Last modified: January 1993]
  1428.  
  1429. Answer: Run the debugger on one display while the application writes to
  1430. another display.
  1431.  
  1432. -----------------------------------------------------------------------------
  1433. Subject: 206)* How can I disable Drag and Drop in my Motif 1.2 client ?
  1434.  
  1435. [Last modified: Oct 94]
  1436.  
  1437. Answer: Several people have reported that for complex hierarchies of widgets,
  1438. drag and drop can slow down an application considerably. If you do not need
  1439. drag and drop's significant power, you can disable it in your application.
  1440.  
  1441. Set the XmDisplay drag-protocol resources to XmDRAG_NONE.  The following code
  1442. fragment demonstrates this:
  1443.  
  1444. #include <Xm/Display.h>
  1445.  
  1446.  
  1447.     dw = XmGetXmDisplay(XtDisplay(shell));
  1448.     /* where "shell" is your client's top-level shell. */
  1449.  
  1450.     XtVaSetValues(dw, XmNdragInitiatorProtocolStyle, XmDRAG_NONE, NULL);
  1451.     XtVaSetValues(dw, XmNdragReceiverProtocolStyle,  XmDRAG_NONE, NULL);
  1452.  
  1453.  
  1454. thanks to Lance Purple (purple@austin.ibm.com)
  1455.  
  1456. Ken Lee (kenton@esd.sgi.com) and Christoph Widmer
  1457. (widmer@einsteinium.SLCS.SLB.COM) describe how to disable drag and drop from a
  1458. resource file:
  1459.  
  1460.         *dragInitiatorProtocolStyle: XmDRAG_NONE
  1461.         *dragReceiverProtocolStyle:  XmDRAG_NONE
  1462.  
  1463. Ken Lee also notes that as of Motif 1.2, the "Xm" prefix is required for all
  1464. token constants in resource files. (Which is why specifying "DRAG_NONE" won't
  1465. work but "XmDRAG_NONE" will.)
  1466.  
  1467. -----------------------------------------------------------------------------
  1468. Subject: 207)  Where can I get info on the Motif drag and drop protocol?
  1469.  
  1470. [Last modified: Sept 94]
  1471.  
  1472. Answer: The drag and drop protocol implemented by OSF is not stable, so they
  1473. have not published it yet. The API should remain stable though.  The OSF
  1474. protocol is not compatable with the OpenLook protocol.  OSF and Sun are
  1475. working on a joint protocol for publication.
  1476.  
  1477. For programming examples on Motif drag and drop, see the Motif 1.2 Programmers
  1478. Guide.
  1479.  
  1480. For a third alternative, try Roger Reynolds drag and drop protocol, available
  1481. from netcom.com in /pub/rogerr.
  1482.  
  1483. Ken Lee, kenton@esd.sgi.com writes: OSF's "Motif Programmers Guide" includes
  1484. complete source code for several drag and drop demos.  There are some simple
  1485. programs demonstrating the basic behaviour, as well as complex programs
  1486. demonstrating more sophisticated options.  I think the source code for some of
  1487. the demos also appears on the OSF tape.
  1488.  
  1489.  
  1490. -----------------------------------------------------------------------------
  1491. Subject: 208)  Why can't I install my own colormap using XInstallColormap?
  1492.  
  1493. [Last modified: Sept 94]
  1494.  
  1495. Answer: You shouldn't install the colormap yourself using XInstallColormap.
  1496. See the ICCCM document for all the reasons.  Instead put the colormap as an
  1497. argument on the Shell widget and the window manager will take care of this.
  1498.  
  1499. When the colormap is installed,  unless you have a display with multiple
  1500. colormaps, the other windows will go "technicolor" and there is no way around
  1501. this problem.
  1502.  
  1503. Thanks to Doug Rand <drand@osf.org>
  1504.  
  1505. -----------------------------------------------------------------------------
  1506. Subject: 209)  How do I get correct shadow colors to match other color
  1507. changes?
  1508.  
  1509. [Last modified: Sept 94]
  1510.  
  1511. Answer:
  1512.  
  1513. Thanks to Craig MacFarlane (craigm@chateau-rouge.ICS.UCI.EDU) for the
  1514. following explanation and code:
  1515.  
  1516. You have to make a call to calculate the new shadow colors.  The trick is
  1517. actually getting a value of type Pixel when all you have is the string "Blue".
  1518. I use the XtConvertAndStore() function to convert from a char * to a Pixel.
  1519. For example:
  1520.  
  1521.  
  1522.   char *color = "blue";
  1523.   XrmValue color_value, pixel_value;
  1524.   Pixel background;
  1525.  
  1526.   color_value.size = strlen(color);
  1527.   color_value.addr = (XtPointer) color;
  1528.   pixel_value.size = sizeof(Pixel);
  1529.   pixel_value.addr = (XtPointer) 0;
  1530.  
  1531.   result = XtConvertAndStore(widget,
  1532.                              XtRString, &color_value,
  1533.                              XtRPixel, &pixel_value);
  1534.  
  1535.   background = (*(Pixel *)pixel_value.addr);
  1536.  
  1537.  
  1538. You can then use the pixel value obtained by XtConvertAndStore() in the
  1539. XmGetColors call.  XmGetColors calculates appropriate foreground, topshadow,
  1540. bottomshadow, and select colors for the given background. e.g.
  1541.  
  1542.  
  1543.   XmGetColors(screen,
  1544.               DefaultColormap(display_id, DefaultScreen(display_id)),
  1545.               background,
  1546.               &foreground, &topshadow, &bottomshadow, &select);
  1547.  
  1548.  
  1549. From here it's trivial to set the shadow colors at the same time you set the
  1550. foreground and background colors.  For example:
  1551.  
  1552.  
  1553.   XtVaSetValues(widget,
  1554.                 XmNforeground, foreground,
  1555.                 XmNbackground, background,
  1556.                 XmNarmColor, select,
  1557.                 XmNtopShadowColor, topshadow,
  1558.                 XmNbottomShadowColor, bottomshadow,
  1559.                 NULL);
  1560.  
  1561.  
  1562. You'll get asthetically pleasing colors every time. :)
  1563.  
  1564. -----------------------------------------------------------------------------
  1565. Subject: 210)+ What color algorithm does Motif use?  I am told that Motif uses
  1566. some sort of algorithm that will take a single color that is defined for the
  1567. "background" and scale it so that the widget remains discriminable from the
  1568. background, etc.  What is the algorithm?
  1569.  
  1570. [Last modified: Oct 94]
  1571.  
  1572. Answer: Chris Flatters (cflatter@nrao.edu) writes: Shiz Kobara's book "Visual
  1573. Design with OSF/Motif", Addison Wesley,  1991, ISBN 0-201-56320-7) is a good
  1574. source for information of this sort.  I haven't seen it in bookshops for a
  1575. while so it may have gone out of print (which would be a pity).  In essence
  1576. each widget has 4 colours which, to first order, are
  1577.  
  1578.         background
  1579.         select          (background * 85%)
  1580.         top shadow      (background * 150%)
  1581.         bottom shadow   (background * 50%)
  1582.  
  1583. An additional correction may be applied to the hues of the calculated colours
  1584. if any of the RGB values saturates.  The algorithm works best if the brightest
  1585. of the RGB components lies in the range 155-175 (on a scale of 0-255).  The
  1586. top shadow becomes darker than the background for light background colours
  1587. which does not lead to a particularly pleasing effect.
  1588.  
  1589. -----------------------------------------------------------------------------
  1590. Subject: 211)+ How can you access the superclass widget from which Motif
  1591. convenience dialogs are subclassed?
  1592.  
  1593. [Last modified: Oct 94]
  1594.  
  1595. Answer: From Kim Frei (uunet!ask.uniras.dk!kimf): If you are using Motif 1.2,
  1596. read about XmTemplateDialog.
  1597.  
  1598. -----------------------------------------------------------------------------
  1599. Subject: 212)  TOPIC: HISTORY and ACKNOWLEDGEMENTS
  1600.  
  1601. Answer:
  1602.  
  1603. History:
  1604. -------
  1605. November 89 to July 93: FAQ was maintained by Jan Newmarch
  1606.                         (jan@ise.canberra.edu.au)
  1607.  
  1608. July 93 to August 94:   FAQ was maintained by Brian Dealy
  1609.                         (dealy@c3i.saic.com)
  1610.  
  1611. Acknowledgments:
  1612. ----------------
  1613. This list was compiled using questions and answers posed to
  1614. comp.windows.x.motif and motif-talk. Some information was excerpted from the
  1615. comp.windows.x FAQ.  To all who contributed one way or the other, thanks! We
  1616. haven't often given individual references, but you may recognize
  1617. contributions. If weve mangled them too much, let the current maintainer know.
  1618.  
  1619.  
  1620.   Jan Newmarch, Information Science and Engineering,
  1621.   University of Canberra, PO Box 1, Belconnen, Act 2616
  1622.   Australia. Tel: (Aust) 6-2522422. Fax: (Aust) 6-2522999
  1623.  
  1624.   ACSnet: jan@ise.canberra.edu.au
  1625.   ARPA:   jan%ise.canberra.edu.au@uunet.uu.net
  1626.   UUCP:   {uunet,ukc}!munnari!ise.canberra.edu.au!jan
  1627.   JANET:  jan%au.edu.canberra.ise@EAN-RELAY
  1628.  
  1629.  
  1630. Jan Newmarch maintained this FAQ for a long time and has really helped a great
  1631. many of us by providing this valuable service.  He deserves a big round of
  1632. applause for his efforts.  I use this resource all the time and it has saved
  1633. me countless hours with manuals and source code trying to relearn what others
  1634. have already discovered.  Jan`s efforts are gratefully acknowledged here.
  1635.  
  1636.  
  1637.   Brian Dealy, SAIC
  1638.   dealy@c3i.saic.com
  1639.  
  1640.  
  1641. Likewise, Brian Dealy of SAIC did an admirable job taking over the Motif FAQ
  1642. from Jan. A considerable amount of information was added during his tenure and
  1643. we greatly appreciate Brian's work on the FAQ, as well as his efforts in
  1644. maintaining the comp.windows.x.motif newsgroup reflector, for the good of all
  1645. Motif-dom.
  1646.  
  1647.  
  1648.   Ken Sall, Century Computing, Inc.
  1649.   ksall@cen.com
  1650.  
  1651.  
  1652.  
  1653.