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. */
28 #include <X11/StringDefs.h>
29 #include <X11/IntrinsicP.h>
30 #include <X11/ObjectP.h>
31 #include <X11/CoreP.h>
32 #include <X11/CompositeP.h>
35 #include "lwlib-utils.h"
37 #include <Xm/BulletinB.h>
38 #include <Xm/CascadeB.h>
39 #include <Xm/CascadeBG.h>
40 #include <Xm/DrawingA.h>
41 #include <Xm/FileSB.h>
45 #include <Xm/MenuShell.h>
46 #include <Xm/MessageB.h>
47 #include <Xm/PanedW.h>
49 #include <Xm/PushBG.h>
50 #include <Xm/ArrowB.h>
51 #include <Xm/SelectioB.h>
54 #include <Xm/ToggleB.h>
55 #include <Xm/ToggleBG.h>
56 #include <Xm/RowColumn.h>
57 #include <Xm/ScrolledW.h>
58 #include <Xm/Separator.h>
59 #include <Xm/DialogS.h>
68 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
71 \f/* Structures to keep destroyed instances */
72 typedef struct _destroyed_instance
79 struct _destroyed_instance
* next
;
82 static destroyed_instance
*make_destroyed_instance
P_ ((char *, char *,
85 static void free_destroyed_instance
P_ ((destroyed_instance
*));
86 Widget first_child
P_ ((Widget
));
87 Boolean lw_motif_widget_p
P_ ((Widget
));
88 static XmString resource_motif_string
P_ ((Widget
, char *));
89 static void destroy_all_children
P_ ((Widget
, int));
90 static void xm_update_label
P_ ((widget_instance
*, Widget
, widget_value
*));
91 static void xm_update_list
P_ ((widget_instance
*, Widget
, widget_value
*));
92 static void xm_update_pushbutton
P_ ((widget_instance
*, Widget
,
94 static void xm_update_cascadebutton
P_ ((widget_instance
*, Widget
,
96 static void xm_update_toggle
P_ ((widget_instance
*, Widget
, widget_value
*));
97 static void xm_update_radiobox
P_ ((widget_instance
*, Widget
, widget_value
*));
98 static void make_menu_in_widget
P_ ((widget_instance
*, Widget
,
99 widget_value
*, int));
100 static void update_one_menu_entry
P_ ((widget_instance
*, Widget
,
101 widget_value
*, Boolean
));
102 static void xm_update_menu
P_ ((widget_instance
*, Widget
, widget_value
*,
104 static void xm_update_text
P_ ((widget_instance
*, Widget
, widget_value
*));
105 static void xm_update_text_field
P_ ((widget_instance
*, Widget
,
107 void xm_update_one_value
P_ ((widget_instance
*, Widget
, widget_value
*));
108 static void activate_button
P_ ((Widget
, XtPointer
, XtPointer
));
109 static Widget make_dialog
P_ ((char *, Widget
, Boolean
, char *, char *,
110 Boolean
, Boolean
, Boolean
, int, int));
111 static destroyed_instance
* find_matching_instance
P_ ((widget_instance
*));
112 static void mark_dead_instance_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
113 static void recenter_widget
P_ ((Widget
));
114 static Widget recycle_instance
P_ ((destroyed_instance
*));
115 Widget xm_create_dialog
P_ ((widget_instance
*));
116 static Widget make_menubar
P_ ((widget_instance
*));
117 static void remove_grabs
P_ ((Widget
, XtPointer
, XtPointer
));
118 static Widget make_popup_menu
P_ ((widget_instance
*));
119 static Widget make_main
P_ ((widget_instance
*));
120 void xm_destroy_instance
P_ ((widget_instance
*));
121 void xm_popup_menu
P_ ((Widget
, XEvent
*));
122 static void set_min_dialog_size
P_ ((Widget
));
123 static void do_call
P_ ((Widget
, XtPointer
, enum do_call_type
));
124 static void xm_generic_callback
P_ ((Widget
, XtPointer
, XtPointer
));
125 static void xm_nosel_callback
P_ ((Widget
, XtPointer
, XtPointer
));
126 static void xm_pull_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
127 static void xm_pop_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
128 void xm_set_keyboard_focus
P_ ((Widget
, Widget
));
129 void xm_set_main_areas
P_ ((Widget
, Widget
, Widget
));
130 static void xm_internal_update_other_instances
P_ ((Widget
, XtPointer
,
134 void xm_update_one_widget
P_ ((widget_instance
*, Widget
, widget_value
*,
136 void xm_pop_instance
P_ ((widget_instance
*, Boolean
));
137 void xm_manage_resizing
P_ ((Widget
, Boolean
));
141 static destroyed_instance
*
142 all_destroyed_instances
= NULL
;
144 static destroyed_instance
*
145 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
152 destroyed_instance
* instance
=
153 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
154 instance
->name
= safe_strdup (name
);
155 instance
->type
= safe_strdup (type
);
156 instance
->widget
= widget
;
157 instance
->parent
= parent
;
158 instance
->pop_up_p
= pop_up_p
;
159 instance
->next
= NULL
;
164 free_destroyed_instance (instance
)
165 destroyed_instance
* instance
;
167 free (instance
->name
);
168 free (instance
->type
);
172 \f/* motif utility functions */
177 return ((CompositeWidget
)widget
)->composite
.children
[0];
181 lw_motif_widget_p (widget
)
185 XtClass (widget
) == xmDialogShellWidgetClass
186 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
190 resource_motif_string (widget
, name
)
197 resource
.resource_name
= name
;
198 resource
.resource_class
= XmCXmString
;
199 resource
.resource_type
= XmRXmString
;
200 resource
.resource_size
= sizeof (XmString
);
201 resource
.resource_offset
= 0;
202 resource
.default_type
= XtRImmediate
;
203 resource
.default_addr
= 0;
205 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
206 "DialogString", &resource
, 1, NULL
, 0);
210 /* Destroy all of the children of WIDGET
211 starting with number FIRST_CHILD_TO_DESTROY. */
214 destroy_all_children (widget
, first_child_to_destroy
)
216 int first_child_to_destroy
;
222 children
= XtCompositeChildren (widget
, &number
);
225 XtUnmanageChildren (children
+ first_child_to_destroy
,
226 number
- first_child_to_destroy
);
228 /* Unmanage all children and destroy them. They will only be
229 really destroyed when we get out of DispatchEvent. */
230 for (i
= first_child_to_destroy
; i
< number
; i
++)
234 /* Cascade buttons have submenus,and these submenus
235 need to be freed. But they are not included in
236 XtCompositeChildren. So get it out of the cascade button
237 and free it. If this child is not a cascade button,
238 then submenu should remain unchanged. */
239 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
240 XtGetValues (children
[i
], al
, 1);
242 XtDestroyWidget (submenu
);
243 XtDestroyWidget (children
[i
]);
246 XtFree ((char *) children
);
251 /* Update the label of widget WIDGET. WIDGET must be a Label widget
252 or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
257 Emacs fills VAL->name with the text to display in the menu, and
258 sets VAL->value to null. Function make_menu_in_widget creates
259 widgets with VAL->name as resource name. This works because the
260 Label widget uses its resource name for display if no
261 XmNlabelString is set.
265 VAL->name is again set to the resource name, but VAL->value is
266 not null, and contains the label string to display. */
269 xm_update_label (instance
, widget
, val
)
270 widget_instance
* instance
;
274 XmString res_string
= 0;
275 XmString built_string
= 0;
276 XmString key_string
= 0;
284 /* A label string is specified, i.e. we are in a dialog. First
285 see if it is overridden by something from the resource file. */
286 res_string
= resource_motif_string (widget
, val
->value
);
290 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
295 XmStringCreateLtoR (val
->value
, XmSTRING_DEFAULT_CHARSET
);
296 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
299 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
304 key_string
= XmStringCreateLtoR (val
->key
, XmSTRING_DEFAULT_CHARSET
);
305 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
309 XtSetValues (widget
, al
, ac
);
312 XmStringFree (built_string
);
315 XmStringFree (key_string
);
318 \f/* update of list */
320 xm_update_list (instance
, widget
, val
)
321 widget_instance
* instance
;
327 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
328 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
330 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
333 XmString xmstr
= XmStringCreate (cur
->value
, XmSTRING_DEFAULT_CHARSET
);
335 XmListAddItem (widget
, xmstr
, 0);
337 XmListSelectPos (widget
, i
, False
);
338 XmStringFree (xmstr
);
342 \f/* update of buttons */
344 xm_update_pushbutton (instance
, widget
, val
)
345 widget_instance
* instance
;
349 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, 0);
350 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
351 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
355 xm_update_cascadebutton (instance
, widget
, val
)
356 widget_instance
* instance
;
360 /* Should also rebuild the menu by calling ...update_menu... */
361 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
362 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
366 \f/* update toggle and radiobox */
368 xm_update_toggle (instance
, widget
, val
)
369 widget_instance
* instance
;
373 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
374 XtAddCallback (widget
, XmNvalueChangedCallback
,
375 xm_generic_callback
, instance
);
376 XtVaSetValues (widget
, XmNset
, val
->selected
,
377 XmNalignment
, XmALIGNMENT_BEGINNING
, 0);
381 xm_update_radiobox (instance
, widget
, val
)
382 widget_instance
* instance
;
390 /* update the callback */
391 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
392 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
394 /* first update all the toggles */
395 /* Energize kernel interface is currently bad. It sets the selected widget
396 with the selected flag but returns it by its name. So we currently
397 have to support both setting the selection with the selected slot
398 of val contents and setting it with the "value" slot of val. The latter
399 has a higher priority. This to be removed when the kernel is fixed. */
400 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
402 toggle
= XtNameToWidget (widget
, cur
->value
);
405 XtVaSetValues (toggle
, XmNsensitive
, cur
->enabled
, 0);
406 if (!val
->value
&& cur
->selected
)
407 XtVaSetValues (toggle
, XmNset
, cur
->selected
, 0);
408 if (val
->value
&& strcmp (val
->value
, cur
->value
))
409 XtVaSetValues (toggle
, XmNset
, False
, 0);
413 /* The selected was specified by the value slot */
416 toggle
= XtNameToWidget (widget
, val
->value
);
418 XtVaSetValues (toggle
, XmNset
, True
, 0);
423 /* update a popup menu, pulldown menu or a menubar */
425 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
428 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
429 widget_instance
* instance
;
432 int keep_first_children
;
434 Widget
* children
= 0;
446 Widget
* old_children
;
447 unsigned int old_num_children
;
449 old_children
= XtCompositeChildren (widget
, &old_num_children
);
451 /* Allocate the children array */
452 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
);
453 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
455 /* WIDGET should be a RowColumn. */
456 if (!XmIsRowColumn (widget
))
459 /* Determine whether WIDGET is a menu bar. */
461 XtSetArg (al
[0], XmNrowColumnType
, &type
);
462 XtGetValues (widget
, al
, 1);
463 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
465 menubar_p
= type
== XmMENU_BAR
;
467 /* Add a callback to popups and pulldowns that is called when
468 it is made invisible again. */
470 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
471 xm_pop_down_callback
, (XtPointer
)instance
);
473 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
474 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
475 child_index
++, cur
= cur
->next
)
476 children
[child_index
] = old_children
[child_index
];
478 /* Check that those are all we have
479 (the caller should have deleted the rest). */
480 if (old_num_children
!= keep_first_children
)
483 /* Create the rest. */
484 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
486 enum menu_separator separator
;
489 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
490 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
491 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
493 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
494 && !lw_separator_p (cur
->name
, &separator
, 1))
497 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
498 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
500 else if (lw_separator_p (cur
->name
, &separator
, 1))
503 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
504 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
506 else if (!cur
->contents
)
509 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
510 else if (!cur
->call_data
)
511 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
512 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
513 || cur
->button_type
== BUTTON_TYPE_RADIO
)
515 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
516 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
517 XtSetArg (al
[ac
], XmNindicatorType
,
518 (cur
->button_type
== BUTTON_TYPE_TOGGLE
519 ? XmN_OF_MANY
: XmONE_OF_MANY
));
521 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
524 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
526 xm_update_label (instance
, button
, cur
);
528 /* Add a callback that is called when the button is
529 selected. Toggle buttons don't support
530 XmNactivateCallback, we use XmNvalueChangedCallback in
531 that case. Don't add a callback to a simple label. */
532 if (cur
->button_type
)
533 xm_update_toggle (instance
, button
, cur
);
534 else if (cur
->call_data
)
535 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
536 (XtPointer
)instance
);
540 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
541 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
542 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
543 /* Non-zero values don't work reliably in conjunction with
545 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
546 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
548 xm_update_label (instance
, button
, cur
);
550 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
551 (XtPointer
)instance
);
554 children
[child_index
] = button
;
557 /* Last entry is the help button. The original comment read "Has to
558 be done after managing the buttons otherwise the menubar is only
559 4 pixels high." This is no longer true, and to make
560 XmNmenuHelpWidget work, we need to set it before managing the
561 children.. --gerd. */
563 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, 0);
565 /* LessTif apparently doesn't recompute centered text when more
566 widgets are added. So, do it after all widgets have been
569 XtVaSetValues (title
, XmNalignment
, XmALIGNMENT_CENTER
, 0);
572 XtManageChildren (children
, num_children
);
574 XtFree ((char *) children
);
576 XtFree ((char *) old_children
);
580 update_one_menu_entry (instance
, widget
, val
, deep_p
)
581 widget_instance
* instance
;
589 widget_value
* contents
;
591 if (val
->this_one_change
== NO_CHANGE
)
594 /* update the sensitivity and userdata */
595 /* Common to all widget types */
596 XtVaSetValues (widget
,
597 XmNsensitive
, val
->enabled
,
598 XmNuserData
, val
->call_data
,
601 /* update the menu button as a label. */
602 if (val
->this_one_change
>= VISIBLE_CHANGE
)
604 xm_update_label (instance
, widget
, val
);
605 if (val
->button_type
)
606 xm_update_toggle (instance
, widget
, val
);
609 /* update the pulldown/pullaside as needed */
612 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
613 XtGetValues (widget
, al
, ac
);
615 contents
= val
->contents
;
621 unsigned int old_num_children
, i
;
625 parent
= XtParent (widget
);
626 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
628 /* Find the widget position within the parent's widget list. */
629 for (i
= 0; i
< old_num_children
; i
++)
630 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
632 if (i
== old_num_children
)
634 if (XmIsCascadeButton (widget_list
[i
]))
636 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
637 make_menu_in_widget (instance
, menu
, contents
, 0);
639 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
640 XtSetValues (widget
, al
, ac
);
646 /* The current menuitem is a XmPushButtonGadget, it
647 needs to be replaced by a CascadeButtonGadget */
648 XtDestroyWidget (widget_list
[i
]);
649 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
650 make_menu_in_widget (instance
, menu
, contents
, 0);
652 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
653 /* Non-zero values don't work reliably in
654 conjunction with Emacs' event loop */
655 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
656 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
657 /* Tell Motif to put it in the right place */
658 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
660 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
661 xm_update_label (instance
, button
, val
);
663 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
664 (XtPointer
)instance
);
665 XtManageChild (button
);
672 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
673 XtSetValues (widget
, al
, ac
);
674 XtDestroyWidget (menu
);
676 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
677 xm_update_menu (instance
, menu
, val
, 1);
681 xm_update_menu (instance
, widget
, val
, deep_p
)
682 widget_instance
* instance
;
688 unsigned int num_children
;
689 int num_children_to_keep
= 0;
693 children
= XtCompositeChildren (widget
, &num_children
);
695 /* Widget is a RowColumn widget whose contents have to be updated
696 * to reflect the list of items in val->contents */
698 /* See how many buttons we can keep, and how many we
699 must completely replace. */
700 if (val
->contents
== 0)
701 num_children_to_keep
= 0;
702 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
706 for (i
= 0, cur
= val
->contents
;
708 && cur
); /* how else to ditch unwanted children ?? - mgd */
709 i
++, cur
= cur
->next
)
711 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
715 num_children_to_keep
= i
;
719 num_children_to_keep
= num_children
;
721 /* Update all the buttons of the RowColumn, in order,
722 except for those we are going to replace entirely. */
725 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
729 num_children_to_keep
= i
;
732 if (children
[i
]->core
.being_destroyed
733 || strcmp (XtName (children
[i
]), cur
->name
))
735 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
740 /* Now replace from scratch all the buttons after the last
741 place that the top-level structure changed. */
742 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
744 destroy_all_children (widget
, num_children_to_keep
);
745 make_menu_in_widget (instance
, widget
, val
->contents
,
746 num_children_to_keep
);
749 XtFree ((char *) children
);
753 /* update text widgets */
756 xm_update_text (instance
, widget
, val
)
757 widget_instance
* instance
;
761 XmTextSetString (widget
, val
->value
? val
->value
: "");
762 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
763 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
764 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
765 XtAddCallback (widget
, XmNvalueChangedCallback
,
766 xm_internal_update_other_instances
, instance
);
770 xm_update_text_field (instance
, widget
, val
)
771 widget_instance
* instance
;
775 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
776 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
777 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
778 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
779 XtAddCallback (widget
, XmNvalueChangedCallback
,
780 xm_internal_update_other_instances
, instance
);
784 /* update a motif widget */
787 xm_update_one_widget (instance
, widget
, val
, deep_p
)
788 widget_instance
* instance
;
795 /* Mark as not edited */
798 /* Common to all widget types */
799 XtVaSetValues (widget
,
800 XmNsensitive
, val
->enabled
,
801 XmNuserData
, val
->call_data
,
804 /* Common to all label like widgets */
805 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
806 xm_update_label (instance
, widget
, val
);
808 class = XtClass (widget
);
809 /* Class specific things */
810 if (class == xmPushButtonWidgetClass
||
811 class == xmArrowButtonWidgetClass
)
813 xm_update_pushbutton (instance
, widget
, val
);
815 else if (class == xmCascadeButtonWidgetClass
)
817 xm_update_cascadebutton (instance
, widget
, val
);
819 else if (class == xmToggleButtonWidgetClass
820 || class == xmToggleButtonGadgetClass
)
822 xm_update_toggle (instance
, widget
, val
);
824 else if (class == xmRowColumnWidgetClass
)
826 Boolean radiobox
= 0;
830 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
831 XtGetValues (widget
, al
, ac
);
834 xm_update_radiobox (instance
, widget
, val
);
836 xm_update_menu (instance
, widget
, val
, deep_p
);
838 else if (class == xmTextWidgetClass
)
840 xm_update_text (instance
, widget
, val
);
842 else if (class == xmTextFieldWidgetClass
)
844 xm_update_text_field (instance
, widget
, val
);
846 else if (class == xmListWidgetClass
)
848 xm_update_list (instance
, widget
, val
);
852 \f/* getting the value back */
854 xm_update_one_value (instance
, widget
, val
)
855 widget_instance
* instance
;
859 WidgetClass
class = XtClass (widget
);
860 widget_value
*old_wv
;
862 /* copy the call_data slot into the "return" widget_value */
863 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
864 if (!strcmp (val
->name
, old_wv
->name
))
866 val
->call_data
= old_wv
->call_data
;
870 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
872 XtVaGetValues (widget
, XmNset
, &val
->selected
, 0);
875 else if (class == xmTextWidgetClass
)
879 val
->value
= XmTextGetString (widget
);
882 else if (class == xmTextFieldWidgetClass
)
886 val
->value
= XmTextFieldGetString (widget
);
889 else if (class == xmRowColumnWidgetClass
)
891 Boolean radiobox
= 0;
895 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
896 XtGetValues (widget
, al
, ac
);
900 CompositeWidget radio
= (CompositeWidget
)widget
;
902 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
905 Widget toggle
= radio
->composite
.children
[i
];
907 XtVaGetValues (toggle
, XmNset
, &set
, 0);
912 val
->value
= safe_strdup (XtName (toggle
));
918 else if (class == xmListWidgetClass
)
922 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
926 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
930 cur
->selected
= False
;
932 for (j
= 0; j
< pos_cnt
; j
++)
933 if (pos_list
[j
] == i
)
935 cur
->selected
= True
;
936 val
->value
= safe_strdup (cur
->name
);
940 XtFree ((char *) pos_list
);
946 /* This function is for activating a button from a program. It's wrong because
947 we pass a NULL argument in the call_data which is not Motif compatible.
948 This is used from the XmNdefaultAction callback of the List widgets to
949 have a double-click put down a dialog box like the button would do.
950 I could not find a way to do that with accelerators.
953 activate_button (widget
, closure
, call_data
)
958 Widget button
= (Widget
)closure
;
959 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
962 /* creation functions */
966 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
967 radio_box
, list
, left_buttons
, right_buttons
)
973 Boolean text_input_slot
;
983 Widget icon_separator
;
988 Widget children
[16]; /* for the final XtManageChildren */
990 Arg al
[64]; /* Arg List */
991 int ac
; /* Arg Count */
997 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
998 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
999 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
1000 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1002 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1003 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1004 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1005 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1010 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1011 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1012 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1016 n_children
= left_buttons
+ right_buttons
+ 1;
1018 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1019 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1020 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1021 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1022 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1023 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1024 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1025 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1026 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1027 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1028 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1029 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1030 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1031 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1032 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1033 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1034 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1035 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1036 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1039 for (i
= 0; i
< left_buttons
; i
++)
1041 char button_name
[16];
1042 sprintf (button_name
, "button%d", i
+ 1);
1046 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1047 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1049 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1050 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1051 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1055 button
= children
[n_children
];
1057 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1058 XtSetValues (row
, al
, ac
);
1064 /* invisible separator button */
1066 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1067 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1070 for (i
= 0; i
< right_buttons
; i
++)
1072 char button_name
[16];
1073 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1075 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1076 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1077 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1078 if (! button
) button
= children
[n_children
];
1082 XtManageChildren (children
, n_children
);
1085 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1086 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1087 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1088 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1089 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1090 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1091 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1092 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1093 separator
= XmCreateSeparator (form
, "", al
, ac
);
1096 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1097 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1098 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1099 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1100 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1101 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1102 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1103 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1106 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1107 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1108 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1109 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1110 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1111 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1112 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1113 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1114 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1115 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1117 if (text_input_slot
)
1120 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1121 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1122 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1123 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1124 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1125 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1126 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1127 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1128 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1129 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1130 value
= XmCreateTextField (form
, "value", al
, ac
);
1136 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1137 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1138 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1139 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1140 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1141 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1142 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1143 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1144 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1145 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1146 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1147 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1148 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1149 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1152 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1153 children
[i
++] = radio_butt
;
1154 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1155 children
[i
++] = radio_butt
;
1156 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1157 children
[i
++] = radio_butt
;
1158 XtManageChildren (children
, i
);
1163 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1164 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1165 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1166 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1167 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1168 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1169 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1170 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1171 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1172 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1173 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1175 /* this is the easiest way I found to have the dble click in the
1176 list activate the default button */
1177 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1181 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1182 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1183 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1184 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1185 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1186 XtSetArg(al
[ac
], XmNbottomWidget
,
1187 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1188 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1189 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1190 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1191 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1192 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1193 message
= XmCreateLabel (form
, "message", al
, ac
);
1196 XtManageChild (value
);
1199 children
[i
] = row
; i
++;
1200 children
[i
] = separator
; i
++;
1201 if (text_input_slot
|| radio_box
)
1203 children
[i
] = value
; i
++;
1205 children
[i
] = message
; i
++;
1206 children
[i
] = icon
; i
++;
1207 children
[i
] = icon_separator
; i
++;
1208 XtManageChildren (children
, i
);
1210 if (text_input_slot
|| list
)
1212 XtInstallAccelerators (value
, button
);
1213 XtSetKeyboardFocus (result
, value
);
1217 XtInstallAccelerators (form
, button
);
1218 XtSetKeyboardFocus (result
, button
);
1224 static destroyed_instance
*
1225 find_matching_instance (instance
)
1226 widget_instance
* instance
;
1228 destroyed_instance
* cur
;
1229 destroyed_instance
* prev
;
1230 char* type
= instance
->info
->type
;
1231 char* name
= instance
->info
->name
;
1233 for (prev
= NULL
, cur
= all_destroyed_instances
;
1235 prev
= cur
, cur
= cur
->next
)
1237 if (!strcmp (cur
->name
, name
)
1238 && !strcmp (cur
->type
, type
)
1239 && cur
->parent
== instance
->parent
1240 && cur
->pop_up_p
== instance
->pop_up_p
)
1243 prev
->next
= cur
->next
;
1245 all_destroyed_instances
= cur
->next
;
1248 /* do some cleanup */
1249 else if (!cur
->widget
)
1252 prev
->next
= cur
->next
;
1254 all_destroyed_instances
= cur
->next
;
1255 free_destroyed_instance (cur
);
1256 cur
= prev
? prev
: all_destroyed_instances
;
1263 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1266 XtPointer call_data
;
1268 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1269 instance
->widget
= NULL
;
1273 recenter_widget (widget
)
1276 Widget parent
= XtParent (widget
);
1277 Screen
* screen
= XtScreen (widget
);
1278 Dimension screen_width
= WidthOfScreen (screen
);
1279 Dimension screen_height
= HeightOfScreen (screen
);
1280 Dimension parent_width
= 0;
1281 Dimension parent_height
= 0;
1282 Dimension child_width
= 0;
1283 Dimension child_height
= 0;
1287 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, 0);
1288 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1291 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1292 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1294 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1296 if (x
+ child_width
> screen_width
)
1297 x
= screen_width
- child_width
;
1301 if (y
+ child_height
> screen_height
)
1302 y
= screen_height
- child_height
;
1306 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, 0);
1310 recycle_instance (instance
)
1311 destroyed_instance
* instance
;
1313 Widget widget
= instance
->widget
;
1315 /* widget is NULL if the parent was destroyed. */
1321 /* Remove the destroy callback as the instance is not in the list
1323 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1324 mark_dead_instance_destroyed
,
1325 (XtPointer
)instance
);
1327 /* Give the focus to the initial item */
1328 focus
= XtNameToWidget (widget
, "*value");
1330 focus
= XtNameToWidget (widget
, "*button1");
1332 XtSetKeyboardFocus (widget
, focus
);
1334 /* shrink the separator label back to their original size */
1335 separator
= XtNameToWidget (widget
, "*separator_button");
1337 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, 0);
1339 /* Center the dialog in its parent */
1340 recenter_widget (widget
);
1342 free_destroyed_instance (instance
);
1347 xm_create_dialog (instance
)
1348 widget_instance
* instance
;
1350 char* name
= instance
->info
->type
;
1351 Widget parent
= instance
->parent
;
1353 Boolean pop_up_p
= instance
->pop_up_p
;
1354 char* shell_name
= 0;
1356 Boolean text_input_slot
= False
;
1357 Boolean radio_box
= False
;
1358 Boolean list
= False
;
1360 int left_buttons
= 0;
1361 int right_buttons
= 1;
1362 destroyed_instance
* dead_one
;
1364 /* try to find a widget to recycle */
1365 dead_one
= find_matching_instance (instance
);
1368 Widget recycled_widget
= recycle_instance (dead_one
);
1369 if (recycled_widget
)
1370 return recycled_widget
;
1375 icon_name
= "dbox-error";
1376 shell_name
= "Error";
1380 icon_name
= "dbox-info";
1381 shell_name
= "Information";
1386 icon_name
= "dbox-question";
1387 shell_name
= "Prompt";
1391 text_input_slot
= True
;
1392 icon_name
= "dbox-question";
1393 shell_name
= "Prompt";
1397 icon_name
= "dbox-question";
1398 shell_name
= "Question";
1402 total_buttons
= name
[1] - '0';
1404 if (name
[3] == 'T' || name
[3] == 't')
1406 text_input_slot
= False
;
1410 right_buttons
= name
[4] - '0';
1412 left_buttons
= total_buttons
- right_buttons
;
1414 widget
= make_dialog (name
, parent
, pop_up_p
,
1415 shell_name
, icon_name
, text_input_slot
, radio_box
,
1416 list
, left_buttons
, right_buttons
);
1418 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1419 (XtPointer
) instance
);
1423 /* Create a menu bar. We turn off the f10 key
1424 because we have not yet managed to make it work right in Motif. */
1427 make_menubar (instance
)
1428 widget_instance
* instance
;
1434 XtSetArg(al
[0], XmNmenuAccelerator
, 0);
1435 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, 1);
1439 remove_grabs (shell
, closure
, call_data
)
1442 XtPointer call_data
;
1444 Widget menu
= (Widget
) closure
;
1445 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1449 make_popup_menu (instance
)
1450 widget_instance
* instance
;
1452 Widget parent
= instance
->parent
;
1453 Window parent_window
= parent
->core
.window
;
1456 /* sets the parent window to 0 to fool Motif into not generating a grab */
1457 parent
->core
.window
= 0;
1458 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1459 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1461 parent
->core
.window
= parent_window
;
1466 make_main (instance
)
1467 widget_instance
* instance
;
1469 Widget parent
= instance
->parent
;
1475 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1476 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1477 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1481 \f/* Table of functions to create widgets */
1485 /* interface with the XDesigner generated functions */
1486 typedef Widget (*widget_maker
) (Widget
);
1487 extern Widget
create_project_p_sheet (Widget parent
);
1488 extern Widget
create_debugger_p_sheet (Widget parent
);
1489 extern Widget
create_breaklist_p_sheet (Widget parent
);
1490 extern Widget
create_le_browser_p_sheet (Widget parent
);
1491 extern Widget
create_class_browser_p_sheet (Widget parent
);
1492 extern Widget
create_call_browser_p_sheet (Widget parent
);
1493 extern Widget
create_build_dialog (Widget parent
);
1494 extern Widget
create_editmode_dialog (Widget parent
);
1495 extern Widget
create_search_dialog (Widget parent
);
1496 extern Widget
create_project_display_dialog (Widget parent
);
1499 make_one (widget_instance
* instance
, widget_maker fn
)
1505 if (instance
->pop_up_p
)
1507 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1508 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1509 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1510 (XtPointer
) instance
);
1515 result
= (*fn
) (instance
->parent
);
1516 XtRealizeWidget (result
);
1522 make_project_p_sheet (widget_instance
* instance
)
1524 return make_one (instance
, create_project_p_sheet
);
1528 make_debugger_p_sheet (widget_instance
* instance
)
1530 return make_one (instance
, create_debugger_p_sheet
);
1534 make_breaklist_p_sheet (widget_instance
* instance
)
1536 return make_one (instance
, create_breaklist_p_sheet
);
1540 make_le_browser_p_sheet (widget_instance
* instance
)
1542 return make_one (instance
, create_le_browser_p_sheet
);
1546 make_class_browser_p_sheet (widget_instance
* instance
)
1548 return make_one (instance
, create_class_browser_p_sheet
);
1552 make_call_browser_p_sheet (widget_instance
* instance
)
1554 return make_one (instance
, create_call_browser_p_sheet
);
1558 make_build_dialog (widget_instance
* instance
)
1560 return make_one (instance
, create_build_dialog
);
1564 make_editmode_dialog (widget_instance
* instance
)
1566 return make_one (instance
, create_editmode_dialog
);
1570 make_search_dialog (widget_instance
* instance
)
1572 return make_one (instance
, create_search_dialog
);
1576 make_project_display_dialog (widget_instance
* instance
)
1578 return make_one (instance
, create_project_display_dialog
);
1581 #endif /* ENERGIZE */
1583 widget_creation_entry
1584 xm_creation_table
[] =
1586 {"menubar", make_menubar
},
1587 {"popup", make_popup_menu
},
1588 {"main", make_main
},
1590 {"project_p_sheet", make_project_p_sheet
},
1591 {"debugger_p_sheet", make_debugger_p_sheet
},
1592 {"breaklist_psheet", make_breaklist_p_sheet
},
1593 {"leb_psheet", make_le_browser_p_sheet
},
1594 {"class_browser_psheet", make_class_browser_p_sheet
},
1595 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1596 {"build", make_build_dialog
},
1597 {"editmode", make_editmode_dialog
},
1598 {"search", make_search_dialog
},
1599 {"project_display", make_project_display_dialog
},
1600 #endif /* ENERGIZE */
1604 \f/* Destruction of instances */
1606 xm_destroy_instance (instance
)
1607 widget_instance
* instance
;
1609 Widget widget
= instance
->widget
;
1610 /* recycle the dialog boxes */
1611 /* Disable the recycling until we can find a way to have the dialog box
1612 get reasonable layout after we modify its contents. */
1614 && XtClass (widget
) == xmDialogShellWidgetClass
)
1616 destroyed_instance
* dead_instance
=
1617 make_destroyed_instance (instance
->info
->name
,
1618 instance
->info
->type
,
1621 instance
->pop_up_p
);
1622 dead_instance
->next
= all_destroyed_instances
;
1623 all_destroyed_instances
= dead_instance
;
1624 XtUnmanageChild (first_child (instance
->widget
));
1625 XFlush (XtDisplay (instance
->widget
));
1626 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1627 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1631 /* This might not be necessary now that the nosel is attached to
1632 popdown instead of destroy, but it can't hurt. */
1633 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1634 xm_nosel_callback
, (XtPointer
)instance
);
1635 XtDestroyWidget (instance
->widget
);
1639 \f/* popup utility */
1641 xm_popup_menu (widget
, event
)
1645 XButtonPressedEvent dummy
;
1649 dummy
.type
= ButtonPress
;
1651 dummy
.send_event
= 0;
1652 dummy
.display
= XtDisplay (widget
);
1653 dummy
.window
= XtWindow (XtParent (widget
));
1656 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1657 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1658 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1659 event
= (XEvent
*) &dummy
;
1662 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1664 /* This is so totally ridiculous: there's NO WAY to tell Motif
1665 that *any* button can select a menu item. Only one button
1666 can have that honor.
1669 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1670 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1671 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1672 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1673 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1674 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, 0);
1675 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1677 XtManageChild (widget
);
1681 set_min_dialog_size (w
)
1686 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, 0);
1687 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, 0);
1691 xm_pop_instance (instance
, up
)
1692 widget_instance
* instance
;
1695 Widget widget
= instance
->widget
;
1697 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1699 Widget widget_to_manage
= first_child (widget
);
1702 XtManageChild (widget_to_manage
);
1703 set_min_dialog_size (widget
);
1704 XtSetKeyboardFocus (instance
->parent
, widget
);
1707 XtUnmanageChild (widget_to_manage
);
1712 XtManageChild (widget
);
1714 XtUnmanageChild (widget
);
1719 /* motif callback */
1722 do_call (widget
, closure
, type
)
1725 enum do_call_type type
;
1729 XtPointer user_data
;
1730 widget_instance
* instance
= (widget_instance
*)closure
;
1731 Widget instance_widget
;
1736 if (widget
->core
.being_destroyed
)
1739 instance_widget
= instance
->widget
;
1740 if (!instance_widget
)
1743 id
= instance
->info
->id
;
1746 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1747 XtGetValues (widget
, al
, ac
);
1751 if (instance
->info
->pre_activate_cb
)
1752 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1755 if (instance
->info
->selection_cb
)
1756 instance
->info
->selection_cb (widget
, id
, user_data
);
1759 if (instance
->info
->selection_cb
)
1760 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1763 if (instance
->info
->post_activate_cb
)
1764 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1771 /* Like lw_internal_update_other_instances except that it does not do
1772 anything if its shell parent is not managed. This is to protect
1773 lw_internal_update_other_instances to dereference freed memory
1774 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1777 xm_internal_update_other_instances (widget
, closure
, call_data
)
1780 XtPointer call_data
;
1783 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1784 if (XtIsShell (parent
))
1786 else if (!XtIsManaged (parent
))
1788 lw_internal_update_other_instances (widget
, closure
, call_data
);
1792 xm_generic_callback (widget
, closure
, call_data
)
1795 XtPointer call_data
;
1797 lw_internal_update_other_instances (widget
, closure
, call_data
);
1798 do_call (widget
, closure
, selection
);
1802 xm_nosel_callback (widget
, closure
, call_data
)
1805 XtPointer call_data
;
1807 /* This callback is only called when a dialog box is dismissed with the wm's
1808 destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed
1809 in that case, not just unmapped, so that it releases its keyboard grabs.
1810 But there are problems with running our callbacks while the widget is in
1811 the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
1812 instead of XmDESTROY and then destroy it ourself after having run the
1815 do_call (widget
, closure
, no_selection
);
1816 XtDestroyWidget (widget
);
1820 xm_pull_down_callback (widget
, closure
, call_data
)
1823 XtPointer call_data
;
1825 do_call (widget
, closure
, pre_activate
);
1829 xm_pop_down_callback (widget
, closure
, call_data
)
1832 XtPointer call_data
;
1834 widget_instance
*instance
= (widget_instance
*) closure
;
1836 if ((!instance
->pop_up_p
&& (XtParent (widget
) == instance
->widget
))
1837 || (XtParent (widget
) == instance
->parent
))
1838 do_call (widget
, closure
, post_activate
);
1842 /* set the keyboard focus */
1844 xm_set_keyboard_focus (parent
, w
)
1848 XmProcessTraversal (w
, 0);
1849 XtSetKeyboardFocus (parent
, w
);
1852 /* Motif hack to set the main window areas. */
1854 xm_set_main_areas (parent
, menubar
, work_area
)
1859 XmMainWindowSetAreas (parent
,
1860 menubar
, /* menubar (maybe 0) */
1861 0, /* command area (psheets) */
1862 0, /* horizontal scroll */
1863 0, /* vertical scroll */
1864 work_area
); /* work area */
1867 /* Motif hack to control resizing on the menubar. */
1869 xm_manage_resizing (w
, flag
)
1875 /* Enable the edit widget for resizing. */
1878 XtSetArg (al
[0], XtNallowShellResize
, 0);
1879 XtSetValues (w
, al
, 1);
1883 /* Disable the edit widget from resizing. */
1886 XtSetArg (al
[0], XtNallowShellResize
, 0);
1887 XtSetValues (w
, al
, 1);