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)
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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
26 #include <X11/StringDefs.h>
27 #include <X11/IntrinsicP.h>
28 #include <X11/ObjectP.h>
29 #include <X11/CoreP.h>
30 #include <X11/CompositeP.h>
33 #include "lwlib-utils.h"
35 #include <Xm/BulletinB.h>
36 #include <Xm/CascadeB.h>
37 #include <Xm/CascadeBG.h>
38 #include <Xm/DrawingA.h>
39 #include <Xm/FileSB.h>
43 #include <Xm/MenuShell.h>
44 #include <Xm/MessageB.h>
45 #include <Xm/PanedW.h>
47 #include <Xm/PushBG.h>
48 #include <Xm/ArrowB.h>
49 #include <Xm/SelectioB.h>
52 #include <Xm/ToggleB.h>
53 #include <Xm/ToggleBG.h>
54 #include <Xm/RowColumn.h>
55 #include <Xm/ScrolledW.h>
56 #include <Xm/Separator.h>
57 #include <Xm/DialogS.h>
66 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
69 \f/* Structures to keep destroyed instances */
70 typedef struct _destroyed_instance
77 struct _destroyed_instance
* next
;
80 static destroyed_instance
*make_destroyed_instance
P_ ((char *, char *,
83 static void free_destroyed_instance
P_ ((destroyed_instance
*));
84 Widget first_child
P_ ((Widget
));
85 Boolean lw_motif_widget_p
P_ ((Widget
));
86 static XmString resource_motif_string
P_ ((Widget
, char *));
87 static void destroy_all_children
P_ ((Widget
, int));
88 static void xm_update_label
P_ ((widget_instance
*, Widget
, widget_value
*));
89 static void xm_update_list
P_ ((widget_instance
*, Widget
, widget_value
*));
90 static void xm_update_pushbutton
P_ ((widget_instance
*, Widget
,
92 static void xm_update_cascadebutton
P_ ((widget_instance
*, Widget
,
94 static void xm_update_toggle
P_ ((widget_instance
*, Widget
, widget_value
*));
95 static void xm_update_radiobox
P_ ((widget_instance
*, Widget
, widget_value
*));
96 static void make_menu_in_widget
P_ ((widget_instance
*, Widget
,
97 widget_value
*, int));
98 static void update_one_menu_entry
P_ ((widget_instance
*, Widget
,
99 widget_value
*, Boolean
));
100 static void xm_update_menu
P_ ((widget_instance
*, Widget
, widget_value
*,
102 static void xm_update_text
P_ ((widget_instance
*, Widget
, widget_value
*));
103 static void xm_update_text_field
P_ ((widget_instance
*, Widget
,
105 void xm_update_one_value
P_ ((widget_instance
*, Widget
, widget_value
*));
106 static void activate_button
P_ ((Widget
, XtPointer
, XtPointer
));
107 static Widget make_dialog
P_ ((char *, Widget
, Boolean
, char *, char *,
108 Boolean
, Boolean
, Boolean
, int, int));
109 static destroyed_instance
* find_matching_instance
P_ ((widget_instance
*));
110 static void mark_dead_instance_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
111 static void recenter_widget
P_ ((Widget
));
112 static Widget recycle_instance
P_ ((destroyed_instance
*));
113 Widget xm_create_dialog
P_ ((widget_instance
*));
114 static Widget make_menubar
P_ ((widget_instance
*));
115 static void remove_grabs
P_ ((Widget
, XtPointer
, XtPointer
));
116 static Widget make_popup_menu
P_ ((widget_instance
*));
117 static Widget make_main
P_ ((widget_instance
*));
118 void xm_destroy_instance
P_ ((widget_instance
*));
119 void xm_popup_menu
P_ ((Widget
, XEvent
*));
120 static void set_min_dialog_size
P_ ((Widget
));
121 static void do_call
P_ ((Widget
, XtPointer
, enum do_call_type
));
122 static void xm_generic_callback
P_ ((Widget
, XtPointer
, XtPointer
));
123 static void xm_nosel_callback
P_ ((Widget
, XtPointer
, XtPointer
));
124 static void xm_pull_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
125 static void xm_pop_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
126 void xm_set_keyboard_focus
P_ ((Widget
, Widget
));
127 void xm_set_main_areas
P_ ((Widget
, Widget
, Widget
));
128 static void xm_internal_update_other_instances
P_ ((Widget
, XtPointer
,
132 void xm_update_one_widget
P_ ((widget_instance
*, Widget
, widget_value
*,
134 void xm_pop_instance
P_ ((widget_instance
*, Boolean
));
135 void xm_manage_resizing
P_ ((Widget
, Boolean
));
139 static destroyed_instance
*
140 all_destroyed_instances
= NULL
;
142 static destroyed_instance
*
143 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
150 destroyed_instance
* instance
=
151 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
152 instance
->name
= safe_strdup (name
);
153 instance
->type
= safe_strdup (type
);
154 instance
->widget
= widget
;
155 instance
->parent
= parent
;
156 instance
->pop_up_p
= pop_up_p
;
157 instance
->next
= NULL
;
162 free_destroyed_instance (instance
)
163 destroyed_instance
* instance
;
165 free (instance
->name
);
166 free (instance
->type
);
170 \f/* motif utility functions */
175 return ((CompositeWidget
)widget
)->composite
.children
[0];
179 lw_motif_widget_p (widget
)
183 XtClass (widget
) == xmDialogShellWidgetClass
184 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
188 resource_motif_string (widget
, name
)
195 resource
.resource_name
= name
;
196 resource
.resource_class
= XmCXmString
;
197 resource
.resource_type
= XmRXmString
;
198 resource
.resource_size
= sizeof (XmString
);
199 resource
.resource_offset
= 0;
200 resource
.default_type
= XtRImmediate
;
201 resource
.default_addr
= 0;
203 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
204 "DialogString", &resource
, 1, NULL
, 0);
208 /* Destroy all of the children of WIDGET
209 starting with number FIRST_CHILD_TO_DESTROY. */
212 destroy_all_children (widget
, first_child_to_destroy
)
214 int first_child_to_destroy
;
220 children
= XtCompositeChildren (widget
, &number
);
223 XtUnmanageChildren (children
+ first_child_to_destroy
,
224 number
- first_child_to_destroy
);
226 /* Unmanage all children and destroy them. They will only be
227 really destroyed when we get out of DispatchEvent. */
228 for (i
= first_child_to_destroy
; i
< number
; i
++)
232 /* Cascade buttons have submenus,and these submenus
233 need to be freed. But they are not included in
234 XtCompositeChildren. So get it out of the cascade button
235 and free it. If this child is not a cascade button,
236 then submenu should remain unchanged. */
237 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
238 XtGetValues (children
[i
], al
, 1);
240 XtDestroyWidget (submenu
);
241 XtDestroyWidget (children
[i
]);
244 XtFree ((char *) children
);
249 /* Update the label of widget WIDGET. WIDGET must be a Label widget
250 or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
255 Emacs fills VAL->name with the text to display in the menu, and
256 sets VAL->value to null. Function make_menu_in_widget creates
257 widgets with VAL->name as resource name. This works because the
258 Label widget uses its resource name for display if no
259 XmNlabelString is set.
263 VAL->name is again set to the resource name, but VAL->value is
264 not null, and contains the label string to display. */
267 xm_update_label (instance
, widget
, val
)
268 widget_instance
* instance
;
272 XmString res_string
= 0;
273 XmString built_string
= 0;
274 XmString key_string
= 0;
282 /* A label string is specified, i.e. we are in a dialog. First
283 see if it is overridden by something from the resource file. */
284 res_string
= resource_motif_string (widget
, val
->value
);
288 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
293 XmStringCreateLtoR (val
->value
, XmSTRING_DEFAULT_CHARSET
);
294 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
297 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
302 key_string
= XmStringCreateLtoR (val
->key
, XmSTRING_DEFAULT_CHARSET
);
303 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
307 XtSetValues (widget
, al
, ac
);
310 XmStringFree (built_string
);
313 XmStringFree (key_string
);
316 \f/* update of list */
318 xm_update_list (instance
, widget
, val
)
319 widget_instance
* instance
;
325 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
326 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
328 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
331 XmString xmstr
= XmStringCreate (cur
->value
, XmSTRING_DEFAULT_CHARSET
);
333 XmListAddItem (widget
, xmstr
, 0);
335 XmListSelectPos (widget
, i
, False
);
336 XmStringFree (xmstr
);
340 \f/* update of buttons */
342 xm_update_pushbutton (instance
, widget
, val
)
343 widget_instance
* instance
;
347 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, 0);
348 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
349 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
353 xm_update_cascadebutton (instance
, widget
, val
)
354 widget_instance
* instance
;
358 /* Should also rebuild the menu by calling ...update_menu... */
359 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
360 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
364 \f/* update toggle and radiobox */
366 xm_update_toggle (instance
, widget
, val
)
367 widget_instance
* instance
;
371 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
372 XtAddCallback (widget
, XmNvalueChangedCallback
,
373 xm_generic_callback
, instance
);
374 XtVaSetValues (widget
, XmNset
, val
->selected
,
375 XmNalignment
, XmALIGNMENT_BEGINNING
, 0);
379 xm_update_radiobox (instance
, widget
, val
)
380 widget_instance
* instance
;
388 /* update the callback */
389 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
390 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
392 /* first update all the toggles */
393 /* Energize kernel interface is currently bad. It sets the selected widget
394 with the selected flag but returns it by its name. So we currently
395 have to support both setting the selection with the selected slot
396 of val contents and setting it with the "value" slot of val. The latter
397 has a higher priority. This to be removed when the kernel is fixed. */
398 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
400 toggle
= XtNameToWidget (widget
, cur
->value
);
403 XtVaSetValues (toggle
, XmNsensitive
, cur
->enabled
, 0);
404 if (!val
->value
&& cur
->selected
)
405 XtVaSetValues (toggle
, XmNset
, cur
->selected
, 0);
406 if (val
->value
&& strcmp (val
->value
, cur
->value
))
407 XtVaSetValues (toggle
, XmNset
, False
, 0);
411 /* The selected was specified by the value slot */
414 toggle
= XtNameToWidget (widget
, val
->value
);
416 XtVaSetValues (toggle
, XmNset
, True
, 0);
421 /* update a popup menu, pulldown menu or a menubar */
423 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
426 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
427 widget_instance
* instance
;
430 int keep_first_children
;
432 Widget
* children
= 0;
444 Widget
* old_children
;
445 unsigned int old_num_children
;
447 old_children
= XtCompositeChildren (widget
, &old_num_children
);
449 /* Allocate the children array */
450 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
);
451 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
453 /* WIDGET should be a RowColumn. */
454 if (!XmIsRowColumn (widget
))
457 /* Determine whether WIDGET is a menu bar. */
459 XtSetArg (al
[0], XmNrowColumnType
, &type
);
460 XtGetValues (widget
, al
, 1);
461 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
463 menubar_p
= type
== XmMENU_BAR
;
465 /* Add a callback to popups and pulldowns that is called when
466 it is made invisible again. */
468 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
469 xm_pop_down_callback
, (XtPointer
)instance
);
471 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
472 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
473 child_index
++, cur
= cur
->next
)
474 children
[child_index
] = old_children
[child_index
];
476 /* Check that those are all we have
477 (the caller should have deleted the rest). */
478 if (old_num_children
!= keep_first_children
)
481 /* Create the rest. */
482 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
484 enum menu_separator separator
;
487 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
488 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
489 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
491 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
492 && !lw_separator_p (cur
->name
, &separator
, 1))
495 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
496 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
498 else if (lw_separator_p (cur
->name
, &separator
, 1))
501 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
502 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
504 else if (!cur
->contents
)
507 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
508 else if (!cur
->call_data
)
509 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
510 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
511 || cur
->button_type
== BUTTON_TYPE_RADIO
)
513 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
514 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
515 XtSetArg (al
[ac
], XmNindicatorType
,
516 (cur
->button_type
== BUTTON_TYPE_TOGGLE
517 ? XmN_OF_MANY
: XmONE_OF_MANY
));
519 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
522 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
524 xm_update_label (instance
, button
, cur
);
526 /* Add a callback that is called when the button is
527 selected. Toggle buttons don't support
528 XmNactivateCallback, we use XmNvalueChangedCallback in
529 that case. Don't add a callback to a simple label. */
530 if (cur
->button_type
)
531 xm_update_toggle (instance
, button
, cur
);
532 else if (cur
->call_data
)
533 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
534 (XtPointer
)instance
);
538 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
539 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
540 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
541 /* Non-zero values don't work reliably in conjunction with
543 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
544 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
546 xm_update_label (instance
, button
, cur
);
548 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
549 (XtPointer
)instance
);
552 children
[child_index
] = button
;
555 /* Last entry is the help button. The original comment read "Has to
556 be done after managing the buttons otherwise the menubar is only
557 4 pixels high." This is no longer true, and to make
558 XmNmenuHelpWidget work, we need to set it before managing the
559 children.. --gerd. */
561 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, 0);
563 /* LessTif apparently doesn't recompute centered text when more
564 widgets are added. So, do it after all widgets have been
567 XtVaSetValues (title
, XmNalignment
, XmALIGNMENT_CENTER
, 0);
570 XtManageChildren (children
, num_children
);
572 XtFree ((char *) children
);
574 XtFree ((char *) old_children
);
578 update_one_menu_entry (instance
, widget
, val
, deep_p
)
579 widget_instance
* instance
;
587 widget_value
* contents
;
589 if (val
->this_one_change
== NO_CHANGE
)
592 /* update the sensitivity and userdata */
593 /* Common to all widget types */
594 XtVaSetValues (widget
,
595 XmNsensitive
, val
->enabled
,
596 XmNuserData
, val
->call_data
,
599 /* update the menu button as a label. */
600 if (val
->this_one_change
>= VISIBLE_CHANGE
)
602 xm_update_label (instance
, widget
, val
);
603 if (val
->button_type
)
604 xm_update_toggle (instance
, widget
, val
);
607 /* update the pulldown/pullaside as needed */
610 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
611 XtGetValues (widget
, al
, ac
);
613 contents
= val
->contents
;
619 unsigned int old_num_children
, i
;
623 parent
= XtParent (widget
);
624 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
626 /* Find the widget position within the parent's widget list. */
627 for (i
= 0; i
< old_num_children
; i
++)
628 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
630 if (i
== old_num_children
)
632 if (XmIsCascadeButton (widget_list
[i
]))
634 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
635 make_menu_in_widget (instance
, menu
, contents
, 0);
637 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
638 XtSetValues (widget
, al
, ac
);
644 /* The current menuitem is a XmPushButtonGadget, it
645 needs to be replaced by a CascadeButtonGadget */
646 XtDestroyWidget (widget_list
[i
]);
647 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
648 make_menu_in_widget (instance
, menu
, contents
, 0);
650 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
651 /* Non-zero values don't work reliably in
652 conjunction with Emacs' event loop */
653 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
654 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
655 /* Tell Motif to put it in the right place */
656 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
658 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
659 xm_update_label (instance
, button
, val
);
661 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
662 (XtPointer
)instance
);
663 XtManageChild (button
);
670 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
671 XtSetValues (widget
, al
, ac
);
672 XtDestroyWidget (menu
);
674 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
675 xm_update_menu (instance
, menu
, val
, 1);
679 xm_update_menu (instance
, widget
, val
, deep_p
)
680 widget_instance
* instance
;
686 unsigned int num_children
;
687 int num_children_to_keep
= 0;
691 children
= XtCompositeChildren (widget
, &num_children
);
693 /* Widget is a RowColumn widget whose contents have to be updated
694 * to reflect the list of items in val->contents */
696 /* See how many buttons we can keep, and how many we
697 must completely replace. */
698 if (val
->contents
== 0)
699 num_children_to_keep
= 0;
700 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
704 for (i
= 0, cur
= val
->contents
;
706 && cur
); /* how else to ditch unwanted children ?? - mgd */
707 i
++, cur
= cur
->next
)
709 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
713 num_children_to_keep
= i
;
717 num_children_to_keep
= num_children
;
719 /* Update all the buttons of the RowColumn, in order,
720 except for those we are going to replace entirely. */
723 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
727 num_children_to_keep
= i
;
730 if (children
[i
]->core
.being_destroyed
731 || strcmp (XtName (children
[i
]), cur
->name
))
733 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
738 /* Now replace from scratch all the buttons after the last
739 place that the top-level structure changed. */
740 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
742 destroy_all_children (widget
, num_children_to_keep
);
743 make_menu_in_widget (instance
, widget
, val
->contents
,
744 num_children_to_keep
);
747 XtFree ((char *) children
);
751 /* update text widgets */
754 xm_update_text (instance
, widget
, val
)
755 widget_instance
* instance
;
759 XmTextSetString (widget
, val
->value
? val
->value
: "");
760 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
761 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
762 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
763 XtAddCallback (widget
, XmNvalueChangedCallback
,
764 xm_internal_update_other_instances
, instance
);
768 xm_update_text_field (instance
, widget
, val
)
769 widget_instance
* instance
;
773 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
774 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
775 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
776 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
777 XtAddCallback (widget
, XmNvalueChangedCallback
,
778 xm_internal_update_other_instances
, instance
);
782 /* update a motif widget */
785 xm_update_one_widget (instance
, widget
, val
, deep_p
)
786 widget_instance
* instance
;
793 /* Mark as not edited */
796 /* Common to all widget types */
797 XtVaSetValues (widget
,
798 XmNsensitive
, val
->enabled
,
799 XmNuserData
, val
->call_data
,
802 /* Common to all label like widgets */
803 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
804 xm_update_label (instance
, widget
, val
);
806 class = XtClass (widget
);
807 /* Class specific things */
808 if (class == xmPushButtonWidgetClass
||
809 class == xmArrowButtonWidgetClass
)
811 xm_update_pushbutton (instance
, widget
, val
);
813 else if (class == xmCascadeButtonWidgetClass
)
815 xm_update_cascadebutton (instance
, widget
, val
);
817 else if (class == xmToggleButtonWidgetClass
818 || class == xmToggleButtonGadgetClass
)
820 xm_update_toggle (instance
, widget
, val
);
822 else if (class == xmRowColumnWidgetClass
)
824 Boolean radiobox
= 0;
828 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
829 XtGetValues (widget
, al
, ac
);
832 xm_update_radiobox (instance
, widget
, val
);
834 xm_update_menu (instance
, widget
, val
, deep_p
);
836 else if (class == xmTextWidgetClass
)
838 xm_update_text (instance
, widget
, val
);
840 else if (class == xmTextFieldWidgetClass
)
842 xm_update_text_field (instance
, widget
, val
);
844 else if (class == xmListWidgetClass
)
846 xm_update_list (instance
, widget
, val
);
850 \f/* getting the value back */
852 xm_update_one_value (instance
, widget
, val
)
853 widget_instance
* instance
;
857 WidgetClass
class = XtClass (widget
);
858 widget_value
*old_wv
;
860 /* copy the call_data slot into the "return" widget_value */
861 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
862 if (!strcmp (val
->name
, old_wv
->name
))
864 val
->call_data
= old_wv
->call_data
;
868 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
870 XtVaGetValues (widget
, XmNset
, &val
->selected
, 0);
873 else if (class == xmTextWidgetClass
)
877 val
->value
= XmTextGetString (widget
);
880 else if (class == xmTextFieldWidgetClass
)
884 val
->value
= XmTextFieldGetString (widget
);
887 else if (class == xmRowColumnWidgetClass
)
889 Boolean radiobox
= 0;
893 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
894 XtGetValues (widget
, al
, ac
);
898 CompositeWidget radio
= (CompositeWidget
)widget
;
900 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
903 Widget toggle
= radio
->composite
.children
[i
];
905 XtVaGetValues (toggle
, XmNset
, &set
, 0);
910 val
->value
= safe_strdup (XtName (toggle
));
916 else if (class == xmListWidgetClass
)
920 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
924 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
928 cur
->selected
= False
;
930 for (j
= 0; j
< pos_cnt
; j
++)
931 if (pos_list
[j
] == i
)
933 cur
->selected
= True
;
934 val
->value
= safe_strdup (cur
->name
);
938 XtFree ((char *) pos_list
);
944 /* This function is for activating a button from a program. It's wrong because
945 we pass a NULL argument in the call_data which is not Motif compatible.
946 This is used from the XmNdefaultAction callback of the List widgets to
947 have a double-click put down a dialog box like the button would do.
948 I could not find a way to do that with accelerators.
951 activate_button (widget
, closure
, call_data
)
956 Widget button
= (Widget
)closure
;
957 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
960 /* creation functions */
964 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
965 radio_box
, list
, left_buttons
, right_buttons
)
971 Boolean text_input_slot
;
981 Widget icon_separator
;
986 Widget children
[16]; /* for the final XtManageChildren */
988 Arg al
[64]; /* Arg List */
989 int ac
; /* Arg Count */
995 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
996 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
997 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
998 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1000 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1001 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1002 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1003 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1008 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1009 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1010 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1014 n_children
= left_buttons
+ right_buttons
+ 1;
1016 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1017 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1018 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1019 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1020 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1021 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1022 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1023 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1024 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1025 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1026 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1027 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1028 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1029 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1030 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1031 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1032 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1033 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1034 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1037 for (i
= 0; i
< left_buttons
; i
++)
1039 char button_name
[16];
1040 sprintf (button_name
, "button%d", i
+ 1);
1044 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1045 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1047 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1048 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1049 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1053 button
= children
[n_children
];
1055 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1056 XtSetValues (row
, al
, ac
);
1062 /* invisible separator button */
1064 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1065 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1068 for (i
= 0; i
< right_buttons
; i
++)
1070 char button_name
[16];
1071 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1073 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1074 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1075 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1076 if (! button
) button
= children
[n_children
];
1080 XtManageChildren (children
, n_children
);
1083 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1084 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1085 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1086 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1087 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1088 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1089 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1090 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1091 separator
= XmCreateSeparator (form
, "", al
, ac
);
1094 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1095 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1096 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1097 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1098 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1099 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1100 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1101 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1104 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1105 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1106 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1107 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1108 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1109 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1110 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1111 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1112 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1113 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1115 if (text_input_slot
)
1118 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1119 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1120 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1121 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1122 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1123 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1124 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1125 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1126 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1127 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1128 value
= XmCreateTextField (form
, "value", al
, ac
);
1134 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1135 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1136 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1137 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1138 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1139 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1140 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1141 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1142 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1143 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1144 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1145 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1146 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1147 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1150 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1151 children
[i
++] = radio_butt
;
1152 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1153 children
[i
++] = radio_butt
;
1154 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1155 children
[i
++] = radio_butt
;
1156 XtManageChildren (children
, i
);
1161 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1162 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1163 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1164 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1165 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1166 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1167 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1168 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1169 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1170 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1171 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1173 /* this is the easiest way I found to have the dble click in the
1174 list activate the default button */
1175 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1179 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1180 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1181 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1182 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1183 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1184 XtSetArg(al
[ac
], XmNbottomWidget
,
1185 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1186 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1187 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1188 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1189 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1190 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1191 message
= XmCreateLabel (form
, "message", al
, ac
);
1194 XtManageChild (value
);
1197 children
[i
] = row
; i
++;
1198 children
[i
] = separator
; i
++;
1199 if (text_input_slot
|| radio_box
)
1201 children
[i
] = value
; i
++;
1203 children
[i
] = message
; i
++;
1204 children
[i
] = icon
; i
++;
1205 children
[i
] = icon_separator
; i
++;
1206 XtManageChildren (children
, i
);
1208 if (text_input_slot
|| list
)
1210 XtInstallAccelerators (value
, button
);
1211 XtSetKeyboardFocus (result
, value
);
1215 XtInstallAccelerators (form
, button
);
1216 XtSetKeyboardFocus (result
, button
);
1222 static destroyed_instance
*
1223 find_matching_instance (instance
)
1224 widget_instance
* instance
;
1226 destroyed_instance
* cur
;
1227 destroyed_instance
* prev
;
1228 char* type
= instance
->info
->type
;
1229 char* name
= instance
->info
->name
;
1231 for (prev
= NULL
, cur
= all_destroyed_instances
;
1233 prev
= cur
, cur
= cur
->next
)
1235 if (!strcmp (cur
->name
, name
)
1236 && !strcmp (cur
->type
, type
)
1237 && cur
->parent
== instance
->parent
1238 && cur
->pop_up_p
== instance
->pop_up_p
)
1241 prev
->next
= cur
->next
;
1243 all_destroyed_instances
= cur
->next
;
1246 /* do some cleanup */
1247 else if (!cur
->widget
)
1250 prev
->next
= cur
->next
;
1252 all_destroyed_instances
= cur
->next
;
1253 free_destroyed_instance (cur
);
1254 cur
= prev
? prev
: all_destroyed_instances
;
1261 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1264 XtPointer call_data
;
1266 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1267 instance
->widget
= NULL
;
1271 recenter_widget (widget
)
1274 Widget parent
= XtParent (widget
);
1275 Screen
* screen
= XtScreen (widget
);
1276 Dimension screen_width
= WidthOfScreen (screen
);
1277 Dimension screen_height
= HeightOfScreen (screen
);
1278 Dimension parent_width
= 0;
1279 Dimension parent_height
= 0;
1280 Dimension child_width
= 0;
1281 Dimension child_height
= 0;
1285 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, 0);
1286 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1289 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1290 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1292 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1294 if (x
+ child_width
> screen_width
)
1295 x
= screen_width
- child_width
;
1299 if (y
+ child_height
> screen_height
)
1300 y
= screen_height
- child_height
;
1304 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, 0);
1308 recycle_instance (instance
)
1309 destroyed_instance
* instance
;
1311 Widget widget
= instance
->widget
;
1313 /* widget is NULL if the parent was destroyed. */
1319 /* Remove the destroy callback as the instance is not in the list
1321 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1322 mark_dead_instance_destroyed
,
1323 (XtPointer
)instance
);
1325 /* Give the focus to the initial item */
1326 focus
= XtNameToWidget (widget
, "*value");
1328 focus
= XtNameToWidget (widget
, "*button1");
1330 XtSetKeyboardFocus (widget
, focus
);
1332 /* shrink the separator label back to their original size */
1333 separator
= XtNameToWidget (widget
, "*separator_button");
1335 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, 0);
1337 /* Center the dialog in its parent */
1338 recenter_widget (widget
);
1340 free_destroyed_instance (instance
);
1345 xm_create_dialog (instance
)
1346 widget_instance
* instance
;
1348 char* name
= instance
->info
->type
;
1349 Widget parent
= instance
->parent
;
1351 Boolean pop_up_p
= instance
->pop_up_p
;
1352 char* shell_name
= 0;
1354 Boolean text_input_slot
= False
;
1355 Boolean radio_box
= False
;
1356 Boolean list
= False
;
1358 int left_buttons
= 0;
1359 int right_buttons
= 1;
1360 destroyed_instance
* dead_one
;
1362 /* try to find a widget to recycle */
1363 dead_one
= find_matching_instance (instance
);
1366 Widget recycled_widget
= recycle_instance (dead_one
);
1367 if (recycled_widget
)
1368 return recycled_widget
;
1373 icon_name
= "dbox-error";
1374 shell_name
= "Error";
1378 icon_name
= "dbox-info";
1379 shell_name
= "Information";
1384 icon_name
= "dbox-question";
1385 shell_name
= "Prompt";
1389 text_input_slot
= True
;
1390 icon_name
= "dbox-question";
1391 shell_name
= "Prompt";
1395 icon_name
= "dbox-question";
1396 shell_name
= "Question";
1400 total_buttons
= name
[1] - '0';
1402 if (name
[3] == 'T' || name
[3] == 't')
1404 text_input_slot
= False
;
1408 right_buttons
= name
[4] - '0';
1410 left_buttons
= total_buttons
- right_buttons
;
1412 widget
= make_dialog (name
, parent
, pop_up_p
,
1413 shell_name
, icon_name
, text_input_slot
, radio_box
,
1414 list
, left_buttons
, right_buttons
);
1416 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1417 (XtPointer
) instance
);
1421 /* Create a menu bar. We turn off the f10 key
1422 because we have not yet managed to make it work right in Motif. */
1425 make_menubar (instance
)
1426 widget_instance
* instance
;
1432 XtSetArg(al
[0], XmNmenuAccelerator
, 0);
1433 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, 1);
1437 remove_grabs (shell
, closure
, call_data
)
1440 XtPointer call_data
;
1442 Widget menu
= (Widget
) closure
;
1443 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1447 make_popup_menu (instance
)
1448 widget_instance
* instance
;
1450 Widget parent
= instance
->parent
;
1451 Window parent_window
= parent
->core
.window
;
1454 /* sets the parent window to 0 to fool Motif into not generating a grab */
1455 parent
->core
.window
= 0;
1456 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1457 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1459 parent
->core
.window
= parent_window
;
1464 make_main (instance
)
1465 widget_instance
* instance
;
1467 Widget parent
= instance
->parent
;
1473 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1474 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1475 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1479 \f/* Table of functions to create widgets */
1483 /* interface with the XDesigner generated functions */
1484 typedef Widget (*widget_maker
) (Widget
);
1485 extern Widget
create_project_p_sheet (Widget parent
);
1486 extern Widget
create_debugger_p_sheet (Widget parent
);
1487 extern Widget
create_breaklist_p_sheet (Widget parent
);
1488 extern Widget
create_le_browser_p_sheet (Widget parent
);
1489 extern Widget
create_class_browser_p_sheet (Widget parent
);
1490 extern Widget
create_call_browser_p_sheet (Widget parent
);
1491 extern Widget
create_build_dialog (Widget parent
);
1492 extern Widget
create_editmode_dialog (Widget parent
);
1493 extern Widget
create_search_dialog (Widget parent
);
1494 extern Widget
create_project_display_dialog (Widget parent
);
1497 make_one (widget_instance
* instance
, widget_maker fn
)
1503 if (instance
->pop_up_p
)
1505 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1506 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1507 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1508 (XtPointer
) instance
);
1513 result
= (*fn
) (instance
->parent
);
1514 XtRealizeWidget (result
);
1520 make_project_p_sheet (widget_instance
* instance
)
1522 return make_one (instance
, create_project_p_sheet
);
1526 make_debugger_p_sheet (widget_instance
* instance
)
1528 return make_one (instance
, create_debugger_p_sheet
);
1532 make_breaklist_p_sheet (widget_instance
* instance
)
1534 return make_one (instance
, create_breaklist_p_sheet
);
1538 make_le_browser_p_sheet (widget_instance
* instance
)
1540 return make_one (instance
, create_le_browser_p_sheet
);
1544 make_class_browser_p_sheet (widget_instance
* instance
)
1546 return make_one (instance
, create_class_browser_p_sheet
);
1550 make_call_browser_p_sheet (widget_instance
* instance
)
1552 return make_one (instance
, create_call_browser_p_sheet
);
1556 make_build_dialog (widget_instance
* instance
)
1558 return make_one (instance
, create_build_dialog
);
1562 make_editmode_dialog (widget_instance
* instance
)
1564 return make_one (instance
, create_editmode_dialog
);
1568 make_search_dialog (widget_instance
* instance
)
1570 return make_one (instance
, create_search_dialog
);
1574 make_project_display_dialog (widget_instance
* instance
)
1576 return make_one (instance
, create_project_display_dialog
);
1579 #endif /* ENERGIZE */
1581 widget_creation_entry
1582 xm_creation_table
[] =
1584 {"menubar", make_menubar
},
1585 {"popup", make_popup_menu
},
1586 {"main", make_main
},
1588 {"project_p_sheet", make_project_p_sheet
},
1589 {"debugger_p_sheet", make_debugger_p_sheet
},
1590 {"breaklist_psheet", make_breaklist_p_sheet
},
1591 {"leb_psheet", make_le_browser_p_sheet
},
1592 {"class_browser_psheet", make_class_browser_p_sheet
},
1593 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1594 {"build", make_build_dialog
},
1595 {"editmode", make_editmode_dialog
},
1596 {"search", make_search_dialog
},
1597 {"project_display", make_project_display_dialog
},
1598 #endif /* ENERGIZE */
1602 \f/* Destruction of instances */
1604 xm_destroy_instance (instance
)
1605 widget_instance
* instance
;
1607 Widget widget
= instance
->widget
;
1608 /* recycle the dialog boxes */
1609 /* Disable the recycling until we can find a way to have the dialog box
1610 get reasonable layout after we modify its contents. */
1612 && XtClass (widget
) == xmDialogShellWidgetClass
)
1614 destroyed_instance
* dead_instance
=
1615 make_destroyed_instance (instance
->info
->name
,
1616 instance
->info
->type
,
1619 instance
->pop_up_p
);
1620 dead_instance
->next
= all_destroyed_instances
;
1621 all_destroyed_instances
= dead_instance
;
1622 XtUnmanageChild (first_child (instance
->widget
));
1623 XFlush (XtDisplay (instance
->widget
));
1624 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1625 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1629 /* This might not be necessary now that the nosel is attached to
1630 popdown instead of destroy, but it can't hurt. */
1631 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1632 xm_nosel_callback
, (XtPointer
)instance
);
1633 XtDestroyWidget (instance
->widget
);
1637 \f/* popup utility */
1639 xm_popup_menu (widget
, event
)
1643 XButtonPressedEvent dummy
;
1647 dummy
.type
= ButtonPress
;
1649 dummy
.send_event
= 0;
1650 dummy
.display
= XtDisplay (widget
);
1651 dummy
.window
= XtWindow (XtParent (widget
));
1654 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1655 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1656 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1657 event
= (XEvent
*) &dummy
;
1660 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1662 /* This is so totally ridiculous: there's NO WAY to tell Motif
1663 that *any* button can select a menu item. Only one button
1664 can have that honor.
1667 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1668 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1669 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1670 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1671 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1672 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, 0);
1673 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1675 XtManageChild (widget
);
1679 set_min_dialog_size (w
)
1684 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, 0);
1685 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, 0);
1689 xm_pop_instance (instance
, up
)
1690 widget_instance
* instance
;
1693 Widget widget
= instance
->widget
;
1695 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1697 Widget widget_to_manage
= first_child (widget
);
1700 XtManageChild (widget_to_manage
);
1701 set_min_dialog_size (widget
);
1702 XtSetKeyboardFocus (instance
->parent
, widget
);
1705 XtUnmanageChild (widget_to_manage
);
1710 XtManageChild (widget
);
1712 XtUnmanageChild (widget
);
1717 /* motif callback */
1720 do_call (widget
, closure
, type
)
1723 enum do_call_type type
;
1727 XtPointer user_data
;
1728 widget_instance
* instance
= (widget_instance
*)closure
;
1729 Widget instance_widget
;
1734 if (widget
->core
.being_destroyed
)
1737 instance_widget
= instance
->widget
;
1738 if (!instance_widget
)
1741 id
= instance
->info
->id
;
1744 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1745 XtGetValues (widget
, al
, ac
);
1749 if (instance
->info
->pre_activate_cb
)
1750 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1753 if (instance
->info
->selection_cb
)
1754 instance
->info
->selection_cb (widget
, id
, user_data
);
1757 if (instance
->info
->selection_cb
)
1758 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1761 if (instance
->info
->post_activate_cb
)
1762 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1769 /* Like lw_internal_update_other_instances except that it does not do
1770 anything if its shell parent is not managed. This is to protect
1771 lw_internal_update_other_instances to dereference freed memory
1772 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1775 xm_internal_update_other_instances (widget
, closure
, call_data
)
1778 XtPointer call_data
;
1781 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1782 if (XtIsShell (parent
))
1784 else if (!XtIsManaged (parent
))
1786 lw_internal_update_other_instances (widget
, closure
, call_data
);
1790 xm_generic_callback (widget
, closure
, call_data
)
1793 XtPointer call_data
;
1795 lw_internal_update_other_instances (widget
, closure
, call_data
);
1796 do_call (widget
, closure
, selection
);
1800 xm_nosel_callback (widget
, closure
, call_data
)
1803 XtPointer call_data
;
1805 /* This callback is only called when a dialog box is dismissed with the wm's
1806 destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed
1807 in that case, not just unmapped, so that it releases its keyboard grabs.
1808 But there are problems with running our callbacks while the widget is in
1809 the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
1810 instead of XmDESTROY and then destroy it ourself after having run the
1813 do_call (widget
, closure
, no_selection
);
1814 XtDestroyWidget (widget
);
1818 xm_pull_down_callback (widget
, closure
, call_data
)
1821 XtPointer call_data
;
1823 do_call (widget
, closure
, pre_activate
);
1827 xm_pop_down_callback (widget
, closure
, call_data
)
1830 XtPointer call_data
;
1832 widget_instance
*instance
= (widget_instance
*) closure
;
1834 if ((!instance
->pop_up_p
&& (XtParent (widget
) == instance
->widget
))
1835 || (XtParent (widget
) == instance
->parent
))
1836 do_call (widget
, closure
, post_activate
);
1840 /* set the keyboard focus */
1842 xm_set_keyboard_focus (parent
, w
)
1846 XmProcessTraversal (w
, 0);
1847 XtSetKeyboardFocus (parent
, w
);
1850 /* Motif hack to set the main window areas. */
1852 xm_set_main_areas (parent
, menubar
, work_area
)
1857 XmMainWindowSetAreas (parent
,
1858 menubar
, /* menubar (maybe 0) */
1859 0, /* command area (psheets) */
1860 0, /* horizontal scroll */
1861 0, /* vertical scroll */
1862 work_area
); /* work area */
1865 /* Motif hack to control resizing on the menubar. */
1867 xm_manage_resizing (w
, flag
)
1873 /* Enable the edit widget for resizing. */
1876 XtSetArg (al
[0], XtNallowShellResize
, 0);
1877 XtSetValues (w
, al
, 1);
1881 /* Disable the edit widget from resizing. */
1884 XtSetArg (al
[0], XtNallowShellResize
, 0);
1885 XtSetValues (w
, al
, 1);