/*----------------------------------------------------------------------*/ static Dimension GetHeight(Widget w) { Dimension min_height; Dimension height; /* Compute the min possible height */ min_height = 2 * _XfeHighlightThickness(w) + 2 * _XfeShadowThickness(w); /* A reasonable preferred height is needed */ assert( _XfePreferredHeight(w) > 0 ); assert( _XfePreferredHeight(w) >= min_height ); /* Force the preferred height if needed */ if (_XfeUsePreferredHeight(w) || (_XfeHeight(w) == XfeDEFAULT_PREFERRED_HEIGHT) || (_XfeHeight(w) <= min_height)) { height = _XfePreferredHeight(w); } else { height = _XfeHeight(w); } return height; }
/*----------------------------------------------------------------------*/ static Position GetPointerY(Widget w) { Window root; Window child; int rx; int ry; int cx; int cy; unsigned int mask; if (XQueryPointer(XtDisplay(w),_XfeWindow(w),&root,&child, &rx,&ry,&cx,&cy,&mask)) { cy -= _XfeY(w); if (cy < 0) { cy = 0; } if (cy > _XfeHeight(w)) { cy = _XfeHeight(w); } return cy; } return 0; }
/*----------------------------------------------------------------------*/ static void LayoutTitle(Widget w) { XfeFancyBoxPart * fp = _XfeFancyBoxPart(w); XfeComboBoxPart * cp = _XfeComboBoxPart(w); int x; int total_icon_width = 0; if (_XfeIsAlive(fp->icon)) { x = _XfeX(fp->icon) + _XfeWidth(fp->icon); total_icon_width = _XfeWidth(fp->icon) + cp->spacing; } else { x = CB_OFFSET_LEFT(w,cp) + cp->title_shadow_thickness; } _XfeConfigureWidget(cp->title, x, (_XfeHeight(w) - _XfeHeight(cp->title)) / 2, CB_RECT_WIDTH(w,cp) - cp->spacing - _XfeWidth(cp->arrow) - total_icon_width - 2 * cp->title_shadow_thickness, CB_RECT_HEIGHT(w,cp) - 2 * cp->title_shadow_thickness); }
/*----------------------------------------------------------------------*/ /* extern */ Dimension XfeVaGetTallestWidget(Widget widget, ...) { va_list vargs; Widget current; Dimension height; Dimension widest_height; /* * Get the first widget's height * (because of the way var args works * we have to start the loop at the second widget) */ widest_height = _XfeHeight(widget); /* * Get the widest height */ va_start (vargs, widget); while ((current = va_arg (vargs, Widget))) { height = _XfeHeight(current); if (height > widest_height) { widest_height = height; } } va_end (vargs); return widest_height; }
/*----------------------------------------------------------------------*/ static void DrawHighlight(Widget w,XEvent * event,Region region,XRectangle * clip_rect) { XfeComboBoxPart * cp = _XfeComboBoxPart(w); /* Make sure the highlight is needed */ if (!cp->highlight_thickness || !_XfeIsRealized(w)) { return; } if (cp->highlighted) { _XmDrawSimpleHighlight(XtDisplay(w), _XfeWindow(w), _XfemHighlightGC(w), 0,0, _XfeWidth(w),_XfeHeight(w), cp->highlight_thickness); } else { assert( XmIsManager(_XfeParent(w)) ); _XmDrawSimpleHighlight(XtDisplay(w), _XfeWindow(w), _XfemBackgroundGC(_XfeParent(w)), 0,0, _XfeWidth(w),_XfeHeight(w), cp->highlight_thickness); } }
/*----------------------------------------------------------------------*/ /* extern */ Boolean XfeMenuIsFull(Widget menu) { Dimension screen_height; Widget last; assert( _XfeIsAlive(menu) ); assert( XmIsRowColumn(menu) ); screen_height = XfeScreenHeight(menu); last = XfeChildrenGetLast(menu); if (!last) { return False; } /* * The menu is "full" if its height plus that of a potential new child * are longer than the screen height. Assume the new child will be * the same height as the last child in the menu. */ if ((_XfeHeight(menu) + (3 * _XfeHeight(last))) > XfeScreenHeight(menu)) { return True; } return False; }
/*----------------------------------------------------------------------*/ static void AccentUpdate(Widget w,Position y) { unsigned char new_accent_type = XmACCENT_NONE; XfeBmButtonPart * bmp = _XfeBmButtonPart(w); Dimension half = _XfeHeight(w) / 2; /* Determine the new accent */ if ( (y <= half) && (y >= 0) ) { new_accent_type = XmACCENT_TOP; } else if ( (y > half) && (y <= _XfeHeight(w)) ) { new_accent_type = XmACCENT_BOTTOM; } /* Make sure the new accent has changed */ if (new_accent_type == bmp->accent_type) { return; } AccentErase(w); bmp->accent_type = new_accent_type; AccentDraw(w); }
/*----------------------------------------------------------------------*/ /* extern */ Dimension _XfeHeightCenter(Widget one,Widget two) { assert( one != NULL ); assert( _XfeIsAlive(one) ); assert( two != NULL ); assert( _XfeIsAlive(two) ); return (_XfeHeight(one) > _XfeHeight(two)) ? ((_XfeHeight(one) - _XfeHeight(two)) / 2) : 0; }
/*----------------------------------------------------------------------*/ static void AccentBottom(Widget w, GC top_gc, GC bottom_gc, Dimension offset_left, Dimension offset_right, Dimension shadow_thickness, Dimension accent_thickness, int code) { Widget pw = _XfeParent(w); int position_index = XfeMenuItemPositionIndex(w); Cardinal num_children = _XfemNumChildren(pw); Position x; Position y; Dimension width; Dimension height = 2 * shadow_thickness + accent_thickness; assert( code == ACCENT_DRAW || code == ACCENT_ERASE ); /* Last item */ if (position_index == (num_children - 1)) { x = _XfeX(w) + offset_left; y = _XfeY(w) + _XfeHeight(w) - height; width = _XfeWidth(w) - offset_left - offset_right; } /* Any other item */ else { x = _XfeX(w) + offset_left; y = _XfeY(w) + _XfeHeight(w) - height / 2; width = _XfeWidth(w) - offset_left - offset_right; } if (code == ACCENT_DRAW) { /* Draw accent */ _XmDrawShadows(XtDisplay(pw),_XfeWindow(pw),top_gc,bottom_gc, x,y,width,height,shadow_thickness,XmSHADOW_IN); } else { /* Erase accent */ XfeDrawRectangle(XtDisplay(pw),_XfeWindow(pw),top_gc, x,y,width,height,shadow_thickness); } }
/*----------------------------------------------------------------------*/ /* extern */ Widget XfeBiggestWidget(Boolean horizontal,WidgetList widgets,Cardinal n) { Dimension biggest_dim = 0; Dimension dim; Widget max_widget = NULL; Widget widget; Cardinal i; assert( widgets != NULL ); if (!widgets) { return NULL; } for (i = 0; i < n; i++) { widget = widgets[i]; assert( _XfeIsAlive(widget) ); dim = (horizontal ? _XfeWidth(widget) : _XfeHeight(widget)); if (dim > biggest_dim) { biggest_dim = dim; max_widget = widget; } } return max_widget; }
/*----------------------------------------------------------------------*/ /* extern */ void _XfeConfigureOrHideWidget(Widget w,int x,int y,int width,int height) { assert( _XfeIsAlive(w) ); /* Make sure the widget is alive */ if (!_XfeIsAlive(w)) { return; } /* Make sure the positions and dimensions are different */ if ((_XfeX(w) == x) && (_XfeY(w) == y) && (_XfeWidth(w) == width) && (_XfeHeight(w) == height)) { return; } /* Hide the widget if its dimensions are less thanb zero */ if (!width || !height) { _XfeSetMappedWhenManaged(w,False); return; } _XfeConfigureWidget(w,x,y,width,height); /* Show the widget */ _XfeSetMappedWhenManaged(w,True); }
/*----------------------------------------------------------------------*/ /* extern */ void _XfeResizeWidget(Widget w,int width,int height) { assert( _XfeIsAlive(w) ); #if 0 printf("_XfeResizeWidget(%s,%d,%d)\n",XtName(w),width,height); #endif #if 0 assert( width > 0 ); assert( height > 0 ); #endif /* Ignore this request if width or height are 0 */ if (!width || !height) { return; } /* Make sure the dimension are different */ if ((_XfeWidth(w) == width) && (_XfeHeight(w) == height)) { return; } _XfeConfigureWidget(w,_XfeX(w),_XfeY(w),width,height); }
/*----------------------------------------------------------------------*/ /* extern */ void XfeDrawShadowsAroundWidget(Widget parent, Widget child, GC top_gc, GC bottom_gc, Dimension offset, Dimension shadow_thickness, unsigned char shadow_type) { assert( _XfeIsAlive(parent) ); assert( _XfeIsAlive(child) ); assert( shadow_thickness > 0 ); assert( XmIsManager(parent) ); _XmDrawShadows(XtDisplay(parent), _XfeWindow(parent), _XfemTopShadowGC(parent), _XfemBottomShadowGC(parent), _XfeX(child) - shadow_thickness - offset, _XfeY(child) - shadow_thickness - offset, _XfeWidth(child) + 2 * shadow_thickness + 2 * offset, _XfeHeight(child) + 2 * shadow_thickness + 2 * offset, shadow_thickness, shadow_type); }
/*----------------------------------------------------------------------*/ static XtGeometryResult QueryGeometry(Widget w,XtWidgetGeometry *req,XtWidgetGeometry *reply) { assert( req != NULL ); assert( reply != NULL ); reply->request_mode = CWWidth | CWHeight; /* Set the reply dimensions */ reply->width = GetWidth(w); reply->height = GetHeight(w); /* XtGeometryYes: Request matches Prefered Geometry. */ if (((req->request_mode & CWWidth) && (req->width == reply->width)) && ((req->request_mode & CWHeight) && (req->height == reply->height))) { return XtGeometryYes; } /* XtGeometryNo: Reply matches current Geometry. */ if ((reply->width == _XfeWidth(w)) && (reply->height == _XfeHeight(w))) { return XtGeometryNo; } /* XtGeometryAlmost: One of reply fields doesn't match cur/req Geometry. */ return XtGeometryAlmost; }
/*----------------------------------------------------------------------*/ static void LayoutArrow(Widget w) { XfeComboBoxPart * cp = _XfeComboBoxPart(w); _XfeConfigureWidget(cp->arrow, _XfeWidth(w) - CB_OFFSET_RIGHT(w,cp) - _XfeWidth(cp->arrow), (_XfeHeight(w) - _XfeHeight(cp->arrow)) / 2, _XfeWidth(cp->arrow), _XfeHeight(cp->arrow)); }
/*----------------------------------------------------------------------*/ static void PreferredGeometry(Widget w,Dimension * width,Dimension * height) { XfeComboBoxPart * cp = _XfeComboBoxPart(w); *height = CB_OFFSET_TOP(w,cp) + CB_OFFSET_BOTTOM(w,cp) + XfeMax(_XfeHeight(cp->title),_XfeHeight(cp->arrow)) + 2 * cp->title_shadow_thickness; *width = CB_OFFSET_LEFT(w,cp) + CB_OFFSET_RIGHT(w,cp) + _XfeWidth(cp->title) + cp->spacing + _XfeWidth(cp->arrow) + 2 * cp->title_shadow_thickness; }
/*----------------------------------------------------------------------*/ /* extern */ Dimension XfeHeight(Widget w) { assert( w != NULL ); #if DEBUG_DIMENSIONS { Dimension height; XtVaGetValues(w,XmNheight,&height,NULL); assert( height == _XfeHeight(w) ); } #endif return _XfeHeight(w); }
/*----------------------------------------------------------------------*/ static void ActionPopup(Widget item,XEvent * event,char ** params,Cardinal * nparams) { Widget w = XfeIsComboBox(item) ? item : _XfeParent(item); XfeComboBoxPart * cp = _XfeComboBoxPart(w); int space_below = ScreenGetSpaceBelow(w); int space_above = ScreenGetSpaceAbove(w); #if 1 printf("ActionPopup(%s,above = %d,below = %d)\n", XtName(w), space_above, space_below); #endif /* Check if we are already popped up */ if (cp->popped_up) { printf("already popped up\n"); StickRemoveTimeout(w); ListUnmanage(w); XtVaSetValues(cp->arrow,XmNarmed,False,NULL); return; } space_below = 200; _XfeConfigureWidget(cp->shell, XfeRootX(w), XfeRootY(w) + _XfeHeight(w), _XfeWidth(w), space_below); /* XtVaSetValues(cp->list, */ /* XmNlistMarginWidth, 100, */ /* NULL); */ /* XtVaSetValues(cp->arrow,XmCArmed,True,NULL); */ /* XtPopup(cp->shell,XtGrabNone); */ /* XMapRaised(XtDisplay(w),_XfeWindow(cp->shell)); */ /* XMapRaised(XtDisplay(w),_XfeWindow(cp->shell)); */ cp->remain_popped_up = False; #if 1 StickAddTimeout(w); #endif XtVaSetValues(cp->arrow,XmNarmed,True,NULL); ListManage(w); }
/*----------------------------------------------------------------------*/ static void DrawPixmap(Widget w,XEvent *event,Region region) { XfeBmCascadePart * bmc = _XfeBmCascadePart(w); XmLabelPart * lp = _XfeXmLabelPart(w); Pixmap pixmap = XmUNSPECIFIED_PIXMAP; Pixmap mask = XmUNSPECIFIED_PIXMAP; Boolean armed = CB_IsArmed(w); if (armed && _XfePixmapGood(bmc->arm_pixmap)) { pixmap = bmc->arm_pixmap; if (_XfePixmapGood(bmc->arm_pixmap_mask)) { mask = bmc->arm_pixmap_mask; } } else if (_XfePixmapGood(lp->pixmap) && bmc->pixmap_width && bmc->pixmap_height) { pixmap = lp->pixmap; if (_XfePixmapGood(bmc->label_pixmap_mask)) { mask = bmc->label_pixmap_mask; } } if (_XfePixmapGood(pixmap)) { Position x = _XfePrimitiveOffset(w) + lp->margin_width; Position y = (_XfeHeight(w) - bmc->pixmap_height) / 2; if (_XfePixmapGood(mask)) { XSetClipOrigin(XtDisplay(w),bmc->pixmap_GC,x,y); XSetClipMask(XtDisplay(w),bmc->pixmap_GC,mask); } else { XSetClipMask(XtDisplay(w),bmc->pixmap_GC,None); } XCopyArea(XtDisplay(w), pixmap, _XfeWindow(w), bmc->pixmap_GC, 0,0, bmc->pixmap_width, bmc->pixmap_height, x, y); } }
/*----------------------------------------------------------------------*/ static void LayoutTitle(Widget w) { XfeComboBoxPart * cp = _XfeComboBoxPart(w); _XfeConfigureWidget(cp->title, CB_OFFSET_LEFT(w,cp) + cp->title_shadow_thickness, (_XfeHeight(w) - _XfeHeight(cp->title)) / 2, CB_RECT_WIDTH(w,cp) - cp->spacing - _XfeWidth(cp->arrow) - 2 * cp->title_shadow_thickness, CB_RECT_HEIGHT(w,cp) - 2 * cp->title_shadow_thickness); }
/*----------------------------------------------------------------------*/ static void AccentUpdate(Widget w,Position y) { unsigned char new_accent_type = XmACCENT_NONE; XfeBmCascadePart * bmc = _XfeBmCascadePart(w); Dimension one_fourth = _XfeHeight(w) / 4; /* Determine the new accent */ if (XfeBmAccentGetFileMode() == XmACCENT_FILE_ANYWHERE) { if ( (y <= one_fourth) && (y >= 0) ) { new_accent_type = XmACCENT_TOP; } else if ( (y > (_XfeHeight(w) - one_fourth)) && (y <= _XfeHeight(w)) ) { new_accent_type = XmACCENT_BOTTOM; } else if ( (y > one_fourth) && (y <= (_XfeHeight(w) - one_fourth))) { new_accent_type = XmACCENT_ALL; } } else { if ( (y >= 0) && (y <= _XfeHeight(w)) ) { new_accent_type = XmACCENT_ALL; } } /* Make sure the new accent has changed */ if (new_accent_type == bmc->accent_type) { return; } AccentErase(w); bmc->accent_type = new_accent_type; AccentDraw(w); }
/*----------------------------------------------------------------------*/ /* extern */ void _XfePreferredGeometry(Widget w,Dimension *width_out,Dimension *height_out) { Dimension width; Dimension height; assert( _XfeIsAlive(w) ); if (XfeIsPrimitive(w)) { width = _XfePreferredWidth(w); height = _XfePreferredHeight(w); } else if (XfeIsManager(w)) { width = _XfemPreferredWidth(w); height = _XfemPreferredHeight(w); } else { XtWidgetGeometry reply; XtQueryGeometry(w,NULL,&reply); if (reply.request_mode & CWWidth) { width = reply.width; } else { width = _XfeWidth(w); } if (reply.request_mode & CWHeight) { height = reply.height; } else { height = _XfeHeight(w); } } if (width_out) { *width_out = width; } if (height_out) { *height_out = height; } }
/*----------------------------------------------------------------------*/ void _XfePrimitiveDrawBuffer(Widget w,XEvent * event,Region region) { XCopyArea(XtDisplay(w), _XfePrimitiveDrawable(w), _XfeWindow(w), _XfeBackgroundGC(w), _XfeHighlightThickness(w),_XfeHighlightThickness(w), _XfeWidth(w) - 2 * _XfeHighlightThickness(w), _XfeHeight(w) - 2 * _XfeHighlightThickness(w), _XfeHighlightThickness(w),_XfeHighlightThickness(w)); }
/*----------------------------------------------------------------------*/ static void BufferAllocate(Widget w) { assert( _XfeBufferType(w) != XmBUFFER_NONE ); switch(_XfeBufferType(w)) { /* Single buffer: allocate a buffer big enough for widget */ case XmBUFFER_PRIVATE: _XfeBufferPixmap(w) = XCreatePixmap(XtDisplay(w), DefaultRootWindow(XtDisplay(w)), _XfeWidth(w), _XfeHeight(w), _XfeDepth(w)); #if 0 printf("%s: Allocating a private buffer at (%d,%d)\n", XtName(w), _XfeWidth(w),_XfeHeight(w)); #endif break; /* Multiple buffer: ask the buffer manager for a buffer */ case XmBUFFER_SHARED: #if 0 printf("%s: Allocating a shared buffer at (%d,%d)\n", XtName(w), _XfeWidth(w),_XfeHeight(w)); #endif _XfeBufferPixmap(w) = _XfePixmapBufferAllocate(w); break; } }
/*----------------------------------------------------------------------*/ static void DrawShadow(Widget w,XEvent * event,Region region,XRectangle * clip_rect) { /* Draw the shadow */ _XmDrawShadows(XtDisplay(w), _XfePrimitiveDrawable(w), _XfeTopShadowGC(w),_XfeBottomShadowGC(w), _XfeHighlightThickness(w), _XfeHighlightThickness(w), _XfeWidth(w) - 2 * _XfeHighlightThickness(w), _XfeHeight(w) - 2 * _XfeHighlightThickness(w), _XfeShadowThickness(w), _XfeShadowType(w)); }
/*----------------------------------------------------------------------*/ void _XfePrimitiveClearBackground(Widget w) { /* Clear the widget background including margins */ if (_XfeBufferType(w) == XmBUFFER_NONE) { XClearArea(XtDisplay(w),_XfeWindow(w), _XfeHighlightThickness(w),_XfeHighlightThickness(w), _XfeWidth(w) - 2 * _XfeHighlightThickness(w), _XfeHeight(w) - 2 * _XfeHighlightThickness(w), False); /*XClearWindow(XtDisplay(w),_XfeWindow(w));*/ } else { XFillRectangle(XtDisplay(w), _XfePrimitiveDrawable(w), _XfeBackgroundGC(w), 0,0, _XfeWidth(w),_XfeHeight(w)); } }
/*----------------------------------------------------------------------*/ static void IconLayout(Widget w) { XfeFancyBoxPart * fp = _XfeFancyBoxPart(w); XfeComboBoxPart * cp = _XfeComboBoxPart(w); if (!_XfeIsAlive(fp->icon)) { return; } _XfeConfigureWidget(fp->icon, CB_OFFSET_LEFT(w,cp) + cp->title_shadow_thickness + cp->spacing, (_XfeHeight(w) - _XfeHeight(fp->icon)) / 2, _XfeWidth(fp->icon), _XfeHeight(fp->icon)); }
/*----------------------------------------------------------------------*/ static void UpdateRect(Widget w) { /* Assign the rect coordinates */ XfeRectSet(&_XfeWidgetRect(w), _XfeOffsetLeft(w), _XfeOffsetTop(w), _XfeWidth(w) - _XfeOffsetLeft(w) - _XfeOffsetRight(w), _XfeHeight(w) - _XfeOffsetTop(w) - _XfeOffsetBottom(w)); }
/*----------------------------------------------------------------------*/ static void DrawBackground(Widget w,XEvent *event,Region region,XRectangle * clip_rect) { XfeArrowPart * ap = _XfeArrowPart(w); XfeButtonPart * bp = _XfeButtonPart(w); if (bp->emulate_motif) { return; } #if 0 (*xfeButtonClassRec.xfe_primitive_class.draw_background)(w, event, region, clip_rect); #else /* Fill the background if needed */ if (bp->fill_on_arm && bp->armed) { XFillRectangle(XtDisplay(w), _XfePrimitiveDrawable(w), bp->armed_GC, 0,0, _XfeWidth(w),_XfeHeight(w)); } else if (bp->fill_on_enter && (bp->raised || _XfePointerInside(w))) { XFillRectangle(XtDisplay(w), _XfePrimitiveDrawable(w), bp->label_raised_GC, 0,0, _XfeWidth(w),_XfeHeight(w)); } #endif }
/*----------------------------------------------------------------------*/ static void DrawTitleShadow(Widget w,XEvent * event,Region region,XRectangle * clip_rect) { XfeFancyBoxPart * fp = _XfeFancyBoxPart(w); XfeComboBoxPart * cp = _XfeComboBoxPart(w); /* Make sure the shadow is needed */ if (!cp->title_shadow_thickness) { return; } if (_XfeIsAlive(fp->icon)) { Dimension icon_x1 = _XfeX(fp->icon) - cp->spacing; Dimension title_x2 = _XfeX(cp->title) + _XfeWidth(cp->title); /* Draw the shadow around the icon and text */ _XmDrawShadows(XtDisplay(w), _XfeWindow(w), _XfemTopShadowGC(w),_XfemBottomShadowGC(w), CB_OFFSET_LEFT(w,cp), _XfeY(cp->title) - cp->title_shadow_thickness, (title_x2 - icon_x1) + 2 * cp->title_shadow_thickness, _XfeHeight(cp->title) + 2 * cp->title_shadow_thickness, cp->title_shadow_thickness, cp->title_shadow_type); } else { /* Draw the shadow around the text only */ XfeDrawShadowsAroundWidget(w, cp->title, _XfemTopShadowGC(w), _XfemBottomShadowGC(w), 0, cp->title_shadow_thickness, cp->title_shadow_type); } }