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