home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tk / os2 / tkOS2Color.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  26KB  |  906 lines

  1. /* 
  2.  * tkOS2Color.c --
  3.  *
  4.  *    Functions to map color names to system color values.
  5.  *
  6.  * Copyright (c) 1996-1997 Illya Vaes
  7.  * Copyright (c) 1995 Sun Microsystems, Inc.
  8.  * Copyright (c) 1994 Software Research Associates, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  */
  13.  
  14. #include "tkOS2Int.h"
  15. #include "xcolors.h"
  16.  
  17. /*
  18.  * This variable indicates whether the color table has been initialized.
  19.  */
  20.  
  21. static int initialized = 0;
  22.  
  23. /*
  24.  * colorTable is a hash table used to look up X colors by name.
  25.  */
  26.  
  27. static Tcl_HashTable colorTable;
  28.  
  29. /*
  30.  * The SystemColorEntries array contains the names and index values for the
  31.  * OS/2 PM indirect system color names.
  32.  */
  33.  
  34. typedef struct {
  35.     char *name;
  36.     int index;
  37. } SystemColorEntry;
  38.  
  39. static SystemColorEntry sysColorEntries[] = {
  40.     { "SystemActiveBorder",        SYSCLR_ACTIVEBORDER },
  41.     { "SystemActiveCaption",        SYSCLR_ACTIVETITLE },
  42.     { "SystemAppWorkspace",        SYSCLR_APPWORKSPACE },
  43.     { "SystemBackground",        SYSCLR_BACKGROUND },
  44.     { "SystemButtonFace",        SYSCLR_BUTTONMIDDLE },
  45.     { "SystemButtonHighlight",        SYSCLR_BUTTONLIGHT },
  46.     { "SystemButtonShadow",        SYSCLR_BUTTONDARK },
  47.     { "SystemButtonText",        SYSCLR_MENUTEXT },
  48.     { "SystemCaptionText",        SYSCLR_TITLETEXT },
  49.     { "SystemDisabledText",        SYSCLR_MENUDISABLEDTEXT },
  50.     { "SystemHighlight",        SYSCLR_HILITEBACKGROUND },
  51.     { "SystemHighlightText",        SYSCLR_HILITEFOREGROUND },
  52.     { "SystemInactiveBorder",        SYSCLR_INACTIVEBORDER },
  53.     { "SystemInactiveCaption",        SYSCLR_INACTIVETITLE },
  54.     { "SystemInactiveCaptionText",    SYSCLR_INACTIVETITLETEXTBGND },
  55.     { "SystemMenu",            SYSCLR_MENU },
  56.     { "SystemMenuText",            SYSCLR_MENUTEXT },
  57.     { "SystemScrollbar",        SYSCLR_SCROLLBAR },
  58.     { "SystemWindow",            SYSCLR_WINDOW },
  59.     { "SystemWindowFrame",        SYSCLR_WINDOWFRAME },
  60.     { "SystemWindowText",        SYSCLR_WINDOWTEXT },
  61.     { NULL,                0 }
  62. };
  63.  
  64. /*
  65.  * The sysColors array is initialized by SetSystemColors().
  66.  */
  67.  
  68. static XColorEntry sysColors[] = {
  69.     { 0, 0, 0, "SystemActiveBorder" },
  70.     { 0, 0, 0, "SystemActiveCaption" },
  71.     { 0, 0, 0, "SystemAppWorkspace" },
  72.     { 0, 0, 0, "SystemBackground" },
  73.     { 0, 0, 0, "SystemButtonFace" },
  74.     { 0, 0, 0, "SystemButtonHighlight" },
  75.     { 0, 0, 0, "SystemButtonShadow" },
  76.     { 0, 0, 0, "SystemButtonText" },
  77.     { 0, 0, 0, "SystemCaptionText" },
  78.     { 0, 0, 0, "SystemDisabledText" },
  79.     { 0, 0, 0, "SystemHighlight" },
  80.     { 0, 0, 0, "SystemHighlightText" },
  81.     { 0, 0, 0, "SystemInactiveBorder" },
  82.     { 0, 0, 0, "SystemInactiveCaption" },
  83.     { 0, 0, 0, "SystemInactiveCaptionText" },
  84.     { 0, 0, 0, "SystemMenu" },
  85.     { 0, 0, 0, "SystemMenuText" },
  86.     { 0, 0, 0, "SystemScrollbar" },
  87.     { 0, 0, 0, "SystemWindow" },
  88.     { 0, 0, 0, "SystemWindowFrame" },
  89.     { 0, 0, 0, "SystemWindowText" },
  90.     { 0, 0, 0, NULL }
  91. };
  92.  
  93. /*
  94.  * Forward declarations for functions defined later in this file.
  95.  */
  96. static int GetColorByName _ANSI_ARGS_((char *name, XColor *color));
  97. static int GetColorByValue _ANSI_ARGS_((char *value, XColor *color));
  98. static void InitColorTable _ANSI_ARGS_((void));
  99. static void SetSystemColors _ANSI_ARGS_((void));
  100.  
  101.  
  102.  
  103. /*
  104.  *----------------------------------------------------------------------
  105.  *
  106.  * SetSystemColors --
  107.  *
  108.  *    Initializes the sysColors array with the current values for
  109.  *    the system colors.
  110.  *
  111.  * Results:
  112.  *    None.
  113.  *
  114.  * Side effects:
  115.  *    Changes the RGB values stored in the sysColors array.
  116.  *
  117.  *----------------------------------------------------------------------
  118.  */
  119.  
  120. static void
  121. SetSystemColors()
  122. {
  123.     SystemColorEntry *sPtr;
  124.     XColorEntry *ePtr;
  125.     LONG color;
  126.  
  127. #ifdef DEBUG
  128.     printf("SetSystemColors\n");
  129. #endif
  130.  
  131.     for (ePtr = sysColors, sPtr = sysColorEntries;
  132.      sPtr->name != NULL; ePtr++, sPtr++)
  133.     {
  134.     color = WinQuerySysColor(HWND_DESKTOP, sPtr->index, 0);
  135.     ePtr->red = GetRValue(color);
  136.     ePtr->green = GetGValue(color);
  137.     ePtr->blue = GetBValue(color);
  138. #ifdef DEBUG
  139.         printf("    SystemColor %d: %x (%d,%d,%d)\n", sPtr->index, color,
  140.                ePtr->red, ePtr->green, ePtr->blue);
  141. #endif
  142.     }
  143. }
  144.  
  145. /*
  146.  *----------------------------------------------------------------------
  147.  *
  148.  * InitColorTable --
  149.  *
  150.  *    Initialize color name database.
  151.  *
  152.  * Results:
  153.  *    None.
  154.  *
  155.  * Side effects:
  156.  *    Builds a hash table of color names and RGB values.
  157.  *
  158.  *----------------------------------------------------------------------
  159.  */
  160.  
  161. static void
  162. InitColorTable()
  163. {
  164.     XColorEntry *colorPtr;
  165.     Tcl_HashEntry *hPtr;
  166.     int dummy;
  167.     char localname[32];
  168.  
  169. #ifdef DEBUG
  170.     printf("InitColorTable\n");
  171. #endif
  172.     Tcl_InitHashTable(&colorTable, TCL_STRING_KEYS);
  173.  
  174.     /*
  175.      * Add X colors to table.
  176.      */
  177.  
  178.     for (colorPtr = xColors; colorPtr->name != NULL; colorPtr++) {
  179.         /* We need a *modifiable* copy of the string from xColors! */
  180.         strncpy(localname, colorPtr->name, 32);
  181.         hPtr = Tcl_CreateHashEntry(&colorTable, strlwr(localname), &dummy);
  182.         Tcl_SetHashValue(hPtr, colorPtr);
  183.     }
  184.     
  185.     /*
  186.      * Add OS/2 PM indirect system colors to table.
  187.      */
  188.  
  189.     SetSystemColors();
  190.     for (colorPtr = sysColors; colorPtr->name != NULL; colorPtr++) {
  191.         /* We need a *modifiable* copy of the string from sysColors! */
  192.         strncpy(localname, colorPtr->name, 32);
  193.         hPtr = Tcl_CreateHashEntry(&colorTable, strlwr(localname), &dummy);
  194.         Tcl_SetHashValue(hPtr, colorPtr);
  195.     }
  196.  
  197.     initialized = 1;
  198. }
  199.  
  200. /*
  201.  *----------------------------------------------------------------------
  202.  *
  203.  * GetColorByName --
  204.  *
  205.  *    Looks for a color in the color table by name, then finds the
  206.  *    closest available color in the palette and converts it to an
  207.  *    XColor structure.
  208.  *
  209.  * Results:
  210.  *    If it finds a match, the color is returned in the color
  211.  *    parameter and the return value is 1.  Otherwise the return
  212.  *    value is 0.
  213.  *
  214.  * Side effects:
  215.  *    None.
  216.  *
  217.  *----------------------------------------------------------------------
  218.  */
  219.  
  220. static int
  221. GetColorByName(name, color)
  222.     char *name;            /* An X color name, e.g. "red" */
  223.     XColor *color;        /* The closest available color. */
  224. {
  225.     Tcl_HashEntry *hPtr;
  226.     XColorEntry *colorPtr;
  227.     char localname[32];
  228.  
  229. #ifdef DEBUG
  230.     printf("GetColorByName %s\n", name);
  231. #endif
  232.  
  233.     if (!initialized) {
  234.     InitColorTable();
  235.     }
  236.  
  237.     /* We need a *modifiable* copy of the string name! */
  238.     strncpy(localname, name, 32);
  239.     hPtr = Tcl_FindHashEntry(&colorTable, (char *) strlwr(localname));
  240.  
  241.     if (hPtr == NULL) {
  242.     return 0;
  243.     }
  244.  
  245.     colorPtr = (XColorEntry *) Tcl_GetHashValue(hPtr);
  246.     color->pixel = RGB(colorPtr->red, colorPtr->green, colorPtr->blue);
  247.     color->red = colorPtr->red << 8;
  248.     color->green = colorPtr->green << 8;
  249.     color->blue = colorPtr->blue << 8;
  250. #ifdef DEBUG
  251.     printf("RGB %x %x %x (PM %d %d %d)\n", color->red, color->green,
  252.            color->blue, colorPtr->red, colorPtr->green, colorPtr->blue);
  253. #endif
  254.     color->pad = 0;
  255.  
  256.     return 1;
  257. }      
  258.  
  259. /*
  260.  *----------------------------------------------------------------------
  261.  *
  262.  * GetColorByValue --
  263.  *
  264.  *    Parses an X RGB color string and finds the closest available
  265.  *    color in the palette and converts it to an XColor structure.
  266.  *    The returned color will have RGB values in the range 0 to 255.
  267.  *
  268.  * Results:
  269.  *    If it finds a match, the color is returned in the color
  270.  *    parameter and the return value is 1.  Otherwise the return
  271.  *    value is 0.
  272.  *
  273.  * Side effects:
  274.  *    None.
  275.  *
  276.  *----------------------------------------------------------------------
  277.  */
  278.  
  279. static int
  280. GetColorByValue(value, color)
  281.     char *value;        /* a string of the form "#RGB", "#RRGGBB", */
  282.                 /* "#RRRGGGBBB", or "#RRRRGGGGBBBB" */
  283.     XColor *color;        /* The closest available color. */
  284. {
  285.     char fmt[16];
  286.     int i;
  287.  
  288.     i = strlen(value+1);
  289.     if (i % 3) {
  290.     return 0;
  291.     }
  292.     i /= 3;
  293.     if (i == 0) {
  294.     return 0;
  295.     }
  296.     sprintf(fmt, "%%%dx%%%dx%%%dx", i, i, i);
  297.     sscanf(value+1, fmt, &color->red, &color->green, &color->blue);
  298.     /*
  299.      * Scale the parse values into 8 bits.
  300.      */
  301. #ifdef DEBUG
  302.     printf("GetColorByValue: %x %x %d\n", color->red, color->green, color->blue);
  303. #endif
  304.     if (i == 1) {
  305.     color->red <<= 4;
  306.     color->green <<= 4;
  307.     color->blue <<= 4;
  308.     } else if (i != 2) {
  309.     color->red >>= (4*(i-2));
  310.     color->green >>= (4*(i-2));
  311.     color->blue >>= (4*(i-2));
  312.     }    
  313.     color->pad = 0;
  314.     color->pixel = RGB(color->red, color->green, color->blue); 
  315.     color->red = color->red << 8;
  316.     color->green = color->green << 8;
  317.     color->blue = color->blue << 8;
  318.  
  319. #ifdef DEBUG
  320.     printf("GetColorByValue: now %x %x %d\n", color->red, color->green, color->blue);
  321. #endif
  322.  
  323.     return 1;
  324. }
  325.  
  326. /*
  327.  *----------------------------------------------------------------------
  328.  *
  329.  * XParseColor --
  330.  *
  331.  *    Decodes an X color specification.
  332.  *
  333.  * Results:
  334.  *    Sets exact_def_return to the parsed color.
  335.  *
  336.  * Side effects:
  337.  *    None.
  338.  *
  339.  *----------------------------------------------------------------------
  340.  */
  341.  
  342. int
  343. XParseColor(display, colormap, spec, exact_def_return)
  344.     Display* display;
  345.     Colormap colormap;
  346.     _Xconst char* spec;
  347.     XColor* exact_def_return;
  348. {
  349.     /*
  350.      * Note that we are violating the const-ness of spec.  This is
  351.      * probably OK in most cases.  But this is a bug in general.
  352.      */
  353.  
  354. #ifdef DEBUG
  355.     printf("XParseColor %s\n", spec);
  356. #endif
  357.  
  358.     if (spec[0] == '#') {
  359.     return GetColorByValue((char *)spec, exact_def_return);
  360.     } else {
  361.     return GetColorByName((char *)spec, exact_def_return);
  362.     }
  363. }
  364.  
  365. /*
  366.  *----------------------------------------------------------------------
  367.  *
  368.  * XAllocColor --
  369.  *
  370.  *    Find the closest available color to the specified XColor.
  371.  *
  372.  * Results:
  373.  *    Updates the color argument and returns 1 on success.  Otherwise
  374.  *    returns 0.
  375.  *
  376.  * Side effects:
  377.  *    Allocates a new color in the palette.
  378.  *
  379.  *----------------------------------------------------------------------
  380.  */
  381.  
  382. int
  383. XAllocColor(display, colormap, color)
  384.     Display* display;
  385.     Colormap colormap;
  386.     XColor* color;
  387. {
  388.     TkOS2Colormap *cmap = (TkOS2Colormap *) colormap;
  389.     RGB entry;
  390.     HPAL oldPal;
  391.     ULONG *palInfo;
  392.     LONG i, found = -1;
  393.  
  394.     /* We lose significance when converting to PM, 256 values per color */
  395.     /*
  396.     entry.bRed = (color->red) / 256;
  397.     entry.bGreen = (color->green) / 256;
  398.     entry.bBlue = (color->blue) / 256;
  399.     */
  400.     entry.bRed = (color->red) >> 8;
  401.     entry.bGreen = (color->green) >> 8;
  402.     entry.bBlue = (color->blue) >> 8;
  403.  
  404. #ifdef DEBUG
  405.     printf("XAllocColor %d %d %d (PM: %d %d %d), cmap %x\n", color->red,
  406.            color->green, color->blue, entry.bRed, entry.bGreen, entry.bBlue,
  407.            cmap);
  408. #endif
  409.  
  410.     if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
  411.     /*
  412.      * Palette support
  413.      */
  414.     ULONG newPixel;
  415.         HPS hps;
  416.     int new, refCount;
  417.     Tcl_HashEntry *entryPtr;
  418.  
  419.         hps = WinGetScreenPS(HWND_DESKTOP);
  420.  
  421. #ifdef DEBUG
  422.         printf("    Palette Manager\n");
  423. #endif
  424.  
  425.     /*
  426.      * Find the nearest existing palette entry.
  427.      */
  428.     
  429.     newPixel = RGB(entry.bRed, entry.bGreen, entry.bBlue);
  430.     oldPal= GpiSelectPalette(hps, cmap->palette);
  431.     if (oldPal == PAL_ERROR) {
  432. #ifdef DEBUG
  433.             printf("GpiSelectPalette PAL_ERROR: %x\n", WinGetLastError(hab));
  434. #endif
  435.             WinReleasePS(hps);
  436.             return 0;
  437.     }
  438.     palInfo= (ULONG *) ckalloc(sizeof(ULONG) * (cmap->size+1));
  439.  
  440.     if (GpiQueryPaletteInfo(cmap->palette, hps, 0L, 0L, cmap->size,
  441.                             palInfo) == PAL_ERROR) {
  442. #ifdef DEBUG
  443.         printf("GpiQueryPaletteInfo PAL_ERROR: %x\n", WinGetLastError(hab));
  444. #endif
  445.         GpiSelectPalette(hps, oldPal);
  446.             WinReleasePS(hps);
  447.         ckfree((char *) palInfo);
  448.             return 0;
  449.     }
  450.  
  451.     /*
  452.      * If this is not a duplicate, allocate a new entry.
  453.      */
  454.     
  455.         for (i=0; i<cmap->size; i++) {
  456.             if (palInfo[i] == newPixel) {
  457.                 found = i;
  458.             }
  459.         }
  460. #ifdef DEBUG
  461.         printf("GpiQueryPaletteInfo found %d\n", found);
  462. #endif
  463.  
  464.     if (found == -1) {
  465.  
  466.         /*
  467.          * Fails if the palette is full.
  468.          */
  469.         if (cmap->size == aDevCaps[CAPS_COLOR_INDEX]) {
  470. #ifdef DEBUG
  471.             printf("palette is full\n");
  472. #endif
  473.             GpiSelectPalette(hps, oldPal);
  474.                 WinReleasePS(hps);
  475.             ckfree((char *) palInfo);
  476.         return 0;
  477.         }
  478.     
  479.         cmap->size++;
  480. #ifdef DEBUG
  481.             printf("adding palInfo[%d]: %d (%d, %d, %d)\n", cmap->size-1,
  482.                    RGB(entry.bRed, entry.bGreen, entry.bBlue),
  483.                    entry.bRed, entry.bGreen, entry.bBlue);
  484. #endif
  485.         palInfo[cmap->size-1]= newPixel;
  486.         GpiSetPaletteEntries(cmap->palette, LCOLF_CONSECRGB, 0L, cmap->size,
  487.                              palInfo);
  488.     }
  489.  
  490.     ckfree((char *) palInfo);
  491.         /*
  492.          * Assign the _index_ in the palette as the pixel, for later use in
  493.          * GpiSetColor et al. ()
  494.          */
  495.         color->pixel = cmap->size-1;
  496.     entryPtr = Tcl_CreateHashEntry(&cmap->refCounts,
  497.         (char *)color->pixel, &new);
  498.     if (new) {
  499. #ifdef DEBUG
  500.             printf("Created new HashEntry: %d\n", color->pixel);
  501. #endif
  502.         refCount = 1;
  503.     } else {
  504.         refCount = ((int) Tcl_GetHashValue(entryPtr)) + 1;
  505. #ifdef DEBUG
  506.             printf("Created HashEntry %d: %d\n", refCount, color->pixel);
  507. #endif
  508.     }
  509.     Tcl_SetHashValue(entryPtr, (ClientData)refCount);
  510.  
  511.     WinReleasePS(hps);
  512.  
  513.     } else {
  514.        LONG index, iColor;
  515.  
  516. #ifdef DEBUG
  517.        printf("    no Palette Manager, nr. colors %d (%s)\n",
  518.               aDevCaps[CAPS_COLORS],
  519.               aDevCaps[CAPS_COLOR_TABLE_SUPPORT] ? "loadable color table" :
  520.               "no loadable color table");
  521. #endif
  522.     
  523.     /*
  524.      * Determine what color will actually be used on non-colormap systems.
  525.      */
  526.  
  527.     color->pixel = GpiQueryNearestColor(globalPS, 0L,
  528.         RGB(entry.bRed, entry.bGreen, entry.bBlue));
  529.     color->red = (GetRValue(color->pixel) << 8);
  530.     color->green = (GetGValue(color->pixel) << 8);
  531.     color->blue = (GetBValue(color->pixel) << 8);
  532. #ifdef DEBUG
  533.         if (color->pixel==GPI_ALTERROR) {
  534.             printf("GpiQueryNearestColor ERROR %x\n", WinGetLastError(hab));
  535.         } else {
  536.             printf("    Using nearest color %x (%d,%d,%d) for %x (%d,%d,%d)\n",
  537.                    color->pixel, GetRValue(color->pixel),
  538.                    GetGValue(color->pixel), GetBValue(color->pixel),
  539.                    RGB(entry.bRed, entry.bGreen, entry.bBlue),
  540.                    color->red, color->green, color->blue);
  541.         }
  542. #endif
  543. if (display->screens->root_visual->class != TrueColor){
  544.     /* See if this color is already in the color table */
  545.         index = GpiQueryColorIndex(globalPS, 0L, color->pixel);
  546. #ifdef DEBUG
  547.         if (index==GPI_ALTERROR) {
  548.             printf("GpiQueryColorIndex ERROR %x\n", WinGetLastError(hab));
  549.         } else {
  550.             printf("            Colorindex %d for %x\n", index, color->pixel);
  551.         }
  552. #endif
  553.     rc = GpiQueryLogColorTable(globalPS, 0L, index, 1, &iColor);
  554. #ifdef DEBUG
  555.         if (iColor==QLCT_ERROR) {
  556.             printf("GpiQueryLogColorTable ERROR %x\n", WinGetLastError(hab));
  557.         } else {
  558.             if (iColor==QLCT_RGB) {
  559.                 printf("GpiQueryLogColorTable in RGB mode\n");
  560.             } else {
  561.                 printf("GpiQueryLogColorTable %d: %x \n", index, iColor);
  562.             }
  563.         }
  564. #endif
  565.     /*
  566.      * If the color isn't in the table yet and loadable color table support,
  567.      * add this color to the table, else just use what's available.
  568.      */
  569.     if (iColor != color->pixel && aDevCaps[CAPS_COLOR_TABLE_SUPPORT]
  570.         && (nextColor <= aDevCaps[CAPS_COLOR_INDEX])) {
  571.         rc = GpiCreateLogColorTable(globalPS, 0L, LCOLF_RGB, nextColor,
  572.                                     1, &color->pixel);
  573.             if (rc==TRUE) {
  574. #ifdef DEBUG
  575.                 printf("    GpiCreateLogColorTable %x at %d OK\n", color->pixel,
  576.                        nextColor);
  577. #endif
  578.                 color->pixel = nextColor;
  579.                 nextColor++;
  580.             } else {
  581.                 color->pixel = index;
  582. #ifdef DEBUG
  583.                 printf("    GpiCreateLogColorTable %x at %d ERROR %x\n",
  584.                        color->pixel, nextColor, WinGetLastError(hab));
  585. #endif
  586.             }
  587.         } else {
  588.             color->pixel = index;
  589.         }
  590. } /* TrueColor */
  591.     }
  592. #ifdef DEBUG
  593.     printf("color->pixel now %x\n", color->pixel);
  594. #endif
  595.  
  596.     return 1;
  597. }
  598.  
  599. /*
  600.  *----------------------------------------------------------------------
  601.  *
  602.  * XAllocNamedColor --
  603.  *
  604.  *    Find the closest color of the given name.
  605.  *
  606.  * Results:
  607.  *    Returns 1 on success with the resulting color in
  608.  *    exact_def_return.  Returns 0 on failure.
  609.  *
  610.  * Side effects:
  611.  *    Allocates a new color in the palette.
  612.  *
  613.  *----------------------------------------------------------------------
  614.  */
  615.  
  616. int
  617. XAllocNamedColor(display, colormap, color_name, screen_def_return,
  618.     exact_def_return)
  619.     Display* display;
  620.     Colormap colormap;
  621.     _Xconst char* color_name;
  622.     XColor* screen_def_return;
  623.     XColor* exact_def_return;
  624. {
  625.     int rval = GetColorByName((char *)color_name, exact_def_return);
  626. #ifdef DEBUG
  627.     printf("XAllocNamedColor\n");
  628. #endif
  629.  
  630.     if (rval) {
  631.     *screen_def_return = *exact_def_return;
  632.     return XAllocColor(display, colormap, exact_def_return);
  633.     } 
  634.     return 0;
  635. }
  636.  
  637. /*
  638.  *----------------------------------------------------------------------
  639.  *
  640.  * XFreeColors --
  641.  *
  642.  *    Deallocate a block of colors.
  643.  *
  644.  * Results:
  645.  *    None.
  646.  *
  647.  * Side effects:
  648.  *    Removes entries for the current palette and compacts the
  649.  *    remaining set.
  650.  *
  651.  *----------------------------------------------------------------------
  652.  */
  653.  
  654. void
  655. XFreeColors(display, colormap, pixels, npixels, planes)
  656.     Display* display;
  657.     Colormap colormap;
  658.     unsigned long* pixels;
  659.     int npixels;
  660.     unsigned long planes;
  661. {
  662.     TkOS2Colormap *cmap = (TkOS2Colormap *) colormap;
  663.     ULONG cref;
  664.     ULONG refCount;
  665.     int i, old, new;
  666.     ULONG *entries;
  667.     Tcl_HashEntry *entryPtr;
  668.  
  669. #ifdef DEBUG
  670.     printf("XFreeColors\n");
  671. #endif
  672.  
  673.     /*
  674.      * We don't have to do anything for non-palette devices.
  675.      */
  676.     
  677.     if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
  678.  
  679.     /*
  680.      * This is really slow for large values of npixels.
  681.      */
  682.     for (i = 0; i < npixels; i++) {
  683.         entryPtr = Tcl_FindHashEntry(&cmap->refCounts,
  684.             (char *) pixels[i]);
  685.         if (!entryPtr) {
  686.         panic("Tried to free a color that isn't allocated.");
  687.         }
  688.         refCount = (int) Tcl_GetHashValue(entryPtr) - 1;
  689.         if (refCount == 0) {
  690.         cref = pixels[i] & 0x00ffffff;
  691.                 entries = (ULONG *) ckalloc(sizeof(ULONG) * cmap->size);
  692.                 /* hps value ignored for specific values of palette */
  693.                 if (GpiQueryPaletteInfo(cmap->palette, NULLHANDLE, 0L, 0L,
  694.                                         cmap->size, entries) == PAL_ERROR) {
  695.                    ckfree((char *)entries);
  696.                    return;
  697.             }
  698.         /* Copy all entries except the one to delete */
  699.         for (old= new= 0; old<cmap->size; old++) {
  700.             if (entries[old] != cref) {
  701.                 entries[new] = entries[old];
  702.                 new++;
  703.             }
  704.         }
  705.         cmap->size--;
  706.             GpiSetPaletteEntries(cmap->palette, LCOLF_CONSECRGB, 0,
  707.                                  cmap->size, entries);
  708.         ckfree((char *) entries);
  709.         Tcl_DeleteHashEntry(entryPtr);
  710.         }
  711.     }
  712.     }
  713. }
  714.  
  715. /*
  716.  *----------------------------------------------------------------------
  717.  *
  718.  * XCreateColormap --
  719.  *
  720.  *    Allocate a new colormap.
  721.  *
  722.  * Results:
  723.  *    Returns a newly allocated colormap.
  724.  *
  725.  * Side effects:
  726.  *    Allocates an empty palette and color list.
  727.  *
  728.  *----------------------------------------------------------------------
  729.  */
  730.  
  731. Colormap
  732. XCreateColormap(display, w, visual, alloc)
  733.     Display* display;
  734.     Window w;
  735.     Visual* visual;
  736.     int alloc;
  737. {
  738.     TkOS2Colormap *cmap = (TkOS2Colormap *) ckalloc(sizeof(TkOS2Colormap));
  739.  
  740. #ifdef DEBUG
  741.     printf("XCreateColormap (%d colors),
  742.            visual id %d class %d, bits %d, map entries %d, masks R%d G%d B%d\n",
  743.            aDevCaps[CAPS_COLOR_INDEX]+1, visual->visualid, visual->class,
  744.            visual->bits_per_rgb, visual->map_entries, visual->red_mask,
  745.            visual->green_mask, visual->blue_mask);
  746.     printf("    CAPS_COLORS %d\n", aDevCaps[CAPS_COLORS]);
  747. #endif
  748.  
  749.     /*
  750.      * Create a palette when we have palette management. Otherwise store the
  751.      * presentation space handle of the window, since color tables are PS-
  752.      * specific.
  753.      */
  754.     if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
  755.         ULONG logPalette[1];
  756.  
  757.         logPalette[0] = 0;
  758.         cmap->palette = GpiCreatePalette(hab, 0L, LCOLF_CONSECRGB, 1L,
  759.                                          logPalette);
  760. #ifdef DEBUG
  761.         if (cmap->palette == GPI_ERROR) {
  762.             printf("    GpiCreatePalette GPI_ERROR %x\n", WinGetLastError(hab));
  763.             ckfree((char *)cmap);
  764.         } else {
  765.             printf("    GpiCreatePalette: %x\n", cmap->palette);
  766.         }
  767. #endif
  768.     } else {
  769.         cmap->palette = (HPAL)NULLHANDLE;
  770.     }
  771.     cmap->size = 0;
  772.     cmap->stale = 0;
  773.     Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);
  774.     return (Colormap)cmap;
  775. }
  776.  
  777. /*
  778.  *----------------------------------------------------------------------
  779.  *
  780.  * XFreeColormap --
  781.  *
  782.  *    Frees the resources associated with the given colormap.
  783.  *
  784.  * Results:
  785.  *    None.
  786.  *
  787.  * Side effects:
  788.  *    Deletes the palette associated with the colormap.  Note that
  789.  *    the palette must not be selected into a device context when
  790.  *    this occurs.
  791.  *
  792.  *----------------------------------------------------------------------
  793.  */
  794.  
  795. void
  796. XFreeColormap(display, colormap)
  797.     Display* display;
  798.     Colormap colormap;
  799. {
  800.     TkOS2Colormap *cmap = (TkOS2Colormap *) colormap;
  801.  
  802. #ifdef DEBUG
  803.     printf("XFreeColormap\n");
  804. #endif
  805.  
  806.     if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
  807.         /* Palette management */
  808.         if (!GpiDeletePalette(cmap->palette)) {
  809.             /* Try to free memory anyway */
  810.             ckfree((char *) cmap);
  811.         panic("Unable to free colormap, palette is still selected.");
  812.         }
  813.     }
  814.     Tcl_DeleteHashTable(&cmap->refCounts);
  815.     ckfree((char *) cmap);
  816. }
  817.  
  818. /*
  819.  *----------------------------------------------------------------------
  820.  *
  821.  * TkOS2SelectPalette --
  822.  *
  823.  *    This function sets up the specified device context with a
  824.  *    given palette.  If the palette is stale, it realizes it in
  825.  *    the background unless the palette is the current global
  826.  *    palette.
  827.  *
  828.  * Results:
  829.  *    Returns the previous palette selected into the device context.
  830.  *
  831.  * Side effects:
  832.  *    May change the system palette.
  833.  *
  834.  *----------------------------------------------------------------------
  835.  */
  836.  
  837. HPAL
  838. TkOS2SelectPalette(hps, hwnd, colormap)
  839.     HPS hps;
  840.     HWND hwnd;
  841.     Colormap colormap;
  842. {
  843.     TkOS2Colormap *cmap = (TkOS2Colormap *) colormap;
  844.     HPAL oldPalette;
  845.     ULONG mapped, changed;
  846.  
  847. #ifdef DEBUG
  848.     printf("TkOS2SelectPalette (%x), nextColor %d\n", cmap->palette, nextColor);
  849. #endif
  850.  
  851.     if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
  852.         oldPalette = GpiSelectPalette(hps, cmap->palette);
  853. #ifdef DEBUG
  854.         if (oldPalette == PAL_ERROR) {
  855.             printf("GpiSelectPalette PAL_ERROR: %x\n", WinGetLastError(hab));
  856.         } else {
  857.             printf("GpiSelectPalette: %x\n", oldPalette);
  858.         }
  859. #endif
  860.         mapped = WinRealizePalette(hwnd, hps, &changed);
  861. #ifdef DEBUG
  862.         if (mapped == PAL_ERROR) {
  863.             printf("WinRealizePalette PAL_ERROR: %x\n", WinGetLastError(hab));
  864.         } else {
  865.             printf("WinRealizePalette: %x\n", mapped);
  866.         }
  867. #endif
  868.         return oldPalette;
  869.     } else {
  870.         PULONG alArray;
  871.         /* Retrieve the "global" color table and create it in this PS */
  872. #ifdef DEBUG
  873.         printf("    ckalloc\'ing %d (%dx%d)\n",
  874.                (unsigned)(sizeof(LONG) * (nextColor)), sizeof(LONG), nextColor);
  875. #endif
  876.         alArray = (PLONG) ckalloc ((unsigned)(sizeof(LONG) * (nextColor)));
  877.         rc = GpiQueryLogColorTable(globalPS, 0L, 0L, nextColor, alArray);
  878. #ifdef DEBUG
  879.         if (rc==QLCT_ERROR) {
  880.             printf("    GpiQueryLogColorTable (0-%d) ERROR %x\n", nextColor-1,
  881.                    WinGetLastError(hab));
  882.         } else {
  883.             if (rc==QLCT_RGB) {
  884.                 printf("    GpiQueryLogColorTable in RGB mode\n");
  885.             } else {
  886.                 printf("    GpiQueryLogColorTable (0-%d) OK\n", nextColor-1);
  887.             }
  888.         }
  889. #endif
  890.         if (rc > 0) {
  891.             rc = GpiCreateLogColorTable(hps, 0L, LCOLF_RGB, 0,
  892.                                         nextColor, alArray);
  893. #ifdef DEBUG
  894.             if (rc!=TRUE) {
  895.                 printf("    GpiCreateLogColorTable ERROR %x\n",
  896.                        WinGetLastError(hab));
  897.             } else {
  898.                 printf("    GpiCreateLogColorTable OK\n");
  899.             }
  900. #endif
  901.         }
  902.         ckfree((char *)alArray);
  903.         return (HPAL)0;
  904.     }
  905. }
  906.