SimpleMenu.c revision 5b16253f
17a84e134Smrg/*
27a84e134SmrgCopyright 1989, 1994, 1998  The Open Group
37a84e134Smrg
47a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its
57a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that
67a84e134Smrgthe above copyright notice appear in all copies and that both that
77a84e134Smrgcopyright notice and this permission notice appear in supporting
87a84e134Smrgdocumentation.
97a84e134Smrg
107a84e134SmrgThe above copyright notice and this permission notice shall be included in
117a84e134Smrgall copies or substantial portions of the Software.
127a84e134Smrg
137a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
147a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
157a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
167a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
177a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
187a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
197a84e134Smrg
207a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be
217a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings
227a84e134Smrgin this Software without prior written authorization from The Open Group.
237a84e134Smrg */
247a84e134Smrg
257a84e134Smrg/*
267a84e134Smrg * SimpleMenu.c - Source code file for SimpleMenu widget.
277a84e134Smrg *
287a84e134Smrg * Date:    April 3, 1989
297a84e134Smrg *
307a84e134Smrg * By:      Chris D. Peterson
31421c997bSmrg *          MIT X Consortium
327a84e134Smrg *          kit@expo.lcs.mit.edu
337a84e134Smrg */
347a84e134Smrg
357a84e134Smrg#ifdef HAVE_CONFIG_H
367a84e134Smrg#include <config.h>
377a84e134Smrg#endif
387a84e134Smrg#include <stdio.h>
397a84e134Smrg#include <X11/IntrinsicP.h>
407a84e134Smrg#include <X11/StringDefs.h>
417a84e134Smrg#include <X11/Xmu/Initer.h>
427a84e134Smrg#include <X11/Xaw/Cardinals.h>
437a84e134Smrg#include <X11/Xaw/SimpleMenP.h>
447a84e134Smrg#include <X11/Xaw/SmeBSBP.h>
457a84e134Smrg#include <X11/Xaw/XawInit.h>
467a84e134Smrg#include "Private.h"
477a84e134Smrg
487a84e134Smrg#define streq(a, b)	(strcmp((a), (b)) == 0)
497a84e134Smrg
507a84e134Smrg#define ForAllChildren(smw, childP)				\
517a84e134Smrgfor ((childP) = (SmeObject *)(smw)->composite.children;		\
527a84e134Smrg     (childP) < (SmeObject *)((smw)->composite.children		\
537a84e134Smrg			      + (smw)->composite.num_children);	\
547a84e134Smrg     (childP)++)
557a84e134Smrg
567a84e134Smrg#ifndef OLDXAW
577a84e134Smrg#define	SMW_UNMAPPING	0x01
587a84e134Smrg#define SMW_POPLEFT	0x02
597a84e134Smrg#endif
607a84e134Smrg
617a84e134Smrg/*
627a84e134Smrg * Class Methods
637a84e134Smrg */
647a84e134Smrgstatic void XawSimpleMenuChangeManaged(Widget);
657a84e134Smrgstatic void XawSimpleMenuClassInitialize(void);
667a84e134Smrgstatic void XawSimpleMenuClassPartInitialize(WidgetClass);
677a84e134Smrgstatic XtGeometryResult XawSimpleMenuGeometryManager(Widget, XtWidgetGeometry*,
687a84e134Smrg						     XtWidgetGeometry*);
697a84e134Smrgstatic void XawSimpleMenuInitialize(Widget, Widget, ArgList, Cardinal*);
707a84e134Smrgstatic void XawSimpleMenuRealize(Widget, XtValueMask*, XSetWindowAttributes*);
717a84e134Smrgstatic void XawSimpleMenuRedisplay(Widget, XEvent*, Region);
727a84e134Smrgstatic void XawSimpleMenuResize(Widget);
737a84e134Smrgstatic Boolean XawSimpleMenuSetValues(Widget, Widget, Widget,
747a84e134Smrg				      ArgList, Cardinal*);
757a84e134Smrgstatic Boolean XawSimpleMenuSetValuesHook(Widget, ArgList, Cardinal*);
767a84e134Smrg#ifndef OLDXAW
777a84e134Smrgstatic void PopupSubMenu(SimpleMenuWidget);
787a84e134Smrgstatic void PopdownSubMenu(SimpleMenuWidget);
797a84e134Smrgstatic void PopupCB(Widget, XtPointer, XtPointer);
807a84e134Smrg#endif
817a84e134Smrg
827a84e134Smrg/*
837a84e134Smrg * Prototypes
847a84e134Smrg */
857a84e134Smrgstatic void AddPositionAction(XtAppContext, XPointer);
867a84e134Smrgstatic void CalculateNewSize(Widget, Dimension*, Dimension*);
877a84e134Smrgstatic void ChangeCursorOnGrab(Widget, XtPointer, XtPointer);
887a84e134Smrgstatic void CreateLabel(Widget);
897a84e134Smrgstatic SmeObject DoGetEventEntry(Widget, int, int);
907a84e134Smrgstatic Widget FindMenu(Widget, String);
917a84e134Smrgstatic SmeObject GetEventEntry(Widget, XEvent*);
927a84e134Smrgstatic void Layout(Widget, Dimension*, Dimension*);
937a84e134Smrgstatic void MakeResizeRequest(Widget);
947a84e134Smrgstatic void MakeSetValuesRequest(Widget, unsigned int, unsigned int);
957a84e134Smrgstatic void MoveMenu(Widget, int, int);
967a84e134Smrgstatic void PositionMenu(Widget, XPoint*);
977a84e134Smrg
987a84e134Smrg/*
997a84e134Smrg * Actions
1007a84e134Smrg */
1017a84e134Smrgstatic void Highlight(Widget, XEvent*, String*, Cardinal*);
1027a84e134Smrgstatic void Notify(Widget, XEvent*, String*, Cardinal*);
1037a84e134Smrg#ifndef OLDXAW
1047a84e134Smrgstatic void Popdown(Widget, XEvent*, String*, Cardinal*);
1057a84e134Smrg#endif
1067a84e134Smrgstatic void PositionMenuAction(Widget, XEvent*, String*, Cardinal*);
1077a84e134Smrgstatic void Unhighlight(Widget, XEvent*, String*, Cardinal*);
1087a84e134Smrg
1097a84e134Smrg/*
1107a84e134Smrg * Initialization
1117a84e134Smrg */
1127a84e134Smrg#define offset(field)	XtOffsetOf(SimpleMenuRec, simple_menu.field)
1137a84e134Smrg
1147a84e134Smrgstatic XtResource resources[] = {
1157a84e134Smrg  /* label */
1167a84e134Smrg  {
1177a84e134Smrg    XtNlabel,
1187a84e134Smrg    XtCLabel,
1197a84e134Smrg    XtRString,
1207a84e134Smrg    sizeof(String),
1217a84e134Smrg    offset(label_string),
1227a84e134Smrg    XtRString,
1237a84e134Smrg    NULL
1247a84e134Smrg  },
1257a84e134Smrg  {
1267a84e134Smrg    XtNlabelClass,
1277a84e134Smrg    XtCLabelClass,
1287a84e134Smrg    XtRPointer,
1297a84e134Smrg    sizeof(WidgetClass),
1307a84e134Smrg    offset(label_class),
1317a84e134Smrg    XtRImmediate,
1327a84e134Smrg    NULL
1337a84e134Smrg  },
1347a84e134Smrg
1357a84e134Smrg  /* layout */
1367a84e134Smrg  {
1377a84e134Smrg    XtNrowHeight,
1387a84e134Smrg    XtCRowHeight,
1397a84e134Smrg    XtRDimension,
1407a84e134Smrg    sizeof(Dimension),
1417a84e134Smrg    offset(row_height),
1427a84e134Smrg    XtRImmediate,
1437a84e134Smrg    (XtPointer)0
1447a84e134Smrg  },
1457a84e134Smrg  {
1467a84e134Smrg    XtNtopMargin,
1477a84e134Smrg    XtCVerticalMargins,
1487a84e134Smrg    XtRDimension,
1497a84e134Smrg    sizeof(Dimension),
1507a84e134Smrg    offset(top_margin),
1517a84e134Smrg    XtRImmediate,
1527a84e134Smrg    (XtPointer)0
1537a84e134Smrg  },
1547a84e134Smrg  {
1557a84e134Smrg    XtNbottomMargin,
1567a84e134Smrg    XtCVerticalMargins,
1577a84e134Smrg    XtRDimension,
1587a84e134Smrg    sizeof(Dimension),
1597a84e134Smrg    offset(bottom_margin),
1607a84e134Smrg    XtRImmediate,
1617a84e134Smrg    (XtPointer)0
1627a84e134Smrg  },
1637a84e134Smrg#ifndef OLDXAW
1647a84e134Smrg  {
1657a84e134Smrg    XtNleftMargin,
1667a84e134Smrg    XtCHorizontalMargins,
1677a84e134Smrg    XtRDimension,
1687a84e134Smrg    sizeof(Dimension),
1697a84e134Smrg    offset(left_margin),
1707a84e134Smrg    XtRImmediate,
1717a84e134Smrg    (XtPointer)0
1727a84e134Smrg  },
1737a84e134Smrg  {
1747a84e134Smrg    XtNrightMargin,
1757a84e134Smrg    XtCHorizontalMargins,
1767a84e134Smrg    XtRDimension,
1777a84e134Smrg    sizeof(Dimension),
1787a84e134Smrg    offset(right_margin),
1797a84e134Smrg    XtRImmediate,
1807a84e134Smrg    (XtPointer)0
1817a84e134Smrg  },
1827a84e134Smrg#endif
1837a84e134Smrg
1847a84e134Smrg  /* misc */
1857a84e134Smrg  {
1867a84e134Smrg    XtNallowShellResize,
1877a84e134Smrg    XtCAllowShellResize,
1887a84e134Smrg    XtRBoolean,
1897a84e134Smrg    sizeof(Boolean),
1907a84e134Smrg    XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize),
1917a84e134Smrg    XtRImmediate,
1927a84e134Smrg    (XtPointer)True
1937a84e134Smrg  },
1947a84e134Smrg  {
1957a84e134Smrg    XtNcursor,
1967a84e134Smrg    XtCCursor,
1977a84e134Smrg    XtRCursor,
1987a84e134Smrg    sizeof(Cursor),
1997a84e134Smrg    offset(cursor),
2007a84e134Smrg    XtRImmediate,
2017a84e134Smrg    (XtPointer)None
2027a84e134Smrg  },
2037a84e134Smrg  {
2047a84e134Smrg    XtNmenuOnScreen,
2057a84e134Smrg    XtCMenuOnScreen,
2067a84e134Smrg    XtRBoolean,
2077a84e134Smrg    sizeof(Boolean),
2087a84e134Smrg    offset(menu_on_screen),
2097a84e134Smrg    XtRImmediate,
2107a84e134Smrg    (XtPointer)True
2117a84e134Smrg  },
2127a84e134Smrg  {
2137a84e134Smrg    XtNpopupOnEntry,
2147a84e134Smrg    XtCPopupOnEntry,
2157a84e134Smrg    XtRWidget,
2167a84e134Smrg    sizeof(Widget),
2177a84e134Smrg    offset(popup_entry),
2187a84e134Smrg    XtRWidget,
2197a84e134Smrg    NULL
2207a84e134Smrg  },
2217a84e134Smrg  {
2227a84e134Smrg    XtNbackingStore,
2237a84e134Smrg    XtCBackingStore,
2247a84e134Smrg    XtRBackingStore,
2257a84e134Smrg    sizeof(int),
226421c997bSmrg    offset(backing_store),
2277a84e134Smrg    XtRImmediate,
2287a84e134Smrg    (XtPointer)(Always + WhenMapped + NotUseful)
2297a84e134Smrg  },
2307a84e134Smrg#ifndef OLDXAW
2317a84e134Smrg  {
2327a84e134Smrg    XawNdisplayList,
2337a84e134Smrg    XawCDisplayList,
2347a84e134Smrg    XawRDisplayList,
2357a84e134Smrg    sizeof(XawDisplayList*),
236421c997bSmrg    offset(display_list),
2377a84e134Smrg    XtRImmediate,
2387a84e134Smrg    NULL
2397a84e134Smrg  },
2407a84e134Smrg#endif
241421c997bSmrg};
2427a84e134Smrg#undef offset
2437a84e134Smrg
2447a84e134Smrgstatic char defaultTranslations[] =
2457a84e134Smrg"<Enter>:"	"highlight()\n"
2467a84e134Smrg"<Leave>:"	"unhighlight()\n"
2477a84e134Smrg"<BtnMotion>:"	"highlight()\n"
2487a84e134Smrg#ifndef OLDXAW
2497a84e134Smrg"<BtnUp>:"	"popdown() notify() unhighlight()\n"
2507a84e134Smrg#else
2517a84e134Smrg"<BtnUp>:"	"MenuPopdown() notify() unhighlight()\n"
2527a84e134Smrg#endif
2537a84e134Smrg;
2547a84e134Smrg
2557a84e134Smrgstatic XtActionsRec actionsList[] =
2567a84e134Smrg{
2577a84e134Smrg  {"notify",            Notify},
2587a84e134Smrg  {"highlight",         Highlight},
2597a84e134Smrg  {"unhighlight",       Unhighlight},
2607a84e134Smrg#ifndef OLDXAW
2617a84e134Smrg  {"popdown",		Popdown},
2627a84e134Smrg  {"set-values",	XawSetValuesAction},
2637a84e134Smrg  {"get-values",	XawGetValuesAction},
2647a84e134Smrg  {"declare",		XawDeclareAction},
2657a84e134Smrg  {"call-proc",		XawCallProcAction},
2667a84e134Smrg#endif
2677a84e134Smrg};
268421c997bSmrg
2697a84e134Smrgstatic CompositeClassExtensionRec extension_rec = {
2707a84e134Smrg  NULL,					/* next_extension */
2717a84e134Smrg  NULLQUARK,				/* record_type */
2727a84e134Smrg  XtCompositeExtensionVersion,		/* version */
2737a84e134Smrg  sizeof(CompositeClassExtensionRec),	/* record_size */
2747a84e134Smrg  True,					/* accepts_objects */
2757a84e134Smrg};
2767a84e134Smrg
2777a84e134Smrg#define Superclass	(&overrideShellClassRec)
2787a84e134SmrgSimpleMenuClassRec simpleMenuClassRec = {
2797a84e134Smrg  /* core */
2807a84e134Smrg  {
2817a84e134Smrg    (WidgetClass)Superclass,		/* superclass */
2827a84e134Smrg    "SimpleMenu",			/* class_name */
2837a84e134Smrg    sizeof(SimpleMenuRec),		/* size */
2847a84e134Smrg    XawSimpleMenuClassInitialize,	/* class_initialize */
2857a84e134Smrg    XawSimpleMenuClassPartInitialize,	/* class_part_initialize */
2867a84e134Smrg    False,				/* class_inited */
2877a84e134Smrg    XawSimpleMenuInitialize,		/* initialize */
2887a84e134Smrg    NULL,				/* initialize_hook */
2897a84e134Smrg    XawSimpleMenuRealize,		/* realize */
2907a84e134Smrg    actionsList,			/* actions */
2917a84e134Smrg    XtNumber(actionsList),		/* num_actions */
2927a84e134Smrg    resources,				/* resources */
2937a84e134Smrg    XtNumber(resources),		/* num_resources */
2947a84e134Smrg    NULLQUARK,				/* xrm_class */
2957a84e134Smrg    True,				/* compress_motion */
2967a84e134Smrg    True,				/* compress_exposure */
2977a84e134Smrg    True,				/* compress_enterleave */
2987a84e134Smrg    False,				/* visible_interest */
2997a84e134Smrg    NULL,				/* destroy */
3007a84e134Smrg    XawSimpleMenuResize,		/* resize */
3017a84e134Smrg    XawSimpleMenuRedisplay,		/* expose */
3027a84e134Smrg    XawSimpleMenuSetValues,		/* set_values */
3037a84e134Smrg    XawSimpleMenuSetValuesHook,		/* set_values_hook */
3047a84e134Smrg    XtInheritSetValuesAlmost,		/* set_values_almost */
3057a84e134Smrg    NULL,				/* get_values_hook */
3067a84e134Smrg    NULL,				/* accept_focus */
3077a84e134Smrg    XtVersion,				/* intrinsics version */
3087a84e134Smrg    NULL,				/* callback offsets */
3097a84e134Smrg    defaultTranslations,		/* tm_table */
3107a84e134Smrg    NULL,				/* query_geometry */
3117a84e134Smrg    NULL,				/* display_accelerator */
3127a84e134Smrg    NULL,				/* extension */
3137a84e134Smrg  },
3147a84e134Smrg  /* composite */
3157a84e134Smrg  {
3167a84e134Smrg    XawSimpleMenuGeometryManager,	/* geometry_manager */
3177a84e134Smrg    XawSimpleMenuChangeManaged,		/* change_managed */
3187a84e134Smrg    XtInheritInsertChild,		/* insert_child */
3197a84e134Smrg    XtInheritDeleteChild,		/* delete_child */
3207a84e134Smrg    NULL,				/* extension */
3217a84e134Smrg  },
3227a84e134Smrg  /* shell */
3237a84e134Smrg  {
3247a84e134Smrg    NULL,				/* extension */
3257a84e134Smrg  },
3267a84e134Smrg  /* override */
3277a84e134Smrg  {
3287a84e134Smrg    NULL,				/* extension */
3297a84e134Smrg  },
3307a84e134Smrg  /* simple_menu */
3317a84e134Smrg  {
3327a84e134Smrg    NULL,				/* extension */
3337a84e134Smrg  },
3347a84e134Smrg};
3357a84e134Smrg
3367a84e134SmrgWidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
3377a84e134Smrg
3387a84e134Smrg/*
3397a84e134Smrg * Implementation
3407a84e134Smrg */
3417a84e134Smrg/*
3427a84e134Smrg * Function:
3437a84e134Smrg *	XawSimpleMenuClassInitialize
3447a84e134Smrg *
3457a84e134Smrg * Description:
3467a84e134Smrg *	Class Initialize routine, called only once.
3477a84e134Smrg */
3487a84e134Smrgstatic void
3497a84e134SmrgXawSimpleMenuClassInitialize(void)
3507a84e134Smrg{
3517a84e134Smrg    XawInitializeWidgetSet();
3527a84e134Smrg    XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
3537a84e134Smrg		   NULL, 0);
3547a84e134Smrg    XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
3557a84e134Smrg		       NULL, 0, XtCacheNone, NULL);
3567a84e134Smrg    XmuAddInitializer(AddPositionAction, NULL);
3577a84e134Smrg}
3587a84e134Smrg
3597a84e134Smrg/*
3607a84e134Smrg * Function:
3617a84e134Smrg *	XawSimpleMenuClassPartInitialize
3627a84e134Smrg *      Arguments: wc - the widget class of the subclass.
3637a84e134Smrg *
3647a84e134Smrg * Description:
3657a84e134Smrg *	  Class Part Initialize routine, called for every subclass.  Makes
3667a84e134Smrg *	sure that the subclasses pick up the extension record.
3677a84e134Smrg */
3687a84e134Smrgstatic void
3697a84e134SmrgXawSimpleMenuClassPartInitialize(WidgetClass wc)
3707a84e134Smrg{
3717a84e134Smrg    SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc;
3727a84e134Smrg
3737a84e134Smrg    /*
3747a84e134Smrg     * Make sure that our subclass gets the extension rec too
3757a84e134Smrg     */
3767a84e134Smrg    extension_rec.next_extension = smwc->composite_class.extension;
3777a84e134Smrg    smwc->composite_class.extension = (XtPointer) &extension_rec;
3787a84e134Smrg}
3797a84e134Smrg
3807a84e134Smrg/*
3817a84e134Smrg *  Function:
3827a84e134Smrg *	XawSimpleMenuInitialize
3837a84e134Smrg *
3847a84e134Smrg * Parameters:
3857a84e134Smrg *	request - widget requested by the argument list
3867a84e134Smrg *	cnew	- new widget with both resource and non resource values
3877a84e134Smrg *
3887a84e134Smrg * Description:
3897a84e134Smrg *	Initializes the simple menu widget.
3907a84e134Smrg */
3917a84e134Smrg/*ARGSUSED*/
3927a84e134Smrgstatic void
3935ec34c4cSmrgXawSimpleMenuInitialize(Widget request _X_UNUSED, Widget cnew,
3945ec34c4cSmrg			ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
3957a84e134Smrg{
3967a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)cnew;
3977a84e134Smrg    Dimension width, height;
3987a84e134Smrg
3997a84e134Smrg    XmuCallInitializers(XtWidgetToApplicationContext(cnew));
4007a84e134Smrg
401421c997bSmrg    if (smw->simple_menu.label_class == NULL)
4027a84e134Smrg	smw->simple_menu.label_class = smeBSBObjectClass;
4037a84e134Smrg
4047a84e134Smrg    smw->simple_menu.label = NULL;
4057a84e134Smrg    smw->simple_menu.entry_set = NULL;
4067a84e134Smrg    smw->simple_menu.recursive_set_values = False;
4077a84e134Smrg#ifndef OLDXAW
4087a84e134Smrg    smw->simple_menu.sub_menu = NULL;
4097a84e134Smrg    smw->simple_menu.state = 0;
4107a84e134Smrg
4117a84e134Smrg    XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL);
4127a84e134Smrg#endif
4137a84e134Smrg
4147a84e134Smrg    if (smw->simple_menu.label_string != NULL)
4157a84e134Smrg	CreateLabel(cnew);
4167a84e134Smrg
4177a84e134Smrg    width = height = 0;
4187a84e134Smrg    CalculateNewSize(cnew, &width, &height);
4197a84e134Smrg
4207a84e134Smrg    smw->simple_menu.menu_width = True;
4217a84e134Smrg
4227a84e134Smrg    if (XtWidth(smw) == 0) {
4237a84e134Smrg	smw->simple_menu.menu_width = False;
4247a84e134Smrg	XtWidth(smw) = width;
4257a84e134Smrg    }
4267a84e134Smrg
4277a84e134Smrg    smw->simple_menu.menu_height = True;
4287a84e134Smrg
4297a84e134Smrg    if (XtHeight(smw) == 0) {
4307a84e134Smrg	smw->simple_menu.menu_height = False;
4317a84e134Smrg	XtHeight(smw) = height;
4327a84e134Smrg    }
4337a84e134Smrg
4347a84e134Smrg    /*
4357a84e134Smrg     * Add a popup_callback routine for changing the cursor
4367a84e134Smrg     */
4377a84e134Smrg    XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL);
4387a84e134Smrg}
4397a84e134Smrg
4407a84e134Smrg/*
4417a84e134Smrg * Function:
4427a84e134Smrg *	XawSimpleMenuRedisplay
4437a84e134Smrg *
4447a84e134Smrg * Parameters:
4457a84e134Smrg *	w      - simple menu widget
4467a84e134Smrg *	event  - X event that caused this redisplay
4477a84e134Smrg *	region - region the needs to be repainted
4487a84e134Smrg *
4497a84e134Smrg * Description:
4507a84e134Smrg *	Redisplays the contents of the widget.
4517a84e134Smrg */
4527a84e134Smrg/*ARGSUSED*/
4537a84e134Smrgstatic void
4545ec34c4cSmrgXawSimpleMenuRedisplay(Widget w, XEvent *event _X_UNUSED, Region region)
4557a84e134Smrg{
4567a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
4577a84e134Smrg    SmeObject *entry;
4587a84e134Smrg    SmeObjectClass cclass;
4597a84e134Smrg
4607a84e134Smrg    if (region == NULL)
4617a84e134Smrg	XClearWindow(XtDisplay(w), XtWindow(w));
4627a84e134Smrg
4637a84e134Smrg#ifndef OLDXAW
4647a84e134Smrg    if (smw->simple_menu.display_list)
4657a84e134Smrg      XawRunDisplayList(w, smw->simple_menu.display_list, event, region);
4667a84e134Smrg#endif
4677a84e134Smrg
4687a84e134Smrg    /*
4697a84e134Smrg     * Check and Paint each of the entries - including the label
4707a84e134Smrg     */
4717a84e134Smrg    ForAllChildren(smw, entry) {
4727a84e134Smrg	if (!XtIsManaged((Widget)*entry))
4737a84e134Smrg	    continue;
4747a84e134Smrg
475421c997bSmrg	if (region != NULL)
4767a84e134Smrg	    switch(XRectInRegion(region, XtX(*entry),XtY(*entry),
4777a84e134Smrg				 XtWidth(*entry), XtHeight(*entry))) {
4787a84e134Smrg		case RectangleIn:
4797a84e134Smrg		case RectanglePart:
4807a84e134Smrg		    break;
4817a84e134Smrg		default:
4827a84e134Smrg		    continue;
4837a84e134Smrg	    }
4847a84e134Smrg
4857a84e134Smrg	cclass = (SmeObjectClass)(*entry)->object.widget_class;
4867a84e134Smrg
4877a84e134Smrg	if (cclass->rect_class.expose != NULL)
4887a84e134Smrg	    (cclass->rect_class.expose)((Widget)*entry, NULL, NULL);
4897a84e134Smrg    }
4907a84e134Smrg}
4917a84e134Smrg
4927a84e134Smrg/*
4937a84e134Smrg * Function:
4947a84e134Smrg *	XawSimpleMenuRealize
4957a84e134Smrg *
4967a84e134Smrg * Parameters:
4977a84e134Smrg *	w     - simple menu widget
4987a84e134Smrg *	mask  - value mask for the window to create
4997a84e134Smrg *	attrs - attributes for the window to create
5007a84e134Smrg *
5017a84e134Smrg * Description:
5027a84e134Smrg *	Realizes the widget.
5037a84e134Smrg */
5047a84e134Smrgstatic void
5057a84e134SmrgXawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs)
5067a84e134Smrg{
5077a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
5087a84e134Smrg#ifndef OLDXAW
5097a84e134Smrg    XawPixmap *pixmap;
5107a84e134Smrg#endif
5117a84e134Smrg
5127a84e134Smrg    attrs->cursor = smw->simple_menu.cursor;
5137a84e134Smrg    *mask |= CWCursor;
5147a84e134Smrg    if (smw->simple_menu.backing_store == Always ||
5157a84e134Smrg	smw->simple_menu.backing_store == NotUseful ||
5167a84e134Smrg	smw->simple_menu.backing_store == WhenMapped) {
5177a84e134Smrg	*mask |= CWBackingStore;
5187a84e134Smrg	attrs->backing_store = smw->simple_menu.backing_store;
5197a84e134Smrg    }
5207a84e134Smrg    else
5215ec34c4cSmrg	*mask &= (XtValueMask)(~CWBackingStore);
5227a84e134Smrg
5237a84e134Smrg    (*Superclass->core_class.realize)(w, mask, attrs);
5247a84e134Smrg
5257a84e134Smrg#ifndef OLDXAW
5267a84e134Smrg    if (w->core.background_pixmap > XtUnspecifiedPixmap) {
5277a84e134Smrg	pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
5285ec34c4cSmrg				      w->core.colormap, (int)w->core.depth);
5297a84e134Smrg	if (pixmap && pixmap->mask)
5307a84e134Smrg	    XawReshapeWidget(w, pixmap);
5317a84e134Smrg    }
5327a84e134Smrg#endif
5337a84e134Smrg}
5347a84e134Smrg
5357a84e134Smrg/*
5367a84e134Smrg * Function:
5377a84e134Smrg *	XawSimpleMenuResize
5387a84e134Smrg *
5397a84e134Smrg * Parameters:
5407a84e134Smrg *	w - simple menu widget
5417a84e134Smrg *
5427a84e134Smrg * Description:
5437a84e134Smrg *	Handle the menu being resized.
5447a84e134Smrg */
5457a84e134Smrgstatic void
5467a84e134SmrgXawSimpleMenuResize(Widget w)
5477a84e134Smrg{
5487a84e134Smrg    if (!XtIsRealized(w))
5497a84e134Smrg	return;
5507a84e134Smrg
5517a84e134Smrg    Layout(w, NULL, NULL);
5527a84e134Smrg
5537a84e134Smrg    XawSimpleMenuRedisplay(w, NULL, NULL);
5547a84e134Smrg}
5557a84e134Smrg
5567a84e134Smrg/*
5577a84e134Smrg * Function:
5587a84e134Smrg *	XawSimpleMenuSetValues
5597a84e134Smrg *
5607a84e134Smrg * Parameters:
5617a84e134Smrg *	current - current state of the widget
5627a84e134Smrg *	request - what was requested
5637a84e134Smrg *	cnew    - what the widget will become
5647a84e134Smrg *
5657a84e134Smrg * Description:
5667a84e134Smrg *	Relayout the menu when one of the resources is changed.
5677a84e134Smrg */
5687a84e134Smrg/*ARGSUSED*/
5697a84e134Smrgstatic Boolean
5705ec34c4cSmrgXawSimpleMenuSetValues(Widget current, Widget request _X_UNUSED, Widget cnew,
5715ec34c4cSmrg		       ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
5727a84e134Smrg{
5737a84e134Smrg    SimpleMenuWidget smw_old = (SimpleMenuWidget)current;
5747a84e134Smrg    SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew;
5757a84e134Smrg    Boolean ret_val = False, layout = False;
5767a84e134Smrg
5777a84e134Smrg    if (!XtIsRealized(current))
5787a84e134Smrg	return (False);
5797a84e134Smrg
5807a84e134Smrg    if (!smw_new->simple_menu.recursive_set_values) {
5817a84e134Smrg	if (XtWidth(smw_new) != XtWidth(smw_old)) {
5827a84e134Smrg	    smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0;
5837a84e134Smrg	    layout = True;
5847a84e134Smrg	}
5857a84e134Smrg	if (XtHeight(smw_new) != XtHeight(smw_old)) {
5867a84e134Smrg	    smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0;
5877a84e134Smrg	    layout = True;
5887a84e134Smrg	}
5897a84e134Smrg    }
5907a84e134Smrg
5917a84e134Smrg    if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
5927a84e134Smrg	XDefineCursor(XtDisplay(cnew), XtWindow(cnew),
5937a84e134Smrg		      smw_new->simple_menu.cursor);
5947a84e134Smrg
5957a84e134Smrg    if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) {
5967a84e134Smrg	if (smw_new->simple_menu.label_string == NULL)	    /* Destroy */
5977a84e134Smrg	    XtDestroyWidget((Widget)smw_old->simple_menu.label);
5987a84e134Smrg	else if (smw_old->simple_menu.label_string == NULL) /* Create */
5997a84e134Smrg	    CreateLabel(cnew);
6007a84e134Smrg	else {						    /* Change */
6017a84e134Smrg	    Arg arglist[1];
602421c997bSmrg
6037a84e134Smrg	    XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string);
6047a84e134Smrg	    XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE);
6057a84e134Smrg	}
6067a84e134Smrg    }
6077a84e134Smrg
6087a84e134Smrg    if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
6097a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(cnew),
6107a84e134Smrg		     "No Dynamic class change of the SimpleMenu Label.");
611421c997bSmrg
6127a84e134Smrg    if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin
6137a84e134Smrg	|| smw_old->simple_menu.bottom_margin
6147a84e134Smrg	!= smw_new->simple_menu.bottom_margin) {
6157a84e134Smrg	layout = True;
6167a84e134Smrg	ret_val = True;
6177a84e134Smrg    }
6187a84e134Smrg
6197a84e134Smrg#ifndef OLDXAW
6207a84e134Smrg    if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) {
6217a84e134Smrg	XawPixmap *opix, *npix;
6227a84e134Smrg
6237a84e134Smrg	opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap,
6247a84e134Smrg				    XtScreen(smw_old), smw_old->core.colormap,
6255ec34c4cSmrg				    (int)smw_old->core.depth);
6267a84e134Smrg	npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap,
6277a84e134Smrg				    XtScreen(smw_new), smw_new->core.colormap,
6285ec34c4cSmrg				    (int)smw_new->core.depth);
6297a84e134Smrg	if ((npix && npix->mask) || (opix && opix->mask))
6307a84e134Smrg	    XawReshapeWidget(cnew, npix);
6317a84e134Smrg    }
6327a84e134Smrg#endif
6337a84e134Smrg
6347a84e134Smrg    if (layout)
6357a84e134Smrg	Layout(cnew, NULL, NULL);
6367a84e134Smrg
6377a84e134Smrg    return (ret_val);
6387a84e134Smrg}
6397a84e134Smrg
640421c997bSmrg/*
6417a84e134Smrg * Function:
6427a84e134Smrg *	XawSimpleMenuSetValuesHook
6437a84e134Smrg *
6447a84e134Smrg * Parameters:
6457a84e134Smrg *	w	 - menu widget
6467a84e134Smrg *	arglist	 - argument list passed to XtSetValues
6477a84e134Smrg *	num_args - number of args
6487a84e134Smrg *
6497a84e134Smrg * Description:
6507a84e134Smrg *	To handle a special case, this is passed the actual arguments.
6517a84e134Smrg */
6527a84e134Smrgstatic Boolean
6537a84e134SmrgXawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args)
6547a84e134Smrg{
6557a84e134Smrg    Cardinal i;
6567a84e134Smrg    Dimension width, height;
657421c997bSmrg
6587a84e134Smrg    width = XtWidth(w);
6597a84e134Smrg    height = XtHeight(w);
660421c997bSmrg
6617a84e134Smrg    for (i = 0 ; i < *num_args ; i++) {
6627a84e134Smrg	if (streq(arglist[i].name, XtNwidth))
6637a84e134Smrg	    width = (Dimension)arglist[i].value;
6647a84e134Smrg	if (streq(arglist[i].name, XtNheight))
6657a84e134Smrg	    height = (Dimension) arglist[i].value;
6667a84e134Smrg    }
6677a84e134Smrg
6687a84e134Smrg    if (width != XtWidth(w) || height != XtHeight(w))
6697a84e134Smrg	MakeSetValuesRequest(w, width, height);
6707a84e134Smrg
6717a84e134Smrg    return (False);
6727a84e134Smrg}
6737a84e134Smrg
6747a84e134Smrg/*
6757a84e134Smrg * Geometry Management routines
6767a84e134Smrg */
6777a84e134Smrg/*
6787a84e134Smrg * Function:
6797a84e134Smrg *	XawSimpleMenuGeometryManager
6807a84e134Smrg *
6817a84e134Smrg * Parameters:
6827a84e134Smrg *	w	- Menu Entry making the request
6837a84e134Smrg *	request - requested new geometry
6847a84e134Smrg *                 reply - the allowed geometry.
6857a84e134Smrg *
6867a84e134Smrg * Description:
6877a84e134Smrg *	This is the SimpleMenu Widget's Geometry Manager.
6887a84e134Smrg *
6897a84e134Smrg * Returns:
6907a84e134Smrg *	XtGeometry{Yes, No, Almost}
6917a84e134Smrg */
6927a84e134Smrgstatic XtGeometryResult
6937a84e134SmrgXawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request,
6947a84e134Smrg			     XtWidgetGeometry *reply)
6957a84e134Smrg{
6967a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w);
6977a84e134Smrg    SmeObject entry = (SmeObject)w;
6987a84e134Smrg    XtGeometryMask mode = request->request_mode;
6997a84e134Smrg    XtGeometryResult answer;
7007a84e134Smrg    Dimension old_height, old_width;
7017a84e134Smrg
7027a84e134Smrg    if (!(mode & CWWidth) && !(mode & CWHeight))
7037a84e134Smrg	return (XtGeometryNo);
7047a84e134Smrg
7057a84e134Smrg    reply->width = request->width;
7067a84e134Smrg    reply->height = request->height;
7077a84e134Smrg
7087a84e134Smrg    old_width = XtWidth(entry);
7097a84e134Smrg    old_height = XtHeight(entry);
7107a84e134Smrg
7117a84e134Smrg    Layout(w, &reply->width, &reply->height);
7127a84e134Smrg
7137a84e134Smrg    /*
7147a84e134Smrg     * Since we are an override shell and have no parent there is no one to
7157a84e134Smrg     * ask to see if this geom change is okay, so I am just going to assume
7167a84e134Smrg     * we can do whatever we want.  If you subclass be very careful with this
7177a84e134Smrg     * assumption, it could bite you.
7187a84e134Smrg     *
7197a84e134Smrg     * Chris D. Peterson - Sept. 1989.
7207a84e134Smrg     */
7217a84e134Smrg    if ((!(mode & CWWidth) || reply->width == request->width)
7227a84e134Smrg	&& (!(mode & CWHeight) || reply->height == request->height)) {
7237a84e134Smrg	if (mode & XtCWQueryOnly) {	/* Actually perform the layout */
7247a84e134Smrg	    XtWidth(entry) = old_width;
7257a84e134Smrg	    XtHeight(entry) = old_height;
7267a84e134Smrg	}
7277a84e134Smrg	else
7287a84e134Smrg	    Layout((Widget)smw, NULL, NULL);
7297a84e134Smrg	answer = XtGeometryDone;
7307a84e134Smrg    }
7317a84e134Smrg    else {
7327a84e134Smrg	XtWidth(entry) = old_width;
7337a84e134Smrg	XtHeight(entry) = old_height;
7347a84e134Smrg
7357a84e134Smrg	if ((reply->width == request->width && !(mode & CWHeight))
7367a84e134Smrg	    || (reply->height == request->height && !(mode & CWWidth))
7377a84e134Smrg	    || (reply->width == request->width
7387a84e134Smrg	    && reply->height == request->height))
7397a84e134Smrg	    answer = XtGeometryNo;
7407a84e134Smrg	else {
7417a84e134Smrg	    answer = XtGeometryAlmost;
7427a84e134Smrg	    reply->request_mode = 0;
7437a84e134Smrg	    if (reply->width != request->width)
7447a84e134Smrg		reply->request_mode |= CWWidth;
7457a84e134Smrg	    if (reply->height != request->height)
7467a84e134Smrg		reply->request_mode |= CWHeight;
7477a84e134Smrg	}
7487a84e134Smrg    }
7497a84e134Smrg
7507a84e134Smrg    return (answer);
7517a84e134Smrg}
7527a84e134Smrg
7537a84e134Smrg/*
7547a84e134Smrg * Function:
7557a84e134Smrg *	XawSimpleMenuChangeManaged
7567a84e134Smrg *
7577a84e134Smrg * Parameters:
7587a84e134Smrg *	w - simple menu widget
7597a84e134Smrg *
7607a84e134Smrg * Description:
7617a84e134Smrg *	Called whenever a new child is managed.
7627a84e134Smrg */
7637a84e134Smrgstatic void
7647a84e134SmrgXawSimpleMenuChangeManaged(Widget w)
7657a84e134Smrg{
7667a84e134Smrg    Layout(w, NULL, NULL);
7677a84e134Smrg}
7687a84e134Smrg
7697a84e134Smrg/*
7707a84e134Smrg * Global Action Routines
771421c997bSmrg *
7727a84e134Smrg * These actions routines will be added to the application's
7737a84e134Smrg * global action list
7747a84e134Smrg */
7757a84e134Smrg/*
7767a84e134Smrg * Function:
7777a84e134Smrg *	PositionMenuAction
778421c997bSmrg *
7797a84e134Smrg * Parameters:
7807a84e134Smrg *	w	   - a widget (no the simple menu widget)
7817a84e134Smrg *	event	   - the event that caused this action
7827a84e134Smrg *	params	   - parameters passed to the routine.
7837a84e134Smrg *                                      we expect the name of the menu here.
7847a84e134Smrg *	num_params - ""
7857a84e134Smrg *
7867a84e134Smrg * Description:
7877a84e134Smrg *	Positions the simple menu widget.
7887a84e134Smrg */
7897a84e134Smrg/*ARGSUSED*/
7907a84e134Smrgstatic void
7917a84e134SmrgPositionMenuAction(Widget w, XEvent *event,
7927a84e134Smrg		   String *params, Cardinal *num_params)
793421c997bSmrg{
7947a84e134Smrg    Widget menu;
7957a84e134Smrg    XPoint loc;
7967a84e134Smrg
7977a84e134Smrg    if (*num_params != 1) {
7987a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w),
7997a84e134Smrg		     "SimpleMenuWidget: position menu action expects "
8007a84e134Smrg		     "only one parameter which is the name of the menu.");
8017a84e134Smrg	return;
8027a84e134Smrg    }
8037a84e134Smrg
8047a84e134Smrg    if ((menu = FindMenu(w, params[0])) == NULL) {
8057a84e134Smrg	char error_buf[BUFSIZ];
8067a84e134Smrg
807421c997bSmrg	snprintf(error_buf, sizeof(error_buf),
808421c997bSmrg		 "SimpleMenuWidget: could not find menu named %s.",
809421c997bSmrg		 params[0]);
8107a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
8117a84e134Smrg	return;
8127a84e134Smrg    }
813421c997bSmrg
8147a84e134Smrg    switch (event->type) {
8157a84e134Smrg	case ButtonPress:
8167a84e134Smrg	case ButtonRelease:
8175ec34c4cSmrg	    loc.x = (short)event->xbutton.x_root;
8185ec34c4cSmrg	    loc.y = (short)event->xbutton.y_root;
8197a84e134Smrg	    PositionMenu(menu, &loc);
8207a84e134Smrg	    break;
8217a84e134Smrg	case EnterNotify:
8227a84e134Smrg	case LeaveNotify:
8235ec34c4cSmrg	    loc.x = (short)event->xcrossing.x_root;
8245ec34c4cSmrg	    loc.y = (short)event->xcrossing.y_root;
8257a84e134Smrg	    PositionMenu(menu, &loc);
8267a84e134Smrg	    break;
8277a84e134Smrg	case MotionNotify:
8285ec34c4cSmrg	    loc.x = (short)event->xmotion.x_root;
8295ec34c4cSmrg	    loc.y = (short)event->xmotion.y_root;
8307a84e134Smrg	    PositionMenu(menu, &loc);
8317a84e134Smrg	    break;
8327a84e134Smrg	default:
8337a84e134Smrg	    PositionMenu(menu, NULL);
8347a84e134Smrg	    break;
8357a84e134Smrg    }
836421c997bSmrg}
8377a84e134Smrg
8387a84e134Smrg/*
8397a84e134Smrg * Widget Action Routines
8407a84e134Smrg */
8417a84e134Smrg/*
8427a84e134Smrg * Function:
8437a84e134Smrg *	Unhighlight
8447a84e134Smrg *
8457a84e134Smrg * Parameters:
8467a84e134Smrg *	w	   - simple menu widget
8477a84e134Smrg *	event	   - event that caused this action
8487a84e134Smrg *	params	   - not used
8497a84e134Smrg *	num_params - ""
850421c997bSmrg *
8517a84e134Smrg * Description:
8527a84e134Smrg *	Unhighlights current entry.
8537a84e134Smrg */
8547a84e134Smrg/*ARGSUSED*/
8557a84e134Smrgstatic void
8565ec34c4cSmrgUnhighlight(Widget w, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED)
857421c997bSmrg{
8587a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
8597a84e134Smrg    SmeObject entry = smw->simple_menu.entry_set;
860421c997bSmrg
8617a84e134Smrg    if (entry == NULL)
8627a84e134Smrg	return;
8637a84e134Smrg
8647a84e134Smrg#ifndef OLDXAW
8657a84e134Smrg    if (!smw->simple_menu.sub_menu)
8667a84e134Smrg#endif
8677a84e134Smrg    {
8687a84e134Smrg	SmeObjectClass cclass;
8697a84e134Smrg
8707a84e134Smrg	smw->simple_menu.entry_set = NULL;
8717a84e134Smrg	cclass = (SmeObjectClass)entry->object.widget_class;
8727a84e134Smrg	(cclass->sme_class.unhighlight)((Widget)entry);
8737a84e134Smrg    }
8747a84e134Smrg}
8757a84e134Smrg
8767a84e134Smrg/*
8777a84e134Smrg * Function:
8787a84e134Smrg *	Highlight
8797a84e134Smrg *
8807a84e134Smrg * Parameters:
8817a84e134Smrg *	w	   - simple menu widget
8827a84e134Smrg *	event	   - event that caused this action
8837a84e134Smrg *	params	   - not used
8847a84e134Smrg *	num_params - ""
8857a84e134Smrg *
8867a84e134Smrg * Description:
8877a84e134Smrg *	Highlights current entry.
8887a84e134Smrg */
8897a84e134Smrg/*ARGSUSED*/
8907a84e134Smrgstatic void
8917a84e134SmrgHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
8927a84e134Smrg{
8937a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
8947a84e134Smrg    SmeObject entry;
8957a84e134Smrg
8967a84e134Smrg    if (!XtIsSensitive(w))
8977a84e134Smrg	return;
8987a84e134Smrg
8997a84e134Smrg    entry = GetEventEntry(w, event);
9007a84e134Smrg
9017a84e134Smrg    if (entry == smw->simple_menu.entry_set)
9027a84e134Smrg	return;
9037a84e134Smrg
9047a84e134Smrg#ifndef OLDXAW
9057a84e134Smrg    if (!smw->simple_menu.sub_menu)
9067a84e134Smrg#endif
9077a84e134Smrg	Unhighlight(w, event, params, num_params);
9087a84e134Smrg
9097a84e134Smrg    if (entry == NULL)
9107a84e134Smrg	return;
9117a84e134Smrg
9127a84e134Smrg    if (!XtIsSensitive((Widget)entry))
9137a84e134Smrg	return;
9147a84e134Smrg
9157a84e134Smrg#ifndef OLDXAW
9167a84e134Smrg    if (smw->simple_menu.sub_menu)
9177a84e134Smrg	PopdownSubMenu(smw);
9187a84e134Smrg#endif
9197a84e134Smrg
9207a84e134Smrg    Unhighlight(w, event, params, num_params);
9217a84e134Smrg
9227a84e134Smrg#ifndef OLDXAW
9237a84e134Smrg    if (!(smw->simple_menu.state & SMW_UNMAPPING))
9247a84e134Smrg#endif
9257a84e134Smrg    {
9267a84e134Smrg	SmeObjectClass cclass;
9277a84e134Smrg
9287a84e134Smrg	smw->simple_menu.entry_set = entry;
9297a84e134Smrg	cclass = (SmeObjectClass)entry->object.widget_class;
9307a84e134Smrg
9317a84e134Smrg	(cclass->sme_class.highlight)((Widget)entry);
9327a84e134Smrg
9337a84e134Smrg#ifndef OLDXAW
9347a84e134Smrg	if (XtIsSubclass((Widget)entry, smeBSBObjectClass))
9357a84e134Smrg	    PopupSubMenu(smw);
9367a84e134Smrg#endif
9377a84e134Smrg    }
9387a84e134Smrg}
9397a84e134Smrg
9407a84e134Smrg/*
9417a84e134Smrg * Function:
9427a84e134Smrg *	Notify
9437a84e134Smrg *
9447a84e134Smrg * Parameters:
9457a84e134Smrg *	w	   - simple menu widget
9467a84e134Smrg *	event	   - event that caused this action
9477a84e134Smrg *	params	   - not used
9487a84e134Smrg *	num_params - ""
9497a84e134Smrg *
9507a84e134Smrg * Description:
9517a84e134Smrg *	Notify user of current entry.
9527a84e134Smrg */
9537a84e134Smrg/*ARGSUSED*/
9547a84e134Smrgstatic void
9555ec34c4cSmrgNotify(Widget w, XEvent *event, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED)
9567a84e134Smrg{
9577a84e134Smrg    SmeObject entry;
9587a84e134Smrg    SmeObjectClass cclass;
9597a84e134Smrg
9607a84e134Smrg    /* may be a propagated event from a sub menu, need to check it */
9617a84e134Smrg    if (XtWindow(w) != event->xany.window)
9627a84e134Smrg	return;
9637a84e134Smrg    entry = GetEventEntry(w, event);
9647a84e134Smrg    if (entry == NULL || !XtIsSensitive((Widget)entry))
9657a84e134Smrg	return;
9667a84e134Smrg
9677a84e134Smrg    cclass = (SmeObjectClass) entry->object.widget_class;
9687a84e134Smrg    (cclass->sme_class.notify)((Widget)entry);
9697a84e134Smrg}
9707a84e134Smrg
9717a84e134Smrg/*
9727a84e134Smrg * Public Functions
9737a84e134Smrg */
9747a84e134Smrg/*
9757a84e134Smrg * Function:
9767a84e134Smrg *	XawSimpleMenuAddGlobalActions
9777a84e134Smrg *
9787a84e134Smrg * Arguments:
9797a84e134Smrg *	app_con - appcontext
9807a84e134Smrg *
9817a84e134Smrg * Description:
9827a84e134Smrg *	Adds the global actions to the simple menu widget.
9837a84e134Smrg */
9847a84e134Smrgvoid
9857a84e134SmrgXawSimpleMenuAddGlobalActions(XtAppContext app_con)
9867a84e134Smrg{
9877a84e134Smrg    XtInitializeWidgetClass(simpleMenuWidgetClass);
9887a84e134Smrg    XmuCallInitializers(app_con);
989421c997bSmrg}
9907a84e134Smrg
9917a84e134Smrg/*
9927a84e134Smrg * Function:
9937a84e134Smrg *	XawSimpleMenuGetActiveEntry
9947a84e134Smrg *
9957a84e134Smrg * Parameters:
9967a84e134Smrg *	w - smw widget
9977a84e134Smrg *
9987a84e134Smrg * Description:
9997a84e134Smrg *	Gets the currently active (set) entry.
10007a84e134Smrg *
10017a84e134Smrg * Returns:
10027a84e134Smrg *	The currently set entry or NULL if none is set
10037a84e134Smrg */
10047a84e134SmrgWidget
10057a84e134SmrgXawSimpleMenuGetActiveEntry(Widget w)
10067a84e134Smrg{
10077a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10087a84e134Smrg
10097a84e134Smrg    return ((Widget)smw->simple_menu.entry_set);
1010421c997bSmrg}
10117a84e134Smrg
10127a84e134Smrg/*
10137a84e134Smrg * Function:
10147a84e134Smrg *	XawSimpleMenuClearActiveEntry
10157a84e134Smrg *
10167a84e134Smrg * Parameters:
10177a84e134Smrg *	w - smw widget
10187a84e134Smrg *
10197a84e134Smrg * Description:
10207a84e134Smrg *	Unsets the currently active (set) entry.
10217a84e134Smrg */
10227a84e134Smrgvoid
10237a84e134SmrgXawSimpleMenuClearActiveEntry(Widget w)
10247a84e134Smrg{
10257a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10267a84e134Smrg
10277a84e134Smrg    smw->simple_menu.entry_set = NULL;
1028421c997bSmrg}
10297a84e134Smrg
10307a84e134Smrg/*
10317a84e134Smrg * Private Functions
10327a84e134Smrg */
10337a84e134Smrg/*
10347a84e134Smrg * Function:
10357a84e134Smrg *	CreateLabel
10367a84e134Smrg *
10377a84e134Smrg * Parameters:
10387a84e134Smrg *	w - smw widget
1039421c997bSmrg *
10407a84e134Smrg * Description:
10417a84e134Smrg * Creates the label object and makes sure it is the first child in
10427a84e134Smrg * in the list.
10437a84e134Smrg */
10447a84e134Smrgstatic void
10457a84e134SmrgCreateLabel(Widget w)
10467a84e134Smrg{
10477a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10487a84e134Smrg    Widget *child, *next_child;
10497a84e134Smrg    int i;
10507a84e134Smrg    Arg args[2];
10517a84e134Smrg
10527a84e134Smrg    if (smw->simple_menu.label_string == NULL ||
10537a84e134Smrg	smw->simple_menu.label != NULL) {
10547a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w),
10557a84e134Smrg		     "Xaw Simple Menu Widget: label string is NULL or "
10567a84e134Smrg		     "label already exists, no label is being created.");
10577a84e134Smrg	return;
10587a84e134Smrg    }
10597a84e134Smrg
10607a84e134Smrg    XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
10617a84e134Smrg    XtSetArg(args[1], XtNjustify, XtJustifyCenter);
1062421c997bSmrg    smw->simple_menu.label = (SmeObject)
1063421c997bSmrg	XtCreateManagedWidget("menuLabel",
10647a84e134Smrg			      smw->simple_menu.label_class, w, args, TWO);
10657a84e134Smrg
10667a84e134Smrg    next_child = NULL;
10677a84e134Smrg    for (child = smw->composite.children + smw->composite.num_children,
10685ec34c4cSmrg	 i = (int)smw->composite.num_children; i > 0; i--, child--) {
10697a84e134Smrg	if (next_child != NULL)
10707a84e134Smrg	    *next_child = *child;
10717a84e134Smrg	next_child = child;
10727a84e134Smrg    }
10737a84e134Smrg    *child = (Widget)smw->simple_menu.label;
10747a84e134Smrg}
10757a84e134Smrg
10767a84e134Smrg/*
10777a84e134Smrg * Function:
10787a84e134Smrg *	Layout
10797a84e134Smrg *
10807a84e134Smrg * Arguments:
10817a84e134Smrg *	w	   - See below
10827a84e134Smrg *	width_ret  - returned width
10837a84e134Smrg *	height_ret - returned height
10847a84e134Smrg *
10857a84e134Smrg * Note:
10867a84e134Smrg * if width == NULL || height == NULL then it assumes the you do not care
10877a84e134Smrg * about the return values, and just want a relayout.
10887a84e134Smrg *
10897a84e134Smrg * if this is not the case then it will set width_ret and height_ret
10905b16253fSmrg * to be width and height that the child would get if it were laid out
10917a84e134Smrg * at this time.
10927a84e134Smrg *
10937a84e134Smrg *	"w" can be the simple menu widget or any of its object children.
10947a84e134Smrg */
10957a84e134Smrgstatic void
10967a84e134SmrgLayout(Widget w, Dimension *width_ret, Dimension *height_ret)
10977a84e134Smrg{
10987a84e134Smrg    SmeObject current_entry;
10997a84e134Smrg    SimpleMenuWidget smw;
11007a84e134Smrg    Dimension width, height;
11017a84e134Smrg    Boolean allow_change_size;
11027a84e134Smrg    Widget kid;
11037a84e134Smrg    Cardinal i, count, n;
11047a84e134Smrg    int width_kid, height_kid, tmp_w, tmp_h;
11057a84e134Smrg    short vadd, hadd, x_ins, y_ins;
11067a84e134Smrg    Dimension *widths;
11077a84e134Smrg
11087a84e134Smrg    height = 0;
11097a84e134Smrg
11107a84e134Smrg    if (XtIsSubclass(w, simpleMenuWidgetClass)) {
11117a84e134Smrg	smw = (SimpleMenuWidget)w;
11127a84e134Smrg	current_entry = NULL;
11137a84e134Smrg    }
11147a84e134Smrg    else {
11157a84e134Smrg	smw = (SimpleMenuWidget)XtParent(w);
11167a84e134Smrg	current_entry = (SmeObject)w;
11177a84e134Smrg    }
11187a84e134Smrg
11197a84e134Smrg    allow_change_size = (!XtIsRealized((Widget)smw)
11207a84e134Smrg			 || smw->shell.allow_shell_resize);
11217a84e134Smrg
11227a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
11237a84e134Smrg	 i < smw->composite.num_children;
11247a84e134Smrg	 i++) {
11257a84e134Smrg	XtWidgetGeometry preferred;
11267a84e134Smrg
11277a84e134Smrg	kid = smw->composite.children[i];
11287a84e134Smrg	if (!XtIsManaged(kid))
11297a84e134Smrg	    continue;
11307a84e134Smrg	if (smw->simple_menu.row_height != 0)
11317a84e134Smrg	    XtHeight(kid) = smw->simple_menu.row_height;
11327a84e134Smrg	XtQueryGeometry(kid, NULL, &preferred);
11337a84e134Smrg	if (preferred.request_mode & CWWidth)
11347a84e134Smrg	    XtWidth(kid) = preferred.width;
11357a84e134Smrg    }
11367a84e134Smrg
11377a84e134Smrg    if (smw->simple_menu.label
11387a84e134Smrg	&& XtIsManaged((Widget)smw->simple_menu.label)) {
11397a84e134Smrg	XtWidgetGeometry preferred;
11407a84e134Smrg
11417a84e134Smrg	kid = (Widget)smw->simple_menu.label;
11427a84e134Smrg	XtQueryGeometry(kid, NULL, &preferred);
11437a84e134Smrg	if (preferred.request_mode & CWWidth)
11447a84e134Smrg	    XtWidth(kid) = preferred.width;
11457a84e134Smrg	if (preferred.request_mode & CWHeight)
11467a84e134Smrg	    XtHeight(kid) = preferred.height;
11477a84e134Smrg    }
11487a84e134Smrg
11497a84e134Smrg    /* reset */
11507a84e134Smrg    if (!smw->simple_menu.menu_width)
11517a84e134Smrg	XtWidth(smw) = 0;
11527a84e134Smrg    if (!smw->simple_menu.menu_height)
11537a84e134Smrg	XtHeight(smw) = 0;
11547a84e134Smrg    if (!XtWidth(smw) || !XtHeight(smw))
11557a84e134Smrg	MakeResizeRequest((Widget)smw);
11567a84e134Smrg
11577a84e134Smrg    widths = (Dimension *)XtMalloc(sizeof(Dimension));
11587a84e134Smrg#ifndef OLDXAW
11595ec34c4cSmrg    hadd = (short)smw->simple_menu.left_margin;
11607a84e134Smrg#else
11617a84e134Smrg    hadd = 0;
11627a84e134Smrg#endif
11635ec34c4cSmrg    vadd = (short)smw->simple_menu.top_margin;
11647a84e134Smrg    if (smw->simple_menu.label)
11655ec34c4cSmrg	vadd = (short)(vadd + XtHeight(smw->simple_menu.label));
11667a84e134Smrg
11677a84e134Smrg    count = 1;
11685ec34c4cSmrg    width = (Dimension)(tmp_w = tmp_h = (int)(n = 0));
11695ec34c4cSmrg    height = (Dimension)vadd;
11707a84e134Smrg
11717a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
11727a84e134Smrg	 i < smw->composite.num_children;
11737a84e134Smrg	 i++) {
11747a84e134Smrg	kid = smw->composite.children[i];
11757a84e134Smrg	if (!XtIsManaged(kid))
11767a84e134Smrg	    continue;
11777a84e134Smrg	width_kid = XtWidth(kid);
11787a84e134Smrg	height_kid = XtHeight(kid);
11797a84e134Smrg
11807a84e134Smrg	if (n && (height + height_kid + smw->simple_menu.bottom_margin
11817a84e134Smrg		  > XtHeight(smw))) {
11827a84e134Smrg	    ++count;
11837a84e134Smrg	    widths = (Dimension *)XtRealloc((char *)widths,
11845ec34c4cSmrg					    (Cardinal)(sizeof(Dimension) * count));
11855ec34c4cSmrg	    widths[count - 1] = (Dimension)width_kid;
11865ec34c4cSmrg	    width = (Dimension)(width + tmp_w);
11877a84e134Smrg	    tmp_w = width_kid;
11885ec34c4cSmrg	    height = (Dimension)(height_kid + vadd);
11897a84e134Smrg	}
11907a84e134Smrg	else
11915ec34c4cSmrg	    height = (Dimension)(height + height_kid);
11927a84e134Smrg	if (height > tmp_h)
11937a84e134Smrg	    tmp_h = height;
11947a84e134Smrg	if (width_kid > tmp_w)
11955ec34c4cSmrg	    widths[count - 1] = (Dimension)(tmp_w = width_kid);
11967a84e134Smrg	++n;
11977a84e134Smrg    }
11987a84e134Smrg
11995ec34c4cSmrg    height = (tmp_h + smw->simple_menu.bottom_margin);
12005ec34c4cSmrg    width = (Dimension)(width + tmp_w);
12017a84e134Smrg
12027a84e134Smrg    if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) {
12037a84e134Smrg	float inc;
12047a84e134Smrg
12055ec34c4cSmrg	inc = (float)(XtWidth(smw->simple_menu.label) - width) / (float)count;
12067a84e134Smrg	width = XtWidth(smw->simple_menu.label);
12077a84e134Smrg	for (n = 0; n < count; n++)
12085ec34c4cSmrg	    widths[n] = (Dimension)(widths[n] + inc);
12097a84e134Smrg    }
12107a84e134Smrg
12117a84e134Smrg#ifndef OLDXAW
12125ec34c4cSmrg    width = (Dimension)(width + (hadd + smw->simple_menu.right_margin));
12137a84e134Smrg#endif
12147a84e134Smrg
12155ec34c4cSmrg    x_ins = (short)(n = count = 0);
12167a84e134Smrg    tmp_w = widths[0];
12177a84e134Smrg    tmp_h = vadd;
12187a84e134Smrg
12197a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
12207a84e134Smrg	 i < smw->composite.num_children;
12217a84e134Smrg	 i++) {
12227a84e134Smrg	kid = smw->composite.children[i];
12237a84e134Smrg	if (!XtIsManaged(kid))
12247a84e134Smrg	    continue;
12257a84e134Smrg
12267a84e134Smrg	height_kid = XtHeight(kid);
12277a84e134Smrg
12287a84e134Smrg	if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin
12297a84e134Smrg		  > XtHeight(smw))) {
12305ec34c4cSmrg	    x_ins = (short)tmp_w;
12317a84e134Smrg	    y_ins = vadd;
12327a84e134Smrg	    ++count;
12337a84e134Smrg	    tmp_w += widths[count];
12347a84e134Smrg	    tmp_h = height_kid + vadd;
12357a84e134Smrg	}
12367a84e134Smrg	else {
12375ec34c4cSmrg	    y_ins = (short)tmp_h;
12387a84e134Smrg	    tmp_h += height_kid;
12397a84e134Smrg	}
12407a84e134Smrg	++n;
12417a84e134Smrg
12425ec34c4cSmrg	XtX(kid) = (Position)(x_ins + hadd);
12437a84e134Smrg	XtY(kid) = y_ins;
12447a84e134Smrg	XtWidth(kid) = widths[count];
12457a84e134Smrg    }
12467a84e134Smrg
12477a84e134Smrg    XtFree((char *)widths);
12487a84e134Smrg
12497a84e134Smrg    if (allow_change_size)
12507a84e134Smrg	MakeSetValuesRequest((Widget) smw, width, height);
12517a84e134Smrg
12527a84e134Smrg    if (smw->simple_menu.label) {
12537a84e134Smrg	XtX(smw->simple_menu.label) = 0;
12545ec34c4cSmrg	XtY(smw->simple_menu.label) = (Position)smw->simple_menu.top_margin;
12555ec34c4cSmrg	XtWidth(smw->simple_menu.label) = (Dimension)(XtWidth(smw)
12567a84e134Smrg#ifndef OLDXAW
12577a84e134Smrg	    - (smw->simple_menu.left_margin + smw->simple_menu.right_margin)
12587a84e134Smrg#endif
12595ec34c4cSmrg	    );
12607a84e134Smrg    }
12617a84e134Smrg    if (current_entry) {
12627a84e134Smrg	if (width_ret)
12637a84e134Smrg	    *width_ret = XtWidth(current_entry);
12647a84e134Smrg	if (height_ret)
12657a84e134Smrg	    *height_ret = XtHeight(current_entry);
12667a84e134Smrg    }
12677a84e134Smrg}
1268421c997bSmrg
12697a84e134Smrg/*
12707a84e134Smrg * Function:
12717a84e134Smrg *	AddPositionAction
12727a84e134Smrg *
12737a84e134Smrg * Parameters:
12747a84e134Smrg *	app_con - application context
12757a84e134Smrg *	data	- (not used)
12767a84e134Smrg *
12777a84e134Smrg * Description:
12787a84e134Smrg *	  Adds the XawPositionSimpleMenu action to the global
12797a84e134Smrg *                   action list for this appcon.
12807a84e134Smrg */
12817a84e134Smrg/*ARGSUSED*/
12827a84e134Smrgstatic void
12835ec34c4cSmrgAddPositionAction(XtAppContext app_con, XPointer data _X_UNUSED)
12847a84e134Smrg{
12857a84e134Smrg    static XtActionsRec pos_action[] = {
12867a84e134Smrg	{"XawPositionSimpleMenu",	PositionMenuAction},
12877a84e134Smrg    };
12887a84e134Smrg
12897a84e134Smrg    XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
12907a84e134Smrg}
12917a84e134Smrg
12927a84e134Smrg/*
12937a84e134Smrg * Function:
12947a84e134Smrg *	FindMenu
12957a84e134Smrg *
12967a84e134Smrg * Parameters:
12977a84e134Smrg *	widget - reference widget
12987a84e134Smrg *	name   - menu widget's name
12997a84e134Smrg *
13007a84e134Smrg * Description:
13017a84e134Smrg *	Find the menu give a name and reference widget
13027a84e134Smrg *
13037a84e134Smrg * Returns:
13047a84e134Smrg *	The menu widget or NULL.
13057a84e134Smrg */
1306421c997bSmrgstatic Widget
13077a84e134SmrgFindMenu(Widget widget, String name)
13087a84e134Smrg{
13097a84e134Smrg    Widget w, menu;
1310421c997bSmrg
13117a84e134Smrg    for (w = widget; w != NULL; w = XtParent(w))
13127a84e134Smrg	if ((menu = XtNameToWidget(w, name)) != NULL)
13137a84e134Smrg	    return (menu);
13147a84e134Smrg
13157a84e134Smrg    return (NULL);
13167a84e134Smrg}
13177a84e134Smrg
13187a84e134Smrg/*
13197a84e134Smrg * Function:
13207a84e134Smrg *	PositionMenu
13217a84e134Smrg *
13227a84e134Smrg * Parameters:
13237a84e134Smrg *	w	 - simple menu widget
13247a84e134Smrg *	location - pointer the the position or NULL
13257a84e134Smrg *
13267a84e134Smrg * Description:
13277a84e134Smrg *	Places the menu
13287a84e134Smrg */
13297a84e134Smrgstatic void
13307a84e134SmrgPositionMenu(Widget w, XPoint *location)
13317a84e134Smrg{
13327a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
13337a84e134Smrg    SmeObject entry;
13347a84e134Smrg    XPoint t_point;
1335421c997bSmrg
13367a84e134Smrg    if (location == NULL) {
13377a84e134Smrg	Window temp1, temp2;
13387a84e134Smrg	int root_x, root_y, tempX, tempY;
13397a84e134Smrg	unsigned int tempM;
1340421c997bSmrg
13417a84e134Smrg	location = &t_point;
13427a84e134Smrg	if (XQueryPointer(XtDisplay(w), XtWindow(w), &temp1, &temp2,
13437a84e134Smrg			  &root_x, &root_y, &tempX, &tempY, &tempM) == False) {
13447a84e134Smrg	    XtAppWarning(XtWidgetToApplicationContext(w),
13457a84e134Smrg			 "Xaw Simple Menu Widget: "
13467a84e134Smrg			 "Could not find location of mouse pointer");
13477a84e134Smrg	    return;
13487a84e134Smrg	}
13497a84e134Smrg	location->x = (short) root_x;
13507a84e134Smrg	location->y = (short) root_y;
13517a84e134Smrg    }
1352421c997bSmrg
13537a84e134Smrg    /*
13547a84e134Smrg     * The width will not be correct unless it is realized
13557a84e134Smrg     */
13567a84e134Smrg    XtRealizeWidget(w);
1357421c997bSmrg
13585ec34c4cSmrg    location->x = (short)(location->x - (XtWidth(w) >> 1));
1359421c997bSmrg
13607a84e134Smrg    if (smw->simple_menu.popup_entry == NULL)
13617a84e134Smrg	entry = smw->simple_menu.label;
13627a84e134Smrg    else
13637a84e134Smrg	entry = smw->simple_menu.popup_entry;
13647a84e134Smrg
13657a84e134Smrg    if (entry != NULL)
13665ec34c4cSmrg      location->y = (short)(location->y - (XtY(entry) + (XtHeight(entry) >> 1)));
13677a84e134Smrg
13687a84e134Smrg    MoveMenu(w, location->x, location->y);
13697a84e134Smrg}
13707a84e134Smrg
13717a84e134Smrg/*
13727a84e134Smrg * Function:
13737a84e134Smrg *	MoveMenu
13747a84e134Smrg *
13757a84e134Smrg * Parameters:
13767a84e134Smrg *	w - simple menu widget
13777a84e134Smrg *	x - current location of the widget
13787a84e134Smrg *	y - ""
13797a84e134Smrg *
13807a84e134Smrg * Description:
13817a84e134Smrg *	  Actually moves the menu, may force it to
13825b16253fSmrg *	to be fully visible if menu_on_screen is True.
13837a84e134Smrg */
13847a84e134Smrgstatic void
13857a84e134SmrgMoveMenu(Widget w, int x, int y)
13867a84e134Smrg{
13877a84e134Smrg    Arg arglist[2];
13887a84e134Smrg    Cardinal num_args = 0;
13897a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
1390421c997bSmrg
13917a84e134Smrg    if (smw->simple_menu.menu_on_screen) {
13927a84e134Smrg	int width = XtWidth(w) + (XtBorderWidth(w) << 1);
13937a84e134Smrg	int height = XtHeight(w) + (XtBorderWidth(w) << 1);
1394421c997bSmrg
13957a84e134Smrg	if (x >= 0) {
13967a84e134Smrg	    int scr_width = WidthOfScreen(XtScreen(w));
13977a84e134Smrg
13987a84e134Smrg	    if (x + width > scr_width)
13997a84e134Smrg		x = scr_width - width;
14007a84e134Smrg	}
1401421c997bSmrg	if (x < 0)
14027a84e134Smrg	    x = 0;
1403421c997bSmrg
14047a84e134Smrg	if (y >= 0) {
14057a84e134Smrg	    int scr_height = HeightOfScreen(XtScreen(w));
14067a84e134Smrg
14077a84e134Smrg	    if (y + height > scr_height)
14087a84e134Smrg		y = scr_height - height;
14097a84e134Smrg	}
14107a84e134Smrg	if (y < 0)
14117a84e134Smrg	    y = 0;
14127a84e134Smrg    }
1413421c997bSmrg
14147a84e134Smrg    XtSetArg(arglist[num_args], XtNx, x); num_args++;
14157a84e134Smrg    XtSetArg(arglist[num_args], XtNy, y); num_args++;
14167a84e134Smrg    XtSetValues(w, arglist, num_args);
14177a84e134Smrg}
14187a84e134Smrg
14197a84e134Smrg/*
14207a84e134Smrg * Function:
14217a84e134Smrg *	ChangeCursorOnGrab
14227a84e134Smrg *
14237a84e134Smrg * Parameters:
14247a84e134Smrg *	w     - menu widget
14257a84e134Smrg *	temp1 - not used
14267a84e134Smrg *	temp2 - ""
14277a84e134Smrg *
14287a84e134Smrg * Description:
14297a84e134Smrg *	  Changes the cursor on the active grab to the one
14307a84e134Smrg *                   specified in out resource list.
14317a84e134Smrg */
14327a84e134Smrg/*ARGSUSED*/
14337a84e134Smrgstatic void
14345ec34c4cSmrgChangeCursorOnGrab(Widget w, XtPointer temp1 _X_UNUSED, XtPointer temp2 _X_UNUSED)
14357a84e134Smrg{
14367a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
1437421c997bSmrg
14387a84e134Smrg    /*
14397a84e134Smrg     * The event mask here is what is currently in the MIT implementation.
14407a84e134Smrg     * There really needs to be a way to get the value of the mask out
14417a84e134Smrg     * of the toolkit (CDP 5/26/89).
14427a84e134Smrg     */
14437a84e134Smrg    XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask | ButtonReleaseMask,
1444421c997bSmrg			     smw->simple_menu.cursor,
14457a84e134Smrg			     XtLastTimestampProcessed(XtDisplay(w)));
14467a84e134Smrg}
14477a84e134Smrg
14487a84e134Smrg/*
14497a84e134Smrg * Function:
14507a84e134Smrg *	MakeSetValuesRequest
14517a84e134Smrg *
14527a84e134Smrg * Parameters:
14537a84e134Smrg *	w      - simple menu widget
14547a84e134Smrg *	width  - size requested
14557a84e134Smrg *	height - ""
14567a84e134Smrg */
14577a84e134Smrgstatic void
14587a84e134SmrgMakeSetValuesRequest(Widget w, unsigned int width, unsigned int height)
14597a84e134Smrg{
14607a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
14617a84e134Smrg    Arg arglist[2];
14627a84e134Smrg    Cardinal num_args = 0;
1463421c997bSmrg
14647a84e134Smrg    if (!smw->simple_menu.recursive_set_values) {
14657a84e134Smrg	if (XtWidth(smw) != width || XtHeight(smw) != height) {
14667a84e134Smrg	    smw->simple_menu.recursive_set_values = True;
14677a84e134Smrg	    XtSetArg(arglist[num_args], XtNwidth, width);   num_args++;
14687a84e134Smrg	    XtSetArg(arglist[num_args], XtNheight, height); num_args++;
14697a84e134Smrg	    XtSetValues(w, arglist, num_args);
14707a84e134Smrg	}
14717a84e134Smrg	else if (XtIsRealized((Widget)smw))
14727a84e134Smrg	    XawSimpleMenuRedisplay((Widget)smw, NULL, NULL);
14737a84e134Smrg    }
14747a84e134Smrg    smw->simple_menu.recursive_set_values = False;
14757a84e134Smrg}
14767a84e134Smrg
14777a84e134Smrgstatic SmeObject
14787a84e134SmrgDoGetEventEntry(Widget w, int x_loc, int y_loc)
14797a84e134Smrg{
14807a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
14817a84e134Smrg    SmeObject *entry;
14827a84e134Smrg
14837a84e134Smrg    ForAllChildren(smw, entry) {
14847a84e134Smrg	if (!XtIsManaged((Widget)*entry))
14857a84e134Smrg	    continue;
14867a84e134Smrg
14877a84e134Smrg	if (x_loc > XtX(*entry)
14887a84e134Smrg	    && x_loc <= XtX(*entry) + XtWidth(*entry)
14897a84e134Smrg	    && y_loc > XtY(*entry)
14907a84e134Smrg	    &&  y_loc <= XtY(*entry) + XtHeight(*entry)) {
14917a84e134Smrg	    if (*entry == smw->simple_menu.label)
14927a84e134Smrg		return (NULL);	/* cannot select the label */
14937a84e134Smrg	    else
14947a84e134Smrg		return (*entry);
14957a84e134Smrg	}
14967a84e134Smrg    }
1497421c997bSmrg
14987a84e134Smrg    return (NULL);
14997a84e134Smrg}
15007a84e134Smrg
15017a84e134Smrg/*
15027a84e134Smrg * Function:
15037a84e134Smrg *	GetEventEntry
15047a84e134Smrg *
15057a84e134Smrg * Parameters:
15067a84e134Smrg *	w     - simple menu widget
15077a84e134Smrg *	event - X event
15087a84e134Smrg *
15097a84e134Smrg * Description:
15107a84e134Smrg *	Gets an entry given an event that has X and Y coords.
15117a84e134Smrg *
15127a84e134Smrg * Returns:
15137a84e134Smrg *	The entry that this point is in
15147a84e134Smrg */
15157a84e134Smrgstatic SmeObject
15167a84e134SmrgGetEventEntry(Widget w, XEvent *event)
15177a84e134Smrg{
15187a84e134Smrg    int x_loc, y_loc, x_root;
15197a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
15207a84e134Smrg    SmeObject entry;
15217a84e134Smrg    int warp, move;
15227a84e134Smrg
15237a84e134Smrg    switch (event->type) {
15247a84e134Smrg	case MotionNotify:
15257a84e134Smrg	    x_loc = event->xmotion.x;
15267a84e134Smrg	    y_loc = event->xmotion.y;
15277a84e134Smrg	    x_root = event->xmotion.x_root;
15287a84e134Smrg	    break;
15297a84e134Smrg	case EnterNotify:
15307a84e134Smrg	case LeaveNotify:
15317a84e134Smrg	    x_loc = event->xcrossing.x;
15327a84e134Smrg	    y_loc = event->xcrossing.y;
15337a84e134Smrg	    x_root = event->xcrossing.x_root;
15347a84e134Smrg	    break;
15357a84e134Smrg	case ButtonPress:
15367a84e134Smrg	case ButtonRelease:
15377a84e134Smrg	    x_loc = event->xbutton.x;
15387a84e134Smrg	    y_loc = event->xbutton.y;
15397a84e134Smrg	    x_root = event->xbutton.x_root;
15407a84e134Smrg	    break;
15417a84e134Smrg	default:
15427a84e134Smrg	    XtAppError(XtWidgetToApplicationContext(w),
15437a84e134Smrg		       "Unknown event type in GetEventEntry().");
15447a84e134Smrg	    return (NULL);
15457a84e134Smrg    }
1546421c997bSmrg
15477a84e134Smrg    if (x_loc < 0 || x_loc >= XtWidth(smw) ||
15487a84e134Smrg	y_loc < 0 || y_loc >= XtHeight(smw))
15497a84e134Smrg	return (NULL);
15507a84e134Smrg
15517a84e134Smrg    /* Move the menu if it's outside the screen, does not check
15527a84e134Smrg     * smw->simple_menu.menu_on_screen because menus is bigger than screen
15537a84e134Smrg     */
15547a84e134Smrg    if (x_root == WidthOfScreen(XtScreen(w)) - 1 &&
15557a84e134Smrg	XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) {
15567a84e134Smrg	warp = -8;
15577a84e134Smrg	if (smw->simple_menu.entry_set) {
15587a84e134Smrg	    entry = DoGetEventEntry(w,
15597a84e134Smrg				    XtX(smw->simple_menu.entry_set)
15607a84e134Smrg				    + XtWidth(smw->simple_menu.entry_set) + 1,
15617a84e134Smrg				    y_loc);
15627a84e134Smrg	    Unhighlight(w, event, NULL, NULL);
15637a84e134Smrg	    if (entry) {
15647a84e134Smrg		warp = -(int)XtWidth(entry) >> 1;
15657a84e134Smrg		move = x_loc - XtWidth(entry) - XtX(entry) + XtBorderWidth(w);
15667a84e134Smrg	    }
15677a84e134Smrg	    else {
15687a84e134Smrg		warp = 0;
15697a84e134Smrg		move = WidthOfScreen(XtScreen(w)) -
15707a84e134Smrg		       (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
15717a84e134Smrg	    }
15727a84e134Smrg	}
15737a84e134Smrg	else {
15747a84e134Smrg	    warp = 0;
15757a84e134Smrg	    move = WidthOfScreen(XtScreen(w)) -
15767a84e134Smrg		   (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
15777a84e134Smrg	}
15787a84e134Smrg    }
15797a84e134Smrg    else if (x_root == 0 && XtX(w) < 0) {
15807a84e134Smrg	warp = 8;
15817a84e134Smrg	if (smw->simple_menu.entry_set) {
15827a84e134Smrg	    entry = DoGetEventEntry(w, XtX(smw->simple_menu.entry_set) - 1,
15837a84e134Smrg				    y_loc);
15847a84e134Smrg	    Unhighlight(w, event, NULL, NULL);
15857a84e134Smrg	    if (entry) {
15867a84e134Smrg		warp = XtWidth(entry) >> 1;
15877a84e134Smrg		move = x_loc - XtX(entry);
15887a84e134Smrg	    }
15897a84e134Smrg	    else
15907a84e134Smrg		move = x_loc + XtBorderWidth(w);
15917a84e134Smrg	}
15927a84e134Smrg	else
15937a84e134Smrg	    move = x_loc + XtBorderWidth(w);
15947a84e134Smrg    }
15957a84e134Smrg    else
15967a84e134Smrg	move = warp = 0;
15977a84e134Smrg
15987a84e134Smrg    if (move)
15995ec34c4cSmrg	XtMoveWidget(w, (Position)(XtX(w) + move), XtY(w));
16007a84e134Smrg    if (warp)
16017a84e134Smrg	XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, warp, 0);
16027a84e134Smrg
16037a84e134Smrg    return (DoGetEventEntry(w, x_loc, y_loc));
16047a84e134Smrg}
16057a84e134Smrg
16067a84e134Smrgstatic void
16077a84e134SmrgCalculateNewSize(Widget w, Dimension *width_return, Dimension *height_return)
16087a84e134Smrg{
16097a84e134Smrg    SimpleMenuWidget xaw = (SimpleMenuWidget)w;
16107a84e134Smrg    Widget kid;
16117a84e134Smrg    Cardinal i;
16127a84e134Smrg    int width_kid, height_kid;
16137a84e134Smrg    int width, height, tmp_w, tmp_h, max_dim;
16147a84e134Smrg    short vadd, hadd;
16157a84e134Smrg    int n, columns, test_h, num_children = 0;
16167a84e134Smrg    Boolean try_layout = False;
16177a84e134Smrg
16187a84e134Smrg#ifndef OLDXAW
16195ec34c4cSmrg    hadd = (short)(xaw->simple_menu.left_margin + xaw->simple_menu.right_margin);
16207a84e134Smrg#else
16217a84e134Smrg    hadd = 0;
16227a84e134Smrg#endif
16235ec34c4cSmrg    vadd = (short)(xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin);
16247a84e134Smrg    if (xaw->simple_menu.label)
16255ec34c4cSmrg	vadd = (short)(vadd + XtHeight(xaw->simple_menu.label));
16267a84e134Smrg
16277a84e134Smrg    if (*height_return)
16287a84e134Smrg	max_dim = *height_return;
16297a84e134Smrg    else if (!XtHeight(w)) {
16307a84e134Smrg	max_dim = HeightOfScreen(XtScreen(w));
16317a84e134Smrg	try_layout = True;
16327a84e134Smrg    }
16337a84e134Smrg    else
16347a84e134Smrg	max_dim = XtHeight(w);
16357a84e134Smrg    max_dim -= vadd;
16367a84e134Smrg
16377a84e134Smrg    width = height = tmp_w = tmp_h = n = test_h = 0;
16387a84e134Smrg    columns = 1;
16397a84e134Smrg    for (i = xaw->simple_menu.label ? 1 : 0;
16407a84e134Smrg	 i < xaw->composite.num_children;
16417a84e134Smrg	 i++) {
16427a84e134Smrg	kid = xaw->composite.children[i];
16437a84e134Smrg	if (!XtIsManaged(kid))
16447a84e134Smrg	    continue;
16457a84e134Smrg	++num_children;
16467a84e134Smrg	width_kid = XtWidth(kid);
16477a84e134Smrg	height_kid = XtHeight(kid);
16487a84e134Smrg
16497a84e134Smrg	if (try_layout) {
16507a84e134Smrg	    if (!test_h)
16517a84e134Smrg		test_h = height_kid;
16527a84e134Smrg	    else if (test_h != height_kid)
16537a84e134Smrg		try_layout = False;
16547a84e134Smrg	}
16557a84e134Smrg
16567a84e134Smrg	if (n && (height + height_kid > max_dim)) {
16577a84e134Smrg	    ++columns;
16587a84e134Smrg	    width += tmp_w;
16597a84e134Smrg	    tmp_w = width_kid;
16607a84e134Smrg	    height = height_kid;
16617a84e134Smrg	}
16627a84e134Smrg	else
16637a84e134Smrg	    height += height_kid;
16647a84e134Smrg	if (height > tmp_h)
16657a84e134Smrg	    tmp_h = height;
16667a84e134Smrg	if (width_kid > tmp_w)
16677a84e134Smrg	    tmp_w = width_kid;
16687a84e134Smrg	++n;
16697a84e134Smrg    }
16707a84e134Smrg
16717a84e134Smrg    height = tmp_h + vadd;
16727a84e134Smrg    width += tmp_w + hadd;
16737a84e134Smrg
16747a84e134Smrg    if (xaw->simple_menu.label)
16757a84e134Smrg	width = XawMax(width, XtWidth(xaw->simple_menu.label) + hadd);
16767a84e134Smrg
16775ec34c4cSmrg    *width_return = (Dimension)width;
16785ec34c4cSmrg    *height_return = (Dimension)height;
16797a84e134Smrg
16807a84e134Smrg    if (try_layout && columns > 1 && num_children > 2) {
16817a84e134Smrg	int space;
16827a84e134Smrg
16837a84e134Smrg	height = test_h * (xaw->simple_menu.label ?
16847a84e134Smrg			   num_children - 1 :
16857a84e134Smrg			   num_children);
16867a84e134Smrg
16877a84e134Smrg	max_dim -= max_dim % test_h;
16887a84e134Smrg	space = max_dim - (height % max_dim);
16897a84e134Smrg	if (space >= test_h * columns) {
16907a84e134Smrg	    height = max_dim - space / columns;
16917a84e134Smrg	    if (height % test_h)
16927a84e134Smrg		height += test_h - (height % test_h);
16935ec34c4cSmrg	    *height_return = (Dimension)(height + vadd);
16947a84e134Smrg	    CalculateNewSize(w, width_return, height_return);
16957a84e134Smrg	}
16967a84e134Smrg    }
16977a84e134Smrg}
16987a84e134Smrg
16997a84e134Smrgstatic void
17007a84e134SmrgMakeResizeRequest(Widget w)
17017a84e134Smrg{
17027a84e134Smrg    int tries;
17037a84e134Smrg    Dimension width, height;
1704421c997bSmrg
17057a84e134Smrg    width = XtWidth(w);
17067a84e134Smrg    height = XtHeight(w);
17077a84e134Smrg
17087a84e134Smrg    for (tries = 0; tries < 100; tries++) {
17097a84e134Smrg	CalculateNewSize(w, &width, &height);
17107a84e134Smrg	if (width == XtWidth(w) && height == XtHeight(w))
17117a84e134Smrg	    break;
17127a84e134Smrg	if (XtMakeResizeRequest(w, width, height, &width, &height) ==
17137a84e134Smrg	    XtGeometryNo)
17147a84e134Smrg	break;
17157a84e134Smrg    }
17167a84e134Smrg}
17177a84e134Smrg
17187a84e134Smrg#ifndef OLDXAW
17197a84e134Smrgstatic void
17207a84e134SmrgPopdown(Widget w, XEvent *event, String *params, Cardinal *num_params)
17217a84e134Smrg{
17227a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
17237a84e134Smrg
17247a84e134Smrg    while (XtParent(w) &&
17257a84e134Smrg	   XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) {
17267a84e134Smrg	if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) {
17277a84e134Smrg	    w = XtParent(w);
17287a84e134Smrg	    smw = (SimpleMenuWidget)w;
17297a84e134Smrg	    smw->simple_menu.entry_set = NULL;
17307a84e134Smrg	}
17317a84e134Smrg	else
17327a84e134Smrg	    break;
17337a84e134Smrg    }
17347a84e134Smrg
17357a84e134Smrg    smw->simple_menu.state |= SMW_UNMAPPING;
17367a84e134Smrg    if (smw->simple_menu.sub_menu)
17377a84e134Smrg	PopdownSubMenu(smw);
17387a84e134Smrg    XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params);
17397a84e134Smrg}
17407a84e134Smrg
17417a84e134Smrgstatic void
17427a84e134SmrgPopupSubMenu(SimpleMenuWidget smw)
17437a84e134Smrg{
17447a84e134Smrg    Arg args[2];
17457a84e134Smrg    Cardinal num_args;
17467a84e134Smrg    Widget menu;
17477a84e134Smrg    SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set;
17487a84e134Smrg    Position menu_x, menu_y;
17497a84e134Smrg    Bool popleft;
17507a84e134Smrg
17517a84e134Smrg    if (entry->sme_bsb.menu_name == NULL)
17527a84e134Smrg	return;
17537a84e134Smrg
17547a84e134Smrg    if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL)
17557a84e134Smrg	return;
17567a84e134Smrg
17577a84e134Smrg    smw->simple_menu.sub_menu = menu;
17587a84e134Smrg
17597a84e134Smrg    if (!XtIsRealized(menu))
17607a84e134Smrg	XtRealizeWidget(menu);
17617a84e134Smrg
17627a84e134Smrg    popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0;
17637a84e134Smrg
1764421c997bSmrg    if (popleft)
17655ec34c4cSmrg	XtTranslateCoords((Widget)smw,
17665ec34c4cSmrg			  (Position)(-(int)XtWidth(menu)),
17675ec34c4cSmrg			  (Position)(XtY(entry) - XtBorderWidth(menu)),
17685ec34c4cSmrg			  &menu_x, &menu_y);
17697a84e134Smrg    else
17705ec34c4cSmrg	XtTranslateCoords((Widget)smw,
17715ec34c4cSmrg			  (Position)XtWidth(smw),
17725ec34c4cSmrg			  (Position)(XtY(entry) - XtBorderWidth(menu)),
17735ec34c4cSmrg			  &menu_x, &menu_y);
17747a84e134Smrg
17757a84e134Smrg    if (!popleft && menu_x >= 0) {
17767a84e134Smrg	int scr_width = WidthOfScreen(XtScreen(menu));
17777a84e134Smrg
17787a84e134Smrg	if (menu_x + XtWidth(menu) > scr_width) {
17795ec34c4cSmrg	    menu_x = (Position)(menu_x - (XtWidth(menu) + XtWidth(smw)));
17807a84e134Smrg	    popleft = True;
17817a84e134Smrg	}
17827a84e134Smrg    }
17837a84e134Smrg    else if (popleft && menu_x < 0) {
17847a84e134Smrg	menu_x = 0;
17857a84e134Smrg	popleft = False;
17867a84e134Smrg    }
17877a84e134Smrg    if (menu_y >= 0) {
17887a84e134Smrg	int scr_height = HeightOfScreen(XtScreen(menu));
17897a84e134Smrg
17907a84e134Smrg	if (menu_y + XtHeight(menu) > scr_height)
17915ec34c4cSmrg	    menu_y = (Position)(scr_height - XtHeight(menu) - XtBorderWidth(menu));
17927a84e134Smrg    }
17937a84e134Smrg    if (menu_y < 0)
17947a84e134Smrg	menu_y = 0;
17957a84e134Smrg
17967a84e134Smrg    num_args = 0;
17977a84e134Smrg    XtSetArg(args[num_args], XtNx, menu_x);	num_args++;
17987a84e134Smrg    XtSetArg(args[num_args], XtNy, menu_y);	num_args++;
17997a84e134Smrg    XtSetValues(menu, args, num_args);
18007a84e134Smrg
18017a84e134Smrg    if (popleft)
18027a84e134Smrg	((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT;
18037a84e134Smrg    else
18045ec34c4cSmrg	((SimpleMenuWidget)menu)->simple_menu.state &= (unsigned char)(~SMW_POPLEFT);
18057a84e134Smrg
18067a84e134Smrg    XtPopup(menu, XtGrabNone);
18077a84e134Smrg}
18087a84e134Smrg
18097a84e134Smrgstatic void
18107a84e134SmrgPopdownSubMenu(SimpleMenuWidget smw)
18117a84e134Smrg{
18127a84e134Smrg    SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu;
18137a84e134Smrg
18147a84e134Smrg    if (!menu)
18157a84e134Smrg	return;
18167a84e134Smrg
18177a84e134Smrg    menu->simple_menu.state |= SMW_UNMAPPING;
18187a84e134Smrg    PopdownSubMenu(menu);
18197a84e134Smrg
18207a84e134Smrg    XtPopdown((Widget)menu);
18217a84e134Smrg
18227a84e134Smrg    smw->simple_menu.sub_menu = NULL;
18237a84e134Smrg}
18247a84e134Smrg
18257a84e134Smrg/*ARGSUSED*/
18267a84e134Smrgstatic void
18275ec34c4cSmrgPopupCB(Widget w, XtPointer client_data _X_UNUSED, XtPointer call_data _X_UNUSED)
18287a84e134Smrg{
18297a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
18307a84e134Smrg
18315ec34c4cSmrg    smw->simple_menu.state &= (unsigned char)(~(SMW_UNMAPPING | SMW_POPLEFT));
18327a84e134Smrg}
18337a84e134Smrg#endif /* OLDXAW */
1834