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