1 /*
2 **
3 ** MButton.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyright (C) 2004 Jose E. Marchesi
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 3 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with GNU gv; see the file COPYING.  If not, write to
20 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ** Boston, MA 02111-1307, USA.
22 **
23 ** Author:   Johannes Plass (plass@thep.physik.uni-mainz.de)
24 **           Department of Physics
25 **           Johannes Gutenberg-University
26 **           Mainz, Germany
27 **
28 **           Jose E. Marchesi (jemarch@gnu.org)
29 **           GNU Project
30 **
31 */
32 #include "ac_config.h"
33 
34 /*
35 #define MESSAGES
36 */
37 #include "message.h"
38 
39 #include <stdio.h>
40 #include "paths.h"
41 #include INC_X11(IntrinsicP.h)
42 #include INC_X11(StringDefs.h)
43 #include INC_XAW(XawInit.h)
44 #include "MButtonP.h"
45 
46 static void ClassInitialize(void);
47 static void PopupMenu(Widget,XEvent*,String*,Cardinal*);
48 
49 #define superclass ((ButtonWidgetClass)&buttonClassRec)
50 
51 static char defaultTranslations[] =
52 "Any<BtnDown>:set()PopupMenu()";
53 
54 #define offset(field) XtOffsetOf(MButtonRec, field)
55 static XtResource resources[] = {
56   {XtNmenuName, XtCMenuName, XtRString, sizeof(String),
57     offset(mbutton.menu_name), XtRString, (XtPointer)"menu"},
58   {XtNsetFrameStyle, XtCSetFrameStyle, XtRFrameType, sizeof(XawFrameType),
59    offset(button.set_frame_style), XtRImmediate, (XtPointer) XawRAISED },
60 };
61 #undef offset
62 
63 static XtActionsRec actionsList[] =
64 {
65   {"PopupMenu",	PopupMenu}
66 };
67 
68 MButtonClassRec mbuttonClassRec = {
69   {
70     (WidgetClass) superclass,		/* superclass		  */
71     "MButton",				/* class_name		  */
72     sizeof(MButtonRec),     	  	/* size			  */
73     ClassInitialize,			/* class_initialize	  */
74     NULL,				/* class_part_initialize  */
75     FALSE,				/* class_inited		  */
76     NULL,				/* initialize		  */
77     NULL,				/* initialize_hook	  */
78     XtInheritRealize,			/* realize		  */
79     actionsList,			/* actions		  */
80     XtNumber(actionsList),		/* num_actions		  */
81     resources,				/* resources		  */
82     XtNumber(resources),		/* resource_count	  */
83     NULLQUARK,				/* xrm_class		  */
84     FALSE,				/* compress_motion	  */
85     TRUE,				/* compress_exposure	  */
86     TRUE,				/* compress_enterleave    */
87     FALSE,				/* visible_interest	  */
88     NULL,				/* destroy		  */
89     XtInheritResize,			/* resize		  */
90     XtInheritExpose,			/* expose		  */
91     NULL,				/* set_values		  */
92     NULL,				/* set_values_hook	  */
93     XtInheritSetValuesAlmost,		/* set_values_almost	  */
94     NULL,				/* get_values_hook	  */
95     NULL,				/* accept_focus		  */
96     XtVersion,				/* version		  */
97     NULL,				/* callback_private	  */
98     defaultTranslations,               	/* tm_table		  */
99     XtInheritQueryGeometry,		/* query_geometry	  */
100     XtInheritDisplayAccelerator,	/* display_accelerator	  */
101     NULL				/* extension		  */
102   },  /* CoreClass fields initialization */
103   {
104     XtInheritChangeSensitive		/* change_sensitive	  */
105   },  /* SimpleClass fields initialization */
106   {
107     XtInheritXaw3dShadowDraw,           /* shadowdraw           */
108   },  /* ThreeDClass fields initialization */
109   {
110     0,                                     /* field not used    */
111   },  /* LabelClass fields initialization */
112   {
113     0,                                     /* field not used    */
114   },  /* CommandClass fields initialization */
115   {
116     0,                                     /* field not used    */
117   },  /* ButtonClass fields initialization */
118   {
119     0,                                     /* field not used    */
120   }  /* MbuttonClass fields initialization */
121 };
122 
123   /* for public consumption */
124 WidgetClass mbuttonWidgetClass = (WidgetClass) &mbuttonClassRec;
125 
126 /****************************************************************
127  *
128  * Private Procedures
129  *
130  ****************************************************************/
131 
ClassInitialize(void)132 static void ClassInitialize(void)
133 {
134   XawInitializeWidgetSet();
135   XtRegisterGrabAction(PopupMenu, True,
136 		       (unsigned int)(ButtonPressMask | ButtonReleaseMask),
137 		       GrabModeAsync, GrabModeAsync);
138 }
139 
140 void
PopupMenu(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params)141 PopupMenu(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params)
142 {
143   MButtonWidget mbw = (MButtonWidget) w;
144   Widget temp;
145   Widget menu;
146   Arg args[5];
147   Cardinal n;
148   int menu_x, menu_y;
149   Dimension menu_width, menu_height,button_width,button_height;
150   Position button_x, button_y;
151 
152   BEGINMESSAGE(PopupMenu)
153 
154   temp = w;
155   menu = NULL;
156   while(temp != NULL) {
157     menu = XtNameToWidget(temp, mbw->mbutton.menu_name);
158     if (!menu) temp = XtParent(temp);
159     else break;
160   }
161 
162   if (!menu) {
163 #if 0
164     char error_buf[BUFSIZ];
165     (void) sprintf(error_buf, "Mbutton: %s %s.","Could not find menu widget named", mbw->mbutton.menu_name);
166     XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
167 #endif
168     ENDMESSAGE(PopupMenu)
169     return;
170   }
171   if (!XtIsRealized(menu)) XtRealizeWidget(menu);
172 
173   menu_width    = menu->core.width  + 2 * menu->core.border_width;
174   menu_height   = menu->core.height + 2 * menu->core.border_width;
175   button_width  = w->core.width     + 2 * w->core.border_width;
176   button_height = w->core.height    + 2 * w->core.border_width;
177 
178   XtTranslateCoords(w, 0, 0, &button_x, &button_y);
179   menu_x = button_x;
180   menu_y = button_y;
181   if (*num_params==0) menu_y += button_height;
182 
183   if (menu_x >= 0) {
184     int scr_width = WidthOfScreen(XtScreen(menu));
185     if (menu_x + menu_width > scr_width) menu_x = scr_width - menu_width;
186   }
187   if (menu_x < 0)  menu_x = 0;
188 
189   if (menu_y >= 0) {
190     int scr_height = HeightOfScreen(XtScreen(menu));
191     if (menu_y + menu_height > scr_height) menu_y = scr_height - menu_height;
192   }
193   if (menu_y < 0) menu_y = 0;
194 
195   n = 0;
196   XtSetArg(args[n], XtNx, menu_x); n++;
197   XtSetArg(args[n], XtNy, menu_y); n++;
198   if (*num_params > 0 && menu_width<button_width) {
199      XtSetArg(args[n], XtNwidth, button_width-2*menu->core.border_width); n++;
200   }
201   XtSetValues(menu, args, n);
202 
203   XtPopupSpringLoaded(menu);
204   ENDMESSAGE(PopupMenu)
205 }
206 
207