* dired.el: (dired-mode): Set font-lock-defaults.
[emacs.git] / lwlib / lwlib-Xm.c
blob7444d3634dcae85fa834dace512cb06c1334b226
1 /* The lwlib interface to Motif widgets.
2 Copyright (C) 1992 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <stdio.h>
25 #include <X11/StringDefs.h>
26 #include <X11/IntrinsicP.h>
27 #include <X11/ObjectP.h>
28 #include <X11/CoreP.h>
29 #include <X11/CompositeP.h>
31 #include "lwlib-Xm.h"
32 #include "lwlib-utils.h"
34 #include <Xm/BulletinB.h>
35 #include <Xm/CascadeB.h>
36 #include <Xm/DrawingA.h>
37 #include <Xm/FileSB.h>
38 #include <Xm/Label.h>
39 #include <Xm/List.h>
40 #include <Xm/MainW.h>
41 #include <Xm/MenuShell.h>
42 #include <Xm/MessageB.h>
43 #include <Xm/PanedW.h>
44 #include <Xm/PushB.h>
45 #include <Xm/PushBG.h>
46 #include <Xm/ArrowB.h>
47 #include <Xm/SelectioB.h>
48 #include <Xm/Text.h>
49 #include <Xm/TextF.h>
50 #include <Xm/ToggleB.h>
51 #include <Xm/ToggleBG.h>
52 #include <Xm/RowColumn.h>
53 #include <Xm/ScrolledW.h>
54 #include <Xm/Separator.h>
55 #include <Xm/DialogS.h>
56 #include <Xm/Form.h>
58 static void xm_pull_down_callback (Widget, XtPointer, XtPointer);
59 static void xm_internal_update_other_instances (Widget, XtPointer,
60 XtPointer);
61 static void xm_generic_callback (Widget, XtPointer, XtPointer);
62 static void xm_nosel_callback (Widget, XtPointer, XtPointer);
63 static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
65 static void
66 xm_update_menu (widget_instance* instance, Widget widget, widget_value* val,
67 Boolean deep_p);
69 \f/* Structures to keep destroyed instances */
70 typedef struct _destroyed_instance
72 char* name;
73 char* type;
74 Widget widget;
75 Widget parent;
76 Boolean pop_up_p;
77 struct _destroyed_instance* next;
78 } destroyed_instance;
80 static destroyed_instance*
81 all_destroyed_instances = NULL;
83 static destroyed_instance*
84 make_destroyed_instance (char* name, char* type, Widget widget, Widget parent,
85 Boolean pop_up_p)
87 destroyed_instance* instance =
88 (destroyed_instance*)malloc (sizeof (destroyed_instance));
89 instance->name = safe_strdup (name);
90 instance->type = safe_strdup (type);
91 instance->widget = widget;
92 instance->parent = parent;
93 instance->pop_up_p = pop_up_p;
94 instance->next = NULL;
95 return instance;
98 static void
99 free_destroyed_instance (destroyed_instance* instance)
101 free (instance->name);
102 free (instance->type);
103 free (instance);
106 \f/* motif utility functions */
107 Widget
108 first_child (Widget widget)
110 return ((CompositeWidget)widget)->composite.children [0];
113 Boolean
114 lw_motif_widget_p (Widget widget)
116 return
117 XtClass (widget) == xmDialogShellWidgetClass
118 || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
121 static XmString
122 resource_motif_string (Widget widget, char* name)
124 XtResource resource;
125 XmString result = 0;
127 resource.resource_name = name;
128 resource.resource_class = XmCXmString;
129 resource.resource_type = XmRXmString;
130 resource.resource_size = sizeof (XmString);
131 resource.resource_offset = 0;
132 resource.default_type = XtRImmediate;
133 resource.default_addr = 0;
135 XtGetSubresources (widget, (XtPointer)&result, "dialogString",
136 "DialogString", &resource, 1, NULL, 0);
137 return result;
140 static void
141 destroy_all_children (Widget widget)
143 Widget* children;
144 unsigned int number;
145 int i;
147 children = XtCompositeChildren (widget, &number);
148 if (children)
150 /* Unmanage all children and destroy them. They will only be
151 * really destroyed when we get out of DispatchEvent. */
152 for (i = 0; i < number; i++)
154 Widget child = children [i];
155 if (!child->core.being_destroyed)
157 XtUnmanageChild (child);
158 XtDestroyWidget (child);
161 XtFree ((char *) children);
165 \f/* update the label of anything subclass of a label */
166 static void
167 xm_update_label (widget_instance* instance, Widget widget, widget_value* val)
169 XmString res_string = 0;
170 XmString built_string = 0;
171 XmString key_string = 0;
172 Arg al [256];
173 int ac;
175 ac = 0;
177 if (val->value)
179 res_string = resource_motif_string (widget, val->value);
181 if (res_string)
183 XtSetArg (al [ac], XmNlabelString, res_string); ac++;
185 else
187 built_string =
188 XmStringCreateLtoR (val->value, XmSTRING_DEFAULT_CHARSET);
189 XtSetArg (al [ac], XmNlabelString, built_string); ac++;
191 XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
194 if (val->key)
196 key_string = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET);
197 XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
200 if (ac)
201 XtSetValues (widget, al, ac);
203 if (built_string)
204 XmStringFree (built_string);
206 if (key_string)
207 XmStringFree (key_string);
210 \f/* update of list */
211 static void
212 xm_update_list (widget_instance* instance, Widget widget, widget_value* val)
214 widget_value* cur;
215 int i;
216 XtRemoveAllCallbacks (widget, XmNsingleSelectionCallback);
217 XtAddCallback (widget, XmNsingleSelectionCallback, xm_generic_callback,
218 instance);
219 for (cur = val->contents, i = 0; cur; cur = cur->next)
220 if (cur->value)
222 XmString xmstr = XmStringCreate (cur->value, XmSTRING_DEFAULT_CHARSET);
223 i += 1;
224 XmListAddItem (widget, xmstr, 0);
225 if (cur->selected)
226 XmListSelectPos (widget, i, False);
227 XmStringFree (xmstr);
231 \f/* update of buttons */
232 static void
233 xm_update_pushbutton (widget_instance* instance, Widget widget,
234 widget_value* val)
236 XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, 0);
237 XtRemoveAllCallbacks (widget, XmNactivateCallback);
238 XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
241 static void
242 xm_update_cascadebutton (widget_instance* instance, Widget widget,
243 widget_value* val)
245 /* Should also rebuild the menu by calling ...update_menu... */
246 XtRemoveAllCallbacks (widget, XmNcascadingCallback);
247 XtAddCallback (widget, XmNcascadingCallback, xm_pull_down_callback,
248 instance);
251 \f/* update toggle and radiobox */
252 static void
253 xm_update_toggle (widget_instance* instance, Widget widget, widget_value* val)
255 XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
256 XtAddCallback (widget, XmNvalueChangedCallback,
257 xm_internal_update_other_instances, instance);
258 XtVaSetValues (widget, XmNset, val->selected,
259 XmNalignment, XmALIGNMENT_BEGINNING, 0);
262 static void
263 xm_update_radiobox (widget_instance* instance, Widget widget,
264 widget_value* val)
266 Widget toggle;
267 widget_value* cur;
269 /* update the callback */
270 XtRemoveAllCallbacks (widget, XmNentryCallback);
271 XtAddCallback (widget, XmNentryCallback, xm_generic_callback, instance);
273 /* first update all the toggles */
274 /* Energize kernel interface is currently bad. It sets the selected widget
275 with the selected flag but returns it by its name. So we currently
276 have to support both setting the selection with the selected slot
277 of val contents and setting it with the "value" slot of val. The latter
278 has a higher priority. This to be removed when the kernel is fixed. */
279 for (cur = val->contents; cur; cur = cur->next)
281 toggle = XtNameToWidget (widget, cur->value);
282 if (toggle)
284 XtVaSetValues (toggle, XmNsensitive, cur->enabled, 0);
285 if (!val->value && cur->selected)
286 XtVaSetValues (toggle, XmNset, cur->selected, 0);
287 if (val->value && strcmp (val->value, cur->value))
288 XtVaSetValues (toggle, XmNset, False, 0);
292 /* The selected was specified by the value slot */
293 if (val->value)
295 toggle = XtNameToWidget (widget, val->value);
296 if (toggle)
297 XtVaSetValues (toggle, XmNset, True, 0);
301 \f/* update a popup menu, pulldown menu or a menubar */
302 static Boolean
303 all_dashes_p (char* s)
305 char* t;
306 for (t = s; *t; t++)
307 if (*t != '-')
308 return False;
309 return True;
312 static void
313 make_menu_in_widget (widget_instance* instance, Widget widget,
314 widget_value* val)
316 Widget* children = 0;
317 int num_children;
318 int child_index;
319 widget_value* cur;
320 Widget button = 0;
321 Widget menu;
322 Arg al [256];
323 int ac;
324 Boolean menubar_p;
326 /* Allocate the children array */
327 for (num_children = 0, cur = val; cur; num_children++, cur = cur->next);
328 children = (Widget*)XtMalloc (num_children * sizeof (Widget));
330 /* tricky way to know if this RowColumn is a menubar or a pulldown... */
331 menubar_p = False;
332 XtSetArg (al[0], XmNisHomogeneous, &menubar_p);
333 XtGetValues (widget, al, 1);
335 /* add the unmap callback for popups and pulldowns */
336 /*** this sounds bogus ***/
337 if (!menubar_p)
338 XtAddCallback (XtParent (widget), XmNpopdownCallback,
339 xm_pop_down_callback, (XtPointer)instance);
341 for (child_index = 0, cur = val; cur; child_index++, cur = cur->next)
343 ac = 0;
344 XtSetArg (al [ac], XmNsensitive, cur->enabled); ac++;
345 XtSetArg (al [ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
346 XtSetArg (al [ac], XmNuserData, cur->call_data); ac++;
348 if (instance->pop_up_p && !cur->contents && !cur->call_data)
350 ac = 0;
351 XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
352 button = XmCreateLabel (widget, cur->name, al, ac);
354 else if (all_dashes_p (cur->name))
356 button = XmCreateSeparator (widget, cur->name, NULL, 0);
358 else if (!cur->contents)
360 if (menubar_p)
361 button = XmCreateCascadeButton (widget, cur->name, al, ac);
362 else if (!cur->call_data)
363 button = XmCreateLabel (widget, cur->name, al, ac);
364 else
365 button = XmCreatePushButtonGadget (widget, cur->name, al, ac);
367 xm_update_label (instance, button, cur);
369 /* don't add a callback to a simple label */
370 if (cur->call_data)
371 XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
372 (XtPointer)instance);
374 else
376 menu = XmCreatePulldownMenu (widget, "pulldown", NULL, 0);
377 make_menu_in_widget (instance, menu, cur->contents);
378 XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
379 button = XmCreateCascadeButton (widget, cur->name, al, ac);
381 xm_update_label (instance, button, cur);
383 XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
384 (XtPointer)instance);
387 children [child_index] = button;
390 XtManageChildren (children, num_children);
392 /* Last entry is the help button. Has to be done after managing
393 * the buttons otherwise the menubar is only 4 pixels high... */
394 if (button)
396 ac = 0;
397 XtSetArg (al [ac], XmNmenuHelpWidget, button); ac++;
398 XtSetValues (widget, al, ac);
401 XtFree ((char *) children);
404 static void
405 update_one_menu_entry (widget_instance* instance, Widget widget,
406 widget_value* val, Boolean deep_p)
408 Arg al [256];
409 int ac;
410 Widget menu;
411 widget_value* contents;
413 if (val->change == NO_CHANGE)
414 return;
416 /* update the sensitivity and userdata */
417 /* Common to all widget types */
418 XtVaSetValues (widget,
419 XmNsensitive, val->enabled,
420 XmNuserData, val->call_data,
423 /* update the menu button as a label. */
424 if (val->change >= VISIBLE_CHANGE)
425 xm_update_label (instance, widget, val);
427 /* update the pulldown/pullaside as needed */
428 ac = 0;
429 menu = NULL;
430 XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
431 XtGetValues (widget, al, ac);
433 contents = val->contents;
435 if (!menu)
437 if (contents)
439 menu = XmCreatePulldownMenu (widget, "pulldown", NULL, 0);
440 make_menu_in_widget (instance, menu, contents);
441 ac = 0;
442 XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
443 XtSetValues (widget, al, ac);
446 else if (!contents)
448 ac = 0;
449 XtSetArg (al [ac], XmNsubMenuId, NULL); ac++;
450 XtSetValues (widget, al, ac);
451 XtDestroyWidget (menu);
453 else if (deep_p && contents->change != NO_CHANGE)
454 xm_update_menu (instance, menu, val, 1);
457 static void
458 xm_update_menu (widget_instance* instance, Widget widget, widget_value* val,
459 Boolean deep_p)
461 /* Widget is a RowColumn widget whose contents have to be updated
462 * to reflect the list of items in val->contents */
463 if (val->contents->change == STRUCTURAL_CHANGE)
465 destroy_all_children (widget);
466 make_menu_in_widget (instance, widget, val->contents);
468 else
470 /* Update all the buttons of the RowColumn in order. */
471 Widget* children;
472 unsigned int num_children;
473 int i;
474 widget_value* cur;
476 children = XtCompositeChildren (widget, &num_children);
477 if (children)
479 for (i = 0, cur = val->contents; i < num_children; i++)
481 if (!cur)
482 abort ();
483 if (children [i]->core.being_destroyed
484 || strcmp (XtName (children [i]), cur->name))
485 continue;
486 update_one_menu_entry (instance, children [i], cur, deep_p);
487 cur = cur->next;
489 XtFree ((char *) children);
491 if (cur)
492 abort ();
497 /* update text widgets */
499 static void
500 xm_update_text (widget_instance* instance, Widget widget, widget_value* val)
502 XmTextSetString (widget, val->value ? val->value : "");
503 XtRemoveAllCallbacks (widget, XmNactivateCallback);
504 XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
505 XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
506 XtAddCallback (widget, XmNvalueChangedCallback,
507 xm_internal_update_other_instances, instance);
510 static void
511 xm_update_text_field (widget_instance* instance, Widget widget,
512 widget_value* val)
514 XmTextFieldSetString (widget, val->value ? val->value : "");
515 XtRemoveAllCallbacks (widget, XmNactivateCallback);
516 XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
517 XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
518 XtAddCallback (widget, XmNvalueChangedCallback,
519 xm_internal_update_other_instances, instance);
523 /* update a motif widget */
525 void
526 xm_update_one_widget (widget_instance* instance, Widget widget,
527 widget_value* val, Boolean deep_p)
529 WidgetClass class;
531 /* Mark as not edited */
532 val->edited = False;
534 /* Common to all widget types */
535 XtVaSetValues (widget,
536 XmNsensitive, val->enabled,
537 XmNuserData, val->call_data,
540 /* Common to all label like widgets */
541 if (XtIsSubclass (widget, xmLabelWidgetClass))
542 xm_update_label (instance, widget, val);
544 class = XtClass (widget);
545 /* Class specific things */
546 if (class == xmPushButtonWidgetClass ||
547 class == xmArrowButtonWidgetClass)
549 xm_update_pushbutton (instance, widget, val);
551 else if (class == xmCascadeButtonWidgetClass)
553 xm_update_cascadebutton (instance, widget, val);
555 else if (class == xmToggleButtonWidgetClass
556 || class == xmToggleButtonGadgetClass)
558 xm_update_toggle (instance, widget, val);
560 else if (class == xmRowColumnWidgetClass)
562 Boolean radiobox = 0;
563 int ac = 0;
564 Arg al [1];
566 XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
567 XtGetValues (widget, al, ac);
569 if (radiobox)
570 xm_update_radiobox (instance, widget, val);
571 else
572 xm_update_menu (instance, widget, val, deep_p);
574 else if (class == xmTextWidgetClass)
576 xm_update_text (instance, widget, val);
578 else if (class == xmTextFieldWidgetClass)
580 xm_update_text_field (instance, widget, val);
582 else if (class == xmListWidgetClass)
584 xm_update_list (instance, widget, val);
588 \f/* getting the value back */
589 void
590 xm_update_one_value (widget_instance* instance, Widget widget,
591 widget_value* val)
593 WidgetClass class = XtClass (widget);
594 widget_value *old_wv;
596 /* copy the call_data slot into the "return" widget_value */
597 for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next)
598 if (!strcmp (val->name, old_wv->name))
600 val->call_data = old_wv->call_data;
601 break;
604 if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
606 XtVaGetValues (widget, XmNset, &val->selected, 0);
607 val->edited = True;
609 else if (class == xmTextWidgetClass)
611 if (val->value)
612 free (val->value);
613 val->value = XmTextGetString (widget);
614 val->edited = True;
616 else if (class == xmTextFieldWidgetClass)
618 if (val->value)
619 free (val->value);
620 val->value = XmTextFieldGetString (widget);
621 val->edited = True;
623 else if (class == xmRowColumnWidgetClass)
625 Boolean radiobox = 0;
626 int ac = 0;
627 Arg al [1];
629 XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
630 XtGetValues (widget, al, ac);
632 if (radiobox)
634 CompositeWidget radio = (CompositeWidget)widget;
635 int i;
636 for (i = 0; i < radio->composite.num_children; i++)
638 int set = False;
639 Widget toggle = radio->composite.children [i];
641 XtVaGetValues (toggle, XmNset, &set, 0);
642 if (set)
644 if (val->value)
645 free (val->value);
646 val->value = safe_strdup (XtName (toggle));
649 val->edited = True;
652 else if (class == xmListWidgetClass)
654 int pos_cnt;
655 int* pos_list;
656 if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt))
658 int i;
659 widget_value* cur;
660 for (cur = val->contents, i = 0; cur; cur = cur->next)
661 if (cur->value)
663 int j;
664 cur->selected = False;
665 i += 1;
666 for (j = 0; j < pos_cnt; j++)
667 if (pos_list [j] == i)
669 cur->selected = True;
670 val->value = safe_strdup (cur->name);
673 val->edited = 1;
674 XtFree ((char *) pos_list);
680 /* This function is for activating a button from a program. It's wrong because
681 we pass a NULL argument in the call_data which is not Motif compatible.
682 This is used from the XmNdefaultAction callback of the List widgets to
683 have a dble-click put down a dialog box like the button woudl do.
684 I could not find a way to do that with accelerators.
686 static void
687 activate_button (Widget widget, XtPointer closure, XtPointer call_data)
689 Widget button = (Widget)closure;
690 XtCallCallbacks (button, XmNactivateCallback, NULL);
693 /* creation functions */
695 /* dialogs */
696 static Widget
697 make_dialog (char* name, Widget parent, Boolean pop_up_p,
698 char* shell_title, char* icon_name, Boolean text_input_slot,
699 Boolean radio_box, Boolean list,
700 int left_buttons, int right_buttons)
702 Widget result;
703 Widget form;
704 Widget row;
705 Widget icon;
706 Widget icon_separator;
707 Widget message;
708 Widget value = 0;
709 Widget separator;
710 Widget button = 0;
711 Widget children [16]; /* for the final XtManageChildren */
712 int n_children;
713 Arg al[64]; /* Arg List */
714 int ac; /* Arg Count */
715 int i;
717 if (pop_up_p)
719 ac = 0;
720 XtSetArg(al[ac], XmNtitle, shell_title); ac++;
721 XtSetArg(al[ac], XtNallowShellResize, True); ac++;
722 XtSetArg(al[ac], XmNdeleteResponse, XmUNMAP); ac++;
723 result = XmCreateDialogShell (parent, "dialog", al, ac);
724 ac = 0;
725 XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
726 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
727 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
728 form = XmCreateForm (result, shell_title, al, ac);
730 else
732 ac = 0;
733 XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
734 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
735 form = XmCreateForm (parent, shell_title, al, ac);
736 result = form;
739 n_children = left_buttons + right_buttons + 1;
740 ac = 0;
741 XtSetArg(al[ac], XmNpacking, n_children == 3?
742 XmPACK_COLUMN: XmPACK_TIGHT); ac++;
743 XtSetArg(al[ac], XmNorientation, n_children == 3?
744 XmVERTICAL: XmHORIZONTAL); ac++;
745 XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
746 XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
747 XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
748 XtSetArg(al[ac], XmNspacing, 13); ac++;
749 XtSetArg(al[ac], XmNadjustLast, False); ac++;
750 XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
751 XtSetArg(al[ac], XmNisAligned, True); ac++;
752 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
753 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
754 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
755 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
756 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
757 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
758 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
759 row = XmCreateRowColumn (form, "row", al, ac);
761 n_children = 0;
762 for (i = 0; i < left_buttons; i++)
764 char button_name [16];
765 sprintf (button_name, "button%d", i + 1);
766 ac = 0;
767 if (i == 0)
769 XtSetArg(al[ac], XmNhighlightThickness, 1); ac++;
770 XtSetArg(al[ac], XmNshowAsDefault, TRUE); ac++;
772 XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
773 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
774 children [n_children] = XmCreatePushButton (row, button_name, al, ac);
776 if (i == 0)
778 button = children [n_children];
779 ac = 0;
780 XtSetArg(al[ac], XmNdefaultButton, button); ac++;
781 XtSetValues (row, al, ac);
784 n_children++;
787 /* invisible seperator button */
788 ac = 0;
789 XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
790 children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
791 n_children++;
793 for (i = 0; i < right_buttons; i++)
795 char button_name [16];
796 sprintf (button_name, "button%d", left_buttons + i + 1);
797 ac = 0;
798 XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
799 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
800 children [n_children] = XmCreatePushButton (row, button_name, al, ac);
801 if (! button) button = children [n_children];
802 n_children++;
805 XtManageChildren (children, n_children);
807 ac = 0;
808 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
809 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
810 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
811 XtSetArg(al[ac], XmNbottomWidget, row); ac++;
812 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
813 XtSetArg(al[ac], XmNleftOffset, 0); ac++;
814 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
815 XtSetArg(al[ac], XmNrightOffset, 0); ac++;
816 separator = XmCreateSeparator (form, "", al, ac);
818 ac = 0;
819 XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
820 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
821 XtSetArg(al[ac], XmNtopOffset, 13); ac++;
822 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
823 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
824 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
825 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
826 icon = XmCreateLabel (form, icon_name, al, ac);
828 ac = 0;
829 XtSetArg(al[ac], XmNmappedWhenManaged, FALSE); ac++;
830 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
831 XtSetArg(al[ac], XmNtopOffset, 6); ac++;
832 XtSetArg(al[ac], XmNtopWidget, icon); ac++;
833 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
834 XtSetArg(al[ac], XmNbottomOffset, 6); ac++;
835 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
836 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_NONE); ac++;
837 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
838 icon_separator = XmCreateLabel (form, "", al, ac);
840 if (text_input_slot)
842 ac = 0;
843 XtSetArg(al[ac], XmNcolumns, 50); ac++;
844 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
845 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
846 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
847 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
848 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
849 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
850 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
851 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
852 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
853 value = XmCreateTextField (form, "value", al, ac);
855 else if (radio_box)
857 Widget radio_butt;
858 ac = 0;
859 XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
860 XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
861 XtSetArg(al[ac], XmNspacing, 13); ac++;
862 XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
863 XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
864 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
865 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
866 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
867 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
868 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
869 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
870 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
871 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
872 value = XmCreateRadioBox (form, "radiobutton1", al, ac);
873 ac = 0;
874 i = 0;
875 radio_butt = XmCreateToggleButtonGadget (value, "radio1", al, ac);
876 children [i++] = radio_butt;
877 radio_butt = XmCreateToggleButtonGadget (value, "radio2", al, ac);
878 children [i++] = radio_butt;
879 radio_butt = XmCreateToggleButtonGadget (value, "radio3", al, ac);
880 children [i++] = radio_butt;
881 XtManageChildren (children, i);
883 else if (list)
885 ac = 0;
886 XtSetArg(al[ac], XmNvisibleItemCount, 5); ac++;
887 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
888 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
889 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
890 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
891 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
892 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
893 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
894 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
895 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
896 value = XmCreateScrolledList (form, "list", al, ac);
898 /* this is the easiest way I found to have the dble click in the
899 list activate the default button */
900 XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
903 ac = 0;
904 XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
905 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
906 XtSetArg(al[ac], XmNtopOffset, 13); ac++;
907 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
908 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
909 XtSetArg(al[ac], XmNbottomWidget,
910 text_input_slot || radio_box || list ? value : separator); ac++;
911 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
912 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
913 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
914 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
915 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
916 message = XmCreateLabel (form, "message", al, ac);
918 if (list)
919 XtManageChild (value);
921 i = 0;
922 children [i] = row; i++;
923 children [i] = separator; i++;
924 if (text_input_slot || radio_box)
926 children [i] = value; i++;
928 children [i] = message; i++;
929 children [i] = icon; i++;
930 children [i] = icon_separator; i++;
931 XtManageChildren (children, i);
933 if (text_input_slot || list)
935 XtInstallAccelerators (value, button);
936 XtSetKeyboardFocus (result, value);
938 else
940 XtInstallAccelerators (form, button);
941 XtSetKeyboardFocus (result, button);
944 return result;
947 static destroyed_instance*
948 find_matching_instance (widget_instance* instance)
950 destroyed_instance* cur;
951 destroyed_instance* prev;
952 char* type = instance->info->type;
953 char* name = instance->info->name;
955 for (prev = NULL, cur = all_destroyed_instances;
956 cur;
957 prev = cur, cur = cur->next)
959 if (!strcmp (cur->name, name)
960 && !strcmp (cur->type, type)
961 && cur->parent == instance->parent
962 && cur->pop_up_p == instance->pop_up_p)
964 if (prev)
965 prev->next = cur->next;
966 else
967 all_destroyed_instances = cur->next;
968 return cur;
970 /* do some cleanup */
971 else if (!cur->widget)
973 if (prev)
974 prev->next = cur->next;
975 else
976 all_destroyed_instances = cur->next;
977 free_destroyed_instance (cur);
978 cur = prev ? prev : all_destroyed_instances;
981 return NULL;
984 static void
985 mark_dead_instance_destroyed (Widget widget, XtPointer closure,
986 XtPointer call_data)
988 destroyed_instance* instance = (destroyed_instance*)closure;
989 instance->widget = NULL;
992 static void
993 recenter_widget (Widget widget)
995 Widget parent = XtParent (widget);
996 Screen* screen = XtScreen (widget);
997 Dimension screen_width = WidthOfScreen (screen);
998 Dimension screen_height = HeightOfScreen (screen);
999 Dimension parent_width = 0;
1000 Dimension parent_height = 0;
1001 Dimension child_width = 0;
1002 Dimension child_height = 0;
1003 Position x;
1004 Position y;
1006 XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, 0);
1007 XtVaGetValues (parent, XtNwidth, &parent_width, XtNheight, &parent_height,
1010 x = (((Position)parent_width) - ((Position)child_width)) / 2;
1011 y = (((Position)parent_height) - ((Position)child_height)) / 2;
1013 XtTranslateCoords (parent, x, y, &x, &y);
1015 if (x + child_width > screen_width)
1016 x = screen_width - child_width;
1017 if (x < 0)
1018 x = 0;
1020 if (y + child_height > screen_height)
1021 y = screen_height - child_height;
1022 if (y < 0)
1023 y = 0;
1025 XtVaSetValues (widget, XtNx, x, XtNy, y, 0);
1028 static Widget
1029 recycle_instance (destroyed_instance* instance)
1031 Widget widget = instance->widget;
1033 /* widget is NULL if the parent was destroyed. */
1034 if (widget)
1036 Widget focus;
1037 Widget separator;
1039 /* Remove the destroy callback as the instance is not in the list
1040 anymore */
1041 XtRemoveCallback (instance->parent, XtNdestroyCallback,
1042 mark_dead_instance_destroyed,
1043 (XtPointer)instance);
1045 /* Give the focus to the initial item */
1046 focus = XtNameToWidget (widget, "*value");
1047 if (!focus)
1048 focus = XtNameToWidget (widget, "*button1");
1049 if (focus)
1050 XtSetKeyboardFocus (widget, focus);
1052 /* shrink the separator label back to their original size */
1053 separator = XtNameToWidget (widget, "*separator_button");
1054 if (separator)
1055 XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, 0);
1057 /* Center the dialog in its parent */
1058 recenter_widget (widget);
1060 free_destroyed_instance (instance);
1061 return widget;
1064 Widget
1065 xm_create_dialog (widget_instance* instance)
1067 char* name = instance->info->type;
1068 Widget parent = instance->parent;
1069 Widget widget;
1070 Boolean pop_up_p = instance->pop_up_p;
1071 char* shell_name = 0;
1072 char* icon_name;
1073 Boolean text_input_slot = False;
1074 Boolean radio_box = False;
1075 Boolean list = False;
1076 int total_buttons;
1077 int left_buttons = 0;
1078 int right_buttons = 1;
1079 destroyed_instance* dead_one;
1081 /* try to find a widget to recycle */
1082 dead_one = find_matching_instance (instance);
1083 if (dead_one)
1085 Widget recycled_widget = recycle_instance (dead_one);
1086 if (recycled_widget)
1087 return recycled_widget;
1090 switch (name [0]){
1091 case 'E': case 'e':
1092 icon_name = "dbox-error";
1093 shell_name = "Error";
1094 break;
1096 case 'I': case 'i':
1097 icon_name = "dbox-info";
1098 shell_name = "Information";
1099 break;
1101 case 'L': case 'l':
1102 list = True;
1103 icon_name = "dbox-question";
1104 shell_name = "Prompt";
1105 break;
1107 case 'P': case 'p':
1108 text_input_slot = True;
1109 icon_name = "dbox-question";
1110 shell_name = "Prompt";
1111 break;
1113 case 'Q': case 'q':
1114 icon_name = "dbox-question";
1115 shell_name = "Question";
1116 break;
1119 total_buttons = name [1] - '0';
1121 if (name [3] == 'T' || name [3] == 't')
1123 text_input_slot = False;
1124 radio_box = True;
1126 else if (name [3])
1127 right_buttons = name [4] - '0';
1129 left_buttons = total_buttons - right_buttons;
1131 widget = make_dialog (name, parent, pop_up_p,
1132 shell_name, icon_name, text_input_slot, radio_box,
1133 list, left_buttons, right_buttons);
1135 XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
1136 (XtPointer) instance);
1137 return widget;
1140 static Widget
1141 make_menubar (widget_instance* instance)
1143 return XmCreateMenuBar (instance->parent, instance->info->name, NULL, 0);
1146 static void
1147 remove_grabs (Widget shell, XtPointer closure, XtPointer call_data)
1149 XmRowColumnWidget menu = (XmRowColumnWidget) closure;
1150 XmRemoveFromPostFromList (menu, XtParent (XtParent ((Widget) menu)));
1153 static Widget
1154 make_popup_menu (widget_instance* instance)
1156 Widget parent = instance->parent;
1157 Window parent_window = parent->core.window;
1158 Widget result;
1160 /* sets the parent window to 0 to fool Motif into not generating a grab */
1161 parent->core.window = 0;
1162 result = XmCreatePopupMenu (parent, instance->info->name, NULL, 0);
1163 XtAddCallback (XtParent (result), XmNpopdownCallback, remove_grabs,
1164 (XtPointer)result);
1165 parent->core.window = parent_window;
1166 return result;
1168 static Widget
1169 make_main (widget_instance* instance)
1171 Widget parent = instance->parent;
1172 Widget result;
1173 Arg al[2];
1174 int ac;
1176 ac = 0;
1177 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
1178 XtSetArg (al[ac], XmNspacing, 0); ac++;
1179 result = XmCreateMainWindow (parent, instance->info->name, al, ac);
1180 return result;
1183 \f/* Table of functions to create widgets */
1185 #ifdef ENERGIZE
1187 /* interface with the XDesigner generated functions */
1188 typedef Widget (*widget_maker) (Widget);
1189 extern Widget create_project_p_sheet (Widget parent);
1190 extern Widget create_debugger_p_sheet (Widget parent);
1191 extern Widget create_breaklist_p_sheet (Widget parent);
1192 extern Widget create_le_browser_p_sheet (Widget parent);
1193 extern Widget create_class_browser_p_sheet (Widget parent);
1194 extern Widget create_call_browser_p_sheet (Widget parent);
1195 extern Widget create_build_dialog (Widget parent);
1196 extern Widget create_editmode_dialog (Widget parent);
1197 extern Widget create_search_dialog (Widget parent);
1198 extern Widget create_project_display_dialog (Widget parent);
1200 static Widget
1201 make_one (widget_instance* instance, widget_maker fn)
1203 Widget result;
1204 Arg al [64];
1205 int ac = 0;
1207 if (instance->pop_up_p)
1209 XtSetArg (al [ac], XmNallowShellResize, TRUE); ac++;
1210 result = XmCreateDialogShell (instance->parent, "dialog", NULL, 0);
1211 XtAddCallback (result, XmNpopdownCallback, &xm_nosel_callback,
1212 (XtPointer) instance);
1213 (*fn) (result);
1215 else
1217 result = (*fn) (instance->parent);
1218 XtRealizeWidget (result);
1220 return result;
1223 static Widget
1224 make_project_p_sheet (widget_instance* instance)
1226 return make_one (instance, create_project_p_sheet);
1229 static Widget
1230 make_debugger_p_sheet (widget_instance* instance)
1232 return make_one (instance, create_debugger_p_sheet);
1235 static Widget
1236 make_breaklist_p_sheet (widget_instance* instance)
1238 return make_one (instance, create_breaklist_p_sheet);
1241 static Widget
1242 make_le_browser_p_sheet (widget_instance* instance)
1244 return make_one (instance, create_le_browser_p_sheet);
1247 static Widget
1248 make_class_browser_p_sheet (widget_instance* instance)
1250 return make_one (instance, create_class_browser_p_sheet);
1253 static Widget
1254 make_call_browser_p_sheet (widget_instance* instance)
1256 return make_one (instance, create_call_browser_p_sheet);
1259 static Widget
1260 make_build_dialog (widget_instance* instance)
1262 return make_one (instance, create_build_dialog);
1265 static Widget
1266 make_editmode_dialog (widget_instance* instance)
1268 return make_one (instance, create_editmode_dialog);
1271 static Widget
1272 make_search_dialog (widget_instance* instance)
1274 return make_one (instance, create_search_dialog);
1277 static Widget
1278 make_project_display_dialog (widget_instance* instance)
1280 return make_one (instance, create_project_display_dialog);
1283 #endif /* ENERGIZE */
1285 widget_creation_entry
1286 xm_creation_table [] =
1288 {"menubar", make_menubar},
1289 {"popup", make_popup_menu},
1290 {"main", make_main},
1291 #ifdef ENERGIZE
1292 {"project_p_sheet", make_project_p_sheet},
1293 {"debugger_p_sheet", make_debugger_p_sheet},
1294 {"breaklist_psheet", make_breaklist_p_sheet},
1295 {"leb_psheet", make_le_browser_p_sheet},
1296 {"class_browser_psheet", make_class_browser_p_sheet},
1297 {"ctree_browser_psheet", make_call_browser_p_sheet},
1298 {"build", make_build_dialog},
1299 {"editmode", make_editmode_dialog},
1300 {"search", make_search_dialog},
1301 {"project_display", make_project_display_dialog},
1302 #endif /* ENERGIZE */
1303 {NULL, NULL}
1306 \f/* Destruction of instances */
1307 void
1308 xm_destroy_instance (widget_instance* instance)
1310 Widget widget = instance->widget;
1311 /* recycle the dialog boxes */
1312 /* Disable the recycling until we can find a way to have the dialog box
1313 get reasonable layout after we modify its contents. */
1314 if (0
1315 && XtClass (widget) == xmDialogShellWidgetClass)
1317 destroyed_instance* dead_instance =
1318 make_destroyed_instance (instance->info->name,
1319 instance->info->type,
1320 instance->widget,
1321 instance->parent,
1322 instance->pop_up_p);
1323 dead_instance->next = all_destroyed_instances;
1324 all_destroyed_instances = dead_instance;
1325 XtUnmanageChild (first_child (instance->widget));
1326 XFlush (XtDisplay (instance->widget));
1327 XtAddCallback (instance->parent, XtNdestroyCallback,
1328 mark_dead_instance_destroyed, (XtPointer)dead_instance);
1330 else
1332 /* This might not be necessary now that the nosel is attached to
1333 popdown instead of destroy, but it can't hurt. */
1334 XtRemoveCallback (instance->widget, XtNdestroyCallback,
1335 xm_nosel_callback, (XtPointer)instance);
1336 XtDestroyWidget (instance->widget);
1340 \f/* popup utility */
1341 void
1342 xm_popup_menu (Widget widget)
1344 XButtonPressedEvent dummy;
1345 XEvent* event;
1347 dummy.type = ButtonPress;
1348 dummy.serial = 0;
1349 dummy.send_event = 0;
1350 dummy.display = XtDisplay (widget);
1351 dummy.window = XtWindow (XtParent (widget));
1352 dummy.time = 0;
1353 dummy.button = 0;
1354 XQueryPointer (dummy.display, dummy.window, &dummy.root,
1355 &dummy.subwindow, &dummy.x_root, &dummy.y_root,
1356 &dummy.x, &dummy.y, &dummy.state);
1357 event = (XEvent *) &dummy;
1359 if (event->type == ButtonPress || event->type == ButtonRelease)
1361 /* This is so totally ridiculous: there's NO WAY to tell Motif
1362 that *any* button can select a menu item. Only one button
1363 can have that honor.
1365 char *trans = 0;
1366 if (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
1367 else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
1368 else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
1369 else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
1370 else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
1371 if (trans) XtVaSetValues (widget, XmNmenuPost, trans, 0);
1372 XmMenuPosition (widget, (XButtonPressedEvent *) event);
1374 XtManageChild (widget);
1377 static void
1378 set_min_dialog_size (Widget w)
1380 short width;
1381 short height;
1382 XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, 0);
1383 XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, 0);
1386 void
1387 xm_pop_instance (widget_instance* instance, Boolean up)
1389 Widget widget = instance->widget;
1391 if (XtClass (widget) == xmDialogShellWidgetClass)
1393 Widget widget_to_manage = first_child (widget);
1394 if (up)
1396 XtManageChild (widget_to_manage);
1397 set_min_dialog_size (widget);
1398 XtSetKeyboardFocus (instance->parent, widget);
1400 else
1401 XtUnmanageChild (widget_to_manage);
1403 else
1405 if (up)
1406 XtManageChild (widget);
1407 else
1408 XtUnmanageChild (widget);
1413 /* motif callback */
1415 enum do_call_type { pre_activate, selection, no_selection, post_activate };
1417 static void
1418 do_call (Widget widget, XtPointer closure, enum do_call_type type)
1420 Arg al [256];
1421 int ac;
1422 XtPointer user_data;
1423 widget_instance* instance = (widget_instance*)closure;
1424 Widget instance_widget;
1425 LWLIB_ID id;
1427 if (!instance)
1428 return;
1429 if (widget->core.being_destroyed)
1430 return;
1432 instance_widget = instance->widget;
1433 if (!instance_widget)
1434 return;
1436 id = instance->info->id;
1437 ac = 0;
1438 user_data = NULL;
1439 XtSetArg (al [ac], XmNuserData, &user_data); ac++;
1440 XtGetValues (widget, al, ac);
1441 switch (type)
1443 case pre_activate:
1444 if (instance->info->pre_activate_cb)
1445 instance->info->pre_activate_cb (widget, id, user_data);
1446 break;
1447 case selection:
1448 if (instance->info->selection_cb)
1449 instance->info->selection_cb (widget, id, user_data);
1450 break;
1451 case no_selection:
1452 if (instance->info->selection_cb)
1453 instance->info->selection_cb (widget, id, (XtPointer) -1);
1454 break;
1455 case post_activate:
1456 if (instance->info->post_activate_cb)
1457 instance->info->post_activate_cb (widget, id, user_data);
1458 break;
1459 default:
1460 abort ();
1464 /* Like lw_internal_update_other_instances except that it does not do
1465 anything if its shell parent is not managed. This is to protect
1466 lw_internal_update_other_instances to dereference freed memory
1467 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1468 list */
1469 static void
1470 xm_internal_update_other_instances (Widget widget, XtPointer closure,
1471 XtPointer call_data)
1473 Widget parent;
1474 for (parent = widget; parent; parent = XtParent (parent))
1475 if (XtIsShell (parent))
1476 break;
1477 else if (!XtIsManaged (parent))
1478 return;
1479 lw_internal_update_other_instances (widget, closure, call_data);
1482 static void
1483 xm_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
1485 lw_internal_update_other_instances (widget, closure, call_data);
1486 do_call (widget, closure, selection);
1489 static void
1490 xm_nosel_callback (Widget widget, XtPointer closure, XtPointer call_data)
1492 /* This callback is only called when a dialog box is dismissed with the wm's
1493 destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed
1494 in that case, not just unmapped, so that it releases its keyboard grabs.
1495 But there are problems with running our callbacks while the widget is in
1496 the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
1497 instead of XmDESTROY and then destroy it ourself after having run the
1498 callback.
1500 do_call (widget, closure, no_selection);
1501 XtDestroyWidget (widget);
1504 static void
1505 xm_pull_down_callback (Widget widget, XtPointer closure, XtPointer call_data)
1507 do_call (widget, closure, pre_activate);
1510 static void
1511 xm_pop_down_callback (Widget widget, XtPointer closure, XtPointer call_data)
1513 do_call (widget, closure, post_activate);
1517 /* set the keyboard focus */
1518 void
1519 xm_set_keyboard_focus (Widget parent, Widget w)
1521 XmProcessTraversal (w, 0);
1522 XtSetKeyboardFocus (parent, w);
1525 /* Motif hack to set the main window areas. */
1526 void
1527 xm_set_main_areas (parent, menubar, work_area)
1528 Widget parent;
1529 Widget menubar;
1530 Widget work_area;
1532 XmMainWindowSetAreas (parent,
1533 menubar, /* menubar (maybe 0) */
1534 0, /* command area (psheets) */
1535 0, /* horizontal scroll */
1536 0, /* vertical scroll */
1537 work_area); /* work area */
1540 /* Motif hack to control resizing on the menubar. */
1541 void
1542 xm_manage_resizing (w, flag)
1543 Widget w;
1544 Boolean flag;
1546 if (flag)
1548 /* Enable the edit widget for resizing. */
1549 Arg al[1];
1551 XtSetArg (al[0], XtNallowShellResize, 0);
1552 XtSetValues (w, al, 1);
1554 else
1556 /* Disable the edit widget from resizing. */
1557 Arg al[1];
1559 XtSetArg (al[0], XtNallowShellResize, 0);
1560 XtSetValues (w, al, 1);