Exemple #1
0
TkCursor *
TkCreateCursorFromData(
    Tk_Window tkwin,		/* Window in which cursor will be used. */
    const char *source,		/* Bitmap data for cursor shape. */
    const char *mask,		/* Bitmap data for cursor mask. */
    int width, int height,	/* Dimensions of cursor. */
    int xHot, int yHot,		/* Location of hot-spot in cursor. */
    XColor fgColor,		/* Foreground color for cursor. */
    XColor bgColor)		/* Background color for cursor. */
{
    Cursor cursor;
    Pixmap sourcePixmap, maskPixmap;
    TkUnixCursor *cursorPtr = NULL;
    Display *display = Tk_Display(tkwin);

    sourcePixmap = XCreateBitmapFromData(display,
	    RootWindowOfScreen(Tk_Screen(tkwin)), source, (unsigned) width,
	    (unsigned) height);
    maskPixmap = XCreateBitmapFromData(display,
	    RootWindowOfScreen(Tk_Screen(tkwin)), mask, (unsigned) width,
	    (unsigned) height);
    cursor = XCreatePixmapCursor(display, sourcePixmap,
	    maskPixmap, &fgColor, &bgColor, (unsigned) xHot, (unsigned) yHot);
    Tk_FreePixmap(display, sourcePixmap);
    Tk_FreePixmap(display, maskPixmap);

    if (cursor != None) {
	cursorPtr = ckalloc(sizeof(TkUnixCursor));
	cursorPtr->info.cursor = (Tk_Cursor) cursor;
	cursorPtr->display = display;
    }
    return (TkCursor *) cursorPtr;
}
Exemple #2
0
static void
FreeBitmap(
    TkBitmap *bitmapPtr)	/* Bitmap to be released. */
{
    TkBitmap *prevPtr;

    bitmapPtr->resourceRefCount--;
    if (bitmapPtr->resourceRefCount > 0) {
	return;
    }

    Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
    Tcl_DeleteHashEntry(bitmapPtr->idHashPtr);
    prevPtr = Tcl_GetHashValue(bitmapPtr->nameHashPtr);
    if (prevPtr == bitmapPtr) {
	if (bitmapPtr->nextPtr == NULL) {
	    Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr);
	} else {
	    Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr);
	}
    } else {
	while (prevPtr->nextPtr != bitmapPtr) {
	    prevPtr = prevPtr->nextPtr;
	}
	prevPtr->nextPtr = bitmapPtr->nextPtr;
    }
    if (bitmapPtr->objRefCount == 0) {
	ckfree(bitmapPtr);
    }
}
void trace_flash (DNATrace *t) {
    int x0, i;
    Display *d = t->display;
    Window w = Tk_WindowId(t->tkwin);
    Pixmap tmp;

    if (!Tk_IsMapped(t->tkwin) || Tk_WindowId(t->tkwin) == 0)
	return;

    x0 = point_to_pixel(t, trace_get_pos(t, t->cursor_pos));

    tmp = Tk_GetPixmap(d, w, 24, t->pos[TRACEP_T].h, Tk_Depth(t->tkwin));
    XCopyArea(d, w, tmp, t->CursorGC,
	      x0-12, t->pos[TRACEP_T].y, 24, t->pos[TRACEP_T].h, 0, 0);

    for (i=12; i > 0; i-=3) {
	XCopyArea(d, tmp, w, t->CursorGC,
		  0, 0, 24, t->pos[TRACEP_T].h, x0-12, t->pos[TRACEP_T].y);

	XFillRectangle(d, w,
		       t->CursorGC,
		       x0 - i, t->pos[TRACEP_T].y,
		       i, t->pos[TRACEP_T].h);

	XSync(d, False);

	myusleep(20000);
    }
    XCopyArea(d, tmp, w, t->CursorGC,
	      0, 0, 24, t->pos[TRACEP_T].h, x0-12, t->pos[TRACEP_T].y);


    Tk_FreePixmap(d, tmp);
}
Exemple #4
0
static void
ImgBmapFree(
    ClientData clientData,	/* Pointer to BitmapInstance structure for
				 * instance to be displayed. */
    Display *display)		/* Display containing window that used image. */
{
    BitmapInstance *instancePtr = clientData;
    BitmapInstance *prevPtr;

    instancePtr->refCount--;
    if (instancePtr->refCount > 0) {
	return;
    }

    /*
     * There are no more uses of the image within this widget. Free the
     * instance structure.
     */

    if (instancePtr->fg != NULL) {
	Tk_FreeColor(instancePtr->fg);
    }
    if (instancePtr->bg != NULL) {
	Tk_FreeColor(instancePtr->bg);
    }
    if (instancePtr->bitmap != None) {
	Tk_FreePixmap(display, instancePtr->bitmap);
    }
    if (instancePtr->mask != None) {
	Tk_FreePixmap(display, instancePtr->mask);
    }
    if (instancePtr->gc != None) {
	Tk_FreeGC(display, instancePtr->gc);
    }
    if (instancePtr->masterPtr->instancePtr == instancePtr) {
	instancePtr->masterPtr->instancePtr = instancePtr->nextPtr;
    } else {
	for (prevPtr = instancePtr->masterPtr->instancePtr;
		prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) {
	    /* Empty loop body */
	}
	prevPtr->nextPtr = instancePtr->nextPtr;
    }
    ckfree((char *) instancePtr);
}
Exemple #5
0
static void
DragImage_UpdateStylePixmap(
    TreeDragImage dragImage)	/* Drag image record. */
{
    TreeCtrl *tree = dragImage->tree;
    int w, h, state = 0;
    XColor *colorPtr;
    GC gc;
    StyleDrawArgs drawArgs;

    w = dragImage->styleW = TreeStyle_NeededWidth(tree, dragImage->instanceStyle, state);
    h = dragImage->styleH = TreeStyle_NeededHeight(tree, dragImage->instanceStyle, state);
    if (w > dragImage->pixmapW || h > dragImage->pixmapH)
    {

	if (dragImage->pixmap != None)
	    Tk_FreePixmap(tree->display, dragImage->pixmap);
	dragImage->pixmap = Tk_GetPixmap(tree->display,
	    Tk_WindowId(tree->tkwin),
	    w, h, Tk_Depth(tree->tkwin));

	dragImage->pixmapW = w;
	dragImage->pixmapH = h;
    }

    colorPtr = Tk_GetColor(tree->interp, tree->tkwin, "pink");
    gc = Tk_GCForColor(colorPtr, Tk_WindowId(tree->tkwin));
    XFillRectangle(tree->display, dragImage->pixmap, gc,
	0, 0, w, h);

    drawArgs.tree = tree;

    drawArgs.td.drawable = dragImage->pixmap;
    drawArgs.td.width = w; drawArgs.td.height = h;

    drawArgs.bounds[0] = drawArgs.bounds[1] = 0;
    drawArgs.bounds[2] = w; drawArgs.bounds[3] = h;

    drawArgs.state = state;
    drawArgs.style = dragImage->instanceStyle;

    drawArgs.indent = 0;

    drawArgs.x = drawArgs.y = 0;
    drawArgs.width = w; drawArgs.height = h;

    drawArgs.justify = TK_JUSTIFY_LEFT;

    TreeStyle_Draw(&drawArgs);

    if (dragImage->tkimage != NULL) {
	Tk_FreeImage(dragImage->tkimage);
	dragImage->tkimage = NULL;
    }
}
Exemple #6
0
static void
UpdatePixmap(
    TreeDragImage dragImage	/* Drag image record. */
    )
{
    TreeCtrl *tree = dragImage->tree;
    int w, h;
    XColor *colorPtr;
    GC gc;
    DragElem *elem;
    unsigned long trans;

    w = dragImage->bounds[2] - dragImage->bounds[0];
    h = dragImage->bounds[3] - dragImage->bounds[1];
    if (w > dragImage->pixmapW || h > dragImage->pixmapH)
    {

	if (dragImage->pixmap != None)
	    Tk_FreePixmap(tree->display, dragImage->pixmap);
	dragImage->pixmap = Tk_GetPixmap(tree->display,
	    Tk_WindowId(tree->tkwin),
	    w, h, Tk_Depth(tree->tkwin));

	dragImage->pixmapW = w;
	dragImage->pixmapH = h;
    }

    colorPtr = Tk_GetColor(tree->interp, tree->tkwin, "pink");
    gc = Tk_GCForColor(colorPtr, Tk_WindowId(tree->tkwin));
    XFillRectangle(tree->display, dragImage->pixmap, gc,
	0, 0, w, h);

    trans = colorPtr->pixel;

    colorPtr = Tk_GetColor(tree->interp, tree->tkwin, "gray50");
    gc = Tk_GCForColor(colorPtr, Tk_WindowId(tree->tkwin));

    for (elem = dragImage->elem; elem != NULL; elem = elem->next) {
	XFillRectangle(tree->display, dragImage->pixmap, gc,
	    elem->x - dragImage->bounds[0],
	    elem->y - dragImage->bounds[1],
	    elem->width, elem->height);
    }

    if (dragImage->image != NULL) {
	Tk_FreeImage(dragImage->image);
	dragImage->image = NULL;
    }
}
Exemple #7
0
/*
 *---------------------------------------------------------------------------
 *
 * imageChanged --
 *
 *     Image-changed callback.
 *
 * Results:
 *     None.
 *
 * Side effects:
 *     None.
 *
 *---------------------------------------------------------------------------
 */
