diff options
Diffstat (limited to 'generic/tkImage.c')
-rw-r--r-- | generic/tkImage.c | 947 |
1 files changed, 494 insertions, 453 deletions
diff --git a/generic/tkImage.c b/generic/tkImage.c index 35f013f..6c7c9cd 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -1,19 +1,17 @@ -/* +/* * tkImage.c -- * - * This module implements the image protocol, which allows lots - * of different kinds of images to be used in lots of different - * widgets. + * This module implements the image protocol, which allows lots of + * different kinds of images to be used in lots of different widgets. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" /* * Each call to Tk_GetImage returns a pointer to one of the following @@ -25,114 +23,162 @@ typedef struct Image { Tk_Window tkwin; /* Window passed to Tk_GetImage (needed to * "re-get" the image later if the manager * changes). */ - Display *display; /* Display for tkwin. Needed because when - * the image is eventually freed tkwin may - * not exist anymore. */ + Display *display; /* Display for tkwin. Needed because when the + * image is eventually freed tkwin may not + * exist anymore. */ struct ImageMaster *masterPtr; /* Master for this image (identifiers image * manager, for example). */ - ClientData instanceData; - /* One word argument to pass to image manager + ClientData instanceData; /* One word argument to pass to image manager * when dealing with this image instance. */ Tk_ImageChangedProc *changeProc; /* Code in widget to call when image changes * in a way that affects redisplay. */ - ClientData widgetClientData; - /* Argument to pass to changeProc. */ + ClientData widgetClientData;/* Argument to pass to changeProc. */ struct Image *nextPtr; /* Next in list of all image instances * associated with the same name. */ - } Image; /* - * For each image master there is one of the following structures, - * which represents a name in the image table and all of the images - * instantiated from it. Entries in mainPtr->imageTable point to - * these structures. + * For each image master there is one of the following structures, which + * represents a name in the image table and all of the images instantiated + * from it. Entries in mainPtr->imageTable point to these structures. */ typedef struct ImageMaster { - Tk_ImageType *typePtr; /* Information about image type. NULL means - * that no image manager owns this image: the + Tk_ImageType *typePtr; /* Information about image type. NULL means + * that no image manager owns this image: the * image was deleted. */ - ClientData masterData; /* One-word argument to pass to image mgr - * when dealing with the master, as opposed - * to instances. */ + ClientData masterData; /* One-word argument to pass to image mgr when + * dealing with the master, as opposed to + * instances. */ int width, height; /* Last known dimensions for image. */ - Tcl_HashTable *tablePtr; /* Pointer to hash table containing image - * (the imageTable field in some TkMainInfo + Tcl_HashTable *tablePtr; /* Pointer to hash table containing image (the + * imageTable field in some TkMainInfo * structure). */ - Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for - * this structure (used to delete the hash + Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for this + * structure (used to delete the hash * entry). */ Image *instancePtr; /* Pointer to first in list of instances * derived from this name. */ int deleted; /* Flag set when image is being deleted. */ - TkWindow *winPtr; /* Main window of interpreter (used to - * detect when the world is falling apart.) */ + TkWindow *winPtr; /* Main window of interpreter (used to detect + * when the world is falling apart.) */ } ImageMaster; typedef struct ThreadSpecificData { - Tk_ImageType *imageTypeList;/* First in a list of all known image - * types. */ - Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image - * types. */ -} ThreadSpecificData; + Tk_ImageType *imageTypeList;/* First in a list of all known image + * types. */ + Tk_ImageType *oldImageTypeList; + /* First in a list of all known old-style + * image types. */ + int initialized; /* Set to 1 if we've initialized the + * structure. */ +} ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Prototypes for local procedures: + * Prototypes for local functions: */ -static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); -static void EventuallyDeleteImage _ANSI_ARGS_((ImageMaster *masterPtr, - int forgetHashEntryNow)); +static void ImageTypeThreadExitProc(ClientData clientData); +static void DeleteImage(ImageMaster *masterPtr); +static void EventuallyDeleteImage(ImageMaster *masterPtr, + int forgetImageHashNow); + +/* + *---------------------------------------------------------------------- + * + * ImageTypeThreadExitProc -- + * + * Clean up the registered list of image types. + * + * Results: + * None. + * + * Side effects: + * The thread's linked lists of photo image formats is deleted. + * + *---------------------------------------------------------------------- + */ + +static void +ImageTypeThreadExitProc( + ClientData clientData) /* not used */ +{ + Tk_ImageType *freePtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + while (tsdPtr->oldImageTypeList != NULL) { + freePtr = tsdPtr->oldImageTypeList; + tsdPtr->oldImageTypeList = tsdPtr->oldImageTypeList->nextPtr; + ckfree((char *) freePtr); + } + while (tsdPtr->imageTypeList != NULL) { + freePtr = tsdPtr->imageTypeList; + tsdPtr->imageTypeList = tsdPtr->imageTypeList->nextPtr; + ckfree((char *) freePtr); + } +} /* *---------------------------------------------------------------------- * * Tk_CreateOldImageType, Tk_CreateImageType -- * - * This procedure is invoked by an image manager to tell Tk about - * a new kind of image and the procedures that manage the new type. - * The procedure is typically invoked during Tcl_AppInit. + * This function is invoked by an image manager to tell Tk about a new + * kind of image and the functions that manage the new type. The function + * is typically invoked during Tcl_AppInit. * * Results: * None. * * Side effects: - * The new image type is entered into a table used in the "image - * create" command. + * The new image type is entered into a table used in the "image create" + * command. * *---------------------------------------------------------------------- */ void -Tk_CreateOldImageType(typePtr) - Tk_ImageType *typePtr; /* Structure describing the type. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreateImageType previously. */ +Tk_CreateOldImageType( + Tk_ImageType *typePtr) /* Structure describing the type. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tk_ImageType *copyPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - typePtr->nextPtr = tsdPtr->oldImageTypeList; - tsdPtr->oldImageTypeList = typePtr; + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL); + } + copyPtr = (Tk_ImageType *) ckalloc(sizeof(Tk_ImageType)); + *copyPtr = *typePtr; + copyPtr->nextPtr = tsdPtr->oldImageTypeList; + tsdPtr->oldImageTypeList = copyPtr; } void -Tk_CreateImageType(typePtr) - Tk_ImageType *typePtr; /* Structure describing the type. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreateImageType previously. */ +Tk_CreateImageType( + Tk_ImageType *typePtr) /* Structure describing the type. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tk_ImageType *copyPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - typePtr->nextPtr = tsdPtr->imageTypeList; - tsdPtr->imageTypeList = typePtr; + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL); + } + copyPtr = (Tk_ImageType *) ckalloc(sizeof(Tk_ImageType)); + *copyPtr = *typePtr; + copyPtr->nextPtr = tsdPtr->imageTypeList; + tsdPtr->imageTypeList = copyPtr; } /* @@ -140,8 +186,8 @@ Tk_CreateImageType(typePtr) * * Tk_ImageObjCmd -- * - * This procedure is invoked to process the "image" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "image" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -153,30 +199,31 @@ Tk_CreateImageType(typePtr) */ int -Tk_ImageObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +Tk_ImageObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { static CONST char *imageOptions[] = { "create", "delete", "height", "inuse", "names", "type", "types", - "width", (char *) NULL + "width", NULL }; enum options { IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_INUSE, IMAGE_NAMES, IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH }; TkWindow *winPtr = (TkWindow *) clientData; - int i, new, firstOption, index; + int i, isNew, firstOption, index; Tk_ImageType *typePtr; ImageMaster *masterPtr; Image *imagePtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; - char idString[16 + TCL_INTEGER_SPACE], *name; + char idString[16 + TCL_INTEGER_SPACE]; TkDisplay *dispPtr = winPtr->dispPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + char *arg, *name; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { @@ -189,276 +236,256 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } switch ((enum options) index) { - case IMAGE_CREATE: { - char *arg; - Tcl_Obj **args; - int oldimage = 0; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?"); - return TCL_ERROR; - } + case IMAGE_CREATE: { + Tcl_Obj **args; + int oldimage = 0; + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?"); + return TCL_ERROR; + } - /* - * Look up the image type. - */ + /* + * Look up the image type. + */ - arg = Tcl_GetString(objv[2]); - for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { + arg = Tcl_GetString(objv[2]); + for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + if ((*arg == typePtr->name[0]) + && (strcmp(arg, typePtr->name) == 0)) { + break; + } + } + if (typePtr == NULL) { + oldimage = 1; + for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { if ((*arg == typePtr->name[0]) && (strcmp(arg, typePtr->name) == 0)) { break; } } - if (typePtr == NULL) { - oldimage = 1; - for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { - if ((*arg == typePtr->name[0]) - && (strcmp(arg, typePtr->name) == 0)) { - break; - } - } - } - if (typePtr == NULL) { - Tcl_AppendResult(interp, "image type \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } + } + if (typePtr == NULL) { + Tcl_AppendResult(interp, "image type \"", arg, "\" doesn't exist", + NULL); + return TCL_ERROR; + } - /* - * Figure out a name to use for the new image. - */ + /* + * Figure out a name to use for the new image. + */ - if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) { - Tcl_CmdInfo dummy; - do { - dispPtr->imageId++; - sprintf(idString, "image%d", dispPtr->imageId); - name = idString; - } while (Tcl_GetCommandInfo(interp, name, &dummy) != 0); - firstOption = 3; - } else { - TkWindow *topWin; - - name = arg; - firstOption = 4; - /* - * Need to check if the _command_ that we are about to - * create is the name of the current master widget - * command (normally "." but could have been renamed) - * and fail in that case before a really nasty and - * hard to stop crash happens. - */ - topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name); - if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) { - Tcl_AppendResult(interp, "images may not be named the ", - "same as the main window", (char *) NULL); - return TCL_ERROR; - } - } + if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) { + Tcl_CmdInfo dummy; + do { + dispPtr->imageId++; + sprintf(idString, "image%d", dispPtr->imageId); + name = idString; + } while (Tcl_GetCommandInfo(interp, name, &dummy) != 0); + firstOption = 3; + } else { + TkWindow *topWin; + + name = arg; + firstOption = 4; /* - * Create the data structure for the new image. + * Need to check if the _command_ that we are about to create is + * the name of the current master widget command (normally "." but + * could have been renamed) and fail in that case before a really + * nasty and hard to stop crash happens. */ - hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, - name, &new); - if (new) { - masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster)); - masterPtr->typePtr = NULL; - masterPtr->masterData = NULL; - masterPtr->width = masterPtr->height = 1; - masterPtr->tablePtr = &winPtr->mainPtr->imageTable; - masterPtr->hPtr = hPtr; - masterPtr->instancePtr = NULL; - masterPtr->deleted = 0; - masterPtr->winPtr = winPtr->mainPtr->winPtr; - Tcl_Preserve((ClientData) masterPtr->winPtr); - Tcl_SetHashValue(hPtr, masterPtr); - } else { - /* - * An image already exists by this name. Disconnect the - * instances from the master. - */ - - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - if (masterPtr->typePtr != NULL) { - for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; - imagePtr = imagePtr->nextPtr) { - (*masterPtr->typePtr->freeProc)( - imagePtr->instanceData, imagePtr->display); - (*imagePtr->changeProc)(imagePtr->widgetClientData, - 0, 0, masterPtr->width, masterPtr->height, - masterPtr->width, masterPtr->height); - } - (*masterPtr->typePtr->deleteProc)(masterPtr->masterData); - masterPtr->typePtr = NULL; - } + topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name); + if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) { + Tcl_AppendResult(interp, "images may not be named the ", + "same as the main window", NULL); + return TCL_ERROR; } + } + /* + * Create the data structure for the new image. + */ + + hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &isNew); + if (isNew) { + masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster)); + masterPtr->typePtr = NULL; + masterPtr->masterData = NULL; + masterPtr->width = masterPtr->height = 1; + masterPtr->tablePtr = &winPtr->mainPtr->imageTable; + masterPtr->hPtr = hPtr; + masterPtr->instancePtr = NULL; + masterPtr->deleted = 0; + masterPtr->winPtr = winPtr->mainPtr->winPtr; + Tcl_Preserve((ClientData) masterPtr->winPtr); + Tcl_SetHashValue(hPtr, masterPtr); + } else { /* - * Call the image type manager so that it can perform its own - * initialization, then re-"get" for any existing instances of - * the image. + * An image already exists by this name. Disconnect the instances + * from the master. */ - objv += firstOption; - objc -= firstOption; - args = (Tcl_Obj **) objv; - if (oldimage) { - int i; - args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *)); - for (i = 0; i < objc; i++) { - args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]); + masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->typePtr != NULL) { + for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; + imagePtr = imagePtr->nextPtr) { + (*masterPtr->typePtr->freeProc)(imagePtr->instanceData, + imagePtr->display); + (*imagePtr->changeProc)(imagePtr->widgetClientData, + 0, 0, masterPtr->width, masterPtr->height, + masterPtr->width, masterPtr->height); } - args[objc] = NULL; + (*masterPtr->typePtr->deleteProc)(masterPtr->masterData); + masterPtr->typePtr = NULL; } - Tcl_Preserve((ClientData) masterPtr); - if ((*typePtr->createProc)(interp, name, objc, - args, typePtr, (Tk_ImageMaster) masterPtr, - &masterPtr->masterData) != TCL_OK) { - EventuallyDeleteImage(masterPtr, 0); - Tcl_Release((ClientData) masterPtr); - if (oldimage) { - ckfree((char *) args); - } - return TCL_ERROR; + masterPtr->deleted = 0; + } + + /* + * Call the image type manager so that it can perform its own + * initialization, then re-"get" for any existing instances of the + * image. + */ + + objv += firstOption; + objc -= firstOption; + args = (Tcl_Obj **) objv; + if (oldimage) { + int i; + + args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]); } + args[objc] = NULL; + } + Tcl_Preserve((ClientData) masterPtr); + if ((*typePtr->createProc)(interp, name, objc, args, typePtr, + (Tk_ImageMaster)masterPtr, &masterPtr->masterData) != TCL_OK) { + EventuallyDeleteImage(masterPtr, 0); Tcl_Release((ClientData) masterPtr); if (oldimage) { ckfree((char *) args); } - masterPtr->typePtr = typePtr; - for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; - imagePtr = imagePtr->nextPtr) { - imagePtr->instanceData = (*typePtr->getProc)( - imagePtr->tkwin, masterPtr->masterData); - } - Tcl_SetResult(interp, - Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), - TCL_STATIC); - break; + return TCL_ERROR; } - case IMAGE_DELETE: { - for (i = 2; i < objc; i++) { - char *arg = Tcl_GetString(objv[i]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr)); - } - break; + Tcl_Release((ClientData) masterPtr); + if (oldimage) { + ckfree((char *) args); } - case IMAGE_HEIGHT: { - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height); - break; + masterPtr->typePtr = typePtr; + for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; + imagePtr = imagePtr->nextPtr) { + imagePtr->instanceData = (*typePtr->getProc)(imagePtr->tkwin, + masterPtr->masterData); } - - case IMAGE_INUSE: { - int count = 0; - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); + Tcl_SetResult(interp, + Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), + TCL_STATIC); + break; + } + case IMAGE_DELETE: + for (i = 2; i < objc; i++) { + arg = Tcl_GetString(objv[i]); hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; + goto alreadyDeleted; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - if (masterPtr->typePtr != NULL && masterPtr->instancePtr != NULL) { - count = 1; + if (masterPtr->deleted) { + goto alreadyDeleted; } - Tcl_SetBooleanObj(Tcl_GetObjResult(interp), count); - break; + DeleteImage(masterPtr); } - - case IMAGE_NAMES: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; + break; + case IMAGE_NAMES: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search); + for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->deleted) { + continue; } - hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search); - for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_AppendElement(interp, Tcl_GetHashKey( + Tcl_AppendElement(interp, Tcl_GetHashKey( &winPtr->mainPtr->imageTable, hPtr)); - } - break; } - - case IMAGE_TYPE: { - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + break; + case IMAGE_TYPES: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + Tcl_AppendElement(interp, typePtr->name); + } + for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + Tcl_AppendElement(interp, typePtr->name); + } + break; + + case IMAGE_HEIGHT: + case IMAGE_INUSE: + case IMAGE_TYPE: + case IMAGE_WIDTH: + /* + * These operations all parse virtually identically. First check to + * see if three args are given. Then get a non-deleted master from the + * third arg. + */ + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name"); + return TCL_ERROR; + } + + arg = Tcl_GetString(objv[2]); + hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); + if (hPtr == NULL) { + goto alreadyDeleted; + } + masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->deleted) { + goto alreadyDeleted; + } + + /* + * Now we read off the specific piece of data we were asked for. + */ + + switch ((enum options) index) { + case IMAGE_HEIGHT: + Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height); + break; + case IMAGE_INUSE: + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), + masterPtr->typePtr!=NULL && masterPtr->instancePtr!=NULL); + break; + case IMAGE_TYPE: if (masterPtr->typePtr != NULL) { Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC); } break; - } - case IMAGE_TYPES: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } - for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { - Tcl_AppendElement(interp, typePtr->name); - } - for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { - Tcl_AppendElement(interp, typePtr->name); - } - break; - } - case IMAGE_WIDTH: { - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + case IMAGE_WIDTH: Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width); break; + default: + Tcl_Panic("can't happen"); } + break; } return TCL_OK; + + alreadyDeleted: + Tcl_AppendResult(interp, "image \"", arg, "\" doesn't exist", NULL); + return TCL_ERROR; } /* @@ -466,33 +493,32 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) * * Tk_ImageChanged -- * - * This procedure is called by an image manager whenever something - * has happened that requires the image to be redrawn (some of its - * pixels have changed, or its size has changed). + * This function is called by an image manager whenever something has + * happened that requires the image to be redrawn (some of its pixels + * have changed, or its size has changed). * * Results: * None. * * Side effects: - * Any widgets that display the image are notified so that they - * can redisplay themselves as appropriate. + * Any widgets that display the image are notified so that they can + * redisplay themselves as appropriate. * *---------------------------------------------------------------------- */ void -Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, - imageHeight) - Tk_ImageMaster imageMaster; /* Image that needs redisplay. */ - int x, y; /* Coordinates of upper-left pixel of - * region of image that needs to be - * redrawn. */ - int width, height; /* Dimensions (in pixels) of region of - * image to redraw. If either dimension - * is zero then the image doesn't need to - * be redrawn (perhaps all that happened is - * that its size changed). */ - int imageWidth, imageHeight;/* New dimensions of image. */ +Tk_ImageChanged( + Tk_ImageMaster imageMaster, /* Image that needs redisplay. */ + int x, int y, /* Coordinates of upper-left pixel of region + * of image that needs to be redrawn. */ + int width, int height, /* Dimensions (in pixels) of region of image + * to redraw. If either dimension is zero then + * the image doesn't need to be redrawn + * (perhaps all that happened is that its size + * changed). */ + int imageWidth, int imageHeight) + /* New dimensions of image. */ { ImageMaster *masterPtr = (ImageMaster *) imageMaster; Image *imagePtr; @@ -500,7 +526,7 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, masterPtr->width = imageWidth; masterPtr->height = imageHeight; for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; - imagePtr = imagePtr->nextPtr) { + imagePtr = imagePtr->nextPtr) { (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y, width, height, imageWidth, imageHeight); } @@ -511,8 +537,8 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, * * Tk_NameOfImage -- * - * Given a token for an image master, this procedure returns - * the name of the image. + * Given a token for an image master, this function returns the name of + * the image. * * Results: * The return value is the string name for imageMaster. @@ -524,8 +550,8 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, */ CONST char * -Tk_NameOfImage(imageMaster) - Tk_ImageMaster imageMaster; /* Token for image. */ +Tk_NameOfImage( + Tk_ImageMaster imageMaster) /* Token for image. */ { ImageMaster *masterPtr = (ImageMaster *) imageMaster; @@ -540,36 +566,34 @@ Tk_NameOfImage(imageMaster) * * Tk_GetImage -- * - * This procedure is invoked by a widget when it wants to use - * a particular image in a particular window. + * This function is invoked by a widget when it wants to use a particular + * image in a particular window. * * Results: - * The return value is a token for the image. If there is no image - * by the given name, then NULL is returned and an error message is - * left in the interp's result. + * The return value is a token for the image. If there is no image by the + * given name, then NULL is returned and an error message is left in the + * interp's result. * * Side effects: - * Tk records the fact that the widget is using the image, and - * it will invoke changeProc later if the widget needs redisplay - * (i.e. its size changes or some of its pixels change). The - * caller must eventually invoke Tk_FreeImage when it no longer - * needs the image. + * Tk records the fact that the widget is using the image, and it will + * invoke changeProc later if the widget needs redisplay (i.e. its size + * changes or some of its pixels change). The caller must eventually + * invoke Tk_FreeImage when it no longer needs the image. * *---------------------------------------------------------------------- */ Tk_Image -Tk_GetImage(interp, tkwin, name, changeProc, clientData) - Tcl_Interp *interp; /* Place to leave error message if image - * can't be found. */ - Tk_Window tkwin; /* Token for window in which image will - * be used. */ - CONST char *name; /* Name of desired image. */ - Tk_ImageChangedProc *changeProc; - /* Procedure to invoke when redisplay is - * needed because image's pixels or size - * changed. */ - ClientData clientData; /* One-word argument to pass to damageProc. */ +Tk_GetImage( + Tcl_Interp *interp, /* Place to leave error message if image can't + * be found. */ + Tk_Window tkwin, /* Token for window in which image will be + * used. */ + CONST char *name, /* Name of desired image. */ + Tk_ImageChangedProc *changeProc, + /* Function to invoke when redisplay is needed + * because image's pixels or size changed. */ + ClientData clientData) /* One-word argument to pass to damageProc. */ { Tcl_HashEntry *hPtr; ImageMaster *masterPtr; @@ -583,6 +607,9 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) if (masterPtr->typePtr == NULL) { goto noSuchImage; } + if (masterPtr->deleted) { + goto noSuchImage; + } imagePtr = (Image *) ckalloc(sizeof(Image)); imagePtr->tkwin = tkwin; imagePtr->display = Tk_Display(tkwin); @@ -595,9 +622,10 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) masterPtr->instancePtr = imagePtr; return (Tk_Image) imagePtr; - noSuchImage: - Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist", - (char *) NULL); + noSuchImage: + if (interp) { + Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist", NULL); + } return NULL; } @@ -606,9 +634,9 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) * * Tk_FreeImage -- * - * This procedure is invoked by a widget when it no longer needs - * an image acquired by a previous call to Tk_GetImage. For each - * call to Tk_GetImage there must be exactly one call to Tk_FreeImage. + * This function is invoked by a widget when it no longer needs an image + * acquired by a previous call to Tk_GetImage. For each call to + * Tk_GetImage there must be exactly one call to Tk_FreeImage. * * Results: * None. @@ -620,9 +648,9 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) */ void -Tk_FreeImage(image) - Tk_Image image; /* Token for image that is no longer - * needed by a widget. */ +Tk_FreeImage( + Tk_Image image) /* Token for image that is no longer needed by + * a widget. */ { Image *imagePtr = (Image *) image; ImageMaster *masterPtr = imagePtr->masterPtr; @@ -647,16 +675,16 @@ Tk_FreeImage(image) } ckfree((char *) imagePtr); - /* - * If there are no more instances left for the master, and if the - * master image has been deleted, then delete the master too. + /* + * If there are no more instances left for the master, and if the master + * image has been deleted, then delete the master too. */ if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) { if (masterPtr->hPtr != NULL) { Tcl_DeleteHashEntry(masterPtr->hPtr); } - Tcl_Release(masterPtr->winPtr); + Tcl_Release((ClientData) masterPtr->winPtr); ckfree((char *) masterPtr); } } @@ -666,29 +694,29 @@ Tk_FreeImage(image) * * Tk_PostscriptImage -- * - * This procedure is called by widgets that contain images in order - * to redisplay an image on the screen or an off-screen pixmap. + * This function is called by widgets that contain images in order to + * redisplay an image on the screen or an off-screen pixmap. * * Results: * None. * * Side effects: - * The image's manager is notified, and it redraws the desired - * portion of the image before returning. + * The image's manager is notified, and it redraws the desired portion of + * the image before returning. * *---------------------------------------------------------------------- */ int -Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) - Tk_Image image; /* Token for image to redisplay. */ - Tcl_Interp *interp; - Tk_Window tkwin; - Tk_PostscriptInfo psinfo; /* postscript info */ - int x, y; /* Upper-left pixel of region in image that +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, height; /* Dimensions of region to redraw. */ - int prepass; + int width, int height, /* Dimensions of region to redraw. */ + int prepass) { Image *imagePtr = (Image *) image; int result; @@ -701,12 +729,13 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) /* * 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. + * Check if an image specific postscript-generation function exists; + * otherwise go on with generic code. */ if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) { @@ -721,12 +750,12 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) /* * 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. + * 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)); + 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); @@ -742,11 +771,13 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) (unsigned int)width, (unsigned int)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. + /* + * The XGetImage() function is apparently not implemented on this + * system. Just ignore it. */ + return TCL_OK; } result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y, @@ -755,39 +786,38 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) XDestroyImage(ximage); return result; } - + /* *---------------------------------------------------------------------- * * Tk_RedrawImage -- * - * This procedure is called by widgets that contain images in order - * to redisplay an image on the screen or an off-screen pixmap. + * This function is called by widgets that contain images in order to + * redisplay an image on the screen or an off-screen pixmap. * * Results: * None. * * Side effects: - * The image's manager is notified, and it redraws the desired - * portion of the image before returning. + * The image's manager is notified, and it redraws the desired portion of + * the image before returning. * *---------------------------------------------------------------------- */ void -Tk_RedrawImage(image, imageX, imageY, width, height, drawable, - drawableX, drawableY) - Tk_Image image; /* Token for image to redisplay. */ - int imageX, imageY; /* Upper-left pixel of region in image that +Tk_RedrawImage( + Tk_Image image, /* Token for image to redisplay. */ + int imageX, int imageY, /* Upper-left pixel of region in image that * needs to be redisplayed. */ - int width, height; /* Dimensions of region to redraw. */ - Drawable drawable; /* Drawable in which to display image - * (window or pixmap). If this is a pixmap, - * it must have the same depth as the window - * used in the Tk_GetImage call for the - * image. */ - int drawableX, drawableY; /* Coordinates in drawable that correspond - * to imageX and imageY. */ + int width, int height, /* Dimensions of region to redraw. */ + Drawable drawable, /* Drawable in which to display image (window + * or pixmap). If this is a pixmap, it must + * have the same depth as the window used in + * the Tk_GetImage call for the image. */ + int drawableX, int drawableY) + /* Coordinates in drawable that correspond to + * imageX and imageY. */ { Image *imagePtr = (Image *) image; @@ -829,11 +859,11 @@ Tk_RedrawImage(image, imageX, imageY, width, height, drawable, * * Tk_SizeOfImage -- * - * This procedure returns the current dimensions of an image. + * This function returns the current dimensions of an image. * * Results: - * The width and height of the image are returned in *widthPtr - * and *heightPtr. + * The width and height of the image are returned in *widthPtr and + * *heightPtr. * * Side effects: * None. @@ -842,10 +872,10 @@ Tk_RedrawImage(image, imageX, imageY, width, height, drawable, */ void -Tk_SizeOfImage(image, widthPtr, heightPtr) - Tk_Image image; /* Token for image whose size is wanted. */ - int *widthPtr; /* Return width of image here. */ - int *heightPtr; /* Return height of image here. */ +Tk_SizeOfImage( + Tk_Image image, /* Token for image whose size is wanted. */ + int *widthPtr, /* Return width of image here. */ + int *heightPtr) /* Return height of image here. */ { Image *imagePtr = (Image *) image; @@ -858,25 +888,23 @@ Tk_SizeOfImage(image, widthPtr, heightPtr) * * Tk_DeleteImage -- * - * Given the name of an image, this procedure destroys the - * image. + * Given the name of an image, this function destroys the image. * * Results: * None. * * Side effects: - * The image is destroyed; existing instances will display as - * blank areas. If no such image exists then the procedure does - * nothing. + * The image is destroyed; existing instances will display as blank + * areas. If no such image exists then the function does nothing. * *---------------------------------------------------------------------- */ void -Tk_DeleteImage(interp, name) - Tcl_Interp *interp; /* Interpreter in which the image was +Tk_DeleteImage( + Tcl_Interp *interp, /* Interpreter in which the image was * created. */ - CONST char *name; /* Name of image. */ + CONST char *name) /* Name of image. */ { Tcl_HashEntry *hPtr; TkWindow *winPtr; @@ -897,22 +925,22 @@ Tk_DeleteImage(interp, name) * * DeleteImage -- * - * This procedure is responsible for deleting an image. + * This function is responsible for deleting an image. * * Results: * None. * * Side effects: - * The connection is dropped between instances of this image and - * an image master. Image instances will redisplay themselves - * as empty areas, but existing instances will not be deleted. + * The connection is dropped between instances of this image and an image + * master. Image instances will redisplay themselves as empty areas, but + * existing instances will not be deleted. * *---------------------------------------------------------------------- */ static void -DeleteImage(masterPtr) - ImageMaster *masterPtr; /* Pointer to main data structure for image. */ +DeleteImage( + ImageMaster *masterPtr) /* Pointer to main data structure for image. */ { Image *imagePtr; Tk_ImageType *typePtr; @@ -922,9 +950,9 @@ DeleteImage(masterPtr) if (typePtr != NULL) { for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; imagePtr = imagePtr->nextPtr) { - (*typePtr->freeProc)(imagePtr->instanceData, - imagePtr->display); - (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0, + (*typePtr->freeProc)(imagePtr->instanceData, + imagePtr->display); + (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0, masterPtr->width, masterPtr->height, masterPtr->width, masterPtr->height); } @@ -936,6 +964,8 @@ DeleteImage(masterPtr) } Tcl_Release((ClientData) masterPtr->winPtr); ckfree((char *) masterPtr); + } else { + masterPtr->deleted = 1; } } @@ -950,19 +980,20 @@ DeleteImage(masterPtr) * None. * * Side effects: - * Image will get freed, though not until it is no longer - * Tcl_Preserve()d by anything. May be called multiple times on - * the same image without ill effects. + * Image will get freed, though not until it is no longer Tcl_Preserve()d + * by anything. May be called multiple times on the same image without + * ill effects. * *---------------------------------------------------------------------- */ static void -EventuallyDeleteImage(masterPtr, forgetHashEntryNow) - ImageMaster *masterPtr; /* Pointer to main data structure for image. */ - int forgetHashEntryNow; +EventuallyDeleteImage( + ImageMaster *masterPtr, /* Pointer to main data structure for image. */ + int forgetImageHashNow) /* Flag to say whether the hash table is about + * to vanish. */ { - if (forgetHashEntryNow) { + if (forgetImageHashNow) { masterPtr->hPtr = NULL; } if (!masterPtr->deleted) { @@ -977,10 +1008,9 @@ EventuallyDeleteImage(masterPtr, forgetHashEntryNow) * * TkDeleteAllImages -- * - * This procedure is called when an application is deleted. It - * calls back all of the managers for all images so that they - * can cleanup, then it deletes all of Tk's internal information - * about images. + * This function is called when an application is deleted. It calls back + * all of the managers for all images so that they can cleanup, then it + * deletes all of Tk's internal information about images. * * Results: * None. @@ -992,8 +1022,8 @@ EventuallyDeleteImage(masterPtr, forgetHashEntryNow) */ void -TkDeleteAllImages(mainPtr) - TkMainInfo *mainPtr; /* Structure describing application that is +TkDeleteAllImages( + TkMainInfo *mainPtr) /* Structure describing application that is * going away. */ { Tcl_HashSearch search; @@ -1011,15 +1041,14 @@ TkDeleteAllImages(mainPtr) * * Tk_GetImageMasterData -- * - * Given the name of an image, this procedure returns the type - * of the image and the clientData associated with its master. + * Given the name of an image, this function returns the type of the + * image and the clientData associated with its master. * * Results: - * If there is no image by the given name, then NULL is returned - * and a NULL value is stored at *typePtrPtr. Otherwise the return - * value is the clientData returned by the createProc when the - * image was created and a pointer to the type structure for the - * image is stored at *typePtrPtr. + * If there is no image by the given name, then NULL is returned and a + * NULL value is stored at *typePtrPtr. Otherwise the return value is the + * clientData returned by the createProc when the image was created and a + * pointer to the type structure for the image is stored at *typePtrPtr. * * Side effects: * None. @@ -1028,12 +1057,12 @@ TkDeleteAllImages(mainPtr) */ ClientData -Tk_GetImageMasterData(interp, name, typePtrPtr) - Tcl_Interp *interp; /* Interpreter in which the image was +Tk_GetImageMasterData( + Tcl_Interp *interp, /* Interpreter in which the image was * created. */ - CONST char *name; /* Name of image. */ - Tk_ImageType **typePtrPtr; /* Points to location to fill in with - * pointer to type information for image. */ + CONST char *name, /* Name of image. */ + Tk_ImageType **typePtrPtr) /* Points to location to fill in with pointer + * to type information for image. */ { Tcl_HashEntry *hPtr; TkWindow *winPtr; @@ -1046,36 +1075,41 @@ Tk_GetImageMasterData(interp, name, typePtrPtr) return NULL; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->deleted) { + *typePtrPtr = NULL; + return NULL; + } *typePtrPtr = masterPtr->typePtr; return masterPtr->masterData; } - + /* *---------------------------------------------------------------------- * * Tk_SetTSOrigin -- * - * Set the pattern origin of the tile to a common point (i.e. the - * origin (0,0) of the top level window) so that tiles from two - * different widgets will match up. This done by setting the - * GCTileStipOrigin field is set to the translated origin of the - * toplevel window in the hierarchy. + * Set the pattern origin of the tile to a common point (i.e. the origin + * (0,0) of the top level window) so that tiles from two different + * widgets will match up. This done by setting the GCTileStipOrigin field + * is set to the translated origin of the toplevel window in the + * hierarchy. * * Results: * None. * * Side Effects: - * The GCTileStipOrigin is reset in the GC. This will cause the - * tile origin to change when the GC is used for drawing. + * The GCTileStipOrigin is reset in the GC. This will cause the tile + * origin to change when the GC is used for drawing. * *---------------------------------------------------------------------- */ + /*ARGSUSED*/ void -Tk_SetTSOrigin(tkwin, gc, x, y) - Tk_Window tkwin; - GC gc; - int x, y; +Tk_SetTSOrigin( + Tk_Window tkwin, + GC gc, + int x, int y) { while (!Tk_TopWinHierarchy(tkwin)) { x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width; @@ -1084,4 +1118,11 @@ Tk_SetTSOrigin(tkwin, gc, x, y) } XSetTSOrigin(Tk_Display(tkwin), gc, x, y); } - + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |