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