Implement NtGdiAnimatePalette (partly ripped from Wine)
[reactos.git] / reactos / subsys / 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 #include <w32k.h>
21
22 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
23
24 int COLOR_gapStart = 256;
25 int COLOR_gapEnd = -1;
26 int COLOR_gapFilled = 0;
27 int COLOR_max = 256;
28
29 #ifndef NO_MAPPING
30 static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
31 #endif
32 //static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
33
34
35 static UINT SystemPaletteUse = SYSPAL_STATIC; /* currently not considered */
36
37 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
38 {
39 // first 10 entries in the system palette
40 // red green blue flags
41 { 0x00, 0x00, 0x00, PC_SYS_USED },
42 { 0x80, 0x00, 0x00, PC_SYS_USED },
43 { 0x00, 0x80, 0x00, PC_SYS_USED },
44 { 0x80, 0x80, 0x00, PC_SYS_USED },
45 { 0x00, 0x00, 0x80, PC_SYS_USED },
46 { 0x80, 0x00, 0x80, PC_SYS_USED },
47 { 0x00, 0x80, 0x80, PC_SYS_USED },
48 { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
49 { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
50 { 0xd4, 0xd0, 0xc7, PC_SYS_USED },
51
52 // ... c_min/2 dynamic colorcells
53 // ... gap (for sparse palettes)
54 // ... c_min/2 dynamic colorcells
55
56 { 0xff, 0xfb, 0xf0, PC_SYS_USED },
57 { 0x3a, 0x6e, 0xa5, PC_SYS_USED },
58 { 0x80, 0x80, 0x80, PC_SYS_USED },
59 { 0xff, 0x00, 0x00, PC_SYS_USED },
60 { 0x00, 0xff, 0x00, PC_SYS_USED },
61 { 0xff, 0xff, 0x00, PC_SYS_USED },
62 { 0x00, 0x00, 0xff, PC_SYS_USED },
63 { 0xff, 0x00, 0xff, PC_SYS_USED },
64 { 0x00, 0xff, 0xff, PC_SYS_USED },
65 { 0xff, 0xff, 0xff, PC_SYS_USED } // last 10
66 };
67
68 const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate(void)
69 {
70 return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
71 }
72
73 BOOL STDCALL NtGdiAnimatePalette(HPALETTE hPal, UINT StartIndex,
74 UINT NumEntries, CONST PPALETTEENTRY PaletteColors)
75 {
76 if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
77 {
78 PPALGDI palPtr;
79 UINT pal_entries;
80 HDC hDC;
81 PDC dc;
82 HWND hHwd;
83 const PALETTEENTRY *pptr = PaletteColors;
84
85 palPtr = (PPALGDI)PALETTE_LockPalette(hPal);
86 if (!palPtr) return FALSE;
87
88 pal_entries = palPtr->NumColors;
89 if (StartIndex >= pal_entries)
90 {
91 PALETTE_UnlockPalette(hPal);
92 return FALSE;
93 }
94 if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
95
96 for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
97 /* According to MSDN, only animate PC_RESERVED colours */
98 if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED) {
99 memcpy( &palPtr->IndexedColors[StartIndex], pptr,
100 sizeof(PALETTEENTRY) );
101 PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
102 }
103 }
104
105 PALETTE_UnlockPalette(hPal);
106
107 /* Immediately apply the new palette if current window uses it */
108 hHwd = NtUserGetDesktopWindow();
109 hDC = (HDC)NtUserGetWindowDC(hHwd);
110 dc = DC_LockDc(hDC);
111 if (NULL != dc)
112 {
113 if (dc->w.hPalette == hPal)
114 {
115 DC_UnlockDc(hDC);
116 NtGdiRealizePalette(hDC);
117 }
118 else
119 DC_UnlockDc(hDC);
120 }
121 NtUserReleaseDC(hHwd,hDC);
122 }
123 return TRUE;
124 }
125
126 HPALETTE STDCALL NtGdiCreateHalftonePalette(HDC hDC)
127 {
128 int i, r, g, b;
129 struct {
130 WORD Version;
131 WORD NumberOfEntries;
132 PALETTEENTRY aEntries[256];
133 } Palette;
134
135 Palette.Version = 0x300;
136 Palette.NumberOfEntries = 256;
137 if (NtGdiGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
138 {
139 return 0;
140 }
141
142 for (r = 0; r < 6; r++)
143 for (g = 0; g < 6; g++)
144 for (b = 0; b < 6; b++)
145 {
146 i = r + g*6 + b*36 + 10;
147 Palette.aEntries[i].peRed = r * 51;
148 Palette.aEntries[i].peGreen = g * 51;
149 Palette.aEntries[i].peBlue = b * 51;
150 }
151
152 for (i = 216; i < 246; i++)
153 {
154 int v = (i - 216) << 3;
155 Palette.aEntries[i].peRed = v;
156 Palette.aEntries[i].peGreen = v;
157 Palette.aEntries[i].peBlue = v;
158 }
159
160 return NtGdiCreatePalette((LOGPALETTE *)&Palette);
161 }
162
163 HPALETTE STDCALL NtGdiCreatePalette(CONST PLOGPALETTE palette)
164 {
165 PPALGDI PalGDI;
166
167 HPALETTE NewPalette = PALETTE_AllocPalette(
168 PAL_INDEXED,
169 palette->palNumEntries,
170 (PULONG)palette->palPalEntry,
171 0, 0, 0);
172
173 PalGDI = (PPALGDI) PALETTE_LockPalette(NewPalette);
174 /* FIXME - Handle PalGDI == NULL!!!! */
175
176 PALETTE_ValidateFlags(PalGDI->IndexedColors, PalGDI->NumColors);
177 PalGDI->logicalToSystem = NULL;
178
179 PALETTE_UnlockPalette(NewPalette);
180
181 return NewPalette;
182 }
183
184 BOOL STDCALL NtGdiGetColorAdjustment(HDC hDC,
185 LPCOLORADJUSTMENT ca)
186 {
187 UNIMPLEMENTED;
188 return FALSE;
189 }
190
191 unsigned short GetNumberOfBits(unsigned int dwMask)
192 {
193 unsigned short wBits;
194 for (wBits = 0; dwMask; dwMask = dwMask & (dwMask - 1))
195 wBits++;
196 return wBits;
197 }
198
199 COLORREF STDCALL NtGdiGetNearestColor(HDC hDC, COLORREF Color)
200 {
201 COLORREF nearest = CLR_INVALID;
202 PDC dc;
203 PPALGDI palGDI;
204 LONG RBits, GBits, BBits;
205
206 dc = DC_LockDc(hDC);
207 if (NULL != dc)
208 {
209 HPALETTE hpal = dc->w.hPalette;
210 palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
211 if (!palGDI)
212 {
213 DC_UnlockDc(hDC);
214 return nearest;
215 }
216
217 switch (palGDI->Mode)
218 {
219 case PAL_INDEXED:
220 nearest = COLOR_LookupNearestColor(palGDI->IndexedColors,
221 palGDI->NumColors, Color);
222 break;
223 case PAL_BGR:
224 case PAL_RGB:
225 nearest = Color;
226 break;
227 case PAL_BITFIELDS:
228 RBits = 8 - GetNumberOfBits(palGDI->RedMask);
229 GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
230 BBits = 8 - GetNumberOfBits(palGDI->BlueMask);
231 nearest = RGB(
232 (GetRValue(Color) >> RBits) << RBits,
233 (GetGValue(Color) >> GBits) << GBits,
234 (GetBValue(Color) >> BBits) << BBits);
235 break;
236 }
237 PALETTE_UnlockPalette(hpal);
238 DC_UnlockDc(hDC);
239 }
240
241 return nearest;
242 }
243
244 UINT STDCALL NtGdiGetNearestPaletteIndex(HPALETTE hpal,
245 COLORREF Color)
246 {
247 PPALGDI palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
248 UINT index = 0;
249
250 if (NULL != palGDI)
251 {
252 /* Return closest match for the given RGB color */
253 index = COLOR_PaletteLookupPixel(palGDI->IndexedColors, palGDI->NumColors, NULL, Color, FALSE);
254 PALETTE_UnlockPalette(hpal);
255 }
256
257 return index;
258 }
259
260 UINT STDCALL NtGdiGetPaletteEntries(HPALETTE hpal,
261 UINT StartIndex,
262 UINT Entries,
263 LPPALETTEENTRY pe)
264 {
265 PPALGDI palGDI;
266 UINT numEntries;
267
268 palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
269 if (NULL == palGDI)
270 {
271 return 0;
272 }
273
274 numEntries = palGDI->NumColors;
275 if (numEntries < StartIndex + Entries)
276 {
277 Entries = numEntries - StartIndex;
278 }
279 if (NULL != pe)
280 {
281 if (numEntries <= StartIndex)
282 {
283 PALETTE_UnlockPalette(hpal);
284 return 0;
285 }
286 memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
287 for (numEntries = 0; numEntries < Entries; numEntries++)
288 {
289 if (pe[numEntries].peFlags & 0xF0)
290 {
291 pe[numEntries].peFlags = 0;
292 }
293 }
294 }
295
296 PALETTE_UnlockPalette(hpal);
297 return Entries;
298 }
299
300 UINT STDCALL NtGdiGetSystemPaletteEntries(HDC hDC,
301 UINT StartIndex,
302 UINT Entries,
303 LPPALETTEENTRY pe)
304 {
305 //UINT i;
306 //PDC dc;
307 /*
308 if (!(dc = AccessUserObject(hdc))) return 0;
309
310 if (!pe)
311 {
312 Entries = dc->GDIInfo->ulNumPalReg;
313 goto done;
314 }
315
316 if (StartIndex >= dc->GDIInfo->ulNumPalReg)
317 {
318 Entries = 0;
319 goto done;
320 }
321
322 if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
323
324 for (i = 0; i < Entries; i++)
325 {
326 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
327 }
328
329 done:
330 // GDI_ReleaseObj(hdc);
331 return count; */
332 // FIXME UNIMPLEMENTED;
333 return 0;
334 }
335
336 UINT STDCALL NtGdiGetSystemPaletteUse(HDC hDC)
337 {
338 return SystemPaletteUse;
339 }
340
341 /*!
342 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.
343
344 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.
345
346 1= IF DRAWING TO A DEVICE
347 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
348 the system palette.
349 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
350
351 2= IF DRAWING TO A MEMORY DC\BITMAP
352 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
353 the dc palette.
354 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
355 */
356 UINT STDCALL NtGdiRealizePalette(HDC hDC)
357 {
358 /*
359 * This function doesn't do any real work now and there's plenty
360 * of bugd in it (calling SetPalette for high/true-color modes,
361 * using DEFAULT_PALETTE instead of the device palette, ...).
362 */
363 #if 1
364 DPRINT1("NtGdiRealizePalette is unimplemented\n");
365 return 0;
366 #else
367 PALOBJ *palPtr, *sysPtr;
368 PPALGDI palGDI, sysGDI;
369 int realized = 0;
370 PDC dc;
371 HPALETTE systemPalette;
372 SURFOBJ *SurfObj;
373 BOOLEAN success;
374 USHORT sysMode, palMode;
375
376 dc = DC_LockDc(hDC);
377 if (!dc)
378 return 0;
379
380 SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
381 systemPalette = NtGdiGetStockObject((INT)DEFAULT_PALETTE);
382 palGDI = PALETTE_LockPalette(dc->w.hPalette);
383 palPtr = (PALOBJ*) palGDI;
384 /* FIXME - Handle palGDI == NULL!!!! */
385
386 // Step 1: Create mapping of system palette\DC palette
387 #ifndef NO_MAPPING
388 realized = PALETTE_SetMapping(palPtr, 0, palGDI->NumColors,
389 (dc->w.hPalette != hPrimaryPalette) ||
390 (dc->w.hPalette == NtGdiGetStockObject(DEFAULT_PALETTE)));
391 #else
392 realized = 0;
393 #endif
394
395 sysGDI = PALETTE_LockPalette(systemPalette);
396 sysPtr = (PALOBJ*) sysGDI;
397 /* FIXME - Handle sysGDI == NULL!!!!! */
398
399 // Step 2:
400 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
401 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
402 // context is a display DC, the physical palette for that device is modified.
403 if(dc->w.flags == DC_MEMORY)
404 {
405 // Memory managed DC
406 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
407 } else {
408 if(GDIDEVFUNCS(SurfObj).SetPalette)
409 {
410 ASSERT(sysGDI->NumColors <= 256);
411 success = GDIDEVFUNCS(SurfObj).SetPalette(
412 dc->PDev, sysPtr, 0, 0, sysGDI->NumColors);
413 }
414 }
415
416 // need to pass this to IntEngCreateXlate with palettes unlocked
417 sysMode = sysGDI->Mode;
418 palMode = palGDI->Mode;
419 PALETTE_UnlockPalette(systemPalette);
420 PALETTE_UnlockPalette(dc->w.hPalette);
421
422 // Step 3: Create the XLATEOBJ for device managed DCs
423 if(dc->w.flags != DC_MEMORY)
424 {
425 // Device managed DC
426 palGDI->logicalToSystem = IntEngCreateXlate(sysMode, palMode, systemPalette, dc->w.hPalette);
427 }
428
429 DC_UnlockDc(hDC);
430
431 return realized;
432 #endif
433 }
434
435 BOOL STDCALL NtGdiResizePalette(HPALETTE hpal,
436 UINT Entries)
437 {
438 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
439 UINT cPrevEnt, prevVer;
440 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
441 XLATEOBJ *XlateObj = NULL;
442
443 if(!palPtr) return FALSE;
444 cPrevEnt = palPtr->logpalette->palNumEntries;
445 prevVer = palPtr->logpalette->palVersion;
446 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
447 size += sizeof(int*) + sizeof(GDIOBJHDR);
448 XlateObj = palPtr->logicalToSystem;
449
450 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
451
452 if(XlateObj)
453 {
454 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
455 if(NewXlateObj == NULL)
456 {
457 ERR("Can not resize logicalToSystem -- out of memory!");
458 GDI_ReleaseObj( hPal );
459 return FALSE;
460 }
461 palPtr->logicalToSystem = NewXlateObj;
462 }
463
464 if(cEntries > cPrevEnt)
465 {
466 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
467 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
468 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
469 }
470 palPtr->logpalette->palNumEntries = cEntries;
471 palPtr->logpalette->palVersion = prevVer;
472 // GDI_ReleaseObj( hPal );
473 return TRUE; */
474
475 UNIMPLEMENTED;
476 return FALSE;
477 }
478
479 /*!
480 * Select logical palette into device context.
481 * \param hDC handle to the device context
482 * \param hpal handle to the palette
483 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
484 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
485 * palette colors in the best way.
486 * \return old palette
487 *
488 * \todo implement ForceBackground == TRUE
489 */
490 HPALETTE STDCALL NtGdiSelectPalette(HDC hDC,
491 HPALETTE hpal,
492 BOOL ForceBackground)
493 {
494 PDC dc;
495 HPALETTE oldPal = NULL;
496 PPALGDI PalGDI;
497
498 // FIXME: mark the palette as a [fore\back]ground pal
499 dc = DC_LockDc(hDC);
500 if (NULL != dc)
501 {
502 /* Check if this is a valid palette handle */
503 PalGDI = PALETTE_LockPalette(hpal);
504 if (NULL != PalGDI)
505 {
506 /* Is this a valid palette for this depth? */
507 if ((dc->w.bitsPerPixel <= 8 && PAL_INDEXED == PalGDI->Mode)
508 || (8 < dc->w.bitsPerPixel && PAL_INDEXED != PalGDI->Mode))
509 {
510 PALETTE_UnlockPalette(hpal);
511 oldPal = dc->w.hPalette;
512 dc->w.hPalette = hpal;
513 }
514 else
515 {
516 PALETTE_UnlockPalette(hpal);
517 oldPal = NULL;
518 }
519 }
520 else
521 {
522 oldPal = NULL;
523 }
524 DC_UnlockDc(hDC);
525 }
526
527 return oldPal;
528 }
529
530 BOOL STDCALL NtGdiSetColorAdjustment(HDC hDC,
531 CONST LPCOLORADJUSTMENT ca)
532 {
533 UNIMPLEMENTED;
534 return FALSE;
535 }
536
537 UINT STDCALL NtGdiSetPaletteEntries(HPALETTE hpal,
538 UINT Start,
539 UINT Entries,
540 CONST LPPALETTEENTRY pe)
541 {
542 PPALGDI palGDI;
543 WORD numEntries;
544
545 palGDI = PALETTE_LockPalette(hpal);
546 if (!palGDI) return 0;
547
548 numEntries = palGDI->NumColors;
549 if (Start >= numEntries)
550 {
551 PALETTE_UnlockPalette(hpal);
552 return 0;
553 }
554 if (numEntries < Start + Entries)
555 {
556 Entries = numEntries - Start;
557 }
558 memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
559 PALETTE_ValidateFlags(palGDI->IndexedColors, palGDI->NumColors);
560 ExFreePool(palGDI->logicalToSystem);
561 palGDI->logicalToSystem = NULL;
562 PALETTE_UnlockPalette(hpal);
563
564 return Entries;
565 }
566
567 UINT STDCALL
568 NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
569 {
570 UINT old = SystemPaletteUse;
571
572 /* Device doesn't support colour palettes */
573 if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
574 return SYSPAL_ERROR;
575 }
576
577 switch (Usage)
578 {
579 case SYSPAL_NOSTATIC:
580 case SYSPAL_NOSTATIC256:
581 case SYSPAL_STATIC:
582 SystemPaletteUse = Usage;
583 break;
584
585 default:
586 old=SYSPAL_ERROR;
587 break;
588 }
589
590 return old;
591 }
592
593 BOOL STDCALL
594 NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
595 {
596 UNIMPLEMENTED;
597 return FALSE;
598 }
599
600 BOOL STDCALL
601 NtGdiUpdateColors(HDC hDC)
602 {
603 HWND hWnd;
604
605 hWnd = (HWND)NtUserCallOneParam((DWORD)hDC, ONEPARAM_ROUTINE_WINDOWFROMDC);
606 if (hWnd == NULL)
607 {
608 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
609 return FALSE;
610 }
611 return NtUserRedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
612 }
613
614 INT STDCALL COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, INT size,
615 XLATEOBJ *XlateObj, COLORREF col, BOOL skipReserved)
616 {
617 int i, best = 0, diff = 0x7fffffff;
618 int r, g, b;
619
620 for( i = 0; i < size && diff ; i++ )
621 {
622 #if 0
623 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
624 continue;
625 #endif
626
627 r = abs((SHORT)palPalEntry[i].peRed - GetRValue(col));
628 g = abs((SHORT)palPalEntry[i].peGreen - GetGValue(col));
629 b = abs((SHORT)palPalEntry[i].peBlue - GetBValue(col));
630
631 r = r*r + g*g + b*b;
632
633 if( r < diff ) { best = i; diff = r; }
634 }
635
636 if (XlateObj == NULL)
637 return best;
638 else
639 return (XlateObj->pulXlate) ? (INT)XlateObj->pulXlate[best] : best;
640 }
641
642 COLORREF STDCALL COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
643 {
644 INT index;
645
646 index = COLOR_PaletteLookupPixel(palPalEntry, size, NULL, color, FALSE);
647 return RGB(
648 palPalEntry[index].peRed,
649 palPalEntry[index].peGreen,
650 palPalEntry[index].peBlue);
651 }
652
653 int STDCALL COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
654 COLORREF col )
655 {
656 int i;
657 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
658 for( i = 0; i < size; i++ )
659 {
660 if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */
661 if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;
662 }
663 return -1;
664 }
665 /* EOF */