static void 
imageChanged(
    ClientData clientData,
    int x,
    int y,
    int width,
    int height,
    int imgWidth,
    int imgHeight
    )
{
    HtmlImage2 *pImage = (HtmlImage2 *)clientData;
    if (pImage && !pImage->pUnscaled && !pImage->nIgnoreChange) {
        HtmlImage2 *p;
        HtmlTree *pTree = pImage->pImageServer->pTree;
        assert(pImage->image);

        for (p = pImage->pNext; p; p = p->pNext) {
            p->isValid = 0;
            assert(!p->pTileName);
        }
        freeTile(pImage);
        pImage->eAlpha = ALPHA_CHANNEL_UNKNOWN;

        /* Delete the pixmap/compressed-data representation */
        if( pImage->pixmap ){
            Tk_FreePixmap(Tk_Display(pTree->tkwin), pImage->pixmap);
            pImage->pixmap = 0;
        }
        freeImageCompressed(pImage);

        if (imgWidth!=pImage->width || imgHeight!=pImage->height) {
            pImage->width = imgWidth;
            pImage->height = imgHeight;
            HtmlWalkTree(pTree, 0, imageChangedCb, (ClientData)pImage);
        }

        Tcl_DoWhenIdle(asyncPixmapify, (ClientData)pImage);

        /* If the image contents have been modified but the size is
         * constant, then just redraw the display. This is lazy. If
         * there were an efficient way to determine the minimum region
         * to draw, then stuff like animated gifs would be much more
         * efficient.
         */
        HtmlCallbackDamage(pTree, 0, 0, 1000000, 1000000);
    }
}
Exemple #8
0
void
TreeDragImage_Free(
    TreeDragImage dragImage	/* Drag image token. */
    )
{
    DragElem *elem = dragImage->elem;

    while (elem != NULL)
	elem = DragElem_Free(dragImage, elem);
#ifdef DRAG_PIXMAP
    if (dragImage->image != NULL)
	Tk_FreeImage(dragImage->image);
    if (dragImage->pixmap != None)
	Tk_FreePixmap(dragImage->tree->display, dragImage->pixmap);
#endif /* DRAG_PIXMAP */
    Tk_FreeConfigOptions((char *) dragImage, dragImage->optionTable,
	dragImage->tree->tkwin);
    WFREE(dragImage, TreeDragImage_);
}
Exemple #9
0
static void 
freeTile (HtmlImage2 *pImage)
{
    HtmlTree *pTree = pImage->pImageServer->pTree;
    int flags = TCL_GLOBAL_ONLY;
    Tcl_Obj *pScript;
    if (pImage->pTileName) {
        pScript = Tcl_NewStringObj("image delete", -1);
        Tcl_IncrRefCount(pScript);
        Tcl_ListObjAppendElement(0, pScript, pImage->pTileName);
        Tcl_EvalObjEx(pTree->interp, pScript, flags);
        Tcl_DecrRefCount(pScript);
    
        Tcl_DecrRefCount(pImage->pTileName);
        pImage->tile = 0;
        pImage->pTileName = 0;
    }
    if (pImage->tilepixmap) {
        assert(pImage->pixmap);
        Tk_FreePixmap(
            Tk_Display(pImage->pImageServer->pTree->tkwin), pImage->tilepixmap);
        pImage->tilepixmap = 0;
    }
}
void
TkpDisplayMenuButton(
    ClientData clientData)	/* Information about widget. */
{
    register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
    GC gc;
    Tk_3DBorder border;
    Pixmap pixmap;
    int x = 0;			/* Initialization needed only to stop compiler
				 * warning. */
    int y = 0;
    register Tk_Window tkwin = mbPtr->tkwin;
    int fullWidth, fullHeight;
    int textXOffset, textYOffset;
    int imageWidth, imageHeight;
    int imageXOffset, imageYOffset;
    int width = 0, height = 0;
				/* Image information that will be used to
				 * restrict disabled pixmap as well */
    int haveImage = 0, haveText = 0;

    mbPtr->flags &= ~REDRAW_PENDING;
    if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
	return;
    }

    if ((mbPtr->state == STATE_DISABLED) && (mbPtr->disabledFg != NULL)) {
	gc = mbPtr->disabledGC;
	border = mbPtr->normalBorder;
    } else if ((mbPtr->state == STATE_ACTIVE)
	       && !Tk_StrictMotif(mbPtr->tkwin)) {
	gc = mbPtr->activeTextGC;
	border = mbPtr->activeBorder;
    } else {
	gc = mbPtr->normalTextGC;
	border = mbPtr->normalBorder;
    }

    if (mbPtr->image != None) {
	Tk_SizeOfImage(mbPtr->image, &width, &height);
	haveImage = 1;
    } else if (mbPtr->bitmap != None) {
	Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
	haveImage = 1;
    }
    imageWidth	= width;
    imageHeight = height;

    haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0);

    /*
     * In order to avoid screen flashes, this function redraws the menu button
     * in a pixmap, then copies the pixmap to the screen in a single
     * operation. This means that there's no point in time where the on-sreen
     * image has been cleared.
     */

    pixmap = Tk_GetPixmap(mbPtr->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);

    imageXOffset = 0;
    imageYOffset = 0;
    textXOffset = 0;
    textYOffset = 0;
    fullWidth = 0;
    fullHeight = 0;

    if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) {
	switch ((enum compound) mbPtr->compound) {
	case COMPOUND_TOP:
	case COMPOUND_BOTTOM:
	    /*
	     * Image is above or below text.
	     */

	    if (mbPtr->compound == COMPOUND_TOP) {
		textYOffset = height + mbPtr->padY;
	    } else {
		imageYOffset = mbPtr->textHeight + mbPtr->padY;
	    }
	    fullHeight = height + mbPtr->textHeight + mbPtr->padY;
	    fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth);
	    textXOffset = (fullWidth - mbPtr->textWidth)/2;
	    imageXOffset = (fullWidth - width)/2;
	    break;
	case COMPOUND_LEFT:
	case COMPOUND_RIGHT:
	    /*
	     * Image is left or right of text.
	     */

	    if (mbPtr->compound == COMPOUND_LEFT) {
		textXOffset = width + mbPtr->padX;
	    } else {
		imageXOffset = mbPtr->textWidth + mbPtr->padX;
	    }
	    fullWidth = mbPtr->textWidth + mbPtr->padX + width;
	    fullHeight = (height > mbPtr->textHeight ? height :
		    mbPtr->textHeight);
	    textYOffset = (fullHeight - mbPtr->textHeight)/2;
	    imageYOffset = (fullHeight - height)/2;
	    break;
	case COMPOUND_CENTER:
	    /*
	     * Image and text are superimposed.
	     */

	    fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth);
	    fullHeight = (height > mbPtr->textHeight ? height :
		    mbPtr->textHeight);
	    textXOffset = (fullWidth - mbPtr->textWidth)/2;
	    imageXOffset = (fullWidth - width)/2;
	    textYOffset = (fullHeight - mbPtr->textHeight)/2;
	    imageYOffset = (fullHeight - height)/2;
	    break;
	case COMPOUND_NONE:
	    break;
	}

	TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,
		mbPtr->indicatorWidth + fullWidth, fullHeight, &x, &y);

	imageXOffset += x;
	imageYOffset += y;
	if (mbPtr->image != NULL) {
	    Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap,
		    imageXOffset, imageYOffset);
	} else if (mbPtr->bitmap != None) {
	    XSetClipOrigin(mbPtr->display, gc, imageXOffset, imageYOffset);
	    XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,
		    gc, 0, 0, (unsigned) width, (unsigned) height,
		    imageXOffset, imageYOffset, 1);
	    XSetClipOrigin(mbPtr->display, gc, 0, 0);
	}

	Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,
		x + textXOffset, y + textYOffset, 0, -1);
	Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,
		x + textXOffset, y + textYOffset, mbPtr->underline);
    } else if (haveImage) {
	TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,
		width + mbPtr->indicatorWidth, height, &x, &y);
	imageXOffset += x;
	imageYOffset += y;
	if (mbPtr->image != NULL) {
	    Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap,
		    imageXOffset, imageYOffset);
	} else if (mbPtr->bitmap != None) {
	    XSetClipOrigin(mbPtr->display, gc, x, y);
	    XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,
		    gc, 0, 0, (unsigned) width, (unsigned) height,
		    x, y, 1);
	    XSetClipOrigin(mbPtr->display, gc, 0, 0);
	}
    } else {
	TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY,
		mbPtr->textWidth + mbPtr->indicatorWidth,
		mbPtr->textHeight, &x, &y);
	Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,
		x + textXOffset, y + textYOffset, 0, -1);
	Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc,
		mbPtr->textLayout, x + textXOffset, y + textYOffset,
		mbPtr->underline);
    }

    /*
     * If the menu button is disabled with a stipple rather than a special
     * foreground color, generate the stippled effect.
     */

    if ((mbPtr->state == STATE_DISABLED)
	    && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) {
	/*
	 * Stipple the whole button if no disabledFg was specified, otherwise
	 * restrict stippling only to displayed image
	 */

	if (mbPtr->disabledFg == NULL) {
	    XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC,
		    mbPtr->inset, mbPtr->inset,
		    (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset),
		    (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset));
	} else {
	    XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC,
		    imageXOffset, imageYOffset,
		    (unsigned) imageWidth, (unsigned) imageHeight);
	}
    }

    /*
     * Draw the cascade indicator for the menu button on the right side of the
     * window, if desired.
     */

    if (mbPtr->indicatorOn) {
	int borderWidth;

	borderWidth = (mbPtr->indicatorHeight+1)/3;
	if (borderWidth < 1) {
	    borderWidth = 1;
	}
	/*y += mbPtr->textHeight / 2;*/
	Tk_Fill3DRectangle(tkwin, pixmap, border,
		Tk_Width(tkwin) - mbPtr->inset - mbPtr->indicatorWidth
		+ mbPtr->indicatorHeight,
		((int) (Tk_Height(tkwin) - mbPtr->indicatorHeight))/2,
		mbPtr->indicatorWidth - 2*mbPtr->indicatorHeight,
		mbPtr->indicatorHeight, borderWidth, TK_RELIEF_RAISED);
    }

    /*
     * Draw the border and traversal highlight last. This way, if the menu
     * button's contents overflow onto the border they'll be covered up by the
     * border.
     */

    if (mbPtr->relief != TK_RELIEF_FLAT) {
	Tk_Draw3DRectangle(tkwin, pixmap, border,
		mbPtr->highlightWidth, mbPtr->highlightWidth,
		Tk_Width(tkwin) - 2*mbPtr->highlightWidth,
		Tk_Height(tkwin) - 2*mbPtr->highlightWidth,
		mbPtr->borderWidth, mbPtr->relief);
    }
    if (mbPtr->highlightWidth != 0) {
	GC gc;

	if (mbPtr->flags & GOT_FOCUS) {
	    gc = Tk_GCForColor(mbPtr->highlightColorPtr, pixmap);
	} else {
	    gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, pixmap);
	}
	Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth, pixmap);
    }

    /*
     * Copy the information from the off-screen pixmap onto the screen, then
     * delete the pixmap.
     */

    XCopyArea(mbPtr->display, pixmap, Tk_WindowId(tkwin),
	    mbPtr->normalTextGC, 0, 0, (unsigned) Tk_Width(tkwin),
	    (unsigned) Tk_Height(tkwin), 0, 0);
    Tk_FreePixmap(mbPtr->display, pixmap);
}
Exemple #11
0
void
TkpDrawCheckIndicator(
    Tk_Window tkwin,		/* handle for resource alloc */
    Display *display,
    Drawable d,			/* what to draw on */
    int x, int y,		/* where to draw */
    Tk_3DBorder bgBorder,	/* colors of the border */
    XColor *indicatorColor,	/* color of the indicator */
    XColor *selectColor,	/* color when selected */
    XColor *disableColor,	/* color when disabled */
    int on,			/* are we on? */
    int disabled,		/* are we disabled? */
    int mode)			/* kind of indicator to draw */
{
    int ix, iy;
    int dim;
    int imgsel, imgstart;
    TkBorder *bg_brdr = (TkBorder*)bgBorder;
    XGCValues gcValues;
    GC copyGC;
    unsigned long imgColors[8];
    XImage *img;
    Pixmap pixmap;
    int depth;

    /*
     * Sanity check.
     */

    if (tkwin == NULL || display == None || d == None || bgBorder == NULL
	    || indicatorColor == NULL) {
	return;
    }

    if (disableColor == NULL) {
	disableColor = bg_brdr->bgColorPtr;
    }

    if (selectColor == NULL) {
	selectColor = bg_brdr->bgColorPtr;
    }

    depth = Tk_Depth(tkwin);

    /*
     * Compute starting point and dimensions of image inside button_images to
     * be used.
     */

    switch (mode) {
    default:
    case CHECK_BUTTON:
	imgsel = on == 2 ? CHECK_DISON_OFFSET :
		on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET;
	imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0;
	imgstart = CHECK_START;
	dim = CHECK_BUTTON_DIM;
	break;

    case CHECK_MENU:
	imgsel = on == 2 ? CHECK_DISOFF_OFFSET :
		on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET;
	imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0;
	imgstart = CHECK_START + 2;
	imgsel += 2;
	dim = CHECK_MENU_DIM;
	break;

    case RADIO_BUTTON:
	imgsel = on == 2 ? RADIO_DISON_OFFSET :
		on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET;
	imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0;
	imgstart = RADIO_START;
	dim = RADIO_BUTTON_DIM;
	break;

    case RADIO_MENU:
	imgsel = on == 2 ? RADIO_DISOFF_OFFSET :
		on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET;
	imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0;
	imgstart = RADIO_START + 3;
	imgsel += 3;
	dim = RADIO_MENU_DIM;
	break;
    }

    /*
     * Allocate the drawing areas to use. Note that we use double-buffering
     * here because not all code paths leading to this function do so.
     */

    pixmap = Tk_GetPixmap(display, d, dim, dim, depth);
    if (pixmap == None) {
	return;
    }

    x -= dim/2;
    y -= dim/2;

    img = XGetImage(display, pixmap, 0, 0,
	    (unsigned int)dim, (unsigned int)dim, AllPlanes, ZPixmap);
    if (img == NULL) {
	return;
    }

    /*
     * Set up the color mapping table.
     */

    TkpGetShadows(bg_brdr, tkwin);

    imgColors[0 /*A*/] =
	    Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel;
    imgColors[1 /*B*/] =
	    Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel;
    imgColors[2 /*C*/] = (bg_brdr->lightColorPtr != NULL) ?
	    Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr)->pixel :
	    WhitePixelOfScreen(bg_brdr->screen);
    imgColors[3 /*D*/] =
	    Tk_GetColorByValue(tkwin, selectColor)->pixel;
    imgColors[4 /*E*/] = (bg_brdr->darkColorPtr != NULL) ?
	    Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr)->pixel :
	    BlackPixelOfScreen(bg_brdr->screen);
    imgColors[5 /*F*/] =
	    Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel;
    imgColors[6 /*G*/] =
	    Tk_GetColorByValue(tkwin, indicatorColor)->pixel;
    imgColors[7 /*H*/] =
	    Tk_GetColorByValue(tkwin, disableColor)->pixel;

    /*
     * Create the image, painting it into an XImage one pixel at a time.
     */

    for (iy=0 ; iy<dim ; iy++) {
	for (ix=0 ; ix<dim ; ix++) {
	    XPutPixel(img, ix, iy,
		    imgColors[button_images[imgstart+iy][imgsel+ix] - 'A'] );
	}
    }

    /*
     * Copy onto our target drawable surface.
     */

    memset(&gcValues, 0, sizeof(gcValues));
    gcValues.background = bg_brdr->bgColorPtr->pixel;
    gcValues.graphics_exposures = False;
    copyGC = Tk_GetGC(tkwin, 0, &gcValues);

    XPutImage(display, pixmap, copyGC, img, 0, 0, 0, 0,
	    (unsigned int)dim, (unsigned int)dim);
    XCopyArea(display, pixmap, d, copyGC, 0, 0,
	    (unsigned int)dim, (unsigned int)dim, x, y);

    /*
     * Tidy up.
     */

    Tk_FreeGC(display, copyGC);
    XDestroyImage(img);
    Tk_FreePixmap(display, pixmap);
}
Exemple #12
0
void 
HtmlImageFree (HtmlImage2 *pImage)
{
    if (!pImage) {
        return;
    }

    assert(pImage->nRef > 0);
    pImage->nRef--;
    if (
        pImage->nRef == 0 && 
        (pImage->pUnscaled || !pImage->pImageServer->isSuspendGC)
    ) {
        /* The reference count for this structure has reached zero.
         * Really delete it. The assert() says that an original image
         * cannot be deleted before all of it's scaled copies.
         */
        assert(pImage->pUnscaled || 0 == pImage->pNext);

        freeImageCompressed(pImage);
        freeTile(pImage);
        if (pImage->pixmap) {
            HtmlTree *pTree = pImage->pImageServer->pTree;
            Tk_FreePixmap(Tk_Display(pTree->tkwin), pImage->pixmap);
            pImage->pixmap = 0;
        }
        if (pImage->image) {
            Tk_FreeImage(pImage->image);
        }
        if (pImage->pImageName) {
            Tcl_Interp *interp = pImage->pImageServer->pTree->interp;
            Tcl_Obj *pEval;
            if (!pImage->pDelete) {
                pEval = Tcl_NewStringObj("image delete", -1);
                Tcl_IncrRefCount(pEval);
            } else {
                pEval = pImage->pDelete;
            }
            Tcl_ListObjAppendElement(interp, pEval, pImage->pImageName);
            Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
            Tcl_DecrRefCount(pEval);
            Tcl_DecrRefCount(pImage->pImageName);
        }

        if (pImage->pUnscaled) {
            HtmlImage2 *pIter;
            for (
                pIter = pImage->pUnscaled; 
                pIter->pNext != pImage; 
                pIter = pIter->pNext
            ) {
                assert(pIter->pNext);
            }
            pIter->pNext = pIter->pNext->pNext;
            HtmlImageFree(pImage->pUnscaled);
        } else {
            const char *zKey = pImage->zUrl;
            Tcl_HashTable *paImage = &pImage->pImageServer->aImage;
            Tcl_HashEntry *pEntry = Tcl_FindHashEntry(paImage, zKey);
            assert(pEntry);
            Tcl_DeleteHashEntry(pEntry);
        }

        HtmlFree(pImage);
        Tcl_CancelIdleCall(asyncPixmapify, (ClientData)pImage);
    }
}
Exemple #13
0
static void
ImgBmapConfigureInstance(
    BitmapInstance *instancePtr)/* Instance to reconfigure. */
{
    BitmapMaster *masterPtr = instancePtr->masterPtr;
    XColor *colorPtr;
    XGCValues gcValues;
    GC gc;
    unsigned int mask;
    Pixmap oldBitmap, oldMask;

    /*
     * For each of the options in masterPtr, translate the string form into an
     * internal form appropriate for instancePtr.
     */

    if (*masterPtr->bgUid != 0) {
	colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
		masterPtr->bgUid);
	if (colorPtr == NULL) {
	    goto error;
	}
    } else {
	colorPtr = NULL;
    }
    if (instancePtr->bg != NULL) {
	Tk_FreeColor(instancePtr->bg);
    }
    instancePtr->bg = colorPtr;

    colorPtr = Tk_GetColor(masterPtr->interp, instancePtr->tkwin,
	    masterPtr->fgUid);
    if (colorPtr == NULL) {
	goto error;
    }
    if (instancePtr->fg != NULL) {
	Tk_FreeColor(instancePtr->fg);
    }
    instancePtr->fg = colorPtr;

    /*
     * Careful: We have to allocate new Pixmaps before deleting the old ones.
     * Otherwise, The XID allocator will always return the same XID for the
     * new Pixmaps as was used for the old Pixmaps. And that will prevent the
     * data and/or mask from changing in the GC below.
     */

    oldBitmap = instancePtr->bitmap;
    instancePtr->bitmap = None;
    oldMask = instancePtr->mask;
    instancePtr->mask = None;

    if (masterPtr->data != NULL) {
	instancePtr->bitmap = XCreateBitmapFromData(
		Tk_Display(instancePtr->tkwin),
		RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
		masterPtr->data, (unsigned) masterPtr->width,
		(unsigned) masterPtr->height);
    }
    if (masterPtr->maskData != NULL) {
	instancePtr->mask = XCreateBitmapFromData(
		Tk_Display(instancePtr->tkwin),
		RootWindowOfScreen(Tk_Screen(instancePtr->tkwin)),
		masterPtr->maskData, (unsigned) masterPtr->width,
		(unsigned) masterPtr->height);
    }

    if (oldMask != None) {
	Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);
    }
    if (oldBitmap != None) {
	Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldBitmap);
    }

    if (masterPtr->data != NULL) {
	gcValues.foreground = instancePtr->fg->pixel;
	gcValues.graphics_exposures = False;
	mask = GCForeground|GCGraphicsExposures;
	if (instancePtr->bg != NULL) {
	    gcValues.background = instancePtr->bg->pixel;
	    mask |= GCBackground;
	    if (instancePtr->mask != None) {
		gcValues.clip_mask = instancePtr->mask;
		mask |= GCClipMask;
	    }
	} else {
	    gcValues.clip_mask = instancePtr->bitmap;
	    mask |= GCClipMask;
	}
	gc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);
    } else {
	gc = None;
    }
    if (instancePtr->gc != None) {
	Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
    }
    instancePtr->gc = gc;
    return;

  error:
    /*
     * An error occurred: clear the graphics context in the instance to make
     * it clear that this instance cannot be displayed. Then report the error.
     */

    if (instancePtr->gc != None) {
	Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
    }
    instancePtr->gc = None;
    Tcl_AppendObjToErrorInfo(masterPtr->interp, Tcl_ObjPrintf(
	    "\n    (while configuring image \"%s\")", Tk_NameOfImage(
	    masterPtr->tkMaster)));
    Tcl_BackgroundError(masterPtr->interp);
}
Exemple #14
0
static void
draw_one_image(Imfsample *imfsample, Drawable d, GC gc, Image *img,
	       int sx, int sy, int sw, int sh)
{
    int sx2, sy2;
    TkImage *tkimg;
    Tk_Window tkwin = imfsample->tkwin;
    Display *dpy = Tk_Display(tkwin);
    XColor *imagecolor = black_color;
    XColor *maskcolor = white_color;

    if (!img->istile) {
	/* Offset the image to draw in the middle of its area,
	   whether larger or smaller than the given area. */
	sx2 = sx + (sw - img->w) / 2;  
	sy2 = sy + (sh - img->h) / 2;
	/* Only change the size of the rectangle being drawn if it's
	   smaller than what was passed in. */
	if (img->w < sw) {
	    sx = sx2;
	    sw = img->w;
	}
	if (img->h < sh) {
	    sy = sy2;
	    sh = img->h;
	}
    }
    /* Pick out a specific subimage if necessary. */
    if (img->numsubimages > 0 && img->subimages)
      img = img->subimages[img->numsubimages - 1];
    tkimg = (TkImage *) img->hook;
    if (tkimg == NULL)
      return;
    XSetClipMask(dpy, gc, None);
    if (tkimg->colr != None && imfsample->show_color) {
	if (img->istile) {
	    XSetFillStyle(dpy, gc, FillTiled);
	    XSetTile(dpy, gc, tkimg->colr);
	    XFillRectangle(dpy, d, gc, sx, sy, sw, sh);
	} else {
	    if (use_clip_mask) {
		if (tkimg->mask != None && imfsample->show_masks) {
		    XSetClipOrigin(dpy, gc, sx2, sy2);
		    /* Use the image's mask to do clipped drawing. */
		    XSetClipMask(dpy, gc, tkimg->mask);
		}
	    } else {
		if (tkimg->mask != None && imfsample->show_masks) {
		    XSetFunction(dpy, gc, GXand);
		    XCopyArea(dpy, tkimg->mask, d, gc, 0, 0, sw, sh, sx, sy);
		}
		XSetFunction(dpy, gc, GXor);
	    }
	    /* Draw the color image. */
	    XCopyArea(dpy, tkimg->colr, d, gc, 0, 0, sw, sh, sx, sy);
	    if (!use_clip_mask)
	      XSetFunction(dpy, gc, GXcopy);
	}
    } else if (tkimg->solid != NULL && imfsample->show_color) {
	XSetFillStyle(dpy, gc, FillSolid);
	XSetForeground(dpy, gc, tkimg->solid->pixel);
	XFillRectangle(dpy, d, gc, sx, sy, sw, sh);
    } else if (tkimg->mono != None || tkimg->mask != None) {
	if (use_clip_mask) {
	    /* The XFillRectangle code below does not work when we draw 
		directly to the screen on the Mac, so we use XCopyArea with a 
		small colored offscreen pixmap instead (this method does not 
		work on Unix or during double buffered drawing on the Mac). */ 
#ifdef MAC
	    if (!imfsample->double_buffer) {
		Pixmap pm = 
		    Tk_GetPixmap(dpy, Tk_WindowId(tkwin), sw, sh, 
				 DefaultDepthOfScreen(Tk_Screen(tkwin)));

		/* Draw the mask. */
		if (tkimg->mask && imfsample->show_masks) {
		    XSetClipMask(dpy, gc, tkimg->mask);
		} else {
		    XSetClipMask(dpy, gc, tkimg->mono);
		}
		if (tkimg->mono != None) {
		    Tk_Fill3DRectangle(tkwin, pm, white_border, 0, 0, 
				       sw, sh, 0, 0);
		} else {
		    Tk_Fill3DRectangle(tkwin, pm, black_border, 0, 0, 
				       sw, sh, 0, 0);
		}
		XCopyArea(dpy, pm, Tk_WindowId(tkwin), gc, 0, 0, 
			  sw, sh, sx, sy);
		/* Draw the image proper. */
		if (tkimg->mono != None) {
		    XSetClipMask(dpy, gc, tkimg->mono);
		    Tk_Fill3DRectangle(tkwin, pm, black_border, 0, 0, 
				       sw, sh, 0, 0);
		    XCopyArea(dpy, pm, Tk_WindowId(tkwin), gc, 0, 0, 
			      sw, sh, sx, sy);
		}
		Tk_FreePixmap(dpy, pm);
		return;
	    }
#endif

		XSetFillStyle(dpy, gc, FillSolid);
		/* Set the color we're going to use for the mask; use the
		imagecolor if we'll be using the mask as the only image. */
		XSetForeground(dpy, gc,
			(tkimg->mono == None ? imagecolor : maskcolor)->pixel);
		XSetClipOrigin(dpy, gc, sx2, sy2);
		/* Set the clip mask to be explicit mask or unit's image. */
		if (tkimg->mask && imfsample->show_masks) {
			XSetClipMask(dpy, gc, tkimg->mask);
		} else {
			XSetClipMask(dpy, gc, tkimg->mono);
		}
		/* Draw the mask. */
		XFillRectangle(dpy, d, gc, sx, sy, sw, sh);
		/* Draw the image proper. */
		if (tkimg->mono != None) {
		    XSetForeground(dpy, gc, imagecolor->pixel);
		    XSetClipMask(dpy, gc, tkimg->mono);
		    XFillRectangle(dpy, d, gc, sx, sy, sw, sh);
		}
	/* The Win32 case. */
	} else {
	    if (tkimg->mask != None && imfsample->show_masks) {
		XSetFunction(dpy, gc, GXand);
		XCopyArea(dpy, tkimg->mask, d, gc, 0, 0, sw, sh, sx, sy);
	    }
	    if (tkimg->mono != None) {
		XSetFunction(dpy, gc, GXor);
		XCopyArea(dpy, tkimg->mono, d, gc, 0, 0, sw, sh, sx, sy);
	    }
	    XSetFunction(dpy, gc, GXcopy);
	}
    }
}
Exemple #15
0
static void
imfsample_display(ClientData cldata)
{
    char *str;
    int row, col, namex, namey, n, sx, sy, update = FALSE, done;
    Imfsample *imfsample = (Imfsample *) cldata;
    Display *dpy = imfsample->display;
    Tk_Window tkwin = imfsample->tkwin;
    GC gc;
    Pixmap pm = None;
    Drawable d;
    Tk_Font tkfont;
    int winwidth = Tk_Width(Tk_Parent(tkwin)); 
    int winheight = Tk_Height(Tk_Parent(tkwin));
    char tclbuf[100];
    int rslt;
	
    imfsample->update_pending = 0;
    if (!Tk_IsMapped(tkwin)) {
	return;
    }
    /* Check if we need to redraw the entire imfsample. */
    if (imfsample->imfapp) {
	if (imfsample->oldfirst != imfsample->firstvisrow
	    || imfsample->redraw) {
		imfsample->oldfirst = imfsample->firstvisrow;
		update = TRUE;
	}
    }
    /* Create a pixmap for double-buffering if necessary. */
    if (imfsample->double_buffer) {
	update = TRUE;
	pm = Tk_GetPixmap(imfsample->display, Tk_WindowId(tkwin),
			  Tk_Width(tkwin), Tk_Height(tkwin),
			  DefaultDepthOfScreen(Tk_Screen(tkwin)));
	d = pm;
    } else {
	d = Tk_WindowId(tkwin);
    }
    if (black_color == NULL) {
	black_color = Tk_GetColor(interp, tkwin, Tk_GetUid("black"));
    }
    if (white_color == NULL) {
	white_color = Tk_GetColor(interp, tkwin, Tk_GetUid("white"));
    }
    if (black_border == NULL) {
	black_border = Tk_Get3DBorder(interp, tkwin, "black");
    }
    if (white_border == NULL) {
	white_border = Tk_Get3DBorder(interp, tkwin, "white");
    }
    /* Collect GC and font for subsequent work. */
    gc = imfsample->gc;
    XSetClipMask(dpy, gc, None);
    if (imfsample->show_names) {
#ifdef WIN32
	tkfont = Tk_GetFont(interp, tkwin, "-family arial -size 8");
#elif defined (MAC)
	tkfont = Tk_GetFont(interp, tkwin, "-family helvetica -size 11");
#else
	tkfont = Tk_GetFont(interp, tkwin, "-family helvetica -size 12");
#endif
	XSetFont(imfsample->display, gc, Tk_FontId(tkfont));
    }

    /* Redraw the entire widget background/border, but not if we
       are just updating the selected image. */
    if (imfsample->selected == imfsample->previous
     	/* Always redraw if we have only one image (e.g. closeups). */
    	|| (imfsample->numimages == 1 && imfsample->selected == -1)
    	|| update) {
	    done = FALSE;
	    if (imfsample->with_terrain >= 0
	    	/* Terrain tiles are not supported on Windows yet. */
	    	&& use_clip_mask) {
		ImageFamily *timf = 
		    imfsample->imf_list[imfsample->with_terrain];
		Image *timg;
		TkImage *tkimg;

		timg = best_image(timf, 64, 64);
		if (timg) {
		    tkimg = (TkImage *) timg->hook;
		    if (tkimg && tkimg->colr) {
			XSetFillStyle(dpy, gc, FillTiled);
			XSetTile(dpy, gc, tkimg->colr);
			XFillRectangle(dpy, d, gc, 0, 0,
				       Tk_Width(tkwin), Tk_Height(tkwin));
			done = TRUE;
		    }
		}
	    }
	    if (!done) {
		Tk_Fill3DRectangle(tkwin, d, imfsample->bg_border, 0, 0,
				   Tk_Width(tkwin), Tk_Height(tkwin),
				   imfsample->border_width, imfsample->relief);
	    }
    }
#if 0
    for (i = 0; i < imfsample->numimages; i++) {
	if (imf_interp_hook)
	  imfsample->imf_list[i] =
	    (*imf_interp_hook)(imfsample->imf_list[i], NULL, TRUE);
    }
#endif
    /* Tweak the default item width/height to something better. */
    if (imfsample->iheight == 0) {
	imfsample->iheight = 32;
	if (imfsample->numimages == 1)
	  imfsample->iheight = imfsample->height;
    }
    if (imfsample->iwidth == 0) {
	imfsample->iwidth = 32;
	if (imfsample->numimages == 1)
	  imfsample->iwidth = imfsample->width;
    }
    imfsample->eltw = imfsample->iwidth;
    if (imfsample->show_grid)
      imfsample->eltw += 2;
    else
      imfsample->eltw += 2 * imfsample->pad;
    if (imfsample->show_names && !imfsample->show_grid)
      imfsample->eltw += 80;
    imfsample->elth = imfsample->iheight;
    if (imfsample->show_grid)
      imfsample->elth += 2;
    else
      imfsample->elth += 2 * imfsample->pad;
    /* Fix a lower bound on the vertical spacing. */
    /* (should be determined by choice of app font) */
    if (imfsample->elth < 10 && !imfsample->show_grid)
      imfsample->elth = 10;
    /* Compute and save the number of columns to use. */
    imfsample->cols = winwidth / imfsample->eltw;
    if (imfsample->cols <= 0)
      imfsample->cols = 1;
    /* We can get a little wider spacing by recalculating the element
       width. */
    if (imfsample->show_names && !imfsample->show_grid)
      imfsample->eltw = (winwidth - 10) / imfsample->cols;
    imfsample->rows = imfsample->numimages / imfsample->cols;
    /* Account for a last partial row. */
    if (imfsample->rows * imfsample->cols < imfsample->numimages)
      ++(imfsample->rows);
    /* Compute the number of visible rows.  It would be time-consuming
       to render all the images, so try to do only the visible ones. */
    imfsample->numvisrows = winheight / imfsample->elth;
    if (imfsample->numvisrows > imfsample->rows)
      imfsample->numvisrows = imfsample->rows;
    if (imfsample->numvisrows < 1)
      imfsample->numvisrows = min(1, imfsample->rows);
    if (imfsample->firstvisrow + imfsample->numvisrows > imfsample->rows)
      imfsample->firstvisrow = imfsample->rows - imfsample->numvisrows;
    /* Imfapp-specific code that adjusts the canvas content to fit a resized
    window and also sets the canvas scrollregion correctly. */
    if (imfsample->imfapp
    	&& imfsample->redraw) {  
	    imfsample->width = Tk_Width(Tk_Parent(tkwin));
	    imfsample->height = imfsample->rows * imfsample->elth + 7;
	    Tk_GeometryRequest(tkwin, imfsample->width, imfsample->height);
	    /* There must be a better way to do this ... */
	    sprintf(tclbuf, 
		    ".images.canvas configure -scrollregion [ list 0 0 0 %d ]", 
		    imfsample->height);
	    rslt = Tcl_Eval(interp, tclbuf);
	    if (rslt == TCL_ERROR) {
	        fprintf(stderr, "Error: %s\n", Tcl_GetStringResult(interp));
	    }
	    /* Force a redraw of the scrollbar if the window was resized. */
	    if (imfsample->numimages) {
		sprintf(tclbuf, ".images.canvas.content yview scroll 0 units");
	    } else {
		sprintf(tclbuf, ".images.scroll set 0 1");
	   }
	    rslt = Tcl_Eval(interp, tclbuf);
	    if (rslt == TCL_ERROR) {
	      fprintf(stderr, "Error: %s\n", Tcl_GetStringResult(interp));
	    }
    }
    /* Now iterate through all the images we want to draw. */
    for (row = imfsample->firstvisrow;
	 row <= (imfsample->firstvisrow + imfsample->numvisrows);
	 ++row) {
	if (row < 0)
	  continue;
	for (col = 0; col < imfsample->cols; ++col) {
	    n = row * imfsample->cols + col;
	    if (n >= imfsample->numimages)
	      break;
	    sx = col * imfsample->eltw;
	    sy = (row - imfsample->firstvisrow) * imfsample->elth;
	    /* Erase the old selected imf if we picked a new one. */
	    if (n == imfsample->previous && n != imfsample->selected) {
		done = FALSE; 
		if (imfsample->with_terrain >= 0
		      /* Terrain tiles are not supported on Windows yet. */
		    && use_clip_mask) {
		    ImageFamily *timf = 
			imfsample->imf_list[imfsample->with_terrain];
		    Image *timg;
		    TkImage *tkimg;

		    timg = best_image(timf, 64, 64);
		    if (timg) {
			tkimg = (TkImage *) timg->hook;
			if (tkimg && tkimg->colr) {
			    XSetFillStyle(dpy, gc, FillTiled);
			    XSetTile(dpy, gc, tkimg->colr);
			    if (imfsample->show_grid) {
				XFillRectangle(dpy, d, gc, sx, sy + 2,
					       imfsample->eltw, 
					       imfsample->elth);
			    } else {
				XFillRectangle(dpy, d, gc, sx, sy + 7,
					       imfsample->eltw, 
					       imfsample->elth);
			    }
			    done = TRUE;
			}
		    }
		}
		if (!done) {
		    if (imfsample->show_grid) {
			Tk_Fill3DRectangle(tkwin, d, imfsample->bg_border, 
					   sx, sy + 2,
					   imfsample->eltw, imfsample->elth,
					   imfsample->border_width, 
					   imfsample->relief);
		    } else {
			Tk_Fill3DRectangle(tkwin, d, imfsample->bg_border, 
					   sx, sy + 7,
					   imfsample->eltw, imfsample->elth,
					   imfsample->border_width, 
					   imfsample->relief);
		    }
		}
	    }
	    /* Just draw the old erased image if we selected a new one, else
	       draw every image. */
	    if (imfsample->selected == imfsample->previous
            	|| n == imfsample->previous
           	|| update) {
		    if (imfsample->show_grid) {
			Tk_Fill3DRectangle(tkwin, d, imfsample->cu_border,
				sx + 2, sy + 2,
				imfsample->iwidth, imfsample->iheight,
				imfsample->border_width, imfsample->relief);
			draw_one_main_image(imfsample, d, gc, 
					    imfsample->imf_list[n],
					    sx + 2, sy + 2,
					    imfsample->iwidth, 
					    imfsample->iheight);
		    } else {
			draw_one_main_image(imfsample, d, gc, 
					    imfsample->imf_list[n],
					    sx + imfsample->pad, 
					    sy + imfsample->pad,
					    imfsample->iwidth, 
					    imfsample->iheight);
		    }
		    if (imfsample->show_names && !imfsample->show_grid) {
			namex = sx + 5;
			namey = sy + imfsample->elth + 3;
			XSetClipMask(dpy, gc, None);
			XSetFillStyle(dpy, gc, FillSolid);
			XSetForeground(dpy, gc, 
				       Tk_3DBorderColor(
					imfsample->fg_border)->pixel);
			str = imfsample->imf_list[n]->name;
			Tk_DrawChars(dpy, d, gc, tkfont, str, strlen(str),
				     namex, namey);
		    }
	    }
	    /* Box the selected imf. */
	    if (n == imfsample->selected) {
		XSetClipMask(dpy, gc, None);
		XSetFillStyle(dpy, gc, FillSolid);
		XSetForeground(dpy, gc, Tk_3DBorderColor(imfsample->fg_border)->pixel);
	  	if (imfsample->show_grid) {
		/* A rectangle on the Mac is 1 pixel smaller in both directions. */
#ifdef MAC
			XDrawRectangle(dpy, d, gc, sx + 2, sy + 2,
				       imfsample->eltw - 2, imfsample->elth - 2);
#else
			XDrawRectangle(dpy, d, gc, sx + 2, sy + 2,
				       imfsample->eltw - 3, imfsample->elth - 3);
#endif
	  	} else {
#ifdef MAC
			XDrawRectangle(dpy, d, gc, sx, sy + 7,
				       imfsample->eltw, imfsample->elth);
#else
			XDrawRectangle(dpy, d, gc, sx, sy + 7,
				       imfsample->eltw - 1, imfsample->elth - 1);
#endif
		}
	    }
	}
    }
    /* Reset the old selected image to the new one if it exists. */
    if (imfsample->selected != -1) {
	imfsample->previous = imfsample->selected;
    }
    /* Reset the redraw flag. */
    imfsample->redraw = FALSE;
    /* If double-buffered, copy to the screen and release the pixmap.  */
    if (imfsample->double_buffer) {
	XCopyArea(imfsample->display, pm, Tk_WindowId(tkwin),
		  imfsample->copygc,
		  0, 0, (unsigned) winwidth, (unsigned) winheight, 0, 0);
	Tk_FreePixmap(imfsample->display, pm);
    }
    if (imfsample->show_names) {
	Tk_FreeFont(tkfont);
    }
    /* In theory this shouldn't be necessary, but in practice the
       interface widgets (esp. the progress bar fill color) are
       affected by the last value of the foreground left over from
       drawing, so set to a consistent value. */
    /* (Note that as of 2000-09-16, some color errors persist, so
       this might not really be necessary -sts) */
    XSetForeground(imfsample->display, imfsample->gc, black_color->pixel);
    XSetBackground(imfsample->display, imfsample->gc, white_color->pixel);
    XSetForeground(imfsample->display, imfsample->copygc, black_color->pixel);
    XSetBackground(imfsample->display, imfsample->copygc, white_color->pixel);
}
Exemple #16
0
int
Tk_PostscriptImage(
    Tk_Image image,		/* Token for image to redisplay. */
    Tcl_Interp *interp,
    Tk_Window tkwin,
    Tk_PostscriptInfo psinfo,	/* postscript info */
    int x, int y,		/* Upper-left pixel of region in image that
				 * needs to be redisplayed. */
    int width, int height,	/* Dimensions of region to redraw. */
    int prepass)
{
    Image *imagePtr = (Image *) image;
    int result;
    XImage *ximage;
    Pixmap pmap;
    GC newGC;
    XGCValues gcValues;

    if (imagePtr->masterPtr->typePtr == NULL) {
	/*
	 * No master for image, so nothing to display on postscript.
	 */

	return TCL_OK;
    }

    /*
     * Check if an image specific postscript-generation function exists;
     * otherwise go on with generic code.
     */

    if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
	return imagePtr->masterPtr->typePtr->postscriptProc(
		imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
		x, y, width, height, prepass);
    }

    if (prepass) {
	return TCL_OK;
    }

    /*
     * Create a Pixmap, tell the image to redraw itself there, and then
     * generate an XImage from the Pixmap. We can then read pixel values out
     * of the XImage.
     */

    pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), width, height,
	    Tk_Depth(tkwin));

    gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
    newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
    if (newGC != NULL) {
	XFillRectangle(Tk_Display(tkwin), pmap, newGC, 0, 0,
		(unsigned) width, (unsigned) height);
	Tk_FreeGC(Tk_Display(tkwin), newGC);
    }

    Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);

    ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,
	    (unsigned) width, (unsigned) height, AllPlanes, ZPixmap);

    Tk_FreePixmap(Tk_Display(tkwin), pmap);

    if (ximage == NULL) {
	/*
	 * The XGetImage() function is apparently not implemented on this
	 * system. Just ignore it.
	 */

	return TCL_OK;
    }
    result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,
	    width, height);

    XDestroyImage(ximage);
    return result;
}
Exemple #17
0
void
TkpDisplayScale(
    ClientData clientData)	/* Widget record for scale. */
{
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tcl_Interp *interp = scalePtr->interp;
    Pixmap pixmap;
    int result;
    char string[PRINT_CHARS];
    XRectangle drawnArea;
    Tcl_DString buf;

    scalePtr->flags &= ~REDRAW_PENDING;
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
	goto done;
    }

    /*
     * Invoke the scale's command if needed.
     */

    Tcl_Preserve(scalePtr);
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
	Tcl_Preserve(interp);
	sprintf(string, scalePtr->format, scalePtr->value);
	Tcl_DStringInit(&buf);
	Tcl_DStringAppend(&buf, scalePtr->command, -1);
	Tcl_DStringAppend(&buf, " ", -1);
	Tcl_DStringAppend(&buf, string, -1);
	result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
	Tcl_DStringFree(&buf);
	if (result != TCL_OK) {
	    Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
	    Tcl_BackgroundException(interp, result);
	}
	Tcl_Release(interp);
    }
    scalePtr->flags &= ~INVOKE_COMMAND;
    if (scalePtr->flags & SCALE_DELETED) {
	Tcl_Release(scalePtr);
	return;
    }
    Tcl_Release(scalePtr);

