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