home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / tcl / tk3.3b1 / tkBitmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-16  |  16.5 KB  |  558 lines

  1. /* 
  2.  * tkBitmap.c --
  3.  *
  4.  *    This file maintains a database of read-only bitmaps for the Tk
  5.  *    toolkit.  This allows bitmaps to be shared between widgets and
  6.  *    also avoids interactions with the X server.
  7.  *
  8.  * Copyright (c) 1990-1993 The Regents of the University of California.
  9.  * All rights reserved.
  10.  *
  11.  * Permission is hereby granted, without written agreement and without
  12.  * license or royalty fees, to use, copy, modify, and distribute this
  13.  * software and its documentation for any purpose, provided that the
  14.  * above copyright notice and the following two paragraphs appear in
  15.  * all copies of this software.
  16.  * 
  17.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  18.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  19.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  20.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  21.  *
  22.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  23.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  24.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  25.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  26.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkBitmap.c,v 1.21 93/06/16 17:15:57 ouster Exp $ SPRITE (Berkeley)";
  31. #endif /* not lint */
  32.  
  33. #include "tkConfig.h"
  34. #include "tk.h"
  35.  
  36. /*
  37.  * The includes below are for pre-defined bitmaps.
  38.  */
  39.  
  40. #include "bitmaps/error"
  41. #include "bitmaps/gray25"
  42. #include "bitmaps/gray50"
  43. #include "bitmaps/hourglass"
  44. #include "bitmaps/info"
  45. #include "bitmaps/questhead"
  46. #include "bitmaps/question"
  47. #include "bitmaps/warning"
  48.  
  49. /*
  50.  * One of the following data structures exists for each bitmap that is
  51.  * currently in use.  Each structure is indexed with both "idTable" and
  52.  * "nameTable".
  53.  */
  54.  
  55. typedef struct {
  56.     Pixmap bitmap;        /* X identifier for bitmap.  None means this
  57.                  * bitmap was created by Tk_DefineBitmap
  58.                  * and it isn't currently in use. */
  59.     unsigned int width, height;    /* Dimensions of bitmap. */
  60.     Display *display;        /* Display for which bitmap is valid. */
  61.     int refCount;        /* Number of active uses of bitmap. */
  62.     Tcl_HashEntry *hashPtr;    /* Entry in nameTable for this structure
  63.                  * (needed when deleting). */
  64. } TkBitmap;
  65.  
  66. /*
  67.  * Hash table to map from a textual description of a bitmap to the
  68.  * TkBitmap record for the bitmap, and key structure used in that
  69.  * hash table:
  70.  */
  71.  
  72. static Tcl_HashTable nameTable;
  73. typedef struct {
  74.     Tk_Uid name;        /* Textual name for desired bitmap. */
  75.     Display *display;        /* Display for which bitmap will be used. */
  76. } NameKey;
  77.  
  78. /*
  79.  * Hash table that maps from <display + bitmap id> to the TkBitmap structure
  80.  * for the bitmap.  This table is used by Tk_FreeBitmap.
  81.  */
  82.  
  83. static Tcl_HashTable idTable;
  84. typedef struct {
  85.     Display *display;        /* Display for which bitmap was allocated. */
  86.     Pixmap pixmap;        /* X identifier for pixmap. */
  87. } IdKey;
  88.  
  89. /*
  90.  * For each call to Tk_DefineBitmap one of the following structures is
  91.  * created to hold information about the bitmap.
  92.  */
  93.  
  94. typedef struct {
  95.     char *source;        /* Bits for bitmap. */
  96.     unsigned int width, height;    /* Dimensions of bitmap. */
  97. } PredefBitmap;
  98.  
  99. /*
  100.  * Hash table create by Tk_DefineBitmap to map from a name to a
  101.  * collection of in-core data about a bitmap.  The table is
  102.  * indexed by the address of the data for the bitmap, and the entries
  103.  * contain pointers to PredefBitmap structures.
  104.  */
  105.  
  106. static Tcl_HashTable predefTable;
  107.  
  108. /*
  109.  * Hash table used by Tk_GetBitmapFromData to map from a collection
  110.  * of in-core data about a bitmap to a Tk_Uid giving an automatically-
  111.  * generated name for the bitmap:
  112.  */
  113.  
  114. static Tcl_HashTable dataTable;
  115. typedef struct {
  116.     char *source;        /* Bitmap bits. */
  117.     unsigned int width, height;    /* Dimensions of bitmap. */
  118. } DataKey;
  119.  
  120. static int initialized = 0;    /* 0 means static structures haven't been
  121.                  * initialized yet. */
  122.  
  123. /*
  124.  * Forward declarations for procedures defined in this file:
  125.  */
  126.  
  127. static void        BitmapInit _ANSI_ARGS_((void));
  128.  
  129. /*
  130.  *----------------------------------------------------------------------
  131.  *
  132.  * Tk_GetBitmap --
  133.  *
  134.  *    Given a string describing a bitmap, locate (or create if necessary)
  135.  *    a bitmap that fits the description.
  136.  *
  137.  * Results:
  138.  *    The return value is the X identifer for the desired bitmap
  139.  *    (i.e. a Pixmap with a single plane), unless string couldn't be
  140.  *    parsed correctly.  In this case, None is returned and an error
  141.  *    message is left in interp->result.  The caller should never
  142.  *    modify the bitmap that is returned, and should eventually call
  143.  *    Tk_FreeBitmap when the bitmap is no longer needed.
  144.  *
  145.  * Side effects:
  146.  *    The bitmap is added to an internal database with a reference count.
  147.  *    For each call to this procedure, there should eventually be a call
  148.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  149.  *    aren't needed anymore.
  150.  *
  151.  *----------------------------------------------------------------------
  152.  */
  153.  
  154. Pixmap
  155. Tk_GetBitmap(interp, tkwin, string)
  156.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  157.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  158.     Tk_Uid string;        /* Description of bitmap.  See manual entry
  159.                  * for details on legal syntax. */
  160. {
  161.     NameKey nameKey;
  162.     IdKey idKey;
  163.     Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
  164.     register TkBitmap *bitmapPtr;
  165.     PredefBitmap *predefPtr;
  166.     int new;
  167.     Pixmap bitmap;
  168.     unsigned int width, height;
  169.     int dummy2;
  170.  
  171.     if (!initialized) {
  172.     BitmapInit();
  173.     }
  174.  
  175.     nameKey.name = string;
  176.     nameKey.display = Tk_Display(tkwin);
  177.     nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
  178.     if (!new) {
  179.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
  180.     bitmapPtr->refCount++;
  181.     return bitmapPtr->bitmap;
  182.     }
  183.  
  184.     /*
  185.      * No suitable bitmap exists.  Create a new bitmap from the
  186.      * information contained in the string.  If the string starts
  187.      * with "@" then the rest of the string is a file name containing
  188.      * the bitmap.  Otherwise the string must refer to a bitmap
  189.      * defined by a call to Tk_DefineBitmap.
  190.      */
  191.  
  192.     if (*string == '@') {
  193.     Tcl_DString buffer;
  194.     int result;
  195.  
  196.     string = Tcl_TildeSubst(interp, string + 1, &buffer);
  197.     if (string == NULL) {
  198.         goto error;
  199.     }
  200.     result = XReadBitmapFile(nameKey.display,
  201.         RootWindowOfScreen(Tk_Screen(tkwin)), string, &width,
  202.         &height, &bitmap, &dummy2, &dummy2);
  203.     Tcl_DStringFree(&buffer);
  204.     if (result != BitmapSuccess) {
  205.         Tcl_AppendResult(interp, "error reading bitmap file \"", string,
  206.             "\"", (char *) NULL);
  207.         goto error;
  208.     }
  209.     } else {
  210.     predefHashPtr = Tcl_FindHashEntry(&predefTable, string);
  211.     if (predefHashPtr == NULL) {
  212.         Tcl_AppendResult(interp, "bitmap \"", string,
  213.             "\" not defined", (char *) NULL);
  214.         goto error;
  215.     }
  216.     predefPtr = (PredefBitmap *) Tcl_GetHashValue(predefHashPtr);
  217.     width = predefPtr->width;
  218.     height = predefPtr->height;
  219.     bitmap = XCreateBitmapFromData(nameKey.display,
  220.         DefaultRootWindow(nameKey.display), predefPtr->source,
  221.         width, height);
  222.     }
  223.  
  224.     /*
  225.      * Add information about this bitmap to our database.
  226.      */
  227.  
  228.     bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
  229.     bitmapPtr->bitmap = bitmap;
  230.     bitmapPtr->width = width;
  231.     bitmapPtr->height = height;
  232.     bitmapPtr->display = nameKey.display;
  233.     bitmapPtr->refCount = 1;
  234.     bitmapPtr->hashPtr = nameHashPtr;
  235.     idKey.display = nameKey.display;
  236.     idKey.pixmap = bitmap;
  237.     idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
  238.         &new);
  239.     if (!new) {
  240.     panic("bitmap already registered in Tk_GetBitmap");
  241.     }
  242.     Tcl_SetHashValue(nameHashPtr, bitmapPtr);
  243.     Tcl_SetHashValue(idHashPtr, bitmapPtr);
  244.     return bitmapPtr->bitmap;
  245.  
  246.     error:
  247.     Tcl_DeleteHashEntry(nameHashPtr);
  248.     return None;
  249. }
  250.  
  251. /*
  252.  *----------------------------------------------------------------------
  253.  *
  254.  * Tk_DefineBitmap --
  255.  *
  256.  *    This procedure associates a textual name with a binary bitmap
  257.  *    description, so that the name may be used to refer to the
  258.  *    bitmap in future calls to Tk_GetBitmap.
  259.  *
  260.  * Results:
  261.  *    A standard Tcl result.  If an error occurs then TCL_ERROR is
  262.  *    returned and a message is left in interp->result.
  263.  *
  264.  * Side effects:
  265.  *    "Name" is entered into the bitmap table and may be used from
  266.  *    here on to refer to the given bitmap.
  267.  *
  268.  *----------------------------------------------------------------------
  269.  */
  270.  
  271. int
  272. Tk_DefineBitmap(interp, name, source, width, height)
  273.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  274.     Tk_Uid name;        /* Name to use for bitmap.  Must not already
  275.                  * be defined as a bitmap. */
  276.     char *source;        /* Address of bits for bitmap. */
  277.     unsigned int width;        /* Width of bitmap. */
  278.     unsigned int height;    /* Height of bitmap. */
  279. {
  280.     int new;
  281.     Tcl_HashEntry *predefHashPtr;
  282.     PredefBitmap *predefPtr;
  283.  
  284.     if (!initialized) {
  285.     BitmapInit();
  286.     }
  287.  
  288.     predefHashPtr = Tcl_CreateHashEntry(&predefTable, name, &new);
  289.     if (!new) {
  290.         Tcl_AppendResult(interp, "bitmap \"", name,
  291.         "\" is already defined", (char *) NULL);
  292.     return TCL_ERROR;
  293.     }
  294.     predefPtr = (PredefBitmap *) malloc(sizeof(PredefBitmap));
  295.     predefPtr->source = source;
  296.     predefPtr->width = width;
  297.     predefPtr->height = height;
  298.     Tcl_SetHashValue(predefHashPtr, predefPtr);
  299.     return TCL_OK;
  300. }
  301.  
  302. /*
  303.  *--------------------------------------------------------------
  304.  *
  305.  * Tk_NameOfBitmap --
  306.  *
  307.  *    Given a bitmap, return a textual string identifying the
  308.  *    bitmap.
  309.  *
  310.  * Results:
  311.  *    The return value is the string name associated with bitmap.
  312.  *
  313.  * Side effects:
  314.  *    None.
  315.  *
  316.  *--------------------------------------------------------------
  317.  */
  318.  
  319. Tk_Uid
  320. Tk_NameOfBitmap(display, bitmap)
  321.     Display *display;            /* Display for which bitmap was
  322.                      * allocated. */
  323.     Pixmap bitmap;            /* Bitmap whose name is wanted. */
  324. {
  325.     IdKey idKey;
  326.     Tcl_HashEntry *idHashPtr;
  327.     TkBitmap *bitmapPtr;
  328.  
  329.     if (!initialized) {
  330.     unknown:
  331.     panic("Tk_NameOfBitmap received unknown bitmap argument");
  332.     }
  333.  
  334.     idKey.display = display;
  335.     idKey.pixmap = bitmap;
  336.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  337.     if (idHashPtr == NULL) {
  338.     goto unknown;
  339.     }
  340.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  341.     return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
  342. }
  343.  
  344. /*
  345.  *--------------------------------------------------------------
  346.  *
  347.  * Tk_SizeOfBitmap --
  348.  *
  349.  *    Given a bitmap managed by this module, returns the width
  350.  *    and height of the bitmap.
  351.  *
  352.  * Results:
  353.  *    The words at *widthPtr and *heightPtr are filled in with
  354.  *    the dimenstions of bitmap.
  355.  *
  356.  * Side effects:
  357.  *    If bitmap isn't managed by this module then the procedure
  358.  *    panics..
  359.  *
  360.  *--------------------------------------------------------------
  361.  */
  362.  
  363. void
  364. Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr)
  365.     Display *display;            /* Display for which bitmap was
  366.                      * allocated. */
  367.     Pixmap bitmap;            /* Bitmap whose size is wanted. */
  368.     unsigned int *widthPtr;        /* Store bitmap width here. */
  369.     unsigned int *heightPtr;        /* Store bitmap height here. */
  370. {
  371.     IdKey idKey;
  372.     Tcl_HashEntry *idHashPtr;
  373.     TkBitmap *bitmapPtr;
  374.  
  375.     if (!initialized) {
  376.     unknownBitmap:
  377.     panic("Tk_SizeOfBitmap received unknown bitmap argument");
  378.     }
  379.  
  380.     idKey.display = display;
  381.     idKey.pixmap = bitmap;
  382.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  383.     if (idHashPtr == NULL) {
  384.     goto unknownBitmap;
  385.     }
  386.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  387.     *widthPtr = bitmapPtr->width;
  388.     *heightPtr = bitmapPtr->height;
  389. }
  390.  
  391. /*
  392.  *----------------------------------------------------------------------
  393.  *
  394.  * Tk_FreeBitmap --
  395.  *
  396.  *    This procedure is called to release a bitmap allocated by
  397.  *    Tk_GetBitmap or TkGetBitmapFromData.
  398.  *
  399.  * Results:
  400.  *    None.
  401.  *
  402.  * Side effects:
  403.  *    The reference count associated with bitmap is decremented, and
  404.  *    it is officially deallocated if no-one is using it anymore.
  405.  *
  406.  *----------------------------------------------------------------------
  407.  */
  408.  
  409. void
  410. Tk_FreeBitmap(display, bitmap)
  411.     Display *display;            /* Display for which bitmap was
  412.                      * allocated. */
  413.     Pixmap bitmap;            /* Bitmap to be released. */
  414. {
  415.     Tcl_HashEntry *idHashPtr;
  416.     register TkBitmap *bitmapPtr;
  417.     IdKey idKey;
  418.  
  419.     if (!initialized) {
  420.     panic("Tk_FreeBitmap called before Tk_GetBitmap");
  421.     }
  422.  
  423.     idKey.display = display;
  424.     idKey.pixmap = bitmap;
  425.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  426.     if (idHashPtr == NULL) {
  427.     panic("Tk_FreeBitmap received unknown bitmap argument");
  428.     }
  429.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  430.     bitmapPtr->refCount--;
  431.     if (bitmapPtr->refCount == 0) {
  432.     XFreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
  433.     Tcl_DeleteHashEntry(idHashPtr);
  434.     Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
  435.     ckfree((char *) bitmapPtr);
  436.     }
  437. }
  438.  
  439. /*
  440.  *----------------------------------------------------------------------
  441.  *
  442.  * Tk_GetBitmapFromData --
  443.  *
  444.  *    Given a description of the bits for a bitmap, make a bitmap that
  445.  *    has the given properties. *** NOTE:  this procedure is obsolete
  446.  *    and really shouldn't be used anymore. ***
  447.  *
  448.  * Results:
  449.  *    The return value is the X identifer for the desired bitmap
  450.  *    (a one-plane Pixmap), unless it couldn't be created properly.
  451.  *    In this case, None is returned and an error message is left in
  452.  *    interp->result.  The caller should never modify the bitmap that
  453.  *    is returned, and should eventually call Tk_FreeBitmap when the
  454.  *    bitmap is no longer needed.
  455.  *
  456.  * Side effects:
  457.  *    The bitmap is added to an internal database with a reference count.
  458.  *    For each call to this procedure, there should eventually be a call
  459.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  460.  *    aren't needed anymore.
  461.  *
  462.  *----------------------------------------------------------------------
  463.  */
  464.  
  465.     /* ARGSUSED */
  466. Pixmap
  467. Tk_GetBitmapFromData(interp, tkwin, source, width, height)
  468.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  469.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  470.     char *source;        /* Bitmap data for bitmap shape. */
  471.     unsigned int width, height;    /* Dimensions of bitmap. */
  472. {
  473.     DataKey nameKey;
  474.     Tcl_HashEntry *dataHashPtr;
  475.     Tk_Uid name = NULL;        /* Initialization need only to prevent
  476.                  * compiler warning. */
  477.     int new;
  478.     static autoNumber = 0;
  479.     char string[20];
  480.  
  481.     if (!initialized) {
  482.     BitmapInit();
  483.     }
  484.  
  485.     nameKey.source = source;
  486.     nameKey.width = width;
  487.     nameKey.height = height;
  488.     dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new);
  489.     if (!new) {
  490.     name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
  491.     } else {
  492.     autoNumber++;
  493.     sprintf(string, "_tk%d", autoNumber);
  494.     name = Tk_GetUid(string);
  495.     Tcl_SetHashValue(dataHashPtr, name);
  496.     if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
  497.         Tcl_DeleteHashEntry(dataHashPtr);
  498.         return TCL_ERROR;
  499.     }
  500.     }
  501.     return Tk_GetBitmap(interp, tkwin, name);
  502. }
  503.  
  504. /*
  505.  *----------------------------------------------------------------------
  506.  *
  507.  * BitmapInit --
  508.  *
  509.  *    Initialize the structures used for bitmap management.
  510.  *
  511.  * Results:
  512.  *    None.
  513.  *
  514.  * Side effects:
  515.  *    Read the code.
  516.  *
  517.  *----------------------------------------------------------------------
  518.  */
  519.  
  520. static void
  521. BitmapInit()
  522. {
  523.     Tcl_Interp *dummy;
  524.  
  525.     dummy = Tcl_CreateInterp();
  526.     initialized = 1;
  527.     Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
  528.     Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
  529.     Tcl_InitHashTable(&predefTable, TCL_ONE_WORD_KEYS);
  530.  
  531.     /*
  532.      * The call below is tricky:  can't use sizeof(IdKey) because it
  533.      * gets padded with extra unpredictable bytes on some 64-bit
  534.      * machines.
  535.      */
  536.  
  537.     Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Pixmap))
  538.         /sizeof(int));
  539.  
  540.     Tk_DefineBitmap(dummy, Tk_GetUid("error"), error_bits,
  541.         error_width, error_height);
  542.     Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), gray50_bits,
  543.         gray50_width, gray50_height);
  544.     Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), gray25_bits,
  545.         gray25_width, gray25_height);
  546.     Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), hourglass_bits,
  547.         hourglass_width, hourglass_height);
  548.     Tk_DefineBitmap(dummy, Tk_GetUid("info"), info_bits,
  549.         info_width, info_height);
  550.     Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), questhead_bits,
  551.         questhead_width, questhead_height);
  552.     Tk_DefineBitmap(dummy, Tk_GetUid("question"), question_bits,
  553.         question_width, question_height);
  554.     Tk_DefineBitmap(dummy, Tk_GetUid("warning"), warning_bits,
  555.         warning_width, warning_height);
  556.     Tcl_DeleteInterp(dummy);
  557. }
  558.