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 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. */
31 #include <X11/StringDefs.h>
32 #include <X11/IntrinsicP.h>
33 #include <X11/ObjectP.h>
34 #include <X11/CoreP.h>
35 #include <X11/CompositeP.h>
37 #include "../src/lisp.h"
40 #include "lwlib-utils.h"
42 #include <Xm/BulletinB.h>
43 #include <Xm/CascadeB.h>
44 #include <Xm/CascadeBG.h>
45 #include <Xm/DrawingA.h>
46 #include <Xm/FileSB.h>
50 #include <Xm/MenuShell.h>
51 #include <Xm/MessageB.h>
52 #include <Xm/PanedW.h>
54 #include <Xm/PushBG.h>
55 #include <Xm/ArrowB.h>
56 #include <Xm/SelectioB.h>
59 #include <Xm/ToggleB.h>
60 #include <Xm/ToggleBG.h>
61 #include <Xm/RowColumn.h>
62 #include <Xm/ScrolledW.h>
63 #include <Xm/Separator.h>
64 #include <Xm/DialogS.h>
68 #if defined __STDC__ || defined PROTOTYPES
74 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
77 \f/* Structures to keep destroyed instances */
78 typedef struct _destroyed_instance
85 struct _destroyed_instance
* next
;
88 static destroyed_instance
*make_destroyed_instance
P_ ((char *, char *,
91 static void free_destroyed_instance
P_ ((destroyed_instance
*));
92 Widget first_child
P_ ((Widget
));
93 Boolean lw_motif_widget_p
P_ ((Widget
));
94 static XmString resource_motif_string
P_ ((Widget
, char *));
95 static void destroy_all_children
P_ ((Widget
, int));
96 static void xm_update_label
P_ ((widget_instance
*, Widget
, widget_value
*));
97 static void xm_update_list
P_ ((widget_instance
*, Widget
, widget_value
*));
98 static void xm_update_pushbutton
P_ ((widget_instance
*, Widget
,
100 static void xm_update_cascadebutton
P_ ((widget_instance
*, Widget
,
102 static void xm_update_toggle
P_ ((widget_instance
*, Widget
, widget_value
*));
103 static void xm_update_radiobox
P_ ((widget_instance
*, Widget
, widget_value
*));
104 static void make_menu_in_widget
P_ ((widget_instance
*, Widget
,
105 widget_value
*, int));
106 static void update_one_menu_entry
P_ ((widget_instance
*, Widget
,
107 widget_value
*, Boolean
));
108 static void xm_update_menu
P_ ((widget_instance
*, Widget
, widget_value
*,
110 static void xm_update_text
P_ ((widget_instance
*, Widget
, widget_value
*));
111 static void xm_update_text_field
P_ ((widget_instance
*, Widget
,
113 void xm_update_one_value
P_ ((widget_instance
*, Widget
, widget_value
*));
114 static void activate_button
P_ ((Widget
, XtPointer
, XtPointer
));
115 static Widget make_dialog
P_ ((char *, Widget
, Boolean
, char *, char *,
116 Boolean
, Boolean
, Boolean
, int, int));
117 static destroyed_instance
* find_matching_instance
P_ ((widget_instance
*));
118 static void mark_dead_instance_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
119 static void recenter_widget
P_ ((Widget
));
120 static Widget recycle_instance
P_ ((destroyed_instance
*));
121 Widget xm_create_dialog
P_ ((widget_instance
*));
122 static Widget make_menubar
P_ ((widget_instance
*));
123 static void remove_grabs
P_ ((Widget
, XtPointer
, XtPointer
));
124 static Widget make_popup_menu
P_ ((widget_instance
*));
125 static Widget make_main
P_ ((widget_instance
*));
126 void xm_destroy_instance
P_ ((widget_instance
*));
127 void xm_popup_menu
P_ ((Widget
, XEvent
*));
128 static void set_min_dialog_size
P_ ((Widget
));
129 static void do_call
P_ ((Widget
, XtPointer
, enum do_call_type
));
130 static void xm_generic_callback
P_ ((Widget
, XtPointer
, XtPointer
));
131 static void xm_nosel_callback
P_ ((Widget
, XtPointer
, XtPointer
));
132 static void xm_pull_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
133 static void xm_pop_down_callback
P_ ((Widget
, XtPointer
, XtPointer
));
134 void xm_set_keyboard_focus
P_ ((Widget
, Widget
));
135 void xm_set_main_areas
P_ ((Widget
, Widget
, Widget
));
136 static void xm_internal_update_other_instances
P_ ((Widget
, XtPointer
,
138 static void xm_arm_callback
P_ ((Widget
, XtPointer
, XtPointer
));
141 void xm_update_one_widget
P_ ((widget_instance
*, Widget
, widget_value
*,
143 void xm_pop_instance
P_ ((widget_instance
*, Boolean
));
144 void xm_manage_resizing
P_ ((Widget
, Boolean
));
150 /* Print the complete X resource name of widget WIDGET to stderr.
151 This is sometimes handy to have available. */
154 x_print_complete_resource_name (widget
)
160 for (i
= 0; i
< 100 && widget
!= NULL
; ++i
)
162 names
[i
] = XtName (widget
);
163 widget
= XtParent (widget
);
166 for (--i
; i
>= 1; --i
)
167 fprintf (stderr
, "%s.", names
[i
]);
168 fprintf (stderr
, "%s\n", names
[0]);
174 static destroyed_instance
*all_destroyed_instances
= NULL
;
176 static destroyed_instance
*
177 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
184 destroyed_instance
* instance
=
185 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
186 instance
->name
= safe_strdup (name
);
187 instance
->type
= safe_strdup (type
);
188 instance
->widget
= widget
;
189 instance
->parent
= parent
;
190 instance
->pop_up_p
= pop_up_p
;
191 instance
->next
= NULL
;
196 free_destroyed_instance (instance
)
197 destroyed_instance
* instance
;
199 free (instance
->name
);
200 free (instance
->type
);
204 \f/* motif utility functions */
209 return ((CompositeWidget
)widget
)->composite
.children
[0];
213 lw_motif_widget_p (widget
)
217 XtClass (widget
) == xmDialogShellWidgetClass
218 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
222 resource_motif_string (widget
, name
)
229 resource
.resource_name
= name
;
230 resource
.resource_class
= XmCXmString
;
231 resource
.resource_type
= XmRXmString
;
232 resource
.resource_size
= sizeof (XmString
);
233 resource
.resource_offset
= 0;
234 resource
.default_type
= XtRImmediate
;
235 resource
.default_addr
= 0;
237 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
238 "DialogString", &resource
, 1, NULL
, 0);
242 /* Destroy all of the children of WIDGET
243 starting with number FIRST_CHILD_TO_DESTROY. */
246 destroy_all_children (widget
, first_child_to_destroy
)
248 int first_child_to_destroy
;
254 children
= XtCompositeChildren (widget
, &number
);
257 XtUnmanageChildren (children
+ first_child_to_destroy
,
258 number
- first_child_to_destroy
);
260 /* Unmanage all children and destroy them. They will only be
261 really destroyed when we get out of DispatchEvent. */
262 for (i
= first_child_to_destroy
; i
< number
; i
++)
266 /* Cascade buttons have submenus,and these submenus
267 need to be freed. But they are not included in
268 XtCompositeChildren. So get it out of the cascade button
269 and free it. If this child is not a cascade button,
270 then submenu should remain unchanged. */
271 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
272 XtGetValues (children
[i
], al
, 1);
275 destroy_all_children (submenu
, 0);
276 XtDestroyWidget (submenu
);
278 XtDestroyWidget (children
[i
]);
281 XtFree ((char *) children
);
287 /* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
288 menu. CLIENT_DATA contains a pointer to the widget_value
289 corresponding to widget W. CALL_DATA contains a
290 XmPushButtonCallbackStruct containing the reason why the callback
294 xm_arm_callback (w
, client_data
, call_data
)
296 XtPointer client_data
, call_data
;
298 XmPushButtonCallbackStruct
*cbs
= (XmPushButtonCallbackStruct
*) call_data
;
299 widget_value
*wv
= (widget_value
*) client_data
;
300 widget_instance
*instance
;
302 /* Get the id of the menu bar or popup menu this widget is in. */
305 if (XmIsRowColumn (w
))
307 unsigned char type
= 0xff;
309 XtVaGetValues (w
, XmNrowColumnType
, &type
, NULL
);
310 if (type
== XmMENU_BAR
|| type
== XmMENU_POPUP
)
319 instance
= lw_get_widget_instance (w
);
320 if (instance
&& instance
->info
->highlight_cb
)
322 call_data
= cbs
->reason
== XmCR_DISARM
? NULL
: wv
;
323 instance
->info
->highlight_cb (w
, instance
->info
->id
, call_data
);
330 /* Update the label of widget WIDGET. WIDGET must be a Label widget
331 or a subclass of Label. WIDGET_INSTANCE is unused. VAL contains
336 Emacs fills VAL->name with the text to display in the menu, and
337 sets VAL->value to null. Function make_menu_in_widget creates
338 widgets with VAL->name as resource name. This works because the
339 Label widget uses its resource name for display if no
340 XmNlabelString is set.
344 VAL->name is again set to the resource name, but VAL->value is
345 not null, and contains the label string to display. */
348 xm_update_label (instance
, widget
, val
)
349 widget_instance
* instance
;
353 XmString res_string
= 0;
354 XmString built_string
= 0;
355 XmString key_string
= 0;
363 /* A label string is specified, i.e. we are in a dialog. First
364 see if it is overridden by something from the resource file. */
365 res_string
= resource_motif_string (widget
, val
->value
);
369 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
374 XmStringCreateLocalized (val
->value
);
375 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
378 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
383 key_string
= XmStringCreateLocalized (val
->key
);
384 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
388 XtSetValues (widget
, al
, ac
);
391 XmStringFree (built_string
);
394 XmStringFree (key_string
);
397 \f/* update of list */
399 xm_update_list (instance
, widget
, val
)
400 widget_instance
* instance
;
406 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
407 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
409 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
412 XmString xmstr
= XmStringCreateLocalized (cur
->value
);
414 XmListAddItem (widget
, xmstr
, 0);
416 XmListSelectPos (widget
, i
, False
);
417 XmStringFree (xmstr
);
421 \f/* update of buttons */
423 xm_update_pushbutton (instance
, widget
, val
)
424 widget_instance
* instance
;
428 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, NULL
);
429 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
430 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
434 xm_update_cascadebutton (instance
, widget
, val
)
435 widget_instance
* instance
;
439 /* Should also rebuild the menu by calling ...update_menu... */
440 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
441 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
445 \f/* update toggle and radiobox */
447 xm_update_toggle (instance
, widget
, val
)
448 widget_instance
* instance
;
452 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
453 XtAddCallback (widget
, XmNvalueChangedCallback
,
454 xm_generic_callback
, instance
);
455 XtVaSetValues (widget
, XmNset
, val
->selected
,
456 XmNalignment
, XmALIGNMENT_BEGINNING
, NULL
);
460 xm_update_radiobox (instance
, widget
, val
)
461 widget_instance
* instance
;
469 /* update the callback */
470 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
471 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
473 /* first update all the toggles */
474 /* Energize kernel interface is currently bad. It sets the selected widget
475 with the selected flag but returns it by its name. So we currently
476 have to support both setting the selection with the selected slot
477 of val contents and setting it with the "value" slot of val. The latter
478 has a higher priority. This to be removed when the kernel is fixed. */
479 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
481 toggle
= XtNameToWidget (widget
, cur
->value
);
484 XtSetSensitive (toggle
, cur
->enabled
);
485 if (!val
->value
&& cur
->selected
)
486 XtVaSetValues (toggle
, XmNset
, cur
->selected
, NULL
);
487 if (val
->value
&& strcmp (val
->value
, cur
->value
))
488 XtVaSetValues (toggle
, XmNset
, False
, NULL
);
492 /* The selected was specified by the value slot */
495 toggle
= XtNameToWidget (widget
, val
->value
);
497 XtVaSetValues (toggle
, XmNset
, True
, NULL
);
502 /* update a popup menu, pulldown menu or a menubar */
504 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
507 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
508 widget_instance
* instance
;
511 int keep_first_children
;
513 Widget
* children
= 0;
525 Widget
* old_children
;
526 unsigned int old_num_children
;
528 /* Disable drag and drop for labels in menu bar. */
529 static char overrideTrans
[] = "<Btn2Down>: Noop()";
530 XtTranslations override
= XtParseTranslationTable (overrideTrans
);
532 old_children
= XtCompositeChildren (widget
, &old_num_children
);
534 /* Allocate the children array */
535 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
)
537 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
539 /* WIDGET should be a RowColumn. */
540 if (!XmIsRowColumn (widget
))
543 /* Determine whether WIDGET is a menu bar. */
545 XtSetArg (al
[0], XmNrowColumnType
, &type
);
546 XtGetValues (widget
, al
, 1);
547 if (type
!= XmMENU_BAR
&& type
!= XmMENU_PULLDOWN
&& type
!= XmMENU_POPUP
)
549 menubar_p
= type
== XmMENU_BAR
;
551 /* Add a callback to popups and pulldowns that is called when
552 it is made invisible again. */
554 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
555 xm_pop_down_callback
, (XtPointer
)instance
);
557 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
558 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
559 child_index
++, cur
= cur
->next
)
560 children
[child_index
] = old_children
[child_index
];
562 /* Check that those are all we have
563 (the caller should have deleted the rest). */
564 if (old_num_children
!= keep_first_children
)
567 /* Create the rest. */
568 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
570 enum menu_separator separator
;
573 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
574 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
575 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
577 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
578 && !lw_separator_p (cur
->name
, &separator
, 1))
581 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
582 title
= button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
584 else if (lw_separator_p (cur
->name
, &separator
, 1))
587 XtSetArg (al
[ac
], XmNseparatorType
, separator
); ++ac
;
588 button
= XmCreateSeparator (widget
, cur
->name
, al
, ac
);
590 else if (!cur
->contents
)
593 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
594 else if (!cur
->call_data
)
595 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
596 else if (cur
->button_type
== BUTTON_TYPE_TOGGLE
597 || cur
->button_type
== BUTTON_TYPE_RADIO
)
599 XtSetArg (al
[ac
], XmNset
, cur
->selected
); ++ac
;
600 XtSetArg (al
[ac
], XmNvisibleWhenOff
, True
); ++ac
;
601 XtSetArg (al
[ac
], XmNindicatorType
,
602 (cur
->button_type
== BUTTON_TYPE_TOGGLE
603 ? XmN_OF_MANY
: XmONE_OF_MANY
));
605 button
= XmCreateToggleButton (widget
, cur
->name
, al
, ac
);
606 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
607 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
611 button
= XmCreatePushButton (widget
, cur
->name
, al
, ac
);
612 XtAddCallback (button
, XmNarmCallback
, xm_arm_callback
, cur
);
613 XtAddCallback (button
, XmNdisarmCallback
, xm_arm_callback
, cur
);
616 xm_update_label (instance
, button
, cur
);
618 /* Add a callback that is called when the button is
619 selected. Toggle buttons don't support
620 XmNactivateCallback, we use XmNvalueChangedCallback in
621 that case. Don't add a callback to a simple label. */
622 if (cur
->button_type
)
623 xm_update_toggle (instance
, button
, cur
);
624 else if (cur
->call_data
)
625 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
626 (XtPointer
)instance
);
630 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
632 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
633 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
634 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
636 xm_update_label (instance
, button
, cur
);
638 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
639 (XtPointer
)instance
);
640 XtOverrideTranslations (button
, override
);
644 children
[child_index
] = button
;
647 /* Last entry is the help button. The original comment read "Has to
648 be done after managing the buttons otherwise the menubar is only
649 4 pixels high." This is no longer true, and to make
650 XmNmenuHelpWidget work, we need to set it before managing the
651 children.. --gerd. */
653 XtVaSetValues (widget
, XmNmenuHelpWidget
, button
, NULL
);
656 XtManageChildren (children
, num_children
);
658 XtFree ((char *) children
);
660 XtFree ((char *) old_children
);
664 update_one_menu_entry (instance
, widget
, val
, deep_p
)
665 widget_instance
* instance
;
673 widget_value
* contents
;
675 if (val
->this_one_change
== NO_CHANGE
)
678 /* update the sensitivity and userdata */
679 /* Common to all widget types */
680 XtSetSensitive (widget
, val
->enabled
);
681 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
683 /* update the menu button as a label. */
684 if (val
->this_one_change
>= VISIBLE_CHANGE
)
686 xm_update_label (instance
, widget
, val
);
687 if (val
->button_type
)
688 xm_update_toggle (instance
, widget
, val
);
691 /* update the pulldown/pullaside as needed */
694 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
695 XtGetValues (widget
, al
, ac
);
697 contents
= val
->contents
;
703 unsigned int old_num_children
, i
;
707 parent
= XtParent (widget
);
708 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
710 /* Find the widget position within the parent's widget list. */
711 for (i
= 0; i
< old_num_children
; i
++)
712 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
714 if (i
== old_num_children
)
716 if (XmIsCascadeButton (widget_list
[i
]))
718 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
719 make_menu_in_widget (instance
, menu
, contents
, 0);
721 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
722 XtSetValues (widget
, al
, ac
);
728 /* The current menuitem is a XmPushButtonGadget, it
729 needs to be replaced by a CascadeButtonGadget */
730 XtDestroyWidget (widget_list
[i
]);
731 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
732 make_menu_in_widget (instance
, menu
, contents
, 0);
734 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
735 /* Non-zero values don't work reliably in
736 conjunction with Emacs' event loop */
737 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
738 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
739 /* Tell Motif to put it in the right place */
740 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
742 button
= XmCreateCascadeButton (parent
, val
->name
, al
, ac
);
743 xm_update_label (instance
, button
, val
);
745 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
746 (XtPointer
)instance
);
747 XtManageChild (button
);
751 XtFree ((char*) widget_list
);
757 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
758 XtSetValues (widget
, al
, ac
);
759 XtDestroyWidget (menu
);
761 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
762 xm_update_menu (instance
, menu
, val
, 1);
766 xm_update_menu (instance
, widget
, val
, deep_p
)
767 widget_instance
* instance
;
773 unsigned int num_children
;
774 int num_children_to_keep
= 0;
778 children
= XtCompositeChildren (widget
, &num_children
);
780 /* Widget is a RowColumn widget whose contents have to be updated
781 * to reflect the list of items in val->contents */
783 /* See how many buttons we can keep, and how many we
784 must completely replace. */
785 if (val
->contents
== 0)
786 num_children_to_keep
= 0;
787 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
791 for (i
= 0, cur
= val
->contents
;
793 && cur
); /* how else to ditch unwanted children ?? - mgd */
794 i
++, cur
= cur
->next
)
796 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
800 num_children_to_keep
= i
;
804 num_children_to_keep
= num_children
;
806 /* Update all the buttons of the RowColumn, in order,
807 except for those we are going to replace entirely. */
810 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
814 num_children_to_keep
= i
;
817 if (children
[i
]->core
.being_destroyed
818 || strcmp (XtName (children
[i
]), cur
->name
))
820 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
825 /* Now replace from scratch all the buttons after the last
826 place that the top-level structure changed. */
827 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
829 destroy_all_children (widget
, num_children_to_keep
);
830 make_menu_in_widget (instance
, widget
, val
->contents
,
831 num_children_to_keep
);
834 XtFree ((char *) children
);
838 /* update text widgets */
841 xm_update_text (instance
, widget
, val
)
842 widget_instance
* instance
;
846 XmTextSetString (widget
, val
->value
? val
->value
: "");
847 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
848 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
849 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
850 XtAddCallback (widget
, XmNvalueChangedCallback
,
851 xm_internal_update_other_instances
, instance
);
855 xm_update_text_field (instance
, widget
, val
)
856 widget_instance
* instance
;
860 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
861 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
862 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
863 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
864 XtAddCallback (widget
, XmNvalueChangedCallback
,
865 xm_internal_update_other_instances
, instance
);
869 /* update a motif widget */
872 xm_update_one_widget (instance
, widget
, val
, deep_p
)
873 widget_instance
* instance
;
880 /* Mark as not edited */
883 /* Common to all widget types */
884 XtSetSensitive (widget
, val
->enabled
);
885 XtVaSetValues (widget
, XmNuserData
, val
->call_data
, NULL
);
887 /* Common to all label like widgets */
888 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
889 xm_update_label (instance
, widget
, val
);
891 class = XtClass (widget
);
892 /* Class specific things */
893 if (class == xmPushButtonWidgetClass
||
894 class == xmArrowButtonWidgetClass
)
896 xm_update_pushbutton (instance
, widget
, val
);
898 else if (class == xmCascadeButtonWidgetClass
)
900 xm_update_cascadebutton (instance
, widget
, val
);
902 else if (class == xmToggleButtonWidgetClass
903 || class == xmToggleButtonGadgetClass
)
905 xm_update_toggle (instance
, widget
, val
);
907 else if (class == xmRowColumnWidgetClass
)
909 Boolean radiobox
= 0;
913 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
914 XtGetValues (widget
, al
, ac
);
917 xm_update_radiobox (instance
, widget
, val
);
919 xm_update_menu (instance
, widget
, val
, deep_p
);
921 else if (class == xmTextWidgetClass
)
923 xm_update_text (instance
, widget
, val
);
925 else if (class == xmTextFieldWidgetClass
)
927 xm_update_text_field (instance
, widget
, val
);
929 else if (class == xmListWidgetClass
)
931 xm_update_list (instance
, widget
, val
);
935 \f/* getting the value back */
937 xm_update_one_value (instance
, widget
, val
)
938 widget_instance
* instance
;
942 WidgetClass
class = XtClass (widget
);
943 widget_value
*old_wv
;
945 /* copy the call_data slot into the "return" widget_value */
946 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
947 if (!strcmp (val
->name
, old_wv
->name
))
949 val
->call_data
= old_wv
->call_data
;
953 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
955 XtVaGetValues (widget
, XmNset
, &val
->selected
, NULL
);
958 else if (class == xmTextWidgetClass
)
961 val
->value
= XmTextGetString (widget
);
964 else if (class == xmTextFieldWidgetClass
)
967 val
->value
= XmTextFieldGetString (widget
);
970 else if (class == xmRowColumnWidgetClass
)
972 Boolean radiobox
= 0;
976 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
977 XtGetValues (widget
, al
, ac
);
981 CompositeWidget radio
= (CompositeWidget
)widget
;
983 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
986 Widget toggle
= radio
->composite
.children
[i
];
988 XtVaGetValues (toggle
, XmNset
, &set
, NULL
);
992 val
->value
= safe_strdup (XtName (toggle
));
998 else if (class == xmListWidgetClass
)
1002 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
1006 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
1010 cur
->selected
= False
;
1012 for (j
= 0; j
< pos_cnt
; j
++)
1013 if (pos_list
[j
] == i
)
1015 cur
->selected
= True
;
1016 val
->value
= safe_strdup (cur
->name
);
1020 XtFree ((char *) pos_list
);
1026 /* This function is for activating a button from a program. It's wrong because
1027 we pass a NULL argument in the call_data which is not Motif compatible.
1028 This is used from the XmNdefaultAction callback of the List widgets to
1029 have a double-click put down a dialog box like the button would do.
1030 I could not find a way to do that with accelerators.
1033 activate_button (widget
, closure
, call_data
)
1036 XtPointer call_data
;
1038 Widget button
= (Widget
)closure
;
1039 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
1042 /* creation functions */
1044 /* Called for key press in dialogs. Used to pop down dialog on ESC. */
1046 dialog_key_cb (widget
, closure
, event
, continue_to_dispatch
)
1050 Boolean
*continue_to_dispatch
;
1053 Modifiers modif_ret
;
1055 XtTranslateKeycode (event
->xkey
.display
, event
->xkey
.keycode
, 0,
1058 if (sym
== osfXK_Cancel
)
1060 Widget w
= *((Widget
*) closure
);
1062 while (w
&& ! XtIsShell (w
))
1065 if (XtIsShell (w
)) XtPopdown (w
);
1068 *continue_to_dispatch
= TRUE
;
1073 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
1074 radio_box
, list
, left_buttons
, right_buttons
)
1080 Boolean text_input_slot
;
1090 Widget icon_separator
;
1095 Widget children
[16]; /* for the final XtManageChildren */
1097 Arg al
[64]; /* Arg List */
1098 int ac
; /* Arg Count */
1104 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
1105 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
1106 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
1107 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
1109 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1110 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
1111 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1112 form
= XmCreateForm (result
, shell_title
, al
, ac
);
1117 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
1118 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1119 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
1123 n_children
= left_buttons
+ right_buttons
+ 1;
1125 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
1126 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
1127 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
1128 XmVERTICAL
: XmHORIZONTAL
); ac
++;
1129 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
1130 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1131 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1132 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1133 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
1134 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1135 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
1136 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1137 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
1138 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1139 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1140 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1141 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1142 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1143 row
= XmCreateRowColumn (form
, "row", al
, ac
);
1146 for (i
= 0; i
< left_buttons
; i
++)
1148 char button_name
[16];
1149 sprintf (button_name
, "button%d", i
+ 1);
1153 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
1154 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
1156 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1157 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1158 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1159 XtAddEventHandler (children
[n_children
],
1160 KeyPressMask
, False
, dialog_key_cb
, result
);
1164 button
= children
[n_children
];
1166 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
1167 XtSetValues (row
, al
, ac
);
1173 /* invisible separator button */
1175 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1176 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
1179 for (i
= 0; i
< right_buttons
; i
++)
1181 char button_name
[16];
1182 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
1184 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
1185 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
1186 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
1187 XtAddEventHandler (children
[n_children
],
1188 KeyPressMask
, False
, dialog_key_cb
, result
);
1190 if (! button
) button
= children
[n_children
];
1194 XtManageChildren (children
, n_children
);
1197 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1198 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1199 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1200 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
1201 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1202 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
1203 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1204 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
1205 separator
= XmCreateSeparator (form
, "", al
, ac
);
1208 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
1209 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1210 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1211 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
1212 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
1213 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1214 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1215 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
1218 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
1219 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
1220 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1221 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1222 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1223 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1224 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1225 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1226 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1227 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1229 if (text_input_slot
)
1232 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1233 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1234 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1235 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1236 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1237 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1238 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1239 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1240 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1241 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1242 value
= XmCreateTextField (form
, "value", al
, ac
);
1248 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1249 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1250 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1251 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1252 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1253 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1254 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1255 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1256 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1257 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1258 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1259 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1260 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1261 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1264 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1265 children
[i
++] = radio_butt
;
1266 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1267 children
[i
++] = radio_butt
;
1268 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1269 children
[i
++] = radio_butt
;
1270 XtManageChildren (children
, i
);
1275 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1276 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1277 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1278 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1279 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1280 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1281 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1282 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1283 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1284 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1285 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1287 /* this is the easiest way I found to have the dble click in the
1288 list activate the default button */
1289 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1293 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1294 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1295 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1296 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1297 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1298 XtSetArg(al
[ac
], XmNbottomWidget
,
1299 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1300 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1301 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1302 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1303 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1304 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1305 message
= XmCreateLabel (form
, "message", al
, ac
);
1308 XtManageChild (value
);
1311 children
[i
] = row
; i
++;
1312 children
[i
] = separator
; i
++;
1313 if (text_input_slot
|| radio_box
)
1315 children
[i
] = value
; i
++;
1317 children
[i
] = message
; i
++;
1318 children
[i
] = icon
; i
++;
1319 children
[i
] = icon_separator
; i
++;
1320 XtManageChildren (children
, i
);
1322 if (text_input_slot
|| list
)
1324 XtInstallAccelerators (value
, button
);
1325 XtSetKeyboardFocus (result
, value
);
1329 XtInstallAccelerators (form
, button
);
1330 XtSetKeyboardFocus (result
, button
);
1336 static destroyed_instance
*
1337 find_matching_instance (instance
)
1338 widget_instance
* instance
;
1340 destroyed_instance
* cur
;
1341 destroyed_instance
* prev
;
1342 char* type
= instance
->info
->type
;
1343 char* name
= instance
->info
->name
;
1345 for (prev
= NULL
, cur
= all_destroyed_instances
;
1347 prev
= cur
, cur
= cur
->next
)
1349 if (!strcmp (cur
->name
, name
)
1350 && !strcmp (cur
->type
, type
)
1351 && cur
->parent
== instance
->parent
1352 && cur
->pop_up_p
== instance
->pop_up_p
)
1355 prev
->next
= cur
->next
;
1357 all_destroyed_instances
= cur
->next
;
1360 /* do some cleanup */
1361 else if (!cur
->widget
)
1364 prev
->next
= cur
->next
;
1366 all_destroyed_instances
= cur
->next
;
1367 free_destroyed_instance (cur
);
1368 cur
= prev
? prev
: all_destroyed_instances
;
1375 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1378 XtPointer call_data
;
1380 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1381 instance
->widget
= NULL
;
1385 recenter_widget (widget
)
1388 Widget parent
= XtParent (widget
);
1389 Screen
* screen
= XtScreen (widget
);
1390 Dimension screen_width
= WidthOfScreen (screen
);
1391 Dimension screen_height
= HeightOfScreen (screen
);
1392 Dimension parent_width
= 0;
1393 Dimension parent_height
= 0;
1394 Dimension child_width
= 0;
1395 Dimension child_height
= 0;
1399 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, NULL
);
1400 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1403 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1404 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1406 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1408 if (x
+ child_width
> screen_width
)
1409 x
= screen_width
- child_width
;
1413 if (y
+ child_height
> screen_height
)
1414 y
= screen_height
- child_height
;
1418 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, NULL
);
1422 recycle_instance (instance
)
1423 destroyed_instance
* instance
;
1425 Widget widget
= instance
->widget
;
1427 /* widget is NULL if the parent was destroyed. */
1433 /* Remove the destroy callback as the instance is not in the list
1435 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1436 mark_dead_instance_destroyed
,
1437 (XtPointer
)instance
);
1439 /* Give the focus to the initial item */
1440 focus
= XtNameToWidget (widget
, "*value");
1442 focus
= XtNameToWidget (widget
, "*button1");
1444 XtSetKeyboardFocus (widget
, focus
);
1446 /* shrink the separator label back to their original size */
1447 separator
= XtNameToWidget (widget
, "*separator_button");
1449 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, NULL
);
1451 /* Center the dialog in its parent */
1452 recenter_widget (widget
);
1454 free_destroyed_instance (instance
);
1459 xm_create_dialog (instance
)
1460 widget_instance
* instance
;
1462 char* name
= instance
->info
->type
;
1463 Widget parent
= instance
->parent
;
1465 Boolean pop_up_p
= instance
->pop_up_p
;
1466 char* shell_name
= 0;
1467 char* icon_name
= 0;
1468 Boolean text_input_slot
= False
;
1469 Boolean radio_box
= False
;
1470 Boolean list
= False
;
1472 int left_buttons
= 0;
1473 int right_buttons
= 1;
1474 destroyed_instance
* dead_one
;
1476 /* try to find a widget to recycle */
1477 dead_one
= find_matching_instance (instance
);
1480 Widget recycled_widget
= recycle_instance (dead_one
);
1481 if (recycled_widget
)
1482 return recycled_widget
;
1487 icon_name
= "dbox-error";
1488 shell_name
= "Error";
1492 icon_name
= "dbox-info";
1493 shell_name
= "Information";
1498 icon_name
= "dbox-question";
1499 shell_name
= "Prompt";
1503 text_input_slot
= True
;
1504 icon_name
= "dbox-question";
1505 shell_name
= "Prompt";
1509 icon_name
= "dbox-question";
1510 shell_name
= "Question";
1514 total_buttons
= name
[1] - '0';
1516 if (name
[3] == 'T' || name
[3] == 't')
1518 text_input_slot
= False
;
1522 right_buttons
= name
[4] - '0';
1524 left_buttons
= total_buttons
- right_buttons
;
1526 widget
= make_dialog (name
, parent
, pop_up_p
,
1527 shell_name
, icon_name
, text_input_slot
, radio_box
,
1528 list
, left_buttons
, right_buttons
);
1530 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1531 (XtPointer
) instance
);
1536 /* Create a menu bar. We turn off the f10 key
1537 because we have not yet managed to make it work right in Motif. */
1540 make_menubar (instance
)
1541 widget_instance
* instance
;
1547 XtSetArg(al
[ac
], XmNmenuAccelerator
, 0); ++ac
;
1548 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, ac
);
1552 remove_grabs (shell
, closure
, call_data
)
1555 XtPointer call_data
;
1557 Widget menu
= (Widget
) closure
;
1558 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1562 make_popup_menu (instance
)
1563 widget_instance
* instance
;
1565 Widget parent
= instance
->parent
;
1566 Window parent_window
= parent
->core
.window
;
1569 /* sets the parent window to 0 to fool Motif into not generating a grab */
1570 parent
->core
.window
= 0;
1571 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1572 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1574 parent
->core
.window
= parent_window
;
1579 make_main (instance
)
1580 widget_instance
* instance
;
1582 Widget parent
= instance
->parent
;
1588 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1589 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1590 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1594 \f/* Table of functions to create widgets */
1598 /* interface with the XDesigner generated functions */
1599 typedef Widget (*widget_maker
) (Widget
);
1600 extern Widget
create_project_p_sheet (Widget parent
);
1601 extern Widget
create_debugger_p_sheet (Widget parent
);
1602 extern Widget
create_breaklist_p_sheet (Widget parent
);
1603 extern Widget
create_le_browser_p_sheet (Widget parent
);
1604 extern Widget
create_class_browser_p_sheet (Widget parent
);
1605 extern Widget
create_call_browser_p_sheet (Widget parent
);
1606 extern Widget
create_build_dialog (Widget parent
);
1607 extern Widget
create_editmode_dialog (Widget parent
);
1608 extern Widget
create_search_dialog (Widget parent
);
1609 extern Widget
create_project_display_dialog (Widget parent
);
1612 make_one (widget_instance
* instance
, widget_maker fn
)
1618 if (instance
->pop_up_p
)
1620 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1621 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1622 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1623 (XtPointer
) instance
);
1628 result
= (*fn
) (instance
->parent
);
1629 XtRealizeWidget (result
);
1635 make_project_p_sheet (widget_instance
* instance
)
1637 return make_one (instance
, create_project_p_sheet
);
1641 make_debugger_p_sheet (widget_instance
* instance
)
1643 return make_one (instance
, create_debugger_p_sheet
);
1647 make_breaklist_p_sheet (widget_instance
* instance
)
1649 return make_one (instance
, create_breaklist_p_sheet
);
1653 make_le_browser_p_sheet (widget_instance
* instance
)
1655 return make_one (instance
, create_le_browser_p_sheet
);
1659 make_class_browser_p_sheet (widget_instance
* instance
)
1661 return make_one (instance
, create_class_browser_p_sheet
);
1665 make_call_browser_p_sheet (widget_instance
* instance
)
1667 return make_one (instance
, create_call_browser_p_sheet
);
1671 make_build_dialog (widget_instance
* instance
)
1673 return make_one (instance
, create_build_dialog
);
1677 make_editmode_dialog (widget_instance
* instance
)
1679 return make_one (instance
, create_editmode_dialog
);
1683 make_search_dialog (widget_instance
* instance
)
1685 return make_one (instance
, create_search_dialog
);
1689 make_project_display_dialog (widget_instance
* instance
)
1691 return make_one (instance
, create_project_display_dialog
);
1694 #endif /* ENERGIZE */
1696 widget_creation_entry
1697 xm_creation_table
[] =
1699 {"menubar", make_menubar
},
1700 {"popup", make_popup_menu
},
1701 {"main", make_main
},
1703 {"project_p_sheet", make_project_p_sheet
},
1704 {"debugger_p_sheet", make_debugger_p_sheet
},
1705 {"breaklist_psheet", make_breaklist_p_sheet
},
1706 {"leb_psheet", make_le_browser_p_sheet
},
1707 {"class_browser_psheet", make_class_browser_p_sheet
},
1708 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1709 {"build", make_build_dialog
},
1710 {"editmode", make_editmode_dialog
},
1711 {"search", make_search_dialog
},
1712 {"project_display", make_project_display_dialog
},
1713 #endif /* ENERGIZE */
1717 \f/* Destruction of instances */
1719 xm_destroy_instance (instance
)
1720 widget_instance
* instance
;
1722 Widget widget
= instance
->widget
;
1723 /* recycle the dialog boxes */
1724 /* Disable the recycling until we can find a way to have the dialog box
1725 get reasonable layout after we modify its contents. */
1727 && XtClass (widget
) == xmDialogShellWidgetClass
)
1729 destroyed_instance
* dead_instance
=
1730 make_destroyed_instance (instance
->info
->name
,
1731 instance
->info
->type
,
1734 instance
->pop_up_p
);
1735 dead_instance
->next
= all_destroyed_instances
;
1736 all_destroyed_instances
= dead_instance
;
1737 XtUnmanageChild (first_child (instance
->widget
));
1738 XFlush (XtDisplay (instance
->widget
));
1739 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1740 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1744 /* This might not be necessary now that the nosel is attached to
1745 popdown instead of destroy, but it can't hurt. */
1746 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1747 xm_nosel_callback
, (XtPointer
)instance
);
1748 XtDestroyWidget (instance
->widget
);
1752 \f/* popup utility */
1754 xm_popup_menu (widget
, event
)
1758 XButtonPressedEvent dummy
;
1762 dummy
.type
= ButtonPress
;
1764 dummy
.send_event
= 0;
1765 dummy
.display
= XtDisplay (widget
);
1766 dummy
.window
= XtWindow (XtParent (widget
));
1769 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1770 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1771 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1772 event
= (XEvent
*) &dummy
;
1775 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1777 /* Setting the menuPost resource only required by Motif 1.1 and
1778 LessTif 0.84 and earlier. With later versions of LessTif,
1779 setting menuPost is unnecessary and may cause problems, so
1781 #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
1783 /* This is so totally ridiculous: there's NO WAY to tell Motif
1784 that *any* button can select a menu item. Only one button
1785 can have that honor. */
1788 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1789 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1790 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1791 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1792 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1793 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, NULL
);
1797 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1800 XtManageChild (widget
);
1804 set_min_dialog_size (w
)
1809 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, NULL
);
1810 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, NULL
);
1814 xm_pop_instance (instance
, up
)
1815 widget_instance
* instance
;
1818 Widget widget
= instance
->widget
;
1820 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1822 Widget widget_to_manage
= first_child (widget
);
1825 XtManageChild (widget_to_manage
);
1826 set_min_dialog_size (widget
);
1827 XtSetKeyboardFocus (instance
->parent
, widget
);
1830 XtUnmanageChild (widget_to_manage
);
1835 XtManageChild (widget
);
1837 XtUnmanageChild (widget
);
1842 /* motif callback */
1845 do_call (widget
, closure
, type
)
1848 enum do_call_type type
;
1852 XtPointer user_data
;
1853 widget_instance
* instance
= (widget_instance
*)closure
;
1854 Widget instance_widget
;
1859 if (widget
->core
.being_destroyed
)
1862 instance_widget
= instance
->widget
;
1863 if (!instance_widget
)
1866 id
= instance
->info
->id
;
1869 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1870 XtGetValues (widget
, al
, ac
);
1875 if (instance
->info
->pre_activate_cb
)
1876 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1880 if (instance
->info
->selection_cb
)
1881 instance
->info
->selection_cb (widget
, id
, user_data
);
1885 if (instance
->info
->selection_cb
)
1886 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1890 if (instance
->info
->post_activate_cb
)
1891 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1899 /* Like lw_internal_update_other_instances except that it does not do
1900 anything if its shell parent is not managed. This is to protect
1901 lw_internal_update_other_instances to dereference freed memory
1902 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1905 xm_internal_update_other_instances (widget
, closure
, call_data
)
1908 XtPointer call_data
;
1911 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1912 if (XtIsShell (parent
))
1914 else if (!XtIsManaged (parent
))
1916 lw_internal_update_other_instances (widget
, closure
, call_data
);
1920 xm_generic_callback (widget
, closure
, call_data
)
1923 XtPointer call_data
;
1925 lw_internal_update_other_instances (widget
, closure
, call_data
);
1926 do_call (widget
, closure
, selection
);
1930 xm_nosel_callback (widget
, closure
, call_data
)
1933 XtPointer call_data
;
1935 /* This callback is only called when a dialog box is dismissed with
1936 the wm's destroy button (WM_DELETE_WINDOW.) We want the dialog
1937 box to be destroyed in that case, not just unmapped, so that it
1938 releases its keyboard grabs. But there are problems with running
1939 our callbacks while the widget is in the process of being
1940 destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
1941 XmDESTROY and then destroy it ourself after having run the
1943 do_call (widget
, closure
, no_selection
);
1944 XtDestroyWidget (widget
);
1948 xm_pull_down_callback (widget
, closure
, call_data
)
1951 XtPointer call_data
;
1953 Widget parent
= XtParent (widget
);
1955 if (XmIsRowColumn (parent
))
1957 unsigned char type
= 0xff;
1958 XtVaGetValues (parent
, XmNrowColumnType
, &type
, NULL
);
1959 if (type
== XmMENU_BAR
)
1960 do_call (widget
, closure
, pre_activate
);
1965 /* XmNpopdownCallback for MenuShell widgets. WIDGET is the MenuShell,
1966 CLOSURE is a pointer to the widget_instance of the shell,
1968 Note that this callback is called for each cascade button in a
1969 menu, whether or not its submenu is visible. */
1972 xm_pop_down_callback (widget
, closure
, call_data
)
1975 XtPointer call_data
;
1977 widget_instance
*instance
= (widget_instance
*) closure
;
1979 if ((!instance
->pop_up_p
&& XtParent (widget
) == instance
->widget
)
1980 || XtParent (widget
) == instance
->parent
)
1981 do_call (widget
, closure
, post_activate
);
1985 /* set the keyboard focus */
1987 xm_set_keyboard_focus (parent
, w
)
1991 XmProcessTraversal (w
, 0);
1992 XtSetKeyboardFocus (parent
, w
);
1995 /* Motif hack to set the main window areas. */
1997 xm_set_main_areas (parent
, menubar
, work_area
)
2002 XmMainWindowSetAreas (parent
,
2003 menubar
, /* menubar (maybe 0) */
2004 0, /* command area (psheets) */
2005 0, /* horizontal scroll */
2006 0, /* vertical scroll */
2007 work_area
); /* work area */
2010 /* Motif hack to control resizing on the menubar. */
2012 xm_manage_resizing (w
, flag
)
2016 XtVaSetValues (w
, XtNallowShellResize
, flag
, NULL
);
2019 /* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
2020 (do not change this comment) */