Release 960805
[wine] / objects / palette.c
1 /*
2  * GDI palette objects
3  *
4  * Copyright 1993,1994 Alexandre Julliard
5  * Copyright 1996 Alex Korobka
6  *
7  */
8 #include <stdlib.h>
9 #include <string.h>
10 #include <X11/Xlib.h>
11
12 #include "color.h"
13 #include "palette.h"
14 #include "stddebug.h"
15 /* #define DEBUG_PALETTE */
16 #include "debug.h"
17
18 extern int              COLOR_LookupSystemPixel(COLORREF);      /* lookup pixel among static entries 
19                                                                  * of the system palette */
20 extern COLORREF         COLOR_GetSystemPaletteEntry(BYTE);
21
22 static WORD SystemPaletteUse = SYSPAL_STATIC;   /* currently not considered */
23
24 static HPALETTE16 hPrimaryPalette = 0; /* used for WM_PALETTECHANGED */
25 static HPALETTE16 hLastRealizedPalette = 0; /* UnrealizeObject() needs it */
26
27
28 /***********************************************************************
29  *           PALETTE_ValidateFlags
30  */
31 void PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, int size)
32 {
33     int i = 0;
34     for( ; i<size ; i++ )
35         lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
36 }
37
38
39 /***********************************************************************
40  *           CreatePalette    (GDI.360)
41  */
42 HPALETTE16 CreatePalette( const LOGPALETTE* palette )
43 {
44     PALETTEOBJ * palettePtr;
45     HPALETTE16 hpalette;
46     int size = sizeof(LOGPALETTE) + (palette->palNumEntries - 1) * sizeof(PALETTEENTRY);
47
48     dprintf_palette(stddeb,"CreatePalette: ");
49
50     dprintf_palette(stddeb,"%i entries, ", palette->palNumEntries);
51
52     hpalette = GDI_AllocObject( size + sizeof(int*) +sizeof(GDIOBJHDR) , PALETTE_MAGIC );
53     if (!hpalette) return 0;
54
55     palettePtr = (PALETTEOBJ *) GDI_HEAP_LIN_ADDR( hpalette );
56     memcpy( &palettePtr->logpalette, palette, size );
57     PALETTE_ValidateFlags(palettePtr->logpalette.palPalEntry, 
58                           palettePtr->logpalette.palNumEntries);
59     palettePtr->mapping = NULL;
60
61     dprintf_palette(stddeb,"returning %04x\n", hpalette);
62     return hpalette;
63 }
64
65
66 /***********************************************************************
67  *           GetPaletteEntries    (GDI.363)
68  */
69 WORD GetPaletteEntries( HPALETTE16 hpalette, WORD start, WORD count,
70                         LPPALETTEENTRY entries )
71 {
72     PALETTEOBJ * palPtr;
73     int numEntries;
74
75     dprintf_palette(stddeb,"GetPaletteEntries: hpal = %04x, %i entries\n", hpalette, count);
76         
77     palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
78     if (!palPtr) return 0;
79
80     numEntries = palPtr->logpalette.palNumEntries;
81     if (start >= numEntries) return 0;
82     if (start+count > numEntries) count = numEntries - start;
83     memcpy( entries, &palPtr->logpalette.palPalEntry[start],
84             count * sizeof(PALETTEENTRY) );
85     for( numEntries = 0; numEntries < count ; numEntries++ )
86          if( entries[numEntries].peFlags & 0xF0 ) entries[numEntries].peFlags = 0;
87     return count;
88 }
89
90
91 /***********************************************************************
92  *           SetPaletteEntries    (GDI.364)
93  */
94 WORD SetPaletteEntries( HPALETTE16 hpalette, WORD start, WORD count,
95                         LPPALETTEENTRY entries )
96 {
97     PALETTEOBJ * palPtr;
98     int numEntries;
99
100     dprintf_palette(stddeb,"SetPaletteEntries: hpal = %04x, %i entries\n", hpalette, count);
101
102     palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
103     if (!palPtr) return 0;
104
105     numEntries = palPtr->logpalette.palNumEntries;
106     if (start >= numEntries) return 0;
107     if (start+count > numEntries) count = numEntries - start;
108     memcpy( &palPtr->logpalette.palPalEntry[start], entries,
109             count * sizeof(PALETTEENTRY) );
110     PALETTE_ValidateFlags(palPtr->logpalette.palPalEntry, 
111                           palPtr->logpalette.palNumEntries);
112     free(palPtr->mapping);
113     palPtr->mapping = NULL;
114
115     return count;
116 }
117
118 /***********************************************************************
119  *           ResizePalette          (GDI.368)
120  */
121 BOOL ResizePalette(HPALETTE16 hPal, UINT cEntries)
122 {
123
124     /* should simply realloc memory and zero out
125      * added entries, if any */
126
127     fprintf(stdnimp,"ResizePalette: empty stub! \n");
128     return FALSE;
129 }
130
131 /***********************************************************************
132  *           AnimatePalette          (GDI.367)
133  */
134 BOOL AnimatePalette(HPALETTE16 hPal, UINT StartIndex, UINT NumEntries,
135                     LPPALETTEENTRY PaletteColors)
136 {
137     fprintf(stdnimp,"AnimatePalette: empty stub! \n");
138     return TRUE;
139 }
140
141 /***********************************************************************
142  *           SetSystemPaletteUse    (GDI.373)
143  */
144 WORD SetSystemPaletteUse( HDC hdc, WORD use)
145 {
146          WORD old=SystemPaletteUse;
147          fprintf(stdnimp,"SetSystemPaletteUse(%04x,%04x) // empty stub !!!\n", hdc, use);
148          SystemPaletteUse=use;
149          return old;
150 }
151
152 /***********************************************************************
153  *           GetSystemPaletteUse    (GDI.374)
154  */
155 WORD GetSystemPaletteUse( HDC hdc )
156 {
157         fprintf(stdnimp,"GetSystemPaletteUse(%04x) // empty stub !!!\n", hdc);
158         return SystemPaletteUse;
159 }
160
161
162 /***********************************************************************
163  *           GetSystemPaletteEntries    (GDI.375)
164  */
165 WORD GetSystemPaletteEntries( HDC hdc, WORD start, WORD count,
166                               LPPALETTEENTRY entries )
167 {
168     WORD i;
169     DC *dc;
170
171     dprintf_palette(stddeb,"GetSystemPaletteEntries: hdc = %04x, cound = %i", hdc, count );
172
173     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
174     if (start >= dc->w.devCaps->sizePalette) return 0;
175     if (start+count >= dc->w.devCaps->sizePalette)
176         count = dc->w.devCaps->sizePalette - start;
177     for (i = 0; i < count; i++)
178     {
179         *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry((BYTE)(start + i));
180
181         dprintf_palette(stddeb,"\tidx(%02x) -> RGB(%08lx)\n", (unsigned char)(start + i), 
182                                                             *(COLORREF*)(entries + i) );
183     }
184     return count;
185 }
186
187
188 /***********************************************************************
189  *           GetNearestPaletteIndex    (GDI.370)
190  */
191 WORD GetNearestPaletteIndex( HPALETTE16 hpalette, COLORREF color )
192 {
193     PALETTEOBJ* palObj = (PALETTEOBJ*) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
194     WORD        index  = 0;
195
196     if( palObj )
197         index = COLOR_PaletteLookupPixel( palObj->logpalette.palPalEntry, 
198                                           palObj->logpalette.palNumEntries, NULL,
199                                           color, FALSE );
200
201     dprintf_palette(stddeb,"GetNearestPaletteIndex(%04x,%06lx): returning %d\n", 
202                     hpalette, color, index );
203     return index;
204 }
205
206
207 /***********************************************************************
208  *           GetNearestColor    (GDI.154)
209  */
210 COLORREF GetNearestColor( HDC hdc, COLORREF color )
211 {
212     COLORREF     nearest = 0xFADECAFE;
213     DC          *dc;
214     PALETTEOBJ  *palObj;
215
216     if ( (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )) )
217     {
218       palObj = (PALETTEOBJ*) 
219                 GDI_GetObjPtr( (dc->w.hPalette)? dc->w.hPalette
220                                                : STOCK_DEFAULT_PALETTE, PALETTE_MAGIC );
221
222       nearest = COLOR_LookupNearestColor( palObj->logpalette.palPalEntry,
223                                           palObj->logpalette.palNumEntries, color );
224     }
225
226     dprintf_palette(stddeb,"GetNearestColor(%06lx): returning %06lx\n", 
227                     color, nearest );
228     return nearest;
229 }
230
231
232 /***********************************************************************
233  *           PALETTE_GetObject
234  */
235 int PALETTE_GetObject( PALETTEOBJ * palette, int count, LPSTR buffer )
236 {
237     if (count > sizeof(WORD)) count = sizeof(WORD);
238     memcpy( buffer, &palette->logpalette.palNumEntries, count );
239     return count;
240 }
241
242
243 /***********************************************************************
244  *           PALETTE_UnrealizeObject
245  */
246 BOOL PALETTE_UnrealizeObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
247 {
248     if (palette->mapping)
249     {
250         free( palette->mapping );
251         palette->mapping = NULL;
252     }
253     if (hLastRealizedPalette == hpalette) hLastRealizedPalette = 0;
254     return TRUE;
255 }
256
257
258 /***********************************************************************
259  *           PALETTE_DeleteObject
260  */
261 BOOL PALETTE_DeleteObject( HPALETTE16 hpalette, PALETTEOBJ *palette )
262 {
263     free( palette->mapping );
264     return GDI_FreeObject( hpalette );
265 }
266
267
268 /***********************************************************************
269  *           GDISelectPalette    (GDI.361)
270  */
271 HPALETTE16 GDISelectPalette( HDC hdc, HPALETTE16 hpal, WORD wBkg)
272 {
273     HPALETTE16 prev;
274     DC *dc;
275
276     dprintf_palette(stddeb, "GDISelectPalette: %04x %04x\n", hdc, hpal );
277     
278     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
279     if (!dc) 
280     {
281         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
282         if (!dc) return 0;
283     }
284     prev = dc->w.hPalette;
285     dc->w.hPalette = hpal;
286     if (!wBkg) hPrimaryPalette = hpal; 
287     return prev;
288 }
289
290
291 /***********************************************************************
292  *           GDIRealizePalette    (GDI.362)
293  *
294  */
295 UINT GDIRealizePalette( HDC hdc )
296 {
297     PALETTEOBJ* palPtr;
298     int         realized = 0;
299     DC*         dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
300     if (!dc) 
301     {
302         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
303         if (!dc) return 0;
304     }
305
306     dprintf_palette(stddeb, "GDIRealizePalette: %04x...", hdc );
307     
308     if( dc &&  dc->w.hPalette != hLastRealizedPalette )
309     {
310         if( dc->w.hPalette == STOCK_DEFAULT_PALETTE )
311             return RealizeDefaultPalette( hdc );
312
313         palPtr = (PALETTEOBJ *) GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC );
314         
315         realized = COLOR_SetMapping(palPtr, dc->w.hPalette != hPrimaryPalette 
316                                   || dc->w.hPalette == STOCK_DEFAULT_PALETTE );
317         hLastRealizedPalette = dc->w.hPalette;
318     }
319     else dprintf_palette(stddeb, " skipping ");
320     
321     dprintf_palette(stdnimp, " realized %i colors\n", realized );
322     return (UINT)realized;
323 }
324
325
326 /***********************************************************************
327  *           RealizeDefaultPalette    (GDI.365)
328  */
329 WORD RealizeDefaultPalette( HDC hdc )
330 {
331     DC          *dc;
332     PALETTEOBJ*  palPtr;
333     int          i, index, realized = 0;
334
335     dprintf_palette(stddeb,"RealizeDefaultPalette: %04x\n", hdc );
336
337     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
338     if (!dc) 
339     {
340         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
341         if (!dc) return 0;
342     }
343
344     if ( dc->w.flags & DC_MEMORY ) return 0;
345
346     hPrimaryPalette = STOCK_DEFAULT_PALETTE;
347     hLastRealizedPalette = STOCK_DEFAULT_PALETTE;
348
349     palPtr = (PALETTEOBJ*)GDI_GetObjPtr(STOCK_DEFAULT_PALETTE, PALETTE_MAGIC );
350
351     /* lookup is needed to account for SetSystemPaletteUse() stuff */
352
353     for( i = 0; i < 20; i++ )
354        {
355          index = COLOR_LookupSystemPixel(*(COLORREF*)(palPtr->logpalette.palPalEntry + i));
356
357          /* mapping is allocated in COLOR_InitPalette() */
358
359          if( index != palPtr->mapping[i] ) { palPtr->mapping[i]=index; realized++; }
360        }
361     return realized;
362 }
363
364 /***********************************************************************
365  *           IsDCCurrentPalette   (GDI.412)
366  */
367 BOOL IsDCCurrentPalette(HDC hDC)
368 {
369     DC* dc = (DC *)GDI_GetObjPtr( hDC, DC_MAGIC );
370     return (dc)?(dc->w.hPalette == hPrimaryPalette):FALSE;
371 }
372
373 /***********************************************************************
374  *           SelectPalette    (USER.282)
375  */
376 HPALETTE16 SelectPalette( HDC hDC, HPALETTE16 hPal, BOOL bForceBackground )
377 {
378     WORD        wBkgPalette = 1;
379     PALETTEOBJ* lpt = (PALETTEOBJ*) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
380
381     dprintf_palette(stddeb,"SelectPalette: dc %04x pal %04x, force=%i ", 
382                             hDC, hPal, bForceBackground);
383     if( !lpt ) return 0;
384
385     dprintf_palette(stddeb," entries = %d\n", 
386                             lpt->logpalette.palNumEntries);
387
388     if( hPal != STOCK_DEFAULT_PALETTE )
389     {
390         HWND hWnd = WindowFromDC( hDC );
391         HWND hActive = GetActiveWindow();
392         
393         /* set primary palette if it's related to current active */
394
395         if((!hWnd || (hActive == hWnd || IsChild(hActive,hWnd))) &&
396             !bForceBackground )
397             wBkgPalette = 0;
398     }
399     return GDISelectPalette( hDC, hPal, wBkgPalette);
400 }
401
402
403 /***********************************************************************
404  *           RealizePalette    (USER.283) (GDI32.280)
405  */
406 UINT16 RealizePalette( HDC32 hDC )
407 {
408     UINT16 realized = GDIRealizePalette( hDC );
409
410     /* do not send anything if no colors were changed */
411
412     if( IsDCCurrentPalette( hDC ) && realized && 
413         !(COLOR_GetSystemPaletteFlags() & COLOR_VIRTUAL) )
414     {
415         /* Send palette change notification */
416
417         HWND hWnd;
418         if( (hWnd = WindowFromDC( hDC )) )
419             SendMessage16( HWND_BROADCAST, WM_PALETTECHANGED, hWnd, 0L);
420     }
421     return realized;
422 }
423
424
425 /**********************************************************************
426  *          UpdateColors        (GDI.366)
427  *
428  */
429 int UpdateColors( HDC hDC )
430 {
431     HWND hWnd = WindowFromDC( hDC );
432
433     /* Docs say that we have to remap current drawable pixel by pixel
434      * but it would take forever given the speed of XGet/PutPixel.
435      */
436     if (hWnd && !(COLOR_GetSystemPaletteFlags() & COLOR_VIRTUAL) ) 
437         InvalidateRect16( hWnd, NULL, FALSE );
438     return 0x666;
439 }
440