- Evgeny Boltik, <BSTSoft AT narod DOT ru>: Fix system palette entries to match the...
[reactos.git] / reactos / subsystems / win32 / win32k / objects / color.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$ */
20
21 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
27
28 int COLOR_gapStart = 256;
29 int COLOR_gapEnd = -1;
30 int COLOR_gapFilled = 0;
31 int COLOR_max = 256;
32
33 #ifndef NO_MAPPING
34 static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
35 #endif
36 //static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
37
38
39 static UINT SystemPaletteUse = SYSPAL_NOSTATIC; /* the program need save the pallete and restore it */
40
41 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
42 {
43 // first 10 entries in the system palette
44 // red green blue flags
45 { 0x00, 0x00, 0x00, PC_SYS_USED },
46 { 0x80, 0x00, 0x00, PC_SYS_USED },
47 { 0x00, 0x80, 0x00, PC_SYS_USED },
48 { 0x80, 0x80, 0x00, PC_SYS_USED },
49 { 0x00, 0x00, 0x80, PC_SYS_USED },
50 { 0x80, 0x00, 0x80, PC_SYS_USED },
51 { 0x00, 0x80, 0x80, PC_SYS_USED },
52 { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
53 { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
54 { 0xa6, 0xca, 0xf0, PC_SYS_USED },
55
56 // ... c_min/2 dynamic colorcells
57 // ... gap (for sparse palettes)
58 // ... c_min/2 dynamic colorcells
59
60 { 0xff, 0xfb, 0xf0, PC_SYS_USED },
61 { 0xa0, 0xa0, 0xa4, PC_SYS_USED },
62 { 0x80, 0x80, 0x80, PC_SYS_USED },
63 { 0xff, 0x00, 0x00, PC_SYS_USED },
64 { 0x00, 0xff, 0x00, PC_SYS_USED },
65 { 0xff, 0xff, 0x00, PC_SYS_USED },
66 { 0x00, 0x00, 0xff, PC_SYS_USED },
67 { 0xff, 0x00, 0xff, PC_SYS_USED },
68 { 0x00, 0xff, 0xff, PC_SYS_USED },
69 { 0xff, 0xff, 0xff, PC_SYS_USED } // last 10
70 };
71
72 const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate(void)
73 {
74 return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
75 }
76
77 UINT APIENTRY
78 IntAnimatePalette(HPALETTE hPal,
79 UINT StartIndex,
80 UINT NumEntries,
81 CONST PPALETTEENTRY PaletteColors)
82 {
83 UINT ret = 0;
84
85 if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
86 {
87 PPALGDI palPtr;
88 UINT pal_entries;
89 HDC hDC;
90 PDC dc;
91 PWINDOW_OBJECT Wnd;
92 const PALETTEENTRY *pptr = PaletteColors;
93
94 palPtr = (PPALGDI)PALETTE_LockPalette(hPal);
95 if (!palPtr) return FALSE;
96
97 pal_entries = palPtr->NumColors;
98 if (StartIndex >= pal_entries)
99 {
100 PALETTE_UnlockPalette(palPtr);
101 return FALSE;
102 }
103 if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
104
105 for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++)
106 {
107 /* According to MSDN, only animate PC_RESERVED colours */
108 if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED)
109 {
110 memcpy( &palPtr->IndexedColors[StartIndex], pptr,
111 sizeof(PALETTEENTRY) );
112 ret++;
113 PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
114 }
115 }
116
117 PALETTE_UnlockPalette(palPtr);
118
119 /* Immediately apply the new palette if current window uses it */
120 Wnd = UserGetDesktopWindow();
121 hDC = UserGetWindowDC(Wnd);
122 dc = DC_LockDc(hDC);
123 if (NULL != dc)
124 {
125 if (dc->dclevel.hpal == hPal)
126 {
127 DC_UnlockDc(dc);
128 IntGdiRealizePalette(hDC);
129 }
130 else
131 DC_UnlockDc(dc);
132 }
133 UserReleaseDC(Wnd,hDC, FALSE);
134 }
135 return ret;
136 }
137
138 HPALETTE APIENTRY NtGdiCreateHalftonePalette(HDC hDC)
139 {
140 int i, r, g, b;
141 struct {
142 WORD Version;
143 WORD NumberOfEntries;
144 PALETTEENTRY aEntries[256];
145 } Palette;
146
147 Palette.Version = 0x300;
148 Palette.NumberOfEntries = 256;
149 if (IntGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
150 {
151 /* from wine, more that 256 color math */
152 Palette.NumberOfEntries = 20;
153 for (i = 0; i < Palette.NumberOfEntries; i++)
154 {
155 Palette.aEntries[i].peRed=0xff;
156 Palette.aEntries[i].peGreen=0xff;
157 Palette.aEntries[i].peBlue=0xff;
158 Palette.aEntries[i].peFlags=0x00;
159 }
160
161 Palette.aEntries[0].peRed=0x00;
162 Palette.aEntries[0].peBlue=0x00;
163 Palette.aEntries[0].peGreen=0x00;
164
165 /* the first 6 */
166 for (i=1; i <= 6; i++)
167 {
168 Palette.aEntries[i].peRed=(i%2)?0x80:0;
169 Palette.aEntries[i].peGreen=(i==2)?0x80:(i==3)?0x80:(i==6)?0x80:0;
170 Palette.aEntries[i].peBlue=(i>3)?0x80:0;
171 }
172
173 for (i=7; i <= 12; i++)
174 {
175 switch(i)
176 {
177 case 7:
178 Palette.aEntries[i].peRed=0xc0;
179 Palette.aEntries[i].peBlue=0xc0;
180 Palette.aEntries[i].peGreen=0xc0;
181 break;
182 case 8:
183 Palette.aEntries[i].peRed=0xc0;
184 Palette.aEntries[i].peGreen=0xdc;
185 Palette.aEntries[i].peBlue=0xc0;
186 break;
187 case 9:
188 Palette.aEntries[i].peRed=0xa6;
189 Palette.aEntries[i].peGreen=0xca;
190 Palette.aEntries[i].peBlue=0xf0;
191 break;
192 case 10:
193 Palette.aEntries[i].peRed=0xff;
194 Palette.aEntries[i].peGreen=0xfb;
195 Palette.aEntries[i].peBlue=0xf0;
196 break;
197 case 11:
198 Palette.aEntries[i].peRed=0xa0;
199 Palette.aEntries[i].peGreen=0xa0;
200 Palette.aEntries[i].peBlue=0xa4;
201 break;
202 case 12:
203 Palette.aEntries[i].peRed=0x80;
204 Palette.aEntries[i].peGreen=0x80;
205 Palette.aEntries[i].peBlue=0x80;
206 }
207 }
208
209 for (i=13; i <= 18; i++)
210 {
211 Palette.aEntries[i].peRed=(i%2)?0xff:0;
212 Palette.aEntries[i].peGreen=(i==14)?0xff:(i==15)?0xff:(i==18)?0xff:0;
213 Palette.aEntries[i].peBlue=(i>15)?0xff:0x00;
214 }
215 }
216 else
217 {
218 /* 256 color table */
219 for (r = 0; r < 6; r++)
220 for (g = 0; g < 6; g++)
221 for (b = 0; b < 6; b++)
222 {
223 i = r + g*6 + b*36 + 10;
224 Palette.aEntries[i].peRed = r * 51;
225 Palette.aEntries[i].peGreen = g * 51;
226 Palette.aEntries[i].peBlue = b * 51;
227 }
228
229 for (i = 216; i < 246; i++)
230 {
231 int v = (i - 216) << 3;
232 Palette.aEntries[i].peRed = v;
233 Palette.aEntries[i].peGreen = v;
234 Palette.aEntries[i].peBlue = v;
235 }
236 }
237
238 return NtGdiCreatePaletteInternal((LOGPALETTE *)&Palette, Palette.NumberOfEntries);
239 }
240
241
242
243 /*
244 * @implemented
245 */
246 HPALETTE APIENTRY
247 NtGdiCreatePaletteInternal ( IN LPLOGPALETTE pLogPal, IN UINT cEntries )
248 {
249 PPALGDI PalGDI;
250 HPALETTE NewPalette;
251
252 pLogPal->palNumEntries = cEntries;
253 NewPalette = PALETTE_AllocPalette( PAL_INDEXED,
254 cEntries,
255 (PULONG)pLogPal->palPalEntry,
256 0, 0, 0);
257
258 if (NewPalette == NULL)
259 {
260 return NULL;
261 }
262
263 PalGDI = (PPALGDI) PALETTE_LockPalette(NewPalette);
264 if (PalGDI != NULL)
265 {
266 PALETTE_ValidateFlags(PalGDI->IndexedColors, PalGDI->NumColors);
267 PalGDI->logicalToSystem = NULL;
268 PALETTE_UnlockPalette(PalGDI);
269 }
270 else
271 {
272 /* FIXME - Handle PalGDI == NULL!!!! */
273 DPRINT1("waring PalGDI is NULL \n");
274 }
275 return NewPalette;
276 }
277
278
279 BOOL APIENTRY NtGdiGetColorAdjustment(HDC hDC,
280 LPCOLORADJUSTMENT ca)
281 {
282 UNIMPLEMENTED;
283 return FALSE;
284 }
285
286 unsigned short GetNumberOfBits(unsigned int dwMask)
287 {
288 unsigned short wBits;
289 for (wBits = 0; dwMask; dwMask = dwMask & (dwMask - 1))
290 wBits++;
291 return wBits;
292 }
293
294 COLORREF APIENTRY NtGdiGetNearestColor(HDC hDC, COLORREF Color)
295 {
296 COLORREF nearest = CLR_INVALID;
297 PDC dc;
298 PPALGDI palGDI;
299 LONG RBits, GBits, BBits;
300
301 dc = DC_LockDc(hDC);
302 if (NULL != dc)
303 {
304 HPALETTE hpal = dc->dclevel.hpal;
305 palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
306 if (!palGDI)
307 {
308 DC_UnlockDc(dc);
309 return nearest;
310 }
311
312 switch (palGDI->Mode)
313 {
314 case PAL_INDEXED:
315 nearest = COLOR_LookupNearestColor(palGDI->IndexedColors,
316 palGDI->NumColors, Color);
317 break;
318 case PAL_BGR:
319 case PAL_RGB:
320 nearest = Color;
321 break;
322 case PAL_BITFIELDS:
323 RBits = 8 - GetNumberOfBits(palGDI->RedMask);
324 GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
325 BBits = 8 - GetNumberOfBits(palGDI->BlueMask);
326 nearest = RGB(
327 (GetRValue(Color) >> RBits) << RBits,
328 (GetGValue(Color) >> GBits) << GBits,
329 (GetBValue(Color) >> BBits) << BBits);
330 break;
331 }
332 PALETTE_UnlockPalette(palGDI);
333 DC_UnlockDc(dc);
334 }
335
336 return nearest;
337 }
338
339 UINT APIENTRY NtGdiGetNearestPaletteIndex(HPALETTE hpal,
340 COLORREF Color)
341 {
342 PPALGDI palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
343 UINT index = 0;
344
345 if (NULL != palGDI)
346 {
347 /* Return closest match for the given RGB color */
348 index = COLOR_PaletteLookupPixel(palGDI->IndexedColors, palGDI->NumColors, NULL, Color, FALSE);
349 PALETTE_UnlockPalette(palGDI);
350 }
351
352 return index;
353 }
354
355 UINT APIENTRY
356 IntGetPaletteEntries(HPALETTE hpal,
357 UINT StartIndex,
358 UINT Entries,
359 LPPALETTEENTRY pe)
360 {
361 PPALGDI palGDI;
362 UINT numEntries;
363
364 palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
365 if (NULL == palGDI)
366 {
367 return 0;
368 }
369
370 numEntries = palGDI->NumColors;
371 if (NULL != pe)
372 {
373 if (numEntries < StartIndex + Entries)
374 {
375 Entries = numEntries - StartIndex;
376 }
377 if (numEntries <= StartIndex)
378 {
379 PALETTE_UnlockPalette(palGDI);
380 return 0;
381 }
382 memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
383 for (numEntries = 0; numEntries < Entries; numEntries++)
384 {
385 if (pe[numEntries].peFlags & 0xF0)
386 {
387 pe[numEntries].peFlags = 0;
388 }
389 }
390 }
391 else
392 {
393 Entries = numEntries;
394 }
395
396 PALETTE_UnlockPalette(palGDI);
397 return Entries;
398 }
399
400 UINT APIENTRY
401 IntGetSystemPaletteEntries(HDC hDC,
402 UINT StartIndex,
403 UINT Entries,
404 LPPALETTEENTRY pe)
405 {
406 PPALGDI palGDI = NULL;
407 PDC dc = NULL;
408 UINT EntriesSize = 0;
409 UINT Ret = 0;
410
411 if (Entries == 0)
412 {
413 SetLastWin32Error(ERROR_INVALID_PARAMETER);
414 return 0;
415 }
416
417 if (pe != NULL)
418 {
419 EntriesSize = Entries * sizeof(pe[0]);
420 if (Entries != EntriesSize / sizeof(pe[0]))
421 {
422 /* Integer overflow! */
423 SetLastWin32Error(ERROR_INVALID_PARAMETER);
424 return 0;
425 }
426 }
427
428 if (!(dc = DC_LockDc(hDC)))
429 {
430 SetLastWin32Error(ERROR_INVALID_HANDLE);
431 return 0;
432 }
433
434 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
435 if (palGDI != NULL)
436 {
437 if (pe != NULL)
438 {
439 if (StartIndex >= palGDI->NumColors)
440 Entries = 0;
441 else if (Entries > palGDI->NumColors - StartIndex)
442 Entries = palGDI->NumColors - StartIndex;
443
444 memcpy(pe,
445 palGDI->IndexedColors + StartIndex,
446 Entries * sizeof(pe[0]));
447
448 Ret = Entries;
449 }
450 else
451 {
452 Ret = dc->ppdev->GDIInfo.ulNumPalReg;
453 }
454 }
455
456 if (palGDI != NULL)
457 PALETTE_UnlockPalette(palGDI);
458
459 if (dc != NULL)
460 DC_UnlockDc(dc);
461
462 return Ret;
463 }
464
465 UINT APIENTRY NtGdiGetSystemPaletteUse(HDC hDC)
466 {
467 return SystemPaletteUse;
468 }
469
470 /*!
471 The RealizePalette function modifies the palette for the device associated with the specified device context. If the device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device context is a display DC, the physical palette for that device is modified.
472
473 A logical palette is a buffer between color-intensive applications and the system, allowing these applications to use as many colors as needed without interfering with colors displayed by other windows.
474
475 1= IF DRAWING TO A DEVICE
476 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
477 the system palette.
478 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
479
480 2= IF DRAWING TO A MEMORY DC\BITMAP
481 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
482 the dc palette.
483 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
484 */
485 UINT FASTCALL IntGdiRealizePalette(HDC hDC)
486 {
487 /*
488 * This function doesn't do any real work now and there's plenty
489 * of bugs in it.
490 */
491
492 PPALGDI palGDI, sysGDI;
493 int realized = 0;
494 PDC dc;
495 HPALETTE systemPalette;
496 USHORT sysMode, palMode;
497
498 dc = DC_LockDc(hDC);
499 if (!dc) return 0;
500
501 systemPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
502 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
503
504 if (palGDI == NULL)
505 {
506 DPRINT1("IntGdiRealizePalette(): palGDI is NULL, exiting\n");
507 DC_UnlockDc(dc);
508 return 0;
509 }
510
511 sysGDI = PALETTE_LockPalette(systemPalette);
512
513 if (sysGDI == NULL)
514 {
515 DPRINT1("IntGdiRealizePalette(): sysGDI is NULL, exiting\n");
516 PALETTE_UnlockPalette(palGDI);
517 DC_UnlockDc(dc);
518 return 0;
519 }
520
521 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
522 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
523 // context is a display DC, the physical palette for that device is modified.
524 if(dc->dctype == DC_TYPE_MEMORY)
525 {
526 // Memory managed DC
527 DPRINT1("RealizePalette unimplemented for memory managed DCs\n");
528 } else
529 {
530 DPRINT1("RealizePalette unimplemented for device DCs\n");
531 }
532
533 // need to pass this to IntEngCreateXlate with palettes unlocked
534 sysMode = sysGDI->Mode;
535 palMode = palGDI->Mode;
536 PALETTE_UnlockPalette(sysGDI);
537 PALETTE_UnlockPalette(palGDI);
538
539 // Create the XLATEOBJ for device managed DCs
540 if(dc->dctype != DC_TYPE_MEMORY)
541 {
542 if (palGDI->logicalToSystem != NULL)
543 {
544 EngDeleteXlate(palGDI->logicalToSystem);
545 }
546 palGDI->logicalToSystem = IntEngCreateXlate(sysMode, palMode, systemPalette, dc->dclevel.hpal);
547 }
548
549 DC_UnlockDc(dc);
550
551 return realized;
552 }
553
554 BOOL APIENTRY NtGdiResizePalette(HPALETTE hpal,
555 UINT Entries)
556 {
557 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
558 UINT cPrevEnt, prevVer;
559 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
560 XLATEOBJ *XlateObj = NULL;
561
562 if(!palPtr) return FALSE;
563 cPrevEnt = palPtr->logpalette->palNumEntries;
564 prevVer = palPtr->logpalette->palVersion;
565 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
566 size += sizeof(int*) + sizeof(GDIOBJHDR);
567 XlateObj = palPtr->logicalToSystem;
568
569 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
570
571 if(XlateObj)
572 {
573 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
574 if(NewXlateObj == NULL)
575 {
576 ERR("Can not resize logicalToSystem -- out of memory!");
577 GDI_ReleaseObj( hPal );
578 return FALSE;
579 }
580 palPtr->logicalToSystem = NewXlateObj;
581 }
582
583 if(cEntries > cPrevEnt)
584 {
585 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
586 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
587 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
588 }
589 palPtr->logpalette->palNumEntries = cEntries;
590 palPtr->logpalette->palVersion = prevVer;
591 // GDI_ReleaseObj( hPal );
592 return TRUE; */
593
594 UNIMPLEMENTED;
595 return FALSE;
596 }
597
598 BOOL APIENTRY NtGdiSetColorAdjustment(HDC hDC,
599 LPCOLORADJUSTMENT ca)
600 {
601 UNIMPLEMENTED;
602 return FALSE;
603 }
604
605 UINT APIENTRY
606 IntSetPaletteEntries(HPALETTE hpal,
607 UINT Start,
608 UINT Entries,
609 CONST LPPALETTEENTRY pe)
610 {
611 PPALGDI palGDI;
612 WORD numEntries;
613
614 if ((UINT)hpal & GDI_HANDLE_STOCK_MASK)
615 {
616 return 0;
617 }
618
619 palGDI = PALETTE_LockPalette(hpal);
620 if (!palGDI) return 0;
621
622 numEntries = palGDI->NumColors;
623 if (Start >= numEntries)
624 {
625 PALETTE_UnlockPalette(palGDI);
626 return 0;
627 }
628 if (numEntries < Start + Entries)
629 {
630 Entries = numEntries - Start;
631 }
632 memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
633 PALETTE_ValidateFlags(palGDI->IndexedColors, palGDI->NumColors);
634 if (palGDI->logicalToSystem)
635 ExFreePool(palGDI->logicalToSystem);
636 palGDI->logicalToSystem = NULL;
637 PALETTE_UnlockPalette(palGDI);
638
639 return Entries;
640 }
641
642 UINT APIENTRY
643 NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
644 {
645 UINT old = SystemPaletteUse;
646
647 /* Device doesn't support colour palettes */
648 if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
649 return SYSPAL_ERROR;
650 }
651
652 switch (Usage)
653 {
654 case SYSPAL_NOSTATIC:
655 case SYSPAL_NOSTATIC256:
656 case SYSPAL_STATIC:
657 SystemPaletteUse = Usage;
658 break;
659
660 default:
661 old=SYSPAL_ERROR;
662 break;
663 }
664
665 return old;
666 }
667
668 BOOL
669 APIENTRY
670 NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
671 {
672 BOOL Ret = FALSE;
673 PPALGDI palGDI;
674
675 if ( !hgdiobj ||
676 ((UINT)hgdiobj & GDI_HANDLE_STOCK_MASK) ||
677 !GDI_HANDLE_IS_TYPE(hgdiobj, GDI_OBJECT_TYPE_PALETTE) )
678 return Ret;
679
680 palGDI = PALETTE_LockPalette(hgdiobj);
681 if (!palGDI) return FALSE;
682
683 // FIXME!!
684 // Need to do something!!!
685 // Zero out Current and Old Translated pointers?
686 //
687 Ret = TRUE;
688 PALETTE_UnlockPalette(palGDI);
689 return Ret;
690 }
691
692 BOOL APIENTRY
693 NtGdiUpdateColors(HDC hDC)
694 {
695 PWINDOW_OBJECT Wnd;
696 BOOL calledFromUser, ret;
697 USER_REFERENCE_ENTRY Ref;
698
699 calledFromUser = UserIsEntered();
700
701 if (!calledFromUser){
702 UserEnterExclusive();
703 }
704
705 Wnd = UserGetWindowObject(IntWindowFromDC(hDC));
706 if (Wnd == NULL)
707 {
708 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
709
710 if (!calledFromUser){
711 UserLeave();
712 }
713
714 return FALSE;
715 }
716
717 UserRefObjectCo(Wnd, &Ref);
718 ret = co_UserRedrawWindow(Wnd, NULL, 0, RDW_INVALIDATE);
719 UserDerefObjectCo(Wnd);
720
721 if (!calledFromUser){
722 UserLeave();
723 }
724
725 return ret;
726 }
727
728 INT APIENTRY COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, INT size,
729 XLATEOBJ *XlateObj, COLORREF col, BOOL skipReserved)
730 {
731 int i, best = 0, diff = 0x7fffffff;
732 int r, g, b;
733
734 for( i = 0; i < size && diff ; i++ )
735 {
736 #if 0
737 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
738 continue;
739 #endif
740
741 r = abs((SHORT)palPalEntry[i].peRed - GetRValue(col));
742 g = abs((SHORT)palPalEntry[i].peGreen - GetGValue(col));
743 b = abs((SHORT)palPalEntry[i].peBlue - GetBValue(col));
744
745 r = r*r + g*g + b*b;
746
747 if( r < diff ) { best = i; diff = r; }
748 }
749
750 if (XlateObj == NULL)
751 return best;
752 else
753 return (XlateObj->pulXlate) ? (INT)XlateObj->pulXlate[best] : best;
754 }
755
756 COLORREF APIENTRY COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
757 {
758 INT index;
759
760 index = COLOR_PaletteLookupPixel(palPalEntry, size, NULL, color, FALSE);
761 return RGB(
762 palPalEntry[index].peRed,
763 palPalEntry[index].peGreen,
764 palPalEntry[index].peBlue);
765 }
766
767 int APIENTRY COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
768 COLORREF col )
769 {
770 int i;
771 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
772 for( i = 0; i < size; i++ )
773 {
774 if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */
775 if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;
776 }
777 return -1;
778 }
779
780
781 W32KAPI
782 LONG
783 APIENTRY
784 NtGdiDoPalette(
785 IN HGDIOBJ hObj,
786 IN WORD iStart,
787 IN WORD cEntries,
788 IN LPVOID pUnsafeEntries,
789 IN DWORD iFunc,
790 IN BOOL bInbound)
791 {
792 LONG ret;
793 LPVOID pEntries = NULL;
794
795 /* FIXME: Handle bInbound correctly */
796
797 if (bInbound &&
798 (pUnsafeEntries == NULL || cEntries == 0))
799 {
800 return 0;
801 }
802
803 if (pUnsafeEntries)
804 {
805 pEntries = ExAllocatePool(PagedPool, cEntries * sizeof(PALETTEENTRY));
806 if (!pEntries)
807 return 0;
808 if (bInbound)
809 {
810 _SEH2_TRY
811 {
812 ProbeForRead(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
813 memcpy(pEntries, pUnsafeEntries, cEntries * sizeof(PALETTEENTRY));
814 }
815 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
816 {
817 ExFreePool(pEntries);
818 _SEH2_YIELD(return 0);
819 }
820 _SEH2_END
821 }
822 }
823
824 ret = 0;
825 switch(iFunc)
826 {
827 case GdiPalAnimate:
828 if (pEntries)
829 ret = IntAnimatePalette((HPALETTE)hObj, iStart, cEntries, (CONST PPALETTEENTRY)pEntries);
830 break;
831
832 case GdiPalSetEntries:
833 if (pEntries)
834 ret = IntSetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (CONST LPPALETTEENTRY)pEntries);
835 break;
836
837 case GdiPalGetEntries:
838 ret = IntGetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
839 break;
840
841 case GdiPalGetSystemEntries:
842 ret = IntGetSystemPaletteEntries((HDC)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
843 break;
844
845 case GdiPalSetColorTable:
846 if (pEntries)
847 ret = IntSetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
848 break;
849
850 case GdiPalGetColorTable:
851 if (pEntries)
852 ret = IntGetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
853 break;
854 }
855
856 if (pEntries)
857 {
858 if (!bInbound)
859 {
860 _SEH2_TRY
861 {
862 ProbeForWrite(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
863 memcpy(pUnsafeEntries, pEntries, cEntries * sizeof(PALETTEENTRY));
864 }
865 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
866 {
867 ret = 0;
868 }
869 _SEH2_END
870 }
871 ExFreePool(pEntries);
872 }
873
874 return ret;
875 }
876
877 /* EOF */