gdi32: Recompute the pen masks on every use to support PALETTEINDEX colors.
[wine] / dlls / gdi32 / palette.c
1 /*
2  * GDI palette objects
3  *
4  * Copyright 1993,1994 Alexandre Julliard
5  * Copyright 1996 Alex Korobka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * NOTES:
22  * PALETTEOBJ is documented in the Dr. Dobbs Journal May 1993.
23  * Information in the "Undocumented Windows" is incorrect.
24  */
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35
36 #include "gdi_private.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(palette);
40
41 typedef BOOL (*unrealize_function)(HPALETTE);
42
43 typedef struct tagPALETTEOBJ
44 {
45     GDIOBJHDR           header;
46     unrealize_function  unrealize;
47     WORD                version;    /* palette version */
48     WORD                count;      /* count of palette entries */
49     PALETTEENTRY       *entries;
50 } PALETTEOBJ;
51
52 static INT PALETTE_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
53 static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle );
54 static BOOL PALETTE_DeleteObject( HGDIOBJ handle );
55
56 static const struct gdi_obj_funcs palette_funcs =
57 {
58     NULL,                     /* pSelectObject */
59     PALETTE_GetObject,        /* pGetObjectA */
60     PALETTE_GetObject,        /* pGetObjectW */
61     PALETTE_UnrealizeObject,  /* pUnrealizeObject */
62     PALETTE_DeleteObject      /* pDeleteObject */
63 };
64
65 /* Pointers to USER implementation of SelectPalette/RealizePalette */
66 /* they will be patched by USER on startup */
67 HPALETTE (WINAPI *pfnSelectPalette)(HDC hdc, HPALETTE hpal, WORD bkgnd ) = GDISelectPalette;
68 UINT (WINAPI *pfnRealizePalette)(HDC hdc) = GDIRealizePalette;
69
70 static UINT SystemPaletteUse = SYSPAL_STATIC;  /* currently not considered */
71
72 static HPALETTE hPrimaryPalette = 0; /* used for WM_PALETTECHANGED */
73 static HPALETTE hLastRealizedPalette = 0; /* UnrealizeObject() needs it */
74
75
76 /***********************************************************************
77  *           PALETTE_Init
78  *
79  * Create the system palette.
80  */
81 HPALETTE PALETTE_Init(void)
82 {
83     const RGBQUAD *entries = get_default_color_table( 8 );
84     char buffer[FIELD_OFFSET( LOGPALETTE, palPalEntry[20] )];
85     LOGPALETTE *palPtr = (LOGPALETTE *)buffer;
86     int i;
87
88     /* create default palette (20 system colors) */
89
90     palPtr->palVersion = 0x300;
91     palPtr->palNumEntries = 20;
92     for (i = 0; i < 10; i++)
93     {
94         palPtr->palPalEntry[i].peRed   = entries[i].rgbRed;
95         palPtr->palPalEntry[i].peGreen = entries[i].rgbGreen;
96         palPtr->palPalEntry[i].peBlue  = entries[i].rgbBlue;
97         palPtr->palPalEntry[i].peFlags = 0;
98     }
99     for (i = 10; i < 20; i++)
100     {
101         palPtr->palPalEntry[i].peRed   = entries[236 + i].rgbRed;
102         palPtr->palPalEntry[i].peGreen = entries[236 + i].rgbGreen;
103         palPtr->palPalEntry[i].peBlue  = entries[236 + i].rgbBlue;
104         palPtr->palPalEntry[i].peFlags = 0;
105     }
106     return CreatePalette( palPtr );
107 }
108
109
110 /***********************************************************************
111  * CreatePalette [GDI32.@]
112  *
113  * Creates a logical color palette.
114  *
115  * RETURNS
116  *    Success: Handle to logical palette
117  *    Failure: NULL
118  */
119 HPALETTE WINAPI CreatePalette(
120     const LOGPALETTE* palette) /* [in] Pointer to logical color palette */
121 {
122     PALETTEOBJ * palettePtr;
123     HPALETTE hpalette;
124     int size;
125
126     if (!palette) return 0;
127     TRACE("entries=%i\n", palette->palNumEntries);
128
129     if (!(palettePtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*palettePtr) ))) return 0;
130     palettePtr->unrealize = NULL;
131     palettePtr->version = palette->palVersion;
132     palettePtr->count   = palette->palNumEntries;
133     size = palettePtr->count * sizeof(*palettePtr->entries);
134     if (!(palettePtr->entries = HeapAlloc( GetProcessHeap(), 0, size )))
135     {
136         HeapFree( GetProcessHeap(), 0, palettePtr );
137         return 0;
138     }
139     memcpy( palettePtr->entries, palette->palPalEntry, size );
140     if (!(hpalette = alloc_gdi_handle( &palettePtr->header, OBJ_PAL, &palette_funcs )))
141     {
142         HeapFree( GetProcessHeap(), 0, palettePtr->entries );
143         HeapFree( GetProcessHeap(), 0, palettePtr );
144     }
145     TRACE("   returning %p\n", hpalette);
146     return hpalette;
147 }
148
149
150 /***********************************************************************
151  * CreateHalftonePalette [GDI32.@]
152  *
153  * Creates a halftone palette.
154  *
155  * RETURNS
156  *    Success: Handle to logical halftone palette
157  *    Failure: 0
158  *
159  * FIXME: This simply creates the halftone palette derived from running
160  *        tests on a windows NT machine. This is assuming a color depth
161  *        of greater that 256 color. On a 256 color device the halftone
162  *        palette will be different and this function will be incorrect
163  */
164 HPALETTE WINAPI CreateHalftonePalette(
165     HDC hdc) /* [in] Handle to device context */
166 {
167     const RGBQUAD *entries = get_default_color_table( 8 );
168     char buffer[FIELD_OFFSET( LOGPALETTE, palPalEntry[256] )];
169     LOGPALETTE *pal = (LOGPALETTE *)buffer;
170     int i;
171
172     pal->palVersion = 0x300;
173     pal->palNumEntries = 256;
174     for (i = 0; i < 256; i++)
175     {
176         pal->palPalEntry[i].peRed   = entries[i].rgbRed;
177         pal->palPalEntry[i].peGreen = entries[i].rgbGreen;
178         pal->palPalEntry[i].peBlue  = entries[i].rgbBlue;
179         pal->palPalEntry[i].peFlags = 0;
180     }
181     return CreatePalette( pal );
182 }
183
184
185 /***********************************************************************
186  * GetPaletteEntries [GDI32.@]
187  *
188  * Retrieves palette entries.
189  *
190  * RETURNS
191  *    Success: Number of entries from logical palette
192  *    Failure: 0
193  */
194 UINT WINAPI GetPaletteEntries(
195     HPALETTE hpalette,    /* [in]  Handle of logical palette */
196     UINT start,           /* [in]  First entry to receive */
197     UINT count,           /* [in]  Number of entries to receive */
198     LPPALETTEENTRY entries) /* [out] Address of array receiving entries */
199 {
200     PALETTEOBJ * palPtr;
201     UINT numEntries;
202
203     TRACE("hpal = %p, count=%i\n", hpalette, count );
204
205     palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
206     if (!palPtr) return 0;
207
208     /* NOTE: not documented but test show this to be the case */
209     if (count == 0)
210     {
211         count = palPtr->count;
212     }
213     else
214     {
215         numEntries = palPtr->count;
216         if (start+count > numEntries) count = numEntries - start;
217         if (entries)
218         {
219             if (start >= numEntries) count = 0;
220             else memcpy( entries, &palPtr->entries[start], count * sizeof(PALETTEENTRY) );
221         }
222     }
223
224     GDI_ReleaseObj( hpalette );
225     return count;
226 }
227
228
229 /***********************************************************************
230  * SetPaletteEntries [GDI32.@]
231  *
232  * Sets color values for range in palette.
233  *
234  * RETURNS
235  *    Success: Number of entries that were set
236  *    Failure: 0
237  */
238 UINT WINAPI SetPaletteEntries(
239     HPALETTE hpalette,    /* [in] Handle of logical palette */
240     UINT start,           /* [in] Index of first entry to set */
241     UINT count,           /* [in] Number of entries to set */
242     const PALETTEENTRY *entries) /* [in] Address of array of structures */
243 {
244     PALETTEOBJ * palPtr;
245     UINT numEntries;
246
247     TRACE("hpal=%p,start=%i,count=%i\n",hpalette,start,count );
248
249     if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
250     palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
251     if (!palPtr) return 0;
252
253     numEntries = palPtr->count;
254     if (start >= numEntries)
255     {
256       GDI_ReleaseObj( hpalette );
257       return 0;
258     }
259     if (start+count > numEntries) count = numEntries - start;
260     memcpy( &palPtr->entries[start], entries, count * sizeof(PALETTEENTRY) );
261     GDI_ReleaseObj( hpalette );
262     UnrealizeObject( hpalette );
263     return count;
264 }
265
266
267 /***********************************************************************
268  * ResizePalette [GDI32.@]
269  *
270  * Resizes logical palette.
271  *
272  * RETURNS
273  *    Success: TRUE
274  *    Failure: FALSE
275  */
276 BOOL WINAPI ResizePalette(
277     HPALETTE hPal, /* [in] Handle of logical palette */
278     UINT cEntries) /* [in] Number of entries in logical palette */
279 {
280     PALETTEOBJ * palPtr = GDI_GetObjPtr( hPal, OBJ_PAL );
281     PALETTEENTRY *entries;
282
283     if( !palPtr ) return FALSE;
284     TRACE("hpal = %p, prev = %i, new = %i\n", hPal, palPtr->count, cEntries );
285
286     if (!(entries = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
287                                  palPtr->entries, cEntries * sizeof(*palPtr->entries) )))
288     {
289         GDI_ReleaseObj( hPal );
290         return FALSE;
291     }
292     palPtr->entries = entries;
293     palPtr->count = cEntries;
294
295     GDI_ReleaseObj( hPal );
296     PALETTE_UnrealizeObject( hPal );
297     return TRUE;
298 }
299
300
301 /***********************************************************************
302  * AnimatePalette [GDI32.@]
303  *
304  * Replaces entries in logical palette.
305  *
306  * RETURNS
307  *    Success: TRUE
308  *    Failure: FALSE
309  *
310  * FIXME
311  *    Should use existing mapping when animating a primary palette
312  */
313 BOOL WINAPI AnimatePalette(
314     HPALETTE hPal,              /* [in] Handle to logical palette */
315     UINT StartIndex,            /* [in] First entry in palette */
316     UINT NumEntries,            /* [in] Count of entries in palette */
317     const PALETTEENTRY* PaletteColors) /* [in] Pointer to first replacement */
318 {
319     TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
320
321     if( hPal != GetStockObject(DEFAULT_PALETTE) )
322     {
323         PALETTEOBJ * palPtr;
324         UINT pal_entries;
325         const PALETTEENTRY *pptr = PaletteColors;
326
327         palPtr = GDI_GetObjPtr( hPal, OBJ_PAL );
328         if (!palPtr) return 0;
329
330         pal_entries = palPtr->count;
331         if (StartIndex >= pal_entries)
332         {
333           GDI_ReleaseObj( hPal );
334           return 0;
335         }
336         if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
337         
338         for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
339           /* According to MSDN, only animate PC_RESERVED colours */
340           if (palPtr->entries[StartIndex].peFlags & PC_RESERVED) {
341             TRACE("Animating colour (%d,%d,%d) to (%d,%d,%d)\n",
342               palPtr->entries[StartIndex].peRed,
343               palPtr->entries[StartIndex].peGreen,
344               palPtr->entries[StartIndex].peBlue,
345               pptr->peRed, pptr->peGreen, pptr->peBlue);
346             palPtr->entries[StartIndex] = *pptr;
347           } else {
348             TRACE("Not animating entry %d -- not PC_RESERVED\n", StartIndex);
349           }
350         }
351         GDI_ReleaseObj( hPal );
352         /* FIXME: check for palette selected in active window */
353     }
354     return TRUE;
355 }
356
357
358 /***********************************************************************
359  * SetSystemPaletteUse [GDI32.@]
360  *
361  * Specify whether the system palette contains 2 or 20 static colors.
362  *
363  * RETURNS
364  *    Success: Previous system palette
365  *    Failure: SYSPAL_ERROR
366  */
367 UINT WINAPI SetSystemPaletteUse(
368     HDC hdc,  /* [in] Handle of device context */
369     UINT use) /* [in] Palette-usage flag */
370 {
371     UINT old = SystemPaletteUse;
372
373     /* Device doesn't support colour palettes */
374     if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)) {
375         return SYSPAL_ERROR;
376     }
377
378     switch (use) {
379         case SYSPAL_NOSTATIC:
380         case SYSPAL_NOSTATIC256:        /* WINVER >= 0x0500 */
381         case SYSPAL_STATIC:
382             SystemPaletteUse = use;
383             return old;
384         default:
385             return SYSPAL_ERROR;
386     }
387 }
388
389
390 /***********************************************************************
391  * GetSystemPaletteUse [GDI32.@]
392  *
393  * Gets state of system palette.
394  *
395  * RETURNS
396  *    Current state of system palette
397  */
398 UINT WINAPI GetSystemPaletteUse(
399     HDC hdc) /* [in] Handle of device context */
400 {
401     return SystemPaletteUse;
402 }
403
404
405 /***********************************************************************
406  * GetSystemPaletteEntries [GDI32.@]
407  *
408  * Gets range of palette entries.
409  *
410  * RETURNS
411  *    Success: Number of entries retrieved from palette
412  *    Failure: 0
413  */
414 UINT WINAPI GetSystemPaletteEntries(
415     HDC hdc,              /* [in]  Handle of device context */
416     UINT start,           /* [in]  Index of first entry to be retrieved */
417     UINT count,           /* [in]  Number of entries to be retrieved */
418     LPPALETTEENTRY entries) /* [out] Array receiving system-palette entries */
419 {
420     UINT ret = 0;
421     DC *dc;
422
423     TRACE("hdc=%p,start=%i,count=%i\n", hdc,start,count);
424
425     if ((dc = get_dc_ptr( hdc )))
426     {
427         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetSystemPaletteEntries );
428         ret = physdev->funcs->pGetSystemPaletteEntries( physdev, start, count, entries );
429         release_dc_ptr( dc );
430     }
431     return ret;
432 }
433
434
435 /***********************************************************************
436  * GetNearestPaletteIndex [GDI32.@]
437  *
438  * Gets palette index for color.
439  *
440  * NOTES
441  *    Should index be initialized to CLR_INVALID instead of 0?
442  *
443  * RETURNS
444  *    Success: Index of entry in logical palette
445  *    Failure: CLR_INVALID
446  */
447 UINT WINAPI GetNearestPaletteIndex(
448     HPALETTE hpalette, /* [in] Handle of logical color palette */
449     COLORREF color)      /* [in] Color to be matched */
450 {
451     PALETTEOBJ* palObj = GDI_GetObjPtr( hpalette, OBJ_PAL );
452     UINT index  = 0;
453
454     if( palObj )
455     {
456         int i, diff = 0x7fffffff;
457         int r,g,b;
458         PALETTEENTRY* entry = palObj->entries;
459
460         for( i = 0; i < palObj->count && diff ; i++, entry++)
461         {
462             r = entry->peRed - GetRValue(color);
463             g = entry->peGreen - GetGValue(color);
464             b = entry->peBlue - GetBValue(color);
465
466             r = r*r + g*g + b*b;
467
468             if( r < diff ) { index = i; diff = r; }
469         }
470         GDI_ReleaseObj( hpalette );
471     }
472     TRACE("(%p,%06x): returning %d\n", hpalette, color, index );
473     return index;
474 }
475
476
477 /* null driver fallback implementation for GetNearestColor */
478 COLORREF nulldrv_GetNearestColor( PHYSDEV dev, COLORREF color )
479 {
480     unsigned char spec_type;
481
482     if (!(GetDeviceCaps( dev->hdc, RASTERCAPS ) & RC_PALETTE)) return color;
483
484     spec_type = color >> 24;
485     if (spec_type == 1 || spec_type == 2)
486     {
487         /* we need logical palette for PALETTERGB and PALETTEINDEX colorrefs */
488         UINT index;
489         PALETTEENTRY entry;
490         HPALETTE hpal = GetCurrentObject( dev->hdc, OBJ_PAL );
491
492         if (!hpal) hpal = GetStockObject( DEFAULT_PALETTE );
493         if (spec_type == 2) /* PALETTERGB */
494             index = GetNearestPaletteIndex( hpal, color );
495         else  /* PALETTEINDEX */
496             index = LOWORD(color);
497
498         if (!GetPaletteEntries( hpal, index, 1, &entry ))
499         {
500             WARN("RGB(%x) : idx %d is out of bounds, assuming NULL\n", color, index );
501             if (!GetPaletteEntries( hpal, 0, 1, &entry )) return CLR_INVALID;
502         }
503         color = RGB( entry.peRed, entry.peGreen, entry.peBlue );
504     }
505     return color & 0x00ffffff;
506 }
507
508
509 /***********************************************************************
510  * GetNearestColor [GDI32.@]
511  *
512  * Gets a system color to match.
513  *
514  * RETURNS
515  *    Success: Color from system palette that corresponds to given color
516  *    Failure: CLR_INVALID
517  */
518 COLORREF WINAPI GetNearestColor(
519     HDC hdc,      /* [in] Handle of device context */
520     COLORREF color) /* [in] Color to be matched */
521 {
522     COLORREF nearest = CLR_INVALID;
523     DC *dc;
524
525     if ((dc = get_dc_ptr( hdc )))
526     {
527         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetNearestColor );
528         nearest = physdev->funcs->pGetNearestColor( physdev, color );
529         release_dc_ptr( dc );
530     }
531     return nearest;
532 }
533
534
535 /***********************************************************************
536  *           PALETTE_GetObject
537  */
538 static INT PALETTE_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
539 {
540     PALETTEOBJ *palette = GDI_GetObjPtr( handle, OBJ_PAL );
541
542     if (!palette) return 0;
543
544     if (buffer)
545     {
546         if (count > sizeof(WORD)) count = sizeof(WORD);
547         memcpy( buffer, &palette->count, count );
548     }
549     else count = sizeof(WORD);
550     GDI_ReleaseObj( handle );
551     return count;
552 }
553
554
555 /***********************************************************************
556  *           PALETTE_UnrealizeObject
557  */
558 static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle )
559 {
560     PALETTEOBJ *palette = GDI_GetObjPtr( handle, OBJ_PAL );
561
562     if (palette)
563     {
564         unrealize_function unrealize = palette->unrealize;
565         palette->unrealize = NULL;
566         GDI_ReleaseObj( handle );
567         if (unrealize) unrealize( handle );
568     }
569
570     if (InterlockedCompareExchangePointer( (void **)&hLastRealizedPalette, 0, handle ) == handle)
571         TRACE("unrealizing palette %p\n", handle);
572
573     return TRUE;
574 }
575
576
577 /***********************************************************************
578  *           PALETTE_DeleteObject
579  */
580 static BOOL PALETTE_DeleteObject( HGDIOBJ handle )
581 {
582     PALETTEOBJ *obj;
583
584     PALETTE_UnrealizeObject( handle );
585     if (!(obj = free_gdi_handle( handle ))) return FALSE;
586     HeapFree( GetProcessHeap(), 0, obj->entries );
587     return HeapFree( GetProcessHeap(), 0, obj );
588 }
589
590
591 /***********************************************************************
592  *           GDISelectPalette    (Not a Windows API)
593  */
594 HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg)
595 {
596     HPALETTE ret = 0;
597     DC *dc;
598
599     TRACE("%p %p\n", hdc, hpal );
600
601     if (GetObjectType(hpal) != OBJ_PAL)
602     {
603       WARN("invalid selected palette %p\n",hpal);
604       return 0;
605     }
606     if ((dc = get_dc_ptr( hdc )))
607     {
608         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectPalette );
609         ret = dc->hPalette;
610         if (physdev->funcs->pSelectPalette( physdev, hpal, FALSE ))
611         {
612             dc->hPalette = hpal;
613             if (!wBkg) hPrimaryPalette = hpal;
614         }
615         else ret = 0;
616         release_dc_ptr( dc );
617     }
618     return ret;
619 }
620
621
622 /***********************************************************************
623  *           GDIRealizePalette    (Not a Windows API)
624  */
625 UINT WINAPI GDIRealizePalette( HDC hdc )
626 {
627     UINT realized = 0;
628     DC* dc = get_dc_ptr( hdc );
629
630     if (!dc) return 0;
631
632     TRACE("%p...\n", hdc );
633
634     if( dc->hPalette == GetStockObject( DEFAULT_PALETTE ))
635     {
636         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRealizeDefaultPalette );
637         realized = physdev->funcs->pRealizeDefaultPalette( physdev );
638     }
639     else if (InterlockedExchangePointer( (void **)&hLastRealizedPalette, dc->hPalette ) != dc->hPalette)
640     {
641         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRealizePalette );
642         PALETTEOBJ *palPtr = GDI_GetObjPtr( dc->hPalette, OBJ_PAL );
643         if (palPtr)
644         {
645             realized = physdev->funcs->pRealizePalette( physdev, dc->hPalette,
646                                                         (dc->hPalette == hPrimaryPalette) );
647             palPtr->unrealize = physdev->funcs->pUnrealizePalette;
648             GDI_ReleaseObj( dc->hPalette );
649         }
650     }
651     else TRACE("  skipping (hLastRealizedPalette = %p)\n", hLastRealizedPalette);
652
653     release_dc_ptr( dc );
654     TRACE("   realized %i colors.\n", realized );
655     return realized;
656 }
657
658
659 /***********************************************************************
660  * SelectPalette [GDI32.@]
661  *
662  * Selects logical palette into DC.
663  *
664  * RETURNS
665  *    Success: Previous logical palette
666  *    Failure: NULL
667  */
668 HPALETTE WINAPI SelectPalette(
669     HDC hDC,               /* [in] Handle of device context */
670     HPALETTE hPal,         /* [in] Handle of logical color palette */
671     BOOL bForceBackground) /* [in] Foreground/background mode */
672 {
673     return pfnSelectPalette( hDC, hPal, bForceBackground );
674 }
675
676
677 /***********************************************************************
678  * RealizePalette [GDI32.@]
679  *
680  * Maps palette entries to system palette.
681  *
682  * RETURNS
683  *    Success: Number of entries in logical palette
684  *    Failure: GDI_ERROR
685  */
686 UINT WINAPI RealizePalette(
687     HDC hDC) /* [in] Handle of device context */
688 {
689     return pfnRealizePalette( hDC );
690 }
691
692
693 typedef HWND (WINAPI *WindowFromDC_funcptr)( HDC );
694 typedef BOOL (WINAPI *RedrawWindow_funcptr)( HWND, const RECT *, HRGN, UINT );
695
696 /**********************************************************************
697  * UpdateColors [GDI32.@]
698  *
699  * Remaps current colors to logical palette.
700  *
701  * RETURNS
702  *    Success: TRUE
703  *    Failure: FALSE
704  */
705 BOOL WINAPI UpdateColors(
706     HDC hDC) /* [in] Handle of device context */
707 {
708     HMODULE mod;
709     int size = GetDeviceCaps( hDC, SIZEPALETTE );
710
711     if (!size) return 0;
712
713     mod = GetModuleHandleA("user32.dll");
714     if (mod)
715     {
716         WindowFromDC_funcptr pWindowFromDC = (WindowFromDC_funcptr)GetProcAddress(mod,"WindowFromDC");
717         if (pWindowFromDC)
718         {
719             HWND hWnd = pWindowFromDC( hDC );
720
721             /* Docs say that we have to remap current drawable pixel by pixel
722              * but it would take forever given the speed of XGet/PutPixel.
723              */
724             if (hWnd && size)
725             {
726                 RedrawWindow_funcptr pRedrawWindow = (void *)GetProcAddress( mod, "RedrawWindow" );
727                 if (pRedrawWindow) pRedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
728             }
729         }
730     }
731     return 0x666;
732 }
733
734 /*********************************************************************
735  *           SetMagicColors   (GDI32.@)
736  */
737 BOOL WINAPI SetMagicColors(HDC hdc, ULONG u1, ULONG u2)
738 {
739     FIXME("(%p 0x%08x 0x%08x): stub\n", hdc, u1, u2);
740     return TRUE;
741 }