#ifndef TK_NO_DOUBLE_BUFFERING
    /*
     * In order to avoid screen flashes, this function redraws the scale in a
     * pixmap, then copies the pixmap to the screen in a single operation.
     * This means that there's no point in time where the on-sreen image has
     * been cleared.
     */

    pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin),
	    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
#else
    pixmap = Tk_WindowId(tkwin);
#endif /* TK_NO_DOUBLE_BUFFERING */
    drawnArea.x = 0;
    drawnArea.y = 0;
    drawnArea.width = Tk_Width(tkwin);
    drawnArea.height = Tk_Height(tkwin);

    /*
     * Much of the redisplay is done totally differently for horizontal and
     * vertical scales. Handle the part that's different.
     */

    if (scalePtr->orient == ORIENT_VERTICAL) {
	DisplayVerticalScale(scalePtr, pixmap, &drawnArea);
    } else {
	DisplayHorizontalScale(scalePtr, pixmap, &drawnArea);
    }

    /*
     * Now handle the part of redisplay that is the same for horizontal and
     * vertical scales: border and traversal highlight.
     */

    if (scalePtr->flags & REDRAW_OTHER) {
	if (scalePtr->relief != TK_RELIEF_FLAT) {
	    Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder,
		    scalePtr->highlightWidth, scalePtr->highlightWidth,
		    Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
		    Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
		    scalePtr->borderWidth, scalePtr->relief);
	}
	if (scalePtr->highlightWidth != 0) {
	    GC gc;

	    if (scalePtr->flags & GOT_FOCUS) {
		gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap);
	    } else {
		gc = Tk_GCForColor(
                        Tk_3DBorderColor(scalePtr->highlightBorder), pixmap);
	    }
	    Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap);
	}
    }

