One more check on valid display which is known to be in the startup
[xcircuit.git] / Xw / MenuPane.c
blobbf3c0d431592d109d463aba8f8a2b0793e9fb598
1 /*************************************<+>*************************************
2 *****************************************************************************
3 **
4 ** File: MenuPane.c
5 **
6 ** Project: X Widgets
7 **
8 ** Description: Menu Pane Meta Class Widget
9 **
10 *****************************************************************************
11 **
12 ** Copyright (c) 1988 by Hewlett-Packard Company
13 ** Copyright (c) 1988 by the Massachusetts Institute of Technology
14 **
15 ** Permission to use, copy, modify, and distribute this software
16 ** and its documentation for any purpose and without fee is hereby
17 ** granted, provided that the above copyright notice appear in all
18 ** copies and that both that copyright notice and this permission
19 ** notice appear in supporting documentation, and that the names of
20 ** Hewlett-Packard or M.I.T. not be used in advertising or publicity
21 ** pertaining to distribution of the software without specific, written
22 ** prior permission.
23 **
24 *****************************************************************************
25 *************************************<+>*************************************/
28 #include <X11/IntrinsicP.h>
29 #include <X11/Xutil.h>
30 #include <X11/StringDefs.h>
31 #include <X11/Xatom.h>
32 #include <Xw/Xw.h>
33 #include <Xw/XwP.h>
35 static void Initialize();
36 static void Destroy();
37 static Boolean SetValues();
38 static void GetFontGC();
39 static void InsertChild();
40 static void ConstraintInitialize();
41 static void ClassPartInitialize();
42 static void SetTraversalFlag();
45 /****************************************************************
47 * MenuPane Resources
49 ****************************************************************/
51 static XtResource resources[] = {
52 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
53 XtOffset(XwMenuPaneWidget, menu_pane.title_font), XtRString, "fixed"},
55 {XtNtitleString, XtCTitleString, XtRString, sizeof(caddr_t),
56 XtOffset(XwMenuPaneWidget, menu_pane.title_string), XtRString, NULL},
58 {XtNtitleImage, XtCTitleImage, XtRImage, sizeof(XImage *),
59 XtOffset(XwMenuPaneWidget, menu_pane.titleImage), XtRImage, NULL},
61 {XtNtitleShowing, XtCTitleShowing, XtRBoolean, sizeof(Boolean),
62 XtOffset(XwMenuPaneWidget, menu_pane.title_showing), XtRString, "TRUE"},
64 {XtNattachTo, XtCAttachTo, XtRString, sizeof(String),
65 XtOffset(XwMenuPaneWidget, menu_pane.attach_to), XtRString, NULL},
67 {XtNmgrTitleOverride, XtCTitleOverride, XtRBoolean, sizeof(Boolean),
68 XtOffset(XwMenuPaneWidget, menu_pane.title_override), XtRString,
69 "FALSE"},
71 {XtNtitleType, XtCTitleType, XtRTitleType, sizeof(int),
72 XtOffset(XwMenuPaneWidget, menu_pane.title_type), XtRString, "string"},
74 {XtNmnemonic, XtCMnemonic, XtRString, sizeof(String),
75 XtOffset(XwMenuPaneWidget, menu_pane.mnemonic),XtRString,NULL},
77 {XtNselect, XtCCallback, XtRCallback, sizeof(caddr_t),
78 XtOffset(XwMenuPaneWidget, menu_pane.select), XtRPointer, NULL}
82 /****************************************************************
84 * Full class record constant
86 ****************************************************************/
88 XwMenuPaneClassRec XwmenupaneClassRec = {
90 /* core_class fields */
91 /* superclass */ (WidgetClass) &XwmanagerClassRec,
92 /* class_name */ "XwMenuPane",
93 /* widget_size */ sizeof(XwMenuPaneRec),
94 /* class_initialize */ NULL,
95 /* class_part_init */ ClassPartInitialize,
96 /* class_inited */ FALSE,
97 /* initialize */ Initialize,
98 /* initialize_hook */ NULL,
99 /* realize */ NULL,
100 /* actions */ NULL,
101 /* num_actions */ 0,
102 /* resources */ resources,
103 /* num_resources */ XtNumber(resources),
104 /* xrm_class */ NULLQUARK,
105 /* compress_motion */ TRUE,
106 /* compress_exposure */ TRUE,
107 /* compress_enterlv */ TRUE,
108 /* visible_interest */ FALSE,
109 /* destroy */ Destroy,
110 /* resize */ NULL,
111 /* expose */ NULL,
112 /* set_values */ SetValues,
113 /* set_values_hook */ NULL,
114 /* set_values_almost */ XtInheritSetValuesAlmost,
115 /* get_values_hook */ NULL,
116 /* accept_focus */ NULL,
117 /* version */ XtVersion,
118 /* PRIVATE cb list */ NULL,
119 /* tm_table */ NULL,
120 /* query_geometry */ NULL,
121 /* display_accelerator */ XtInheritDisplayAccelerator,
122 /* extension */ NULL
124 /* composite_class fields */
125 /* geometry_manager */ NULL,
126 /* change_managed */ NULL,
127 /* insert_child */ InsertChild,
128 /* delete_child */ XtInheritDeleteChild,
129 NULL,
131 /* constraint class fields */
132 /* resources */ NULL,
133 /* num_resources */ 0,
134 /* Constraint_size */ sizeof (Boolean),
135 /* initialize */ ConstraintInitialize,
136 /* destroy */ NULL,
137 /* set_values */ NULL,
138 NULL,
140 /* manager_class fields */
141 /* traversal handler */ NULL,
142 /* translations */ NULL,
144 /* menu pane class - none */
145 /* setTraversalFlag */ (XwWBoolProc) SetTraversalFlag
149 WidgetClass XwmenupaneWidgetClass = (WidgetClass)&XwmenupaneClassRec;
152 /*************************************<->*************************************
154 * ProcedureName (parameters)
156 * Description:
157 * -----------
158 * xxxxxxxxxxxxxxxxxxxxxxx
161 * Inputs:
162 * ------
163 * xxxxxxxxxxxx = xxxxxxxxxxxxx
165 * Outputs:
166 * -------
167 * xxxxxxxxxxxx = xxxxxxxxxxxxx
169 * Procedures Called
170 * -----------------
172 *************************************<->***********************************/
174 static void ClassPartInitialize (wc)
176 register XwMenuPaneWidgetClass wc;
179 if (wc->constraint_class.initialize == XtInheritMenuPaneConstraintInit)
180 wc->constraint_class.initialize = (XtInitProc) ClassPartInitialize;
182 if (wc->menu_pane_class.setTraversalFlag == XtInheritSetTraversalFlagProc)
183 wc->menu_pane_class.setTraversalFlag = (XwWBoolProc) SetTraversalFlag;
187 /*************************************<->*************************************
189 * ProcedureName (parameters)
191 * Description:
192 * -----------
193 * xxxxxxxxxxxxxxxxxxxxxxx
196 * Inputs:
197 * ------
198 * xxxxxxxxxxxx = xxxxxxxxxxxxx
200 * Outputs:
201 * -------
202 * xxxxxxxxxxxx = xxxxxxxxxxxxx
204 * Procedures Called
205 * -----------------
207 *************************************<->***********************************/
209 static void ConstraintInitialize (request, new)
211 Widget request;
212 Widget new;
215 Boolean * managed_and_mapped;
217 managed_and_mapped = (Boolean *) new->core.constraints;
219 /* Widgets are never managed when they are first created */
220 *managed_and_mapped = FALSE;
224 /*************************************<->*************************************
226 * ProcedureName (parameters)
228 * Description:
229 * -----------
230 * xxxxxxxxxxxxxxxxxxxxxxx
233 * Inputs:
234 * ------
235 * xxxxxxxxxxxx = xxxxxxxxxxxxx
237 * Outputs:
238 * -------
239 * xxxxxxxxxxxx = xxxxxxxxxxxxx
241 * Procedures Called
242 * -----------------
244 *************************************<->***********************************/
246 static void InsertChild (w)
247 Widget w;
249 CompositeWidgetClass composite;
250 Widget parent, grandparent, greatgrandparent;
252 /* Invoke our superclass's insert_child procedure */
253 composite = (CompositeWidgetClass)
254 XwmenupaneWidgetClass->core_class.superclass;
256 (*(composite->composite_class.insert_child)) (w);
258 /* Call menu mgr's AddButton() procedure */
259 if ((parent = (Widget) XtParent(w)) &&
260 (grandparent = (Widget) XtParent(parent)) &&
261 (greatgrandparent = (Widget) XtParent(grandparent)) &&
262 (XtIsSubclass (greatgrandparent, XwmenumgrWidgetClass)))
264 (*((XwMenuMgrWidgetClass)XtClass(greatgrandparent))->menu_mgr_class.
265 addButton) (greatgrandparent, w);
270 /*************************************<->*************************************
272 * Initialize
275 * Description:
276 * -----------
277 * Initialize the menu_pane fields within the widget's instance structure.
280 * Inputs:
281 * ------
282 * xxxxxxxxxxxx = xxxxxxxxxxxxx
284 * Outputs:
285 * -------
286 * xxxxxxxxxxxx = xxxxxxxxxxxxx
288 * Procedures Called
289 * -----------------
291 *************************************<->***********************************/
293 static void Initialize (request, new)
294 XwMenuPaneWidget request, new;
296 Widget parent, grandparent;
297 KeySym tempKeysym;
300 * Always force traversal off for a menupane. We inherit our
301 * traversal setting from our menu manager, and it will take
302 * care of setting us to the correct state.
304 new->manager.traversal_on = FALSE;
306 new->menu_pane.attachId = NULL;
308 /* Call menu mgr's AddPane() procedure */
309 if ((parent = (Widget) XtParent(new)) &&
310 (grandparent = (Widget) XtParent(parent)) &&
311 (XtIsSubclass (grandparent, XwmenumgrWidgetClass)))
313 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.addPane)
314 (grandparent, (Widget)new);
316 else
317 grandparent = NULL;
320 /* Get the GC used to display the title string/image */
321 GetFontGC (new);
323 /* Save a copy of the title string, if present */
324 if (new->menu_pane.title_string)
326 new->menu_pane.title_string = (String)
327 strcpy(XtMalloc(XwStrlen(new->menu_pane.title_string) + 1),
328 new->menu_pane.title_string);
330 else
332 /* Set a default title string: the widget name */
333 new->menu_pane.title_string = (String)
334 strcpy(XtMalloc(XwStrlen(new->core.name) + 1),
335 new->core.name);
338 /* Save a copy of the accelerator string, if present */
339 if ((new->menu_pane.mnemonic) && (*(new->menu_pane.mnemonic) != '\0'))
341 /* Valid mnemonic specified */
342 char mne = new->menu_pane.mnemonic[0];
344 new->menu_pane.mnemonic = (String)XtMalloc(2);
345 new->menu_pane.mnemonic[0] = mne;
346 new->menu_pane.mnemonic[1] = '\0';
348 /* Register it with the menu manager */
349 if (grandparent)
351 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
352 setPostMnemonic) (grandparent, (Widget)new, new->menu_pane.mnemonic);
355 else
357 if (new->menu_pane.mnemonic)
358 XtWarning ("MenuPane: Invalid mnemonic; disabling feature");
359 new->menu_pane.mnemonic = NULL;
362 /* Save a copy of the attach string, if present */
363 if (new->menu_pane.attach_to)
365 new->menu_pane.attach_to = (String)
366 strcpy(XtMalloc(XwStrlen(new->menu_pane.attach_to) + 1),
367 new->menu_pane.attach_to);
369 /* Call menu mgr's AttachPane() procedure */
370 if (grandparent)
372 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
373 attachPane) (grandparent, (Widget)new, new->menu_pane.attach_to);
377 } /* Initialize */
380 /*************************************<->*************************************
382 * SetValues
384 * Description:
385 * -----------
388 * Inputs:
389 * ------
390 * xxxxxxxxxxxx = xxxxxxxxxxxxx
392 * Outputs:
393 * -------
394 * xxxxxxxxxxxx = xxxxxxxxxxxxx
396 * Procedures Called
397 * -----------------
399 *************************************<->***********************************/
401 static Boolean SetValues (current, request, new)
402 XwMenuPaneWidget current, request, new;
404 Boolean redrawFlag = FALSE;
405 Boolean titleAttributeChange = FALSE;
406 Widget parent, grandparent;
407 KeySym tempKeysym;
409 /* We never allow our traversal flag to change using SetValues() */
410 new->manager.traversal_on = current->manager.traversal_on;
412 /* Determine if we are being controlled by a menu manager */
413 if (((parent = (Widget) XtParent(new)) == NULL) ||
414 ((grandparent = (Widget) XtParent(parent)) == NULL) ||
415 (!XtIsSubclass (grandparent, XwmenumgrWidgetClass)))
417 grandparent = NULL;
420 if ((new->menu_pane.title_type != XwSTRING) &&
421 (new->menu_pane.title_type != XwIMAGE))
423 XtWarning("MenuPane: Invalid title type; using previous setting");
424 new->menu_pane.title_type = current->menu_pane.title_type;
427 if ((current->menu_pane.title_showing != new->menu_pane.title_showing) ||
428 (current->menu_pane.title_override != new->menu_pane.title_override))
430 redrawFlag = TRUE;
433 /* Handle the case of a changed title string or image */
435 if (current->menu_pane.title_string != new->menu_pane.title_string)
437 /* Allocate a new buffer to hold the string */
438 if (new->menu_pane.title_string)
440 new->menu_pane.title_string = (String)
441 strcpy (XtMalloc (XwStrlen (new->menu_pane.title_string) + 1),
442 new->menu_pane.title_string);
444 else
446 /* Assign a default title: the widget name */
447 new->menu_pane.title_string = (String)
448 strcpy (XtMalloc (XwStrlen (new->core.name) + 1),
449 new->core.name);
453 * Free up the buffer holding the old title string.
454 * XtFree() is smart enough to catch a NULL pointer.
456 XtFree (current->menu_pane.title_string);
458 if (new->menu_pane.title_type == XwSTRING)
460 titleAttributeChange = TRUE;
462 if (new->menu_pane.title_showing)
463 redrawFlag = TRUE;
467 if (current->menu_pane.titleImage != new->menu_pane.titleImage)
470 * Depending upon whether the depth of the title image can change,
471 * we may need to generate a new GC, which will be used by our call
472 * to XPutImage(). However, I don't believe this is the case.
475 if (new->menu_pane.title_type == XwIMAGE)
477 titleAttributeChange = TRUE;
479 if (new->menu_pane.title_showing)
480 redrawFlag = TRUE;
484 if (current->menu_pane.title_type != new->menu_pane.title_type)
486 redrawFlag = TRUE;
487 titleAttributeChange = TRUE;
491 /* Determine if the menu manager needs to attach us elsewhere */
493 if (current->menu_pane.attach_to != new->menu_pane.attach_to)
495 /* Allocate a new buffer to hold the string */
496 if (new->menu_pane.attach_to)
498 new->menu_pane.attach_to = (String)
499 strcpy (XtMalloc (XwStrlen (new->menu_pane.attach_to) + 1),
500 new->menu_pane.attach_to);
503 /* Call menu mgr's DetachPane() procedure */
504 if (grandparent)
506 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
507 detachPane) (grandparent, (Widget)new, current->menu_pane.attach_to);
511 * Free up the buffer holding the old attach string.
512 * XtFree() is smart enough to catch a NULL pointer.
514 XtFree (current->menu_pane.attach_to);
516 /* Call menu mgr's AttachPane() procedure */
517 if (grandparent)
519 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
520 attachPane) (grandparent, (Widget)new, new->menu_pane.attach_to);
524 /* Determine if the post mnemonic needs to be changed */
526 if (current->menu_pane.mnemonic != new->menu_pane.mnemonic)
528 if (new->menu_pane.mnemonic)
530 if (*(new->menu_pane.mnemonic) == '\0')
532 /* Invalid string; revert to previous one */
533 XtWarning
534 ("MenuPane: Invalid post mnemonic; using previous setting");
535 new->menu_pane.mnemonic = current->menu_pane.mnemonic;
537 else
539 /* Valid string; remove old mnemonic, and add new one */
540 char mne = new->menu_pane.mnemonic[0];
542 new->menu_pane.mnemonic = (String) XtMalloc(2);
543 new->menu_pane.mnemonic[0] = mne;
544 new->menu_pane.mnemonic[1] = '\0';
546 if (grandparent && current->menu_pane.mnemonic)
548 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
549 clearPostMnemonic) (grandparent, (Widget)current);
552 if (grandparent)
554 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
555 setPostMnemonic) (grandparent, (Widget)new,
556 new->menu_pane.mnemonic);
558 XtFree (current->menu_pane.mnemonic);
561 else
563 /* Remove old accelerator */
564 if (grandparent && current->menu_pane.mnemonic)
566 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
567 clearPostMnemonic) (grandparent, (Widget)current);
570 new->menu_pane.mnemonic = NULL;
572 XtFree(current->menu_pane.mnemonic);
577 /* Force a redraw and get a new GC if the font attributes change */
579 if ((current->manager.foreground != new->manager.foreground) ||
580 (current->menu_pane.title_font->fid != new->menu_pane.title_font->fid))
582 XtDestroyGC (current->menu_pane.titleGC);
583 GetFontGC (new);
584 redrawFlag = TRUE;
585 titleAttributeChange = TRUE;
588 if ((current->core.background_pixel != new->core.background_pixel) ||
589 (current->manager.background_tile != new->manager.background_tile))
591 titleAttributeChange = TRUE;
594 if (((new->core.sensitive != current->core.sensitive) ||
595 (new->core.ancestor_sensitive != current->core.ancestor_sensitive)) &&
596 grandparent)
598 /* Call menu mgr's paneSensitivityChanged() procedure */
599 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
600 paneSensitivityChanged) (grandparent, (Widget)new);
603 if (titleAttributeChange && grandparent)
605 /* Call menu mgr's SetTitleAttributes() procedure */
606 (*((XwMenuMgrWidgetClass)XtClass(grandparent))->menu_mgr_class.
607 setTitleAttributes) (grandparent, (Widget)new);
611 return (redrawFlag);
615 /*************************************<->*************************************
617 * GetFontGC
619 * Description:
620 * -----------
623 * Inputs:
624 * ------
625 * xxxxxxxxxxxx = xxxxxxxxxxxxx
627 * Outputs:
628 * -------
629 * xxxxxxxxxxxx = xxxxxxxxxxxxx
631 * Procedures Called
632 * -----------------
634 *************************************<->***********************************/
636 static void GetFontGC (mw)
638 XwMenuPaneWidget mw;
641 XGCValues values;
643 values.foreground = mw->manager.foreground;
644 values.background = mw->core.background_pixel;
645 values.font = mw->menu_pane.title_font->fid;
646 values.line_width = 1;
647 values.line_style = LineSolid;
648 values.function = GXcopy;
649 values.plane_mask = AllPlanes;
650 values.subwindow_mode = ClipByChildren;
651 values.clip_x_origin = 0;
652 values.clip_y_origin = 0;
653 values.clip_mask = None;
655 mw->menu_pane.titleGC = XtGetGC ((Widget)mw, GCForeground | GCFont |
656 GCFunction | GCLineWidth | GCLineStyle |
657 GCBackground | GCPlaneMask | GCSubwindowMode |
658 GCClipXOrigin | GCClipYOrigin | GCClipMask,
659 &values);
663 /*************************************<->*************************************
665 * Destroy
667 * Description:
668 * -----------
671 * Inputs:
672 * ------
673 * xxxxxxxxxxxx = xxxxxxxxxxxxx
675 * Outputs:
676 * -------
677 * xxxxxxxxxxxx = xxxxxxxxxxxxx
679 * Procedures Called
680 * -----------------
682 *************************************<->***********************************/
684 static void Destroy (mw)
686 XwMenuPaneWidget mw;
689 /* Free up our resources */
691 if (mw->menu_pane.title_string)
692 XtFree (mw->menu_pane.title_string);
694 if (mw->menu_pane.attach_to)
695 XtFree (mw->menu_pane.attach_to);
697 if (mw->menu_pane.mnemonic)
698 XtFree (mw->menu_pane.mnemonic);
700 XtDestroyGC (mw->menu_pane.titleGC);
702 XtRemoveCallbacks ((Widget)mw, XtNselect, mw->menu_pane.select);
706 /*************************************<->*************************************
708 * _XwSetMappedManagedChildrenList (parameters)
710 * Description:
711 * -----------
712 * MenuPane widgets are only interested in using their children
713 * which are both managed and mapped_when_managed, during layout
714 * calculations. This global routine traverses the list of
715 * children for the specified manager widget, and constructs a
716 * parallel list of only those children meeting the above criteria.
719 * Inputs:
720 * ------
721 * xxxxxxxxxxxx = xxxxxxxxxxxxx
723 * Outputs:
724 * -------
725 * xxxxxxxxxxxx = xxxxxxxxxxxxx
727 * Procedures Called
728 * -----------------
730 *************************************<->***********************************/
732 void _XwSetMappedManagedChildrenList (mw)
734 XwManagerWidget mw;
737 int i;
739 mw->manager.num_managed_children = 0;
741 for (i = 0; i < mw->composite.num_children; i++)
743 if ((mw->composite.children[i]->core.managed) &&
744 (mw->composite.children[i]->core.mapped_when_managed))
746 /* Add to list */
747 if ((mw->manager.num_managed_children + 1) >
748 mw->manager.num_slots)
750 /* Grow the list */
751 mw->manager.num_slots += XwBLOCK;
752 mw->manager.managed_children = (WidgetList)
753 XtRealloc ((caddr_t)mw->manager.managed_children,
754 (mw->manager.num_slots * sizeof(Widget)));
757 mw->manager.managed_children [mw->manager.num_managed_children++] =
758 mw->composite.children[i];
763 * In case this has been called during a SetValues on the pane,
764 * we want to make sure that both the new and old widgets get
765 * properly updated.
767 ((XwManagerWidget)mw->core.self)->manager.num_managed_children =
768 mw->manager.num_managed_children;
769 ((XwManagerWidget)mw->core.self)->manager.managed_children =
770 mw->manager.managed_children;
774 /*************************************<->*************************************
776 * SetTraversalFlag(parameters)
778 * Description:
779 * -----------
780 * xxxxxxxxxxxxxxxxxxxxxxx
783 * Inputs:
784 * ------
785 * xxxxxxxxxxxx = xxxxxxxxxxxxx
787 * Outputs:
788 * -------
789 * xxxxxxxxxxxx = xxxxxxxxxxxxx
791 * Procedures Called
792 * -----------------
794 *************************************<->***********************************/
796 static void SetTraversalFlag (w, enableFlag)
798 XwMenuPaneWidget w;
799 Boolean enableFlag;
802 w->manager.traversal_on = enableFlag;
804 if (enableFlag == True)
806 XtAugmentTranslations ((Widget)w, XwmanagerClassRec.manager_class.
807 translations);
808 w->core.widget_class->core_class.visible_interest = True;
813 /*************************************<->*************************************
815 * _XwAllAttachesAreSensitive(parameters)
817 * Description:
818 * -----------
819 * This functions verifies that the path from a menubutton back upto
820 * the top level menupane has no insensitive widgets (panes or buttons)
821 * in it.
824 * Inputs:
825 * ------
826 * xxxxxxxxxxxx = xxxxxxxxxxxxx
828 * Outputs:
829 * -------
830 * xxxxxxxxxxxx = xxxxxxxxxxxxx
832 * Procedures Called
833 * -----------------
835 *************************************<->***********************************/
837 Boolean _XwAllAttachesAreSensitive (menuBtn)
839 Widget menuBtn;
842 XwMenuPaneWidget parent;
844 while (menuBtn != NULL)
846 parent = (XwMenuPaneWidget)XtParent(menuBtn);
848 if (!XtIsSensitive((Widget)parent) || !XtIsSensitive(menuBtn))
849 return (False);
851 menuBtn = (Widget) parent->menu_pane.attachId;
854 return (True);