예제 #1
0
파일: tkTreeDrag.c 프로젝트: aosm/tcl
static void
UpdateImage(
    TreeDragImage dragImage	/* Drag image record. */
    )
{
    TreeCtrl *tree = dragImage->tree;
    Tk_PhotoHandle photoH;
    XImage *ximage;
    int width = dragImage->bounds[2] - dragImage->bounds[0];
    int height = dragImage->bounds[3] - dragImage->bounds[1];
    int alpha = 128;
    XColor *colorPtr;

    if (dragImage->image != NULL) {
	Tk_FreeImage(dragImage->image);
	dragImage->image = NULL;
    }

    photoH = Tk_FindPhoto(tree->interp, "::TreeCtrl::ImageDrag");
    if (photoH == NULL) {
	Tcl_GlobalEval(tree->interp, "image create photo ::TreeCtrl::ImageDrag");
	photoH = Tk_FindPhoto(tree->interp, "::TreeCtrl::ImageDrag");
	if (photoH == NULL)
	    return;
    }

    /* Pixmap -> XImage */
    ximage = XGetImage(tree->display, dragImage->pixmap, 0, 0,
	    (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
    if (ximage == NULL)
	panic("tkTreeDrag.c:UpdateImage() ximage is NULL");

    /* XImage -> Tk_Image */
    colorPtr = Tk_GetColor(tree->interp, tree->tkwin, "pink");
    Tree_XImage2Photo(tree->interp, photoH, ximage, colorPtr->pixel, alpha);

    XDestroyImage(ximage);

    dragImage->image = Tk_GetImage(tree->interp, tree->tkwin,
	"::TreeCtrl::ImageDrag", NULL, (ClientData) NULL);
}
예제 #2
0
/*
 * Ttk_UseImage --
 * 	Acquire a Tk_Image from the cache.
 */
Tk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr)
{
    const char *imageName = Tcl_GetString(objPtr);
    int newEntry;
    Tcl_HashEntry *entryPtr =
	Tcl_CreateHashEntry(&cache->imageTable,imageName,&newEntry);
    Tk_Image image;

    InitCacheWindow(cache, tkwin);

    if (!newEntry) {
	return Tcl_GetHashValue(entryPtr);
    }

    image = Tk_GetImage(cache->interp, tkwin, imageName, NullImageChanged,0);
    Tcl_SetHashValue(entryPtr, image);

    if (!image) {
	Tcl_BackgroundException(cache->interp, TCL_ERROR);
    }

    return image;
}
예제 #3
0
/* TtkGetImageSpec --
 * 	Constructs a Ttk_ImageSpec * from a Tcl_Obj *.
 * 	Result must be released using TtkFreeImageSpec.
 *
 * TODO: Need a variant of this that takes a user-specified ImageChanged proc
 */
Ttk_ImageSpec *
TtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
{
    Ttk_ImageSpec *imageSpec = 0;
    int i = 0, n = 0, objc;
    Tcl_Obj **objv;

    imageSpec = (Ttk_ImageSpec *)ckalloc(sizeof(*imageSpec));
    imageSpec->baseImage = 0;
    imageSpec->mapCount = 0;
    imageSpec->states = 0;
    imageSpec->images = 0;

    if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
        goto error;
    }

    if ((objc % 2) != 1) {
        if (interp) {
            Tcl_SetResult(interp,
                          "image specification must contain an odd number of elements",
                          TCL_STATIC);
        }
        goto error;
    }

    n = (objc - 1) / 2;
    imageSpec->states = (Ttk_StateSpec*)ckalloc(n * sizeof(Ttk_StateSpec));
    imageSpec->images = (Tk_Image*)ckalloc(n * sizeof(Tk_Image *));

    /* Get base image:
    */
    imageSpec->baseImage = Tk_GetImage(
                               interp, tkwin, Tcl_GetString(objv[0]), NullImageChanged, NULL);
    if (!imageSpec->baseImage) {
        goto error;
    }

    /* Extract state and image specifications:
     */
    for (i = 0; i < n; ++i) {
        Tcl_Obj *stateSpec = objv[2*i + 1];
        const char *imageName = Tcl_GetString(objv[2*i + 2]);
        Ttk_StateSpec state;

        if (Ttk_GetStateSpecFromObj(interp, stateSpec, &state) != TCL_OK) {
            goto error;
        }
        imageSpec->states[i] = state;

        imageSpec->images[i] = Tk_GetImage(
                                   interp, tkwin, imageName, NullImageChanged, NULL);
        if (imageSpec->images[i] == NULL) {
            goto error;
        }
        imageSpec->mapCount = i+1;
    }

    return imageSpec;

error:
    TtkFreeImageSpec(imageSpec);
    return NULL;
}
예제 #4
0
static int
ConfigureImage(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Canvas canvas,		/* Canvas containing itemPtr. */
    Tk_Item *itemPtr,		/* Image item to reconfigure. */
    int objc,			/* Number of elements in objv.  */
    Tcl_Obj *const objv[],	/* Arguments describing things to configure. */
    int flags)			/* Flags to pass to Tk_ConfigureWidget. */
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;
    Tk_Window tkwin;
    Tk_Image image;

    tkwin = Tk_CanvasTkwin(canvas);
    if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc,
                                     (const char **) objv, (char *) imgPtr, flags|TK_CONFIG_OBJS)) {
        return TCL_ERROR;
    }

    /*
     * Create the image. Save the old image around and don't free it until
     * after the new one is allocated. This keeps the reference count from
     * going to zero so the image doesn't have to be recreated if it hasn't
     * changed.
     */

    if (imgPtr->activeImageString != NULL) {
        itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
    } else {
        itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
    }
    if (imgPtr->imageString != NULL) {
        image = Tk_GetImage(interp, tkwin, imgPtr->imageString,
                            ImageChangedProc, imgPtr);
        if (image == NULL) {
            return TCL_ERROR;
        }
    } else {
        image = NULL;
    }
    if (imgPtr->image != NULL) {
        Tk_FreeImage(imgPtr->image);
    }
    imgPtr->image = image;
    if (imgPtr->activeImageString != NULL) {
        image = Tk_GetImage(interp, tkwin, imgPtr->activeImageString,
                            ImageChangedProc, imgPtr);
        if (image == NULL) {
            return TCL_ERROR;
        }
    } else {
        image = NULL;
    }
    if (imgPtr->activeImage != NULL) {
        Tk_FreeImage(imgPtr->activeImage);
    }
    imgPtr->activeImage = image;
    if (imgPtr->disabledImageString != NULL) {
        image = Tk_GetImage(interp, tkwin, imgPtr->disabledImageString,
                            ImageChangedProc, imgPtr);
        if (image == NULL) {
            return TCL_ERROR;
        }
    } else {
        image = NULL;
    }
    if (imgPtr->disabledImage != NULL) {
        Tk_FreeImage(imgPtr->disabledImage);
    }
    imgPtr->disabledImage = image;
    ComputeImageBbox(canvas, imgPtr);
    return TCL_OK;
}
예제 #5
0
Tk_Image
HtmlImageImage(HtmlImage2 *pImage)
{
    assert(pImage && (pImage->isValid == 1 || pImage->isValid == 0));
    if (!pImage->isValid) {
        /* pImage->image is invalid. This happens if the underlying Tk
         * image, or the image that this is a scaled copy of, is changed
         * or deleted. It also happens the first time this function is
         * called after a call to HtmlImageScale().
         */ 
        Tk_PhotoHandle photo;
        Tk_PhotoImageBlock block;
        Tcl_Interp *interp = pImage->pImageServer->pTree->interp;
        HtmlImage2 *pUnscaled = pImage->pUnscaled;

        if (pUnscaled->pixmap) {
            Tcl_Obj *apObj[4];
            int rc;

/*printf("TODO: BAD. Have to recreate image to make scaled copy.\n");*/

            apObj[0] = pUnscaled->pImageName;
            apObj[1] = Tcl_NewStringObj("configure", -1);
            apObj[2] = Tcl_NewStringObj("-data", -1);
            apObj[3] = pUnscaled->pCompressed;

            Tcl_IncrRefCount(apObj[1]);
            Tcl_IncrRefCount(apObj[2]);
            Tcl_IncrRefCount(apObj[3]);
            pUnscaled->nIgnoreChange++;
            rc = Tcl_EvalObjv(interp, 4, apObj, TCL_EVAL_GLOBAL);
            pUnscaled->nIgnoreChange--;
            assert(rc==TCL_OK);
            Tcl_IncrRefCount(apObj[3]);
            Tcl_DecrRefCount(apObj[2]);
            Tcl_DecrRefCount(apObj[1]);
        }

        assert(pUnscaled);
        if (!pImage->pImageName) {
            /* If pImageName is still NULL, then create a new photo
             * image to write the scaled data to. Todo: Is it possible
             * to do this without invoking a script, creating the Tcl
             * command etc.?
             */
            Tk_Window win = pImage->pImageServer->pTree->tkwin;
            Tcl_Interp *interp = pImage->pImageServer->pTree->interp;
            const char *z;

            Tcl_Eval(interp, "image create photo");
            pImage->pImageName = Tcl_GetObjResult(interp);
            Tcl_IncrRefCount(pImage->pImageName);
            assert(0 == pImage->pDelete);
            assert(0 == pImage->image);

            z = Tcl_GetString(pImage->pImageName);
            pImage->image = Tk_GetImage(interp, win, z, imageChanged, pImage);
        }
        assert(pImage->image);

        CHECK_INTEGER_PLAUSIBILITY(pImage->width);
        CHECK_INTEGER_PLAUSIBILITY(pImage->height);
        CHECK_INTEGER_PLAUSIBILITY(pUnscaled->width);
        CHECK_INTEGER_PLAUSIBILITY(pUnscaled->height);

        /* Write the scaled data into image pImage->image */
        photo = Tk_FindPhoto(interp, Tcl_GetString(pUnscaled->pImageName));
        if (photo) {
            Tk_PhotoGetImage(photo, &block);
        }
        if (photo && block.pixelPtr) { 
            int x, y;                /* Iterator variables */
            int w, h;                /* Width and height of unscaled image */
            int sw, sh;              /* Width and height of scaled image */
            Tk_PhotoHandle s_photo;
            Tk_PhotoImageBlock s_block;

            sw = pImage->width;
            sh = pImage->height;
            w = pUnscaled->width;
            h = pUnscaled->height;
            s_photo = Tk_FindPhoto(interp, Tcl_GetString(pImage->pImageName));

            s_block.pixelPtr = (unsigned char *)HtmlAlloc("temp", sw * sh * 4);
            s_block.width = sw;
            s_block.height = sh;
            s_block.pitch = sw * 4;
            s_block.pixelSize = 4;
            s_block.offset[0] = 0;
            s_block.offset[1] = 1;
            s_block.offset[2] = 2;
            s_block.offset[3] = 3;

            for (x=0; x<sw; x++) {
                int orig_x = ((x * w) / sw);
                for (y=0; y<sh; y++) {
                    unsigned char *zOrig;
                    unsigned char *zScale;
                    int orig_y = ((y * h) / sh);

                    zOrig = &block.pixelPtr[
                        orig_x * block.pixelSize + orig_y * block.pitch];
                    zScale = &s_block.pixelPtr[
                        x * s_block.pixelSize + y * s_block.pitch];

                    zScale[0] = zOrig[block.offset[0]];
                    zScale[1] = zOrig[block.offset[1]];
                    zScale[2] = zOrig[block.offset[2]];
                    zScale[3] = zOrig[block.offset[3]];
                }
            }
            photoputblock(interp, s_photo, &s_block, 0, 0, sw, sh, 0);
            HtmlFree(s_block.pixelPtr);
        } else {
            return HtmlImageImage(pImage->pUnscaled);
        }

        pImage->isValid = 1;
        if (pUnscaled->pixmap) {
            Tcl_Obj *apObj[4];

            apObj[0] = Tcl_NewStringObj("image", -1);
            apObj[1] = Tcl_NewStringObj("create", -1);
            apObj[2] = Tcl_NewStringObj("photo", -1);
            apObj[3] = pUnscaled->pImageName;

            Tcl_IncrRefCount(apObj[0]);
            Tcl_IncrRefCount(apObj[1]);
            Tcl_IncrRefCount(apObj[2]);
            pUnscaled->nIgnoreChange++;
            Tcl_EvalObjv(interp, 4, apObj, TCL_EVAL_GLOBAL);
            pUnscaled->nIgnoreChange--;
            Tcl_DecrRefCount(apObj[2]);
            Tcl_DecrRefCount(apObj[1]);
            Tcl_IncrRefCount(apObj[0]);
        }
    }

    return pImage->image;
}
예제 #6
0
/*
 *---------------------------------------------------------------------------
 *
 * HtmlImageServerGet --
 *
 *     Retrieve an HtmlImage2 object for the image at URL zUrl from 
 *     an image-server. The caller should match this call with a single
 *     HtmlImageFree() when the image object is no longer required.
 *
 *     If the image is not already in the cache, the Tcl script 
 *     configured as the widget -imagecmd is invoked. If this command
 *     raises an error or returns an invalid result, then this function 
 *     returns NULL. A Tcl back-ground error is propagated in this case 
 *     also.
 *
 * Results:
 *     Pointer to HtmlImage2 object containing the image from zUrl, or
 *     NULL, if zUrl was invalid for some reason.
 *
 * Side effects:
 *     May invoke -imagecmd script.
 *
 *---------------------------------------------------------------------------
 */
