1 /* $XConsortium: SimpleMenu.c,v 1.44 94/04/17 20:12:45 kaleb Exp $ */
4 Copyright (c) 1989, 1994 X Consortium
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
29 * SimpleMenu.c - Source code file for SimpleMenu widget.
33 * By: Chris D. Peterson
35 * kit@expo.lcs.mit.edu
39 #include <X11/IntrinsicP.h>
40 #include <X11/StringDefs.h>
42 #include <X11/Xaw/XawInit.h>
43 #include <X11/Xaw/SimpleMenP.h>
44 #include <X11/Xaw/SmeBSB.h>
45 #include <X11/Xaw/Cardinals.h>
47 #include <X11/Xmu/Initer.h>
48 #include <X11/Xmu/CharSet.h>
50 #define streq(a, b) ( strcmp((a), (b)) == 0 )
52 #define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field)
54 static XtResource resources
[] = {
60 {XtNlabel
, XtCLabel
, XtRString
, sizeof(String
),
61 offset(label_string
), XtRString
, NULL
},
62 {XtNlabelClass
, XtCLabelClass
, XtRPointer
, sizeof(WidgetClass
),
63 offset(label_class
), XtRImmediate
, (XtPointer
) NULL
},
69 {XtNrowHeight
, XtCRowHeight
, XtRDimension
, sizeof(Dimension
),
70 offset(row_height
), XtRImmediate
, (XtPointer
) 0},
71 {XtNtopMargin
, XtCVerticalMargins
, XtRDimension
, sizeof(Dimension
),
72 offset(top_margin
), XtRImmediate
, (XtPointer
) 0},
73 {XtNbottomMargin
, XtCVerticalMargins
, XtRDimension
, sizeof(Dimension
),
74 offset(bottom_margin
), XtRImmediate
, (XtPointer
) 0},
80 { XtNallowShellResize
, XtCAllowShellResize
, XtRBoolean
, sizeof(Boolean
),
81 XtOffsetOf(SimpleMenuRec
, shell
.allow_shell_resize
),
82 XtRImmediate
, (XtPointer
) TRUE
},
83 {XtNcursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
84 offset(cursor
), XtRImmediate
, (XtPointer
) None
},
85 {XtNmenuOnScreen
, XtCMenuOnScreen
, XtRBoolean
, sizeof(Boolean
),
86 offset(menu_on_screen
), XtRImmediate
, (XtPointer
) TRUE
},
87 {XtNpopupOnEntry
, XtCPopupOnEntry
, XtRWidget
, sizeof(Widget
),
88 offset(popup_entry
), XtRWidget
, NULL
},
89 {XtNbackingStore
, XtCBackingStore
, XtRBackingStore
, sizeof (int),
90 offset(backing_store
),
91 XtRImmediate
, (XtPointer
) (Always
+ WhenMapped
+ NotUseful
)},
95 static char defaultTranslations
[] =
96 "<EnterWindow>: highlight() \n\
97 <LeaveWindow>: unhighlight() \n\
98 <BtnMotion>: highlight() \n\
99 <BtnUp>: MenuPopdown() notify() unhighlight()";
102 * Semi Public function definitions.
105 static void Redisplay(), Realize(), Resize(), ChangeManaged();
106 static void Initialize(), ClassInitialize(), ClassPartInitialize();
107 static Boolean
SetValues(), SetValuesHook();
108 static XtGeometryResult
GeometryManager();
111 * Action Routine Definitions
114 static void Highlight(), Unhighlight(), Notify(), PositionMenuAction();
117 * Private Function Definitions.
120 static void MakeSetValuesRequest(), CreateLabel(), Layout();
121 static void AddPositionAction(), PositionMenu(), ChangeCursorOnGrab();
122 static Dimension
GetMenuWidth(), GetMenuHeight();
123 static Widget
FindMenu();
124 static SmeObject
GetEventEntry();
125 static void MoveMenu();
127 static XtActionsRec actionsList
[] =
130 {"highlight", Highlight
},
131 {"unhighlight", Unhighlight
},
134 static CompositeClassExtensionRec extension_rec
= {
135 /* next_extension */ NULL
,
136 /* record_type */ NULLQUARK
,
137 /* version */ XtCompositeExtensionVersion
,
138 /* record_size */ sizeof(CompositeClassExtensionRec
),
139 /* accepts_objects */ TRUE
,
142 #define superclass (&overrideShellClassRec)
144 SimpleMenuClassRec simpleMenuClassRec
= {
146 /* superclass */ (WidgetClass
) superclass
,
147 /* class_name */ "SimpleMenu",
148 /* size */ sizeof(SimpleMenuRec
),
149 /* class_initialize */ ClassInitialize
,
150 /* class_part_initialize*/ ClassPartInitialize
,
151 /* Class init'ed */ FALSE
,
152 /* initialize */ Initialize
,
153 /* initialize_hook */ NULL
,
154 /* realize */ Realize
,
155 /* actions */ actionsList
,
156 /* num_actions */ XtNumber(actionsList
),
157 /* resources */ resources
,
158 /* resource_count */ XtNumber(resources
),
159 /* xrm_class */ NULLQUARK
,
160 /* compress_motion */ TRUE
,
161 /* compress_exposure */ TRUE
,
162 /* compress_enterleave*/ TRUE
,
163 /* visible_interest */ FALSE
,
166 /* expose */ Redisplay
,
167 /* set_values */ SetValues
,
168 /* set_values_hook */ SetValuesHook
,
169 /* set_values_almost */ XtInheritSetValuesAlmost
,
170 /* get_values_hook */ NULL
,
171 /* accept_focus */ NULL
,
172 /* intrinsics version */ XtVersion
,
173 /* callback offsets */ NULL
,
174 /* tm_table */ defaultTranslations
,
175 /* query_geometry */ NULL
,
176 /* display_accelerator*/ NULL
,
179 /* geometry_manager */ GeometryManager
,
180 /* change_managed */ ChangeManaged
,
181 /* insert_child */ XtInheritInsertChild
,
182 /* delete_child */ XtInheritDeleteChild
,
185 /* Shell extension */ NULL
187 /* Override extension */ NULL
189 /* Simple Menu extension*/ NULL
193 WidgetClass simpleMenuWidgetClass
= (WidgetClass
)&simpleMenuClassRec
;
195 #define ForAllChildren(smw, childP) \
196 for ( (childP) = (SmeObject *) (smw)->composite.children ; \
197 (childP) < (SmeObject *) ( (smw)->composite.children + \
198 (smw)->composite.num_children ) ; \
201 /************************************************************
203 * Semi-Public Functions.
205 ************************************************************/
207 /* Function Name: ClassInitialize
208 * Description: Class Initialize routine, called only once.
216 XawInitializeWidgetSet();
217 XtAddConverter( XtRString
, XtRBackingStore
, XmuCvtStringToBackingStore
,
218 (XtConvertArgList
)NULL
, (Cardinal
)0 );
219 XmuAddInitializer( AddPositionAction
, NULL
);
222 /* Function Name: ClassInitialize
223 * Description: Class Part Initialize routine, called for every
224 * subclass. Makes sure that the subclasses pick up
225 * the extension record.
226 * Arguments: wc - the widget class of the subclass.
231 ClassPartInitialize(wc
)
234 SimpleMenuWidgetClass smwc
= (SimpleMenuWidgetClass
) wc
;
237 * Make sure that our subclass gets the extension rec too.
240 extension_rec
.next_extension
= smwc
->composite_class
.extension
;
241 smwc
->composite_class
.extension
= (XtPointer
) &extension_rec
;
244 /* Function Name: Initialize
245 * Description: Initializes the simple menu widget
246 * Arguments: request - the widget requested by the argument list.
247 * new - the new widget with both resource and non
254 Initialize(request
, new, args
, num_args
)
259 SimpleMenuWidget smw
= (SimpleMenuWidget
) new;
261 XmuCallInitializers(XtWidgetToApplicationContext(new));
263 if (smw
->simple_menu
.label_class
== NULL
)
264 smw
->simple_menu
.label_class
= smeBSBObjectClass
;
266 smw
->simple_menu
.label
= NULL
;
267 smw
->simple_menu
.entry_set
= NULL
;
268 smw
->simple_menu
.recursive_set_values
= FALSE
;
270 if (smw
->simple_menu
.label_string
!= NULL
)
273 smw
->simple_menu
.menu_width
= TRUE
;
275 if (smw
->core
.width
== 0) {
276 smw
->simple_menu
.menu_width
= FALSE
;
277 smw
->core
.width
= GetMenuWidth(new, (Widget
)NULL
);
280 smw
->simple_menu
.menu_height
= TRUE
;
282 if (smw
->core
.height
== 0) {
283 smw
->simple_menu
.menu_height
= FALSE
;
284 smw
->core
.height
= GetMenuHeight(new);
288 * Add a popup_callback routine for changing the cursor.
291 XtAddCallback(new, XtNpopupCallback
, ChangeCursorOnGrab
, (XtPointer
)NULL
);
294 /* Function Name: Redisplay
295 * Description: Redisplays the contents of the widget.
296 * Arguments: w - the simple menu widget.
297 * event - the X event that caused this redisplay.
298 * region - the region the needs to be repainted.
304 Redisplay(w
, event
, region
)
309 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
311 SmeObjectClass
class;
314 XClearWindow(XtDisplay(w
), XtWindow(w
));
317 * Check and Paint each of the entries - including the label.
320 ForAllChildren(smw
, entry
) {
321 if (!XtIsManaged ( (Widget
) *entry
)) continue;
324 switch(XRectInRegion(region
, (int) (*entry
)->rectangle
.x
,
325 (int) (*entry
)->rectangle
.y
,
326 (unsigned int) (*entry
)->rectangle
.width
,
327 (unsigned int) (*entry
)->rectangle
.height
)) {
334 class = (SmeObjectClass
) (*entry
)->object
.widget_class
;
336 if (class->rect_class
.expose
!= NULL
)
337 (class->rect_class
.expose
)( (Widget
) *entry
, NULL
, NULL
);
341 /* Function Name: Realize
342 * Description: Realizes the widget.
343 * Arguments: w - the simple menu widget.
344 * mask - value mask for the window to create.
345 * attrs - attributes for the window to create.
350 Realize(w
, mask
, attrs
)
353 XSetWindowAttributes
* attrs
;
355 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
357 attrs
->cursor
= smw
->simple_menu
.cursor
;
359 if ((smw
->simple_menu
.backing_store
== Always
) ||
360 (smw
->simple_menu
.backing_store
== NotUseful
) ||
361 (smw
->simple_menu
.backing_store
== WhenMapped
) ) {
362 *mask
|= CWBackingStore
;
363 attrs
->backing_store
= smw
->simple_menu
.backing_store
;
366 *mask
&= ~CWBackingStore
;
368 (*superclass
->core_class
.realize
) (w
, mask
, attrs
);
371 /* Function Name: Resize
372 * Description: Handle the menu being resized bigger.
373 * Arguments: w - the simple menu widget.
381 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
384 if ( !XtIsRealized(w
) ) return;
386 ForAllChildren(smw
, entry
) /* reset width of all entries. */
387 if (XtIsManaged( (Widget
) *entry
))
388 (*entry
)->rectangle
.width
= smw
->core
.width
;
390 Redisplay(w
, (XEvent
*) NULL
, (Region
) NULL
);
393 /* Function Name: SetValues
394 * Description: Relayout the menu when one of the resources is changed.
395 * Arguments: current - current state of the widget.
396 * request - what was requested.
397 * new - what the widget will become.
403 SetValues(current
, request
, new, args
, num_args
)
404 Widget current
, request
, new;
408 SimpleMenuWidget smw_old
= (SimpleMenuWidget
) current
;
409 SimpleMenuWidget smw_new
= (SimpleMenuWidget
) new;
410 Boolean ret_val
= FALSE
, layout
= FALSE
;
412 if (!XtIsRealized(current
)) return(FALSE
);
414 if (!smw_new
->simple_menu
.recursive_set_values
) {
415 if (smw_new
->core
.width
!= smw_old
->core
.width
) {
416 smw_new
->simple_menu
.menu_width
= (smw_new
->core
.width
!= 0);
419 if (smw_new
->core
.height
!= smw_old
->core
.height
) {
420 smw_new
->simple_menu
.menu_height
= (smw_new
->core
.height
!= 0);
425 if (smw_old
->simple_menu
.cursor
!= smw_new
->simple_menu
.cursor
)
426 XDefineCursor(XtDisplay(new),
427 XtWindow(new), smw_new
->simple_menu
.cursor
);
429 if (smw_old
->simple_menu
.label_string
!=smw_new
->simple_menu
.label_string
)
430 if (smw_new
->simple_menu
.label_string
== NULL
) /* Destroy. */
431 XtDestroyWidget((Widget
) smw_old
->simple_menu
.label
);
432 else if (smw_old
->simple_menu
.label_string
== NULL
) /* Create. */
437 XtSetArg(arglist
[0], XtNlabel
, smw_new
->simple_menu
.label_string
);
438 XtSetValues((Widget
) smw_new
->simple_menu
.label
, arglist
, ONE
);
441 if (smw_old
->simple_menu
.label_class
!= smw_new
->simple_menu
.label_class
)
442 XtAppWarning(XtWidgetToApplicationContext(new),
443 "No Dynamic class change of the SimpleMenu Label.");
445 if ((smw_old
->simple_menu
.top_margin
!= smw_new
->simple_menu
.top_margin
) ||
446 (smw_old
->simple_menu
.bottom_margin
!=
447 smw_new
->simple_menu
.bottom_margin
) /* filler................. */ ) {
453 Layout(new, (Dimension
*)NULL
, (Dimension
*)NULL
);
458 /* Function Name: SetValuesHook
459 * Description: To handle a special case, this is passed the
461 * Arguments: w - the menu widget.
462 * arglist - the argument list passed to XtSetValues.
463 * num_args - the number of args.
468 * If the user actually passed a width and height to the widget
469 * then this MUST be used, rather than our newly calculated width and
474 SetValuesHook(w
, arglist
, num_args
)
480 Dimension width
, height
;
482 width
= w
->core
.width
;
483 height
= w
->core
.height
;
485 for ( i
= 0 ; i
< *num_args
; i
++) {
486 if ( streq(arglist
[i
].name
, XtNwidth
) )
487 width
= (Dimension
) arglist
[i
].value
;
488 if ( streq(arglist
[i
].name
, XtNheight
) )
489 height
= (Dimension
) arglist
[i
].value
;
492 if ((width
!= w
->core
.width
) || (height
!= w
->core
.height
))
493 MakeSetValuesRequest(w
, width
, height
);
497 /************************************************************
499 * Geometry Management routines.
501 ************************************************************/
503 /* Function Name: GeometryManager
504 * Description: This is the SimpleMenu Widget's Geometry Manager.
505 * Arguments: w - the Menu Entry making the request.
506 * request - requested new geometry.
507 * reply - the allowed geometry.
508 * Returns: XtGeometry{Yes, No, Almost}.
511 static XtGeometryResult
512 GeometryManager(w
, request
, reply
)
514 XtWidgetGeometry
* request
, * reply
;
516 SimpleMenuWidget smw
= (SimpleMenuWidget
) XtParent(w
);
517 SmeObject entry
= (SmeObject
) w
;
518 XtGeometryMask mode
= request
->request_mode
;
519 XtGeometryResult answer
;
520 Dimension old_height
, old_width
;
522 if ( !(mode
& CWWidth
) && !(mode
& CWHeight
) )
523 return(XtGeometryNo
);
525 reply
->width
= request
->width
;
526 reply
->height
= request
->height
;
528 old_width
= entry
->rectangle
.width
;
529 old_height
= entry
->rectangle
.height
;
531 Layout(w
, &(reply
->width
), &(reply
->height
) );
534 * Since we are an override shell and have no parent there is no one to
535 * ask to see if this geom change is okay, so I am just going to assume
536 * we can do whatever we want. If you subclass be very careful with this
537 * assumption, it could bite you.
539 * Chris D. Peterson - Sept. 1989.
542 if ( (reply
->width
== request
->width
) &&
543 (reply
->height
== request
->height
) ) {
545 if ( mode
& XtCWQueryOnly
) { /* Actually perform the layout. */
546 entry
->rectangle
.width
= old_width
;
547 entry
->rectangle
.height
= old_height
;
550 Layout(( Widget
) smw
, (Dimension
*)NULL
, (Dimension
*)NULL
);
552 answer
= XtGeometryDone
;
555 entry
->rectangle
.width
= old_width
;
556 entry
->rectangle
.height
= old_height
;
558 if ( ((reply
->width
== request
->width
) && !(mode
& CWHeight
)) ||
559 ((reply
->height
== request
->height
) && !(mode
& CWWidth
)) ||
560 ((reply
->width
== request
->width
) &&
561 (reply
->height
== request
->height
)) )
562 answer
= XtGeometryNo
;
564 answer
= XtGeometryAlmost
;
565 reply
->request_mode
= 0;
566 if (reply
->width
!= request
->width
)
567 reply
->request_mode
|= CWWidth
;
568 if (reply
->height
!= request
->height
)
569 reply
->request_mode
|= CWHeight
;
575 /* Function Name: ChangeManaged
576 * Description: called whenever a new child is managed.
577 * Arguments: w - the simple menu widget.
585 Layout(w
, (Dimension
*)NULL
, (Dimension
*)NULL
);
588 /************************************************************
590 * Global Action Routines.
592 * These actions routines will be added to the application's
593 * global action list.
595 ************************************************************/
597 /* Function Name: PositionMenuAction
598 * Description: Positions the simple menu widget.
599 * Arguments: w - a widget (no the simple menu widget.)
600 * event - the event that caused this action.
601 * params, num_params - parameters passed to the routine.
602 * we expect the name of the menu here.
608 PositionMenuAction(w
, event
, params
, num_params
)
612 Cardinal
* num_params
;
616 char error_buf
[BUFSIZ
];
619 char* fmt
= "Xaw SimpleMenuWidget: could not find menu named: \"%s\"";
621 if (*num_params
!= 1) {
622 char error_buf
[BUFSIZ
];
623 (void) sprintf(error_buf
, "%s %s",
624 "Xaw - SimpleMenuWidget: position menu action expects only one",
625 "parameter which is the name of the menu.");
626 XtAppWarning(XtWidgetToApplicationContext(w
),
627 "Xaw - SimpleMenuWidget: position menu action expects only one parameter which is the name of the menu.");
631 if ( (menu
= FindMenu(w
, params
[0])) == NULL
) {
632 if ((len
= strlen (fmt
) + strlen (params
[0])) < sizeof error_buf
)
635 ebp
= XtMalloc (len
+ 1);
638 strcpy (ebp
, "Xaw - SimpleMenuWidget: could not find menu");
640 (void) sprintf(ebp
, fmt
, params
[0]);
641 XtAppWarning(XtWidgetToApplicationContext(w
), ebp
);
642 if (ebp
!= error_buf
) XtFree (ebp
);
646 switch (event
->type
) {
649 loc
.x
= event
->xbutton
.x_root
;
650 loc
.y
= event
->xbutton
.y_root
;
651 PositionMenu(menu
, &loc
);
655 loc
.x
= event
->xcrossing
.x_root
;
656 loc
.y
= event
->xcrossing
.y_root
;
657 PositionMenu(menu
, &loc
);
660 loc
.x
= event
->xmotion
.x_root
;
661 loc
.y
= event
->xmotion
.y_root
;
662 PositionMenu(menu
, &loc
);
665 PositionMenu(menu
, (XPoint
*)NULL
);
670 /************************************************************
672 * Widget Action Routines.
674 ************************************************************/
676 /* Function Name: Unhighlight
677 * Description: Unhighlights current entry.
678 * Arguments: w - the simple menu widget.
679 * event - the event that caused this action.
680 * params, num_params - ** NOT USED **
686 Unhighlight(w
, event
, params
, num_params
)
690 Cardinal
* num_params
;
692 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
693 SmeObject entry
= smw
->simple_menu
.entry_set
;
694 SmeObjectClass
class;
696 if ( entry
== NULL
) return;
698 smw
->simple_menu
.entry_set
= NULL
;
699 class = (SmeObjectClass
) entry
->object
.widget_class
;
700 (class->sme_class
.unhighlight
) ( (Widget
) entry
);
703 /* Function Name: Highlight
704 * Description: Highlights current entry.
705 * Arguments: w - the simple menu widget.
706 * event - the event that caused this action.
707 * params, num_params - ** NOT USED **
713 Highlight(w
, event
, params
, num_params
)
717 Cardinal
* num_params
;
719 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
721 SmeObjectClass
class;
723 if ( !XtIsSensitive(w
) ) return;
725 entry
= GetEventEntry(w
, event
);
727 if (entry
== smw
->simple_menu
.entry_set
) return;
729 Unhighlight(w
, event
, params
, num_params
);
731 if (entry
== NULL
) return;
733 if ( !XtIsSensitive( (Widget
) entry
)) {
734 smw
->simple_menu
.entry_set
= NULL
;
738 smw
->simple_menu
.entry_set
= entry
;
739 class = (SmeObjectClass
) entry
->object
.widget_class
;
741 (class->sme_class
.highlight
) ( (Widget
) entry
);
744 /* Function Name: Notify
745 * Description: Notify user of current entry.
746 * Arguments: w - the simple menu widget.
747 * event - the event that caused this action.
748 * params, num_params - ** NOT USED **
754 Notify(w
, event
, params
, num_params
)
758 Cardinal
* num_params
;
760 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
761 SmeObject entry
= smw
->simple_menu
.entry_set
;
762 SmeObjectClass
class;
764 if ( (entry
== NULL
) || !XtIsSensitive((Widget
) entry
) ) return;
766 class = (SmeObjectClass
) entry
->object
.widget_class
;
767 (class->sme_class
.notify
)( (Widget
) entry
);
770 /************************************************************
774 ************************************************************/
776 /* Function Name: XawSimpleMenuAddGlobalActions
777 * Description: adds the global actions to the simple menu widget.
778 * Arguments: app_con - the appcontext.
783 #if NeedFunctionPrototypes
784 XawSimpleMenuAddGlobalActions(XtAppContext app_con
)
786 XawSimpleMenuAddGlobalActions(app_con
)
787 XtAppContext app_con
;
790 XtInitializeWidgetClass(simpleMenuWidgetClass
);
791 XmuCallInitializers( app_con
);
795 /* Function Name: XawSimpleMenuGetActiveEntry
796 * Description: Gets the currently active (set) entry.
797 * Arguments: w - the smw widget.
798 * Returns: the currently set entry or NULL if none is set.
802 #if NeedFunctionPrototypes
803 XawSimpleMenuGetActiveEntry(Widget w
)
805 XawSimpleMenuGetActiveEntry(w
)
809 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
811 return( (Widget
) smw
->simple_menu
.entry_set
);
814 /* Function Name: XawSimpleMenuClearActiveEntry
815 * Description: Unsets the currently active (set) entry.
816 * Arguments: w - the smw widget.
821 #if NeedFunctionPrototypes
822 XawSimpleMenuClearActiveEntry(Widget w
)
824 XawSimpleMenuClearActiveEntry(w
)
828 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
830 smw
->simple_menu
.entry_set
= NULL
;
833 /************************************************************
837 ************************************************************/
839 /* Function Name: CreateLabel
840 * Description: Creates a the menu label.
841 * Arguments: w - the smw widget.
844 * Creates the label object and makes sure it is the first child in
852 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
853 Widget
* child
, * next_child
;
857 if ( (smw
->simple_menu
.label_string
== NULL
) ||
858 (smw
->simple_menu
.label
!= NULL
) ) {
859 char error_buf
[BUFSIZ
];
861 (void) sprintf(error_buf
, "Xaw Simple Menu Widget: %s or %s, %s",
862 "label string is NULL", "label already exists",
863 "no label is being created.");
864 XtAppWarning(XtWidgetToApplicationContext(w
), error_buf
);
868 XtSetArg(args
[0], XtNlabel
, smw
->simple_menu
.label_string
);
869 XtSetArg(args
[1], XtNjustify
, XtJustifyCenter
);
870 smw
->simple_menu
.label
= (SmeObject
)
871 XtCreateManagedWidget("menuLabel",
872 smw
->simple_menu
.label_class
, w
,
876 for (child
= smw
->composite
.children
+ smw
->composite
.num_children
,
877 i
= smw
->composite
.num_children
; i
> 0 ; i
--, child
--) {
878 if (next_child
!= NULL
)
879 *next_child
= *child
;
882 *child
= (Widget
) smw
->simple_menu
.label
;
885 /* Function Name: Layout
886 * Description: lays the menu entries out all nice and neat.
887 * Arguments: w - See below (+++)
888 * width_ret, height_ret - The returned width and
892 * if width == NULL || height == NULL then it assumes the you do not care
893 * about the return values, and just want a relayout.
895 * if this is not the case then it will set width_ret and height_ret
896 * to be width and height that the child would get if it were layed out
899 * +++ "w" can be the simple menu widget or any of its object children.
903 Layout(w
, width_ret
, height_ret
)
905 Dimension
*width_ret
, *height_ret
;
907 SmeObject current_entry
, *entry
;
908 SimpleMenuWidget smw
;
909 Dimension width
, height
;
910 Boolean do_layout
= ((height_ret
== NULL
) || (width_ret
== NULL
));
911 Boolean allow_change_size
;
914 if ( XtIsSubclass(w
, simpleMenuWidgetClass
) ) {
915 smw
= (SimpleMenuWidget
) w
;
916 current_entry
= NULL
;
919 smw
= (SimpleMenuWidget
) XtParent(w
);
920 current_entry
= (SmeObject
) w
;
923 allow_change_size
= (!XtIsRealized((Widget
)smw
) ||
924 (smw
->shell
.allow_shell_resize
));
926 if ( smw
->simple_menu
.menu_height
)
927 height
= smw
->core
.height
;
930 height
= smw
->simple_menu
.top_margin
;
931 ForAllChildren(smw
, entry
) {
932 if (!XtIsManaged( (Widget
) *entry
)) continue;
934 if ( (smw
->simple_menu
.row_height
!= 0) &&
935 (*entry
!= smw
->simple_menu
.label
) )
936 (*entry
)->rectangle
.height
= smw
->simple_menu
.row_height
;
938 (*entry
)->rectangle
.y
= height
;
939 (*entry
)->rectangle
.x
= 0;
940 height
+= (*entry
)->rectangle
.height
;
942 height
+= smw
->simple_menu
.bottom_margin
;
945 if ((smw
->simple_menu
.row_height
!= 0) &&
946 (current_entry
!= smw
->simple_menu
.label
) )
947 height
= smw
->simple_menu
.row_height
;
950 if (smw
->simple_menu
.menu_width
)
951 width
= smw
->core
.width
;
952 else if ( allow_change_size
)
953 width
= GetMenuWidth((Widget
) smw
, (Widget
) current_entry
);
955 width
= smw
->core
.width
;
958 ForAllChildren(smw
, entry
)
959 if (XtIsManaged( (Widget
) *entry
))
960 (*entry
)->rectangle
.width
= width
;
962 if (allow_change_size
)
963 MakeSetValuesRequest((Widget
) smw
, width
, height
);
968 *height_ret
= height
;
972 /* Function Name: AddPositionAction
973 * Description: Adds the XawPositionSimpleMenu action to the global
974 * action list for this appcon.
975 * Arguments: app_con - the application context for this app.
982 AddPositionAction(app_con
, data
)
983 XtAppContext app_con
;
986 static XtActionsRec pos_action
[] = {
987 { "XawPositionSimpleMenu", PositionMenuAction
},
990 XtAppAddActions(app_con
, pos_action
, XtNumber(pos_action
));
993 /* Function Name: FindMenu
994 * Description: Find the menu give a name and reference widget.
995 * Arguments: widget - reference widget.
996 * name - the menu widget's name.
997 * Returns: the menu widget or NULL.
1001 FindMenu(widget
, name
)
1007 for ( w
= widget
; w
!= NULL
; w
= XtParent(w
) )
1008 if ( (menu
= XtNameToWidget(w
, name
)) != NULL
)
1013 /* Function Name: PositionMenu
1014 * Description: Places the menu
1015 * Arguments: w - the simple menu widget.
1016 * location - a pointer the the position or NULL.
1021 PositionMenu(w
, location
)
1025 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1029 if (location
== NULL
) {
1030 Window junk1
, junk2
;
1031 int root_x
, root_y
, junkX
, junkY
;
1034 location
= &t_point
;
1035 if (XQueryPointer(XtDisplay(w
), XtWindow(w
), &junk1
, &junk2
,
1036 &root_x
, &root_y
, &junkX
, &junkY
, &junkM
) == FALSE
) {
1037 char error_buf
[BUFSIZ
];
1038 (void) sprintf(error_buf
, "%s %s", "Xaw Simple Menu Widget:",
1039 "Could not find location of mouse pointer");
1040 XtAppWarning(XtWidgetToApplicationContext(w
), error_buf
);
1043 location
->x
= (short) root_x
;
1044 location
->y
= (short) root_y
;
1048 * The width will not be correct unless it is realized.
1053 location
->x
-= (Position
) w
->core
.width
/2;
1055 if (smw
->simple_menu
.popup_entry
== NULL
)
1056 entry
= smw
->simple_menu
.label
;
1058 entry
= smw
->simple_menu
.popup_entry
;
1061 location
->y
-= entry
->rectangle
.y
+ entry
->rectangle
.height
/2;
1063 MoveMenu(w
, (Position
) location
->x
, (Position
) location
->y
);
1066 /* Function Name: MoveMenu
1067 * Description: Actually moves the menu, may force it to
1068 * to be fully visable if menu_on_screen is TRUE.
1069 * Arguments: w - the simple menu widget.
1070 * x, y - the current location of the widget.
1080 Cardinal num_args
= 0;
1081 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1083 if (smw
->simple_menu
.menu_on_screen
) {
1084 int width
= w
->core
.width
+ 2 * w
->core
.border_width
;
1085 int height
= w
->core
.height
+ 2 * w
->core
.border_width
;
1088 int scr_width
= WidthOfScreen(XtScreen(w
));
1089 if (x
+ width
> scr_width
)
1090 x
= scr_width
- width
;
1096 int scr_height
= HeightOfScreen(XtScreen(w
));
1097 if (y
+ height
> scr_height
)
1098 y
= scr_height
- height
;
1104 XtSetArg(arglist
[num_args
], XtNx
, x
); num_args
++;
1105 XtSetArg(arglist
[num_args
], XtNy
, y
); num_args
++;
1106 XtSetValues(w
, arglist
, num_args
);
1109 /* Function Name: ChangeCursorOnGrab
1110 * Description: Changes the cursor on the active grab to the one
1111 * specified in out resource list.
1112 * Arguments: w - the widget.
1113 * junk, garbage - ** NOT USED **.
1119 ChangeCursorOnGrab(w
, junk
, garbage
)
1121 XtPointer junk
, garbage
;
1123 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1126 * The event mask here is what is currently in the MIT implementation.
1127 * There really needs to be a way to get the value of the mask out
1128 * of the toolkit (CDP 5/26/89).
1131 XChangeActivePointerGrab(XtDisplay(w
), ButtonPressMask
|ButtonReleaseMask
,
1132 smw
->simple_menu
.cursor
,
1133 XtLastTimestampProcessed(XtDisplay(w
)));
1136 /* Function Name: MakeSetValuesRequest
1137 * Description: Makes a (possibly recursive) call to SetValues,
1138 * I take great pains to not go into an infinite loop.
1139 * Arguments: w - the simple menu widget.
1140 * width, height - the size of the ask for.
1145 MakeSetValuesRequest(w
, width
, height
)
1147 Dimension width
, height
;
1149 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1151 Cardinal num_args
= (Cardinal
) 0;
1153 if ( !smw
->simple_menu
.recursive_set_values
) {
1154 if ( (smw
->core
.width
!= width
) || (smw
->core
.height
!= height
) ) {
1155 smw
->simple_menu
.recursive_set_values
= TRUE
;
1156 XtSetArg(arglist
[num_args
], XtNwidth
, width
); num_args
++;
1157 XtSetArg(arglist
[num_args
], XtNheight
, height
); num_args
++;
1158 XtSetValues(w
, arglist
, num_args
);
1160 else if (XtIsRealized( (Widget
) smw
))
1161 Redisplay((Widget
) smw
, (XEvent
*) NULL
, (Region
) NULL
);
1163 smw
->simple_menu
.recursive_set_values
= FALSE
;
1166 /* Function Name: GetMenuWidth
1167 * Description: Sets the length of the widest entry in pixels.
1168 * Arguments: w - the simple menu widget.
1169 * Returns: width of menu.
1173 GetMenuWidth(w
, w_ent
)
1176 SmeObject cur_entry
= (SmeObject
) w_ent
;
1177 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1178 Dimension width
, widest
= (Dimension
) 0;
1181 if ( smw
->simple_menu
.menu_width
)
1182 return(smw
->core
.width
);
1184 ForAllChildren(smw
, entry
) {
1185 XtWidgetGeometry preferred
;
1187 if (!XtIsManaged( (Widget
) *entry
)) continue;
1189 if (*entry
!= cur_entry
) {
1190 XtQueryGeometry((Widget
) *entry
, (XtWidgetGeometry
*)NULL
, &preferred
);
1192 if (preferred
.request_mode
& CWWidth
)
1193 width
= preferred
.width
;
1195 width
= (*entry
)->rectangle
.width
;
1198 width
= (*entry
)->rectangle
.width
;
1200 if ( width
> widest
)
1207 /* Function Name: GetMenuHeight
1208 * Description: Sets the length of the widest entry in pixels.
1209 * Arguments: w - the simple menu widget.
1210 * Returns: width of menu.
1217 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1221 if (smw
->simple_menu
.menu_height
)
1222 return(smw
->core
.height
);
1224 height
= smw
->simple_menu
.top_margin
+ smw
->simple_menu
.bottom_margin
;
1226 if (smw
->simple_menu
.row_height
== 0) {
1227 ForAllChildren(smw
, entry
)
1228 if (XtIsManaged ((Widget
) *entry
))
1229 height
+= (*entry
)->rectangle
.height
;
1231 height
+= smw
->simple_menu
.row_height
* smw
->composite
.num_children
;
1236 /* Function Name: GetEventEntry
1237 * Description: Gets an entry given an event that has X and Y coords.
1238 * Arguments: w - the simple menu widget.
1239 * event - the event.
1240 * Returns: the entry that this point is in.
1244 GetEventEntry(w
, event
)
1248 Position x_loc
, y_loc
;
1249 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1252 switch (event
->type
) {
1254 x_loc
= event
->xmotion
.x
;
1255 y_loc
= event
->xmotion
.y
;
1259 x_loc
= event
->xcrossing
.x
;
1260 y_loc
= event
->xcrossing
.y
;
1264 x_loc
= event
->xbutton
.x
;
1265 y_loc
= event
->xbutton
.y
;
1268 XtAppError(XtWidgetToApplicationContext(w
),
1269 "Unknown event type in GetEventEntry().");
1273 if ( (x_loc
< 0) || (x_loc
>= (int)smw
->core
.width
) || (y_loc
< 0) ||
1274 (y_loc
>= (int)smw
->core
.height
) )
1277 ForAllChildren(smw
, entry
) {
1278 if (!XtIsManaged ((Widget
) *entry
)) continue;
1280 if ( ((*entry
)->rectangle
.y
< y_loc
) &&
1281 ((*entry
)->rectangle
.y
+ (int) (*entry
)->rectangle
.height
> y_loc
) )
1282 if ( *entry
== smw
->simple_menu
.label
)
1283 return(NULL
); /* cannot select the label. */