#include "tkButton.h"
typedef
struct
UnixButton {
TkButton info;
} UnixButton;
Tk_ClassProcs tkpButtonProcs = {
sizeof
(Tk_ClassProcs),
TkButtonWorldChanged,
};
TkButton *
TkpCreateButton(tkwin)
Tk_Window tkwin;
{
UnixButton *butPtr = (UnixButton *)ckalloc(
sizeof
(UnixButton));
return
(TkButton *) butPtr;
}
void
TkpDisplayButton(clientData)
ClientData clientData;
{
register
TkButton *butPtr = (TkButton *) clientData;
GC gc;
Tk_3DBorder border;
Pixmap pixmap;
int
x = 0;
int
y, relief;
Tk_Window tkwin = butPtr->tkwin;
int
width, height, fullWidth, fullHeight;
int
textXOffset, textYOffset;
int
haveImage = 0, haveText = 0;
int
offset;
int
imageWidth, imageHeight;
int
imageXOffset = 0, imageYOffset = 0;
butPtr->flags &= ~REDRAW_PENDING;
if
((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return
;
}
border = butPtr->normalBorder;
if
((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
gc = butPtr->disabledGC;
}
else
if
((butPtr->state == STATE_ACTIVE)
&& !Tk_StrictMotif(butPtr->tkwin)) {
gc = butPtr->activeTextGC;
border = butPtr->activeBorder;
}
else
{
gc = butPtr->normalTextGC;
}
if
((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE)
&& (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {
border = butPtr->selectBorder;
}
relief = butPtr->relief;
if
((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {
if
(butPtr->flags & SELECTED) {
relief = TK_RELIEF_SUNKEN;
}
else
if
(butPtr->overRelief != relief) {
relief = butPtr->offRelief;
}
}
offset = (butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin);
pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),
Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),
Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
if
(butPtr->image != NULL) {
Tk_SizeOfImage(butPtr->image, &width, &height);
haveImage = 1;
}
else
if
(butPtr->bitmap != None) {
Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
haveImage = 1;
}
imageWidth = width;
imageHeight = height;
haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
if
(butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
textXOffset = 0;
textYOffset = 0;
fullWidth = 0;
fullHeight = 0;
switch
((
enum
compound) butPtr->compound) {
case
COMPOUND_TOP:
case
COMPOUND_BOTTOM: {
if
(butPtr->compound == COMPOUND_TOP) {
textYOffset = height + butPtr->padY;
}
else
{
imageYOffset = butPtr->textHeight + butPtr->padY;
}
fullHeight = height + butPtr->textHeight + butPtr->padY;
fullWidth = (width > butPtr->textWidth ? width :
butPtr->textWidth);
textXOffset = (fullWidth - butPtr->textWidth)/2;
imageXOffset = (fullWidth - width)/2;
break
;
}
case
COMPOUND_LEFT:
case
COMPOUND_RIGHT: {
if
(butPtr->compound == COMPOUND_LEFT) {
textXOffset = width + butPtr->padX;
}
else
{
imageXOffset = butPtr->textWidth + butPtr->padX;
}
fullWidth = butPtr->textWidth + butPtr->padX + width;
fullHeight = (height > butPtr->textHeight ? height :
butPtr->textHeight);
textYOffset = (fullHeight - butPtr->textHeight)/2;
imageYOffset = (fullHeight - height)/2;
break
;
}
case
COMPOUND_CENTER: {
fullWidth = (width > butPtr->textWidth ? width :
butPtr->textWidth);
fullHeight = (height > butPtr->textHeight ? height :
butPtr->textHeight);
textXOffset = (fullWidth - butPtr->textWidth)/2;
imageXOffset = (fullWidth - width)/2;
textYOffset = (fullHeight - butPtr->textHeight)/2;
imageYOffset = (fullHeight - height)/2;
break
;
}
case
COMPOUND_NONE: {
break
;}
}
TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
butPtr->indicatorSpace + fullWidth, fullHeight, &x, &y);
x += butPtr->indicatorSpace;
x += offset;
y += offset;
if
(relief == TK_RELIEF_RAISED) {
x -= offset;
y -= offset;
}
else
if
(relief == TK_RELIEF_SUNKEN) {
x += offset;
y += offset;
}
imageXOffset += x;
imageYOffset += y;
if
(butPtr->image != NULL) {
if
((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {
Tk_RedrawImage(butPtr->selectImage, 0, 0,
width, height, pixmap, imageXOffset, imageYOffset);
}
else
{
Tk_RedrawImage(butPtr->image, 0, 0, width,
height, pixmap, imageXOffset, imageYOffset);
}
}
else
{
XSetClipOrigin(butPtr->display, gc, imageXOffset, imageYOffset);
XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc,
0, 0, (unsigned
int
) width, (unsigned
int
) height,
imageXOffset, imageYOffset, 1);
XSetClipOrigin(butPtr->display, gc, 0, 0);
}
Tk_DrawTextLayout(butPtr->display, pixmap, gc,
butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1);
Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,
butPtr->textLayout, x + textXOffset, y + textYOffset,
butPtr->underline);
y += fullHeight/2;
}
else
{
if
(haveImage) {
TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,
butPtr->indicatorSpace + width, height, &x, &y);
x += butPtr->indicatorSpace;
x += offset;
y += offset;
if
(relief == TK_RELIEF_RAISED) {
x -= offset;
y -= offset;
}
else
if
(relief == TK_RELIEF_SUNKEN) {
x += offset;
y += offset;
}
imageXOffset += x;
imageXOffset += y;
if
(butPtr->image != NULL) {
if
((butPtr->selectImage != NULL) &&
(butPtr->flags & SELECTED)) {
Tk_RedrawImage(butPtr->selectImage, 0, 0, width,
height, pixmap, x, y);
}
else
{
Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,
x, y);
}
}
else
{
XSetClipOrigin(butPtr->display, gc, x, y);
XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,
(unsigned
int
) width, (unsigned
int
) height, x, y, 1);
XSetClipOrigin(butPtr->display, gc, 0, 0);
}
y += height/2;
}
else
{
TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
butPtr->indicatorSpace + butPtr->textWidth,
butPtr->textHeight, &x, &y);
x += butPtr->indicatorSpace;
x += offset;
y += offset;
if
(relief == TK_RELIEF_RAISED) {
x -= offset;
y -= offset;
}
else
if
(relief == TK_RELIEF_SUNKEN) {
x += offset;
y += offset;
}
Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,
x, y, 0, -1);
Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,
butPtr->textLayout, x, y, butPtr->underline);
y += butPtr->textHeight/2;
}
}
if
((butPtr->type == TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
int
dim;
dim = butPtr->indicatorDiameter;
x -= butPtr->indicatorSpace;
y -= dim/2;
if
(dim > 2*butPtr->borderWidth) {
Tk_Draw3DRectangle(tkwin, pixmap, border, x, y, dim, dim,
butPtr->borderWidth,
(butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN :
TK_RELIEF_RAISED);
x += butPtr->borderWidth;
y += butPtr->borderWidth;
dim -= 2*butPtr->borderWidth;
if
(butPtr->flags & SELECTED) {
GC gc;
if
(butPtr->state != STATE_DISABLED) {
if
(butPtr->selectBorder != NULL) {
gc = Tk_3DBorderGC(tkwin, butPtr->selectBorder,
TK_3D_FLAT_GC);
}
else
{
gc = Tk_3DBorderGC(tkwin, butPtr->normalBorder,
TK_3D_FLAT_GC);
}
}
else
{
if
(butPtr->disabledFg != NULL) {
gc = butPtr->disabledGC;
}
else
{
gc = butPtr->normalTextGC;
XSetForeground(butPtr->display, butPtr->disabledGC,
Tk_3DBorderColor(butPtr->normalBorder)->pixel);
}
}
XFillRectangle(butPtr->display, pixmap, gc, x, y,
(unsigned
int
) dim, (unsigned
int
) dim);
}
else
{
Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, x, y,
dim, dim, butPtr->borderWidth, TK_RELIEF_FLAT);
}
}
}
else
if
((butPtr->type == TYPE_RADIO_BUTTON) && butPtr->indicatorOn) {
XPoint points[4];
int
radius;
radius = butPtr->indicatorDiameter/2;
points[0].x = x - butPtr->indicatorSpace;
points[0].y = y;
points[1].x = points[0].x + radius;
points[1].y = points[0].y + radius;
points[2].x = points[1].x + radius;
points[2].y = points[0].y;
points[3].x = points[1].x;
points[3].y = points[0].y - radius;
if
(butPtr->flags & SELECTED) {
GC gc;
if
(butPtr->state != STATE_DISABLED) {
if
(butPtr->selectBorder != NULL) {
gc = Tk_3DBorderGC(tkwin, butPtr->selectBorder,
TK_3D_FLAT_GC);
}
else
{
gc = Tk_3DBorderGC(tkwin, butPtr->normalBorder,
TK_3D_FLAT_GC);
}
}
else
{
if
(butPtr->disabledFg != NULL) {
gc = butPtr->disabledGC;
}
else
{
gc = butPtr->normalTextGC;
XSetForeground(butPtr->display, butPtr->disabledGC,
Tk_3DBorderColor(butPtr->normalBorder)->pixel);
}
}
XFillPolygon(butPtr->display, pixmap, gc, points, 4, Convex,
CoordModeOrigin);
}
else
{
Tk_Fill3DPolygon(tkwin, pixmap, butPtr->normalBorder, points,
4, butPtr->borderWidth, TK_RELIEF_FLAT);
}
Tk_Draw3DPolygon(tkwin, pixmap, border, points, 4, butPtr->borderWidth,
(butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN :
TK_RELIEF_RAISED);
}
if
((butPtr->state == STATE_DISABLED)
&& ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {
if
((butPtr->flags & SELECTED) && !butPtr->indicatorOn
&& (butPtr->selectBorder != NULL)) {
XSetForeground(butPtr->display, butPtr->stippleGC,
Tk_3DBorderColor(butPtr->selectBorder)->pixel);
}
if
(butPtr->disabledFg == NULL) {
XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0,
(unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin));
}
else
{
XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC,
imageXOffset, imageYOffset,
(unsigned) imageWidth, (unsigned) imageHeight);
}
if
((butPtr->flags & SELECTED) && !butPtr->indicatorOn
&& (butPtr->selectBorder != NULL)) {
XSetForeground(butPtr->display, butPtr->stippleGC,
Tk_3DBorderColor(butPtr->normalBorder)->pixel);
}
}
if
(relief != TK_RELIEF_FLAT) {
int
inset = butPtr->highlightWidth;
if
(butPtr->defaultState == DEFAULT_ACTIVE) {
Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,
inset, Tk_Width(tkwin) - 2*inset,
Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT);
inset += 2;
Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,
inset, Tk_Width(tkwin) - 2*inset,
Tk_Height(tkwin) - 2*inset, 1, TK_RELIEF_SUNKEN);
inset++;
Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,
inset, Tk_Width(tkwin) - 2*inset,
Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT);
inset += 2;
}
else
if
(butPtr->defaultState == DEFAULT_NORMAL) {
Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0,
0, Tk_Width(tkwin), Tk_Height(tkwin), 5, TK_RELIEF_FLAT);
inset += 5;
}
Tk_Draw3DRectangle(tkwin, pixmap, border, inset, inset,
Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
butPtr->borderWidth, relief);
}
if
(butPtr->highlightWidth > 0) {
GC gc;
if
(butPtr->flags & GOT_FOCUS) {
gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
}
else
{
gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder),
pixmap);
}
if
(butPtr->defaultState == DEFAULT_NORMAL) {
TkDrawInsetFocusHighlight(tkwin, gc, butPtr->highlightWidth,
pixmap, 5);
}
else
{
Tk_DrawFocusHighlight(tkwin, gc, butPtr->highlightWidth, pixmap);
}
}
XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),
butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),
(unsigned) Tk_Height(tkwin), 0, 0);
Tk_FreePixmap(butPtr->display, pixmap);
}
void
TkpComputeButtonGeometry(butPtr)
register
TkButton *butPtr;
{
int
width, height, avgWidth, txtWidth, txtHeight;
int
haveImage = 0, haveText = 0;
Tk_FontMetrics fm;
butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth;
if
(butPtr->defaultState != DEFAULT_DISABLED) {
butPtr->inset += 5;
}
butPtr->indicatorSpace = 0;
width = 0;
height = 0;
txtWidth = 0;
txtHeight = 0;
avgWidth = 0;
if
(butPtr->image != NULL) {
Tk_SizeOfImage(butPtr->image, &width, &height);
haveImage = 1;
}
else
if
(butPtr->bitmap != None) {
Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
haveImage = 1;
}
if
(haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
Tk_FreeTextLayout(butPtr->textLayout);
butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
txtWidth = butPtr->textWidth;
txtHeight = butPtr->textHeight;
avgWidth = Tk_TextWidth(butPtr->tkfont,
"0"
, 1);
Tk_GetFontMetrics(butPtr->tkfont, &fm);
haveText = (txtWidth != 0 && txtHeight != 0);
}
if
(butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
switch
((
enum
compound) butPtr->compound) {
case
COMPOUND_TOP:
case
COMPOUND_BOTTOM: {
height += txtHeight + butPtr->padY;
width = (width > txtWidth ? width : txtWidth);
break
;
}
case
COMPOUND_LEFT:
case
COMPOUND_RIGHT: {
width += txtWidth + butPtr->padX;
height = (height > txtHeight ? height : txtHeight);
break
;
}
case
COMPOUND_CENTER: {
width = (width > txtWidth ? width : txtWidth);
height = (height > txtHeight ? height : txtHeight);
break
;
}
case
COMPOUND_NONE: {
break
;}
}
if
(butPtr->width > 0) {
width = butPtr->width;
}
if
(butPtr->height > 0) {
height = butPtr->height;
}
if
((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
butPtr->indicatorSpace = height;
if
(butPtr->type == TYPE_CHECK_BUTTON) {
butPtr->indicatorDiameter = (65*height)/100;
}
else
{
butPtr->indicatorDiameter = (75*height)/100;
}
}
width += 2*butPtr->padX;
height += 2*butPtr->padY;
}
else
{
if
(haveImage) {
if
(butPtr->width > 0) {
width = butPtr->width;
}
if
(butPtr->height > 0) {
height = butPtr->height;
}
if
((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
butPtr->indicatorSpace = height;
if
(butPtr->type == TYPE_CHECK_BUTTON) {
butPtr->indicatorDiameter = (65*height)/100;
}
else
{
butPtr->indicatorDiameter = (75*height)/100;
}
}
}
else
{
width = txtWidth;
height = txtHeight;
if
(butPtr->width > 0) {
width = butPtr->width * avgWidth;
}
if
(butPtr->height > 0) {
height = butPtr->height * fm.linespace;
}
if
((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
butPtr->indicatorDiameter = fm.linespace;
if
(butPtr->type == TYPE_CHECK_BUTTON) {
butPtr->indicatorDiameter =
(80*butPtr->indicatorDiameter)/100;
}
butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;
}
}
}
if
((butPtr->image == NULL) && (butPtr->bitmap == None)) {
width += 2*butPtr->padX;
height += 2*butPtr->padY;
}
if
((butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin)) {
width += 2;
height += 2;
}
Tk_GeometryRequest(butPtr->tkwin, (
int
) (width + butPtr->indicatorSpace
+ 2*butPtr->inset), (
int
) (height + 2*butPtr->inset));
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}