1 /* The lwlib interface to Motif widgets.
2 Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
5 Copyright (C) 1992 Lucid, Inc.
7 This file is part of the Lucid Widget Library.
9 The Lucid Widget Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 1, or (at your option)
14 The Lucid Widget Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
32 #include <X11/StringDefs.h>
33 #include <X11/IntrinsicP.h>
34 #include <X11/ObjectP.h>
35 #include <X11/CoreP.h>
36 #include <X11/CompositeP.h>
38 #include "../src/lisp.h"
41 #include "lwlib-utils.h"
43 #include <Xm/BulletinB.h>
44 #include <Xm/CascadeB.h>
45 #include <Xm/CascadeBG.h>
46 #include <Xm/DrawingA.h>
47 #include <Xm/FileSB.h>
51 #include <Xm/MenuShell.h>
52 #include <Xm/MessageB.h>
53 #include <Xm/PanedW.h>
55 #include <Xm/PushBG.h>
56 #include <Xm/ArrowB.h>
57 #include <Xm/SelectioB.h>
60 #include <Xm/ToggleB.h>
61 #include <Xm/ToggleBG.h>
62 #include <Xm/RowColumn.h>
63 #include <Xm/ScrolledW.h>
64 #include <Xm/Separator.h>
65 #include <Xm/DialogS.h>
69 #if defined __STDC__ || defined PROTOTYPES
75 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
78 \f/* Structures to keep destroyed instances */
79 typedef struct _destroyed_instance
86 struct _destroyed_instance
* next
;
89 static destroyed_instance
*make_destroyed_instance
P_ ((char *, char *,
92 static void free_destroyed_instance
P_ ((destroyed_instance
*));
93 Widget first_child
P_ ((Widget
));
94 Boolean lw_motif_widget_p
P_ ((Widget
));
95 static XmString resource_motif_string
P_ ((Widget
, char *));
96 static void destroy_all_children
P_ ((Widget
, int));
97 static void xm_update_label
P_ ((widget_instance
*, Widget
, widget_value
*));
98 static void xm_update_list
P_ ((widget_instance
*, Widget
, widget_value
*));
99 static void xm_update_pushbutton
P_ ((widget_instance
*, Widget
,
101 static void xm_update_cascadebutton
P_ ((widget_instance
*, Widget
,
103 static void xm_update_toggle
P_ ((widget_instance
*, Widget
, widget_value
*));
104 static void xm_update_radiobox
P_ ((widget_instance
*, Widget
, widget_value
*));
105 static void make_menu_in_widget
P_ ((widget_instance
*, Widget
,
106 widget_value
*, int));
107 static void update_one_menu_entry
P_ ((widget_instance
*, Widget
,
108 widget_value
*, Boolean
));
109 static void xm_update_menu
P_ ((widget_instance
*, Widget
, widget_value
*,
111 static void xm_update_text
P_ ((widget_instance
*, Widget
, widget_value
*));
112 static void xm_update_text_field
P_ ((widget_instance
*, Widget
,
114 void xm_update_one_value
P_ ((widget_instance
*, Widget
, widget_value
*));
115 static void activate_button
P_ ((Widget
, XtPointer
, XtPointer
));
116 static Widget make_dialog
P_ ((char *, Widget
, Boolean
, char *, char *,
117 Boolean
, Boolean
, Boolean
, int, int));
118 static destroyed_instance
* find_matching_instance
P_ ((widget_instance
*));
119 static void mark_dead_instance_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
120 static void recenter_widget
P_ ((Widget
));
121 static Widget recycle_instance
P_ ((destroyed_instance
*));
122 Widget xm_create_dialog
P_ ((widget_instance
*));
123 static Widget make_menubar
P_ ((widget_instance
*));
124 static void remove_grabs
P_ ((Widget
, XtPointer
, XtPointer
));
125 static Widget make_popup_menu
P_ ((widget_instance
*));
126 static Widget make_main
P_ ((widget_instance
*));
127 void xm_destroy_instance
P_ ((widget_instance
*));
128 void xm_popup_menu
P_ ((Widget
, XEvent
*));
129 static void set_min_dialog_size
P_ ((Widget
));
130 static void do_call
P_ ((Widget
, XtPointer
, enum do_call_type
));
131 static void xm_generic_callback
P_ ((Widget
, XtPointer
, XtPointer
));
132 static void xm_nosel_callback
P_ ((Widget
, XtPointer
, XtPointer
));
133 static void xm_pull_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
134 static void xm_pop_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
135 void xm_set_keyboard_focus
P_ ((Widget
, Widget
));
136 void xm_set_main_areas
P_ ((Widget
, Widget
, Widget
));
137 static void xm_internal_update_other_instances
P_ ((Widget
, XtPointer
,
139 static void xm_arm_callback
P_ ((Widget
, XtPointer
, XtPointer
));
142 void xm_update_one_widget
P_ ((widget_instance
*, Widget
, widget_value
*,
144 void xm_pop_instance
P_ ((widget_instance
*, Boolean
));
145 void xm_manage_resizing
P_ ((Widget
, Boolean
));
151 /* Print the complete X resource name of widget WIDGET to stderr.
152 This is sometimes handy to have available. */
155 x_print_complete_resource_name (widget
)
161 for (i
= 0; i
< 100 && widget
!= NULL
; ++i
)
163 names
[i
] = XtName (widget
);
164 widget
= XtParent (widget
);
167 for (--i
; i
>= 1; --i
)
168 fprintf (stderr
, "%s.", names
[i
]);
169 fprintf (stderr
, "%s\n", names
[0]);
175 static destroyed_instance
*all_destroyed_instances
= NULL
;
177 static destroyed_instance
*
178 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
185 destroyed_instance
* instance
=
186 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
187 instance
->name
= safe_strdup (name
);
188 instance
->type
= safe_strdup (type
);
189 instance
->widget
= widget
;
190 instance
->parent
= parent
;
191 instance
->pop_up_p
= pop_up_p
;
192 instance
->next
= NULL
;
197 free_destroyed_instance (instance
)
198 destroyed_instance
* instance
;
200 free (instance
->name
);
201 free (instance
->type
);
205 \f/* motif utility functions */
210 return ((CompositeWidget
)widget
)->composite
.children
[0];
214 lw_motif_widget_p (widget
)
218 XtClass (widget
) == xmDialogShellWidgetClass
219 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
223 resource_motif_string (widget
, name
)
230 resource
.resource_name
= name
;
231 resource
.resource_class
= XmCXmString
;
232 resource
.resource_type
= XmRXmString
;
233 resource
.resource_size
= sizeof (XmString
);
234 resource
.resource_offset
= 0;
235 resource
.default_type
= XtRImmediate
;
236 resource
.default_addr
= 0;
238 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
239 "DialogString", &resource
, 1, NULL
, 0);
243 /* Destroy all of the children of WIDGET
244 starting with number FIRST_CHILD_TO_DESTROY. */
247 destroy_all_children (widget
, first_child_to_destroy
)
249 int first_child_to_destroy
;
255 children
= XtCompositeChildren (widget
, &number
);
258 XtUnmanageChildren (children
+ first_child_to_destroy
,
259 number
- first_child_to_destroy
);
261 /* Unmanage all children and destroy them. They will only be
262 really destroyed when we get out of DispatchEvent. */
263 for (i
= first_child_to_destroy
; i
< number
; i
++)
267 /* Cascade buttons have submenus,and these submenus
268 need to be freed. But they are not included in
269 XtCompositeChildren. So get it out of the cascade button
270 and free it. If this child is not a cascade button,
271 then submenu should remain unchanged. */
272 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
273 XtGetValues (children
[i
], al
, 1);
276 destroy_all_children (submenu
, 0);
277 XtDestroyWidget (submenu
);
279 XtDestroyWidget (children
[i
]);
282 XtFree ((char *) children
);
288 /* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
289 menu. CLIENT_DATA contains a pointer to the widget_value
290 corresponding to widget W. CALL_DATA contains a
291 XmPushButtonCallbackStruct containing the reason why the callback
295 xm_arm_callback (w
, client_data
, call_data
)
297 XtPointer client_data
, call_data
;
299 XmPushButtonCallbackStruct
*cbs
= (XmPushButtonCallbackStruct
*) call_data
;
300 widget_value
*wv
= (widget_value
*) client_data
;
301 widget_instance
*instance
;
303 /* Get the id of the menu bar or popup menu this widget is in. */
306 if (XmIsRowColumn (w
))
308 unsigned char type
= 0xff;
310 XtVaGetValues (w
, XmNrowColumnType
, &type
, NULL
);
311 if (type
== XmMENU_BAR
|| type
== XmMENU_POPUP
)
320 instance
= lw_get_widget_instance (w
);
321 if (instance
&& instance
->info
->highlight_cb
)
323 call_data
= cbs
->reason
== XmCR_DISARM
? NULL
: wv
;
324 instance
->info
->highlight_cb (w
, instance
->info
->id
, call_data
);
331 /* Update the label of widget WIDGET. WIDGET must be a Label widget
332 or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
337 Emacs fills VAL->name with the text to display in the menu, and
338 sets VAL->value to null. Function make_menu_in_widget creates
339 widgets with VAL->name as resource name. This works because the
340 Label widget uses its resource name for display if no
341 XmNlabelString is set.
345 VAL->name is again set to the resource name, but VAL->value is
346 not null, and contains the label string to display. */
349 xm_update_label (instance
, widget
, val
)
350 widget_instance
* instance
;
354 XmString res_string
= 0;
355 XmString built_string
= 0;
356 XmString key_string
= 0;
364 /* A label string is specified, i.e. we are in a dialog. First
365 see if it is overridden by something from the resource file. */
366 res_string
= resource_motif_string (widget
, val
->value
);
370 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
375 XmStringCreateLocalized (val
->value
);
376 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
379 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
384 key_string
= XmStringCreateLocalized (val
->key
);
385 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
389 XtSetValues (widget
, al
, ac
);
392 XmStringFree (built_string
);
395 XmStringFree (key_string
);
398 \f/* update of list */
400 xm_update_list (instance
, widget
, val
)
401 widget_instance
* instance
;
407 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
408 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
410 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
413 XmString xmstr
= XmStringCreateLocalized (cur
->value
);
415 XmListAddItem (widget
, xmstr
, 0);
417 XmListSelectPos (widget
, i
, False
);
418 XmStringFree (xmstr
);
422 \f/* update of buttons */
424 xm_update_pushbutton (instance
, widget
, val
)
425 widget_instance
* instance
;
429 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, NULL
);
430 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
431 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
435 xm_update_cascadebutton (instance
, widget
, val
)
436 widget_instance
* instance
;
440 /* Should also rebuild the menu by calling ...update_menu... */
441 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
442 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
446 \f/* update toggle and radiobox */
448 xm_update_toggle (instance
, widget
, val
)
449 widget_instance
* instance
;
453 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
454 XtAddCallback (widget
, XmNvalueChangedCallback
,
455 xm_generic_callback
, instance
);
456 XtVaSetValues (widget
, XmNset
, val
->selected
,
457 XmNalignment
, XmALIGNMENT_BEGINNING
, NULL
);
461 xm_update_radiobox (instance
, widget
, val
)
462 widget_instance
* instance
;
470 /* update the callback */
471 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
472 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
474 /* first update all the toggles */
475 /* Energize kernel interface is currently bad. It sets the selected widget
476 with the selected flag but returns it by its name. So we currently
477 have to support both setting the selection with the selected slot
478 of val contents and setting it with the "value" slot of val. The latter
479 has a higher priority. This to be removed when the kernel is fixed. */
480 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
482 toggle
= XtNameToWidget (widget
, cur
->value
);
485 XtSetSensitive (toggle
, cur
->enabled
);
486 if (!val
->value
&& cur
->selected
)
487 XtVaSetValues (toggle
, XmNset
, cur
->selected
, NULL
);
488 if (val
->value
&& strcmp (val
->value
, cur
->value
))
489 XtVaSetValues (toggle
, XmNset
, False
, NULL
);
493 /* The selected was specified by the value slot */
496 toggle
= XtNameToWidget (widget
, val
->value
);
498 XtVaSetValues (toggle
, XmNset
, True
, NULL
);
503 /* update a popup menu, pulldown menu or a menubar */
505 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
508 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
509 widget_instance
* instance
;
512 int keep_first_children
;
514 Widget
* children
= 0;
526 Widget
* old_children
;
527 unsigned int old_num_children
;
529 /* Disable drag and drop for labels in menu bar. */
530 static char overrideTrans
[] = "<Btn2Down>: Noop()";
531 XtTranslations override
= XtParseTranslationTable (overrideTrans
);
533 old_children
= XtCompositeChildren (widget
, &old_num_children
);
535 /* Allocate the children array */
536 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
)
538 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
540 /* WIDGET should be a RowColumn. */
541 if (!XmIsRowColumn (widget
))
544 /* Determine whether WIDGET is a menu bar. */
546 XtSetArg (al
[0], XmNrowColumnType
, &type
);
547 XtGetValues (widget
, al
, 1);
548 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
550 menubar_p
= type
== XmMENU_BAR
;
552 /* Add a callback to popups and pulldowns that is called when
553 it is made invisible again. */
555 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
556 xm_pop_down_callback
, (XtPointer
)instance
);
558 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
559 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
560 child_index
++, cur
= cur
->next
)
561 children
[child_index
] = old_children
[child_index
];
563 /* Check that those are all we have
564 (the caller should have deleted the rest). */
565 if (old_num_children
!= keep_first_children
)
568 /* Create the rest. */
569 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
571 enum menu_separator separator
;
574 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
575 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
576 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
578 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
579 && !lw_separator_p (cur
->name
, &separator
, 1))
582 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
583 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
585 else if (lw_separator_p (cur
->name
, &separator
, 1))
588 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
589 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
591 else if (!cur
->contents
)
594 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
595 else if (!cur
->call_data
)
596 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
597 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
598 || cur
->button_type
== BUTTON_TYPE_RADIO
)
600 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
601 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
602 XtSetArg (al
[ac
], XmNindicatorType
,
603 (cur
->button_type
== BUTTON_TYPE_TOGGLE
604 ? XmN_OF_MANY
: XmONE_OF_MANY
));
606 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
607 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
608 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
612 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
613 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
614 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
617 xm_update_label (instance
, button
, cur
);
619 /* Add a callback that is called when the button is
620 selected. Toggle buttons don't support
621 XmNactivateCallback, we use XmNvalueChangedCallback in
622 that case. Don't add a callback to a simple label. */
623 if (cur
->button_type
)
624 xm_update_toggle (instance
, button
, cur
);
625 else if (cur
->call_data
)
626 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
627 (XtPointer
)instance
);
631 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
633 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
634 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
635 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
637 xm_update_label (instance
, button
, cur
);
639 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
640 (XtPointer
)instance
);
641 XtOverrideTranslations (button
, override
);
645 children
[child_index
] = button
;
648 /* Last entry is the help button. The original comment read "Has to
649 be done after managing the buttons otherwise the menubar is only
650 4 pixels high." This is no longer true, and to make
651 XmNmenuHelpWidget work, we need to set it before managing the
652 children.. --gerd. */
654 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, NULL
);
657 XtManageChildren (children
, num_children
);
659 XtFree ((char *) children
);
661 XtFree ((char *) old_children
);
665 update_one_menu_entry (instance
, widget
, val
, deep_p
)
666 widget_instance
* instance
;
674 widget_value
* contents
;
676 if (val
->this_one_change
== NO_CHANGE
)
679 /* update the sensitivity and userdata */
680 /* Common to all widget types */
681 XtSetSensitive (widget
, val
->enabled
);
682 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
684 /* update the menu button as a label. */
685 if (val
->this_one_change
>= VISIBLE_CHANGE
)
687 xm_update_label (instance
, widget
, val
);
688 if (val
->button_type
)
689 xm_update_toggle (instance
, widget
, val
);
692 /* update the pulldown/pullaside as needed */
695 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
696 XtGetValues (widget
, al
, ac
);
698 contents
= val
->contents
;
704 unsigned int old_num_children
, i
;
708 parent
= XtParent (widget
);
709 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
711 /* Find the widget position within the parent's widget list. */
712 for (i
= 0; i
< old_num_children
; i
++)
713 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
715 if (i
== old_num_children
)
717 if (XmIsCascadeButton (widget_list
[i
]))
719 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
720 make_menu_in_widget (instance
, menu
, contents
, 0);
722 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
723 XtSetValues (widget
, al
, ac
);
729 /* The current menuitem is a XmPushButtonGadget, it
730 needs to be replaced by a CascadeButtonGadget */
731 XtDestroyWidget (widget_list
[i
]);
732 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
733 make_menu_in_widget (instance
, menu
, contents
, 0);
735 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
736 /* Non-zero values don't work reliably in
737 conjunction with Emacs' event loop */
738 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
739 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
740 /* Tell Motif to put it in the right place */
741 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
743 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
744 xm_update_label (instance
, button
, val
);
746 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
747 (XtPointer
)instance
);
748 XtManageChild (button
);
752 XtFree ((char*) widget_list
);
758 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
759 XtSetValues (widget
, al
, ac
);
760 XtDestroyWidget (menu
);
762 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
763 xm_update_menu (instance
, menu
, val
, 1);
767 xm_update_menu (instance
, widget
, val
, deep_p
)
768 widget_instance
* instance
;
774 unsigned int num_children
;
775 int num_children_to_keep
= 0;
779 children
= XtCompositeChildren (widget
, &num_children
);
781 /* Widget is a RowColumn widget whose contents have to be updated
782 * to reflect the list of items in val->contents */
784 /* See how many buttons we can keep, and how many we
785 must completely replace. */
786 if (val
->contents
== 0)
787 num_children_to_keep
= 0;
788 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
792 for (i
= 0, cur
= val
->contents
;
794 && cur
); /* how else to ditch unwanted children ?? - mgd */
795 i
++, cur
= cur
->next
)
797 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
801 num_children_to_keep
= i
;
805 num_children_to_keep
= num_children
;
807 /* Update all the buttons of the RowColumn, in order,
808 except for those we are going to replace entirely. */
811 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
815 num_children_to_keep
= i
;
818 if (children
[i
]->core
.being_destroyed
819 || strcmp (XtName (children
[i
]), cur
->name
))
821 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
826 /* Now replace from scratch all the buttons after the last
827 place that the top-level structure changed. */
828 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
830 destroy_all_children (widget
, num_children_to_keep
);
831 make_menu_in_widget (instance
, widget
, val
->contents
,
832 num_children_to_keep
);
835 XtFree ((char *) children
);
839 /* update text widgets */
842 xm_update_text (instance
, widget
, val
)
843 widget_instance
* instance
;
847 XmTextSetString (widget
, val
->value
? val
->value
: "");
848 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
849 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
850 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
851 XtAddCallback (widget
, XmNvalueChangedCallback
,
852 xm_internal_update_other_instances
, instance
);
856 xm_update_text_field (instance
, widget
, val
)
857 widget_instance
* instance
;
861 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
862 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
863 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
864 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
865 XtAddCallback (widget
, XmNvalueChangedCallback
,
866 xm_internal_update_other_instances
, instance
);
870 /* update a motif widget */
873 xm_update_one_widget (instance
, widget
, val
, deep_p
)
874 widget_instance
* instance
;
881 /* Mark as not edited */
884 /* Common to all widget types */
885 XtSetSensitive (widget
, val
->enabled
);
886 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
888 /* Common to all label like widgets */
889 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
890 xm_update_label (instance
, widget
, val
);
892 class = XtClass (widget
);
893 /* Class specific things */
894 if (class == xmPushButtonWidgetClass
||
895 class == xmArrowButtonWidgetClass
)
897 xm_update_pushbutton (instance
, widget
, val
);
899 else if (class == xmCascadeButtonWidgetClass
)
901 xm_update_cascadebutton (instance
, widget
, val
);
903 else if (class == xmToggleButtonWidgetClass
904 || class == xmToggleButtonGadgetClass
)
906 xm_update_toggle (instance
, widget
, val
);
908 else if (class == xmRowColumnWidgetClass
)
910 Boolean radiobox
= 0;
914 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
915 XtGetValues (widget
, al
, ac
);
918 xm_update_radiobox (instance
, widget
, val
);
920 xm_update_menu (instance
, widget
, val
, deep_p
);
922 else if (class == xmTextWidgetClass
)
924 xm_update_text (instance
, widget
, val
);
926 else if (class == xmTextFieldWidgetClass
)
928 xm_update_text_field (instance
, widget
, val
);
930 else if (class == xmListWidgetClass
)
932 xm_update_list (instance
, widget
, val
);
936 \f/* getting the value back */
938 xm_update_one_value (instance
, widget
, val
)
939 widget_instance
* instance
;
943 WidgetClass
class = XtClass (widget
);
944 widget_value
*old_wv
;
946 /* copy the call_data slot into the "return" widget_value */
947 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
948 if (!strcmp (val
->name
, old_wv
->name
))
950 val
->call_data
= old_wv
->call_data
;
954 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
956 XtVaGetValues (widget
, XmNset
, &val
->selected
, NULL
);
959 else if (class == xmTextWidgetClass
)
962 val
->value
= XmTextGetString (widget
);
965 else if (class == xmTextFieldWidgetClass
)
968 val
->value
= XmTextFieldGetString (widget
);
971 else if (class == xmRowColumnWidgetClass
)
973 Boolean radiobox
= 0;
977 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
978 XtGetValues (widget
, al
, ac
);
982 CompositeWidget radio
= (CompositeWidget
)widget
;
984 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
987 Widget toggle
= radio
->composite
.children
[i
];
989 XtVaGetValues (toggle
, XmNset
, &set
, NULL
);
993 val
->value
= safe_strdup (XtName (toggle
));
999 else if (class == xmListWidgetClass
)
1003 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
1007 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
1011 cur
->selected
= False
;
1013 for (j
= 0; j
< pos_cnt
; j
++)
1014 if (pos_list
[j
] == i
)
1016 cur
->selected
= True
;
1017 val
->value
= safe_strdup (cur
->name
);
1021 XtFree ((char *) pos_list
);
1027 /* This function is for activating a button from a program. It's wrong because
1028 we pass a NULL argument in the call_data which is not Motif compatible.
1029 This is used from the XmNdefaultAction callback of the List widgets to
1030 have a double-click put down a dialog box like the button would do.
1031 I could not find a way to do that with accelerators.
1034 activate_button (widget
, closure
, call_data
)
1037 XtPointer call_data
;
1039 Widget button
= (Widget
)closure
;
1040 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
1043 /* creation functions */
1045 /* Called for key press in dialogs. Used to pop down dialog on ESC. */
1047 dialog_key_cb (widget
, closure
, event
, continue_to_dispatch
)
1051 Boolean
*continue_to_dispatch
;
1054 Modifiers modif_ret
;
1056 XtTranslateKeycode (event
->xkey
.display
, event
->xkey
.keycode
, 0,
1059 if (sym
== osfXK_Cancel
)
1061 Widget w
= *((Widget
*) closure
);
1063 while (w
&& ! XtIsShell (w
))
1066 if (XtIsShell (w
)) XtPopdown (w
);
1069 *continue_to_dispatch
= TRUE
;
1074 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
1075 radio_box
, list
, left_buttons
, right_buttons
)
1081 Boolean text_input_slot
;
1091 Widget icon_separator
;
1096 Widget children
[16]; /* for the final XtManageChildren */
1098 Arg al
[64]; /* Arg List */
1099 int ac
; /* Arg Count */
1105 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
1106 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
1107 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
1108 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1110 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1111 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1112 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1113 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1118 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1119 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1120 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1124 n_children
= left_buttons
+ right_buttons
+ 1;
1126 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1127 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1128 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1129 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1130 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1131 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1132 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1133 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1134 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1135 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1136 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1137 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1138 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1139 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1140 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1141 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1142 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1143 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1144 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1147 for (i
= 0; i
< left_buttons
; i
++)
1149 char button_name
[16];
1150 sprintf (button_name
, "button%d", i
+ 1);
1154 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1155 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1157 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1158 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1159 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1160 XtAddEventHandler (children
[n_children
],
1161 KeyPressMask
, False
, dialog_key_cb
, result
);
1165 button
= children
[n_children
];
1167 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1168 XtSetValues (row
, al
, ac
);
1174 /* invisible separator button */
1176 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1177 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1180 for (i
= 0; i
< right_buttons
; i
++)
1182 char button_name
[16];
1183 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1185 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1186 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1187 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1188 XtAddEventHandler (children
[n_children
],
1189 KeyPressMask
, False
, dialog_key_cb
, result
);
1191 if (! button
) button
= children
[n_children
];
1195 XtManageChildren (children
, n_children
);
1198 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1199 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1200 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1201 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1202 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1203 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1204 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1205 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1206 separator
= XmCreateSeparator (form
, "", al
, ac
);
1209 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1210 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1211 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1212 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1213 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1214 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1215 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1216 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1219 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1220 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1221 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1222 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1223 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1224 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1225 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1226 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1227 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1228 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1230 if (text_input_slot
)
1233 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1234 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1235 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1236 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1237 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1238 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1239 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1240 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1241 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1242 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1243 value
= XmCreateTextField (form
, "value", al
, ac
);
1249 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1250 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1251 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1252 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1253 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1254 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1255 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1256 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1257 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1258 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1259 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1260 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1261 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1262 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1265 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1266 children
[i
++] = radio_butt
;
1267 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1268 children
[i
++] = radio_butt
;
1269 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1270 children
[i
++] = radio_butt
;
1271 XtManageChildren (children
, i
);
1276 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1277 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1278 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1279 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1280 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1281 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1282 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1283 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1284 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1285 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1286 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1288 /* this is the easiest way I found to have the dble click in the
1289 list activate the default button */
1290 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1294 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1295 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1296 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1297 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1298 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1299 XtSetArg(al
[ac
], XmNbottomWidget
,
1300 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1301 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1302 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1303 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1304 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1305 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1306 message
= XmCreateLabel (form
, "message", al
, ac
);
1309 XtManageChild (value
);
1312 children
[i
] = row
; i
++;
1313 children
[i
] = separator
; i
++;
1314 if (text_input_slot
|| radio_box
)
1316 children
[i
] = value
; i
++;
1318 children
[i
] = message
; i
++;
1319 children
[i
] = icon
; i
++;
1320 children
[i
] = icon_separator
; i
++;
1321 XtManageChildren (children
, i
);
1323 if (text_input_slot
|| list
)
1325 XtInstallAccelerators (value
, button
);
1326 XtSetKeyboardFocus (result
, value
);
1330 XtInstallAccelerators (form
, button
);
1331 XtSetKeyboardFocus (result
, button
);
1337 static destroyed_instance
*
1338 find_matching_instance (instance
)
1339 widget_instance
* instance
;
1341 destroyed_instance
* cur
;
1342 destroyed_instance
* prev
;
1343 char* type
= instance
->info
->type
;
1344 char* name
= instance
->info
->name
;
1346 for (prev
= NULL
, cur
= all_destroyed_instances
;
1348 prev
= cur
, cur
= cur
->next
)
1350 if (!strcmp (cur
->name
, name
)
1351 && !strcmp (cur
->type
, type
)
1352 && cur
->parent
== instance
->parent
1353 && cur
->pop_up_p
== instance
->pop_up_p
)
1356 prev
->next
= cur
->next
;
1358 all_destroyed_instances
= cur
->next
;
1361 /* do some cleanup */
1362 else if (!cur
->widget
)
1365 prev
->next
= cur
->next
;
1367 all_destroyed_instances
= cur
->next
;
1368 free_destroyed_instance (cur
);
1369 cur
= prev
? prev
: all_destroyed_instances
;
1376 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1379 XtPointer call_data
;
1381 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1382 instance
->widget
= NULL
;
1386 recenter_widget (widget
)
1389 Widget parent
= XtParent (widget
);
1390 Screen
* screen
= XtScreen (widget
);
1391 Dimension screen_width
= WidthOfScreen (screen
);
1392 Dimension screen_height
= HeightOfScreen (screen
);
1393 Dimension parent_width
= 0;
1394 Dimension parent_height
= 0;
1395 Dimension child_width
= 0;
1396 Dimension child_height
= 0;
1400 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, NULL
);
1401 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1404 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1405 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1407 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1409 if (x
+ child_width
> screen_width
)
1410 x
= screen_width
- child_width
;
1414 if (y
+ child_height
> screen_height
)
1415 y
= screen_height
- child_height
;
1419 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, NULL
);
1423 recycle_instance (instance
)
1424 destroyed_instance
* instance
;
1426 Widget widget
= instance
->widget
;
1428 /* widget is NULL if the parent was destroyed. */
1434 /* Remove the destroy callback as the instance is not in the list
1436 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1437 mark_dead_instance_destroyed
,
1438 (XtPointer
)instance
);
1440 /* Give the focus to the initial item */
1441 focus
= XtNameToWidget (widget
, "*value");
1443 focus
= XtNameToWidget (widget
, "*button1");
1445 XtSetKeyboardFocus (widget
, focus
);
1447 /* shrink the separator label back to their original size */
1448 separator
= XtNameToWidget (widget
, "*separator_button");
1450 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, NULL
);
1452 /* Center the dialog in its parent */
1453 recenter_widget (widget
);
1455 free_destroyed_instance (instance
);
1460 xm_create_dialog (instance
)
1461 widget_instance
* instance
;
1463 char* name
= instance
->info
->type
;
1464 Widget parent
= instance
->parent
;
1466 Boolean pop_up_p
= instance
->pop_up_p
;
1467 char* shell_name
= 0;
1468 char* icon_name
= 0;
1469 Boolean text_input_slot
= False
;
1470 Boolean radio_box
= False
;
1471 Boolean list
= False
;
1473 int left_buttons
= 0;
1474 int right_buttons
= 1;
1475 destroyed_instance
* dead_one
;
1477 /* try to find a widget to recycle */
1478 dead_one
= find_matching_instance (instance
);
1481 Widget recycled_widget
= recycle_instance (dead_one
);
1482 if (recycled_widget
)
1483 return recycled_widget
;
1488 icon_name
= "dbox-error";
1489 shell_name
= "Error";
1493 icon_name
= "dbox-info";
1494 shell_name
= "Information";
1499 icon_name
= "dbox-question";
1500 shell_name
= "Prompt";
1504 text_input_slot
= True
;
1505 icon_name
= "dbox-question";
1506 shell_name
= "Prompt";
1510 icon_name
= "dbox-question";
1511 shell_name
= "Question";
1515 total_buttons
= name
[1] - '0';
1517 if (name
[3] == 'T' || name
[3] == 't')
1519 text_input_slot
= False
;
1523 right_buttons
= name
[4] - '0';
1525 left_buttons
= total_buttons
- right_buttons
;
1527 widget
= make_dialog (name
, parent
, pop_up_p
,
1528 shell_name
, icon_name
, text_input_slot
, radio_box
,
1529 list
, left_buttons
, right_buttons
);
1531 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1532 (XtPointer
) instance
);
1537 /* Create a menu bar. We turn off the f10 key
1538 because we have not yet managed to make it work right in Motif. */
1541 make_menubar (instance
)
1542 widget_instance
* instance
;
1548 XtSetArg(al
[ac
], XmNmenuAccelerator
, 0); ++ac
;
1549 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, ac
);
1553 remove_grabs (shell
, closure
, call_data
)
1556 XtPointer call_data
;
1558 Widget menu
= (Widget
) closure
;
1559 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1563 make_popup_menu (instance
)
1564 widget_instance
* instance
;
1566 Widget parent
= instance
->parent
;
1567 Window parent_window
= parent
->core
.window
;
1570 /* sets the parent window to 0 to fool Motif into not generating a grab */
1571 parent
->core
.window
= 0;
1572 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1573 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1575 parent
->core
.window
= parent_window
;
1580 make_main (instance
)
1581 widget_instance
* instance
;
1583 Widget parent
= instance
->parent
;
1589 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1590 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1591 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1595 \f/* Table of functions to create widgets */
1599 /* interface with the XDesigner generated functions */
1600 typedef Widget (*widget_maker
) (Widget
);
1601 extern Widget
create_project_p_sheet (Widget parent
);
1602 extern Widget
create_debugger_p_sheet (Widget parent
);
1603 extern Widget
create_breaklist_p_sheet (Widget parent
);
1604 extern Widget
create_le_browser_p_sheet (Widget parent
);
1605 extern Widget
create_class_browser_p_sheet (Widget parent
);
1606 extern Widget
create_call_browser_p_sheet (Widget parent
);
1607 extern Widget
create_build_dialog (Widget parent
);
1608 extern Widget
create_editmode_dialog (Widget parent
);
1609 extern Widget
create_search_dialog (Widget parent
);
1610 extern Widget
create_project_display_dialog (Widget parent
);
1613 make_one (widget_instance
* instance
, widget_maker fn
)
1619 if (instance
->pop_up_p
)
1621 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1622 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1623 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1624 (XtPointer
) instance
);
1629 result
= (*fn
) (instance
->parent
);
1630 XtRealizeWidget (result
);
1636 make_project_p_sheet (widget_instance
* instance
)
1638 return make_one (instance
, create_project_p_sheet
);
1642 make_debugger_p_sheet (widget_instance
* instance
)
1644 return make_one (instance
, create_debugger_p_sheet
);
1648 make_breaklist_p_sheet (widget_instance
* instance
)
1650 return make_one (instance
, create_breaklist_p_sheet
);
1654 make_le_browser_p_sheet (widget_instance
* instance
)
1656 return make_one (instance
, create_le_browser_p_sheet
);
1660 make_class_browser_p_sheet (widget_instance
* instance
)
1662 return make_one (instance
, create_class_browser_p_sheet
);
1666 make_call_browser_p_sheet (widget_instance
* instance
)
1668 return make_one (instance
, create_call_browser_p_sheet
);
1672 make_build_dialog (widget_instance
* instance
)
1674 return make_one (instance
, create_build_dialog
);
1678 make_editmode_dialog (widget_instance
* instance
)
1680 return make_one (instance
, create_editmode_dialog
);
1684 make_search_dialog (widget_instance
* instance
)
1686 return make_one (instance
, create_search_dialog
);
1690 make_project_display_dialog (widget_instance
* instance
)
1692 return make_one (instance
, create_project_display_dialog
);
1695 #endif /* ENERGIZE */
1697 widget_creation_entry
1698 xm_creation_table
[] =
1700 {"menubar", make_menubar
},
1701 {"popup", make_popup_menu
},
1702 {"main", make_main
},
1704 {"project_p_sheet", make_project_p_sheet
},
1705 {"debugger_p_sheet", make_debugger_p_sheet
},
1706 {"breaklist_psheet", make_breaklist_p_sheet
},
1707 {"leb_psheet", make_le_browser_p_sheet
},
1708 {"class_browser_psheet", make_class_browser_p_sheet
},
1709 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1710 {"build", make_build_dialog
},
1711 {"editmode", make_editmode_dialog
},
1712 {"search", make_search_dialog
},
1713 {"project_display", make_project_display_dialog
},
1714 #endif /* ENERGIZE */
1718 \f/* Destruction of instances */
1720 xm_destroy_instance (instance
)
1721 widget_instance
* instance
;
1723 Widget widget
= instance
->widget
;
1724 /* recycle the dialog boxes */
1725 /* Disable the recycling until we can find a way to have the dialog box
1726 get reasonable layout after we modify its contents. */
1728 && XtClass (widget
) == xmDialogShellWidgetClass
)
1730 destroyed_instance
* dead_instance
=
1731 make_destroyed_instance (instance
->info
->name
,
1732 instance
->info
->type
,
1735 instance
->pop_up_p
);
1736 dead_instance
->next
= all_destroyed_instances
;
1737 all_destroyed_instances
= dead_instance
;
1738 XtUnmanageChild (first_child (instance
->widget
));
1739 XFlush (XtDisplay (instance
->widget
));
1740 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1741 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1745 /* This might not be necessary now that the nosel is attached to
1746 popdown instead of destroy, but it can't hurt. */
1747 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1748 xm_nosel_callback
, (XtPointer
)instance
);
1749 XtDestroyWidget (instance
->widget
);
1753 \f/* popup utility */
1755 xm_popup_menu (widget
, event
)
1759 XButtonPressedEvent dummy
;
1763 dummy
.type
= ButtonPress
;
1765 dummy
.send_event
= 0;
1766 dummy
.display
= XtDisplay (widget
);
1767 dummy
.window
= XtWindow (XtParent (widget
));
1770 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1771 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1772 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1773 event
= (XEvent
*) &dummy
;
1776 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1778 /* Setting the menuPost resource only required by Motif 1.1 and
1779 LessTif 0.84 and earlier. With later versions of LessTif,
1780 setting menuPost is unnecessary and may cause problems, so
1782 #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
1784 /* This is so totally ridiculous: there's NO WAY to tell Motif
1785 that *any* button can select a menu item. Only one button
1786 can have that honor. */
1789 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1790 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1791 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1792 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1793 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1794 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, NULL
);
1798 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1801 XtManageChild (widget
);
1805 set_min_dialog_size (w
)
1810 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, NULL
);
1811 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, NULL
);
1815 xm_pop_instance (instance
, up
)
1816 widget_instance
* instance
;
1819 Widget widget
= instance
->widget
;
1821 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1823 Widget widget_to_manage
= first_child (widget
);
1826 XtManageChild (widget_to_manage
);
1827 set_min_dialog_size (widget
);
1828 XtSetKeyboardFocus (instance
->parent
, widget
);
1831 XtUnmanageChild (widget_to_manage
);
1836 XtManageChild (widget
);
1838 XtUnmanageChild (widget
);
1843 /* motif callback */
1846 do_call (widget
, closure
, type
)
1849 enum do_call_type type
;
1853 XtPointer user_data
;
1854 widget_instance
* instance
= (widget_instance
*)closure
;
1855 Widget instance_widget
;
1860 if (widget
->core
.being_destroyed
)
1863 instance_widget
= instance
->widget
;
1864 if (!instance_widget
)
1867 id
= instance
->info
->id
;
1870 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1871 XtGetValues (widget
, al
, ac
);
1876 if (instance
->info
->pre_activate_cb
)
1877 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1881 if (instance
->info
->selection_cb
)
1882 instance
->info
->selection_cb (widget
, id
, user_data
);
1886 if (instance
->info
->selection_cb
)
1887 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1891 if (instance
->info
->post_activate_cb
)
1892 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1900 /* Like lw_internal_update_other_instances except that it does not do
1901 anything if its shell parent is not managed. This is to protect
1902 lw_internal_update_other_instances to dereference freed memory
1903 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1906 xm_internal_update_other_instances (widget
, closure
, call_data
)
1909 XtPointer call_data
;
1912 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1913 if (XtIsShell (parent
))
1915 else if (!XtIsManaged (parent
))
1917 lw_internal_update_other_instances (widget
, closure
, call_data
);
1921 xm_generic_callback (widget
, closure
, call_data
)
1924 XtPointer call_data
;
1926 lw_internal_update_other_instances (widget
, closure
, call_data
);
1927 do_call (widget
, closure
, selection
);
1931 xm_nosel_callback (widget
, closure
, call_data
)
1934 XtPointer call_data
;
1936 /* This callback is only called when a dialog box is dismissed with
1937 the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog
1938 box to be destroyed in that case, not just unmapped, so that it
1939 releases its keyboard grabs. But there are problems with running
1940 our callbacks while the widget is in the process of being
1941 destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
1942 XmDESTROY and then destroy it ourself after having run the
1944 do_call (widget
, closure
, no_selection
);
1945 XtDestroyWidget (widget
);
1949 xm_pull_down_callback (widget
, closure
, call_data
)
1952 XtPointer call_data
;
1954 Widget parent
= XtParent (widget
);
1956 if (XmIsRowColumn (parent
))
1958 unsigned char type
= 0xff;
1959 XtVaGetValues (parent
, XmNrowColumnType
, &type
, NULL
);
1960 if (type
== XmMENU_BAR
)
1961 do_call (widget
, closure
, pre_activate
);
1966 /* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
1967 CLOSURE is a pointer to the widget_instance of the shell,
1969 Note that this callback is called for each cascade button in a
1970 menu, whether or not its submenu is visible. */
1973 xm_pop_down_callback (widget
, closure
, call_data
)
1976 XtPointer call_data
;
1978 widget_instance
*instance
= (widget_instance
*) closure
;
1980 if ((!instance
->pop_up_p
&& XtParent (widget
) == instance
->widget
)
1981 || XtParent (widget
) == instance
->parent
)
1982 do_call (widget
, closure
, post_activate
);
1986 /* set the keyboard focus */
1988 xm_set_keyboard_focus (parent
, w
)
1992 XmProcessTraversal (w
, 0);
1993 XtSetKeyboardFocus (parent
, w
);
1996 /* Motif hack to set the main window areas. */
1998 xm_set_main_areas (parent
, menubar
, work_area
)
2003 XmMainWindowSetAreas (parent
,
2004 menubar
, /* menubar (maybe 0) */
2005 0, /* command area (psheets) */
2006 0, /* horizontal scroll */
2007 0, /* vertical scroll */
2008 work_area
); /* work area */
2011 /* Motif hack to control resizing on the menubar. */
2013 xm_manage_resizing (w
, flag
)
2017 XtVaSetValues (w
, XtNallowShellResize
, flag
, NULL
);
2020 /* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
2021 (do not change this comment) */