lwlib-Xm.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959
  1. /* The lwlib interface to Motif widgets.
  2. Copyright (C) 1994-1997, 1999-2012 Free Software Foundation, Inc.
  3. Copyright (C) 1992 Lucid, Inc.
  4. This file is part of the Lucid Widget Library.
  5. The Lucid Widget Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9. The Lucid Widget Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Emacs; see the file COPYING. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA. */
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20. #include <unistd.h>
  21. #include <stdio.h>
  22. #include <setjmp.h>
  23. #include <X11/StringDefs.h>
  24. #include <X11/IntrinsicP.h>
  25. #include <X11/ObjectP.h>
  26. #include <X11/CoreP.h>
  27. #include <X11/CompositeP.h>
  28. #include <lisp.h>
  29. #include "lwlib-Xm.h"
  30. #include "lwlib-utils.h"
  31. #include <Xm/BulletinB.h>
  32. #include <Xm/CascadeB.h>
  33. #include <Xm/CascadeBG.h>
  34. #include <Xm/DrawingA.h>
  35. #include <Xm/FileSB.h>
  36. #include <Xm/Label.h>
  37. #include <Xm/List.h>
  38. #include <Xm/MainW.h>
  39. #include <Xm/MenuShell.h>
  40. #include <Xm/MessageB.h>
  41. #include <Xm/PanedW.h>
  42. #include <Xm/PushB.h>
  43. #include <Xm/PushBG.h>
  44. #include <Xm/ArrowB.h>
  45. #include <Xm/SelectioB.h>
  46. #include <Xm/Text.h>
  47. #include <Xm/TextF.h>
  48. #include <Xm/ToggleB.h>
  49. #include <Xm/ToggleBG.h>
  50. #include <Xm/RowColumn.h>
  51. #include <Xm/ScrolledW.h>
  52. #include <Xm/Separator.h>
  53. #include <Xm/DialogS.h>
  54. #include <Xm/Form.h>
  55. enum do_call_type { pre_activate, selection, no_selection, post_activate };
  56. /* Structures to keep destroyed instances */
  57. typedef struct _destroyed_instance
  58. {
  59. char* name;
  60. char* type;
  61. Widget widget;
  62. Widget parent;
  63. Boolean pop_up_p;
  64. struct _destroyed_instance* next;
  65. } destroyed_instance;
  66. static destroyed_instance *make_destroyed_instance (char *, char *,
  67. Widget, Widget,
  68. Boolean);
  69. static void free_destroyed_instance (destroyed_instance*);
  70. Widget first_child (Widget);
  71. Boolean lw_motif_widget_p (Widget);
  72. static XmString resource_motif_string (Widget, char *);
  73. static void destroy_all_children (Widget, int);
  74. static void xm_update_label (widget_instance *, Widget, widget_value *);
  75. static void xm_update_list (widget_instance *, Widget, widget_value *);
  76. static void xm_update_pushbutton (widget_instance *, Widget,
  77. widget_value *);
  78. static void xm_update_cascadebutton (widget_instance *, Widget,
  79. widget_value *);
  80. static void xm_update_toggle (widget_instance *, Widget, widget_value *);
  81. static void xm_update_radiobox (widget_instance *, Widget, widget_value *);
  82. static void make_menu_in_widget (widget_instance *, Widget,
  83. widget_value *, int);
  84. static void update_one_menu_entry (widget_instance *, Widget,
  85. widget_value *, Boolean);
  86. static void xm_update_menu (widget_instance *, Widget, widget_value *,
  87. Boolean);
  88. static void xm_update_text (widget_instance *, Widget, widget_value *);
  89. static void xm_update_text_field (widget_instance *, Widget,
  90. widget_value *);
  91. void xm_update_one_value (widget_instance *, Widget, widget_value *);
  92. static void activate_button (Widget, XtPointer, XtPointer);
  93. static Widget make_dialog (char *, Widget, Boolean, char *, char *,
  94. Boolean, Boolean, Boolean, int, int);
  95. static destroyed_instance* find_matching_instance (widget_instance*);
  96. static void mark_dead_instance_destroyed (Widget, XtPointer, XtPointer);
  97. static void recenter_widget (Widget);
  98. static Widget recycle_instance (destroyed_instance*);
  99. Widget xm_create_dialog (widget_instance*);
  100. static Widget make_menubar (widget_instance*);
  101. static void remove_grabs (Widget, XtPointer, XtPointer);
  102. static Widget make_popup_menu (widget_instance*);
  103. static Widget make_main (widget_instance*);
  104. void xm_destroy_instance (widget_instance*);
  105. void xm_popup_menu (Widget, XEvent *);
  106. static void set_min_dialog_size (Widget);
  107. static void do_call (Widget, XtPointer, enum do_call_type);
  108. static void xm_generic_callback (Widget, XtPointer, XtPointer);
  109. static void xm_nosel_callback (Widget, XtPointer, XtPointer);
  110. static void xm_pull_down_callback (Widget, XtPointer, XtPointer);
  111. static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
  112. void xm_set_keyboard_focus (Widget, Widget);
  113. void xm_set_main_areas (Widget, Widget, Widget);
  114. static void xm_internal_update_other_instances (Widget, XtPointer,
  115. XtPointer);
  116. static void xm_arm_callback (Widget, XtPointer, XtPointer);
  117. #if 0
  118. void xm_update_one_widget (widget_instance *, Widget, widget_value *,
  119. Boolean);
  120. void xm_pop_instance (widget_instance*, Boolean);
  121. void xm_manage_resizing (Widget, Boolean);
  122. #endif
  123. #if 0
  124. /* Print the complete X resource name of widget WIDGET to stderr.
  125. This is sometimes handy to have available. */
  126. void
  127. x_print_complete_resource_name (Widget widget)
  128. {
  129. int i;
  130. String names[100];
  131. for (i = 0; i < 100 && widget != NULL; ++i)
  132. {
  133. names[i] = XtName (widget);
  134. widget = XtParent (widget);
  135. }
  136. for (--i; i >= 1; --i)
  137. fprintf (stderr, "%s.", names[i]);
  138. fprintf (stderr, "%s\n", names[0]);
  139. }
  140. #endif /* 0 */
  141. static destroyed_instance *all_destroyed_instances = NULL;
  142. static destroyed_instance*
  143. make_destroyed_instance (char* name,
  144. char* type,
  145. Widget widget,
  146. Widget parent,
  147. Boolean pop_up_p)
  148. {
  149. destroyed_instance* instance =
  150. (destroyed_instance*) xmalloc (sizeof (destroyed_instance));
  151. instance->name = safe_strdup (name);
  152. instance->type = safe_strdup (type);
  153. instance->widget = widget;
  154. instance->parent = parent;
  155. instance->pop_up_p = pop_up_p;
  156. instance->next = NULL;
  157. return instance;
  158. }
  159. static void
  160. free_destroyed_instance (destroyed_instance* instance)
  161. {
  162. xfree (instance->name);
  163. xfree (instance->type);
  164. xfree (instance);
  165. }
  166. /* motif utility functions */
  167. Widget
  168. first_child (Widget widget)
  169. {
  170. return ((CompositeWidget)widget)->composite.children [0];
  171. }
  172. Boolean
  173. lw_motif_widget_p (Widget widget)
  174. {
  175. return
  176. XtClass (widget) == xmDialogShellWidgetClass
  177. || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
  178. }
  179. static XmString
  180. resource_motif_string (Widget widget,
  181. char* name)
  182. {
  183. XtResource resource;
  184. XmString result = 0;
  185. resource.resource_name = name;
  186. resource.resource_class = XmCXmString;
  187. resource.resource_type = XmRXmString;
  188. resource.resource_size = sizeof (XmString);
  189. resource.resource_offset = 0;
  190. resource.default_type = XtRImmediate;
  191. resource.default_addr = 0;
  192. XtGetSubresources (widget, (XtPointer)&result, "dialogString",
  193. "DialogString", &resource, 1, NULL, 0);
  194. return result;
  195. }
  196. /* Destroy all of the children of WIDGET
  197. starting with number FIRST_CHILD_TO_DESTROY. */
  198. static void
  199. destroy_all_children (Widget widget,
  200. int first_child_to_destroy)
  201. {
  202. Widget* children;
  203. unsigned int number;
  204. int i;
  205. children = XtCompositeChildren (widget, &number);
  206. if (children)
  207. {
  208. XtUnmanageChildren (children + first_child_to_destroy,
  209. number - first_child_to_destroy);
  210. /* Unmanage all children and destroy them. They will only be
  211. really destroyed when we get out of DispatchEvent. */
  212. for (i = first_child_to_destroy; i < number; i++)
  213. {
  214. Arg al[2];
  215. Widget submenu = 0;
  216. /* Cascade buttons have submenus,and these submenus
  217. need to be freed. But they are not included in
  218. XtCompositeChildren. So get it out of the cascade button
  219. and free it. If this child is not a cascade button,
  220. then submenu should remain unchanged. */
  221. XtSetArg (al[0], XmNsubMenuId, &submenu);
  222. XtGetValues (children[i], al, 1);
  223. if (submenu)
  224. {
  225. destroy_all_children (submenu, 0);
  226. XtDestroyWidget (submenu);
  227. }
  228. XtDestroyWidget (children[i]);
  229. }
  230. XtFree ((char *) children);
  231. }
  232. }
  233. /* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
  234. menu. CLIENT_DATA contains a pointer to the widget_value
  235. corresponding to widget W. CALL_DATA contains a
  236. XmPushButtonCallbackStruct containing the reason why the callback
  237. is called. */
  238. static void
  239. xm_arm_callback (Widget w, XtPointer client_data, XtPointer call_data)
  240. {
  241. XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *) call_data;
  242. widget_value *wv = (widget_value *) client_data;
  243. widget_instance *instance;
  244. /* Get the id of the menu bar or popup menu this widget is in. */
  245. while (w != NULL)
  246. {
  247. if (XmIsRowColumn (w))
  248. {
  249. unsigned char type = 0xff;
  250. XtVaGetValues (w, XmNrowColumnType, &type, NULL);
  251. if (type == XmMENU_BAR || type == XmMENU_POPUP)
  252. break;
  253. }
  254. w = XtParent (w);
  255. }
  256. if (w != NULL)
  257. {
  258. instance = lw_get_widget_instance (w);
  259. if (instance && instance->info->highlight_cb)
  260. {
  261. call_data = cbs->reason == XmCR_DISARM ? NULL : wv;
  262. instance->info->highlight_cb (w, instance->info->id, call_data);
  263. }
  264. }
  265. }
  266. /* Update the label of widget WIDGET. WIDGET must be a Label widget
  267. or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
  268. the value to update.
  269. Menus:
  270. Emacs fills VAL->name with the text to display in the menu, and
  271. sets VAL->value to null. Function make_menu_in_widget creates
  272. widgets with VAL->name as resource name. This works because the
  273. Label widget uses its resource name for display if no
  274. XmNlabelString is set.
  275. Dialogs:
  276. VAL->name is again set to the resource name, but VAL->value is
  277. not null, and contains the label string to display. */
  278. static void
  279. xm_update_label (widget_instance* instance,
  280. Widget widget,
  281. widget_value* val)
  282. {
  283. XmString res_string = 0;
  284. XmString built_string = 0;
  285. XmString key_string = 0;
  286. Arg al [256];
  287. int ac;
  288. ac = 0;
  289. if (val->value)
  290. {
  291. /* A label string is specified, i.e. we are in a dialog. First
  292. see if it is overridden by something from the resource file. */
  293. res_string = resource_motif_string (widget, val->value);
  294. if (res_string)
  295. {
  296. XtSetArg (al [ac], XmNlabelString, res_string); ac++;
  297. }
  298. else
  299. {
  300. built_string =
  301. XmStringCreateLocalized (val->value);
  302. XtSetArg (al [ac], XmNlabelString, built_string); ac++;
  303. }
  304. XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
  305. }
  306. if (val->key)
  307. {
  308. key_string = XmStringCreateLocalized (val->key);
  309. XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
  310. }
  311. if (ac)
  312. XtSetValues (widget, al, ac);
  313. if (built_string)
  314. XmStringFree (built_string);
  315. if (key_string)
  316. XmStringFree (key_string);
  317. }
  318. /* update of list */
  319. static void
  320. xm_update_list (widget_instance* instance,
  321. Widget widget,
  322. widget_value* val)
  323. {
  324. widget_value* cur;
  325. int i;
  326. XtRemoveAllCallbacks (widget, XmNsingleSelectionCallback);
  327. XtAddCallback (widget, XmNsingleSelectionCallback, xm_generic_callback,
  328. instance);
  329. for (cur = val->contents, i = 0; cur; cur = cur->next)
  330. if (cur->value)
  331. {
  332. XmString xmstr = XmStringCreateLocalized (cur->value);
  333. i += 1;
  334. XmListAddItem (widget, xmstr, 0);
  335. if (cur->selected)
  336. XmListSelectPos (widget, i, False);
  337. XmStringFree (xmstr);
  338. }
  339. }
  340. /* update of buttons */
  341. static void
  342. xm_update_pushbutton (widget_instance* instance,
  343. Widget widget,
  344. widget_value* val)
  345. {
  346. XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, NULL);
  347. XtRemoveAllCallbacks (widget, XmNactivateCallback);
  348. XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
  349. }
  350. static void
  351. xm_update_cascadebutton (widget_instance* instance,
  352. Widget widget,
  353. widget_value* val)
  354. {
  355. /* Should also rebuild the menu by calling ...update_menu... */
  356. XtRemoveAllCallbacks (widget, XmNcascadingCallback);
  357. XtAddCallback (widget, XmNcascadingCallback, xm_pull_down_callback,
  358. instance);
  359. }
  360. /* update toggle and radiobox */
  361. static void
  362. xm_update_toggle (widget_instance* instance,
  363. Widget widget,
  364. widget_value* val)
  365. {
  366. XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
  367. XtAddCallback (widget, XmNvalueChangedCallback,
  368. xm_generic_callback, instance);
  369. XtVaSetValues (widget, XmNset, val->selected,
  370. XmNalignment, XmALIGNMENT_BEGINNING, NULL);
  371. }
  372. static void
  373. xm_update_radiobox (widget_instance* instance,
  374. Widget widget,
  375. widget_value* val)
  376. {
  377. Widget toggle;
  378. widget_value* cur;
  379. /* update the callback */
  380. XtRemoveAllCallbacks (widget, XmNentryCallback);
  381. XtAddCallback (widget, XmNentryCallback, xm_generic_callback, instance);
  382. /* first update all the toggles */
  383. /* Energize kernel interface is currently bad. It sets the selected widget
  384. with the selected flag but returns it by its name. So we currently
  385. have to support both setting the selection with the selected slot
  386. of val contents and setting it with the "value" slot of val. The latter
  387. has a higher priority. This to be removed when the kernel is fixed. */
  388. for (cur = val->contents; cur; cur = cur->next)
  389. {
  390. toggle = XtNameToWidget (widget, cur->value);
  391. if (toggle)
  392. {
  393. XtSetSensitive (toggle, cur->enabled);
  394. if (!val->value && cur->selected)
  395. XtVaSetValues (toggle, XmNset, cur->selected, NULL);
  396. if (val->value && strcmp (val->value, cur->value))
  397. XtVaSetValues (toggle, XmNset, False, NULL);
  398. }
  399. }
  400. /* The selected was specified by the value slot */
  401. if (val->value)
  402. {
  403. toggle = XtNameToWidget (widget, val->value);
  404. if (toggle)
  405. XtVaSetValues (toggle, XmNset, True, NULL);
  406. }
  407. }
  408. /* update a popup menu, pulldown menu or a menubar */
  409. /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
  410. static void
  411. make_menu_in_widget (widget_instance* instance,
  412. Widget widget,
  413. widget_value* val,
  414. int keep_first_children)
  415. {
  416. Widget* children = 0;
  417. int num_children;
  418. int child_index;
  419. widget_value* cur;
  420. Widget button = 0;
  421. Widget title = 0;
  422. Widget menu;
  423. Arg al [256];
  424. int ac;
  425. Boolean menubar_p;
  426. unsigned char type;
  427. Widget* old_children;
  428. unsigned int old_num_children;
  429. /* Disable drag and drop for labels in menu bar. */
  430. static char overrideTrans[] = "<Btn2Down>: Noop()";
  431. XtTranslations override = XtParseTranslationTable (overrideTrans);
  432. old_children = XtCompositeChildren (widget, &old_num_children);
  433. /* Allocate the children array */
  434. for (num_children = 0, cur = val; cur; num_children++, cur = cur->next)
  435. ;
  436. children = (Widget*)(void*)XtMalloc (num_children * sizeof (Widget));
  437. /* WIDGET should be a RowColumn. */
  438. if (!XmIsRowColumn (widget))
  439. abort ();
  440. /* Determine whether WIDGET is a menu bar. */
  441. type = -1;
  442. XtSetArg (al[0], XmNrowColumnType, &type);
  443. XtGetValues (widget, al, 1);
  444. if (type != XmMENU_BAR && type != XmMENU_PULLDOWN && type != XmMENU_POPUP)
  445. abort ();
  446. menubar_p = type == XmMENU_BAR;
  447. /* Add a callback to popups and pulldowns that is called when
  448. it is made invisible again. */
  449. if (!menubar_p)
  450. XtAddCallback (XtParent (widget), XmNpopdownCallback,
  451. xm_pop_down_callback, (XtPointer)instance);
  452. /* Preserve the first KEEP_FIRST_CHILDREN old children. */
  453. for (child_index = 0, cur = val; child_index < keep_first_children;
  454. child_index++, cur = cur->next)
  455. children[child_index] = old_children[child_index];
  456. /* Check that those are all we have
  457. (the caller should have deleted the rest). */
  458. if (old_num_children != keep_first_children)
  459. abort ();
  460. /* Create the rest. */
  461. for (child_index = keep_first_children; cur; child_index++, cur = cur->next)
  462. {
  463. enum menu_separator separator;
  464. ac = 0;
  465. XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++;
  466. XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
  467. XtSetArg (al[ac], XmNuserData, cur->call_data); ac++;
  468. if (instance->pop_up_p && !cur->contents && !cur->call_data
  469. && !lw_separator_p (cur->name, &separator, 1))
  470. {
  471. ac = 0;
  472. XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
  473. title = button = XmCreateLabel (widget, cur->name, al, ac);
  474. }
  475. else if (lw_separator_p (cur->name, &separator, 1))
  476. {
  477. ac = 0;
  478. XtSetArg (al[ac], XmNseparatorType, separator); ++ac;
  479. button = XmCreateSeparator (widget, cur->name, al, ac);
  480. }
  481. else if (!cur->contents)
  482. {
  483. if (menubar_p)
  484. button = XmCreateCascadeButton (widget, cur->name, al, ac);
  485. else if (!cur->call_data)
  486. button = XmCreateLabel (widget, cur->name, al, ac);
  487. else if (cur->button_type == BUTTON_TYPE_TOGGLE
  488. || cur->button_type == BUTTON_TYPE_RADIO)
  489. {
  490. XtSetArg (al[ac], XmNset, cur->selected); ++ac;
  491. XtSetArg (al[ac], XmNvisibleWhenOff, True); ++ac;
  492. XtSetArg (al[ac], XmNindicatorType,
  493. (cur->button_type == BUTTON_TYPE_TOGGLE
  494. ? XmN_OF_MANY : XmONE_OF_MANY));
  495. ++ac;
  496. button = XmCreateToggleButton (widget, cur->name, al, ac);
  497. XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
  498. XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
  499. }
  500. else
  501. {
  502. button = XmCreatePushButton (widget, cur->name, al, ac);
  503. XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
  504. XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
  505. }
  506. xm_update_label (instance, button, cur);
  507. /* Add a callback that is called when the button is
  508. selected. Toggle buttons don't support
  509. XmNactivateCallback, we use XmNvalueChangedCallback in
  510. that case. Don't add a callback to a simple label. */
  511. if (cur->button_type)
  512. xm_update_toggle (instance, button, cur);
  513. else if (cur->call_data)
  514. XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
  515. (XtPointer)instance);
  516. }
  517. else
  518. {
  519. menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0);
  520. make_menu_in_widget (instance, menu, cur->contents, 0);
  521. XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
  522. button = XmCreateCascadeButton (widget, cur->name, al, ac);
  523. xm_update_label (instance, button, cur);
  524. XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
  525. (XtPointer)instance);
  526. XtOverrideTranslations (button, override);
  527. }
  528. children[child_index] = button;
  529. }
  530. /* Last entry is the help button. The original comment read "Has to
  531. be done after managing the buttons otherwise the menubar is only
  532. 4 pixels high." This is no longer true, and to make
  533. XmNmenuHelpWidget work, we need to set it before managing the
  534. children.. --gerd. */
  535. if (button)
  536. XtVaSetValues (widget, XmNmenuHelpWidget, button, NULL);
  537. if (num_children)
  538. XtManageChildren (children, num_children);
  539. XtFree ((char *) children);
  540. if (old_children)
  541. XtFree ((char *) old_children);
  542. }
  543. static void
  544. update_one_menu_entry (widget_instance* instance,
  545. Widget widget,
  546. widget_value* val,
  547. Boolean deep_p)
  548. {
  549. Arg al [256];
  550. int ac;
  551. Widget menu;
  552. widget_value* contents;
  553. if (val->this_one_change == NO_CHANGE)
  554. return;
  555. /* update the sensitivity and userdata */
  556. /* Common to all widget types */
  557. XtSetSensitive (widget, val->enabled);
  558. XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
  559. /* update the menu button as a label. */
  560. if (val->this_one_change >= VISIBLE_CHANGE)
  561. {
  562. xm_update_label (instance, widget, val);
  563. if (val->button_type)
  564. xm_update_toggle (instance, widget, val);
  565. }
  566. /* update the pulldown/pullaside as needed */
  567. ac = 0;
  568. menu = NULL;
  569. XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
  570. XtGetValues (widget, al, ac);
  571. contents = val->contents;
  572. if (!menu)
  573. {
  574. if (contents)
  575. {
  576. unsigned int old_num_children, i;
  577. Widget parent;
  578. Widget *widget_list;
  579. parent = XtParent (widget);
  580. widget_list = XtCompositeChildren (parent, &old_num_children);
  581. /* Find the widget position within the parent's widget list. */
  582. for (i = 0; i < old_num_children; i++)
  583. if (strcmp (XtName (widget_list[i]), XtName (widget)) == 0)
  584. break;
  585. if (i == old_num_children)
  586. abort ();
  587. if (XmIsCascadeButton (widget_list[i]))
  588. {
  589. menu = XmCreatePulldownMenu (parent, XtName(widget), NULL, 0);
  590. make_menu_in_widget (instance, menu, contents, 0);
  591. ac = 0;
  592. XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
  593. XtSetValues (widget, al, ac);
  594. }
  595. else
  596. {
  597. Widget button;
  598. /* The current menuitem is a XmPushButtonGadget, it
  599. needs to be replaced by a CascadeButtonGadget */
  600. XtDestroyWidget (widget_list[i]);
  601. menu = XmCreatePulldownMenu (parent, val->name, NULL, 0);
  602. make_menu_in_widget (instance, menu, contents, 0);
  603. ac = 0;
  604. XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
  605. /* Non-zero values don't work reliably in
  606. conjunction with Emacs' event loop */
  607. XtSetArg (al [ac], XmNmappingDelay, 0); ac++;
  608. #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
  609. /* Tell Motif to put it in the right place */
  610. XtSetArg (al [ac], XmNpositionIndex , i); ac++;
  611. #endif
  612. button = XmCreateCascadeButton (parent, val->name, al, ac);
  613. xm_update_label (instance, button, val);
  614. XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
  615. (XtPointer)instance);
  616. XtManageChild (button);
  617. }
  618. if (widget_list)
  619. XtFree ((char*) widget_list);
  620. }
  621. }
  622. else if (!contents)
  623. {
  624. ac = 0;
  625. XtSetArg (al [ac], XmNsubMenuId, NULL); ac++;
  626. XtSetValues (widget, al, ac);
  627. XtDestroyWidget (menu);
  628. }
  629. else if (deep_p && contents->change != NO_CHANGE)
  630. xm_update_menu (instance, menu, val, 1);
  631. }
  632. static void
  633. xm_update_menu (widget_instance* instance,
  634. Widget widget,
  635. widget_value* val,
  636. Boolean deep_p)
  637. {
  638. Widget* children;
  639. unsigned int num_children;
  640. int num_children_to_keep = 0;
  641. int i;
  642. widget_value* cur;
  643. children = XtCompositeChildren (widget, &num_children);
  644. /* Widget is a RowColumn widget whose contents have to be updated
  645. * to reflect the list of items in val->contents */
  646. /* See how many buttons we can keep, and how many we
  647. must completely replace. */
  648. if (val->contents == 0)
  649. num_children_to_keep = 0;
  650. else if (val->contents->change == STRUCTURAL_CHANGE)
  651. {
  652. if (children)
  653. {
  654. for (i = 0, cur = val->contents;
  655. (i < num_children
  656. && cur); /* how else to ditch unwanted children ?? - mgd */
  657. i++, cur = cur->next)
  658. {
  659. if (cur->this_one_change == STRUCTURAL_CHANGE)
  660. break;
  661. }
  662. num_children_to_keep = i;
  663. }
  664. }
  665. else
  666. num_children_to_keep = num_children;
  667. /* Update all the buttons of the RowColumn, in order,
  668. except for those we are going to replace entirely. */
  669. if (children)
  670. {
  671. for (i = 0, cur = val->contents; i < num_children_to_keep; i++)
  672. {
  673. if (!cur)
  674. {
  675. num_children_to_keep = i;
  676. break;
  677. }
  678. if (children [i]->core.being_destroyed
  679. || strcmp (XtName (children [i]), cur->name))
  680. continue;
  681. update_one_menu_entry (instance, children [i], cur, deep_p);
  682. cur = cur->next;
  683. }
  684. }
  685. /* Now replace from scratch all the buttons after the last
  686. place that the top-level structure changed. */
  687. if (val->contents && val->contents->change == STRUCTURAL_CHANGE)
  688. {
  689. destroy_all_children (widget, num_children_to_keep);
  690. make_menu_in_widget (instance, widget, val->contents,
  691. num_children_to_keep);
  692. }
  693. XtFree ((char *) children);
  694. }
  695. /* update text widgets */
  696. static void
  697. xm_update_text (widget_instance* instance,
  698. Widget widget,
  699. widget_value* val)
  700. {
  701. XmTextSetString (widget, val->value ? val->value : "");
  702. XtRemoveAllCallbacks (widget, XmNactivateCallback);
  703. XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
  704. XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
  705. XtAddCallback (widget, XmNvalueChangedCallback,
  706. xm_internal_update_other_instances, instance);
  707. }
  708. static void
  709. xm_update_text_field (widget_instance* instance,
  710. Widget widget,
  711. widget_value* val)
  712. {
  713. XmTextFieldSetString (widget, val->value ? val->value : "");
  714. XtRemoveAllCallbacks (widget, XmNactivateCallback);
  715. XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
  716. XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
  717. XtAddCallback (widget, XmNvalueChangedCallback,
  718. xm_internal_update_other_instances, instance);
  719. }
  720. /* update a motif widget */
  721. void
  722. xm_update_one_widget (widget_instance* instance,
  723. Widget widget,
  724. widget_value* val,
  725. Boolean deep_p)
  726. {
  727. WidgetClass class;
  728. /* Mark as not edited */
  729. val->edited = False;
  730. /* Common to all widget types */
  731. XtSetSensitive (widget, val->enabled);
  732. XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
  733. /* Common to all label like widgets */
  734. if (XtIsSubclass (widget, xmLabelWidgetClass))
  735. xm_update_label (instance, widget, val);
  736. class = XtClass (widget);
  737. /* Class specific things */
  738. if (class == xmPushButtonWidgetClass ||
  739. class == xmArrowButtonWidgetClass)
  740. {
  741. xm_update_pushbutton (instance, widget, val);
  742. }
  743. else if (class == xmCascadeButtonWidgetClass)
  744. {
  745. xm_update_cascadebutton (instance, widget, val);
  746. }
  747. else if (class == xmToggleButtonWidgetClass
  748. || class == xmToggleButtonGadgetClass)
  749. {
  750. xm_update_toggle (instance, widget, val);
  751. }
  752. else if (class == xmRowColumnWidgetClass)
  753. {
  754. Boolean radiobox = 0;
  755. int ac = 0;
  756. Arg al [1];
  757. XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
  758. XtGetValues (widget, al, ac);
  759. if (radiobox)
  760. xm_update_radiobox (instance, widget, val);
  761. else
  762. xm_update_menu (instance, widget, val, deep_p);
  763. }
  764. else if (class == xmTextWidgetClass)
  765. {
  766. xm_update_text (instance, widget, val);
  767. }
  768. else if (class == xmTextFieldWidgetClass)
  769. {
  770. xm_update_text_field (instance, widget, val);
  771. }
  772. else if (class == xmListWidgetClass)
  773. {
  774. xm_update_list (instance, widget, val);
  775. }
  776. }
  777. /* getting the value back */
  778. void
  779. xm_update_one_value (widget_instance* instance,
  780. Widget widget,
  781. widget_value* val)
  782. {
  783. WidgetClass class = XtClass (widget);
  784. widget_value *old_wv;
  785. /* copy the call_data slot into the "return" widget_value */
  786. for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next)
  787. if (!strcmp (val->name, old_wv->name))
  788. {
  789. val->call_data = old_wv->call_data;
  790. break;
  791. }
  792. if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
  793. {
  794. XtVaGetValues (widget, XmNset, &val->selected, NULL);
  795. val->edited = True;
  796. }
  797. else if (class == xmTextWidgetClass)
  798. {
  799. xfree (val->value);
  800. val->value = XmTextGetString (widget);
  801. val->edited = True;
  802. }
  803. else if (class == xmTextFieldWidgetClass)
  804. {
  805. xfree (val->value);
  806. val->value = XmTextFieldGetString (widget);
  807. val->edited = True;
  808. }
  809. else if (class == xmRowColumnWidgetClass)
  810. {
  811. Boolean radiobox = 0;
  812. int ac = 0;
  813. Arg al [1];
  814. XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
  815. XtGetValues (widget, al, ac);
  816. if (radiobox)
  817. {
  818. CompositeWidget radio = (CompositeWidget)widget;
  819. int i;
  820. for (i = 0; i < radio->composite.num_children; i++)
  821. {
  822. int set = False;
  823. Widget toggle = radio->composite.children [i];
  824. XtVaGetValues (toggle, XmNset, &set, NULL);
  825. if (set)
  826. {
  827. xfree (val->value);
  828. val->value = safe_strdup (XtName (toggle));
  829. }
  830. }
  831. val->edited = True;
  832. }
  833. }
  834. else if (class == xmListWidgetClass)
  835. {
  836. int pos_cnt;
  837. int* pos_list;
  838. if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt))
  839. {
  840. int i;
  841. widget_value* cur;
  842. for (cur = val->contents, i = 0; cur; cur = cur->next)
  843. if (cur->value)
  844. {
  845. int j;
  846. cur->selected = False;
  847. i += 1;
  848. for (j = 0; j < pos_cnt; j++)
  849. if (pos_list [j] == i)
  850. {
  851. cur->selected = True;
  852. val->value = safe_strdup (cur->name);
  853. }
  854. }
  855. val->edited = 1;
  856. XtFree ((char *) pos_list);
  857. }
  858. }
  859. }
  860. /* This function is for activating a button from a program. It's wrong because
  861. we pass a NULL argument in the call_data which is not Motif compatible.
  862. This is used from the XmNdefaultAction callback of the List widgets to
  863. have a double-click put down a dialog box like the button would do.
  864. I could not find a way to do that with accelerators.
  865. */
  866. static void
  867. activate_button (Widget widget,
  868. XtPointer closure,
  869. XtPointer call_data)
  870. {
  871. Widget button = (Widget)closure;
  872. XtCallCallbacks (button, XmNactivateCallback, NULL);
  873. }
  874. /* creation functions */
  875. /* Called for key press in dialogs. Used to pop down dialog on ESC. */
  876. static void
  877. dialog_key_cb (Widget widget,
  878. XtPointer closure,
  879. XEvent *event,
  880. Boolean *continue_to_dispatch)
  881. {
  882. KeySym sym = 0;
  883. Modifiers modif_ret;
  884. XtTranslateKeycode (event->xkey.display, event->xkey.keycode, 0,
  885. &modif_ret, &sym);
  886. if (sym == osfXK_Cancel)
  887. {
  888. Widget w = *((Widget *) closure);
  889. while (w && ! XtIsShell (w))
  890. w = XtParent (w);
  891. if (XtIsShell (w)) XtPopdown (w);
  892. }
  893. *continue_to_dispatch = TRUE;
  894. }
  895. /* dialogs */
  896. static Widget
  897. make_dialog (char* name,
  898. Widget parent,
  899. Boolean pop_up_p,
  900. char* shell_title,
  901. char* icon_name,
  902. Boolean text_input_slot,
  903. Boolean radio_box,
  904. Boolean list,
  905. int left_buttons,
  906. int right_buttons)
  907. {
  908. Widget result;
  909. Widget form;
  910. Widget row;
  911. Widget icon;
  912. Widget icon_separator;
  913. Widget message_label;
  914. Widget value = 0;
  915. Widget separator;
  916. Widget button = 0;
  917. Widget children [16]; /* for the final XtManageChildren */
  918. int n_children;
  919. Arg al[64]; /* Arg List */
  920. int ac; /* Arg Count */
  921. int i;
  922. if (pop_up_p)
  923. {
  924. ac = 0;
  925. XtSetArg(al[ac], XmNtitle, shell_title); ac++;
  926. XtSetArg(al[ac], XtNallowShellResize, True); ac++;
  927. XtSetArg(al[ac], XmNdeleteResponse, XmUNMAP); ac++;
  928. result = XmCreateDialogShell (parent, "dialog", al, ac);
  929. ac = 0;
  930. XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
  931. /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
  932. XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  933. form = XmCreateForm (result, shell_title, al, ac);
  934. }
  935. else
  936. {
  937. ac = 0;
  938. XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
  939. XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  940. form = XmCreateForm (parent, shell_title, al, ac);
  941. result = form;
  942. }
  943. n_children = left_buttons + right_buttons + 1;
  944. ac = 0;
  945. XtSetArg(al[ac], XmNpacking, n_children == 3?
  946. XmPACK_COLUMN: XmPACK_TIGHT); ac++;
  947. XtSetArg(al[ac], XmNorientation, n_children == 3?
  948. XmVERTICAL: XmHORIZONTAL); ac++;
  949. XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
  950. XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
  951. XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
  952. XtSetArg(al[ac], XmNspacing, 13); ac++;
  953. XtSetArg(al[ac], XmNadjustLast, False); ac++;
  954. XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
  955. XtSetArg(al[ac], XmNisAligned, True); ac++;
  956. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  957. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
  958. XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  959. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  960. XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  961. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  962. XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  963. row = XmCreateRowColumn (form, "row", al, ac);
  964. n_children = 0;
  965. for (i = 0; i < left_buttons; i++)
  966. {
  967. char button_name [16];
  968. sprintf (button_name, "button%d", i + 1);
  969. ac = 0;
  970. if (i == 0)
  971. {
  972. XtSetArg(al[ac], XmNhighlightThickness, 1); ac++;
  973. XtSetArg(al[ac], XmNshowAsDefault, TRUE); ac++;
  974. }
  975. XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
  976. XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  977. children [n_children] = XmCreatePushButton (row, button_name, al, ac);
  978. XtAddEventHandler (children [n_children],
  979. KeyPressMask, False, dialog_key_cb, result);
  980. if (i == 0)
  981. {
  982. button = children [n_children];
  983. ac = 0;
  984. XtSetArg(al[ac], XmNdefaultButton, button); ac++;
  985. XtSetValues (row, al, ac);
  986. }
  987. n_children++;
  988. }
  989. /* invisible separator button */
  990. ac = 0;
  991. XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
  992. children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
  993. n_children++;
  994. for (i = 0; i < right_buttons; i++)
  995. {
  996. char button_name [16];
  997. sprintf (button_name, "button%d", left_buttons + i + 1);
  998. ac = 0;
  999. XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
  1000. XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  1001. children [n_children] = XmCreatePushButton (row, button_name, al, ac);
  1002. XtAddEventHandler (children [n_children],
  1003. KeyPressMask, False, dialog_key_cb, result);
  1004. if (! button) button = children [n_children];
  1005. n_children++;
  1006. }
  1007. XtManageChildren (children, n_children);
  1008. ac = 0;
  1009. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1010. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1011. XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1012. XtSetArg(al[ac], XmNbottomWidget, row); ac++;
  1013. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  1014. XtSetArg(al[ac], XmNleftOffset, 0); ac++;
  1015. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1016. XtSetArg(al[ac], XmNrightOffset, 0); ac++;
  1017. separator = XmCreateSeparator (form, "", al, ac);
  1018. ac = 0;
  1019. XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1020. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1021. XtSetArg(al[ac], XmNtopOffset, 13); ac++;
  1022. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
  1023. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  1024. XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1025. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
  1026. icon = XmCreateLabel (form, icon_name, al, ac);
  1027. ac = 0;
  1028. XtSetArg(al[ac], XmNmappedWhenManaged, FALSE); ac++;
  1029. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  1030. XtSetArg(al[ac], XmNtopOffset, 6); ac++;
  1031. XtSetArg(al[ac], XmNtopWidget, icon); ac++;
  1032. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1033. XtSetArg(al[ac], XmNbottomOffset, 6); ac++;
  1034. XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1035. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_NONE); ac++;
  1036. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
  1037. icon_separator = XmCreateLabel (form, "", al, ac);
  1038. if (text_input_slot)
  1039. {
  1040. ac = 0;
  1041. XtSetArg(al[ac], XmNcolumns, 50); ac++;
  1042. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1043. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1044. XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1045. XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1046. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1047. XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1048. XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1049. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1050. XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1051. value = XmCreateTextField (form, "value", al, ac);
  1052. }
  1053. else if (radio_box)
  1054. {
  1055. Widget radio_butt;
  1056. ac = 0;
  1057. XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
  1058. XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
  1059. XtSetArg(al[ac], XmNspacing, 13); ac++;
  1060. XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
  1061. XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
  1062. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1063. XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1064. XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1065. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1066. XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1067. XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1068. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1069. XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1070. value = XmCreateRadioBox (form, "radiobutton1", al, ac);
  1071. ac = 0;
  1072. i = 0;
  1073. radio_butt = XmCreateToggleButtonGadget (value, "radio1", al, ac);
  1074. children [i++] = radio_butt;
  1075. radio_butt = XmCreateToggleButtonGadget (value, "radio2", al, ac);
  1076. children [i++] = radio_butt;
  1077. radio_butt = XmCreateToggleButtonGadget (value, "radio3", al, ac);
  1078. children [i++] = radio_butt;
  1079. XtManageChildren (children, i);
  1080. }
  1081. else if (list)
  1082. {
  1083. ac = 0;
  1084. XtSetArg(al[ac], XmNvisibleItemCount, 5); ac++;
  1085. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1086. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1087. XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1088. XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1089. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1090. XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1091. XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1092. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1093. XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1094. value = XmCreateScrolledList (form, "list", al, ac);
  1095. /* this is the easiest way I found to have the dble click in the
  1096. list activate the default button */
  1097. XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
  1098. }
  1099. ac = 0;
  1100. XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
  1101. XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1102. XtSetArg(al[ac], XmNtopOffset, 13); ac++;
  1103. XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1104. XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1105. XtSetArg(al[ac], XmNbottomWidget,
  1106. text_input_slot || radio_box || list ? value : separator); ac++;
  1107. XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1108. XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1109. XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1110. XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1111. XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1112. message_label = XmCreateLabel (form, "message", al, ac);
  1113. if (list)
  1114. XtManageChild (value);
  1115. i = 0;
  1116. children [i] = row; i++;
  1117. children [i] = separator; i++;
  1118. if (text_input_slot || radio_box)
  1119. {
  1120. children [i] = value; i++;
  1121. }
  1122. children [i] = message_label; i++;
  1123. children [i] = icon; i++;
  1124. children [i] = icon_separator; i++;
  1125. XtManageChildren (children, i);
  1126. if (text_input_slot || list)
  1127. {
  1128. XtInstallAccelerators (value, button);
  1129. XtSetKeyboardFocus (result, value);
  1130. }
  1131. else
  1132. {
  1133. XtInstallAccelerators (form, button);
  1134. XtSetKeyboardFocus (result, button);
  1135. }
  1136. return result;
  1137. }
  1138. static destroyed_instance*
  1139. find_matching_instance (widget_instance* instance)
  1140. {
  1141. destroyed_instance* cur;
  1142. destroyed_instance* prev;
  1143. char* type = instance->info->type;
  1144. char* name = instance->info->name;
  1145. for (prev = NULL, cur = all_destroyed_instances;
  1146. cur;
  1147. prev = cur, cur = cur->next)
  1148. {
  1149. if (!strcmp (cur->name, name)
  1150. && !strcmp (cur->type, type)
  1151. && cur->parent == instance->parent
  1152. && cur->pop_up_p == instance->pop_up_p)
  1153. {
  1154. if (prev)
  1155. prev->next = cur->next;
  1156. else
  1157. all_destroyed_instances = cur->next;
  1158. return cur;
  1159. }
  1160. /* do some cleanup */
  1161. else if (!cur->widget)
  1162. {
  1163. if (prev)
  1164. prev->next = cur->next;
  1165. else
  1166. all_destroyed_instances = cur->next;
  1167. free_destroyed_instance (cur);
  1168. cur = prev ? prev : all_destroyed_instances;
  1169. }
  1170. }
  1171. return NULL;
  1172. }
  1173. static void
  1174. mark_dead_instance_destroyed (Widget widget,
  1175. XtPointer closure,
  1176. XtPointer call_data)
  1177. {
  1178. destroyed_instance* instance = (destroyed_instance*)closure;
  1179. instance->widget = NULL;
  1180. }
  1181. static void
  1182. recenter_widget (Widget widget)
  1183. {
  1184. Widget parent = XtParent (widget);
  1185. Screen* screen = XtScreen (widget);
  1186. Dimension screen_width = WidthOfScreen (screen);
  1187. Dimension screen_height = HeightOfScreen (screen);
  1188. Dimension parent_width = 0;
  1189. Dimension parent_height = 0;
  1190. Dimension child_width = 0;
  1191. Dimension child_height = 0;
  1192. Position x;
  1193. Position y;
  1194. XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, NULL);
  1195. XtVaGetValues (parent, XtNwidth, &parent_width, XtNheight, &parent_height,
  1196. NULL);
  1197. x = (((Position)parent_width) - ((Position)child_width)) / 2;
  1198. y = (((Position)parent_height) - ((Position)child_height)) / 2;
  1199. XtTranslateCoords (parent, x, y, &x, &y);
  1200. if (x + child_width > screen_width)
  1201. x = screen_width - child_width;
  1202. if (x < 0)
  1203. x = 0;
  1204. if (y + child_height > screen_height)
  1205. y = screen_height - child_height;
  1206. if (y < 0)
  1207. y = 0;
  1208. XtVaSetValues (widget, XtNx, x, XtNy, y, NULL);
  1209. }
  1210. static Widget
  1211. recycle_instance (destroyed_instance* instance)
  1212. {
  1213. Widget widget = instance->widget;
  1214. /* widget is NULL if the parent was destroyed. */
  1215. if (widget)
  1216. {
  1217. Widget focus;
  1218. Widget separator;
  1219. /* Remove the destroy callback as the instance is not in the list
  1220. anymore */
  1221. XtRemoveCallback (instance->parent, XtNdestroyCallback,
  1222. mark_dead_instance_destroyed,
  1223. (XtPointer)instance);
  1224. /* Give the focus to the initial item */
  1225. focus = XtNameToWidget (widget, "*value");
  1226. if (!focus)
  1227. focus = XtNameToWidget (widget, "*button1");
  1228. if (focus)
  1229. XtSetKeyboardFocus (widget, focus);
  1230. /* shrink the separator label back to their original size */
  1231. separator = XtNameToWidget (widget, "*separator_button");
  1232. if (separator)
  1233. XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, NULL);
  1234. /* Center the dialog in its parent */
  1235. recenter_widget (widget);
  1236. }
  1237. free_destroyed_instance (instance);
  1238. return widget;
  1239. }
  1240. Widget
  1241. xm_create_dialog (widget_instance* instance)
  1242. {
  1243. char* name = instance->info->type;
  1244. Widget parent = instance->parent;
  1245. Widget widget;
  1246. Boolean pop_up_p = instance->pop_up_p;
  1247. char* shell_name = 0;
  1248. char* icon_name = 0;
  1249. Boolean text_input_slot = False;
  1250. Boolean radio_box = False;
  1251. Boolean list = False;
  1252. int total_buttons;
  1253. int left_buttons = 0;
  1254. int right_buttons = 1;
  1255. destroyed_instance* dead_one;
  1256. /* try to find a widget to recycle */
  1257. dead_one = find_matching_instance (instance);
  1258. if (dead_one)
  1259. {
  1260. Widget recycled_widget = recycle_instance (dead_one);
  1261. if (recycled_widget)
  1262. return recycled_widget;
  1263. }
  1264. switch (name [0]){
  1265. case 'E': case 'e':
  1266. icon_name = "dbox-error";
  1267. shell_name = "Error";
  1268. break;
  1269. case 'I': case 'i':
  1270. icon_name = "dbox-info";
  1271. shell_name = "Information";
  1272. break;
  1273. case 'L': case 'l':
  1274. list = True;
  1275. icon_name = "dbox-question";
  1276. shell_name = "Prompt";
  1277. break;
  1278. case 'P': case 'p':
  1279. text_input_slot = True;
  1280. icon_name = "dbox-question";
  1281. shell_name = "Prompt";
  1282. break;
  1283. case 'Q': case 'q':
  1284. icon_name = "dbox-question";
  1285. shell_name = "Question";
  1286. break;
  1287. }
  1288. total_buttons = name [1] - '0';
  1289. if (name [3] == 'T' || name [3] == 't')
  1290. {
  1291. text_input_slot = False;
  1292. radio_box = True;
  1293. }
  1294. else if (name [3])
  1295. right_buttons = name [4] - '0';
  1296. left_buttons = total_buttons - right_buttons;
  1297. widget = make_dialog (name, parent, pop_up_p,
  1298. shell_name, icon_name, text_input_slot, radio_box,
  1299. list, left_buttons, right_buttons);
  1300. XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
  1301. (XtPointer) instance);
  1302. return widget;
  1303. }
  1304. /* Create a menu bar. We turn off the f10 key
  1305. because we have not yet managed to make it work right in Motif. */
  1306. static Widget
  1307. make_menubar (widget_instance* instance)
  1308. {
  1309. Arg al[3];
  1310. int ac;
  1311. ac = 0;
  1312. XtSetArg(al[ac], XmNmenuAccelerator, 0); ++ac;
  1313. return XmCreateMenuBar (instance->parent, instance->info->name, al, ac);
  1314. }
  1315. static void
  1316. remove_grabs (Widget shell,
  1317. XtPointer closure,
  1318. XtPointer call_data)
  1319. {
  1320. Widget menu = (Widget) closure;
  1321. XmRemoveFromPostFromList (menu, XtParent (XtParent (menu)));
  1322. }
  1323. static Widget
  1324. make_popup_menu (widget_instance* instance)
  1325. {
  1326. Widget parent = instance->parent;
  1327. Window parent_window = parent->core.window;
  1328. Widget result;
  1329. /* sets the parent window to 0 to fool Motif into not generating a grab */
  1330. parent->core.window = 0;
  1331. result = XmCreatePopupMenu (parent, instance->info->name, NULL, 0);
  1332. XtAddCallback (XtParent (result), XmNpopdownCallback, remove_grabs,
  1333. (XtPointer)result);
  1334. parent->core.window = parent_window;
  1335. return result;
  1336. }
  1337. static Widget
  1338. make_main (widget_instance* instance)
  1339. {
  1340. Widget parent = instance->parent;
  1341. Widget result;
  1342. Arg al[2];
  1343. int ac;
  1344. ac = 0;
  1345. XtSetArg (al[ac], XtNborderWidth, 0); ac++;
  1346. XtSetArg (al[ac], XmNspacing, 0); ac++;
  1347. result = XmCreateMainWindow (parent, instance->info->name, al, ac);
  1348. return result;
  1349. }
  1350. /* Table of functions to create widgets */
  1351. #ifdef ENERGIZE
  1352. /* interface with the XDesigner generated functions */
  1353. typedef Widget (*widget_maker) (Widget);
  1354. extern Widget create_project_p_sheet (Widget parent);
  1355. extern Widget create_debugger_p_sheet (Widget parent);
  1356. extern Widget create_breaklist_p_sheet (Widget parent);
  1357. extern Widget create_le_browser_p_sheet (Widget parent);
  1358. extern Widget create_class_browser_p_sheet (Widget parent);
  1359. extern Widget create_call_browser_p_sheet (Widget parent);
  1360. extern Widget create_build_dialog (Widget parent);
  1361. extern Widget create_editmode_dialog (Widget parent);
  1362. extern Widget create_search_dialog (Widget parent);
  1363. extern Widget create_project_display_dialog (Widget parent);
  1364. static Widget
  1365. make_one (widget_instance* instance, widget_maker fn)
  1366. {
  1367. Widget result;
  1368. Arg al [64];
  1369. int ac = 0;
  1370. if (instance->pop_up_p)
  1371. {
  1372. XtSetArg (al [ac], XmNallowShellResize, TRUE); ac++;
  1373. result = XmCreateDialogShell (instance->parent, "dialog", NULL, 0);
  1374. XtAddCallback (result, XmNpopdownCallback, &xm_nosel_callback,
  1375. (XtPointer) instance);
  1376. (*fn) (result);
  1377. }
  1378. else
  1379. {
  1380. result = (*fn) (instance->parent);
  1381. XtRealizeWidget (result);
  1382. }
  1383. return result;
  1384. }
  1385. static Widget
  1386. make_project_p_sheet (widget_instance* instance)
  1387. {
  1388. return make_one (instance, create_project_p_sheet);
  1389. }
  1390. static Widget
  1391. make_debugger_p_sheet (widget_instance* instance)
  1392. {
  1393. return make_one (instance, create_debugger_p_sheet);
  1394. }
  1395. static Widget
  1396. make_breaklist_p_sheet (widget_instance* instance)
  1397. {
  1398. return make_one (instance, create_breaklist_p_sheet);
  1399. }
  1400. static Widget
  1401. make_le_browser_p_sheet (widget_instance* instance)
  1402. {
  1403. return make_one (instance, create_le_browser_p_sheet);
  1404. }
  1405. static Widget
  1406. make_class_browser_p_sheet (widget_instance* instance)
  1407. {
  1408. return make_one (instance, create_class_browser_p_sheet);
  1409. }
  1410. static Widget
  1411. make_call_browser_p_sheet (widget_instance* instance)
  1412. {
  1413. return make_one (instance, create_call_browser_p_sheet);
  1414. }
  1415. static Widget
  1416. make_build_dialog (widget_instance* instance)
  1417. {
  1418. return make_one (instance, create_build_dialog);
  1419. }
  1420. static Widget
  1421. make_editmode_dialog (widget_instance* instance)
  1422. {
  1423. return make_one (instance, create_editmode_dialog);
  1424. }
  1425. static Widget
  1426. make_search_dialog (widget_instance* instance)
  1427. {
  1428. return make_one (instance, create_search_dialog);
  1429. }
  1430. static Widget
  1431. make_project_display_dialog (widget_instance* instance)
  1432. {
  1433. return make_one (instance, create_project_display_dialog);
  1434. }
  1435. #endif /* ENERGIZE */
  1436. widget_creation_entry
  1437. xm_creation_table [] =
  1438. {
  1439. {"menubar", make_menubar},
  1440. {"popup", make_popup_menu},
  1441. {"main", make_main},
  1442. #ifdef ENERGIZE
  1443. {"project_p_sheet", make_project_p_sheet},
  1444. {"debugger_p_sheet", make_debugger_p_sheet},
  1445. {"breaklist_psheet", make_breaklist_p_sheet},
  1446. {"leb_psheet", make_le_browser_p_sheet},
  1447. {"class_browser_psheet", make_class_browser_p_sheet},
  1448. {"ctree_browser_psheet", make_call_browser_p_sheet},
  1449. {"build", make_build_dialog},
  1450. {"editmode", make_editmode_dialog},
  1451. {"search", make_search_dialog},
  1452. {"project_display", make_project_display_dialog},
  1453. #endif /* ENERGIZE */
  1454. {NULL, NULL}
  1455. };
  1456. /* Destruction of instances */
  1457. void
  1458. xm_destroy_instance ( widget_instance* instance)
  1459. {
  1460. Widget widget = instance->widget;
  1461. /* recycle the dialog boxes */
  1462. /* Disable the recycling until we can find a way to have the dialog box
  1463. get reasonable layout after we modify its contents. */
  1464. if (0
  1465. && XtClass (widget) == xmDialogShellWidgetClass)
  1466. {
  1467. destroyed_instance* dead_instance =
  1468. make_destroyed_instance (instance->info->name,
  1469. instance->info->type,
  1470. instance->widget,
  1471. instance->parent,
  1472. instance->pop_up_p);
  1473. dead_instance->next = all_destroyed_instances;
  1474. all_destroyed_instances = dead_instance;
  1475. XtUnmanageChild (first_child (instance->widget));
  1476. XFlush (XtDisplay (instance->widget));
  1477. XtAddCallback (instance->parent, XtNdestroyCallback,
  1478. mark_dead_instance_destroyed, (XtPointer)dead_instance);
  1479. }
  1480. else
  1481. {
  1482. /* This might not be necessary now that the nosel is attached to
  1483. popdown instead of destroy, but it can't hurt. */
  1484. XtRemoveCallback (instance->widget, XtNdestroyCallback,
  1485. xm_nosel_callback, (XtPointer)instance);
  1486. XtDestroyWidget (instance->widget);
  1487. }
  1488. }
  1489. /* popup utility */
  1490. void
  1491. xm_popup_menu (Widget widget, XEvent *event)
  1492. {
  1493. XButtonPressedEvent dummy;
  1494. if (event == 0)
  1495. {
  1496. dummy.type = ButtonPress;
  1497. dummy.serial = 0;
  1498. dummy.send_event = 0;
  1499. dummy.display = XtDisplay (widget);
  1500. dummy.window = XtWindow (XtParent (widget));
  1501. dummy.time = 0;
  1502. dummy.button = 0;
  1503. XQueryPointer (dummy.display, dummy.window, &dummy.root,
  1504. &dummy.subwindow, &dummy.x_root, &dummy.y_root,
  1505. &dummy.x, &dummy.y, &dummy.state);
  1506. event = (XEvent *) &dummy;
  1507. }
  1508. if (event->type == ButtonPress || event->type == ButtonRelease)
  1509. {
  1510. /* Setting the menuPost resource only required by Motif 1.1 and
  1511. LessTif 0.84 and earlier. With later versions of LessTif,
  1512. setting menuPost is unnecessary and may cause problems, so
  1513. don't do it. */
  1514. #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
  1515. {
  1516. /* This is so totally ridiculous: there's NO WAY to tell Motif
  1517. that *any* button can select a menu item. Only one button
  1518. can have that honor. */
  1519. char *trans = 0;
  1520. if (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
  1521. else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
  1522. else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
  1523. else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
  1524. else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
  1525. if (trans) XtVaSetValues (widget, XmNmenuPost, trans, NULL);
  1526. }
  1527. #endif
  1528. XmMenuPosition (widget, (XButtonPressedEvent *) event);
  1529. }
  1530. XtManageChild (widget);
  1531. }
  1532. static void
  1533. set_min_dialog_size (Widget w)
  1534. {
  1535. short width;
  1536. short height;
  1537. XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, NULL);
  1538. XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, NULL);
  1539. }
  1540. void
  1541. xm_pop_instance (widget_instance* instance, Boolean up)
  1542. {
  1543. Widget widget = instance->widget;
  1544. if (XtClass (widget) == xmDialogShellWidgetClass)
  1545. {
  1546. Widget widget_to_manage = first_child (widget);
  1547. if (up)
  1548. {
  1549. XtManageChild (widget_to_manage);
  1550. set_min_dialog_size (widget);
  1551. XtSetKeyboardFocus (instance->parent, widget);
  1552. }
  1553. else
  1554. XtUnmanageChild (widget_to_manage);
  1555. }
  1556. else
  1557. {
  1558. if (up)
  1559. XtManageChild (widget);
  1560. else
  1561. XtUnmanageChild (widget);
  1562. }
  1563. }
  1564. /* motif callback */
  1565. static void
  1566. do_call (Widget widget,
  1567. XtPointer closure,
  1568. enum do_call_type type)
  1569. {
  1570. Arg al [256];
  1571. int ac;
  1572. XtPointer user_data;
  1573. widget_instance* instance = (widget_instance*)closure;
  1574. Widget instance_widget;
  1575. LWLIB_ID id;
  1576. if (!instance)
  1577. return;
  1578. if (widget->core.being_destroyed)
  1579. return;
  1580. instance_widget = instance->widget;
  1581. if (!instance_widget)
  1582. return;
  1583. id = instance->info->id;
  1584. ac = 0;
  1585. user_data = NULL;
  1586. XtSetArg (al [ac], XmNuserData, &user_data); ac++;
  1587. XtGetValues (widget, al, ac);
  1588. switch (type)
  1589. {
  1590. case pre_activate:
  1591. if (instance->info->pre_activate_cb)
  1592. instance->info->pre_activate_cb (widget, id, user_data);
  1593. break;
  1594. case selection:
  1595. if (instance->info->selection_cb)
  1596. instance->info->selection_cb (widget, id, user_data);
  1597. break;
  1598. case no_selection:
  1599. if (instance->info->selection_cb)
  1600. instance->info->selection_cb (widget, id, (XtPointer) -1);
  1601. break;
  1602. case post_activate:
  1603. if (instance->info->post_activate_cb)
  1604. instance->info->post_activate_cb (widget, id, user_data);
  1605. break;
  1606. default:
  1607. abort ();
  1608. }
  1609. }
  1610. /* Like lw_internal_update_other_instances except that it does not do
  1611. anything if its shell parent is not managed. This is to protect
  1612. lw_internal_update_other_instances to dereference freed memory
  1613. if the widget was ``destroyed'' by caching it in the all_destroyed_instances
  1614. list */
  1615. static void
  1616. xm_internal_update_other_instances (Widget widget,
  1617. XtPointer closure,
  1618. XtPointer call_data)
  1619. {
  1620. Widget parent;
  1621. for (parent = widget; parent; parent = XtParent (parent))
  1622. if (XtIsShell (parent))
  1623. break;
  1624. else if (!XtIsManaged (parent))
  1625. return;
  1626. lw_internal_update_other_instances (widget, closure, call_data);
  1627. }
  1628. static void
  1629. xm_generic_callback (Widget widget,
  1630. XtPointer closure,
  1631. XtPointer call_data)
  1632. {
  1633. lw_internal_update_other_instances (widget, closure, call_data);
  1634. do_call (widget, closure, selection);
  1635. }
  1636. static void
  1637. xm_nosel_callback (Widget widget,
  1638. XtPointer closure,
  1639. XtPointer call_data)
  1640. {
  1641. /* This callback is only called when a dialog box is dismissed with
  1642. the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog
  1643. box to be destroyed in that case, not just unmapped, so that it
  1644. releases its keyboard grabs. But there are problems with running
  1645. our callbacks while the widget is in the process of being
  1646. destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
  1647. XmDESTROY and then destroy it ourself after having run the
  1648. callback. */
  1649. do_call (widget, closure, no_selection);
  1650. XtDestroyWidget (widget);
  1651. }
  1652. static void
  1653. xm_pull_down_callback (Widget widget,
  1654. XtPointer closure,
  1655. XtPointer call_data)
  1656. {
  1657. Widget parent = XtParent (widget);
  1658. if (XmIsRowColumn (parent))
  1659. {
  1660. unsigned char type = 0xff;
  1661. XtVaGetValues (parent, XmNrowColumnType, &type, NULL);
  1662. if (type == XmMENU_BAR)
  1663. do_call (widget, closure, pre_activate);
  1664. }
  1665. }
  1666. /* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
  1667. CLOSURE is a pointer to the widget_instance of the shell,
  1668. Note that this callback is called for each cascade button in a
  1669. menu, whether or not its submenu is visible. */
  1670. static void
  1671. xm_pop_down_callback (Widget widget,
  1672. XtPointer closure,
  1673. XtPointer call_data)
  1674. {
  1675. widget_instance *instance = (widget_instance *) closure;
  1676. if ((!instance->pop_up_p && XtParent (widget) == instance->widget)
  1677. || XtParent (widget) == instance->parent)
  1678. do_call (widget, closure, post_activate);
  1679. }
  1680. /* set the keyboard focus */
  1681. void
  1682. xm_set_keyboard_focus (Widget parent, Widget w)
  1683. {
  1684. XmProcessTraversal (w, 0);
  1685. XtSetKeyboardFocus (parent, w);
  1686. }
  1687. /* Motif hack to set the main window areas. */
  1688. void
  1689. xm_set_main_areas (Widget parent,
  1690. Widget menubar,
  1691. Widget work_area)
  1692. {
  1693. XmMainWindowSetAreas (parent,
  1694. menubar, /* menubar (maybe 0) */
  1695. 0, /* command area (psheets) */
  1696. 0, /* horizontal scroll */
  1697. 0, /* vertical scroll */
  1698. work_area); /* work area */
  1699. }
  1700. /* Motif hack to control resizing on the menubar. */
  1701. void
  1702. xm_manage_resizing (Widget w, Boolean flag)
  1703. {
  1704. XtVaSetValues (w, XtNallowShellResize, flag, NULL);
  1705. }