/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwincolor.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwincolor.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 44 by dashley, Fri Oct 14 02:09:58 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkwincolor.c,v 1.1.1.1 2001/06/13 05:12:03 dtashley Exp $ */  
   
 /*  
  * tkWinColor.c --  
  *  
  *      Functions to map color names to system color values.  
  *  
  * Copyright (c) 1995 Sun Microsystems, Inc.  
  * Copyright (c) 1994 Software Research Associates, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tkwincolor.c,v 1.1.1.1 2001/06/13 05:12:03 dtashley Exp $  
  */  
   
 #include "tkWinInt.h"  
 #include "tkColor.h"  
   
 /*  
  * The following structure is used to keep track of each color that is  
  * allocated by this module.  
  */  
   
 typedef struct WinColor {  
     TkColor info;               /* Generic color information. */  
     int index;                  /* Index for GetSysColor(), -1 if color  
                                  * is not a "live" system color. */  
 } WinColor;  
   
 /*  
  * The sysColors array contains the names and index values for the  
  * Windows indirect system color names.  In use, all of the names  
  * will have the string "System" prepended, but we omit it in the table  
  * to save space.  
  */  
   
 typedef struct {  
     char *name;  
     int index;  
 } SystemColorEntry;  
   
   
 static SystemColorEntry sysColors[] = {  
     "3dDarkShadow",             COLOR_3DDKSHADOW,  
     "3dLight",                  COLOR_3DLIGHT,  
     "ActiveBorder",             COLOR_ACTIVEBORDER,  
     "ActiveCaption",            COLOR_ACTIVECAPTION,  
     "AppWorkspace",             COLOR_APPWORKSPACE,  
     "Background",               COLOR_BACKGROUND,  
     "ButtonFace",               COLOR_BTNFACE,  
     "ButtonHighlight",          COLOR_BTNHIGHLIGHT,  
     "ButtonShadow",             COLOR_BTNSHADOW,  
     "ButtonText",               COLOR_BTNTEXT,  
     "CaptionText",              COLOR_CAPTIONTEXT,  
     "DisabledText",             COLOR_GRAYTEXT,  
     "GrayText",                 COLOR_GRAYTEXT,  
     "Highlight",                COLOR_HIGHLIGHT,  
     "HighlightText",            COLOR_HIGHLIGHTTEXT,  
     "InactiveBorder",           COLOR_INACTIVEBORDER,  
     "InactiveCaption",          COLOR_INACTIVECAPTION,  
     "InactiveCaptionText",      COLOR_INACTIVECAPTIONTEXT,  
     "InfoBackground",           COLOR_INFOBK,  
     "InfoText",                 COLOR_INFOTEXT,  
     "Menu",                     COLOR_MENU,  
     "MenuText",                 COLOR_MENUTEXT,  
     "Scrollbar",                COLOR_SCROLLBAR,  
     "Window",                   COLOR_WINDOW,  
     "WindowFrame",              COLOR_WINDOWFRAME,  
     "WindowText",               COLOR_WINDOWTEXT,  
     NULL,                       0  
 };  
   
 typedef struct ThreadSpecificData {  
     int ncolors;  
 } ThreadSpecificData;  
 static Tcl_ThreadDataKey dataKey;  
   
 /*  
  * Forward declarations for functions defined later in this file.  
  */  
   
 static int      FindSystemColor _ANSI_ARGS_((const char *name,  
                     XColor *colorPtr, int *indexPtr));  
 static int      GetColorByName _ANSI_ARGS_((char *name, XColor *color));  
 static int      GetColorByValue _ANSI_ARGS_((char *value, XColor *color));  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * FindSystemColor --  
  *  
  *      This routine finds the color entry that corresponds to the  
  *      specified color.  
  *  
  * Results:  
  *      Returns non-zero on success.  The RGB values of the XColor  
  *      will be initialized to the proper values on success.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static int  
 FindSystemColor(name, colorPtr, indexPtr)  
     const char *name;           /* Color name. */  
     XColor *colorPtr;           /* Where to store results. */  
     int *indexPtr;              /* Out parameter to store color index. */  
 {  
     int l, u, r, i;  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     /*  
      * Count the number of elements in the color array if we haven't  
      * done so yet.  
      */  
   
     if (tsdPtr->ncolors == 0) {  
         SystemColorEntry *ePtr;  
         int version;  
   
         version = LOBYTE(LOWORD(GetVersion()));  
         for (ePtr = sysColors; ePtr->name != NULL; ePtr++) {  
             if (version < 4) {  
                 if (ePtr->index == COLOR_3DDKSHADOW) {  
                     ePtr->index = COLOR_BTNSHADOW;  
                 } else if (ePtr->index == COLOR_3DLIGHT) {  
                     ePtr->index = COLOR_BTNHIGHLIGHT;  
                 }  
             }  
             tsdPtr->ncolors++;  
         }  
     }  
   
     /*  
      * Perform a binary search on the sorted array of colors.  
      */  
   
     l = 0;  
     u = tsdPtr->ncolors - 1;  
     while (l <= u) {  
         i = (l + u) / 2;  
         r = strcasecmp(name, sysColors[i].name);  
         if (r == 0) {  
             break;  
         } else if (r < 0) {  
             u = i-1;  
         } else {  
             l = i+1;  
         }  
     }  
     if (l > u) {  
         return 0;  
     }  
   
     *indexPtr = sysColors[i].index;  
     colorPtr->pixel = GetSysColor(sysColors[i].index);  
     /*  
      * x257 is (value<<8 + value) to get the properly bit shifted  
      * and padded value.  [Bug: 4919]  
      */  
     colorPtr->red = GetRValue(colorPtr->pixel) * 257;  
     colorPtr->green = GetGValue(colorPtr->pixel) * 257;  
     colorPtr->blue = GetBValue(colorPtr->pixel) * 257;  
     colorPtr->flags = DoRed|DoGreen|DoBlue;  
     colorPtr->pad = 0;  
     return 1;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpGetColor --  
  *  
  *      Allocate a new TkColor for the color with the given name.  
  *  
  * Results:  
  *      Returns a newly allocated TkColor, or NULL on failure.  
  *  
  * Side effects:  
  *      May invalidate the colormap cache associated with tkwin upon  
  *      allocating a new colormap entry.  Allocates a new TkColor  
  *      structure.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 TkColor *  
 TkpGetColor(tkwin, name)  
     Tk_Window tkwin;            /* Window in which color will be used. */  
     Tk_Uid name;                /* Name of color to allocated (in form  
                                  * suitable for passing to XParseColor). */  
 {  
     WinColor *winColPtr;  
     XColor color;  
     int index = -1;             /* -1 indicates that this is not an indirect  
                                  * sytem color. */  
   
     /*  
      * Check to see if it is a system color or an X color string.  If the  
      * color is found, allocate a new WinColor and store the XColor and the  
      * system color index.  
      */  
   
     if (((strncasecmp(name, "system", 6) == 0)  
             && FindSystemColor(name+6, &color, &index))  
             || XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name,  
                     &color)) {  
         winColPtr = (WinColor *) ckalloc(sizeof(WinColor));  
         winColPtr->info.color = color;  
         winColPtr->index = index;  
   
         XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin),  
                 &winColPtr->info.color);  
         return (TkColor *) winColPtr;  
     }  
     return (TkColor *) NULL;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpGetColorByValue --  
  *  
  *      Given a desired set of red-green-blue intensities for a color,  
  *      locate a pixel value to use to draw that color in a given  
  *      window.  
  *  
  * Results:  
  *      The return value is a pointer to an TkColor structure that  
  *      indicates the closest red, blue, and green intensities available  
  *      to those specified in colorPtr, and also specifies a pixel  
  *      value to use to draw in that color.  
  *  
  * Side effects:  
  *      May invalidate the colormap cache for the specified window.  
  *      Allocates a new TkColor structure.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 TkColor *  
 TkpGetColorByValue(tkwin, colorPtr)  
     Tk_Window tkwin;            /* Window in which color will be used. */  
     XColor *colorPtr;           /* Red, green, and blue fields indicate  
                                  * desired color. */  
 {  
     WinColor *tkColPtr = (WinColor *) ckalloc(sizeof(WinColor));  
   
     tkColPtr->info.color.red = colorPtr->red;  
     tkColPtr->info.color.green = colorPtr->green;  
     tkColPtr->info.color.blue = colorPtr->blue;  
     tkColPtr->info.color.pixel = 0;  
     tkColPtr->index = -1;  
     XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin), &tkColPtr->info.color);  
     return (TkColor *) tkColPtr;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpFreeColor --  
  *  
  *      Release the specified color back to the system.  
  *  
  * Results:  
  *      None  
  *  
  * Side effects:  
  *      Invalidates the colormap cache for the colormap associated with  
  *      the given color.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkpFreeColor(tkColPtr)  
     TkColor *tkColPtr;          /* Color to be released.  Must have been  
                                  * allocated by TkpGetColor or  
                                  * TkpGetColorByValue. */  
 {  
     Screen *screen = tkColPtr->screen;  
   
     XFreeColors(DisplayOfScreen(screen), tkColPtr->colormap,  
             &tkColPtr->color.pixel, 1, 0L);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinIndexOfColor --  
  *  
  *      Given a color, return the system color index that was used  
  *      to create the color.  
  *  
  * Results:  
  *      If the color was allocated using a system indirect color name,  
  *      then the corresponding GetSysColor() index is returned.  
  *      Otherwise, -1 is returned.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 TkWinIndexOfColor(colorPtr)  
     XColor *colorPtr;  
 {  
     register WinColor *winColPtr = (WinColor *) colorPtr;  
     if (winColPtr->info.magic == COLOR_MAGIC) {  
         return winColPtr->index;  
     }      
     return -1;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * XAllocColor --  
  *  
  *      Find the closest available color to the specified XColor.  
  *  
  * Results:  
  *      Updates the color argument and returns 1 on success.  Otherwise  
  *      returns 0.  
  *  
  * Side effects:  
  *      Allocates a new color in the palette.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 XAllocColor(display, colormap, color)  
     Display* display;  
     Colormap colormap;  
     XColor* color;  
 {  
     TkWinColormap *cmap = (TkWinColormap *) colormap;  
     PALETTEENTRY entry, closeEntry;  
     HDC dc = GetDC(NULL);  
   
     entry.peRed = (color->red) >> 8;  
     entry.peGreen = (color->green) >> 8;  
     entry.peBlue = (color->blue) >> 8;  
     entry.peFlags = 0;  
   
     if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {  
         unsigned long sizePalette = GetDeviceCaps(dc, SIZEPALETTE);  
         UINT newPixel, closePixel;  
         int new, refCount;  
         Tcl_HashEntry *entryPtr;  
         UINT index;  
   
         /*  
          * Find the nearest existing palette entry.  
          */  
           
         newPixel = RGB(entry.peRed, entry.peGreen, entry.peBlue);  
         index = GetNearestPaletteIndex(cmap->palette, newPixel);  
         GetPaletteEntries(cmap->palette, index, 1, &closeEntry);  
         closePixel = RGB(closeEntry.peRed, closeEntry.peGreen,  
                 closeEntry.peBlue);  
   
         /*  
          * If this is not a duplicate, allocate a new entry.  Note that  
          * we may get values for index that are above the current size  
          * of the palette.  This happens because we don't shrink the size of  
          * the palette object when we deallocate colors so there may be  
          * stale values that match in the upper slots.  We should ignore  
          * those values and just put the new color in as if the colors  
          * had not matched.  
          */  
           
         if ((index >= cmap->size) || (newPixel != closePixel)) {  
             if (cmap->size == sizePalette) {  
                 color->red   = closeEntry.peRed * 257;  
                 color->green = closeEntry.peGreen * 257;  
                 color->blue  = closeEntry.peBlue * 257;  
                 entry = closeEntry;  
                 if (index >= cmap->size) {  
                     OutputDebugString("XAllocColor: Colormap is bigger than we thought");  
                 }  
             } else {  
                 cmap->size++;  
                 ResizePalette(cmap->palette, cmap->size);  
                 SetPaletteEntries(cmap->palette, cmap->size - 1, 1, &entry);  
             }  
         }  
   
         color->pixel = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);  
         entryPtr = Tcl_CreateHashEntry(&cmap->refCounts,  
                 (char *) color->pixel, &new);  
         if (new) {  
             refCount = 1;  
         } else {  
             refCount = ((int) Tcl_GetHashValue(entryPtr)) + 1;  
         }  
         Tcl_SetHashValue(entryPtr, (ClientData)refCount);  
     } else {  
           
         /*  
          * Determine what color will actually be used on non-colormap systems.  
          */  
           
         color->pixel = GetNearestColor(dc,  
                 RGB(entry.peRed, entry.peGreen, entry.peBlue));  
         color->red    = GetRValue(color->pixel) * 257;  
         color->green  = GetGValue(color->pixel) * 257;  
         color->blue   = GetBValue(color->pixel) * 257;  
     }  
   
     ReleaseDC(NULL, dc);  
     return 1;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * XFreeColors --  
  *  
  *      Deallocate a block of colors.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Removes entries for the current palette and compacts the  
  *      remaining set.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 XFreeColors(display, colormap, pixels, npixels, planes)  
     Display* display;  
     Colormap colormap;  
     unsigned long* pixels;  
     int npixels;  
     unsigned long planes;  
 {  
     TkWinColormap *cmap = (TkWinColormap *) colormap;  
     COLORREF cref;  
     UINT count, index, refCount;  
     int i;  
     PALETTEENTRY entry, *entries;  
     Tcl_HashEntry *entryPtr;  
     HDC dc = GetDC(NULL);  
   
     /*  
      * We don't have to do anything for non-palette devices.  
      */  
       
     if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {  
   
         /*  
          * This is really slow for large values of npixels.  
          */  
   
         for (i = 0; i < npixels; i++) {  
             entryPtr = Tcl_FindHashEntry(&cmap->refCounts,  
                     (char *) pixels[i]);  
             if (!entryPtr) {  
                 panic("Tried to free a color that isn't allocated.");  
             }  
             refCount = (int) Tcl_GetHashValue(entryPtr) - 1;  
             if (refCount == 0) {  
                 cref = pixels[i] & 0x00ffffff;  
                 index = GetNearestPaletteIndex(cmap->palette, cref);  
                 GetPaletteEntries(cmap->palette, index, 1, &entry);  
                 if (cref == RGB(entry.peRed, entry.peGreen, entry.peBlue)) {  
                     count = cmap->size - index;  
                     entries = (PALETTEENTRY *) ckalloc(sizeof(PALETTEENTRY)  
                             * count);  
                     GetPaletteEntries(cmap->palette, index+1, count, entries);  
                     SetPaletteEntries(cmap->palette, index, count, entries);  
                     ckfree((char *) entries);  
                     cmap->size--;  
                 } else {  
                     panic("Tried to free a color that isn't allocated.");  
                 }  
                 Tcl_DeleteHashEntry(entryPtr);  
             } else {  
                 Tcl_SetHashValue(entryPtr, (ClientData)refCount);  
             }  
         }  
     }  
     ReleaseDC(NULL, dc);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * XCreateColormap --  
  *  
  *      Allocate a new colormap.  
  *  
  * Results:  
  *      Returns a newly allocated colormap.  
  *  
  * Side effects:  
  *      Allocates an empty palette and color list.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 Colormap  
 XCreateColormap(display, w, visual, alloc)  
     Display* display;  
     Window w;  
     Visual* visual;  
     int alloc;  
 {  
     char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];  
     LOGPALETTE *logPalettePtr;  
     PALETTEENTRY *entryPtr;  
     TkWinColormap *cmap;  
     Tcl_HashEntry *hashPtr;  
     int new;  
     UINT i;  
     HPALETTE sysPal;  
   
     /*  
      * Allocate a starting palette with all of the reserved colors.  
      */  
   
     logPalettePtr = (LOGPALETTE *) logPalBuf;  
     logPalettePtr->palVersion = 0x300;  
     sysPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);  
     logPalettePtr->palNumEntries = GetPaletteEntries(sysPal, 0, 256,  
             logPalettePtr->palPalEntry);  
   
     cmap = (TkWinColormap *) ckalloc(sizeof(TkWinColormap));  
     cmap->size = logPalettePtr->palNumEntries;  
     cmap->stale = 0;  
     cmap->palette = CreatePalette(logPalettePtr);  
   
     /*  
      * Add hash entries for each of the static colors.  
      */  
   
     Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);  
     for (i = 0; i < logPalettePtr->palNumEntries; i++) {  
         entryPtr = logPalettePtr->palPalEntry + i;  
         hashPtr = Tcl_CreateHashEntry(&cmap->refCounts, (char*) PALETTERGB(  
             entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue), &new);  
         Tcl_SetHashValue(hashPtr, (ClientData)1);  
     }  
   
     return (Colormap)cmap;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * XFreeColormap --  
  *  
  *      Frees the resources associated with the given colormap.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Deletes the palette associated with the colormap.  Note that  
  *      the palette must not be selected into a device context when  
  *      this occurs.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 XFreeColormap(display, colormap)  
     Display* display;  
     Colormap colormap;  
 {  
     TkWinColormap *cmap = (TkWinColormap *) colormap;  
     if (!DeleteObject(cmap->palette)) {  
         panic("Unable to free colormap, palette is still selected.");  
     }  
     Tcl_DeleteHashTable(&cmap->refCounts);  
     ckfree((char *) cmap);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinSelectPalette --  
  *  
  *      This function sets up the specified device context with a  
  *      given palette.  If the palette is stale, it realizes it in  
  *      the background unless the palette is the current global  
  *      palette.  
  *  
  * Results:  
  *      Returns the previous palette selected into the device context.  
  *  
  * Side effects:  
  *      May change the system palette.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 HPALETTE  
 TkWinSelectPalette(dc, colormap)  
     HDC dc;  
     Colormap colormap;  
 {  
     TkWinColormap *cmap = (TkWinColormap *) colormap;  
     HPALETTE oldPalette;  
   
     oldPalette = SelectPalette(dc, cmap->palette,  
             (cmap->palette == TkWinGetSystemPalette()) ? FALSE : TRUE);  
     RealizePalette(dc);  
     return oldPalette;  
 }  
   
   
 /* $History: tkWinColor.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 3:10a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKWINCOLOR.C */  
1    /* $Header$ */
2    
3    /*
4     * tkWinColor.c --
5     *
6     *      Functions to map color names to system color values.
7     *
8     * Copyright (c) 1995 Sun Microsystems, Inc.
9     * Copyright (c) 1994 Software Research Associates, 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: tkwincolor.c,v 1.1.1.1 2001/06/13 05:12:03 dtashley Exp $
15     */
16    
17    #include "tkWinInt.h"
18    #include "tkColor.h"
19    
20    /*
21     * The following structure is used to keep track of each color that is
22     * allocated by this module.
23     */
24    
25    typedef struct WinColor {
26        TkColor info;               /* Generic color information. */
27        int index;                  /* Index for GetSysColor(), -1 if color
28                                     * is not a "live" system color. */
29    } WinColor;
30    
31    /*
32     * The sysColors array contains the names and index values for the
33     * Windows indirect system color names.  In use, all of the names
34     * will have the string "System" prepended, but we omit it in the table
35     * to save space.
36     */
37    
38    typedef struct {
39        char *name;
40        int index;
41    } SystemColorEntry;
42    
43    
44    static SystemColorEntry sysColors[] = {
45        "3dDarkShadow",             COLOR_3DDKSHADOW,
46        "3dLight",                  COLOR_3DLIGHT,
47        "ActiveBorder",             COLOR_ACTIVEBORDER,
48        "ActiveCaption",            COLOR_ACTIVECAPTION,
49        "AppWorkspace",             COLOR_APPWORKSPACE,
50        "Background",               COLOR_BACKGROUND,
51        "ButtonFace",               COLOR_BTNFACE,
52        "ButtonHighlight",          COLOR_BTNHIGHLIGHT,
53        "ButtonShadow",             COLOR_BTNSHADOW,
54        "ButtonText",               COLOR_BTNTEXT,
55        "CaptionText",              COLOR_CAPTIONTEXT,
56        "DisabledText",             COLOR_GRAYTEXT,
57        "GrayText",                 COLOR_GRAYTEXT,
58        "Highlight",                COLOR_HIGHLIGHT,
59        "HighlightText",            COLOR_HIGHLIGHTTEXT,
60        "InactiveBorder",           COLOR_INACTIVEBORDER,
61        "InactiveCaption",          COLOR_INACTIVECAPTION,
62        "InactiveCaptionText",      COLOR_INACTIVECAPTIONTEXT,
63        "InfoBackground",           COLOR_INFOBK,
64        "InfoText",                 COLOR_INFOTEXT,
65        "Menu",                     COLOR_MENU,
66        "MenuText",                 COLOR_MENUTEXT,
67        "Scrollbar",                COLOR_SCROLLBAR,
68        "Window",                   COLOR_WINDOW,
69        "WindowFrame",              COLOR_WINDOWFRAME,
70        "WindowText",               COLOR_WINDOWTEXT,
71        NULL,                       0
72    };
73    
74    typedef struct ThreadSpecificData {
75        int ncolors;
76    } ThreadSpecificData;
77    static Tcl_ThreadDataKey dataKey;
78    
79    /*
80     * Forward declarations for functions defined later in this file.
81     */
82    
83    static int      FindSystemColor _ANSI_ARGS_((const char *name,
84                        XColor *colorPtr, int *indexPtr));
85    static int      GetColorByName _ANSI_ARGS_((char *name, XColor *color));
86    static int      GetColorByValue _ANSI_ARGS_((char *value, XColor *color));
87    
88    /*
89     *----------------------------------------------------------------------
90     *
91     * FindSystemColor --
92     *
93     *      This routine finds the color entry that corresponds to the
94     *      specified color.
95     *
96     * Results:
97     *      Returns non-zero on success.  The RGB values of the XColor
98     *      will be initialized to the proper values on success.
99     *
100     * Side effects:
101     *      None.
102     *
103     *----------------------------------------------------------------------
104     */
105    
106    static int
107    FindSystemColor(name, colorPtr, indexPtr)
108        const char *name;           /* Color name. */
109        XColor *colorPtr;           /* Where to store results. */
110        int *indexPtr;              /* Out parameter to store color index. */
111    {
112        int l, u, r, i;
113        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
114                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
115    
116        /*
117         * Count the number of elements in the color array if we haven't
118         * done so yet.
119         */
120    
121        if (tsdPtr->ncolors == 0) {
122            SystemColorEntry *ePtr;
123            int version;
124    
125            version = LOBYTE(LOWORD(GetVersion()));
126            for (ePtr = sysColors; ePtr->name != NULL; ePtr++) {
127                if (version < 4) {
128                    if (ePtr->index == COLOR_3DDKSHADOW) {
129                        ePtr->index = COLOR_BTNSHADOW;
130                    } else if (ePtr->index == COLOR_3DLIGHT) {
131                        ePtr->index = COLOR_BTNHIGHLIGHT;
132                    }
133                }
134                tsdPtr->ncolors++;
135            }
136        }
137    
138        /*
139         * Perform a binary search on the sorted array of colors.
140         */
141    
142        l = 0;
143        u = tsdPtr->ncolors - 1;
144        while (l <= u) {
145            i = (l + u) / 2;
146            r = strcasecmp(name, sysColors[i].name);
147            if (r == 0) {
148                break;
149            } else if (r < 0) {
150                u = i-1;
151            } else {
152                l = i+1;
153            }
154        }
155        if (l > u) {
156            return 0;
157        }
158    
159        *indexPtr = sysColors[i].index;
160        colorPtr->pixel = GetSysColor(sysColors[i].index);
161        /*
162         * x257 is (value<<8 + value) to get the properly bit shifted
163         * and padded value.  [Bug: 4919]
164         */
165        colorPtr->red = GetRValue(colorPtr->pixel) * 257;
166        colorPtr->green = GetGValue(colorPtr->pixel) * 257;
167        colorPtr->blue = GetBValue(colorPtr->pixel) * 257;
168        colorPtr->flags = DoRed|DoGreen|DoBlue;
169        colorPtr->pad = 0;
170        return 1;
171    }
172    
173    /*
174     *----------------------------------------------------------------------
175     *
176     * TkpGetColor --
177     *
178     *      Allocate a new TkColor for the color with the given name.
179     *
180     * Results:
181     *      Returns a newly allocated TkColor, or NULL on failure.
182     *
183     * Side effects:
184     *      May invalidate the colormap cache associated with tkwin upon
185     *      allocating a new colormap entry.  Allocates a new TkColor
186     *      structure.
187     *
188     *----------------------------------------------------------------------
189     */
190    
191    TkColor *
192    TkpGetColor(tkwin, name)
193        Tk_Window tkwin;            /* Window in which color will be used. */
194        Tk_Uid name;                /* Name of color to allocated (in form
195                                     * suitable for passing to XParseColor). */
196    {
197        WinColor *winColPtr;
198        XColor color;
199        int index = -1;             /* -1 indicates that this is not an indirect
200                                     * sytem color. */
201    
202        /*
203         * Check to see if it is a system color or an X color string.  If the
204         * color is found, allocate a new WinColor and store the XColor and the
205         * system color index.
206         */
207    
208        if (((strncasecmp(name, "system", 6) == 0)
209                && FindSystemColor(name+6, &color, &index))
210                || XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name,
211                        &color)) {
212            winColPtr = (WinColor *) ckalloc(sizeof(WinColor));
213            winColPtr->info.color = color;
214            winColPtr->index = index;
215    
216            XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin),
217                    &winColPtr->info.color);
218            return (TkColor *) winColPtr;
219        }
220        return (TkColor *) NULL;
221    }
222    
223    /*
224     *----------------------------------------------------------------------
225     *
226     * TkpGetColorByValue --
227     *
228     *      Given a desired set of red-green-blue intensities for a color,
229     *      locate a pixel value to use to draw that color in a given
230     *      window.
231     *
232     * Results:
233     *      The return value is a pointer to an TkColor structure that
234     *      indicates the closest red, blue, and green intensities available
235     *      to those specified in colorPtr, and also specifies a pixel
236     *      value to use to draw in that color.
237     *
238     * Side effects:
239     *      May invalidate the colormap cache for the specified window.
240     *      Allocates a new TkColor structure.
241     *
242     *----------------------------------------------------------------------
243     */
244    
245    TkColor *
246    TkpGetColorByValue(tkwin, colorPtr)
247        Tk_Window tkwin;            /* Window in which color will be used. */
248        XColor *colorPtr;           /* Red, green, and blue fields indicate
249                                     * desired color. */
250    {
251        WinColor *tkColPtr = (WinColor *) ckalloc(sizeof(WinColor));
252    
253        tkColPtr->info.color.red = colorPtr->red;
254        tkColPtr->info.color.green = colorPtr->green;
255        tkColPtr->info.color.blue = colorPtr->blue;
256        tkColPtr->info.color.pixel = 0;
257        tkColPtr->index = -1;
258        XAllocColor(Tk_Display(tkwin), Tk_Colormap(tkwin), &tkColPtr->info.color);
259        return (TkColor *) tkColPtr;
260    }
261    
262    /*
263     *----------------------------------------------------------------------
264     *
265     * TkpFreeColor --
266     *
267     *      Release the specified color back to the system.
268     *
269     * Results:
270     *      None
271     *
272     * Side effects:
273     *      Invalidates the colormap cache for the colormap associated with
274     *      the given color.
275     *
276     *----------------------------------------------------------------------
277     */
278    
279    void
280    TkpFreeColor(tkColPtr)
281        TkColor *tkColPtr;          /* Color to be released.  Must have been
282                                     * allocated by TkpGetColor or
283                                     * TkpGetColorByValue. */
284    {
285        Screen *screen = tkColPtr->screen;
286    
287        XFreeColors(DisplayOfScreen(screen), tkColPtr->colormap,
288                &tkColPtr->color.pixel, 1, 0L);
289    }
290    
291    /*
292     *----------------------------------------------------------------------
293     *
294     * TkWinIndexOfColor --
295     *
296     *      Given a color, return the system color index that was used
297     *      to create the color.
298     *
299     * Results:
300     *      If the color was allocated using a system indirect color name,
301     *      then the corresponding GetSysColor() index is returned.
302     *      Otherwise, -1 is returned.
303     *
304     * Side effects:
305     *      None.
306     *
307     *----------------------------------------------------------------------
308     */
309    
310    int
311    TkWinIndexOfColor(colorPtr)
312        XColor *colorPtr;
313    {
314        register WinColor *winColPtr = (WinColor *) colorPtr;
315        if (winColPtr->info.magic == COLOR_MAGIC) {
316            return winColPtr->index;
317        }    
318        return -1;
319    }
320    
321    /*
322     *----------------------------------------------------------------------
323     *
324     * XAllocColor --
325     *
326     *      Find the closest available color to the specified XColor.
327     *
328     * Results:
329     *      Updates the color argument and returns 1 on success.  Otherwise
330     *      returns 0.
331     *
332     * Side effects:
333     *      Allocates a new color in the palette.
334     *
335     *----------------------------------------------------------------------
336     */
337    
338    int
339    XAllocColor(display, colormap, color)
340        Display* display;
341        Colormap colormap;
342        XColor* color;
343    {
344        TkWinColormap *cmap = (TkWinColormap *) colormap;
345        PALETTEENTRY entry, closeEntry;
346        HDC dc = GetDC(NULL);
347    
348        entry.peRed = (color->red) >> 8;
349        entry.peGreen = (color->green) >> 8;
350        entry.peBlue = (color->blue) >> 8;
351        entry.peFlags = 0;
352    
353        if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
354            unsigned long sizePalette = GetDeviceCaps(dc, SIZEPALETTE);
355            UINT newPixel, closePixel;
356            int new, refCount;
357            Tcl_HashEntry *entryPtr;
358            UINT index;
359    
360            /*
361             * Find the nearest existing palette entry.
362             */
363            
364            newPixel = RGB(entry.peRed, entry.peGreen, entry.peBlue);
365            index = GetNearestPaletteIndex(cmap->palette, newPixel);
366            GetPaletteEntries(cmap->palette, index, 1, &closeEntry);
367            closePixel = RGB(closeEntry.peRed, closeEntry.peGreen,
368                    closeEntry.peBlue);
369    
370            /*
371             * If this is not a duplicate, allocate a new entry.  Note that
372             * we may get values for index that are above the current size
373             * of the palette.  This happens because we don't shrink the size of
374             * the palette object when we deallocate colors so there may be
375             * stale values that match in the upper slots.  We should ignore
376             * those values and just put the new color in as if the colors
377             * had not matched.
378             */
379            
380            if ((index >= cmap->size) || (newPixel != closePixel)) {
381                if (cmap->size == sizePalette) {
382                    color->red   = closeEntry.peRed * 257;
383                    color->green = closeEntry.peGreen * 257;
384                    color->blue  = closeEntry.peBlue * 257;
385                    entry = closeEntry;
386                    if (index >= cmap->size) {
387                        OutputDebugString("XAllocColor: Colormap is bigger than we thought");
388                    }
389                } else {
390                    cmap->size++;
391                    ResizePalette(cmap->palette, cmap->size);
392                    SetPaletteEntries(cmap->palette, cmap->size - 1, 1, &entry);
393                }
394            }
395    
396            color->pixel = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);
397            entryPtr = Tcl_CreateHashEntry(&cmap->refCounts,
398                    (char *) color->pixel, &new);
399            if (new) {
400                refCount = 1;
401            } else {
402                refCount = ((int) Tcl_GetHashValue(entryPtr)) + 1;
403            }
404            Tcl_SetHashValue(entryPtr, (ClientData)refCount);
405        } else {
406            
407            /*
408             * Determine what color will actually be used on non-colormap systems.
409             */
410            
411            color->pixel = GetNearestColor(dc,
412                    RGB(entry.peRed, entry.peGreen, entry.peBlue));
413            color->red    = GetRValue(color->pixel) * 257;
414            color->green  = GetGValue(color->pixel) * 257;
415            color->blue   = GetBValue(color->pixel) * 257;
416        }
417    
418        ReleaseDC(NULL, dc);
419        return 1;
420    }
421    
422    /*
423     *----------------------------------------------------------------------
424     *
425     * XFreeColors --
426     *
427     *      Deallocate a block of colors.
428     *
429     * Results:
430     *      None.
431     *
432     * Side effects:
433     *      Removes entries for the current palette and compacts the
434     *      remaining set.
435     *
436     *----------------------------------------------------------------------
437     */
438    
439    void
440    XFreeColors(display, colormap, pixels, npixels, planes)
441        Display* display;
442        Colormap colormap;
443        unsigned long* pixels;
444        int npixels;
445        unsigned long planes;
446    {
447        TkWinColormap *cmap = (TkWinColormap *) colormap;
448        COLORREF cref;
449        UINT count, index, refCount;
450        int i;
451        PALETTEENTRY entry, *entries;
452        Tcl_HashEntry *entryPtr;
453        HDC dc = GetDC(NULL);
454    
455        /*
456         * We don't have to do anything for non-palette devices.
457         */
458        
459        if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
460    
461            /*
462             * This is really slow for large values of npixels.
463             */
464    
465            for (i = 0; i < npixels; i++) {
466                entryPtr = Tcl_FindHashEntry(&cmap->refCounts,
467                        (char *) pixels[i]);
468                if (!entryPtr) {
469                    panic("Tried to free a color that isn't allocated.");
470                }
471                refCount = (int) Tcl_GetHashValue(entryPtr) - 1;
472                if (refCount == 0) {
473                    cref = pixels[i] & 0x00ffffff;
474                    index = GetNearestPaletteIndex(cmap->palette, cref);
475                    GetPaletteEntries(cmap->palette, index, 1, &entry);
476                    if (cref == RGB(entry.peRed, entry.peGreen, entry.peBlue)) {
477                        count = cmap->size - index;
478                        entries = (PALETTEENTRY *) ckalloc(sizeof(PALETTEENTRY)
479                                * count);
480                        GetPaletteEntries(cmap->palette, index+1, count, entries);
481                        SetPaletteEntries(cmap->palette, index, count, entries);
482                        ckfree((char *) entries);
483                        cmap->size--;
484                    } else {
485                        panic("Tried to free a color that isn't allocated.");
486                    }
487                    Tcl_DeleteHashEntry(entryPtr);
488                } else {
489                    Tcl_SetHashValue(entryPtr, (ClientData)refCount);
490                }
491            }
492        }
493        ReleaseDC(NULL, dc);
494    }
495    
496    /*
497     *----------------------------------------------------------------------
498     *
499     * XCreateColormap --
500     *
501     *      Allocate a new colormap.
502     *
503     * Results:
504     *      Returns a newly allocated colormap.
505     *
506     * Side effects:
507     *      Allocates an empty palette and color list.
508     *
509     *----------------------------------------------------------------------
510     */
511    
512    Colormap
513    XCreateColormap(display, w, visual, alloc)
514        Display* display;
515        Window w;
516        Visual* visual;
517        int alloc;
518    {
519        char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
520        LOGPALETTE *logPalettePtr;
521        PALETTEENTRY *entryPtr;
522        TkWinColormap *cmap;
523        Tcl_HashEntry *hashPtr;
524        int new;
525        UINT i;
526        HPALETTE sysPal;
527    
528        /*
529         * Allocate a starting palette with all of the reserved colors.
530         */
531    
532        logPalettePtr = (LOGPALETTE *) logPalBuf;
533        logPalettePtr->palVersion = 0x300;
534        sysPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
535        logPalettePtr->palNumEntries = GetPaletteEntries(sysPal, 0, 256,
536                logPalettePtr->palPalEntry);
537    
538        cmap = (TkWinColormap *) ckalloc(sizeof(TkWinColormap));
539        cmap->size = logPalettePtr->palNumEntries;
540        cmap->stale = 0;
541        cmap->palette = CreatePalette(logPalettePtr);
542    
543        /*
544         * Add hash entries for each of the static colors.
545         */
546    
547        Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);
548        for (i = 0; i < logPalettePtr->palNumEntries; i++) {
549            entryPtr = logPalettePtr->palPalEntry + i;
550            hashPtr = Tcl_CreateHashEntry(&cmap->refCounts, (char*) PALETTERGB(
551                entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue), &new);
552            Tcl_SetHashValue(hashPtr, (ClientData)1);
553        }
554    
555        return (Colormap)cmap;
556    }
557    
558    /*
559     *----------------------------------------------------------------------
560     *
561     * XFreeColormap --
562     *
563     *      Frees the resources associated with the given colormap.
564     *
565     * Results:
566     *      None.
567     *
568     * Side effects:
569     *      Deletes the palette associated with the colormap.  Note that
570     *      the palette must not be selected into a device context when
571     *      this occurs.
572     *
573     *----------------------------------------------------------------------
574     */
575    
576    void
577    XFreeColormap(display, colormap)
578        Display* display;
579        Colormap colormap;
580    {
581        TkWinColormap *cmap = (TkWinColormap *) colormap;
582        if (!DeleteObject(cmap->palette)) {
583            panic("Unable to free colormap, palette is still selected.");
584        }
585        Tcl_DeleteHashTable(&cmap->refCounts);
586        ckfree((char *) cmap);
587    }
588    
589    /*
590     *----------------------------------------------------------------------
591     *
592     * TkWinSelectPalette --
593     *
594     *      This function sets up the specified device context with a
595     *      given palette.  If the palette is stale, it realizes it in
596     *      the background unless the palette is the current global
597     *      palette.
598     *
599     * Results:
600     *      Returns the previous palette selected into the device context.
601     *
602     * Side effects:
603     *      May change the system palette.
604     *
605     *----------------------------------------------------------------------
606     */
607    
608    HPALETTE
609    TkWinSelectPalette(dc, colormap)
610        HDC dc;
611        Colormap colormap;
612    {
613        TkWinColormap *cmap = (TkWinColormap *) colormap;
614        HPALETTE oldPalette;
615    
616        oldPalette = SelectPalette(dc, cmap->palette,
617                (cmap->palette == TkWinGetSystemPalette()) ? FALSE : TRUE);
618        RealizePalette(dc);
619        return oldPalette;
620    }
621    
622    /* End of tkwincolor.c */

Legend:
Removed from v.44  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25