diff options
Diffstat (limited to 'libXaw/src/SimpleMenu.c')
-rw-r--r-- | libXaw/src/SimpleMenu.c | 3664 |
1 files changed, 1830 insertions, 1834 deletions
diff --git a/libXaw/src/SimpleMenu.c b/libXaw/src/SimpleMenu.c index b7ed28651..cfde9df29 100644 --- a/libXaw/src/SimpleMenu.c +++ b/libXaw/src/SimpleMenu.c @@ -1,1834 +1,1830 @@ -/* $Xorg: SimpleMenu.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */ - -/* -Copyright 1989, 1994, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - */ - -/* $XFree86: xc/lib/Xaw/SimpleMenu.c,v 3.21 2001/03/23 23:59:15 paulo Exp $ */ - -/* - * SimpleMenu.c - Source code file for SimpleMenu widget. - * - * Date: April 3, 1989 - * - * By: Chris D. Peterson - * MIT X Consortium - * kit@expo.lcs.mit.edu - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <X11/IntrinsicP.h> -#include <X11/StringDefs.h> -#include <X11/Xmu/Initer.h> -#include <X11/Xmu/SysUtil.h> -#include <X11/Xaw/Cardinals.h> -#include <X11/Xaw/SimpleMenP.h> -#include <X11/Xaw/SmeBSBP.h> -#include <X11/Xaw/XawInit.h> -#include "Private.h" - -#define streq(a, b) (strcmp((a), (b)) == 0) - -#define ForAllChildren(smw, childP) \ -for ((childP) = (SmeObject *)(smw)->composite.children; \ - (childP) < (SmeObject *)((smw)->composite.children \ - + (smw)->composite.num_children); \ - (childP)++) - -#ifndef OLDXAW -#define SMW_UNMAPPING 0x01 -#define SMW_POPLEFT 0x02 -#endif - -/* - * Class Methods - */ -static void XawSimpleMenuChangeManaged(Widget); -static void XawSimpleMenuClassInitialize(void); -static void XawSimpleMenuClassPartInitialize(WidgetClass); -static XtGeometryResult XawSimpleMenuGeometryManager(Widget, XtWidgetGeometry*, - XtWidgetGeometry*); -static void XawSimpleMenuInitialize(Widget, Widget, ArgList, Cardinal*); -static void XawSimpleMenuRealize(Widget, XtValueMask*, XSetWindowAttributes*); -static void XawSimpleMenuRedisplay(Widget, XEvent*, Region); -static void XawSimpleMenuResize(Widget); -static Boolean XawSimpleMenuSetValues(Widget, Widget, Widget, - ArgList, Cardinal*); -static Boolean XawSimpleMenuSetValuesHook(Widget, ArgList, Cardinal*); -#ifndef OLDXAW -static void PopupSubMenu(SimpleMenuWidget); -static void PopdownSubMenu(SimpleMenuWidget); -static void PopupCB(Widget, XtPointer, XtPointer); -#endif - -/* - * Prototypes - */ -static void AddPositionAction(XtAppContext, XPointer); -static void CalculateNewSize(Widget, Dimension*, Dimension*); -static void ChangeCursorOnGrab(Widget, XtPointer, XtPointer); -static void CreateLabel(Widget); -static SmeObject DoGetEventEntry(Widget, int, int); -static Widget FindMenu(Widget, String); -static SmeObject GetEventEntry(Widget, XEvent*); -static void Layout(Widget, Dimension*, Dimension*); -static void MakeResizeRequest(Widget); -static void MakeSetValuesRequest(Widget, unsigned int, unsigned int); -static void MoveMenu(Widget, int, int); -static void PositionMenu(Widget, XPoint*); - -/* - * Actions - */ -static void Highlight(Widget, XEvent*, String*, Cardinal*); -static void Notify(Widget, XEvent*, String*, Cardinal*); -#ifndef OLDXAW -static void Popdown(Widget, XEvent*, String*, Cardinal*); -#endif -static void PositionMenuAction(Widget, XEvent*, String*, Cardinal*); -static void Unhighlight(Widget, XEvent*, String*, Cardinal*); - -/* - * Initialization - */ -#define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field) - -static XtResource resources[] = { - /* label */ - { - XtNlabel, - XtCLabel, - XtRString, - sizeof(String), - offset(label_string), - XtRString, - NULL - }, - { - XtNlabelClass, - XtCLabelClass, - XtRPointer, - sizeof(WidgetClass), - offset(label_class), - XtRImmediate, - NULL - }, - - /* layout */ - { - XtNrowHeight, - XtCRowHeight, - XtRDimension, - sizeof(Dimension), - offset(row_height), - XtRImmediate, - (XtPointer)0 - }, - { - XtNtopMargin, - XtCVerticalMargins, - XtRDimension, - sizeof(Dimension), - offset(top_margin), - XtRImmediate, - (XtPointer)0 - }, - { - XtNbottomMargin, - XtCVerticalMargins, - XtRDimension, - sizeof(Dimension), - offset(bottom_margin), - XtRImmediate, - (XtPointer)0 - }, -#ifndef OLDXAW - { - XtNleftMargin, - XtCHorizontalMargins, - XtRDimension, - sizeof(Dimension), - offset(left_margin), - XtRImmediate, - (XtPointer)0 - }, - { - XtNrightMargin, - XtCHorizontalMargins, - XtRDimension, - sizeof(Dimension), - offset(right_margin), - XtRImmediate, - (XtPointer)0 - }, -#endif - - /* misc */ - { - XtNallowShellResize, - XtCAllowShellResize, - XtRBoolean, - sizeof(Boolean), - XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize), - XtRImmediate, - (XtPointer)True - }, - { - XtNcursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - offset(cursor), - XtRImmediate, - (XtPointer)None - }, - { - XtNmenuOnScreen, - XtCMenuOnScreen, - XtRBoolean, - sizeof(Boolean), - offset(menu_on_screen), - XtRImmediate, - (XtPointer)True - }, - { - XtNpopupOnEntry, - XtCPopupOnEntry, - XtRWidget, - sizeof(Widget), - offset(popup_entry), - XtRWidget, - NULL - }, - { - XtNbackingStore, - XtCBackingStore, - XtRBackingStore, - sizeof(int), - offset(backing_store), - XtRImmediate, - (XtPointer)(Always + WhenMapped + NotUseful) - }, -#ifndef OLDXAW - { - XawNdisplayList, - XawCDisplayList, - XawRDisplayList, - sizeof(XawDisplayList*), - offset(display_list), - XtRImmediate, - NULL - }, -#endif -}; -#undef offset - -static char defaultTranslations[] = -"<Enter>:" "highlight()\n" -"<Leave>:" "unhighlight()\n" -"<BtnMotion>:" "highlight()\n" -#ifndef OLDXAW -"<BtnUp>:" "popdown() notify() unhighlight()\n" -#else -"<BtnUp>:" "MenuPopdown() notify() unhighlight()\n" -#endif -; - -static XtActionsRec actionsList[] = -{ - {"notify", Notify}, - {"highlight", Highlight}, - {"unhighlight", Unhighlight}, -#ifndef OLDXAW - {"popdown", Popdown}, - {"set-values", XawSetValuesAction}, - {"get-values", XawGetValuesAction}, - {"declare", XawDeclareAction}, - {"call-proc", XawCallProcAction}, -#endif -}; - -static CompositeClassExtensionRec extension_rec = { - NULL, /* next_extension */ - NULLQUARK, /* record_type */ - XtCompositeExtensionVersion, /* version */ - sizeof(CompositeClassExtensionRec), /* record_size */ - True, /* accepts_objects */ -}; - -#define Superclass (&overrideShellClassRec) -SimpleMenuClassRec simpleMenuClassRec = { - /* core */ - { - (WidgetClass)Superclass, /* superclass */ - "SimpleMenu", /* class_name */ - sizeof(SimpleMenuRec), /* size */ - XawSimpleMenuClassInitialize, /* class_initialize */ - XawSimpleMenuClassPartInitialize, /* class_part_initialize */ - False, /* class_inited */ - XawSimpleMenuInitialize, /* initialize */ - NULL, /* initialize_hook */ - XawSimpleMenuRealize, /* realize */ - actionsList, /* actions */ - XtNumber(actionsList), /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resources */ - NULLQUARK, /* xrm_class */ - True, /* compress_motion */ - True, /* compress_exposure */ - True, /* compress_enterleave */ - False, /* visible_interest */ - NULL, /* destroy */ - XawSimpleMenuResize, /* resize */ - XawSimpleMenuRedisplay, /* expose */ - XawSimpleMenuSetValues, /* set_values */ - XawSimpleMenuSetValuesHook, /* set_values_hook */ - XtInheritSetValuesAlmost, /* set_values_almost */ - NULL, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* intrinsics version */ - NULL, /* callback offsets */ - defaultTranslations, /* tm_table */ - NULL, /* query_geometry */ - NULL, /* display_accelerator */ - NULL, /* extension */ - }, - /* composite */ - { - XawSimpleMenuGeometryManager, /* geometry_manager */ - XawSimpleMenuChangeManaged, /* change_managed */ - XtInheritInsertChild, /* insert_child */ - XtInheritDeleteChild, /* delete_child */ - NULL, /* extension */ - }, - /* shell */ - { - NULL, /* extension */ - }, - /* override */ - { - NULL, /* extension */ - }, - /* simple_menu */ - { - NULL, /* extension */ - }, -}; - -WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec; - -/* - * Implementation - */ -/* - * Function: - * XawSimpleMenuClassInitialize - * - * Description: - * Class Initialize routine, called only once. - */ -static void -XawSimpleMenuClassInitialize(void) -{ - XawInitializeWidgetSet(); - XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, - NULL, 0); - XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString, - NULL, 0, XtCacheNone, NULL); - XmuAddInitializer(AddPositionAction, NULL); -} - -/* - * Function: - * XawSimpleMenuClassPartInitialize - * Arguments: wc - the widget class of the subclass. - * - * Description: - * Class Part Initialize routine, called for every subclass. Makes - * sure that the subclasses pick up the extension record. - */ -static void -XawSimpleMenuClassPartInitialize(WidgetClass wc) -{ - SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc; - - /* - * Make sure that our subclass gets the extension rec too - */ - extension_rec.next_extension = smwc->composite_class.extension; - smwc->composite_class.extension = (XtPointer) &extension_rec; -} - -/* - * Function: - * XawSimpleMenuInitialize - * - * Parameters: - * request - widget requested by the argument list - * cnew - new widget with both resource and non resource values - * - * Description: - * Initializes the simple menu widget. - */ -/*ARGSUSED*/ -static void -XawSimpleMenuInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)cnew; - Dimension width, height; - - XmuCallInitializers(XtWidgetToApplicationContext(cnew)); - - if (smw->simple_menu.label_class == NULL) - smw->simple_menu.label_class = smeBSBObjectClass; - - smw->simple_menu.label = NULL; - smw->simple_menu.entry_set = NULL; - smw->simple_menu.recursive_set_values = False; -#ifndef OLDXAW - smw->simple_menu.sub_menu = NULL; - smw->simple_menu.state = 0; - - XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL); -#endif - - if (smw->simple_menu.label_string != NULL) - CreateLabel(cnew); - - width = height = 0; - CalculateNewSize(cnew, &width, &height); - - smw->simple_menu.menu_width = True; - - if (XtWidth(smw) == 0) { - smw->simple_menu.menu_width = False; - XtWidth(smw) = width; - } - - smw->simple_menu.menu_height = True; - - if (XtHeight(smw) == 0) { - smw->simple_menu.menu_height = False; - XtHeight(smw) = height; - } - - /* - * Add a popup_callback routine for changing the cursor - */ - XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL); -} - -/* - * Function: - * XawSimpleMenuRedisplay - * - * Parameters: - * w - simple menu widget - * event - X event that caused this redisplay - * region - region the needs to be repainted - * - * Description: - * Redisplays the contents of the widget. - */ -/*ARGSUSED*/ -static void -XawSimpleMenuRedisplay(Widget w, XEvent *event, Region region) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - SmeObject *entry; - SmeObjectClass cclass; - - if (region == NULL) - XClearWindow(XtDisplay(w), XtWindow(w)); - -#ifndef OLDXAW - if (smw->simple_menu.display_list) - XawRunDisplayList(w, smw->simple_menu.display_list, event, region); -#endif - - /* - * Check and Paint each of the entries - including the label - */ - ForAllChildren(smw, entry) { - if (!XtIsManaged((Widget)*entry)) - continue; - - if (region != NULL) - switch(XRectInRegion(region, XtX(*entry),XtY(*entry), - XtWidth(*entry), XtHeight(*entry))) { - case RectangleIn: - case RectanglePart: - break; - default: - continue; - } - - cclass = (SmeObjectClass)(*entry)->object.widget_class; - - if (cclass->rect_class.expose != NULL) - (cclass->rect_class.expose)((Widget)*entry, NULL, NULL); - } -} - -/* - * Function: - * XawSimpleMenuRealize - * - * Parameters: - * w - simple menu widget - * mask - value mask for the window to create - * attrs - attributes for the window to create - * - * Description: - * Realizes the widget. - */ -static void -XawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; -#ifndef OLDXAW - XawPixmap *pixmap; -#endif - - attrs->cursor = smw->simple_menu.cursor; - *mask |= CWCursor; - if (smw->simple_menu.backing_store == Always || - smw->simple_menu.backing_store == NotUseful || - smw->simple_menu.backing_store == WhenMapped) { - *mask |= CWBackingStore; - attrs->backing_store = smw->simple_menu.backing_store; - } - else - *mask &= ~CWBackingStore; - - (*Superclass->core_class.realize)(w, mask, attrs); - -#ifndef OLDXAW - if (w->core.background_pixmap > XtUnspecifiedPixmap) { - pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w), - w->core.colormap, w->core.depth); - if (pixmap && pixmap->mask) - XawReshapeWidget(w, pixmap); - } -#endif -} - -/* - * Function: - * XawSimpleMenuResize - * - * Parameters: - * w - simple menu widget - * - * Description: - * Handle the menu being resized. - */ -static void -XawSimpleMenuResize(Widget w) -{ - if (!XtIsRealized(w)) - return; - - Layout(w, NULL, NULL); - - XawSimpleMenuRedisplay(w, NULL, NULL); -} - -/* - * Function: - * XawSimpleMenuSetValues - * - * Parameters: - * current - current state of the widget - * request - what was requested - * cnew - what the widget will become - * - * Description: - * Relayout the menu when one of the resources is changed. - */ -/*ARGSUSED*/ -static Boolean -XawSimpleMenuSetValues(Widget current, Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - SimpleMenuWidget smw_old = (SimpleMenuWidget)current; - SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew; - Boolean ret_val = False, layout = False; - - if (!XtIsRealized(current)) - return (False); - - if (!smw_new->simple_menu.recursive_set_values) { - if (XtWidth(smw_new) != XtWidth(smw_old)) { - smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0; - layout = True; - } - if (XtHeight(smw_new) != XtHeight(smw_old)) { - smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0; - layout = True; - } - } - - if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor) - XDefineCursor(XtDisplay(cnew), XtWindow(cnew), - smw_new->simple_menu.cursor); - - if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) { - if (smw_new->simple_menu.label_string == NULL) /* Destroy */ - XtDestroyWidget((Widget)smw_old->simple_menu.label); - else if (smw_old->simple_menu.label_string == NULL) /* Create */ - CreateLabel(cnew); - else { /* Change */ - Arg arglist[1]; - - XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string); - XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE); - } - } - - if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class) - XtAppWarning(XtWidgetToApplicationContext(cnew), - "No Dynamic class change of the SimpleMenu Label."); - - if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin - || smw_old->simple_menu.bottom_margin - != smw_new->simple_menu.bottom_margin) { - layout = True; - ret_val = True; - } - -#ifndef OLDXAW - if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) { - XawPixmap *opix, *npix; - - opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap, - XtScreen(smw_old), smw_old->core.colormap, - smw_old->core.depth); - npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap, - XtScreen(smw_new), smw_new->core.colormap, - smw_new->core.depth); - if ((npix && npix->mask) || (opix && opix->mask)) - XawReshapeWidget(cnew, npix); - } -#endif - - if (layout) - Layout(cnew, NULL, NULL); - - return (ret_val); -} - -/* - * Function: - * XawSimpleMenuSetValuesHook - * - * Parameters: - * w - menu widget - * arglist - argument list passed to XtSetValues - * num_args - number of args - * - * Description: - * To handle a special case, this is passed the actual arguments. - */ -static Boolean -XawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args) -{ - Cardinal i; - Dimension width, height; - - width = XtWidth(w); - height = XtHeight(w); - - for (i = 0 ; i < *num_args ; i++) { - if (streq(arglist[i].name, XtNwidth)) - width = (Dimension)arglist[i].value; - if (streq(arglist[i].name, XtNheight)) - height = (Dimension) arglist[i].value; - } - - if (width != XtWidth(w) || height != XtHeight(w)) - MakeSetValuesRequest(w, width, height); - - return (False); -} - -/* - * Geometry Management routines - */ -/* - * Function: - * XawSimpleMenuGeometryManager - * - * Parameters: - * w - Menu Entry making the request - * request - requested new geometry - * reply - the allowed geometry. - * - * Description: - * This is the SimpleMenu Widget's Geometry Manager. - * - * Returns: - * XtGeometry{Yes, No, Almost} - */ -static XtGeometryResult -XawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request, - XtWidgetGeometry *reply) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w); - SmeObject entry = (SmeObject)w; - XtGeometryMask mode = request->request_mode; - XtGeometryResult answer; - Dimension old_height, old_width; - - if (!(mode & CWWidth) && !(mode & CWHeight)) - return (XtGeometryNo); - - reply->width = request->width; - reply->height = request->height; - - old_width = XtWidth(entry); - old_height = XtHeight(entry); - - Layout(w, &reply->width, &reply->height); - - /* - * Since we are an override shell and have no parent there is no one to - * ask to see if this geom change is okay, so I am just going to assume - * we can do whatever we want. If you subclass be very careful with this - * assumption, it could bite you. - * - * Chris D. Peterson - Sept. 1989. - */ - if ((!(mode & CWWidth) || reply->width == request->width) - && (!(mode & CWHeight) || reply->height == request->height)) { - if (mode & XtCWQueryOnly) { /* Actually perform the layout */ - XtWidth(entry) = old_width; - XtHeight(entry) = old_height; - } - else - Layout((Widget)smw, NULL, NULL); - answer = XtGeometryDone; - } - else { - XtWidth(entry) = old_width; - XtHeight(entry) = old_height; - - if ((reply->width == request->width && !(mode & CWHeight)) - || (reply->height == request->height && !(mode & CWWidth)) - || (reply->width == request->width - && reply->height == request->height)) - answer = XtGeometryNo; - else { - answer = XtGeometryAlmost; - reply->request_mode = 0; - if (reply->width != request->width) - reply->request_mode |= CWWidth; - if (reply->height != request->height) - reply->request_mode |= CWHeight; - } - } - - return (answer); -} - -/* - * Function: - * XawSimpleMenuChangeManaged - * - * Parameters: - * w - simple menu widget - * - * Description: - * Called whenever a new child is managed. - */ -static void -XawSimpleMenuChangeManaged(Widget w) -{ - Layout(w, NULL, NULL); -} - -/* - * Global Action Routines - * - * These actions routines will be added to the application's - * global action list - */ -/* - * Function: - * PositionMenuAction - * - * Parameters: - * w - a widget (no the simple menu widget) - * event - the event that caused this action - * params - parameters passed to the routine. - * we expect the name of the menu here. - * num_params - "" - * - * Description: - * Positions the simple menu widget. - */ -/*ARGSUSED*/ -static void -PositionMenuAction(Widget w, XEvent *event, - String *params, Cardinal *num_params) -{ - Widget menu; - XPoint loc; - - if (*num_params != 1) { - XtAppWarning(XtWidgetToApplicationContext(w), - "SimpleMenuWidget: position menu action expects " - "only one parameter which is the name of the menu."); - return; - } - - if ((menu = FindMenu(w, params[0])) == NULL) { - char error_buf[BUFSIZ]; - - (void)XmuSnprintf(error_buf, sizeof(error_buf), - "SimpleMenuWidget: could not find menu named %s.", - params[0]); - XtAppWarning(XtWidgetToApplicationContext(w), error_buf); - return; - } - - switch (event->type) { - case ButtonPress: - case ButtonRelease: - loc.x = event->xbutton.x_root; - loc.y = event->xbutton.y_root; - PositionMenu(menu, &loc); - break; - case EnterNotify: - case LeaveNotify: - loc.x = event->xcrossing.x_root; - loc.y = event->xcrossing.y_root; - PositionMenu(menu, &loc); - break; - case MotionNotify: - loc.x = event->xmotion.x_root; - loc.y = event->xmotion.y_root; - PositionMenu(menu, &loc); - break; - default: - PositionMenu(menu, NULL); - break; - } -} - -/* - * Widget Action Routines - */ -/* - * Function: - * Unhighlight - * - * Parameters: - * w - simple menu widget - * event - event that caused this action - * params - not used - * num_params - "" - * - * Description: - * Unhighlights current entry. - */ -/*ARGSUSED*/ -static void -Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - SmeObject entry = smw->simple_menu.entry_set; - - if (entry == NULL) - return; - -#ifndef OLDXAW - if (!smw->simple_menu.sub_menu) -#endif - { - SmeObjectClass cclass; - - smw->simple_menu.entry_set = NULL; - cclass = (SmeObjectClass)entry->object.widget_class; - (cclass->sme_class.unhighlight)((Widget)entry); - } -} - -/* - * Function: - * Highlight - * - * Parameters: - * w - simple menu widget - * event - event that caused this action - * params - not used - * num_params - "" - * - * Description: - * Highlights current entry. - */ -/*ARGSUSED*/ -static void -Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - SmeObject entry; - - if (!XtIsSensitive(w)) - return; - - entry = GetEventEntry(w, event); - - if (entry == smw->simple_menu.entry_set) - return; - -#ifndef OLDXAW - if (!smw->simple_menu.sub_menu) -#endif - Unhighlight(w, event, params, num_params); - - if (entry == NULL) - return; - - if (!XtIsSensitive((Widget)entry)) - return; - -#ifndef OLDXAW - if (smw->simple_menu.sub_menu) - PopdownSubMenu(smw); -#endif - - Unhighlight(w, event, params, num_params); - -#ifndef OLDXAW - if (!(smw->simple_menu.state & SMW_UNMAPPING)) -#endif - { - SmeObjectClass cclass; - - smw->simple_menu.entry_set = entry; - cclass = (SmeObjectClass)entry->object.widget_class; - - (cclass->sme_class.highlight)((Widget)entry); - -#ifndef OLDXAW - if (XtIsSubclass((Widget)entry, smeBSBObjectClass)) - PopupSubMenu(smw); -#endif - } -} - -/* - * Function: - * Notify - * - * Parameters: - * w - simple menu widget - * event - event that caused this action - * params - not used - * num_params - "" - * - * Description: - * Notify user of current entry. - */ -/*ARGSUSED*/ -static void -Notify(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - SmeObject entry; - SmeObjectClass cclass; - - /* may be a propagated event from a sub menu, need to check it */ - if (XtWindow(w) != event->xany.window) - return; - entry = GetEventEntry(w, event); - if (entry == NULL || !XtIsSensitive((Widget)entry)) - return; - - cclass = (SmeObjectClass) entry->object.widget_class; - (cclass->sme_class.notify)((Widget)entry); -} - -/* - * Public Functions - */ -/* - * Function: - * XawSimpleMenuAddGlobalActions - * - * Arguments: - * app_con - appcontext - * - * Description: - * Adds the global actions to the simple menu widget. - */ -void -XawSimpleMenuAddGlobalActions(XtAppContext app_con) -{ - XtInitializeWidgetClass(simpleMenuWidgetClass); - XmuCallInitializers(app_con); -} - -/* - * Function: - * XawSimpleMenuGetActiveEntry - * - * Parameters: - * w - smw widget - * - * Description: - * Gets the currently active (set) entry. - * - * Returns: - * The currently set entry or NULL if none is set - */ -Widget -XawSimpleMenuGetActiveEntry(Widget w) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - - return ((Widget)smw->simple_menu.entry_set); -} - -/* - * Function: - * XawSimpleMenuClearActiveEntry - * - * Parameters: - * w - smw widget - * - * Description: - * Unsets the currently active (set) entry. - */ -void -XawSimpleMenuClearActiveEntry(Widget w) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - - smw->simple_menu.entry_set = NULL; -} - -/* - * Private Functions - */ -/* - * Function: - * CreateLabel - * - * Parameters: - * w - smw widget - * - * Description: - * Creates the label object and makes sure it is the first child in - * in the list. - */ -static void -CreateLabel(Widget w) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - Widget *child, *next_child; - int i; - Arg args[2]; - - if (smw->simple_menu.label_string == NULL || - smw->simple_menu.label != NULL) { - XtAppWarning(XtWidgetToApplicationContext(w), - "Xaw Simple Menu Widget: label string is NULL or " - "label already exists, no label is being created."); - return; - } - - XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string); - XtSetArg(args[1], XtNjustify, XtJustifyCenter); - smw->simple_menu.label = (SmeObject) - XtCreateManagedWidget("menuLabel", - smw->simple_menu.label_class, w, args, TWO); - - next_child = NULL; - for (child = smw->composite.children + smw->composite.num_children, - i = smw->composite.num_children; i > 0; i--, child--) { - if (next_child != NULL) - *next_child = *child; - next_child = child; - } - *child = (Widget)smw->simple_menu.label; -} - -/* - * Function: - * Layout - * - * Arguments: - * w - See below - * width_ret - returned width - * height_ret - returned height - * - * Note: - * if width == NULL || height == NULL then it assumes the you do not care - * about the return values, and just want a relayout. - * - * if this is not the case then it will set width_ret and height_ret - * to be width and height that the child would get if it were layed out - * at this time. - * - * "w" can be the simple menu widget or any of its object children. - */ -static void -Layout(Widget w, Dimension *width_ret, Dimension *height_ret) -{ - SmeObject current_entry; - SimpleMenuWidget smw; - Dimension width, height; - Boolean allow_change_size; - Widget kid; - Cardinal i, count, n; - int width_kid, height_kid, tmp_w, tmp_h; - short vadd, hadd, x_ins, y_ins; - Dimension *widths; - - height = 0; - - if (XtIsSubclass(w, simpleMenuWidgetClass)) { - smw = (SimpleMenuWidget)w; - current_entry = NULL; - } - else { - smw = (SimpleMenuWidget)XtParent(w); - current_entry = (SmeObject)w; - } - - allow_change_size = (!XtIsRealized((Widget)smw) - || smw->shell.allow_shell_resize); - - for (i = smw->simple_menu.label ? 1 : 0; - i < smw->composite.num_children; - i++) { - XtWidgetGeometry preferred; - - kid = smw->composite.children[i]; - if (!XtIsManaged(kid)) - continue; - if (smw->simple_menu.row_height != 0) - XtHeight(kid) = smw->simple_menu.row_height; - XtQueryGeometry(kid, NULL, &preferred); - if (preferred.request_mode & CWWidth) - XtWidth(kid) = preferred.width; - } - - if (smw->simple_menu.label - && XtIsManaged((Widget)smw->simple_menu.label)) { - XtWidgetGeometry preferred; - - kid = (Widget)smw->simple_menu.label; - XtQueryGeometry(kid, NULL, &preferred); - if (preferred.request_mode & CWWidth) - XtWidth(kid) = preferred.width; - if (preferred.request_mode & CWHeight) - XtHeight(kid) = preferred.height; - } - - /* reset */ - if (!smw->simple_menu.menu_width) - XtWidth(smw) = 0; - if (!smw->simple_menu.menu_height) - XtHeight(smw) = 0; - if (!XtWidth(smw) || !XtHeight(smw)) - MakeResizeRequest((Widget)smw); - - widths = (Dimension *)XtMalloc(sizeof(Dimension)); -#ifndef OLDXAW - hadd = smw->simple_menu.left_margin; -#else - hadd = 0; -#endif - vadd = smw->simple_menu.top_margin; - if (smw->simple_menu.label) - vadd += XtHeight(smw->simple_menu.label); - - count = 1; - width = tmp_w = tmp_h = n = 0; - height = vadd; - - for (i = smw->simple_menu.label ? 1 : 0; - i < smw->composite.num_children; - i++) { - kid = smw->composite.children[i]; - if (!XtIsManaged(kid)) - continue; - width_kid = XtWidth(kid); - height_kid = XtHeight(kid); - - if (n && (height + height_kid + smw->simple_menu.bottom_margin - > XtHeight(smw))) { - ++count; - widths = (Dimension *)XtRealloc((char *)widths, - sizeof(Dimension) * count); - widths[count - 1] = width_kid; - width += tmp_w; - tmp_w = width_kid; - height = height_kid + vadd; - } - else - height += height_kid; - if (height > tmp_h) - tmp_h = height; - if (width_kid > tmp_w) - widths[count - 1] = tmp_w = width_kid; - ++n; - } - - height = tmp_h + smw->simple_menu.bottom_margin; - width += tmp_w; - - if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) { - float inc; - - inc = (XtWidth(smw->simple_menu.label) - width) / (float)count; - width = XtWidth(smw->simple_menu.label); - for (n = 0; n < count; n++) - widths[n] += inc; - } - -#ifndef OLDXAW - width += hadd + smw->simple_menu.right_margin; -#endif - - x_ins = n = count = 0; - tmp_w = widths[0]; - tmp_h = vadd; - - for (i = smw->simple_menu.label ? 1 : 0; - i < smw->composite.num_children; - i++) { - kid = smw->composite.children[i]; - if (!XtIsManaged(kid)) - continue; - - height_kid = XtHeight(kid); - - if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin - > XtHeight(smw))) { - x_ins = tmp_w; - y_ins = vadd; - ++count; - tmp_w += widths[count]; - tmp_h = height_kid + vadd; - } - else { - y_ins = tmp_h; - tmp_h += height_kid; - } - ++n; - - XtX(kid) = x_ins + hadd; - XtY(kid) = y_ins; - XtWidth(kid) = widths[count]; - } - - XtFree((char *)widths); - - if (allow_change_size) - MakeSetValuesRequest((Widget) smw, width, height); - - if (smw->simple_menu.label) { - XtX(smw->simple_menu.label) = 0; - XtY(smw->simple_menu.label) = smw->simple_menu.top_margin; - XtWidth(smw->simple_menu.label) = XtWidth(smw) -#ifndef OLDXAW - - (smw->simple_menu.left_margin + smw->simple_menu.right_margin) -#endif - ; - } - if (current_entry) { - if (width_ret) - *width_ret = XtWidth(current_entry); - if (height_ret) - *height_ret = XtHeight(current_entry); - } -} - -/* - * Function: - * AddPositionAction - * - * Parameters: - * app_con - application context - * data - (not used) - * - * Description: - * Adds the XawPositionSimpleMenu action to the global - * action list for this appcon. - */ -/*ARGSUSED*/ -static void -AddPositionAction(XtAppContext app_con, XPointer data) -{ - static XtActionsRec pos_action[] = { - {"XawPositionSimpleMenu", PositionMenuAction}, - }; - - XtAppAddActions(app_con, pos_action, XtNumber(pos_action)); -} - -/* - * Function: - * FindMenu - * - * Parameters: - * widget - reference widget - * name - menu widget's name - * - * Description: - * Find the menu give a name and reference widget - * - * Returns: - * The menu widget or NULL. - */ -static Widget -FindMenu(Widget widget, String name) -{ - Widget w, menu; - - for (w = widget; w != NULL; w = XtParent(w)) - if ((menu = XtNameToWidget(w, name)) != NULL) - return (menu); - - return (NULL); -} - -/* - * Function: - * PositionMenu - * - * Parameters: - * w - simple menu widget - * location - pointer the the position or NULL - * - * Description: - * Places the menu - */ -static void -PositionMenu(Widget w, XPoint *location) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - SmeObject entry; - XPoint t_point; - - if (location == NULL) { - Window temp1, temp2; - int root_x, root_y, tempX, tempY; - unsigned int tempM; - - location = &t_point; - if (XQueryPointer(XtDisplay(w), XtWindow(w), &temp1, &temp2, - &root_x, &root_y, &tempX, &tempY, &tempM) == False) { - XtAppWarning(XtWidgetToApplicationContext(w), - "Xaw Simple Menu Widget: " - "Could not find location of mouse pointer"); - return; - } - location->x = (short) root_x; - location->y = (short) root_y; - } - - /* - * The width will not be correct unless it is realized - */ - XtRealizeWidget(w); - - location->x -= XtWidth(w) >> 1; - - if (smw->simple_menu.popup_entry == NULL) - entry = smw->simple_menu.label; - else - entry = smw->simple_menu.popup_entry; - - if (entry != NULL) - location->y -= XtY(entry) + (XtHeight(entry) >> 1); - - MoveMenu(w, location->x, location->y); -} - -/* - * Function: - * MoveMenu - * - * Parameters: - * w - simple menu widget - * x - current location of the widget - * y - "" - * - * Description: - * Actually moves the menu, may force it to - * to be fully visable if menu_on_screen is True. - */ -static void -MoveMenu(Widget w, int x, int y) -{ - Arg arglist[2]; - Cardinal num_args = 0; - SimpleMenuWidget smw = (SimpleMenuWidget)w; - - if (smw->simple_menu.menu_on_screen) { - int width = XtWidth(w) + (XtBorderWidth(w) << 1); - int height = XtHeight(w) + (XtBorderWidth(w) << 1); - - if (x >= 0) { - int scr_width = WidthOfScreen(XtScreen(w)); - - if (x + width > scr_width) - x = scr_width - width; - } - if (x < 0) - x = 0; - - if (y >= 0) { - int scr_height = HeightOfScreen(XtScreen(w)); - - if (y + height > scr_height) - y = scr_height - height; - } - if (y < 0) - y = 0; - } - - XtSetArg(arglist[num_args], XtNx, x); num_args++; - XtSetArg(arglist[num_args], XtNy, y); num_args++; - XtSetValues(w, arglist, num_args); -} - -/* - * Function: - * ChangeCursorOnGrab - * - * Parameters: - * w - menu widget - * temp1 - not used - * temp2 - "" - * - * Description: - * Changes the cursor on the active grab to the one - * specified in out resource list. - */ -/*ARGSUSED*/ -static void -ChangeCursorOnGrab(Widget w, XtPointer temp1, XtPointer temp2) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - - /* - * The event mask here is what is currently in the MIT implementation. - * There really needs to be a way to get the value of the mask out - * of the toolkit (CDP 5/26/89). - */ - XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask | ButtonReleaseMask, - smw->simple_menu.cursor, - XtLastTimestampProcessed(XtDisplay(w))); -} - -/* - * Function: - * MakeSetValuesRequest - * - * Parameters: - * w - simple menu widget - * width - size requested - * height - "" - */ -static void -MakeSetValuesRequest(Widget w, unsigned int width, unsigned int height) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - Arg arglist[2]; - Cardinal num_args = 0; - - if (!smw->simple_menu.recursive_set_values) { - if (XtWidth(smw) != width || XtHeight(smw) != height) { - smw->simple_menu.recursive_set_values = True; - XtSetArg(arglist[num_args], XtNwidth, width); num_args++; - XtSetArg(arglist[num_args], XtNheight, height); num_args++; - XtSetValues(w, arglist, num_args); - } - else if (XtIsRealized((Widget)smw)) - XawSimpleMenuRedisplay((Widget)smw, NULL, NULL); - } - smw->simple_menu.recursive_set_values = False; -} - -static SmeObject -DoGetEventEntry(Widget w, int x_loc, int y_loc) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - SmeObject *entry; - - ForAllChildren(smw, entry) { - if (!XtIsManaged((Widget)*entry)) - continue; - - if (x_loc > XtX(*entry) - && x_loc <= XtX(*entry) + XtWidth(*entry) - && y_loc > XtY(*entry) - && y_loc <= XtY(*entry) + XtHeight(*entry)) { - if (*entry == smw->simple_menu.label) - return (NULL); /* cannot select the label */ - else - return (*entry); - } - } - - return (NULL); -} - -/* - * Function: - * GetEventEntry - * - * Parameters: - * w - simple menu widget - * event - X event - * - * Description: - * Gets an entry given an event that has X and Y coords. - * - * Returns: - * The entry that this point is in - */ -static SmeObject -GetEventEntry(Widget w, XEvent *event) -{ - int x_loc, y_loc, x_root; - SimpleMenuWidget smw = (SimpleMenuWidget)w; - SmeObject entry; - int warp, move; - - switch (event->type) { - case MotionNotify: - x_loc = event->xmotion.x; - y_loc = event->xmotion.y; - x_root = event->xmotion.x_root; - break; - case EnterNotify: - case LeaveNotify: - x_loc = event->xcrossing.x; - y_loc = event->xcrossing.y; - x_root = event->xcrossing.x_root; - break; - case ButtonPress: - case ButtonRelease: - x_loc = event->xbutton.x; - y_loc = event->xbutton.y; - x_root = event->xbutton.x_root; - break; - default: - XtAppError(XtWidgetToApplicationContext(w), - "Unknown event type in GetEventEntry()."); - return (NULL); - } - - if (x_loc < 0 || x_loc >= XtWidth(smw) || - y_loc < 0 || y_loc >= XtHeight(smw)) - return (NULL); - - /* Move the menu if it's outside the screen, does not check - * smw->simple_menu.menu_on_screen because menus is bigger than screen - */ - if (x_root == WidthOfScreen(XtScreen(w)) - 1 && - XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) { - warp = -8; - if (smw->simple_menu.entry_set) { - entry = DoGetEventEntry(w, - XtX(smw->simple_menu.entry_set) - + XtWidth(smw->simple_menu.entry_set) + 1, - y_loc); - Unhighlight(w, event, NULL, NULL); - if (entry) { - warp = -(int)XtWidth(entry) >> 1; - move = x_loc - XtWidth(entry) - XtX(entry) + XtBorderWidth(w); - } - else { - warp = 0; - move = WidthOfScreen(XtScreen(w)) - - (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1)); - } - } - else { - warp = 0; - move = WidthOfScreen(XtScreen(w)) - - (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1)); - } - } - else if (x_root == 0 && XtX(w) < 0) { - warp = 8; - if (smw->simple_menu.entry_set) { - entry = DoGetEventEntry(w, XtX(smw->simple_menu.entry_set) - 1, - y_loc); - Unhighlight(w, event, NULL, NULL); - if (entry) { - warp = XtWidth(entry) >> 1; - move = x_loc - XtX(entry); - } - else - move = x_loc + XtBorderWidth(w); - } - else - move = x_loc + XtBorderWidth(w); - } - else - move = warp = 0; - - if (move) - XtMoveWidget(w, XtX(w) + move, XtY(w)); - if (warp) - XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, warp, 0); - - return (DoGetEventEntry(w, x_loc, y_loc)); -} - -static void -CalculateNewSize(Widget w, Dimension *width_return, Dimension *height_return) -{ - SimpleMenuWidget xaw = (SimpleMenuWidget)w; - Widget kid; - Cardinal i; - int width_kid, height_kid; - int width, height, tmp_w, tmp_h, max_dim; - short vadd, hadd; - int n, columns, test_h, num_children = 0; - Boolean try_layout = False; - -#ifndef OLDXAW - hadd = xaw->simple_menu.left_margin + xaw->simple_menu.right_margin; -#else - hadd = 0; -#endif - vadd = xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin; - if (xaw->simple_menu.label) - vadd += XtHeight(xaw->simple_menu.label); - - if (*height_return) - max_dim = *height_return; - else if (!XtHeight(w)) { - max_dim = HeightOfScreen(XtScreen(w)); - try_layout = True; - } - else - max_dim = XtHeight(w); - max_dim -= vadd; - - width = height = tmp_w = tmp_h = n = test_h = 0; - columns = 1; - for (i = xaw->simple_menu.label ? 1 : 0; - i < xaw->composite.num_children; - i++) { - kid = xaw->composite.children[i]; - if (!XtIsManaged(kid)) - continue; - ++num_children; - width_kid = XtWidth(kid); - height_kid = XtHeight(kid); - - if (try_layout) { - if (!test_h) - test_h = height_kid; - else if (test_h != height_kid) - try_layout = False; - } - - if (n && (height + height_kid > max_dim)) { - ++columns; - width += tmp_w; - tmp_w = width_kid; - height = height_kid; - } - else - height += height_kid; - if (height > tmp_h) - tmp_h = height; - if (width_kid > tmp_w) - tmp_w = width_kid; - ++n; - } - - height = tmp_h + vadd; - width += tmp_w + hadd; - - if (xaw->simple_menu.label) - width = XawMax(width, XtWidth(xaw->simple_menu.label) + hadd); - - *width_return = width; - *height_return = height; - - if (try_layout && columns > 1 && num_children > 2) { - int space; - - height = test_h * (xaw->simple_menu.label ? - num_children - 1 : - num_children); - - max_dim -= max_dim % test_h; - space = max_dim - (height % max_dim); - if (space >= test_h * columns) { - height = max_dim - space / columns; - if (height % test_h) - height += test_h - (height % test_h); - *height_return = height + vadd; - CalculateNewSize(w, width_return, height_return); - } - } -} - -static void -MakeResizeRequest(Widget w) -{ - int tries; - Dimension width, height; - - width = XtWidth(w); - height = XtHeight(w); - - for (tries = 0; tries < 100; tries++) { - CalculateNewSize(w, &width, &height); - if (width == XtWidth(w) && height == XtHeight(w)) - break; - if (XtMakeResizeRequest(w, width, height, &width, &height) == - XtGeometryNo) - break; - } -} - -#ifndef OLDXAW -static void -Popdown(Widget w, XEvent *event, String *params, Cardinal *num_params) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - - while (XtParent(w) && - XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) { - if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) { - w = XtParent(w); - smw = (SimpleMenuWidget)w; - smw->simple_menu.entry_set = NULL; - } - else - break; - } - - smw->simple_menu.state |= SMW_UNMAPPING; - if (smw->simple_menu.sub_menu) - PopdownSubMenu(smw); - XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params); -} - -static void -PopupSubMenu(SimpleMenuWidget smw) -{ - Arg args[2]; - Cardinal num_args; - Widget menu; - SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set; - Position menu_x, menu_y; - Bool popleft; - - if (entry->sme_bsb.menu_name == NULL) - return; - - if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL) - return; - - smw->simple_menu.sub_menu = menu; - - if (!XtIsRealized(menu)) - XtRealizeWidget(menu); - - popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0; - - if (popleft) - XtTranslateCoords((Widget)smw, -(int)XtWidth(menu), - XtY(entry) - XtBorderWidth(menu), &menu_x, &menu_y); - else - XtTranslateCoords((Widget)smw, XtWidth(smw), XtY(entry) - - XtBorderWidth(menu), &menu_x, &menu_y); - - if (!popleft && menu_x >= 0) { - int scr_width = WidthOfScreen(XtScreen(menu)); - - if (menu_x + XtWidth(menu) > scr_width) { - menu_x -= XtWidth(menu) + XtWidth(smw); - popleft = True; - } - } - else if (popleft && menu_x < 0) { - menu_x = 0; - popleft = False; - } - if (menu_y >= 0) { - int scr_height = HeightOfScreen(XtScreen(menu)); - - if (menu_y + XtHeight(menu) > scr_height) - menu_y = scr_height - XtHeight(menu) - XtBorderWidth(menu); - } - if (menu_y < 0) - menu_y = 0; - - num_args = 0; - XtSetArg(args[num_args], XtNx, menu_x); num_args++; - XtSetArg(args[num_args], XtNy, menu_y); num_args++; - XtSetValues(menu, args, num_args); - - if (popleft) - ((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT; - else - ((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT; - - XtPopup(menu, XtGrabNone); -} - -static void -PopdownSubMenu(SimpleMenuWidget smw) -{ - SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu; - - if (!menu) - return; - - menu->simple_menu.state |= SMW_UNMAPPING; - PopdownSubMenu(menu); - - XtPopdown((Widget)menu); - - smw->simple_menu.sub_menu = NULL; -} - -/*ARGSUSED*/ -static void -PopupCB(Widget w, XtPointer client_data, XtPointer call_data) -{ - SimpleMenuWidget smw = (SimpleMenuWidget)w; - - smw->simple_menu.state &= ~(SMW_UNMAPPING | SMW_POPLEFT); -} -#endif /* OLDXAW */ +/*
+Copyright 1989, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ */
+
+/*
+ * SimpleMenu.c - Source code file for SimpleMenu widget.
+ *
+ * Date: April 3, 1989
+ *
+ * By: Chris D. Peterson
+ * MIT X Consortium
+ * kit@expo.lcs.mit.edu
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Initer.h>
+#include <X11/Xmu/SysUtil.h>
+#include <X11/Xaw/Cardinals.h>
+#include <X11/Xaw/SimpleMenP.h>
+#include <X11/Xaw/SmeBSBP.h>
+#include <X11/Xaw/XawInit.h>
+#include "Private.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+#define ForAllChildren(smw, childP) \
+for ((childP) = (SmeObject *)(smw)->composite.children; \
+ (childP) < (SmeObject *)((smw)->composite.children \
+ + (smw)->composite.num_children); \
+ (childP)++)
+
+#ifndef OLDXAW
+#define SMW_UNMAPPING 0x01
+#define SMW_POPLEFT 0x02
+#endif
+
+/*
+ * Class Methods
+ */
+static void XawSimpleMenuChangeManaged(Widget);
+static void XawSimpleMenuClassInitialize(void);
+static void XawSimpleMenuClassPartInitialize(WidgetClass);
+static XtGeometryResult XawSimpleMenuGeometryManager(Widget, XtWidgetGeometry*,
+ XtWidgetGeometry*);
+static void XawSimpleMenuInitialize(Widget, Widget, ArgList, Cardinal*);
+static void XawSimpleMenuRealize(Widget, XtValueMask*, XSetWindowAttributes*);
+static void XawSimpleMenuRedisplay(Widget, XEvent*, Region);
+static void XawSimpleMenuResize(Widget);
+static Boolean XawSimpleMenuSetValues(Widget, Widget, Widget,
+ ArgList, Cardinal*);
+static Boolean XawSimpleMenuSetValuesHook(Widget, ArgList, Cardinal*);
+#ifndef OLDXAW
+static void PopupSubMenu(SimpleMenuWidget);
+static void PopdownSubMenu(SimpleMenuWidget);
+static void PopupCB(Widget, XtPointer, XtPointer);
+#endif
+
+/*
+ * Prototypes
+ */
+static void AddPositionAction(XtAppContext, XPointer);
+static void CalculateNewSize(Widget, Dimension*, Dimension*);
+static void ChangeCursorOnGrab(Widget, XtPointer, XtPointer);
+static void CreateLabel(Widget);
+static SmeObject DoGetEventEntry(Widget, int, int);
+static Widget FindMenu(Widget, String);
+static SmeObject GetEventEntry(Widget, XEvent*);
+static void Layout(Widget, Dimension*, Dimension*);
+static void MakeResizeRequest(Widget);
+static void MakeSetValuesRequest(Widget, unsigned int, unsigned int);
+static void MoveMenu(Widget, int, int);
+static void PositionMenu(Widget, XPoint*);
+
+/*
+ * Actions
+ */
+static void Highlight(Widget, XEvent*, String*, Cardinal*);
+static void Notify(Widget, XEvent*, String*, Cardinal*);
+#ifndef OLDXAW
+static void Popdown(Widget, XEvent*, String*, Cardinal*);
+#endif
+static void PositionMenuAction(Widget, XEvent*, String*, Cardinal*);
+static void Unhighlight(Widget, XEvent*, String*, Cardinal*);
+
+/*
+ * Initialization
+ */
+#define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field)
+
+static XtResource resources[] = {
+ /* label */
+ {
+ XtNlabel,
+ XtCLabel,
+ XtRString,
+ sizeof(String),
+ offset(label_string),
+ XtRString,
+ NULL
+ },
+ {
+ XtNlabelClass,
+ XtCLabelClass,
+ XtRPointer,
+ sizeof(WidgetClass),
+ offset(label_class),
+ XtRImmediate,
+ NULL
+ },
+
+ /* layout */
+ {
+ XtNrowHeight,
+ XtCRowHeight,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(row_height),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNtopMargin,
+ XtCVerticalMargins,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(top_margin),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNbottomMargin,
+ XtCVerticalMargins,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(bottom_margin),
+ XtRImmediate,
+ (XtPointer)0
+ },
+#ifndef OLDXAW
+ {
+ XtNleftMargin,
+ XtCHorizontalMargins,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(left_margin),
+ XtRImmediate,
+ (XtPointer)0
+ },
+ {
+ XtNrightMargin,
+ XtCHorizontalMargins,
+ XtRDimension,
+ sizeof(Dimension),
+ offset(right_margin),
+ XtRImmediate,
+ (XtPointer)0
+ },
+#endif
+
+ /* misc */
+ {
+ XtNallowShellResize,
+ XtCAllowShellResize,
+ XtRBoolean,
+ sizeof(Boolean),
+ XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize),
+ XtRImmediate,
+ (XtPointer)True
+ },
+ {
+ XtNcursor,
+ XtCCursor,
+ XtRCursor,
+ sizeof(Cursor),
+ offset(cursor),
+ XtRImmediate,
+ (XtPointer)None
+ },
+ {
+ XtNmenuOnScreen,
+ XtCMenuOnScreen,
+ XtRBoolean,
+ sizeof(Boolean),
+ offset(menu_on_screen),
+ XtRImmediate,
+ (XtPointer)True
+ },
+ {
+ XtNpopupOnEntry,
+ XtCPopupOnEntry,
+ XtRWidget,
+ sizeof(Widget),
+ offset(popup_entry),
+ XtRWidget,
+ NULL
+ },
+ {
+ XtNbackingStore,
+ XtCBackingStore,
+ XtRBackingStore,
+ sizeof(int),
+ offset(backing_store),
+ XtRImmediate,
+ (XtPointer)(Always + WhenMapped + NotUseful)
+ },
+#ifndef OLDXAW
+ {
+ XawNdisplayList,
+ XawCDisplayList,
+ XawRDisplayList,
+ sizeof(XawDisplayList*),
+ offset(display_list),
+ XtRImmediate,
+ NULL
+ },
+#endif
+};
+#undef offset
+
+static char defaultTranslations[] =
+"<Enter>:" "highlight()\n"
+"<Leave>:" "unhighlight()\n"
+"<BtnMotion>:" "highlight()\n"
+#ifndef OLDXAW
+"<BtnUp>:" "popdown() notify() unhighlight()\n"
+#else
+"<BtnUp>:" "MenuPopdown() notify() unhighlight()\n"
+#endif
+;
+
+static XtActionsRec actionsList[] =
+{
+ {"notify", Notify},
+ {"highlight", Highlight},
+ {"unhighlight", Unhighlight},
+#ifndef OLDXAW
+ {"popdown", Popdown},
+ {"set-values", XawSetValuesAction},
+ {"get-values", XawGetValuesAction},
+ {"declare", XawDeclareAction},
+ {"call-proc", XawCallProcAction},
+#endif
+};
+
+static CompositeClassExtensionRec extension_rec = {
+ NULL, /* next_extension */
+ NULLQUARK, /* record_type */
+ XtCompositeExtensionVersion, /* version */
+ sizeof(CompositeClassExtensionRec), /* record_size */
+ True, /* accepts_objects */
+};
+
+#define Superclass (&overrideShellClassRec)
+SimpleMenuClassRec simpleMenuClassRec = {
+ /* core */
+ {
+ (WidgetClass)Superclass, /* superclass */
+ "SimpleMenu", /* class_name */
+ sizeof(SimpleMenuRec), /* size */
+ XawSimpleMenuClassInitialize, /* class_initialize */
+ XawSimpleMenuClassPartInitialize, /* class_part_initialize */
+ False, /* class_inited */
+ XawSimpleMenuInitialize, /* initialize */
+ NULL, /* initialize_hook */
+ XawSimpleMenuRealize, /* realize */
+ actionsList, /* actions */
+ XtNumber(actionsList), /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* num_resources */
+ NULLQUARK, /* xrm_class */
+ True, /* compress_motion */
+ True, /* compress_exposure */
+ True, /* compress_enterleave */
+ False, /* visible_interest */
+ NULL, /* destroy */
+ XawSimpleMenuResize, /* resize */
+ XawSimpleMenuRedisplay, /* expose */
+ XawSimpleMenuSetValues, /* set_values */
+ XawSimpleMenuSetValuesHook, /* set_values_hook */
+ XtInheritSetValuesAlmost, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* intrinsics version */
+ NULL, /* callback offsets */
+ defaultTranslations, /* tm_table */
+ NULL, /* query_geometry */
+ NULL, /* display_accelerator */
+ NULL, /* extension */
+ },
+ /* composite */
+ {
+ XawSimpleMenuGeometryManager, /* geometry_manager */
+ XawSimpleMenuChangeManaged, /* change_managed */
+ XtInheritInsertChild, /* insert_child */
+ XtInheritDeleteChild, /* delete_child */
+ NULL, /* extension */
+ },
+ /* shell */
+ {
+ NULL, /* extension */
+ },
+ /* override */
+ {
+ NULL, /* extension */
+ },
+ /* simple_menu */
+ {
+ NULL, /* extension */
+ },
+};
+
+WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec;
+
+/*
+ * Implementation
+ */
+/*
+ * Function:
+ * XawSimpleMenuClassInitialize
+ *
+ * Description:
+ * Class Initialize routine, called only once.
+ */
+static void
+XawSimpleMenuClassInitialize(void)
+{
+ XawInitializeWidgetSet();
+ XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+ NULL, 0);
+ XtSetTypeConverter(XtRBackingStore, XtRString, XmuCvtBackingStoreToString,
+ NULL, 0, XtCacheNone, NULL);
+ XmuAddInitializer(AddPositionAction, NULL);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuClassPartInitialize
+ * Arguments: wc - the widget class of the subclass.
+ *
+ * Description:
+ * Class Part Initialize routine, called for every subclass. Makes
+ * sure that the subclasses pick up the extension record.
+ */
+static void
+XawSimpleMenuClassPartInitialize(WidgetClass wc)
+{
+ SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass)wc;
+
+ /*
+ * Make sure that our subclass gets the extension rec too
+ */
+ extension_rec.next_extension = smwc->composite_class.extension;
+ smwc->composite_class.extension = (XtPointer) &extension_rec;
+}
+
+/*
+ * Function:
+ * XawSimpleMenuInitialize
+ *
+ * Parameters:
+ * request - widget requested by the argument list
+ * cnew - new widget with both resource and non resource values
+ *
+ * Description:
+ * Initializes the simple menu widget.
+ */
+/*ARGSUSED*/
+static void
+XawSimpleMenuInitialize(Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)cnew;
+ Dimension width, height;
+
+ XmuCallInitializers(XtWidgetToApplicationContext(cnew));
+
+ if (smw->simple_menu.label_class == NULL)
+ smw->simple_menu.label_class = smeBSBObjectClass;
+
+ smw->simple_menu.label = NULL;
+ smw->simple_menu.entry_set = NULL;
+ smw->simple_menu.recursive_set_values = False;
+#ifndef OLDXAW
+ smw->simple_menu.sub_menu = NULL;
+ smw->simple_menu.state = 0;
+
+ XtAddCallback(cnew, XtNpopupCallback, PopupCB, NULL);
+#endif
+
+ if (smw->simple_menu.label_string != NULL)
+ CreateLabel(cnew);
+
+ width = height = 0;
+ CalculateNewSize(cnew, &width, &height);
+
+ smw->simple_menu.menu_width = True;
+
+ if (XtWidth(smw) == 0) {
+ smw->simple_menu.menu_width = False;
+ XtWidth(smw) = width;
+ }
+
+ smw->simple_menu.menu_height = True;
+
+ if (XtHeight(smw) == 0) {
+ smw->simple_menu.menu_height = False;
+ XtHeight(smw) = height;
+ }
+
+ /*
+ * Add a popup_callback routine for changing the cursor
+ */
+ XtAddCallback(cnew, XtNpopupCallback, ChangeCursorOnGrab, NULL);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuRedisplay
+ *
+ * Parameters:
+ * w - simple menu widget
+ * event - X event that caused this redisplay
+ * region - region the needs to be repainted
+ *
+ * Description:
+ * Redisplays the contents of the widget.
+ */
+/*ARGSUSED*/
+static void
+XawSimpleMenuRedisplay(Widget w, XEvent *event, Region region)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ SmeObject *entry;
+ SmeObjectClass cclass;
+
+ if (region == NULL)
+ XClearWindow(XtDisplay(w), XtWindow(w));
+
+#ifndef OLDXAW
+ if (smw->simple_menu.display_list)
+ XawRunDisplayList(w, smw->simple_menu.display_list, event, region);
+#endif
+
+ /*
+ * Check and Paint each of the entries - including the label
+ */
+ ForAllChildren(smw, entry) {
+ if (!XtIsManaged((Widget)*entry))
+ continue;
+
+ if (region != NULL)
+ switch(XRectInRegion(region, XtX(*entry),XtY(*entry),
+ XtWidth(*entry), XtHeight(*entry))) {
+ case RectangleIn:
+ case RectanglePart:
+ break;
+ default:
+ continue;
+ }
+
+ cclass = (SmeObjectClass)(*entry)->object.widget_class;
+
+ if (cclass->rect_class.expose != NULL)
+ (cclass->rect_class.expose)((Widget)*entry, NULL, NULL);
+ }
+}
+
+/*
+ * Function:
+ * XawSimpleMenuRealize
+ *
+ * Parameters:
+ * w - simple menu widget
+ * mask - value mask for the window to create
+ * attrs - attributes for the window to create
+ *
+ * Description:
+ * Realizes the widget.
+ */
+static void
+XawSimpleMenuRealize(Widget w, XtValueMask *mask, XSetWindowAttributes *attrs)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+#ifndef OLDXAW
+ XawPixmap *pixmap;
+#endif
+
+ attrs->cursor = smw->simple_menu.cursor;
+ *mask |= CWCursor;
+ if (smw->simple_menu.backing_store == Always ||
+ smw->simple_menu.backing_store == NotUseful ||
+ smw->simple_menu.backing_store == WhenMapped) {
+ *mask |= CWBackingStore;
+ attrs->backing_store = smw->simple_menu.backing_store;
+ }
+ else
+ *mask &= ~CWBackingStore;
+
+ (*Superclass->core_class.realize)(w, mask, attrs);
+
+#ifndef OLDXAW
+ if (w->core.background_pixmap > XtUnspecifiedPixmap) {
+ pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
+ w->core.colormap, w->core.depth);
+ if (pixmap && pixmap->mask)
+ XawReshapeWidget(w, pixmap);
+ }
+#endif
+}
+
+/*
+ * Function:
+ * XawSimpleMenuResize
+ *
+ * Parameters:
+ * w - simple menu widget
+ *
+ * Description:
+ * Handle the menu being resized.
+ */
+static void
+XawSimpleMenuResize(Widget w)
+{
+ if (!XtIsRealized(w))
+ return;
+
+ Layout(w, NULL, NULL);
+
+ XawSimpleMenuRedisplay(w, NULL, NULL);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuSetValues
+ *
+ * Parameters:
+ * current - current state of the widget
+ * request - what was requested
+ * cnew - what the widget will become
+ *
+ * Description:
+ * Relayout the menu when one of the resources is changed.
+ */
+/*ARGSUSED*/
+static Boolean
+XawSimpleMenuSetValues(Widget current, Widget request, Widget cnew,
+ ArgList args, Cardinal *num_args)
+{
+ SimpleMenuWidget smw_old = (SimpleMenuWidget)current;
+ SimpleMenuWidget smw_new = (SimpleMenuWidget)cnew;
+ Boolean ret_val = False, layout = False;
+
+ if (!XtIsRealized(current))
+ return (False);
+
+ if (!smw_new->simple_menu.recursive_set_values) {
+ if (XtWidth(smw_new) != XtWidth(smw_old)) {
+ smw_new->simple_menu.menu_width = XtWidth(smw_new) != 0;
+ layout = True;
+ }
+ if (XtHeight(smw_new) != XtHeight(smw_old)) {
+ smw_new->simple_menu.menu_height = XtHeight(smw_new) != 0;
+ layout = True;
+ }
+ }
+
+ if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor)
+ XDefineCursor(XtDisplay(cnew), XtWindow(cnew),
+ smw_new->simple_menu.cursor);
+
+ if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) {
+ if (smw_new->simple_menu.label_string == NULL) /* Destroy */
+ XtDestroyWidget((Widget)smw_old->simple_menu.label);
+ else if (smw_old->simple_menu.label_string == NULL) /* Create */
+ CreateLabel(cnew);
+ else { /* Change */
+ Arg arglist[1];
+
+ XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string);
+ XtSetValues((Widget)smw_new->simple_menu.label, arglist, ONE);
+ }
+ }
+
+ if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class)
+ XtAppWarning(XtWidgetToApplicationContext(cnew),
+ "No Dynamic class change of the SimpleMenu Label.");
+
+ if (smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin
+ || smw_old->simple_menu.bottom_margin
+ != smw_new->simple_menu.bottom_margin) {
+ layout = True;
+ ret_val = True;
+ }
+
+#ifndef OLDXAW
+ if (smw_old->core.background_pixmap != smw_new->core.background_pixmap) {
+ XawPixmap *opix, *npix;
+
+ opix = XawPixmapFromXPixmap(smw_old->core.background_pixmap,
+ XtScreen(smw_old), smw_old->core.colormap,
+ smw_old->core.depth);
+ npix = XawPixmapFromXPixmap(smw_new->core.background_pixmap,
+ XtScreen(smw_new), smw_new->core.colormap,
+ smw_new->core.depth);
+ if ((npix && npix->mask) || (opix && opix->mask))
+ XawReshapeWidget(cnew, npix);
+ }
+#endif
+
+ if (layout)
+ Layout(cnew, NULL, NULL);
+
+ return (ret_val);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuSetValuesHook
+ *
+ * Parameters:
+ * w - menu widget
+ * arglist - argument list passed to XtSetValues
+ * num_args - number of args
+ *
+ * Description:
+ * To handle a special case, this is passed the actual arguments.
+ */
+static Boolean
+XawSimpleMenuSetValuesHook(Widget w, ArgList arglist, Cardinal *num_args)
+{
+ Cardinal i;
+ Dimension width, height;
+
+ width = XtWidth(w);
+ height = XtHeight(w);
+
+ for (i = 0 ; i < *num_args ; i++) {
+ if (streq(arglist[i].name, XtNwidth))
+ width = (Dimension)arglist[i].value;
+ if (streq(arglist[i].name, XtNheight))
+ height = (Dimension) arglist[i].value;
+ }
+
+ if (width != XtWidth(w) || height != XtHeight(w))
+ MakeSetValuesRequest(w, width, height);
+
+ return (False);
+}
+
+/*
+ * Geometry Management routines
+ */
+/*
+ * Function:
+ * XawSimpleMenuGeometryManager
+ *
+ * Parameters:
+ * w - Menu Entry making the request
+ * request - requested new geometry
+ * reply - the allowed geometry.
+ *
+ * Description:
+ * This is the SimpleMenu Widget's Geometry Manager.
+ *
+ * Returns:
+ * XtGeometry{Yes, No, Almost}
+ */
+static XtGeometryResult
+XawSimpleMenuGeometryManager(Widget w, XtWidgetGeometry *request,
+ XtWidgetGeometry *reply)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)XtParent(w);
+ SmeObject entry = (SmeObject)w;
+ XtGeometryMask mode = request->request_mode;
+ XtGeometryResult answer;
+ Dimension old_height, old_width;
+
+ if (!(mode & CWWidth) && !(mode & CWHeight))
+ return (XtGeometryNo);
+
+ reply->width = request->width;
+ reply->height = request->height;
+
+ old_width = XtWidth(entry);
+ old_height = XtHeight(entry);
+
+ Layout(w, &reply->width, &reply->height);
+
+ /*
+ * Since we are an override shell and have no parent there is no one to
+ * ask to see if this geom change is okay, so I am just going to assume
+ * we can do whatever we want. If you subclass be very careful with this
+ * assumption, it could bite you.
+ *
+ * Chris D. Peterson - Sept. 1989.
+ */
+ if ((!(mode & CWWidth) || reply->width == request->width)
+ && (!(mode & CWHeight) || reply->height == request->height)) {
+ if (mode & XtCWQueryOnly) { /* Actually perform the layout */
+ XtWidth(entry) = old_width;
+ XtHeight(entry) = old_height;
+ }
+ else
+ Layout((Widget)smw, NULL, NULL);
+ answer = XtGeometryDone;
+ }
+ else {
+ XtWidth(entry) = old_width;
+ XtHeight(entry) = old_height;
+
+ if ((reply->width == request->width && !(mode & CWHeight))
+ || (reply->height == request->height && !(mode & CWWidth))
+ || (reply->width == request->width
+ && reply->height == request->height))
+ answer = XtGeometryNo;
+ else {
+ answer = XtGeometryAlmost;
+ reply->request_mode = 0;
+ if (reply->width != request->width)
+ reply->request_mode |= CWWidth;
+ if (reply->height != request->height)
+ reply->request_mode |= CWHeight;
+ }
+ }
+
+ return (answer);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuChangeManaged
+ *
+ * Parameters:
+ * w - simple menu widget
+ *
+ * Description:
+ * Called whenever a new child is managed.
+ */
+static void
+XawSimpleMenuChangeManaged(Widget w)
+{
+ Layout(w, NULL, NULL);
+}
+
+/*
+ * Global Action Routines
+ *
+ * These actions routines will be added to the application's
+ * global action list
+ */
+/*
+ * Function:
+ * PositionMenuAction
+ *
+ * Parameters:
+ * w - a widget (no the simple menu widget)
+ * event - the event that caused this action
+ * params - parameters passed to the routine.
+ * we expect the name of the menu here.
+ * num_params - ""
+ *
+ * Description:
+ * Positions the simple menu widget.
+ */
+/*ARGSUSED*/
+static void
+PositionMenuAction(Widget w, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ Widget menu;
+ XPoint loc;
+
+ if (*num_params != 1) {
+ XtAppWarning(XtWidgetToApplicationContext(w),
+ "SimpleMenuWidget: position menu action expects "
+ "only one parameter which is the name of the menu.");
+ return;
+ }
+
+ if ((menu = FindMenu(w, params[0])) == NULL) {
+ char error_buf[BUFSIZ];
+
+ (void)XmuSnprintf(error_buf, sizeof(error_buf),
+ "SimpleMenuWidget: could not find menu named %s.",
+ params[0]);
+ XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
+ return;
+ }
+
+ switch (event->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ loc.x = event->xbutton.x_root;
+ loc.y = event->xbutton.y_root;
+ PositionMenu(menu, &loc);
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ loc.x = event->xcrossing.x_root;
+ loc.y = event->xcrossing.y_root;
+ PositionMenu(menu, &loc);
+ break;
+ case MotionNotify:
+ loc.x = event->xmotion.x_root;
+ loc.y = event->xmotion.y_root;
+ PositionMenu(menu, &loc);
+ break;
+ default:
+ PositionMenu(menu, NULL);
+ break;
+ }
+}
+
+/*
+ * Widget Action Routines
+ */
+/*
+ * Function:
+ * Unhighlight
+ *
+ * Parameters:
+ * w - simple menu widget
+ * event - event that caused this action
+ * params - not used
+ * num_params - ""
+ *
+ * Description:
+ * Unhighlights current entry.
+ */
+/*ARGSUSED*/
+static void
+Unhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ SmeObject entry = smw->simple_menu.entry_set;
+
+ if (entry == NULL)
+ return;
+
+#ifndef OLDXAW
+ if (!smw->simple_menu.sub_menu)
+#endif
+ {
+ SmeObjectClass cclass;
+
+ smw->simple_menu.entry_set = NULL;
+ cclass = (SmeObjectClass)entry->object.widget_class;
+ (cclass->sme_class.unhighlight)((Widget)entry);
+ }
+}
+
+/*
+ * Function:
+ * Highlight
+ *
+ * Parameters:
+ * w - simple menu widget
+ * event - event that caused this action
+ * params - not used
+ * num_params - ""
+ *
+ * Description:
+ * Highlights current entry.
+ */
+/*ARGSUSED*/
+static void
+Highlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ SmeObject entry;
+
+ if (!XtIsSensitive(w))
+ return;
+
+ entry = GetEventEntry(w, event);
+
+ if (entry == smw->simple_menu.entry_set)
+ return;
+
+#ifndef OLDXAW
+ if (!smw->simple_menu.sub_menu)
+#endif
+ Unhighlight(w, event, params, num_params);
+
+ if (entry == NULL)
+ return;
+
+ if (!XtIsSensitive((Widget)entry))
+ return;
+
+#ifndef OLDXAW
+ if (smw->simple_menu.sub_menu)
+ PopdownSubMenu(smw);
+#endif
+
+ Unhighlight(w, event, params, num_params);
+
+#ifndef OLDXAW
+ if (!(smw->simple_menu.state & SMW_UNMAPPING))
+#endif
+ {
+ SmeObjectClass cclass;
+
+ smw->simple_menu.entry_set = entry;
+ cclass = (SmeObjectClass)entry->object.widget_class;
+
+ (cclass->sme_class.highlight)((Widget)entry);
+
+#ifndef OLDXAW
+ if (XtIsSubclass((Widget)entry, smeBSBObjectClass))
+ PopupSubMenu(smw);
+#endif
+ }
+}
+
+/*
+ * Function:
+ * Notify
+ *
+ * Parameters:
+ * w - simple menu widget
+ * event - event that caused this action
+ * params - not used
+ * num_params - ""
+ *
+ * Description:
+ * Notify user of current entry.
+ */
+/*ARGSUSED*/
+static void
+Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ SmeObject entry;
+ SmeObjectClass cclass;
+
+ /* may be a propagated event from a sub menu, need to check it */
+ if (XtWindow(w) != event->xany.window)
+ return;
+ entry = GetEventEntry(w, event);
+ if (entry == NULL || !XtIsSensitive((Widget)entry))
+ return;
+
+ cclass = (SmeObjectClass) entry->object.widget_class;
+ (cclass->sme_class.notify)((Widget)entry);
+}
+
+/*
+ * Public Functions
+ */
+/*
+ * Function:
+ * XawSimpleMenuAddGlobalActions
+ *
+ * Arguments:
+ * app_con - appcontext
+ *
+ * Description:
+ * Adds the global actions to the simple menu widget.
+ */
+void
+XawSimpleMenuAddGlobalActions(XtAppContext app_con)
+{
+ XtInitializeWidgetClass(simpleMenuWidgetClass);
+ XmuCallInitializers(app_con);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuGetActiveEntry
+ *
+ * Parameters:
+ * w - smw widget
+ *
+ * Description:
+ * Gets the currently active (set) entry.
+ *
+ * Returns:
+ * The currently set entry or NULL if none is set
+ */
+Widget
+XawSimpleMenuGetActiveEntry(Widget w)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+
+ return ((Widget)smw->simple_menu.entry_set);
+}
+
+/*
+ * Function:
+ * XawSimpleMenuClearActiveEntry
+ *
+ * Parameters:
+ * w - smw widget
+ *
+ * Description:
+ * Unsets the currently active (set) entry.
+ */
+void
+XawSimpleMenuClearActiveEntry(Widget w)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+
+ smw->simple_menu.entry_set = NULL;
+}
+
+/*
+ * Private Functions
+ */
+/*
+ * Function:
+ * CreateLabel
+ *
+ * Parameters:
+ * w - smw widget
+ *
+ * Description:
+ * Creates the label object and makes sure it is the first child in
+ * in the list.
+ */
+static void
+CreateLabel(Widget w)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ Widget *child, *next_child;
+ int i;
+ Arg args[2];
+
+ if (smw->simple_menu.label_string == NULL ||
+ smw->simple_menu.label != NULL) {
+ XtAppWarning(XtWidgetToApplicationContext(w),
+ "Xaw Simple Menu Widget: label string is NULL or "
+ "label already exists, no label is being created.");
+ return;
+ }
+
+ XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string);
+ XtSetArg(args[1], XtNjustify, XtJustifyCenter);
+ smw->simple_menu.label = (SmeObject)
+ XtCreateManagedWidget("menuLabel",
+ smw->simple_menu.label_class, w, args, TWO);
+
+ next_child = NULL;
+ for (child = smw->composite.children + smw->composite.num_children,
+ i = smw->composite.num_children; i > 0; i--, child--) {
+ if (next_child != NULL)
+ *next_child = *child;
+ next_child = child;
+ }
+ *child = (Widget)smw->simple_menu.label;
+}
+
+/*
+ * Function:
+ * Layout
+ *
+ * Arguments:
+ * w - See below
+ * width_ret - returned width
+ * height_ret - returned height
+ *
+ * Note:
+ * if width == NULL || height == NULL then it assumes the you do not care
+ * about the return values, and just want a relayout.
+ *
+ * if this is not the case then it will set width_ret and height_ret
+ * to be width and height that the child would get if it were layed out
+ * at this time.
+ *
+ * "w" can be the simple menu widget or any of its object children.
+ */
+static void
+Layout(Widget w, Dimension *width_ret, Dimension *height_ret)
+{
+ SmeObject current_entry;
+ SimpleMenuWidget smw;
+ Dimension width, height;
+ Boolean allow_change_size;
+ Widget kid;
+ Cardinal i, count, n;
+ int width_kid, height_kid, tmp_w, tmp_h;
+ short vadd, hadd, x_ins, y_ins;
+ Dimension *widths;
+
+ height = 0;
+
+ if (XtIsSubclass(w, simpleMenuWidgetClass)) {
+ smw = (SimpleMenuWidget)w;
+ current_entry = NULL;
+ }
+ else {
+ smw = (SimpleMenuWidget)XtParent(w);
+ current_entry = (SmeObject)w;
+ }
+
+ allow_change_size = (!XtIsRealized((Widget)smw)
+ || smw->shell.allow_shell_resize);
+
+ for (i = smw->simple_menu.label ? 1 : 0;
+ i < smw->composite.num_children;
+ i++) {
+ XtWidgetGeometry preferred;
+
+ kid = smw->composite.children[i];
+ if (!XtIsManaged(kid))
+ continue;
+ if (smw->simple_menu.row_height != 0)
+ XtHeight(kid) = smw->simple_menu.row_height;
+ XtQueryGeometry(kid, NULL, &preferred);
+ if (preferred.request_mode & CWWidth)
+ XtWidth(kid) = preferred.width;
+ }
+
+ if (smw->simple_menu.label
+ && XtIsManaged((Widget)smw->simple_menu.label)) {
+ XtWidgetGeometry preferred;
+
+ kid = (Widget)smw->simple_menu.label;
+ XtQueryGeometry(kid, NULL, &preferred);
+ if (preferred.request_mode & CWWidth)
+ XtWidth(kid) = preferred.width;
+ if (preferred.request_mode & CWHeight)
+ XtHeight(kid) = preferred.height;
+ }
+
+ /* reset */
+ if (!smw->simple_menu.menu_width)
+ XtWidth(smw) = 0;
+ if (!smw->simple_menu.menu_height)
+ XtHeight(smw) = 0;
+ if (!XtWidth(smw) || !XtHeight(smw))
+ MakeResizeRequest((Widget)smw);
+
+ widths = (Dimension *)XtMalloc(sizeof(Dimension));
+#ifndef OLDXAW
+ hadd = smw->simple_menu.left_margin;
+#else
+ hadd = 0;
+#endif
+ vadd = smw->simple_menu.top_margin;
+ if (smw->simple_menu.label)
+ vadd += XtHeight(smw->simple_menu.label);
+
+ count = 1;
+ width = tmp_w = tmp_h = n = 0;
+ height = vadd;
+
+ for (i = smw->simple_menu.label ? 1 : 0;
+ i < smw->composite.num_children;
+ i++) {
+ kid = smw->composite.children[i];
+ if (!XtIsManaged(kid))
+ continue;
+ width_kid = XtWidth(kid);
+ height_kid = XtHeight(kid);
+
+ if (n && (height + height_kid + smw->simple_menu.bottom_margin
+ > XtHeight(smw))) {
+ ++count;
+ widths = (Dimension *)XtRealloc((char *)widths,
+ sizeof(Dimension) * count);
+ widths[count - 1] = width_kid;
+ width += tmp_w;
+ tmp_w = width_kid;
+ height = height_kid + vadd;
+ }
+ else
+ height += height_kid;
+ if (height > tmp_h)
+ tmp_h = height;
+ if (width_kid > tmp_w)
+ widths[count - 1] = tmp_w = width_kid;
+ ++n;
+ }
+
+ height = tmp_h + smw->simple_menu.bottom_margin;
+ width += tmp_w;
+
+ if (smw->simple_menu.label && width < XtWidth(smw->simple_menu.label)) {
+ float inc;
+
+ inc = (XtWidth(smw->simple_menu.label) - width) / (float)count;
+ width = XtWidth(smw->simple_menu.label);
+ for (n = 0; n < count; n++)
+ widths[n] += inc;
+ }
+
+#ifndef OLDXAW
+ width += hadd + smw->simple_menu.right_margin;
+#endif
+
+ x_ins = n = count = 0;
+ tmp_w = widths[0];
+ tmp_h = vadd;
+
+ for (i = smw->simple_menu.label ? 1 : 0;
+ i < smw->composite.num_children;
+ i++) {
+ kid = smw->composite.children[i];
+ if (!XtIsManaged(kid))
+ continue;
+
+ height_kid = XtHeight(kid);
+
+ if (n && (tmp_h + height_kid + smw->simple_menu.bottom_margin
+ > XtHeight(smw))) {
+ x_ins = tmp_w;
+ y_ins = vadd;
+ ++count;
+ tmp_w += widths[count];
+ tmp_h = height_kid + vadd;
+ }
+ else {
+ y_ins = tmp_h;
+ tmp_h += height_kid;
+ }
+ ++n;
+
+ XtX(kid) = x_ins + hadd;
+ XtY(kid) = y_ins;
+ XtWidth(kid) = widths[count];
+ }
+
+ XtFree((char *)widths);
+
+ if (allow_change_size)
+ MakeSetValuesRequest((Widget) smw, width, height);
+
+ if (smw->simple_menu.label) {
+ XtX(smw->simple_menu.label) = 0;
+ XtY(smw->simple_menu.label) = smw->simple_menu.top_margin;
+ XtWidth(smw->simple_menu.label) = XtWidth(smw)
+#ifndef OLDXAW
+ - (smw->simple_menu.left_margin + smw->simple_menu.right_margin)
+#endif
+ ;
+ }
+ if (current_entry) {
+ if (width_ret)
+ *width_ret = XtWidth(current_entry);
+ if (height_ret)
+ *height_ret = XtHeight(current_entry);
+ }
+}
+
+/*
+ * Function:
+ * AddPositionAction
+ *
+ * Parameters:
+ * app_con - application context
+ * data - (not used)
+ *
+ * Description:
+ * Adds the XawPositionSimpleMenu action to the global
+ * action list for this appcon.
+ */
+/*ARGSUSED*/
+static void
+AddPositionAction(XtAppContext app_con, XPointer data)
+{
+ static XtActionsRec pos_action[] = {
+ {"XawPositionSimpleMenu", PositionMenuAction},
+ };
+
+ XtAppAddActions(app_con, pos_action, XtNumber(pos_action));
+}
+
+/*
+ * Function:
+ * FindMenu
+ *
+ * Parameters:
+ * widget - reference widget
+ * name - menu widget's name
+ *
+ * Description:
+ * Find the menu give a name and reference widget
+ *
+ * Returns:
+ * The menu widget or NULL.
+ */
+static Widget
+FindMenu(Widget widget, String name)
+{
+ Widget w, menu;
+
+ for (w = widget; w != NULL; w = XtParent(w))
+ if ((menu = XtNameToWidget(w, name)) != NULL)
+ return (menu);
+
+ return (NULL);
+}
+
+/*
+ * Function:
+ * PositionMenu
+ *
+ * Parameters:
+ * w - simple menu widget
+ * location - pointer the the position or NULL
+ *
+ * Description:
+ * Places the menu
+ */
+static void
+PositionMenu(Widget w, XPoint *location)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ SmeObject entry;
+ XPoint t_point;
+
+ if (location == NULL) {
+ Window temp1, temp2;
+ int root_x, root_y, tempX, tempY;
+ unsigned int tempM;
+
+ location = &t_point;
+ if (XQueryPointer(XtDisplay(w), XtWindow(w), &temp1, &temp2,
+ &root_x, &root_y, &tempX, &tempY, &tempM) == False) {
+ XtAppWarning(XtWidgetToApplicationContext(w),
+ "Xaw Simple Menu Widget: "
+ "Could not find location of mouse pointer");
+ return;
+ }
+ location->x = (short) root_x;
+ location->y = (short) root_y;
+ }
+
+ /*
+ * The width will not be correct unless it is realized
+ */
+ XtRealizeWidget(w);
+
+ location->x -= XtWidth(w) >> 1;
+
+ if (smw->simple_menu.popup_entry == NULL)
+ entry = smw->simple_menu.label;
+ else
+ entry = smw->simple_menu.popup_entry;
+
+ if (entry != NULL)
+ location->y -= XtY(entry) + (XtHeight(entry) >> 1);
+
+ MoveMenu(w, location->x, location->y);
+}
+
+/*
+ * Function:
+ * MoveMenu
+ *
+ * Parameters:
+ * w - simple menu widget
+ * x - current location of the widget
+ * y - ""
+ *
+ * Description:
+ * Actually moves the menu, may force it to
+ * to be fully visable if menu_on_screen is True.
+ */
+static void
+MoveMenu(Widget w, int x, int y)
+{
+ Arg arglist[2];
+ Cardinal num_args = 0;
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+
+ if (smw->simple_menu.menu_on_screen) {
+ int width = XtWidth(w) + (XtBorderWidth(w) << 1);
+ int height = XtHeight(w) + (XtBorderWidth(w) << 1);
+
+ if (x >= 0) {
+ int scr_width = WidthOfScreen(XtScreen(w));
+
+ if (x + width > scr_width)
+ x = scr_width - width;
+ }
+ if (x < 0)
+ x = 0;
+
+ if (y >= 0) {
+ int scr_height = HeightOfScreen(XtScreen(w));
+
+ if (y + height > scr_height)
+ y = scr_height - height;
+ }
+ if (y < 0)
+ y = 0;
+ }
+
+ XtSetArg(arglist[num_args], XtNx, x); num_args++;
+ XtSetArg(arglist[num_args], XtNy, y); num_args++;
+ XtSetValues(w, arglist, num_args);
+}
+
+/*
+ * Function:
+ * ChangeCursorOnGrab
+ *
+ * Parameters:
+ * w - menu widget
+ * temp1 - not used
+ * temp2 - ""
+ *
+ * Description:
+ * Changes the cursor on the active grab to the one
+ * specified in out resource list.
+ */
+/*ARGSUSED*/
+static void
+ChangeCursorOnGrab(Widget w, XtPointer temp1, XtPointer temp2)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+
+ /*
+ * The event mask here is what is currently in the MIT implementation.
+ * There really needs to be a way to get the value of the mask out
+ * of the toolkit (CDP 5/26/89).
+ */
+ XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask | ButtonReleaseMask,
+ smw->simple_menu.cursor,
+ XtLastTimestampProcessed(XtDisplay(w)));
+}
+
+/*
+ * Function:
+ * MakeSetValuesRequest
+ *
+ * Parameters:
+ * w - simple menu widget
+ * width - size requested
+ * height - ""
+ */
+static void
+MakeSetValuesRequest(Widget w, unsigned int width, unsigned int height)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ Arg arglist[2];
+ Cardinal num_args = 0;
+
+ if (!smw->simple_menu.recursive_set_values) {
+ if (XtWidth(smw) != width || XtHeight(smw) != height) {
+ smw->simple_menu.recursive_set_values = True;
+ XtSetArg(arglist[num_args], XtNwidth, width); num_args++;
+ XtSetArg(arglist[num_args], XtNheight, height); num_args++;
+ XtSetValues(w, arglist, num_args);
+ }
+ else if (XtIsRealized((Widget)smw))
+ XawSimpleMenuRedisplay((Widget)smw, NULL, NULL);
+ }
+ smw->simple_menu.recursive_set_values = False;
+}
+
+static SmeObject
+DoGetEventEntry(Widget w, int x_loc, int y_loc)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ SmeObject *entry;
+
+ ForAllChildren(smw, entry) {
+ if (!XtIsManaged((Widget)*entry))
+ continue;
+
+ if (x_loc > XtX(*entry)
+ && x_loc <= XtX(*entry) + XtWidth(*entry)
+ && y_loc > XtY(*entry)
+ && y_loc <= XtY(*entry) + XtHeight(*entry)) {
+ if (*entry == smw->simple_menu.label)
+ return (NULL); /* cannot select the label */
+ else
+ return (*entry);
+ }
+ }
+
+ return (NULL);
+}
+
+/*
+ * Function:
+ * GetEventEntry
+ *
+ * Parameters:
+ * w - simple menu widget
+ * event - X event
+ *
+ * Description:
+ * Gets an entry given an event that has X and Y coords.
+ *
+ * Returns:
+ * The entry that this point is in
+ */
+static SmeObject
+GetEventEntry(Widget w, XEvent *event)
+{
+ int x_loc, y_loc, x_root;
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+ SmeObject entry;
+ int warp, move;
+
+ switch (event->type) {
+ case MotionNotify:
+ x_loc = event->xmotion.x;
+ y_loc = event->xmotion.y;
+ x_root = event->xmotion.x_root;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ x_loc = event->xcrossing.x;
+ y_loc = event->xcrossing.y;
+ x_root = event->xcrossing.x_root;
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ x_loc = event->xbutton.x;
+ y_loc = event->xbutton.y;
+ x_root = event->xbutton.x_root;
+ break;
+ default:
+ XtAppError(XtWidgetToApplicationContext(w),
+ "Unknown event type in GetEventEntry().");
+ return (NULL);
+ }
+
+ if (x_loc < 0 || x_loc >= XtWidth(smw) ||
+ y_loc < 0 || y_loc >= XtHeight(smw))
+ return (NULL);
+
+ /* Move the menu if it's outside the screen, does not check
+ * smw->simple_menu.menu_on_screen because menus is bigger than screen
+ */
+ if (x_root == WidthOfScreen(XtScreen(w)) - 1 &&
+ XtX(w) + XtWidth(w) + (XtBorderWidth(w)) > x_root) {
+ warp = -8;
+ if (smw->simple_menu.entry_set) {
+ entry = DoGetEventEntry(w,
+ XtX(smw->simple_menu.entry_set)
+ + XtWidth(smw->simple_menu.entry_set) + 1,
+ y_loc);
+ Unhighlight(w, event, NULL, NULL);
+ if (entry) {
+ warp = -(int)XtWidth(entry) >> 1;
+ move = x_loc - XtWidth(entry) - XtX(entry) + XtBorderWidth(w);
+ }
+ else {
+ warp = 0;
+ move = WidthOfScreen(XtScreen(w)) -
+ (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
+ }
+ }
+ else {
+ warp = 0;
+ move = WidthOfScreen(XtScreen(w)) -
+ (XtX(w) + XtWidth(w) + (XtBorderWidth(w) << 1));
+ }
+ }
+ else if (x_root == 0 && XtX(w) < 0) {
+ warp = 8;
+ if (smw->simple_menu.entry_set) {
+ entry = DoGetEventEntry(w, XtX(smw->simple_menu.entry_set) - 1,
+ y_loc);
+ Unhighlight(w, event, NULL, NULL);
+ if (entry) {
+ warp = XtWidth(entry) >> 1;
+ move = x_loc - XtX(entry);
+ }
+ else
+ move = x_loc + XtBorderWidth(w);
+ }
+ else
+ move = x_loc + XtBorderWidth(w);
+ }
+ else
+ move = warp = 0;
+
+ if (move)
+ XtMoveWidget(w, XtX(w) + move, XtY(w));
+ if (warp)
+ XWarpPointer(XtDisplay(w), None, None, 0, 0, 0, 0, warp, 0);
+
+ return (DoGetEventEntry(w, x_loc, y_loc));
+}
+
+static void
+CalculateNewSize(Widget w, Dimension *width_return, Dimension *height_return)
+{
+ SimpleMenuWidget xaw = (SimpleMenuWidget)w;
+ Widget kid;
+ Cardinal i;
+ int width_kid, height_kid;
+ int width, height, tmp_w, tmp_h, max_dim;
+ short vadd, hadd;
+ int n, columns, test_h, num_children = 0;
+ Boolean try_layout = False;
+
+#ifndef OLDXAW
+ hadd = xaw->simple_menu.left_margin + xaw->simple_menu.right_margin;
+#else
+ hadd = 0;
+#endif
+ vadd = xaw->simple_menu.top_margin + xaw->simple_menu.bottom_margin;
+ if (xaw->simple_menu.label)
+ vadd += XtHeight(xaw->simple_menu.label);
+
+ if (*height_return)
+ max_dim = *height_return;
+ else if (!XtHeight(w)) {
+ max_dim = HeightOfScreen(XtScreen(w));
+ try_layout = True;
+ }
+ else
+ max_dim = XtHeight(w);
+ max_dim -= vadd;
+
+ width = height = tmp_w = tmp_h = n = test_h = 0;
+ columns = 1;
+ for (i = xaw->simple_menu.label ? 1 : 0;
+ i < xaw->composite.num_children;
+ i++) {
+ kid = xaw->composite.children[i];
+ if (!XtIsManaged(kid))
+ continue;
+ ++num_children;
+ width_kid = XtWidth(kid);
+ height_kid = XtHeight(kid);
+
+ if (try_layout) {
+ if (!test_h)
+ test_h = height_kid;
+ else if (test_h != height_kid)
+ try_layout = False;
+ }
+
+ if (n && (height + height_kid > max_dim)) {
+ ++columns;
+ width += tmp_w;
+ tmp_w = width_kid;
+ height = height_kid;
+ }
+ else
+ height += height_kid;
+ if (height > tmp_h)
+ tmp_h = height;
+ if (width_kid > tmp_w)
+ tmp_w = width_kid;
+ ++n;
+ }
+
+ height = tmp_h + vadd;
+ width += tmp_w + hadd;
+
+ if (xaw->simple_menu.label)
+ width = XawMax(width, XtWidth(xaw->simple_menu.label) + hadd);
+
+ *width_return = width;
+ *height_return = height;
+
+ if (try_layout && columns > 1 && num_children > 2) {
+ int space;
+
+ height = test_h * (xaw->simple_menu.label ?
+ num_children - 1 :
+ num_children);
+
+ max_dim -= max_dim % test_h;
+ space = max_dim - (height % max_dim);
+ if (space >= test_h * columns) {
+ height = max_dim - space / columns;
+ if (height % test_h)
+ height += test_h - (height % test_h);
+ *height_return = height + vadd;
+ CalculateNewSize(w, width_return, height_return);
+ }
+ }
+}
+
+static void
+MakeResizeRequest(Widget w)
+{
+ int tries;
+ Dimension width, height;
+
+ width = XtWidth(w);
+ height = XtHeight(w);
+
+ for (tries = 0; tries < 100; tries++) {
+ CalculateNewSize(w, &width, &height);
+ if (width == XtWidth(w) && height == XtHeight(w))
+ break;
+ if (XtMakeResizeRequest(w, width, height, &width, &height) ==
+ XtGeometryNo)
+ break;
+ }
+}
+
+#ifndef OLDXAW
+static void
+Popdown(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+
+ while (XtParent(w) &&
+ XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) {
+ if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) {
+ w = XtParent(w);
+ smw = (SimpleMenuWidget)w;
+ smw->simple_menu.entry_set = NULL;
+ }
+ else
+ break;
+ }
+
+ smw->simple_menu.state |= SMW_UNMAPPING;
+ if (smw->simple_menu.sub_menu)
+ PopdownSubMenu(smw);
+ XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params);
+}
+
+static void
+PopupSubMenu(SimpleMenuWidget smw)
+{
+ Arg args[2];
+ Cardinal num_args;
+ Widget menu;
+ SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set;
+ Position menu_x, menu_y;
+ Bool popleft;
+
+ if (entry->sme_bsb.menu_name == NULL)
+ return;
+
+ if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL)
+ return;
+
+ smw->simple_menu.sub_menu = menu;
+
+ if (!XtIsRealized(menu))
+ XtRealizeWidget(menu);
+
+ popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0;
+
+ if (popleft)
+ XtTranslateCoords((Widget)smw, -(int)XtWidth(menu),
+ XtY(entry) - XtBorderWidth(menu), &menu_x, &menu_y);
+ else
+ XtTranslateCoords((Widget)smw, XtWidth(smw), XtY(entry)
+ - XtBorderWidth(menu), &menu_x, &menu_y);
+
+ if (!popleft && menu_x >= 0) {
+ int scr_width = WidthOfScreen(XtScreen(menu));
+
+ if (menu_x + XtWidth(menu) > scr_width) {
+ menu_x -= XtWidth(menu) + XtWidth(smw);
+ popleft = True;
+ }
+ }
+ else if (popleft && menu_x < 0) {
+ menu_x = 0;
+ popleft = False;
+ }
+ if (menu_y >= 0) {
+ int scr_height = HeightOfScreen(XtScreen(menu));
+
+ if (menu_y + XtHeight(menu) > scr_height)
+ menu_y = scr_height - XtHeight(menu) - XtBorderWidth(menu);
+ }
+ if (menu_y < 0)
+ menu_y = 0;
+
+ num_args = 0;
+ XtSetArg(args[num_args], XtNx, menu_x); num_args++;
+ XtSetArg(args[num_args], XtNy, menu_y); num_args++;
+ XtSetValues(menu, args, num_args);
+
+ if (popleft)
+ ((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT;
+ else
+ ((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT;
+
+ XtPopup(menu, XtGrabNone);
+}
+
+static void
+PopdownSubMenu(SimpleMenuWidget smw)
+{
+ SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu;
+
+ if (!menu)
+ return;
+
+ menu->simple_menu.state |= SMW_UNMAPPING;
+ PopdownSubMenu(menu);
+
+ XtPopdown((Widget)menu);
+
+ smw->simple_menu.sub_menu = NULL;
+}
+
+/*ARGSUSED*/
+static void
+PopupCB(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ SimpleMenuWidget smw = (SimpleMenuWidget)w;
+
+ smw->simple_menu.state &= ~(SMW_UNMAPPING | SMW_POPLEFT);
+}
+#endif /* OLDXAW */
|