tkImage.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:31k
源码类别:

通讯编程

开发平台:

Visual C++

  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-1997 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.  * RCS: @(#) $Id: tkImage.c,v 1.19.2.2 2003/09/17 23:45:05 dgp Exp $
  15.  */
  16. #include "tkInt.h"
  17. #include "tkPort.h"
  18. /*
  19.  * Each call to Tk_GetImage returns a pointer to one of the following
  20.  * structures, which is used as a token by clients (widgets) that
  21.  * display images.
  22.  */
  23. typedef struct Image {
  24.     Tk_Window tkwin; /* Window passed to Tk_GetImage (needed to
  25.  * "re-get" the image later if the manager
  26.  * changes). */
  27.     Display *display; /* Display for tkwin.  Needed because when
  28.  * the image is eventually freed tkwin may
  29.  * not exist anymore. */
  30.     struct ImageMaster *masterPtr;
  31. /* Master for this image (identifiers image
  32.  * manager, for example). */
  33.     ClientData instanceData;
  34. /* One word argument to pass to image manager
  35.  * when dealing with this image instance. */
  36.     Tk_ImageChangedProc *changeProc;
  37. /* Code in widget to call when image changes
  38.  * in a way that affects redisplay. */
  39.     ClientData widgetClientData;
  40. /* Argument to pass to changeProc. */
  41.     struct Image *nextPtr; /* Next in list of all image instances
  42.  * associated with the same name. */
  43. } Image;
  44. /*
  45.  * For each image master there is one of the following structures,
  46.  * which represents a name in the image table and all of the images
  47.  * instantiated from it.  Entries in mainPtr->imageTable point to
  48.  * these structures.
  49.  */
  50. typedef struct ImageMaster {
  51.     Tk_ImageType *typePtr; /* Information about image type.  NULL means
  52.  * that no image manager owns this image:  the
  53.  * image was deleted. */
  54.     ClientData masterData; /* One-word argument to pass to image mgr
  55.  * when dealing with the master, as opposed
  56.  * to instances. */
  57.     int width, height; /* Last known dimensions for image. */
  58.     Tcl_HashTable *tablePtr; /* Pointer to hash table containing image
  59.  * (the imageTable field in some TkMainInfo
  60.  * structure). */
  61.     Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for
  62.  * this structure (used to delete the hash
  63.  * entry). */
  64.     Image *instancePtr; /* Pointer to first in list of instances
  65.  * derived from this name. */
  66.     int deleted; /* Flag set when image is being deleted. */
  67.     TkWindow *winPtr; /* Main window of interpreter (used to
  68.  * detect when the world is falling apart.) */
  69. } ImageMaster;
  70. typedef struct ThreadSpecificData {
  71.     Tk_ImageType *imageTypeList;/* First in a list of all known image 
  72.  * types. */  
  73.     Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image 
  74.  * types. */  
  75. } ThreadSpecificData;           
  76. static Tcl_ThreadDataKey dataKey;
  77. /*
  78.  * Prototypes for local procedures:
  79.  */
  80. static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
  81. static void EventuallyDeleteImage _ANSI_ARGS_((ImageMaster *masterPtr,
  82.    int forgetHashEntryNow));
  83. /*
  84.  *----------------------------------------------------------------------
  85.  *
  86.  * Tk_CreateOldImageType, Tk_CreateImageType --
  87.  *
  88.  * This procedure is invoked by an image manager to tell Tk about
  89.  * a new kind of image and the procedures that manage the new type.
  90.  * The procedure is typically invoked during Tcl_AppInit.
  91.  *
  92.  * Results:
  93.  * None.
  94.  *
  95.  * Side effects:
  96.  * The new image type is entered into a table used in the "image
  97.  * create" command.
  98.  *
  99.  *----------------------------------------------------------------------
  100.  */
  101. void
  102. Tk_CreateOldImageType(typePtr)
  103.     Tk_ImageType *typePtr; /* Structure describing the type.  All of
  104.  * the fields except "nextPtr" must be filled
  105.  * in by caller.  Must not have been passed
  106.  * to Tk_CreateImageType previously. */
  107. {
  108.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  109.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  110.     typePtr->nextPtr = tsdPtr->oldImageTypeList;
  111.     tsdPtr->oldImageTypeList = typePtr;
  112. }
  113. void
  114. Tk_CreateImageType(typePtr)
  115.     Tk_ImageType *typePtr; /* Structure describing the type.  All of
  116.  * the fields except "nextPtr" must be filled
  117.  * in by caller.  Must not have been passed
  118.  * to Tk_CreateImageType previously. */
  119. {
  120.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  121.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  122.     typePtr->nextPtr = tsdPtr->imageTypeList;
  123.     tsdPtr->imageTypeList = typePtr;
  124. }
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * Tk_ImageObjCmd --
  129.  *
  130.  * This procedure is invoked to process the "image" Tcl command.
  131.  * See the user documentation for details on what it does.
  132.  *
  133.  * Results:
  134.  * A standard Tcl result.
  135.  *
  136.  * Side effects:
  137.  * See the user documentation.
  138.  *
  139.  *----------------------------------------------------------------------
  140.  */
  141. int
  142. Tk_ImageObjCmd(clientData, interp, objc, objv)
  143.     ClientData clientData; /* Main window associated with interpreter. */
  144.     Tcl_Interp *interp; /* Current interpreter. */
  145.     int objc; /* Number of arguments. */
  146.     Tcl_Obj *CONST objv[]; /* Argument strings. */
  147. {
  148.     static CONST char *imageOptions[] = {
  149. "create", "delete", "height", "inuse", "names", "type", "types",
  150.     "width", (char *) NULL
  151.     };
  152.     enum options {
  153. IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_INUSE, IMAGE_NAMES,
  154. IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH
  155.     };
  156.     TkWindow *winPtr = (TkWindow *) clientData;
  157.     int i, new, firstOption,  index;
  158.     Tk_ImageType *typePtr;
  159.     ImageMaster *masterPtr;
  160.     Image *imagePtr;
  161.     Tcl_HashEntry *hPtr;
  162.     Tcl_HashSearch search;
  163.     char idString[16 + TCL_INTEGER_SPACE], *name;
  164.     TkDisplay *dispPtr = winPtr->dispPtr;
  165.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  166.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  167.     if (objc < 2) {
  168. Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
  169. return TCL_ERROR;
  170.     }
  171.     if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0,
  172.     &index) != TCL_OK) {
  173. return TCL_ERROR;
  174.     }
  175.     switch ((enum options) index) {
  176. case IMAGE_CREATE: {
  177.     char *arg;
  178.     Tcl_Obj **args;
  179.     int oldimage = 0;
  180.     if (objc < 3) {
  181. Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?");
  182. return TCL_ERROR;
  183.     }
  184.     /*
  185.      * Look up the image type.
  186.      */
  187.     arg = Tcl_GetString(objv[2]);
  188.     for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
  189.  typePtr = typePtr->nextPtr) {
  190. if ((*arg == typePtr->name[0])
  191. && (strcmp(arg, typePtr->name) == 0)) {
  192.     break;
  193. }
  194.     }
  195.     if (typePtr == NULL) {
  196. oldimage = 1;
  197. for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
  198.      typePtr = typePtr->nextPtr) {
  199.     if ((*arg == typePtr->name[0])
  200.     && (strcmp(arg, typePtr->name) == 0)) {
  201. break;
  202.     }
  203. }
  204.     }
  205.     if (typePtr == NULL) {
  206. Tcl_AppendResult(interp, "image type "", arg,
  207. "" doesn't exist", (char *) NULL);
  208. return TCL_ERROR;
  209.     }
  210.     /*
  211.      * Figure out a name to use for the new image.
  212.      */
  213.     if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {
  214.                 Tcl_CmdInfo dummy;
  215.                 do {
  216.     dispPtr->imageId++;
  217.     sprintf(idString, "image%d", dispPtr->imageId);
  218.     name = idString;
  219.                 } while (Tcl_GetCommandInfo(interp, name, &dummy) != 0);
  220. firstOption = 3;
  221.     } else {
  222. TkWindow *topWin;
  223. name = arg;
  224. firstOption = 4;
  225. /*
  226.  * Need to check if the _command_ that we are about to
  227.  * create is the name of the current master widget
  228.  * command (normally "." but could have been renamed)
  229.  * and fail in that case before a really nasty and
  230.  * hard to stop crash happens.
  231.  */
  232. topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name);
  233. if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) {
  234.     Tcl_AppendResult(interp, "images may not be named the ",
  235.     "same as the main window", (char *) NULL);
  236.     return TCL_ERROR;
  237. }
  238.     }
  239.     /*
  240.      * Create the data structure for the new image.
  241.      */
  242.     hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable,
  243.     name, &new);
  244.     if (new) {
  245. masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
  246. masterPtr->typePtr = NULL;
  247. masterPtr->masterData = NULL;
  248. masterPtr->width = masterPtr->height = 1;
  249. masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
  250. masterPtr->hPtr = hPtr;
  251. masterPtr->instancePtr = NULL;
  252. masterPtr->deleted = 0;
  253. masterPtr->winPtr = winPtr->mainPtr->winPtr;
  254. Tcl_Preserve((ClientData) masterPtr->winPtr);
  255. Tcl_SetHashValue(hPtr, masterPtr);
  256.     } else {
  257. /*
  258.  * An image already exists by this name.  Disconnect the
  259.  * instances from the master.
  260.  */
  261. masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  262. if (masterPtr->typePtr != NULL) {
  263.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  264.  imagePtr = imagePtr->nextPtr) {
  265. (*masterPtr->typePtr->freeProc)(
  266.     imagePtr->instanceData, imagePtr->display);
  267. (*imagePtr->changeProc)(imagePtr->widgetClientData,
  268. 0, 0, masterPtr->width, masterPtr->height,
  269. masterPtr->width, masterPtr->height);
  270.     }
  271.     (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
  272.     masterPtr->typePtr = NULL;
  273. }
  274.     }
  275.     /*
  276.      * Call the image type manager so that it can perform its own
  277.      * initialization, then re-"get" for any existing instances of
  278.      * the image.
  279.      */
  280.     objv += firstOption;
  281.     objc -= firstOption;
  282.     args = (Tcl_Obj **) objv;
  283.     if (oldimage) {
  284. int i;
  285. args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *));
  286. for (i = 0; i < objc; i++) {
  287.     args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);
  288. }
  289. args[objc] = NULL;
  290.     }
  291.     Tcl_Preserve((ClientData) masterPtr);
  292.     if ((*typePtr->createProc)(interp, name, objc,
  293.     args, typePtr, (Tk_ImageMaster) masterPtr,
  294.     &masterPtr->masterData) != TCL_OK) {
  295. EventuallyDeleteImage(masterPtr, 0);
  296. Tcl_Release((ClientData) masterPtr);
  297. if (oldimage) {
  298.     ckfree((char *) args);
  299. }
  300. return TCL_ERROR;
  301.     }
  302.     Tcl_Release((ClientData) masterPtr);
  303.     if (oldimage) {
  304. ckfree((char *) args);
  305.     }
  306.     masterPtr->typePtr = typePtr;
  307.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  308.  imagePtr = imagePtr->nextPtr) {
  309. imagePtr->instanceData = (*typePtr->getProc)(
  310.     imagePtr->tkwin, masterPtr->masterData);
  311.     }
  312.     Tcl_SetResult(interp,
  313.     Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),
  314.     TCL_STATIC);
  315.     break;
  316. }
  317. case IMAGE_DELETE: {
  318.     for (i = 2; i < objc; i++) {
  319. char *arg = Tcl_GetString(objv[i]);
  320. hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
  321. if (hPtr == NULL) {
  322.     Tcl_AppendResult(interp, "image "", arg,
  323.     "" doesn't exist", (char *) NULL);
  324.     return TCL_ERROR;
  325. }
  326. DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr));
  327.     }
  328.     break;
  329. }
  330. case IMAGE_HEIGHT: {
  331.     char *arg;
  332.     if (objc != 3) {
  333. Tcl_WrongNumArgs(interp, 2, objv, "name");
  334. return TCL_ERROR;
  335.     }
  336.     arg = Tcl_GetString(objv[2]);
  337.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
  338.     if (hPtr == NULL) {
  339. Tcl_AppendResult(interp, "image "", arg,
  340. "" doesn't exist", (char *) NULL);
  341. return TCL_ERROR;
  342.     }
  343.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  344.     Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
  345.     break;
  346. }
  347. case IMAGE_INUSE: {
  348.     int count = 0;
  349.     char *arg;
  350.     if (objc != 3) {
  351. Tcl_WrongNumArgs(interp, 2, objv, "name");
  352. return TCL_ERROR;
  353.     }
  354.     arg = Tcl_GetString(objv[2]);
  355.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
  356.     if (hPtr == NULL) {
  357. Tcl_AppendResult(interp, "image "", arg,
  358. "" doesn't exist", (char *) NULL);
  359. return TCL_ERROR;
  360.     }
  361.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  362.     if (masterPtr->typePtr != NULL && masterPtr->instancePtr != NULL) {
  363. count = 1;
  364.     }
  365.     Tcl_SetBooleanObj(Tcl_GetObjResult(interp), count);
  366.     break;
  367. }
  368. case IMAGE_NAMES: {
  369.     if (objc != 2) {
  370. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  371. return TCL_ERROR;
  372.     }
  373.     hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
  374.     for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  375. Tcl_AppendElement(interp, Tcl_GetHashKey(
  376.     &winPtr->mainPtr->imageTable, hPtr));
  377.     }
  378.     break;
  379. }
  380. case IMAGE_TYPE: {
  381.     char *arg;
  382.     if (objc != 3) {
  383. Tcl_WrongNumArgs(interp, 2, objv, "name");
  384. return TCL_ERROR;
  385.     }
  386.     arg = Tcl_GetString(objv[2]);
  387.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
  388.     if (hPtr == NULL) {
  389. Tcl_AppendResult(interp, "image "", arg,
  390. "" doesn't exist", (char *) NULL);
  391. return TCL_ERROR;
  392.     }
  393.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  394.     if (masterPtr->typePtr != NULL) {
  395. Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);
  396.     }
  397.     break;
  398. }
  399. case IMAGE_TYPES: {
  400.     if (objc != 2) {
  401. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  402. return TCL_ERROR;
  403.     }
  404.     for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
  405.  typePtr = typePtr->nextPtr) {
  406. Tcl_AppendElement(interp, typePtr->name);
  407.     }
  408.     for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
  409.  typePtr = typePtr->nextPtr) {
  410. Tcl_AppendElement(interp, typePtr->name);
  411.     }
  412.     break;
  413. }
  414. case IMAGE_WIDTH: {
  415.     char *arg;
  416.     if (objc != 3) {
  417. Tcl_WrongNumArgs(interp, 2, objv, "name");
  418. return TCL_ERROR;
  419.     }
  420.     arg = Tcl_GetString(objv[2]);
  421.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
  422.     if (hPtr == NULL) {
  423. Tcl_AppendResult(interp, "image "", arg,
  424. "" doesn't exist", (char *) NULL);
  425. return TCL_ERROR;
  426.     }
  427.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  428.     Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width);
  429.     break;
  430. }
  431.     }
  432.     return TCL_OK;
  433. }
  434. /*
  435.  *----------------------------------------------------------------------
  436.  *
  437.  * Tk_ImageChanged --
  438.  *
  439.  * This procedure is called by an image manager whenever something
  440.  * has happened that requires the image to be redrawn (some of its
  441.  * pixels have changed, or its size has changed).
  442.  *
  443.  * Results:
  444.  * None.
  445.  *
  446.  * Side effects:
  447.  * Any widgets that display the image are notified so that they
  448.  * can redisplay themselves as appropriate.
  449.  *
  450.  *----------------------------------------------------------------------
  451.  */
  452. void
  453. Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,
  454. imageHeight)
  455.     Tk_ImageMaster imageMaster; /* Image that needs redisplay. */
  456.     int x, y; /* Coordinates of upper-left pixel of
  457.  * region of image that needs to be
  458.  * redrawn. */
  459.     int width, height; /* Dimensions (in pixels) of region of
  460.  * image to redraw.  If either dimension
  461.  * is zero then the image doesn't need to
  462.  * be redrawn (perhaps all that happened is
  463.  * that its size changed). */
  464.     int imageWidth, imageHeight;/* New dimensions of image. */
  465. {
  466.     ImageMaster *masterPtr = (ImageMaster *) imageMaster;
  467.     Image *imagePtr;
  468.     masterPtr->width = imageWidth;
  469.     masterPtr->height = imageHeight;
  470.     for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  471.  imagePtr = imagePtr->nextPtr) {
  472. (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,
  473. width, height, imageWidth, imageHeight);
  474.     }
  475. }
  476. /*
  477.  *----------------------------------------------------------------------
  478.  *
  479.  * Tk_NameOfImage --
  480.  *
  481.  * Given a token for an image master, this procedure returns
  482.  * the name of the image.
  483.  *
  484.  * Results:
  485.  * The return value is the string name for imageMaster.
  486.  *
  487.  * Side effects:
  488.  * None.
  489.  *
  490.  *----------------------------------------------------------------------
  491.  */
  492. CONST char *
  493. Tk_NameOfImage(imageMaster)
  494.     Tk_ImageMaster imageMaster; /* Token for image. */
  495. {
  496.     ImageMaster *masterPtr = (ImageMaster *) imageMaster;
  497.     if (masterPtr->hPtr == NULL) {
  498. return NULL;
  499.     }
  500.     return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr);
  501. }
  502. /*
  503.  *----------------------------------------------------------------------
  504.  *
  505.  * Tk_GetImage --
  506.  *
  507.  * This procedure is invoked by a widget when it wants to use
  508.  * a particular image in a particular window.
  509.  *
  510.  * Results:
  511.  * The return value is a token for the image.  If there is no image
  512.  * by the given name, then NULL is returned and an error message is
  513.  * left in the interp's result.
  514.  *
  515.  * Side effects:
  516.  * Tk records the fact that the widget is using the image, and
  517.  * it will invoke changeProc later if the widget needs redisplay
  518.  * (i.e. its size changes or some of its pixels change).  The
  519.  * caller must eventually invoke Tk_FreeImage when it no longer
  520.  * needs the image.
  521.  *
  522.  *----------------------------------------------------------------------
  523.  */
  524. Tk_Image
  525. Tk_GetImage(interp, tkwin, name, changeProc, clientData)
  526.     Tcl_Interp *interp; /* Place to leave error message if image
  527.  * can't be found. */
  528.     Tk_Window tkwin; /* Token for window in which image will
  529.  * be used. */
  530.     CONST char *name; /* Name of desired image. */
  531.     Tk_ImageChangedProc *changeProc;
  532. /* Procedure to invoke when redisplay is
  533.  * needed because image's pixels or size
  534.  * changed. */
  535.     ClientData clientData; /* One-word argument to pass to damageProc. */
  536. {
  537.     Tcl_HashEntry *hPtr;
  538.     ImageMaster *masterPtr;
  539.     Image *imagePtr;
  540.     hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->imageTable, name);
  541.     if (hPtr == NULL) {
  542. goto noSuchImage;
  543.     }
  544.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  545.     if (masterPtr->typePtr == NULL) {
  546. goto noSuchImage;
  547.     }
  548.     imagePtr = (Image *) ckalloc(sizeof(Image));
  549.     imagePtr->tkwin = tkwin;
  550.     imagePtr->display = Tk_Display(tkwin);
  551.     imagePtr->masterPtr = masterPtr;
  552.     imagePtr->instanceData =
  553.     (*masterPtr->typePtr->getProc)(tkwin, masterPtr->masterData);
  554.     imagePtr->changeProc = changeProc;
  555.     imagePtr->widgetClientData = clientData;
  556.     imagePtr->nextPtr = masterPtr->instancePtr;
  557.     masterPtr->instancePtr = imagePtr;
  558.     return (Tk_Image) imagePtr;
  559.     noSuchImage:
  560.     Tcl_AppendResult(interp, "image "", name, "" doesn't exist",
  561.     (char *) NULL);
  562.     return NULL;
  563. }
  564. /*
  565.  *----------------------------------------------------------------------
  566.  *
  567.  * Tk_FreeImage --
  568.  *
  569.  * This procedure is invoked by a widget when it no longer needs
  570.  * an image acquired by a previous call to Tk_GetImage.  For each
  571.  * call to Tk_GetImage there must be exactly one call to Tk_FreeImage.
  572.  *
  573.  * Results:
  574.  * None.
  575.  *
  576.  * Side effects:
  577.  * The association between the image and the widget is removed.
  578.  *
  579.  *----------------------------------------------------------------------
  580.  */
  581. void
  582. Tk_FreeImage(image)
  583.     Tk_Image image; /* Token for image that is no longer
  584.  * needed by a widget. */
  585. {
  586.     Image *imagePtr = (Image *) image;
  587.     ImageMaster *masterPtr = imagePtr->masterPtr;
  588.     Image *prevPtr;
  589.     /*
  590.      * Clean up the particular instance.
  591.      */
  592.     if (masterPtr->typePtr != NULL) {
  593. (*masterPtr->typePtr->freeProc)(imagePtr->instanceData,
  594. imagePtr->display);
  595.     }
  596.     prevPtr = masterPtr->instancePtr;
  597.     if (prevPtr == imagePtr) {
  598. masterPtr->instancePtr = imagePtr->nextPtr;
  599.     } else {
  600. while (prevPtr->nextPtr != imagePtr) {
  601.     prevPtr = prevPtr->nextPtr;
  602. }
  603. prevPtr->nextPtr = imagePtr->nextPtr;
  604.     }
  605.     ckfree((char *) imagePtr);
  606.     /* 
  607.      * If there are no more instances left for the master, and if the
  608.      * master image has been deleted, then delete the master too.
  609.      */
  610.     if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) {
  611. if (masterPtr->hPtr != NULL) {
  612.     Tcl_DeleteHashEntry(masterPtr->hPtr);
  613. }
  614. Tcl_Release(masterPtr->winPtr);
  615. ckfree((char *) masterPtr);
  616.     }
  617. }
  618. /*
  619.  *----------------------------------------------------------------------
  620.  *
  621.  * Tk_PostscriptImage --
  622.  *
  623.  * This procedure is called by widgets that contain images in order
  624.  * to redisplay an image on the screen or an off-screen pixmap.
  625.  *
  626.  * Results:
  627.  * None.
  628.  *
  629.  * Side effects:
  630.  * The image's manager is notified, and it redraws the desired
  631.  * portion of the image before returning.
  632.  *
  633.  *----------------------------------------------------------------------
  634.  */
  635. int
  636. Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass)
  637.     Tk_Image image; /* Token for image to redisplay. */
  638.     Tcl_Interp *interp;
  639.     Tk_Window tkwin;
  640.     Tk_PostscriptInfo psinfo; /* postscript info */
  641.     int x, y; /* Upper-left pixel of region in image that
  642.  * needs to be redisplayed. */
  643.     int width, height; /* Dimensions of region to redraw. */
  644.     int prepass;
  645. {
  646.     Image *imagePtr = (Image *) image;
  647.     int result;
  648.     XImage *ximage;
  649.     Pixmap pmap;
  650.     GC newGC;
  651.     XGCValues gcValues;
  652.     if (imagePtr->masterPtr->typePtr == NULL) {
  653. /*
  654.  * No master for image, so nothing to display on postscript.
  655.  */
  656. return TCL_OK;
  657.     }
  658.     /*
  659.      * Check if an image specific postscript-generation function
  660.      * exists; otherwise go on with generic code.
  661.      */
  662.     if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
  663. return (*imagePtr->masterPtr->typePtr->postscriptProc)(
  664.     imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
  665.     x, y, width, height, prepass);
  666.     }
  667.     if (prepass) {
  668. return TCL_OK;
  669.     }
  670.     /*
  671.      * Create a Pixmap, tell the image to redraw itself there, and then
  672.      * generate an XImage from the Pixmap.  We can then read pixel 
  673.      * values out of the XImage.
  674.      */
  675.     pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
  676.                         width, height, Tk_Depth(tkwin));
  677.     gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
  678.     newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
  679.     if (newGC != None) {
  680. XFillRectangle(Tk_Display(tkwin), pmap, newGC,
  681. 0, 0, (unsigned int)width, (unsigned int)height);
  682. Tk_FreeGC(Tk_Display(tkwin), newGC);
  683.     }
  684.     Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);
  685.     ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,
  686.     (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
  687.     Tk_FreePixmap(Tk_Display(tkwin), pmap);
  688.     
  689.     if (ximage == NULL) {
  690. /* The XGetImage() function is apparently not
  691.  * implemented on this system. Just ignore it.
  692.  */
  693. return TCL_OK;
  694.     }
  695.     result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,
  696.     width, height);
  697.     XDestroyImage(ximage);
  698.     return result;
  699. }
  700. /*
  701.  *----------------------------------------------------------------------
  702.  *
  703.  * Tk_RedrawImage --
  704.  *
  705.  * This procedure is called by widgets that contain images in order
  706.  * to redisplay an image on the screen or an off-screen pixmap.
  707.  *
  708.  * Results:
  709.  * None.
  710.  *
  711.  * Side effects:
  712.  * The image's manager is notified, and it redraws the desired
  713.  * portion of the image before returning.
  714.  *
  715.  *----------------------------------------------------------------------
  716.  */
  717. void
  718. Tk_RedrawImage(image, imageX, imageY, width, height, drawable,
  719. drawableX, drawableY)
  720.     Tk_Image image; /* Token for image to redisplay. */
  721.     int imageX, imageY; /* Upper-left pixel of region in image that
  722.  * needs to be redisplayed. */
  723.     int width, height; /* Dimensions of region to redraw. */
  724.     Drawable drawable; /* Drawable in which to display image
  725.  * (window or pixmap).  If this is a pixmap,
  726.  * it must have the same depth as the window
  727.  * used in the Tk_GetImage call for the
  728.  * image. */
  729.     int drawableX, drawableY; /* Coordinates in drawable that correspond
  730.  * to imageX and imageY. */
  731. {
  732.     Image *imagePtr = (Image *) image;
  733.     if (imagePtr->masterPtr->typePtr == NULL) {
  734. /*
  735.  * No master for image, so nothing to display.
  736.  */
  737. return;
  738.     }
  739.     /*
  740.      * Clip the redraw area to the area of the image.
  741.      */
  742.     if (imageX < 0) {
  743. width += imageX;
  744. drawableX -= imageX;
  745. imageX = 0;
  746.     }
  747.     if (imageY < 0) {
  748. height += imageY;
  749. drawableY -= imageY;
  750. imageY = 0;
  751.     }
  752.     if ((imageX + width) > imagePtr->masterPtr->width) {
  753. width = imagePtr->masterPtr->width - imageX;
  754.     }
  755.     if ((imageY + height) > imagePtr->masterPtr->height) {
  756. height = imagePtr->masterPtr->height - imageY;
  757.     }
  758.     (*imagePtr->masterPtr->typePtr->displayProc)(
  759.     imagePtr->instanceData, imagePtr->display, drawable,
  760.     imageX, imageY, width, height, drawableX, drawableY);
  761. }
  762. /*
  763.  *----------------------------------------------------------------------
  764.  *
  765.  * Tk_SizeOfImage --
  766.  *
  767.  * This procedure returns the current dimensions of an image.
  768.  *
  769.  * Results:
  770.  * The width and height of the image are returned in *widthPtr
  771.  * and *heightPtr.
  772.  *
  773.  * Side effects:
  774.  * None.
  775.  *
  776.  *----------------------------------------------------------------------
  777.  */
  778. void
  779. Tk_SizeOfImage(image, widthPtr, heightPtr)
  780.     Tk_Image image; /* Token for image whose size is wanted. */
  781.     int *widthPtr; /* Return width of image here. */
  782.     int *heightPtr; /* Return height of image here. */
  783. {
  784.     Image *imagePtr = (Image *) image;
  785.     *widthPtr = imagePtr->masterPtr->width;
  786.     *heightPtr = imagePtr->masterPtr->height;
  787. }
  788. /*
  789.  *----------------------------------------------------------------------
  790.  *
  791.  * Tk_DeleteImage --
  792.  *
  793.  * Given the name of an image, this procedure destroys the
  794.  * image.
  795.  *
  796.  * Results:
  797.  * None.
  798.  *
  799.  * Side effects:
  800.  * The image is destroyed; existing instances will display as
  801.  * blank areas.  If no such image exists then the procedure does
  802.  * nothing.
  803.  *
  804.  *----------------------------------------------------------------------
  805.  */
  806. void
  807. Tk_DeleteImage(interp, name)
  808.     Tcl_Interp *interp; /* Interpreter in which the image was
  809.  * created. */
  810.     CONST char *name; /* Name of image. */
  811. {
  812.     Tcl_HashEntry *hPtr;
  813.     TkWindow *winPtr;
  814.     winPtr = (TkWindow *) Tk_MainWindow(interp);
  815.     if (winPtr == NULL) {
  816. return;
  817.     }
  818.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
  819.     if (hPtr == NULL) {
  820. return;
  821.     }
  822.     DeleteImage((ImageMaster *)Tcl_GetHashValue(hPtr));
  823. }
  824. /*
  825.  *----------------------------------------------------------------------
  826.  *
  827.  * DeleteImage --
  828.  *
  829.  * This procedure is responsible for deleting an image.
  830.  *
  831.  * Results:
  832.  * None.
  833.  *
  834.  * Side effects:
  835.  * The connection is dropped between instances of this image and
  836.  * an image master.  Image instances will redisplay themselves
  837.  * as empty areas, but existing instances will not be deleted.
  838.  *
  839.  *----------------------------------------------------------------------
  840.  */
  841. static void
  842. DeleteImage(masterPtr)
  843.     ImageMaster *masterPtr; /* Pointer to main data structure for image. */
  844. {
  845.     Image *imagePtr;
  846.     Tk_ImageType *typePtr;
  847.     typePtr = masterPtr->typePtr;
  848.     masterPtr->typePtr = NULL;
  849.     if (typePtr != NULL) {
  850. for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
  851. imagePtr = imagePtr->nextPtr) {
  852.    (*typePtr->freeProc)(imagePtr->instanceData,
  853.    imagePtr->display);
  854.    (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
  855.     masterPtr->width, masterPtr->height, masterPtr->width,
  856.     masterPtr->height);
  857. }
  858. (*typePtr->deleteProc)(masterPtr->masterData);
  859.     }
  860.     if (masterPtr->instancePtr == NULL) {
  861. if (masterPtr->hPtr != NULL) {
  862.     Tcl_DeleteHashEntry(masterPtr->hPtr);
  863. }
  864. Tcl_Release((ClientData) masterPtr->winPtr);
  865. ckfree((char *) masterPtr);
  866.     }
  867. }
  868. /*
  869.  *----------------------------------------------------------------------
  870.  *
  871.  * EventuallyDeleteImage --
  872.  *
  873.  * Arrange for an image to be deleted when it is safe to do so.
  874.  *
  875.  * Results:
  876.  * None.
  877.  *
  878.  * Side effects:
  879.  * Image will get freed, though not until it is no longer
  880.  * Tcl_Preserve()d by anything.  May be called multiple times on
  881.  * the same image without ill effects.
  882.  *
  883.  *----------------------------------------------------------------------
  884.  */
  885. static void
  886. EventuallyDeleteImage(masterPtr, forgetHashEntryNow)
  887.     ImageMaster *masterPtr; /* Pointer to main data structure for image. */
  888.     int forgetHashEntryNow;
  889. {
  890.     if (forgetHashEntryNow) {
  891. masterPtr->hPtr = NULL;
  892.     }
  893.     if (!masterPtr->deleted) {
  894. masterPtr->deleted = 1;
  895. Tcl_EventuallyFree((ClientData) masterPtr,
  896. (Tcl_FreeProc *)DeleteImage);
  897.     }
  898. }
  899. /*
  900.  *----------------------------------------------------------------------
  901.  *
  902.  * TkDeleteAllImages --
  903.  *
  904.  * This procedure is called when an application is deleted.  It
  905.  * calls back all of the managers for all images so that they
  906.  * can cleanup, then it deletes all of Tk's internal information
  907.  * about images.
  908.  *
  909.  * Results:
  910.  * None.
  911.  *
  912.  * Side effects:
  913.  * All information for all images gets deleted.
  914.  *
  915.  *----------------------------------------------------------------------
  916.  */
  917. void
  918. TkDeleteAllImages(mainPtr)
  919.     TkMainInfo *mainPtr; /* Structure describing application that is
  920.  * going away. */
  921. {
  922.     Tcl_HashSearch search;
  923.     Tcl_HashEntry *hPtr;
  924.     for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search);
  925.     hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
  926. EventuallyDeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr), 1);
  927.     }
  928.     Tcl_DeleteHashTable(&mainPtr->imageTable);
  929. }
  930. /*
  931.  *----------------------------------------------------------------------
  932.  *
  933.  * Tk_GetImageMasterData --
  934.  *
  935.  * Given the name of an image, this procedure returns the type
  936.  * of the image and the clientData associated with its master.
  937.  *
  938.  * Results:
  939.  * If there is no image by the given name, then NULL is returned
  940.  * and a NULL value is stored at *typePtrPtr.  Otherwise the return
  941.  * value is the clientData returned by the createProc when the
  942.  * image was created and a pointer to the type structure for the
  943.  * image is stored at *typePtrPtr.
  944.  *
  945.  * Side effects:
  946.  * None.
  947.  *
  948.  *----------------------------------------------------------------------
  949.  */
  950. ClientData
  951. Tk_GetImageMasterData(interp, name, typePtrPtr)
  952.     Tcl_Interp *interp; /* Interpreter in which the image was
  953.  * created. */
  954.     CONST char *name; /* Name of image. */
  955.     Tk_ImageType **typePtrPtr; /* Points to location to fill in with
  956.  * pointer to type information for image. */
  957. {
  958.     Tcl_HashEntry *hPtr;
  959.     TkWindow *winPtr;
  960.     ImageMaster *masterPtr;
  961.     winPtr = (TkWindow *) Tk_MainWindow(interp);
  962.     hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, name);
  963.     if (hPtr == NULL) {
  964. *typePtrPtr = NULL;
  965. return NULL;
  966.     }
  967.     masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
  968.     *typePtrPtr = masterPtr->typePtr;
  969.     return masterPtr->masterData;
  970. }
  971. /*
  972.  *----------------------------------------------------------------------
  973.  *
  974.  * Tk_SetTSOrigin --
  975.  *
  976.  * Set the pattern origin of the tile to a common point (i.e. the
  977.  * origin (0,0) of the top level window) so that tiles from two
  978.  * different widgets will match up.  This done by setting the
  979.  * GCTileStipOrigin field is set to the translated origin of the
  980.  * toplevel window in the hierarchy.
  981.  *
  982.  * Results:
  983.  * None.
  984.  *
  985.  * Side Effects:
  986.  * The GCTileStipOrigin is reset in the GC.  This will cause the
  987.  * tile origin to change when the GC is used for drawing.
  988.  *
  989.  *----------------------------------------------------------------------
  990.  */
  991. /*ARGSUSED*/
  992. void
  993. Tk_SetTSOrigin(tkwin, gc, x, y)
  994.     Tk_Window tkwin;
  995.     GC gc;
  996.     int x, y;
  997. {
  998.     while (!Tk_TopWinHierarchy(tkwin)) {
  999. x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
  1000. y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
  1001. tkwin = Tk_Parent(tkwin);
  1002.     }
  1003.     XSetTSOrigin(Tk_Display(tkwin), gc, x, y);
  1004. }