17a84e134Smrg/* 27a84e134SmrgCopyright 1989, 1994, 1998 The Open Group 37a84e134Smrg 47a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its 57a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that 67a84e134Smrgthe above copyright notice appear in all copies and that both that 77a84e134Smrgcopyright notice and this permission notice appear in supporting 87a84e134Smrgdocumentation. 97a84e134Smrg 107a84e134SmrgThe above copyright notice and this permission notice shall be included in 117a84e134Smrgall copies or substantial portions of the Software. 127a84e134Smrg 137a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 147a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 157a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 167a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 177a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 187a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 197a84e134Smrg 207a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be 217a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings 227a84e134Smrgin this Software without prior written authorization from The Open Group. 237a84e134Smrg * 247a84e134Smrg */ 257a84e134Smrg 267a84e134Smrg/* 277a84e134Smrg * MenuButton.c - Source code for MenuButton widget. 287a84e134Smrg * 297a84e134Smrg * This is the source code for the Athena MenuButton widget. 307a84e134Smrg * It is intended to provide an easy method of activating pulldown menus. 317a84e134Smrg * 327a84e134Smrg * Date: May 2, 1989 337a84e134Smrg * 347a84e134Smrg * By: Chris D. Peterson 35421c997bSmrg * 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/Xaw/MenuButtoP.h> 467a84e134Smrg#include <X11/Xaw/XawInit.h> 477a84e134Smrg#include "Private.h" 487a84e134Smrg 497a84e134Smrg/* 507a84e134Smrg * Class Methods 517a84e134Smrg */ 527a84e134Smrgstatic void XawMenuButtonClassInitialize(void); 537a84e134Smrgstatic void XawMenuButtonInitialize(Widget, Widget, ArgList, Cardinal*); 547a84e134Smrgstatic void XawMenuButtonDestroy(Widget); 557a84e134Smrgstatic Boolean XawMenuButtonSetValues(Widget, Widget, Widget, ArgList, Cardinal*); 567a84e134Smrg 577a84e134Smrg/* 587a84e134Smrg * Actions 597a84e134Smrg */ 607a84e134Smrgstatic void PopupMenu(Widget, XEvent*, String*, Cardinal*); 617a84e134Smrg 627a84e134Smrg/* 637a84e134Smrg * Initialization 647a84e134Smrg */ 657a84e134Smrg#define superclass ((CommandWidgetClass)&commandClassRec) 667a84e134Smrg 67421c997bSmrgstatic char defaultTranslations[] = 687a84e134Smrg"<Enter>:" "highlight()\n" 697a84e134Smrg"<Leave>:" "reset()\n" 707a84e134Smrg"Any<BtnDown>:" "reset() PopupMenu()\n"; 717a84e134Smrg 727a84e134Smrgstatic char default_menu_name[] = "menu"; 737a84e134Smrg 747a84e134Smrg#define offset(field) XtOffsetOf(MenuButtonRec, field) 757a84e134Smrgstatic XtResource resources[] = { 767a84e134Smrg { 777a84e134Smrg XtNmenuName, 787a84e134Smrg XtCMenuName, 797a84e134Smrg XtRString, 807a84e134Smrg sizeof(String), 817a84e134Smrg offset(menu_button.menu_name), 827a84e134Smrg XtRString, 837a84e134Smrg (XtPointer)default_menu_name 847a84e134Smrg }, 857a84e134Smrg}; 867a84e134Smrg#undef offset 877a84e134Smrg 887a84e134Smrgstatic XtActionsRec actionsList[] = 897a84e134Smrg{ 907a84e134Smrg {"PopupMenu", PopupMenu}, 917a84e134Smrg}; 927a84e134Smrg 937a84e134SmrgMenuButtonClassRec menuButtonClassRec = { 947a84e134Smrg /* core */ 957a84e134Smrg { 967a84e134Smrg (WidgetClass)superclass, /* superclass */ 977a84e134Smrg "MenuButton", /* class_name */ 98421c997bSmrg sizeof(MenuButtonRec), /* size */ 997a84e134Smrg XawMenuButtonClassInitialize, /* class_initialize */ 1007a84e134Smrg NULL, /* class_part_initialize */ 1017a84e134Smrg False, /* class_inited */ 1027a84e134Smrg XawMenuButtonInitialize, /* initialize */ 1037a84e134Smrg NULL, /* initialize_hook */ 1047a84e134Smrg XtInheritRealize, /* realize */ 1057a84e134Smrg actionsList, /* actions */ 1067a84e134Smrg XtNumber(actionsList), /* num_actions */ 1077a84e134Smrg resources, /* resources */ 1087a84e134Smrg XtNumber(resources), /* num_resources */ 1097a84e134Smrg NULLQUARK, /* xrm_class */ 1107a84e134Smrg False, /* compress_motion */ 1117a84e134Smrg True, /* compress_exposure */ 1127a84e134Smrg True, /* compress_enterleave */ 1137a84e134Smrg False, /* visible_interest */ 1147a84e134Smrg XawMenuButtonDestroy, /* destroy */ 1157a84e134Smrg XtInheritResize, /* resize */ 1167a84e134Smrg XtInheritExpose, /* expose */ 1177a84e134Smrg XawMenuButtonSetValues, /* set_values */ 1187a84e134Smrg NULL, /* set_values_hook */ 1197a84e134Smrg XtInheritSetValuesAlmost, /* set_values_almost */ 1207a84e134Smrg NULL, /* get_values_hook */ 1217a84e134Smrg NULL, /* accept_focus */ 1227a84e134Smrg XtVersion, /* version */ 1237a84e134Smrg NULL, /* callback_private */ 124421c997bSmrg defaultTranslations, /* tm_table */ 1257a84e134Smrg XtInheritQueryGeometry, /* query_geometry */ 1267a84e134Smrg XtInheritDisplayAccelerator, /* display_accelerator */ 1277a84e134Smrg NULL, /* extension */ 1287a84e134Smrg }, 1297a84e134Smrg /* simple */ 1307a84e134Smrg { 131efbcb2bfSmrg XtInheritChangeSensitive, /* change_sensitive */ 132efbcb2bfSmrg#ifndef OLDXAW 133efbcb2bfSmrg NULL, 134efbcb2bfSmrg#endif 1357a84e134Smrg }, 1367a84e134Smrg /* label */ 1377a84e134Smrg { 1387a84e134Smrg NULL, /* extension */ 1397a84e134Smrg }, 1407a84e134Smrg /* command */ 1417a84e134Smrg { 1427a84e134Smrg NULL, /* extension */ 1437a84e134Smrg }, 1447a84e134Smrg /* menu_button */ 1457a84e134Smrg { 1467a84e134Smrg NULL, /* extension */ 1477a84e134Smrg }, 1487a84e134Smrg}; 1497a84e134Smrg 1507a84e134SmrgWidgetClass menuButtonWidgetClass = (WidgetClass)&menuButtonClassRec; 1517a84e134Smrg 1527a84e134Smrg/* 1537a84e134Smrg * Implementation 1547a84e134Smrg */ 1557a84e134Smrgstatic void 1567a84e134SmrgXawMenuButtonClassInitialize(void) 1577a84e134Smrg{ 1587a84e134Smrg XawInitializeWidgetSet(); 1597a84e134Smrg XtRegisterGrabAction(PopupMenu, True, 1607a84e134Smrg ButtonPressMask | ButtonReleaseMask, 1617a84e134Smrg GrabModeAsync, GrabModeAsync); 1627a84e134Smrg} 1637a84e134Smrg 1647a84e134Smrg/*ARGSUSED*/ 1657a84e134Smrgstatic void 1665ec34c4cSmrgXawMenuButtonInitialize(Widget request _X_UNUSED, Widget cnew, 1675ec34c4cSmrg ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 1687a84e134Smrg{ 1697a84e134Smrg MenuButtonWidget mbw = (MenuButtonWidget)cnew; 1707a84e134Smrg 1717a84e134Smrg if (mbw->menu_button.menu_name != default_menu_name) 1727a84e134Smrg mbw->menu_button.menu_name = XtNewString(mbw->menu_button.menu_name); 1737a84e134Smrg} 1747a84e134Smrg 1757a84e134Smrgstatic void 1767a84e134SmrgXawMenuButtonDestroy(Widget w) 1777a84e134Smrg{ 1787a84e134Smrg MenuButtonWidget mbw = (MenuButtonWidget)w; 1797a84e134Smrg 1807a84e134Smrg if (mbw->menu_button.menu_name != default_menu_name) 1817a84e134Smrg XtFree(mbw->menu_button.menu_name); 1827a84e134Smrg} 1837a84e134Smrg 1847a84e134Smrg/*ARGSUSED*/ 1857a84e134Smrgstatic Boolean 1865ec34c4cSmrgXawMenuButtonSetValues(Widget current, Widget request _X_UNUSED, Widget cnew, 1875ec34c4cSmrg ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 1887a84e134Smrg{ 1897a84e134Smrg MenuButtonWidget mbw_old = (MenuButtonWidget)current; 1907a84e134Smrg MenuButtonWidget mbw_new = (MenuButtonWidget)cnew; 1917a84e134Smrg 1927a84e134Smrg if (mbw_old->menu_button.menu_name != mbw_new->menu_button.menu_name) { 1937a84e134Smrg if (mbw_old->menu_button.menu_name != default_menu_name) 1947a84e134Smrg XtFree(mbw_old->menu_button.menu_name); 1957a84e134Smrg if (mbw_new->menu_button.menu_name != default_menu_name) 1967a84e134Smrg mbw_new->menu_button.menu_name = 1977a84e134Smrg XtNewString(mbw_new->menu_button.menu_name); 1987a84e134Smrg } 1997a84e134Smrg 2007a84e134Smrg return (False); 2017a84e134Smrg} 2027a84e134Smrg 2037a84e134Smrg/*ARGSUSED*/ 2047a84e134Smrgstatic void 2055ec34c4cSmrgPopupMenu(Widget w, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 2067a84e134Smrg{ 2077a84e134Smrg MenuButtonWidget mbw = (MenuButtonWidget)w; 2087a84e134Smrg Widget menu = NULL, temp; 2097a84e134Smrg Arg arglist[2]; 2107a84e134Smrg Cardinal num_args; 2117a84e134Smrg int menu_x, menu_y, menu_width, menu_height, button_height; 2127a84e134Smrg Position button_x, button_y; 2137a84e134Smrg 214efbcb2bfSmrg if ((temp = w) == NULL) 215efbcb2bfSmrg return; 216efbcb2bfSmrg 2177a84e134Smrg while(temp != NULL) { 2187a84e134Smrg menu = XtNameToWidget(temp, mbw->menu_button.menu_name); 219421c997bSmrg if (menu == NULL) 2207a84e134Smrg temp = XtParent(temp); 2217a84e134Smrg else 2227a84e134Smrg break; 2237a84e134Smrg } 2247a84e134Smrg 2257a84e134Smrg if (menu == NULL) { 2267a84e134Smrg char error_buf[BUFSIZ]; 2277a84e134Smrg 228421c997bSmrg snprintf(error_buf, sizeof(error_buf), 229421c997bSmrg "MenuButton: Could not find menu widget named %s.", 230421c997bSmrg mbw->menu_button.menu_name); 2317a84e134Smrg XtAppWarning(XtWidgetToApplicationContext(w), error_buf); 2327a84e134Smrg return; 2337a84e134Smrg } 2347a84e134Smrg 2357a84e134Smrg if (!XtIsRealized(menu)) 2367a84e134Smrg XtRealizeWidget(menu); 237421c997bSmrg 2387a84e134Smrg menu_width = XtWidth(menu) + (XtBorderWidth(menu) << 1); 2397a84e134Smrg button_height = XtHeight(w) + (XtBorderWidth(w) << 1); 2407a84e134Smrg menu_height = XtHeight(menu) + (XtBorderWidth(menu) << 1); 2417a84e134Smrg 2427a84e134Smrg XtTranslateCoords(w, 0, 0, &button_x, &button_y); 2437a84e134Smrg menu_x = button_x; 2447a84e134Smrg menu_y = button_y + button_height; 2457a84e134Smrg 2467a84e134Smrg if (menu_y >= 0) { 2477a84e134Smrg int scr_height = HeightOfScreen(XtScreen(menu)); 2487a84e134Smrg 2497a84e134Smrg if (menu_y + menu_height > scr_height) 2507a84e134Smrg menu_y = button_y - menu_height; 2517a84e134Smrg if (menu_y < 0) { 2527a84e134Smrg menu_y = scr_height - menu_height; 2537a84e134Smrg menu_x = button_x + XtWidth(w) + (XtBorderWidth(w) << 1); 2547a84e134Smrg if (menu_x + menu_width > WidthOfScreen(XtScreen(menu))) 2557a84e134Smrg menu_x = button_x - menu_width; 2567a84e134Smrg } 2577a84e134Smrg } 2587a84e134Smrg if (menu_y < 0) 2597a84e134Smrg menu_y = 0; 2607a84e134Smrg 2617a84e134Smrg if (menu_x >= 0) { 2627a84e134Smrg int scr_width = WidthOfScreen(XtScreen(menu)); 2637a84e134Smrg 2647a84e134Smrg if (menu_x + menu_width > scr_width) 2657a84e134Smrg menu_x = scr_width - menu_width; 2667a84e134Smrg } 267421c997bSmrg if (menu_x < 0) 2687a84e134Smrg menu_x = 0; 2697a84e134Smrg 2707a84e134Smrg num_args = 0; 2717a84e134Smrg XtSetArg(arglist[num_args], XtNx, menu_x); num_args++; 2727a84e134Smrg XtSetArg(arglist[num_args], XtNy, menu_y); num_args++; 2737a84e134Smrg XtSetValues(menu, arglist, num_args); 2747a84e134Smrg 2757a84e134Smrg XtPopupSpringLoaded(menu); 2767a84e134Smrg} 277