#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/SysUtil.h>
#include <X11/Xaw/MenuButtoP.h>
#include <X11/Xaw/XawInit.h>
#include "Private.h"
static void XawMenuButtonClassInitialize(void);
static void XawMenuButtonInitialize(Widget, Widget, ArgList, Cardinal*);
static void XawMenuButtonDestroy(Widget);
static Boolean XawMenuButtonSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
static void PopupMenu(Widget, XEvent*, String*, Cardinal*);
#define superclass ((CommandWidgetClass)&commandClassRec)
static char defaultTranslations[] =
"<Enter>:" "highlight()\n"
"<Leave>:" "reset()\n"
"Any<BtnDown>:" "reset() PopupMenu()\n";
static char default_menu_name[] = "menu";
#define offset(field) XtOffsetOf(MenuButtonRec, field)
static XtResource resources[] = {
{
XtNmenuName,
XtCMenuName,
XtRString,
sizeof(String),
offset(menu_button.menu_name),
XtRString,
(XtPointer)default_menu_name
},
};
#undef offset
static XtActionsRec actionsList[] =
{
{"PopupMenu", PopupMenu},
};
MenuButtonClassRec menuButtonClassRec = {
{
(WidgetClass)superclass,
"MenuButton",
sizeof(MenuButtonRec),
XawMenuButtonClassInitialize,
NULL,
False,
XawMenuButtonInitialize,
NULL,
XtInheritRealize,
actionsList,
XtNumber(actionsList),
resources,
XtNumber(resources),
NULLQUARK,
False,
True,
True,
False,
XawMenuButtonDestroy,
XtInheritResize,
XtInheritExpose,
XawMenuButtonSetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
defaultTranslations,
XtInheritQueryGeometry,
XtInheritDisplayAccelerator,
NULL,
},
{
XtInheritChangeSensitive
},
{
NULL,
},
{
NULL,
},
{
NULL,
},
};
WidgetClass menuButtonWidgetClass = (WidgetClass)&menuButtonClassRec;
static void
XawMenuButtonClassInitialize(void)
{
XawInitializeWidgetSet();
XtRegisterGrabAction(PopupMenu, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync);
}
static void
XawMenuButtonInitialize(Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
MenuButtonWidget mbw = (MenuButtonWidget)cnew;
if (mbw->menu_button.menu_name != default_menu_name)
mbw->menu_button.menu_name = XtNewString(mbw->menu_button.menu_name);
}
static void
XawMenuButtonDestroy(Widget w)
{
MenuButtonWidget mbw = (MenuButtonWidget)w;
if (mbw->menu_button.menu_name != default_menu_name)
XtFree(mbw->menu_button.menu_name);
}
static Boolean
XawMenuButtonSetValues(Widget current, Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
MenuButtonWidget mbw_old = (MenuButtonWidget)current;
MenuButtonWidget mbw_new = (MenuButtonWidget)cnew;
if (mbw_old->menu_button.menu_name != mbw_new->menu_button.menu_name) {
if (mbw_old->menu_button.menu_name != default_menu_name)
XtFree(mbw_old->menu_button.menu_name);
if (mbw_new->menu_button.menu_name != default_menu_name)
mbw_new->menu_button.menu_name =
XtNewString(mbw_new->menu_button.menu_name);
}
return (False);
}
static void
PopupMenu(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
MenuButtonWidget mbw = (MenuButtonWidget)w;
Widget menu = NULL, temp;
Arg arglist[2];
Cardinal num_args;
int menu_x, menu_y, menu_width, menu_height, button_height;
Position button_x, button_y;
temp = w;
while(temp != NULL) {
menu = XtNameToWidget(temp, mbw->menu_button.menu_name);
if (menu == NULL)
temp = XtParent(temp);
else
break;
}
if (menu == NULL) {
char error_buf[BUFSIZ];
(void)XmuSnprintf(error_buf, sizeof(error_buf),
"MenuButton: Could not find menu widget named %s.",
mbw->menu_button.menu_name);
XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
return;
}
if (!XtIsRealized(menu))
XtRealizeWidget(menu);
menu_width = XtWidth(menu) + (XtBorderWidth(menu) << 1);
button_height = XtHeight(w) + (XtBorderWidth(w) << 1);
menu_height = XtHeight(menu) + (XtBorderWidth(menu) << 1);
XtTranslateCoords(w, 0, 0, &button_x, &button_y);
menu_x = button_x;
menu_y = button_y + button_height;
if (menu_y >= 0) {
int scr_height = HeightOfScreen(XtScreen(menu));
if (menu_y + menu_height > scr_height)
menu_y = button_y - menu_height;
if (menu_y < 0) {
menu_y = scr_height - menu_height;
menu_x = button_x + XtWidth(w) + (XtBorderWidth(w) << 1);
if (menu_x + menu_width > WidthOfScreen(XtScreen(menu)))
menu_x = button_x - menu_width;
}
}
if (menu_y < 0)
menu_y = 0;
if (menu_x >= 0) {
int scr_width = WidthOfScreen(XtScreen(menu));
if (menu_x + menu_width > scr_width)
menu_x = scr_width - menu_width;
}
if (menu_x < 0)
menu_x = 0;
num_args = 0;
XtSetArg(arglist[num_args], XtNx, menu_x); num_args++;
XtSetArg(arglist[num_args], XtNy, menu_y); num_args++;
XtSetValues(menu, arglist, num_args);
XtPopupSpringLoaded(menu);
}