gtk+3: fix dependencies for new gnome/accessibility/at-spi2-core
[oi-userland.git] / components / x11 / libXaw5 / src / SimpleMenu.c
blob1ad03712077d5e8556d52b01997f93481494d07c
1 /* $XConsortium: SimpleMenu.c,v 1.44 94/04/17 20:12:45 kaleb Exp $ */
3 /*
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.
31 * Date: April 3, 1989
33 * By: Chris D. Peterson
34 * MIT X Consortium
35 * kit@expo.lcs.mit.edu
38 #include <stdio.h>
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[] = {
57 * Label 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},
66 * Layout Resources.
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},
77 * Misc. Resources
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)},
92 };
93 #undef offset
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[] =
129 {"notify", Notify},
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,
164 /* destroy */ NULL,
165 /* resize */ Resize,
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,
177 /* extension */ NULL
179 /* geometry_manager */ GeometryManager,
180 /* change_managed */ ChangeManaged,
181 /* insert_child */ XtInheritInsertChild,
182 /* delete_child */ XtInheritDeleteChild,
183 /* extension */ NULL
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 ) ; \
199 (childP)++ )
201 /************************************************************
203 * Semi-Public Functions.
205 ************************************************************/
207 /* Function Name: ClassInitialize
208 * Description: Class Initialize routine, called only once.
209 * Arguments: none.
210 * Returns: none.
213 static void
214 ClassInitialize()
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.
227 * Returns: none.
230 static void
231 ClassPartInitialize(wc)
232 WidgetClass 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
248 * resource values.
249 * Returns: none.
252 /* ARGSUSED */
253 static void
254 Initialize(request, new, args, num_args)
255 Widget request, new;
256 ArgList args;
257 Cardinal *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)
271 CreateLabel(new);
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.
299 * Returns: none.
302 /* ARGSUSED */
303 static void
304 Redisplay(w, event, region)
305 Widget w;
306 XEvent * event;
307 Region region;
309 SimpleMenuWidget smw = (SimpleMenuWidget) w;
310 SmeObject * entry;
311 SmeObjectClass class;
313 if (region == NULL)
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;
323 if (region != NULL)
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)) {
328 case RectangleIn:
329 case RectanglePart:
330 break;
331 default:
332 continue;
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.
346 * Returns: none
349 static void
350 Realize(w, mask, attrs)
351 Widget w;
352 XtValueMask * mask;
353 XSetWindowAttributes * attrs;
355 SimpleMenuWidget smw = (SimpleMenuWidget) w;
357 attrs->cursor = smw->simple_menu.cursor;
358 *mask |= CWCursor;
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;
365 else
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.
374 * Returns: none.
377 static void
378 Resize(w)
379 Widget w;
381 SimpleMenuWidget smw = (SimpleMenuWidget) w;
382 SmeObject * entry;
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.
398 * Returns: none
401 /* ARGSUSED */
402 static Boolean
403 SetValues(current, request, new, args, num_args)
404 Widget current, request, new;
405 ArgList args;
406 Cardinal *num_args;
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);
417 layout = TRUE;
419 if (smw_new->core.height != smw_old->core.height) {
420 smw_new->simple_menu.menu_height = (smw_new->core.height != 0);
421 layout = TRUE;
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. */
433 CreateLabel(new);
434 else { /* Change. */
435 Arg arglist[1];
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................. */ ) {
448 layout = TRUE;
449 ret_val = TRUE;
452 if (layout)
453 Layout(new, (Dimension *)NULL, (Dimension *)NULL);
455 return(ret_val);
458 /* Function Name: SetValuesHook
459 * Description: To handle a special case, this is passed the
460 * actual arguments.
461 * Arguments: w - the menu widget.
462 * arglist - the argument list passed to XtSetValues.
463 * num_args - the number of args.
464 * Returns: none
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
470 * height.
473 static Boolean
474 SetValuesHook(w, arglist, num_args)
475 Widget w;
476 ArgList arglist;
477 Cardinal *num_args;
479 Cardinal i;
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);
494 return(FALSE);
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)
513 Widget w;
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;
549 else {
550 Layout(( Widget) smw, (Dimension *)NULL, (Dimension *)NULL);
552 answer = XtGeometryDone;
554 else {
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;
563 else {
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;
572 return(answer);
575 /* Function Name: ChangeManaged
576 * Description: called whenever a new child is managed.
577 * Arguments: w - the simple menu widget.
578 * Returns: none.
581 static void
582 ChangeManaged(w)
583 Widget w;
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.
603 * Returns: none
606 /* ARGSUSED */
607 static void
608 PositionMenuAction(w, event, params, num_params)
609 Widget w;
610 XEvent * event;
611 String * params;
612 Cardinal * num_params;
614 Widget menu;
615 XPoint loc;
616 char error_buf[BUFSIZ];
617 char* ebp;
618 int len;
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.");
628 return;
631 if ( (menu = FindMenu(w, params[0])) == NULL) {
632 if ((len = strlen (fmt) + strlen (params[0])) < sizeof error_buf)
633 ebp = error_buf;
634 else
635 ebp = XtMalloc (len + 1);
636 if (ebp == NULL) {
637 ebp = error_buf;
638 strcpy (ebp, "Xaw - SimpleMenuWidget: could not find menu");
639 } else
640 (void) sprintf(ebp, fmt, params[0]);
641 XtAppWarning(XtWidgetToApplicationContext(w), ebp);
642 if (ebp != error_buf) XtFree (ebp);
643 return;
646 switch (event->type) {
647 case ButtonPress:
648 case ButtonRelease:
649 loc.x = event->xbutton.x_root;
650 loc.y = event->xbutton.y_root;
651 PositionMenu(menu, &loc);
652 break;
653 case EnterNotify:
654 case LeaveNotify:
655 loc.x = event->xcrossing.x_root;
656 loc.y = event->xcrossing.y_root;
657 PositionMenu(menu, &loc);
658 break;
659 case MotionNotify:
660 loc.x = event->xmotion.x_root;
661 loc.y = event->xmotion.y_root;
662 PositionMenu(menu, &loc);
663 break;
664 default:
665 PositionMenu(menu, (XPoint *)NULL);
666 break;
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 **
681 * Returns: none
684 /* ARGSUSED */
685 static void
686 Unhighlight(w, event, params, num_params)
687 Widget w;
688 XEvent * event;
689 String * 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 **
708 * Returns: none
711 /* ARGSUSED */
712 static void
713 Highlight(w, event, params, num_params)
714 Widget w;
715 XEvent * event;
716 String * params;
717 Cardinal * num_params;
719 SimpleMenuWidget smw = (SimpleMenuWidget) w;
720 SmeObject entry;
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;
735 return;
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 **
749 * Returns: none
752 /* ARGSUSED */
753 static void
754 Notify(w, event, params, num_params)
755 Widget w;
756 XEvent * event;
757 String * 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 /************************************************************
772 * Public Functions.
774 ************************************************************/
776 /* Function Name: XawSimpleMenuAddGlobalActions
777 * Description: adds the global actions to the simple menu widget.
778 * Arguments: app_con - the appcontext.
779 * Returns: none.
782 void
783 #if NeedFunctionPrototypes
784 XawSimpleMenuAddGlobalActions(XtAppContext app_con)
785 #else
786 XawSimpleMenuAddGlobalActions(app_con)
787 XtAppContext app_con;
788 #endif
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.
801 Widget
802 #if NeedFunctionPrototypes
803 XawSimpleMenuGetActiveEntry(Widget w)
804 #else
805 XawSimpleMenuGetActiveEntry(w)
806 Widget w;
807 #endif
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.
817 * Returns: none.
820 void
821 #if NeedFunctionPrototypes
822 XawSimpleMenuClearActiveEntry(Widget w)
823 #else
824 XawSimpleMenuClearActiveEntry(w)
825 Widget w;
826 #endif
828 SimpleMenuWidget smw = (SimpleMenuWidget) w;
830 smw->simple_menu.entry_set = NULL;
833 /************************************************************
835 * Private Functions.
837 ************************************************************/
839 /* Function Name: CreateLabel
840 * Description: Creates a the menu label.
841 * Arguments: w - the smw widget.
842 * Returns: none.
844 * Creates the label object and makes sure it is the first child in
845 * in the list.
848 static void
849 CreateLabel(w)
850 Widget w;
852 SimpleMenuWidget smw = (SimpleMenuWidget) w;
853 Widget * child, * next_child;
854 int i;
855 Arg args[2];
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);
865 return;
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,
873 args, TWO);
875 next_child = NULL;
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;
880 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
889 * height values.
890 * Returns: none.
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
897 * at this time.
899 * +++ "w" can be the simple menu widget or any of its object children.
902 static void
903 Layout(w, width_ret, height_ret)
904 Widget w;
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;
912 height = 0;
914 if ( XtIsSubclass(w, simpleMenuWidgetClass) ) {
915 smw = (SimpleMenuWidget) w;
916 current_entry = NULL;
918 else {
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;
928 else
929 if (do_layout) {
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;
944 else {
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);
954 else
955 width = smw->core.width;
957 if (do_layout) {
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);
965 else {
966 *width_ret = width;
967 if (height != 0)
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.
976 * data - NOT USED.
977 * Returns: none.
980 /* ARGSUSED */
981 static void
982 AddPositionAction(app_con, data)
983 XtAppContext app_con;
984 XPointer data;
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.
1000 static Widget
1001 FindMenu(widget, name)
1002 Widget widget;
1003 String name;
1005 Widget w, menu;
1007 for ( w = widget ; w != NULL ; w = XtParent(w) )
1008 if ( (menu = XtNameToWidget(w, name)) != NULL )
1009 return(menu);
1010 return(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.
1017 * Returns: none.
1020 static void
1021 PositionMenu(w, location)
1022 Widget w;
1023 XPoint * location;
1025 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1026 SmeObject entry;
1027 XPoint t_point;
1029 if (location == NULL) {
1030 Window junk1, junk2;
1031 int root_x, root_y, junkX, junkY;
1032 unsigned int junkM;
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);
1041 return;
1043 location->x = (short) root_x;
1044 location->y = (short) root_y;
1048 * The width will not be correct unless it is realized.
1051 XtRealizeWidget(w);
1053 location->x -= (Position) w->core.width/2;
1055 if (smw->simple_menu.popup_entry == NULL)
1056 entry = smw->simple_menu.label;
1057 else
1058 entry = smw->simple_menu.popup_entry;
1060 if (entry != NULL)
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.
1071 * Returns: none
1074 static void
1075 MoveMenu(w, x, y)
1076 Widget w;
1077 Position x, y;
1079 Arg arglist[2];
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;
1087 if (x >= 0) {
1088 int scr_width = WidthOfScreen(XtScreen(w));
1089 if (x + width > scr_width)
1090 x = scr_width - width;
1092 if (x < 0)
1093 x = 0;
1095 if (y >= 0) {
1096 int scr_height = HeightOfScreen(XtScreen(w));
1097 if (y + height > scr_height)
1098 y = scr_height - height;
1100 if (y < 0)
1101 y = 0;
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 **.
1114 * Returns: None.
1117 /* ARGSUSED */
1118 static void
1119 ChangeCursorOnGrab(w, junk, garbage)
1120 Widget w;
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.
1141 * Returns: none
1144 static void
1145 MakeSetValuesRequest(w, width, height)
1146 Widget w;
1147 Dimension width, height;
1149 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1150 Arg arglist[2];
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.
1172 static Dimension
1173 GetMenuWidth(w, w_ent)
1174 Widget w, w_ent;
1176 SmeObject cur_entry = (SmeObject) w_ent;
1177 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1178 Dimension width, widest = (Dimension) 0;
1179 SmeObject * entry;
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;
1194 else
1195 width = (*entry)->rectangle.width;
1197 else
1198 width = (*entry)->rectangle.width;
1200 if ( width > widest )
1201 widest = width;
1204 return(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.
1213 static Dimension
1214 GetMenuHeight(w)
1215 Widget w;
1217 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1218 SmeObject * entry;
1219 Dimension height;
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;
1230 } else
1231 height += smw->simple_menu.row_height * smw->composite.num_children;
1233 return(height);
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.
1243 static SmeObject
1244 GetEventEntry(w, event)
1245 Widget w;
1246 XEvent * event;
1248 Position x_loc, y_loc;
1249 SimpleMenuWidget smw = (SimpleMenuWidget) w;
1250 SmeObject * entry;
1252 switch (event->type) {
1253 case MotionNotify:
1254 x_loc = event->xmotion.x;
1255 y_loc = event->xmotion.y;
1256 break;
1257 case EnterNotify:
1258 case LeaveNotify:
1259 x_loc = event->xcrossing.x;
1260 y_loc = event->xcrossing.y;
1261 break;
1262 case ButtonPress:
1263 case ButtonRelease:
1264 x_loc = event->xbutton.x;
1265 y_loc = event->xbutton.y;
1266 break;
1267 default:
1268 XtAppError(XtWidgetToApplicationContext(w),
1269 "Unknown event type in GetEventEntry().");
1270 break;
1273 if ( (x_loc < 0) || (x_loc >= (int)smw->core.width) || (y_loc < 0) ||
1274 (y_loc >= (int)smw->core.height) )
1275 return(NULL);
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. */
1284 else
1285 return(*entry);
1288 return(NULL);