1 /* $Id: MegaB.c,v 1.1 2002/05/14 23:01:27 dannybackx Exp $ */
2 /*
3  * Copyright 1994 John L. Cwikla
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without fee,
7  * provided that the above copyright notice appears in all copies and that
8  * both that copyright notice and this permission notice appear in
9  * supporting documentation, and that the name of John L. Cwikla or
10  * Wolfram Research, Inc not be used in advertising or publicity
11  * pertaining to distribution of the software without specific, written
12  * prior permission.	John L. Cwikla and Wolfram Research, Inc make no
13  * representations about the suitability of this software for any
14  * purpose. It is provided "as is" without express or implied warranty.
15  *
16  * John L. Cwikla and Wolfram Research, Inc disclaim all warranties with
17  * regard to this software, including all implied warranties of
18  * merchantability and fitness, in no event shall John L. Cwikla or
19  * Wolfram Research, Inc be liable for any special, indirect or
20  * consequential damages or any damages whatsoever resulting from loss of
21  * use, data or profits, whether in an action of contract, negligence or
22  * other tortious action, arising out of or in connection with the use or
23  * performance of this software.
24  *
25  * Author:
26  *  John L. Cwikla
27  *  X Programmer
28  *  Wolfram Research Inc.
29  *
30  *  cwikla@wri.com
31 */
32 
33 #include <Xm/XmP.h>
34 #include <Xm/XmosP.h>
35 
36 #include <Xm/BaseClassP.h>
37 #include <Xm/DrawP.h>
38 #include <Xm/MenuShellP.h>
39 #include <Xm/MenuUtilP.h>
40 #include <Xm/CascadeB.h>
41 #include <Xm/CascadeBG.h>
42 #include <X11/Xfuncs.h>
43 
44 #if HAVE_SOURCE || defined(LESSTIF_VERSION)
45 #include "XmI/TraversalI.h"
46 #endif /* HAVE_SOURCE */
47 
48 #include "MegaBP.h"
49 
50 #include <stdio.h>
51 #include <ctype.h>
52 
53 #define SCROLL_TIME 100
54 #define MINI_SEP_HEIGHT 3
55 
56 static XtWidgetClassProc classPartInit(WidgetClass _wc);
57 static XtProc classInit();
58 static XtInitProc initialize(Widget _request, Widget _new, String *_args,
59 		Cardinal *_numArg);
60 static XtWidgetProc destroy(Widget _mbw);
61 static void expose(Widget _mbw, XEvent *_event, Region _region);
62 static Boolean setValues(Widget _current, Widget _request, Widget _new, ArgList args, Cardinal *num_args);
63 static void borderHighlight(Widget _mbw);
64 static void borderUnhighlight(Widget _mbw);
65 
66 static void getMaxWidthPos(Widget _mbw, int *_maxWidthPos, Dimension *_height);
67 static void drawMiniSeparator(Widget _mbw, Position _y);
68 
69 static void enterWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
70 static void leaveWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
71 static void buttonMotion(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
72 static void up(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
73 static void down(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
74 static void buttonUp(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
75 static void buttonDown(Widget _mbw, XEvent *_event, String *_params,
76 		Cardinal *_numParms);
77 static void armAndActivate(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
78 static void focusIn(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
79 static void focusOut(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams);
80 static void timedScroll(XtPointer _closure, XtIntervalId *_id);
81 static Boolean cvtStringToMegaButtonMode(Display *_display, XrmValuePtr _args,
82 	Cardinal *_numArgs, XrmValuePtr _from, XrmValuePtr _to, XtPointer *_data);
83 
84 static void drawShadowedItem(Widget _mbw, int _pos, Boolean _clear);
85 static void drawArrow(Widget _mbw, int _pos, int _direction, Boolean _sensitive);
86 static void clearArrow(Widget _mbw, int _pos);
87 static void scroll(Widget _mbw, int _direction, Boolean _addTimeout, int _delay);
88 static void findGoodShowPos(Widget _mbw);
89 
90 static void toggleDrawProc(Widget _mbw, Position _x, Position _y, Boolean _on);
91 static void toggleSpaceProc(Widget _mbw, Dimension *_width, Dimension *_height);
92 
93 static void recheckSizesAtPos(Widget _mbw, int _pos);
94 
95 static Widget XtGetShell(Widget _w);
96 
97 #define CORE(w) (((XmMegaButtonWidget)(w))->core)
98 #define PRIM(w) (((XmMegaButtonWidget)(w))->primitive)
99 #define LABEL(w) (((XmMegaButtonWidget)(w))->label)
100 #define PUSH(w) (((XmMegaButtonWidget)(w))->push_button)
101 #define MB(w) (((XmMegaButtonWidget)(w))->mega_button)
102 
103 #define WIDTH(w) (((XmMegaButtonWidget)(w))->core.width)
104 #define HEIGHT(w) (((XmMegaButtonWidget)(w))->core.height)
105 
106 #define VIS_COUNT(w) (((XmMegaButtonWidget)(w))->mega_button.visibleItemCount)
107 #define ICOUNT(w) (((XmMegaButtonWidget)(w))->mega_button.itemCount)
108 #define ITEMS(w) (((XmMegaButtonWidget)(w))->mega_button._items)
109 #define EXITEMS(w) (((XmMegaButtonWidget)(w))->mega_button.exitems)
110 #define VIS_POS(w) (((XmMegaButtonWidget)(w))->mega_button.visiblePos)
111 #define FPOS(w) (((XmMegaButtonWidget)(w))->mega_button.firstVisibleItem)
112 #define EL_HEIGHT(w) (((XmMegaButtonWidget)(w))->mega_button.elementHeight)
113 #define YOFFSET(w) (((XmMegaButtonWidget)(w))->mega_button.yOffset)
114 #define XOFFSET(w) (((XmMegaButtonWidget)(w))->mega_button.xOffset)
115 #define HAS_ARROWS(w) (((XmMegaButtonWidget)(w))->mega_button.hasArrows)
116 #define SET_POS(w) (((XmMegaButtonWidget)(w))->mega_button.setPosition)
117 #define COPY_GC(w) (((XmMegaButtonWidget)(w))->mega_button.copyGC)
118 #define TIMER(w) (((XmMegaButtonWidget)(w))->mega_button.timer)
119 #define TDIR(w) (((XmMegaButtonWidget)(w))->mega_button.timedScrollDirection)
120 #define SFOS(w) (((XmMegaButtonWidget)(w))->mega_button.savedFillOnSelect)
121 #define IDELAY(w) (((XmMegaButtonWidget)(w))->mega_button.initialDelay)
122 #define RDELAY(w) (((XmMegaButtonWidget)(w))->mega_button.repeatDelay)
123 #define FAKE_ITEM(w) (((XmMegaButtonWidget)(w))->mega_button.fakeItem)
124 #define CUR_SIZE(w) (((XmMegaButtonWidget)(w))->mega_button.currentSize)
125 #define DATA(w) (((XmMegaButtonWidget)(w))->mega_button.data)
126 #define CB_DATA(w) (((XmMegaButtonWidget)(w))->mega_button.cbData)
127 #define MAX_STRING_POS(w) (((XmMegaButtonWidget)(w))->mega_button.maxStringPos)
128 #define MAX_STRING_WIDTH(w) (((XmMegaButtonWidget)(w))->mega_button.maxStringWidth)
129 #define MODE(w) (((XmMegaButtonWidget)(w))->mega_button.mode)
130 #define TOG_DATA(w) (((XmMegaButtonWidget)(w))->mega_button.toggleData)
131 #define FILL_ON_SELECT(w) (((XmMegaButtonWidget)(w))->mega_button.fillOnSelect)
132 #define SELECT_COLOR(w) (((XmMegaButtonWidget)(w))->mega_button.selectColor)
133 #define SELECT_GC(w) (((XmMegaButtonWidget)(w))->mega_button.selectGC)
134 #define CHUNK_SIZE(w) (((XmMegaButtonWidget)(w))->mega_button.chunkSize)
135 #define VIS_W_OFF(w) (((XmMegaButtonWidget)(w))->mega_button.visibleWhenOff)
136 #define STR_HEIGHT(w) (((XmMegaButtonWidget)(w))->mega_button.stringHeight)
137 
138 #define DEFAULT_CHUNK_SIZE 50
139 
140 static char traversalTranslations[] =
141 "<Btn1Motion>: BtnMotion() \n\
142 <Enter>: Enter() \n\
143 <Leave>: Leave() \n\
144 <Key>osfHelp:Help() \n\
145 <Unmap>:Unmap()\n\
146 <FocusOut>:FocusOut()\n\
147 <FocusIn>:FocusIn()\n\
148 <Key>osfCancel:MenuEscape()\n\
149 <Key>osfUp: MegaButtonTraverseUp() \n\
150 <Key>osfDown: MegaButtonTraverseDown() \n\
151 <Key>osfLeft:MenuTraverseLeft()\n\
152 <Key>osfRight:MenuTraverseRight()\n\
153 <Key>osfSelect:ArmAndActivate()\n\
154 <Key>osfActivate:ArmAndActivate()\n\
155 ~s ~m ~a <Key>Return:ArmAndActivate()\n\
156 ~s ~m ~a <Key>space:ArmAndActivate()";
157 
158 #define TheOffset(field) XtOffset(XmMegaButtonWidget, mega_button.field)
159 static XtResource resources[] =
160 {
161 	{XmNitems, XmCItems, XtRPointer, sizeof(XtPointer),
162 		TheOffset(exitems), XmRImmediate, (XtPointer)NULL},
163 	{XmNitemCount, XmCItemCount, XtRInt, sizeof(int),
164 		TheOffset(itemCount), XmRImmediate, (XtPointer)0},
165 	{XmNvisibleItemCount, XmCVisibleItemCount, XmRInt, sizeof(int),
166 		TheOffset(visibleItemCount), XtRImmediate, (XtPointer)0},
167 	{XmNsetPosition, XmCSetPosition, XtRInt, sizeof(int),
168 		TheOffset(setPosition), XmRImmediate, (XtPointer)-1},
169 	{XmNrepeatDelay, XmCRepeatDelay, XmRInt, sizeof(int),
170 		TheOffset(repeatDelay), XmRImmediate, (XtPointer)50},
171 	{XmNinitialDelay, XmCInitialDelay, XmRInt, sizeof(int),
172 		TheOffset(initialDelay), XmRImmediate, (XtPointer)250},
173 	{XmNbuttonMode, XmCButtonMode, XmRMegaButtonMode, sizeof(unsigned char),
174 		TheOffset(mode), XmRImmediate, (XtPointer)XmMODE_TOGGLE_BUTTON},
175 	{XmNselectColor, XmCSelectColor, XmRPixel, sizeof(Pixel),
176 		TheOffset(selectColor), XmRCallProc, (XtPointer)_XmSelectColorDefault},
177 	{XmNfillOnSelect, XmCFillOnSelect, XmRBoolean, sizeof(Boolean),
178 		TheOffset(fillOnSelect), XmRImmediate, (XtPointer)FALSE},
179 	{XmNchunkSize, XmCChunkSize, XmRInt, sizeof(int),
180 		TheOffset(chunkSize), XmRImmediate, (XtPointer)DEFAULT_CHUNK_SIZE},
181 	{XmNcallbackData, XmCCallbackData, XmRPointer, sizeof(XtPointer),
182 		TheOffset(cbData), XmRImmediate, (XtPointer)NULL},
183 	{XmNvisibleWhenOff, XmCVisibleWhenOff, XmRBoolean, sizeof(Boolean),
184 		TheOffset(visibleWhenOff), XtRImmediate, (XtPointer)FALSE},
185 };
186 
187 #undef TheOffset
188 
189 static XtActionsRec actions[] =
190 {
191 	{ "Enter",		  (XtActionProc) enterWidget  },
192 	{ "Leave",		  (XtActionProc) leaveWidget  },
193 	{ "BtnMotion",		(XtActionProc) buttonMotion },
194 	{ "MegaButtonTraverseUp",				(XtActionProc) up },
195 	{ "MegaButtonTraverseDown",				(XtActionProc) down },
196 	{ "ArmAndActivate", (XtActionProc) armAndActivate },
197 	{ "BtnUp",		  (XtActionProc) buttonUp },
198 	{ "BtnDown",	(XtActionProc) buttonDown},
199 	{ "FocusIn",	 (XtActionProc) focusIn },
200 	{ "FocusOut",	(XtActionProc) focusOut},
201 
202 	{"MenuBtnDown",	 (XtActionProc)down},
203 	{"MenuBtnUp",		(XtActionProc)up},
204 	{"PulldownBtnDown",	 (XtActionProc)down},
205 	{"PulldownBtnUp",		(XtActionProc)up},
206 	{"PopupBtnDown",		(XtActionProc)down},
207 	{"PopupBtnUp",		  (XtActionProc)up},
208 	{"MenuBarBtnDown",	  (XtActionProc)down},
209 	{"MenuBarBtnUp",		(XtActionProc)up},
210 
211 	{"MenuTraverseUp",	  (XtActionProc)up},
212 	{"MenuTraverseDown",	(XtActionProc)down},
213 	{"MenuFocusIn",		 (XtActionProc)focusIn },
214 	{"MenuFocusOut",		(XtActionProc)focusOut },
215 	{"MenuUnmap",			(XtActionProc)leaveWidget },
216 	{"MenuEnter",			(XtActionProc)enterWidget},
217 
218 }; /* actions */
219 
220 static XmBaseClassExtRec		megaBBaseClassExtRec =
221 {
222 	NULL,									 /* Next extension		*/
223 	NULLQUARK,								/* record type XmQmotif */
224 	XmBaseClassExtVersion,					/* version			  */
225 	sizeof(XmBaseClassExtRec),				/* size				 */
226 	XmInheritInitializePrehook,						/* initialize prehook	*/
227 	XmInheritSetValuesPrehook,				/* set_values prehook	*/
228 	XmInheritInitializePosthook,						/* initialize posthook  */
229 	XmInheritSetValuesPosthook,				/* set_values posthook  */
230 	XmInheritClass,							/* secondary class	  */
231 	XmInheritSecObjectCreate,				 /* creation proc		*/
232 	XmInheritGetSecResData,					/* getSecResData		*/
233 	{0},									  /* fast subclass		*/
234 	XmInheritGetValuesPrehook,				/* get_values prehook	*/
235 	XmInheritGetValuesPosthook,				/* get_values posthook  */
236 	(XtWidgetClassProc)NULL,				  /* classPartInitPrehook */
237 	(XtWidgetClassProc)NULL,				  /* classPartInitPosthook*/
238 	NULL,									 /* ext_resources		*/
239 	NULL,									 /* compiled_ext_resources*/
240 	0,										/* num_ext_resources	*/
241 	FALSE,									/* use_sub_resources	*/
242 	XmInheritWidgetNavigable,				 /* widgetNavigable	  */
243 	XmInheritFocusChange,					 /* focusChange		  */
244 };
245 
246 XmPrimitiveClassExtRec _XmMegaBPrimClassExtRec =
247 {
248 	NULL,
249 	NULLQUARK,
250 	XmPrimitiveClassExtVersion,
251 	sizeof(XmPrimitiveClassExtRec),
252 	XmInheritBaselineProc,				  /* widget_baseline */
253 	XmInheritDisplayRectProc,				/* widget_display_rect */
254 	(XmWidgetMarginsProc)NULL,			  /* widget_margins */
255 };
256 
257 
258 XmMegaButtonClassRec xmMegaButtonClassRec =
259 {
260 	{
261 		(WidgetClass)&xmPushButtonClassRec,			  /* superclass */
262 		"XmMegaButton",								 /* class_name */
263 		(Cardinal)sizeof(XmMegaButtonRec),		 /* widget size */
264 		(XtProc)classInit,							  /* class_init */
265 		(XtWidgetClassProc)classPartInit,			/* class_part_init */
266 		(XtEnum)FALSE,								/* class_inited */
267 		(XtInitProc)initialize,						 /* initialize */
268 		(XtArgsProc)NULL,								/* init_hook */
269 		XtInheritRealize,							/* realize */
270 		(XtActionList)actions,							  /* actions */
271 		(Cardinal)XtNumber(actions),						/* num_actions */
272 		(XtResourceList)resources,							/* resources */
273 		(Cardinal)XtNumber(resources),						/* num_resources */
274 		NULLQUARK,									/* xrm_class */
275 		TRUE,										/* compress_motion */
276 		(XtEnum)FALSE,								/* compress_exposur */
277 		TRUE,										/* compress enterleave */
278 		FALSE,									  /* visibility_interest */
279 		(XtWidgetProc)destroy,							  /* destroy */
280 		(XtWidgetProc)XtInheritResize,
281 		(XtExposeProc)expose,
282 		(XtSetValuesFunc)setValues,						  /* set_values */
283 		(XtArgsFunc)NULL,								/* set_values_hook */
284 		XtInheritSetValuesAlmost,					/* set_values_almost */
285 		(XtArgsProc)NULL,								/* get_values_hook */
286 		NULL, 						/* accept_focus */
287 		XtVersion,									/* version */
288 		(XtPointer)NULL,								/* callback_private */
289 		XtInheritTranslations,
290 		(XtGeometryHandler)NULL,		  /* query_geometry */
291 		XtInheritDisplayAccelerator,				 /* display_accelerator */
292 		(XtPointer)&megaBBaseClassExtRec,										/* extension */
293 	},
294 	{ 	/* xmPrimitiveClass */
295 		(XtWidgetProc)borderHighlight,
296 		(XtWidgetProc)borderUnhighlight,
297 		XtInheritTranslations,
298 		(XtActionProc)armAndActivate,
299 		NULL,
300 		0,
301 		(XtPointer)&_XmMegaBPrimClassExtRec,
302 	},
303 	{	/* xmLabelClass */
304 		(XtWidgetProc) XmInheritSetOverrideCallback,
305 		NULL,
306 		NULL,
307 		NULL,
308 	},
309 	{ 	/* xmPushButtonClass */
310 		(XtPointer)NULL,
311 	},
312 	{
313 		XmInheritMegaButtonToggleSpaceProc,
314 		XmInheritMegaButtonToggleDrawProc,
315 	}
316 };
317 
318 WidgetClass xmMegaButtonWidgetClass = (WidgetClass)&xmMegaButtonClassRec;
319 
320 
classPartInit(WidgetClass _wc)321 static XtWidgetClassProc classPartInit(WidgetClass _wc)
322 {
323 	XmMegaButtonWidgetClass mbwc;
324 
325 	_XmFastSubclassInit(_wc, (XmPUSH_BUTTON_BIT | XmLABEL_BIT |
326 							XmPRIMITIVE_BIT));
327 
328 	mbwc = (XmMegaButtonWidgetClass)_wc;
329 	if (mbwc->mega_button_class.toggleSpaceProc == XmInheritMegaButtonToggleSpaceProc)
330 		mbwc->mega_button_class.toggleSpaceProc = toggleSpaceProc;
331 	if (mbwc->mega_button_class.toggleDrawProc == XmInheritMegaButtonToggleDrawProc)
332 		mbwc->mega_button_class.toggleDrawProc = toggleDrawProc;
333 	return (XtWidgetClassProc)NULL;
334 }
335 
classInit()336 static XtProc classInit()
337 {
338 	xmMegaButtonClassRec.label_class.translations = (String)XtParseTranslationTable(traversalTranslations);
339 
340 	XtSetTypeConverter(XtRString, XmRMegaButtonMode, cvtStringToMegaButtonMode,
341 		(XtConvertArgList)NULL, 0,
342 			XtCacheAll, (XtDestructor)NULL);
343 
344 	return (XtProc)NULL;
345 }
346 
initialize(Widget _request,Widget _new,String * _args,Cardinal * _numArgs)347 static XtInitProc initialize(Widget _request, Widget _new, String *_args, Cardinal *_numArgs)
348 {
349 	int i;
350 	XmString xmstring;
351 	XGCValues gcValues;
352 	Dimension width;
353 
354 	VIS_POS(_new) = -1;
355 
356 	FPOS(_new) = 0;
357 	TOG_DATA(_new) = NULL;
358 	if ((MODE(_new) == XmMODE_TOGGLE_BUTTON) && (SET_POS(_new) > (ICOUNT(_new)-1)))
359 		SET_POS(_new) = ICOUNT(_new) - 1;
360 
361 	if (CHUNK_SIZE(_new) < 1)
362 		CHUNK_SIZE(_new) = DEFAULT_CHUNK_SIZE;
363 
364 	if (ICOUNT(_new) == 0)
365 	{
366 		if (LABEL(_new)._label == (_XmString) XmUNSPECIFIED)
367 		{
368 			xmstring = _XmOSGetLocalizedString ((char *) NULL,  /* reserved */
369 						(Widget)_new,
370 						XmNlabelString,
371 						"\0");
372 
373 			LABEL(_new)._label =  _XmStringCreate(xmstring);
374 		}
375 		else
376 		if (LABEL(_new)._label == NULL)
377 		{
378 			xmstring = _XmOSGetLocalizedString ((char *) NULL,  /* reserved */
379 						(Widget)_new,
380 						XmNlabelString,
381 						CORE(_new).name);
382 
383 			LABEL(_new)._label =  _XmStringCreate(xmstring);
384 		}
385 		ICOUNT(_new) = 1;
386 		ITEMS(_new) = XtNew(_XmString);
387 		ITEMS(_new)[0] = LABEL(_new)._label;
388 		DATA(_new) = XtNew(XtPointer);
389 		DATA(_new)[0] = (XtPointer)NULL;
390 		FAKE_ITEM(_new) = TRUE;
391 	}
392 	else
393 	{
394 		ITEMS(_new) = (_XmString *)XtMalloc(sizeof(_XmString) * ICOUNT(_new));
395 		DATA(_new) = (XtPointer)XtCalloc(ICOUNT(_new), sizeof(XtPointer));
396 		if (CB_DATA(_new) != NULL)
397 			for(i=0;i<ICOUNT(_new);i++)
398 			{
399 				ITEMS(_new)[i] = _XmStringCreate(EXITEMS(_new)[i]);
400 				DATA(_new)[i] = CB_DATA(_new)[i];
401 			}
402 		else
403 			for(i=0;i<ICOUNT(_new);i++)
404 			{
405 				ITEMS(_new)[i] = _XmStringCreate(EXITEMS(_new)[i]);
406 				DATA(_new)[i] = NULL;
407 			}
408 
409 		FAKE_ITEM(_new) = FALSE;
410 	}
411 
412 	CUR_SIZE(_new) = ICOUNT(_new);
413 
414 	getMaxWidthPos(_new, &MAX_STRING_POS(_new), &EL_HEIGHT(_new));
415 	_XmStringExtent(LABEL(_new).font, ITEMS(_new)[0], &width, &STR_HEIGHT(_new));
416 
417 
418 	EL_HEIGHT(_new) += 2 * PRIM(_new).shadow_thickness;
419 	HEIGHT(_new) = EL_HEIGHT(_new);
420 
421 	LABEL(_new)._label = ITEMS(_new)[MAX_STRING_POS(_new)];
422 	_XmCalcLabelDimensions((Widget)_new);
423 	MAX_STRING_WIDTH(_new) = LABEL(_new).TextRect.width;
424 	WIDTH(_new) = 0;
425 	(*xmLabelWidgetClass->core_class.resize) ((Widget)_new);
426 
427 	YOFFSET(_new) = LABEL(_new).TextRect.y;
428 	XOFFSET(_new) = LABEL(_new).TextRect.x;
429 
430 	if ( (MODE(_new) == XmMODE_TOGGLE_BUTTON) && ( ((XmMegaButtonWidgetClass)XtClass(_new))->mega_button_class.toggleSpaceProc))
431 		(( (XmMegaButtonWidgetClass)XtClass(_new))->mega_button_class.toggleSpaceProc)(_new, &WIDTH(_new), &EL_HEIGHT(_new));
432 
433 	if (VIS_COUNT(_new) == 0)
434 	{
435 		Dimension dheight;
436 		int vcount;
437 
438 		dheight = DisplayHeight(XtDisplay(_new), DefaultScreen(XtDisplay(_new)));
439 
440 		vcount = dheight/EL_HEIGHT(_new) - 4;
441 		if (vcount <=3)
442 			vcount = 3;
443 
444 		VIS_COUNT(_new) = vcount;
445 	}
446 
447 	HAS_ARROWS(_new) = ICOUNT(_new) > VIS_COUNT(_new);
448 
449 	if (HAS_ARROWS(_new))
450 		HEIGHT(_new) =
451 			HEIGHT(_new) * (VIS_COUNT(_new) + 2) + (2 * MINI_SEP_HEIGHT);
452 	else
453 		HEIGHT(_new) *= ICOUNT(_new);
454 
455 	gcValues.foreground = CORE(_new).background_pixel;
456 	COPY_GC(_new) = XtGetGC((Widget)_new, GCForeground, &gcValues);
457 
458 	gcValues.foreground = FILL_ON_SELECT(_new) ? SELECT_COLOR(_new) : CORE(_new).background_pixel;
459 
460 	SELECT_GC(_new) = XtGetGC((Widget)_new, GCForeground, &gcValues);
461 	TIMER(_new) = -1;
462 
463 	return (XtInitProc)NULL;
464 }
465 
destroy(Widget _mbw)466 static XtWidgetProc destroy(Widget _mbw)
467 {
468 	register int i;
469 
470 	XtReleaseGC((Widget)_mbw, COPY_GC(_mbw));
471 	XtReleaseGC((Widget)_mbw, SELECT_GC(_mbw));
472 
473       for(i=0;i<ICOUNT(_mbw);i++) {
474               if(ITEMS(_mbw)[i] != LABEL(_mbw)._label)
475                       _XmStringFree(ITEMS(_mbw)[i]);
476       }
477 
478 	XtFree((char *)ITEMS(_mbw));
479 	XtFree((char *)DATA(_mbw));
480 
481 	return (XtWidgetProc)NULL;
482 }
483 
expose(Widget _mbw,XEvent * _event,Region _region)484 static void expose(Widget _mbw, XEvent *_event, Region _region)
485 {
486 	GC gc;
487 	int i, first;
488 	Position y;
489 
490 	if (_event && _XmIsEventUnique(_event ))
491 		return; /* from _XmFastExpose... */
492 
493 	findGoodShowPos(_mbw);
494 
495 	gc = XtIsSensitive(_mbw) ? LABEL(_mbw).normal_GC : LABEL(_mbw).insensitive_GC;
496 
497 	first = FPOS(_mbw);
498 	y = 0;
499 	if (HAS_ARROWS(_mbw))
500 	{
501 		drawArrow(_mbw, 0, XmARROW_UP, (FPOS(_mbw) != 0));
502 		y += EL_HEIGHT(_mbw);
503 		drawMiniSeparator(_mbw, EL_HEIGHT(_mbw));
504 		y += MINI_SEP_HEIGHT;
505 	}
506 
507 	y += YOFFSET(_mbw);
508 	LABEL(_mbw).TextRect.x = XOFFSET(_mbw);
509 
510 	for(i=0;(i<VIS_COUNT(_mbw)) && ((first + i) < ICOUNT(_mbw)); i++)
511 	{
512 		LABEL(_mbw)._label = ITEMS(_mbw)[first+i];
513 		_XmCalcLabelDimensions((Widget)_mbw);
514 
515 		LABEL(_mbw).TextRect.y = y;
516 
517 		(*xmLabelWidgetClass->core_class.expose) ((Widget)_mbw,  _event, _region);
518 
519 		if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) && ( ((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc))
520 		{
521 			if ((first + i) == SET_POS(_mbw))
522 				(*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)(_mbw, LABEL(_mbw).TextRect.x, y, TRUE);
523 			else
524 				if (VIS_W_OFF(_mbw))
525 				 (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)(_mbw, LABEL(_mbw).TextRect.x, y, FALSE);
526 		}
527 
528 		y += EL_HEIGHT(_mbw);
529 	}
530 
531 	y -= YOFFSET(_mbw);
532 
533 	if (HAS_ARROWS(_mbw))
534 	{
535 		drawMiniSeparator(_mbw, y);
536 		y += MINI_SEP_HEIGHT;
537 		drawArrow(_mbw, VIS_COUNT(_mbw)+1, XmARROW_DOWN, ((ICOUNT(_mbw))-FPOS(_mbw)) > VIS_COUNT(_mbw));
538 	}
539 
540 	/* drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); */
541 }
542 
setValues(Widget _current,Widget _request,Widget _new,ArgList args,Cardinal * num_args)543 static Boolean setValues( Widget _current, Widget _request, Widget _new, ArgList args, Cardinal *num_args)
544 {
545 	return FALSE;
546 }
547 
getMaxWidthPos(Widget _mbw,int * _maxWidthPos,Dimension * _height)548 static void getMaxWidthPos(Widget _mbw, int *_maxWidthPos, Dimension *_height)
549 {
550 	int first, i;
551 	Dimension maxHeight, maxWidth;
552 	int mwp;
553 
554 	if (ICOUNT(_mbw) == 0)
555 	{
556 		*_maxWidthPos = 0;
557 		*_height = 1;
558 		return;
559 	}
560 
561 	first = FPOS(_mbw);
562 	mwp = 0;
563 	maxHeight = 1;
564 	maxWidth = 1;
565 	for(i=0; (first + i) < ICOUNT(_mbw); i++)
566 	{
567 		LABEL(_mbw)._label = ITEMS(_mbw)[first+i];
568 		_XmCalcLabelDimensions((Widget)_mbw);
569 
570 		if (LABEL(_mbw).TextRect.width > maxWidth)
571 		{
572 			maxWidth = LABEL(_mbw).TextRect.width;
573 			mwp = i;
574 		}
575 
576 		if (LABEL(_mbw).TextRect.height > maxHeight)
577 			maxHeight = LABEL(_mbw).TextRect.height;
578 	}
579 
580 	*_maxWidthPos = mwp;
581 	*_height = maxHeight;
582 }
583 
584 
drawShadowedItem(Widget _mbw,int _pos,Boolean _clear)585 static void drawShadowedItem(Widget _mbw, int _pos, Boolean _clear)
586 {
587 	Position y;
588 
589 
590 	if ( (_pos < 0) || (HAS_ARROWS(_mbw) && (_pos > (VIS_COUNT(_mbw)+1))) ||
591 		(!HAS_ARROWS(_mbw) && (_pos >= VIS_COUNT(_mbw)))
592 		)
593 		return;
594 
595 	y = 0;
596 	if (HAS_ARROWS(_mbw))
597 	{
598 		if (_pos > 0)
599 			y += MINI_SEP_HEIGHT;
600 
601 		if (_pos > VIS_COUNT(_mbw) )
602 			y += MINI_SEP_HEIGHT;
603 	}
604 
605 	y += (_pos * EL_HEIGHT(_mbw));
606 
607 	if (_clear)
608 	{
609 		_XmClearBorder(XtDisplay((Widget)_mbw), XtWindow((Widget)_mbw),
610 				0, y, WIDTH(_mbw), EL_HEIGHT(_mbw),
611 				PRIM(_mbw).shadow_thickness);
612 	}
613 	else
614 	{
615 		_XmDrawShadows(XtDisplay((Widget)_mbw), XtWindow((Widget)_mbw),
616 				PRIM(_mbw).top_shadow_GC,
617 				PRIM(_mbw).bottom_shadow_GC,
618 				0, y, WIDTH(_mbw), EL_HEIGHT(_mbw),
619 				PRIM(_mbw).shadow_thickness,
620 				XmSHADOW_OUT);
621 	}
622 }
623 
clearArrow(Widget _mbw,int _pos)624 static void clearArrow(Widget _mbw, int _pos)
625 {
626 	Position y = 0;
627 	if (HAS_ARROWS(_mbw))
628 	{
629 		if (_pos > 0)
630 			y += MINI_SEP_HEIGHT;
631 
632 		if (_pos > VIS_COUNT(_mbw) )
633 			y += MINI_SEP_HEIGHT;
634 	}
635 
636 	y += (_pos * EL_HEIGHT(_mbw));
637 
638 	XClearArea(XtDisplay(_mbw), XtWindow(_mbw),
639 		PRIM(_mbw).shadow_thickness, y + PRIM(_mbw).shadow_thickness,
640 		WIDTH(_mbw) - 2 * PRIM(_mbw).shadow_thickness,
641 		EL_HEIGHT(_mbw) - 2 * PRIM(_mbw).shadow_thickness, FALSE);
642 }
643 
yToPos(Widget _mbw,Position _y)644 static int yToPos(Widget _mbw, Position _y)
645 {
646 	Dimension topOffset, bottomOffset;
647 
648 	if ((_y >= 0) && HAS_ARROWS(_mbw))
649 	{
650 		if ((Dimension)_y <= EL_HEIGHT(_mbw))
651 			return 0;
652 
653 		topOffset = EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT;
654 		if ((Dimension)_y <= topOffset)
655 			return 0;
656 
657 		bottomOffset = HEIGHT(_mbw) - EL_HEIGHT(_mbw);
658 		if ((Dimension)_y >= bottomOffset)
659 			return VIS_COUNT(_mbw)+1;
660 
661 		bottomOffset -= MINI_SEP_HEIGHT;
662 
663 		if ((Dimension)_y >= bottomOffset)
664 			return VIS_COUNT(_mbw);
665 
666 		_y -= MINI_SEP_HEIGHT;
667 	}
668 
669 	return _y/EL_HEIGHT(_mbw);
670 }
671 
672 
enterWidget(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)673 static void enterWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
674 {
675 	if (ICOUNT(_mbw) == 0)
676 		return;
677 
678 	XtCallActionProc((Widget)_mbw, "PrimitiveEnter", _event, _params, *_numParams);
679 	if ( LABEL(_mbw).menu_type != XmWORK_AREA )
680 	{
681 		if (_XmGetInDragMode((Widget)_mbw))
682 		{
683 			drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
684 			VIS_POS(_mbw) = yToPos(_mbw, _event->xbutton.y);
685 			drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE);
686 
687 			if (HAS_ARROWS(_mbw))
688 			{
689 				if (VIS_POS(_mbw) == VIS_COUNT(_mbw)+1)
690 				{
691 					TDIR(_mbw) = XmTRAVERSE_DOWN;
692 					TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw),
693 						(unsigned long)IDELAY(_mbw),
694 						timedScroll, (XtPointer)_mbw);
695 				}
696 				else
697 				if (VIS_POS(_mbw) == 0)
698 				{
699 					TDIR(_mbw) = XmTRAVERSE_UP;
700 					TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw),
701 						(unsigned long)IDELAY(_mbw),
702 						timedScroll, (XtPointer)_mbw);
703 				}
704 			}
705 		}
706 	}
707 }
708 
leaveWidget(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)709 static void leaveWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
710 {
711 	if (ICOUNT(_mbw) == 0)
712 		return;
713 
714 	XtCallActionProc((Widget)_mbw, "PrimitiveLeave", _event, _params, *_numParams);
715 	if ( LABEL(_mbw).menu_type != XmWORK_AREA )
716 	{
717 /* 		if ( _XmGetInDragMode((Widget)_mbw) )  */
718 
719 		/* drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); */
720 
721 		if (TIMER(_mbw) != -1)
722 		{
723 			XtRemoveTimeOut(TIMER(_mbw));
724 			TIMER(_mbw) = -1;
725 		}
726 	}
727 	drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
728 }
729 
buttonMotion(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)730 static void buttonMotion(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
731 {
732 	if (ICOUNT(_mbw) == 0)
733 		return;
734 
735 
736 	if ( LABEL(_mbw).menu_type != XmWORK_AREA )
737 	{
738 		int pos = yToPos(_mbw, _event->xmotion.y);
739 		if (pos != VIS_POS(_mbw))
740 		{
741 			if (TIMER(_mbw) != -1)
742 			{
743 				XtRemoveTimeOut(TIMER(_mbw));
744 				TIMER(_mbw) = -1;
745 			}
746 			drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
747 			drawShadowedItem(_mbw, pos, FALSE);
748 			VIS_POS(_mbw) = pos;
749 
750 			if (HAS_ARROWS(_mbw))
751 			{
752 				if (VIS_POS(_mbw) == VIS_COUNT(_mbw)+1)
753 					scroll(_mbw, XmTRAVERSE_DOWN, TRUE, IDELAY(_mbw));
754 				else
755 				if (VIS_POS(_mbw) == 0)
756 					scroll(_mbw, XmTRAVERSE_UP, TRUE, IDELAY(_mbw));
757 			}
758 			_XmSetInDragMode((Widget)_mbw, TRUE);
759 		}
760 	}
761 }
762 
up(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)763 static void up(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
764 {
765 	int vpos;
766 
767 	if (ICOUNT(_mbw) == 0)
768 		return;
769 
770 	if (LABEL(_mbw).menu_type != XmWORK_AREA )
771 	{
772 		if (!_XmGetInDragMode((Widget)_mbw))
773 		{
774 			vpos = VIS_POS(_mbw);
775 			vpos--;
776 
777 			if ((vpos == -1) && (FPOS(_mbw) == 0))
778 			{
779 				CompositeWidget parent = (CompositeWidget)XtParent(_mbw);
780 				if (parent->composite.num_children > 1)
781 				{
782 					XtCallActionProc((Widget)_mbw, "PrimitiveTraverseUp", _event, _params, *_numParams);
783 					return;
784 				}
785 			}
786 
787 			if (HAS_ARROWS(_mbw) && (vpos <= 0))
788 			{
789 				if (vpos == 0)
790 				{
791 					drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
792 					drawShadowedItem(_mbw, vpos, FALSE);
793 				}
794 				scroll(_mbw, XmTRAVERSE_UP, FALSE, 0);
795 				VIS_POS(_mbw) = 0;
796 			}
797 			else
798 			{
799 				if (!HAS_ARROWS(_mbw) && (vpos == -1))
800 					vpos = ICOUNT(_mbw)-1;
801 
802 				if (vpos != VIS_POS(_mbw))
803 				{
804 					drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
805 					drawShadowedItem(_mbw, vpos, FALSE);
806 					VIS_POS(_mbw) = vpos;
807 				}
808 			}
809 
810 			_XmRecordEvent(_event);
811 		}
812 	}
813 
814 }
815 
down(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)816 static void down(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
817 {
818 	int vpos;
819 
820 	if (ICOUNT(_mbw) == 0)
821 		return;
822 
823 	if (LABEL(_mbw).menu_type != XmWORK_AREA )
824 	{
825 		if (!_XmGetInDragMode((Widget)_mbw))
826 		{
827 			vpos = VIS_POS(_mbw);
828 			vpos++;
829 
830 			_XmRecordEvent(_event);
831 
832 			if (HAS_ARROWS(_mbw) && (vpos >= (VIS_COUNT(_mbw) + 1)))
833 			{
834 				if (VIS_POS(_mbw) != (VIS_COUNT(_mbw)+1))
835 				{
836 					drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
837 					drawShadowedItem(_mbw, vpos, FALSE);
838 				}
839 				else
840 				if (FPOS(_mbw) >= (ICOUNT(_mbw)-VIS_COUNT(_mbw)))
841 				{
842 					CompositeWidget parent = (CompositeWidget)XtParent(_mbw);
843 					if (parent->composite.num_children > 1)
844 					{
845 						XtCallActionProc((Widget)_mbw, "PrimitiveTraverseDown", _event, _params, *_numParams);
846 						return;
847 					}
848 				}
849 
850 				scroll(_mbw, XmTRAVERSE_DOWN, FALSE, 0);
851 				VIS_POS(_mbw) = VIS_COUNT(_mbw) + 1;
852 			}
853 			else
854 			{
855 				if (!HAS_ARROWS(_mbw))
856 				{
857 					if (vpos == ICOUNT(_mbw))
858 					{
859 						CompositeWidget parent = (CompositeWidget)XtParent(_mbw);
860 						if (parent->composite.num_children > 1)
861 						{
862 							XtCallActionProc((Widget)_mbw, "PrimitiveTraverseDown", _event, _params, *_numParams);
863 							return;
864 						}
865 						else
866 							vpos = 0;
867 					}
868 				}
869 
870 				drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
871 				drawShadowedItem(_mbw, vpos, FALSE);
872 				VIS_POS(_mbw) = vpos;
873 			}
874 		}
875 	}
876 
877 }
878 
buttonUp(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)879 static void buttonUp(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
880 {
881 	XmMegaButtonCallbackStruct mtbcs;
882 	Widget parent, shell;
883 	Boolean validButton;
884 	Boolean poppedUp;
885 	Boolean isMenuPane;
886 
887 	if (TIMER(_mbw) != -1)
888 	{
889 		XtRemoveTimeOut(TIMER(_mbw));
890 		TIMER(_mbw) = -1;
891 	}
892 
893 	if (ICOUNT(_mbw) == 0)
894 		return;
895 
896 	isMenuPane = (LABEL(_mbw).menu_type == XmMENU_PULLDOWN) || (LABEL(_mbw).menu_type == XmMENU_POPUP);
897 	shell = XtGetShell((Widget)_mbw);
898 	parent = XtParent(_mbw);
899 
900 	if (_event && (_event->type == ButtonRelease))
901 	{
902 		(* xmLabelClassRec.label_class.menuProcs) (XmMENU_BUTTON, parent, NULL, _event, &validButton);
903 		if (!validButton)
904 			return;
905 
906 		VIS_POS(_mbw) = yToPos(_mbw, _event->xbutton.y);
907 	}
908 
909 	if (HAS_ARROWS(_mbw) && !_XmGetInDragMode((Widget)_mbw))
910 	{
911 		if (VIS_POS(_mbw) == 0)
912 		{
913 			_XmRecordEvent(_event);
914 			return;
915 		}
916 		else
917 		if (VIS_POS(_mbw) == (VIS_COUNT(_mbw)+1))
918 		{
919 			_XmRecordEvent(_event);
920 			return;
921 		}
922 	}
923 
924 	if (isMenuPane && !XmIsMenuShell(shell))
925 		(* xmLabelClassRec.label_class.menuProcs) (XmMENU_POPDOWN, (Widget) _mbw, NULL, _event, &poppedUp);
926 	else
927 		(* xmLabelClassRec.label_class.menuProcs) (XmMENU_BUTTON_POPDOWN, (Widget) _mbw , NULL,
928 			_event, &poppedUp);
929 
930 	_XmRecordEvent(_event);
931 
932 	if (poppedUp)
933 		return;
934 
935 	mtbcs.reason = XmCR_ACTIVATE;
936 	mtbcs.event = _event;
937 	if (HAS_ARROWS(_mbw))
938 	{
939 		if ((VIS_POS(_mbw) == 0) || (VIS_POS(_mbw) == (VIS_COUNT(_mbw)+1)))
940 			return;
941 
942 		mtbcs.pos = FPOS(_mbw) + VIS_POS(_mbw) - 1;
943 
944 	}
945 	else
946 		mtbcs.pos = VIS_POS(_mbw);
947 	mtbcs.callbackValue = DATA(_mbw)[mtbcs.pos];
948 	mtbcs.string = _XmStringCreateExternal(LABEL(_mbw).font, ITEMS(_mbw)[mtbcs.pos]);
949 
950 	SET_POS(_mbw) = mtbcs.pos;
951 
952 #if 0
953 	if (XmIsRowColumn(parent))
954 		(* xmLabelClassRec.label_class.menuProcs) (XmMENU_CALLBACK, parent, FALSE, _mbw, (XtPointer)&mtbcs);
955 	else
956 #endif
957 		XtCallCallbackList((Widget)_mbw, PUSH(_mbw).activate_callback, &mtbcs);
958 
959 	_XmSetInDragMode((Widget)_mbw, False);
960 }
961 
buttonDown(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParms)962 static void buttonDown(Widget _mbw, XEvent *_event, String *_params,
963 		Cardinal *_numParms)
964 {
965 	ShellWidget popupShell;
966 	int validButton, pos = 0;
967 	Widget child;
968 
969 	if (ICOUNT(_mbw) == 0)
970 		return;
971 
972 	XAllowEvents(XtDisplay(_mbw), SyncPointer, CurrentTime);
973 
974 	if (_event && (_event->type == ButtonPress))
975 	{
976 		(* xmLabelClassRec.label_class.menuProcs) (XmMENU_BUTTON, XtParent(_mbw), NULL, _event, &validButton);
977 		if (!validButton)
978 			return;
979 
980 		pos = yToPos(_mbw, _event->xbutton.y);
981 	}
982 
983 	if (HAS_ARROWS(_mbw) && !_XmGetInDragMode((Widget)_mbw))
984 	{
985 		if (pos == 0)
986 		{
987 			drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
988 			VIS_POS(_mbw) = pos;
989 			drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE);
990 			_XmRecordEvent(_event);
991 			scroll(_mbw, XmTRAVERSE_UP, TRUE, IDELAY(_mbw));
992 			return;
993 		}
994 		else
995 		if (pos == (VIS_COUNT(_mbw)+1))
996 		{
997 			drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
998 			VIS_POS(_mbw) = pos;
999 			drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE);
1000 			_XmRecordEvent(_event);
1001 			scroll(_mbw, XmTRAVERSE_DOWN, TRUE, IDELAY(_mbw));
1002 			return;
1003 		}
1004 	}
1005 
1006 	VIS_POS(_mbw) = pos;
1007 
1008 	_XmSetInDragMode((Widget)_mbw, TRUE);
1009 
1010 	popupShell = (ShellWidget)_XmGetRC_PopupPosted(XtParent(_mbw));
1011 	if  (popupShell)
1012 	{
1013 		if (popupShell->shell.popped_up)
1014 			(* xmLabelClassRec.label_class.menuProcs)(XmMENU_SHELL_POPDOWN, (Widget)popupShell, NULL, _event, NULL);
1015 
1016 		child = ((XmManagerWidget)XtParent(_mbw))->manager.active_child;
1017 		if (child && (XmIsCascadeButton(child) || XmIsCascadeButtonGadget(child)))
1018 			XmCascadeButtonHighlight (child, FALSE);
1019 	}
1020 
1021 	XmProcessTraversal( (Widget)_mbw, XmTRAVERSE_CURRENT);
1022 
1023 	_XmSetInDragMode((Widget)_mbw, FALSE);
1024 
1025 	_XmRecordEvent(_event);
1026 }
1027 
armAndActivate(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)1028 static void armAndActivate(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
1029 {
1030 	XmMegaButtonCallbackStruct mtbcs;
1031 
1032 	if (ICOUNT(_mbw) == 0)
1033 		return;
1034 
1035 	mtbcs.reason = XmCR_ACTIVATE;
1036 	mtbcs.event = _event;
1037 	if (HAS_ARROWS(_mbw))
1038 	{
1039 		if ((VIS_POS(_mbw) == 0) || (VIS_POS(_mbw) == (VIS_COUNT(_mbw)+1)))
1040 			return;
1041 
1042 		mtbcs.pos = FPOS(_mbw) + VIS_POS(_mbw) - 1;
1043 
1044 	}
1045 	else
1046 		mtbcs.pos = VIS_POS(_mbw);
1047 	mtbcs.callbackValue = DATA(_mbw)[mtbcs.pos];
1048 	mtbcs.string = _XmStringCreateExternal(LABEL(_mbw).font, ITEMS(_mbw)[mtbcs.pos]);
1049 
1050 	SET_POS(_mbw) = mtbcs.pos;
1051 
1052 	XFlush(XtDisplay(_mbw));
1053 
1054 	XtCallCallbackList((Widget)_mbw, PUSH(_mbw).activate_callback, &mtbcs);
1055 }
1056 
XtGetShell(Widget _w)1057 static Widget XtGetShell(Widget _w)
1058 {
1059 	Widget temp;
1060 
1061 	temp = _w;
1062 	while(temp && !XtIsSubclass(temp, shellWidgetClass))
1063 		temp = XtParent(temp);
1064 
1065 	return temp;
1066 }
1067 
1068 #if !HAVE_SOURCE && !defined(LESSTIF_VERSION)
1069 
1070 struct _XmFocusDataRec
1071 {
1072 	Widget not_used;
1073 	Widget not_used_2;
1074 	Widget old_focus_item;
1075 };
1076 
1077 #endif /* HAVE_SOURCE */
1078 
1079 /*
1080 ** This is a tad hackish.  The general idea is that there is no way to tell which
1081 ** directory the focusIn event came from if we are in a menu.  So get the
1082 ** focusData which has the last widget to have focus.  Use this as an index
1083 ** into the RowCol's children, and go from there.
1084 */
1085 
focusIn(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)1086 static void focusIn(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
1087 {
1088 	int labelCount;
1089 	Widget oldFocus;
1090 	CompositeWidget parent;
1091 	XmFocusData focusData;
1092 	WidgetList children;
1093 	int myI, oldI, i;
1094 
1095 	VIS_POS(_mbw) = 0;
1096 	if (ICOUNT(_mbw) == 0)
1097 		return;
1098 
1099 	focusData = _XmGetFocusData((Widget)_mbw);
1100 
1101 	if (focusData && focusData->old_focus_item)
1102 	{
1103 		oldFocus = focusData->old_focus_item;
1104 		parent = (CompositeWidget)XtParent(_mbw);
1105 
1106 		children = parent->composite.children;
1107 		myI = -1;
1108 		oldI = -1;
1109 		labelCount = 0;
1110 		for(i=0;(i<parent->composite.num_children);i++)
1111 		{
1112 			if (children[i] == (Widget)_mbw)
1113 				myI = i;
1114 			else
1115 			if (children[i] == oldFocus)
1116 				oldI = i;
1117 			else
1118 			if (XmIsLabel(children[i]))
1119 				labelCount++;
1120 
1121 			if ((myI != -1) && (oldI != -1))
1122 				break;
1123 		}
1124 
1125 		if ( (oldI != -1) && ((myI < oldI) ||
1126 			 ((myI > oldI) && labelCount)))
1127 			VIS_POS(_mbw) = (HAS_ARROWS(_mbw) ? VIS_COUNT(_mbw) + 1 : ICOUNT(_mbw)-1);
1128 	}
1129 
1130 
1131 
1132 	drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE);
1133 }
1134 
focusOut(Widget _mbw,XEvent * _event,String * _params,Cardinal * _numParams)1135 static void focusOut(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams)
1136 {
1137 	if (ICOUNT(_mbw) == 0)
1138 		return;
1139 
1140 	if (TIMER(_mbw) != -1)
1141 	{
1142 		XtRemoveTimeOut(TIMER(_mbw));
1143 		TIMER(_mbw) = -1;
1144 	}
1145 
1146 	drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
1147 	VIS_POS(_mbw) = 0;
1148 }
1149 
borderHighlight(Widget _mbw)1150 static void borderHighlight(Widget _mbw)
1151 {
1152 	if (ICOUNT(_mbw) == 0)
1153 		return;
1154 
1155 
1156 	if ((LABEL(_mbw).menu_type == XmMENU_PULLDOWN) || (LABEL(_mbw).menu_type == XmMENU_POPUP))
1157 	{
1158 		drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE);
1159 	}
1160 }
1161 
borderUnhighlight(Widget _mbw)1162 static void borderUnhighlight(Widget _mbw)
1163 {
1164 	if (ICOUNT(_mbw) == 0)
1165 		return;
1166 
1167 
1168 	if ((LABEL(_mbw).menu_type == XmMENU_PULLDOWN) || (LABEL(_mbw).menu_type == XmMENU_POPUP))
1169 		drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE);
1170 }
1171 
drawMiniSeparator(Widget _mbw,Position _y)1172 static void drawMiniSeparator(Widget _mbw, Position _y)
1173 {
1174 	int i, firstHalf, secondHalf;
1175 
1176 	firstHalf = MINI_SEP_HEIGHT/2;
1177 	secondHalf = firstHalf;
1178 
1179 	if (MINI_SEP_HEIGHT % 2)
1180 		secondHalf++;
1181 
1182 	for(i=secondHalf;i<MINI_SEP_HEIGHT;i++)
1183 		XDrawLine(XtDisplay(_mbw), XtWindow(_mbw), PRIM(_mbw).top_shadow_GC,
1184 			0, _y+i, WIDTH(_mbw), _y+i);
1185 
1186 	for(i=0;i<firstHalf;i++)
1187 		XDrawLine(XtDisplay(_mbw), XtWindow(_mbw), PRIM(_mbw).bottom_shadow_GC,
1188 			0, _y+i, WIDTH(_mbw), _y+i);
1189 }
1190 
1191 
drawArrow(Widget _mbw,int _pos,int _direction,Boolean _sensitive)1192 static void drawArrow(Widget _mbw, int _pos, int _direction, Boolean _sensitive)
1193 {
1194 	Dimension arrowWidth;
1195 	Position y = 0;
1196 
1197 	if (HAS_ARROWS(_mbw))
1198 	{
1199 		if (_pos > 0)
1200 			y += MINI_SEP_HEIGHT;
1201 
1202 		if (_pos > VIS_COUNT(_mbw) )
1203 			y += MINI_SEP_HEIGHT;
1204 	}
1205 
1206 	y += (_pos * EL_HEIGHT(_mbw));
1207 
1208 
1209 	arrowWidth = WIDTH(_mbw)/5;
1210 
1211 	_XmDrawArrow(XtDisplay((Widget)(_mbw)),
1212 			XtWindow ((Widget)(_mbw)),
1213 			_sensitive ? PRIM(_mbw).top_shadow_GC : PRIM(_mbw).bottom_shadow_GC,
1214 			_sensitive ? PRIM(_mbw).bottom_shadow_GC : PRIM(_mbw).top_shadow_GC,
1215 			_sensitive ? COPY_GC(_mbw) : LABEL(_mbw).insensitive_GC,
1216 			WIDTH(_mbw)/2 - arrowWidth/2,
1217 			y + PRIM(_mbw).shadow_thickness,
1218 			arrowWidth,
1219 			EL_HEIGHT(_mbw) - 2 * (PRIM(_mbw).shadow_thickness),
1220 			PRIM(_mbw).shadow_thickness, _direction);
1221 }
1222 
timedScroll(XtPointer _closure,XtIntervalId * _id)1223 static void timedScroll(XtPointer _closure, XtIntervalId *_id)
1224 {
1225 	XmMegaButtonWidget mbw = (XmMegaButtonWidget)_closure;
1226 
1227 	scroll((Widget)mbw, TDIR(mbw), TRUE, RDELAY(mbw));
1228 }
1229 
scroll(Widget _mbw,int _direction,Boolean _addTimeout,int _delay)1230 static void scroll(Widget _mbw, int _direction, Boolean _addTimeout, int _delay)
1231 {
1232 	Position sy, dy;
1233 
1234 	TIMER(_mbw) = -1;
1235 
1236 	if (_direction == XmTRAVERSE_DOWN)
1237 	{
1238 		if ((FPOS(_mbw) + VIS_COUNT(_mbw)) >= ICOUNT(_mbw))
1239 			return;
1240 
1241 		/* drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); */
1242 
1243 		sy = 2 * EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT;
1244 		dy = sy - EL_HEIGHT(_mbw);
1245 
1246 		XCopyArea(XtDisplay(_mbw), XtWindow(_mbw), XtWindow(_mbw),
1247 			COPY_GC(_mbw),
1248 			0, sy, WIDTH(_mbw), EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw)-1),
1249 			0, dy);
1250 
1251 		XClearArea(XtDisplay(_mbw), XtWindow(_mbw),
1252 			PRIM(_mbw).shadow_thickness, dy + EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw)-1),
1253 			WIDTH(_mbw)-2*PRIM(_mbw).shadow_thickness,
1254 			EL_HEIGHT(_mbw), FALSE);
1255 
1256 		FPOS(_mbw)++;
1257 
1258 		LABEL(_mbw)._label = ITEMS(_mbw)[FPOS(_mbw)+VIS_COUNT(_mbw)-1];
1259 		_XmCalcLabelDimensions((Widget)_mbw);
1260 
1261 		LABEL(_mbw).TextRect.y = YOFFSET(_mbw) + (VIS_COUNT(_mbw)*EL_HEIGHT(_mbw)) + MINI_SEP_HEIGHT;
1262 		LABEL(_mbw).TextRect.x = XOFFSET(_mbw);
1263 
1264 
1265 		(*xmLabelWidgetClass->core_class.expose)
1266 			((Widget)_mbw,  NULL, (Region)NULL);
1267 
1268 
1269 		if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) &&
1270 			((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)
1271 
1272 		{
1273 			if ((FPOS(_mbw)+VIS_COUNT(_mbw)-1) == SET_POS(_mbw))
1274 				(*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)(_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, TRUE);
1275 			else
1276 			if (VIS_W_OFF(_mbw))
1277 				(*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)
1278 					(_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, FALSE);
1279 		}
1280 
1281 		if (_addTimeout && ((FPOS(_mbw) + VIS_COUNT(_mbw)) < ICOUNT(_mbw)))
1282 		{
1283 			TDIR(_mbw) = XmTRAVERSE_DOWN;
1284 			TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw),
1285 				(unsigned long) _delay,
1286 				timedScroll, (XtPointer)_mbw);
1287 		}
1288 
1289 	}
1290 	else
1291 	if (_direction == XmTRAVERSE_UP)
1292 	{
1293 		if (FPOS(_mbw) == 0)
1294 			return;
1295 
1296 		/* drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); */
1297 
1298 		sy = EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT;
1299 		dy = sy + EL_HEIGHT(_mbw);
1300 
1301 		XCopyArea(XtDisplay(_mbw), XtWindow(_mbw), XtWindow(_mbw),
1302 			COPY_GC(_mbw),
1303 			0, sy, WIDTH(_mbw), EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw)-1),
1304 			0, dy);
1305 
1306 		XClearArea(XtDisplay(_mbw), XtWindow(_mbw),
1307 			PRIM(_mbw).shadow_thickness, EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT,
1308 			WIDTH(_mbw)-2*PRIM(_mbw).shadow_thickness,
1309 			EL_HEIGHT(_mbw), FALSE);
1310 
1311 		FPOS(_mbw)--;
1312 
1313 		LABEL(_mbw)._label = ITEMS(_mbw)[FPOS(_mbw)];
1314 		_XmCalcLabelDimensions((Widget)_mbw);
1315 
1316 		LABEL(_mbw).TextRect.y = YOFFSET(_mbw) + EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT;
1317 		LABEL(_mbw).TextRect.x = XOFFSET(_mbw);
1318 
1319 
1320 		(*xmLabelWidgetClass->core_class.expose) ((Widget)_mbw,  NULL, (Region)NULL);
1321 
1322 		if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) &&
1323 			((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)
1324 
1325 		{
1326 			if (FPOS(_mbw) == SET_POS(_mbw))
1327 				(*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)
1328 						(_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, TRUE);
1329 			else
1330 			if (VIS_W_OFF(_mbw))
1331 				(*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)
1332 					(_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, FALSE);
1333 		}
1334 
1335 
1336 		if (_addTimeout && (FPOS(_mbw) != 0))
1337 		{
1338 			TDIR(_mbw) = XmTRAVERSE_UP;
1339 			TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw),
1340 				(unsigned long) _delay,
1341 				timedScroll, (XtPointer)_mbw);
1342 		}
1343 	}
1344 
1345 	if (_direction == XmTRAVERSE_DOWN)
1346 	{
1347 		if (FPOS(_mbw) != 0)
1348 		{
1349 			if (((ICOUNT(_mbw))-FPOS(_mbw)) <= VIS_COUNT(_mbw))
1350 			{
1351 				clearArrow(_mbw, VIS_COUNT(_mbw)+1);
1352 				drawArrow(_mbw, VIS_COUNT(_mbw)+1, XmARROW_DOWN, FALSE);
1353 			}
1354 			drawArrow(_mbw, 0, XmARROW_UP, TRUE);
1355 		}
1356 
1357 	}
1358 	else
1359 	{
1360 		if (FPOS(_mbw) == 0)
1361 		{
1362 			clearArrow(_mbw, 0);
1363 			drawArrow(_mbw, 0, XmARROW_UP, FALSE);
1364 		}
1365 		drawArrow(_mbw, VIS_COUNT(_mbw)+1, XmARROW_DOWN, TRUE);
1366 	}
1367 }
1368 
toggleDrawProc(Widget _mbw,Position _x,Position _y,Boolean _on)1369 static void toggleDrawProc(Widget _mbw, Position _x, Position _y, Boolean _on)
1370 {
1371 	int ecalc;
1372 
1373 	ecalc = STR_HEIGHT(_mbw) - 2 * PRIM(_mbw).shadow_thickness;
1374 
1375 	if (ecalc < 5)
1376 		ecalc = 5;
1377 
1378 	_y += EL_HEIGHT(_mbw)/2 - ecalc/2 - PRIM(_mbw).shadow_thickness;
1379 
1380 	_x -= (ecalc + LABEL(_mbw).margin_width);
1381 
1382 	_XmDrawDiamond(XtDisplay((Widget)_mbw), XtWindow((Widget)_mbw),
1383 			_on ? PRIM(_mbw).bottom_shadow_GC : PRIM(_mbw).top_shadow_GC,
1384 			_on ? PRIM(_mbw).top_shadow_GC : PRIM(_mbw).bottom_shadow_GC,
1385 			_on ? SELECT_GC(_mbw) : COPY_GC(_mbw),
1386 			_x, _y,
1387 			ecalc, ecalc,
1388 			PRIM(_mbw).shadow_thickness,
1389 			TRUE);
1390 }
1391 
toggleSpaceProc(Widget _mbw,Dimension * _width,Dimension * _height)1392 static void toggleSpaceProc(Widget _mbw, Dimension *_width, Dimension *_height)
1393 {
1394 	int ecalc = STR_HEIGHT(_mbw) - 2 * PRIM(_mbw).shadow_thickness;
1395 	if (ecalc < 5)
1396 		ecalc = 5;
1397 
1398 	XOFFSET(_mbw) += ecalc + LABEL(_mbw).margin_width;
1399 	*_width += ecalc + LABEL(_mbw).margin_width;
1400 }
1401 
findGoodShowPos(Widget _mbw)1402 static void findGoodShowPos(Widget _mbw)
1403 {
1404 	int topDiff, bottomDiff;
1405 
1406 	if (MODE(_mbw) != XmMODE_TOGGLE_BUTTON)
1407 	{
1408 		FPOS(_mbw) = 0;
1409 		return;
1410 	}
1411 
1412 	VIS_POS(_mbw) = 0;
1413 	if (!HAS_ARROWS(_mbw) || (SET_POS(_mbw) == -1))
1414 		FPOS(_mbw) = 0;
1415 	else
1416 	{
1417 		topDiff = SET_POS(_mbw) - VIS_COUNT(_mbw)/2;
1418 		if (topDiff < 0)
1419 			FPOS(_mbw) = 0;
1420 		else
1421 		{
1422 			bottomDiff = (ICOUNT(_mbw)-1) - SET_POS(_mbw);
1423 
1424 			if (bottomDiff < VIS_COUNT(_mbw))
1425 				FPOS(_mbw) = (ICOUNT(_mbw))-VIS_COUNT(_mbw);
1426 			else
1427 				FPOS(_mbw) = topDiff;
1428 		}
1429 	}
1430 }
1431 
toLower(char * _str1,char * _str2,int _length)1432 static void toLower(char *_str1, char *_str2, int _length)
1433 {
1434 	int i;
1435 	char *ptr;
1436 
1437 	for(ptr=_str1,i=0;(ptr!=NULL) && (i<_length);ptr++,i++)
1438 		*(_str2+i) = tolower(*ptr);
1439 }
1440 
cvtStringToMegaButtonMode(Display * _display,XrmValuePtr _args,Cardinal * _numArgs,XrmValuePtr _from,XrmValuePtr _to,XtPointer * _data)1441 static Boolean cvtStringToMegaButtonMode(Display *_display, XrmValuePtr _args,
1442 	Cardinal *_numArgs, XrmValuePtr _from, XrmValuePtr _to, XtPointer *_data)
1443 {
1444 	char *lower;
1445 	static unsigned char mode;
1446 	Boolean badConversion = FALSE;
1447 
1448 	if (*_numArgs != 0)
1449 	{
1450 		XtAppWarningMsg(XtDisplayToApplicationContext(_display), "cvtStringToMegaButtonMode", "wrongParamaters",
1451 		"ResourceError",
1452 		"cvtStringToMegaButtonMode needs no arguments.",
1453 		(String *)NULL, (Cardinal *)NULL);
1454 	}
1455 
1456 	lower = XtNewString(_from->addr);
1457 	toLower(_from->addr, lower, strlen(_from->addr));
1458 
1459 	mode = XmMODE_TOGGLE_BUTTON;
1460 
1461 	if (!strncmp(lower, "mode_toggle_button", 18))
1462 		mode = XmMODE_TOGGLE_BUTTON;
1463 	else
1464 	if (!strncmp(lower, "mode_push_button", 16))
1465 		mode = XmMODE_PUSH_BUTTON;
1466 	else
1467 	if (!strncmp(lower, "toggle_button", 13))
1468 		mode = XmMODE_TOGGLE_BUTTON;
1469 	else
1470 	if (!strncmp(lower, "push_button", 11))
1471 		mode = XmMODE_PUSH_BUTTON;
1472 	else
1473 		badConversion = TRUE;
1474 
1475 	XtFree(lower);
1476 
1477 	if (badConversion)
1478 		XtDisplayStringConversionWarning(_display, _from->addr, XmRMegaButtonMode);
1479 	else
1480 	{
1481 		if (_to->addr == NULL)
1482 			_to->addr = (XtPointer)&mode;
1483 		else
1484 		if (_to->size < sizeof(unsigned char))
1485 			badConversion = TRUE;
1486 		else
1487 			*(unsigned char *)_to->addr = mode;
1488 			_to->size = sizeof(unsigned char);
1489 	}
1490 
1491 	return !badConversion;
1492 }
1493 
1494 
XmMegaButtonAddItem(Widget _w,XmString _item,int _pos,XtPointer _cbData)1495 void XmMegaButtonAddItem(Widget _w, XmString _item, int _pos, XtPointer _cbData)
1496 {
1497 	XmMegaButtonWidget mbw;
1498 
1499 	if (!XmIsMegaButton(_w))
1500 		return;
1501 
1502 	mbw = (XmMegaButtonWidget)_w;
1503 
1504 	if (FAKE_ITEM(mbw))
1505 	{
1506 		ICOUNT(mbw)--;
1507 		FAKE_ITEM(mbw) = FALSE;
1508 		WIDTH(mbw) = 0;
1509 		MAX_STRING_WIDTH(mbw) = 1;
1510 	}
1511 
1512 	if ((_pos < 0) ||  (_pos > (ICOUNT(mbw))))
1513 		_pos = ICOUNT(mbw);
1514 
1515 	if (ICOUNT(mbw) == CUR_SIZE(mbw))
1516 	{
1517 		CUR_SIZE(mbw) += CHUNK_SIZE(mbw);
1518 		ITEMS(mbw) = (_XmString *)XtRealloc((char *)ITEMS(mbw), sizeof(_XmString) * CUR_SIZE(mbw));
1519 		DATA(mbw) = (XtPointer *)XtRealloc((char *)DATA(mbw), sizeof(XtPointer) * CUR_SIZE(mbw));
1520 	}
1521 
1522 	bcopy(ITEMS(mbw)+_pos, ITEMS(mbw)+_pos+1, (ICOUNT(mbw)-_pos) * sizeof(_XmString));
1523 	bcopy(DATA(mbw)+_pos, DATA(mbw)+_pos+1, (ICOUNT(mbw)-_pos) * sizeof(XtPointer));
1524 
1525 	ITEMS(mbw)[_pos] = _XmStringCreate(_item);
1526 	DATA(mbw)[_pos] = _cbData;
1527 	ICOUNT(mbw)++;
1528 
1529 	recheckSizesAtPos((Widget)mbw, _pos);
1530 }
1531 
recheckSizesAtPos(Widget _mbw,int _pos)1532 static void recheckSizesAtPos(Widget _mbw, int _pos)
1533 {
1534 	ShellWidget popupShell;
1535 	XtGeometryResult result;
1536 
1537 	popupShell = (ShellWidget)XtGetShell((Widget)_mbw);
1538 	if (popupShell && !popupShell->shell.popped_up)
1539 	{
1540 		Dimension width, height;
1541 		Dimension replyWidth, replyHeight, oldWidth;
1542 
1543 		width = WIDTH(_mbw);
1544 		height = HEIGHT(_mbw);
1545 
1546 		if (!HAS_ARROWS(_mbw))
1547 		{
1548 			HAS_ARROWS(_mbw) = ICOUNT(_mbw) > VIS_COUNT(_mbw);
1549 
1550 			if (!HAS_ARROWS(_mbw))
1551 				height = EL_HEIGHT(_mbw) * ICOUNT(_mbw);
1552 			else
1553 				height = EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw) + 2) + 2 * MINI_SEP_HEIGHT;
1554 		}
1555 
1556 		LABEL(_mbw)._label = ITEMS(_mbw)[_pos];
1557 		_XmCalcLabelDimensions((Widget)_mbw);
1558 
1559 		if (LABEL(_mbw).TextRect.width > MAX_STRING_WIDTH(_mbw))
1560 		{
1561 			MAX_STRING_WIDTH(_mbw) = LABEL(_mbw).TextRect.width;
1562 			MAX_STRING_POS(_mbw) = _pos;
1563 			oldWidth = WIDTH(_mbw);
1564 			WIDTH(_mbw) = 0;
1565 			(*xmLabelWidgetClass->core_class.resize) ((Widget)_mbw);
1566 			width = WIDTH(_mbw);
1567 			WIDTH(_mbw) = oldWidth;
1568 
1569 /* 			YOFFSET(_mbw) = LABEL(_mbw).TextRect.y; */
1570 			XOFFSET(_mbw) = LABEL(_mbw).TextRect.x;
1571 
1572 			if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) &&
1573 						( ((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleSpaceProc))
1574 				(( (XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleSpaceProc)
1575 						(_mbw, &width, &EL_HEIGHT(_mbw));
1576 		}
1577 
1578 		if (height == 0)
1579 			height = 2 * PRIM(_mbw).shadow_thickness;
1580 		if (width == 0)
1581 			width = 2 * PRIM(_mbw).shadow_thickness;
1582 
1583 		while((result = XtMakeResizeRequest((Widget)_mbw, width, height, &replyWidth,
1584 			&replyHeight)) == XtGeometryAlmost)
1585 		{
1586 			width = replyWidth;
1587 			height = replyHeight;
1588 		}
1589 	}
1590 }
1591 
XmMegaButtonRemoveItem(Widget _w,int _pos)1592 XtPointer XmMegaButtonRemoveItem(Widget _w, int _pos)
1593 {
1594 	XtPointer data;
1595 	XmMegaButtonWidget mbw;
1596 
1597 	mbw = (XmMegaButtonWidget)_w;
1598 
1599 	if ((_pos < 0) || (_pos >= ICOUNT(mbw)))
1600 		return NULL;
1601 
1602 	_XmStringFree(ITEMS(mbw)[_pos]);
1603 	data = DATA(mbw)[_pos];
1604 
1605 	ICOUNT(mbw)--;
1606 	bcopy(ITEMS(mbw)+_pos+1, ITEMS(mbw)+_pos, (ICOUNT(mbw)-_pos) * sizeof(_XmString));
1607 	bcopy(DATA(mbw)+_pos+1, DATA(mbw)+_pos, (ICOUNT(mbw)-_pos) * sizeof(XtPointer));
1608 
1609 	if (ICOUNT(mbw) != 0)
1610 		recheckSizesAtPos((Widget)mbw, 0);
1611 
1612 	return data;
1613 }
1614 
XmMegaButtonItemCount(Widget _w,Boolean _forgetFake)1615 int XmMegaButtonItemCount(Widget _w, Boolean _forgetFake)
1616 {
1617 	XmMegaButtonWidget mbw;
1618 
1619 	mbw = (XmMegaButtonWidget)_w;
1620 
1621 	if (_forgetFake && FAKE_ITEM(mbw))
1622 		return 0;
1623 	else
1624 		return (ICOUNT(mbw));
1625 }
1626 
1627 
XmMegaButtonGetPos(Widget _w)1628 int XmMegaButtonGetPos(Widget _w)
1629 {
1630 	XmMegaButtonWidget mbw;
1631 
1632 	mbw = (XmMegaButtonWidget)_w;
1633 	if (MODE(mbw) == XmMODE_TOGGLE_BUTTON)
1634 		return SET_POS(mbw);
1635 	else
1636 		return -1;
1637 }
1638 
XmMegaButtonSetPos(Widget _w,int _pos)1639 void XmMegaButtonSetPos(Widget _w, int _pos)
1640 {
1641 	XmMegaButtonWidget mbw;
1642 
1643 	mbw = (XmMegaButtonWidget)_w;
1644 	if (MODE(mbw) == XmMODE_TOGGLE_BUTTON)
1645 	{
1646 		if (_pos > (ICOUNT(mbw)-1))
1647 			_pos = ICOUNT(mbw) - 1;
1648 
1649 		SET_POS(mbw) = _pos;
1650 	}
1651 }
1652 
XmMegaButtonGetXmStringAtPos(Widget _w,int _pos)1653 extern XmString XmMegaButtonGetXmStringAtPos(Widget _w, int _pos)
1654 {
1655 	XmMegaButtonWidget mbw = (XmMegaButtonWidget)_w;
1656 
1657 	if ((_pos >= 0) && (_pos < ICOUNT(mbw)))
1658 		return _XmStringCreateExternal(LABEL(mbw).font, ITEMS(mbw)[_pos]);
1659 
1660 	return (XmString)NULL;
1661 }
1662 
XmMegaButtonSetXmStringAtPos(Widget _w,XmString _xmstring,int _pos)1663 extern void XmMegaButtonSetXmStringAtPos(Widget _w, XmString _xmstring, int _pos)
1664 {
1665 	XmMegaButtonWidget mbw = (XmMegaButtonWidget)_w;
1666 
1667 	if ((_pos >= 0) && (_pos < ICOUNT(mbw)))
1668 	{
1669 		_XmStringFree(ITEMS(mbw)[_pos]);
1670 		ITEMS(mbw)[_pos] = _XmStringCreate(_xmstring);
1671 		recheckSizesAtPos((Widget)mbw, _pos);
1672 	}
1673 }
1674