Added another detection of strength-reduce bug in GCC.
[wine] / objects / palette.c
1 /*
2  * GDI palette objects
3  *
4  * Copyright 1993,1994 Alexandre Julliard
5  * Copyright 1996 Alex Korobka
6  *
7  * PALETTEOBJ is documented in the Dr. Dobbs Journal May 1993.
8  * Information in the "Undocumented Windows" is incorrect.
9  */
10
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "winbase.h"
15 #include "windef.h"
16 #include "wingdi.h"
17 #include "wine/winuser16.h"
18 #include "gdi.h"
19 #include "color.h"
20 #include "palette.h"
21 #include "debugtools.h"
22 #include "callback.h"
23 #include "winerror.h"
24
25 DEFAULT_DEBUG_CHANNEL(palette);
26
27 PALETTE_DRIVER *PALETTE_Driver = NULL;
28
29 /* Pointers to USER implementation of SelectPalette/RealizePalette */
30 /* they will be patched by USER on startup */
31 FARPROC pfnSelectPalette = NULL;
32 FARPROC pfnRealizePalette = NULL;
33
34 static UINT SystemPaletteUse = SYSPAL_STATIC;  /* currently not considered */
35
36 static HPALETTE16 hPrimaryPalette = 0; /* used for WM_PALETTECHANGED */
37 static HPALETTE16 hLastRealizedPalette = 0; /* UnrealizeObject() needs it */
38
39
40 /***********************************************************************
41  *           PALETTE_Init
42  *
43  * Create the system palette.
44  */
45 HPALETTE16 PALETTE_Init(void)
46 {
47     int                 i;
48     HPALETTE16          hpalette;
49     LOGPALETTE *        palPtr;
50     PALETTEOBJ*         palObj;
51     const PALETTEENTRY* __sysPalTemplate = COLOR_GetSystemPaletteTemplate();
52
53     /* create default palette (20 system colors) */
54
55     palPtr = HeapAlloc( GetProcessHeap(), 0,
56              sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY));
57     if (!palPtr) return FALSE;
58
59     palPtr->palVersion = 0x300;
60     palPtr->palNumEntries = NB_RESERVED_COLORS;
61     for( i = 0; i < NB_RESERVED_COLORS; i ++ )
62     {
63         palPtr->palPalEntry[i].peRed = __sysPalTemplate[i].peRed;
64         palPtr->palPalEntry[i].peGreen = __sysPalTemplate[i].peGreen;
65         palPtr->palPalEntry[i].peBlue = __sysPalTemplate[i].peBlue;
66         palPtr->palPalEntry[i].peFlags = 0;
67     }
68     hpalette = CreatePalette16( palPtr );
69     HeapFree( GetProcessHeap(), 0, palPtr );
70
71     palObj = (PALETTEOBJ*) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
72     if (palObj)
73     {
74         if (!(palObj->mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(int) * 20 )))
75             ERR("Can not create palette mapping -- out of memory!");
76         GDI_ReleaseObj( hpalette );
77     }
78     return hpalette;
79 }
80
81 /***********************************************************************
82  *           PALETTE_ValidateFlags
83  */
84 void PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, int size)
85 {
86     int i = 0;
87     for( ; i<size ; i++ )
88         lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
89 }
90
91
92 /***********************************************************************
93  *           CreatePalette16    (GDI.360)
94  */
95 HPALETTE16 WINAPI CreatePalette16( const LOGPALETTE* palette )
96 {
97     return CreatePalette( palette );
98 }
99
100
101 /***********************************************************************
102  * CreatePalette [GDI32.53]  Creates a logical color palette
103  *
104  * RETURNS
105  *    Success: Handle to logical palette
106  *    Failure: NULL
107  */
108 HPALETTE WINAPI CreatePalette(
109     const LOGPALETTE* palette) /* [in] Pointer to logical color palette */
110 {
111     PALETTEOBJ * palettePtr;
112     HPALETTE hpalette;
113     int size;
114     
115     if (!palette) return 0;
116     TRACE("entries=%i\n", palette->palNumEntries);
117
118     size = sizeof(LOGPALETTE) + (palette->palNumEntries - 1) * sizeof(PALETTEENTRY);
119
120     if (!(palettePtr = GDI_AllocObject( size + sizeof(int*) +sizeof(GDIOBJHDR),
121                                         PALETTE_MAGIC, &hpalette ))) return 0;
122     memcpy( &palettePtr->logpalette, palette, size );
123     PALETTE_ValidateFlags(palettePtr->logpalette.palPalEntry, 
124                           palettePtr->logpalette.palNumEntries);
125     palettePtr->mapping = NULL;
126     GDI_ReleaseObj( hpalette );
127
128     TRACE("   returning %04x\n", hpalette);
129     return hpalette;
130 }
131
132
133 /***********************************************************************
134  * CreateHalftonePalette16 [GDI.?]  Creates a halftone palette
135  *
136  * RETURNS
137  *    Success: Handle to logical halftone palette
138  *    Failure: 0
139  */
140 HPALETTE16 WINAPI CreateHalftonePalette16(
141     HDC16 hdc) /* [in] Handle to device context */
142 {
143     return CreateHalftonePalette(hdc);
144 }
145
146         
147 /***********************************************************************
148  * CreateHalftonePalette [GDI32.47]  Creates a halftone palette
149  *
150  * RETURNS
151  *    Success: Handle to logical halftone palette
152  *    Failure: 0
153  *
154  * FIXME: not truly tested
155  */
156 HPALETTE WINAPI CreateHalftonePalette(
157     HDC hdc) /* [in] Handle to device context */
158 {
159     int i, r, g, b;
160     struct {
161         WORD Version;
162         WORD NumberOfEntries;
163         PALETTEENTRY aEntries[256];
164     } Palette;
165
166     Palette.Version = 0x300;
167     Palette.NumberOfEntries = 256;
168     GetSystemPaletteEntries(hdc, 0, 256, Palette.aEntries);
169
170     for (r = 0; r < 6; r++) {
171         for (g = 0; g < 6; g++) {
172             for (b = 0; b < 6; b++) {
173                 i = r + g*6 + b*36 + 10;
174                 Palette.aEntries[i].peRed = r * 51;
175                 Palette.aEntries[i].peGreen = g * 51;
176                 Palette.aEntries[i].peBlue = b * 51;
177             }    
178           }
179         }
180         
181     for (i = 216; i < 246; i++) {
182         int v = (i - 216) * 8;
183         Palette.aEntries[i].peRed = v;
184         Palette.aEntries[i].peGreen = v;
185         Palette.aEntries[i].peBlue = v;
186         }
187         
188     return CreatePalette((LOGPALETTE *)&Palette);
189 }
190
191
192 /***********************************************************************
193  *           GetPaletteEntries16    (GDI.363)
194  */
195 UINT16 WINAPI GetPaletteEntries16( HPALETTE16 hpalette, UINT16 start,
196                                    UINT16 count, LPPALETTEENTRY entries )
197 {
198     return GetPaletteEntries( hpalette, start, count, entries );
199 }
200
201
202 /***********************************************************************
203  * GetPaletteEntries [GDI32.209]  Retrieves palette entries
204  *
205  * RETURNS
206  *    Success: Number of entries from logical palette
207  *    Failure: 0
208  */
209 UINT WINAPI GetPaletteEntries(
210     HPALETTE hpalette,    /* [in]  Handle of logical palette */
211     UINT start,           /* [in]  First entry to receive */
212     UINT count,           /* [in]  Number of entries to receive */
213     LPPALETTEENTRY entries) /* [out] Address of array receiving entries */
214 {
215     PALETTEOBJ * palPtr;
216     INT numEntries;
217
218     TRACE("hpal = %04x, count=%i\n", hpalette, count );
219         
220     palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
221     if (!palPtr) return 0;
222
223     numEntries = palPtr->logpalette.palNumEntries;
224     if (start+count > numEntries) count = numEntries - start;
225     if (entries)
226     { 
227       if (start >= numEntries) 
228       {
229         GDI_ReleaseObj( hpalette );
230         return 0;
231       }
232       memcpy( entries, &palPtr->logpalette.palPalEntry[start],
233               count * sizeof(PALETTEENTRY) );
234       for( numEntries = 0; numEntries < count ; numEntries++ )
235            if (entries[numEntries].peFlags & 0xF0)
236                entries[numEntries].peFlags = 0;
237     }
238
239     GDI_ReleaseObj( hpalette );
240     return count;
241 }
242
243
244 /***********************************************************************
245  *           SetPaletteEntries16    (GDI.364)
246  */
247 UINT16 WINAPI SetPaletteEntries16( HPALETTE16 hpalette, UINT16 start,
248                                    UINT16 count, LPPALETTEENTRY entries )
249 {
250     return SetPaletteEntries( hpalette, start, count, entries );
251 }
252
253
254 /***********************************************************************
255  * SetPaletteEntries [GDI32.326]  Sets color values for range in palette
256  *
257  * RETURNS
258  *    Success: Number of entries that were set
259  *    Failure: 0
260  */
261 UINT WINAPI SetPaletteEntries(
262     HPALETTE hpalette,    /* [in] Handle of logical palette */
263     UINT start,           /* [in] Index of first entry to set */
264     UINT count,           /* [in] Number of entries to set */
265     LPPALETTEENTRY entries) /* [in] Address of array of structures */
266 {
267     PALETTEOBJ * palPtr;
268     INT numEntries;
269
270     TRACE("hpal=%04x,start=%i,count=%i\n",hpalette,start,count );
271
272     palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
273     if (!palPtr) return 0;
274
275     numEntries = palPtr->logpalette.palNumEntries;
276     if (start >= numEntries) 
277     {
278       GDI_ReleaseObj( hpalette );
279       return 0;
280     }
281     if (start+count > numEntries) count = numEntries - start;
282     memcpy( &palPtr->logpalette.palPalEntry[start], entries,
283             count * sizeof(PALETTEENTRY) );
284     PALETTE_ValidateFlags(palPtr->logpalette.palPalEntry, 
285                           palPtr->logpalette.palNumEntries);
286     HeapFree( GetProcessHeap(), 0, palPtr->mapping );
287     palPtr->mapping = NULL;
288     GDI_ReleaseObj( hpalette );
289     return count;
290 }
291
292
293 /***********************************************************************
294  *           ResizePalette16   (GDI.368)
295  */
296 BOOL16 WINAPI ResizePalette16( HPALETTE16 hPal, UINT16 cEntries )
297 {
298     return ResizePalette( hPal, cEntries );
299 }
300
301
302 /***********************************************************************
303  * ResizePalette [GDI32.289]  Resizes logical palette
304  *
305  * RETURNS
306  *    Success: TRUE
307  *    Failure: FALSE
308  */
309 BOOL WINAPI ResizePalette(
310     HPALETTE hPal, /* [in] Handle of logical palette */
311     UINT cEntries) /* [in] Number of entries in logical palette */
312 {
313     PALETTEOBJ * palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
314     UINT         cPrevEnt, prevVer;
315     int          prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
316     int*         mapping = NULL;
317
318     TRACE("hpal = %04x, prev = %i, new = %i\n",
319                     hPal, palPtr ? palPtr->logpalette.palNumEntries : -1,
320                     cEntries );
321     if( !palPtr ) return FALSE;
322     cPrevEnt = palPtr->logpalette.palNumEntries;
323     prevVer = palPtr->logpalette.palVersion;
324     prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) +
325                                         sizeof(int*) + sizeof(GDIOBJHDR);
326     size += sizeof(int*) + sizeof(GDIOBJHDR);
327     mapping = palPtr->mapping;
328     
329     if (!(palPtr = GDI_ReallocObject( size, hPal, palPtr ))) return FALSE;
330
331     if( mapping ) 
332     {
333         int *newMap = (int*) HeapReAlloc(GetProcessHeap(), 0, 
334                                     mapping, cEntries * sizeof(int) );
335         if(newMap == NULL) 
336         {
337             ERR("Can not resize mapping -- out of memory!");
338             GDI_ReleaseObj( hPal );
339             return FALSE;
340         }
341         palPtr->mapping = newMap;
342     }
343
344     if( cEntries > cPrevEnt ) 
345     {
346         if( mapping )
347             memset(palPtr->mapping + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
348         memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
349         PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), 
350                                                      cEntries - cPrevEnt );
351     }
352     palPtr->logpalette.palNumEntries = cEntries;
353     palPtr->logpalette.palVersion = prevVer;
354     GDI_ReleaseObj( hPal );
355     return TRUE;
356 }
357
358
359 /***********************************************************************
360  *           AnimatePalette16   (GDI.367)
361  */
362 void WINAPI AnimatePalette16( HPALETTE16 hPal, UINT16 StartIndex,
363                               UINT16 NumEntries, const PALETTEENTRY* PaletteColors)
364 {
365     AnimatePalette( hPal, StartIndex, NumEntries, PaletteColors );
366 }
367
368
369 /***********************************************************************
370  * AnimatePalette [GDI32.6]  Replaces entries in logical palette
371  *
372  * RETURNS
373  *    Success: TRUE
374  *    Failure: FALSE
375  *
376  * FIXME
377  *    Should use existing mapping when animating a primary palette
378  */
379 BOOL WINAPI AnimatePalette(
380     HPALETTE hPal,              /* [in] Handle to logical palette */
381     UINT StartIndex,            /* [in] First entry in palette */
382     UINT NumEntries,            /* [in] Count of entries in palette */
383     const PALETTEENTRY* PaletteColors) /* [in] Pointer to first replacement */
384 {
385     TRACE("%04x (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
386
387     if( hPal != GetStockObject(DEFAULT_PALETTE) )
388     {
389         PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
390         if (!palPtr) return FALSE;
391
392         if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
393         {
394             UINT u;
395             for( u = 0; u < NumEntries; u++ )
396                 palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u];
397             PALETTE_Driver->
398               pSetMapping(palPtr, StartIndex, NumEntries,
399                           hPal != hPrimaryPalette );
400             GDI_ReleaseObj( hPal );
401             return TRUE;
402         }
403         GDI_ReleaseObj( hPal );
404     }
405     return FALSE;
406 }
407
408
409 /***********************************************************************
410  *           SetSystemPaletteUse16   (GDI.373)
411  */
412 UINT16 WINAPI SetSystemPaletteUse16( HDC16 hdc, UINT16 use )
413 {
414     return SetSystemPaletteUse( hdc, use );
415 }
416
417
418 /***********************************************************************
419  * SetSystemPaletteUse [GDI32.335]
420  *
421  * RETURNS
422  *    Success: Previous system palette
423  *    Failure: SYSPAL_ERROR
424  */
425 UINT WINAPI SetSystemPaletteUse(
426     HDC hdc,  /* [in] Handle of device context */
427     UINT use) /* [in] Palette-usage flag */
428 {
429     UINT old = SystemPaletteUse;
430     FIXME("(%04x,%04x): stub\n", hdc, use );
431     SystemPaletteUse = use;
432     return old;
433 }
434
435
436 /***********************************************************************
437  *           GetSystemPaletteUse16   (GDI.374)
438  */
439 UINT16 WINAPI GetSystemPaletteUse16( HDC16 hdc )
440 {
441     return SystemPaletteUse;
442 }
443
444
445 /***********************************************************************
446  * GetSystemPaletteUse [GDI32.223]  Gets state of system palette
447  *
448  * RETURNS
449  *    Current state of system palette
450  */
451 UINT WINAPI GetSystemPaletteUse(
452     HDC hdc) /* [in] Handle of device context */
453 {
454     return SystemPaletteUse;
455 }
456
457
458 /***********************************************************************
459  *           GetSystemPaletteEntries16   (GDI.375)
460  */
461 UINT16 WINAPI GetSystemPaletteEntries16( HDC16 hdc, UINT16 start, UINT16 count,
462                                          LPPALETTEENTRY entries )
463 {
464     return GetSystemPaletteEntries( hdc, start, count, entries );
465 }
466
467
468 /***********************************************************************
469  * GetSystemPaletteEntries [GDI32.222]  Gets range of palette entries
470  *
471  * RETURNS
472  *    Success: Number of entries retrieved from palette
473  *    Failure: 0
474  */
475 UINT WINAPI GetSystemPaletteEntries(
476     HDC hdc,              /* [in]  Handle of device context */
477     UINT start,           /* [in]  Index of first entry to be retrieved */
478     UINT count,           /* [in]  Number of entries to be retrieved */
479     LPPALETTEENTRY entries) /* [out] Array receiving system-palette entries */
480 {
481     UINT i;
482     DC *dc;
483
484     TRACE("hdc=%04x,start=%i,count=%i\n", hdc,start,count);
485
486     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
487
488     if (!entries)
489     {
490         count = dc->devCaps->sizePalette;
491         goto done;
492     }
493
494     if (start >= dc->devCaps->sizePalette)
495       {
496         count = 0;
497         goto done;
498       }
499
500     if (start+count >= dc->devCaps->sizePalette)
501         count = dc->devCaps->sizePalette - start;
502     for (i = 0; i < count; i++)
503     {
504         *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry( start + i );
505
506         TRACE("\tidx(%02x) -> RGB(%08lx)\n",
507                          start + i, *(COLORREF*)(entries + i) );
508     }
509  done:
510     GDI_ReleaseObj( hdc );
511     return count;
512 }
513
514
515 /***********************************************************************
516  *           GetNearestPaletteIndex16   (GDI.370)
517  */
518 UINT16 WINAPI GetNearestPaletteIndex16( HPALETTE16 hpalette, COLORREF color )
519 {
520     return GetNearestPaletteIndex( hpalette, color );
521 }
522
523
524 /***********************************************************************
525  * GetNearestPaletteIndex [GDI32.203]  Gets palette index for color
526  *
527  * NOTES
528  *    Should index be initialized to CLR_INVALID instead of 0?
529  *
530  * RETURNS
531  *    Success: Index of entry in logical palette
532  *    Failure: CLR_INVALID
533  */
534 UINT WINAPI GetNearestPaletteIndex(
535     HPALETTE hpalette, /* [in] Handle of logical color palette */
536     COLORREF color)      /* [in] Color to be matched */
537 {
538     PALETTEOBJ* palObj = (PALETTEOBJ*)GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
539     UINT index  = 0;
540
541     if( palObj )
542     {
543       index = COLOR_PaletteLookupPixel(palObj->logpalette.palPalEntry, 
544                                        palObj->logpalette.palNumEntries,
545                                        NULL, color, FALSE );
546
547       GDI_ReleaseObj( hpalette );
548     }
549     TRACE("(%04x,%06lx): returning %d\n", hpalette, color, index );
550     return index;
551 }
552
553
554 /***********************************************************************
555  *           GetNearestColor16   (GDI.154)
556  */
557 COLORREF WINAPI GetNearestColor16( HDC16 hdc, COLORREF color )
558 {
559     return GetNearestColor( hdc, color );
560 }
561
562
563 /***********************************************************************
564  * GetNearestColor [GDI32.202]  Gets a system color to match
565  *
566  * RETURNS
567  *    Success: Color from system palette that corresponds to given color
568  *    Failure: CLR_INVALID
569  */
570 COLORREF WINAPI GetNearestColor(
571     HDC hdc,      /* [in] Handle of device context */
572     COLORREF color) /* [in] Color to be matched */
573 {
574     COLORREF     nearest = CLR_INVALID;
575     DC          *dc;
576     PALETTEOBJ  *palObj;
577
578     if ( (dc = DC_GetDCPtr( hdc )) )
579     {
580         HPALETTE hpal = (dc->hPalette)? dc->hPalette : GetStockObject( DEFAULT_PALETTE );
581         palObj = GDI_GetObjPtr( hpal, PALETTE_MAGIC );
582         if (!palObj) {
583             GDI_ReleaseObj( hdc );
584             return nearest;
585         }
586
587         nearest = COLOR_LookupNearestColor( palObj->logpalette.palPalEntry,
588                                             palObj->logpalette.palNumEntries, color );
589         GDI_ReleaseObj( hpal );
590         GDI_ReleaseObj( hdc );
591     }
592
593     TRACE("(%06lx): returning %06lx\n", color, nearest );
594     return nearest;
595 }
596
597
598 /***********************************************************************
599  *           PALETTE_GetObject
600  */
601 int PALETTE_GetObject( PALETTEOBJ * palette, int count, LPSTR buffer )
602 {
603     if (count > sizeof(WORD)) count = sizeof(WORD);
604     memcpy( buffer, &palette->logpalette.palNumEntries, count );
605     return count;
606 }
607
608
609 /***********************************************************************
610  *           PALETTE_UnrealizeObject
611  */
612 BOOL PALETTE_UnrealizeObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
613 {
614     if (palette->mapping)
615     {
616         HeapFree( GetProcessHeap(), 0, palette->mapping );
617         palette->mapping = NULL;
618     }
619     if (hLastRealizedPalette == hpalette) hLastRealizedPalette = 0;
620     return TRUE;
621 }
622
623
624 /***********************************************************************
625  *           PALETTE_DeleteObject
626  */
627 BOOL PALETTE_DeleteObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
628 {
629     HeapFree( GetProcessHeap(), 0, palette->mapping );
630     if (hLastRealizedPalette == hpalette) hLastRealizedPalette = 0;
631     return GDI_FreeObject( hpalette, palette );
632 }
633
634
635 /***********************************************************************
636  *           GDISelectPalette    (GDI.361)
637  */
638 HPALETTE16 WINAPI GDISelectPalette16( HDC16 hdc, HPALETTE16 hpal, WORD wBkg)
639 {
640     HPALETTE16 prev;
641     DC *dc;
642
643     TRACE("%04x %04x\n", hdc, hpal );
644
645     if (GetObjectType(hpal) != OBJ_PAL)
646     {
647       WARN("invalid selected palette %04x\n",hpal);
648       return 0;
649     }
650     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
651     prev = dc->hPalette;
652     dc->hPalette = hpal;
653     GDI_ReleaseObj( hdc );
654     if (!wBkg) hPrimaryPalette = hpal; 
655     return prev;
656 }
657
658
659 /***********************************************************************
660  *           GDIRealizePalette    (GDI.362)
661  */
662 UINT16 WINAPI GDIRealizePalette16( HDC16 hdc )
663 {
664     PALETTEOBJ* palPtr;
665     int realized = 0;
666     DC* dc = DC_GetDCPtr( hdc );
667
668     if (!dc) return 0;
669
670     TRACE("%04x...\n", hdc );
671     
672     if(dc->hPalette != hLastRealizedPalette )
673     {
674         if( dc->hPalette == GetStockObject( DEFAULT_PALETTE )) {
675             realized = RealizeDefaultPalette16( hdc );
676             GDI_ReleaseObj( hdc );
677             return (UINT16)realized;
678         }
679
680
681         palPtr = (PALETTEOBJ *) GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC );
682
683         if (!palPtr) {
684             GDI_ReleaseObj( hdc );
685             FIXME("invalid selected palette %04x\n",dc->hPalette);
686             return 0;
687         }
688         
689         realized = PALETTE_Driver->
690           pSetMapping(palPtr,0,palPtr->logpalette.palNumEntries,
691                       (dc->hPalette != hPrimaryPalette) ||
692                       (dc->hPalette == GetStockObject( DEFAULT_PALETTE )));
693         hLastRealizedPalette = dc->hPalette;
694         GDI_ReleaseObj( dc->hPalette );
695     }
696     else TRACE("  skipping (hLastRealizedPalette = %04x)\n",
697                          hLastRealizedPalette);
698     GDI_ReleaseObj( hdc );
699
700     TRACE("   realized %i colors.\n", realized );
701     return (UINT16)realized;
702 }
703
704
705 /***********************************************************************
706  *           RealizeDefaultPalette    (GDI.365)
707  */
708 UINT16 WINAPI RealizeDefaultPalette16( HDC16 hdc )
709 {
710     UINT16 ret = 0;
711     DC          *dc;
712     PALETTEOBJ*  palPtr;
713
714     TRACE("%04x\n", hdc );
715
716     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
717
718     if (!(dc->flags & DC_MEMORY))
719     {
720         palPtr = (PALETTEOBJ*)GDI_GetObjPtr( GetStockObject(DEFAULT_PALETTE), PALETTE_MAGIC );
721         if (palPtr)
722         {
723             /* lookup is needed to account for SetSystemPaletteUse() stuff */
724             ret = PALETTE_Driver->pUpdateMapping(palPtr);
725             GDI_ReleaseObj( GetStockObject(DEFAULT_PALETTE) );
726         }
727     }
728     GDI_ReleaseObj( hdc );
729     return ret;
730 }
731
732 /***********************************************************************
733  *           IsDCCurrentPalette   (GDI.412)
734  */
735 BOOL16 WINAPI IsDCCurrentPalette16(HDC16 hDC)
736 {
737     DC *dc = DC_GetDCPtr( hDC );
738     if (dc) 
739     {
740       BOOL bRet = dc->hPalette == hPrimaryPalette;
741       GDI_ReleaseObj( hDC );
742       return bRet;
743     }
744     return FALSE;
745 }
746
747
748 /***********************************************************************
749  * SelectPalette [GDI32.300]  Selects logical palette into DC
750  *
751  * RETURNS
752  *    Success: Previous logical palette
753  *    Failure: NULL
754  */
755 HPALETTE WINAPI SelectPalette(
756     HDC hDC,               /* [in] Handle of device context */
757     HPALETTE hPal,         /* [in] Handle of logical color palette */
758     BOOL bForceBackground) /* [in] Foreground/background mode */
759 {
760     return pfnSelectPalette( hDC, hPal, bForceBackground );
761 }
762
763
764 /***********************************************************************
765  * RealizePalette [GDI32.280]  Maps palette entries to system palette
766  *
767  * RETURNS
768  *    Success: Number of entries in logical palette
769  *    Failure: GDI_ERROR
770  */
771 UINT WINAPI RealizePalette(
772     HDC hDC) /* [in] Handle of device context */
773 {
774     return pfnRealizePalette( hDC );
775 }
776
777
778 /**********************************************************************
779  *            UpdateColors16   (GDI.366)
780  */
781 INT16 WINAPI UpdateColors16( HDC16 hDC )
782 {
783     DC *dc;
784     HWND hWnd;
785     int size;
786
787     if (!(dc = DC_GetDCPtr( hDC ))) return 0;
788     size = dc->devCaps->sizePalette;
789     GDI_ReleaseObj( hDC );
790     if (Callout.WindowFromDC)
791     {
792         hWnd = Callout.WindowFromDC( hDC );
793
794         /* Docs say that we have to remap current drawable pixel by pixel
795          * but it would take forever given the speed of XGet/PutPixel.
796          */
797         if (hWnd && size)
798             Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
799     }
800     return 0x666;
801 }
802
803
804 /**********************************************************************
805  * UpdateColors [GDI32.359]  Remaps current colors to logical palette
806  *
807  * RETURNS
808  *    Success: TRUE
809  *    Failure: FALSE
810  */
811 BOOL WINAPI UpdateColors(
812     HDC hDC) /* [in] Handle of device context */
813 {
814     UpdateColors16( hDC );
815     return TRUE;
816 }
817
818
819 /*********************************************************************
820  *           SetMagicColors16   (GDI.606)
821  */
822 VOID WINAPI SetMagicColors16(HDC16 hDC, COLORREF color, UINT16 index)
823 {
824     FIXME("(hDC %04x, color %04x, index %04x): stub\n", hDC, (int)color, index);
825
826 }
827
828 /**********************************************************************
829  * GetICMProfileA [GDI32.316]
830  *
831  * Returns the filename of the specified device context's color
832  * management profile, even if color management is not enabled
833  * for that DC.
834  *
835  * RETURNS
836  *    TRUE if name copied succesfully OR lpszFilename is NULL
837  *    FALSE if the buffer length pointed to by lpcbName is too small
838  *
839  * NOTE
840  *    The buffer length pointed to by lpcbName is ALWAYS updated to
841  *    the length required regardless of other actions this function
842  *    may take.
843  *
844  * FIXME
845  *    How does Windows assign these?  Some registry key?
846  */
847
848 #define WINEICM "winefake.icm"  /* easy-to-identify fake filename */
849
850 BOOL WINAPI GetICMProfileA(HDC hDC, LPDWORD lpcbName, LPSTR lpszFilename)
851 {
852     DWORD callerLen;
853
854     FIXME("(%04x, %p, %p): partial stub\n", hDC, lpcbName, lpszFilename);
855
856     callerLen = *lpcbName;
857
858     /* all 3 behaviors require the required buffer size to be set */
859     *lpcbName = strlen(WINEICM);
860
861     /* behavior 1: if lpszFilename is NULL, return size of string and no error */
862     if ((DWORD)lpszFilename == (DWORD)0x00000000)
863         return TRUE;
864     
865     /* behavior 2: if buffer size too small, return size of string and error */
866     if (callerLen < strlen(WINEICM)) 
867     {
868         SetLastError(ERROR_INSUFFICIENT_BUFFER);
869         return FALSE;
870     }
871
872     /* behavior 3: if buffer size OK and pointer not NULL, copy and return size */
873     strcpy(lpszFilename, WINEICM);
874     return TRUE;
875 }