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