/* $Id: MegaB.c,v 1.1 2002/05/14 23:01:27 dannybackx Exp $ */ /* * Copyright 1994 John L. Cwikla * * 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 appears in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of John L. Cwikla or * Wolfram Research, Inc not be used in advertising or publicity * pertaining to distribution of the software without specific, written * prior permission. John L. Cwikla and Wolfram Research, Inc make no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * John L. Cwikla and Wolfram Research, Inc disclaim all warranties with * regard to this software, including all implied warranties of * merchantability and fitness, in no event shall John L. Cwikla or * Wolfram Research, Inc be liable for any special, indirect or * consequential damages or any damages whatsoever resulting from loss of * use, data or profits, whether in an action of contract, negligence or * other tortious action, arising out of or in connection with the use or * performance of this software. * * Author: * John L. Cwikla * X Programmer * Wolfram Research Inc. * * cwikla@wri.com */ #include #include #include #include #include #include #include #include #include #if HAVE_SOURCE || defined(LESSTIF_VERSION) #include "XmI/TraversalI.h" #endif /* HAVE_SOURCE */ #include "MegaBP.h" #include #include #define SCROLL_TIME 100 #define MINI_SEP_HEIGHT 3 static XtWidgetClassProc classPartInit(WidgetClass _wc); static XtProc classInit(); static XtInitProc initialize(Widget _request, Widget _new, String *_args, Cardinal *_numArg); static XtWidgetProc destroy(Widget _mbw); static void expose(Widget _mbw, XEvent *_event, Region _region); static Boolean setValues(Widget _current, Widget _request, Widget _new, ArgList args, Cardinal *num_args); static void borderHighlight(Widget _mbw); static void borderUnhighlight(Widget _mbw); static void getMaxWidthPos(Widget _mbw, int *_maxWidthPos, Dimension *_height); static void drawMiniSeparator(Widget _mbw, Position _y); static void enterWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void leaveWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void buttonMotion(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void up(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void down(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void buttonUp(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void buttonDown(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParms); static void armAndActivate(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void focusIn(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void focusOut(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams); static void timedScroll(XtPointer _closure, XtIntervalId *_id); static Boolean cvtStringToMegaButtonMode(Display *_display, XrmValuePtr _args, Cardinal *_numArgs, XrmValuePtr _from, XrmValuePtr _to, XtPointer *_data); static void drawShadowedItem(Widget _mbw, int _pos, Boolean _clear); static void drawArrow(Widget _mbw, int _pos, int _direction, Boolean _sensitive); static void clearArrow(Widget _mbw, int _pos); static void scroll(Widget _mbw, int _direction, Boolean _addTimeout, int _delay); static void findGoodShowPos(Widget _mbw); static void toggleDrawProc(Widget _mbw, Position _x, Position _y, Boolean _on); static void toggleSpaceProc(Widget _mbw, Dimension *_width, Dimension *_height); static void recheckSizesAtPos(Widget _mbw, int _pos); static Widget XtGetShell(Widget _w); #define CORE(w) (((XmMegaButtonWidget)(w))->core) #define PRIM(w) (((XmMegaButtonWidget)(w))->primitive) #define LABEL(w) (((XmMegaButtonWidget)(w))->label) #define PUSH(w) (((XmMegaButtonWidget)(w))->push_button) #define MB(w) (((XmMegaButtonWidget)(w))->mega_button) #define WIDTH(w) (((XmMegaButtonWidget)(w))->core.width) #define HEIGHT(w) (((XmMegaButtonWidget)(w))->core.height) #define VIS_COUNT(w) (((XmMegaButtonWidget)(w))->mega_button.visibleItemCount) #define ICOUNT(w) (((XmMegaButtonWidget)(w))->mega_button.itemCount) #define ITEMS(w) (((XmMegaButtonWidget)(w))->mega_button._items) #define EXITEMS(w) (((XmMegaButtonWidget)(w))->mega_button.exitems) #define VIS_POS(w) (((XmMegaButtonWidget)(w))->mega_button.visiblePos) #define FPOS(w) (((XmMegaButtonWidget)(w))->mega_button.firstVisibleItem) #define EL_HEIGHT(w) (((XmMegaButtonWidget)(w))->mega_button.elementHeight) #define YOFFSET(w) (((XmMegaButtonWidget)(w))->mega_button.yOffset) #define XOFFSET(w) (((XmMegaButtonWidget)(w))->mega_button.xOffset) #define HAS_ARROWS(w) (((XmMegaButtonWidget)(w))->mega_button.hasArrows) #define SET_POS(w) (((XmMegaButtonWidget)(w))->mega_button.setPosition) #define COPY_GC(w) (((XmMegaButtonWidget)(w))->mega_button.copyGC) #define TIMER(w) (((XmMegaButtonWidget)(w))->mega_button.timer) #define TDIR(w) (((XmMegaButtonWidget)(w))->mega_button.timedScrollDirection) #define SFOS(w) (((XmMegaButtonWidget)(w))->mega_button.savedFillOnSelect) #define IDELAY(w) (((XmMegaButtonWidget)(w))->mega_button.initialDelay) #define RDELAY(w) (((XmMegaButtonWidget)(w))->mega_button.repeatDelay) #define FAKE_ITEM(w) (((XmMegaButtonWidget)(w))->mega_button.fakeItem) #define CUR_SIZE(w) (((XmMegaButtonWidget)(w))->mega_button.currentSize) #define DATA(w) (((XmMegaButtonWidget)(w))->mega_button.data) #define CB_DATA(w) (((XmMegaButtonWidget)(w))->mega_button.cbData) #define MAX_STRING_POS(w) (((XmMegaButtonWidget)(w))->mega_button.maxStringPos) #define MAX_STRING_WIDTH(w) (((XmMegaButtonWidget)(w))->mega_button.maxStringWidth) #define MODE(w) (((XmMegaButtonWidget)(w))->mega_button.mode) #define TOG_DATA(w) (((XmMegaButtonWidget)(w))->mega_button.toggleData) #define FILL_ON_SELECT(w) (((XmMegaButtonWidget)(w))->mega_button.fillOnSelect) #define SELECT_COLOR(w) (((XmMegaButtonWidget)(w))->mega_button.selectColor) #define SELECT_GC(w) (((XmMegaButtonWidget)(w))->mega_button.selectGC) #define CHUNK_SIZE(w) (((XmMegaButtonWidget)(w))->mega_button.chunkSize) #define VIS_W_OFF(w) (((XmMegaButtonWidget)(w))->mega_button.visibleWhenOff) #define STR_HEIGHT(w) (((XmMegaButtonWidget)(w))->mega_button.stringHeight) #define DEFAULT_CHUNK_SIZE 50 static char traversalTranslations[] = ": BtnMotion() \n\ : Enter() \n\ : Leave() \n\ osfHelp:Help() \n\ :Unmap()\n\ :FocusOut()\n\ :FocusIn()\n\ osfCancel:MenuEscape()\n\ osfUp: MegaButtonTraverseUp() \n\ osfDown: MegaButtonTraverseDown() \n\ osfLeft:MenuTraverseLeft()\n\ osfRight:MenuTraverseRight()\n\ osfSelect:ArmAndActivate()\n\ osfActivate:ArmAndActivate()\n\ ~s ~m ~a Return:ArmAndActivate()\n\ ~s ~m ~a space:ArmAndActivate()"; #define TheOffset(field) XtOffset(XmMegaButtonWidget, mega_button.field) static XtResource resources[] = { {XmNitems, XmCItems, XtRPointer, sizeof(XtPointer), TheOffset(exitems), XmRImmediate, (XtPointer)NULL}, {XmNitemCount, XmCItemCount, XtRInt, sizeof(int), TheOffset(itemCount), XmRImmediate, (XtPointer)0}, {XmNvisibleItemCount, XmCVisibleItemCount, XmRInt, sizeof(int), TheOffset(visibleItemCount), XtRImmediate, (XtPointer)0}, {XmNsetPosition, XmCSetPosition, XtRInt, sizeof(int), TheOffset(setPosition), XmRImmediate, (XtPointer)-1}, {XmNrepeatDelay, XmCRepeatDelay, XmRInt, sizeof(int), TheOffset(repeatDelay), XmRImmediate, (XtPointer)50}, {XmNinitialDelay, XmCInitialDelay, XmRInt, sizeof(int), TheOffset(initialDelay), XmRImmediate, (XtPointer)250}, {XmNbuttonMode, XmCButtonMode, XmRMegaButtonMode, sizeof(unsigned char), TheOffset(mode), XmRImmediate, (XtPointer)XmMODE_TOGGLE_BUTTON}, {XmNselectColor, XmCSelectColor, XmRPixel, sizeof(Pixel), TheOffset(selectColor), XmRCallProc, (XtPointer)_XmSelectColorDefault}, {XmNfillOnSelect, XmCFillOnSelect, XmRBoolean, sizeof(Boolean), TheOffset(fillOnSelect), XmRImmediate, (XtPointer)FALSE}, {XmNchunkSize, XmCChunkSize, XmRInt, sizeof(int), TheOffset(chunkSize), XmRImmediate, (XtPointer)DEFAULT_CHUNK_SIZE}, {XmNcallbackData, XmCCallbackData, XmRPointer, sizeof(XtPointer), TheOffset(cbData), XmRImmediate, (XtPointer)NULL}, {XmNvisibleWhenOff, XmCVisibleWhenOff, XmRBoolean, sizeof(Boolean), TheOffset(visibleWhenOff), XtRImmediate, (XtPointer)FALSE}, }; #undef TheOffset static XtActionsRec actions[] = { { "Enter", (XtActionProc) enterWidget }, { "Leave", (XtActionProc) leaveWidget }, { "BtnMotion", (XtActionProc) buttonMotion }, { "MegaButtonTraverseUp", (XtActionProc) up }, { "MegaButtonTraverseDown", (XtActionProc) down }, { "ArmAndActivate", (XtActionProc) armAndActivate }, { "BtnUp", (XtActionProc) buttonUp }, { "BtnDown", (XtActionProc) buttonDown}, { "FocusIn", (XtActionProc) focusIn }, { "FocusOut", (XtActionProc) focusOut}, {"MenuBtnDown", (XtActionProc)down}, {"MenuBtnUp", (XtActionProc)up}, {"PulldownBtnDown", (XtActionProc)down}, {"PulldownBtnUp", (XtActionProc)up}, {"PopupBtnDown", (XtActionProc)down}, {"PopupBtnUp", (XtActionProc)up}, {"MenuBarBtnDown", (XtActionProc)down}, {"MenuBarBtnUp", (XtActionProc)up}, {"MenuTraverseUp", (XtActionProc)up}, {"MenuTraverseDown", (XtActionProc)down}, {"MenuFocusIn", (XtActionProc)focusIn }, {"MenuFocusOut", (XtActionProc)focusOut }, {"MenuUnmap", (XtActionProc)leaveWidget }, {"MenuEnter", (XtActionProc)enterWidget}, }; /* actions */ static XmBaseClassExtRec megaBBaseClassExtRec = { NULL, /* Next extension */ NULLQUARK, /* record type XmQmotif */ XmBaseClassExtVersion, /* version */ sizeof(XmBaseClassExtRec), /* size */ XmInheritInitializePrehook, /* initialize prehook */ XmInheritSetValuesPrehook, /* set_values prehook */ XmInheritInitializePosthook, /* initialize posthook */ XmInheritSetValuesPosthook, /* set_values posthook */ XmInheritClass, /* secondary class */ XmInheritSecObjectCreate, /* creation proc */ XmInheritGetSecResData, /* getSecResData */ {0}, /* fast subclass */ XmInheritGetValuesPrehook, /* get_values prehook */ XmInheritGetValuesPosthook, /* get_values posthook */ (XtWidgetClassProc)NULL, /* classPartInitPrehook */ (XtWidgetClassProc)NULL, /* classPartInitPosthook*/ NULL, /* ext_resources */ NULL, /* compiled_ext_resources*/ 0, /* num_ext_resources */ FALSE, /* use_sub_resources */ XmInheritWidgetNavigable, /* widgetNavigable */ XmInheritFocusChange, /* focusChange */ }; XmPrimitiveClassExtRec _XmMegaBPrimClassExtRec = { NULL, NULLQUARK, XmPrimitiveClassExtVersion, sizeof(XmPrimitiveClassExtRec), XmInheritBaselineProc, /* widget_baseline */ XmInheritDisplayRectProc, /* widget_display_rect */ (XmWidgetMarginsProc)NULL, /* widget_margins */ }; XmMegaButtonClassRec xmMegaButtonClassRec = { { (WidgetClass)&xmPushButtonClassRec, /* superclass */ "XmMegaButton", /* class_name */ (Cardinal)sizeof(XmMegaButtonRec), /* widget size */ (XtProc)classInit, /* class_init */ (XtWidgetClassProc)classPartInit, /* class_part_init */ (XtEnum)FALSE, /* class_inited */ (XtInitProc)initialize, /* initialize */ (XtArgsProc)NULL, /* init_hook */ XtInheritRealize, /* realize */ (XtActionList)actions, /* actions */ (Cardinal)XtNumber(actions), /* num_actions */ (XtResourceList)resources, /* resources */ (Cardinal)XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ (XtEnum)FALSE, /* compress_exposur */ TRUE, /* compress enterleave */ FALSE, /* visibility_interest */ (XtWidgetProc)destroy, /* destroy */ (XtWidgetProc)XtInheritResize, (XtExposeProc)expose, (XtSetValuesFunc)setValues, /* set_values */ (XtArgsFunc)NULL, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ (XtArgsProc)NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ (XtPointer)NULL, /* callback_private */ XtInheritTranslations, (XtGeometryHandler)NULL, /* query_geometry */ XtInheritDisplayAccelerator, /* display_accelerator */ (XtPointer)&megaBBaseClassExtRec, /* extension */ }, { /* xmPrimitiveClass */ (XtWidgetProc)borderHighlight, (XtWidgetProc)borderUnhighlight, XtInheritTranslations, (XtActionProc)armAndActivate, NULL, 0, (XtPointer)&_XmMegaBPrimClassExtRec, }, { /* xmLabelClass */ (XtWidgetProc) XmInheritSetOverrideCallback, NULL, NULL, NULL, }, { /* xmPushButtonClass */ (XtPointer)NULL, }, { XmInheritMegaButtonToggleSpaceProc, XmInheritMegaButtonToggleDrawProc, } }; WidgetClass xmMegaButtonWidgetClass = (WidgetClass)&xmMegaButtonClassRec; static XtWidgetClassProc classPartInit(WidgetClass _wc) { XmMegaButtonWidgetClass mbwc; _XmFastSubclassInit(_wc, (XmPUSH_BUTTON_BIT | XmLABEL_BIT | XmPRIMITIVE_BIT)); mbwc = (XmMegaButtonWidgetClass)_wc; if (mbwc->mega_button_class.toggleSpaceProc == XmInheritMegaButtonToggleSpaceProc) mbwc->mega_button_class.toggleSpaceProc = toggleSpaceProc; if (mbwc->mega_button_class.toggleDrawProc == XmInheritMegaButtonToggleDrawProc) mbwc->mega_button_class.toggleDrawProc = toggleDrawProc; return (XtWidgetClassProc)NULL; } static XtProc classInit() { xmMegaButtonClassRec.label_class.translations = (String)XtParseTranslationTable(traversalTranslations); XtSetTypeConverter(XtRString, XmRMegaButtonMode, cvtStringToMegaButtonMode, (XtConvertArgList)NULL, 0, XtCacheAll, (XtDestructor)NULL); return (XtProc)NULL; } static XtInitProc initialize(Widget _request, Widget _new, String *_args, Cardinal *_numArgs) { int i; XmString xmstring; XGCValues gcValues; Dimension width; VIS_POS(_new) = -1; FPOS(_new) = 0; TOG_DATA(_new) = NULL; if ((MODE(_new) == XmMODE_TOGGLE_BUTTON) && (SET_POS(_new) > (ICOUNT(_new)-1))) SET_POS(_new) = ICOUNT(_new) - 1; if (CHUNK_SIZE(_new) < 1) CHUNK_SIZE(_new) = DEFAULT_CHUNK_SIZE; if (ICOUNT(_new) == 0) { if (LABEL(_new)._label == (_XmString) XmUNSPECIFIED) { xmstring = _XmOSGetLocalizedString ((char *) NULL, /* reserved */ (Widget)_new, XmNlabelString, "\0"); LABEL(_new)._label = _XmStringCreate(xmstring); } else if (LABEL(_new)._label == NULL) { xmstring = _XmOSGetLocalizedString ((char *) NULL, /* reserved */ (Widget)_new, XmNlabelString, CORE(_new).name); LABEL(_new)._label = _XmStringCreate(xmstring); } ICOUNT(_new) = 1; ITEMS(_new) = XtNew(_XmString); ITEMS(_new)[0] = LABEL(_new)._label; DATA(_new) = XtNew(XtPointer); DATA(_new)[0] = (XtPointer)NULL; FAKE_ITEM(_new) = TRUE; } else { ITEMS(_new) = (_XmString *)XtMalloc(sizeof(_XmString) * ICOUNT(_new)); DATA(_new) = (XtPointer)XtCalloc(ICOUNT(_new), sizeof(XtPointer)); if (CB_DATA(_new) != NULL) for(i=0;icore_class.resize) ((Widget)_new); YOFFSET(_new) = LABEL(_new).TextRect.y; XOFFSET(_new) = LABEL(_new).TextRect.x; if ( (MODE(_new) == XmMODE_TOGGLE_BUTTON) && ( ((XmMegaButtonWidgetClass)XtClass(_new))->mega_button_class.toggleSpaceProc)) (( (XmMegaButtonWidgetClass)XtClass(_new))->mega_button_class.toggleSpaceProc)(_new, &WIDTH(_new), &EL_HEIGHT(_new)); if (VIS_COUNT(_new) == 0) { Dimension dheight; int vcount; dheight = DisplayHeight(XtDisplay(_new), DefaultScreen(XtDisplay(_new))); vcount = dheight/EL_HEIGHT(_new) - 4; if (vcount <=3) vcount = 3; VIS_COUNT(_new) = vcount; } HAS_ARROWS(_new) = ICOUNT(_new) > VIS_COUNT(_new); if (HAS_ARROWS(_new)) HEIGHT(_new) = HEIGHT(_new) * (VIS_COUNT(_new) + 2) + (2 * MINI_SEP_HEIGHT); else HEIGHT(_new) *= ICOUNT(_new); gcValues.foreground = CORE(_new).background_pixel; COPY_GC(_new) = XtGetGC((Widget)_new, GCForeground, &gcValues); gcValues.foreground = FILL_ON_SELECT(_new) ? SELECT_COLOR(_new) : CORE(_new).background_pixel; SELECT_GC(_new) = XtGetGC((Widget)_new, GCForeground, &gcValues); TIMER(_new) = -1; return (XtInitProc)NULL; } static XtWidgetProc destroy(Widget _mbw) { register int i; XtReleaseGC((Widget)_mbw, COPY_GC(_mbw)); XtReleaseGC((Widget)_mbw, SELECT_GC(_mbw)); for(i=0;icore_class.expose) ((Widget)_mbw, _event, _region); if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) && ( ((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)) { if ((first + i) == SET_POS(_mbw)) (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)(_mbw, LABEL(_mbw).TextRect.x, y, TRUE); else if (VIS_W_OFF(_mbw)) (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)(_mbw, LABEL(_mbw).TextRect.x, y, FALSE); } y += EL_HEIGHT(_mbw); } y -= YOFFSET(_mbw); if (HAS_ARROWS(_mbw)) { drawMiniSeparator(_mbw, y); y += MINI_SEP_HEIGHT; drawArrow(_mbw, VIS_COUNT(_mbw)+1, XmARROW_DOWN, ((ICOUNT(_mbw))-FPOS(_mbw)) > VIS_COUNT(_mbw)); } /* drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); */ } static Boolean setValues( Widget _current, Widget _request, Widget _new, ArgList args, Cardinal *num_args) { return FALSE; } static void getMaxWidthPos(Widget _mbw, int *_maxWidthPos, Dimension *_height) { int first, i; Dimension maxHeight, maxWidth; int mwp; if (ICOUNT(_mbw) == 0) { *_maxWidthPos = 0; *_height = 1; return; } first = FPOS(_mbw); mwp = 0; maxHeight = 1; maxWidth = 1; for(i=0; (first + i) < ICOUNT(_mbw); i++) { LABEL(_mbw)._label = ITEMS(_mbw)[first+i]; _XmCalcLabelDimensions((Widget)_mbw); if (LABEL(_mbw).TextRect.width > maxWidth) { maxWidth = LABEL(_mbw).TextRect.width; mwp = i; } if (LABEL(_mbw).TextRect.height > maxHeight) maxHeight = LABEL(_mbw).TextRect.height; } *_maxWidthPos = mwp; *_height = maxHeight; } static void drawShadowedItem(Widget _mbw, int _pos, Boolean _clear) { Position y; if ( (_pos < 0) || (HAS_ARROWS(_mbw) && (_pos > (VIS_COUNT(_mbw)+1))) || (!HAS_ARROWS(_mbw) && (_pos >= VIS_COUNT(_mbw))) ) return; y = 0; if (HAS_ARROWS(_mbw)) { if (_pos > 0) y += MINI_SEP_HEIGHT; if (_pos > VIS_COUNT(_mbw) ) y += MINI_SEP_HEIGHT; } y += (_pos * EL_HEIGHT(_mbw)); if (_clear) { _XmClearBorder(XtDisplay((Widget)_mbw), XtWindow((Widget)_mbw), 0, y, WIDTH(_mbw), EL_HEIGHT(_mbw), PRIM(_mbw).shadow_thickness); } else { _XmDrawShadows(XtDisplay((Widget)_mbw), XtWindow((Widget)_mbw), PRIM(_mbw).top_shadow_GC, PRIM(_mbw).bottom_shadow_GC, 0, y, WIDTH(_mbw), EL_HEIGHT(_mbw), PRIM(_mbw).shadow_thickness, XmSHADOW_OUT); } } static void clearArrow(Widget _mbw, int _pos) { Position y = 0; if (HAS_ARROWS(_mbw)) { if (_pos > 0) y += MINI_SEP_HEIGHT; if (_pos > VIS_COUNT(_mbw) ) y += MINI_SEP_HEIGHT; } y += (_pos * EL_HEIGHT(_mbw)); XClearArea(XtDisplay(_mbw), XtWindow(_mbw), PRIM(_mbw).shadow_thickness, y + PRIM(_mbw).shadow_thickness, WIDTH(_mbw) - 2 * PRIM(_mbw).shadow_thickness, EL_HEIGHT(_mbw) - 2 * PRIM(_mbw).shadow_thickness, FALSE); } static int yToPos(Widget _mbw, Position _y) { Dimension topOffset, bottomOffset; if ((_y >= 0) && HAS_ARROWS(_mbw)) { if ((Dimension)_y <= EL_HEIGHT(_mbw)) return 0; topOffset = EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT; if ((Dimension)_y <= topOffset) return 0; bottomOffset = HEIGHT(_mbw) - EL_HEIGHT(_mbw); if ((Dimension)_y >= bottomOffset) return VIS_COUNT(_mbw)+1; bottomOffset -= MINI_SEP_HEIGHT; if ((Dimension)_y >= bottomOffset) return VIS_COUNT(_mbw); _y -= MINI_SEP_HEIGHT; } return _y/EL_HEIGHT(_mbw); } static void enterWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { if (ICOUNT(_mbw) == 0) return; XtCallActionProc((Widget)_mbw, "PrimitiveEnter", _event, _params, *_numParams); if ( LABEL(_mbw).menu_type != XmWORK_AREA ) { if (_XmGetInDragMode((Widget)_mbw)) { drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); VIS_POS(_mbw) = yToPos(_mbw, _event->xbutton.y); drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); if (HAS_ARROWS(_mbw)) { if (VIS_POS(_mbw) == VIS_COUNT(_mbw)+1) { TDIR(_mbw) = XmTRAVERSE_DOWN; TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw), (unsigned long)IDELAY(_mbw), timedScroll, (XtPointer)_mbw); } else if (VIS_POS(_mbw) == 0) { TDIR(_mbw) = XmTRAVERSE_UP; TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw), (unsigned long)IDELAY(_mbw), timedScroll, (XtPointer)_mbw); } } } } } static void leaveWidget(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { if (ICOUNT(_mbw) == 0) return; XtCallActionProc((Widget)_mbw, "PrimitiveLeave", _event, _params, *_numParams); if ( LABEL(_mbw).menu_type != XmWORK_AREA ) { /* if ( _XmGetInDragMode((Widget)_mbw) ) */ /* drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); */ if (TIMER(_mbw) != -1) { XtRemoveTimeOut(TIMER(_mbw)); TIMER(_mbw) = -1; } } drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); } static void buttonMotion(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { if (ICOUNT(_mbw) == 0) return; if ( LABEL(_mbw).menu_type != XmWORK_AREA ) { int pos = yToPos(_mbw, _event->xmotion.y); if (pos != VIS_POS(_mbw)) { if (TIMER(_mbw) != -1) { XtRemoveTimeOut(TIMER(_mbw)); TIMER(_mbw) = -1; } drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); drawShadowedItem(_mbw, pos, FALSE); VIS_POS(_mbw) = pos; if (HAS_ARROWS(_mbw)) { if (VIS_POS(_mbw) == VIS_COUNT(_mbw)+1) scroll(_mbw, XmTRAVERSE_DOWN, TRUE, IDELAY(_mbw)); else if (VIS_POS(_mbw) == 0) scroll(_mbw, XmTRAVERSE_UP, TRUE, IDELAY(_mbw)); } _XmSetInDragMode((Widget)_mbw, TRUE); } } } static void up(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { int vpos; if (ICOUNT(_mbw) == 0) return; if (LABEL(_mbw).menu_type != XmWORK_AREA ) { if (!_XmGetInDragMode((Widget)_mbw)) { vpos = VIS_POS(_mbw); vpos--; if ((vpos == -1) && (FPOS(_mbw) == 0)) { CompositeWidget parent = (CompositeWidget)XtParent(_mbw); if (parent->composite.num_children > 1) { XtCallActionProc((Widget)_mbw, "PrimitiveTraverseUp", _event, _params, *_numParams); return; } } if (HAS_ARROWS(_mbw) && (vpos <= 0)) { if (vpos == 0) { drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); drawShadowedItem(_mbw, vpos, FALSE); } scroll(_mbw, XmTRAVERSE_UP, FALSE, 0); VIS_POS(_mbw) = 0; } else { if (!HAS_ARROWS(_mbw) && (vpos == -1)) vpos = ICOUNT(_mbw)-1; if (vpos != VIS_POS(_mbw)) { drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); drawShadowedItem(_mbw, vpos, FALSE); VIS_POS(_mbw) = vpos; } } _XmRecordEvent(_event); } } } static void down(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { int vpos; if (ICOUNT(_mbw) == 0) return; if (LABEL(_mbw).menu_type != XmWORK_AREA ) { if (!_XmGetInDragMode((Widget)_mbw)) { vpos = VIS_POS(_mbw); vpos++; _XmRecordEvent(_event); if (HAS_ARROWS(_mbw) && (vpos >= (VIS_COUNT(_mbw) + 1))) { if (VIS_POS(_mbw) != (VIS_COUNT(_mbw)+1)) { drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); drawShadowedItem(_mbw, vpos, FALSE); } else if (FPOS(_mbw) >= (ICOUNT(_mbw)-VIS_COUNT(_mbw))) { CompositeWidget parent = (CompositeWidget)XtParent(_mbw); if (parent->composite.num_children > 1) { XtCallActionProc((Widget)_mbw, "PrimitiveTraverseDown", _event, _params, *_numParams); return; } } scroll(_mbw, XmTRAVERSE_DOWN, FALSE, 0); VIS_POS(_mbw) = VIS_COUNT(_mbw) + 1; } else { if (!HAS_ARROWS(_mbw)) { if (vpos == ICOUNT(_mbw)) { CompositeWidget parent = (CompositeWidget)XtParent(_mbw); if (parent->composite.num_children > 1) { XtCallActionProc((Widget)_mbw, "PrimitiveTraverseDown", _event, _params, *_numParams); return; } else vpos = 0; } } drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); drawShadowedItem(_mbw, vpos, FALSE); VIS_POS(_mbw) = vpos; } } } } static void buttonUp(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { XmMegaButtonCallbackStruct mtbcs; Widget parent, shell; Boolean validButton; Boolean poppedUp; Boolean isMenuPane; if (TIMER(_mbw) != -1) { XtRemoveTimeOut(TIMER(_mbw)); TIMER(_mbw) = -1; } if (ICOUNT(_mbw) == 0) return; isMenuPane = (LABEL(_mbw).menu_type == XmMENU_PULLDOWN) || (LABEL(_mbw).menu_type == XmMENU_POPUP); shell = XtGetShell((Widget)_mbw); parent = XtParent(_mbw); if (_event && (_event->type == ButtonRelease)) { (* xmLabelClassRec.label_class.menuProcs) (XmMENU_BUTTON, parent, NULL, _event, &validButton); if (!validButton) return; VIS_POS(_mbw) = yToPos(_mbw, _event->xbutton.y); } if (HAS_ARROWS(_mbw) && !_XmGetInDragMode((Widget)_mbw)) { if (VIS_POS(_mbw) == 0) { _XmRecordEvent(_event); return; } else if (VIS_POS(_mbw) == (VIS_COUNT(_mbw)+1)) { _XmRecordEvent(_event); return; } } if (isMenuPane && !XmIsMenuShell(shell)) (* xmLabelClassRec.label_class.menuProcs) (XmMENU_POPDOWN, (Widget) _mbw, NULL, _event, &poppedUp); else (* xmLabelClassRec.label_class.menuProcs) (XmMENU_BUTTON_POPDOWN, (Widget) _mbw , NULL, _event, &poppedUp); _XmRecordEvent(_event); if (poppedUp) return; mtbcs.reason = XmCR_ACTIVATE; mtbcs.event = _event; if (HAS_ARROWS(_mbw)) { if ((VIS_POS(_mbw) == 0) || (VIS_POS(_mbw) == (VIS_COUNT(_mbw)+1))) return; mtbcs.pos = FPOS(_mbw) + VIS_POS(_mbw) - 1; } else mtbcs.pos = VIS_POS(_mbw); mtbcs.callbackValue = DATA(_mbw)[mtbcs.pos]; mtbcs.string = _XmStringCreateExternal(LABEL(_mbw).font, ITEMS(_mbw)[mtbcs.pos]); SET_POS(_mbw) = mtbcs.pos; #if 0 if (XmIsRowColumn(parent)) (* xmLabelClassRec.label_class.menuProcs) (XmMENU_CALLBACK, parent, FALSE, _mbw, (XtPointer)&mtbcs); else #endif XtCallCallbackList((Widget)_mbw, PUSH(_mbw).activate_callback, &mtbcs); _XmSetInDragMode((Widget)_mbw, False); } static void buttonDown(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParms) { ShellWidget popupShell; int validButton, pos = 0; Widget child; if (ICOUNT(_mbw) == 0) return; XAllowEvents(XtDisplay(_mbw), SyncPointer, CurrentTime); if (_event && (_event->type == ButtonPress)) { (* xmLabelClassRec.label_class.menuProcs) (XmMENU_BUTTON, XtParent(_mbw), NULL, _event, &validButton); if (!validButton) return; pos = yToPos(_mbw, _event->xbutton.y); } if (HAS_ARROWS(_mbw) && !_XmGetInDragMode((Widget)_mbw)) { if (pos == 0) { drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); VIS_POS(_mbw) = pos; drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); _XmRecordEvent(_event); scroll(_mbw, XmTRAVERSE_UP, TRUE, IDELAY(_mbw)); return; } else if (pos == (VIS_COUNT(_mbw)+1)) { drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); VIS_POS(_mbw) = pos; drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); _XmRecordEvent(_event); scroll(_mbw, XmTRAVERSE_DOWN, TRUE, IDELAY(_mbw)); return; } } VIS_POS(_mbw) = pos; _XmSetInDragMode((Widget)_mbw, TRUE); popupShell = (ShellWidget)_XmGetRC_PopupPosted(XtParent(_mbw)); if (popupShell) { if (popupShell->shell.popped_up) (* xmLabelClassRec.label_class.menuProcs)(XmMENU_SHELL_POPDOWN, (Widget)popupShell, NULL, _event, NULL); child = ((XmManagerWidget)XtParent(_mbw))->manager.active_child; if (child && (XmIsCascadeButton(child) || XmIsCascadeButtonGadget(child))) XmCascadeButtonHighlight (child, FALSE); } XmProcessTraversal( (Widget)_mbw, XmTRAVERSE_CURRENT); _XmSetInDragMode((Widget)_mbw, FALSE); _XmRecordEvent(_event); } static void armAndActivate(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { XmMegaButtonCallbackStruct mtbcs; if (ICOUNT(_mbw) == 0) return; mtbcs.reason = XmCR_ACTIVATE; mtbcs.event = _event; if (HAS_ARROWS(_mbw)) { if ((VIS_POS(_mbw) == 0) || (VIS_POS(_mbw) == (VIS_COUNT(_mbw)+1))) return; mtbcs.pos = FPOS(_mbw) + VIS_POS(_mbw) - 1; } else mtbcs.pos = VIS_POS(_mbw); mtbcs.callbackValue = DATA(_mbw)[mtbcs.pos]; mtbcs.string = _XmStringCreateExternal(LABEL(_mbw).font, ITEMS(_mbw)[mtbcs.pos]); SET_POS(_mbw) = mtbcs.pos; XFlush(XtDisplay(_mbw)); XtCallCallbackList((Widget)_mbw, PUSH(_mbw).activate_callback, &mtbcs); } static Widget XtGetShell(Widget _w) { Widget temp; temp = _w; while(temp && !XtIsSubclass(temp, shellWidgetClass)) temp = XtParent(temp); return temp; } #if !HAVE_SOURCE && !defined(LESSTIF_VERSION) struct _XmFocusDataRec { Widget not_used; Widget not_used_2; Widget old_focus_item; }; #endif /* HAVE_SOURCE */ /* ** This is a tad hackish. The general idea is that there is no way to tell which ** directory the focusIn event came from if we are in a menu. So get the ** focusData which has the last widget to have focus. Use this as an index ** into the RowCol's children, and go from there. */ static void focusIn(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { int labelCount; Widget oldFocus; CompositeWidget parent; XmFocusData focusData; WidgetList children; int myI, oldI, i; VIS_POS(_mbw) = 0; if (ICOUNT(_mbw) == 0) return; focusData = _XmGetFocusData((Widget)_mbw); if (focusData && focusData->old_focus_item) { oldFocus = focusData->old_focus_item; parent = (CompositeWidget)XtParent(_mbw); children = parent->composite.children; myI = -1; oldI = -1; labelCount = 0; for(i=0;(icomposite.num_children);i++) { if (children[i] == (Widget)_mbw) myI = i; else if (children[i] == oldFocus) oldI = i; else if (XmIsLabel(children[i])) labelCount++; if ((myI != -1) && (oldI != -1)) break; } if ( (oldI != -1) && ((myI < oldI) || ((myI > oldI) && labelCount))) VIS_POS(_mbw) = (HAS_ARROWS(_mbw) ? VIS_COUNT(_mbw) + 1 : ICOUNT(_mbw)-1); } drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); } static void focusOut(Widget _mbw, XEvent *_event, String *_params, Cardinal *_numParams) { if (ICOUNT(_mbw) == 0) return; if (TIMER(_mbw) != -1) { XtRemoveTimeOut(TIMER(_mbw)); TIMER(_mbw) = -1; } drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); VIS_POS(_mbw) = 0; } static void borderHighlight(Widget _mbw) { if (ICOUNT(_mbw) == 0) return; if ((LABEL(_mbw).menu_type == XmMENU_PULLDOWN) || (LABEL(_mbw).menu_type == XmMENU_POPUP)) { drawShadowedItem(_mbw, VIS_POS(_mbw), FALSE); } } static void borderUnhighlight(Widget _mbw) { if (ICOUNT(_mbw) == 0) return; if ((LABEL(_mbw).menu_type == XmMENU_PULLDOWN) || (LABEL(_mbw).menu_type == XmMENU_POPUP)) drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); } static void drawMiniSeparator(Widget _mbw, Position _y) { int i, firstHalf, secondHalf; firstHalf = MINI_SEP_HEIGHT/2; secondHalf = firstHalf; if (MINI_SEP_HEIGHT % 2) secondHalf++; for(i=secondHalf;i 0) y += MINI_SEP_HEIGHT; if (_pos > VIS_COUNT(_mbw) ) y += MINI_SEP_HEIGHT; } y += (_pos * EL_HEIGHT(_mbw)); arrowWidth = WIDTH(_mbw)/5; _XmDrawArrow(XtDisplay((Widget)(_mbw)), XtWindow ((Widget)(_mbw)), _sensitive ? PRIM(_mbw).top_shadow_GC : PRIM(_mbw).bottom_shadow_GC, _sensitive ? PRIM(_mbw).bottom_shadow_GC : PRIM(_mbw).top_shadow_GC, _sensitive ? COPY_GC(_mbw) : LABEL(_mbw).insensitive_GC, WIDTH(_mbw)/2 - arrowWidth/2, y + PRIM(_mbw).shadow_thickness, arrowWidth, EL_HEIGHT(_mbw) - 2 * (PRIM(_mbw).shadow_thickness), PRIM(_mbw).shadow_thickness, _direction); } static void timedScroll(XtPointer _closure, XtIntervalId *_id) { XmMegaButtonWidget mbw = (XmMegaButtonWidget)_closure; scroll((Widget)mbw, TDIR(mbw), TRUE, RDELAY(mbw)); } static void scroll(Widget _mbw, int _direction, Boolean _addTimeout, int _delay) { Position sy, dy; TIMER(_mbw) = -1; if (_direction == XmTRAVERSE_DOWN) { if ((FPOS(_mbw) + VIS_COUNT(_mbw)) >= ICOUNT(_mbw)) return; /* drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); */ sy = 2 * EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT; dy = sy - EL_HEIGHT(_mbw); XCopyArea(XtDisplay(_mbw), XtWindow(_mbw), XtWindow(_mbw), COPY_GC(_mbw), 0, sy, WIDTH(_mbw), EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw)-1), 0, dy); XClearArea(XtDisplay(_mbw), XtWindow(_mbw), PRIM(_mbw).shadow_thickness, dy + EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw)-1), WIDTH(_mbw)-2*PRIM(_mbw).shadow_thickness, EL_HEIGHT(_mbw), FALSE); FPOS(_mbw)++; LABEL(_mbw)._label = ITEMS(_mbw)[FPOS(_mbw)+VIS_COUNT(_mbw)-1]; _XmCalcLabelDimensions((Widget)_mbw); LABEL(_mbw).TextRect.y = YOFFSET(_mbw) + (VIS_COUNT(_mbw)*EL_HEIGHT(_mbw)) + MINI_SEP_HEIGHT; LABEL(_mbw).TextRect.x = XOFFSET(_mbw); (*xmLabelWidgetClass->core_class.expose) ((Widget)_mbw, NULL, (Region)NULL); if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) && ((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc) { if ((FPOS(_mbw)+VIS_COUNT(_mbw)-1) == SET_POS(_mbw)) (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc)(_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, TRUE); else if (VIS_W_OFF(_mbw)) (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc) (_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, FALSE); } if (_addTimeout && ((FPOS(_mbw) + VIS_COUNT(_mbw)) < ICOUNT(_mbw))) { TDIR(_mbw) = XmTRAVERSE_DOWN; TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw), (unsigned long) _delay, timedScroll, (XtPointer)_mbw); } } else if (_direction == XmTRAVERSE_UP) { if (FPOS(_mbw) == 0) return; /* drawShadowedItem(_mbw, VIS_POS(_mbw), TRUE); */ sy = EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT; dy = sy + EL_HEIGHT(_mbw); XCopyArea(XtDisplay(_mbw), XtWindow(_mbw), XtWindow(_mbw), COPY_GC(_mbw), 0, sy, WIDTH(_mbw), EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw)-1), 0, dy); XClearArea(XtDisplay(_mbw), XtWindow(_mbw), PRIM(_mbw).shadow_thickness, EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT, WIDTH(_mbw)-2*PRIM(_mbw).shadow_thickness, EL_HEIGHT(_mbw), FALSE); FPOS(_mbw)--; LABEL(_mbw)._label = ITEMS(_mbw)[FPOS(_mbw)]; _XmCalcLabelDimensions((Widget)_mbw); LABEL(_mbw).TextRect.y = YOFFSET(_mbw) + EL_HEIGHT(_mbw) + MINI_SEP_HEIGHT; LABEL(_mbw).TextRect.x = XOFFSET(_mbw); (*xmLabelWidgetClass->core_class.expose) ((Widget)_mbw, NULL, (Region)NULL); if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) && ((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc) { if (FPOS(_mbw) == SET_POS(_mbw)) (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc) (_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, TRUE); else if (VIS_W_OFF(_mbw)) (*((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleDrawProc) (_mbw, LABEL(_mbw).TextRect.x, LABEL(_mbw).TextRect.y, FALSE); } if (_addTimeout && (FPOS(_mbw) != 0)) { TDIR(_mbw) = XmTRAVERSE_UP; TIMER(_mbw) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)_mbw), (unsigned long) _delay, timedScroll, (XtPointer)_mbw); } } if (_direction == XmTRAVERSE_DOWN) { if (FPOS(_mbw) != 0) { if (((ICOUNT(_mbw))-FPOS(_mbw)) <= VIS_COUNT(_mbw)) { clearArrow(_mbw, VIS_COUNT(_mbw)+1); drawArrow(_mbw, VIS_COUNT(_mbw)+1, XmARROW_DOWN, FALSE); } drawArrow(_mbw, 0, XmARROW_UP, TRUE); } } else { if (FPOS(_mbw) == 0) { clearArrow(_mbw, 0); drawArrow(_mbw, 0, XmARROW_UP, FALSE); } drawArrow(_mbw, VIS_COUNT(_mbw)+1, XmARROW_DOWN, TRUE); } } static void toggleDrawProc(Widget _mbw, Position _x, Position _y, Boolean _on) { int ecalc; ecalc = STR_HEIGHT(_mbw) - 2 * PRIM(_mbw).shadow_thickness; if (ecalc < 5) ecalc = 5; _y += EL_HEIGHT(_mbw)/2 - ecalc/2 - PRIM(_mbw).shadow_thickness; _x -= (ecalc + LABEL(_mbw).margin_width); _XmDrawDiamond(XtDisplay((Widget)_mbw), XtWindow((Widget)_mbw), _on ? PRIM(_mbw).bottom_shadow_GC : PRIM(_mbw).top_shadow_GC, _on ? PRIM(_mbw).top_shadow_GC : PRIM(_mbw).bottom_shadow_GC, _on ? SELECT_GC(_mbw) : COPY_GC(_mbw), _x, _y, ecalc, ecalc, PRIM(_mbw).shadow_thickness, TRUE); } static void toggleSpaceProc(Widget _mbw, Dimension *_width, Dimension *_height) { int ecalc = STR_HEIGHT(_mbw) - 2 * PRIM(_mbw).shadow_thickness; if (ecalc < 5) ecalc = 5; XOFFSET(_mbw) += ecalc + LABEL(_mbw).margin_width; *_width += ecalc + LABEL(_mbw).margin_width; } static void findGoodShowPos(Widget _mbw) { int topDiff, bottomDiff; if (MODE(_mbw) != XmMODE_TOGGLE_BUTTON) { FPOS(_mbw) = 0; return; } VIS_POS(_mbw) = 0; if (!HAS_ARROWS(_mbw) || (SET_POS(_mbw) == -1)) FPOS(_mbw) = 0; else { topDiff = SET_POS(_mbw) - VIS_COUNT(_mbw)/2; if (topDiff < 0) FPOS(_mbw) = 0; else { bottomDiff = (ICOUNT(_mbw)-1) - SET_POS(_mbw); if (bottomDiff < VIS_COUNT(_mbw)) FPOS(_mbw) = (ICOUNT(_mbw))-VIS_COUNT(_mbw); else FPOS(_mbw) = topDiff; } } } static void toLower(char *_str1, char *_str2, int _length) { int i; char *ptr; for(ptr=_str1,i=0;(ptr!=NULL) && (i<_length);ptr++,i++) *(_str2+i) = tolower(*ptr); } static Boolean cvtStringToMegaButtonMode(Display *_display, XrmValuePtr _args, Cardinal *_numArgs, XrmValuePtr _from, XrmValuePtr _to, XtPointer *_data) { char *lower; static unsigned char mode; Boolean badConversion = FALSE; if (*_numArgs != 0) { XtAppWarningMsg(XtDisplayToApplicationContext(_display), "cvtStringToMegaButtonMode", "wrongParamaters", "ResourceError", "cvtStringToMegaButtonMode needs no arguments.", (String *)NULL, (Cardinal *)NULL); } lower = XtNewString(_from->addr); toLower(_from->addr, lower, strlen(_from->addr)); mode = XmMODE_TOGGLE_BUTTON; if (!strncmp(lower, "mode_toggle_button", 18)) mode = XmMODE_TOGGLE_BUTTON; else if (!strncmp(lower, "mode_push_button", 16)) mode = XmMODE_PUSH_BUTTON; else if (!strncmp(lower, "toggle_button", 13)) mode = XmMODE_TOGGLE_BUTTON; else if (!strncmp(lower, "push_button", 11)) mode = XmMODE_PUSH_BUTTON; else badConversion = TRUE; XtFree(lower); if (badConversion) XtDisplayStringConversionWarning(_display, _from->addr, XmRMegaButtonMode); else { if (_to->addr == NULL) _to->addr = (XtPointer)&mode; else if (_to->size < sizeof(unsigned char)) badConversion = TRUE; else *(unsigned char *)_to->addr = mode; _to->size = sizeof(unsigned char); } return !badConversion; } void XmMegaButtonAddItem(Widget _w, XmString _item, int _pos, XtPointer _cbData) { XmMegaButtonWidget mbw; if (!XmIsMegaButton(_w)) return; mbw = (XmMegaButtonWidget)_w; if (FAKE_ITEM(mbw)) { ICOUNT(mbw)--; FAKE_ITEM(mbw) = FALSE; WIDTH(mbw) = 0; MAX_STRING_WIDTH(mbw) = 1; } if ((_pos < 0) || (_pos > (ICOUNT(mbw)))) _pos = ICOUNT(mbw); if (ICOUNT(mbw) == CUR_SIZE(mbw)) { CUR_SIZE(mbw) += CHUNK_SIZE(mbw); ITEMS(mbw) = (_XmString *)XtRealloc((char *)ITEMS(mbw), sizeof(_XmString) * CUR_SIZE(mbw)); DATA(mbw) = (XtPointer *)XtRealloc((char *)DATA(mbw), sizeof(XtPointer) * CUR_SIZE(mbw)); } bcopy(ITEMS(mbw)+_pos, ITEMS(mbw)+_pos+1, (ICOUNT(mbw)-_pos) * sizeof(_XmString)); bcopy(DATA(mbw)+_pos, DATA(mbw)+_pos+1, (ICOUNT(mbw)-_pos) * sizeof(XtPointer)); ITEMS(mbw)[_pos] = _XmStringCreate(_item); DATA(mbw)[_pos] = _cbData; ICOUNT(mbw)++; recheckSizesAtPos((Widget)mbw, _pos); } static void recheckSizesAtPos(Widget _mbw, int _pos) { ShellWidget popupShell; XtGeometryResult result; popupShell = (ShellWidget)XtGetShell((Widget)_mbw); if (popupShell && !popupShell->shell.popped_up) { Dimension width, height; Dimension replyWidth, replyHeight, oldWidth; width = WIDTH(_mbw); height = HEIGHT(_mbw); if (!HAS_ARROWS(_mbw)) { HAS_ARROWS(_mbw) = ICOUNT(_mbw) > VIS_COUNT(_mbw); if (!HAS_ARROWS(_mbw)) height = EL_HEIGHT(_mbw) * ICOUNT(_mbw); else height = EL_HEIGHT(_mbw) * (VIS_COUNT(_mbw) + 2) + 2 * MINI_SEP_HEIGHT; } LABEL(_mbw)._label = ITEMS(_mbw)[_pos]; _XmCalcLabelDimensions((Widget)_mbw); if (LABEL(_mbw).TextRect.width > MAX_STRING_WIDTH(_mbw)) { MAX_STRING_WIDTH(_mbw) = LABEL(_mbw).TextRect.width; MAX_STRING_POS(_mbw) = _pos; oldWidth = WIDTH(_mbw); WIDTH(_mbw) = 0; (*xmLabelWidgetClass->core_class.resize) ((Widget)_mbw); width = WIDTH(_mbw); WIDTH(_mbw) = oldWidth; /* YOFFSET(_mbw) = LABEL(_mbw).TextRect.y; */ XOFFSET(_mbw) = LABEL(_mbw).TextRect.x; if ( (MODE(_mbw) == XmMODE_TOGGLE_BUTTON) && ( ((XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleSpaceProc)) (( (XmMegaButtonWidgetClass)XtClass(_mbw))->mega_button_class.toggleSpaceProc) (_mbw, &width, &EL_HEIGHT(_mbw)); } if (height == 0) height = 2 * PRIM(_mbw).shadow_thickness; if (width == 0) width = 2 * PRIM(_mbw).shadow_thickness; while((result = XtMakeResizeRequest((Widget)_mbw, width, height, &replyWidth, &replyHeight)) == XtGeometryAlmost) { width = replyWidth; height = replyHeight; } } } XtPointer XmMegaButtonRemoveItem(Widget _w, int _pos) { XtPointer data; XmMegaButtonWidget mbw; mbw = (XmMegaButtonWidget)_w; if ((_pos < 0) || (_pos >= ICOUNT(mbw))) return NULL; _XmStringFree(ITEMS(mbw)[_pos]); data = DATA(mbw)[_pos]; ICOUNT(mbw)--; bcopy(ITEMS(mbw)+_pos+1, ITEMS(mbw)+_pos, (ICOUNT(mbw)-_pos) * sizeof(_XmString)); bcopy(DATA(mbw)+_pos+1, DATA(mbw)+_pos, (ICOUNT(mbw)-_pos) * sizeof(XtPointer)); if (ICOUNT(mbw) != 0) recheckSizesAtPos((Widget)mbw, 0); return data; } int XmMegaButtonItemCount(Widget _w, Boolean _forgetFake) { XmMegaButtonWidget mbw; mbw = (XmMegaButtonWidget)_w; if (_forgetFake && FAKE_ITEM(mbw)) return 0; else return (ICOUNT(mbw)); } int XmMegaButtonGetPos(Widget _w) { XmMegaButtonWidget mbw; mbw = (XmMegaButtonWidget)_w; if (MODE(mbw) == XmMODE_TOGGLE_BUTTON) return SET_POS(mbw); else return -1; } void XmMegaButtonSetPos(Widget _w, int _pos) { XmMegaButtonWidget mbw; mbw = (XmMegaButtonWidget)_w; if (MODE(mbw) == XmMODE_TOGGLE_BUTTON) { if (_pos > (ICOUNT(mbw)-1)) _pos = ICOUNT(mbw) - 1; SET_POS(mbw) = _pos; } } extern XmString XmMegaButtonGetXmStringAtPos(Widget _w, int _pos) { XmMegaButtonWidget mbw = (XmMegaButtonWidget)_w; if ((_pos >= 0) && (_pos < ICOUNT(mbw))) return _XmStringCreateExternal(LABEL(mbw).font, ITEMS(mbw)[_pos]); return (XmString)NULL; } extern void XmMegaButtonSetXmStringAtPos(Widget _w, XmString _xmstring, int _pos) { XmMegaButtonWidget mbw = (XmMegaButtonWidget)_w; if ((_pos >= 0) && (_pos < ICOUNT(mbw))) { _XmStringFree(ITEMS(mbw)[_pos]); ITEMS(mbw)[_pos] = _XmStringCreate(_xmstring); recheckSizesAtPos((Widget)mbw, _pos); } }