#ifndef TK_NO_DOUBLE_BUFFERING
    /*
     * Copy the information from the off-screen pixmap onto the screen, then
     * delete the pixmap.
     */

    XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin),
	    scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width,
	    drawnArea.height, drawnArea.x, drawnArea.y);
    Tk_FreePixmap(scalePtr->display, pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */

  done:
    scalePtr->flags &= ~REDRAW_ALL;
}
Exemple #18
0
GC
Tk_GetGC(
    Tk_Window tkwin,		/* Window in which GC will be used. */
    register unsigned long valueMask,
				/* 1 bits correspond to values specified in
				 * *valuesPtr; other values are set from
				 * defaults. */
    register XGCValues *valuePtr)
				/* Values are specified here for bits set in
				 * valueMask. */
{
    ValueKey valueKey;
    Tcl_HashEntry *valueHashPtr, *idHashPtr;
    register TkGC *gcPtr;
    int isNew;
    Drawable d, freeDrawable;
    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;

    if (dispPtr->gcInit <= 0) {
	GCInit(dispPtr);
    }

    /*
     * Must zero valueKey at start to clear out pad bytes that may be part of
     * structure on some systems.
     */

    memset(&valueKey, 0, sizeof(valueKey));

    /*
     * First, check to see if there's already a GC that will work for this
     * request (exact matches only, sorry).
     */

    if (valueMask & GCFunction) {
	valueKey.values.function = valuePtr->function;
    } else {
	valueKey.values.function = GXcopy;
    }
    if (valueMask & GCPlaneMask) {
	valueKey.values.plane_mask = valuePtr->plane_mask;
    } else {
	valueKey.values.plane_mask = (unsigned) ~0;
    }
    if (valueMask & GCForeground) {
	valueKey.values.foreground = valuePtr->foreground;
    } else {
	valueKey.values.foreground = 0;
    }
    if (valueMask & GCBackground) {
	valueKey.values.background = valuePtr->background;
    } else {
	valueKey.values.background = 1;
    }
    if (valueMask & GCLineWidth) {
	valueKey.values.line_width = valuePtr->line_width;
    } else {
	valueKey.values.line_width = 0;
    }
    if (valueMask & GCLineStyle) {
	valueKey.values.line_style = valuePtr->line_style;
    } else {
	valueKey.values.line_style = LineSolid;
    }
    if (valueMask & GCCapStyle) {
	valueKey.values.cap_style = valuePtr->cap_style;
    } else {
	valueKey.values.cap_style = CapButt;
    }
    if (valueMask & GCJoinStyle) {
	valueKey.values.join_style = valuePtr->join_style;
    } else {
	valueKey.values.join_style = JoinMiter;
    }
    if (valueMask & GCFillStyle) {
	valueKey.values.fill_style = valuePtr->fill_style;
    } else {
	valueKey.values.fill_style = FillSolid;
    }
    if (valueMask & GCFillRule) {
	valueKey.values.fill_rule = valuePtr->fill_rule;
    } else {
	valueKey.values.fill_rule = EvenOddRule;
    }
    if (valueMask & GCArcMode) {
	valueKey.values.arc_mode = valuePtr->arc_mode;
    } else {
	valueKey.values.arc_mode = ArcPieSlice;
    }
    if (valueMask & GCTile) {
	valueKey.values.tile = valuePtr->tile;
    } else {
	valueKey.values.tile = None;
    }
    if (valueMask & GCStipple) {
	valueKey.values.stipple = valuePtr->stipple;
    } else {
	valueKey.values.stipple = None;
    }
    if (valueMask & GCTileStipXOrigin) {
	valueKey.values.ts_x_origin = valuePtr->ts_x_origin;
    } else {
	valueKey.values.ts_x_origin = 0;
    }
    if (valueMask & GCTileStipYOrigin) {
	valueKey.values.ts_y_origin = valuePtr->ts_y_origin;
    } else {
	valueKey.values.ts_y_origin = 0;
    }
    if (valueMask & GCFont) {
	valueKey.values.font = valuePtr->font;
    } else {
	valueKey.values.font = None;
    }
    if (valueMask & GCSubwindowMode) {
	valueKey.values.subwindow_mode = valuePtr->subwindow_mode;
    } else {
	valueKey.values.subwindow_mode = ClipByChildren;
    }
    if (valueMask & GCGraphicsExposures) {
	valueKey.values.graphics_exposures = valuePtr->graphics_exposures;
    } else {
	valueKey.values.graphics_exposures = True;
    }
    if (valueMask & GCClipXOrigin) {
	valueKey.values.clip_x_origin = valuePtr->clip_x_origin;
    } else {
	valueKey.values.clip_x_origin = 0;
    }
    if (valueMask & GCClipYOrigin) {
	valueKey.values.clip_y_origin = valuePtr->clip_y_origin;
    } else {
	valueKey.values.clip_y_origin = 0;
    }
    if (valueMask & GCClipMask) {
	valueKey.values.clip_mask = valuePtr->clip_mask;
    } else {
	valueKey.values.clip_mask = None;
    }
    if (valueMask & GCDashOffset) {
	valueKey.values.dash_offset = valuePtr->dash_offset;
    } else {
	valueKey.values.dash_offset = 0;
    }
    if (valueMask & GCDashList) {
	valueKey.values.dashes = valuePtr->dashes;
    } else {
	valueKey.values.dashes = 4;
    }
    valueKey.display = Tk_Display(tkwin);
    valueKey.screenNum = Tk_ScreenNumber(tkwin);
    valueKey.depth = Tk_Depth(tkwin);
    valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable,
	    (char *) &valueKey, &isNew);
    if (!isNew) {
	gcPtr = Tcl_GetHashValue(valueHashPtr);
	gcPtr->refCount++;
	return gcPtr->gc;
    }

    /*
     * No GC is currently available for this set of values. Allocate a new GC
     * and add a new structure to the database.
     */

    gcPtr = ckalloc(sizeof(TkGC));

    /*
     * Find or make a drawable to use to specify the screen and depth of the
     * GC. We may have to make a small pixmap, to avoid doing
     * Tk_MakeWindowExist on the window.
     */

    freeDrawable = None;
    if (Tk_WindowId(tkwin) != None) {
	d = Tk_WindowId(tkwin);
    } else if (valueKey.depth ==
	    DefaultDepth(valueKey.display, valueKey.screenNum)) {
	d = RootWindow(valueKey.display, valueKey.screenNum);
    } else {
	d = Tk_GetPixmap(valueKey.display,
		RootWindow(valueKey.display, valueKey.screenNum),
		1, 1, valueKey.depth);
	freeDrawable = d;
    }

    gcPtr->gc = XCreateGC(valueKey.display, d, valueMask, &valueKey.values);
    gcPtr->display = valueKey.display;
    gcPtr->refCount = 1;
    gcPtr->valueHashPtr = valueHashPtr;
    idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable,
	    (char *) gcPtr->gc, &isNew);
    if (!isNew) {
	Tcl_Panic("GC already registered in Tk_GetGC");
    }
    Tcl_SetHashValue(valueHashPtr, gcPtr);
    Tcl_SetHashValue(idHashPtr, gcPtr);
    if (freeDrawable != None) {
	Tk_FreePixmap(valueKey.display, freeDrawable);
    }

    return gcPtr->gc;
}
Exemple #19
0
void
TkpDisplayButton(
    ClientData clientData)	/* Information about widget. */
{
    register TkButton *butPtr = (TkButton *) clientData;
    GC gc;
    Tk_3DBorder border;
    Pixmap pixmap;
    int x = 0;			/* Initialization only needed to stop compiler
				 * warning. */
    int y, relief;
    Tk_Window tkwin = butPtr->tkwin;
    int width, height, fullWidth, fullHeight;
    int textXOffset, textYOffset;
    int haveImage = 0, haveText = 0;
    int offset;			/* 1 means this is a button widget, so we
				 * offset the text to make the button appear
				 * to move up and down as the relief
				 * changes. */
    int imageWidth, imageHeight;
    int imageXOffset = 0, imageYOffset = 0;
				/* image information that will be used to
				 * restrict disabled pixmap as well */

    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;
    }

    /*
     * Override the relief specified for the button if this is a checkbutton
     * or radiobutton and there's no indicator. The new relief is as follows:
     *      If the button is select  --> "sunken"
     *      If relief==overrelief    --> relief
     *      Otherwise                --> overrelief
     *
     * The effect we are trying to achieve is as follows:
     *
     *      value    mouse-over?   -->   relief
     *     -------  ------------        --------
     *       off        no               flat
     *       off        yes              raised
     *       on         no               sunken
     *       on         yes              sunken
     *
     * This is accomplished by configuring the checkbutton or radiobutton like
     * this:
     *
     *     -indicatoron 0 -overrelief raised -offrelief flat
     *
     * Bindings (see library/button.tcl) will copy the -overrelief into
     * -relief on mouseover. Hence, we can tell if we are in mouse-over by
     * comparing relief against overRelief. This is an aweful kludge, but it
     * gives use the desired behavior while keeping the code backwards
     * compatible.
     */

    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);

    /*
     * In order to avoid screen flashes, this function redraws the button in a
     * pixmap, then copies the pixmap to the screen in a single operation.
     * This means that there's no point in time where the on-screen image has
     * been cleared.
     */

    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);

    /*
     * Display image or bitmap or text for button.
     */

    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:
	    /*
	     * Image is above or below text.
	     */

	    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:
	    /*
	     * Image is left or right of text.
	     */

	    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:
	    /*
	     * Image and text are superimposed.
	     */

	    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) {
	    /*
	     * Do boundary clipping, so that Tk_RedrawImage is passed valid
	     * coordinates. [Bug 979239]
	     */

	    if (imageXOffset < 0) {
		imageXOffset = 0;
	    }
	    if (imageYOffset < 0) {
		imageYOffset = 0;
	    }
	    if (width > Tk_Width(tkwin)) {
		width = Tk_Width(tkwin);
	    }
	    if (height > Tk_Height(tkwin)) {
		height = Tk_Height(tkwin);
	    }
	    if ((width + imageXOffset) > Tk_Width(tkwin)) {
		imageXOffset = Tk_Width(tkwin) - width;
	    }
	    if ((height + imageYOffset) > Tk_Height(tkwin)) {
		imageYOffset = Tk_Height(tkwin) - height;
	    }

	    if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {
		Tk_RedrawImage(butPtr->selectImage, 0, 0,
			width, height, pixmap, imageXOffset, imageYOffset);
	    } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) {
		Tk_RedrawImage(butPtr->tristateImage, 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;
	    imageYOffset += y;
	    if (butPtr->image != NULL) {
		/*
		 * Do boundary clipping, so that Tk_RedrawImage is passed
		 * valid coordinates. [Bug 979239]
		 */

		if (imageXOffset < 0) {
		    imageXOffset = 0;
		}
		if (imageYOffset < 0) {
		    imageYOffset = 0;
		}
		if (width > Tk_Width(tkwin)) {
		    width = Tk_Width(tkwin);
		}
		if (height > Tk_Height(tkwin)) {
		    height = Tk_Height(tkwin);
		}
		if ((width + imageXOffset) > Tk_Width(tkwin)) {
		    imageXOffset = Tk_Width(tkwin) - width;
		}
		if ((height + imageYOffset) > Tk_Height(tkwin)) {
		    imageYOffset = Tk_Height(tkwin) - height;
		}

		if ((butPtr->selectImage != NULL) &&
			(butPtr->flags & SELECTED)) {
		    Tk_RedrawImage(butPtr->selectImage, 0, 0, width,
			    height, pixmap, imageXOffset, imageYOffset);
		} else if ((butPtr->tristateImage != NULL) &&
			(butPtr->flags & TRISTATED)) {
		    Tk_RedrawImage(butPtr->tristateImage, 0, 0, width,
			    height, pixmap, imageXOffset, imageYOffset);
		} else {
		    Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,
			    imageXOffset, imageYOffset);
		}
	    } 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;
	}
    }

    /*
     * Draw the indicator for check buttons and radio buttons. At this point,
     * x and y refer to the top-left corner of the text or image or bitmap.
     */

    if ((butPtr->type == TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
	if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) {
	    TkBorder *selBorder = (TkBorder *) butPtr->selectBorder;
	    XColor *selColor = NULL;

	    if (selBorder != NULL) {
		selColor = selBorder->bgColorPtr;
	    }
	    x -= butPtr->indicatorSpace/2;
	    y = Tk_Height(tkwin)/2;
	    TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y,
		    border, butPtr->normalFg, selColor, butPtr->disabledFg,
		    ((butPtr->flags & SELECTED) ? 1 :
			    (butPtr->flags & TRISTATED) ? 2 : 0),
		    (butPtr->state == STATE_DISABLED), CHECK_BUTTON);
	}
    } else if ((butPtr->type == TYPE_RADIO_BUTTON) && butPtr->indicatorOn) {
	if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) {
	    TkBorder *selBorder = (TkBorder *) butPtr->selectBorder;
	    XColor *selColor = NULL;

	    if (selBorder != NULL) {
		selColor = selBorder->bgColorPtr;
	    }
	    x -= butPtr->indicatorSpace/2;
	    y = Tk_Height(tkwin)/2;
	    TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y,
		    border, butPtr->normalFg, selColor, butPtr->disabledFg,
		    ((butPtr->flags & SELECTED) ? 1 :
			    (butPtr->flags & TRISTATED) ? 2 : 0),
		    (butPtr->state == STATE_DISABLED), RADIO_BUTTON);
	}
    }

    /*
     * If the button is disabled with a stipple rather than a special
     * foreground color, generate the stippled effect. If the widget is
     * selected and we use a different background color when selected, must
     * temporarily modify the GC so the stippling is the right color.
     */

    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);
	}

	/*
	 * Stipple the whole button if no disabledFg was specified, otherwise
	 * restrict stippling only to displayed image
	 */

	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);
	}
    }

    /*
     * Draw the border and traversal highlight last. This way, if the button's
     * contents overflow they'll be covered up by the border. This code is
     * complicated by the possible combinations of focus highlight and default
     * rings. We draw the focus and highlight rings using the highlight border
     * and highlight foreground color.
     */

    if (relief != TK_RELIEF_FLAT) {
	int inset = butPtr->highlightWidth;

	if (butPtr->defaultState == DEFAULT_ACTIVE) {
	    /*
	     * Draw the default ring with 2 pixels of space between the
	     * default ring and the button and the default ring and the focus
	     * ring. Note that we need to explicitly draw the space in the
	     * highlightBorder color to ensure that we overwrite any overflow
	     * text and/or a different button background color.
	     */

	    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) {
	    /*
	     * Leave room for the default ring and write over any text or
	     * background color.
	     */

	    Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0,
		    0, Tk_Width(tkwin), Tk_Height(tkwin), 5, TK_RELIEF_FLAT);
	    inset += 5;
	}

	/*
	 * Draw the button border.
	 */

	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);
	}

	/*
	 * Make sure the focus ring shrink-wraps the actual button, not the
	 * padding space left for a default ring.
	 */

	if (butPtr->defaultState == DEFAULT_NORMAL) {
	    TkDrawInsetFocusHighlight(tkwin, gc, butPtr->highlightWidth,
		    pixmap, 5);
	} else {
	    Tk_DrawFocusHighlight(tkwin, gc, butPtr->highlightWidth, pixmap);
	}
    }

    /*
     * Copy the information from the off-screen pixmap onto the screen, then
     * delete the 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);
}
Exemple #20
0
static Cursor
CreateCursorFromTableOrFile(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    Tk_Window tkwin,		/* Window in which cursor will be used. */
    int argc,
    const char **argv,		/* Cursor spec parsed into elements. */
    const struct TkCursorName *tkCursorPtr)
				/* Non-NULL when cursor is defined in Tk
				 * table. */
{
    Cursor cursor = None;

    int width, height, maskWidth, maskHeight;
    int xHot = -1, yHot = -1;
    int dummy1, dummy2;
    XColor fg, bg;
    const char *fgColor;
    const char *bgColor;
    int inTkTable = (tkCursorPtr != NULL);

    Display *display = Tk_Display(tkwin);
    Drawable drawable = RootWindowOfScreen(Tk_Screen(tkwin));

    Pixmap source = None;
    Pixmap mask = None;

    /*
     * A cursor defined in a file accepts either 2 or 4 arguments.
     *
     * {srcfile fg}
     * {srcfile maskfile fg bg}
     *
     * A cursor defined in the Tk table accepts 1, 2, or 3 arguments.
     *
     * {tkcursorname}
     * {tkcursorname fg}
     * {tkcursorname fg bg}
     */

    if (inTkTable) {
	/*
	 * This logic is like TkReadBitmapFile().
	 */

	char *data;

	data = TkGetBitmapData(NULL, tkCursorPtr->data, NULL,
		&width, &height, &xHot, &yHot);
	if (data == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error reading bitmap data for \"%s\"", argv[0]));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "BITMAP_DATA", NULL);
	    goto cleanup;
	}

	source = XCreateBitmapFromData(display, drawable, data, width,height);
	ckfree(data);
    } else {
	if (TkReadBitmapFile(display, drawable, &argv[0][1],
		(unsigned *) &width, (unsigned *) &height,
		&source, &xHot, &yHot) != BitmapSuccess) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "cleanup reading bitmap file \"%s\"", &argv[0][1]));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "BITMAP_FILE", NULL);
	    goto cleanup;
	}
    }

    if ((xHot < 0) || (yHot < 0) || (xHot >= width) || (yHot >= height)) {
	if (inTkTable) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad hot spot in bitmap data for \"%s\"", argv[0]));
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad hot spot in bitmap file \"%s\"", &argv[0][1]));
	}
	Tcl_SetErrorCode(interp, "TK", "CURSOR", "HOTSPOT", NULL);
	goto cleanup;
    }

    /*
     * Parse color names from optional fg and bg arguments
     */

    if (argc == 1) {
	fg.red = fg.green = fg.blue = 0;
	bg.red = bg.green = bg.blue = 65535;
    } else if (argc == 2) {
	fgColor = argv[1];
	if (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid color name \"%s\"", fgColor));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL);
	    goto cleanup;
	}
	if (inTkTable) {
	    bg.red = bg.green = bg.blue = 0;
	} else {
	    bg = fg;
	}
    } else {
	/* 3 or 4 arguments */
	if (inTkTable) {
	    fgColor = argv[1];
	    bgColor = argv[2];
	} else {
	    fgColor = argv[2];
	    bgColor = argv[3];
	}
	if (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid color name \"%s\"", fgColor));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL);
	    goto cleanup;
	}
	if (TkParseColor(display, Tk_Colormap(tkwin), bgColor, &bg) == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "invalid color name \"%s\"", bgColor));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL);
	    goto cleanup;
	}
    }

    /*
     * If there is no mask data, then create the cursor now.
     */

    if ((!inTkTable && (argc == 2)) || (inTkTable && tkCursorPtr->mask == NULL)) {
	cursor = XCreatePixmapCursor(display, source, source,
		&fg, &fg, (unsigned) xHot, (unsigned) yHot);
	goto cleanup;
    }

    /*
     * Parse bitmap mask data and create cursor with fg and bg colors.
     */

    if (inTkTable) {
	/*
	 * This logic is like TkReadBitmapFile().
	 */

	char *data;

	data = TkGetBitmapData(NULL, tkCursorPtr->mask, NULL,
		&maskWidth, &maskHeight, &dummy1, &dummy2);
	if (data == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error reading bitmap mask data for \"%s\"", argv[0]));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "MASK_DATA", NULL);
	    goto cleanup;
	}

	mask = XCreateBitmapFromData(display, drawable, data, maskWidth,
		maskHeight);

	ckfree(data);
    } else {
	if (TkReadBitmapFile(display, drawable, argv[1],
		(unsigned int *) &maskWidth, (unsigned int *) &maskHeight,
		&mask, &dummy1, &dummy2) != BitmapSuccess) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "cleanup reading bitmap file \"%s\"", argv[1]));
	    Tcl_SetErrorCode(interp, "TK", "CURSOR", "MASK_FILE", NULL);
	    goto cleanup;
	}
    }

    if ((maskWidth != width) || (maskHeight != height)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"source and mask bitmaps have different sizes", -1));
	Tcl_SetErrorCode(interp, "TK", "CURSOR", "SIZE_MATCH", NULL);
	goto cleanup;
    }

    cursor = XCreatePixmapCursor(display, source, mask,
	    &fg, &bg, (unsigned) xHot, (unsigned) yHot);

  cleanup:
    if (source != None) {
	Tk_FreePixmap(display, source);
    }
    if (mask != None) {
	Tk_FreePixmap(display, mask);
    }
    return cursor;
}