1 /* The lwlib interface to Motif widgets.
2 Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005
3 Free Software Foundation, Inc.
4 Copyright (C) 1992 Lucid, Inc.
6 This file is part of the Lucid Widget Library.
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
30 #include <X11/StringDefs.h>
31 #include <X11/IntrinsicP.h>
32 #include <X11/ObjectP.h>
33 #include <X11/CoreP.h>
34 #include <X11/CompositeP.h>
36 #include "../src/lisp.h"
39 #include "lwlib-utils.h"
41 #include <Xm/BulletinB.h>
42 #include <Xm/CascadeB.h>
43 #include <Xm/CascadeBG.h>
44 #include <Xm/DrawingA.h>
45 #include <Xm/FileSB.h>
49 #include <Xm/MenuShell.h>
50 #include <Xm/MessageB.h>
51 #include <Xm/PanedW.h>
53 #include <Xm/PushBG.h>
54 #include <Xm/ArrowB.h>
55 #include <Xm/SelectioB.h>
58 #include <Xm/ToggleB.h>
59 #include <Xm/ToggleBG.h>
60 #include <Xm/RowColumn.h>
61 #include <Xm/ScrolledW.h>
62 #include <Xm/Separator.h>
63 #include <Xm/DialogS.h>
67 #if defined __STDC__ || defined PROTOTYPES
73 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
76 \f/* Structures to keep destroyed instances */
77 typedef struct _destroyed_instance
84 struct _destroyed_instance
* next
;
87 static destroyed_instance
*make_destroyed_instance
P_ ((char *, char *,
90 static void free_destroyed_instance
P_ ((destroyed_instance
*));
91 Widget first_child
P_ ((Widget
));
92 Boolean lw_motif_widget_p
P_ ((Widget
));
93 static XmString resource_motif_string
P_ ((Widget
, char *));
94 static void destroy_all_children
P_ ((Widget
, int));
95 static void xm_update_label
P_ ((widget_instance
*, Widget
, widget_value
*));
96 static void xm_update_list
P_ ((widget_instance
*, Widget
, widget_value
*));
97 static void xm_update_pushbutton
P_ ((widget_instance
*, Widget
,
99 static void xm_update_cascadebutton
P_ ((widget_instance
*, Widget
,
101 static void xm_update_toggle
P_ ((widget_instance
*, Widget
, widget_value
*));
102 static void xm_update_radiobox
P_ ((widget_instance
*, Widget
, widget_value
*));
103 static void make_menu_in_widget
P_ ((widget_instance
*, Widget
,
104 widget_value
*, int));
105 static void update_one_menu_entry
P_ ((widget_instance
*, Widget
,
106 widget_value
*, Boolean
));
107 static void xm_update_menu
P_ ((widget_instance
*, Widget
, widget_value
*,
109 static void xm_update_text
P_ ((widget_instance
*, Widget
, widget_value
*));
110 static void xm_update_text_field
P_ ((widget_instance
*, Widget
,
112 void xm_update_one_value
P_ ((widget_instance
*, Widget
, widget_value
*));
113 static void activate_button
P_ ((Widget
, XtPointer
, XtPointer
));
114 static Widget make_dialog
P_ ((char *, Widget
, Boolean
, char *, char *,
115 Boolean
, Boolean
, Boolean
, int, int));
116 static destroyed_instance
* find_matching_instance
P_ ((widget_instance
*));
117 static void mark_dead_instance_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
118 static void recenter_widget
P_ ((Widget
));
119 static Widget recycle_instance
P_ ((destroyed_instance
*));
120 Widget xm_create_dialog
P_ ((widget_instance
*));
121 static Widget make_menubar
P_ ((widget_instance
*));
122 static void remove_grabs
P_ ((Widget
, XtPointer
, XtPointer
));
123 static Widget make_popup_menu
P_ ((widget_instance
*));
124 static Widget make_main
P_ ((widget_instance
*));
125 void xm_destroy_instance
P_ ((widget_instance
*));
126 void xm_popup_menu
P_ ((Widget
, XEvent
*));
127 static void set_min_dialog_size
P_ ((Widget
));
128 static void do_call
P_ ((Widget
, XtPointer
, enum do_call_type
));
129 static void xm_generic_callback
P_ ((Widget
, XtPointer
, XtPointer
));
130 static void xm_nosel_callback
P_ ((Widget
, XtPointer
, XtPointer
));
131 static void xm_pull_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
132 static void xm_pop_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
133 void xm_set_keyboard_focus
P_ ((Widget
, Widget
));
134 void xm_set_main_areas
P_ ((Widget
, Widget
, Widget
));
135 static void xm_internal_update_other_instances
P_ ((Widget
, XtPointer
,
137 static void xm_arm_callback
P_ ((Widget
, XtPointer
, XtPointer
));
140 void xm_update_one_widget
P_ ((widget_instance
*, Widget
, widget_value
*,
142 void xm_pop_instance
P_ ((widget_instance
*, Boolean
));
143 void xm_manage_resizing
P_ ((Widget
, Boolean
));
149 /* Print the complete X resource name of widget WIDGET to stderr.
150 This is sometimes handy to have available. */
153 x_print_complete_resource_name (widget
)
159 for (i
= 0; i
< 100 && widget
!= NULL
; ++i
)
161 names
[i
] = XtName (widget
);
162 widget
= XtParent (widget
);
165 for (--i
; i
>= 1; --i
)
166 fprintf (stderr
, "%s.", names
[i
]);
167 fprintf (stderr
, "%s\n", names
[0]);
173 static destroyed_instance
*all_destroyed_instances
= NULL
;
175 static destroyed_instance
*
176 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
183 destroyed_instance
* instance
=
184 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
185 instance
->name
= safe_strdup (name
);
186 instance
->type
= safe_strdup (type
);
187 instance
->widget
= widget
;
188 instance
->parent
= parent
;
189 instance
->pop_up_p
= pop_up_p
;
190 instance
->next
= NULL
;
195 free_destroyed_instance (instance
)
196 destroyed_instance
* instance
;
198 free (instance
->name
);
199 free (instance
->type
);
203 \f/* motif utility functions */
208 return ((CompositeWidget
)widget
)->composite
.children
[0];
212 lw_motif_widget_p (widget
)
216 XtClass (widget
) == xmDialogShellWidgetClass
217 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
221 resource_motif_string (widget
, name
)
228 resource
.resource_name
= name
;
229 resource
.resource_class
= XmCXmString
;
230 resource
.resource_type
= XmRXmString
;
231 resource
.resource_size
= sizeof (XmString
);
232 resource
.resource_offset
= 0;
233 resource
.default_type
= XtRImmediate
;
234 resource
.default_addr
= 0;
236 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
237 "DialogString", &resource
, 1, NULL
, 0);
241 /* Destroy all of the children of WIDGET
242 starting with number FIRST_CHILD_TO_DESTROY. */
245 destroy_all_children (widget
, first_child_to_destroy
)
247 int first_child_to_destroy
;
253 children
= XtCompositeChildren (widget
, &number
);
256 XtUnmanageChildren (children
+ first_child_to_destroy
,
257 number
- first_child_to_destroy
);
259 /* Unmanage all children and destroy them. They will only be
260 really destroyed when we get out of DispatchEvent. */
261 for (i
= first_child_to_destroy
; i
< number
; i
++)
265 /* Cascade buttons have submenus,and these submenus
266 need to be freed. But they are not included in
267 XtCompositeChildren. So get it out of the cascade button
268 and free it. If this child is not a cascade button,
269 then submenu should remain unchanged. */
270 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
271 XtGetValues (children
[i
], al
, 1);
274 destroy_all_children (submenu
, 0);
275 XtDestroyWidget (submenu
);
277 XtDestroyWidget (children
[i
]);
280 XtFree ((char *) children
);
286 /* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
287 menu. CLIENT_DATA contains a pointer to the widget_value
288 corresponding to widget W. CALL_DATA contains a
289 XmPushButtonCallbackStruct containing the reason why the callback
293 xm_arm_callback (w
, client_data
, call_data
)
295 XtPointer client_data
, call_data
;
297 XmPushButtonCallbackStruct
*cbs
= (XmPushButtonCallbackStruct
*) call_data
;
298 widget_value
*wv
= (widget_value
*) client_data
;
299 widget_instance
*instance
;
301 /* Get the id of the menu bar or popup menu this widget is in. */
304 if (XmIsRowColumn (w
))
306 unsigned char type
= 0xff;
308 XtVaGetValues (w
, XmNrowColumnType
, &type
, NULL
);
309 if (type
== XmMENU_BAR
|| type
== XmMENU_POPUP
)
318 instance
= lw_get_widget_instance (w
);
319 if (instance
&& instance
->info
->highlight_cb
)
321 call_data
= cbs
->reason
== XmCR_DISARM
? NULL
: wv
;
322 instance
->info
->highlight_cb (w
, instance
->info
->id
, call_data
);
329 /* Update the label of widget WIDGET. WIDGET must be a Label widget
330 or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
335 Emacs fills VAL->name with the text to display in the menu, and
336 sets VAL->value to null. Function make_menu_in_widget creates
337 widgets with VAL->name as resource name. This works because the
338 Label widget uses its resource name for display if no
339 XmNlabelString is set.
343 VAL->name is again set to the resource name, but VAL->value is
344 not null, and contains the label string to display. */
347 xm_update_label (instance
, widget
, val
)
348 widget_instance
* instance
;
352 XmString res_string
= 0;
353 XmString built_string
= 0;
354 XmString key_string
= 0;
362 /* A label string is specified, i.e. we are in a dialog. First
363 see if it is overridden by something from the resource file. */
364 res_string
= resource_motif_string (widget
, val
->value
);
368 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
373 XmStringCreateLocalized (val
->value
);
374 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
377 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
382 key_string
= XmStringCreateLocalized (val
->key
);
383 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
387 XtSetValues (widget
, al
, ac
);
390 XmStringFree (built_string
);
393 XmStringFree (key_string
);
396 \f/* update of list */
398 xm_update_list (instance
, widget
, val
)
399 widget_instance
* instance
;
405 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
406 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
408 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
411 XmString xmstr
= XmStringCreateLocalized (cur
->value
);
413 XmListAddItem (widget
, xmstr
, 0);
415 XmListSelectPos (widget
, i
, False
);
416 XmStringFree (xmstr
);
420 \f/* update of buttons */
422 xm_update_pushbutton (instance
, widget
, val
)
423 widget_instance
* instance
;
427 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, NULL
);
428 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
429 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
433 xm_update_cascadebutton (instance
, widget
, val
)
434 widget_instance
* instance
;
438 /* Should also rebuild the menu by calling ...update_menu... */
439 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
440 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
444 \f/* update toggle and radiobox */
446 xm_update_toggle (instance
, widget
, val
)
447 widget_instance
* instance
;
451 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
452 XtAddCallback (widget
, XmNvalueChangedCallback
,
453 xm_generic_callback
, instance
);
454 XtVaSetValues (widget
, XmNset
, val
->selected
,
455 XmNalignment
, XmALIGNMENT_BEGINNING
, NULL
);
459 xm_update_radiobox (instance
, widget
, val
)
460 widget_instance
* instance
;
468 /* update the callback */
469 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
470 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
472 /* first update all the toggles */
473 /* Energize kernel interface is currently bad. It sets the selected widget
474 with the selected flag but returns it by its name. So we currently
475 have to support both setting the selection with the selected slot
476 of val contents and setting it with the "value" slot of val. The latter
477 has a higher priority. This to be removed when the kernel is fixed. */
478 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
480 toggle
= XtNameToWidget (widget
, cur
->value
);
483 XtSetSensitive (toggle
, cur
->enabled
);
484 if (!val
->value
&& cur
->selected
)
485 XtVaSetValues (toggle
, XmNset
, cur
->selected
, NULL
);
486 if (val
->value
&& strcmp (val
->value
, cur
->value
))
487 XtVaSetValues (toggle
, XmNset
, False
, NULL
);
491 /* The selected was specified by the value slot */
494 toggle
= XtNameToWidget (widget
, val
->value
);
496 XtVaSetValues (toggle
, XmNset
, True
, NULL
);
501 /* update a popup menu, pulldown menu or a menubar */
503 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
506 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
507 widget_instance
* instance
;
510 int keep_first_children
;
512 Widget
* children
= 0;
524 Widget
* old_children
;
525 unsigned int old_num_children
;
527 old_children
= XtCompositeChildren (widget
, &old_num_children
);
529 /* Allocate the children array */
530 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
)
532 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
534 /* WIDGET should be a RowColumn. */
535 if (!XmIsRowColumn (widget
))
538 /* Determine whether WIDGET is a menu bar. */
540 XtSetArg (al
[0], XmNrowColumnType
, &type
);
541 XtGetValues (widget
, al
, 1);
542 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
544 menubar_p
= type
== XmMENU_BAR
;
546 /* Add a callback to popups and pulldowns that is called when
547 it is made invisible again. */
549 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
550 xm_pop_down_callback
, (XtPointer
)instance
);
552 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
553 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
554 child_index
++, cur
= cur
->next
)
555 children
[child_index
] = old_children
[child_index
];
557 /* Check that those are all we have
558 (the caller should have deleted the rest). */
559 if (old_num_children
!= keep_first_children
)
562 /* Create the rest. */
563 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
565 enum menu_separator separator
;
568 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
569 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
570 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
572 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
573 && !lw_separator_p (cur
->name
, &separator
, 1))
576 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
577 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
579 else if (lw_separator_p (cur
->name
, &separator
, 1))
582 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
583 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
585 else if (!cur
->contents
)
588 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
589 else if (!cur
->call_data
)
590 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
591 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
592 || cur
->button_type
== BUTTON_TYPE_RADIO
)
594 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
595 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
596 XtSetArg (al
[ac
], XmNindicatorType
,
597 (cur
->button_type
== BUTTON_TYPE_TOGGLE
598 ? XmN_OF_MANY
: XmONE_OF_MANY
));
600 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
601 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
602 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
606 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
607 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
608 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
611 xm_update_label (instance
, button
, cur
);
613 /* Add a callback that is called when the button is
614 selected. Toggle buttons don't support
615 XmNactivateCallback, we use XmNvalueChangedCallback in
616 that case. Don't add a callback to a simple label. */
617 if (cur
->button_type
)
618 xm_update_toggle (instance
, button
, cur
);
619 else if (cur
->call_data
)
620 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
621 (XtPointer
)instance
);
625 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
627 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
628 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
629 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
631 xm_update_label (instance
, button
, cur
);
633 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
634 (XtPointer
)instance
);
637 children
[child_index
] = button
;
640 /* Last entry is the help button. The original comment read "Has to
641 be done after managing the buttons otherwise the menubar is only
642 4 pixels high." This is no longer true, and to make
643 XmNmenuHelpWidget work, we need to set it before managing the
644 children.. --gerd. */
646 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, NULL
);
649 XtManageChildren (children
, num_children
);
651 XtFree ((char *) children
);
653 XtFree ((char *) old_children
);
657 update_one_menu_entry (instance
, widget
, val
, deep_p
)
658 widget_instance
* instance
;
666 widget_value
* contents
;
668 if (val
->this_one_change
== NO_CHANGE
)
671 /* update the sensitivity and userdata */
672 /* Common to all widget types */
673 XtSetSensitive (widget
, val
->enabled
);
674 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
676 /* update the menu button as a label. */
677 if (val
->this_one_change
>= VISIBLE_CHANGE
)
679 xm_update_label (instance
, widget
, val
);
680 if (val
->button_type
)
681 xm_update_toggle (instance
, widget
, val
);
684 /* update the pulldown/pullaside as needed */
687 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
688 XtGetValues (widget
, al
, ac
);
690 contents
= val
->contents
;
696 unsigned int old_num_children
, i
;
700 parent
= XtParent (widget
);
701 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
703 /* Find the widget position within the parent's widget list. */
704 for (i
= 0; i
< old_num_children
; i
++)
705 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
707 if (i
== old_num_children
)
709 if (XmIsCascadeButton (widget_list
[i
]))
711 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
712 make_menu_in_widget (instance
, menu
, contents
, 0);
714 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
715 XtSetValues (widget
, al
, ac
);
721 /* The current menuitem is a XmPushButtonGadget, it
722 needs to be replaced by a CascadeButtonGadget */
723 XtDestroyWidget (widget_list
[i
]);
724 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
725 make_menu_in_widget (instance
, menu
, contents
, 0);
727 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
728 /* Non-zero values don't work reliably in
729 conjunction with Emacs' event loop */
730 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
731 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
732 /* Tell Motif to put it in the right place */
733 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
735 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
736 xm_update_label (instance
, button
, val
);
738 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
739 (XtPointer
)instance
);
740 XtManageChild (button
);
744 XtFree ((char*) widget_list
);
750 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
751 XtSetValues (widget
, al
, ac
);
752 XtDestroyWidget (menu
);
754 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
755 xm_update_menu (instance
, menu
, val
, 1);
759 xm_update_menu (instance
, widget
, val
, deep_p
)
760 widget_instance
* instance
;
766 unsigned int num_children
;
767 int num_children_to_keep
= 0;
771 children
= XtCompositeChildren (widget
, &num_children
);
773 /* Widget is a RowColumn widget whose contents have to be updated
774 * to reflect the list of items in val->contents */
776 /* See how many buttons we can keep, and how many we
777 must completely replace. */
778 if (val
->contents
== 0)
779 num_children_to_keep
= 0;
780 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
784 for (i
= 0, cur
= val
->contents
;
786 && cur
); /* how else to ditch unwanted children ?? - mgd */
787 i
++, cur
= cur
->next
)
789 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
793 num_children_to_keep
= i
;
797 num_children_to_keep
= num_children
;
799 /* Update all the buttons of the RowColumn, in order,
800 except for those we are going to replace entirely. */
803 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
807 num_children_to_keep
= i
;
810 if (children
[i
]->core
.being_destroyed
811 || strcmp (XtName (children
[i
]), cur
->name
))
813 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
818 /* Now replace from scratch all the buttons after the last
819 place that the top-level structure changed. */
820 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
822 destroy_all_children (widget
, num_children_to_keep
);
823 make_menu_in_widget (instance
, widget
, val
->contents
,
824 num_children_to_keep
);
827 XtFree ((char *) children
);
831 /* update text widgets */
834 xm_update_text (instance
, widget
, val
)
835 widget_instance
* instance
;
839 XmTextSetString (widget
, val
->value
? val
->value
: "");
840 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
841 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
842 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
843 XtAddCallback (widget
, XmNvalueChangedCallback
,
844 xm_internal_update_other_instances
, instance
);
848 xm_update_text_field (instance
, widget
, val
)
849 widget_instance
* instance
;
853 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
854 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
855 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
856 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
857 XtAddCallback (widget
, XmNvalueChangedCallback
,
858 xm_internal_update_other_instances
, instance
);
862 /* update a motif widget */
865 xm_update_one_widget (instance
, widget
, val
, deep_p
)
866 widget_instance
* instance
;
873 /* Mark as not edited */
876 /* Common to all widget types */
877 XtSetSensitive (widget
, val
->enabled
);
878 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
880 /* Common to all label like widgets */
881 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
882 xm_update_label (instance
, widget
, val
);
884 class = XtClass (widget
);
885 /* Class specific things */
886 if (class == xmPushButtonWidgetClass
||
887 class == xmArrowButtonWidgetClass
)
889 xm_update_pushbutton (instance
, widget
, val
);
891 else if (class == xmCascadeButtonWidgetClass
)
893 xm_update_cascadebutton (instance
, widget
, val
);
895 else if (class == xmToggleButtonWidgetClass
896 || class == xmToggleButtonGadgetClass
)
898 xm_update_toggle (instance
, widget
, val
);
900 else if (class == xmRowColumnWidgetClass
)
902 Boolean radiobox
= 0;
906 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
907 XtGetValues (widget
, al
, ac
);
910 xm_update_radiobox (instance
, widget
, val
);
912 xm_update_menu (instance
, widget
, val
, deep_p
);
914 else if (class == xmTextWidgetClass
)
916 xm_update_text (instance
, widget
, val
);
918 else if (class == xmTextFieldWidgetClass
)
920 xm_update_text_field (instance
, widget
, val
);
922 else if (class == xmListWidgetClass
)
924 xm_update_list (instance
, widget
, val
);
928 \f/* getting the value back */
930 xm_update_one_value (instance
, widget
, val
)
931 widget_instance
* instance
;
935 WidgetClass
class = XtClass (widget
);
936 widget_value
*old_wv
;
938 /* copy the call_data slot into the "return" widget_value */
939 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
940 if (!strcmp (val
->name
, old_wv
->name
))
942 val
->call_data
= old_wv
->call_data
;
946 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
948 XtVaGetValues (widget
, XmNset
, &val
->selected
, NULL
);
951 else if (class == xmTextWidgetClass
)
955 val
->value
= XmTextGetString (widget
);
958 else if (class == xmTextFieldWidgetClass
)
962 val
->value
= XmTextFieldGetString (widget
);
965 else if (class == xmRowColumnWidgetClass
)
967 Boolean radiobox
= 0;
971 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
972 XtGetValues (widget
, al
, ac
);
976 CompositeWidget radio
= (CompositeWidget
)widget
;
978 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
981 Widget toggle
= radio
->composite
.children
[i
];
983 XtVaGetValues (toggle
, XmNset
, &set
, NULL
);
988 val
->value
= safe_strdup (XtName (toggle
));
994 else if (class == xmListWidgetClass
)
998 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
1002 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
1006 cur
->selected
= False
;
1008 for (j
= 0; j
< pos_cnt
; j
++)
1009 if (pos_list
[j
] == i
)
1011 cur
->selected
= True
;
1012 val
->value
= safe_strdup (cur
->name
);
1016 XtFree ((char *) pos_list
);
1022 /* This function is for activating a button from a program. It's wrong because
1023 we pass a NULL argument in the call_data which is not Motif compatible.
1024 This is used from the XmNdefaultAction callback of the List widgets to
1025 have a double-click put down a dialog box like the button would do.
1026 I could not find a way to do that with accelerators.
1029 activate_button (widget
, closure
, call_data
)
1032 XtPointer call_data
;
1034 Widget button
= (Widget
)closure
;
1035 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
1038 /* creation functions */
1040 /* Called for key press in dialogs. Used to pop down dialog on ESC. */
1042 dialog_key_cb (widget
, closure
, event
, continue_to_dispatch
)
1046 Boolean
*continue_to_dispatch
;
1049 Modifiers modif_ret
;
1051 XtTranslateKeycode (event
->xkey
.display
, event
->xkey
.keycode
, 0,
1054 if (sym
== osfXK_Cancel
)
1056 Widget w
= *((Widget
*) closure
);
1058 while (w
&& ! XtIsShell (w
))
1061 if (XtIsShell (w
)) XtPopdown (w
);
1064 *continue_to_dispatch
= TRUE
;
1069 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
1070 radio_box
, list
, left_buttons
, right_buttons
)
1076 Boolean text_input_slot
;
1086 Widget icon_separator
;
1091 Widget children
[16]; /* for the final XtManageChildren */
1093 Arg al
[64]; /* Arg List */
1094 int ac
; /* Arg Count */
1100 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
1101 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
1102 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
1103 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1105 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1106 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1107 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1108 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1113 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1114 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1115 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1119 n_children
= left_buttons
+ right_buttons
+ 1;
1121 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1122 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1123 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1124 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1125 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1126 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1127 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1128 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1129 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1130 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1131 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1132 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1133 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1134 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1135 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1136 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1137 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1138 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1139 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1142 for (i
= 0; i
< left_buttons
; i
++)
1144 char button_name
[16];
1145 sprintf (button_name
, "button%d", i
+ 1);
1149 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1150 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1152 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1153 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1154 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1155 XtAddEventHandler (children
[n_children
],
1156 KeyPressMask
, False
, dialog_key_cb
, result
);
1160 button
= children
[n_children
];
1162 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1163 XtSetValues (row
, al
, ac
);
1169 /* invisible separator button */
1171 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1172 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1175 for (i
= 0; i
< right_buttons
; i
++)
1177 char button_name
[16];
1178 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1180 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1181 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1182 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1183 XtAddEventHandler (children
[n_children
],
1184 KeyPressMask
, False
, dialog_key_cb
, result
);
1186 if (! button
) button
= children
[n_children
];
1190 XtManageChildren (children
, n_children
);
1193 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1194 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1195 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1196 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1197 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1198 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1199 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1200 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1201 separator
= XmCreateSeparator (form
, "", al
, ac
);
1204 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1205 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1206 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1207 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1208 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1209 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1210 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1211 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1214 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1215 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1216 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1217 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1218 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1219 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1220 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1221 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1222 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1223 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1225 if (text_input_slot
)
1228 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1229 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1230 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1231 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1232 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1233 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1234 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1235 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1236 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1237 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1238 value
= XmCreateTextField (form
, "value", al
, ac
);
1244 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1245 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1246 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1247 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1248 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1249 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1250 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1251 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1252 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1253 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1254 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1255 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1256 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1257 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1260 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1261 children
[i
++] = radio_butt
;
1262 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1263 children
[i
++] = radio_butt
;
1264 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1265 children
[i
++] = radio_butt
;
1266 XtManageChildren (children
, i
);
1271 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1272 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1273 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1274 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1275 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1276 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1277 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1278 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1279 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1280 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1281 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1283 /* this is the easiest way I found to have the dble click in the
1284 list activate the default button */
1285 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1289 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1290 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1291 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1292 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1293 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1294 XtSetArg(al
[ac
], XmNbottomWidget
,
1295 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1296 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1297 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1298 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1299 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1300 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1301 message
= XmCreateLabel (form
, "message", al
, ac
);
1304 XtManageChild (value
);
1307 children
[i
] = row
; i
++;
1308 children
[i
] = separator
; i
++;
1309 if (text_input_slot
|| radio_box
)
1311 children
[i
] = value
; i
++;
1313 children
[i
] = message
; i
++;
1314 children
[i
] = icon
; i
++;
1315 children
[i
] = icon_separator
; i
++;
1316 XtManageChildren (children
, i
);
1318 if (text_input_slot
|| list
)
1320 XtInstallAccelerators (value
, button
);
1321 XtSetKeyboardFocus (result
, value
);
1325 XtInstallAccelerators (form
, button
);
1326 XtSetKeyboardFocus (result
, button
);
1332 static destroyed_instance
*
1333 find_matching_instance (instance
)
1334 widget_instance
* instance
;
1336 destroyed_instance
* cur
;
1337 destroyed_instance
* prev
;
1338 char* type
= instance
->info
->type
;
1339 char* name
= instance
->info
->name
;
1341 for (prev
= NULL
, cur
= all_destroyed_instances
;
1343 prev
= cur
, cur
= cur
->next
)
1345 if (!strcmp (cur
->name
, name
)
1346 && !strcmp (cur
->type
, type
)
1347 && cur
->parent
== instance
->parent
1348 && cur
->pop_up_p
== instance
->pop_up_p
)
1351 prev
->next
= cur
->next
;
1353 all_destroyed_instances
= cur
->next
;
1356 /* do some cleanup */
1357 else if (!cur
->widget
)
1360 prev
->next
= cur
->next
;
1362 all_destroyed_instances
= cur
->next
;
1363 free_destroyed_instance (cur
);
1364 cur
= prev
? prev
: all_destroyed_instances
;
1371 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1374 XtPointer call_data
;
1376 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1377 instance
->widget
= NULL
;
1381 recenter_widget (widget
)
1384 Widget parent
= XtParent (widget
);
1385 Screen
* screen
= XtScreen (widget
);
1386 Dimension screen_width
= WidthOfScreen (screen
);
1387 Dimension screen_height
= HeightOfScreen (screen
);
1388 Dimension parent_width
= 0;
1389 Dimension parent_height
= 0;
1390 Dimension child_width
= 0;
1391 Dimension child_height
= 0;
1395 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, NULL
);
1396 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1399 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1400 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1402 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1404 if (x
+ child_width
> screen_width
)
1405 x
= screen_width
- child_width
;
1409 if (y
+ child_height
> screen_height
)
1410 y
= screen_height
- child_height
;
1414 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, NULL
);
1418 recycle_instance (instance
)
1419 destroyed_instance
* instance
;
1421 Widget widget
= instance
->widget
;
1423 /* widget is NULL if the parent was destroyed. */
1429 /* Remove the destroy callback as the instance is not in the list
1431 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1432 mark_dead_instance_destroyed
,
1433 (XtPointer
)instance
);
1435 /* Give the focus to the initial item */
1436 focus
= XtNameToWidget (widget
, "*value");
1438 focus
= XtNameToWidget (widget
, "*button1");
1440 XtSetKeyboardFocus (widget
, focus
);
1442 /* shrink the separator label back to their original size */
1443 separator
= XtNameToWidget (widget
, "*separator_button");
1445 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, NULL
);
1447 /* Center the dialog in its parent */
1448 recenter_widget (widget
);
1450 free_destroyed_instance (instance
);
1455 xm_create_dialog (instance
)
1456 widget_instance
* instance
;
1458 char* name
= instance
->info
->type
;
1459 Widget parent
= instance
->parent
;
1461 Boolean pop_up_p
= instance
->pop_up_p
;
1462 char* shell_name
= 0;
1463 char* icon_name
= 0;
1464 Boolean text_input_slot
= False
;
1465 Boolean radio_box
= False
;
1466 Boolean list
= False
;
1468 int left_buttons
= 0;
1469 int right_buttons
= 1;
1470 destroyed_instance
* dead_one
;
1472 /* try to find a widget to recycle */
1473 dead_one
= find_matching_instance (instance
);
1476 Widget recycled_widget
= recycle_instance (dead_one
);
1477 if (recycled_widget
)
1478 return recycled_widget
;
1483 icon_name
= "dbox-error";
1484 shell_name
= "Error";
1488 icon_name
= "dbox-info";
1489 shell_name
= "Information";
1494 icon_name
= "dbox-question";
1495 shell_name
= "Prompt";
1499 text_input_slot
= True
;
1500 icon_name
= "dbox-question";
1501 shell_name
= "Prompt";
1505 icon_name
= "dbox-question";
1506 shell_name
= "Question";
1510 total_buttons
= name
[1] - '0';
1512 if (name
[3] == 'T' || name
[3] == 't')
1514 text_input_slot
= False
;
1518 right_buttons
= name
[4] - '0';
1520 left_buttons
= total_buttons
- right_buttons
;
1522 widget
= make_dialog (name
, parent
, pop_up_p
,
1523 shell_name
, icon_name
, text_input_slot
, radio_box
,
1524 list
, left_buttons
, right_buttons
);
1526 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1527 (XtPointer
) instance
);
1532 /* Create a menu bar. We turn off the f10 key
1533 because we have not yet managed to make it work right in Motif. */
1536 make_menubar (instance
)
1537 widget_instance
* instance
;
1543 XtSetArg(al
[ac
], XmNmenuAccelerator
, 0); ++ac
;
1544 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, ac
);
1548 remove_grabs (shell
, closure
, call_data
)
1551 XtPointer call_data
;
1553 Widget menu
= (Widget
) closure
;
1554 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1558 make_popup_menu (instance
)
1559 widget_instance
* instance
;
1561 Widget parent
= instance
->parent
;
1562 Window parent_window
= parent
->core
.window
;
1565 /* sets the parent window to 0 to fool Motif into not generating a grab */
1566 parent
->core
.window
= 0;
1567 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1568 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1570 parent
->core
.window
= parent_window
;
1575 make_main (instance
)
1576 widget_instance
* instance
;
1578 Widget parent
= instance
->parent
;
1584 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1585 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1586 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1590 \f/* Table of functions to create widgets */
1594 /* interface with the XDesigner generated functions */
1595 typedef Widget (*widget_maker
) (Widget
);
1596 extern Widget
create_project_p_sheet (Widget parent
);
1597 extern Widget
create_debugger_p_sheet (Widget parent
);
1598 extern Widget
create_breaklist_p_sheet (Widget parent
);
1599 extern Widget
create_le_browser_p_sheet (Widget parent
);
1600 extern Widget
create_class_browser_p_sheet (Widget parent
);
1601 extern Widget
create_call_browser_p_sheet (Widget parent
);
1602 extern Widget
create_build_dialog (Widget parent
);
1603 extern Widget
create_editmode_dialog (Widget parent
);
1604 extern Widget
create_search_dialog (Widget parent
);
1605 extern Widget
create_project_display_dialog (Widget parent
);
1608 make_one (widget_instance
* instance
, widget_maker fn
)
1614 if (instance
->pop_up_p
)
1616 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1617 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1618 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1619 (XtPointer
) instance
);
1624 result
= (*fn
) (instance
->parent
);
1625 XtRealizeWidget (result
);
1631 make_project_p_sheet (widget_instance
* instance
)
1633 return make_one (instance
, create_project_p_sheet
);
1637 make_debugger_p_sheet (widget_instance
* instance
)
1639 return make_one (instance
, create_debugger_p_sheet
);
1643 make_breaklist_p_sheet (widget_instance
* instance
)
1645 return make_one (instance
, create_breaklist_p_sheet
);
1649 make_le_browser_p_sheet (widget_instance
* instance
)
1651 return make_one (instance
, create_le_browser_p_sheet
);
1655 make_class_browser_p_sheet (widget_instance
* instance
)
1657 return make_one (instance
, create_class_browser_p_sheet
);
1661 make_call_browser_p_sheet (widget_instance
* instance
)
1663 return make_one (instance
, create_call_browser_p_sheet
);
1667 make_build_dialog (widget_instance
* instance
)
1669 return make_one (instance
, create_build_dialog
);
1673 make_editmode_dialog (widget_instance
* instance
)
1675 return make_one (instance
, create_editmode_dialog
);
1679 make_search_dialog (widget_instance
* instance
)
1681 return make_one (instance
, create_search_dialog
);
1685 make_project_display_dialog (widget_instance
* instance
)
1687 return make_one (instance
, create_project_display_dialog
);
1690 #endif /* ENERGIZE */
1692 widget_creation_entry
1693 xm_creation_table
[] =
1695 {"menubar", make_menubar
},
1696 {"popup", make_popup_menu
},
1697 {"main", make_main
},
1699 {"project_p_sheet", make_project_p_sheet
},
1700 {"debugger_p_sheet", make_debugger_p_sheet
},
1701 {"breaklist_psheet", make_breaklist_p_sheet
},
1702 {"leb_psheet", make_le_browser_p_sheet
},
1703 {"class_browser_psheet", make_class_browser_p_sheet
},
1704 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1705 {"build", make_build_dialog
},
1706 {"editmode", make_editmode_dialog
},
1707 {"search", make_search_dialog
},
1708 {"project_display", make_project_display_dialog
},
1709 #endif /* ENERGIZE */
1713 \f/* Destruction of instances */
1715 xm_destroy_instance (instance
)
1716 widget_instance
* instance
;
1718 Widget widget
= instance
->widget
;
1719 /* recycle the dialog boxes */
1720 /* Disable the recycling until we can find a way to have the dialog box
1721 get reasonable layout after we modify its contents. */
1723 && XtClass (widget
) == xmDialogShellWidgetClass
)
1725 destroyed_instance
* dead_instance
=
1726 make_destroyed_instance (instance
->info
->name
,
1727 instance
->info
->type
,
1730 instance
->pop_up_p
);
1731 dead_instance
->next
= all_destroyed_instances
;
1732 all_destroyed_instances
= dead_instance
;
1733 XtUnmanageChild (first_child (instance
->widget
));
1734 XFlush (XtDisplay (instance
->widget
));
1735 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1736 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1740 /* This might not be necessary now that the nosel is attached to
1741 popdown instead of destroy, but it can't hurt. */
1742 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1743 xm_nosel_callback
, (XtPointer
)instance
);
1744 XtDestroyWidget (instance
->widget
);
1748 \f/* popup utility */
1750 xm_popup_menu (widget
, event
)
1754 XButtonPressedEvent dummy
;
1758 dummy
.type
= ButtonPress
;
1760 dummy
.send_event
= 0;
1761 dummy
.display
= XtDisplay (widget
);
1762 dummy
.window
= XtWindow (XtParent (widget
));
1765 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1766 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1767 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1768 event
= (XEvent
*) &dummy
;
1771 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1773 /* Setting the menuPost resource only required by Motif 1.1 and
1774 LessTif 0.84 and earlier. With later versions of LessTif,
1775 setting menuPost is unnecessary and may cause problems, so
1777 #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
1779 /* This is so totally ridiculous: there's NO WAY to tell Motif
1780 that *any* button can select a menu item. Only one button
1781 can have that honor. */
1784 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1785 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1786 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1787 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1788 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1789 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, NULL
);
1793 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1796 XtManageChild (widget
);
1800 set_min_dialog_size (w
)
1805 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, NULL
);
1806 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, NULL
);
1810 xm_pop_instance (instance
, up
)
1811 widget_instance
* instance
;
1814 Widget widget
= instance
->widget
;
1816 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1818 Widget widget_to_manage
= first_child (widget
);
1821 XtManageChild (widget_to_manage
);
1822 set_min_dialog_size (widget
);
1823 XtSetKeyboardFocus (instance
->parent
, widget
);
1826 XtUnmanageChild (widget_to_manage
);
1831 XtManageChild (widget
);
1833 XtUnmanageChild (widget
);
1838 /* motif callback */
1841 do_call (widget
, closure
, type
)
1844 enum do_call_type type
;
1848 XtPointer user_data
;
1849 widget_instance
* instance
= (widget_instance
*)closure
;
1850 Widget instance_widget
;
1855 if (widget
->core
.being_destroyed
)
1858 instance_widget
= instance
->widget
;
1859 if (!instance_widget
)
1862 id
= instance
->info
->id
;
1865 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1866 XtGetValues (widget
, al
, ac
);
1871 if (instance
->info
->pre_activate_cb
)
1872 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1876 if (instance
->info
->selection_cb
)
1877 instance
->info
->selection_cb (widget
, id
, user_data
);
1881 if (instance
->info
->selection_cb
)
1882 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1886 if (instance
->info
->post_activate_cb
)
1887 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1895 /* Like lw_internal_update_other_instances except that it does not do
1896 anything if its shell parent is not managed. This is to protect
1897 lw_internal_update_other_instances to dereference freed memory
1898 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1901 xm_internal_update_other_instances (widget
, closure
, call_data
)
1904 XtPointer call_data
;
1907 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1908 if (XtIsShell (parent
))
1910 else if (!XtIsManaged (parent
))
1912 lw_internal_update_other_instances (widget
, closure
, call_data
);
1916 xm_generic_callback (widget
, closure
, call_data
)
1919 XtPointer call_data
;
1921 lw_internal_update_other_instances (widget
, closure
, call_data
);
1922 do_call (widget
, closure
, selection
);
1926 xm_nosel_callback (widget
, closure
, call_data
)
1929 XtPointer call_data
;
1931 /* This callback is only called when a dialog box is dismissed with
1932 the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog
1933 box to be destroyed in that case, not just unmapped, so that it
1934 releases its keyboard grabs. But there are problems with running
1935 our callbacks while the widget is in the process of being
1936 destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
1937 XmDESTROY and then destroy it ourself after having run the
1939 do_call (widget
, closure
, no_selection
);
1940 XtDestroyWidget (widget
);
1944 xm_pull_down_callback (widget
, closure
, call_data
)
1947 XtPointer call_data
;
1949 Widget parent
= XtParent (widget
);
1951 if (XmIsRowColumn (parent
))
1953 unsigned char type
= 0xff;
1954 XtVaGetValues (parent
, XmNrowColumnType
, &type
, NULL
);
1955 if (type
== XmMENU_BAR
)
1956 do_call (widget
, closure
, pre_activate
);
1961 /* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
1962 CLOSURE is a pointer to the widget_instance of the shell,
1964 Note that this callback is called for each cascade button in a
1965 menu, whether or not its submenu is visible. */
1968 xm_pop_down_callback (widget
, closure
, call_data
)
1971 XtPointer call_data
;
1973 widget_instance
*instance
= (widget_instance
*) closure
;
1975 if ((!instance
->pop_up_p
&& XtParent (widget
) == instance
->widget
)
1976 || XtParent (widget
) == instance
->parent
)
1977 do_call (widget
, closure
, post_activate
);
1981 /* set the keyboard focus */
1983 xm_set_keyboard_focus (parent
, w
)
1987 XmProcessTraversal (w
, 0);
1988 XtSetKeyboardFocus (parent
, w
);
1991 /* Motif hack to set the main window areas. */
1993 xm_set_main_areas (parent
, menubar
, work_area
)
1998 XmMainWindowSetAreas (parent
,
1999 menubar
, /* menubar (maybe 0) */
2000 0, /* command area (psheets) */
2001 0, /* horizontal scroll */
2002 0, /* vertical scroll */
2003 work_area
); /* work area */
2006 /* Motif hack to control resizing on the menubar. */
2008 xm_manage_resizing (w
, flag
)
2012 XtVaSetValues (w
, XtNallowShellResize
, flag
, NULL
);
2015 /* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
2016 (do not change this comment) */