HtmlImage2 *
HtmlImageServerGet (HtmlImageServer *p, const char *zUrl) 
{
    Tcl_Obj *pImageCmd = p->pTree->options.imagecmd;
    Tcl_Interp *interp = p->pTree->interp;
    Tcl_HashEntry *pEntry = 0;
    HtmlImage2 *pImage = 0;

    /* Try to find the requested image in the hash table. */
    if (pImageCmd) {
        int new_entry;
        pEntry = Tcl_CreateHashEntry(&p->aImage, zUrl, &new_entry);
        if (new_entry) {
            Tcl_Obj *pEval;
            Tcl_Obj *pResult;
            int rc;
            int nObj;
            Tcl_Obj **apObj = 0;
            Tk_Image img;
           
	    /* The image could not be found in the hash table and an 
             * -imagecmd callback is configured. The callback script 
             * must be executed to obtain an image. Build up a script 
             * in pEval and execute it. Put the result in variable pResult.
             */
            pEval = Tcl_DuplicateObj(pImageCmd);
            Tcl_IncrRefCount(pEval);
            Tcl_ListObjAppendElement(interp, pEval, Tcl_NewStringObj(zUrl, -1));
            rc = Tcl_EvalObjEx(interp, pEval, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
            Tcl_DecrRefCount(pEval);
            if (rc != TCL_OK) {
                goto image_get_out;
            }
            pResult = Tcl_GetObjResult(interp);
    
            /* Read the result into array apObj. If the result was
             * not a valid Tcl list, return NULL and raise a background
             * error about the badly formed list.
             */
            rc = Tcl_ListObjGetElements(interp, pResult, &nObj, &apObj);
            if (rc != TCL_OK) {
                goto image_get_out;
            }
            if (nObj==0) {
                Tcl_DeleteHashEntry(pEntry);
                goto image_unavailable;
            }

            pImage = HtmlNew(HtmlImage2);
            if (nObj == 1 || nObj == 2) {
                img = Tk_GetImage(
                    interp, p->pTree->tkwin, Tcl_GetString(apObj[0]),
                    imageChanged, pImage
                );
            }
            if ((nObj != 1 && nObj != 2) || !img) {
                Tcl_ResetResult(interp);
                Tcl_AppendResult(interp,  "-imagecmd returned bad value", 0);
                HtmlFree(pImage);
                pImage = 0;
                goto image_get_out;
            }

            Tcl_SetHashValue(pEntry, (ClientData)pImage);
            Tcl_IncrRefCount(apObj[0]);
            pImage->pImageName = apObj[0];
            if (nObj == 2) {
                Tcl_IncrRefCount(apObj[1]);
                pImage->pDelete = apObj[1];
            }
            pImage->pImageServer = p;
            pImage->zUrl = Tcl_GetHashKey(&p->aImage, pEntry);
            pImage->image = img;
            Tk_SizeOfImage(pImage->image, &pImage->width, &pImage->height);
            pImage->isValid = 1;
            HtmlImagePixmap(pImage);
        }
    }

image_get_out:
    pImage = (HtmlImage2 *)(pEntry ? Tcl_GetHashValue(pEntry) : 0);
    HtmlImageRef(pImage);
    if (!pImage && pImageCmd) {
        Tcl_BackgroundError(interp);
        Tcl_ResetResult(interp);
        assert(pEntry);
        Tcl_DeleteHashEntry(pEntry);
    }

image_unavailable:
    return pImage;
}
예제 #7
0
/*
 *---------------------------------------------------------------------------
 *
 * HtmlImageTile --
 *
 * Results:
 *
 * Side effects:
 *     None.
 *
 *---------------------------------------------------------------------------
 */
Tk_Image 
HtmlImageTile(
    HtmlImage2 *pImage,    /* Image object */
    int *pW,
    int *pH
    )
{
    HtmlTree *pTree = pImage->pImageServer->pTree;
    Tcl_Interp *interp = pTree->interp;

    Tcl_Obj *pTileName;             /* Name of tile image at the script level */
    Tk_PhotoHandle tilephoto;       /* Photo of tile */
    Tk_PhotoImageBlock tileblock;   /* Block of tile image */
    int iTileWidth;
    int iTileHeight;

    Tk_PhotoHandle origphoto;
    Tk_PhotoImageBlock origblock;

    int x;
    int y;

    /* The tile has already been generated. Return it. */
    if (pImage->pTileName) {
        goto return_tile;
    }

    /* The image is too big to bother with a tile. Return the original. */
    if (!tilesize(pImage, &iTileWidth, &iTileHeight)) {
        goto return_original;
    }

    /* Retrieve the block for the original image */
    origphoto = Tk_FindPhoto(interp, Tcl_GetString(pImage->pImageName));
    if (!origphoto) goto return_original;
    Tk_PhotoGetImage(origphoto, &origblock);
    if (!origblock.pixelPtr) goto return_original;

    /* Create the tile image. Surely there is a way to do this without
     * invoking a script, but I haven't found it yet.
     */
    Tcl_Eval(interp, "image create photo");
    pTileName = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(pTileName);
    tilephoto = Tk_FindPhoto(interp, Tcl_GetString(pTileName));
    Tk_PhotoGetImage(tilephoto, &tileblock);
    pImage->pTileName = pTileName;
    pImage->tile = Tk_GetImage(
            interp, pTree->tkwin, Tcl_GetString(pTileName), imageChanged, 0
    );

    /* Allocate a block to write the tile data into. */
    tileblock.pixelPtr = (unsigned char *)HtmlAlloc(
        "temp", iTileWidth * iTileHeight * 4
    );
    tileblock.width = iTileWidth;
    tileblock.height = iTileHeight;
    tileblock.pitch = iTileWidth * 4;
    tileblock.pixelSize = 4;
    tileblock.offset[0] = 0;
    tileblock.offset[1] = 1;
    tileblock.offset[2] = 2;
    tileblock.offset[3] = 3;

    for (x = 0; x < iTileWidth; x++) {
        for (y = 0; y < iTileHeight; y++) {
            unsigned char *zOrig;
            unsigned char *zScale;
            zOrig = &origblock.pixelPtr[
                 (x % pImage->width) *origblock.pixelSize + 
                 (y % pImage->height) * origblock.pitch
            ];
            zScale = &tileblock.pixelPtr[x * 4 + y * tileblock.pitch];
            zScale[0] = zOrig[origblock.offset[0]];
            zScale[1] = zOrig[origblock.offset[1]];
            zScale[2] = zOrig[origblock.offset[2]];
            zScale[3] = zOrig[origblock.offset[3]];
        }
    }

    photoputblock(interp,tilephoto,&tileblock,0,0,iTileWidth,iTileHeight,0);
    HtmlFree(tileblock.pixelPtr);
    pImage->iTileWidth = iTileWidth;
    pImage->iTileHeight = iTileHeight;

return_tile:
    *pW = pImage->iTileWidth;
    *pH = pImage->iTileHeight;
    return pImage->tile;

return_original:
    HtmlImageSize(pImage, pW, pH);
    return HtmlImageImage(pImage);
}
예제 #8
0
static int
ConfigureMenuButton(
    Tcl_Interp *interp,		/* Used for error reporting. */
    register TkMenuButton *mbPtr,
    /* Information about widget; may or may not
     * already have values for some fields. */
    int objc,			/* Number of valid entries in objv. */
    Tcl_Obj *const objv[])	/* Arguments. */
{
    Tk_SavedOptions savedOptions;
    Tcl_Obj *errorResult = NULL;
    int error;
    Tk_Image image;

    /*
     * Eliminate any existing trace on variables monitored by the menubutton.
     */

    if (mbPtr->textVarName != NULL) {
        Tcl_UntraceVar(interp, mbPtr->textVarName,
                       TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                       MenuButtonTextVarProc, mbPtr);
    }

    /*
     * The following loop is potentially executed twice. During the first pass
     * configuration options get set to their new values. If there is an error
     * in this pass, we execute a second pass to restore all the options to
     * their previous values.
     */

    for (error = 0; error <= 1; error++) {
        if (!error) {
            /*
             * First pass: set options to new values.
             */

            if (Tk_SetOptions(interp, (char *) mbPtr,
                              mbPtr->optionTable, objc, objv,
                              mbPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
                continue;
            }
        } else {
            /*
             * Second pass: restore options to old values.
             */

            errorResult = Tcl_GetObjResult(interp);
            Tcl_IncrRefCount(errorResult);
            Tk_RestoreSavedOptions(&savedOptions);
        }

        /*
         * A few options need special processing, such as setting the
         * background from a 3-D border, or filling in complicated defaults
         * that couldn't be specified to Tk_SetOptions.
         */

        if ((mbPtr->state == STATE_ACTIVE)
                && !Tk_StrictMotif(mbPtr->tkwin)) {
            Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);
        } else {
            Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);
        }

        if (mbPtr->highlightWidth < 0) {
            mbPtr->highlightWidth = 0;
        }

        if (mbPtr->padX < 0) {
            mbPtr->padX = 0;
        }
        if (mbPtr->padY < 0) {
            mbPtr->padY = 0;
        }

        /*
         * Get the image for the widget, if there is one. Allocate the new
         * image before freeing the old one, so that the reference count
         * doesn't go to zero and cause image data to be discarded.
         */

        if (mbPtr->imageString != NULL) {
            image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,
                                mbPtr->imageString, MenuButtonImageProc, mbPtr);
            if (image == NULL) {
                return TCL_ERROR;
            }
        } else {
            image = NULL;
        }
        if (mbPtr->image != NULL) {
            Tk_FreeImage(mbPtr->image);
        }
        mbPtr->image = image;

        /*
         * Recompute the geometry for the button.
         */

        if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {
            if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString,
                             &mbPtr->width) != TCL_OK) {
widthError:
                Tcl_AddErrorInfo(interp, "\n    (processing -width option)");
                continue;
            }
            if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString,
                             &mbPtr->height) != TCL_OK) {
heightError:
                Tcl_AddErrorInfo(interp, "\n    (processing -height option)");
                continue;
            }
        } else {
            if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width)
                    != TCL_OK) {
                goto widthError;
            }
            if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height)
                    != TCL_OK) {
                goto heightError;
            }
        }
        break;
    }

    if (!error) {
        Tk_FreeSavedOptions(&savedOptions);
    }

    if (mbPtr->textVarName != NULL) {
        /*
         * If no image or -compound is used, display the value of a variable.
         * Set up a trace to watch for any changes in it, create the variable
         * if it doesn't exist, and fetch its current value.
         */
        const char *value;

        value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);
        if (value == NULL) {
            Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,
                       TCL_GLOBAL_ONLY);
        } else {
            if (mbPtr->text != NULL) {
                ckfree(mbPtr->text);
            }
            mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
            strcpy(mbPtr->text, value);
        }
        Tcl_TraceVar(interp, mbPtr->textVarName,
                     TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                     MenuButtonTextVarProc, mbPtr);
    }

    TkMenuButtonWorldChanged(mbPtr);
    if (error) {
        Tcl_SetObjResult(interp, errorResult);
        Tcl_DecrRefCount(errorResult);
        return TCL_ERROR;
    }
    return TCL_OK;
}
예제 #9
0
/*
** Given an <IMG> markup, find or create an appropriate HtmlImage
** structure and return a pointer to that structure.  NULL might
** be returned.
**
** This routine may invoke a callback procedure which could delete
** the HTML widget.  Use HtmlLock() if necessary to preserve the
** widget structure.
*/
HtmlImage *HtmlGetImage(HtmlWidget *htmlPtr, HtmlElement *p){
  char *zWidth;
  char *zHeight;
  char *zSrc;
  const char *zImageName;
  HtmlImage *pImage;
  int result;
  Tcl_DString cmd;
  int lenSrc, lenW, lenH;   /* Lengths of various strings */

  if( p->base.type!=Html_IMG ){ CANT_HAPPEN; return 0; }
  if( htmlPtr->zGetImage==0 || htmlPtr->zGetImage[0]==0 ){
    TestPoint(0);
    return 0;
  }
  zSrc = HtmlMarkupArg(p, "src", 0);
  if( zSrc==0 ){
    return 0;
  }
  HtmlLock(htmlPtr);
  zSrc = HtmlResolveUri(htmlPtr, zSrc);
  if( HtmlUnlock(htmlPtr) || zSrc==0 ) return 0;
  zWidth = HtmlMarkupArg(p, "width", "");
  zHeight = HtmlMarkupArg(p, "height", "");
  for(pImage=htmlPtr->imageList; pImage; pImage=pImage->pNext){
    if( strcmp(pImage->zUrl,zSrc)==0
    &&  strcmp(pImage->zWidth, zWidth)==0
    &&  strcmp(pImage->zHeight, zHeight)==0 ){
      HtmlFree(zSrc);
      return pImage;
    }
  }
  Tcl_DStringInit(&cmd);
  Tcl_DStringAppend(&cmd, htmlPtr->zGetImage, -1);
  Tcl_DStringAppendElement(&cmd,zSrc);
  Tcl_DStringAppendElement(&cmd,zWidth);
  Tcl_DStringAppendElement(&cmd,zHeight);
  Tcl_DStringStartSublist(&cmd);
  HtmlAppendArglist(&cmd, p);
  Tcl_DStringEndSublist(&cmd);
  HtmlLock(htmlPtr);
  result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd));
  Tcl_DStringFree(&cmd);
  if( HtmlUnlock(htmlPtr) ){
    HtmlFree(zSrc);
  }
  zImageName = Tcl_GetStringResult(htmlPtr->interp);
  lenSrc = strlen(zSrc);
  lenW = strlen(zWidth);
  lenH = strlen(zHeight);
  pImage = HtmlAlloc( sizeof(HtmlImage) + lenSrc + lenW + lenH + 3 );
  memset(pImage,0,sizeof(HtmlImage));
  pImage->htmlPtr = htmlPtr;
  pImage->zUrl = (char*)&pImage[1];
  strcpy(pImage->zUrl,zSrc);
  HtmlFree(zSrc);
  pImage->zWidth = &pImage->zUrl[lenSrc+1];
  strcpy(pImage->zWidth, zWidth);
  pImage->zHeight = &pImage->zWidth[lenW+1];
  strcpy(pImage->zHeight, zHeight);
  pImage->w = 0;
  pImage->h = 0;
  if( result==TCL_OK ){
    pImage->image = Tk_GetImage(htmlPtr->interp, htmlPtr->clipwin,
                                zImageName, ImageChangeProc, pImage);
    TestPoint(0);
  }else{
    Tcl_AddErrorInfo(htmlPtr->interp,
      "\n    (\"-imagecommand\" command executed by html widget)");
    Tcl_BackgroundError(htmlPtr->interp);
    pImage->image = 0;
    TestPoint(0);
  }
  if( pImage->image==0 ){
    HtmlFree((char*)pImage);
    TestPoint(0);
    return 0;
  }
  pImage->pNext = htmlPtr->imageList;
  htmlPtr->imageList = pImage;
  TestPoint(0);
  Tcl_ResetResult(htmlPtr->interp);
  return pImage;
}