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>
34 #include "../src/lisp.h"
37 #include "lwlib-utils.h"
39 #include <Xm/BulletinB.h>
40 #include <Xm/CascadeB.h>
41 #include <Xm/CascadeBG.h>
42 #include <Xm/DrawingA.h>
43 #include <Xm/FileSB.h>
47 #include <Xm/MenuShell.h>
48 #include <Xm/MessageB.h>
49 #include <Xm/PanedW.h>
51 #include <Xm/PushBG.h>
52 #include <Xm/ArrowB.h>
53 #include <Xm/SelectioB.h>
56 #include <Xm/ToggleB.h>
57 #include <Xm/ToggleBG.h>
58 #include <Xm/RowColumn.h>
59 #include <Xm/ScrolledW.h>
60 #include <Xm/Separator.h>
61 #include <Xm/DialogS.h>
65 #if defined __STDC__ || defined PROTOTYPES
71 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
74 \f/* Structures to keep destroyed instances */
75 typedef struct _destroyed_instance
82 struct _destroyed_instance
* next
;
85 static destroyed_instance
*make_destroyed_instance
P_ ((char *, char *,
88 static void free_destroyed_instance
P_ ((destroyed_instance
*));
89 Widget first_child
P_ ((Widget
));
90 Boolean lw_motif_widget_p
P_ ((Widget
));
91 static XmString resource_motif_string
P_ ((Widget
, char *));
92 static void destroy_all_children
P_ ((Widget
, int));
93 static void xm_update_label
P_ ((widget_instance
*, Widget
, widget_value
*));
94 static void xm_update_list
P_ ((widget_instance
*, Widget
, widget_value
*));
95 static void xm_update_pushbutton
P_ ((widget_instance
*, Widget
,
97 static void xm_update_cascadebutton
P_ ((widget_instance
*, Widget
,
99 static void xm_update_toggle
P_ ((widget_instance
*, Widget
, widget_value
*));
100 static void xm_update_radiobox
P_ ((widget_instance
*, Widget
, widget_value
*));
101 static void make_menu_in_widget
P_ ((widget_instance
*, Widget
,
102 widget_value
*, int));
103 static void update_one_menu_entry
P_ ((widget_instance
*, Widget
,
104 widget_value
*, Boolean
));
105 static void xm_update_menu
P_ ((widget_instance
*, Widget
, widget_value
*,
107 static void xm_update_text
P_ ((widget_instance
*, Widget
, widget_value
*));
108 static void xm_update_text_field
P_ ((widget_instance
*, Widget
,
110 void xm_update_one_value
P_ ((widget_instance
*, Widget
, widget_value
*));
111 static void activate_button
P_ ((Widget
, XtPointer
, XtPointer
));
112 static Widget make_dialog
P_ ((char *, Widget
, Boolean
, char *, char *,
113 Boolean
, Boolean
, Boolean
, int, int));
114 static destroyed_instance
* find_matching_instance
P_ ((widget_instance
*));
115 static void mark_dead_instance_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
116 static void recenter_widget
P_ ((Widget
));
117 static Widget recycle_instance
P_ ((destroyed_instance
*));
118 Widget xm_create_dialog
P_ ((widget_instance
*));
119 static Widget make_menubar
P_ ((widget_instance
*));
120 static void remove_grabs
P_ ((Widget
, XtPointer
, XtPointer
));
121 static Widget make_popup_menu
P_ ((widget_instance
*));
122 static Widget make_main
P_ ((widget_instance
*));
123 void xm_destroy_instance
P_ ((widget_instance
*));
124 void xm_popup_menu
P_ ((Widget
, XEvent
*));
125 static void set_min_dialog_size
P_ ((Widget
));
126 static void do_call
P_ ((Widget
, XtPointer
, enum do_call_type
));
127 static void xm_generic_callback
P_ ((Widget
, XtPointer
, XtPointer
));
128 static void xm_nosel_callback
P_ ((Widget
, XtPointer
, XtPointer
));
129 static void xm_pull_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
130 static void xm_pop_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
131 void xm_set_keyboard_focus
P_ ((Widget
, Widget
));
132 void xm_set_main_areas
P_ ((Widget
, Widget
, Widget
));
133 static void xm_internal_update_other_instances
P_ ((Widget
, XtPointer
,
135 static void xm_arm_callback
P_ ((Widget
, XtPointer
, XtPointer
));
138 void xm_update_one_widget
P_ ((widget_instance
*, Widget
, widget_value
*,
140 void xm_pop_instance
P_ ((widget_instance
*, Boolean
));
141 void xm_manage_resizing
P_ ((Widget
, Boolean
));
147 /* Print the complete X resource name of widget WIDGET to stderr.
148 This is sometimes handy to have available. */
151 x_print_complete_resource_name (widget
)
157 for (i
= 0; i
< 100 && widget
!= NULL
; ++i
)
159 names
[i
] = XtName (widget
);
160 widget
= XtParent (widget
);
163 for (--i
; i
>= 1; --i
)
164 fprintf (stderr
, "%s.", names
[i
]);
165 fprintf (stderr
, "%s\n", names
[0]);
171 static destroyed_instance
*all_destroyed_instances
= NULL
;
173 static destroyed_instance
*
174 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
181 destroyed_instance
* instance
=
182 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
183 instance
->name
= safe_strdup (name
);
184 instance
->type
= safe_strdup (type
);
185 instance
->widget
= widget
;
186 instance
->parent
= parent
;
187 instance
->pop_up_p
= pop_up_p
;
188 instance
->next
= NULL
;
193 free_destroyed_instance (instance
)
194 destroyed_instance
* instance
;
196 free (instance
->name
);
197 free (instance
->type
);
201 \f/* motif utility functions */
206 return ((CompositeWidget
)widget
)->composite
.children
[0];
210 lw_motif_widget_p (widget
)
214 XtClass (widget
) == xmDialogShellWidgetClass
215 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
219 resource_motif_string (widget
, name
)
226 resource
.resource_name
= name
;
227 resource
.resource_class
= XmCXmString
;
228 resource
.resource_type
= XmRXmString
;
229 resource
.resource_size
= sizeof (XmString
);
230 resource
.resource_offset
= 0;
231 resource
.default_type
= XtRImmediate
;
232 resource
.default_addr
= 0;
234 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
235 "DialogString", &resource
, 1, NULL
, 0);
239 /* Destroy all of the children of WIDGET
240 starting with number FIRST_CHILD_TO_DESTROY. */
243 destroy_all_children (widget
, first_child_to_destroy
)
245 int first_child_to_destroy
;
251 children
= XtCompositeChildren (widget
, &number
);
254 XtUnmanageChildren (children
+ first_child_to_destroy
,
255 number
- first_child_to_destroy
);
257 /* Unmanage all children and destroy them. They will only be
258 really destroyed when we get out of DispatchEvent. */
259 for (i
= first_child_to_destroy
; i
< number
; i
++)
263 /* Cascade buttons have submenus,and these submenus
264 need to be freed. But they are not included in
265 XtCompositeChildren. So get it out of the cascade button
266 and free it. If this child is not a cascade button,
267 then submenu should remain unchanged. */
268 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
269 XtGetValues (children
[i
], al
, 1);
272 destroy_all_children (submenu
, 0);
273 XtDestroyWidget (submenu
);
275 XtDestroyWidget (children
[i
]);
278 XtFree ((char *) children
);
284 /* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
285 menu. CLIENT_DATA contains a pointer to the widget_value
286 corresponding to widget W. CALL_DATA contains a
287 XmPushButtonCallbackStruct containing the reason why the callback
291 xm_arm_callback (w
, client_data
, call_data
)
293 XtPointer client_data
, call_data
;
295 XmPushButtonCallbackStruct
*cbs
= (XmPushButtonCallbackStruct
*) call_data
;
296 widget_value
*wv
= (widget_value
*) client_data
;
297 widget_instance
*instance
;
299 /* Get the id of the menu bar or popup menu this widget is in. */
302 if (XmIsRowColumn (w
))
304 unsigned char type
= 0xff;
306 XtVaGetValues (w
, XmNrowColumnType
, &type
, NULL
);
307 if (type
== XmMENU_BAR
|| type
== XmMENU_POPUP
)
316 instance
= lw_get_widget_instance (w
);
317 if (instance
&& instance
->info
->highlight_cb
)
319 call_data
= cbs
->reason
== XmCR_DISARM
? NULL
: wv
;
320 instance
->info
->highlight_cb (w
, instance
->info
->id
, call_data
);
327 /* Update the label of widget WIDGET. WIDGET must be a Label widget
328 or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
333 Emacs fills VAL->name with the text to display in the menu, and
334 sets VAL->value to null. Function make_menu_in_widget creates
335 widgets with VAL->name as resource name. This works because the
336 Label widget uses its resource name for display if no
337 XmNlabelString is set.
341 VAL->name is again set to the resource name, but VAL->value is
342 not null, and contains the label string to display. */
345 xm_update_label (instance
, widget
, val
)
346 widget_instance
* instance
;
350 XmString res_string
= 0;
351 XmString built_string
= 0;
352 XmString key_string
= 0;
360 /* A label string is specified, i.e. we are in a dialog. First
361 see if it is overridden by something from the resource file. */
362 res_string
= resource_motif_string (widget
, val
->value
);
366 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
371 XmStringCreateLtoR (val
->value
, XmSTRING_DEFAULT_CHARSET
);
372 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
375 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
380 key_string
= XmStringCreateLtoR (val
->key
, XmSTRING_DEFAULT_CHARSET
);
381 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
385 XtSetValues (widget
, al
, ac
);
388 XmStringFree (built_string
);
391 XmStringFree (key_string
);
394 \f/* update of list */
396 xm_update_list (instance
, widget
, val
)
397 widget_instance
* instance
;
403 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
404 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
406 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
409 XmString xmstr
= XmStringCreate (cur
->value
, XmSTRING_DEFAULT_CHARSET
);
411 XmListAddItem (widget
, xmstr
, 0);
413 XmListSelectPos (widget
, i
, False
);
414 XmStringFree (xmstr
);
418 \f/* update of buttons */
420 xm_update_pushbutton (instance
, widget
, val
)
421 widget_instance
* instance
;
425 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, NULL
);
426 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
427 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
431 xm_update_cascadebutton (instance
, widget
, val
)
432 widget_instance
* instance
;
436 /* Should also rebuild the menu by calling ...update_menu... */
437 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
438 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
442 \f/* update toggle and radiobox */
444 xm_update_toggle (instance
, widget
, val
)
445 widget_instance
* instance
;
449 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
450 XtAddCallback (widget
, XmNvalueChangedCallback
,
451 xm_generic_callback
, instance
);
452 XtVaSetValues (widget
, XmNset
, val
->selected
,
453 XmNalignment
, XmALIGNMENT_BEGINNING
, NULL
);
457 xm_update_radiobox (instance
, widget
, val
)
458 widget_instance
* instance
;
466 /* update the callback */
467 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
468 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
470 /* first update all the toggles */
471 /* Energize kernel interface is currently bad. It sets the selected widget
472 with the selected flag but returns it by its name. So we currently
473 have to support both setting the selection with the selected slot
474 of val contents and setting it with the "value" slot of val. The latter
475 has a higher priority. This to be removed when the kernel is fixed. */
476 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
478 toggle
= XtNameToWidget (widget
, cur
->value
);
481 XtSetSensitive (toggle
, cur
->enabled
);
482 if (!val
->value
&& cur
->selected
)
483 XtVaSetValues (toggle
, XmNset
, cur
->selected
, NULL
);
484 if (val
->value
&& strcmp (val
->value
, cur
->value
))
485 XtVaSetValues (toggle
, XmNset
, False
, NULL
);
489 /* The selected was specified by the value slot */
492 toggle
= XtNameToWidget (widget
, val
->value
);
494 XtVaSetValues (toggle
, XmNset
, True
, NULL
);
499 /* update a popup menu, pulldown menu or a menubar */
501 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
504 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
505 widget_instance
* instance
;
508 int keep_first_children
;
510 Widget
* children
= 0;
522 Widget
* old_children
;
523 unsigned int old_num_children
;
525 old_children
= XtCompositeChildren (widget
, &old_num_children
);
527 /* Allocate the children array */
528 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
)
530 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
532 /* WIDGET should be a RowColumn. */
533 if (!XmIsRowColumn (widget
))
536 /* Determine whether WIDGET is a menu bar. */
538 XtSetArg (al
[0], XmNrowColumnType
, &type
);
539 XtGetValues (widget
, al
, 1);
540 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
542 menubar_p
= type
== XmMENU_BAR
;
544 /* Add a callback to popups and pulldowns that is called when
545 it is made invisible again. */
547 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
548 xm_pop_down_callback
, (XtPointer
)instance
);
550 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
551 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
552 child_index
++, cur
= cur
->next
)
553 children
[child_index
] = old_children
[child_index
];
555 /* Check that those are all we have
556 (the caller should have deleted the rest). */
557 if (old_num_children
!= keep_first_children
)
560 /* Create the rest. */
561 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
563 enum menu_separator separator
;
566 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
567 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
568 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
570 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
571 && !lw_separator_p (cur
->name
, &separator
, 1))
574 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
575 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
577 else if (lw_separator_p (cur
->name
, &separator
, 1))
580 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
581 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
583 else if (!cur
->contents
)
586 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
587 else if (!cur
->call_data
)
588 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
589 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
590 || cur
->button_type
== BUTTON_TYPE_RADIO
)
592 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
593 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
594 XtSetArg (al
[ac
], XmNindicatorType
,
595 (cur
->button_type
== BUTTON_TYPE_TOGGLE
596 ? XmN_OF_MANY
: XmONE_OF_MANY
));
598 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
599 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
600 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
604 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
605 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
606 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
609 xm_update_label (instance
, button
, cur
);
611 /* Add a callback that is called when the button is
612 selected. Toggle buttons don't support
613 XmNactivateCallback, we use XmNvalueChangedCallback in
614 that case. Don't add a callback to a simple label. */
615 if (cur
->button_type
)
616 xm_update_toggle (instance
, button
, cur
);
617 else if (cur
->call_data
)
618 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
619 (XtPointer
)instance
);
623 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
625 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
626 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
627 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
629 xm_update_label (instance
, button
, cur
);
631 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
632 (XtPointer
)instance
);
635 children
[child_index
] = button
;
638 /* Last entry is the help button. The original comment read "Has to
639 be done after managing the buttons otherwise the menubar is only
640 4 pixels high." This is no longer true, and to make
641 XmNmenuHelpWidget work, we need to set it before managing the
642 children.. --gerd. */
644 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, NULL
);
647 XtManageChildren (children
, num_children
);
649 XtFree ((char *) children
);
651 XtFree ((char *) old_children
);
655 update_one_menu_entry (instance
, widget
, val
, deep_p
)
656 widget_instance
* instance
;
664 widget_value
* contents
;
666 if (val
->this_one_change
== NO_CHANGE
)
669 /* update the sensitivity and userdata */
670 /* Common to all widget types */
671 XtSetSensitive (widget
, val
->enabled
);
672 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
674 /* update the menu button as a label. */
675 if (val
->this_one_change
>= VISIBLE_CHANGE
)
677 xm_update_label (instance
, widget
, val
);
678 if (val
->button_type
)
679 xm_update_toggle (instance
, widget
, val
);
682 /* update the pulldown/pullaside as needed */
685 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
686 XtGetValues (widget
, al
, ac
);
688 contents
= val
->contents
;
694 unsigned int old_num_children
, i
;
698 parent
= XtParent (widget
);
699 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
701 /* Find the widget position within the parent's widget list. */
702 for (i
= 0; i
< old_num_children
; i
++)
703 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
705 if (i
== old_num_children
)
707 if (XmIsCascadeButton (widget_list
[i
]))
709 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
710 make_menu_in_widget (instance
, menu
, contents
, 0);
712 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
713 XtSetValues (widget
, al
, ac
);
719 /* The current menuitem is a XmPushButtonGadget, it
720 needs to be replaced by a CascadeButtonGadget */
721 XtDestroyWidget (widget_list
[i
]);
722 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
723 make_menu_in_widget (instance
, menu
, contents
, 0);
725 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
726 /* Non-zero values don't work reliably in
727 conjunction with Emacs' event loop */
728 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
729 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
730 /* Tell Motif to put it in the right place */
731 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
733 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
734 xm_update_label (instance
, button
, val
);
736 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
737 (XtPointer
)instance
);
738 XtManageChild (button
);
742 XtFree ((char*) widget_list
);
748 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
749 XtSetValues (widget
, al
, ac
);
750 XtDestroyWidget (menu
);
752 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
753 xm_update_menu (instance
, menu
, val
, 1);
757 xm_update_menu (instance
, widget
, val
, deep_p
)
758 widget_instance
* instance
;
764 unsigned int num_children
;
765 int num_children_to_keep
= 0;
769 children
= XtCompositeChildren (widget
, &num_children
);
771 /* Widget is a RowColumn widget whose contents have to be updated
772 * to reflect the list of items in val->contents */
774 /* See how many buttons we can keep, and how many we
775 must completely replace. */
776 if (val
->contents
== 0)
777 num_children_to_keep
= 0;
778 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
782 for (i
= 0, cur
= val
->contents
;
784 && cur
); /* how else to ditch unwanted children ?? - mgd */
785 i
++, cur
= cur
->next
)
787 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
791 num_children_to_keep
= i
;
795 num_children_to_keep
= num_children
;
797 /* Update all the buttons of the RowColumn, in order,
798 except for those we are going to replace entirely. */
801 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
805 num_children_to_keep
= i
;
808 if (children
[i
]->core
.being_destroyed
809 || strcmp (XtName (children
[i
]), cur
->name
))
811 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
816 /* Now replace from scratch all the buttons after the last
817 place that the top-level structure changed. */
818 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
820 destroy_all_children (widget
, num_children_to_keep
);
821 make_menu_in_widget (instance
, widget
, val
->contents
,
822 num_children_to_keep
);
825 XtFree ((char *) children
);
829 /* update text widgets */
832 xm_update_text (instance
, widget
, val
)
833 widget_instance
* instance
;
837 XmTextSetString (widget
, val
->value
? val
->value
: "");
838 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
839 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
840 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
841 XtAddCallback (widget
, XmNvalueChangedCallback
,
842 xm_internal_update_other_instances
, instance
);
846 xm_update_text_field (instance
, widget
, val
)
847 widget_instance
* instance
;
851 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
852 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
853 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
854 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
855 XtAddCallback (widget
, XmNvalueChangedCallback
,
856 xm_internal_update_other_instances
, instance
);
860 /* update a motif widget */
863 xm_update_one_widget (instance
, widget
, val
, deep_p
)
864 widget_instance
* instance
;
871 /* Mark as not edited */
874 /* Common to all widget types */
875 XtSetSensitive (widget
, val
->enabled
);
876 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
878 /* Common to all label like widgets */
879 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
880 xm_update_label (instance
, widget
, val
);
882 class = XtClass (widget
);
883 /* Class specific things */
884 if (class == xmPushButtonWidgetClass
||
885 class == xmArrowButtonWidgetClass
)
887 xm_update_pushbutton (instance
, widget
, val
);
889 else if (class == xmCascadeButtonWidgetClass
)
891 xm_update_cascadebutton (instance
, widget
, val
);
893 else if (class == xmToggleButtonWidgetClass
894 || class == xmToggleButtonGadgetClass
)
896 xm_update_toggle (instance
, widget
, val
);
898 else if (class == xmRowColumnWidgetClass
)
900 Boolean radiobox
= 0;
904 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
905 XtGetValues (widget
, al
, ac
);
908 xm_update_radiobox (instance
, widget
, val
);
910 xm_update_menu (instance
, widget
, val
, deep_p
);
912 else if (class == xmTextWidgetClass
)
914 xm_update_text (instance
, widget
, val
);
916 else if (class == xmTextFieldWidgetClass
)
918 xm_update_text_field (instance
, widget
, val
);
920 else if (class == xmListWidgetClass
)
922 xm_update_list (instance
, widget
, val
);
926 \f/* getting the value back */
928 xm_update_one_value (instance
, widget
, val
)
929 widget_instance
* instance
;
933 WidgetClass
class = XtClass (widget
);
934 widget_value
*old_wv
;
936 /* copy the call_data slot into the "return" widget_value */
937 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
938 if (!strcmp (val
->name
, old_wv
->name
))
940 val
->call_data
= old_wv
->call_data
;
944 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
946 XtVaGetValues (widget
, XmNset
, &val
->selected
, NULL
);
949 else if (class == xmTextWidgetClass
)
953 val
->value
= XmTextGetString (widget
);
956 else if (class == xmTextFieldWidgetClass
)
960 val
->value
= XmTextFieldGetString (widget
);
963 else if (class == xmRowColumnWidgetClass
)
965 Boolean radiobox
= 0;
969 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
970 XtGetValues (widget
, al
, ac
);
974 CompositeWidget radio
= (CompositeWidget
)widget
;
976 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
979 Widget toggle
= radio
->composite
.children
[i
];
981 XtVaGetValues (toggle
, XmNset
, &set
, NULL
);
986 val
->value
= safe_strdup (XtName (toggle
));
992 else if (class == xmListWidgetClass
)
996 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
1000 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
1004 cur
->selected
= False
;
1006 for (j
= 0; j
< pos_cnt
; j
++)
1007 if (pos_list
[j
] == i
)
1009 cur
->selected
= True
;
1010 val
->value
= safe_strdup (cur
->name
);
1014 XtFree ((char *) pos_list
);
1020 /* This function is for activating a button from a program. It's wrong because
1021 we pass a NULL argument in the call_data which is not Motif compatible.
1022 This is used from the XmNdefaultAction callback of the List widgets to
1023 have a double-click put down a dialog box like the button would do.
1024 I could not find a way to do that with accelerators.
1027 activate_button (widget
, closure
, call_data
)
1030 XtPointer call_data
;
1032 Widget button
= (Widget
)closure
;
1033 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
1036 /* creation functions */
1038 /* Called for key press in dialogs. Used to pop down dialog on ESC. */
1040 dialog_key_cb (widget
, closure
, event
, continue_to_dispatch
)
1044 Boolean
*continue_to_dispatch
;
1047 Modifiers modif_ret
;
1049 XtTranslateKeycode (event
->xkey
.display
, event
->xkey
.keycode
, 0,
1052 if (sym
== osfXK_Cancel
)
1054 Widget w
= *((Widget
*) closure
);
1056 while (w
&& ! XtIsShell (w
))
1059 if (XtIsShell (w
)) XtPopdown (w
);
1062 *continue_to_dispatch
= TRUE
;
1067 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
1068 radio_box
, list
, left_buttons
, right_buttons
)
1074 Boolean text_input_slot
;
1084 Widget icon_separator
;
1089 Widget children
[16]; /* for the final XtManageChildren */
1091 Arg al
[64]; /* Arg List */
1092 int ac
; /* Arg Count */
1098 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
1099 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
1100 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
1101 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1103 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1104 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1105 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1106 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1111 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1112 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1113 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1117 n_children
= left_buttons
+ right_buttons
+ 1;
1119 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1120 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1121 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1122 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1123 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1124 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1125 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1126 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1127 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1128 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1129 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1130 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1131 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1132 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1133 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1134 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1135 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1136 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1137 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1140 for (i
= 0; i
< left_buttons
; i
++)
1142 char button_name
[16];
1143 sprintf (button_name
, "button%d", i
+ 1);
1147 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1148 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1150 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1151 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1152 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1153 XtAddEventHandler (children
[n_children
],
1154 KeyPressMask
, False
, dialog_key_cb
, result
);
1158 button
= children
[n_children
];
1160 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1161 XtSetValues (row
, al
, ac
);
1167 /* invisible separator button */
1169 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1170 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1173 for (i
= 0; i
< right_buttons
; i
++)
1175 char button_name
[16];
1176 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1178 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1179 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1180 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1181 XtAddEventHandler (children
[n_children
],
1182 KeyPressMask
, False
, dialog_key_cb
, result
);
1184 if (! button
) button
= children
[n_children
];
1188 XtManageChildren (children
, n_children
);
1191 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1192 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1193 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1194 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1195 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1196 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1197 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1198 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1199 separator
= XmCreateSeparator (form
, "", al
, ac
);
1202 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1203 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1204 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1205 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1206 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1207 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1208 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1209 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1212 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1213 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1214 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1215 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1216 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1217 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1218 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1219 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1220 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1221 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1223 if (text_input_slot
)
1226 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1227 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1228 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1229 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1230 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1231 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1232 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1233 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1234 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1235 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1236 value
= XmCreateTextField (form
, "value", al
, ac
);
1242 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1243 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1244 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1245 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1246 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1247 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1248 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1249 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1250 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1251 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1252 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1253 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1254 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1255 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1258 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1259 children
[i
++] = radio_butt
;
1260 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1261 children
[i
++] = radio_butt
;
1262 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1263 children
[i
++] = radio_butt
;
1264 XtManageChildren (children
, i
);
1269 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1270 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1271 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1272 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1273 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1274 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1275 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1276 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1277 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1278 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1279 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1281 /* this is the easiest way I found to have the dble click in the
1282 list activate the default button */
1283 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1287 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1288 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1289 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1290 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1291 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1292 XtSetArg(al
[ac
], XmNbottomWidget
,
1293 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1294 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1295 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1296 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1297 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1298 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1299 message
= XmCreateLabel (form
, "message", al
, ac
);
1302 XtManageChild (value
);
1305 children
[i
] = row
; i
++;
1306 children
[i
] = separator
; i
++;
1307 if (text_input_slot
|| radio_box
)
1309 children
[i
] = value
; i
++;
1311 children
[i
] = message
; i
++;
1312 children
[i
] = icon
; i
++;
1313 children
[i
] = icon_separator
; i
++;
1314 XtManageChildren (children
, i
);
1316 if (text_input_slot
|| list
)
1318 XtInstallAccelerators (value
, button
);
1319 XtSetKeyboardFocus (result
, value
);
1323 XtInstallAccelerators (form
, button
);
1324 XtSetKeyboardFocus (result
, button
);
1330 static destroyed_instance
*
1331 find_matching_instance (instance
)
1332 widget_instance
* instance
;
1334 destroyed_instance
* cur
;
1335 destroyed_instance
* prev
;
1336 char* type
= instance
->info
->type
;
1337 char* name
= instance
->info
->name
;
1339 for (prev
= NULL
, cur
= all_destroyed_instances
;
1341 prev
= cur
, cur
= cur
->next
)
1343 if (!strcmp (cur
->name
, name
)
1344 && !strcmp (cur
->type
, type
)
1345 && cur
->parent
== instance
->parent
1346 && cur
->pop_up_p
== instance
->pop_up_p
)
1349 prev
->next
= cur
->next
;
1351 all_destroyed_instances
= cur
->next
;
1354 /* do some cleanup */
1355 else if (!cur
->widget
)
1358 prev
->next
= cur
->next
;
1360 all_destroyed_instances
= cur
->next
;
1361 free_destroyed_instance (cur
);
1362 cur
= prev
? prev
: all_destroyed_instances
;
1369 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1372 XtPointer call_data
;
1374 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1375 instance
->widget
= NULL
;
1379 recenter_widget (widget
)
1382 Widget parent
= XtParent (widget
);
1383 Screen
* screen
= XtScreen (widget
);
1384 Dimension screen_width
= WidthOfScreen (screen
);
1385 Dimension screen_height
= HeightOfScreen (screen
);
1386 Dimension parent_width
= 0;
1387 Dimension parent_height
= 0;
1388 Dimension child_width
= 0;
1389 Dimension child_height
= 0;
1393 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, NULL
);
1394 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1397 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1398 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1400 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1402 if (x
+ child_width
> screen_width
)
1403 x
= screen_width
- child_width
;
1407 if (y
+ child_height
> screen_height
)
1408 y
= screen_height
- child_height
;
1412 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, NULL
);
1416 recycle_instance (instance
)
1417 destroyed_instance
* instance
;
1419 Widget widget
= instance
->widget
;
1421 /* widget is NULL if the parent was destroyed. */
1427 /* Remove the destroy callback as the instance is not in the list
1429 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1430 mark_dead_instance_destroyed
,
1431 (XtPointer
)instance
);
1433 /* Give the focus to the initial item */
1434 focus
= XtNameToWidget (widget
, "*value");
1436 focus
= XtNameToWidget (widget
, "*button1");
1438 XtSetKeyboardFocus (widget
, focus
);
1440 /* shrink the separator label back to their original size */
1441 separator
= XtNameToWidget (widget
, "*separator_button");
1443 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, NULL
);
1445 /* Center the dialog in its parent */
1446 recenter_widget (widget
);
1448 free_destroyed_instance (instance
);
1453 xm_create_dialog (instance
)
1454 widget_instance
* instance
;
1456 char* name
= instance
->info
->type
;
1457 Widget parent
= instance
->parent
;
1459 Boolean pop_up_p
= instance
->pop_up_p
;
1460 char* shell_name
= 0;
1461 char* icon_name
= 0;
1462 Boolean text_input_slot
= False
;
1463 Boolean radio_box
= False
;
1464 Boolean list
= False
;
1466 int left_buttons
= 0;
1467 int right_buttons
= 1;
1468 destroyed_instance
* dead_one
;
1470 /* try to find a widget to recycle */
1471 dead_one
= find_matching_instance (instance
);
1474 Widget recycled_widget
= recycle_instance (dead_one
);
1475 if (recycled_widget
)
1476 return recycled_widget
;
1481 icon_name
= "dbox-error";
1482 shell_name
= "Error";
1486 icon_name
= "dbox-info";
1487 shell_name
= "Information";
1492 icon_name
= "dbox-question";
1493 shell_name
= "Prompt";
1497 text_input_slot
= True
;
1498 icon_name
= "dbox-question";
1499 shell_name
= "Prompt";
1503 icon_name
= "dbox-question";
1504 shell_name
= "Question";
1508 total_buttons
= name
[1] - '0';
1510 if (name
[3] == 'T' || name
[3] == 't')
1512 text_input_slot
= False
;
1516 right_buttons
= name
[4] - '0';
1518 left_buttons
= total_buttons
- right_buttons
;
1520 widget
= make_dialog (name
, parent
, pop_up_p
,
1521 shell_name
, icon_name
, text_input_slot
, radio_box
,
1522 list
, left_buttons
, right_buttons
);
1524 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1525 (XtPointer
) instance
);
1530 /* Create a menu bar. We turn off the f10 key
1531 because we have not yet managed to make it work right in Motif. */
1534 make_menubar (instance
)
1535 widget_instance
* instance
;
1541 XtSetArg(al
[ac
], XmNmenuAccelerator
, 0); ++ac
;
1542 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, ac
);
1546 remove_grabs (shell
, closure
, call_data
)
1549 XtPointer call_data
;
1551 Widget menu
= (Widget
) closure
;
1552 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1556 make_popup_menu (instance
)
1557 widget_instance
* instance
;
1559 Widget parent
= instance
->parent
;
1560 Window parent_window
= parent
->core
.window
;
1563 /* sets the parent window to 0 to fool Motif into not generating a grab */
1564 parent
->core
.window
= 0;
1565 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1566 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1568 parent
->core
.window
= parent_window
;
1573 make_main (instance
)
1574 widget_instance
* instance
;
1576 Widget parent
= instance
->parent
;
1582 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1583 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1584 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1588 \f/* Table of functions to create widgets */
1592 /* interface with the XDesigner generated functions */
1593 typedef Widget (*widget_maker
) (Widget
);
1594 extern Widget
create_project_p_sheet (Widget parent
);
1595 extern Widget
create_debugger_p_sheet (Widget parent
);
1596 extern Widget
create_breaklist_p_sheet (Widget parent
);
1597 extern Widget
create_le_browser_p_sheet (Widget parent
);
1598 extern Widget
create_class_browser_p_sheet (Widget parent
);
1599 extern Widget
create_call_browser_p_sheet (Widget parent
);
1600 extern Widget
create_build_dialog (Widget parent
);
1601 extern Widget
create_editmode_dialog (Widget parent
);
1602 extern Widget
create_search_dialog (Widget parent
);
1603 extern Widget
create_project_display_dialog (Widget parent
);
1606 make_one (widget_instance
* instance
, widget_maker fn
)
1612 if (instance
->pop_up_p
)
1614 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1615 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1616 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1617 (XtPointer
) instance
);
1622 result
= (*fn
) (instance
->parent
);
1623 XtRealizeWidget (result
);
1629 make_project_p_sheet (widget_instance
* instance
)
1631 return make_one (instance
, create_project_p_sheet
);
1635 make_debugger_p_sheet (widget_instance
* instance
)
1637 return make_one (instance
, create_debugger_p_sheet
);
1641 make_breaklist_p_sheet (widget_instance
* instance
)
1643 return make_one (instance
, create_breaklist_p_sheet
);
1647 make_le_browser_p_sheet (widget_instance
* instance
)
1649 return make_one (instance
, create_le_browser_p_sheet
);
1653 make_class_browser_p_sheet (widget_instance
* instance
)
1655 return make_one (instance
, create_class_browser_p_sheet
);
1659 make_call_browser_p_sheet (widget_instance
* instance
)
1661 return make_one (instance
, create_call_browser_p_sheet
);
1665 make_build_dialog (widget_instance
* instance
)
1667 return make_one (instance
, create_build_dialog
);
1671 make_editmode_dialog (widget_instance
* instance
)
1673 return make_one (instance
, create_editmode_dialog
);
1677 make_search_dialog (widget_instance
* instance
)
1679 return make_one (instance
, create_search_dialog
);
1683 make_project_display_dialog (widget_instance
* instance
)
1685 return make_one (instance
, create_project_display_dialog
);
1688 #endif /* ENERGIZE */
1690 widget_creation_entry
1691 xm_creation_table
[] =
1693 {"menubar", make_menubar
},
1694 {"popup", make_popup_menu
},
1695 {"main", make_main
},
1697 {"project_p_sheet", make_project_p_sheet
},
1698 {"debugger_p_sheet", make_debugger_p_sheet
},
1699 {"breaklist_psheet", make_breaklist_p_sheet
},
1700 {"leb_psheet", make_le_browser_p_sheet
},
1701 {"class_browser_psheet", make_class_browser_p_sheet
},
1702 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1703 {"build", make_build_dialog
},
1704 {"editmode", make_editmode_dialog
},
1705 {"search", make_search_dialog
},
1706 {"project_display", make_project_display_dialog
},
1707 #endif /* ENERGIZE */
1711 \f/* Destruction of instances */
1713 xm_destroy_instance (instance
)
1714 widget_instance
* instance
;
1716 Widget widget
= instance
->widget
;
1717 /* recycle the dialog boxes */
1718 /* Disable the recycling until we can find a way to have the dialog box
1719 get reasonable layout after we modify its contents. */
1721 && XtClass (widget
) == xmDialogShellWidgetClass
)
1723 destroyed_instance
* dead_instance
=
1724 make_destroyed_instance (instance
->info
->name
,
1725 instance
->info
->type
,
1728 instance
->pop_up_p
);
1729 dead_instance
->next
= all_destroyed_instances
;
1730 all_destroyed_instances
= dead_instance
;
1731 XtUnmanageChild (first_child (instance
->widget
));
1732 XFlush (XtDisplay (instance
->widget
));
1733 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1734 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1738 /* This might not be necessary now that the nosel is attached to
1739 popdown instead of destroy, but it can't hurt. */
1740 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1741 xm_nosel_callback
, (XtPointer
)instance
);
1742 XtDestroyWidget (instance
->widget
);
1746 \f/* popup utility */
1748 xm_popup_menu (widget
, event
)
1752 XButtonPressedEvent dummy
;
1756 dummy
.type
= ButtonPress
;
1758 dummy
.send_event
= 0;
1759 dummy
.display
= XtDisplay (widget
);
1760 dummy
.window
= XtWindow (XtParent (widget
));
1763 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1764 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1765 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1766 event
= (XEvent
*) &dummy
;
1769 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1771 /* Setting the menuPost resource only required by Motif 1.1 and
1772 LessTif 0.84 and earlier. With later versions of LessTif,
1773 setting menuPost is unnecessary and may cause problems, so
1775 #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
1777 /* This is so totally ridiculous: there's NO WAY to tell Motif
1778 that *any* button can select a menu item. Only one button
1779 can have that honor. */
1782 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1783 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1784 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1785 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1786 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1787 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, NULL
);
1791 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1794 XtManageChild (widget
);
1798 set_min_dialog_size (w
)
1803 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, NULL
);
1804 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, NULL
);
1808 xm_pop_instance (instance
, up
)
1809 widget_instance
* instance
;
1812 Widget widget
= instance
->widget
;
1814 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1816 Widget widget_to_manage
= first_child (widget
);
1819 XtManageChild (widget_to_manage
);
1820 set_min_dialog_size (widget
);
1821 XtSetKeyboardFocus (instance
->parent
, widget
);
1824 XtUnmanageChild (widget_to_manage
);
1829 XtManageChild (widget
);
1831 XtUnmanageChild (widget
);
1836 /* motif callback */
1839 do_call (widget
, closure
, type
)
1842 enum do_call_type type
;
1846 XtPointer user_data
;
1847 widget_instance
* instance
= (widget_instance
*)closure
;
1848 Widget instance_widget
;
1853 if (widget
->core
.being_destroyed
)
1856 instance_widget
= instance
->widget
;
1857 if (!instance_widget
)
1860 id
= instance
->info
->id
;
1863 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1864 XtGetValues (widget
, al
, ac
);
1869 if (instance
->info
->pre_activate_cb
)
1870 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1874 if (instance
->info
->selection_cb
)
1875 instance
->info
->selection_cb (widget
, id
, user_data
);
1879 if (instance
->info
->selection_cb
)
1880 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1884 if (instance
->info
->post_activate_cb
)
1885 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1893 /* Like lw_internal_update_other_instances except that it does not do
1894 anything if its shell parent is not managed. This is to protect
1895 lw_internal_update_other_instances to dereference freed memory
1896 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1899 xm_internal_update_other_instances (widget
, closure
, call_data
)
1902 XtPointer call_data
;
1905 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1906 if (XtIsShell (parent
))
1908 else if (!XtIsManaged (parent
))
1910 lw_internal_update_other_instances (widget
, closure
, call_data
);
1914 xm_generic_callback (widget
, closure
, call_data
)
1917 XtPointer call_data
;
1919 lw_internal_update_other_instances (widget
, closure
, call_data
);
1920 do_call (widget
, closure
, selection
);
1924 xm_nosel_callback (widget
, closure
, call_data
)
1927 XtPointer call_data
;
1929 /* This callback is only called when a dialog box is dismissed with
1930 the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog
1931 box to be destroyed in that case, not just unmapped, so that it
1932 releases its keyboard grabs. But there are problems with running
1933 our callbacks while the widget is in the process of being
1934 destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
1935 XmDESTROY and then destroy it ourself after having run the
1937 do_call (widget
, closure
, no_selection
);
1938 XtDestroyWidget (widget
);
1942 xm_pull_down_callback (widget
, closure
, call_data
)
1945 XtPointer call_data
;
1947 Widget parent
= XtParent (widget
);
1949 if (XmIsRowColumn (parent
))
1951 unsigned char type
= 0xff;
1952 XtVaGetValues (parent
, XmNrowColumnType
, &type
, NULL
);
1953 if (type
== XmMENU_BAR
)
1954 do_call (widget
, closure
, pre_activate
);
1959 /* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
1960 CLOSURE is a pointer to the widget_instance of the shell,
1962 Note that this callback is called for each cascade button in a
1963 menu, whether or not its submenu is visible. */
1966 xm_pop_down_callback (widget
, closure
, call_data
)
1969 XtPointer call_data
;
1971 widget_instance
*instance
= (widget_instance
*) closure
;
1973 if ((!instance
->pop_up_p
&& XtParent (widget
) == instance
->widget
)
1974 || XtParent (widget
) == instance
->parent
)
1975 do_call (widget
, closure
, post_activate
);
1979 /* set the keyboard focus */
1981 xm_set_keyboard_focus (parent
, w
)
1985 XmProcessTraversal (w
, 0);
1986 XtSetKeyboardFocus (parent
, w
);
1989 /* Motif hack to set the main window areas. */
1991 xm_set_main_areas (parent
, menubar
, work_area
)
1996 XmMainWindowSetAreas (parent
,
1997 menubar
, /* menubar (maybe 0) */
1998 0, /* command area (psheets) */
1999 0, /* horizontal scroll */
2000 0, /* vertical scroll */
2001 work_area
); /* work area */
2004 /* Motif hack to control resizing on the menubar. */
2006 xm_manage_resizing (w
, flag
)
2010 XtVaSetValues (w
, XtNallowShellResize
, flag
, NULL
);
2013 /* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
2014 (do not change this comment) */