1 /* The lwlib interface to Motif widgets.
2 Copyright (C) 1992 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
26 #include <X11/StringDefs.h>
27 #include <X11/IntrinsicP.h>
28 #include <X11/ObjectP.h>
29 #include <X11/CoreP.h>
30 #include <X11/CompositeP.h>
33 #include "lwlib-utils.h"
35 #include <Xm/BulletinB.h>
36 #include <Xm/CascadeB.h>
37 #include <Xm/CascadeBG.h>
38 #include <Xm/DrawingA.h>
39 #include <Xm/FileSB.h>
43 #include <Xm/MenuShell.h>
44 #include <Xm/MessageB.h>
45 #include <Xm/PanedW.h>
47 #include <Xm/PushBG.h>
48 #include <Xm/ArrowB.h>
49 #include <Xm/SelectioB.h>
52 #include <Xm/ToggleB.h>
53 #include <Xm/ToggleBG.h>
54 #include <Xm/RowColumn.h>
55 #include <Xm/ScrolledW.h>
56 #include <Xm/Separator.h>
57 #include <Xm/DialogS.h>
60 static void xm_pull_down_callback (/* Widget, XtPointer, XtPointer */);
61 static void xm_internal_update_other_instances (/* Widget, XtPointer,
63 static void xm_generic_callback (/* Widget, XtPointer, XtPointer */);
64 static void xm_nosel_callback (/* Widget, XtPointer, XtPointer */);
65 static void xm_pop_down_callback (/* Widget, XtPointer, XtPointer */);
67 static void xm_update_menu (/* widget_instance*, Widget, widget_value*,
71 \f/* Structures to keep destroyed instances */
72 typedef struct _destroyed_instance
79 struct _destroyed_instance
* next
;
82 static destroyed_instance
*
83 all_destroyed_instances
= NULL
;
85 static destroyed_instance
*
86 make_destroyed_instance (name
, type
, widget
, parent
, pop_up_p
)
93 destroyed_instance
* instance
=
94 (destroyed_instance
*)malloc (sizeof (destroyed_instance
));
95 instance
->name
= safe_strdup (name
);
96 instance
->type
= safe_strdup (type
);
97 instance
->widget
= widget
;
98 instance
->parent
= parent
;
99 instance
->pop_up_p
= pop_up_p
;
100 instance
->next
= NULL
;
105 free_destroyed_instance (instance
)
106 destroyed_instance
* instance
;
108 free (instance
->name
);
109 free (instance
->type
);
113 \f/* motif utility functions */
118 return ((CompositeWidget
)widget
)->composite
.children
[0];
122 lw_motif_widget_p (widget
)
126 XtClass (widget
) == xmDialogShellWidgetClass
127 || XmIsPrimitive (widget
) || XmIsManager (widget
) || XmIsGadget (widget
);
131 resource_motif_string (widget
, name
)
138 resource
.resource_name
= name
;
139 resource
.resource_class
= XmCXmString
;
140 resource
.resource_type
= XmRXmString
;
141 resource
.resource_size
= sizeof (XmString
);
142 resource
.resource_offset
= 0;
143 resource
.default_type
= XtRImmediate
;
144 resource
.default_addr
= 0;
146 XtGetSubresources (widget
, (XtPointer
)&result
, "dialogString",
147 "DialogString", &resource
, 1, NULL
, 0);
151 /* Destroy all of the children of WIDGET
152 starting with number FIRST_CHILD_TO_DESTROY. */
155 destroy_all_children (widget
, first_child_to_destroy
)
157 int first_child_to_destroy
;
163 children
= XtCompositeChildren (widget
, &number
);
166 XtUnmanageChildren (children
+ first_child_to_destroy
,
167 number
- first_child_to_destroy
);
169 /* Unmanage all children and destroy them. They will only be
170 really destroyed when we get out of DispatchEvent. */
171 for (i
= first_child_to_destroy
; i
< number
; i
++)
175 /* Cascade buttons have submenus,and these submenus
176 need to be freed. But they are not included in
177 XtCompositeChildren. So get it out of the cascade button
178 and free it. If this child is not a cascade button,
179 then submenu should remain unchanged. */
180 XtSetArg (al
[0], XmNsubMenuId
, &submenu
);
181 XtGetValues (children
[i
], al
, 1);
183 XtDestroyWidget (submenu
);
184 XtDestroyWidget (children
[i
]);
187 XtFree ((char *) children
);
191 \f/* update the label of anything subclass of a label */
193 xm_update_label (instance
, widget
, val
)
194 widget_instance
* instance
;
198 XmString res_string
= 0;
199 XmString built_string
= 0;
200 XmString key_string
= 0;
208 res_string
= resource_motif_string (widget
, val
->value
);
212 XtSetArg (al
[ac
], XmNlabelString
, res_string
); ac
++;
217 XmStringCreateLtoR (val
->value
, XmSTRING_DEFAULT_CHARSET
);
218 XtSetArg (al
[ac
], XmNlabelString
, built_string
); ac
++;
220 XtSetArg (al
[ac
], XmNlabelType
, XmSTRING
); ac
++;
225 key_string
= XmStringCreateLtoR (val
->key
, XmSTRING_DEFAULT_CHARSET
);
226 XtSetArg (al
[ac
], XmNacceleratorText
, key_string
); ac
++;
230 XtSetValues (widget
, al
, ac
);
233 XmStringFree (built_string
);
236 XmStringFree (key_string
);
239 \f/* update of list */
241 xm_update_list (instance
, widget
, val
)
242 widget_instance
* instance
;
248 XtRemoveAllCallbacks (widget
, XmNsingleSelectionCallback
);
249 XtAddCallback (widget
, XmNsingleSelectionCallback
, xm_generic_callback
,
251 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
254 XmString xmstr
= XmStringCreate (cur
->value
, XmSTRING_DEFAULT_CHARSET
);
256 XmListAddItem (widget
, xmstr
, 0);
258 XmListSelectPos (widget
, i
, False
);
259 XmStringFree (xmstr
);
263 \f/* update of buttons */
265 xm_update_pushbutton (instance
, widget
, val
)
266 widget_instance
* instance
;
270 XtVaSetValues (widget
, XmNalignment
, XmALIGNMENT_CENTER
, 0);
271 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
272 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
276 xm_update_cascadebutton (instance
, widget
, val
)
277 widget_instance
* instance
;
281 /* Should also rebuild the menu by calling ...update_menu... */
282 XtRemoveAllCallbacks (widget
, XmNcascadingCallback
);
283 XtAddCallback (widget
, XmNcascadingCallback
, xm_pull_down_callback
,
287 \f/* update toggle and radiobox */
289 xm_update_toggle (instance
, widget
, val
)
290 widget_instance
* instance
;
294 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
295 XtAddCallback (widget
, XmNvalueChangedCallback
,
296 xm_internal_update_other_instances
, instance
);
297 XtVaSetValues (widget
, XmNset
, val
->selected
,
298 XmNalignment
, XmALIGNMENT_BEGINNING
, 0);
302 xm_update_radiobox (instance
, widget
, val
)
303 widget_instance
* instance
;
311 /* update the callback */
312 XtRemoveAllCallbacks (widget
, XmNentryCallback
);
313 XtAddCallback (widget
, XmNentryCallback
, xm_generic_callback
, instance
);
315 /* first update all the toggles */
316 /* Energize kernel interface is currently bad. It sets the selected widget
317 with the selected flag but returns it by its name. So we currently
318 have to support both setting the selection with the selected slot
319 of val contents and setting it with the "value" slot of val. The latter
320 has a higher priority. This to be removed when the kernel is fixed. */
321 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
323 toggle
= XtNameToWidget (widget
, cur
->value
);
326 XtVaSetValues (toggle
, XmNsensitive
, cur
->enabled
, 0);
327 if (!val
->value
&& cur
->selected
)
328 XtVaSetValues (toggle
, XmNset
, cur
->selected
, 0);
329 if (val
->value
&& strcmp (val
->value
, cur
->value
))
330 XtVaSetValues (toggle
, XmNset
, False
, 0);
334 /* The selected was specified by the value slot */
337 toggle
= XtNameToWidget (widget
, val
->value
);
339 XtVaSetValues (toggle
, XmNset
, True
, 0);
343 \f/* update a popup menu, pulldown menu or a menubar */
355 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep. */
358 make_menu_in_widget (instance
, widget
, val
, keep_first_children
)
359 widget_instance
* instance
;
362 int keep_first_children
;
364 Widget
* children
= 0;
374 Widget
* old_children
;
375 unsigned int old_num_children
;
377 old_children
= XtCompositeChildren (widget
, &old_num_children
);
379 /* Allocate the children array */
380 for (num_children
= 0, cur
= val
; cur
; num_children
++, cur
= cur
->next
);
381 children
= (Widget
*)XtMalloc (num_children
* sizeof (Widget
));
383 /* tricky way to know if this RowColumn is a menubar or a pulldown... */
385 XtSetArg (al
[0], XmNisHomogeneous
, &menubar_p
);
386 XtGetValues (widget
, al
, 1);
388 /* add the unmap callback for popups and pulldowns */
389 /*** this sounds bogus ***/
391 XtAddCallback (XtParent (widget
), XmNpopdownCallback
,
392 xm_pop_down_callback
, (XtPointer
)instance
);
394 /* Preserve the first KEEP_FIRST_CHILDREN old children. */
395 for (child_index
= 0, cur
= val
; child_index
< keep_first_children
;
396 child_index
++, cur
= cur
->next
)
397 children
[child_index
] = old_children
[child_index
];
399 /* Check that those are all we have
400 (the caller should have deleted the rest). */
401 if (old_num_children
!= keep_first_children
)
404 /* Create the rest. */
405 for (child_index
= keep_first_children
; cur
; child_index
++, cur
= cur
->next
)
408 XtSetArg (al
[ac
], XmNsensitive
, cur
->enabled
); ac
++;
409 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
410 XtSetArg (al
[ac
], XmNuserData
, cur
->call_data
); ac
++;
412 if (instance
->pop_up_p
&& !cur
->contents
&& !cur
->call_data
413 && !all_dashes_p (cur
->name
))
416 XtSetArg (al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
417 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
419 else if (all_dashes_p (cur
->name
))
421 button
= XmCreateSeparator (widget
, cur
->name
, NULL
, 0);
423 else if (!cur
->contents
)
426 button
= XmCreateCascadeButton (widget
, cur
->name
, al
, ac
);
427 else if (!cur
->call_data
)
428 button
= XmCreateLabel (widget
, cur
->name
, al
, ac
);
430 button
= XmCreatePushButtonGadget (widget
, cur
->name
, al
, ac
);
432 xm_update_label (instance
, button
, cur
);
434 /* don't add a callback to a simple label */
436 XtAddCallback (button
, XmNactivateCallback
, xm_generic_callback
,
437 (XtPointer
)instance
);
441 menu
= XmCreatePulldownMenu (widget
, cur
->name
, NULL
, 0);
442 make_menu_in_widget (instance
, menu
, cur
->contents
, 0);
443 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
444 /* non-zero values don't work reliably in
445 conjunction with Emacs' event loop */
446 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
447 button
= XmCreateCascadeButtonGadget (widget
, cur
->name
, al
, ac
);
449 xm_update_label (instance
, button
, cur
);
451 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
452 (XtPointer
)instance
);
455 children
[child_index
] = button
;
458 XtManageChildren (children
, num_children
);
460 /* Last entry is the help button. Has to be done after managing
461 * the buttons otherwise the menubar is only 4 pixels high... */
465 XtSetArg (al
[ac
], XmNmenuHelpWidget
, button
); ac
++;
466 XtSetValues (widget
, al
, ac
);
469 XtFree ((char *) children
);
471 XtFree ((char *) old_children
);
475 update_one_menu_entry (instance
, widget
, val
, deep_p
)
476 widget_instance
* instance
;
484 widget_value
* contents
;
486 if (val
->this_one_change
== NO_CHANGE
)
489 /* update the sensitivity and userdata */
490 /* Common to all widget types */
491 XtVaSetValues (widget
,
492 XmNsensitive
, val
->enabled
,
493 XmNuserData
, val
->call_data
,
496 /* update the menu button as a label. */
497 if (val
->this_one_change
>= VISIBLE_CHANGE
)
498 xm_update_label (instance
, widget
, val
);
500 /* update the pulldown/pullaside as needed */
503 XtSetArg (al
[ac
], XmNsubMenuId
, &menu
); ac
++;
504 XtGetValues (widget
, al
, ac
);
506 contents
= val
->contents
;
512 unsigned int old_num_children
, i
;
516 parent
= XtParent (widget
);
517 widget_list
= XtCompositeChildren (parent
, &old_num_children
);
519 /* Find the widget position within the parent's widget list. */
520 for (i
= 0; i
< old_num_children
; i
++)
521 if (strcmp (XtName (widget_list
[i
]), XtName (widget
)) == 0)
523 if (i
== old_num_children
)
525 if (XmIsCascadeButton (widget_list
[i
]))
527 menu
= XmCreatePulldownMenu (parent
, XtName(widget
), NULL
, 0);
528 make_menu_in_widget (instance
, menu
, contents
, 0);
530 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
531 XtSetValues (widget
, al
, ac
);
537 /* The current menuitem is a XmPushButtonGadget, it
538 needs to be replaced by a CascadeButtonGadget */
539 XtDestroyWidget (widget_list
[i
]);
540 menu
= XmCreatePulldownMenu (parent
, val
->name
, NULL
, 0);
541 make_menu_in_widget (instance
, menu
, contents
, 0);
543 XtSetArg (al
[ac
], XmNsubMenuId
, menu
); ac
++;
544 /* Non-zero values don't work reliably in
545 conjunction with Emacs' event loop */
546 XtSetArg (al
[ac
], XmNmappingDelay
, 0); ac
++;
547 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0. */
548 /* Tell Motif to put it in the right place */
549 XtSetArg (al
[ac
], XmNpositionIndex
, i
); ac
++;
551 button
= XmCreateCascadeButtonGadget (parent
, val
->name
, al
, ac
);
552 xm_update_label (instance
, button
, val
);
554 XtAddCallback (button
, XmNcascadingCallback
, xm_pull_down_callback
,
555 (XtPointer
)instance
);
556 XtManageChild (button
);
563 XtSetArg (al
[ac
], XmNsubMenuId
, NULL
); ac
++;
564 XtSetValues (widget
, al
, ac
);
565 XtDestroyWidget (menu
);
567 else if (deep_p
&& contents
->change
!= NO_CHANGE
)
568 xm_update_menu (instance
, menu
, val
, 1);
572 xm_update_menu (instance
, widget
, val
, deep_p
)
573 widget_instance
* instance
;
579 unsigned int num_children
;
580 int num_children_to_keep
= 0;
584 children
= XtCompositeChildren (widget
, &num_children
);
586 /* Widget is a RowColumn widget whose contents have to be updated
587 * to reflect the list of items in val->contents */
589 /* See how many buttons we can keep, and how many we
590 must completely replace. */
591 if (val
->contents
== 0)
592 num_children_to_keep
= 0;
593 else if (val
->contents
->change
== STRUCTURAL_CHANGE
)
597 for (i
= 0, cur
= val
->contents
;
599 && cur
); /* how else to ditch unwanted children ?? - mgd */
600 i
++, cur
= cur
->next
)
602 if (cur
->this_one_change
== STRUCTURAL_CHANGE
)
606 num_children_to_keep
= i
;
610 num_children_to_keep
= num_children
;
612 /* Update all the buttons of the RowColumn, in order,
613 except for those we are going to replace entirely. */
616 for (i
= 0, cur
= val
->contents
; i
< num_children_to_keep
; i
++)
620 num_children_to_keep
= i
;
623 if (children
[i
]->core
.being_destroyed
624 || strcmp (XtName (children
[i
]), cur
->name
))
626 update_one_menu_entry (instance
, children
[i
], cur
, deep_p
);
631 /* Now replace from scratch all the buttons after the last
632 place that the top-level structure changed. */
633 if (val
->contents
->change
== STRUCTURAL_CHANGE
)
635 destroy_all_children (widget
, num_children_to_keep
);
636 make_menu_in_widget (instance
, widget
, val
->contents
,
637 num_children_to_keep
);
640 XtFree ((char *) children
);
644 /* update text widgets */
647 xm_update_text (instance
, widget
, val
)
648 widget_instance
* instance
;
652 XmTextSetString (widget
, val
->value
? val
->value
: "");
653 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
654 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
655 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
656 XtAddCallback (widget
, XmNvalueChangedCallback
,
657 xm_internal_update_other_instances
, instance
);
661 xm_update_text_field (instance
, widget
, val
)
662 widget_instance
* instance
;
666 XmTextFieldSetString (widget
, val
->value
? val
->value
: "");
667 XtRemoveAllCallbacks (widget
, XmNactivateCallback
);
668 XtAddCallback (widget
, XmNactivateCallback
, xm_generic_callback
, instance
);
669 XtRemoveAllCallbacks (widget
, XmNvalueChangedCallback
);
670 XtAddCallback (widget
, XmNvalueChangedCallback
,
671 xm_internal_update_other_instances
, instance
);
675 /* update a motif widget */
678 xm_update_one_widget (instance
, widget
, val
, deep_p
)
679 widget_instance
* instance
;
686 /* Mark as not edited */
689 /* Common to all widget types */
690 XtVaSetValues (widget
,
691 XmNsensitive
, val
->enabled
,
692 XmNuserData
, val
->call_data
,
695 /* Common to all label like widgets */
696 if (XtIsSubclass (widget
, xmLabelWidgetClass
))
697 xm_update_label (instance
, widget
, val
);
699 class = XtClass (widget
);
700 /* Class specific things */
701 if (class == xmPushButtonWidgetClass
||
702 class == xmArrowButtonWidgetClass
)
704 xm_update_pushbutton (instance
, widget
, val
);
706 else if (class == xmCascadeButtonWidgetClass
)
708 xm_update_cascadebutton (instance
, widget
, val
);
710 else if (class == xmToggleButtonWidgetClass
711 || class == xmToggleButtonGadgetClass
)
713 xm_update_toggle (instance
, widget
, val
);
715 else if (class == xmRowColumnWidgetClass
)
717 Boolean radiobox
= 0;
721 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
722 XtGetValues (widget
, al
, ac
);
725 xm_update_radiobox (instance
, widget
, val
);
727 xm_update_menu (instance
, widget
, val
, deep_p
);
729 else if (class == xmTextWidgetClass
)
731 xm_update_text (instance
, widget
, val
);
733 else if (class == xmTextFieldWidgetClass
)
735 xm_update_text_field (instance
, widget
, val
);
737 else if (class == xmListWidgetClass
)
739 xm_update_list (instance
, widget
, val
);
743 \f/* getting the value back */
745 xm_update_one_value (instance
, widget
, val
)
746 widget_instance
* instance
;
750 WidgetClass
class = XtClass (widget
);
751 widget_value
*old_wv
;
753 /* copy the call_data slot into the "return" widget_value */
754 for (old_wv
= instance
->info
->val
->contents
; old_wv
; old_wv
= old_wv
->next
)
755 if (!strcmp (val
->name
, old_wv
->name
))
757 val
->call_data
= old_wv
->call_data
;
761 if (class == xmToggleButtonWidgetClass
|| class == xmToggleButtonGadgetClass
)
763 XtVaGetValues (widget
, XmNset
, &val
->selected
, 0);
766 else if (class == xmTextWidgetClass
)
770 val
->value
= XmTextGetString (widget
);
773 else if (class == xmTextFieldWidgetClass
)
777 val
->value
= XmTextFieldGetString (widget
);
780 else if (class == xmRowColumnWidgetClass
)
782 Boolean radiobox
= 0;
786 XtSetArg (al
[ac
], XmNradioBehavior
, &radiobox
); ac
++;
787 XtGetValues (widget
, al
, ac
);
791 CompositeWidget radio
= (CompositeWidget
)widget
;
793 for (i
= 0; i
< radio
->composite
.num_children
; i
++)
796 Widget toggle
= radio
->composite
.children
[i
];
798 XtVaGetValues (toggle
, XmNset
, &set
, 0);
803 val
->value
= safe_strdup (XtName (toggle
));
809 else if (class == xmListWidgetClass
)
813 if (XmListGetSelectedPos (widget
, &pos_list
, &pos_cnt
))
817 for (cur
= val
->contents
, i
= 0; cur
; cur
= cur
->next
)
821 cur
->selected
= False
;
823 for (j
= 0; j
< pos_cnt
; j
++)
824 if (pos_list
[j
] == i
)
826 cur
->selected
= True
;
827 val
->value
= safe_strdup (cur
->name
);
831 XtFree ((char *) pos_list
);
837 /* This function is for activating a button from a program. It's wrong because
838 we pass a NULL argument in the call_data which is not Motif compatible.
839 This is used from the XmNdefaultAction callback of the List widgets to
840 have a double-click put down a dialog box like the button would do.
841 I could not find a way to do that with accelerators.
844 activate_button (widget
, closure
, call_data
)
849 Widget button
= (Widget
)closure
;
850 XtCallCallbacks (button
, XmNactivateCallback
, NULL
);
853 /* creation functions */
857 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
858 radio_box
, list
, left_buttons
, right_buttons
)
864 Boolean text_input_slot
;
874 Widget icon_separator
;
879 Widget children
[16]; /* for the final XtManageChildren */
881 Arg al
[64]; /* Arg List */
882 int ac
; /* Arg Count */
888 XtSetArg(al
[ac
], XmNtitle
, shell_title
); ac
++;
889 XtSetArg(al
[ac
], XtNallowShellResize
, True
); ac
++;
890 XtSetArg(al
[ac
], XmNdeleteResponse
, XmUNMAP
); ac
++;
891 result
= XmCreateDialogShell (parent
, "dialog", al
, ac
);
893 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
894 /* XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
895 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
896 form
= XmCreateForm (result
, shell_title
, al
, ac
);
901 XtSetArg(al
[ac
], XmNautoUnmanage
, FALSE
); ac
++;
902 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
903 form
= XmCreateForm (parent
, shell_title
, al
, ac
);
907 n_children
= left_buttons
+ right_buttons
+ 1;
909 XtSetArg(al
[ac
], XmNpacking
, n_children
== 3?
910 XmPACK_COLUMN
: XmPACK_TIGHT
); ac
++;
911 XtSetArg(al
[ac
], XmNorientation
, n_children
== 3?
912 XmVERTICAL
: XmHORIZONTAL
); ac
++;
913 XtSetArg(al
[ac
], XmNnumColumns
, left_buttons
+ right_buttons
+ 1); ac
++;
914 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
915 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
916 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
917 XtSetArg(al
[ac
], XmNadjustLast
, False
); ac
++;
918 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
919 XtSetArg(al
[ac
], XmNisAligned
, True
); ac
++;
920 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
921 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_FORM
); ac
++;
922 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
923 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
924 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
925 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
926 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
927 row
= XmCreateRowColumn (form
, "row", al
, ac
);
930 for (i
= 0; i
< left_buttons
; i
++)
932 char button_name
[16];
933 sprintf (button_name
, "button%d", i
+ 1);
937 XtSetArg(al
[ac
], XmNhighlightThickness
, 1); ac
++;
938 XtSetArg(al
[ac
], XmNshowAsDefault
, TRUE
); ac
++;
940 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
941 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
942 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
946 button
= children
[n_children
];
948 XtSetArg(al
[ac
], XmNdefaultButton
, button
); ac
++;
949 XtSetValues (row
, al
, ac
);
955 /* invisible separator button */
957 XtSetArg (al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
958 children
[n_children
] = XmCreateLabel (row
, "separator_button", al
, ac
);
961 for (i
= 0; i
< right_buttons
; i
++)
963 char button_name
[16];
964 sprintf (button_name
, "button%d", left_buttons
+ i
+ 1);
966 XtSetArg(al
[ac
], XmNmarginWidth
, 10); ac
++;
967 XtSetArg(al
[ac
], XmNnavigationType
, XmTAB_GROUP
); ac
++;
968 children
[n_children
] = XmCreatePushButton (row
, button_name
, al
, ac
);
969 if (! button
) button
= children
[n_children
];
973 XtManageChildren (children
, n_children
);
976 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
977 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
978 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
979 XtSetArg(al
[ac
], XmNbottomWidget
, row
); ac
++;
980 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
981 XtSetArg(al
[ac
], XmNleftOffset
, 0); ac
++;
982 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
983 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
984 separator
= XmCreateSeparator (form
, "", al
, ac
);
987 XtSetArg(al
[ac
], XmNlabelType
, XmPIXMAP
); ac
++;
988 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
989 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
990 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_NONE
); ac
++;
991 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
992 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
993 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
994 icon
= XmCreateLabel (form
, icon_name
, al
, ac
);
997 XtSetArg(al
[ac
], XmNmappedWhenManaged
, FALSE
); ac
++;
998 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_WIDGET
); ac
++;
999 XtSetArg(al
[ac
], XmNtopOffset
, 6); ac
++;
1000 XtSetArg(al
[ac
], XmNtopWidget
, icon
); ac
++;
1001 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1002 XtSetArg(al
[ac
], XmNbottomOffset
, 6); ac
++;
1003 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1004 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_NONE
); ac
++;
1005 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_NONE
); ac
++;
1006 icon_separator
= XmCreateLabel (form
, "", al
, ac
);
1008 if (text_input_slot
)
1011 XtSetArg(al
[ac
], XmNcolumns
, 50); ac
++;
1012 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1013 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1014 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1015 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1016 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1017 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1018 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1019 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1020 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1021 value
= XmCreateTextField (form
, "value", al
, ac
);
1027 XtSetArg(al
[ac
], XmNmarginWidth
, 0); ac
++;
1028 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
1029 XtSetArg(al
[ac
], XmNspacing
, 13); ac
++;
1030 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_CENTER
); ac
++;
1031 XtSetArg(al
[ac
], XmNorientation
, XmHORIZONTAL
); ac
++;
1032 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1033 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1034 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1035 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1036 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1037 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1038 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1039 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1040 value
= XmCreateRadioBox (form
, "radiobutton1", al
, ac
);
1043 radio_butt
= XmCreateToggleButtonGadget (value
, "radio1", al
, ac
);
1044 children
[i
++] = radio_butt
;
1045 radio_butt
= XmCreateToggleButtonGadget (value
, "radio2", al
, ac
);
1046 children
[i
++] = radio_butt
;
1047 radio_butt
= XmCreateToggleButtonGadget (value
, "radio3", al
, ac
);
1048 children
[i
++] = radio_butt
;
1049 XtManageChildren (children
, i
);
1054 XtSetArg(al
[ac
], XmNvisibleItemCount
, 5); ac
++;
1055 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_NONE
); ac
++;
1056 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1057 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1058 XtSetArg(al
[ac
], XmNbottomWidget
, separator
); ac
++;
1059 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1060 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1061 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1062 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1063 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1064 value
= XmCreateScrolledList (form
, "list", al
, ac
);
1066 /* this is the easiest way I found to have the dble click in the
1067 list activate the default button */
1068 XtAddCallback (value
, XmNdefaultActionCallback
, activate_button
, button
);
1072 XtSetArg(al
[ac
], XmNalignment
, XmALIGNMENT_BEGINNING
); ac
++;
1073 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
1074 XtSetArg(al
[ac
], XmNtopOffset
, 13); ac
++;
1075 XtSetArg(al
[ac
], XmNbottomAttachment
, XmATTACH_WIDGET
); ac
++;
1076 XtSetArg(al
[ac
], XmNbottomOffset
, 13); ac
++;
1077 XtSetArg(al
[ac
], XmNbottomWidget
,
1078 text_input_slot
|| radio_box
|| list
? value
: separator
); ac
++;
1079 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_WIDGET
); ac
++;
1080 XtSetArg(al
[ac
], XmNleftOffset
, 13); ac
++;
1081 XtSetArg(al
[ac
], XmNleftWidget
, icon
); ac
++;
1082 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
1083 XtSetArg(al
[ac
], XmNrightOffset
, 13); ac
++;
1084 message
= XmCreateLabel (form
, "message", al
, ac
);
1087 XtManageChild (value
);
1090 children
[i
] = row
; i
++;
1091 children
[i
] = separator
; i
++;
1092 if (text_input_slot
|| radio_box
)
1094 children
[i
] = value
; i
++;
1096 children
[i
] = message
; i
++;
1097 children
[i
] = icon
; i
++;
1098 children
[i
] = icon_separator
; i
++;
1099 XtManageChildren (children
, i
);
1101 if (text_input_slot
|| list
)
1103 XtInstallAccelerators (value
, button
);
1104 XtSetKeyboardFocus (result
, value
);
1108 XtInstallAccelerators (form
, button
);
1109 XtSetKeyboardFocus (result
, button
);
1115 static destroyed_instance
*
1116 find_matching_instance (instance
)
1117 widget_instance
* instance
;
1119 destroyed_instance
* cur
;
1120 destroyed_instance
* prev
;
1121 char* type
= instance
->info
->type
;
1122 char* name
= instance
->info
->name
;
1124 for (prev
= NULL
, cur
= all_destroyed_instances
;
1126 prev
= cur
, cur
= cur
->next
)
1128 if (!strcmp (cur
->name
, name
)
1129 && !strcmp (cur
->type
, type
)
1130 && cur
->parent
== instance
->parent
1131 && cur
->pop_up_p
== instance
->pop_up_p
)
1134 prev
->next
= cur
->next
;
1136 all_destroyed_instances
= cur
->next
;
1139 /* do some cleanup */
1140 else if (!cur
->widget
)
1143 prev
->next
= cur
->next
;
1145 all_destroyed_instances
= cur
->next
;
1146 free_destroyed_instance (cur
);
1147 cur
= prev
? prev
: all_destroyed_instances
;
1154 mark_dead_instance_destroyed (widget
, closure
, call_data
)
1157 XtPointer call_data
;
1159 destroyed_instance
* instance
= (destroyed_instance
*)closure
;
1160 instance
->widget
= NULL
;
1164 recenter_widget (widget
)
1167 Widget parent
= XtParent (widget
);
1168 Screen
* screen
= XtScreen (widget
);
1169 Dimension screen_width
= WidthOfScreen (screen
);
1170 Dimension screen_height
= HeightOfScreen (screen
);
1171 Dimension parent_width
= 0;
1172 Dimension parent_height
= 0;
1173 Dimension child_width
= 0;
1174 Dimension child_height
= 0;
1178 XtVaGetValues (widget
, XtNwidth
, &child_width
, XtNheight
, &child_height
, 0);
1179 XtVaGetValues (parent
, XtNwidth
, &parent_width
, XtNheight
, &parent_height
,
1182 x
= (((Position
)parent_width
) - ((Position
)child_width
)) / 2;
1183 y
= (((Position
)parent_height
) - ((Position
)child_height
)) / 2;
1185 XtTranslateCoords (parent
, x
, y
, &x
, &y
);
1187 if (x
+ child_width
> screen_width
)
1188 x
= screen_width
- child_width
;
1192 if (y
+ child_height
> screen_height
)
1193 y
= screen_height
- child_height
;
1197 XtVaSetValues (widget
, XtNx
, x
, XtNy
, y
, 0);
1201 recycle_instance (instance
)
1202 destroyed_instance
* instance
;
1204 Widget widget
= instance
->widget
;
1206 /* widget is NULL if the parent was destroyed. */
1212 /* Remove the destroy callback as the instance is not in the list
1214 XtRemoveCallback (instance
->parent
, XtNdestroyCallback
,
1215 mark_dead_instance_destroyed
,
1216 (XtPointer
)instance
);
1218 /* Give the focus to the initial item */
1219 focus
= XtNameToWidget (widget
, "*value");
1221 focus
= XtNameToWidget (widget
, "*button1");
1223 XtSetKeyboardFocus (widget
, focus
);
1225 /* shrink the separator label back to their original size */
1226 separator
= XtNameToWidget (widget
, "*separator_button");
1228 XtVaSetValues (separator
, XtNwidth
, 5, XtNheight
, 5, 0);
1230 /* Center the dialog in its parent */
1231 recenter_widget (widget
);
1233 free_destroyed_instance (instance
);
1238 xm_create_dialog (instance
)
1239 widget_instance
* instance
;
1241 char* name
= instance
->info
->type
;
1242 Widget parent
= instance
->parent
;
1244 Boolean pop_up_p
= instance
->pop_up_p
;
1245 char* shell_name
= 0;
1247 Boolean text_input_slot
= False
;
1248 Boolean radio_box
= False
;
1249 Boolean list
= False
;
1251 int left_buttons
= 0;
1252 int right_buttons
= 1;
1253 destroyed_instance
* dead_one
;
1255 /* try to find a widget to recycle */
1256 dead_one
= find_matching_instance (instance
);
1259 Widget recycled_widget
= recycle_instance (dead_one
);
1260 if (recycled_widget
)
1261 return recycled_widget
;
1266 icon_name
= "dbox-error";
1267 shell_name
= "Error";
1271 icon_name
= "dbox-info";
1272 shell_name
= "Information";
1277 icon_name
= "dbox-question";
1278 shell_name
= "Prompt";
1282 text_input_slot
= True
;
1283 icon_name
= "dbox-question";
1284 shell_name
= "Prompt";
1288 icon_name
= "dbox-question";
1289 shell_name
= "Question";
1293 total_buttons
= name
[1] - '0';
1295 if (name
[3] == 'T' || name
[3] == 't')
1297 text_input_slot
= False
;
1301 right_buttons
= name
[4] - '0';
1303 left_buttons
= total_buttons
- right_buttons
;
1305 widget
= make_dialog (name
, parent
, pop_up_p
,
1306 shell_name
, icon_name
, text_input_slot
, radio_box
,
1307 list
, left_buttons
, right_buttons
);
1309 XtAddCallback (widget
, XmNpopdownCallback
, xm_nosel_callback
,
1310 (XtPointer
) instance
);
1314 /* Create a menu bar. We turn off the f10 key
1315 because we have not yet managed to make it work right in Motif. */
1318 make_menubar (instance
)
1319 widget_instance
* instance
;
1325 XtSetArg(al
[0], XmNmenuAccelerator
, 0);
1326 return XmCreateMenuBar (instance
->parent
, instance
->info
->name
, al
, 1);
1330 remove_grabs (shell
, closure
, call_data
)
1333 XtPointer call_data
;
1335 Widget menu
= (Widget
) closure
;
1336 XmRemoveFromPostFromList (menu
, XtParent (XtParent (menu
)));
1340 make_popup_menu (instance
)
1341 widget_instance
* instance
;
1343 Widget parent
= instance
->parent
;
1344 Window parent_window
= parent
->core
.window
;
1347 /* sets the parent window to 0 to fool Motif into not generating a grab */
1348 parent
->core
.window
= 0;
1349 result
= XmCreatePopupMenu (parent
, instance
->info
->name
, NULL
, 0);
1350 XtAddCallback (XtParent (result
), XmNpopdownCallback
, remove_grabs
,
1352 parent
->core
.window
= parent_window
;
1356 make_main (instance
)
1357 widget_instance
* instance
;
1359 Widget parent
= instance
->parent
;
1365 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1366 XtSetArg (al
[ac
], XmNspacing
, 0); ac
++;
1367 result
= XmCreateMainWindow (parent
, instance
->info
->name
, al
, ac
);
1371 \f/* Table of functions to create widgets */
1375 /* interface with the XDesigner generated functions */
1376 typedef Widget (*widget_maker
) (Widget
);
1377 extern Widget
create_project_p_sheet (Widget parent
);
1378 extern Widget
create_debugger_p_sheet (Widget parent
);
1379 extern Widget
create_breaklist_p_sheet (Widget parent
);
1380 extern Widget
create_le_browser_p_sheet (Widget parent
);
1381 extern Widget
create_class_browser_p_sheet (Widget parent
);
1382 extern Widget
create_call_browser_p_sheet (Widget parent
);
1383 extern Widget
create_build_dialog (Widget parent
);
1384 extern Widget
create_editmode_dialog (Widget parent
);
1385 extern Widget
create_search_dialog (Widget parent
);
1386 extern Widget
create_project_display_dialog (Widget parent
);
1389 make_one (widget_instance
* instance
, widget_maker fn
)
1395 if (instance
->pop_up_p
)
1397 XtSetArg (al
[ac
], XmNallowShellResize
, TRUE
); ac
++;
1398 result
= XmCreateDialogShell (instance
->parent
, "dialog", NULL
, 0);
1399 XtAddCallback (result
, XmNpopdownCallback
, &xm_nosel_callback
,
1400 (XtPointer
) instance
);
1405 result
= (*fn
) (instance
->parent
);
1406 XtRealizeWidget (result
);
1412 make_project_p_sheet (widget_instance
* instance
)
1414 return make_one (instance
, create_project_p_sheet
);
1418 make_debugger_p_sheet (widget_instance
* instance
)
1420 return make_one (instance
, create_debugger_p_sheet
);
1424 make_breaklist_p_sheet (widget_instance
* instance
)
1426 return make_one (instance
, create_breaklist_p_sheet
);
1430 make_le_browser_p_sheet (widget_instance
* instance
)
1432 return make_one (instance
, create_le_browser_p_sheet
);
1436 make_class_browser_p_sheet (widget_instance
* instance
)
1438 return make_one (instance
, create_class_browser_p_sheet
);
1442 make_call_browser_p_sheet (widget_instance
* instance
)
1444 return make_one (instance
, create_call_browser_p_sheet
);
1448 make_build_dialog (widget_instance
* instance
)
1450 return make_one (instance
, create_build_dialog
);
1454 make_editmode_dialog (widget_instance
* instance
)
1456 return make_one (instance
, create_editmode_dialog
);
1460 make_search_dialog (widget_instance
* instance
)
1462 return make_one (instance
, create_search_dialog
);
1466 make_project_display_dialog (widget_instance
* instance
)
1468 return make_one (instance
, create_project_display_dialog
);
1471 #endif /* ENERGIZE */
1473 widget_creation_entry
1474 xm_creation_table
[] =
1476 {"menubar", make_menubar
},
1477 {"popup", make_popup_menu
},
1478 {"main", make_main
},
1480 {"project_p_sheet", make_project_p_sheet
},
1481 {"debugger_p_sheet", make_debugger_p_sheet
},
1482 {"breaklist_psheet", make_breaklist_p_sheet
},
1483 {"leb_psheet", make_le_browser_p_sheet
},
1484 {"class_browser_psheet", make_class_browser_p_sheet
},
1485 {"ctree_browser_psheet", make_call_browser_p_sheet
},
1486 {"build", make_build_dialog
},
1487 {"editmode", make_editmode_dialog
},
1488 {"search", make_search_dialog
},
1489 {"project_display", make_project_display_dialog
},
1490 #endif /* ENERGIZE */
1494 \f/* Destruction of instances */
1496 xm_destroy_instance (instance
)
1497 widget_instance
* instance
;
1499 Widget widget
= instance
->widget
;
1500 /* recycle the dialog boxes */
1501 /* Disable the recycling until we can find a way to have the dialog box
1502 get reasonable layout after we modify its contents. */
1504 && XtClass (widget
) == xmDialogShellWidgetClass
)
1506 destroyed_instance
* dead_instance
=
1507 make_destroyed_instance (instance
->info
->name
,
1508 instance
->info
->type
,
1511 instance
->pop_up_p
);
1512 dead_instance
->next
= all_destroyed_instances
;
1513 all_destroyed_instances
= dead_instance
;
1514 XtUnmanageChild (first_child (instance
->widget
));
1515 XFlush (XtDisplay (instance
->widget
));
1516 XtAddCallback (instance
->parent
, XtNdestroyCallback
,
1517 mark_dead_instance_destroyed
, (XtPointer
)dead_instance
);
1521 /* This might not be necessary now that the nosel is attached to
1522 popdown instead of destroy, but it can't hurt. */
1523 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1524 xm_nosel_callback
, (XtPointer
)instance
);
1525 XtDestroyWidget (instance
->widget
);
1529 \f/* popup utility */
1531 xm_popup_menu (widget
, event
)
1535 XButtonPressedEvent dummy
;
1539 dummy
.type
= ButtonPress
;
1541 dummy
.send_event
= 0;
1542 dummy
.display
= XtDisplay (widget
);
1543 dummy
.window
= XtWindow (XtParent (widget
));
1546 XQueryPointer (dummy
.display
, dummy
.window
, &dummy
.root
,
1547 &dummy
.subwindow
, &dummy
.x_root
, &dummy
.y_root
,
1548 &dummy
.x
, &dummy
.y
, &dummy
.state
);
1549 event
= (XEvent
*) &dummy
;
1552 if (event
->type
== ButtonPress
|| event
->type
== ButtonRelease
)
1554 /* This is so totally ridiculous: there's NO WAY to tell Motif
1555 that *any* button can select a menu item. Only one button
1556 can have that honor.
1559 if (event
->xbutton
.state
& Button5Mask
) trans
= "<Btn5Down>";
1560 else if (event
->xbutton
.state
& Button4Mask
) trans
= "<Btn4Down>";
1561 else if (event
->xbutton
.state
& Button3Mask
) trans
= "<Btn3Down>";
1562 else if (event
->xbutton
.state
& Button2Mask
) trans
= "<Btn2Down>";
1563 else if (event
->xbutton
.state
& Button1Mask
) trans
= "<Btn1Down>";
1564 if (trans
) XtVaSetValues (widget
, XmNmenuPost
, trans
, 0);
1565 XmMenuPosition (widget
, (XButtonPressedEvent
*) event
);
1567 XtManageChild (widget
);
1571 set_min_dialog_size (w
)
1576 XtVaGetValues (w
, XmNwidth
, &width
, XmNheight
, &height
, 0);
1577 XtVaSetValues (w
, XmNminWidth
, width
, XmNminHeight
, height
, 0);
1581 xm_pop_instance (instance
, up
)
1582 widget_instance
* instance
;
1585 Widget widget
= instance
->widget
;
1587 if (XtClass (widget
) == xmDialogShellWidgetClass
)
1589 Widget widget_to_manage
= first_child (widget
);
1592 XtManageChild (widget_to_manage
);
1593 set_min_dialog_size (widget
);
1594 XtSetKeyboardFocus (instance
->parent
, widget
);
1597 XtUnmanageChild (widget_to_manage
);
1602 XtManageChild (widget
);
1604 XtUnmanageChild (widget
);
1609 /* motif callback */
1611 enum do_call_type
{ pre_activate
, selection
, no_selection
, post_activate
};
1614 do_call (widget
, closure
, type
)
1617 enum do_call_type type
;
1621 XtPointer user_data
;
1622 widget_instance
* instance
= (widget_instance
*)closure
;
1623 Widget instance_widget
;
1628 if (widget
->core
.being_destroyed
)
1631 instance_widget
= instance
->widget
;
1632 if (!instance_widget
)
1635 id
= instance
->info
->id
;
1638 XtSetArg (al
[ac
], XmNuserData
, &user_data
); ac
++;
1639 XtGetValues (widget
, al
, ac
);
1643 if (instance
->info
->pre_activate_cb
)
1644 instance
->info
->pre_activate_cb (widget
, id
, user_data
);
1647 if (instance
->info
->selection_cb
)
1648 instance
->info
->selection_cb (widget
, id
, user_data
);
1651 if (instance
->info
->selection_cb
)
1652 instance
->info
->selection_cb (widget
, id
, (XtPointer
) -1);
1655 if (instance
->info
->post_activate_cb
)
1656 instance
->info
->post_activate_cb (widget
, id
, user_data
);
1663 /* Like lw_internal_update_other_instances except that it does not do
1664 anything if its shell parent is not managed. This is to protect
1665 lw_internal_update_other_instances to dereference freed memory
1666 if the widget was ``destroyed'' by caching it in the all_destroyed_instances
1669 xm_internal_update_other_instances (widget
, closure
, call_data
)
1672 XtPointer call_data
;
1675 for (parent
= widget
; parent
; parent
= XtParent (parent
))
1676 if (XtIsShell (parent
))
1678 else if (!XtIsManaged (parent
))
1680 lw_internal_update_other_instances (widget
, closure
, call_data
);
1684 xm_generic_callback (widget
, closure
, call_data
)
1687 XtPointer call_data
;
1689 lw_internal_update_other_instances (widget
, closure
, call_data
);
1690 do_call (widget
, closure
, selection
);
1694 xm_nosel_callback (widget
, closure
, call_data
)
1697 XtPointer call_data
;
1699 /* This callback is only called when a dialog box is dismissed with the wm's
1700 destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed
1701 in that case, not just unmapped, so that it releases its keyboard grabs.
1702 But there are problems with running our callbacks while the widget is in
1703 the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
1704 instead of XmDESTROY and then destroy it ourself after having run the
1707 do_call (widget
, closure
, no_selection
);
1708 XtDestroyWidget (widget
);
1712 xm_pull_down_callback (widget
, closure
, call_data
)
1715 XtPointer call_data
;
1717 do_call (widget
, closure
, pre_activate
);
1721 xm_pop_down_callback (widget
, closure
, call_data
)
1724 XtPointer call_data
;
1726 widget_instance
*instance
= (widget_instance
*) closure
;
1728 if ((!instance
->pop_up_p
&& (XtParent (widget
) == instance
->widget
))
1729 || (XtParent (widget
) == instance
->parent
))
1730 do_call (widget
, closure
, post_activate
);
1734 /* set the keyboard focus */
1736 xm_set_keyboard_focus (parent
, w
)
1740 XmProcessTraversal (w
, 0);
1741 XtSetKeyboardFocus (parent
, w
);
1744 /* Motif hack to set the main window areas. */
1746 xm_set_main_areas (parent
, menubar
, work_area
)
1751 XmMainWindowSetAreas (parent
,
1752 menubar
, /* menubar (maybe 0) */
1753 0, /* command area (psheets) */
1754 0, /* horizontal scroll */
1755 0, /* vertical scroll */
1756 work_area
); /* work area */
1759 /* Motif hack to control resizing on the menubar. */
1761 xm_manage_resizing (w
, flag
)
1767 /* Enable the edit widget for resizing. */
1770 XtSetArg (al
[0], XtNallowShellResize
, 0);
1771 XtSetValues (w
, al
, 1);
1775 /* Disable the edit widget from resizing. */
1778 XtSetArg (al
[0], XtNallowShellResize
, 0);
1779 XtSetValues (w
, al
, 1);