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 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 1, 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., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, 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 /* Disable drag and drop for labels in menu bar. */
528 static char overrideTrans
[] = "<Btn2Down>: Noop()";
529 XtTranslations override
= XtParseTranslationTable (overrideTrans
);
531 old_children
= XtCompositeChildren (widget
, &old_num_children
);
533 /* Allocate the children array */
534 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
)
536 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
538 /* WIDGET should be a RowColumn. */
539 if (!XmIsRowColumn (widget
))
542 /* Determine whether WIDGET is a menu bar. */
544 XtSetArg (al
[0], XmNrowColumnType
, &type
);
545 XtGetValues (widget
, al
, 1);
546 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
548 menubar_p
= type
== XmMENU_BAR
;
550 /* Add a callback to popups and pulldowns that is called when
551 it is made invisible again. */
553 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
554 xm_pop_down_callback
, (XtPointer
)instance
);
556 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
557 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
558 child_index
++, cur
= cur
->next
)
559 children
[child_index
] = old_children
[child_index
];
561 /* Check that those are all we have
562 (the caller should have deleted the rest). */
563 if (old_num_children
!= keep_first_children
)
566 /* Create the rest. */
567 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
569 enum menu_separator separator
;
572 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
573 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
574 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
576 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
577 && !lw_separator_p (cur
->name
, &separator
, 1))
580 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
581 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
583 else if (lw_separator_p (cur
->name
, &separator
, 1))
586 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
587 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
589 else if (!cur
->contents
)
592 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
593 else if (!cur
->call_data
)
594 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
595 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
596 || cur
->button_type
== BUTTON_TYPE_RADIO
)
598 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
599 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
600 XtSetArg (al
[ac
], XmNindicatorType
,
601 (cur
->button_type
== BUTTON_TYPE_TOGGLE
602 ? XmN_OF_MANY
: XmONE_OF_MANY
));
604 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
605 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
606 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
610 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
611 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
612 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
615 xm_update_label (instance
, button
, cur
);
617 /* Add a callback that is called when the button is
618 selected. Toggle buttons don't support
619 XmNactivateCallback, we use XmNvalueChangedCallback in
620 that case. Don't add a callback to a simple label. */
621 if (cur
->button_type
)
622 xm_update_toggle (instance
, button
, cur
);
623 else if (cur
->call_data
)
624 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
625 (XtPointer
)instance
);
629 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
631 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
632 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
633 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
635 xm_update_label (instance
, button
, cur
);
637 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
638 (XtPointer
)instance
);
639 XtOverrideTranslations (button
, override
);
643 children
[child_index
] = button
;
646 /* Last entry is the help button. The original comment read "Has to
647 be done after managing the buttons otherwise the menubar is only
648 4 pixels high." This is no longer true, and to make
649 XmNmenuHelpWidget work, we need to set it before managing the
650 children.. --gerd. */
652 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, NULL
);
655 XtManageChildren (children
, num_children
);
657 XtFree ((char *) children
);
659 XtFree ((char *) old_children
);
663 update_one_menu_entry (instance
, widget
, val
, deep_p
)
664 widget_instance
* instance
;
672 widget_value
* contents
;
674 if (val
->this_one_change
== NO_CHANGE
)
677 /* update the sensitivity and userdata */
678 /* Common to all widget types */
679 XtSetSensitive (widget
, val
->enabled
);
680 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
682 /* update the menu button as a label. */
683 if (val
->this_one_change
>= VISIBLE_CHANGE
)
685 xm_update_label (instance
, widget
, val
);
686 if (val
->button_type
)
687 xm_update_toggle (instance
, widget
, val
);
690 /* update the pulldown/pullaside as needed */
693 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
694 XtGetValues (widget
, al
, ac
);
696 contents
= val
->contents
;
702 unsigned int old_num_children
, i
;
706 parent
= XtParent (widget
);
707 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
709 /* Find the widget position within the parent's widget list. */
710 for (i
= 0; i
< old_num_children
; i
++)
711 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
713 if (i
== old_num_children
)
715 if (XmIsCascadeButton (widget_list
[i
]))
717 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
718 make_menu_in_widget (instance
, menu
, contents
, 0);
720 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
721 XtSetValues (widget
, al
, ac
);
727 /* The current menuitem is a XmPushButtonGadget, it
728 needs to be replaced by a CascadeButtonGadget */
729 XtDestroyWidget (widget_list
[i
]);
730 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
731 make_menu_in_widget (instance
, menu
, contents
, 0);
733 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
734 /* Non-zero values don't work reliably in
735 conjunction with Emacs' event loop */
736 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
737 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
738 /* Tell Motif to put it in the right place */
739 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
741 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
742 xm_update_label (instance
, button
, val
);
744 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
745 (XtPointer
)instance
);
746 XtManageChild (button
);
750 XtFree ((char*) widget_list
);
756 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
757 XtSetValues (widget
, al
, ac
);
758 XtDestroyWidget (menu
);
760 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
761 xm_update_menu (instance
, menu
, val
, 1);
765 xm_update_menu (instance
, widget
, val
, deep_p
)
766 widget_instance
* instance
;
772 unsigned int num_children
;
773 int num_children_to_keep
= 0;
777 children
= XtCompositeChildren (widget
, &num_children
);
779 /* Widget is a RowColumn widget whose contents have to be updated
780 * to reflect the list of items in val->contents */
782 /* See how many buttons we can keep, and how many we
783 must completely replace. */
784 if (val
->contents
== 0)
785 num_children_to_keep
= 0;
786 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
790 for (i
= 0, cur
= val
->contents
;
792 && cur
); /* how else to ditch unwanted children ?? - mgd */
793 i
++, cur
= cur
->next
)
795 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
799 num_children_to_keep
= i
;
803 num_children_to_keep
= num_children
;
805 /* Update all the buttons of the RowColumn, in order,
806 except for those we are going to replace entirely. */
809 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
813 num_children_to_keep
= i
;
816 if (children
[i
]->core
.being_destroyed
817 || strcmp (XtName (children
[i
]), cur
->name
))
819 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
824 /* Now replace from scratch all the buttons after the last
825 place that the top-level structure changed. */
826 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
828 destroy_all_children (widget
, num_children_to_keep
);
829 make_menu_in_widget (instance
, widget
, val
->contents
,
830 num_children_to_keep
);
833 XtFree ((char *) children
);
837 /* update text widgets */
840 xm_update_text (instance
, widget
, val
)
841 widget_instance
* instance
;
845 XmTextSetString (widget
, val
->value
? val
->value
: "");
846 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
847 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
848 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
849 XtAddCallback (widget
, XmNvalueChangedCallback
,
850 xm_internal_update_other_instances
, instance
);
854 xm_update_text_field (instance
, widget
, val
)
855 widget_instance
* instance
;
859 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
860 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
861 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
862 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
863 XtAddCallback (widget
, XmNvalueChangedCallback
,
864 xm_internal_update_other_instances
, instance
);
868 /* update a motif widget */
871 xm_update_one_widget (instance
, widget
, val
, deep_p
)
872 widget_instance
* instance
;
879 /* Mark as not edited */
882 /* Common to all widget types */
883 XtSetSensitive (widget
, val
->enabled
);
884 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
886 /* Common to all label like widgets */
887 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
888 xm_update_label (instance
, widget
, val
);
890 class = XtClass (widget
);
891 /* Class specific things */
892 if (class == xmPushButtonWidgetClass
||
893 class == xmArrowButtonWidgetClass
)
895 xm_update_pushbutton (instance
, widget
, val
);
897 else if (class == xmCascadeButtonWidgetClass
)
899 xm_update_cascadebutton (instance
, widget
, val
);
901 else if (class == xmToggleButtonWidgetClass
902 || class == xmToggleButtonGadgetClass
)
904 xm_update_toggle (instance
, widget
, val
);
906 else if (class == xmRowColumnWidgetClass
)
908 Boolean radiobox
= 0;
912 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
913 XtGetValues (widget
, al
, ac
);
916 xm_update_radiobox (instance
, widget
, val
);
918 xm_update_menu (instance
, widget
, val
, deep_p
);
920 else if (class == xmTextWidgetClass
)
922 xm_update_text (instance
, widget
, val
);
924 else if (class == xmTextFieldWidgetClass
)
926 xm_update_text_field (instance
, widget
, val
);
928 else if (class == xmListWidgetClass
)
930 xm_update_list (instance
, widget
, val
);
934 \f/* getting the value back */
936 xm_update_one_value (instance
, widget
, val
)
937 widget_instance
* instance
;
941 WidgetClass
class = XtClass (widget
);
942 widget_value
*old_wv
;
944 /* copy the call_data slot into the "return" widget_value */
945 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
946 if (!strcmp (val
->name
, old_wv
->name
))
948 val
->call_data
= old_wv
->call_data
;
952 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
954 XtVaGetValues (widget
, XmNset
, &val
->selected
, NULL
);
957 else if (class == xmTextWidgetClass
)
960 val
->value
= XmTextGetString (widget
);
963 else if (class == xmTextFieldWidgetClass
)
966 val
->value
= XmTextFieldGetString (widget
);
969 else if (class == xmRowColumnWidgetClass
)
971 Boolean radiobox
= 0;
975 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
976 XtGetValues (widget
, al
, ac
);
980 CompositeWidget radio
= (CompositeWidget
)widget
;
982 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
985 Widget toggle
= radio
->composite
.children
[i
];
987 XtVaGetValues (toggle
, XmNset
, &set
, NULL
);
991 val
->value
= safe_strdup (XtName (toggle
));
997 else if (class == xmListWidgetClass
)
1001 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
1005 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
1009 cur
->selected
= False
;
1011 for (j
= 0; j
< pos_cnt
; j
++)
1012 if (pos_list
[j
] == i
)
1014 cur
->selected
= True
;
1015 val
->value
= safe_strdup (cur
->name
);
1019 XtFree ((char *) pos_list
);
1025 /* This function is for activating a button from a program. It's wrong because
1026 we pass a NULL argument in the call_data which is not Motif compatible.
1027 This is used from the XmNdefaultAction callback of the List widgets to
1028 have a double-click put down a dialog box like the button would do.
1029 I could not find a way to do that with accelerators.
1032 activate_button (widget
, closure
, call_data
)
1035 XtPointer call_data
;
1037 Widget button
= (Widget
)closure
;
1038 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
1041 /* creation functions */
1043 /* Called for key press in dialogs. Used to pop down dialog on ESC. */
1045 dialog_key_cb (widget
, closure
, event
, continue_to_dispatch
)
1049 Boolean
*continue_to_dispatch
;
1052 Modifiers modif_ret
;
1054 XtTranslateKeycode (event
->xkey
.display
, event
->xkey
.keycode
, 0,
1057 if (sym
== osfXK_Cancel
)
1059 Widget w
= *((Widget
*) closure
);
1061 while (w
&& ! XtIsShell (w
))
1064 if (XtIsShell (w
)) XtPopdown (w
);
1067 *continue_to_dispatch
= TRUE
;
1072 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
1073 radio_box
, list
, left_buttons
, right_buttons
)
1079 Boolean text_input_slot
;
1089 Widget icon_separator
;
1094 Widget children
[16]; /* for the final XtManageChildren */
1096 Arg al
[64]; /* Arg List */
1097 int ac
; /* Arg Count */
1103 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
1104 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
1105 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
1106 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1108 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1109 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1110 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1111 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1116 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1117 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1118 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1122 n_children
= left_buttons
+ right_buttons
+ 1;
1124 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1125 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1126 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1127 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1128 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1129 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1130 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1131 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1132 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1133 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1134 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1135 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1136 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1137 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1138 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1139 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1140 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1141 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1142 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1145 for (i
= 0; i
< left_buttons
; i
++)
1147 char button_name
[16];
1148 sprintf (button_name
, "button%d", i
+ 1);
1152 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1153 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1155 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1156 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1157 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1158 XtAddEventHandler (children
[n_children
],
1159 KeyPressMask
, False
, dialog_key_cb
, result
);
1163 button
= children
[n_children
];
1165 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1166 XtSetValues (row
, al
, ac
);
1172 /* invisible separator button */
1174 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1175 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1178 for (i
= 0; i
< right_buttons
; i
++)
1180 char button_name
[16];
1181 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1183 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1184 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1185 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1186 XtAddEventHandler (children
[n_children
],
1187 KeyPressMask
, False
, dialog_key_cb
, result
);
1189 if (! button
) button
= children
[n_children
];
1193 XtManageChildren (children
, n_children
);
1196 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1197 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1198 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1199 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1200 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1201 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1202 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1203 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1204 separator
= XmCreateSeparator (form
, "", al
, ac
);
1207 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1208 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1209 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1210 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1211 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1212 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1213 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1214 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1217 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1218 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1219 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1220 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1221 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1222 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1223 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1224 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1225 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1226 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1228 if (text_input_slot
)
1231 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1232 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1233 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1234 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1235 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1236 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1237 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1238 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1239 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1240 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1241 value
= XmCreateTextField (form
, "value", al
, ac
);
1247 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1248 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1249 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1250 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1251 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1252 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1253 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1254 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1255 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1256 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1257 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1258 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1259 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1260 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1263 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1264 children
[i
++] = radio_butt
;
1265 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1266 children
[i
++] = radio_butt
;
1267 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1268 children
[i
++] = radio_butt
;
1269 XtManageChildren (children
, i
);
1274 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1275 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1276 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1277 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1278 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1279 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1280 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1281 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1282 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1283 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1284 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1286 /* this is the easiest way I found to have the dble click in the
1287 list activate the default button */
1288 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1292 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1293 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1294 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1295 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1296 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1297 XtSetArg(al
[ac
], XmNbottomWidget
,
1298 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1299 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1300 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1301 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1302 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1303 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1304 message
= XmCreateLabel (form
, "message", al
, ac
);
1307 XtManageChild (value
);
1310 children
[i
] = row
; i
++;
1311 children
[i
] = separator
; i
++;
1312 if (text_input_slot
|| radio_box
)
1314 children
[i
] = value
; i
++;
1316 children
[i
] = message
; i
++;
1317 children
[i
] = icon
; i
++;
1318 children
[i
] = icon_separator
; i
++;
1319 XtManageChildren (children
, i
);
1321 if (text_input_slot
|| list
)
1323 XtInstallAccelerators (value
, button
);
1324 XtSetKeyboardFocus (result
, value
);
1328 XtInstallAccelerators (form
, button
);
1329 XtSetKeyboardFocus (result
, button
);
1335 static destroyed_instance
*
1336 find_matching_instance (instance
)
1337 widget_instance
* instance
;
1339 destroyed_instance
* cur
;
1340 destroyed_instance
* prev
;
1341 char* type
= instance
->info
->type
;
1342 char* name
= instance
->info
->name
;
1344 for (prev
= NULL
, cur
= all_destroyed_instances
;
1346 prev
= cur
, cur
= cur
->next
)
1348 if (!strcmp (cur
->name
, name
)
1349 && !strcmp (cur
->type
, type
)
1350 && cur
->parent
== instance
->parent
1351 && cur
->pop_up_p
== instance
->pop_up_p
)
1354 prev
->next
= cur
->next
;
1356 all_destroyed_instances
= cur
->next
;
1359 /* do some cleanup */
1360 else if (!cur
->widget
)
1363 prev
->next
= cur
->next
;
1365 all_destroyed_instances
= cur
->next
;
1366 free_destroyed_instance (cur
);
1367 cur
= prev
? prev
: all_destroyed_instances
;
1374 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1377 XtPointer call_data
;
1379 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1380 instance
->widget
= NULL
;
1384 recenter_widget (widget
)
1387 Widget parent
= XtParent (widget
);
1388 Screen
* screen
= XtScreen (widget
);
1389 Dimension screen_width
= WidthOfScreen (screen
);
1390 Dimension screen_height
= HeightOfScreen (screen
);
1391 Dimension parent_width
= 0;
1392 Dimension parent_height
= 0;
1393 Dimension child_width
= 0;
1394 Dimension child_height
= 0;
1398 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, NULL
);
1399 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1402 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1403 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1405 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1407 if (x
+ child_width
> screen_width
)
1408 x
= screen_width
- child_width
;
1412 if (y
+ child_height
> screen_height
)
1413 y
= screen_height
- child_height
;
1417 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, NULL
);
1421 recycle_instance (instance
)
1422 destroyed_instance
* instance
;
1424 Widget widget
= instance
->widget
;
1426 /* widget is NULL if the parent was destroyed. */
1432 /* Remove the destroy callback as the instance is not in the list
1434 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1435 mark_dead_instance_destroyed
,
1436 (XtPointer
)instance
);
1438 /* Give the focus to the initial item */
1439 focus
= XtNameToWidget (widget
, "*value");
1441 focus
= XtNameToWidget (widget
, "*button1");
1443 XtSetKeyboardFocus (widget
, focus
);
1445 /* shrink the separator label back to their original size */
1446 separator
= XtNameToWidget (widget
, "*separator_button");
1448 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, NULL
);
1450 /* Center the dialog in its parent */
1451 recenter_widget (widget
);
1453 free_destroyed_instance (instance
);
1458 xm_create_dialog (instance
)
1459 widget_instance
* instance
;
1461 char* name
= instance
->info
->type
;
1462 Widget parent
= instance
->parent
;
1464 Boolean pop_up_p
= instance
->pop_up_p
;
1465 char* shell_name
= 0;
1466 char* icon_name
= 0;
1467 Boolean text_input_slot
= False
;
1468 Boolean radio_box
= False
;
1469 Boolean list
= False
;
1471 int left_buttons
= 0;
1472 int right_buttons
= 1;
1473 destroyed_instance
* dead_one
;
1475 /* try to find a widget to recycle */
1476 dead_one
= find_matching_instance (instance
);
1479 Widget recycled_widget
= recycle_instance (dead_one
);
1480 if (recycled_widget
)
1481 return recycled_widget
;
1486 icon_name
= "dbox-error";
1487 shell_name
= "Error";
1491 icon_name
= "dbox-info";
1492 shell_name
= "Information";
1497 icon_name
= "dbox-question";
1498 shell_name
= "Prompt";
1502 text_input_slot
= True
;
1503 icon_name
= "dbox-question";
1504 shell_name
= "Prompt";
1508 icon_name
= "dbox-question";
1509 shell_name
= "Question";
1513 total_buttons
= name
[1] - '0';
1515 if (name
[3] == 'T' || name
[3] == 't')
1517 text_input_slot
= False
;
1521 right_buttons
= name
[4] - '0';
1523 left_buttons
= total_buttons
- right_buttons
;
1525 widget
= make_dialog (name
, parent
, pop_up_p
,
1526 shell_name
, icon_name
, text_input_slot
, radio_box
,
1527 list
, left_buttons
, right_buttons
);
1529 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1530 (XtPointer
) instance
);
1535 /* Create a menu bar. We turn off the f10 key
1536 because we have not yet managed to make it work right in Motif. */
1539 make_menubar (instance
)
1540 widget_instance
* instance
;
1546 XtSetArg(al
[ac
], XmNmenuAccelerator
, 0); ++ac
;
1547 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, ac
);
1551 remove_grabs (shell
, closure
, call_data
)
1554 XtPointer call_data
;
1556 Widget menu
= (Widget
) closure
;
1557 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1561 make_popup_menu (instance
)
1562 widget_instance
* instance
;
1564 Widget parent
= instance
->parent
;
1565 Window parent_window
= parent
->core
.window
;
1568 /* sets the parent window to 0 to fool Motif into not generating a grab */
1569 parent
->core
.window
= 0;
1570 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1571 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1573 parent
->core
.window
= parent_window
;
1578 make_main (instance
)
1579 widget_instance
* instance
;
1581 Widget parent
= instance
->parent
;
1587 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1588 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1589 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1593 \f/* Table of functions to create widgets */
1597 /* interface with the XDesigner generated functions */
1598 typedef Widget (*widget_maker
) (Widget
);
1599 extern Widget
create_project_p_sheet (Widget parent
);
1600 extern Widget
create_debugger_p_sheet (Widget parent
);
1601 extern Widget
create_breaklist_p_sheet (Widget parent
);
1602 extern Widget
create_le_browser_p_sheet (Widget parent
);
1603 extern Widget
create_class_browser_p_sheet (Widget parent
);
1604 extern Widget
create_call_browser_p_sheet (Widget parent
);
1605 extern Widget
create_build_dialog (Widget parent
);
1606 extern Widget
create_editmode_dialog (Widget parent
);
1607 extern Widget
create_search_dialog (Widget parent
);
1608 extern Widget
create_project_display_dialog (Widget parent
);
1611 make_one (widget_instance
* instance
, widget_maker fn
)
1617 if (instance
->pop_up_p
)
1619 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1620 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1621 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1622 (XtPointer
) instance
);
1627 result
= (*fn
) (instance
->parent
);
1628 XtRealizeWidget (result
);
1634 make_project_p_sheet (widget_instance
* instance
)
1636 return make_one (instance
, create_project_p_sheet
);
1640 make_debugger_p_sheet (widget_instance
* instance
)
1642 return make_one (instance
, create_debugger_p_sheet
);
1646 make_breaklist_p_sheet (widget_instance
* instance
)
1648 return make_one (instance
, create_breaklist_p_sheet
);
1652 make_le_browser_p_sheet (widget_instance
* instance
)
1654 return make_one (instance
, create_le_browser_p_sheet
);
1658 make_class_browser_p_sheet (widget_instance
* instance
)
1660 return make_one (instance
, create_class_browser_p_sheet
);
1664 make_call_browser_p_sheet (widget_instance
* instance
)
1666 return make_one (instance
, create_call_browser_p_sheet
);
1670 make_build_dialog (widget_instance
* instance
)
1672 return make_one (instance
, create_build_dialog
);
1676 make_editmode_dialog (widget_instance
* instance
)
1678 return make_one (instance
, create_editmode_dialog
);
1682 make_search_dialog (widget_instance
* instance
)
1684 return make_one (instance
, create_search_dialog
);
1688 make_project_display_dialog (widget_instance
* instance
)
1690 return make_one (instance
, create_project_display_dialog
);
1693 #endif /* ENERGIZE */
1695 widget_creation_entry
1696 xm_creation_table
[] =
1698 {"menubar", make_menubar
},
1699 {"popup", make_popup_menu
},
1700 {"main", make_main
},
1702 {"project_p_sheet", make_project_p_sheet
},
1703 {"debugger_p_sheet", make_debugger_p_sheet
},
1704 {"breaklist_psheet", make_breaklist_p_sheet
},
1705 {"leb_psheet", make_le_browser_p_sheet
},
1706 {"class_browser_psheet", make_class_browser_p_sheet
},
1707 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1708 {"build", make_build_dialog
},
1709 {"editmode", make_editmode_dialog
},
1710 {"search", make_search_dialog
},
1711 {"project_display", make_project_display_dialog
},
1712 #endif /* ENERGIZE */
1716 \f/* Destruction of instances */
1718 xm_destroy_instance (instance
)
1719 widget_instance
* instance
;
1721 Widget widget
= instance
->widget
;
1722 /* recycle the dialog boxes */
1723 /* Disable the recycling until we can find a way to have the dialog box
1724 get reasonable layout after we modify its contents. */
1726 && XtClass (widget
) == xmDialogShellWidgetClass
)
1728 destroyed_instance
* dead_instance
=
1729 make_destroyed_instance (instance
->info
->name
,
1730 instance
->info
->type
,
1733 instance
->pop_up_p
);
1734 dead_instance
->next
= all_destroyed_instances
;
1735 all_destroyed_instances
= dead_instance
;
1736 XtUnmanageChild (first_child (instance
->widget
));
1737 XFlush (XtDisplay (instance
->widget
));
1738 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1739 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1743 /* This might not be necessary now that the nosel is attached to
1744 popdown instead of destroy, but it can't hurt. */
1745 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1746 xm_nosel_callback
, (XtPointer
)instance
);
1747 XtDestroyWidget (instance
->widget
);
1751 \f/* popup utility */
1753 xm_popup_menu (widget
, event
)
1757 XButtonPressedEvent dummy
;
1761 dummy
.type
= ButtonPress
;
1763 dummy
.send_event
= 0;
1764 dummy
.display
= XtDisplay (widget
);
1765 dummy
.window
= XtWindow (XtParent (widget
));
1768 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1769 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1770 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1771 event
= (XEvent
*) &dummy
;
1774 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1776 /* Setting the menuPost resource only required by Motif 1.1 and
1777 LessTif 0.84 and earlier. With later versions of LessTif,
1778 setting menuPost is unnecessary and may cause problems, so
1780 #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
1782 /* This is so totally ridiculous: there's NO WAY to tell Motif
1783 that *any* button can select a menu item. Only one button
1784 can have that honor. */
1787 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1788 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1789 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1790 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1791 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1792 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, NULL
);
1796 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1799 XtManageChild (widget
);
1803 set_min_dialog_size (w
)
1808 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, NULL
);
1809 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, NULL
);
1813 xm_pop_instance (instance
, up
)
1814 widget_instance
* instance
;
1817 Widget widget
= instance
->widget
;
1819 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1821 Widget widget_to_manage
= first_child (widget
);
1824 XtManageChild (widget_to_manage
);
1825 set_min_dialog_size (widget
);
1826 XtSetKeyboardFocus (instance
->parent
, widget
);
1829 XtUnmanageChild (widget_to_manage
);
1834 XtManageChild (widget
);
1836 XtUnmanageChild (widget
);
1841 /* motif callback */
1844 do_call (widget
, closure
, type
)
1847 enum do_call_type type
;
1851 XtPointer user_data
;
1852 widget_instance
* instance
= (widget_instance
*)closure
;
1853 Widget instance_widget
;
1858 if (widget
->core
.being_destroyed
)
1861 instance_widget
= instance
->widget
;
1862 if (!instance_widget
)
1865 id
= instance
->info
->id
;
1868 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1869 XtGetValues (widget
, al
, ac
);
1874 if (instance
->info
->pre_activate_cb
)
1875 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1879 if (instance
->info
->selection_cb
)
1880 instance
->info
->selection_cb (widget
, id
, user_data
);
1884 if (instance
->info
->selection_cb
)
1885 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1889 if (instance
->info
->post_activate_cb
)
1890 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1898 /* Like lw_internal_update_other_instances except that it does not do
1899 anything if its shell parent is not managed. This is to protect
1900 lw_internal_update_other_instances to dereference freed memory
1901 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1904 xm_internal_update_other_instances (widget
, closure
, call_data
)
1907 XtPointer call_data
;
1910 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1911 if (XtIsShell (parent
))
1913 else if (!XtIsManaged (parent
))
1915 lw_internal_update_other_instances (widget
, closure
, call_data
);
1919 xm_generic_callback (widget
, closure
, call_data
)
1922 XtPointer call_data
;
1924 lw_internal_update_other_instances (widget
, closure
, call_data
);
1925 do_call (widget
, closure
, selection
);
1929 xm_nosel_callback (widget
, closure
, call_data
)
1932 XtPointer call_data
;
1934 /* This callback is only called when a dialog box is dismissed with
1935 the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog
1936 box to be destroyed in that case, not just unmapped, so that it
1937 releases its keyboard grabs. But there are problems with running
1938 our callbacks while the widget is in the process of being
1939 destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
1940 XmDESTROY and then destroy it ourself after having run the
1942 do_call (widget
, closure
, no_selection
);
1943 XtDestroyWidget (widget
);
1947 xm_pull_down_callback (widget
, closure
, call_data
)
1950 XtPointer call_data
;
1952 Widget parent
= XtParent (widget
);
1954 if (XmIsRowColumn (parent
))
1956 unsigned char type
= 0xff;
1957 XtVaGetValues (parent
, XmNrowColumnType
, &type
, NULL
);
1958 if (type
== XmMENU_BAR
)
1959 do_call (widget
, closure
, pre_activate
);
1964 /* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
1965 CLOSURE is a pointer to the widget_instance of the shell,
1967 Note that this callback is called for each cascade button in a
1968 menu, whether or not its submenu is visible. */
1971 xm_pop_down_callback (widget
, closure
, call_data
)
1974 XtPointer call_data
;
1976 widget_instance
*instance
= (widget_instance
*) closure
;
1978 if ((!instance
->pop_up_p
&& XtParent (widget
) == instance
->widget
)
1979 || XtParent (widget
) == instance
->parent
)
1980 do_call (widget
, closure
, post_activate
);
1984 /* set the keyboard focus */
1986 xm_set_keyboard_focus (parent
, w
)
1990 XmProcessTraversal (w
, 0);
1991 XtSetKeyboardFocus (parent
, w
);
1994 /* Motif hack to set the main window areas. */
1996 xm_set_main_areas (parent
, menubar
, work_area
)
2001 XmMainWindowSetAreas (parent
,
2002 menubar
, /* menubar (maybe 0) */
2003 0, /* command area (psheets) */
2004 0, /* horizontal scroll */
2005 0, /* vertical scroll */
2006 work_area
); /* work area */
2009 /* Motif hack to control resizing on the menubar. */
2011 xm_manage_resizing (w
, flag
)
2015 XtVaSetValues (w
, XtNallowShellResize
, flag
, NULL
);
2018 /* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
2019 (do not change this comment) */