1 #if ( !defined(lint) && !defined(SABER) )
2 static char Xrcsid
[] = "$XConsortium: SimpleMenu.c,v 1.32 89/12/11 15:01:50 kit Exp $";
6 * Copyright 1989 Massachusetts Institute of Technology
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of M.I.T. not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. M.I.T. makes no representations about the
15 * suitability of this software for any purpose. It is provided "as is"
16 * without express or implied warranty.
18 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
20 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 * SimpleMenu.c - Source code file for SimpleMenu widget.
31 * By: Chris D. Peterson
33 * kit@expo.lcs.mit.edu
37 #include <X11/IntrinsicP.h>
38 #include <X11/StringDefs.h>
40 #include <./Xaw3_1XawInit.h>
41 #include <./Xaw3_1SimpleMenP.h>
42 #include <./Xaw3_1SmeBSB.h>
43 #include <./Xaw3_1Cardinals.h>
45 #include <X11/Xmu/Initer.h>
46 #include <X11/Xmu/CharSet.h>
48 #define streq(a, b) ( strcmp((a), (b)) == 0 )
50 #define offset(field) XtOffset(SimpleMenuWidget, simple_menu.field)
52 static XtResource resources
[] = {
58 {XtNlabel
, XtCLabel
, XtRString
, sizeof(String
),
59 offset(label_string
), XtRString
, NULL
},
60 {XtNlabelClass
, XtCLabelClass
, XtRPointer
, sizeof(WidgetClass
),
61 offset(label_class
), XtRImmediate
, (caddr_t
) NULL
},
67 {XtNrowHeight
, XtCRowHeight
, XtRDimension
, sizeof(Dimension
),
68 offset(row_height
), XtRImmediate
, (caddr_t
) 0},
69 {XtNtopMargin
, XtCVerticalMargins
, XtRDimension
, sizeof(Dimension
),
70 offset(top_margin
), XtRImmediate
, (caddr_t
) 0},
71 {XtNbottomMargin
, XtCVerticalMargins
, XtRDimension
, sizeof(Dimension
),
72 offset(bottom_margin
), XtRImmediate
, (caddr_t
) 0},
78 { XtNallowShellResize
, XtCAllowShellResize
, XtRBoolean
, sizeof(Boolean
),
79 XtOffset(SimpleMenuWidget
, shell
.allow_shell_resize
),
80 XtRImmediate
, (XtPointer
) TRUE
},
81 {XtNcursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
82 offset(cursor
), XtRImmediate
, (caddr_t
) None
},
83 {XtNmenuOnScreen
, XtCMenuOnScreen
, XtRBoolean
, sizeof(Boolean
),
84 offset(menu_on_screen
), XtRImmediate
, (caddr_t
) TRUE
},
85 {XtNpopupOnEntry
, XtCPopupOnEntry
, XtRWidget
, sizeof(Widget
),
86 offset(popup_entry
), XtRWidget
, NULL
},
87 {XtNbackingStore
, XtCBackingStore
, XtRBackingStore
, sizeof (int),
88 offset(backing_store
),
89 XtRImmediate
, (caddr_t
) (Always
+ WhenMapped
+ NotUseful
)},
93 static char defaultTranslations
[] =
94 "<EnterWindow>: highlight() \n\
95 <LeaveWindow>: unhighlight() \n\
96 <BtnMotion>: highlight() \n\
97 <BtnUp>: MenuPopdown() notify() unhighlight()";
100 * Semi Public function definitions.
103 static void Redisplay(), Realize(), Resize(), ChangeManaged();
104 static void Initialize(), ClassInitialize(), ClassPartInitialize();
105 static Boolean
SetValues(), SetValuesHook();
106 static XtGeometryResult
GeometryManager();
109 * Action Routine Definitions
112 static void Highlight(), Unhighlight(), Notify(), PositionMenuAction();
115 * Private Function Definitions.
118 static void MakeSetValuesRequest(), CreateLabel(), Layout();
119 static void AddPositionAction(), PositionMenu(), ChangeCursorOnGrab();
120 static Dimension
GetMenuWidth(), GetMenuHeight();
121 static Widget
FindMenu();
122 static SmeObject
GetEventEntry();
124 static XtActionsRec actionsList
[] =
127 {"highlight", Highlight
},
128 {"unhighlight", Unhighlight
},
131 CompositeClassExtensionRec extension_rec
= {
132 /* next_extension */ NULL
,
133 /* record_type */ NULLQUARK
,
134 /* version */ XtCompositeExtensionVersion
,
135 /* record_size */ sizeof(CompositeClassExtensionRec
),
136 /* accepts_objects */ TRUE
,
139 #define superclass (&overrideShellClassRec)
141 SimpleMenuClassRec simpleMenuClassRec
= {
143 /* superclass */ (WidgetClass
) superclass
,
144 /* class_name */ "SimpleMenu",
145 /* size */ sizeof(SimpleMenuRec
),
146 /* class_initialize */ ClassInitialize
,
147 /* class_part_initialize*/ ClassPartInitialize
,
148 /* Class init'ed */ FALSE
,
149 /* initialize */ Initialize
,
150 /* initialize_hook */ NULL
,
151 /* realize */ Realize
,
152 /* actions */ actionsList
,
153 /* num_actions */ XtNumber(actionsList
),
154 /* resources */ resources
,
155 /* resource_count */ XtNumber(resources
),
156 /* xrm_class */ NULLQUARK
,
157 /* compress_motion */ TRUE
,
158 /* compress_exposure */ TRUE
,
159 /* compress_enterleave*/ TRUE
,
160 /* visible_interest */ FALSE
,
163 /* expose */ Redisplay
,
164 /* set_values */ SetValues
,
165 /* set_values_hook */ SetValuesHook
,
166 /* set_values_almost */ XtInheritSetValuesAlmost
,
167 /* get_values_hook */ NULL
,
168 /* accept_focus */ NULL
,
169 /* intrinsics version */ XtVersion
,
170 /* callback offsets */ NULL
,
171 /* tm_table */ defaultTranslations
,
172 /* query_geometry */ NULL
,
173 /* display_accelerator*/ NULL
,
176 /* geometry_manager */ GeometryManager
,
177 /* change_managed */ ChangeManaged
,
178 /* insert_child */ XtInheritInsertChild
,
179 /* delete_child */ XtInheritDeleteChild
,
182 /* Shell extension */ NULL
184 /* Override extension */ NULL
186 /* Simple Menu extension*/ NULL
190 WidgetClass simpleMenuWidgetClass
= (WidgetClass
)&simpleMenuClassRec
;
192 /************************************************************
194 * Semi-Public Functions.
196 ************************************************************/
198 /* Function Name: ClassInitialize
199 * Description: Class Initialize routine, called only once.
207 XawInitializeWidgetSet();
208 XtAddConverter( XtRString
, XtRBackingStore
, XmuCvtStringToBackingStore
,
210 XmuAddInitializer( AddPositionAction
, NULL
);
213 /* Function Name: ClassInitialize
214 * Description: Class Part Initialize routine, called for every
215 * subclass. Makes sure that the subclasses pick up
216 * the extension record.
217 * Arguments: wc - the widget class of the subclass.
222 ClassPartInitialize(wc
)
225 SimpleMenuWidgetClass smwc
= (SimpleMenuWidgetClass
) wc
;
228 * Make sure that our subclass gets the extension rec too.
231 extension_rec
.next_extension
= smwc
->composite_class
.extension
;
232 smwc
->composite_class
.extension
= (caddr_t
) &extension_rec
;
235 /* Function Name: Initialize
236 * Description: Initializes the simple menu widget
237 * Arguments: request - the widget requested by the argument list.
238 * new - the new widget with both resource and non
245 Initialize(request
, new)
248 SimpleMenuWidget smw
= (SimpleMenuWidget
) new;
250 XmuCallInitializers(XtWidgetToApplicationContext(new));
252 if (smw
->simple_menu
.label_class
== NULL
)
253 smw
->simple_menu
.label_class
= smeBSBObjectClass
;
255 smw
->simple_menu
.label
= NULL
;
256 smw
->simple_menu
.entry_set
= NULL
;
257 smw
->simple_menu
.recursive_set_values
= FALSE
;
259 if (smw
->simple_menu
.label_string
!= NULL
)
262 smw
->simple_menu
.menu_width
= TRUE
;
264 if (smw
->core
.width
== 0) {
265 smw
->simple_menu
.menu_width
= FALSE
;
266 smw
->core
.width
= GetMenuWidth(new, NULL
);
269 smw
->simple_menu
.menu_height
= TRUE
;
271 if (smw
->core
.height
== 0) {
272 smw
->simple_menu
.menu_height
= FALSE
;
273 smw
->core
.height
= GetMenuHeight(new);
277 * Add a popup_callback routine for changing the cursor.
280 XtAddCallback(new, XtNpopupCallback
, ChangeCursorOnGrab
, NULL
);
283 /* Function Name: Redisplay
284 * Description: Redisplays the contents of the widget.
285 * Arguments: w - the simple menu widget.
286 * event - the X event that caused this redisplay.
287 * region - the region the needs to be repainted.
293 Redisplay(w
, event
, region
)
298 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
300 SmeObjectClass
class;
303 XClearWindow(XtDisplay(w
), XtWindow(w
));
306 * Check and Paint each of the entries - including the label.
309 ForAllChildren(smw
, entry
) {
310 if (!XtIsManaged ( (Widget
) *entry
)) continue;
313 switch(XRectInRegion(region
, (int) (*entry
)->rectangle
.x
,
314 (int) (*entry
)->rectangle
.y
,
315 (unsigned int) (*entry
)->rectangle
.width
,
316 (unsigned int) (*entry
)->rectangle
.height
)) {
323 class = (SmeObjectClass
) (*entry
)->object
.widget_class
;
325 if (class->rect_class
.expose
!= NULL
)
326 (class->rect_class
.expose
)( (Widget
) *entry
, NULL
, NULL
);
330 /* Function Name: Realize
331 * Description: Realizes the widget.
332 * Arguments: w - the simple menu widget.
333 * mask - value mask for the window to create.
334 * attrs - attributes for the window to create.
339 Realize(w
, mask
, attrs
)
342 XSetWindowAttributes
* attrs
;
344 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
346 attrs
->cursor
= smw
->simple_menu
.cursor
;
348 if ((smw
->simple_menu
.backing_store
== Always
) ||
349 (smw
->simple_menu
.backing_store
== NotUseful
) ||
350 (smw
->simple_menu
.backing_store
== WhenMapped
) ) {
351 *mask
|= CWBackingStore
;
352 attrs
->backing_store
= smw
->simple_menu
.backing_store
;
355 *mask
&= ~CWBackingStore
;
357 (*superclass
->core_class
.realize
) (w
, mask
, attrs
);
360 /* Function Name: Resize
361 * Description: Handle the menu being resized bigger.
362 * Arguments: w - the simple menu widget.
370 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
373 if ( !XtIsRealized(w
) ) return;
375 ForAllChildren(smw
, entry
) /* reset width of all entries. */
376 if (XtIsManaged( (Widget
) *entry
))
377 (*entry
)->rectangle
.width
= smw
->core
.width
;
379 Redisplay(w
, (XEvent
*) NULL
, (Region
) NULL
);
382 /* Function Name: SetValues
383 * Description: Relayout the menu when one of the resources is changed.
384 * Arguments: current - current state of the widget.
385 * request - what was requested.
386 * new - what the widget will become.
392 SetValues(current
, request
, new)
393 Widget current
, request
, new;
395 SimpleMenuWidget smw_old
= (SimpleMenuWidget
) current
;
396 SimpleMenuWidget smw_new
= (SimpleMenuWidget
) new;
397 Boolean ret_val
= FALSE
, layout
= FALSE
;
399 if (!XtIsRealized(current
)) return(FALSE
);
401 if (!smw_new
->simple_menu
.recursive_set_values
) {
402 if (smw_new
->core
.width
!= smw_old
->core
.width
) {
403 smw_new
->simple_menu
.menu_width
= (smw_new
->core
.width
!= 0);
406 if (smw_new
->core
.height
!= smw_old
->core
.height
) {
407 smw_new
->simple_menu
.menu_height
= (smw_new
->core
.height
!= 0);
412 if (smw_old
->simple_menu
.cursor
!= smw_new
->simple_menu
.cursor
)
413 XDefineCursor(XtDisplay(new),
414 XtWindow(new), smw_new
->simple_menu
.cursor
);
416 if (smw_old
->simple_menu
.label_string
!=smw_new
->simple_menu
.label_string
)
417 if (smw_new
->simple_menu
.label_string
== NULL
) /* Destroy. */
418 XtDestroyWidget((Widget
)smw_old
->simple_menu
.label
);
419 else if (smw_old
->simple_menu
.label_string
== NULL
) /* Create. */
424 XtSetArg(args
[0], XtNlabel
, smw_new
->simple_menu
.label_string
);
425 XtSetValues((Widget
)smw_new
->simple_menu
.label
, args
, ONE
);
428 if (smw_old
->simple_menu
.label_class
!= smw_new
->simple_menu
.label_class
)
429 XtAppWarning(XtWidgetToApplicationContext(new),
430 "No Dynamic class change of the SimpleMenu Label.");
432 if ((smw_old
->simple_menu
.top_margin
!= smw_new
->simple_menu
.top_margin
) ||
433 (smw_old
->simple_menu
.bottom_margin
!=
434 smw_new
->simple_menu
.bottom_margin
) /* filler................. */ ) {
440 Layout(new, NULL
, NULL
);
445 /* Function Name: SetValuesHook
446 * Description: To handle a special case, this is passed the
448 * Arguments: w - the menu widget.
449 * arglist - the argument list passed to XtSetValues.
450 * num_args - the number of args.
455 * If the user actually passed a width and height to the widget
456 * then this MUST be used, rather than our newly calculated width and
461 SetValuesHook(w
, arglist
, num_args
)
467 Dimension width
, height
;
469 width
= w
->core
.width
;
470 height
= w
->core
.height
;
472 for ( i
= 0 ; i
< *num_args
; i
++) {
473 if ( streq(arglist
[i
].name
, XtNwidth
) )
474 width
= (Dimension
) arglist
[i
].value
;
475 if ( streq(arglist
[i
].name
, XtNheight
) )
476 height
= (Dimension
) arglist
[i
].value
;
479 if ((width
!= w
->core
.width
) || (height
!= w
->core
.height
))
480 MakeSetValuesRequest(w
, width
, height
);
484 /************************************************************
486 * Geometry Management routines.
488 ************************************************************/
490 /* Function Name: GeometryManager
491 * Description: This is the SimpleMenu Widget's Geometry Manager.
492 * Arguments: w - the Menu Entry making the request.
493 * request - requested new geometry.
494 * reply - the allowed geometry.
495 * Returns: XtGeometry{Yes, No, Almost}.
498 static XtGeometryResult
499 GeometryManager(w
, request
, reply
)
501 XtWidgetGeometry
* request
, * reply
;
503 SimpleMenuWidget smw
= (SimpleMenuWidget
) XtParent(w
);
504 SmeObject entry
= (SmeObject
) w
;
505 XtGeometryMask mode
= request
->request_mode
;
506 XtGeometryResult answer
;
507 Dimension old_height
, old_width
;
509 if ( !(mode
& CWWidth
) && !(mode
& CWHeight
) )
510 return(XtGeometryNo
);
512 reply
->width
= request
->width
;
513 reply
->height
= request
->height
;
515 old_width
= entry
->rectangle
.width
;
516 old_height
= entry
->rectangle
.height
;
518 Layout(w
, &(reply
->width
), &(reply
->height
) );
521 * Since we are an override shell and have no parent there is no one to
522 * ask to see if this geom change is okay, so I am just going to assume
523 * we can do whatever we want. If you subclass be very careful with this
524 * assumption, it could bite you.
526 * Chris D. Peterson - Sept. 1989.
529 if ( (reply
->width
== request
->width
) &&
530 (reply
->height
== request
->height
) ) {
532 if ( mode
& XtCWQueryOnly
) { /* Actually perform the layout. */
533 entry
->rectangle
.width
= old_width
;
534 entry
->rectangle
.height
= old_height
;
537 Layout(( Widget
) smw
, NULL
, NULL
);
539 answer
= XtGeometryDone
;
542 entry
->rectangle
.width
= old_width
;
543 entry
->rectangle
.height
= old_height
;
545 if ( ((reply
->width
== request
->width
) && !(mode
& CWHeight
)) ||
546 ((reply
->height
== request
->height
) && !(mode
& CWWidth
)) ||
547 ((reply
->width
== request
->width
) &&
548 (reply
->height
== request
->height
)) )
549 answer
= XtGeometryNo
;
551 answer
= XtGeometryAlmost
;
552 reply
->request_mode
= 0;
553 if (reply
->width
!= request
->width
)
554 reply
->request_mode
|= CWWidth
;
555 if (reply
->height
!= request
->height
)
556 reply
->request_mode
|= CWHeight
;
562 /* Function Name: ChangeManaged
563 * Description: called whenever a new child is managed.
564 * Arguments: w - the simple menu widget.
572 Layout(w
, NULL
, NULL
);
575 /************************************************************
577 * Global Action Routines.
579 * These actions routines will be added to the application's
580 * global action list.
582 ************************************************************/
584 /* Function Name: PositionMenuAction
585 * Description: Positions the simple menu widget.
586 * Arguments: w - a widget (no the simple menu widget.)
587 * event - the event that caused this action.
588 * params, num_params - parameters passed to the routine.
589 * we expect the name of the menu here.
595 PositionMenuAction(w
, event
, params
, num_params
)
599 Cardinal
* num_params
;
604 if (*num_params
!= 1) {
605 char error_buf
[BUFSIZ
];
606 sprintf(error_buf
, "%s %s",
607 "Xaw - SimpleMenuWidget: position menu action expects only one",
608 "parameter which is the name of the menu.");
609 XtAppWarning(XtWidgetToApplicationContext(w
), error_buf
);
613 if ( (menu
= FindMenu(w
, params
[0])) == NULL
) {
614 char error_buf
[BUFSIZ
];
615 sprintf(error_buf
, "%s '%s'",
616 "Xaw - SimpleMenuWidget: could not find menu named: ", params
[0]);
617 XtAppWarning(XtWidgetToApplicationContext(w
), error_buf
);
621 switch (event
->type
) {
624 loc
.x
= event
->xbutton
.x_root
;
625 loc
.y
= event
->xbutton
.y_root
;
626 PositionMenu(menu
, &loc
);
630 loc
.x
= event
->xcrossing
.x_root
;
631 loc
.y
= event
->xcrossing
.y_root
;
632 PositionMenu(menu
, &loc
);
635 loc
.x
= event
->xmotion
.x_root
;
636 loc
.y
= event
->xmotion
.y_root
;
637 PositionMenu(menu
, &loc
);
640 PositionMenu(menu
, NULL
);
645 /************************************************************
647 * Widget Action Routines.
649 ************************************************************/
651 /* Function Name: Unhighlight
652 * Description: Unhighlights current entry.
653 * Arguments: w - the simple menu widget.
654 * event - the event that caused this action.
655 * params, num_params - ** NOT USED **
661 Unhighlight(w
, event
, params
, num_params
)
665 Cardinal
* num_params
;
667 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
668 SmeObject entry
= smw
->simple_menu
.entry_set
;
669 SmeObjectClass
class;
671 if ( entry
== NULL
) return;
673 smw
->simple_menu
.entry_set
= NULL
;
674 class = (SmeObjectClass
) entry
->object
.widget_class
;
675 (class->sme_class
.unhighlight
) ( (Widget
) entry
);
678 /* Function Name: Highlight
679 * Description: Highlights current entry.
680 * Arguments: w - the simple menu widget.
681 * event - the event that caused this action.
682 * params, num_params - ** NOT USED **
688 Highlight(w
, event
, params
, num_params
)
692 Cardinal
* num_params
;
694 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
696 SmeObjectClass
class;
698 if ( !XtIsSensitive(w
) ) return;
700 entry
= GetEventEntry(w
, event
);
702 if (entry
== smw
->simple_menu
.entry_set
) return;
704 Unhighlight(w
, event
, params
, num_params
);
706 if (entry
== NULL
) return;
708 if ( !XtIsSensitive( (Widget
) entry
)) {
709 smw
->simple_menu
.entry_set
= NULL
;
713 smw
->simple_menu
.entry_set
= entry
;
714 class = (SmeObjectClass
) entry
->object
.widget_class
;
716 (class->sme_class
.highlight
) ( (Widget
) entry
);
719 /* Function Name: Notify
720 * Description: Notify user of current entry.
721 * Arguments: w - the simple menu widget.
722 * event - the event that caused this action.
723 * params, num_params - ** NOT USED **
729 Notify(w
, event
, params
, num_params
)
733 Cardinal
* num_params
;
735 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
736 SmeObject entry
= smw
->simple_menu
.entry_set
;
737 SmeObjectClass
class;
739 if ( (entry
== NULL
) || !XtIsSensitive((Widget
) entry
) ) return;
741 class = (SmeObjectClass
) entry
->object
.widget_class
;
742 (class->sme_class
.notify
)( (Widget
) entry
);
745 /************************************************************
749 ************************************************************/
751 /* Function Name: XawSimpleMenuAddGlobalActions
752 * Description: adds the global actions to the simple menu widget.
753 * Arguments: app_con - the appcontext.
758 XawSimpleMenuAddGlobalActions(app_con
)
759 XtAppContext app_con
;
761 XtInitializeWidgetClass(simpleMenuWidgetClass
);
762 XmuCallInitializers( app_con
);
766 /* Function Name: XawSimpleMenuGetActiveEntry
767 * Description: Gets the currently active (set) entry.
768 * Arguments: w - the smw widget.
769 * Returns: the currently set entry or NULL if none is set.
773 XawSimpleMenuGetActiveEntry(w
)
776 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
778 return( (Widget
) smw
->simple_menu
.entry_set
);
781 /* Function Name: XawSimpleMenuClearActiveEntry
782 * Description: Unsets the currently active (set) entry.
783 * Arguments: w - the smw widget.
788 XawSimpleMenuClearActiveEntry(w
)
791 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
793 smw
->simple_menu
.entry_set
= NULL
;
796 /************************************************************
800 ************************************************************/
802 /* Function Name: CreateLabel
803 * Description: Creates a the menu label.
804 * Arguments: w - the smw widget.
807 * Creates the label object and makes sure it is the first child in
815 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
816 register Widget
* child
, * next_child
;
820 if ( (smw
->simple_menu
.label_string
== NULL
) ||
821 (smw
->simple_menu
.label
!= NULL
) ) {
822 char error_buf
[BUFSIZ
];
824 sprintf(error_buf
, "Xaw Simple Menu Widget: %s or %s, %s",
825 "label string is NULL", "label already exists",
826 "no label is being created.");
827 XtAppWarning(XtWidgetToApplicationContext(w
), error_buf
);
831 XtSetArg(args
[0], XtNlabel
, smw
->simple_menu
.label_string
);
832 XtSetArg(args
[1], XtNjustify
, XtJustifyCenter
);
833 smw
->simple_menu
.label
= (SmeObject
)
834 XtCreateManagedWidget("menuLabel",
835 smw
->simple_menu
.label_class
, w
,
839 for (child
= smw
->composite
.children
+ smw
->composite
.num_children
,
840 i
= smw
->composite
.num_children
; i
> 0 ; i
--, child
--) {
841 if (next_child
!= NULL
)
842 *next_child
= *child
;
845 *child
= (Widget
) smw
->simple_menu
.label
;
848 /* Function Name: Layout
849 * Description: lays the menu entries out all nice and neat.
850 * Arguments: w - See below (+++)
851 * width_ret, height_ret - The returned width and
855 * if width == NULL || height == NULL then it assumes the you do not care
856 * about the return values, and just want a relayout.
858 * if this is not the case then it will set width_ret and height_ret
859 * to be width and height that the child would get if it were layed out
862 * +++ "w" can be the simple menu widget or any of its object children.
866 Layout(w
, width_ret
, height_ret
)
868 Dimension
*width_ret
, *height_ret
;
870 SmeObject current_entry
, *entry
;
871 SimpleMenuWidget smw
;
872 Dimension width
, height
;
873 Boolean do_layout
= ((height_ret
== NULL
) || (width_ret
== NULL
));
874 Boolean allow_change_size
;
877 if ( XtIsSubclass(w
, simpleMenuWidgetClass
) ) {
878 smw
= (SimpleMenuWidget
) w
;
879 current_entry
= NULL
;
882 smw
= (SimpleMenuWidget
) XtParent(w
);
883 current_entry
= (SmeObject
) w
;
886 allow_change_size
= (!XtIsRealized((Widget
)smw
) ||
887 (smw
->shell
.allow_shell_resize
));
889 if ( smw
->simple_menu
.menu_height
)
890 height
= smw
->core
.height
;
893 height
= smw
->simple_menu
.top_margin
;
894 ForAllChildren(smw
, entry
) {
895 if (!XtIsManaged( (Widget
) *entry
)) continue;
897 if ( (smw
->simple_menu
.row_height
!= 0) &&
898 (*entry
!= smw
->simple_menu
.label
) )
899 (*entry
)->rectangle
.height
= smw
->simple_menu
.row_height
;
901 (*entry
)->rectangle
.y
= height
;
902 (*entry
)->rectangle
.x
= 0;
903 height
+= (*entry
)->rectangle
.height
;
905 height
+= smw
->simple_menu
.bottom_margin
;
908 if ((smw
->simple_menu
.row_height
!= 0) &&
909 (current_entry
!= smw
->simple_menu
.label
) )
910 height
= smw
->simple_menu
.row_height
;
913 if (smw
->simple_menu
.menu_width
)
914 width
= smw
->core
.width
;
915 else if ( allow_change_size
)
916 width
= GetMenuWidth((Widget
) smw
, (Widget
) current_entry
);
918 width
= smw
->core
.width
;
921 ForAllChildren(smw
, entry
)
922 if (XtIsManaged( (Widget
) *entry
))
923 (*entry
)->rectangle
.width
= width
;
925 if (allow_change_size
)
926 MakeSetValuesRequest((Widget
) smw
, width
, height
);
931 *height_ret
= height
;
935 /* Function Name: AddPositionAction
936 * Description: Adds the XawPositionSimpleMenu action to the global
937 * action list for this appcon.
938 * Arguments: app_con - the application context for this app.
945 AddPositionAction(app_con
, data
)
946 XtAppContext app_con
;
949 static XtActionsRec pos_action
[] = {
950 { "XawPositionSimpleMenu", PositionMenuAction
},
953 XtAppAddActions(app_con
, pos_action
, XtNumber(pos_action
));
956 /* Function Name: FindMenu
957 * Description: Find the menu give a name and reference widget.
958 * Arguments: widget - reference widget.
959 * name - the menu widget's name.
960 * Returns: the menu widget or NULL.
964 FindMenu(widget
, name
)
968 register Widget w
, menu
;
970 for ( w
= widget
; w
!= NULL
; w
= XtParent(w
) )
971 if ( (menu
= XtNameToWidget(w
, name
)) != NULL
)
976 /* Function Name: MoveMenu
977 * Description: Actually moves the menu, may force it to
978 * to be fully visable if menu_on_screen is TRUE.
979 * Arguments: w - the simple menu widget.
980 * x, y - the current location of the widget.
990 Cardinal num_args
= 0;
991 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
993 if (smw
->simple_menu
.menu_on_screen
) {
994 int width
= w
->core
.width
+ 2 * w
->core
.border_width
;
995 int height
= w
->core
.height
+ 2 * w
->core
.border_width
;
1000 int scr_width
= WidthOfScreen(XtScreen(w
));
1001 if (x
+ width
> scr_width
)
1002 x
= scr_width
- width
;
1008 int scr_height
= HeightOfScreen(XtScreen(w
));
1009 if (y
+ height
> scr_height
)
1010 y
= scr_height
- height
;
1014 XtSetArg(arglist
[num_args
], XtNx
, x
); num_args
++;
1015 XtSetArg(arglist
[num_args
], XtNy
, y
); num_args
++;
1016 XtSetValues(w
, arglist
, num_args
);
1019 /* Function Name: PositionMenu
1020 * Description: Places the menu
1021 * Arguments: w - the simple menu widget.
1022 * location - a pointer the the position or NULL.
1027 PositionMenu(w
, location
)
1031 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1035 if (location
== NULL
) {
1036 Window junk1
, junk2
;
1037 int root_x
, root_y
, junkX
, junkY
;
1040 location
= &t_point
;
1041 if (XQueryPointer(XtDisplay(w
), XtWindow(w
), &junk1
, &junk2
,
1042 &root_x
, &root_y
, &junkX
, &junkY
, &junkM
) == FALSE
) {
1043 char error_buf
[BUFSIZ
];
1044 sprintf(error_buf
, "%s %s", "Xaw - SimpleMenuWidget:",
1045 "Could not find location of mouse pointer");
1046 XtAppWarning(XtWidgetToApplicationContext(w
), error_buf
);
1049 location
->x
= (short) root_x
;
1050 location
->y
= (short) root_y
;
1054 * The width will not be correct unless it is realized.
1059 location
->x
-= (Position
) w
->core
.width
/2;
1061 if (smw
->simple_menu
.popup_entry
== NULL
)
1062 entry
= smw
->simple_menu
.label
;
1064 entry
= smw
->simple_menu
.popup_entry
;
1067 location
->y
-= entry
->rectangle
.y
+ entry
->rectangle
.height
/2;
1069 MoveMenu(w
, (Position
) location
->x
, (Position
) location
->y
);
1072 /* Function Name: ChangeCursorOnGrab
1073 * Description: Changes the cursor on the active grab to the one
1074 * specified in out resource list.
1075 * Arguments: w - the widget.
1076 * junk, garbage - ** NOT USED **.
1082 ChangeCursorOnGrab(w
, junk
, garbage
)
1084 caddr_t junk
, garbage
;
1086 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1089 * The event mask here is what is currently in the MIT implementation.
1090 * There really needs to be a way to get the value of the mask out
1091 * of the toolkit (CDP 5/26/89).
1094 XChangeActivePointerGrab(XtDisplay(w
), ButtonPressMask
|ButtonReleaseMask
,
1095 smw
->simple_menu
.cursor
, CurrentTime
);
1098 /* Function Name: MakeSetValuesRequest
1099 * Description: Makes a (possibly recursive) call to SetValues,
1100 * I take great pains to not go into an infinite loop.
1101 * Arguments: w - the simple menu widget.
1102 * width, height - the size of the ask for.
1107 MakeSetValuesRequest(w
, width
, height
)
1109 Dimension width
, height
;
1111 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1113 Cardinal num_args
= (Cardinal
) 0;
1115 if ( !smw
->simple_menu
.recursive_set_values
) {
1116 if ( (smw
->core
.width
!= width
) || (smw
->core
.height
!= height
) ) {
1117 smw
->simple_menu
.recursive_set_values
= TRUE
;
1118 XtSetArg(arglist
[num_args
], XtNwidth
, width
); num_args
++;
1119 XtSetArg(arglist
[num_args
], XtNheight
, height
); num_args
++;
1120 XtSetValues(w
, arglist
, num_args
);
1122 else if (XtIsRealized( (Widget
) smw
))
1123 Redisplay((Widget
) smw
, (XEvent
*) NULL
, (Region
) NULL
);
1125 smw
->simple_menu
.recursive_set_values
= FALSE
;
1128 /* Function Name: GetMenuWidth
1129 * Description: Sets the length of the widest entry in pixels.
1130 * Arguments: w - the simple menu widget.
1131 * Returns: width of menu.
1135 GetMenuWidth(w
, w_ent
)
1138 SmeObject cur_entry
= (SmeObject
) w_ent
;
1139 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1140 Dimension width
, widest
= (Dimension
) 0;
1143 if ( smw
->simple_menu
.menu_width
)
1144 return(smw
->core
.width
);
1146 ForAllChildren(smw
, entry
) {
1147 XtWidgetGeometry preferred
;
1149 if (!XtIsManaged( (Widget
) *entry
)) continue;
1151 if (*entry
!= cur_entry
) {
1152 XtQueryGeometry((Widget
)*entry
, NULL
, &preferred
);
1154 if (preferred
.request_mode
& CWWidth
)
1155 width
= preferred
.width
;
1157 width
= (*entry
)->rectangle
.width
;
1160 width
= (*entry
)->rectangle
.width
;
1162 if ( width
> widest
)
1169 /* Function Name: GetMenuHeight
1170 * Description: Sets the length of the widest entry in pixels.
1171 * Arguments: w - the simple menu widget.
1172 * Returns: width of menu.
1179 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1183 if (smw
->simple_menu
.menu_height
)
1184 return(smw
->core
.height
);
1186 height
= smw
->simple_menu
.top_margin
+ smw
->simple_menu
.bottom_margin
;
1188 if (smw
->simple_menu
.row_height
== 0)
1189 ForAllChildren(smw
, entry
)
1190 if (XtIsManaged ((Widget
) *entry
))
1191 height
+= (*entry
)->rectangle
.height
;
1193 height
+= smw
->simple_menu
.row_height
* smw
->composite
.num_children
;
1198 /* Function Name: GetEventEntry
1199 * Description: Gets an entry given an event that has X and Y coords.
1200 * Arguments: w - the simple menu widget.
1201 * event - the event.
1202 * Returns: the entry that this point is in.
1206 GetEventEntry(w
, event
)
1210 Position x_loc
, y_loc
;
1211 SimpleMenuWidget smw
= (SimpleMenuWidget
) w
;
1214 switch (event
->type
) {
1216 x_loc
= event
->xmotion
.x
;
1217 y_loc
= event
->xmotion
.y
;
1221 x_loc
= event
->xcrossing
.x
;
1222 y_loc
= event
->xcrossing
.y
;
1226 x_loc
= event
->xbutton
.x
;
1227 y_loc
= event
->xbutton
.y
;
1230 XtAppError(XtWidgetToApplicationContext(w
),
1231 "Unknown event type in GetEventEntry().");
1235 if ( (x_loc
< 0) || (x_loc
>= smw
->core
.width
) || (y_loc
< 0) ||
1236 (y_loc
>= smw
->core
.height
) )
1239 ForAllChildren(smw
, entry
) {
1240 if (!XtIsManaged ((Widget
) *entry
)) continue;
1242 if ( ((*entry
)->rectangle
.y
< y_loc
) &&
1243 ((*entry
)->rectangle
.y
+ (*entry
)->rectangle
.height
> y_loc
) )
1244 if ( *entry
== smw
->simple_menu
.label
)
1245 return(NULL
); /* cannot select the label. */