fix winquake color glitc bug
[reactos.git] / reactos / subsys / win32k / objects / color.c
index e765bef..19e5f7e 100644 (file)
+/*
+ *  ReactOS W32 Subsystem
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$ */
+#include <w32k.h>
 
-#undef WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <win32k/color.h>
+// FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
 
-// #define NDEBUG
-#include <internal/debug.h>
+int COLOR_gapStart = 256;
+int COLOR_gapEnd = -1;
+int COLOR_gapFilled = 0;
+int COLOR_max = 256;
 
-BOOL STDCALL W32kAnimatePalette(HPALETTE  hpal,
-                         UINT  StartIndex,
-                         UINT  Entries,
-                         CONST PPALETTEENTRY  ppe)
+#ifndef NO_MAPPING
+static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
+#endif
+//static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
+
+
+static UINT SystemPaletteUse = SYSPAL_NOSTATIC;  /* the program need save the palate and restore it */
+
+const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
 {
-  UNIMPLEMENTED;
+  // first 10 entries in the system palette
+  // red  green blue  flags
+  { 0x00, 0x00, 0x00, PC_SYS_USED },
+  { 0x80, 0x00, 0x00, PC_SYS_USED },
+  { 0x00, 0x80, 0x00, PC_SYS_USED },
+  { 0x80, 0x80, 0x00, PC_SYS_USED },
+  { 0x00, 0x00, 0x80, PC_SYS_USED },
+  { 0x80, 0x00, 0x80, PC_SYS_USED },
+  { 0x00, 0x80, 0x80, PC_SYS_USED },
+  { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
+  { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
+  { 0xd4, 0xd0, 0xc7, PC_SYS_USED },
+
+  // ... c_min/2 dynamic colorcells
+  // ... gap (for sparse palettes)
+  // ... c_min/2 dynamic colorcells
+
+  { 0xff, 0xfb, 0xf0, PC_SYS_USED },
+  { 0x3a, 0x6e, 0xa5, PC_SYS_USED },
+  { 0x80, 0x80, 0x80, PC_SYS_USED },
+  { 0xff, 0x00, 0x00, PC_SYS_USED },
+  { 0x00, 0xff, 0x00, PC_SYS_USED },
+  { 0xff, 0xff, 0x00, PC_SYS_USED },
+  { 0x00, 0x00, 0xff, PC_SYS_USED },
+  { 0xff, 0x00, 0xff, PC_SYS_USED },
+  { 0x00, 0xff, 0xff, PC_SYS_USED },
+  { 0xff, 0xff, 0xff, PC_SYS_USED }     // last 10
+};
+
+const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate(void)
+{
+   return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
 }
 
-HPALETTE STDCALL W32kCreateHalftonePalette(HDC  hDC)
+BOOL STDCALL NtGdiAnimatePalette(HPALETTE hPal, UINT StartIndex,
+   UINT NumEntries, CONST PPALETTEENTRY PaletteColors)
 {
-  UNIMPLEMENTED;
+    if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
+    {
+        PPALGDI palPtr;
+        UINT pal_entries;
+        HDC hDC;
+        PDC dc;        
+               HWND hHwd;
+        const PALETTEENTRY *pptr = PaletteColors;
+        palPtr = (PPALGDI)PALETTE_LockPalette(hPal);
+        if (!palPtr) return FALSE;
+        pal_entries = palPtr->NumColors;
+        if (StartIndex >= pal_entries)
+        {
+          PALETTE_UnlockPalette(hPal);
+          return FALSE;
+        }
+        if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
+        for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
+          /* According to MSDN, only animate PC_RESERVED colours */
+          if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED) {
+            memcpy( &palPtr->IndexedColors[StartIndex], pptr,
+                    sizeof(PALETTEENTRY) );
+            PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
+          }
+        }
+        PALETTE_UnlockPalette(hPal);
+        /* Immediately apply the new palette if current window uses it */              
+               hHwd = NtUserGetDesktopWindow();
+        hDC =  (HDC)NtUserGetWindowDC(hHwd);
+        dc = DC_LockDc(hDC);
+        if (NULL != dc)
+        {
+          if (dc->w.hPalette == hPal)
+          {
+            DC_UnlockDc(hDC);
+            NtGdiRealizePalette(hDC);
+          }
+          else
+            DC_UnlockDc(hDC);
+        }              
+               NtUserReleaseDC(hHwd,hDC);   
+    }
+    return TRUE;
 }
 
-HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE lgpl)
+HPALETTE STDCALL NtGdiCreateHalftonePalette(HDC  hDC)
 {
-  UNIMPLEMENTED;
+   int i, r, g, b;
+   struct {
+      WORD Version;
+      WORD NumberOfEntries;
+      PALETTEENTRY aEntries[256];
+   } Palette;
+
+   Palette.Version = 0x300;
+   Palette.NumberOfEntries = 256;
+   if (NtGdiGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
+   {
+      return 0;
+   }
+
+   for (r = 0; r < 6; r++)
+      for (g = 0; g < 6; g++)
+         for (b = 0; b < 6; b++)
+         {
+            i = r + g*6 + b*36 + 10;
+            Palette.aEntries[i].peRed = r * 51;
+            Palette.aEntries[i].peGreen = g * 51;
+            Palette.aEntries[i].peBlue = b * 51;
+         }
+
+   for (i = 216; i < 246; i++)
+   {
+      int v = (i - 216) << 3;
+      Palette.aEntries[i].peRed = v;
+      Palette.aEntries[i].peGreen = v;
+      Palette.aEntries[i].peBlue = v;
+   }
+
+   return NtGdiCreatePalette((LOGPALETTE *)&Palette);
+}
+
+HPALETTE STDCALL NtGdiCreatePalette(CONST PLOGPALETTE palette)
+{
+  PPALGDI PalGDI;
+
+  HPALETTE NewPalette = PALETTE_AllocPalette(
+         PAL_INDEXED,
+         palette->palNumEntries,
+         (PULONG)palette->palPalEntry,
+         0, 0, 0);
+
+  PalGDI = (PPALGDI) PALETTE_LockPalette(NewPalette);
+  /* FIXME - Handle PalGDI == NULL!!!! */
+
+  PALETTE_ValidateFlags(PalGDI->IndexedColors, PalGDI->NumColors);
+  PalGDI->logicalToSystem = NULL;
+
+  PALETTE_UnlockPalette(NewPalette);
+
+  return NewPalette;
 }
 
-BOOL STDCALL W32kGetColorAdjustment(HDC  hDC,
+BOOL STDCALL NtGdiGetColorAdjustment(HDC  hDC,
                              LPCOLORADJUSTMENT  ca)
 {
-  UNIMPLEMENTED;
+   UNIMPLEMENTED;
+   return FALSE;
 }
 
-COLORREF STDCALL W32kGetNearestColor(HDC  hDC,
-                              COLORREF  Color)
+unsigned short GetNumberOfBits(unsigned int dwMask)
 {
-  UNIMPLEMENTED;
+   unsigned short wBits;
+   for (wBits = 0; dwMask; dwMask = dwMask & (dwMask - 1))
+      wBits++;
+   return wBits;
 }
 
-UINT STDCALL W32kGetNearestPaletteIndex(HPALETTE  hpal,
+COLORREF STDCALL NtGdiGetNearestColor(HDC hDC, COLORREF Color)
+{
+   COLORREF nearest = CLR_INVALID;
+   PDC dc;
+   PPALGDI palGDI;
+   LONG RBits, GBits, BBits;
+
+   dc = DC_LockDc(hDC);
+   if (NULL != dc)
+   {
+      HPALETTE hpal = dc->w.hPalette;
+      palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
+      if (!palGDI)
+      {
+         DC_UnlockDc(hDC);
+         return nearest;
+      }
+
+      switch (palGDI->Mode)
+      {
+         case PAL_INDEXED:
+            nearest = COLOR_LookupNearestColor(palGDI->IndexedColors,
+               palGDI->NumColors, Color);
+            break;
+         case PAL_BGR:
+         case PAL_RGB:
+            nearest = Color;
+            break;
+         case PAL_BITFIELDS:
+            RBits = 8 - GetNumberOfBits(palGDI->RedMask);
+            GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
+            BBits = 8 - GetNumberOfBits(palGDI->BlueMask);
+            nearest = RGB(
+              (GetRValue(Color) >> RBits) << RBits,
+              (GetGValue(Color) >> GBits) << GBits,
+              (GetBValue(Color) >> BBits) << BBits);
+            break;
+      }
+      PALETTE_UnlockPalette(hpal);
+      DC_UnlockDc(hDC);
+   }
+
+   return nearest;
+}
+
+UINT STDCALL NtGdiGetNearestPaletteIndex(HPALETTE  hpal,
                                  COLORREF  Color)
 {
-  UNIMPLEMENTED;
+  PPALGDI palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
+  UINT index  = 0;
+
+  if (NULL != palGDI)
+    {
+      /* Return closest match for the given RGB color */
+      index = COLOR_PaletteLookupPixel(palGDI->IndexedColors, palGDI->NumColors, NULL, Color, FALSE);
+      PALETTE_UnlockPalette(hpal);
+    }
+
+  return index;
 }
 
-UINT STDCALL W32kGetPaletteEntries(HPALETTE  hpal,
+UINT STDCALL NtGdiGetPaletteEntries(HPALETTE  hpal,
                             UINT  StartIndex,
                             UINT  Entries,
                             LPPALETTEENTRY  pe)
 {
-  UNIMPLEMENTED;
+  PPALGDI palGDI;
+  UINT numEntries;
+
+  palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
+  if (NULL == palGDI)
+    {
+      return 0;
+    }
+
+  numEntries = palGDI->NumColors;
+  if (numEntries < StartIndex + Entries)
+    {
+      Entries = numEntries - StartIndex;
+    }
+  if (NULL != pe)
+    {
+      if (numEntries <= StartIndex)
+       {
+         PALETTE_UnlockPalette(hpal);
+         return 0;
+       }
+      memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
+      for (numEntries = 0; numEntries < Entries; numEntries++)
+       {
+         if (pe[numEntries].peFlags & 0xF0)
+           {
+             pe[numEntries].peFlags = 0;
+           }
+       }
+    }
+
+  PALETTE_UnlockPalette(hpal);
+  return Entries;
 }
 
-UINT STDCALL W32kGetSystemPaletteEntries(HDC  hDC,
+UINT STDCALL NtGdiGetSystemPaletteEntries(HDC  hDC,
                                   UINT  StartIndex,
                                   UINT  Entries,
                                   LPPALETTEENTRY  pe)
 {
-  UNIMPLEMENTED;
+  //UINT i;
+  //PDC dc;
+/*
+  if (!(dc = AccessUserObject(hdc))) return 0;
+
+  if (!pe)
+  {
+    Entries = dc->GDIInfo->ulNumPalReg;
+    goto done;
+  }
+
+  if (StartIndex >= dc->GDIInfo->ulNumPalReg)
+  {
+    Entries = 0;
+    goto done;
+  }
+
+  if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
+
+  for (i = 0; i < Entries; i++)
+  {
+    *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
+  }
+
+  done:
+//    GDI_ReleaseObj(hdc);
+  return count; */
+  // FIXME UNIMPLEMENTED;
+  return 0;
 }
 
-UINT STDCALL W32kGetSystemPaletteUse(HDC  hDC)
-{
-  UNIMPLEMENTED;
+UINT STDCALL NtGdiGetSystemPaletteUse(HDC  hDC)
+{  
+  return SystemPaletteUse;
 }
 
-UINT STDCALL W32kRealizePalette(HDC  hDC)
+/*!
+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.
+
+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.
+
+1= IF DRAWING TO A DEVICE
+-- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
+   the system palette.
+-- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
+
+2= IF DRAWING TO A MEMORY DC\BITMAP
+-- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
+   the dc palette.
+-- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
+*/
+UINT STDCALL NtGdiRealizePalette(HDC hDC)
 {
-  UNIMPLEMENTED;
+  /*
+   * This function doesn't do any real work now and there's plenty
+   * of bugd in it (calling SetPalette for high/true-color modes,
+   * using DEFAULT_PALETTE instead of the device palette, ...).
+   */
+  PALOBJ *palPtr, *sysPtr;
+  PPALGDI palGDI, sysGDI;
+  int realized = 0;
+  PDC dc;
+  HPALETTE systemPalette;
+  BOOLEAN success;
+  USHORT sysMode, palMode;
+
+  dc = DC_LockDc(hDC);
+  if (!dc)
+       return 0;
+
+  systemPalette = NtGdiGetStockObject((INT)DEFAULT_PALETTE);
+  palGDI = PALETTE_LockPalette(dc->w.hPalette);
+  palPtr = (PALOBJ*) palGDI;
+  /* FIXME - Handle palGDI == NULL!!!! */
+
+  // Step 1: Create mapping of system palette\DC palette
+#ifndef NO_MAPPING
+  realized = PALETTE_SetMapping(palPtr, 0, palGDI->NumColors,
+               (dc->w.hPalette != hPrimaryPalette) ||
+               (dc->w.hPalette == NtGdiGetStockObject(DEFAULT_PALETTE)));
+#else
+  realized = 0;
+#endif
+
+  sysGDI = PALETTE_LockPalette(systemPalette);
+  sysPtr = (PALOBJ*) sysGDI;
+  /* FIXME - Handle sysGDI == NULL!!!!! */
+
+  // Step 2:
+  // 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.
+  if(dc->w.flags == DC_MEMORY)
+  {
+    // Memory managed DC
+    DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
+  } else {
+    if( ((GDIDEVICE *)dc->GDIDevice)->DriverFunctions.SetPalette)
+    {
+      ASSERT(palGDI->NumColors <= 256);
+      success = ((GDIDEVICE *)dc->GDIDevice)->DriverFunctions.SetPalette(
+        dc->PDev, palPtr, 0, 0, palGDI->NumColors);
+    }
+  }
+
+  // need to pass this to IntEngCreateXlate with palettes unlocked
+  sysMode = sysGDI->Mode;
+  palMode = palGDI->Mode;
+  PALETTE_UnlockPalette(systemPalette);
+  PALETTE_UnlockPalette(dc->w.hPalette);
+
+  // Step 3: Create the XLATEOBJ for device managed DCs
+  if(dc->w.flags != DC_MEMORY)
+  {
+    // Device managed DC
+    palGDI->logicalToSystem = IntEngCreateXlate(sysMode, palMode, systemPalette, dc->w.hPalette);
+  }
+
+  DC_UnlockDc(hDC);
+
+  return realized;
 }
 
-BOOL STDCALL W32kResizePalette(HPALETTE  hpal,
+BOOL STDCALL NtGdiResizePalette(HPALETTE  hpal,
                         UINT  Entries)
 {
+/*  PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
+  UINT cPrevEnt, prevVer;
+  INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
+  XLATEOBJ *XlateObj = NULL;
+
+  if(!palPtr) return FALSE;
+  cPrevEnt = palPtr->logpalette->palNumEntries;
+  prevVer = palPtr->logpalette->palVersion;
+  prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
+  size += sizeof(int*) + sizeof(GDIOBJHDR);
+  XlateObj = palPtr->logicalToSystem;
+
+  if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
+
+  if(XlateObj)
+  {
+    XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
+    if(NewXlateObj == NULL)
+    {
+      ERR("Can not resize logicalToSystem -- out of memory!");
+      GDI_ReleaseObj( hPal );
+      return FALSE;
+    }
+    palPtr->logicalToSystem = NewXlateObj;
+  }
+
+  if(cEntries > cPrevEnt)
+  {
+    if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
+    memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
+    PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
+  }
+  palPtr->logpalette->palNumEntries = cEntries;
+  palPtr->logpalette->palVersion = prevVer;
+//    GDI_ReleaseObj( hPal );
+  return TRUE; */
+
   UNIMPLEMENTED;
+  return FALSE;
 }
 
-HPALETTE STDCALL W32kSelectPalette(HDC  hDC,
+/*!
+ * Select logical palette into device context.
+ * \param      hDC                             handle to the device context
+ * \param      hpal                            handle to the palette
+ * \param      ForceBackground         If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
+ *                                                             is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
+ *                                                             palette colors in the best way.
+ * \return     old palette
+ *
+ * \todo       implement ForceBackground == TRUE
+*/
+HPALETTE STDCALL NtGdiSelectPalette(HDC  hDC,
                             HPALETTE  hpal,
                             BOOL  ForceBackground)
 {
-  UNIMPLEMENTED;
+  PDC dc;
+  HPALETTE oldPal = NULL;
+  PPALGDI PalGDI;
+
+  // FIXME: mark the palette as a [fore\back]ground pal
+  dc = DC_LockDc(hDC);
+  if (NULL != dc)
+    {
+      /* Check if this is a valid palette handle */
+      PalGDI = PALETTE_LockPalette(hpal);
+      if (NULL != PalGDI)
+       {
+          /* Is this a valid palette for this depth? */
+          if ((dc->w.bitsPerPixel <= 8 && PAL_INDEXED == PalGDI->Mode)
+              || (8 < dc->w.bitsPerPixel && PAL_INDEXED != PalGDI->Mode))
+            {
+              PALETTE_UnlockPalette(hpal);
+              oldPal = dc->w.hPalette;
+              dc->w.hPalette = hpal;
+            }
+          else
+            {
+              PALETTE_UnlockPalette(hpal);
+              oldPal = NULL;
+            }
+       }
+      else
+       {
+         oldPal = NULL;
+       }
+      DC_UnlockDc(hDC);
+    }
+
+  return oldPal;
 }
 
-BOOL STDCALL W32kSetColorAdjustment(HDC  hDC,
+BOOL STDCALL NtGdiSetColorAdjustment(HDC  hDC,
                              CONST LPCOLORADJUSTMENT  ca)
 {
-  UNIMPLEMENTED;
+   UNIMPLEMENTED;
+   return FALSE;
 }
 
-UINT STDCALL W32kSetPaletteEntries(HPALETTE  hpal,
+UINT STDCALL NtGdiSetPaletteEntries(HPALETTE  hpal,
                             UINT  Start,
                             UINT  Entries,
                             CONST LPPALETTEENTRY  pe)
 {
-  UNIMPLEMENTED;
+  PPALGDI palGDI;
+  WORD numEntries;
+
+  palGDI = PALETTE_LockPalette(hpal);
+  if (!palGDI) return 0;
+
+  numEntries = palGDI->NumColors;
+  if (Start >= numEntries)
+    {
+      PALETTE_UnlockPalette(hpal);
+      return 0;
+    }
+  if (numEntries < Start + Entries)
+    {
+      Entries = numEntries - Start;
+    }
+  memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
+  PALETTE_ValidateFlags(palGDI->IndexedColors, palGDI->NumColors);
+  ExFreePool(palGDI->logicalToSystem);
+  palGDI->logicalToSystem = NULL;
+  PALETTE_UnlockPalette(hpal);
+
+  return Entries;
 }
 
-UINT STDCALL W32kSetSystemPaletteUse(HDC  hDC,
-                              UINT  Usage)
+UINT STDCALL
+NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
 {
-  UNIMPLEMENTED;
+    UINT old = SystemPaletteUse;
+
+    /* Device doesn't support colour palettes */
+    if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
+        return SYSPAL_ERROR;
+    }
+
+    switch (Usage) 
+       {
+               case SYSPAL_NOSTATIC:
+        case SYSPAL_NOSTATIC256:       
+        case SYSPAL_STATIC:
+                               SystemPaletteUse = Usage;                               
+                               break;
+
+        default:
+                               old=SYSPAL_ERROR;
+                               break;
+       }
+
+ return old;
 }
 
-BOOL STDCALL W32kUnrealizeObject(HGDIOBJ  hgdiobj)
+BOOL STDCALL
+NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
 {
-  UNIMPLEMENTED;
+   UNIMPLEMENTED;
+   return FALSE;
 }
 
-BOOL STDCALL W32kUpdateColors(HDC  hDC)
+BOOL STDCALL
+NtGdiUpdateColors(HDC hDC)
 {
-  UNIMPLEMENTED;
+   HWND hWnd;
+
+   hWnd = (HWND)NtUserCallOneParam((DWORD)hDC, ONEPARAM_ROUTINE_WINDOWFROMDC);
+   if (hWnd == NULL)
+   {
+      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+      return FALSE;
+   }
+   return NtUserRedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE);
 }
 
+INT STDCALL COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, INT size,
+                             XLATEOBJ *XlateObj, COLORREF col, BOOL skipReserved)
+{
+  int i, best = 0, diff = 0x7fffffff;
+  int r, g, b;
+
+  for( i = 0; i < size && diff ; i++ )
+  {
+#if 0
+    if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags  & PC_SYS_RESERVED))
+      continue;
+#endif
+
+    r = abs((SHORT)palPalEntry[i].peRed - GetRValue(col));
+    g = abs((SHORT)palPalEntry[i].peGreen - GetGValue(col));
+    b = abs((SHORT)palPalEntry[i].peBlue - GetBValue(col));
+
+    r = r*r + g*g + b*b;
+
+    if( r < diff ) { best = i; diff = r; }
+  }
+
+  if (XlateObj == NULL)
+    return best;
+  else
+    return (XlateObj->pulXlate) ? (INT)XlateObj->pulXlate[best] : best;
+}
+
+COLORREF STDCALL COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
+{
+   INT index;
+
+   index = COLOR_PaletteLookupPixel(palPalEntry, size, NULL, color, FALSE);
+   return RGB(
+      palPalEntry[index].peRed,
+      palPalEntry[index].peGreen,
+      palPalEntry[index].peBlue);
+}
+
+int STDCALL COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
+                                   COLORREF col )
+{
+  int i;
+  BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
+  for( i = 0; i < size; i++ )
+  {
+    if( palPalEntry[i].peFlags & PC_SYS_USED )  /* skips gap */
+      if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;
+  }
+  return -1;
+}
+/* EOF */