(file_name_as_directory, Ffile_name_directory)
[emacs.git] / lwlib / lwlib-Xm.c
blob2cb6b9b2a1824bdf62444f27d5c2b7d78b745c54
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
349 && !all_dashes_p (cur->name))
351 ac = 0;
352 XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
353 button = XmCreateLabel (widget, cur->name, al, ac);
355 else if (all_dashes_p (cur->name))
357 button = XmCreateSeparator (widget, cur->name, NULL, 0);
359 else if (!cur->contents)
361 if (menubar_p)
362 button = XmCreateCascadeButton (widget, cur->name, al, ac);
363 else if (!cur->call_data)
364 button = XmCreateLabel (widget, cur->name, al, ac);
365 else
366 button = XmCreatePushButtonGadget (widget, cur->name, al, ac);
368 xm_update_label (instance, button, cur);
370 /* don't add a callback to a simple label */
371 if (cur->call_data)
372 XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
373 (XtPointer)instance);
375 else
377 menu = XmCreatePulldownMenu (widget, "pulldown", NULL, 0);
378 make_menu_in_widget (instance, menu, cur->contents);
379 XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
380 button = XmCreateCascadeButton (widget, cur->name, al, ac);
382 xm_update_label (instance, button, cur);
384 XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
385 (XtPointer)instance);
388 children [child_index] = button;
391 XtManageChildren (children, num_children);
393 /* Last entry is the help button. Has to be done after managing
394 * the buttons otherwise the menubar is only 4 pixels high... */
395 if (button)
397 ac = 0;
398 XtSetArg (al [ac], XmNmenuHelpWidget, button); ac++;
399 XtSetValues (widget, al, ac);
402 XtFree ((char *) children);
405 static void
406 update_one_menu_entry (widget_instance* instance, Widget widget,
407 widget_value* val, Boolean deep_p)
409 Arg al [256];
410 int ac;
411 Widget menu;
412 widget_value* contents;
414 if (val->change == NO_CHANGE)
415 return;
417 /* update the sensitivity and userdata */
418 /* Common to all widget types */
419 XtVaSetValues (widget,
420 XmNsensitive, val->enabled,
421 XmNuserData, val->call_data,
424 /* update the menu button as a label. */
425 if (val->change >= VISIBLE_CHANGE)
426 xm_update_label (instance, widget, val);
428 /* update the pulldown/pullaside as needed */
429 ac = 0;
430 menu = NULL;
431 XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
432 XtGetValues (widget, al, ac);
434 contents = val->contents;
436 if (!menu)
438 if (contents)
440 menu = XmCreatePulldownMenu (XtParent (widget), "pulldown", NULL, 0);
441 make_menu_in_widget (instance, menu, contents);
442 ac = 0;
443 XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
444 XtSetValues (widget, al, ac);
447 else if (!contents)
449 ac = 0;
450 XtSetArg (al [ac], XmNsubMenuId, NULL); ac++;
451 XtSetValues (widget, al, ac);
452 XtDestroyWidget (menu);
454 else if (deep_p && contents->change != NO_CHANGE)
455 xm_update_menu (instance, menu, val, 1);
458 static void
459 xm_update_menu (widget_instance* instance, Widget widget, widget_value* val,
460 Boolean deep_p)
462 /* Widget is a RowColumn widget whose contents have to be updated
463 * to reflect the list of items in val->contents */
464 if (val->contents->change == STRUCTURAL_CHANGE)
466 destroy_all_children (widget);
467 make_menu_in_widget (instance, widget, val->contents);
469 else
471 /* Update all the buttons of the RowColumn in order. */
472 Widget* children;
473 unsigned int num_children;
474 int i;
475 widget_value* cur;
477 children = XtCompositeChildren (widget, &num_children);
478 if (children)
480 for (i = 0, cur = val->contents; i < num_children; i++)
482 if (!cur)
483 abort ();
484 if (children [i]->core.being_destroyed
485 || strcmp (XtName (children [i]), cur->name))
486 continue;
487 update_one_menu_entry (instance, children [i], cur, deep_p);
488 cur = cur->next;
490 XtFree ((char *) children);
492 if (cur)
493 abort ();
498 /* update text widgets */
500 static void
501 xm_update_text (widget_instance* instance, Widget widget, widget_value* val)
503 XmTextSetString (widget, val->value ? val->value : "");
504 XtRemoveAllCallbacks (widget, XmNactivateCallback);
505 XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
506 XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
507 XtAddCallback (widget, XmNvalueChangedCallback,
508 xm_internal_update_other_instances, instance);
511 static void
512 xm_update_text_field (widget_instance* instance, Widget widget,
513 widget_value* val)
515 XmTextFieldSetString (widget, val->value ? val->value : "");
516 XtRemoveAllCallbacks (widget, XmNactivateCallback);
517 XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
518 XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
519 XtAddCallback (widget, XmNvalueChangedCallback,
520 xm_internal_update_other_instances, instance);
524 /* update a motif widget */
526 void
527 xm_update_one_widget (widget_instance* instance, Widget widget,
528 widget_value* val, Boolean deep_p)
530 WidgetClass class;
532 /* Mark as not edited */
533 val->edited = False;
535 /* Common to all widget types */
536 XtVaSetValues (widget,
537 XmNsensitive, val->enabled,
538 XmNuserData, val->call_data,
541 /* Common to all label like widgets */
542 if (XtIsSubclass (widget, xmLabelWidgetClass))
543 xm_update_label (instance, widget, val);
545 class = XtClass (widget);
546 /* Class specific things */
547 if (class == xmPushButtonWidgetClass ||
548 class == xmArrowButtonWidgetClass)
550 xm_update_pushbutton (instance, widget, val);
552 else if (class == xmCascadeButtonWidgetClass)
554 xm_update_cascadebutton (instance, widget, val);
556 else if (class == xmToggleButtonWidgetClass
557 || class == xmToggleButtonGadgetClass)
559 xm_update_toggle (instance, widget, val);
561 else if (class == xmRowColumnWidgetClass)
563 Boolean radiobox = 0;
564 int ac = 0;
565 Arg al [1];
567 XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
568 XtGetValues (widget, al, ac);
570 if (radiobox)
571 xm_update_radiobox (instance, widget, val);
572 else
573 xm_update_menu (instance, widget, val, deep_p);
575 else if (class == xmTextWidgetClass)
577 xm_update_text (instance, widget, val);
579 else if (class == xmTextFieldWidgetClass)
581 xm_update_text_field (instance, widget, val);
583 else if (class == xmListWidgetClass)
585 xm_update_list (instance, widget, val);
589 \f/* getting the value back */
590 void
591 xm_update_one_value (widget_instance* instance, Widget widget,
592 widget_value* val)
594 WidgetClass class = XtClass (widget);
595 widget_value *old_wv;
597 /* copy the call_data slot into the "return" widget_value */
598 for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next)
599 if (!strcmp (val->name, old_wv->name))
601 val->call_data = old_wv->call_data;
602 break;
605 if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
607 XtVaGetValues (widget, XmNset, &val->selected, 0);
608 val->edited = True;
610 else if (class == xmTextWidgetClass)
612 if (val->value)
613 free (val->value);
614 val->value = XmTextGetString (widget);
615 val->edited = True;
617 else if (class == xmTextFieldWidgetClass)
619 if (val->value)
620 free (val->value);
621 val->value = XmTextFieldGetString (widget);
622 val->edited = True;
624 else if (class == xmRowColumnWidgetClass)
626 Boolean radiobox = 0;
627 int ac = 0;
628 Arg al [1];
630 XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
631 XtGetValues (widget, al, ac);
633 if (radiobox)
635 CompositeWidget radio = (CompositeWidget)widget;
636 int i;
637 for (i = 0; i < radio->composite.num_children; i++)
639 int set = False;
640 Widget toggle = radio->composite.children [i];
642 XtVaGetValues (toggle, XmNset, &set, 0);
643 if (set)
645 if (val->value)
646 free (val->value);
647 val->value = safe_strdup (XtName (toggle));
650 val->edited = True;
653 else if (class == xmListWidgetClass)
655 int pos_cnt;
656 int* pos_list;
657 if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt))
659 int i;
660 widget_value* cur;
661 for (cur = val->contents, i = 0; cur; cur = cur->next)
662 if (cur->value)
664 int j;
665 cur->selected = False;
666 i += 1;
667 for (j = 0; j < pos_cnt; j++)
668 if (pos_list [j] == i)
670 cur->selected = True;
671 val->value = safe_strdup (cur->name);
674 val->edited = 1;
675 XtFree ((char *) pos_list);
681 /* This function is for activating a button from a program. It's wrong because
682 we pass a NULL argument in the call_data which is not Motif compatible.
683 This is used from the XmNdefaultAction callback of the List widgets to
684 have a dble-click put down a dialog box like the button woudl do.
685 I could not find a way to do that with accelerators.
687 static void
688 activate_button (Widget widget, XtPointer closure, XtPointer call_data)
690 Widget button = (Widget)closure;
691 XtCallCallbacks (button, XmNactivateCallback, NULL);
694 /* creation functions */
696 /* dialogs */
697 static Widget
698 make_dialog (char* name, Widget parent, Boolean pop_up_p,
699 char* shell_title, char* icon_name, Boolean text_input_slot,
700 Boolean radio_box, Boolean list,
701 int left_buttons, int right_buttons)
703 Widget result;
704 Widget form;
705 Widget row;
706 Widget icon;
707 Widget icon_separator;
708 Widget message;
709 Widget value = 0;
710 Widget separator;
711 Widget button = 0;
712 Widget children [16]; /* for the final XtManageChildren */
713 int n_children;
714 Arg al[64]; /* Arg List */
715 int ac; /* Arg Count */
716 int i;
718 if (pop_up_p)
720 ac = 0;
721 XtSetArg(al[ac], XmNtitle, shell_title); ac++;
722 XtSetArg(al[ac], XtNallowShellResize, True); ac++;
723 XtSetArg(al[ac], XmNdeleteResponse, XmUNMAP); ac++;
724 result = XmCreateDialogShell (parent, "dialog", al, ac);
725 ac = 0;
726 XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
727 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
728 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
729 form = XmCreateForm (result, shell_title, al, ac);
731 else
733 ac = 0;
734 XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
735 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
736 form = XmCreateForm (parent, shell_title, al, ac);
737 result = form;
740 n_children = left_buttons + right_buttons + 1;
741 ac = 0;
742 XtSetArg(al[ac], XmNpacking, n_children == 3?
743 XmPACK_COLUMN: XmPACK_TIGHT); ac++;
744 XtSetArg(al[ac], XmNorientation, n_children == 3?
745 XmVERTICAL: XmHORIZONTAL); ac++;
746 XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
747 XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
748 XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
749 XtSetArg(al[ac], XmNspacing, 13); ac++;
750 XtSetArg(al[ac], XmNadjustLast, False); ac++;
751 XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
752 XtSetArg(al[ac], XmNisAligned, True); ac++;
753 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
754 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
755 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
756 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
757 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
758 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
759 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
760 row = XmCreateRowColumn (form, "row", al, ac);
762 n_children = 0;
763 for (i = 0; i < left_buttons; i++)
765 char button_name [16];
766 sprintf (button_name, "button%d", i + 1);
767 ac = 0;
768 if (i == 0)
770 XtSetArg(al[ac], XmNhighlightThickness, 1); ac++;
771 XtSetArg(al[ac], XmNshowAsDefault, TRUE); ac++;
773 XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
774 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
775 children [n_children] = XmCreatePushButton (row, button_name, al, ac);
777 if (i == 0)
779 button = children [n_children];
780 ac = 0;
781 XtSetArg(al[ac], XmNdefaultButton, button); ac++;
782 XtSetValues (row, al, ac);
785 n_children++;
788 /* invisible seperator button */
789 ac = 0;
790 XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
791 children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
792 n_children++;
794 for (i = 0; i < right_buttons; i++)
796 char button_name [16];
797 sprintf (button_name, "button%d", left_buttons + i + 1);
798 ac = 0;
799 XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
800 XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
801 children [n_children] = XmCreatePushButton (row, button_name, al, ac);
802 if (! button) button = children [n_children];
803 n_children++;
806 XtManageChildren (children, n_children);
808 ac = 0;
809 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
810 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
811 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
812 XtSetArg(al[ac], XmNbottomWidget, row); ac++;
813 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
814 XtSetArg(al[ac], XmNleftOffset, 0); ac++;
815 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
816 XtSetArg(al[ac], XmNrightOffset, 0); ac++;
817 separator = XmCreateSeparator (form, "", al, ac);
819 ac = 0;
820 XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
821 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
822 XtSetArg(al[ac], XmNtopOffset, 13); ac++;
823 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
824 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
825 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
826 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
827 icon = XmCreateLabel (form, icon_name, al, ac);
829 ac = 0;
830 XtSetArg(al[ac], XmNmappedWhenManaged, FALSE); ac++;
831 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
832 XtSetArg(al[ac], XmNtopOffset, 6); ac++;
833 XtSetArg(al[ac], XmNtopWidget, icon); ac++;
834 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
835 XtSetArg(al[ac], XmNbottomOffset, 6); ac++;
836 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
837 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_NONE); ac++;
838 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
839 icon_separator = XmCreateLabel (form, "", al, ac);
841 if (text_input_slot)
843 ac = 0;
844 XtSetArg(al[ac], XmNcolumns, 50); ac++;
845 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
846 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
847 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
848 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
849 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
850 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
851 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
852 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
853 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
854 value = XmCreateTextField (form, "value", al, ac);
856 else if (radio_box)
858 Widget radio_butt;
859 ac = 0;
860 XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
861 XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
862 XtSetArg(al[ac], XmNspacing, 13); ac++;
863 XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
864 XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
865 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
866 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
867 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
868 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
869 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
870 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
871 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
872 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
873 value = XmCreateRadioBox (form, "radiobutton1", al, ac);
874 ac = 0;
875 i = 0;
876 radio_butt = XmCreateToggleButtonGadget (value, "radio1", al, ac);
877 children [i++] = radio_butt;
878 radio_butt = XmCreateToggleButtonGadget (value, "radio2", al, ac);
879 children [i++] = radio_butt;
880 radio_butt = XmCreateToggleButtonGadget (value, "radio3", al, ac);
881 children [i++] = radio_butt;
882 XtManageChildren (children, i);
884 else if (list)
886 ac = 0;
887 XtSetArg(al[ac], XmNvisibleItemCount, 5); ac++;
888 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
889 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
890 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
891 XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
892 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
893 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
894 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
895 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
896 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
897 value = XmCreateScrolledList (form, "list", al, ac);
899 /* this is the easiest way I found to have the dble click in the
900 list activate the default button */
901 XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
904 ac = 0;
905 XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
906 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
907 XtSetArg(al[ac], XmNtopOffset, 13); ac++;
908 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
909 XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
910 XtSetArg(al[ac], XmNbottomWidget,
911 text_input_slot || radio_box || list ? value : separator); ac++;
912 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
913 XtSetArg(al[ac], XmNleftOffset, 13); ac++;
914 XtSetArg(al[ac], XmNleftWidget, icon); ac++;
915 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
916 XtSetArg(al[ac], XmNrightOffset, 13); ac++;
917 message = XmCreateLabel (form, "message", al, ac);
919 if (list)
920 XtManageChild (value);
922 i = 0;
923 children [i] = row; i++;
924 children [i] = separator; i++;
925 if (text_input_slot || radio_box)
927 children [i] = value; i++;
929 children [i] = message; i++;
930 children [i] = icon; i++;
931 children [i] = icon_separator; i++;
932 XtManageChildren (children, i);
934 if (text_input_slot || list)
936 XtInstallAccelerators (value, button);
937 XtSetKeyboardFocus (result, value);
939 else
941 XtInstallAccelerators (form, button);
942 XtSetKeyboardFocus (result, button);
945 return result;
948 static destroyed_instance*
949 find_matching_instance (widget_instance* instance)
951 destroyed_instance* cur;
952 destroyed_instance* prev;
953 char* type = instance->info->type;
954 char* name = instance->info->name;
956 for (prev = NULL, cur = all_destroyed_instances;
957 cur;
958 prev = cur, cur = cur->next)
960 if (!strcmp (cur->name, name)
961 && !strcmp (cur->type, type)
962 && cur->parent == instance->parent
963 && cur->pop_up_p == instance->pop_up_p)
965 if (prev)
966 prev->next = cur->next;
967 else
968 all_destroyed_instances = cur->next;
969 return cur;
971 /* do some cleanup */
972 else if (!cur->widget)
974 if (prev)
975 prev->next = cur->next;
976 else
977 all_destroyed_instances = cur->next;
978 free_destroyed_instance (cur);
979 cur = prev ? prev : all_destroyed_instances;
982 return NULL;
985 static void
986 mark_dead_instance_destroyed (Widget widget, XtPointer closure,
987 XtPointer call_data)
989 destroyed_instance* instance = (destroyed_instance*)closure;
990 instance->widget = NULL;
993 static void
994 recenter_widget (Widget widget)
996 Widget parent = XtParent (widget);
997 Screen* screen = XtScreen (widget);
998 Dimension screen_width = WidthOfScreen (screen);
999 Dimension screen_height = HeightOfScreen (screen);
1000 Dimension parent_width = 0;
1001 Dimension parent_height = 0;
1002 Dimension child_width = 0;
1003 Dimension child_height = 0;
1004 Position x;
1005 Position y;
1007 XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, 0);
1008 XtVaGetValues (parent, XtNwidth, &parent_width, XtNheight, &parent_height,
1011 x = (((Position)parent_width) - ((Position)child_width)) / 2;
1012 y = (((Position)parent_height) - ((Position)child_height)) / 2;
1014 XtTranslateCoords (parent, x, y, &x, &y);
1016 if (x + child_width > screen_width)
1017 x = screen_width - child_width;
1018 if (x < 0)
1019 x = 0;
1021 if (y + child_height > screen_height)
1022 y = screen_height - child_height;
1023 if (y < 0)
1024 y = 0;
1026 XtVaSetValues (widget, XtNx, x, XtNy, y, 0);
1029 static Widget
1030 recycle_instance (destroyed_instance* instance)
1032 Widget widget = instance->widget;
1034 /* widget is NULL if the parent was destroyed. */
1035 if (widget)
1037 Widget focus;
1038 Widget separator;
1040 /* Remove the destroy callback as the instance is not in the list
1041 anymore */
1042 XtRemoveCallback (instance->parent, XtNdestroyCallback,
1043 mark_dead_instance_destroyed,
1044 (XtPointer)instance);
1046 /* Give the focus to the initial item */
1047 focus = XtNameToWidget (widget, "*value");
1048 if (!focus)
1049 focus = XtNameToWidget (widget, "*button1");
1050 if (focus)
1051 XtSetKeyboardFocus (widget, focus);
1053 /* shrink the separator label back to their original size */
1054 separator = XtNameToWidget (widget, "*separator_button");
1055 if (separator)
1056 XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, 0);
1058 /* Center the dialog in its parent */
1059 recenter_widget (widget);
1061 free_destroyed_instance (instance);
1062 return widget;
1065 Widget
1066 xm_create_dialog (widget_instance* instance)
1068 char* name = instance->info->type;
1069 Widget parent = instance->parent;
1070 Widget widget;
1071 Boolean pop_up_p = instance->pop_up_p;
1072 char* shell_name = 0;
1073 char* icon_name;
1074 Boolean text_input_slot = False;
1075 Boolean radio_box = False;
1076 Boolean list = False;
1077 int total_buttons;
1078 int left_buttons = 0;
1079 int right_buttons = 1;
1080 destroyed_instance* dead_one;
1082 /* try to find a widget to recycle */
1083 dead_one = find_matching_instance (instance);
1084 if (dead_one)
1086 Widget recycled_widget = recycle_instance (dead_one);
1087 if (recycled_widget)
1088 return recycled_widget;
1091 switch (name [0]){
1092 case 'E': case 'e':
1093 icon_name = "dbox-error";
1094 shell_name = "Error";
1095 break;
1097 case 'I': case 'i':
1098 icon_name = "dbox-info";
1099 shell_name = "Information";
1100 break;
1102 case 'L': case 'l':
1103 list = True;
1104 icon_name = "dbox-question";
1105 shell_name = "Prompt";
1106 break;
1108 case 'P': case 'p':
1109 text_input_slot = True;
1110 icon_name = "dbox-question";
1111 shell_name = "Prompt";
1112 break;
1114 case 'Q': case 'q':
1115 icon_name = "dbox-question";
1116 shell_name = "Question";
1117 break;
1120 total_buttons = name [1] - '0';
1122 if (name [3] == 'T' || name [3] == 't')
1124 text_input_slot = False;
1125 radio_box = True;
1127 else if (name [3])
1128 right_buttons = name [4] - '0';
1130 left_buttons = total_buttons - right_buttons;
1132 widget = make_dialog (name, parent, pop_up_p,
1133 shell_name, icon_name, text_input_slot, radio_box,
1134 list, left_buttons, right_buttons);
1136 XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
1137 (XtPointer) instance);
1138 return widget;
1141 static Widget
1142 make_menubar (widget_instance* instance)
1144 return XmCreateMenuBar (instance->parent, instance->info->name, NULL, 0);
1147 static void
1148 remove_grabs (Widget shell, XtPointer closure, XtPointer call_data)
1150 XmRowColumnWidget menu = (XmRowColumnWidget) closure;
1151 XmRemoveFromPostFromList (menu, XtParent (XtParent ((Widget) menu)));
1154 static Widget
1155 make_popup_menu (widget_instance* instance)
1157 Widget parent = instance->parent;
1158 Window parent_window = parent->core.window;
1159 Widget result;
1161 /* sets the parent window to 0 to fool Motif into not generating a grab */
1162 parent->core.window = 0;
1163 result = XmCreatePopupMenu (parent, instance->info->name, NULL, 0);
1164 XtAddCallback (XtParent (result), XmNpopdownCallback, remove_grabs,
1165 (XtPointer)result);
1166 parent->core.window = parent_window;
1167 return result;
1169 static Widget
1170 make_main (widget_instance* instance)
1172 Widget parent = instance->parent;
1173 Widget result;
1174 Arg al[2];
1175 int ac;
1177 ac = 0;
1178 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
1179 XtSetArg (al[ac], XmNspacing, 0); ac++;
1180 result = XmCreateMainWindow (parent, instance->info->name, al, ac);
1181 return result;
1184 \f/* Table of functions to create widgets */
1186 #ifdef ENERGIZE
1188 /* interface with the XDesigner generated functions */
1189 typedef Widget (*widget_maker) (Widget);
1190 extern Widget create_project_p_sheet (Widget parent);
1191 extern Widget create_debugger_p_sheet (Widget parent);
1192 extern Widget create_breaklist_p_sheet (Widget parent);
1193 extern Widget create_le_browser_p_sheet (Widget parent);
1194 extern Widget create_class_browser_p_sheet (Widget parent);
1195 extern Widget create_call_browser_p_sheet (Widget parent);
1196 extern Widget create_build_dialog (Widget parent);
1197 extern Widget create_editmode_dialog (Widget parent);
1198 extern Widget create_search_dialog (Widget parent);
1199 extern Widget create_project_display_dialog (Widget parent);
1201 static Widget
1202 make_one (widget_instance* instance, widget_maker fn)
1204 Widget result;
1205 Arg al [64];
1206 int ac = 0;
1208 if (instance->pop_up_p)
1210 XtSetArg (al [ac], XmNallowShellResize, TRUE); ac++;
1211 result = XmCreateDialogShell (instance->parent, "dialog", NULL, 0);
1212 XtAddCallback (result, XmNpopdownCallback, &xm_nosel_callback,
1213 (XtPointer) instance);
1214 (*fn) (result);
1216 else
1218 result = (*fn) (instance->parent);
1219 XtRealizeWidget (result);
1221 return result;
1224 static Widget
1225 make_project_p_sheet (widget_instance* instance)
1227 return make_one (instance, create_project_p_sheet);
1230 static Widget
1231 make_debugger_p_sheet (widget_instance* instance)
1233 return make_one (instance, create_debugger_p_sheet);
1236 static Widget
1237 make_breaklist_p_sheet (widget_instance* instance)
1239 return make_one (instance, create_breaklist_p_sheet);
1242 static Widget
1243 make_le_browser_p_sheet (widget_instance* instance)
1245 return make_one (instance, create_le_browser_p_sheet);
1248 static Widget
1249 make_class_browser_p_sheet (widget_instance* instance)
1251 return make_one (instance, create_class_browser_p_sheet);
1254 static Widget
1255 make_call_browser_p_sheet (widget_instance* instance)
1257 return make_one (instance, create_call_browser_p_sheet);
1260 static Widget
1261 make_build_dialog (widget_instance* instance)
1263 return make_one (instance, create_build_dialog);
1266 static Widget
1267 make_editmode_dialog (widget_instance* instance)
1269 return make_one (instance, create_editmode_dialog);
1272 static Widget
1273 make_search_dialog (widget_instance* instance)
1275 return make_one (instance, create_search_dialog);
1278 static Widget
1279 make_project_display_dialog (widget_instance* instance)
1281 return make_one (instance, create_project_display_dialog);
1284 #endif /* ENERGIZE */
1286 widget_creation_entry
1287 xm_creation_table [] =
1289 {"menubar", make_menubar},
1290 {"popup", make_popup_menu},
1291 {"main", make_main},
1292 #ifdef ENERGIZE
1293 {"project_p_sheet", make_project_p_sheet},
1294 {"debugger_p_sheet", make_debugger_p_sheet},
1295 {"breaklist_psheet", make_breaklist_p_sheet},
1296 {"leb_psheet", make_le_browser_p_sheet},
1297 {"class_browser_psheet", make_class_browser_p_sheet},
1298 {"ctree_browser_psheet", make_call_browser_p_sheet},
1299 {"build", make_build_dialog},
1300 {"editmode", make_editmode_dialog},
1301 {"search", make_search_dialog},
1302 {"project_display", make_project_display_dialog},
1303 #endif /* ENERGIZE */
1304 {NULL, NULL}
1307 \f/* Destruction of instances */
1308 void
1309 xm_destroy_instance (widget_instance* instance)
1311 Widget widget = instance->widget;
1312 /* recycle the dialog boxes */
1313 /* Disable the recycling until we can find a way to have the dialog box
1314 get reasonable layout after we modify its contents. */
1315 if (0
1316 && XtClass (widget) == xmDialogShellWidgetClass)
1318 destroyed_instance* dead_instance =
1319 make_destroyed_instance (instance->info->name,
1320 instance->info->type,
1321 instance->widget,
1322 instance->parent,
1323 instance->pop_up_p);
1324 dead_instance->next = all_destroyed_instances;
1325 all_destroyed_instances = dead_instance;
1326 XtUnmanageChild (first_child (instance->widget));
1327 XFlush (XtDisplay (instance->widget));
1328 XtAddCallback (instance->parent, XtNdestroyCallback,
1329 mark_dead_instance_destroyed, (XtPointer)dead_instance);
1331 else
1333 /* This might not be necessary now that the nosel is attached to
1334 popdown instead of destroy, but it can't hurt. */
1335 XtRemoveCallback (instance->widget, XtNdestroyCallback,
1336 xm_nosel_callback, (XtPointer)instance);
1337 XtDestroyWidget (instance->widget);
1341 \f/* popup utility */
1342 void
1343 xm_popup_menu (Widget widget)
1345 XButtonPressedEvent dummy;
1346 XEvent* event;
1348 dummy.type = ButtonPress;
1349 dummy.serial = 0;
1350 dummy.send_event = 0;
1351 dummy.display = XtDisplay (widget);
1352 dummy.window = XtWindow (XtParent (widget));
1353 dummy.time = 0;
1354 dummy.button = 0;
1355 XQueryPointer (dummy.display, dummy.window, &dummy.root,
1356 &dummy.subwindow, &dummy.x_root, &dummy.y_root,
1357 &dummy.x, &dummy.y, &dummy.state);
1358 event = (XEvent *) &dummy;
1360 if (event->type == ButtonPress || event->type == ButtonRelease)
1362 /* This is so totally ridiculous: there's NO WAY to tell Motif
1363 that *any* button can select a menu item. Only one button
1364 can have that honor.
1366 char *trans = 0;
1367 if (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
1368 else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
1369 else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
1370 else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
1371 else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
1372 if (trans) XtVaSetValues (widget, XmNmenuPost, trans, 0);
1373 XmMenuPosition (widget, (XButtonPressedEvent *) event);
1375 XtManageChild (widget);
1378 static void
1379 set_min_dialog_size (Widget w)
1381 short width;
1382 short height;
1383 XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, 0);
1384 XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, 0);
1387 void
1388 xm_pop_instance (widget_instance* instance, Boolean up)
1390 Widget widget = instance->widget;
1392 if (XtClass (widget) == xmDialogShellWidgetClass)
1394 Widget widget_to_manage = first_child (widget);
1395 if (up)
1397 XtManageChild (widget_to_manage);
1398 set_min_dialog_size (widget);
1399 XtSetKeyboardFocus (instance->parent, widget);
1401 else
1402 XtUnmanageChild (widget_to_manage);
1404 else
1406 if (up)
1407 XtManageChild (widget);
1408 else
1409 XtUnmanageChild (widget);
1414 /* motif callback */
1416 enum do_call_type { pre_activate, selection, no_selection, post_activate };
1418 static void
1419 do_call (Widget widget, XtPointer closure, enum do_call_type type)
1421 Arg al [256];
1422 int ac;
1423 XtPointer user_data;
1424 widget_instance* instance = (widget_instance*)closure;
1425 Widget instance_widget;
1426 LWLIB_ID id;
1428 if (!instance)
1429 return;
1430 if (widget->core.being_destroyed)
1431 return;
1433 instance_widget = instance->widget;
1434 if (!instance_widget)
1435 return;
1437 id = instance->info->id;
1438 ac = 0;
1439 user_data = NULL;
1440 XtSetArg (al [ac], XmNuserData, &user_data); ac++;
1441 XtGetValues (widget, al, ac);
1442 switch (type)
1444 case pre_activate:
1445 if (instance->info->pre_activate_cb)
1446 instance->info->pre_activate_cb (widget, id, user_data);
1447 break;
1448 case selection:
1449 if (instance->info->selection_cb)
1450 instance->info->selection_cb (widget, id, user_data);
1451 break;
1452 case no_selection:
1453 if (instance->info->selection_cb)
1454 instance->info->selection_cb (widget, id, (XtPointer) -1);
1455 break;
1456 case post_activate:
1457 if (instance->info->post_activate_cb)
1458 instance->info->post_activate_cb (widget, id, user_data);
1459 break;
1460 default:
1461 abort ();
1465 /* Like lw_internal_update_other_instances except that it does not do
1466 anything if its shell parent is not managed. This is to protect
1467 lw_internal_update_other_instances to dereference freed memory
1468 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1469 list */
1470 static void
1471 xm_internal_update_other_instances (Widget widget, XtPointer closure,
1472 XtPointer call_data)
1474 Widget parent;
1475 for (parent = widget; parent; parent = XtParent (parent))
1476 if (XtIsShell (parent))
1477 break;
1478 else if (!XtIsManaged (parent))
1479 return;
1480 lw_internal_update_other_instances (widget, closure, call_data);
1483 static void
1484 xm_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
1486 lw_internal_update_other_instances (widget, closure, call_data);
1487 do_call (widget, closure, selection);
1490 static void
1491 xm_nosel_callback (Widget widget, XtPointer closure, XtPointer call_data)
1493 /* This callback is only called when a dialog box is dismissed with the wm's
1494 destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed
1495 in that case, not just unmapped, so that it releases its keyboard grabs.
1496 But there are problems with running our callbacks while the widget is in
1497 the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
1498 instead of XmDESTROY and then destroy it ourself after having run the
1499 callback.
1501 do_call (widget, closure, no_selection);
1502 XtDestroyWidget (widget);
1505 static void
1506 xm_pull_down_callback (Widget widget, XtPointer closure, XtPointer call_data)
1508 do_call (widget, closure, pre_activate);
1511 static void
1512 xm_pop_down_callback (Widget widget, XtPointer closure, XtPointer call_data)
1514 widget_instance *instance = (widget_instance *) closure;
1516 if (!instance->pop_up_p || (XtParent (widget) == instance->parent))
1517 do_call (widget, closure, post_activate);
1521 /* set the keyboard focus */
1522 void
1523 xm_set_keyboard_focus (Widget parent, Widget w)
1525 XmProcessTraversal (w, 0);
1526 XtSetKeyboardFocus (parent, w);
1529 /* Motif hack to set the main window areas. */
1530 void
1531 xm_set_main_areas (parent, menubar, work_area)
1532 Widget parent;
1533 Widget menubar;
1534 Widget work_area;
1536 XmMainWindowSetAreas (parent,
1537 menubar, /* menubar (maybe 0) */
1538 0, /* command area (psheets) */
1539 0, /* horizontal scroll */
1540 0, /* vertical scroll */
1541 work_area); /* work area */
1544 /* Motif hack to control resizing on the menubar. */
1545 void
1546 xm_manage_resizing (w, flag)
1547 Widget w;
1548 Boolean flag;
1550 if (flag)
1552 /* Enable the edit widget for resizing. */
1553 Arg al[1];
1555 XtSetArg (al[0], XtNallowShellResize, 0);
1556 XtSetValues (w, al, 1);
1558 else
1560 /* Disable the edit widget from resizing. */
1561 Arg al[1];
1563 XtSetArg (al[0], XtNallowShellResize, 0);
1564 XtSetValues (w, al, 1);