home *** CD-ROM | disk | FTP | other *** search
/ Ultra Pack / UltraComputing Partner Applications.iso / SunLabs / tclTK / src / tk4.0 / tkImage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-06  |  21.5 KB  |  747 lines

  1. /* 
  2.  * tkImage.c --
  3.  *
  4.  *    This module implements the image protocol, which allows lots
  5.  *    of different kinds of images to be used in lots of different
  6.  *    widgets.
  7.  *
  8.  * Copyright (c) 1994 The Regents of the University of California.
  9.  * Copyright (c) 1994-1995 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  */
  14.  
  15. static char sccsid[] = "@(#) tkImage.c 1.8 95/03/17 16:01:56";
  16.  
  17. #include "tkInt.h"
  18. #include "tkPort.h"
  19.  
  20. /*
  21.  * Each call to Tk_GetImage returns a pointer to one of the following
  22.  * structures, which is used as a token by clients (widgets) that
  23.  * display images.
  24.  */
  25.  
  26. typedef struct Image {
  27.     Tk_Window tkwin;        /* Window passed to Tk_GetImage (needed to
  28.                  * "re-get" the image later if the manager
  29.                  * changes). */
  30.     Display *display;        /* Display for tkwin.  Needed because when
  31.                  * the image is eventually freed tkwin may
  32.                  * not exist anymore. */
  33.     struct ImageMaster *masterPtr;
  34.                 /* Master for this image (identifiers image
  35.                  * manager, for example). */
  36.     ClientData instanceData;
  37.                 /* One word argument to pass to image manager
  38.                  * when dealing with this image instance. */
  39.     Tk_ImageChangedProc *changeProc;
  40.                 /* Code in widget to call when image changes
  41.                  * in a way that affects redisplay. */
  42.     ClientData widgetClientData;
  43.                 /* Argument to pass to changeProc. */
  44.     struct Image *nextPtr;    /* Next in list of all image instances
  45.                  * associated with the same name. */
  46.  
  47. } Image;
  48.  
  49. /*
  50.  * For each image master there is one of the following structures,
  51.  * which represents a name in the image table and all of the images
  52.  * instantiated from it.  Entries in mainPtr->imageTable point to
  53.  * these structures.
  54.  */
  55.  
  56. typedef struct ImageMaster {
  57.     Tk_ImageType *typePtr;    /* Information about image type.  NULL means
  58.                  * that no image manager owns this image:  the
  59.                  * image was deleted. */
  60.     ClientData masterData;    /* One-word argument to pass to image mgr
  61.                  * when dealing with the master, as opposed
  62.                  * to instances. */
  63.     int width, height;        /* Last known dimensions for image. */
  64.     Tcl_HashTable *tablePtr;    /* Pointer to hash table containing image
  65.                  * (the imageTable field in some TkMainInfo
  66.                  * structure). */
  67.     Tcl_HashEntry *hPtr;    /* Hash entry in mainPtr->imageTable for
  68.                  * this structure (used to delete the hash
  69.                  * entry). */
  70.     Image *instancePtr;        /* Pointer to first in list of instances
  71.                  * derived from this name. */
  72. } ImageMaster;
  73.  
  74. /*
  75.  * The following variable points to the first in a list of all known
  76.  * image types.
  77.  */
  78.  
  79. static Tk_ImageType *imageTypeList = NULL;
  80.  
  81. /*
  82.  * Prototypes for local procedures:
  83.  */
  84.  
  85. static void        DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
  86.  
  87. /*
  88.  *----------------------------------------------------------------------
  89.  *
  90.  * Tk_CreateImageType --
  91.  *
  92.  *    This procedure is invoked by an image manager to tell Tk about
  93.  *    a new kind of image and the procedures that manage the new type.
  94.  *    The procedure is typically invoked during Tcl_AppInit.
  95.  *
  96.  * Results:
  97.  *    None.
  98.  *
  99.  * Side effects:
  100.  *    The new image type is entered into a table used in the "image
  101.  *    create" command.
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105.  
  106. void
  107. Tk_CreateImageType(typePtr)
  108.     Tk_ImageType *typePtr;    /* Structure describing the type.  All of
  109.                  * the fields except "nextPtr" must be filled
  110.                  * in by caller.  Must not have been passed
  111.                  * to Tk_CreateImageType previously. */
  112. {
  113.     Tk_ImageType *typePtr2;
  114.  
  115.     typePtr2 = (Tk_ImageType *) ckalloc(sizeof(Tk_ImageType));
  116.     *typePtr2 = *typePtr;
  117.     typePtr2->name = (char *) ckalloc((unsigned) (strlen(typePtr->name) + 1));
  118.     strcpy(typePtr2->name, typePtr->name);
  119.     typePtr2->nextPtr = imageTypeList;
  120.     imageTypeList = typePtr2;
  121. }
  122.  
  123. /*
  124.  *----------------------------------------------------------------------
  125.  *
  126.  * Tk_ImageCmd --
  127.  *
  128.  *    This procedure is invoked to process the "image" Tcl command.
  129.  *    See the user documentation for details on what it does.
  130.  *
  131.  * Results:
  132.  *    A standard Tcl result.
  133.  *
  134.  * Side effects:
  135.  *    See the user documentation.
  136.  *
  137.  *----------------------------------------------------------------------
  138.  */
  139.  
  140. int
  141. Tk_ImageCmd(clientData, interp, argc, argv)
  142.     ClientData clientData;    /* Main window associated with interpreter. */
  143.     Tcl_Interp *interp;        /* Current interpreter. */
  144.     int argc;            /* Number of arguments. */
  145.     char **argv;        /* Argument strings. */
  146. {
  147.     TkWindow *winPtr = (TkWindow *) clientData;
  148.     int c, i, new, firstOption;
  149.     size_t length;
  150.     Tk_ImageType *typePtr;
  151.     ImageMaster *masterPtr;
  152.     Image *imagePtr;
  153.     Tcl_HashEntry *hPtr;
  154.     Tcl_HashSearch search;
  155.     char idString[30], *name;
  156.     static int id = 0;
  157.  
  158.     if (argc < 2) {
  159.     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  160.         " option ?args?\"", (char *) NULL);
  161.     return TCL_ERROR;
  162.     }
  163.     c = argv[1][0];
  164.     length = strlen(argv[1]);
  165.     if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)) {
  166.     if (argc < 3) {
  167.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  168.             " create type ?name? ?options?\"", (char *) NULL);
  169.         return TCL_ERROR;
  170.     }
  171.     c = argv[2][0];
  172.  
  173.     /*
  174.      * Look up the image type.
  175.      */
  176.  
  177.     for (typePtr = imageTypeList; typePtr != NULL;
  178.         typePtr = typePtr->nextPtr) {
  179.         if ((c == typePtr->name[0])
  180.             && (strcmp(argv[2], typePtr->name) == 0)) {
  181.         break;
  182.         }
  183.     }
  184.     if (typePtr == NULL) {
  185.         Tcl_AppendResult(interp, "image type \"", argv[2],
  186.             "\" doesn't exist", (char *) NULL);
  187.         return TCL_ERROR;
  188.     }
  189.  
  190.     /*
  191.      * Figure out a name to use for the new image.
  192.      */
  193.  
  194.     if ((argc == 3) || (argv[3][0] == '-')) {
  195.         id++;
  196.         sprintf(idString, "image%d", id);
  197.         name = idString;
  198.         firstOption = 3;
  199.     } else {
  200.         name = argv[3];
  201.         firstOption = 4;
  202.     }
  203.  
  204.     /*
  205.      * Create the data structure for the new image.
  206.      */
  207.  
  208.     hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &new);
  209.     if (new) {
  210.         masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
  211.         masterPtr->typePtr = NULL;
  212.         masterPtr->masterData = NULL;
  213.         masterPtr->width = masterPtr->height = 1;
  214.         masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
  215.         masterPtr->hPtr = hPtr;
  216.         masterPtr->instancePtr = NULL;
  217.         Tcl_SetHashValue(hPtr, masterPtr);
  218.     } else {
  219.         /*
  220.          * An image already exists by this name.  Disconnect the
  221.          * instances from the master.
  222.          */
  223.  
  224.         masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  225.         if (masterPtr->typePtr != NULL) {
  226.         for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  227.             imagePtr = imagePtr->nextPtr) {
  228.            (*masterPtr->typePtr->freeProc)(
  229.                imagePtr->instanceData, imagePtr->display);
  230.            (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
  231.             masterPtr->width, masterPtr->height, masterPtr->width,
  232.             masterPtr->height);
  233.         }
  234.         (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
  235.         masterPtr->typePtr = NULL;
  236.         }
  237.     }
  238.  
  239.     /*
  240.      * Call the image type manager so that it can perform its own
  241.      * initialization, then re-"get" for any existing instances of
  242.      * the image.
  243.      */
  244.  
  245.     if ((*typePtr->createProc)(interp, name, argc-firstOption,
  246.         argv+firstOption, typePtr, (Tk_ImageMaster) masterPtr,
  247.         &masterPtr->masterData) != TCL_OK) {
  248.         DeleteImage(masterPtr);
  249.         return TCL_ERROR;
  250.     }
  251.     masterPtr->typePtr = typePtr;
  252.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  253.         imagePtr = imagePtr->nextPtr) {
  254.        imagePtr->instanceData = (*typePtr->getProc)(
  255.            imagePtr->tkwin, masterPtr->masterData);
  256.     }
  257.     interp->result = Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr);
  258.     } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
  259.     for (i = 2; i < argc; i++) {
  260.         hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[i]);
  261.         if (hPtr == NULL) {
  262.         Tcl_AppendResult(interp, "image \"", argv[i],
  263.             "\" doesn't exist", (char *) NULL);
  264.         return TCL_ERROR;
  265.         }
  266.         masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  267.         DeleteImage(masterPtr);
  268.     }
  269.     } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) {
  270.     if (argc != 3) {
  271.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  272.             " height name\"", (char *) NULL);
  273.         return TCL_ERROR;
  274.     }
  275.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
  276.     if (hPtr == NULL) {
  277.         Tcl_AppendResult(interp, "image \"", argv[2],
  278.             "\" doesn't exist", (char *) NULL);
  279.         return TCL_ERROR;
  280.     }
  281.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  282.     sprintf(interp->result, "%d", masterPtr->height);
  283.     } else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) {
  284.     if (argc != 2) {
  285.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  286.             " names\"", (char *) NULL);
  287.         return TCL_ERROR;
  288.     }
  289.     for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
  290.         hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  291.         Tcl_AppendElement(interp, Tcl_GetHashKey(
  292.             &winPtr->mainPtr->imageTable, hPtr));
  293.     }
  294.     } else if ((c == 't') && (strcmp(argv[1], "type") == 0)) {
  295.     if (argc != 3) {
  296.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  297.             " type name\"", (char *) NULL);
  298.         return TCL_ERROR;
  299.     }
  300.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
  301.     if (hPtr == NULL) {
  302.         Tcl_AppendResult(interp, "image \"", argv[2],
  303.             "\" doesn't exist", (char *) NULL);
  304.         return TCL_ERROR;
  305.     }
  306.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  307.     if (masterPtr->typePtr != NULL) {
  308.         interp->result = masterPtr->typePtr->name;
  309.     }
  310.     } else if ((c == 't') && (strcmp(argv[1], "types") == 0)) {
  311.     if (argc != 2) {
  312.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  313.             " types\"", (char *) NULL);
  314.         return TCL_ERROR;
  315.     }
  316.     for (typePtr = imageTypeList; typePtr != NULL;
  317.         typePtr = typePtr->nextPtr) {
  318.         Tcl_AppendElement(interp, typePtr->name);
  319.     }
  320.     } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) {
  321.     if (argc != 3) {
  322.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  323.             " width name\"", (char *) NULL);
  324.         return TCL_ERROR;
  325.     }
  326.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
  327.     if (hPtr == NULL) {
  328.         Tcl_AppendResult(interp, "image \"", argv[2],
  329.             "\" doesn't exist", (char *) NULL);
  330.         return TCL_ERROR;
  331.     }
  332.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  333.     sprintf(interp->result, "%d", masterPtr->width);
  334.     } else {
  335.     Tcl_AppendResult(interp, "bad option \"", argv[1],
  336.         "\": must be create, delete, height, names, type, types,",
  337.         " or width", (char *) NULL);
  338.     return TCL_ERROR;
  339.     }
  340.     return TCL_OK;
  341. }
  342.  
  343. /*
  344.  *----------------------------------------------------------------------
  345.  *
  346.  * Tk_ImageChanged --
  347.  *
  348.  *    This procedure is called by an image manager whenever something
  349.  *    has happened that requires the image to be redrawn (some of its
  350.  *    pixels have changed, or its size has changed).
  351.  *
  352.  * Results:
  353.  *    None.
  354.  *
  355.  * Side effects:
  356.  *    Any widgets that display the image are notified so that they
  357.  *    can redisplay themselves as appropriate.
  358.  *
  359.  *----------------------------------------------------------------------
  360.  */
  361.  
  362. void
  363. Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,
  364.     imageHeight)
  365.     Tk_ImageMaster imageMaster;    /* Image that needs redisplay. */
  366.     int x, y;            /* Coordinates of upper-left pixel of
  367.                  * region of image that needs to be
  368.                  * redrawn. */
  369.     int width, height;        /* Dimensions (in pixels) of region of
  370.                  * image to redraw.  If either dimension
  371.                  * is zero then the image doesn't need to
  372.                  * be redrawn (perhaps all that happened is
  373.                  * that its size changed). */
  374.     int imageWidth, imageHeight;/* New dimensions of image. */
  375. {
  376.     ImageMaster *masterPtr = (ImageMaster *) imageMaster;
  377.     Image *imagePtr;
  378.  
  379.     masterPtr->width = imageWidth;
  380.     masterPtr->height = imageHeight;
  381.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  382.         imagePtr = imagePtr->nextPtr) {
  383.     (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,
  384.         width, height, imageWidth, imageHeight);
  385.     }
  386. }
  387.  
  388. /*
  389.  *----------------------------------------------------------------------
  390.  *
  391.  * Tk_NameOfImage --
  392.  *
  393.  *    Given a token for an image master, this procedure returns
  394.  *    the name of the image.
  395.  *
  396.  * Results:
  397.  *    The return value is the string name for imageMaster.
  398.  *
  399.  * Side effects:
  400.  *    None.
  401.  *
  402.  *----------------------------------------------------------------------
  403.  */
  404.  
  405. char *
  406. Tk_NameOfImage(imageMaster)
  407.     Tk_ImageMaster imageMaster;        /* Token for image. */
  408. {
  409.     ImageMaster *masterPtr = (ImageMaster *) imageMaster;
  410.  
  411.     return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
  412. }
  413.  
  414. /*
  415.  *----------------------------------------------------------------------
  416.  *
  417.  * Tk_GetImage --
  418.  *
  419.  *    This procedure is invoked by a widget when it wants to use
  420.  *    a particular image in a particular window.
  421.  *
  422.  * Results:
  423.  *    The return value is a token for the image.  If there is no image
  424.  *    by the given name, then NULL is returned and an error message is
  425.  *    left in interp->result.
  426.  *
  427.  * Side effects:
  428.  *    Tk records the fact that the widget is using the image, and
  429.  *    it will invoke changeProc later if the widget needs redisplay
  430.  *    (i.e. its size changes or some of its pixels change).  The
  431.  *    caller must eventually invoke Tk_FreeImage when it no longer
  432.  *    needs the image.
  433.  *
  434.  *----------------------------------------------------------------------
  435.  */
  436.  
  437. Tk_Image
  438. Tk_GetImage(interp, tkwin, name, changeProc, clientData)
  439.     Tcl_Interp *interp;        /* Place to leave error message if image
  440.                  * can't be found. */
  441.     Tk_Window tkwin;        /* Token for window in which image will
  442.                  * be used. */
  443.     char *name;            /* Name of desired image. */
  444.     Tk_ImageChangedProc *changeProc;
  445.                 /* Procedure to invoke when redisplay is
  446.                  * needed because image's pixels or size
  447.                  * changed. */
  448.     ClientData clientData;    /* One-word argument to pass to damageProc. */
  449. {
  450.     Tcl_HashEntry *hPtr;
  451.     ImageMaster *masterPtr;
  452.     Image *imagePtr;
  453.  
  454.     hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
  455.     if (hPtr == NULL) {
  456.     Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist",
  457.         (char *) NULL);
  458.     return NULL;
  459.     }
  460.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  461.     imagePtr = (Image *) ckalloc(sizeof(Image));
  462.     imagePtr->tkwin = tkwin;
  463.     imagePtr->display = Tk_Display(tkwin);
  464.     imagePtr->masterPtr = masterPtr;
  465.     imagePtr->instanceData =
  466.         (*masterPtr->typePtr->getProc)(tkwin, masterPtr->masterData);
  467.     imagePtr->changeProc = changeProc;
  468.     imagePtr->widgetClientData = clientData;
  469.     imagePtr->nextPtr = masterPtr->instancePtr;
  470.     masterPtr->instancePtr = imagePtr;
  471.     return (Tk_Image) imagePtr;
  472. }
  473.  
  474. /*
  475.  *----------------------------------------------------------------------
  476.  *
  477.  * Tk_FreeImage --
  478.  *
  479.  *    This procedure is invoked by a widget when it no longer needs
  480.  *    an image acquired by a previous call to Tk_GetImage.  For each
  481.  *    call to Tk_GetImage there must be exactly one call to Tk_FreeImage.
  482.  *
  483.  * Results:
  484.  *    None.
  485.  *
  486.  * Side effects:
  487.  *    The association between the image and the widget is removed.
  488.  *
  489.  *----------------------------------------------------------------------
  490.  */
  491.  
  492. void
  493. Tk_FreeImage(image)
  494.     Tk_Image image;        /* Token for image that is no longer
  495.                  * needed by a widget. */
  496. {
  497.     Image *imagePtr = (Image *) image;
  498.     ImageMaster *masterPtr = imagePtr->masterPtr;
  499.     Image *prevPtr;
  500.  
  501.     /*
  502.      * Clean up the particular instance.
  503.      */
  504.  
  505.     if (masterPtr->typePtr != NULL) {
  506.     (*masterPtr->typePtr->freeProc)(imagePtr->instanceData,
  507.         imagePtr->display);
  508.     }
  509.     prevPtr = masterPtr->instancePtr;
  510.     if (prevPtr == imagePtr) {
  511.     masterPtr->instancePtr = imagePtr->nextPtr;
  512.     } else {
  513.     while (prevPtr->nextPtr != imagePtr) {
  514.         prevPtr = prevPtr->nextPtr;
  515.     }
  516.     prevPtr->nextPtr = imagePtr->nextPtr;
  517.     }
  518.     ckfree((char *) imagePtr);
  519.  
  520.     /* 
  521.      * If there are no more instances left for the master, and if the
  522.      * master image has been deleted, then delete the master too.
  523.      */
  524.  
  525.     if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
  526.     Tcl_DeleteHashEntry(masterPtr->hPtr);
  527.     ckfree((char *) masterPtr);
  528.     }
  529. }
  530.  
  531. /*
  532.  *----------------------------------------------------------------------
  533.  *
  534.  * Tk_RedrawImage --
  535.  *
  536.  *    This procedure is called by widgets that contain images in order
  537.  *    to redisplay an image on the screen or an off-screen pixmap.
  538.  *
  539.  * Results:
  540.  *    None.
  541.  *
  542.  * Side effects:
  543.  *    The image's manager is notified, and it redraws the desired
  544.  *    portion of the image before returning.
  545.  *
  546.  *----------------------------------------------------------------------
  547.  */
  548.  
  549. void
  550. Tk_RedrawImage(image, imageX, imageY, width, height, drawable,
  551.     drawableX, drawableY)
  552.     Tk_Image image;        /* Token for image to redisplay. */
  553.     int imageX, imageY;        /* Upper-left pixel of region in image that
  554.                  * needs to be redisplayed. */
  555.     int width, height;        /* Dimensions of region to redraw. */
  556.     Drawable drawable;        /* Drawable in which to display image
  557.                  * (window or pixmap).  If this is a pixmap,
  558.                  * it must have the same depth as the window
  559.                  * used in the Tk_GetImage call for the
  560.                  * image. */
  561.     int drawableX, drawableY;    /* Coordinates in drawable that correspond
  562.                  * to imageX and imageY. */
  563. {
  564.     Image *imagePtr = (Image *) image;
  565.  
  566.     if (imagePtr->masterPtr->typePtr == NULL) {
  567.     /*
  568.      * No master for image, so nothing to display.
  569.      */
  570.  
  571.     return;
  572.     }
  573.  
  574.     /*
  575.      * Clip the redraw area to the area of the image.
  576.      */
  577.  
  578.     if (imageX < 0) {
  579.     width += imageX;
  580.     drawableX -= imageX;
  581.     imageX = 0;
  582.     }
  583.     if (imageY < 0) {
  584.     height += imageY;
  585.     drawableY -= imageY;
  586.     imageY = 0;
  587.     }
  588.     if ((imageX + width) > imagePtr->masterPtr->width) {
  589.     width = imagePtr->masterPtr->width - imageX;
  590.     }
  591.     if ((imageY + height) > imagePtr->masterPtr->height) {
  592.     height = imagePtr->masterPtr->height - imageY;
  593.     }
  594.     (*imagePtr->masterPtr->typePtr->displayProc)(
  595.         imagePtr->instanceData, imagePtr->display, drawable,
  596.         imageX, imageY, width, height, drawableX, drawableY);
  597. }
  598.  
  599. /*
  600.  *----------------------------------------------------------------------
  601.  *
  602.  * Tk_SizeOfImage --
  603.  *
  604.  *    This procedure returns the current dimensions of an image.
  605.  *
  606.  * Results:
  607.  *    The width and height of the image are returned in *widthPtr
  608.  *    and *heightPtr.
  609.  *
  610.  * Side effects:
  611.  *    None.
  612.  *
  613.  *----------------------------------------------------------------------
  614.  */
  615.  
  616. void
  617. Tk_SizeOfImage(image, widthPtr, heightPtr)
  618.     Tk_Image image;        /* Token for image whose size is wanted. */
  619.     int *widthPtr;        /* Return width of image here. */
  620.     int *heightPtr;        /* Return height of image here. */
  621. {
  622.     Image *imagePtr = (Image *) image;
  623.  
  624.     *widthPtr = imagePtr->masterPtr->width;
  625.     *heightPtr = imagePtr->masterPtr->height;
  626. }
  627.  
  628. /*
  629.  *----------------------------------------------------------------------
  630.  *
  631.  * Tk_DeleteImage --
  632.  *
  633.  *    Given the name of an image, this procedure destroys the
  634.  *    image.
  635.  *
  636.  * Results:
  637.  *    None.
  638.  *
  639.  * Side effects:
  640.  *    The image is destroyed; existing instances will display as
  641.  *    blank areas.  If no such image exists then the procedure does
  642.  *    nothing.
  643.  *
  644.  *----------------------------------------------------------------------
  645.  */
  646.  
  647. void
  648. Tk_DeleteImage(interp, name)
  649.     Tcl_Interp *interp;        /* Interpreter in which the image was
  650.                  * created. */
  651.     char *name;            /* Name of image. */
  652. {
  653.     Tcl_HashEntry *hPtr;
  654.     Tcl_CmdInfo info;
  655.     TkWindow *winPtr;
  656.  
  657.     if (Tcl_GetCommandInfo(interp, "winfo", &info) == 0) {
  658.     return;
  659.     }
  660.     winPtr = (TkWindow *) info.clientData;
  661.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
  662.     if (hPtr == NULL) {
  663.     return;
  664.     }
  665.     DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr));
  666. }
  667.  
  668. /*
  669.  *----------------------------------------------------------------------
  670.  *
  671.  * DeleteImage --
  672.  *
  673.  *    This procedure is responsible for deleting an image.
  674.  *
  675.  * Results:
  676.  *    None.
  677.  *
  678.  * Side effects:
  679.  *    The connection is dropped between instances of this image and
  680.  *    an image master.  Image instances will redisplay themselves
  681.  *    as empty areas, but existing instances will not be deleted.
  682.  *
  683.  *----------------------------------------------------------------------
  684.  */
  685.  
  686. static void
  687. DeleteImage(masterPtr)
  688.     ImageMaster *masterPtr;    /* Pointer to main data structure for image. */
  689. {
  690.     Image *imagePtr;
  691.     Tk_ImageType *typePtr;
  692.  
  693.     typePtr = masterPtr->typePtr;
  694.     masterPtr->typePtr = NULL;
  695.     if (typePtr != NULL) {
  696.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  697.         imagePtr = imagePtr->nextPtr) {
  698.        (*typePtr->freeProc)(imagePtr->instanceData,
  699.            imagePtr->display);
  700.        (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
  701.             masterPtr->width, masterPtr->height, masterPtr->width,
  702.             masterPtr->height);
  703.     }
  704.     (*typePtr->deleteProc)(masterPtr->masterData);
  705.     }
  706.     if (masterPtr->instancePtr == NULL) {
  707.     Tcl_DeleteHashEntry(masterPtr->hPtr);
  708.     ckfree((char *) masterPtr);
  709.     }
  710. }
  711.  
  712. /*
  713.  *----------------------------------------------------------------------
  714.  *
  715.  * TkDeleteAllImages --
  716.  *
  717.  *    This procedure is called when an application is deleted.  It
  718.  *    calls back all of the managers for all images so that they
  719.  *    can cleanup, then it deletes all of Tk's internal information
  720.  *    about images.
  721.  *
  722.  * Results:
  723.  *    None.
  724.  *
  725.  * Side effects:
  726.  *    All information for all images gets deleted.
  727.  *
  728.  *----------------------------------------------------------------------
  729.  */
  730.  
  731. void
  732. TkDeleteAllImages(mainPtr)
  733.     TkMainInfo *mainPtr;    /* Structure describing application that is
  734.                  * going away. */
  735. {
  736.     Tcl_HashSearch search;
  737.     Tcl_HashEntry *hPtr;
  738.     ImageMaster *masterPtr;
  739.  
  740.     for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
  741.         hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  742.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  743.     DeleteImage(masterPtr);
  744.     }
  745.     Tcl_DeleteHashTable(&mainPtr->imageTable);
  746. }
  747.