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 */
275efbcb2bfSmrg#ifndef OLDXAW
276efbcb2bfSmrg  False,				/* allows_change_managed_set */
277efbcb2bfSmrg#endif
2787a84e134Smrg};
2797a84e134Smrg
2807a84e134Smrg#define Superclass	(&overrideShellClassRec)
2817a84e134SmrgSimpleMenuClassRec simpleMenuClassRec = {
2827a84e134Smrg  /* core */
2837a84e134Smrg  {
2847a84e134Smrg    (WidgetClass)Superclass,		/* superclass */
2857a84e134Smrg    "SimpleMenu",			/* class_name */
2867a84e134Smrg    sizeof(SimpleMenuRec),		/* size */
2877a84e134Smrg    XawSimpleMenuClassInitialize,	/* class_initialize */
2887a84e134Smrg    XawSimpleMenuClassPartInitialize,	/* class_part_initialize */
2897a84e134Smrg    False,				/* class_inited */
2907a84e134Smrg    XawSimpleMenuInitialize,		/* initialize */
2917a84e134Smrg    NULL,				/* initialize_hook */
2927a84e134Smrg    XawSimpleMenuRealize,		/* realize */
2937a84e134Smrg    actionsList,			/* actions */
2947a84e134Smrg    XtNumber(actionsList),		/* num_actions */
2957a84e134Smrg    resources,				/* resources */
2967a84e134Smrg    XtNumber(resources),		/* num_resources */
2977a84e134Smrg    NULLQUARK,				/* xrm_class */
2987a84e134Smrg    True,				/* compress_motion */
2997a84e134Smrg    True,				/* compress_exposure */
3007a84e134Smrg    True,				/* compress_enterleave */
3017a84e134Smrg    False,				/* visible_interest */
3027a84e134Smrg    NULL,				/* destroy */
3037a84e134Smrg    XawSimpleMenuResize,		/* resize */
3047a84e134Smrg    XawSimpleMenuRedisplay,		/* expose */
3057a84e134Smrg    XawSimpleMenuSetValues,		/* set_values */
3067a84e134Smrg    XawSimpleMenuSetValuesHook,		/* set_values_hook */
3077a84e134Smrg    XtInheritSetValuesAlmost,		/* set_values_almost */
3087a84e134Smrg    NULL,				/* get_values_hook */
3097a84e134Smrg    NULL,				/* accept_focus */
3107a84e134Smrg    XtVersion,				/* intrinsics version */
3117a84e134Smrg    NULL,				/* callback offsets */
3127a84e134Smrg    defaultTranslations,		/* tm_table */
3137a84e134Smrg    NULL,				/* query_geometry */
3147a84e134Smrg    NULL,				/* display_accelerator */
3157a84e134Smrg    NULL,				/* extension */
3167a84e134Smrg  },
3177a84e134Smrg  /* composite */
3187a84e134Smrg  {
3197a84e134Smrg    XawSimpleMenuGeometryManager,	/* geometry_manager */
3207a84e134Smrg    XawSimpleMenuChangeManaged,		/* change_managed */
3217a84e134Smrg    XtInheritInsertChild,		/* insert_child */
3227a84e134Smrg    XtInheritDeleteChild,		/* delete_child */
3237a84e134Smrg    NULL,				/* extension */
3247a84e134Smrg  },
3257a84e134Smrg  /* shell */
3267a84e134Smrg  {
3277a84e134Smrg    NULL,				/* extension */
3287a84e134Smrg  },
3297a84e134Smrg  /* override */
3307a84e134Smrg  {
3317a84e134Smrg    NULL,				/* extension */
3327a84e134Smrg  },
3337a84e134Smrg  /* simple_menu */
3347a84e134Smrg  {
3357a84e134Smrg    NULL,				/* extension */
3367a84e134Smrg  },
3377a84e134Smrg};
3387a84e134Smrg
3397a84e134SmrgWidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
3407a84e134Smrg
3417a84e134Smrg/*
3427a84e134Smrg * Implementation
3437a84e134Smrg */
3447a84e134Smrg/*
3457a84e134Smrg * Function:
3467a84e134Smrg *	XawSimpleMenuClassInitialize
3477a84e134Smrg *
3487a84e134Smrg * Description:
3497a84e134Smrg *	Class Initialize routine, called only once.
3507a84e134Smrg */
3517a84e134Smrgstatic void
3527a84e134SmrgXawSimpleMenuClassInitialize(void)
3537a84e134Smrg{
3547a84e134Smrg    XawInitializeWidgetSet();
3557a84e134Smrg    XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
3567a84e134Smrg		   NULL, 0);
3577a84e134Smrg    XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
3587a84e134Smrg		       NULL, 0, XtCacheNone, NULL);
3597a84e134Smrg    XmuAddInitializer(AddPositionAction, NULL);
3607a84e134Smrg}
3617a84e134Smrg
3627a84e134Smrg/*
3637a84e134Smrg * Function:
3647a84e134Smrg *	XawSimpleMenuClassPartInitialize
3657a84e134Smrg *      Arguments: wc - the widget class of the subclass.
3667a84e134Smrg *
3677a84e134Smrg * Description:
3687a84e134Smrg *	  Class Part Initialize routine, called for every subclass.  Makes
3697a84e134Smrg *	sure that the subclasses pick up the extension record.
3707a84e134Smrg */
3717a84e134Smrgstatic void
3727a84e134SmrgXawSimpleMenuClassPartInitialize(WidgetClass wc)
3737a84e134Smrg{
3747a84e134Smrg    SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc;
3757a84e134Smrg
3767a84e134Smrg    /*
3777a84e134Smrg     * Make sure that our subclass gets the extension rec too
3787a84e134Smrg     */
3797a84e134Smrg    extension_rec.next_extension = smwc->composite_class.extension;
3807a84e134Smrg    smwc->composite_class.extension = (XtPointer) &extension_rec;
3817a84e134Smrg}
3827a84e134Smrg
3837a84e134Smrg/*
3847a84e134Smrg *  Function:
3857a84e134Smrg *	XawSimpleMenuInitialize
3867a84e134Smrg *
3877a84e134Smrg * Parameters:
3887a84e134Smrg *	request - widget requested by the argument list
3897a84e134Smrg *	cnew	- new widget with both resource and non resource values
3907a84e134Smrg *
3917a84e134Smrg * Description:
3927a84e134Smrg *	Initializes the simple menu widget.
3937a84e134Smrg */
3947a84e134Smrg/*ARGSUSED*/
3957a84e134Smrgstatic void
3965ec34c4cSmrgXawSimpleMenuInitialize(Widget request _X_UNUSED, Widget cnew,
3975ec34c4cSmrg			ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
3987a84e134Smrg{
3997a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)cnew;
4007a84e134Smrg    Dimension width, height;
4017a84e134Smrg
4027a84e134Smrg    XmuCallInitializers(XtWidgetToApplicationContext(cnew));
4037a84e134Smrg
404421c997bSmrg    if (smw->simple_menu.label_class == NULL)
4057a84e134Smrg	smw->simple_menu.label_class = smeBSBObjectClass;
4067a84e134Smrg
4077a84e134Smrg    smw->simple_menu.label = NULL;
4087a84e134Smrg    smw->simple_menu.entry_set = NULL;
4097a84e134Smrg    smw->simple_menu.recursive_set_values = False;
4107a84e134Smrg#ifndef OLDXAW
4117a84e134Smrg    smw->simple_menu.sub_menu = NULL;
4127a84e134Smrg    smw->simple_menu.state = 0;
4137a84e134Smrg
4147a84e134Smrg    XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL);
4157a84e134Smrg#endif
4167a84e134Smrg
4177a84e134Smrg    if (smw->simple_menu.label_string != NULL)
4187a84e134Smrg	CreateLabel(cnew);
4197a84e134Smrg
4207a84e134Smrg    width = height = 0;
4217a84e134Smrg    CalculateNewSize(cnew, &width, &height);
4227a84e134Smrg
4237a84e134Smrg    smw->simple_menu.menu_width = True;
4247a84e134Smrg
4257a84e134Smrg    if (XtWidth(smw) == 0) {
4267a84e134Smrg	smw->simple_menu.menu_width = False;
4277a84e134Smrg	XtWidth(smw) = width;
4287a84e134Smrg    }
4297a84e134Smrg
4307a84e134Smrg    smw->simple_menu.menu_height = True;
4317a84e134Smrg
4327a84e134Smrg    if (XtHeight(smw) == 0) {
4337a84e134Smrg	smw->simple_menu.menu_height = False;
4347a84e134Smrg	XtHeight(smw) = height;
4357a84e134Smrg    }
4367a84e134Smrg
4377a84e134Smrg    /*
4387a84e134Smrg     * Add a popup_callback routine for changing the cursor
4397a84e134Smrg     */
4407a84e134Smrg    XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL);
4417a84e134Smrg}
4427a84e134Smrg
4437a84e134Smrg/*
4447a84e134Smrg * Function:
4457a84e134Smrg *	XawSimpleMenuRedisplay
4467a84e134Smrg *
4477a84e134Smrg * Parameters:
4487a84e134Smrg *	w      - simple menu widget
4497a84e134Smrg *	event  - X event that caused this redisplay
4507a84e134Smrg *	region - region the needs to be repainted
4517a84e134Smrg *
4527a84e134Smrg * Description:
4537a84e134Smrg *	Redisplays the contents of the widget.
4547a84e134Smrg */
4557a84e134Smrg/*ARGSUSED*/
4567a84e134Smrgstatic void
4575ec34c4cSmrgXawSimpleMenuRedisplay(Widget w, XEvent *event _X_UNUSED, Region region)
4587a84e134Smrg{
4597a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
4607a84e134Smrg    SmeObject *entry;
4617a84e134Smrg    SmeObjectClass cclass;
4627a84e134Smrg
4637a84e134Smrg    if (region == NULL)
4647a84e134Smrg	XClearWindow(XtDisplay(w), XtWindow(w));
4657a84e134Smrg
4667a84e134Smrg#ifndef OLDXAW
4677a84e134Smrg    if (smw->simple_menu.display_list)
4687a84e134Smrg      XawRunDisplayList(w, smw->simple_menu.display_list, event, region);
4697a84e134Smrg#endif
4707a84e134Smrg
4717a84e134Smrg    /*
4727a84e134Smrg     * Check and Paint each of the entries - including the label
4737a84e134Smrg     */
4747a84e134Smrg    ForAllChildren(smw, entry) {
4757a84e134Smrg	if (!XtIsManaged((Widget)*entry))
4767a84e134Smrg	    continue;
4777a84e134Smrg
478421c997bSmrg	if (region != NULL)
4797a84e134Smrg	    switch(XRectInRegion(region, XtX(*entry),XtY(*entry),
4807a84e134Smrg				 XtWidth(*entry), XtHeight(*entry))) {
4817a84e134Smrg		case RectangleIn:
4827a84e134Smrg		case RectanglePart:
4837a84e134Smrg		    break;
4847a84e134Smrg		default:
4857a84e134Smrg		    continue;
4867a84e134Smrg	    }
4877a84e134Smrg
4887a84e134Smrg	cclass = (SmeObjectClass)(*entry)->object.widget_class;
4897a84e134Smrg
4907a84e134Smrg	if (cclass->rect_class.expose != NULL)
4917a84e134Smrg	    (cclass->rect_class.expose)((Widget)*entry, NULL, NULL);
4927a84e134Smrg    }
4937a84e134Smrg}
4947a84e134Smrg
4957a84e134Smrg/*
4967a84e134Smrg * Function:
4977a84e134Smrg *	XawSimpleMenuRealize
4987a84e134Smrg *
4997a84e134Smrg * Parameters:
5007a84e134Smrg *	w     - simple menu widget
5017a84e134Smrg *	mask  - value mask for the window to create
5027a84e134Smrg *	attrs - attributes for the window to create
5037a84e134Smrg *
5047a84e134Smrg * Description:
5057a84e134Smrg *	Realizes the widget.
5067a84e134Smrg */
5077a84e134Smrgstatic void
5087a84e134SmrgXawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs)
5097a84e134Smrg{
5107a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
5117a84e134Smrg#ifndef OLDXAW
5127a84e134Smrg    XawPixmap *pixmap;
5137a84e134Smrg#endif
5147a84e134Smrg
5157a84e134Smrg    attrs->cursor = smw->simple_menu.cursor;
5167a84e134Smrg    *mask |= CWCursor;
5177a84e134Smrg    if (smw->simple_menu.backing_store == Always ||
5187a84e134Smrg	smw->simple_menu.backing_store == NotUseful ||
5197a84e134Smrg	smw->simple_menu.backing_store == WhenMapped) {
5207a84e134Smrg	*mask |= CWBackingStore;
5217a84e134Smrg	attrs->backing_store = smw->simple_menu.backing_store;
5227a84e134Smrg    }
5237a84e134Smrg    else
5245ec34c4cSmrg	*mask &= (XtValueMask)(~CWBackingStore);
5257a84e134Smrg
5267a84e134Smrg    (*Superclass->core_class.realize)(w, mask, attrs);
5277a84e134Smrg
5287a84e134Smrg#ifndef OLDXAW
5297a84e134Smrg    if (w->core.background_pixmap > XtUnspecifiedPixmap) {
5307a84e134Smrg	pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
5315ec34c4cSmrg				      w->core.colormap, (int)w->core.depth);
5327a84e134Smrg	if (pixmap && pixmap->mask)
5337a84e134Smrg	    XawReshapeWidget(w, pixmap);
5347a84e134Smrg    }
5357a84e134Smrg#endif
5367a84e134Smrg}
5377a84e134Smrg
5387a84e134Smrg/*
5397a84e134Smrg * Function:
5407a84e134Smrg *	XawSimpleMenuResize
5417a84e134Smrg *
5427a84e134Smrg * Parameters:
5437a84e134Smrg *	w - simple menu widget
5447a84e134Smrg *
5457a84e134Smrg * Description:
5467a84e134Smrg *	Handle the menu being resized.
5477a84e134Smrg */
5487a84e134Smrgstatic void
5497a84e134SmrgXawSimpleMenuResize(Widget w)
5507a84e134Smrg{
5517a84e134Smrg    if (!XtIsRealized(w))
5527a84e134Smrg	return;
5537a84e134Smrg
5547a84e134Smrg    Layout(w, NULL, NULL);
5557a84e134Smrg
5567a84e134Smrg    XawSimpleMenuRedisplay(w, NULL, NULL);
5577a84e134Smrg}
5587a84e134Smrg
5597a84e134Smrg/*
5607a84e134Smrg * Function:
5617a84e134Smrg *	XawSimpleMenuSetValues
5627a84e134Smrg *
5637a84e134Smrg * Parameters:
5647a84e134Smrg *	current - current state of the widget
5657a84e134Smrg *	request - what was requested
5667a84e134Smrg *	cnew    - what the widget will become
5677a84e134Smrg *
5687a84e134Smrg * Description:
5697a84e134Smrg *	Relayout the menu when one of the resources is changed.
5707a84e134Smrg */
5717a84e134Smrg/*ARGSUSED*/
5727a84e134Smrgstatic Boolean
5735ec34c4cSmrgXawSimpleMenuSetValues(Widget current, Widget request _X_UNUSED, Widget cnew,
5745ec34c4cSmrg		       ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
5757a84e134Smrg{
5767a84e134Smrg    SimpleMenuWidget smw_old = (SimpleMenuWidget)current;
5777a84e134Smrg    SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew;
5787a84e134Smrg    Boolean ret_val = False, layout = False;
5797a84e134Smrg
5807a84e134Smrg    if (!XtIsRealized(current))
5817a84e134Smrg	return (False);
5827a84e134Smrg
5837a84e134Smrg    if (!smw_new->simple_menu.recursive_set_values) {
5847a84e134Smrg	if (XtWidth(smw_new) != XtWidth(smw_old)) {
5857a84e134Smrg	    smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0;
5867a84e134Smrg	    layout = True;
5877a84e134Smrg	}
5887a84e134Smrg	if (XtHeight(smw_new) != XtHeight(smw_old)) {
5897a84e134Smrg	    smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0;
5907a84e134Smrg	    layout = True;
5917a84e134Smrg	}
5927a84e134Smrg    }
5937a84e134Smrg
5947a84e134Smrg    if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
5957a84e134Smrg	XDefineCursor(XtDisplay(cnew), XtWindow(cnew),
5967a84e134Smrg		      smw_new->simple_menu.cursor);
5977a84e134Smrg
5987a84e134Smrg    if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) {
5997a84e134Smrg	if (smw_new->simple_menu.label_string == NULL)	    /* Destroy */
6007a84e134Smrg	    XtDestroyWidget((Widget)smw_old->simple_menu.label);
6017a84e134Smrg	else if (smw_old->simple_menu.label_string == NULL) /* Create */
6027a84e134Smrg	    CreateLabel(cnew);
6037a84e134Smrg	else {						    /* Change */
6047a84e134Smrg	    Arg arglist[1];
605421c997bSmrg
6067a84e134Smrg	    XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string);
6077a84e134Smrg	    XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE);
6087a84e134Smrg	}
6097a84e134Smrg    }
6107a84e134Smrg
6117a84e134Smrg    if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
6127a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(cnew),
6137a84e134Smrg		     "No Dynamic class change of the SimpleMenu Label.");
614421c997bSmrg
6157a84e134Smrg    if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin
6167a84e134Smrg	|| smw_old->simple_menu.bottom_margin
6177a84e134Smrg	!= smw_new->simple_menu.bottom_margin) {
6187a84e134Smrg	layout = True;
6197a84e134Smrg	ret_val = True;
6207a84e134Smrg    }
6217a84e134Smrg
6227a84e134Smrg#ifndef OLDXAW
6237a84e134Smrg    if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) {
6247a84e134Smrg	XawPixmap *opix, *npix;
6257a84e134Smrg
6267a84e134Smrg	opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap,
6277a84e134Smrg				    XtScreen(smw_old), smw_old->core.colormap,
6285ec34c4cSmrg				    (int)smw_old->core.depth);
6297a84e134Smrg	npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap,
6307a84e134Smrg				    XtScreen(smw_new), smw_new->core.colormap,
6315ec34c4cSmrg				    (int)smw_new->core.depth);
6327a84e134Smrg	if ((npix && npix->mask) || (opix && opix->mask))
6337a84e134Smrg	    XawReshapeWidget(cnew, npix);
6347a84e134Smrg    }
6357a84e134Smrg#endif
6367a84e134Smrg
6377a84e134Smrg    if (layout)
6387a84e134Smrg	Layout(cnew, NULL, NULL);
6397a84e134Smrg
6407a84e134Smrg    return (ret_val);
6417a84e134Smrg}
6427a84e134Smrg
643421c997bSmrg/*
6447a84e134Smrg * Function:
6457a84e134Smrg *	XawSimpleMenuSetValuesHook
6467a84e134Smrg *
6477a84e134Smrg * Parameters:
6487a84e134Smrg *	w	 - menu widget
6497a84e134Smrg *	arglist	 - argument list passed to XtSetValues
6507a84e134Smrg *	num_args - number of args
6517a84e134Smrg *
6527a84e134Smrg * Description:
6537a84e134Smrg *	To handle a special case, this is passed the actual arguments.
6547a84e134Smrg */
6557a84e134Smrgstatic Boolean
6567a84e134SmrgXawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args)
6577a84e134Smrg{
6587a84e134Smrg    Cardinal i;
6597a84e134Smrg    Dimension width, height;
660421c997bSmrg
6617a84e134Smrg    width = XtWidth(w);
6627a84e134Smrg    height = XtHeight(w);
663421c997bSmrg
6647a84e134Smrg    for (i = 0 ; i < *num_args ; i++) {
6657a84e134Smrg	if (streq(arglist[i].name, XtNwidth))
6667a84e134Smrg	    width = (Dimension)arglist[i].value;
6677a84e134Smrg	if (streq(arglist[i].name, XtNheight))
6687a84e134Smrg	    height = (Dimension) arglist[i].value;
6697a84e134Smrg    }
6707a84e134Smrg
6717a84e134Smrg    if (width != XtWidth(w) || height != XtHeight(w))
6727a84e134Smrg	MakeSetValuesRequest(w, width, height);
6737a84e134Smrg
6747a84e134Smrg    return (False);
6757a84e134Smrg}
6767a84e134Smrg
6777a84e134Smrg/*
6787a84e134Smrg * Geometry Management routines
6797a84e134Smrg */
6807a84e134Smrg/*
6817a84e134Smrg * Function:
6827a84e134Smrg *	XawSimpleMenuGeometryManager
6837a84e134Smrg *
6847a84e134Smrg * Parameters:
6857a84e134Smrg *	w	- Menu Entry making the request
6867a84e134Smrg *	request - requested new geometry
6877a84e134Smrg *                 reply - the allowed geometry.
6887a84e134Smrg *
6897a84e134Smrg * Description:
6907a84e134Smrg *	This is the SimpleMenu Widget's Geometry Manager.
6917a84e134Smrg *
6927a84e134Smrg * Returns:
6937a84e134Smrg *	XtGeometry{Yes, No, Almost}
6947a84e134Smrg */
6957a84e134Smrgstatic XtGeometryResult
6967a84e134SmrgXawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request,
6977a84e134Smrg			     XtWidgetGeometry *reply)
6987a84e134Smrg{
6997a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w);
7007a84e134Smrg    SmeObject entry = (SmeObject)w;
7017a84e134Smrg    XtGeometryMask mode = request->request_mode;
7027a84e134Smrg    XtGeometryResult answer;
7037a84e134Smrg    Dimension old_height, old_width;
7047a84e134Smrg
7057a84e134Smrg    if (!(mode & CWWidth) && !(mode & CWHeight))
7067a84e134Smrg	return (XtGeometryNo);
7077a84e134Smrg
7087a84e134Smrg    reply->width = request->width;
7097a84e134Smrg    reply->height = request->height;
7107a84e134Smrg
7117a84e134Smrg    old_width = XtWidth(entry);
7127a84e134Smrg    old_height = XtHeight(entry);
7137a84e134Smrg
7147a84e134Smrg    Layout(w, &reply->width, &reply->height);
7157a84e134Smrg
7167a84e134Smrg    /*
7177a84e134Smrg     * Since we are an override shell and have no parent there is no one to
7187a84e134Smrg     * ask to see if this geom change is okay, so I am just going to assume
7197a84e134Smrg     * we can do whatever we want.  If you subclass be very careful with this
7207a84e134Smrg     * assumption, it could bite you.
7217a84e134Smrg     *
7227a84e134Smrg     * Chris D. Peterson - Sept. 1989.
7237a84e134Smrg     */
7247a84e134Smrg    if ((!(mode & CWWidth) || reply->width == request->width)
7257a84e134Smrg	&& (!(mode & CWHeight) || reply->height == request->height)) {
7267a84e134Smrg	if (mode & XtCWQueryOnly) {	/* Actually perform the layout */
7277a84e134Smrg	    XtWidth(entry) = old_width;
7287a84e134Smrg	    XtHeight(entry) = old_height;
7297a84e134Smrg	}
7307a84e134Smrg	else
7317a84e134Smrg	    Layout((Widget)smw, NULL, NULL);
7327a84e134Smrg	answer = XtGeometryDone;
7337a84e134Smrg    }
7347a84e134Smrg    else {
7357a84e134Smrg	XtWidth(entry) = old_width;
7367a84e134Smrg	XtHeight(entry) = old_height;
7377a84e134Smrg
7387a84e134Smrg	if ((reply->width == request->width && !(mode & CWHeight))
7397a84e134Smrg	    || (reply->height == request->height && !(mode & CWWidth))
7407a84e134Smrg	    || (reply->width == request->width
7417a84e134Smrg	    && reply->height == request->height))
7427a84e134Smrg	    answer = XtGeometryNo;
7437a84e134Smrg	else {
7447a84e134Smrg	    answer = XtGeometryAlmost;
7457a84e134Smrg	    reply->request_mode = 0;
7467a84e134Smrg	    if (reply->width != request->width)
7477a84e134Smrg		reply->request_mode |= CWWidth;
7487a84e134Smrg	    if (reply->height != request->height)
7497a84e134Smrg		reply->request_mode |= CWHeight;
7507a84e134Smrg	}
7517a84e134Smrg    }
7527a84e134Smrg
7537a84e134Smrg    return (answer);
7547a84e134Smrg}
7557a84e134Smrg
7567a84e134Smrg/*
7577a84e134Smrg * Function:
7587a84e134Smrg *	XawSimpleMenuChangeManaged
7597a84e134Smrg *
7607a84e134Smrg * Parameters:
7617a84e134Smrg *	w - simple menu widget
7627a84e134Smrg *
7637a84e134Smrg * Description:
7647a84e134Smrg *	Called whenever a new child is managed.
7657a84e134Smrg */
7667a84e134Smrgstatic void
7677a84e134SmrgXawSimpleMenuChangeManaged(Widget w)
7687a84e134Smrg{
7697a84e134Smrg    Layout(w, NULL, NULL);
7707a84e134Smrg}
7717a84e134Smrg
7727a84e134Smrg/*
7737a84e134Smrg * Global Action Routines
774421c997bSmrg *
7757a84e134Smrg * These actions routines will be added to the application's
7767a84e134Smrg * global action list
7777a84e134Smrg */
7787a84e134Smrg/*
7797a84e134Smrg * Function:
7807a84e134Smrg *	PositionMenuAction
781421c997bSmrg *
7827a84e134Smrg * Parameters:
7837a84e134Smrg *	w	   - a widget (no the simple menu widget)
7847a84e134Smrg *	event	   - the event that caused this action
7857a84e134Smrg *	params	   - parameters passed to the routine.
7867a84e134Smrg *                                      we expect the name of the menu here.
7877a84e134Smrg *	num_params - ""
7887a84e134Smrg *
7897a84e134Smrg * Description:
7907a84e134Smrg *	Positions the simple menu widget.
7917a84e134Smrg */
7927a84e134Smrg/*ARGSUSED*/
7937a84e134Smrgstatic void
7947a84e134SmrgPositionMenuAction(Widget w, XEvent *event,
7957a84e134Smrg		   String *params, Cardinal *num_params)
796421c997bSmrg{
7977a84e134Smrg    Widget menu;
7987a84e134Smrg    XPoint loc;
7997a84e134Smrg
8007a84e134Smrg    if (*num_params != 1) {
8017a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w),
8027a84e134Smrg		     "SimpleMenuWidget: position menu action expects "
8037a84e134Smrg		     "only one parameter which is the name of the menu.");
8047a84e134Smrg	return;
8057a84e134Smrg    }
8067a84e134Smrg
8077a84e134Smrg    if ((menu = FindMenu(w, params[0])) == NULL) {
8087a84e134Smrg	char error_buf[BUFSIZ];
8097a84e134Smrg
810421c997bSmrg	snprintf(error_buf, sizeof(error_buf),
811421c997bSmrg		 "SimpleMenuWidget: could not find menu named %s.",
812421c997bSmrg		 params[0]);
8137a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
8147a84e134Smrg	return;
8157a84e134Smrg    }
816421c997bSmrg
8177a84e134Smrg    switch (event->type) {
8187a84e134Smrg	case ButtonPress:
8197a84e134Smrg	case ButtonRelease:
8205ec34c4cSmrg	    loc.x = (short)event->xbutton.x_root;
8215ec34c4cSmrg	    loc.y = (short)event->xbutton.y_root;
8227a84e134Smrg	    PositionMenu(menu, &loc);
8237a84e134Smrg	    break;
8247a84e134Smrg	case EnterNotify:
8257a84e134Smrg	case LeaveNotify:
8265ec34c4cSmrg	    loc.x = (short)event->xcrossing.x_root;
8275ec34c4cSmrg	    loc.y = (short)event->xcrossing.y_root;
8287a84e134Smrg	    PositionMenu(menu, &loc);
8297a84e134Smrg	    break;
8307a84e134Smrg	case MotionNotify:
8315ec34c4cSmrg	    loc.x = (short)event->xmotion.x_root;
8325ec34c4cSmrg	    loc.y = (short)event->xmotion.y_root;
8337a84e134Smrg	    PositionMenu(menu, &loc);
8347a84e134Smrg	    break;
8357a84e134Smrg	default:
8367a84e134Smrg	    PositionMenu(menu, NULL);
8377a84e134Smrg	    break;
8387a84e134Smrg    }
839421c997bSmrg}
8407a84e134Smrg
8417a84e134Smrg/*
8427a84e134Smrg * Widget Action Routines
8437a84e134Smrg */
8447a84e134Smrg/*
8457a84e134Smrg * Function:
8467a84e134Smrg *	Unhighlight
8477a84e134Smrg *
8487a84e134Smrg * Parameters:
8497a84e134Smrg *	w	   - simple menu widget
8507a84e134Smrg *	event	   - event that caused this action
8517a84e134Smrg *	params	   - not used
8527a84e134Smrg *	num_params - ""
853421c997bSmrg *
8547a84e134Smrg * Description:
8557a84e134Smrg *	Unhighlights current entry.
8567a84e134Smrg */
8577a84e134Smrg/*ARGSUSED*/
8587a84e134Smrgstatic void
8595ec34c4cSmrgUnhighlight(Widget w, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED)
860421c997bSmrg{
8617a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
8627a84e134Smrg    SmeObject entry = smw->simple_menu.entry_set;
863421c997bSmrg
8647a84e134Smrg    if (entry == NULL)
8657a84e134Smrg	return;
8667a84e134Smrg
8677a84e134Smrg#ifndef OLDXAW
8687a84e134Smrg    if (!smw->simple_menu.sub_menu)
8697a84e134Smrg#endif
8707a84e134Smrg    {
8717a84e134Smrg	SmeObjectClass cclass;
8727a84e134Smrg
8737a84e134Smrg	smw->simple_menu.entry_set = NULL;
8747a84e134Smrg	cclass = (SmeObjectClass)entry->object.widget_class;
8757a84e134Smrg	(cclass->sme_class.unhighlight)((Widget)entry);
8767a84e134Smrg    }
8777a84e134Smrg}
8787a84e134Smrg
8797a84e134Smrg/*
8807a84e134Smrg * Function:
8817a84e134Smrg *	Highlight
8827a84e134Smrg *
8837a84e134Smrg * Parameters:
8847a84e134Smrg *	w	   - simple menu widget
8857a84e134Smrg *	event	   - event that caused this action
8867a84e134Smrg *	params	   - not used
8877a84e134Smrg *	num_params - ""
8887a84e134Smrg *
8897a84e134Smrg * Description:
8907a84e134Smrg *	Highlights current entry.
8917a84e134Smrg */
8927a84e134Smrg/*ARGSUSED*/
8937a84e134Smrgstatic void
8947a84e134SmrgHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
8957a84e134Smrg{
8967a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
8977a84e134Smrg    SmeObject entry;
8987a84e134Smrg
8997a84e134Smrg    if (!XtIsSensitive(w))
9007a84e134Smrg	return;
9017a84e134Smrg
9027a84e134Smrg    entry = GetEventEntry(w, event);
9037a84e134Smrg
9047a84e134Smrg    if (entry == smw->simple_menu.entry_set)
9057a84e134Smrg	return;
9067a84e134Smrg
9077a84e134Smrg#ifndef OLDXAW
9087a84e134Smrg    if (!smw->simple_menu.sub_menu)
9097a84e134Smrg#endif
9107a84e134Smrg	Unhighlight(w, event, params, num_params);
9117a84e134Smrg
9127a84e134Smrg    if (entry == NULL)
9137a84e134Smrg	return;
9147a84e134Smrg
9157a84e134Smrg    if (!XtIsSensitive((Widget)entry))
9167a84e134Smrg	return;
9177a84e134Smrg
9187a84e134Smrg#ifndef OLDXAW
9197a84e134Smrg    if (smw->simple_menu.sub_menu)
9207a84e134Smrg	PopdownSubMenu(smw);
9217a84e134Smrg#endif
9227a84e134Smrg
9237a84e134Smrg    Unhighlight(w, event, params, num_params);
9247a84e134Smrg
9257a84e134Smrg#ifndef OLDXAW
9267a84e134Smrg    if (!(smw->simple_menu.state & SMW_UNMAPPING))
9277a84e134Smrg#endif
9287a84e134Smrg    {
9297a84e134Smrg	SmeObjectClass cclass;
9307a84e134Smrg
9317a84e134Smrg	smw->simple_menu.entry_set = entry;
9327a84e134Smrg	cclass = (SmeObjectClass)entry->object.widget_class;
9337a84e134Smrg
9347a84e134Smrg	(cclass->sme_class.highlight)((Widget)entry);
9357a84e134Smrg
9367a84e134Smrg#ifndef OLDXAW
9377a84e134Smrg	if (XtIsSubclass((Widget)entry, smeBSBObjectClass))
9387a84e134Smrg	    PopupSubMenu(smw);
9397a84e134Smrg#endif
9407a84e134Smrg    }
9417a84e134Smrg}
9427a84e134Smrg
9437a84e134Smrg/*
9447a84e134Smrg * Function:
9457a84e134Smrg *	Notify
9467a84e134Smrg *
9477a84e134Smrg * Parameters:
9487a84e134Smrg *	w	   - simple menu widget
9497a84e134Smrg *	event	   - event that caused this action
9507a84e134Smrg *	params	   - not used
9517a84e134Smrg *	num_params - ""
9527a84e134Smrg *
9537a84e134Smrg * Description:
9547a84e134Smrg *	Notify user of current entry.
9557a84e134Smrg */
9567a84e134Smrg/*ARGSUSED*/
9577a84e134Smrgstatic void
9585ec34c4cSmrgNotify(Widget w, XEvent *event, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED)
9597a84e134Smrg{
9607a84e134Smrg    SmeObject entry;
9617a84e134Smrg    SmeObjectClass cclass;
9627a84e134Smrg
9637a84e134Smrg    /* may be a propagated event from a sub menu, need to check it */
9647a84e134Smrg    if (XtWindow(w) != event->xany.window)
9657a84e134Smrg	return;
9667a84e134Smrg    entry = GetEventEntry(w, event);
9677a84e134Smrg    if (entry == NULL || !XtIsSensitive((Widget)entry))
9687a84e134Smrg	return;
9697a84e134Smrg
9707a84e134Smrg    cclass = (SmeObjectClass) entry->object.widget_class;
9717a84e134Smrg    (cclass->sme_class.notify)((Widget)entry);
9727a84e134Smrg}
9737a84e134Smrg
9747a84e134Smrg/*
9757a84e134Smrg * Public Functions
9767a84e134Smrg */
9777a84e134Smrg/*
9787a84e134Smrg * Function:
9797a84e134Smrg *	XawSimpleMenuAddGlobalActions
9807a84e134Smrg *
9817a84e134Smrg * Arguments:
9827a84e134Smrg *	app_con - appcontext
9837a84e134Smrg *
9847a84e134Smrg * Description:
9857a84e134Smrg *	Adds the global actions to the simple menu widget.
9867a84e134Smrg */
9877a84e134Smrgvoid
9887a84e134SmrgXawSimpleMenuAddGlobalActions(XtAppContext app_con)
9897a84e134Smrg{
9907a84e134Smrg    XtInitializeWidgetClass(simpleMenuWidgetClass);
9917a84e134Smrg    XmuCallInitializers(app_con);
992421c997bSmrg}
9937a84e134Smrg
9947a84e134Smrg/*
9957a84e134Smrg * Function:
9967a84e134Smrg *	XawSimpleMenuGetActiveEntry
9977a84e134Smrg *
9987a84e134Smrg * Parameters:
9997a84e134Smrg *	w - smw widget
10007a84e134Smrg *
10017a84e134Smrg * Description:
10027a84e134Smrg *	Gets the currently active (set) entry.
10037a84e134Smrg *
10047a84e134Smrg * Returns:
10057a84e134Smrg *	The currently set entry or NULL if none is set
10067a84e134Smrg */
10077a84e134SmrgWidget
10087a84e134SmrgXawSimpleMenuGetActiveEntry(Widget w)
10097a84e134Smrg{
10107a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10117a84e134Smrg
10127a84e134Smrg    return ((Widget)smw->simple_menu.entry_set);
1013421c997bSmrg}
10147a84e134Smrg
10157a84e134Smrg/*
10167a84e134Smrg * Function:
10177a84e134Smrg *	XawSimpleMenuClearActiveEntry
10187a84e134Smrg *
10197a84e134Smrg * Parameters:
10207a84e134Smrg *	w - smw widget
10217a84e134Smrg *
10227a84e134Smrg * Description:
10237a84e134Smrg *	Unsets the currently active (set) entry.
10247a84e134Smrg */
10257a84e134Smrgvoid
10267a84e134SmrgXawSimpleMenuClearActiveEntry(Widget w)
10277a84e134Smrg{
10287a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10297a84e134Smrg
10307a84e134Smrg    smw->simple_menu.entry_set = NULL;
1031421c997bSmrg}
10327a84e134Smrg
10337a84e134Smrg/*
10347a84e134Smrg * Private Functions
10357a84e134Smrg */
10367a84e134Smrg/*
10377a84e134Smrg * Function:
10387a84e134Smrg *	CreateLabel
10397a84e134Smrg *
10407a84e134Smrg * Parameters:
10417a84e134Smrg *	w - smw widget
1042421c997bSmrg *
10437a84e134Smrg * Description:
10447a84e134Smrg * Creates the label object and makes sure it is the first child in
10457a84e134Smrg * in the list.
10467a84e134Smrg */
10477a84e134Smrgstatic void
10487a84e134SmrgCreateLabel(Widget w)
10497a84e134Smrg{
10507a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10517a84e134Smrg    Widget *child, *next_child;
10527a84e134Smrg    int i;
10537a84e134Smrg    Arg args[2];
10547a84e134Smrg
10557a84e134Smrg    if (smw->simple_menu.label_string == NULL ||
10567a84e134Smrg	smw->simple_menu.label != NULL) {
10577a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w),
10587a84e134Smrg		     "Xaw Simple Menu Widget: label string is NULL or "
10597a84e134Smrg		     "label already exists, no label is being created.");
10607a84e134Smrg	return;
10617a84e134Smrg    }
10627a84e134Smrg
10637a84e134Smrg    XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
10647a84e134Smrg    XtSetArg(args[1], XtNjustify, XtJustifyCenter);
1065421c997bSmrg    smw->simple_menu.label = (SmeObject)
1066421c997bSmrg	XtCreateManagedWidget("menuLabel",
10677a84e134Smrg			      smw->simple_menu.label_class, w, args, TWO);
10687a84e134Smrg
10697a84e134Smrg    next_child = NULL;
10707a84e134Smrg    for (child = smw->composite.children + smw->composite.num_children,
10715ec34c4cSmrg	 i = (int)smw->composite.num_children; i > 0; i--, child--) {
10727a84e134Smrg	if (next_child != NULL)
10737a84e134Smrg	    *next_child = *child;
10747a84e134Smrg	next_child = child;
10757a84e134Smrg    }
1076efbcb2bfSmrg
1077efbcb2bfSmrg    if (child != NULL)
1078efbcb2bfSmrg	*child = (Widget)smw->simple_menu.label;
10797a84e134Smrg}
10807a84e134Smrg
10817a84e134Smrg/*
10827a84e134Smrg * Function:
10837a84e134Smrg *	Layout
10847a84e134Smrg *
10857a84e134Smrg * Arguments:
10867a84e134Smrg *	w	   - See below
10877a84e134Smrg *	width_ret  - returned width
10887a84e134Smrg *	height_ret - returned height
10897a84e134Smrg *
10907a84e134Smrg * Note:
10917a84e134Smrg * if width == NULL || height == NULL then it assumes the you do not care
10927a84e134Smrg * about the return values, and just want a relayout.
10937a84e134Smrg *
10947a84e134Smrg * if this is not the case then it will set width_ret and height_ret
10955b16253fSmrg * to be width and height that the child would get if it were laid out
10967a84e134Smrg * at this time.
10977a84e134Smrg *
10987a84e134Smrg *	"w" can be the simple menu widget or any of its object children.
10997a84e134Smrg */
11007a84e134Smrgstatic void
11017a84e134SmrgLayout(Widget w, Dimension *width_ret, Dimension *height_ret)
11027a84e134Smrg{
11037a84e134Smrg    SmeObject current_entry;
11047a84e134Smrg    SimpleMenuWidget smw;
11057a84e134Smrg    Dimension width, height;
11067a84e134Smrg    Boolean allow_change_size;
11077a84e134Smrg    Widget kid;
11087a84e134Smrg    Cardinal i, count, n;
11097a84e134Smrg    int width_kid, height_kid, tmp_w, tmp_h;
11107a84e134Smrg    short vadd, hadd, x_ins, y_ins;
11117a84e134Smrg    Dimension *widths;
11127a84e134Smrg
11137a84e134Smrg    if (XtIsSubclass(w, simpleMenuWidgetClass)) {
11147a84e134Smrg	smw = (SimpleMenuWidget)w;
11157a84e134Smrg	current_entry = NULL;
11167a84e134Smrg    }
11177a84e134Smrg    else {
11187a84e134Smrg	smw = (SimpleMenuWidget)XtParent(w);
11197a84e134Smrg	current_entry = (SmeObject)w;
11207a84e134Smrg    }
11217a84e134Smrg
11227a84e134Smrg    allow_change_size = (!XtIsRealized((Widget)smw)
11237a84e134Smrg			 || smw->shell.allow_shell_resize);
11247a84e134Smrg
11257a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
11267a84e134Smrg	 i < smw->composite.num_children;
11277a84e134Smrg	 i++) {
11287a84e134Smrg	XtWidgetGeometry preferred;
11297a84e134Smrg
11307a84e134Smrg	kid = smw->composite.children[i];
11317a84e134Smrg	if (!XtIsManaged(kid))
11327a84e134Smrg	    continue;
11337a84e134Smrg	if (smw->simple_menu.row_height != 0)
11347a84e134Smrg	    XtHeight(kid) = smw->simple_menu.row_height;
11357a84e134Smrg	XtQueryGeometry(kid, NULL, &preferred);
11367a84e134Smrg	if (preferred.request_mode & CWWidth)
11377a84e134Smrg	    XtWidth(kid) = preferred.width;
11387a84e134Smrg    }
11397a84e134Smrg
11407a84e134Smrg    if (smw->simple_menu.label
11417a84e134Smrg	&& XtIsManaged((Widget)smw->simple_menu.label)) {
11427a84e134Smrg	XtWidgetGeometry preferred;
11437a84e134Smrg
11447a84e134Smrg	kid = (Widget)smw->simple_menu.label;
11457a84e134Smrg	XtQueryGeometry(kid, NULL, &preferred);
11467a84e134Smrg	if (preferred.request_mode & CWWidth)
11477a84e134Smrg	    XtWidth(kid) = preferred.width;
11487a84e134Smrg	if (preferred.request_mode & CWHeight)
11497a84e134Smrg	    XtHeight(kid) = preferred.height;
11507a84e134Smrg    }
11517a84e134Smrg
11527a84e134Smrg    /* reset */
11537a84e134Smrg    if (!smw->simple_menu.menu_width)
11547a84e134Smrg	XtWidth(smw) = 0;
11557a84e134Smrg    if (!smw->simple_menu.menu_height)
11567a84e134Smrg	XtHeight(smw) = 0;
11577a84e134Smrg    if (!XtWidth(smw) || !XtHeight(smw))
11587a84e134Smrg	MakeResizeRequest((Widget)smw);
11597a84e134Smrg
11607a84e134Smrg    widths = (Dimension *)XtMalloc(sizeof(Dimension));
11617a84e134Smrg#ifndef OLDXAW
11625ec34c4cSmrg    hadd = (short)smw->simple_menu.left_margin;
11637a84e134Smrg#else
11647a84e134Smrg    hadd = 0;
11657a84e134Smrg#endif
11665ec34c4cSmrg    vadd = (short)smw->simple_menu.top_margin;
11677a84e134Smrg    if (smw->simple_menu.label)
11685ec34c4cSmrg	vadd = (short)(vadd + XtHeight(smw->simple_menu.label));
11697a84e134Smrg
11707a84e134Smrg    count = 1;
11715ec34c4cSmrg    width = (Dimension)(tmp_w = tmp_h = (int)(n = 0));
11725ec34c4cSmrg    height = (Dimension)vadd;
11737a84e134Smrg
11747a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
11757a84e134Smrg	 i < smw->composite.num_children;
11767a84e134Smrg	 i++) {
11777a84e134Smrg	kid = smw->composite.children[i];
11787a84e134Smrg	if (!XtIsManaged(kid))
11797a84e134Smrg	    continue;
11807a84e134Smrg	width_kid = XtWidth(kid);
11817a84e134Smrg	height_kid = XtHeight(kid);
11827a84e134Smrg
11837a84e134Smrg	if (n && (height + height_kid + smw->simple_menu.bottom_margin
11847a84e134Smrg		  > XtHeight(smw))) {
11857a84e134Smrg	    ++count;
11867a84e134Smrg	    widths = (Dimension *)XtRealloc((char *)widths,
11875ec34c4cSmrg					    (Cardinal)(sizeof(Dimension) * count));
11885ec34c4cSmrg	    widths[count - 1] = (Dimension)width_kid;
11895ec34c4cSmrg	    width = (Dimension)(width + tmp_w);
11907a84e134Smrg	    tmp_w = width_kid;
11915ec34c4cSmrg	    height = (Dimension)(height_kid + vadd);
11927a84e134Smrg	}
11937a84e134Smrg	else
11945ec34c4cSmrg	    height = (Dimension)(height + height_kid);
11957a84e134Smrg	if (height > tmp_h)
11967a84e134Smrg	    tmp_h = height;
11977a84e134Smrg	if (width_kid > tmp_w)
11985ec34c4cSmrg	    widths[count - 1] = (Dimension)(tmp_w = width_kid);
11997a84e134Smrg	++n;
12007a84e134Smrg    }
12017a84e134Smrg
1202efbcb2bfSmrg    height = (Dimension)(tmp_h + smw->simple_menu.bottom_margin);
12035ec34c4cSmrg    width = (Dimension)(width + tmp_w);
12047a84e134Smrg
12057a84e134Smrg    if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) {
12067a84e134Smrg	float inc;
12077a84e134Smrg
12085ec34c4cSmrg	inc = (float)(XtWidth(smw->simple_menu.label) - width) / (float)count;
12097a84e134Smrg	width = XtWidth(smw->simple_menu.label);
12107a84e134Smrg	for (n = 0; n < count; n++)
12115ec34c4cSmrg	    widths[n] = (Dimension)(widths[n] + inc);
12127a84e134Smrg    }
12137a84e134Smrg
12147a84e134Smrg#ifndef OLDXAW
12155ec34c4cSmrg    width = (Dimension)(width + (hadd + smw->simple_menu.right_margin));
12167a84e134Smrg#endif
12177a84e134Smrg
12185ec34c4cSmrg    x_ins = (short)(n = count = 0);
12197a84e134Smrg    tmp_w = widths[0];
12207a84e134Smrg    tmp_h = vadd;
12217a84e134Smrg
12227a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
12237a84e134Smrg	 i < smw->composite.num_children;
12247a84e134Smrg	 i++) {
12257a84e134Smrg	kid = smw->composite.children[i];
12267a84e134Smrg	if (!XtIsManaged(kid))
12277a84e134Smrg	    continue;
12287a84e134Smrg
12297a84e134Smrg	height_kid = XtHeight(kid);
12307a84e134Smrg
12317a84e134Smrg	if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin
12327a84e134Smrg		  > XtHeight(smw))) {
12335ec34c4cSmrg	    x_ins = (short)tmp_w;
12347a84e134Smrg	    y_ins = vadd;
12357a84e134Smrg	    ++count;
12367a84e134Smrg	    tmp_w += widths[count];
12377a84e134Smrg	    tmp_h = height_kid + vadd;
12387a84e134Smrg	}
12397a84e134Smrg	else {
12405ec34c4cSmrg	    y_ins = (short)tmp_h;
12417a84e134Smrg	    tmp_h += height_kid;
12427a84e134Smrg	}
12437a84e134Smrg	++n;
12447a84e134Smrg
12455ec34c4cSmrg	XtX(kid) = (Position)(x_ins + hadd);
12467a84e134Smrg	XtY(kid) = y_ins;
12477a84e134Smrg	XtWidth(kid) = widths[count];
12487a84e134Smrg    }
12497a84e134Smrg
12507a84e134Smrg    XtFree((char *)widths);
12517a84e134Smrg
12527a84e134Smrg    if (allow_change_size)
12537a84e134Smrg	MakeSetValuesRequest((Widget) smw, width, height);
12547a84e134Smrg
12557a84e134Smrg    if (smw->simple_menu.label) {
12567a84e134Smrg	XtX(smw->simple_menu.label) = 0;
12575ec34c4cSmrg	XtY(smw->simple_menu.label) = (Position)smw->simple_menu.top_margin;
12585ec34c4cSmrg	XtWidth(smw->simple_menu.label) = (Dimension)(XtWidth(smw)
12597a84e134Smrg#ifndef OLDXAW
12607a84e134Smrg	    - (smw->simple_menu.left_margin + smw->simple_menu.right_margin)
12617a84e134Smrg#endif
12625ec34c4cSmrg	    );
12637a84e134Smrg    }
12647a84e134Smrg    if (current_entry) {
12657a84e134Smrg	if (width_ret)
12667a84e134Smrg	    *width_ret = XtWidth(current_entry);
12677a84e134Smrg	if (height_ret)
12687a84e134Smrg	    *height_ret = XtHeight(current_entry);
12697a84e134Smrg    }
12707a84e134Smrg}
1271421c997bSmrg
12727a84e134Smrg/*
12737a84e134Smrg * Function:
12747a84e134Smrg *	AddPositionAction
12757a84e134Smrg *
12767a84e134Smrg * Parameters:
12777a84e134Smrg *	app_con - application context
12787a84e134Smrg *	data	- (not used)
12797a84e134Smrg *
12807a84e134Smrg * Description:
12817a84e134Smrg *	  Adds the XawPositionSimpleMenu action to the global
12827a84e134Smrg *                   action list for this appcon.
12837a84e134Smrg */
12847a84e134Smrg/*ARGSUSED*/
12857a84e134Smrgstatic void
12865ec34c4cSmrgAddPositionAction(XtAppContext app_con, XPointer data _X_UNUSED)
12877a84e134Smrg{
12887a84e134Smrg    static XtActionsRec pos_action[] = {
12897a84e134Smrg	{"XawPositionSimpleMenu",	PositionMenuAction},
12907a84e134Smrg    };
12917a84e134Smrg
12927a84e134Smrg    XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
12937a84e134Smrg}
12947a84e134Smrg
12957a84e134Smrg/*
12967a84e134Smrg * Function:
12977a84e134Smrg *	FindMenu
12987a84e134Smrg *
12997a84e134Smrg * Parameters:
13007a84e134Smrg *	widget - reference widget
13017a84e134Smrg *	name   - menu widget's name
13027a84e134Smrg *
13037a84e134Smrg * Description:
13047a84e134Smrg *	Find the menu give a name and reference widget
13057a84e134Smrg *
13067a84e134Smrg * Returns:
13077a84e134Smrg *	The menu widget or NULL.
13087a84e134Smrg */
1309421c997bSmrgstatic Widget
13107a84e134SmrgFindMenu(Widget widget, String name)
13117a84e134Smrg{
1312efbcb2bfSmrg    Widget w;
1313421c997bSmrg
1314efbcb2bfSmrg    for (w = widget; w != NULL; w = XtParent(w)) {
1315efbcb2bfSmrg	Widget menu = XtNameToWidget(w, name);
13167a84e134Smrg
1317efbcb2bfSmrg	if (menu != NULL)
1318efbcb2bfSmrg	    return (menu);
1319efbcb2bfSmrg    }
13207a84e134Smrg    return (NULL);
13217a84e134Smrg}
13227a84e134Smrg
13237a84e134Smrg/*
13247a84e134Smrg * Function:
13257a84e134Smrg *	PositionMenu
13267a84e134Smrg *
13277a84e134Smrg * Parameters:
13287a84e134Smrg *	w	 - simple menu widget
13297a84e134Smrg *	location - pointer the the position or NULL
13307a84e134Smrg *
13317a84e134Smrg * Description:
13327a84e134Smrg *	Places the menu
13337a84e134Smrg */
13347a84e134Smrgstatic void
13357a84e134SmrgPositionMenu(Widget w, XPoint *location)
13367a84e134Smrg{
13377a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
13387a84e134Smrg    SmeObject entry;
13397a84e134Smrg    XPoint t_point;
1340421c997bSmrg
13417a84e134Smrg    if (location == NULL) {
13427a84e134Smrg	Window temp1, temp2;
13437a84e134Smrg	int root_x, root_y, tempX, tempY;
13447a84e134Smrg	unsigned int tempM;
1345421c997bSmrg
13467a84e134Smrg	location = &t_point;
13477a84e134Smrg	if (XQueryPointer(XtDisplay(w), XtWindow(w), &temp1, &temp2,
13487a84e134Smrg			  &root_x, &root_y, &tempX, &tempY, &tempM) == False) {
13497a84e134Smrg	    XtAppWarning(XtWidgetToApplicationContext(w),
13507a84e134Smrg			 "Xaw Simple Menu Widget: "
13517a84e134Smrg			 "Could not find location of mouse pointer");
13527a84e134Smrg	    return;
13537a84e134Smrg	}
13547a84e134Smrg	location->x = (short) root_x;
13557a84e134Smrg	location->y = (short) root_y;
13567a84e134Smrg    }
1357421c997bSmrg
13587a84e134Smrg    /*
13597a84e134Smrg     * The width will not be correct unless it is realized
13607a84e134Smrg     */
13617a84e134Smrg    XtRealizeWidget(w);
1362421c997bSmrg
13635ec34c4cSmrg    location->x = (short)(location->x - (XtWidth(w) >> 1));
1364421c997bSmrg
13657a84e134Smrg    if (smw->simple_menu.popup_entry == NULL)
13667a84e134Smrg	entry = smw->simple_menu.label;
13677a84e134Smrg    else
13687a84e134Smrg	entry = smw->simple_menu.popup_entry;
13697a84e134Smrg
13707a84e134Smrg    if (entry != NULL)
13715ec34c4cSmrg      location->y = (short)(location->y - (XtY(entry) + (XtHeight(entry) >> 1)));
13727a84e134Smrg
13737a84e134Smrg    MoveMenu(w, location->x, location->y);
13747a84e134Smrg}
13757a84e134Smrg
13767a84e134Smrg/*
13777a84e134Smrg * Function:
13787a84e134Smrg *	MoveMenu
13797a84e134Smrg *
13807a84e134Smrg * Parameters:
13817a84e134Smrg *	w - simple menu widget
13827a84e134Smrg *	x - current location of the widget
13837a84e134Smrg *	y - ""
13847a84e134Smrg *
13857a84e134Smrg * Description:
13867a84e134Smrg *	  Actually moves the menu, may force it to
13875b16253fSmrg *	to be fully visible if menu_on_screen is True.
13887a84e134Smrg */
13897a84e134Smrgstatic void
13907a84e134SmrgMoveMenu(Widget w, int x, int y)
13917a84e134Smrg{
13927a84e134Smrg    Arg arglist[2];
13937a84e134Smrg    Cardinal num_args = 0;
13947a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
1395421c997bSmrg
13967a84e134Smrg    if (smw->simple_menu.menu_on_screen) {
13977a84e134Smrg	int width = XtWidth(w) + (XtBorderWidth(w) << 1);
13987a84e134Smrg	int height = XtHeight(w) + (XtBorderWidth(w) << 1);
1399421c997bSmrg
14007a84e134Smrg	if (x >= 0) {
14017a84e134Smrg	    int scr_width = WidthOfScreen(XtScreen(w));
14027a84e134Smrg
14037a84e134Smrg	    if (x + width > scr_width)
14047a84e134Smrg		x = scr_width - width;
14057a84e134Smrg	}
1406421c997bSmrg	if (x < 0)
14077a84e134Smrg	    x = 0;
1408421c997bSmrg
14097a84e134Smrg	if (y >= 0) {
14107a84e134Smrg	    int scr_height = HeightOfScreen(XtScreen(w));
14117a84e134Smrg
14127a84e134Smrg	    if (y + height > scr_height)
14137a84e134Smrg		y = scr_height - height;
14147a84e134Smrg	}
14157a84e134Smrg	if (y < 0)
14167a84e134Smrg	    y = 0;
14177a84e134Smrg    }
1418421c997bSmrg
14197a84e134Smrg    XtSetArg(arglist[num_args], XtNx, x); num_args++;
14207a84e134Smrg    XtSetArg(arglist[num_args], XtNy, y); num_args++;
14217a84e134Smrg    XtSetValues(w, arglist, num_args);
14227a84e134Smrg}
14237a84e134Smrg
14247a84e134Smrg/*
14257a84e134Smrg * Function:
14267a84e134Smrg *	ChangeCursorOnGrab
14277a84e134Smrg *
14287a84e134Smrg * Parameters:
14297a84e134Smrg *	w     - menu widget
14307a84e134Smrg *	temp1 - not used
14317a84e134Smrg *	temp2 - ""
14327a84e134Smrg *
14337a84e134Smrg * Description:
14347a84e134Smrg *	  Changes the cursor on the active grab to the one
14357a84e134Smrg *                   specified in out resource list.
14367a84e134Smrg */
14377a84e134Smrg/*ARGSUSED*/
14387a84e134Smrgstatic void
14395ec34c4cSmrgChangeCursorOnGrab(Widget w, XtPointer temp1 _X_UNUSED, XtPointer temp2 _X_UNUSED)
14407a84e134Smrg{
14417a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
1442421c997bSmrg
14437a84e134Smrg    /*
14447a84e134Smrg     * The event mask here is what is currently in the MIT implementation.
14457a84e134Smrg     * There really needs to be a way to get the value of the mask out
14467a84e134Smrg     * of the toolkit (CDP 5/26/89).
14477a84e134Smrg     */
14487a84e134Smrg    XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask | ButtonReleaseMask,
1449421c997bSmrg			     smw->simple_menu.cursor,
14507a84e134Smrg			     XtLastTimestampProcessed(XtDisplay(w)));
14517a84e134Smrg}
14527a84e134Smrg
14537a84e134Smrg/*
14547a84e134Smrg * Function:
14557a84e134Smrg *	MakeSetValuesRequest
14567a84e134Smrg *
14577a84e134Smrg * Parameters:
14587a84e134Smrg *	w      - simple menu widget
14597a84e134Smrg *	width  - size requested
14607a84e134Smrg *	height - ""
14617a84e134Smrg */
14627a84e134Smrgstatic void
14637a84e134SmrgMakeSetValuesRequest(Widget w, unsigned int width, unsigned int height)
14647a84e134Smrg{
14657a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
1466421c997bSmrg
14677a84e134Smrg    if (!smw->simple_menu.recursive_set_values) {
14687a84e134Smrg	if (XtWidth(smw) != width || XtHeight(smw) != height) {
1469efbcb2bfSmrg	    Arg arglist[2];
1470efbcb2bfSmrg	    Cardinal num_args = 0;
1471efbcb2bfSmrg
14727a84e134Smrg	    smw->simple_menu.recursive_set_values = True;
14737a84e134Smrg	    XtSetArg(arglist[num_args], XtNwidth, width);   num_args++;
14747a84e134Smrg	    XtSetArg(arglist[num_args], XtNheight, height); num_args++;
14757a84e134Smrg	    XtSetValues(w, arglist, num_args);
14767a84e134Smrg	}
14777a84e134Smrg	else if (XtIsRealized((Widget)smw))
14787a84e134Smrg	    XawSimpleMenuRedisplay((Widget)smw, NULL, NULL);
14797a84e134Smrg    }
14807a84e134Smrg    smw->simple_menu.recursive_set_values = False;
14817a84e134Smrg}
14827a84e134Smrg
14837a84e134Smrgstatic SmeObject
14847a84e134SmrgDoGetEventEntry(Widget w, int x_loc, int y_loc)
14857a84e134Smrg{
14867a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
14877a84e134Smrg    SmeObject *entry;
14887a84e134Smrg
14897a84e134Smrg    ForAllChildren(smw, entry) {
14907a84e134Smrg	if (!XtIsManaged((Widget)*entry))
14917a84e134Smrg	    continue;
14927a84e134Smrg
14937a84e134Smrg	if (x_loc > XtX(*entry)
14947a84e134Smrg	    && x_loc <= XtX(*entry) + XtWidth(*entry)
14957a84e134Smrg	    && y_loc > XtY(*entry)
14967a84e134Smrg	    &&  y_loc <= XtY(*entry) + XtHeight(*entry)) {
14977a84e134Smrg	    if (*entry == smw->simple_menu.label)
14987a84e134Smrg		return (NULL);	/* cannot select the label */
14997a84e134Smrg	    else
15007a84e134Smrg		return (*entry);
15017a84e134Smrg	}
15027a84e134Smrg    }
1503421c997bSmrg
15047a84e134Smrg    return (NULL);
15057a84e134Smrg}
15067a84e134Smrg
15077a84e134Smrg/*
15087a84e134Smrg * Function:
15097a84e134Smrg *	GetEventEntry
15107a84e134Smrg *
15117a84e134Smrg * Parameters:
15127a84e134Smrg *	w     - simple menu widget
15137a84e134Smrg *	event - X event
15147a84e134Smrg *
15157a84e134Smrg * Description:
15167a84e134Smrg *	Gets an entry given an event that has X and Y coords.
15177a84e134Smrg *
15187a84e134Smrg * Returns:
15197a84e134Smrg *	The entry that this point is in
15207a84e134Smrg */
15217a84e134Smrgstatic SmeObject
15227a84e134SmrgGetEventEntry(Widget w, XEvent *event)
15237a84e134Smrg{
15247a84e134Smrg    int x_loc, y_loc, x_root;
15257a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
15267a84e134Smrg    SmeObject entry;
15277a84e134Smrg    int warp, move;
15287a84e134Smrg
15297a84e134Smrg    switch (event->type) {
15307a84e134Smrg	case MotionNotify:
15317a84e134Smrg	    x_loc = event->xmotion.x;
15327a84e134Smrg	    y_loc = event->xmotion.y;
15337a84e134Smrg	    x_root = event->xmotion.x_root;
15347a84e134Smrg	    break;
15357a84e134Smrg	case EnterNotify:
15367a84e134Smrg	case LeaveNotify:
15377a84e134Smrg	    x_loc = event->xcrossing.x;
15387a84e134Smrg	    y_loc = event->xcrossing.y;
15397a84e134Smrg	    x_root = event->xcrossing.x_root;
15407a84e134Smrg	    break;
15417a84e134Smrg	case ButtonPress:
15427a84e134Smrg	case ButtonRelease:
15437a84e134Smrg	    x_loc = event->xbutton.x;
15447a84e134Smrg	    y_loc = event->xbutton.y;
15457a84e134Smrg	    x_root = event->xbutton.x_root;
15467a84e134Smrg	    break;
15477a84e134Smrg	default:
15487a84e134Smrg	    XtAppError(XtWidgetToApplicationContext(w),
15497a84e134Smrg		       "Unknown event type in GetEventEntry().");
15507a84e134Smrg	    return (NULL);
15517a84e134Smrg    }
1552421c997bSmrg
15537a84e134Smrg    if (x_loc < 0 || x_loc >= XtWidth(smw) ||
15547a84e134Smrg	y_loc < 0 || y_loc >= XtHeight(smw))
15557a84e134Smrg	return (NULL);
15567a84e134Smrg
15577a84e134Smrg    /* Move the menu if it's outside the screen, does not check
15587a84e134Smrg     * smw->simple_menu.menu_on_screen because menus is bigger than screen
15597a84e134Smrg     */
15607a84e134Smrg    if (x_root == WidthOfScreen(XtScreen(w)) - 1 &&
15617a84e134Smrg	XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) {
15627a84e134Smrg	if (smw->simple_menu.entry_set) {
15637a84e134Smrg	    entry = DoGetEventEntry(w,
15647a84e134Smrg				    XtX(smw->simple_menu.entry_set)
15657a84e134Smrg				    + XtWidth(smw->simple_menu.entry_set) + 1,
15667a84e134Smrg				    y_loc);
15677a84e134Smrg	    Unhighlight(w, event, NULL, NULL);
15687a84e134Smrg	    if (entry) {
15697a84e134Smrg		warp = -(int)XtWidth(entry) >> 1;
15707a84e134Smrg		move = x_loc - XtWidth(entry) - XtX(entry) + XtBorderWidth(w);
15717a84e134Smrg	    }
15727a84e134Smrg	    else {
15737a84e134Smrg		warp = 0;
15747a84e134Smrg		move = WidthOfScreen(XtScreen(w)) -
15757a84e134Smrg		       (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
15767a84e134Smrg	    }
15777a84e134Smrg	}
15787a84e134Smrg	else {
15797a84e134Smrg	    warp = 0;
15807a84e134Smrg	    move = WidthOfScreen(XtScreen(w)) -
15817a84e134Smrg		   (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
15827a84e134Smrg	}
15837a84e134Smrg    }
15847a84e134Smrg    else if (x_root == 0 && XtX(w) < 0) {
15857a84e134Smrg	warp = 8;
15867a84e134Smrg	if (smw->simple_menu.entry_set) {
15877a84e134Smrg	    entry = DoGetEventEntry(w, XtX(smw->simple_menu.entry_set) - 1,
15887a84e134Smrg				    y_loc);
15897a84e134Smrg	    Unhighlight(w, event, NULL, NULL);
15907a84e134Smrg	    if (entry) {
15917a84e134Smrg		warp = XtWidth(entry) >> 1;
15927a84e134Smrg		move = x_loc - XtX(entry);
15937a84e134Smrg	    }
15947a84e134Smrg	    else
15957a84e134Smrg		move = x_loc + XtBorderWidth(w);
15967a84e134Smrg	}
15977a84e134Smrg	else
15987a84e134Smrg	    move = x_loc + XtBorderWidth(w);
15997a84e134Smrg    }
16007a84e134Smrg    else
16017a84e134Smrg	move = warp = 0;
16027a84e134Smrg
16037a84e134Smrg    if (move)
16045ec34c4cSmrg	XtMoveWidget(w, (Position)(XtX(w) + move), XtY(w));
16057a84e134Smrg    if (warp)
16067a84e134Smrg	XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, warp, 0);
16077a84e134Smrg
16087a84e134Smrg    return (DoGetEventEntry(w, x_loc, y_loc));
16097a84e134Smrg}
16107a84e134Smrg
16117a84e134Smrgstatic void
16127a84e134SmrgCalculateNewSize(Widget w, Dimension *width_return, Dimension *height_return)
16137a84e134Smrg{
16147a84e134Smrg    SimpleMenuWidget xaw = (SimpleMenuWidget)w;
16157a84e134Smrg    Widget kid;
16167a84e134Smrg    Cardinal i;
16177a84e134Smrg    int width_kid, height_kid;
16187a84e134Smrg    int width, height, tmp_w, tmp_h, max_dim;
16197a84e134Smrg    short vadd, hadd;
16207a84e134Smrg    int n, columns, test_h, num_children = 0;
16217a84e134Smrg    Boolean try_layout = False;
16227a84e134Smrg
16237a84e134Smrg#ifndef OLDXAW
16245ec34c4cSmrg    hadd = (short)(xaw->simple_menu.left_margin + xaw->simple_menu.right_margin);
16257a84e134Smrg#else
16267a84e134Smrg    hadd = 0;
16277a84e134Smrg#endif
16285ec34c4cSmrg    vadd = (short)(xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin);
16297a84e134Smrg    if (xaw->simple_menu.label)
16305ec34c4cSmrg	vadd = (short)(vadd + XtHeight(xaw->simple_menu.label));
16317a84e134Smrg
16327a84e134Smrg    if (*height_return)
16337a84e134Smrg	max_dim = *height_return;
16347a84e134Smrg    else if (!XtHeight(w)) {
16357a84e134Smrg	max_dim = HeightOfScreen(XtScreen(w));
16367a84e134Smrg	try_layout = True;
16377a84e134Smrg    }
16387a84e134Smrg    else
16397a84e134Smrg	max_dim = XtHeight(w);
16407a84e134Smrg    max_dim -= vadd;
16417a84e134Smrg
16427a84e134Smrg    width = height = tmp_w = tmp_h = n = test_h = 0;
16437a84e134Smrg    columns = 1;
16447a84e134Smrg    for (i = xaw->simple_menu.label ? 1 : 0;
16457a84e134Smrg	 i < xaw->composite.num_children;
16467a84e134Smrg	 i++) {
16477a84e134Smrg	kid = xaw->composite.children[i];
16487a84e134Smrg	if (!XtIsManaged(kid))
16497a84e134Smrg	    continue;
16507a84e134Smrg	++num_children;
16517a84e134Smrg	width_kid = XtWidth(kid);
16527a84e134Smrg	height_kid = XtHeight(kid);
16537a84e134Smrg
16547a84e134Smrg	if (try_layout) {
16557a84e134Smrg	    if (!test_h)
16567a84e134Smrg		test_h = height_kid;
16577a84e134Smrg	    else if (test_h != height_kid)
16587a84e134Smrg		try_layout = False;
16597a84e134Smrg	}
16607a84e134Smrg
16617a84e134Smrg	if (n && (height + height_kid > max_dim)) {
16627a84e134Smrg	    ++columns;
16637a84e134Smrg	    width += tmp_w;
16647a84e134Smrg	    tmp_w = width_kid;
16657a84e134Smrg	    height = height_kid;
16667a84e134Smrg	}
16677a84e134Smrg	else
16687a84e134Smrg	    height += height_kid;
16697a84e134Smrg	if (height > tmp_h)
16707a84e134Smrg	    tmp_h = height;
16717a84e134Smrg	if (width_kid > tmp_w)
16727a84e134Smrg	    tmp_w = width_kid;
16737a84e134Smrg	++n;
16747a84e134Smrg    }
16757a84e134Smrg
16767a84e134Smrg    height = tmp_h + vadd;
16777a84e134Smrg    width += tmp_w + hadd;
16787a84e134Smrg
16797a84e134Smrg    if (xaw->simple_menu.label)
16807a84e134Smrg	width = XawMax(width, XtWidth(xaw->simple_menu.label) + hadd);
16817a84e134Smrg
16825ec34c4cSmrg    *width_return = (Dimension)width;
16835ec34c4cSmrg    *height_return = (Dimension)height;
16847a84e134Smrg
16857a84e134Smrg    if (try_layout && columns > 1 && num_children > 2) {
16867a84e134Smrg	int space;
16877a84e134Smrg
16887a84e134Smrg	height = test_h * (xaw->simple_menu.label ?
16897a84e134Smrg			   num_children - 1 :
16907a84e134Smrg			   num_children);
16917a84e134Smrg
16927a84e134Smrg	max_dim -= max_dim % test_h;
16937a84e134Smrg	space = max_dim - (height % max_dim);
16947a84e134Smrg	if (space >= test_h * columns) {
16957a84e134Smrg	    height = max_dim - space / columns;
16967a84e134Smrg	    if (height % test_h)
16977a84e134Smrg		height += test_h - (height % test_h);
16985ec34c4cSmrg	    *height_return = (Dimension)(height + vadd);
16997a84e134Smrg	    CalculateNewSize(w, width_return, height_return);
17007a84e134Smrg	}
17017a84e134Smrg    }
17027a84e134Smrg}
17037a84e134Smrg
17047a84e134Smrgstatic void
17057a84e134SmrgMakeResizeRequest(Widget w)
17067a84e134Smrg{
17077a84e134Smrg    int tries;
17087a84e134Smrg    Dimension width, height;
1709421c997bSmrg
17107a84e134Smrg    width = XtWidth(w);
17117a84e134Smrg    height = XtHeight(w);
17127a84e134Smrg
17137a84e134Smrg    for (tries = 0; tries < 100; tries++) {
17147a84e134Smrg	CalculateNewSize(w, &width, &height);
17157a84e134Smrg	if (width == XtWidth(w) && height == XtHeight(w))
17167a84e134Smrg	    break;
17177a84e134Smrg	if (XtMakeResizeRequest(w, width, height, &width, &height) ==
17187a84e134Smrg	    XtGeometryNo)
17197a84e134Smrg	break;
17207a84e134Smrg    }
17217a84e134Smrg}
17227a84e134Smrg
17237a84e134Smrg#ifndef OLDXAW
17247a84e134Smrgstatic void
17257a84e134SmrgPopdown(Widget w, XEvent *event, String *params, Cardinal *num_params)
17267a84e134Smrg{
17277a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
17287a84e134Smrg
17297a84e134Smrg    while (XtParent(w) &&
17307a84e134Smrg	   XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) {
17317a84e134Smrg	if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) {
17327a84e134Smrg	    w = XtParent(w);
17337a84e134Smrg	    smw = (SimpleMenuWidget)w;
17347a84e134Smrg	    smw->simple_menu.entry_set = NULL;
17357a84e134Smrg	}
17367a84e134Smrg	else
17377a84e134Smrg	    break;
17387a84e134Smrg    }
17397a84e134Smrg
17407a84e134Smrg    smw->simple_menu.state |= SMW_UNMAPPING;
17417a84e134Smrg    if (smw->simple_menu.sub_menu)
17427a84e134Smrg	PopdownSubMenu(smw);
17437a84e134Smrg    XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params);
17447a84e134Smrg}
17457a84e134Smrg
17467a84e134Smrgstatic void
17477a84e134SmrgPopupSubMenu(SimpleMenuWidget smw)
17487a84e134Smrg{
17497a84e134Smrg    Arg args[2];
17507a84e134Smrg    Cardinal num_args;
17517a84e134Smrg    Widget menu;
17527a84e134Smrg    SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set;
17537a84e134Smrg    Position menu_x, menu_y;
17547a84e134Smrg    Bool popleft;
17557a84e134Smrg
17567a84e134Smrg    if (entry->sme_bsb.menu_name == NULL)
17577a84e134Smrg	return;
17587a84e134Smrg
17597a84e134Smrg    if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL)
17607a84e134Smrg	return;
17617a84e134Smrg
17627a84e134Smrg    smw->simple_menu.sub_menu = menu;
17637a84e134Smrg
17647a84e134Smrg    if (!XtIsRealized(menu))
17657a84e134Smrg	XtRealizeWidget(menu);
17667a84e134Smrg
17677a84e134Smrg    popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0;
17687a84e134Smrg
1769421c997bSmrg    if (popleft)
17705ec34c4cSmrg	XtTranslateCoords((Widget)smw,
17715ec34c4cSmrg			  (Position)(-(int)XtWidth(menu)),
17725ec34c4cSmrg			  (Position)(XtY(entry) - XtBorderWidth(menu)),
17735ec34c4cSmrg			  &menu_x, &menu_y);
17747a84e134Smrg    else
17755ec34c4cSmrg	XtTranslateCoords((Widget)smw,
17765ec34c4cSmrg			  (Position)XtWidth(smw),
17775ec34c4cSmrg			  (Position)(XtY(entry) - XtBorderWidth(menu)),
17785ec34c4cSmrg			  &menu_x, &menu_y);
17797a84e134Smrg
17807a84e134Smrg    if (!popleft && menu_x >= 0) {
17817a84e134Smrg	int scr_width = WidthOfScreen(XtScreen(menu));
17827a84e134Smrg
17837a84e134Smrg	if (menu_x + XtWidth(menu) > scr_width) {
17845ec34c4cSmrg	    menu_x = (Position)(menu_x - (XtWidth(menu) + XtWidth(smw)));
17857a84e134Smrg	    popleft = True;
17867a84e134Smrg	}
17877a84e134Smrg    }
17887a84e134Smrg    else if (popleft && menu_x < 0) {
17897a84e134Smrg	menu_x = 0;
17907a84e134Smrg	popleft = False;
17917a84e134Smrg    }
17927a84e134Smrg    if (menu_y >= 0) {
17937a84e134Smrg	int scr_height = HeightOfScreen(XtScreen(menu));
17947a84e134Smrg
17957a84e134Smrg	if (menu_y + XtHeight(menu) > scr_height)
17965ec34c4cSmrg	    menu_y = (Position)(scr_height - XtHeight(menu) - XtBorderWidth(menu));
17977a84e134Smrg    }
17987a84e134Smrg    if (menu_y < 0)
17997a84e134Smrg	menu_y = 0;
18007a84e134Smrg
18017a84e134Smrg    num_args = 0;
18027a84e134Smrg    XtSetArg(args[num_args], XtNx, menu_x);	num_args++;
18037a84e134Smrg    XtSetArg(args[num_args], XtNy, menu_y);	num_args++;
18047a84e134Smrg    XtSetValues(menu, args, num_args);
18057a84e134Smrg
18067a84e134Smrg    if (popleft)
18077a84e134Smrg	((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT;
18087a84e134Smrg    else
18095ec34c4cSmrg	((SimpleMenuWidget)menu)->simple_menu.state &= (unsigned char)(~SMW_POPLEFT);
18107a84e134Smrg
18117a84e134Smrg    XtPopup(menu, XtGrabNone);
18127a84e134Smrg}
18137a84e134Smrg
18147a84e134Smrgstatic void
18157a84e134SmrgPopdownSubMenu(SimpleMenuWidget smw)
18167a84e134Smrg{
18177a84e134Smrg    SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu;
18187a84e134Smrg
18197a84e134Smrg    if (!menu)
18207a84e134Smrg	return;
18217a84e134Smrg
18227a84e134Smrg    menu->simple_menu.state |= SMW_UNMAPPING;
18237a84e134Smrg    PopdownSubMenu(menu);
18247a84e134Smrg
18257a84e134Smrg    XtPopdown((Widget)menu);
18267a84e134Smrg
18277a84e134Smrg    smw->simple_menu.sub_menu = NULL;
18287a84e134Smrg}
18297a84e134Smrg
18307a84e134Smrg/*ARGSUSED*/
18317a84e134Smrgstatic void
18325ec34c4cSmrgPopupCB(Widget w, XtPointer client_data _X_UNUSED, XtPointer call_data _X_UNUSED)
18337a84e134Smrg{
18347a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
18357a84e134Smrg
18365ec34c4cSmrg    smw->simple_menu.state &= (unsigned char)(~(SMW_UNMAPPING | SMW_POPLEFT));
18377a84e134Smrg}
18387a84e134Smrg#endif /* OLDXAW */
1839