SimpleMenu.c revision 7a84e134
17a84e134Smrg/* $Xorg: SimpleMenu.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */
27a84e134Smrg
37a84e134Smrg/*
47a84e134SmrgCopyright 1989, 1994, 1998  The Open Group
57a84e134Smrg
67a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its
77a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that
87a84e134Smrgthe above copyright notice appear in all copies and that both that
97a84e134Smrgcopyright notice and this permission notice appear in supporting
107a84e134Smrgdocumentation.
117a84e134Smrg
127a84e134SmrgThe above copyright notice and this permission notice shall be included in
137a84e134Smrgall copies or substantial portions of the Software.
147a84e134Smrg
157a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
187a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
197a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
207a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
217a84e134Smrg
227a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be
237a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings
247a84e134Smrgin this Software without prior written authorization from The Open Group.
257a84e134Smrg */
267a84e134Smrg
277a84e134Smrg/* $XFree86: xc/lib/Xaw/SimpleMenu.c,v 3.21 2001/03/23 23:59:15 paulo Exp $ */
287a84e134Smrg
297a84e134Smrg/*
307a84e134Smrg * SimpleMenu.c - Source code file for SimpleMenu widget.
317a84e134Smrg *
327a84e134Smrg * Date:    April 3, 1989
337a84e134Smrg *
347a84e134Smrg * By:      Chris D. Peterson
357a84e134Smrg *          MIT X Consortium
367a84e134Smrg *          kit@expo.lcs.mit.edu
377a84e134Smrg */
387a84e134Smrg
397a84e134Smrg#ifdef HAVE_CONFIG_H
407a84e134Smrg#include <config.h>
417a84e134Smrg#endif
427a84e134Smrg#include <stdio.h>
437a84e134Smrg#include <X11/IntrinsicP.h>
447a84e134Smrg#include <X11/StringDefs.h>
457a84e134Smrg#include <X11/Xmu/Initer.h>
467a84e134Smrg#include <X11/Xmu/SysUtil.h>
477a84e134Smrg#include <X11/Xaw/Cardinals.h>
487a84e134Smrg#include <X11/Xaw/SimpleMenP.h>
497a84e134Smrg#include <X11/Xaw/SmeBSBP.h>
507a84e134Smrg#include <X11/Xaw/XawInit.h>
517a84e134Smrg#include "Private.h"
527a84e134Smrg
537a84e134Smrg#define streq(a, b)	(strcmp((a), (b)) == 0)
547a84e134Smrg
557a84e134Smrg#define ForAllChildren(smw, childP)				\
567a84e134Smrgfor ((childP) = (SmeObject *)(smw)->composite.children;		\
577a84e134Smrg     (childP) < (SmeObject *)((smw)->composite.children		\
587a84e134Smrg			      + (smw)->composite.num_children);	\
597a84e134Smrg     (childP)++)
607a84e134Smrg
617a84e134Smrg#ifndef OLDXAW
627a84e134Smrg#define	SMW_UNMAPPING	0x01
637a84e134Smrg#define SMW_POPLEFT	0x02
647a84e134Smrg#endif
657a84e134Smrg
667a84e134Smrg/*
677a84e134Smrg * Class Methods
687a84e134Smrg */
697a84e134Smrgstatic void XawSimpleMenuChangeManaged(Widget);
707a84e134Smrgstatic void XawSimpleMenuClassInitialize(void);
717a84e134Smrgstatic void XawSimpleMenuClassPartInitialize(WidgetClass);
727a84e134Smrgstatic XtGeometryResult XawSimpleMenuGeometryManager(Widget, XtWidgetGeometry*,
737a84e134Smrg						     XtWidgetGeometry*);
747a84e134Smrgstatic void XawSimpleMenuInitialize(Widget, Widget, ArgList, Cardinal*);
757a84e134Smrgstatic void XawSimpleMenuRealize(Widget, XtValueMask*, XSetWindowAttributes*);
767a84e134Smrgstatic void XawSimpleMenuRedisplay(Widget, XEvent*, Region);
777a84e134Smrgstatic void XawSimpleMenuResize(Widget);
787a84e134Smrgstatic Boolean XawSimpleMenuSetValues(Widget, Widget, Widget,
797a84e134Smrg				      ArgList, Cardinal*);
807a84e134Smrgstatic Boolean XawSimpleMenuSetValuesHook(Widget, ArgList, Cardinal*);
817a84e134Smrg#ifndef OLDXAW
827a84e134Smrgstatic void PopupSubMenu(SimpleMenuWidget);
837a84e134Smrgstatic void PopdownSubMenu(SimpleMenuWidget);
847a84e134Smrgstatic void PopupCB(Widget, XtPointer, XtPointer);
857a84e134Smrg#endif
867a84e134Smrg
877a84e134Smrg/*
887a84e134Smrg * Prototypes
897a84e134Smrg */
907a84e134Smrgstatic void AddPositionAction(XtAppContext, XPointer);
917a84e134Smrgstatic void CalculateNewSize(Widget, Dimension*, Dimension*);
927a84e134Smrgstatic void ChangeCursorOnGrab(Widget, XtPointer, XtPointer);
937a84e134Smrgstatic void CreateLabel(Widget);
947a84e134Smrgstatic SmeObject DoGetEventEntry(Widget, int, int);
957a84e134Smrgstatic Widget FindMenu(Widget, String);
967a84e134Smrgstatic SmeObject GetEventEntry(Widget, XEvent*);
977a84e134Smrgstatic void Layout(Widget, Dimension*, Dimension*);
987a84e134Smrgstatic void MakeResizeRequest(Widget);
997a84e134Smrgstatic void MakeSetValuesRequest(Widget, unsigned int, unsigned int);
1007a84e134Smrgstatic void MoveMenu(Widget, int, int);
1017a84e134Smrgstatic void PositionMenu(Widget, XPoint*);
1027a84e134Smrg
1037a84e134Smrg/*
1047a84e134Smrg * Actions
1057a84e134Smrg */
1067a84e134Smrgstatic void Highlight(Widget, XEvent*, String*, Cardinal*);
1077a84e134Smrgstatic void Notify(Widget, XEvent*, String*, Cardinal*);
1087a84e134Smrg#ifndef OLDXAW
1097a84e134Smrgstatic void Popdown(Widget, XEvent*, String*, Cardinal*);
1107a84e134Smrg#endif
1117a84e134Smrgstatic void PositionMenuAction(Widget, XEvent*, String*, Cardinal*);
1127a84e134Smrgstatic void Unhighlight(Widget, XEvent*, String*, Cardinal*);
1137a84e134Smrg
1147a84e134Smrg/*
1157a84e134Smrg * Initialization
1167a84e134Smrg */
1177a84e134Smrg#define offset(field)	XtOffsetOf(SimpleMenuRec, simple_menu.field)
1187a84e134Smrg
1197a84e134Smrgstatic XtResource resources[] = {
1207a84e134Smrg  /* label */
1217a84e134Smrg  {
1227a84e134Smrg    XtNlabel,
1237a84e134Smrg    XtCLabel,
1247a84e134Smrg    XtRString,
1257a84e134Smrg    sizeof(String),
1267a84e134Smrg    offset(label_string),
1277a84e134Smrg    XtRString,
1287a84e134Smrg    NULL
1297a84e134Smrg  },
1307a84e134Smrg  {
1317a84e134Smrg    XtNlabelClass,
1327a84e134Smrg    XtCLabelClass,
1337a84e134Smrg    XtRPointer,
1347a84e134Smrg    sizeof(WidgetClass),
1357a84e134Smrg    offset(label_class),
1367a84e134Smrg    XtRImmediate,
1377a84e134Smrg    NULL
1387a84e134Smrg  },
1397a84e134Smrg
1407a84e134Smrg  /* layout */
1417a84e134Smrg  {
1427a84e134Smrg    XtNrowHeight,
1437a84e134Smrg    XtCRowHeight,
1447a84e134Smrg    XtRDimension,
1457a84e134Smrg    sizeof(Dimension),
1467a84e134Smrg    offset(row_height),
1477a84e134Smrg    XtRImmediate,
1487a84e134Smrg    (XtPointer)0
1497a84e134Smrg  },
1507a84e134Smrg  {
1517a84e134Smrg    XtNtopMargin,
1527a84e134Smrg    XtCVerticalMargins,
1537a84e134Smrg    XtRDimension,
1547a84e134Smrg    sizeof(Dimension),
1557a84e134Smrg    offset(top_margin),
1567a84e134Smrg    XtRImmediate,
1577a84e134Smrg    (XtPointer)0
1587a84e134Smrg  },
1597a84e134Smrg  {
1607a84e134Smrg    XtNbottomMargin,
1617a84e134Smrg    XtCVerticalMargins,
1627a84e134Smrg    XtRDimension,
1637a84e134Smrg    sizeof(Dimension),
1647a84e134Smrg    offset(bottom_margin),
1657a84e134Smrg    XtRImmediate,
1667a84e134Smrg    (XtPointer)0
1677a84e134Smrg  },
1687a84e134Smrg#ifndef OLDXAW
1697a84e134Smrg  {
1707a84e134Smrg    XtNleftMargin,
1717a84e134Smrg    XtCHorizontalMargins,
1727a84e134Smrg    XtRDimension,
1737a84e134Smrg    sizeof(Dimension),
1747a84e134Smrg    offset(left_margin),
1757a84e134Smrg    XtRImmediate,
1767a84e134Smrg    (XtPointer)0
1777a84e134Smrg  },
1787a84e134Smrg  {
1797a84e134Smrg    XtNrightMargin,
1807a84e134Smrg    XtCHorizontalMargins,
1817a84e134Smrg    XtRDimension,
1827a84e134Smrg    sizeof(Dimension),
1837a84e134Smrg    offset(right_margin),
1847a84e134Smrg    XtRImmediate,
1857a84e134Smrg    (XtPointer)0
1867a84e134Smrg  },
1877a84e134Smrg#endif
1887a84e134Smrg
1897a84e134Smrg  /* misc */
1907a84e134Smrg  {
1917a84e134Smrg    XtNallowShellResize,
1927a84e134Smrg    XtCAllowShellResize,
1937a84e134Smrg    XtRBoolean,
1947a84e134Smrg    sizeof(Boolean),
1957a84e134Smrg    XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize),
1967a84e134Smrg    XtRImmediate,
1977a84e134Smrg    (XtPointer)True
1987a84e134Smrg  },
1997a84e134Smrg  {
2007a84e134Smrg    XtNcursor,
2017a84e134Smrg    XtCCursor,
2027a84e134Smrg    XtRCursor,
2037a84e134Smrg    sizeof(Cursor),
2047a84e134Smrg    offset(cursor),
2057a84e134Smrg    XtRImmediate,
2067a84e134Smrg    (XtPointer)None
2077a84e134Smrg  },
2087a84e134Smrg  {
2097a84e134Smrg    XtNmenuOnScreen,
2107a84e134Smrg    XtCMenuOnScreen,
2117a84e134Smrg    XtRBoolean,
2127a84e134Smrg    sizeof(Boolean),
2137a84e134Smrg    offset(menu_on_screen),
2147a84e134Smrg    XtRImmediate,
2157a84e134Smrg    (XtPointer)True
2167a84e134Smrg  },
2177a84e134Smrg  {
2187a84e134Smrg    XtNpopupOnEntry,
2197a84e134Smrg    XtCPopupOnEntry,
2207a84e134Smrg    XtRWidget,
2217a84e134Smrg    sizeof(Widget),
2227a84e134Smrg    offset(popup_entry),
2237a84e134Smrg    XtRWidget,
2247a84e134Smrg    NULL
2257a84e134Smrg  },
2267a84e134Smrg  {
2277a84e134Smrg    XtNbackingStore,
2287a84e134Smrg    XtCBackingStore,
2297a84e134Smrg    XtRBackingStore,
2307a84e134Smrg    sizeof(int),
2317a84e134Smrg    offset(backing_store),
2327a84e134Smrg    XtRImmediate,
2337a84e134Smrg    (XtPointer)(Always + WhenMapped + NotUseful)
2347a84e134Smrg  },
2357a84e134Smrg#ifndef OLDXAW
2367a84e134Smrg  {
2377a84e134Smrg    XawNdisplayList,
2387a84e134Smrg    XawCDisplayList,
2397a84e134Smrg    XawRDisplayList,
2407a84e134Smrg    sizeof(XawDisplayList*),
2417a84e134Smrg    offset(display_list),
2427a84e134Smrg    XtRImmediate,
2437a84e134Smrg    NULL
2447a84e134Smrg  },
2457a84e134Smrg#endif
2467a84e134Smrg};
2477a84e134Smrg#undef offset
2487a84e134Smrg
2497a84e134Smrgstatic char defaultTranslations[] =
2507a84e134Smrg"<Enter>:"	"highlight()\n"
2517a84e134Smrg"<Leave>:"	"unhighlight()\n"
2527a84e134Smrg"<BtnMotion>:"	"highlight()\n"
2537a84e134Smrg#ifndef OLDXAW
2547a84e134Smrg"<BtnUp>:"	"popdown() notify() unhighlight()\n"
2557a84e134Smrg#else
2567a84e134Smrg"<BtnUp>:"	"MenuPopdown() notify() unhighlight()\n"
2577a84e134Smrg#endif
2587a84e134Smrg;
2597a84e134Smrg
2607a84e134Smrgstatic XtActionsRec actionsList[] =
2617a84e134Smrg{
2627a84e134Smrg  {"notify",            Notify},
2637a84e134Smrg  {"highlight",         Highlight},
2647a84e134Smrg  {"unhighlight",       Unhighlight},
2657a84e134Smrg#ifndef OLDXAW
2667a84e134Smrg  {"popdown",		Popdown},
2677a84e134Smrg  {"set-values",	XawSetValuesAction},
2687a84e134Smrg  {"get-values",	XawGetValuesAction},
2697a84e134Smrg  {"declare",		XawDeclareAction},
2707a84e134Smrg  {"call-proc",		XawCallProcAction},
2717a84e134Smrg#endif
2727a84e134Smrg};
2737a84e134Smrg
2747a84e134Smrgstatic CompositeClassExtensionRec extension_rec = {
2757a84e134Smrg  NULL,					/* next_extension */
2767a84e134Smrg  NULLQUARK,				/* record_type */
2777a84e134Smrg  XtCompositeExtensionVersion,		/* version */
2787a84e134Smrg  sizeof(CompositeClassExtensionRec),	/* record_size */
2797a84e134Smrg  True,					/* accepts_objects */
2807a84e134Smrg};
2817a84e134Smrg
2827a84e134Smrg#define Superclass	(&overrideShellClassRec)
2837a84e134SmrgSimpleMenuClassRec simpleMenuClassRec = {
2847a84e134Smrg  /* core */
2857a84e134Smrg  {
2867a84e134Smrg    (WidgetClass)Superclass,		/* superclass */
2877a84e134Smrg    "SimpleMenu",			/* class_name */
2887a84e134Smrg    sizeof(SimpleMenuRec),		/* size */
2897a84e134Smrg    XawSimpleMenuClassInitialize,	/* class_initialize */
2907a84e134Smrg    XawSimpleMenuClassPartInitialize,	/* class_part_initialize */
2917a84e134Smrg    False,				/* class_inited */
2927a84e134Smrg    XawSimpleMenuInitialize,		/* initialize */
2937a84e134Smrg    NULL,				/* initialize_hook */
2947a84e134Smrg    XawSimpleMenuRealize,		/* realize */
2957a84e134Smrg    actionsList,			/* actions */
2967a84e134Smrg    XtNumber(actionsList),		/* num_actions */
2977a84e134Smrg    resources,				/* resources */
2987a84e134Smrg    XtNumber(resources),		/* num_resources */
2997a84e134Smrg    NULLQUARK,				/* xrm_class */
3007a84e134Smrg    True,				/* compress_motion */
3017a84e134Smrg    True,				/* compress_exposure */
3027a84e134Smrg    True,				/* compress_enterleave */
3037a84e134Smrg    False,				/* visible_interest */
3047a84e134Smrg    NULL,				/* destroy */
3057a84e134Smrg    XawSimpleMenuResize,		/* resize */
3067a84e134Smrg    XawSimpleMenuRedisplay,		/* expose */
3077a84e134Smrg    XawSimpleMenuSetValues,		/* set_values */
3087a84e134Smrg    XawSimpleMenuSetValuesHook,		/* set_values_hook */
3097a84e134Smrg    XtInheritSetValuesAlmost,		/* set_values_almost */
3107a84e134Smrg    NULL,				/* get_values_hook */
3117a84e134Smrg    NULL,				/* accept_focus */
3127a84e134Smrg    XtVersion,				/* intrinsics version */
3137a84e134Smrg    NULL,				/* callback offsets */
3147a84e134Smrg    defaultTranslations,		/* tm_table */
3157a84e134Smrg    NULL,				/* query_geometry */
3167a84e134Smrg    NULL,				/* display_accelerator */
3177a84e134Smrg    NULL,				/* extension */
3187a84e134Smrg  },
3197a84e134Smrg  /* composite */
3207a84e134Smrg  {
3217a84e134Smrg    XawSimpleMenuGeometryManager,	/* geometry_manager */
3227a84e134Smrg    XawSimpleMenuChangeManaged,		/* change_managed */
3237a84e134Smrg    XtInheritInsertChild,		/* insert_child */
3247a84e134Smrg    XtInheritDeleteChild,		/* delete_child */
3257a84e134Smrg    NULL,				/* extension */
3267a84e134Smrg  },
3277a84e134Smrg  /* shell */
3287a84e134Smrg  {
3297a84e134Smrg    NULL,				/* extension */
3307a84e134Smrg  },
3317a84e134Smrg  /* override */
3327a84e134Smrg  {
3337a84e134Smrg    NULL,				/* extension */
3347a84e134Smrg  },
3357a84e134Smrg  /* simple_menu */
3367a84e134Smrg  {
3377a84e134Smrg    NULL,				/* extension */
3387a84e134Smrg  },
3397a84e134Smrg};
3407a84e134Smrg
3417a84e134SmrgWidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
3427a84e134Smrg
3437a84e134Smrg/*
3447a84e134Smrg * Implementation
3457a84e134Smrg */
3467a84e134Smrg/*
3477a84e134Smrg * Function:
3487a84e134Smrg *	XawSimpleMenuClassInitialize
3497a84e134Smrg *
3507a84e134Smrg * Description:
3517a84e134Smrg *	Class Initialize routine, called only once.
3527a84e134Smrg */
3537a84e134Smrgstatic void
3547a84e134SmrgXawSimpleMenuClassInitialize(void)
3557a84e134Smrg{
3567a84e134Smrg    XawInitializeWidgetSet();
3577a84e134Smrg    XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
3587a84e134Smrg		   NULL, 0);
3597a84e134Smrg    XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
3607a84e134Smrg		       NULL, 0, XtCacheNone, NULL);
3617a84e134Smrg    XmuAddInitializer(AddPositionAction, NULL);
3627a84e134Smrg}
3637a84e134Smrg
3647a84e134Smrg/*
3657a84e134Smrg * Function:
3667a84e134Smrg *	XawSimpleMenuClassPartInitialize
3677a84e134Smrg *      Arguments: wc - the widget class of the subclass.
3687a84e134Smrg *
3697a84e134Smrg * Description:
3707a84e134Smrg *	  Class Part Initialize routine, called for every subclass.  Makes
3717a84e134Smrg *	sure that the subclasses pick up the extension record.
3727a84e134Smrg */
3737a84e134Smrgstatic void
3747a84e134SmrgXawSimpleMenuClassPartInitialize(WidgetClass wc)
3757a84e134Smrg{
3767a84e134Smrg    SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc;
3777a84e134Smrg
3787a84e134Smrg    /*
3797a84e134Smrg     * Make sure that our subclass gets the extension rec too
3807a84e134Smrg     */
3817a84e134Smrg    extension_rec.next_extension = smwc->composite_class.extension;
3827a84e134Smrg    smwc->composite_class.extension = (XtPointer) &extension_rec;
3837a84e134Smrg}
3847a84e134Smrg
3857a84e134Smrg/*
3867a84e134Smrg *  Function:
3877a84e134Smrg *	XawSimpleMenuInitialize
3887a84e134Smrg *
3897a84e134Smrg * Parameters:
3907a84e134Smrg *	request - widget requested by the argument list
3917a84e134Smrg *	cnew	- new widget with both resource and non resource values
3927a84e134Smrg *
3937a84e134Smrg * Description:
3947a84e134Smrg *	Initializes the simple menu widget.
3957a84e134Smrg */
3967a84e134Smrg/*ARGSUSED*/
3977a84e134Smrgstatic void
3987a84e134SmrgXawSimpleMenuInitialize(Widget request, Widget cnew,
3997a84e134Smrg			ArgList args, Cardinal *num_args)
4007a84e134Smrg{
4017a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)cnew;
4027a84e134Smrg    Dimension width, height;
4037a84e134Smrg
4047a84e134Smrg    XmuCallInitializers(XtWidgetToApplicationContext(cnew));
4057a84e134Smrg
4067a84e134Smrg    if (smw->simple_menu.label_class == NULL)
4077a84e134Smrg	smw->simple_menu.label_class = smeBSBObjectClass;
4087a84e134Smrg
4097a84e134Smrg    smw->simple_menu.label = NULL;
4107a84e134Smrg    smw->simple_menu.entry_set = NULL;
4117a84e134Smrg    smw->simple_menu.recursive_set_values = False;
4127a84e134Smrg#ifndef OLDXAW
4137a84e134Smrg    smw->simple_menu.sub_menu = NULL;
4147a84e134Smrg    smw->simple_menu.state = 0;
4157a84e134Smrg
4167a84e134Smrg    XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL);
4177a84e134Smrg#endif
4187a84e134Smrg
4197a84e134Smrg    if (smw->simple_menu.label_string != NULL)
4207a84e134Smrg	CreateLabel(cnew);
4217a84e134Smrg
4227a84e134Smrg    width = height = 0;
4237a84e134Smrg    CalculateNewSize(cnew, &width, &height);
4247a84e134Smrg
4257a84e134Smrg    smw->simple_menu.menu_width = True;
4267a84e134Smrg
4277a84e134Smrg    if (XtWidth(smw) == 0) {
4287a84e134Smrg	smw->simple_menu.menu_width = False;
4297a84e134Smrg	XtWidth(smw) = width;
4307a84e134Smrg    }
4317a84e134Smrg
4327a84e134Smrg    smw->simple_menu.menu_height = True;
4337a84e134Smrg
4347a84e134Smrg    if (XtHeight(smw) == 0) {
4357a84e134Smrg	smw->simple_menu.menu_height = False;
4367a84e134Smrg	XtHeight(smw) = height;
4377a84e134Smrg    }
4387a84e134Smrg
4397a84e134Smrg    /*
4407a84e134Smrg     * Add a popup_callback routine for changing the cursor
4417a84e134Smrg     */
4427a84e134Smrg    XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL);
4437a84e134Smrg}
4447a84e134Smrg
4457a84e134Smrg/*
4467a84e134Smrg * Function:
4477a84e134Smrg *	XawSimpleMenuRedisplay
4487a84e134Smrg *
4497a84e134Smrg * Parameters:
4507a84e134Smrg *	w      - simple menu widget
4517a84e134Smrg *	event  - X event that caused this redisplay
4527a84e134Smrg *	region - region the needs to be repainted
4537a84e134Smrg *
4547a84e134Smrg * Description:
4557a84e134Smrg *	Redisplays the contents of the widget.
4567a84e134Smrg */
4577a84e134Smrg/*ARGSUSED*/
4587a84e134Smrgstatic void
4597a84e134SmrgXawSimpleMenuRedisplay(Widget w, XEvent *event, Region region)
4607a84e134Smrg{
4617a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
4627a84e134Smrg    SmeObject *entry;
4637a84e134Smrg    SmeObjectClass cclass;
4647a84e134Smrg
4657a84e134Smrg    if (region == NULL)
4667a84e134Smrg	XClearWindow(XtDisplay(w), XtWindow(w));
4677a84e134Smrg
4687a84e134Smrg#ifndef OLDXAW
4697a84e134Smrg    if (smw->simple_menu.display_list)
4707a84e134Smrg      XawRunDisplayList(w, smw->simple_menu.display_list, event, region);
4717a84e134Smrg#endif
4727a84e134Smrg
4737a84e134Smrg    /*
4747a84e134Smrg     * Check and Paint each of the entries - including the label
4757a84e134Smrg     */
4767a84e134Smrg    ForAllChildren(smw, entry) {
4777a84e134Smrg	if (!XtIsManaged((Widget)*entry))
4787a84e134Smrg	    continue;
4797a84e134Smrg
4807a84e134Smrg	if (region != NULL)
4817a84e134Smrg	    switch(XRectInRegion(region, XtX(*entry),XtY(*entry),
4827a84e134Smrg				 XtWidth(*entry), XtHeight(*entry))) {
4837a84e134Smrg		case RectangleIn:
4847a84e134Smrg		case RectanglePart:
4857a84e134Smrg		    break;
4867a84e134Smrg		default:
4877a84e134Smrg		    continue;
4887a84e134Smrg	    }
4897a84e134Smrg
4907a84e134Smrg	cclass = (SmeObjectClass)(*entry)->object.widget_class;
4917a84e134Smrg
4927a84e134Smrg	if (cclass->rect_class.expose != NULL)
4937a84e134Smrg	    (cclass->rect_class.expose)((Widget)*entry, NULL, NULL);
4947a84e134Smrg    }
4957a84e134Smrg}
4967a84e134Smrg
4977a84e134Smrg/*
4987a84e134Smrg * Function:
4997a84e134Smrg *	XawSimpleMenuRealize
5007a84e134Smrg *
5017a84e134Smrg * Parameters:
5027a84e134Smrg *	w     - simple menu widget
5037a84e134Smrg *	mask  - value mask for the window to create
5047a84e134Smrg *	attrs - attributes for the window to create
5057a84e134Smrg *
5067a84e134Smrg * Description:
5077a84e134Smrg *	Realizes the widget.
5087a84e134Smrg */
5097a84e134Smrgstatic void
5107a84e134SmrgXawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs)
5117a84e134Smrg{
5127a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
5137a84e134Smrg#ifndef OLDXAW
5147a84e134Smrg    XawPixmap *pixmap;
5157a84e134Smrg#endif
5167a84e134Smrg
5177a84e134Smrg    attrs->cursor = smw->simple_menu.cursor;
5187a84e134Smrg    *mask |= CWCursor;
5197a84e134Smrg    if (smw->simple_menu.backing_store == Always ||
5207a84e134Smrg	smw->simple_menu.backing_store == NotUseful ||
5217a84e134Smrg	smw->simple_menu.backing_store == WhenMapped) {
5227a84e134Smrg	*mask |= CWBackingStore;
5237a84e134Smrg	attrs->backing_store = smw->simple_menu.backing_store;
5247a84e134Smrg    }
5257a84e134Smrg    else
5267a84e134Smrg	*mask &= ~CWBackingStore;
5277a84e134Smrg
5287a84e134Smrg    (*Superclass->core_class.realize)(w, mask, attrs);
5297a84e134Smrg
5307a84e134Smrg#ifndef OLDXAW
5317a84e134Smrg    if (w->core.background_pixmap > XtUnspecifiedPixmap) {
5327a84e134Smrg	pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
5337a84e134Smrg				      w->core.colormap, w->core.depth);
5347a84e134Smrg	if (pixmap && pixmap->mask)
5357a84e134Smrg	    XawReshapeWidget(w, pixmap);
5367a84e134Smrg    }
5377a84e134Smrg#endif
5387a84e134Smrg}
5397a84e134Smrg
5407a84e134Smrg/*
5417a84e134Smrg * Function:
5427a84e134Smrg *	XawSimpleMenuResize
5437a84e134Smrg *
5447a84e134Smrg * Parameters:
5457a84e134Smrg *	w - simple menu widget
5467a84e134Smrg *
5477a84e134Smrg * Description:
5487a84e134Smrg *	Handle the menu being resized.
5497a84e134Smrg */
5507a84e134Smrgstatic void
5517a84e134SmrgXawSimpleMenuResize(Widget w)
5527a84e134Smrg{
5537a84e134Smrg    if (!XtIsRealized(w))
5547a84e134Smrg	return;
5557a84e134Smrg
5567a84e134Smrg    Layout(w, NULL, NULL);
5577a84e134Smrg
5587a84e134Smrg    XawSimpleMenuRedisplay(w, NULL, NULL);
5597a84e134Smrg}
5607a84e134Smrg
5617a84e134Smrg/*
5627a84e134Smrg * Function:
5637a84e134Smrg *	XawSimpleMenuSetValues
5647a84e134Smrg *
5657a84e134Smrg * Parameters:
5667a84e134Smrg *	current - current state of the widget
5677a84e134Smrg *	request - what was requested
5687a84e134Smrg *	cnew    - what the widget will become
5697a84e134Smrg *
5707a84e134Smrg * Description:
5717a84e134Smrg *	Relayout the menu when one of the resources is changed.
5727a84e134Smrg */
5737a84e134Smrg/*ARGSUSED*/
5747a84e134Smrgstatic Boolean
5757a84e134SmrgXawSimpleMenuSetValues(Widget current, Widget request, Widget cnew,
5767a84e134Smrg		       ArgList args, Cardinal *num_args)
5777a84e134Smrg{
5787a84e134Smrg    SimpleMenuWidget smw_old = (SimpleMenuWidget)current;
5797a84e134Smrg    SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew;
5807a84e134Smrg    Boolean ret_val = False, layout = False;
5817a84e134Smrg
5827a84e134Smrg    if (!XtIsRealized(current))
5837a84e134Smrg	return (False);
5847a84e134Smrg
5857a84e134Smrg    if (!smw_new->simple_menu.recursive_set_values) {
5867a84e134Smrg	if (XtWidth(smw_new) != XtWidth(smw_old)) {
5877a84e134Smrg	    smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0;
5887a84e134Smrg	    layout = True;
5897a84e134Smrg	}
5907a84e134Smrg	if (XtHeight(smw_new) != XtHeight(smw_old)) {
5917a84e134Smrg	    smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0;
5927a84e134Smrg	    layout = True;
5937a84e134Smrg	}
5947a84e134Smrg    }
5957a84e134Smrg
5967a84e134Smrg    if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
5977a84e134Smrg	XDefineCursor(XtDisplay(cnew), XtWindow(cnew),
5987a84e134Smrg		      smw_new->simple_menu.cursor);
5997a84e134Smrg
6007a84e134Smrg    if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) {
6017a84e134Smrg	if (smw_new->simple_menu.label_string == NULL)	    /* Destroy */
6027a84e134Smrg	    XtDestroyWidget((Widget)smw_old->simple_menu.label);
6037a84e134Smrg	else if (smw_old->simple_menu.label_string == NULL) /* Create */
6047a84e134Smrg	    CreateLabel(cnew);
6057a84e134Smrg	else {						    /* Change */
6067a84e134Smrg	    Arg arglist[1];
6077a84e134Smrg
6087a84e134Smrg	    XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string);
6097a84e134Smrg	    XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE);
6107a84e134Smrg	}
6117a84e134Smrg    }
6127a84e134Smrg
6137a84e134Smrg    if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
6147a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(cnew),
6157a84e134Smrg		     "No Dynamic class change of the SimpleMenu Label.");
6167a84e134Smrg
6177a84e134Smrg    if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin
6187a84e134Smrg	|| smw_old->simple_menu.bottom_margin
6197a84e134Smrg	!= smw_new->simple_menu.bottom_margin) {
6207a84e134Smrg	layout = True;
6217a84e134Smrg	ret_val = True;
6227a84e134Smrg    }
6237a84e134Smrg
6247a84e134Smrg#ifndef OLDXAW
6257a84e134Smrg    if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) {
6267a84e134Smrg	XawPixmap *opix, *npix;
6277a84e134Smrg
6287a84e134Smrg	opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap,
6297a84e134Smrg				    XtScreen(smw_old), smw_old->core.colormap,
6307a84e134Smrg				    smw_old->core.depth);
6317a84e134Smrg	npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap,
6327a84e134Smrg				    XtScreen(smw_new), smw_new->core.colormap,
6337a84e134Smrg				    smw_new->core.depth);
6347a84e134Smrg	if ((npix && npix->mask) || (opix && opix->mask))
6357a84e134Smrg	    XawReshapeWidget(cnew, npix);
6367a84e134Smrg    }
6377a84e134Smrg#endif
6387a84e134Smrg
6397a84e134Smrg    if (layout)
6407a84e134Smrg	Layout(cnew, NULL, NULL);
6417a84e134Smrg
6427a84e134Smrg    return (ret_val);
6437a84e134Smrg}
6447a84e134Smrg
6457a84e134Smrg/*
6467a84e134Smrg * Function:
6477a84e134Smrg *	XawSimpleMenuSetValuesHook
6487a84e134Smrg *
6497a84e134Smrg * Parameters:
6507a84e134Smrg *	w	 - menu widget
6517a84e134Smrg *	arglist	 - argument list passed to XtSetValues
6527a84e134Smrg *	num_args - number of args
6537a84e134Smrg *
6547a84e134Smrg * Description:
6557a84e134Smrg *	To handle a special case, this is passed the actual arguments.
6567a84e134Smrg */
6577a84e134Smrgstatic Boolean
6587a84e134SmrgXawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args)
6597a84e134Smrg{
6607a84e134Smrg    Cardinal i;
6617a84e134Smrg    Dimension width, height;
6627a84e134Smrg
6637a84e134Smrg    width = XtWidth(w);
6647a84e134Smrg    height = XtHeight(w);
6657a84e134Smrg
6667a84e134Smrg    for (i = 0 ; i < *num_args ; i++) {
6677a84e134Smrg	if (streq(arglist[i].name, XtNwidth))
6687a84e134Smrg	    width = (Dimension)arglist[i].value;
6697a84e134Smrg	if (streq(arglist[i].name, XtNheight))
6707a84e134Smrg	    height = (Dimension) arglist[i].value;
6717a84e134Smrg    }
6727a84e134Smrg
6737a84e134Smrg    if (width != XtWidth(w) || height != XtHeight(w))
6747a84e134Smrg	MakeSetValuesRequest(w, width, height);
6757a84e134Smrg
6767a84e134Smrg    return (False);
6777a84e134Smrg}
6787a84e134Smrg
6797a84e134Smrg/*
6807a84e134Smrg * Geometry Management routines
6817a84e134Smrg */
6827a84e134Smrg/*
6837a84e134Smrg * Function:
6847a84e134Smrg *	XawSimpleMenuGeometryManager
6857a84e134Smrg *
6867a84e134Smrg * Parameters:
6877a84e134Smrg *	w	- Menu Entry making the request
6887a84e134Smrg *	request - requested new geometry
6897a84e134Smrg *                 reply - the allowed geometry.
6907a84e134Smrg *
6917a84e134Smrg * Description:
6927a84e134Smrg *	This is the SimpleMenu Widget's Geometry Manager.
6937a84e134Smrg *
6947a84e134Smrg * Returns:
6957a84e134Smrg *	XtGeometry{Yes, No, Almost}
6967a84e134Smrg */
6977a84e134Smrgstatic XtGeometryResult
6987a84e134SmrgXawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request,
6997a84e134Smrg			     XtWidgetGeometry *reply)
7007a84e134Smrg{
7017a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w);
7027a84e134Smrg    SmeObject entry = (SmeObject)w;
7037a84e134Smrg    XtGeometryMask mode = request->request_mode;
7047a84e134Smrg    XtGeometryResult answer;
7057a84e134Smrg    Dimension old_height, old_width;
7067a84e134Smrg
7077a84e134Smrg    if (!(mode & CWWidth) && !(mode & CWHeight))
7087a84e134Smrg	return (XtGeometryNo);
7097a84e134Smrg
7107a84e134Smrg    reply->width = request->width;
7117a84e134Smrg    reply->height = request->height;
7127a84e134Smrg
7137a84e134Smrg    old_width = XtWidth(entry);
7147a84e134Smrg    old_height = XtHeight(entry);
7157a84e134Smrg
7167a84e134Smrg    Layout(w, &reply->width, &reply->height);
7177a84e134Smrg
7187a84e134Smrg    /*
7197a84e134Smrg     * Since we are an override shell and have no parent there is no one to
7207a84e134Smrg     * ask to see if this geom change is okay, so I am just going to assume
7217a84e134Smrg     * we can do whatever we want.  If you subclass be very careful with this
7227a84e134Smrg     * assumption, it could bite you.
7237a84e134Smrg     *
7247a84e134Smrg     * Chris D. Peterson - Sept. 1989.
7257a84e134Smrg     */
7267a84e134Smrg    if ((!(mode & CWWidth) || reply->width == request->width)
7277a84e134Smrg	&& (!(mode & CWHeight) || reply->height == request->height)) {
7287a84e134Smrg	if (mode & XtCWQueryOnly) {	/* Actually perform the layout */
7297a84e134Smrg	    XtWidth(entry) = old_width;
7307a84e134Smrg	    XtHeight(entry) = old_height;
7317a84e134Smrg	}
7327a84e134Smrg	else
7337a84e134Smrg	    Layout((Widget)smw, NULL, NULL);
7347a84e134Smrg	answer = XtGeometryDone;
7357a84e134Smrg    }
7367a84e134Smrg    else {
7377a84e134Smrg	XtWidth(entry) = old_width;
7387a84e134Smrg	XtHeight(entry) = old_height;
7397a84e134Smrg
7407a84e134Smrg	if ((reply->width == request->width && !(mode & CWHeight))
7417a84e134Smrg	    || (reply->height == request->height && !(mode & CWWidth))
7427a84e134Smrg	    || (reply->width == request->width
7437a84e134Smrg	    && reply->height == request->height))
7447a84e134Smrg	    answer = XtGeometryNo;
7457a84e134Smrg	else {
7467a84e134Smrg	    answer = XtGeometryAlmost;
7477a84e134Smrg	    reply->request_mode = 0;
7487a84e134Smrg	    if (reply->width != request->width)
7497a84e134Smrg		reply->request_mode |= CWWidth;
7507a84e134Smrg	    if (reply->height != request->height)
7517a84e134Smrg		reply->request_mode |= CWHeight;
7527a84e134Smrg	}
7537a84e134Smrg    }
7547a84e134Smrg
7557a84e134Smrg    return (answer);
7567a84e134Smrg}
7577a84e134Smrg
7587a84e134Smrg/*
7597a84e134Smrg * Function:
7607a84e134Smrg *	XawSimpleMenuChangeManaged
7617a84e134Smrg *
7627a84e134Smrg * Parameters:
7637a84e134Smrg *	w - simple menu widget
7647a84e134Smrg *
7657a84e134Smrg * Description:
7667a84e134Smrg *	Called whenever a new child is managed.
7677a84e134Smrg */
7687a84e134Smrgstatic void
7697a84e134SmrgXawSimpleMenuChangeManaged(Widget w)
7707a84e134Smrg{
7717a84e134Smrg    Layout(w, NULL, NULL);
7727a84e134Smrg}
7737a84e134Smrg
7747a84e134Smrg/*
7757a84e134Smrg * Global Action Routines
7767a84e134Smrg *
7777a84e134Smrg * These actions routines will be added to the application's
7787a84e134Smrg * global action list
7797a84e134Smrg */
7807a84e134Smrg/*
7817a84e134Smrg * Function:
7827a84e134Smrg *	PositionMenuAction
7837a84e134Smrg *
7847a84e134Smrg * Parameters:
7857a84e134Smrg *	w	   - a widget (no the simple menu widget)
7867a84e134Smrg *	event	   - the event that caused this action
7877a84e134Smrg *	params	   - parameters passed to the routine.
7887a84e134Smrg *                                      we expect the name of the menu here.
7897a84e134Smrg *	num_params - ""
7907a84e134Smrg *
7917a84e134Smrg * Description:
7927a84e134Smrg *	Positions the simple menu widget.
7937a84e134Smrg */
7947a84e134Smrg/*ARGSUSED*/
7957a84e134Smrgstatic void
7967a84e134SmrgPositionMenuAction(Widget w, XEvent *event,
7977a84e134Smrg		   String *params, Cardinal *num_params)
7987a84e134Smrg{
7997a84e134Smrg    Widget menu;
8007a84e134Smrg    XPoint loc;
8017a84e134Smrg
8027a84e134Smrg    if (*num_params != 1) {
8037a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w),
8047a84e134Smrg		     "SimpleMenuWidget: position menu action expects "
8057a84e134Smrg		     "only one parameter which is the name of the menu.");
8067a84e134Smrg	return;
8077a84e134Smrg    }
8087a84e134Smrg
8097a84e134Smrg    if ((menu = FindMenu(w, params[0])) == NULL) {
8107a84e134Smrg	char error_buf[BUFSIZ];
8117a84e134Smrg
8127a84e134Smrg	(void)XmuSnprintf(error_buf, sizeof(error_buf),
8137a84e134Smrg			  "SimpleMenuWidget: could not find menu named %s.",
8147a84e134Smrg			  params[0]);
8157a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
8167a84e134Smrg	return;
8177a84e134Smrg    }
8187a84e134Smrg
8197a84e134Smrg    switch (event->type) {
8207a84e134Smrg	case ButtonPress:
8217a84e134Smrg	case ButtonRelease:
8227a84e134Smrg	    loc.x = event->xbutton.x_root;
8237a84e134Smrg	    loc.y = event->xbutton.y_root;
8247a84e134Smrg	    PositionMenu(menu, &loc);
8257a84e134Smrg	    break;
8267a84e134Smrg	case EnterNotify:
8277a84e134Smrg	case LeaveNotify:
8287a84e134Smrg	    loc.x = event->xcrossing.x_root;
8297a84e134Smrg	    loc.y = event->xcrossing.y_root;
8307a84e134Smrg	    PositionMenu(menu, &loc);
8317a84e134Smrg	    break;
8327a84e134Smrg	case MotionNotify:
8337a84e134Smrg	    loc.x = event->xmotion.x_root;
8347a84e134Smrg	    loc.y = event->xmotion.y_root;
8357a84e134Smrg	    PositionMenu(menu, &loc);
8367a84e134Smrg	    break;
8377a84e134Smrg	default:
8387a84e134Smrg	    PositionMenu(menu, NULL);
8397a84e134Smrg	    break;
8407a84e134Smrg    }
8417a84e134Smrg}
8427a84e134Smrg
8437a84e134Smrg/*
8447a84e134Smrg * Widget Action Routines
8457a84e134Smrg */
8467a84e134Smrg/*
8477a84e134Smrg * Function:
8487a84e134Smrg *	Unhighlight
8497a84e134Smrg *
8507a84e134Smrg * Parameters:
8517a84e134Smrg *	w	   - simple menu widget
8527a84e134Smrg *	event	   - event that caused this action
8537a84e134Smrg *	params	   - not used
8547a84e134Smrg *	num_params - ""
8557a84e134Smrg *
8567a84e134Smrg * Description:
8577a84e134Smrg *	Unhighlights current entry.
8587a84e134Smrg */
8597a84e134Smrg/*ARGSUSED*/
8607a84e134Smrgstatic void
8617a84e134SmrgUnhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
8627a84e134Smrg{
8637a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
8647a84e134Smrg    SmeObject entry = smw->simple_menu.entry_set;
8657a84e134Smrg
8667a84e134Smrg    if (entry == NULL)
8677a84e134Smrg	return;
8687a84e134Smrg
8697a84e134Smrg#ifndef OLDXAW
8707a84e134Smrg    if (!smw->simple_menu.sub_menu)
8717a84e134Smrg#endif
8727a84e134Smrg    {
8737a84e134Smrg	SmeObjectClass cclass;
8747a84e134Smrg
8757a84e134Smrg	smw->simple_menu.entry_set = NULL;
8767a84e134Smrg	cclass = (SmeObjectClass)entry->object.widget_class;
8777a84e134Smrg	(cclass->sme_class.unhighlight)((Widget)entry);
8787a84e134Smrg    }
8797a84e134Smrg}
8807a84e134Smrg
8817a84e134Smrg/*
8827a84e134Smrg * Function:
8837a84e134Smrg *	Highlight
8847a84e134Smrg *
8857a84e134Smrg * Parameters:
8867a84e134Smrg *	w	   - simple menu widget
8877a84e134Smrg *	event	   - event that caused this action
8887a84e134Smrg *	params	   - not used
8897a84e134Smrg *	num_params - ""
8907a84e134Smrg *
8917a84e134Smrg * Description:
8927a84e134Smrg *	Highlights current entry.
8937a84e134Smrg */
8947a84e134Smrg/*ARGSUSED*/
8957a84e134Smrgstatic void
8967a84e134SmrgHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
8977a84e134Smrg{
8987a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
8997a84e134Smrg    SmeObject entry;
9007a84e134Smrg
9017a84e134Smrg    if (!XtIsSensitive(w))
9027a84e134Smrg	return;
9037a84e134Smrg
9047a84e134Smrg    entry = GetEventEntry(w, event);
9057a84e134Smrg
9067a84e134Smrg    if (entry == smw->simple_menu.entry_set)
9077a84e134Smrg	return;
9087a84e134Smrg
9097a84e134Smrg#ifndef OLDXAW
9107a84e134Smrg    if (!smw->simple_menu.sub_menu)
9117a84e134Smrg#endif
9127a84e134Smrg	Unhighlight(w, event, params, num_params);
9137a84e134Smrg
9147a84e134Smrg    if (entry == NULL)
9157a84e134Smrg	return;
9167a84e134Smrg
9177a84e134Smrg    if (!XtIsSensitive((Widget)entry))
9187a84e134Smrg	return;
9197a84e134Smrg
9207a84e134Smrg#ifndef OLDXAW
9217a84e134Smrg    if (smw->simple_menu.sub_menu)
9227a84e134Smrg	PopdownSubMenu(smw);
9237a84e134Smrg#endif
9247a84e134Smrg
9257a84e134Smrg    Unhighlight(w, event, params, num_params);
9267a84e134Smrg
9277a84e134Smrg#ifndef OLDXAW
9287a84e134Smrg    if (!(smw->simple_menu.state & SMW_UNMAPPING))
9297a84e134Smrg#endif
9307a84e134Smrg    {
9317a84e134Smrg	SmeObjectClass cclass;
9327a84e134Smrg
9337a84e134Smrg	smw->simple_menu.entry_set = entry;
9347a84e134Smrg	cclass = (SmeObjectClass)entry->object.widget_class;
9357a84e134Smrg
9367a84e134Smrg	(cclass->sme_class.highlight)((Widget)entry);
9377a84e134Smrg
9387a84e134Smrg#ifndef OLDXAW
9397a84e134Smrg	if (XtIsSubclass((Widget)entry, smeBSBObjectClass))
9407a84e134Smrg	    PopupSubMenu(smw);
9417a84e134Smrg#endif
9427a84e134Smrg    }
9437a84e134Smrg}
9447a84e134Smrg
9457a84e134Smrg/*
9467a84e134Smrg * Function:
9477a84e134Smrg *	Notify
9487a84e134Smrg *
9497a84e134Smrg * Parameters:
9507a84e134Smrg *	w	   - simple menu widget
9517a84e134Smrg *	event	   - event that caused this action
9527a84e134Smrg *	params	   - not used
9537a84e134Smrg *	num_params - ""
9547a84e134Smrg *
9557a84e134Smrg * Description:
9567a84e134Smrg *	Notify user of current entry.
9577a84e134Smrg */
9587a84e134Smrg/*ARGSUSED*/
9597a84e134Smrgstatic void
9607a84e134SmrgNotify(Widget w, XEvent *event, String *params, Cardinal *num_params)
9617a84e134Smrg{
9627a84e134Smrg    SmeObject entry;
9637a84e134Smrg    SmeObjectClass cclass;
9647a84e134Smrg
9657a84e134Smrg    /* may be a propagated event from a sub menu, need to check it */
9667a84e134Smrg    if (XtWindow(w) != event->xany.window)
9677a84e134Smrg	return;
9687a84e134Smrg    entry = GetEventEntry(w, event);
9697a84e134Smrg    if (entry == NULL || !XtIsSensitive((Widget)entry))
9707a84e134Smrg	return;
9717a84e134Smrg
9727a84e134Smrg    cclass = (SmeObjectClass) entry->object.widget_class;
9737a84e134Smrg    (cclass->sme_class.notify)((Widget)entry);
9747a84e134Smrg}
9757a84e134Smrg
9767a84e134Smrg/*
9777a84e134Smrg * Public Functions
9787a84e134Smrg */
9797a84e134Smrg/*
9807a84e134Smrg * Function:
9817a84e134Smrg *	XawSimpleMenuAddGlobalActions
9827a84e134Smrg *
9837a84e134Smrg * Arguments:
9847a84e134Smrg *	app_con - appcontext
9857a84e134Smrg *
9867a84e134Smrg * Description:
9877a84e134Smrg *	Adds the global actions to the simple menu widget.
9887a84e134Smrg */
9897a84e134Smrgvoid
9907a84e134SmrgXawSimpleMenuAddGlobalActions(XtAppContext app_con)
9917a84e134Smrg{
9927a84e134Smrg    XtInitializeWidgetClass(simpleMenuWidgetClass);
9937a84e134Smrg    XmuCallInitializers(app_con);
9947a84e134Smrg}
9957a84e134Smrg
9967a84e134Smrg/*
9977a84e134Smrg * Function:
9987a84e134Smrg *	XawSimpleMenuGetActiveEntry
9997a84e134Smrg *
10007a84e134Smrg * Parameters:
10017a84e134Smrg *	w - smw widget
10027a84e134Smrg *
10037a84e134Smrg * Description:
10047a84e134Smrg *	Gets the currently active (set) entry.
10057a84e134Smrg *
10067a84e134Smrg * Returns:
10077a84e134Smrg *	The currently set entry or NULL if none is set
10087a84e134Smrg */
10097a84e134SmrgWidget
10107a84e134SmrgXawSimpleMenuGetActiveEntry(Widget w)
10117a84e134Smrg{
10127a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10137a84e134Smrg
10147a84e134Smrg    return ((Widget)smw->simple_menu.entry_set);
10157a84e134Smrg}
10167a84e134Smrg
10177a84e134Smrg/*
10187a84e134Smrg * Function:
10197a84e134Smrg *	XawSimpleMenuClearActiveEntry
10207a84e134Smrg *
10217a84e134Smrg * Parameters:
10227a84e134Smrg *	w - smw widget
10237a84e134Smrg *
10247a84e134Smrg * Description:
10257a84e134Smrg *	Unsets the currently active (set) entry.
10267a84e134Smrg */
10277a84e134Smrgvoid
10287a84e134SmrgXawSimpleMenuClearActiveEntry(Widget w)
10297a84e134Smrg{
10307a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10317a84e134Smrg
10327a84e134Smrg    smw->simple_menu.entry_set = NULL;
10337a84e134Smrg}
10347a84e134Smrg
10357a84e134Smrg/*
10367a84e134Smrg * Private Functions
10377a84e134Smrg */
10387a84e134Smrg/*
10397a84e134Smrg * Function:
10407a84e134Smrg *	CreateLabel
10417a84e134Smrg *
10427a84e134Smrg * Parameters:
10437a84e134Smrg *	w - smw widget
10447a84e134Smrg *
10457a84e134Smrg * Description:
10467a84e134Smrg * Creates the label object and makes sure it is the first child in
10477a84e134Smrg * in the list.
10487a84e134Smrg */
10497a84e134Smrgstatic void
10507a84e134SmrgCreateLabel(Widget w)
10517a84e134Smrg{
10527a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
10537a84e134Smrg    Widget *child, *next_child;
10547a84e134Smrg    int i;
10557a84e134Smrg    Arg args[2];
10567a84e134Smrg
10577a84e134Smrg    if (smw->simple_menu.label_string == NULL ||
10587a84e134Smrg	smw->simple_menu.label != NULL) {
10597a84e134Smrg	XtAppWarning(XtWidgetToApplicationContext(w),
10607a84e134Smrg		     "Xaw Simple Menu Widget: label string is NULL or "
10617a84e134Smrg		     "label already exists, no label is being created.");
10627a84e134Smrg	return;
10637a84e134Smrg    }
10647a84e134Smrg
10657a84e134Smrg    XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
10667a84e134Smrg    XtSetArg(args[1], XtNjustify, XtJustifyCenter);
10677a84e134Smrg    smw->simple_menu.label = (SmeObject)
10687a84e134Smrg	XtCreateManagedWidget("menuLabel",
10697a84e134Smrg			      smw->simple_menu.label_class, w, args, TWO);
10707a84e134Smrg
10717a84e134Smrg    next_child = NULL;
10727a84e134Smrg    for (child = smw->composite.children + smw->composite.num_children,
10737a84e134Smrg	 i = smw->composite.num_children; i > 0; i--, child--) {
10747a84e134Smrg	if (next_child != NULL)
10757a84e134Smrg	    *next_child = *child;
10767a84e134Smrg	next_child = child;
10777a84e134Smrg    }
10787a84e134Smrg    *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
10957a84e134Smrg * to be width and height that the child would get if it were layed 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    height = 0;
11147a84e134Smrg
11157a84e134Smrg    if (XtIsSubclass(w, simpleMenuWidgetClass)) {
11167a84e134Smrg	smw = (SimpleMenuWidget)w;
11177a84e134Smrg	current_entry = NULL;
11187a84e134Smrg    }
11197a84e134Smrg    else {
11207a84e134Smrg	smw = (SimpleMenuWidget)XtParent(w);
11217a84e134Smrg	current_entry = (SmeObject)w;
11227a84e134Smrg    }
11237a84e134Smrg
11247a84e134Smrg    allow_change_size = (!XtIsRealized((Widget)smw)
11257a84e134Smrg			 || smw->shell.allow_shell_resize);
11267a84e134Smrg
11277a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
11287a84e134Smrg	 i < smw->composite.num_children;
11297a84e134Smrg	 i++) {
11307a84e134Smrg	XtWidgetGeometry preferred;
11317a84e134Smrg
11327a84e134Smrg	kid = smw->composite.children[i];
11337a84e134Smrg	if (!XtIsManaged(kid))
11347a84e134Smrg	    continue;
11357a84e134Smrg	if (smw->simple_menu.row_height != 0)
11367a84e134Smrg	    XtHeight(kid) = smw->simple_menu.row_height;
11377a84e134Smrg	XtQueryGeometry(kid, NULL, &preferred);
11387a84e134Smrg	if (preferred.request_mode & CWWidth)
11397a84e134Smrg	    XtWidth(kid) = preferred.width;
11407a84e134Smrg    }
11417a84e134Smrg
11427a84e134Smrg    if (smw->simple_menu.label
11437a84e134Smrg	&& XtIsManaged((Widget)smw->simple_menu.label)) {
11447a84e134Smrg	XtWidgetGeometry preferred;
11457a84e134Smrg
11467a84e134Smrg	kid = (Widget)smw->simple_menu.label;
11477a84e134Smrg	XtQueryGeometry(kid, NULL, &preferred);
11487a84e134Smrg	if (preferred.request_mode & CWWidth)
11497a84e134Smrg	    XtWidth(kid) = preferred.width;
11507a84e134Smrg	if (preferred.request_mode & CWHeight)
11517a84e134Smrg	    XtHeight(kid) = preferred.height;
11527a84e134Smrg    }
11537a84e134Smrg
11547a84e134Smrg    /* reset */
11557a84e134Smrg    if (!smw->simple_menu.menu_width)
11567a84e134Smrg	XtWidth(smw) = 0;
11577a84e134Smrg    if (!smw->simple_menu.menu_height)
11587a84e134Smrg	XtHeight(smw) = 0;
11597a84e134Smrg    if (!XtWidth(smw) || !XtHeight(smw))
11607a84e134Smrg	MakeResizeRequest((Widget)smw);
11617a84e134Smrg
11627a84e134Smrg    widths = (Dimension *)XtMalloc(sizeof(Dimension));
11637a84e134Smrg#ifndef OLDXAW
11647a84e134Smrg    hadd = smw->simple_menu.left_margin;
11657a84e134Smrg#else
11667a84e134Smrg    hadd = 0;
11677a84e134Smrg#endif
11687a84e134Smrg    vadd = smw->simple_menu.top_margin;
11697a84e134Smrg    if (smw->simple_menu.label)
11707a84e134Smrg	vadd += XtHeight(smw->simple_menu.label);
11717a84e134Smrg
11727a84e134Smrg    count = 1;
11737a84e134Smrg    width = tmp_w = tmp_h = n = 0;
11747a84e134Smrg    height = vadd;
11757a84e134Smrg
11767a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
11777a84e134Smrg	 i < smw->composite.num_children;
11787a84e134Smrg	 i++) {
11797a84e134Smrg	kid = smw->composite.children[i];
11807a84e134Smrg	if (!XtIsManaged(kid))
11817a84e134Smrg	    continue;
11827a84e134Smrg	width_kid = XtWidth(kid);
11837a84e134Smrg	height_kid = XtHeight(kid);
11847a84e134Smrg
11857a84e134Smrg	if (n && (height + height_kid + smw->simple_menu.bottom_margin
11867a84e134Smrg		  > XtHeight(smw))) {
11877a84e134Smrg	    ++count;
11887a84e134Smrg	    widths = (Dimension *)XtRealloc((char *)widths,
11897a84e134Smrg					    sizeof(Dimension) * count);
11907a84e134Smrg	    widths[count - 1] = width_kid;
11917a84e134Smrg	    width += tmp_w;
11927a84e134Smrg	    tmp_w = width_kid;
11937a84e134Smrg	    height = height_kid + vadd;
11947a84e134Smrg	}
11957a84e134Smrg	else
11967a84e134Smrg	    height += height_kid;
11977a84e134Smrg	if (height > tmp_h)
11987a84e134Smrg	    tmp_h = height;
11997a84e134Smrg	if (width_kid > tmp_w)
12007a84e134Smrg	    widths[count - 1] = tmp_w = width_kid;
12017a84e134Smrg	++n;
12027a84e134Smrg    }
12037a84e134Smrg
12047a84e134Smrg    height = tmp_h + smw->simple_menu.bottom_margin;
12057a84e134Smrg    width += tmp_w;
12067a84e134Smrg
12077a84e134Smrg    if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) {
12087a84e134Smrg	float inc;
12097a84e134Smrg
12107a84e134Smrg	inc = (XtWidth(smw->simple_menu.label) - width) / (float)count;
12117a84e134Smrg	width = XtWidth(smw->simple_menu.label);
12127a84e134Smrg	for (n = 0; n < count; n++)
12137a84e134Smrg	    widths[n] += inc;
12147a84e134Smrg    }
12157a84e134Smrg
12167a84e134Smrg#ifndef OLDXAW
12177a84e134Smrg    width += hadd + smw->simple_menu.right_margin;
12187a84e134Smrg#endif
12197a84e134Smrg
12207a84e134Smrg    x_ins = n = count = 0;
12217a84e134Smrg    tmp_w = widths[0];
12227a84e134Smrg    tmp_h = vadd;
12237a84e134Smrg
12247a84e134Smrg    for (i = smw->simple_menu.label ? 1 : 0;
12257a84e134Smrg	 i < smw->composite.num_children;
12267a84e134Smrg	 i++) {
12277a84e134Smrg	kid = smw->composite.children[i];
12287a84e134Smrg	if (!XtIsManaged(kid))
12297a84e134Smrg	    continue;
12307a84e134Smrg
12317a84e134Smrg	height_kid = XtHeight(kid);
12327a84e134Smrg
12337a84e134Smrg	if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin
12347a84e134Smrg		  > XtHeight(smw))) {
12357a84e134Smrg	    x_ins = tmp_w;
12367a84e134Smrg	    y_ins = vadd;
12377a84e134Smrg	    ++count;
12387a84e134Smrg	    tmp_w += widths[count];
12397a84e134Smrg	    tmp_h = height_kid + vadd;
12407a84e134Smrg	}
12417a84e134Smrg	else {
12427a84e134Smrg	    y_ins = tmp_h;
12437a84e134Smrg	    tmp_h += height_kid;
12447a84e134Smrg	}
12457a84e134Smrg	++n;
12467a84e134Smrg
12477a84e134Smrg	XtX(kid) = x_ins + hadd;
12487a84e134Smrg	XtY(kid) = y_ins;
12497a84e134Smrg	XtWidth(kid) = widths[count];
12507a84e134Smrg    }
12517a84e134Smrg
12527a84e134Smrg    XtFree((char *)widths);
12537a84e134Smrg
12547a84e134Smrg    if (allow_change_size)
12557a84e134Smrg	MakeSetValuesRequest((Widget) smw, width, height);
12567a84e134Smrg
12577a84e134Smrg    if (smw->simple_menu.label) {
12587a84e134Smrg	XtX(smw->simple_menu.label) = 0;
12597a84e134Smrg	XtY(smw->simple_menu.label) = smw->simple_menu.top_margin;
12607a84e134Smrg	XtWidth(smw->simple_menu.label) = XtWidth(smw)
12617a84e134Smrg#ifndef OLDXAW
12627a84e134Smrg	    - (smw->simple_menu.left_margin + smw->simple_menu.right_margin)
12637a84e134Smrg#endif
12647a84e134Smrg	    ;
12657a84e134Smrg    }
12667a84e134Smrg    if (current_entry) {
12677a84e134Smrg	if (width_ret)
12687a84e134Smrg	    *width_ret = XtWidth(current_entry);
12697a84e134Smrg	if (height_ret)
12707a84e134Smrg	    *height_ret = XtHeight(current_entry);
12717a84e134Smrg    }
12727a84e134Smrg}
12737a84e134Smrg
12747a84e134Smrg/*
12757a84e134Smrg * Function:
12767a84e134Smrg *	AddPositionAction
12777a84e134Smrg *
12787a84e134Smrg * Parameters:
12797a84e134Smrg *	app_con - application context
12807a84e134Smrg *	data	- (not used)
12817a84e134Smrg *
12827a84e134Smrg * Description:
12837a84e134Smrg *	  Adds the XawPositionSimpleMenu action to the global
12847a84e134Smrg *                   action list for this appcon.
12857a84e134Smrg */
12867a84e134Smrg/*ARGSUSED*/
12877a84e134Smrgstatic void
12887a84e134SmrgAddPositionAction(XtAppContext app_con, XPointer data)
12897a84e134Smrg{
12907a84e134Smrg    static XtActionsRec pos_action[] = {
12917a84e134Smrg	{"XawPositionSimpleMenu",	PositionMenuAction},
12927a84e134Smrg    };
12937a84e134Smrg
12947a84e134Smrg    XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
12957a84e134Smrg}
12967a84e134Smrg
12977a84e134Smrg/*
12987a84e134Smrg * Function:
12997a84e134Smrg *	FindMenu
13007a84e134Smrg *
13017a84e134Smrg * Parameters:
13027a84e134Smrg *	widget - reference widget
13037a84e134Smrg *	name   - menu widget's name
13047a84e134Smrg *
13057a84e134Smrg * Description:
13067a84e134Smrg *	Find the menu give a name and reference widget
13077a84e134Smrg *
13087a84e134Smrg * Returns:
13097a84e134Smrg *	The menu widget or NULL.
13107a84e134Smrg */
13117a84e134Smrgstatic Widget
13127a84e134SmrgFindMenu(Widget widget, String name)
13137a84e134Smrg{
13147a84e134Smrg    Widget w, menu;
13157a84e134Smrg
13167a84e134Smrg    for (w = widget; w != NULL; w = XtParent(w))
13177a84e134Smrg	if ((menu = XtNameToWidget(w, name)) != NULL)
13187a84e134Smrg	    return (menu);
13197a84e134Smrg
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;
13407a84e134Smrg
13417a84e134Smrg    if (location == NULL) {
13427a84e134Smrg	Window temp1, temp2;
13437a84e134Smrg	int root_x, root_y, tempX, tempY;
13447a84e134Smrg	unsigned int tempM;
13457a84e134Smrg
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    }
13577a84e134Smrg
13587a84e134Smrg    /*
13597a84e134Smrg     * The width will not be correct unless it is realized
13607a84e134Smrg     */
13617a84e134Smrg    XtRealizeWidget(w);
13627a84e134Smrg
13637a84e134Smrg    location->x -= XtWidth(w) >> 1;
13647a84e134Smrg
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)
13717a84e134Smrg      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
13877a84e134Smrg *	to be fully visable 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;
13957a84e134Smrg
13967a84e134Smrg    if (smw->simple_menu.menu_on_screen) {
13977a84e134Smrg	int width = XtWidth(w) + (XtBorderWidth(w) << 1);
13987a84e134Smrg	int height = XtHeight(w) + (XtBorderWidth(w) << 1);
13997a84e134Smrg
14007a84e134Smrg	if (x >= 0) {
14017a84e134Smrg	    int scr_width = WidthOfScreen(XtScreen(w));
14027a84e134Smrg
14037a84e134Smrg	    if (x + width > scr_width)
14047a84e134Smrg		x = scr_width - width;
14057a84e134Smrg	}
14067a84e134Smrg	if (x < 0)
14077a84e134Smrg	    x = 0;
14087a84e134Smrg
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    }
14187a84e134Smrg
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
14397a84e134SmrgChangeCursorOnGrab(Widget w, XtPointer temp1, XtPointer temp2)
14407a84e134Smrg{
14417a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
14427a84e134Smrg
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,
14497a84e134Smrg			     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;
14667a84e134Smrg    Arg arglist[2];
14677a84e134Smrg    Cardinal num_args = 0;
14687a84e134Smrg
14697a84e134Smrg    if (!smw->simple_menu.recursive_set_values) {
14707a84e134Smrg	if (XtWidth(smw) != width || XtHeight(smw) != height) {
14717a84e134Smrg	    smw->simple_menu.recursive_set_values = True;
14727a84e134Smrg	    XtSetArg(arglist[num_args], XtNwidth, width);   num_args++;
14737a84e134Smrg	    XtSetArg(arglist[num_args], XtNheight, height); num_args++;
14747a84e134Smrg	    XtSetValues(w, arglist, num_args);
14757a84e134Smrg	}
14767a84e134Smrg	else if (XtIsRealized((Widget)smw))
14777a84e134Smrg	    XawSimpleMenuRedisplay((Widget)smw, NULL, NULL);
14787a84e134Smrg    }
14797a84e134Smrg    smw->simple_menu.recursive_set_values = False;
14807a84e134Smrg}
14817a84e134Smrg
14827a84e134Smrgstatic SmeObject
14837a84e134SmrgDoGetEventEntry(Widget w, int x_loc, int y_loc)
14847a84e134Smrg{
14857a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
14867a84e134Smrg    SmeObject *entry;
14877a84e134Smrg
14887a84e134Smrg    ForAllChildren(smw, entry) {
14897a84e134Smrg	if (!XtIsManaged((Widget)*entry))
14907a84e134Smrg	    continue;
14917a84e134Smrg
14927a84e134Smrg	if (x_loc > XtX(*entry)
14937a84e134Smrg	    && x_loc <= XtX(*entry) + XtWidth(*entry)
14947a84e134Smrg	    && y_loc > XtY(*entry)
14957a84e134Smrg	    &&  y_loc <= XtY(*entry) + XtHeight(*entry)) {
14967a84e134Smrg	    if (*entry == smw->simple_menu.label)
14977a84e134Smrg		return (NULL);	/* cannot select the label */
14987a84e134Smrg	    else
14997a84e134Smrg		return (*entry);
15007a84e134Smrg	}
15017a84e134Smrg    }
15027a84e134Smrg
15037a84e134Smrg    return (NULL);
15047a84e134Smrg}
15057a84e134Smrg
15067a84e134Smrg/*
15077a84e134Smrg * Function:
15087a84e134Smrg *	GetEventEntry
15097a84e134Smrg *
15107a84e134Smrg * Parameters:
15117a84e134Smrg *	w     - simple menu widget
15127a84e134Smrg *	event - X event
15137a84e134Smrg *
15147a84e134Smrg * Description:
15157a84e134Smrg *	Gets an entry given an event that has X and Y coords.
15167a84e134Smrg *
15177a84e134Smrg * Returns:
15187a84e134Smrg *	The entry that this point is in
15197a84e134Smrg */
15207a84e134Smrgstatic SmeObject
15217a84e134SmrgGetEventEntry(Widget w, XEvent *event)
15227a84e134Smrg{
15237a84e134Smrg    int x_loc, y_loc, x_root;
15247a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
15257a84e134Smrg    SmeObject entry;
15267a84e134Smrg    int warp, move;
15277a84e134Smrg
15287a84e134Smrg    switch (event->type) {
15297a84e134Smrg	case MotionNotify:
15307a84e134Smrg	    x_loc = event->xmotion.x;
15317a84e134Smrg	    y_loc = event->xmotion.y;
15327a84e134Smrg	    x_root = event->xmotion.x_root;
15337a84e134Smrg	    break;
15347a84e134Smrg	case EnterNotify:
15357a84e134Smrg	case LeaveNotify:
15367a84e134Smrg	    x_loc = event->xcrossing.x;
15377a84e134Smrg	    y_loc = event->xcrossing.y;
15387a84e134Smrg	    x_root = event->xcrossing.x_root;
15397a84e134Smrg	    break;
15407a84e134Smrg	case ButtonPress:
15417a84e134Smrg	case ButtonRelease:
15427a84e134Smrg	    x_loc = event->xbutton.x;
15437a84e134Smrg	    y_loc = event->xbutton.y;
15447a84e134Smrg	    x_root = event->xbutton.x_root;
15457a84e134Smrg	    break;
15467a84e134Smrg	default:
15477a84e134Smrg	    XtAppError(XtWidgetToApplicationContext(w),
15487a84e134Smrg		       "Unknown event type in GetEventEntry().");
15497a84e134Smrg	    return (NULL);
15507a84e134Smrg    }
15517a84e134Smrg
15527a84e134Smrg    if (x_loc < 0 || x_loc >= XtWidth(smw) ||
15537a84e134Smrg	y_loc < 0 || y_loc >= XtHeight(smw))
15547a84e134Smrg	return (NULL);
15557a84e134Smrg
15567a84e134Smrg    /* Move the menu if it's outside the screen, does not check
15577a84e134Smrg     * smw->simple_menu.menu_on_screen because menus is bigger than screen
15587a84e134Smrg     */
15597a84e134Smrg    if (x_root == WidthOfScreen(XtScreen(w)) - 1 &&
15607a84e134Smrg	XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) {
15617a84e134Smrg	warp = -8;
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)
16047a84e134Smrg	XtMoveWidget(w, 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
16247a84e134Smrg    hadd = xaw->simple_menu.left_margin + xaw->simple_menu.right_margin;
16257a84e134Smrg#else
16267a84e134Smrg    hadd = 0;
16277a84e134Smrg#endif
16287a84e134Smrg    vadd = xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin;
16297a84e134Smrg    if (xaw->simple_menu.label)
16307a84e134Smrg	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
16827a84e134Smrg    *width_return = width;
16837a84e134Smrg    *height_return = 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);
16987a84e134Smrg	    *height_return = 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;
17097a84e134Smrg
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
17697a84e134Smrg    if (popleft)
17707a84e134Smrg	XtTranslateCoords((Widget)smw, -(int)XtWidth(menu),
17717a84e134Smrg			  XtY(entry) - XtBorderWidth(menu), &menu_x, &menu_y);
17727a84e134Smrg    else
17737a84e134Smrg	XtTranslateCoords((Widget)smw, XtWidth(smw), XtY(entry)
17747a84e134Smrg			  - XtBorderWidth(menu), &menu_x, &menu_y);
17757a84e134Smrg
17767a84e134Smrg    if (!popleft && menu_x >= 0) {
17777a84e134Smrg	int scr_width = WidthOfScreen(XtScreen(menu));
17787a84e134Smrg
17797a84e134Smrg	if (menu_x + XtWidth(menu) > scr_width) {
17807a84e134Smrg	    menu_x -= XtWidth(menu) + XtWidth(smw);
17817a84e134Smrg	    popleft = True;
17827a84e134Smrg	}
17837a84e134Smrg    }
17847a84e134Smrg    else if (popleft && menu_x < 0) {
17857a84e134Smrg	menu_x = 0;
17867a84e134Smrg	popleft = False;
17877a84e134Smrg    }
17887a84e134Smrg    if (menu_y >= 0) {
17897a84e134Smrg	int scr_height = HeightOfScreen(XtScreen(menu));
17907a84e134Smrg
17917a84e134Smrg	if (menu_y + XtHeight(menu) > scr_height)
17927a84e134Smrg	    menu_y = scr_height - XtHeight(menu) - XtBorderWidth(menu);
17937a84e134Smrg    }
17947a84e134Smrg    if (menu_y < 0)
17957a84e134Smrg	menu_y = 0;
17967a84e134Smrg
17977a84e134Smrg    num_args = 0;
17987a84e134Smrg    XtSetArg(args[num_args], XtNx, menu_x);	num_args++;
17997a84e134Smrg    XtSetArg(args[num_args], XtNy, menu_y);	num_args++;
18007a84e134Smrg    XtSetValues(menu, args, num_args);
18017a84e134Smrg
18027a84e134Smrg    if (popleft)
18037a84e134Smrg	((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT;
18047a84e134Smrg    else
18057a84e134Smrg	((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT;
18067a84e134Smrg
18077a84e134Smrg    XtPopup(menu, XtGrabNone);
18087a84e134Smrg}
18097a84e134Smrg
18107a84e134Smrgstatic void
18117a84e134SmrgPopdownSubMenu(SimpleMenuWidget smw)
18127a84e134Smrg{
18137a84e134Smrg    SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu;
18147a84e134Smrg
18157a84e134Smrg    if (!menu)
18167a84e134Smrg	return;
18177a84e134Smrg
18187a84e134Smrg    menu->simple_menu.state |= SMW_UNMAPPING;
18197a84e134Smrg    PopdownSubMenu(menu);
18207a84e134Smrg
18217a84e134Smrg    XtPopdown((Widget)menu);
18227a84e134Smrg
18237a84e134Smrg    smw->simple_menu.sub_menu = NULL;
18247a84e134Smrg}
18257a84e134Smrg
18267a84e134Smrg/*ARGSUSED*/
18277a84e134Smrgstatic void
18287a84e134SmrgPopupCB(Widget w, XtPointer client_data, XtPointer call_data)
18297a84e134Smrg{
18307a84e134Smrg    SimpleMenuWidget smw = (SimpleMenuWidget)w;
18317a84e134Smrg
18327a84e134Smrg    smw->simple_menu.state &= ~(SMW_UNMAPPING | SMW_POPLEFT);
18337a84e134Smrg}
18347a84e134Smrg#endif /* OLDXAW */
1835