Add missing wReserved1 member to DCB structure definition.
[wine] / graphics / x11drv / palette.c
1 /*
2  * X11DRV OEM bitmap objects
3  *
4  * Copyright 1994, 1995 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "ts_xlib.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "gdi.h"
29 #include "palette.h"
30 #include "windef.h"
31 #include "winreg.h"
32 #include "x11drv.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(palette);
36
37 /* Palette indexed mode:
38  *      logical palette -> mapping -> pixel
39  *
40  *
41  * Windows needs contiguous color space ( from 0 to n ) but
42  * it is possible only with the private colormap. Otherwise we
43  * have to map DC palette indices to real pixel values. With
44  * private colormaps it boils down to the identity mapping. The
45  * other special case is when we have a fixed color visual with
46  * the screendepth > 8 - we abandon palette mappings altogether
47  * because pixel values can be calculated without X server
48  * assistance.
49  *
50  * Windows palette manager is described in the
51  * http://premium.microsoft.com/msdn/library/techart/f30/f34/f40/d4d/sa942.htm
52  */
53
54 static PALETTEENTRY *COLOR_sysPal; /* current system palette */
55
56 static int COLOR_gapStart = 256;
57 static int COLOR_gapEnd = -1;
58 static int COLOR_gapFilled = 0;
59 static int COLOR_max = 256;
60
61 Colormap X11DRV_PALETTE_PaletteXColormap = 0;
62 UINT16   X11DRV_PALETTE_PaletteFlags     = 0;
63
64 typedef struct {
65     int shift;
66     int scale;
67     int max;
68 } ColorShifts;
69
70 /* initialize to zero to handle abortive X11DRV_PALETTE_VIRTUAL visuals */
71 static ColorShifts X11DRV_PALETTE_PRed   = {0,0,0};
72 static ColorShifts X11DRV_PALETTE_LRed   = {0,0,0};
73 static ColorShifts X11DRV_PALETTE_PGreen = {0,0,0};
74 static ColorShifts X11DRV_PALETTE_LGreen = {0,0,0};
75 static ColorShifts X11DRV_PALETTE_PBlue  = {0,0,0};
76 static ColorShifts X11DRV_PALETTE_LBlue  = {0,0,0};
77 static int X11DRV_PALETTE_Graymax        = 0;
78
79 static int palette_size;
80
81 /* First free dynamic color cell, 0 = full palette, -1 = fixed palette */
82 static int           X11DRV_PALETTE_firstFree = 0;
83 static unsigned char X11DRV_PALETTE_freeList[256];
84
85 /**********************************************************************/
86
87    /* Map an EGA index (0..15) to a pixel value in the system color space.  */
88
89 int X11DRV_PALETTE_mapEGAPixel[16];
90
91 /**********************************************************************/
92
93 #define NB_COLORCUBE_START_INDEX        63
94 #define NB_PALETTE_EMPTY_VALUE          -1
95
96 /* Maps entry in the system palette to X pixel value */
97 int *X11DRV_PALETTE_PaletteToXPixel = NULL;
98
99 /* Maps pixel to the entry in the system palette */
100 int *X11DRV_PALETTE_XPixelToPalette = NULL;
101
102 /**********************************************************************/
103
104 static BOOL X11DRV_PALETTE_BuildPrivateMap( const PALETTEENTRY *sys_pal_template );
105 static BOOL X11DRV_PALETTE_BuildSharedMap( const PALETTEENTRY *sys_pal_template );
106 static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, ColorShifts *physical, ColorShifts *to_logical);
107 static void X11DRV_PALETTE_FillDefaultColors( const PALETTEENTRY *sys_pal_template );
108 static void X11DRV_PALETTE_FormatSystemPalette(void);
109 static BOOL X11DRV_PALETTE_CheckSysColor( const PALETTEENTRY *sys_pal_template, COLORREF c);
110 static int X11DRV_PALETTE_LookupSystemXPixel(COLORREF col);
111
112
113 /***********************************************************************
114  *           COLOR_Init
115  *
116  * Initialize color management.
117  */
118 int X11DRV_PALETTE_Init(void)
119 {
120     int mask, white, black;
121     int monoPlane;
122     PALETTEENTRY sys_pal_template[NB_RESERVED_COLORS];
123
124     TRACE("initializing palette manager...\n");
125
126     white = WhitePixel( gdi_display, DefaultScreen(gdi_display) );
127     black = BlackPixel( gdi_display, DefaultScreen(gdi_display) );
128     monoPlane = 1;
129     for( mask = 1; !((white & mask)^(black & mask)); mask <<= 1 )
130          monoPlane++;
131     X11DRV_PALETTE_PaletteFlags = (white & mask) ? X11DRV_PALETTE_WHITESET : 0;
132     palette_size = visual->map_entries;
133
134     switch(visual->class)
135     {
136     case DirectColor:
137         X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_VIRTUAL;
138     case GrayScale:
139     case PseudoColor:
140     {
141         HKEY hkey;
142         BOOL private_color_map = FALSE;
143         if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
144         {
145             char buffer[20];
146             DWORD type, count = sizeof(buffer);
147             if(!RegQueryValueExA(hkey, "PrivateColorMap", 0, &type, buffer, &count))
148             {
149                 char ch = buffer[0];
150                 private_color_map = (ch == 'y' || ch == 'Y' || ch == 't' || ch == 'T' || ch == '1');
151             }
152             RegCloseKey(hkey);
153         }
154
155         if (private_color_map)
156         {
157             XSetWindowAttributes win_attr;
158
159             X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap( gdi_display, root_window,
160                                                  visual, AllocAll );
161             if (X11DRV_PALETTE_PaletteXColormap)
162             {
163                 X11DRV_PALETTE_PaletteFlags |= (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_WHITESET);
164
165                 monoPlane = 1;
166                 for( white = palette_size - 1; !(white & 1); white >>= 1 )
167                      monoPlane++;
168
169                 if( root_window != DefaultRootWindow(gdi_display) )
170                 {
171                     win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
172                     TSXChangeWindowAttributes( gdi_display, root_window, CWColormap, &win_attr );
173                 }
174                 break;
175             }
176         }
177         X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
178                                                             visual, AllocNone);
179         break;
180     }
181
182     case StaticGray:
183         X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
184                                                             visual, AllocNone);
185         X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_FIXED;
186         X11DRV_PALETTE_Graymax = (1 << screen_depth)-1;
187         break;
188
189     case TrueColor:
190         X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_VIRTUAL;
191     case StaticColor: {
192         int *depths,nrofdepths;
193         /* FIXME: hack to detect XFree32 XF_VGA16 ... We just have
194          * depths 1 and 4
195          */
196         depths=TSXListDepths(gdi_display,DefaultScreen(gdi_display),&nrofdepths);
197         if ((nrofdepths==2) && ((depths[0]==4) || depths[1]==4)) {
198             monoPlane = 1;
199             for( white = palette_size - 1; !(white & 1); white >>= 1 )
200                 monoPlane++;
201             X11DRV_PALETTE_PaletteFlags = (white & mask) ? X11DRV_PALETTE_WHITESET : 0;
202             X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
203                                                                 visual, AllocNone);
204             TSXFree(depths);
205             break;
206         }
207         TSXFree(depths);
208         X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
209                                                             visual, AllocNone);
210         X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_FIXED;
211         X11DRV_PALETTE_ComputeShifts(visual->red_mask, &X11DRV_PALETTE_PRed, &X11DRV_PALETTE_LRed);
212         X11DRV_PALETTE_ComputeShifts(visual->green_mask, &X11DRV_PALETTE_PGreen, &X11DRV_PALETTE_LGreen);
213         X11DRV_PALETTE_ComputeShifts(visual->blue_mask, &X11DRV_PALETTE_PBlue, &X11DRV_PALETTE_LBlue);
214         break;
215       }
216     }
217
218     TRACE(" visual class %i (%i)\n",  visual->class, monoPlane);
219
220     memset(X11DRV_PALETTE_freeList, 0, 256*sizeof(unsigned char));
221
222     GetPaletteEntries( GetStockObject(DEFAULT_PALETTE), 0, NB_RESERVED_COLORS, sys_pal_template );
223
224     if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
225         X11DRV_PALETTE_BuildPrivateMap( sys_pal_template );
226     else
227         X11DRV_PALETTE_BuildSharedMap( sys_pal_template );
228
229     /* Build free list */
230
231     if( X11DRV_PALETTE_firstFree != -1 )
232         X11DRV_PALETTE_FormatSystemPalette();
233
234     X11DRV_PALETTE_FillDefaultColors( sys_pal_template );
235
236     if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
237         palette_size = 0;
238     else
239         palette_size = visual->map_entries;
240
241     return palette_size;
242 }
243
244 /***********************************************************************
245  *           X11DRV_PALETTE_Cleanup
246  *
247  * Free external colors we grabbed in the FillDefaultPalette()
248  */
249 void X11DRV_PALETTE_Cleanup(void)
250 {
251   if( COLOR_gapFilled )
252     TSXFreeColors(gdi_display, X11DRV_PALETTE_PaletteXColormap,
253                   (unsigned long*)(X11DRV_PALETTE_PaletteToXPixel + COLOR_gapStart),
254                   COLOR_gapFilled, 0);
255 }
256
257 /***********************************************************************
258  *              X11DRV_PALETTE_ComputeShifts
259  *
260  * Calculate conversion parameters for direct mapped visuals
261  */
262 static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, ColorShifts *physical, ColorShifts *to_logical)
263 {
264     int i;
265
266     if (maskbits==0)
267     {
268         physical->shift=0;
269         physical->scale=0;
270         physical->max=0;
271         to_logical->shift=0;
272         to_logical->scale=0;
273         to_logical->max=0;
274         return;
275     }
276
277     for(i=0;!(maskbits&1);i++)
278         maskbits >>= 1;
279
280     physical->shift = i;
281     physical->max = maskbits;
282
283     for(i=0;maskbits!=0;i++)
284         maskbits >>= 1;
285     physical->scale = i;
286
287     if (physical->scale>8)
288     {
289         /* On FreeBSD, VNC's default 32bpp mode is bgrabb (ffc00000,3ff800,7ff)!
290          * So we adjust the shifts to also normalize the color fields to
291          * the Win32 standard of 8 bits per color.
292          */
293         to_logical->shift=physical->shift+(physical->scale-8);
294         to_logical->scale=8;
295         to_logical->max=0xff;
296     } else {
297         to_logical->shift=physical->shift;
298         to_logical->scale=physical->scale;
299         to_logical->max=physical->max;
300     }
301 }
302
303 /***********************************************************************
304  *           X11DRV_PALETTE_BuildPrivateMap
305  *
306  * Allocate colorcells and initialize mapping tables.
307  */
308 static BOOL X11DRV_PALETTE_BuildPrivateMap( const PALETTEENTRY *sys_pal_template )
309 {
310     /* Private colormap - identity mapping */
311
312     XColor color;
313     int i;
314
315     if((COLOR_sysPal = (PALETTEENTRY*)HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY)*palette_size)) == NULL) {
316         WARN("Can not allocate system palette\n");
317         return FALSE;
318     }
319
320     TRACE("Building private map - %i palette entries\n", palette_size);
321
322       /* Allocate system palette colors */
323
324     for( i=0; i < palette_size; i++ )
325     {
326        if( i < NB_RESERVED_COLORS/2 )
327        {
328          color.red   = sys_pal_template[i].peRed * 65535 / 255;
329          color.green = sys_pal_template[i].peGreen * 65535 / 255;
330          color.blue  = sys_pal_template[i].peBlue * 65535 / 255;
331          COLOR_sysPal[i] = sys_pal_template[i];
332          COLOR_sysPal[i].peFlags |= PC_SYS_USED;
333        }
334        else if( i >= palette_size - NB_RESERVED_COLORS/2 )
335        {
336          int j = NB_RESERVED_COLORS + i - palette_size;
337          color.red   = sys_pal_template[j].peRed * 65535 / 255;
338          color.green = sys_pal_template[j].peGreen * 65535 / 255;
339          color.blue  = sys_pal_template[j].peBlue * 65535 / 255;
340          COLOR_sysPal[i] = sys_pal_template[j];
341          COLOR_sysPal[i].peFlags |= PC_SYS_USED;
342        }
343
344        color.flags = DoRed | DoGreen | DoBlue;
345        color.pixel = i;
346        TSXStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
347
348        /* Set EGA mapping if color is from the first or last eight */
349
350        if (i < 8)
351            X11DRV_PALETTE_mapEGAPixel[i] = color.pixel;
352        else if (i >= palette_size - 8 )
353            X11DRV_PALETTE_mapEGAPixel[i - (palette_size - 16)] = color.pixel;
354     }
355
356     X11DRV_PALETTE_XPixelToPalette = X11DRV_PALETTE_PaletteToXPixel = NULL;
357
358     COLOR_gapStart = 256; COLOR_gapEnd = -1;
359
360     X11DRV_PALETTE_firstFree = (palette_size > NB_RESERVED_COLORS)?NB_RESERVED_COLORS/2 : -1;
361
362     return FALSE;
363 }
364
365 /***********************************************************************
366  *           X11DRV_PALETTE_BuildSharedMap
367  *
368  * Allocate colorcells and initialize mapping tables.
369  */
370 static BOOL X11DRV_PALETTE_BuildSharedMap( const PALETTEENTRY *sys_pal_template )
371 {
372    XColor               color;
373    unsigned long        sysPixel[NB_RESERVED_COLORS];
374    unsigned long*       pixDynMapping = NULL;
375    unsigned long        plane_masks[1];
376    int                  i, j, warn = 0;
377    int                  diff, r, g, b, max = 256, bp = 0, wp = 1;
378    int                  step = 1;
379    int                  defaultCM_max_copy;
380    Colormap             defaultCM;
381    XColor               defaultColors[256];
382    HKEY hkey;
383
384    defaultCM_max_copy = 128;
385    COLOR_max = 256;
386
387    if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
388    {
389         char buffer[20];
390         DWORD type, count;
391
392         count = sizeof(buffer);
393         if(!RegQueryValueExA(hkey, "CopyDefaultColors", 0, &type, buffer, &count))
394             defaultCM_max_copy = atoi(buffer);
395
396         count = sizeof(buffer);
397         if(!RegQueryValueExA(hkey, "AllocSystemColors", 0, &type, buffer, &count))
398             COLOR_max = atoi(buffer);
399
400         RegCloseKey(hkey);
401    }
402
403    /* Copy the first bunch of colors out of the default colormap to prevent
404     * colormap flashing as much as possible.  We're likely to get the most
405     * important Window Manager colors, etc in the first 128 colors */
406    defaultCM = DefaultColormap( gdi_display, DefaultScreen(gdi_display) );
407
408    for (i = 0; i < defaultCM_max_copy; i++)
409        defaultColors[i].pixel = (long) i;
410    TSXQueryColors(gdi_display, defaultCM, &defaultColors[0], defaultCM_max_copy);
411    for (i = 0; i < defaultCM_max_copy; i++)
412        TSXAllocColor( gdi_display, X11DRV_PALETTE_PaletteXColormap, &defaultColors[i] );
413
414    if (COLOR_max > 256) COLOR_max = 256;
415    else if (COLOR_max < 20) COLOR_max = 20;
416    TRACE("%d colors configured.\n", COLOR_max);
417
418    TRACE("Building shared map - %i palette entries\n", palette_size);
419
420    /* Be nice and allocate system colors as read-only */
421
422    for( i = 0; i < NB_RESERVED_COLORS; i++ )
423      {
424         color.red   = sys_pal_template[i].peRed * 65535 / 255;
425         color.green = sys_pal_template[i].peGreen * 65535 / 255;
426         color.blue  = sys_pal_template[i].peBlue * 65535 / 255;
427         color.flags = DoRed | DoGreen | DoBlue;
428
429         if (!TSXAllocColor( gdi_display, X11DRV_PALETTE_PaletteXColormap, &color ))
430         {
431              XColor     best, c;
432
433              if( !warn++ )
434              {
435                   WARN("Not enough colors for the full system palette.\n");
436
437                   bp = BlackPixel(gdi_display, DefaultScreen(gdi_display));
438                   wp = WhitePixel(gdi_display, DefaultScreen(gdi_display));
439
440                   max = (0xffffffff)>>(32 - screen_depth);
441                   if( max > 256 )
442                   {
443                       step = max/256;
444                       max = 256;
445                   }
446              }
447
448              /* reinit color (XAllocColor() may change it)
449               * and map to the best shared colorcell */
450
451              color.red   = sys_pal_template[i].peRed * 65535 / 255;
452              color.green = sys_pal_template[i].peGreen * 65535 / 255;
453              color.blue  = sys_pal_template[i].peBlue * 65535 / 255;
454
455              best.pixel = best.red = best.green = best.blue = 0;
456              for( c.pixel = 0, diff = 0x7fffffff; c.pixel < max; c.pixel += step )
457              {
458                 TSXQueryColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &c);
459                 r = (c.red - color.red)>>8;
460                 g = (c.green - color.green)>>8;
461                 b = (c.blue - color.blue)>>8;
462                 r = r*r + g*g + b*b;
463                 if( r < diff ) { best = c; diff = r; }
464              }
465
466              if( TSXAllocColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &best) )
467                  color.pixel = best.pixel;
468              else color.pixel = (i < NB_RESERVED_COLORS/2)? bp : wp;
469         }
470
471         sysPixel[i] = color.pixel;
472
473         TRACE("syscolor(%lx) -> pixel %i\n",
474                       *(COLORREF*)(sys_pal_template+i), (int)color.pixel);
475
476         /* Set EGA mapping if color in the first or last eight */
477
478         if (i < 8)
479             X11DRV_PALETTE_mapEGAPixel[i] = color.pixel;
480         else if (i >= NB_RESERVED_COLORS - 8 )
481             X11DRV_PALETTE_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
482      }
483
484    /* now allocate changeable set */
485
486    if( !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
487      {
488         int c_min = 0, c_max = palette_size, c_val;
489
490         TRACE("Dynamic colormap... \n");
491
492         /* let's become the first client that actually follows
493          * X guidelines and does binary search...
494          */
495
496         if((pixDynMapping = (unsigned long*)HeapAlloc(GetProcessHeap(), 0, sizeof(long)*palette_size)) == NULL) {
497             WARN("Out of memory while building system palette.\n");
498             return FALSE;
499         }
500
501         /* comment this out if you want to debug palette init */
502         TSXGrabServer(gdi_display);
503
504         while( c_max - c_min > 0 )
505           {
506              c_val = (c_max + c_min)/2 + (c_max + c_min)%2;
507
508              if( !TSXAllocColorCells(gdi_display, X11DRV_PALETTE_PaletteXColormap, False,
509                                    plane_masks, 0, pixDynMapping, c_val) )
510                  c_max = c_val - 1;
511              else
512                {
513                  TSXFreeColors(gdi_display, X11DRV_PALETTE_PaletteXColormap, pixDynMapping, c_val, 0);
514                  c_min = c_val;
515                }
516           }
517
518         if( c_min > COLOR_max - NB_RESERVED_COLORS)
519             c_min = COLOR_max - NB_RESERVED_COLORS;
520
521         c_min = (c_min/2) + (c_min/2);          /* need even set for split palette */
522
523         if( c_min > 0 )
524           if( !TSXAllocColorCells(gdi_display, X11DRV_PALETTE_PaletteXColormap, False,
525                                 plane_masks, 0, pixDynMapping, c_min) )
526             {
527               WARN("Inexplicable failure during colorcell allocation.\n");
528               c_min = 0;
529             }
530
531         palette_size = c_min + NB_RESERVED_COLORS;
532
533         TSXUngrabServer(gdi_display);
534
535         TRACE("adjusted size %i colorcells\n", palette_size);
536      }
537    else if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
538         {
539           /* virtual colorspace - ToPhysical takes care of
540            * color translations but we have to allocate full palette
541            * to maintain compatibility
542            */
543           palette_size = 256;
544           TRACE("Virtual colorspace - screendepth %i\n", screen_depth);
545         }
546    else palette_size = NB_RESERVED_COLORS;      /* system palette only - however we can alloc a bunch
547                                          * of colors and map to them */
548
549    TRACE("Shared system palette uses %i colors.\n", palette_size);
550
551    /* set gap to account for pixel shortage. It has to be right in the center
552     * of the system palette because otherwise raster ops get screwed. */
553
554    if( palette_size >= 256 )
555      { COLOR_gapStart = 256; COLOR_gapEnd = -1; }
556    else
557      { COLOR_gapStart = palette_size/2; COLOR_gapEnd = 255 - palette_size/2; }
558
559    X11DRV_PALETTE_firstFree = ( palette_size > NB_RESERVED_COLORS &&
560                       (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL || !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED)) )
561                      ? NB_RESERVED_COLORS/2 : -1;
562
563    COLOR_sysPal = (PALETTEENTRY*)HeapAlloc(GetProcessHeap(),0,sizeof(PALETTEENTRY)*256);
564    if(COLOR_sysPal == NULL) {
565        ERR("Can not allocate system palette!\n");
566        return FALSE;
567    }
568
569    /* setup system palette entry <-> pixel mappings and fill in 20 fixed entries */
570
571    if (screen_depth <= 8)
572    {
573        X11DRV_PALETTE_XPixelToPalette = HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(int) );
574        if(X11DRV_PALETTE_XPixelToPalette == NULL) {
575            ERR("Out of memory: XPixelToPalette!\n");
576            return FALSE;
577        }
578        for( i = 0; i < 256; i++ )
579            X11DRV_PALETTE_XPixelToPalette[i] = NB_PALETTE_EMPTY_VALUE;
580    }
581
582    /* for hicolor visuals PaletteToPixel mapping is used to skip
583     * RGB->pixel calculation in X11DRV_PALETTE_ToPhysical().
584     */
585
586    X11DRV_PALETTE_PaletteToXPixel = (int*)HeapAlloc(GetProcessHeap(),0,sizeof(int)*256);
587    if(X11DRV_PALETTE_PaletteToXPixel == NULL) {
588        ERR("Out of memory: PaletteToXPixel!\n");
589        return FALSE;
590    }
591
592    for( i = j = 0; i < 256; i++ )
593    {
594       if( i >= COLOR_gapStart && i <= COLOR_gapEnd )
595       {
596          X11DRV_PALETTE_PaletteToXPixel[i] = NB_PALETTE_EMPTY_VALUE;
597          COLOR_sysPal[i].peFlags = 0;   /* mark as unused */
598          continue;
599       }
600
601       if( i < NB_RESERVED_COLORS/2 )
602       {
603         X11DRV_PALETTE_PaletteToXPixel[i] = sysPixel[i];
604         COLOR_sysPal[i] = sys_pal_template[i];
605         COLOR_sysPal[i].peFlags |= PC_SYS_USED;
606       }
607       else if( i >= 256 - NB_RESERVED_COLORS/2 )
608       {
609         X11DRV_PALETTE_PaletteToXPixel[i] = sysPixel[(i + NB_RESERVED_COLORS) - 256];
610         COLOR_sysPal[i] = sys_pal_template[(i + NB_RESERVED_COLORS) - 256];
611         COLOR_sysPal[i].peFlags |= PC_SYS_USED;
612       }
613       else if( pixDynMapping )
614              X11DRV_PALETTE_PaletteToXPixel[i] = pixDynMapping[j++];
615            else
616              X11DRV_PALETTE_PaletteToXPixel[i] = i;
617
618       TRACE("index %i -> pixel %i\n", i, X11DRV_PALETTE_PaletteToXPixel[i]);
619
620       if( X11DRV_PALETTE_XPixelToPalette )
621           X11DRV_PALETTE_XPixelToPalette[X11DRV_PALETTE_PaletteToXPixel[i]] = i;
622    }
623
624    if( pixDynMapping ) HeapFree(GetProcessHeap(), 0, pixDynMapping);
625
626    return TRUE;
627 }
628
629 /***********************************************************************
630  *      Colormap Initialization
631  */
632 static void X11DRV_PALETTE_FillDefaultColors( const PALETTEENTRY *sys_pal_template )
633 {
634  /* initialize unused entries to what Windows uses as a color
635   * cube - based on Greg Kreider's code.
636   */
637
638   int i = 0, idx = 0;
639   int red, no_r, inc_r;
640   int green, no_g, inc_g;
641   int blue, no_b, inc_b;
642
643   if (palette_size <= NB_RESERVED_COLORS)
644         return;
645   while (i*i*i < (palette_size - NB_RESERVED_COLORS)) i++;
646   no_r = no_g = no_b = --i;
647   if ((no_r * (no_g+1) * no_b) < (palette_size - NB_RESERVED_COLORS)) no_g++;
648   if ((no_r * no_g * (no_b+1)) < (palette_size - NB_RESERVED_COLORS)) no_b++;
649   inc_r = (255 - NB_COLORCUBE_START_INDEX)/no_r;
650   inc_g = (255 - NB_COLORCUBE_START_INDEX)/no_g;
651   inc_b = (255 - NB_COLORCUBE_START_INDEX)/no_b;
652
653   idx = X11DRV_PALETTE_firstFree;
654
655   if( idx != -1 )
656     for (blue = NB_COLORCUBE_START_INDEX; blue < 256 && idx; blue += inc_b )
657      for (green = NB_COLORCUBE_START_INDEX; green < 256 && idx; green += inc_g )
658       for (red = NB_COLORCUBE_START_INDEX; red < 256 && idx; red += inc_r )
659       {
660          /* weird but true */
661
662          if( red == NB_COLORCUBE_START_INDEX && green == red && blue == green ) continue;
663
664          COLOR_sysPal[idx].peRed = red;
665          COLOR_sysPal[idx].peGreen = green;
666          COLOR_sysPal[idx].peBlue = blue;
667
668          /* set X color */
669
670          if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
671          {
672             if (X11DRV_PALETTE_PRed.max != 255) no_r = (red * X11DRV_PALETTE_PRed.max) / 255;
673             if (X11DRV_PALETTE_PGreen.max != 255) no_g = (green * X11DRV_PALETTE_PGreen.max) / 255;
674             if (X11DRV_PALETTE_PBlue.max != 255) no_b = (blue * X11DRV_PALETTE_PBlue.max) / 255;
675
676             X11DRV_PALETTE_PaletteToXPixel[idx] = (no_r << X11DRV_PALETTE_PRed.shift) | (no_g << X11DRV_PALETTE_PGreen.shift) | (no_b << X11DRV_PALETTE_PBlue.shift);
677          }
678          else if( !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
679          {
680            XColor color;
681            color.pixel = (X11DRV_PALETTE_PaletteToXPixel)? X11DRV_PALETTE_PaletteToXPixel[idx] : idx;
682            color.red = COLOR_sysPal[idx].peRed << 8;
683            color.green = COLOR_sysPal[idx].peGreen << 8;
684            color.blue =  COLOR_sysPal[idx].peBlue << 8;
685            color.flags = DoRed | DoGreen | DoBlue;
686            TSXStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
687          }
688          idx = X11DRV_PALETTE_freeList[idx];
689       }
690
691   /* try to fill some entries in the "gap" with
692    * what's already in the colormap - they will be
693    * mappable to but not changeable. */
694
695   if( COLOR_gapStart < COLOR_gapEnd && X11DRV_PALETTE_XPixelToPalette )
696   {
697     XColor      xc;
698     int         r, g, b, max;
699
700     max = COLOR_max - (256 - (COLOR_gapEnd - COLOR_gapStart));
701     for ( i = 0, idx = COLOR_gapStart; i < 256 && idx <= COLOR_gapEnd; i++ )
702       if( X11DRV_PALETTE_XPixelToPalette[i] == NB_PALETTE_EMPTY_VALUE )
703         {
704           xc.pixel = i;
705
706           TSXQueryColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &xc);
707           r = xc.red>>8; g = xc.green>>8; b = xc.blue>>8;
708
709           if( xc.pixel < 256 && X11DRV_PALETTE_CheckSysColor( sys_pal_template, RGB(r, g, b)) &&
710               TSXAllocColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &xc) )
711           {
712              X11DRV_PALETTE_XPixelToPalette[xc.pixel] = idx;
713              X11DRV_PALETTE_PaletteToXPixel[idx] = xc.pixel;
714            *(COLORREF*)(COLOR_sysPal + idx) = RGB(r, g, b);
715              COLOR_sysPal[idx++].peFlags |= PC_SYS_USED;
716              if( --max <= 0 ) break;
717           }
718         }
719     COLOR_gapFilled = idx - COLOR_gapStart;
720   }
721 }
722
723
724 /***********************************************************************
725  *           X11DRV_IsSolidColor
726  *
727  * Check whether 'color' can be represented with a solid color.
728  */
729 BOOL X11DRV_IsSolidColor( COLORREF color )
730 {
731     int i;
732     const PALETTEENTRY *pEntry = COLOR_sysPal;
733
734     if (color & 0xff000000) return TRUE;  /* indexed color */
735
736     if (!color || (color == 0xffffff)) return TRUE;  /* black or white */
737
738     for (i = 0; i < 256 ; i++, pEntry++)
739     {
740         if( i < COLOR_gapStart || i > COLOR_gapEnd )
741             if ((GetRValue(color) == pEntry->peRed) &&
742                 (GetGValue(color) == pEntry->peGreen) &&
743                 (GetBValue(color) == pEntry->peBlue)) return TRUE;
744     }
745     return FALSE;
746 }
747
748
749 /***********************************************************************
750  *           X11DRV_PALETTE_ToLogical
751  *
752  * Return RGB color for given X pixel.
753  */
754 COLORREF X11DRV_PALETTE_ToLogical(int pixel)
755 {
756     XColor color;
757
758 #if 0
759     /* truecolor visual */
760
761     if (screen_depth >= 24) return pixel;
762 #endif
763
764     /* check for hicolor visuals first */
765
766     if ( (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) && !X11DRV_PALETTE_Graymax )
767     {
768          color.red = (pixel >> X11DRV_PALETTE_LRed.shift) & X11DRV_PALETTE_LRed.max;
769          if (X11DRV_PALETTE_LRed.scale<8)
770              color.red=  color.red   << (8-X11DRV_PALETTE_LRed.scale) |
771                          color.red   >> (2*X11DRV_PALETTE_LRed.scale-8);
772          color.green = (pixel >> X11DRV_PALETTE_LGreen.shift) & X11DRV_PALETTE_LGreen.max;
773          if (X11DRV_PALETTE_LGreen.scale<8)
774              color.green=color.green << (8-X11DRV_PALETTE_LGreen.scale) |
775                          color.green >> (2*X11DRV_PALETTE_LGreen.scale-8);
776          color.blue = (pixel >> X11DRV_PALETTE_LBlue.shift) & X11DRV_PALETTE_LBlue.max;
777          if (X11DRV_PALETTE_LBlue.scale<8)
778              color.blue= color.blue  << (8-X11DRV_PALETTE_LBlue.scale)  |
779                          color.blue  >> (2*X11DRV_PALETTE_LBlue.scale-8);
780                  return RGB(color.red,color.green,color.blue);
781     }
782
783     /* check if we can bypass X */
784
785     if ((screen_depth <= 8) && (pixel < 256) &&
786         !(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_VIRTUAL | X11DRV_PALETTE_FIXED)) ) {
787          return  ( *(COLORREF*)(COLOR_sysPal +
788                    ((X11DRV_PALETTE_XPixelToPalette)?X11DRV_PALETTE_XPixelToPalette[pixel]:pixel)) ) & 0x00ffffff;
789     }
790
791     color.pixel = pixel;
792     TSXQueryColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
793     return RGB(color.red >> 8, color.green >> 8, color.blue >> 8);
794 }
795
796
797 /***********************************************************************
798  *           X11DRV_SysPaletteLookupPixel
799  */
800 static int X11DRV_SysPaletteLookupPixel( COLORREF col, BOOL skipReserved )
801 {
802     int i, best = 0, diff = 0x7fffffff;
803     int r,g,b;
804
805     for( i = 0; i < palette_size && diff ; i++ )
806     {
807         if( !(COLOR_sysPal[i].peFlags & PC_SYS_USED) ||
808             (skipReserved && COLOR_sysPal[i].peFlags  & PC_SYS_RESERVED) )
809             continue;
810
811         r = COLOR_sysPal[i].peRed - GetRValue(col);
812         g = COLOR_sysPal[i].peGreen - GetGValue(col);
813         b = COLOR_sysPal[i].peBlue - GetBValue(col);
814
815         r = r*r + g*g + b*b;
816
817         if( r < diff ) { best = i; diff = r; }
818     }
819     return best;
820 }
821
822
823 /***********************************************************************
824  *           X11DRV_PALETTE_ToPhysical
825  *
826  * Return the physical color closest to 'color'.
827  */
828 int X11DRV_PALETTE_ToPhysical( X11DRV_PDEVICE *physDev, COLORREF color )
829 {
830     DC *dc = physDev ? physDev->dc : NULL;
831     WORD                 index = 0;
832     HPALETTE             hPal = (dc)? dc->hPalette: GetStockObject(DEFAULT_PALETTE);
833     unsigned char        spec_type = color >> 24;
834     PALETTEOBJ*          palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
835
836     /* palPtr can be NULL when DC is being destroyed */
837     if( !palPtr ) return 0;
838
839     if ( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED )
840     {
841         /* there is no colormap limitation; we are going to have to compute
842          * the pixel value from the visual information stored earlier
843          */
844
845         unsigned        long red, green, blue;
846         unsigned        idx = 0;
847
848         switch(spec_type)
849         {
850           case 1: /* PALETTEINDEX */
851
852             if( (idx = color & 0xffff) >= palPtr->logpalette.palNumEntries)
853             {
854                 WARN("RGB(%lx) : idx %d is out of bounds, assuming black\n", color, idx);
855                 GDI_ReleaseObj( hPal );
856                 return 0;
857             }
858
859             if( palPtr->mapping )
860             {
861                 int ret = palPtr->mapping[idx];
862                 GDI_ReleaseObj( hPal );
863                 return ret;
864             }
865             color = *(COLORREF*)(palPtr->logpalette.palPalEntry + idx);
866             break;
867
868           default:
869             color &= 0xffffff;
870             /* fall through to RGB */
871
872           case 0: /* RGB */
873             if( dc && (dc->bitsPerPixel == 1) )
874             {
875                 GDI_ReleaseObj( hPal );
876                 return (((color >> 16) & 0xff) +
877                         ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
878             }
879
880         }
881
882         red = GetRValue(color); green = GetGValue(color); blue = GetBValue(color);
883
884         if (X11DRV_PALETTE_Graymax)
885         {
886             /* grayscale only; return scaled value */
887             GDI_ReleaseObj( hPal );
888             return ( (red * 30 + green * 59 + blue * 11) * X11DRV_PALETTE_Graymax) / 25500;
889         }
890         else
891         {
892             /* scale each individually and construct the TrueColor pixel value */
893             if (X11DRV_PALETTE_PRed.scale < 8)
894                 red = red >> (8-X11DRV_PALETTE_PRed.scale);
895             else if (X11DRV_PALETTE_PRed.scale > 8)
896                 red =   red   << (X11DRV_PALETTE_PRed.scale-8) |
897                         red   >> (16-X11DRV_PALETTE_PRed.scale);
898             if (X11DRV_PALETTE_PGreen.scale < 8)
899                 green = green >> (8-X11DRV_PALETTE_PGreen.scale);
900             else if (X11DRV_PALETTE_PGreen.scale > 8)
901                 green = green << (X11DRV_PALETTE_PGreen.scale-8) |
902                         green >> (16-X11DRV_PALETTE_PGreen.scale);
903             if (X11DRV_PALETTE_PBlue.scale < 8)
904                 blue =  blue  >> (8-X11DRV_PALETTE_PBlue.scale);
905             else if (X11DRV_PALETTE_PBlue.scale > 8)
906                 blue =  blue  << (X11DRV_PALETTE_PBlue.scale-8) |
907                         blue  >> (16-X11DRV_PALETTE_PBlue.scale);
908
909             GDI_ReleaseObj( hPal );
910             return (red << X11DRV_PALETTE_PRed.shift) | (green << X11DRV_PALETTE_PGreen.shift) | (blue << X11DRV_PALETTE_PBlue.shift);
911         }
912     }
913     else
914     {
915
916         if( !palPtr->mapping )
917             WARN("Palette %p is not realized\n", dc->hPalette);
918
919         switch(spec_type)       /* we have to peruse DC and system palette */
920         {
921             default:
922                 color &= 0xffffff;
923                 /* fall through to RGB */
924
925             case 0:  /* RGB */
926                 if( dc && (dc->bitsPerPixel == 1) )
927                 {
928                     GDI_ReleaseObj( hPal );
929                     return (((color >> 16) & 0xff) +
930                             ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
931                 }
932
933                 index = X11DRV_SysPaletteLookupPixel( color, FALSE);
934                 if (X11DRV_PALETTE_PaletteToXPixel) index = X11DRV_PALETTE_PaletteToXPixel[index];
935
936                 /* TRACE(palette,"RGB(%lx) -> pixel %i\n", color, index);
937                  */
938                 break;
939             case 1:  /* PALETTEINDEX */
940                 index = color & 0xffff;
941
942                 if( index >= palPtr->logpalette.palNumEntries )
943                     WARN("RGB(%lx) : index %i is out of bounds\n", color, index);
944                 else if( palPtr->mapping ) index = palPtr->mapping[index];
945
946                 /*  TRACE(palette,"PALETTEINDEX(%04x) -> pixel %i\n", (WORD)color, index);
947                  */
948                 break;
949             case 2:  /* PALETTERGB */
950                 index = GetNearestPaletteIndex( hPal, color );
951                 if (palPtr->mapping) index = palPtr->mapping[index];
952                 /* TRACE(palette,"PALETTERGB(%lx) -> pixel %i\n", color, index);
953                  */
954                 break;
955         }
956     }
957
958     GDI_ReleaseObj( hPal );
959     return index;
960 }
961
962 /***********************************************************************
963  *           X11DRV_PALETTE_LookupSystemXPixel
964  */
965 static int X11DRV_PALETTE_LookupSystemXPixel(COLORREF col)
966 {
967  int            i, best = 0, diff = 0x7fffffff;
968  int            size = palette_size;
969  int            r,g,b;
970
971  for( i = 0; i < size && diff ; i++ )
972     {
973       if( i == NB_RESERVED_COLORS/2 )
974       {
975         int newi = size - NB_RESERVED_COLORS/2;
976         if (newi>i) i=newi;
977       }
978
979       r = COLOR_sysPal[i].peRed - GetRValue(col);
980       g = COLOR_sysPal[i].peGreen - GetGValue(col);
981       b = COLOR_sysPal[i].peBlue - GetBValue(col);
982
983       r = r*r + g*g + b*b;
984
985       if( r < diff ) { best = i; diff = r; }
986     }
987
988  return (X11DRV_PALETTE_PaletteToXPixel)? X11DRV_PALETTE_PaletteToXPixel[best] : best;
989 }
990
991 /***********************************************************************
992  *           X11DRV_PALETTE_FormatSystemPalette
993  */
994 static void X11DRV_PALETTE_FormatSystemPalette(void)
995 {
996  /* Build free list so we'd have an easy way to find
997   * out if there are any available colorcells.
998   */
999
1000   int i, j = X11DRV_PALETTE_firstFree = NB_RESERVED_COLORS/2;
1001
1002   COLOR_sysPal[j].peFlags = 0;
1003   for( i = NB_RESERVED_COLORS/2 + 1 ; i < 256 - NB_RESERVED_COLORS/2 ; i++ )
1004     if( i < COLOR_gapStart || i > COLOR_gapEnd )
1005       {
1006         COLOR_sysPal[i].peFlags = 0;  /* unused tag */
1007         X11DRV_PALETTE_freeList[j] = i;   /* next */
1008         j = i;
1009       }
1010   X11DRV_PALETTE_freeList[j] = 0;
1011 }
1012
1013 /***********************************************************************
1014  *           X11DRV_PALETTE_CheckSysColor
1015  */
1016 static BOOL X11DRV_PALETTE_CheckSysColor( const PALETTEENTRY *sys_pal_template, COLORREF c)
1017 {
1018   int i;
1019   for( i = 0; i < NB_RESERVED_COLORS; i++ )
1020        if( c == (*(COLORREF*)(sys_pal_template + i) & 0x00ffffff) )
1021            return 0;
1022   return 1;
1023 }
1024
1025
1026 /***********************************************************************
1027  *           X11DRV_LookupSysPaletteExact
1028  */
1029 static int X11DRV_LookupSysPaletteExact( COLORREF col )
1030 {
1031     int i;
1032     BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
1033     for( i = 0; i < palette_size; i++ )
1034     {
1035         if( COLOR_sysPal[i].peFlags & PC_SYS_USED )  /* skips gap */
1036             if( COLOR_sysPal[i].peRed == r &&
1037                 COLOR_sysPal[i].peGreen == g &&
1038                 COLOR_sysPal[i].peBlue == b )
1039                 return i;
1040     }
1041     return -1;
1042 }
1043
1044
1045 /***********************************************************************
1046  *           X11DRV_PALETTE_SetMapping
1047  *
1048  * Set the color-mapping table for selected palette.
1049  * Return number of entries which mapping has changed.
1050  */
1051 static UINT X11DRV_PALETTE_SetMapping( PALETTEOBJ* palPtr, UINT uStart, UINT uNum, BOOL mapOnly )
1052 {
1053     char flag;
1054     int  prevMapping = (palPtr->mapping) ? 1 : 0;
1055     int  index;
1056     UINT iRemapped = 0;
1057     int* mapping;
1058
1059     /* reset dynamic system palette entries */
1060
1061     if( !mapOnly && X11DRV_PALETTE_firstFree != -1)
1062          X11DRV_PALETTE_FormatSystemPalette();
1063
1064     /* initialize palette mapping table */
1065
1066     mapping = HeapReAlloc( GetProcessHeap(), 0, palPtr->mapping,
1067                            sizeof(int)*palPtr->logpalette.palNumEntries);
1068     if(mapping == NULL) {
1069         ERR("Can not allocate new mapping -- memory exausted!\n");
1070         return 0;
1071     }
1072     palPtr->mapping = mapping;
1073
1074     if (uStart >= palPtr->logpalette.palNumEntries) return 0;
1075
1076     if (uStart + uNum > palPtr->logpalette.palNumEntries)
1077         uNum = palPtr->logpalette.palNumEntries - uStart;
1078
1079     for( uNum += uStart; uStart < uNum; uStart++ )
1080     {
1081         index = -1;
1082         flag = PC_SYS_USED;
1083
1084         switch( palPtr->logpalette.palPalEntry[uStart].peFlags & 0x07 )
1085         {
1086         case PC_EXPLICIT:   /* palette entries are indices into system palette */
1087             index = *(WORD*)(palPtr->logpalette.palPalEntry + uStart);
1088             if( index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd) )
1089             {
1090                 WARN("PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index);
1091                 index = 0;
1092             }
1093             break;
1094
1095         case PC_RESERVED:   /* forbid future mappings to this entry */
1096             flag |= PC_SYS_RESERVED;
1097
1098             /* fall through */
1099         default:            /* try to collapse identical colors */
1100             index = X11DRV_LookupSysPaletteExact(*(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
1101             /* fall through */
1102         case PC_NOCOLLAPSE:
1103             if( index < 0 )
1104             {
1105                 if( X11DRV_PALETTE_firstFree > 0 && !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
1106                 {
1107                     XColor color;
1108                     index = X11DRV_PALETTE_firstFree;  /* ought to be available */
1109                     X11DRV_PALETTE_firstFree = X11DRV_PALETTE_freeList[index];
1110
1111                     color.pixel = (X11DRV_PALETTE_PaletteToXPixel) ? X11DRV_PALETTE_PaletteToXPixel[index] : index;
1112                     color.red = palPtr->logpalette.palPalEntry[uStart].peRed << 8;
1113                     color.green = palPtr->logpalette.palPalEntry[uStart].peGreen << 8;
1114                     color.blue = palPtr->logpalette.palPalEntry[uStart].peBlue << 8;
1115                     color.flags = DoRed | DoGreen | DoBlue;
1116                     TSXStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
1117
1118                     COLOR_sysPal[index] = palPtr->logpalette.palPalEntry[uStart];
1119                     COLOR_sysPal[index].peFlags = flag;
1120                     X11DRV_PALETTE_freeList[index] = 0;
1121
1122                     if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
1123                     break;
1124                 }
1125                 else if ( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
1126                 {
1127                     index = X11DRV_PALETTE_ToPhysical( NULL, 0x00ffffff &
1128                              *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
1129                     break;
1130                 }
1131
1132                 /* we have to map to existing entry in the system palette */
1133
1134                 index = X11DRV_SysPaletteLookupPixel( *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart), TRUE);
1135             }
1136             palPtr->logpalette.palPalEntry[uStart].peFlags |= PC_SYS_USED;
1137
1138             if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
1139             break;
1140         }
1141
1142         if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++;
1143         palPtr->mapping[uStart] = index;
1144
1145         TRACE("entry %i (%lx) -> pixel %i\n", uStart,
1146                                 *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart), index);
1147
1148     }
1149     return iRemapped;
1150 }
1151
1152 /***********************************************************************
1153  *              GetSystemPaletteEntries   (X11DRV.@)
1154  */
1155 UINT X11DRV_GetSystemPaletteEntries( X11DRV_PDEVICE *physDev, UINT start, UINT count,
1156                                      LPPALETTEENTRY entries )
1157 {
1158     UINT i;
1159
1160     if (!entries) return palette_size;
1161     if (start >= palette_size) return 0;
1162     if (start + count >= palette_size) count = palette_size - start;
1163
1164     for (i = 0; i < count; i++)
1165     {
1166         entries[i].peRed   = COLOR_sysPal[start + i].peRed;
1167         entries[i].peGreen = COLOR_sysPal[start + i].peGreen;
1168         entries[i].peBlue  = COLOR_sysPal[start + i].peBlue;
1169         entries[i].peFlags = 0;
1170         TRACE("\tidx(%02x) -> RGB(%08lx)\n", start + i, *(COLORREF*)(entries + i) );
1171     }
1172     return count;
1173 }
1174
1175
1176 /***********************************************************************
1177  *              GetNearestColor   (X11DRV.@)
1178  */
1179 COLORREF X11DRV_GetNearestColor( X11DRV_PDEVICE *physDev, COLORREF color )
1180 {
1181     unsigned char spec_type = color >> 24;
1182     COLORREF nearest;
1183
1184     if (!palette_size) return color;
1185
1186     if (spec_type == 1 || spec_type == 2)
1187     {
1188         /* we need logical palette for PALETTERGB and PALETTEINDEX colorrefs */
1189
1190         UINT index;
1191         PALETTEENTRY entry;
1192         HPALETTE hpal = GetCurrentObject( physDev->hdc, OBJ_PAL );
1193
1194         if (!hpal) hpal = GetStockObject( DEFAULT_PALETTE );
1195
1196         if (spec_type == 2) /* PALETTERGB */
1197             index = GetNearestPaletteIndex( hpal, color );
1198         else  /* PALETTEINDEX */
1199             index = LOWORD(color);
1200
1201         if (!GetPaletteEntries( hpal, index, 1, &entry ))
1202         {
1203             WARN("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, index );
1204             if (!GetPaletteEntries( hpal, 0, 1, &entry )) return CLR_INVALID;
1205         }
1206         color = RGB( entry.peRed,  entry.peGreen, entry.peBlue );
1207     }
1208     color &= 0x00ffffff;
1209     nearest = (0x00ffffff & *(COLORREF*)(COLOR_sysPal + X11DRV_SysPaletteLookupPixel(color, FALSE)));
1210
1211     TRACE("(%06lx): returning %06lx\n", color, nearest );
1212     return nearest;
1213 }
1214
1215
1216 /***********************************************************************
1217  *              RealizePalette    (X11DRV.@)
1218  */
1219 UINT X11DRV_RealizePalette( X11DRV_PDEVICE *physDev, HPALETTE hpal, BOOL primary )
1220 {
1221     UINT ret;
1222     PALETTEOBJ *palPtr;
1223
1224     if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) return 0;
1225
1226     if (!(palPtr = GDI_GetObjPtr( hpal, PALETTE_MAGIC ))) return 0;
1227     ret = X11DRV_PALETTE_SetMapping( palPtr, 0, palPtr->logpalette.palNumEntries, !primary );
1228     GDI_ReleaseObj( hpal );
1229     return ret;
1230 }
1231
1232
1233 /***********************************************************************
1234  *              RealizeDefaultPalette    (X11DRV.@)
1235  */
1236 UINT X11DRV_RealizeDefaultPalette( X11DRV_PDEVICE *physDev )
1237 {
1238     UINT ret = 0;
1239
1240     if (palette_size && GetObjectType(physDev->hdc) != OBJ_MEMDC)
1241     {
1242         PALETTEOBJ*  palPtr = GDI_GetObjPtr( GetStockObject(DEFAULT_PALETTE), PALETTE_MAGIC );
1243         if (palPtr)
1244         {
1245             /* lookup is needed to account for SetSystemPaletteUse() stuff */
1246             int i, index;
1247
1248             for( i = 0; i < 20; i++ )
1249             {
1250                 index = X11DRV_PALETTE_LookupSystemXPixel(*(COLORREF*)(palPtr->logpalette.palPalEntry + i));
1251                 /* mapping is allocated in COLOR_InitPalette() */
1252                 if( index != palPtr->mapping[i] )
1253                 {
1254                     palPtr->mapping[i]=index;
1255                     ret++;
1256                 }
1257             }
1258             GDI_ReleaseObj( GetStockObject(DEFAULT_PALETTE) );
1259         }
1260     }
1261     return ret;
1262 }