Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2639 lines
76 KiB

/******************************Module*Header*******************************\
* Module Name: palgdi.cxx
*
* This module provides the API level interface functions for dealing with
* palettes.
*
* Created: 07-Nov-1990 22:21:11
* Author: Patrick Haluptzok patrickh
*
* Copyright (c) 1990-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
// hForePalette is a global variable that tells which palette is currently
// realized in the foreground.
HPALETTE hForePalette = 0;
PW32PROCESS hForePID = 0;
#if DBG
ULONG DbgPal = 0;
#define PAL_DEBUG(l,x) {if (l <= DbgPal) {DbgPrint("%p ", hpalDC); DbgPrint(x);}}
#else
#define PAL_DEBUG(l,x)
#endif
/******************************Public*Routine******************************\
* GreGetDIBColorTable
*
* Get the color table of the DIB section currently selected into the dc
* identified by the given hdc. If the surface is not a DIB section,
* this function will fail.
*
* History:
* 07-Sep-1993 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
#if ((BMF_1BPP != 1) || (BMF_4BPP != 2) || (BMF_8BPP != 3))
#error GetDIBColorTable BAD FORMAT
#endif
UINT
APIENTRY
GreGetDIBColorTable(
HDC hdc,
UINT iStart,
UINT cEntries,
RGBQUAD *pRGB
)
{
UINT iRet = 0;
DCOBJ dco(hdc);
if (pRGB != (RGBQUAD *)NULL)
{
if (dco.bValid())
{
//
// Protect against dynamic mode changes while we go grunging
// around in the surface.
//
DEVLOCKOBJ dlo;
dlo.vLockNoDrawing(dco);
//
// Fail if the selected in surface is not a DIB or the depth is more than
// 8BPP.
//
SURFACE *pSurf = dco.pSurfaceEff();
ULONG iFormat = pSurf->iFormat();
if ((pSurf->bDIBSection() || (pSurf->pPal != NULL)) &&
(iFormat <= BMF_8BPP) && (iFormat >= BMF_1BPP))
{
//
// Lock the surface palette and figure out the max index allowed on the
// palette. Win95 does not return un-used entries.
//
XEPALOBJ pal(pSurf->ppal());
ASSERTGDI(pal.bValid(), "GetDIBColorTable: invalid pal\n");
UINT iMax = (UINT) pal.cEntries();
if (iStart >= iMax)
{
return(0);
}
UINT iLast = iStart + cEntries;
if (iLast > iMax)
{
iLast = iMax;
}
pal.vFill_rgbquads(pRGB, iStart, iRet = iLast - iStart);
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
}
return(iRet);
}
/******************************Public*Routine******************************\
* GreSetDIBColorTable
*
* Set the color table of the DIB section currently selected into the dc
* identified by the given hdc. If the surface is not a DIB section,
* this function will fail.
*
* History:
* 07-Sep-1993 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
UINT
APIENTRY
GreSetDIBColorTable(
HDC hdc,
UINT iStart,
UINT cEntries,
RGBQUAD *pRGB
)
{
UINT iRet = 0;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// Protect against dynamic mode changes while we go grunging
// around in the surface.
//
DEVLOCKOBJ dlo;
dlo.vLockNoDrawing(dco);
//
// Fail if the selected in surface is not a DIB or the depth is more than
// 8BPP.
//
SURFACE *pSurf = dco.pSurfaceEff();
ULONG iFormat = pSurf->iFormat();
if (pSurf->bDIBSection() &&
(iFormat <= BMF_8BPP) && (iFormat >= BMF_1BPP))
{
//
// Mark the brushes dirty.
//
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
//
// Lock the surface palette and figure out the max
// index allowed on the palette.
//
XEPALOBJ pal(pSurf->ppal());
ASSERTGDI(pal.bValid(), "GetDIBColorTable: invalid pal\n");
UINT iMax = (UINT) pal.cEntries();
if (iStart < iMax)
{
UINT iLast = iStart + cEntries;
if (iLast > iMax)
iLast = iMax;
pal.vCopy_rgbquad(pRGB, iStart, iRet = iLast - iStart);
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
return(iRet);
}
/******************************Public*Routine******************************\
* GreCreatePalette - creates a palette from the logpal information given
*
* API function.
*
* returns HPALETTE for succes, (HPALETTE) 0 for failure
*
* History:
* 07-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
HPALETTE
APIENTRY
GreCreatePalette(
LPLOGPALETTE pLogPal
)
{
return(GreCreatePaletteInternal(pLogPal,pLogPal->palNumEntries));
}
HPALETTE
APIENTRY
GreCreatePaletteInternal(
LPLOGPALETTE pLogPal,
UINT cEntries
)
{
if ((pLogPal->palVersion != 0x300) || (cEntries == 0))
{
WARNING("GreCreatePalette failed, 0 entries or wrong version\n");
return((HPALETTE) 0);
}
//
// The constructor checks for invalid flags and fails if they are found.
//
PALMEMOBJ pal;
if (!pal.bCreatePalette(PAL_INDEXED,
cEntries,
(PULONG) pLogPal->palPalEntry,
0, 0, 0,
(PAL_DC | PAL_FREE)))
{
return((HPALETTE) 0);
}
ASSERTGDI(pal.cEntries() != 0, "ERROR can't be 0, bGetEntriesFrom depends on that");
pal.vKeepIt();
GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT);
return((HPALETTE) pal.hpal());
}
/******************************Public*Routine******************************\
* NtGdiCreatePaletteInternal()
*
* History:
* 01-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HPALETTE
APIENTRY
NtGdiCreatePaletteInternal(
LPLOGPALETTE pLogPal,
UINT cEntries
)
{
HPALETTE hpalRet = (HPALETTE)1;
//
// verify cEntries
//
if (cEntries <= 65536)
{
int cj = cEntries * sizeof(PALETTEENTRY) + offsetof(LOGPALETTE,palPalEntry);
WORD Version;
PULONG pPaletteEntry;
__try
{
// it is safe to do a byte here. If we can access dword's on byte boundries
// this will work. If not we will hit an exception under a try except. Winhelp
// passes in an unaligned palette but only on x86.
ProbeForRead(pLogPal,cj, sizeof(BYTE));
Version = pLogPal->palVersion;
pPaletteEntry = (PULONG) pLogPal->palPalEntry;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
hpalRet = (HPALETTE)0;
}
if (hpalRet)
{
if ((Version != 0x300) || (cEntries == 0))
{
WARNING("GreCreatePalette failed, 0 entries or wrong version\n");
hpalRet = (HPALETTE)0;
}
if (hpalRet)
{
//
// The constructor checks for invalid flags and fails if they are found.
//
PALMEMOBJ pal;
BOOL bStatus;
//
// bCreatePalette must use a try-except when accessing pPaletteEntry
//
bStatus = pal.bCreatePalette(PAL_INDEXED,
cEntries,
pPaletteEntry,
0,
0,
0,
(PAL_DC | PAL_FREE));
if (bStatus)
{
ASSERTGDI(pal.cEntries() != 0, "ERROR can't be 0, bGetEntriesFrom depends on that");
bStatus = GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT);
if (bStatus)
{
pal.vKeepIt();
hpalRet = pal.hpal();
}
else
{
hpalRet = (HPALETTE)0;
}
}
else
{
hpalRet = (HPALETTE)0;
}
}
}
}
else
{
hpalRet = 0;
WARNING("GreCreatePalette failed,cEntries too large\n");
}
return(hpalRet);
}
/******************************Public*Routine******************************\
* GreCreateCompatibleHalftonePalette
*
* Creates the win95 compatible halftone palette
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 11/27/1996 Mark Enstrom [marke]
*
\**************************************************************************/
HPALETTE
APIENTRY
GreCreateCompatibleHalftonePalette(
HDC hdc
)
{
HPALETTE hpalRet;
PALMEMOBJ pal;
BOOL bStatus;
//
// bCreatePalette must use a try-except when accessing pPaletteEntry
//
bStatus = pal.bCreatePalette(PAL_INDEXED,
256,
(PULONG)&aPalHalftone[0].ul,
0,
0,
0,
(PAL_DC | PAL_FREE | PAL_HT));
if (bStatus)
{
ASSERTGDI(pal.cEntries() != 0, "ERROR can't be 0, bGetEntriesFrom depends on that");
pal.flPal(PAL_HT);
bStatus = GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT);
if (bStatus)
{
pal.vKeepIt();
hpalRet = pal.hpal();
}
else
{
hpalRet = (HPALETTE)0;
}
}
else
{
hpalRet = (HPALETTE)0;
}
return(hpalRet);
}
/******************************Public*Routine******************************\
* GreCreateHalftonePalette(hdc)
*
* Create a halftone palette for the given DC.
*
* History:
* 31-Aug-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
HPALETTE
APIENTRY
GreCreateHalftonePalette(
HDC hdc
)
{
//
// Validate and lock down the DC. NOTE: Even though the surface is accessed
// in this function, it is only for information purposes. No reading or
// writing of the surface occurs.
//
DCOBJ dco(hdc);
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return((HPALETTE) 0);
}
//
// Get the PDEV from the DC.
//
PDEVOBJ po(dco.hdev());
//
// Acquire the devlock to protect against dynamic mode changes while
// we enable halftoning for the PDEV and we construct the halftone
// palette from this information.
//
DEVLOCKOBJ dlo(po);
//
// Create the halftone block if it has not existed yet.
//
if ((po.pDevHTInfo() == NULL) &&
!po.bEnableHalftone((PCOLORADJUSTMENT)NULL))
return((HPALETTE) 0);
DEVICEHALFTONEINFO *pDevHTInfo = (DEVICEHALFTONEINFO *)po.pDevHTInfo();
//
// Use the entries in the halftone palette in the halftone block to create
// the palette.
//
EPALOBJ palHT((HPALETTE)pDevHTInfo->DeviceOwnData);
ASSERTGDI(palHT.bValid(), "GreCreateHalftonePalette: invalid HT pal\n");
PALMEMOBJ pal;
if (palHT.cEntries())
{
if (!pal.bCreatePalette(PAL_INDEXED, palHT.cEntries(),
(PULONG)palHT.apalColorGet(), 0, 0, 0,
(PAL_DC | PAL_FREE | PAL_HT)))
{
return((HPALETTE) 0);
}
}
else
{
//
// 16BPP halftone uses 555 for RGB. We can't create a zero
// entry palette at the API level, so lets create a default palette.
//
if (!pal.bCreatePalette(PAL_INDEXED, (ULONG)logDefaultPal.palNumEntries,
(PULONG)logDefaultPal.palPalEntry, 0, 0, 0,
PAL_DC | PAL_FREE | PAL_HT))
{
return(FALSE);
}
}
pal.vKeepIt();
GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT);
return((HPALETTE) pal.hpal());
}
/******************************Public*Routine******************************\
* GreGetNearestPaletteIndex - returns the nearest palette index to crColor
* in the hpalette. Can only fail if hpal passed in is busy or bad.
*
* API function.
*
* returns value >= 0 for success, -1 for failure.
*
* History:
* 09-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
UINT
APIENTRY
NtGdiGetNearestPaletteIndex(
HPALETTE hpal,
COLORREF crColor
)
{
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid())
{
//
// If the palette has 0 entries return the color passed in.
//
if (pal.cEntries())
{
if (crColor & 0x01000000)
{
crColor &= 0x0000FFFF;
if (crColor >= pal.cEntries())
crColor = 0;
}
else
{
crColor &= 0x00FFFFFF;
crColor = pal.ulGetNearestFromPalentry(*((PPALETTEENTRY) &crColor));
}
}
}
else
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
crColor = CLR_INVALID;
}
return((UINT) crColor);
}
/******************************Public*Routine******************************\
* GreAnimatePalette
*
* API function
*
* Returns: The number of logical palette entries animated, 0 for error.
*
* History:
* 17-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GreAnimatePalette(HPALETTE hpal, UINT ulStartIndex,
UINT ulNumEntries, CONST PALETTEENTRY *lpPaletteColors)
{
BOOL bReturn = FALSE;
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid())
{
bReturn = (BOOL) pal.ulAnimatePalette(ulStartIndex, ulNumEntries, lpPaletteColors);
}
return(bReturn);
}
/******************************Public*Routine******************************\
* GreGetPaletteEntries
*
* API function
*
* returns: 0 for failure, else number of entries retrieved.
*
* History:
* 18-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
UINT APIENTRY GreGetPaletteEntries(HPALETTE hpal, UINT ulStartIndex,
UINT ulNumEntries, LPPALETTEENTRY pRGB)
{
//
// Note on this call we can just let the default palette go through
// since it isn't getting modified, and the constructor is smart
// enough not to really lock it down.
//
EPALOBJ pal((HPALETTE) hpal);
if (!pal.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return(0);
}
return(pal.ulGetEntries(ulStartIndex, ulNumEntries, pRGB, FALSE));
}
/******************************Public*Routine******************************\
* GreSetPaletteEntries
*
* API function
*
* returns: 0 for failure, else number of entries retrieved.
*
* History:
* 18-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
UINT
GreSetPaletteEntries(
HPALETTE hpal,
UINT ulStartIndex,
UINT ulNumEntries,
CONST PALETTEENTRY *pRGB
)
{
//
// Note on this call we don't worry about STOCKOBJ_PAL because ulSetEntries
// won't let the default palette get modified.
//
UINT uiReturn = 0;
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid())
{
//
// You must grab the palette semaphore to touch the linked list of DC's.
//
SEMOBJ semo(ghsemPalette);
uiReturn = (UINT) pal.ulSetEntries(ulStartIndex, ulNumEntries, pRGB);
//
// Run down all the DC's for this palette.
// Set the flags to dirty the brushes, since we changed the palette!
//
{
MLOCKFAST mlo;
HDC hdcNext = pal.hdcHead();
while ( hdcNext != (HDC)0 )
{
MDCOBJA dco(hdcNext);
//
// WINBUG #55203 2-1-2000 bhouse Remove temporary fix to avoid AV when setting DIRTY_BRUSHES
// This is just a temp fix (since '95 hehehe) to keep
// this from doing an AV. Lingyun, making the
// brush flags all be in kernel memory will
// fix this.
//
// this should just be
// dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
//
if (GreGetObjectOwner((HOBJ)hdcNext,DC_TYPE) == W32GetCurrentPID())
{
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
}
else
{
dco.pdc->flbrushAdd(DIRTY_FILL);
}
hdcNext = dco.pdc->hdcNext();
}
}
}
return(uiReturn);
}
/******************************Public*Routine******************************\
* GreGetNearestColor
*
* This function returns the color that will be displayed on the device
* if a solid brush was created with the given colorref.
*
* History:
* Mon 29-Nov-1993 -by- Patrick Haluptzok [patrickh]
* Don't round the color on non-indexed devices
*
* 15-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
COLORREF APIENTRY GreGetNearestColor(HDC hdc, COLORREF crColor)
{
ULONG ulRet;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// Protect against dynamic mode changes while we go grunging
// around in the surface.
//
DEVLOCKOBJ dlo;
dlo.vLockNoDrawing(dco);
XEPALOBJ palDC(dco.ppal());
XEPALOBJ palSurf;
SURFACE *pSurf = dco.pSurfaceEff();
if ((dco.dctp() == DCTYPE_INFO) || (dco.dctp() == DCTYPE_DIRECT))
{
PDEVOBJ po(dco.hdev());
ASSERTGDI(po.bValid(), "ERROR GreGetNearestColor invalid PDEV\n");
palSurf.ppalSet(po.ppalSurf());
ASSERTGDI(palSurf.bValid(), "ERROR GreGetNearestColor invalid palDefault");
}
else
{
ASSERTGDI(dco.dctp() == DCTYPE_MEMORY, "Not a memory DC type");
palSurf.ppalSet(pSurf->ppal());
}
//
// if ICM translate the color to CMYK, just return the passed CMYK color.
//
if (dco.pdc->bIsCMYKColor())
{
ulRet = crColor;
}
else
{
if (((crColor & 0x01000000) == 0) &&
(palSurf.bValid() && !(palSurf.bIsIndexed())))
{
//
// Well if it isn't index it's RGB,BGR, or Bitfields.
// In any case to support Win3.1 we need to return exactly
// what was passed in otherwise they think we are a monochrome
// device. Bitfields could result is some messy rounding so
// it's more exact to just return the RGB passed in.
//
ulRet = crColor & 0x00FFFFFF; // mask off the highest byte
}
else
{
ulRet = ulIndexToRGB(palSurf, palDC, ulGetNearestIndexFromColorref(palSurf, palDC, crColor));
}
}
}
else
{
ulRet = CLR_INVALID;
}
return(ulRet);
}
/******************************Public*Routine******************************\
* GreGetSystemPaletteEntries
*
* API Function - copies out the range of palette entries from the DC's
* surface's palette.
*
* returns: number of entries retrieved from the surface palette, 0 for FAIL
*
* History:
* 15-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
UINT APIENTRY GreGetSystemPaletteEntries(HDC hdc, UINT ulStartIndex,
UINT ulNumEntries, PPALETTEENTRY pRGB)
{
UINT uiReturn = 0;
DCOBJ dco(hdc);
if (dco.bValid())
{
PDEVOBJ po(dco.hdev());
//
// Acquire the devlock while grunging in the surface palette to
// protect against dynamic mode changes.
//
DEVLOCKOBJ dlo(po);
if (po.bIsPalManaged())
{
XEPALOBJ palSurf(po.ppalSurf());
uiReturn = (UINT) palSurf.ulGetEntries(ulStartIndex, ulNumEntries,
pRGB, TRUE);
}
}
return(uiReturn);
}
/******************************Public*Routine******************************\
* GreGetSystemPaletteUse
*
* API function
*
* returns: SYSPAL_STATIC or SYSPAL_NOSTATIC, 0 for an error
*
* History:
* 15-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
UINT APIENTRY GreGetSystemPaletteUse(HDC hdc)
{
ULONG ulReturn = SYSPAL_ERROR;
DCOBJ dco(hdc);
if (dco.bValid())
{
PDEVOBJ po(dco.hdev());
//
// Acquire the devlock while grunging in the surface palette to
// protect against dynamic mode changes.
//
DEVLOCKOBJ dlo(po);
if (po.bIsPalManaged())
{
XEPALOBJ palSurf(po.ppalSurf());
if (palSurf.bIsNoStatic())
{
ulReturn = SYSPAL_NOSTATIC;
}
else if (palSurf.bIsNoStatic256())
{
ulReturn = SYSPAL_NOSTATIC256;
}
else
{
ulReturn = SYSPAL_STATIC;
}
}
}
return(ulReturn);
}
/******************************Public*Routine******************************\
* GreSetSystemPaletteUse
*
* API function - Sets the number of reserved entries if palette managed
*
* returns - the old flag for the palette, 0 for error
*
* History:
* 15-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
UINT APIENTRY GreSetSystemPaletteUse(HDC hdc, UINT ulUsage)
{
//
// Validate the parameters, Win3.1 sets the flag to static if it's invalid.
//
if ((ulUsage != SYSPAL_STATIC) && (ulUsage != SYSPAL_NOSTATIC) &&
(ulUsage != SYSPAL_NOSTATIC256))
ulUsage = SYSPAL_STATIC;
//
// Initialize return value.
//
ULONG ulReturn = SYSPAL_ERROR;
BOOL bPalChanged = FALSE;
ULONG i;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit. This also protects us
// from dynamic mode changes that change the 'bIsPalManaged'
// status.
//
PDEVOBJ po(dco.hdev());
DEVLOCKOBJ dlo(po);
XEPALOBJ palSurf(po.ppalSurf());
XEPALOBJ palDC(dco.ppal());
if (po.bIsPalManaged())
{
//
// The palette managed case.
//
{
//
// Protect access to the goodies in the system palette
// with the SEMOBJ. We don't want a realize happening
// while we fiddle flags.
//
SEMOBJ semo(ghsemPalette);
if (palSurf.bIsNoStatic())
{
ulReturn = SYSPAL_NOSTATIC;
}
else if (palSurf.bIsNoStatic256())
{
ulReturn = SYSPAL_NOSTATIC256;
}
else
{
ulReturn = SYSPAL_STATIC;
}
if (ulUsage == SYSPAL_STATIC)
{
//
// reset the colors from their original copy in the devinfo palette.
// The copy already has the flags properly set.
//
if (palSurf.bIsNoStatic() || palSurf.bIsNoStatic256())
{
//
// Change the palette that GDI manages, copy over up to
// 20 static colors from ppalDefault
//
XEPALOBJ palOriginal(ppalDefault);
ASSERTGDI(palOriginal.bValid(), "ERROR ulMakeStatic0");
ULONG ulNumReserved = palSurf.ulNumReserved() >> 1;
if (ulNumReserved > 10)
{
ulNumReserved = 10;
}
//
// set the beginning entries
//
for (i = 0; i < ulNumReserved; i++)
{
PALETTEENTRY palEntry = palOriginal.palentryGet(i);
palEntry.peFlags = PC_USED | PC_FOREGROUND;
palSurf.palentrySet(i,palEntry);
}
//
// set the ending entries
//
ULONG ulCurrentPal = palSurf.cEntries();
ULONG ulCurrentDef = 20;
for (i = 0; i < ulNumReserved; i++)
{
PALETTEENTRY palEntry;
ulCurrentPal--;
ulCurrentDef--;
palEntry = palOriginal.palentryGet(ulCurrentDef);
palEntry.peFlags = PC_USED | PC_FOREGROUND;
palSurf.palentrySet(ulCurrentPal,palEntry);
}
//
// Mark the brushes dirty for this DC.
//
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
palSurf.flPalSet(palSurf.flPal() & ~PAL_NOSTATIC & ~PAL_NOSTATIC256);
palSurf.vUpdateTime();
bPalChanged = TRUE;
}
}
else if (ulUsage == SYSPAL_NOSTATIC)
{
//
// unmark all the static colors, with the exception of black and
// white that stay with us.
//
for (i = 1; i < (palSurf.cEntries()-1); i++)
{
palSurf.apalColorGet()[i].pal.peFlags = 0;
}
palSurf.vSetNoStatic();
}
else //SYSPAL_NOSTATIC256
{
//
// unmark all the static colors
//
for (i = 0; i < (palSurf.cEntries()); i++)
{
palSurf.apalColorGet()[i].pal.peFlags = 0;
}
palSurf.vSetNoStatic256();
}
}
if (bPalChanged)
{
SEMOBJ so(po.hsemPointer());
if (!po.bDisabled())
{
po.pfnSetPalette()(
po.dhpdevParent(),
(PALOBJ *) &palSurf,
0,
0,
palSurf.cEntries());
}
}
}
}
return(ulReturn);
}
/******************************Public*Routine******************************\
* NtGdiResizePalette()
*
* API function
*
* returns: TRUE for success, FALSE for failure
*
* History:
* Tue 10-Sep-1991 -by- Patrick Haluptzok [patrickh]
* rewrite to be multi-threaded safe
*
* 19-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
#define PAL_MAX_SIZE 1024
BOOL
APIENTRY
NtGdiResizePalette(
HPALETTE hpal,
UINT cEntry
)
{
//
// Check for quick out before constructors
//
if ((cEntry > PAL_MAX_SIZE) || (cEntry == 0))
{
WARNING("GreResizePalette failed - invalid size\n");
return(FALSE);
}
BOOL bReturn = FALSE;
//
// Validate the parameter.
//
EPALOBJ palOld(hpal);
if ((palOld.bValid()) && (!palOld.bIsPalDefault()) && (palOld.bIsPalDC()))
{
//
// Create a new palette. Don't mark it to keep because after
// bSwap it will be palOld and we want it to be deleted.
//
PALMEMOBJ pal;
if (pal.bCreatePalette(PAL_INDEXED,
cEntry,
(PULONG) NULL,
0, 0, 0,
PAL_DC | PAL_FREE))
{
//
// Grab the palette semaphore which stops any palettes from being selected
// in or out. It protects the linked DC list, can't copy DC head until
// we hold it.
//
SEMOBJ semo(ghsemPalette);
//
// Copy the data from old palette.
//
pal.vCopyEntriesFrom(palOld);
pal.flPalSet(palOld.flPal());
pal.hdcHead(palOld.hdcHead());
pal.hdev(palOld.hdev());
pal.cRefhpal(palOld.cRefhpal());
pal.vComputeCallTables();
HDC hdcNext, hdcTemp;
MLOCKFAST mlo;
//
// Run down the list and exclusive lock all the handles.
//
{
hdcNext = pal.hdcHead();
while (hdcNext != (HDC) 0)
{
MDCOBJ dcoLock(hdcNext);
if (!dcoLock.bLocked())
{
WARNING1("ResizePalette failed because a DC the hpal is in is busy\n");
break;
}
hdcNext = dcoLock.pdc->hdcNext();
dcoLock.vDontUnlockDC();
}
}
if (hdcNext == (HDC) 0)
{
//
// We have the palette semaphore and all the DC's exclusively locked. Noone else
// can be accessing the translates because you must hold one of those things to
// access them. So we can delete the translates.
//
palOld.vMakeNoXlate();
palOld.vUpdateTime();
//
// Note that bSwap calls locked SpapHandle vesrion so the Hmgr Resource
// is required (luckily it was grabbed earlier).
//
//
// try to swap palettes, bSwap can only succedd if
// this routine owns the only locks on the objecs
//
bReturn = pal.bSwap((PPALETTE *) &palOld,1,1);
if (bReturn)
{
ASSERTGDI(bReturn, "ERROR no way");
//
// Run down all the DC's for this palette and update the pointer.
// Set the flags to dirty the brushes since we changed the palette.
//
{
hdcNext = pal.hdcHead();
while (hdcNext != (HDC)0)
{
MDCOBJA dcoAltLock(hdcNext);
dcoAltLock.pdc->ppal(palOld.ppalGet());
dcoAltLock.ulDirty(dcoAltLock.ulDirty() | DIRTY_BRUSHES);
hdcNext = dcoAltLock.pdc->hdcNext();
}
}
}
else
{
WARNING1("ResizePalette failed - ref count != 1\n");
}
}
else
{
WARNING1("ResizePalette failed lock of DC in chain\n");
}
//
// Unlock all the DC we have locked and return FALSE
//
{
hdcTemp = pal.hdcHead();
while (hdcTemp != hdcNext)
{
MDCOBJ dcoUnlock(hdcTemp);
ASSERTGDI(dcoUnlock.bLocked(), "ERROR couldn't re-lock to unlock");
DEC_EXCLUSIVE_REF_CNT(dcoUnlock.pdc);
hdcTemp = dcoUnlock.pdc->hdcNext();
}
}
}
else
{
WARNING("GreResizePalette failed palette creation\n");
}
}
else
{
WARNING("GreResizePalette failed invalid hpal\n");
}
return(bReturn);
}
/******************************Public*Routine******************************\
* GreUpdateColors
*
* API function - Updates the colors in the Visible Region for a Window on
* a palette mangaged device.
*
* This is an example of how UpdateColors is used:
*
* case WM_PALETTECHANGED:
*
* // if NTPAL was not responsible for palette change and if
* // palette realization causes a palette change, do a redraw.
*
* if ((HWND)wParam != hWnd)
* {
* if (bLegitDraw)
* {
* hDC = GetDC(hWnd);
* hOldPal = SelectPalette(hDC, hpalCurrent, 0);
*
* i = RealizePalette(hDC);
*
* if (i)
* {
* if (bUpdateColors)
* {
* UpdateColors(hDC);
* UpdateCount++;
* }
* else
* InvalidateRect(hWnd, (LPRECT) (NULL), 1);
* }
*
* SelectPalette(hDC, hOldPal, 0);
* ReleaseDC(hWnd, hDC);
* }
* }
* break;
*
* The hpal can only be selected into 1 type of device DC at a time.
* Xlates from the DC palette to the surface palette are only done on DC's
* that are for the PDEV surface. Since an hpal can only be selected into
* one of these and creation and deletion of the pxlate needs to be semaphored
* we use the PDEV semaphore to protect it's access.
*
* An xlate vector mapping the DC palette to the surface palette is created
* during a RealizePalette if the surface is a palette managed device. This
* is put in pxlate in the hpal. The old pxlate is moved into pxlateOld
* and the xlate in pxlateOld is deleted. UpdateColors works by looking at
* the difference between the current xlate mapping and the old xlate mapping
* and updating the pixels in the VisRgn to get a closest mapping.
*
* This API can only be called once for a palette. The old xlate is deleted
* during UpdateColors so that the next time it is called it will fail. This
* is because it only makes sense to update the pixels once. Doing it more
* than once would give ugly unpredictable results.
*
* History:
* 12-Dec-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL APIENTRY NtGdiUpdateColors(HDC hdc)
{
BOOL bReturn = FALSE;
DCOBJ dco(hdc);
if (!dco.bValidSurf())
{
return(FALSE);
}
PDEVOBJ pdo(dco.hdev());
//
// Grab DEVLOCK for output and to lock the surface
//
DEVLOCKOBJ dlo(dco);
if (pdo.bIsPalManaged())
{
SURFACE *pSurf = dco.pSurface();
//
// This only works on palette managed surfaces.
//
if (pSurf == pdo.pSurface())
{
XEPALOBJ palSurf(pSurf->ppal());
XEPALOBJ palDC(dco.ppal());
//
// Accumulate bounds. We can do this before knowing if the operation is
// successful because bounds can be loose.
//
if (dco.fjAccum())
dco.vAccumulate(dco.erclWindow());
if (dlo.bValid())
{
if ((palDC.ptransCurrent() != NULL) &&
(palDC.ptransOld() != NULL))
{
XLATEMEMOBJ xlo(palSurf, palDC);
if (xlo.bValid())
{
ECLIPOBJ co(dco.prgnEffRao(), dco.erclWindow());
//
// Check the destination which is reduced by clipping.
//
if (!co.erclExclude().bEmpty())
{
//
// Exclude the pointer.
//
DEVEXCLUDEOBJ dxo(dco,&co.erclExclude(),&co);
//
// Inc the target surface uniqueness
//
INC_SURF_UNIQ(pSurf);
if (!pdo.bMetaDriver())
{
//
// Dispatch the call. Give it no mask.
//
bReturn = (*PPFNGET(pdo, CopyBits, pSurf->flags())) (
pSurf->pSurfobj(),
pSurf->pSurfobj(),
&co,
xlo.pxlo(),
(RECTL *) &co.erclExclude(),
(POINTL *) &co.erclExclude());
}
else
{
//
// Dispatch to DDML.
//
bReturn = MulUpdateColors(
pSurf->pSurfobj(),
&co,
xlo.pxlo());
}
}
else
bReturn = TRUE;
}
}
else
bReturn = TRUE; // Nothing to update
}
else
{
bReturn = dco.bFullScreen();
}
}
}
return(bReturn);
}
/******************************Public*Routine******************************\
* RealizeDefaultPalette
*
* Take away colors that have been realized by other Windows. Reset it to
* state where no colors have been taken. Return number of colors
*
* History:
* 07-Jan-1993 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
extern "C"
ULONG GreRealizeDefaultPalette(
HDC hdcScreen,
BOOL bClearDefaultPalette)
{
DCOBJ dco(hdcScreen);
if (dco.bValid())
{
PDEVOBJ po(dco.hdev());
//
// Block out the GreRealizePalette code. Also protect us from
// dynamic mode changes while we grunge in the surface palette.
//
DEVLOCKOBJ dlo(po);
SEMOBJ semo(ghsemPalette);
if (po.bIsPalManaged())
{
XEPALOBJ palSurf(po.ppalSurf());
ASSERTGDI(palSurf.bIsPalManaged(), "GreRealizeDefaultPalette");
//
// Now map back to static colors if necesary. Win3.1 does not do this but we do
// just in case naughty app died and left the palette hosed.
//
//
if (palSurf.bIsNoStatic() || palSurf.bIsNoStatic256())
{
GreSetSystemPaletteUse(hdcScreen, SYSPAL_STATIC);
}
//
// Get rid of the PC_FOREGROUND flag from the non-reserved entries.
//
ULONG ulTemp = palSurf.ulNumReserved() >> 1;
ULONG ulMax = palSurf.cEntries() - ulTemp;
for (; ulTemp < ulMax; ulTemp++)
{
palSurf.apalColorGet()[ulTemp].pal.peFlags &= (~PC_FOREGROUND);
}
if (bClearDefaultPalette)
{
hForePalette = NULL;
}
palSurf.vUpdateTime();
//
// Mark the brushes dirty.
//
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
}
}
else
{
WARNING("ERROR User called RealizeDefaultPalette with bad hdc\n");
}
//
// What should this return value be ?
//
return(0);
}
/******************************Public*Routine******************************\
* UnrealizeObject
*
* Resets a logical palette.
*
* History:
* 16-May-1993 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL GreUnrealizeObject(HANDLE hpal)
{
BOOL bReturn = FALSE;
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid())
{
//
// You must grab the palette semaphore to access the translates.
//
SEMOBJ semo(ghsemPalette);
if (pal.ptransFore() != NULL)
{
pal.ptransFore()->iUniq = 0;
}
if (pal.ptransCurrent() != NULL)
{
pal.ptransCurrent()->iUniq = 0;
}
bReturn = TRUE;
}
return(bReturn);
}
/******************************Public*Routine******************************\
* GreRealizePalette
*
* Re-written to be Win3.1 compatible.
*
* History:
* 22-Nov-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
extern "C" DWORD GreRealizePalette(HDC hdc)
{
ULONG nTransChanged = 0;
ULONG nPhysChanged = 0;
DCOBJ dco(hdc);
if (dco.bValid())
{
PDEVOBJ po(dco.hdev());
//
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit. This also protects us
// from dynamic mode changes that change the 'bIsPalManaged'
// status.
//
DEVLOCKOBJ dlo(po);
XEPALOBJ palSurf(po.ppalSurf());
XEPALOBJ palDC(dco.ppal());
HPALETTE hpalDC = palDC.hpal();
HDC hdcNext, hdcTemp;
if (po.bIsPalManaged())
{
ASSERTGDI(palSurf.bIsPalManaged(), "GreRealizePalette");
//
// Access to the ptrans and the fields of the hpal are protected by
// this semaphore.
//
SEMOBJ semo(ghsemPalette);
if ((SAMEHANDLE(hpalDC,hForePalette)) ||
((dco.pdc->iGraphicsMode() == GM_COMPATIBLE) &&
(SAMEINDEX(hpalDC, hForePalette)) &&
(hForePID == W32GetCurrentProcess())))
{
//
// Check for early out.
//
if (palDC.bIsPalDefault())
{
//
// Do nothing.
//
PAL_DEBUG(2,"DC has default palette quick out\n");
}
else
{
if ((palDC.ptransFore() != NULL) &&
(palDC.ptransFore() == palDC.ptransCurrent()) &&
(palDC.ptransFore()->iUniq == palSurf.ulTime()))
{
//
// Everything is valid.
//
PAL_DEBUG(2,"ptransCurrent == ptransFore quick out\n");
}
else
{
MLOCKFAST mlo;
//
// Run down the list and exclusive lock all the handles.
//
{
hdcNext = palDC.hdcHead();
while (hdcNext != (HDC) 0)
{
MDCOBJ dcoLock(hdcNext);
if (!dcoLock.bLocked())
{
WARNING1("GreRealizePalette failed because a DC the hpal is in is busy\n");
break;
}
dcoLock.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
hdcNext = dcoLock.pdc->hdcNext();
dcoLock.vDontUnlockDC();
}
}
if (hdcNext == (HDC) 0)
{
//
// Get rid of the old mapping, it is useless now.
//
if (palDC.ptransOld())
{
if (palDC.ptransOld() != palDC.ptransFore())
VFREEMEM(palDC.ptransOld());
palDC.ptransOld(NULL);
}
//
// Check if we have stale translates.
// UnrealizeObject and SetPaletteEntries can cause it.
//
if ((palDC.ptransFore()) && (palDC.ptransFore()->iUniq == 0))
{
if (palDC.ptransCurrent() != palDC.ptransFore())
VFREEMEM(palDC.ptransFore());
palDC.ptransFore(NULL);
}
//
// Check if we need a new foreground realization.
//
if (palDC.ptransFore() == NULL)
{
//
// Need to force ourselves in for the first time.
//
PAL_DEBUG(2,"Creating a foreground realization\n");
palDC.ptransFore(ptransMatchAPal(dco.pdc,palSurf, palDC, TRUE, &nPhysChanged, &nTransChanged));
if (palDC.ptransFore() == NULL)
{
WARNING("RealizePalette failed initial foreground realize\n");
}
}
else
{
//
// Foreground Realize already done and isn't stale.
// Force the foreground mapping into the physical palette.
//
PAL_DEBUG(2,"Forcing a foreground realization in to palette\n");
vMatchAPal(dco.pdc,palSurf, palDC, &nPhysChanged, &nTransChanged);
}
palDC.ptransOld(palDC.ptransCurrent());
palDC.ptransCurrent(palDC.ptransFore());
}
else
{
WARNING("GreRealizePalette failed to lock down all DC's in linked list\n");
}
//
// Unlock all the DC we have locked.
//
{
hdcTemp = palDC.hdcHead();
while (hdcTemp != hdcNext)
{
MDCOBJ dcoUnlock(hdcTemp);
ASSERTGDI(dcoUnlock.bLocked(), "ERROR couldn't re-lock to unlock");
DEC_EXCLUSIVE_REF_CNT(dcoUnlock.pdc);
hdcTemp = dcoUnlock.pdc->hdcNext();
}
}
}
}
}
else
{
//
// We are a background palette.
//
if (!palDC.bIsPalDefault())
{
//
// Check for the quick out.
//
if ((palDC.ptransCurrent() != NULL) &&
(palDC.ptransCurrent()->iUniq == palSurf.ulTime()))
{
//
// Well it's good enough. Nothing has changed that
// would give us any better mapping.
//
PAL_DEBUG(2,"ptransCurrent not foreground but good enough\n");
}
else
{
MLOCKFAST mlo;
//
// Run down the list and exclusive lock all the handles.
//
{
hdcNext = palDC.hdcHead();
while (hdcNext != (HDC) 0)
{
MDCOBJ dcoLock(hdcNext);
if (!dcoLock.bLocked())
{
WARNING1("GreRealizePalette failed because a DC the hpal is in is busy\n");
break;
}
dcoLock.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
hdcNext = dcoLock.pdc->hdcNext();
dcoLock.vDontUnlockDC();
}
}
if (hdcNext == (HDC) 0)
{
//
// We have work to do, get rid of the old translate.
//
if (palDC.ptransOld())
{
if (palDC.ptransOld() != palDC.ptransFore())
VFREEMEM(palDC.ptransOld());
palDC.ptransOld(NULL);
}
//
// Check if we have stale translates.
// UnrealizeObject and SetPaletteEntries can cause it.
//
if ((palDC.ptransFore()) && (palDC.ptransFore()->iUniq == 0))
{
if (palDC.ptransCurrent() != palDC.ptransFore())
{
VFREEMEM(palDC.ptransFore());
}
palDC.ptransFore(NULL);
}
//
// Check for initial foreground realization.
//
PAL_DEBUG(2,"Realizing in the background\n");
if (palDC.ptransFore() == NULL)
{
//
// Create a scratch pad to establish a foreground realize.
//
PAL_DEBUG(2,"Making ptransFore in the background\n");
PALMEMOBJ palTemp;
if (palTemp.bCreatePalette(PAL_INDEXED,
palSurf.cEntries(),
NULL,
0, 0, 0, PAL_MANAGED))
{
ULONG ulTemp = 0;
ASSERTGDI(palTemp.cEntries() == 256, "ERROR palTemp invalid");
palTemp.vCopyEntriesFrom(palSurf);
palTemp.ulNumReserved(palSurf.ulNumReserved());
palTemp.flPalSet(palSurf.flPal());
palTemp.vComputeCallTables();
PAL_DEBUG(2,"Need to make a foreground realize first\n");
//
// Need to map ourselves for the first time. This actually doesn't
// change the current surface palette but instead computes the
// translate vector that would result if it was to be mapped in now.
//
palDC.ptransFore(ptransMatchAPal(dco.pdc,palTemp, palDC, TRUE, &ulTemp, &ulTemp));
}
#if DBG
if (palDC.ptransFore() == NULL)
{
WARNING("RealizePalette failed initial foreground realize\n");
}
#endif
}
//
// Save the Current mapping into Old.
//
palDC.ptransOld(palDC.ptransCurrent());
if (palDC.ptransFore() == NULL)
{
//
// The Current can't be set if the Fore
// is NULL so we're done.
//
palDC.ptransCurrent(NULL);
}
else
{
//
// Get the new Current mapping.
//
PAL_DEBUG(2,"Making ptransCurrent\n");
palDC.ptransCurrent(ptransMatchAPal(dco.pdc,palSurf, palDC, FALSE, &nPhysChanged, &nTransChanged));
if (palDC.ptransCurrent() == NULL)
{
//
// Well we can't have the foreground set
// and the current being NULL so just
// make it foreground for this memory
// failure case.
//
palDC.ptransCurrent(palDC.ptransFore());
WARNING("ptransCurrent failed allocation in RealizePalette");
}
}
}
//
// Unlock all the DC we have locked.
//
{
hdcTemp = palDC.hdcHead();
while (hdcTemp != hdcNext)
{
MDCOBJ dcoUnlock(hdcTemp);
ASSERTGDI(dcoUnlock.bLocked(), "ERROR couldn't re-lock to unlock");
DEC_EXCLUSIVE_REF_CNT(dcoUnlock.pdc);
hdcTemp = dcoUnlock.pdc->hdcNext();
}
}
}
}
}
}
//
// Check if the device needs to be notified.
//
if (nPhysChanged)
{
//
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit.
//
GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
GreEnterMonitoredSection(po.ppdev, WD_DEVLOCK);
{
SEMOBJ so(po.hsemPointer());
if (!po.bDisabled())
{
po.pfnSetPalette()(
po.dhpdevParent(),
(PALOBJ *) &palSurf,
0,
0,
palSurf.cEntries());
}
}
GreExitMonitoredSection(po.ppdev, WD_DEVLOCK);
GreReleaseSemaphoreEx(po.hsemDevLock());
//
// mark palsurf if it is a halftone palette
//
if (palSurf.cEntries() == 256)
{
ULONG ulIndex;
for (ulIndex=0;ulIndex<256;ulIndex++)
{
if (
(palSurf.ulEntryGet(ulIndex) & 0xffffff) !=
(aPalHalftone[ulIndex].ul & 0xffffff)
)
{
break;
}
}
if (ulIndex == 256)
{
palSurf.flPal(PAL_HT);
}
else
{
FLONG fl = palSurf.flPal();
fl &= ~PAL_HT;
palSurf.flPalSet(fl);
}
}
}
}
return(nTransChanged | (nPhysChanged << 16));
}
/******************************Public*Routine******************************\
* IsDCCurrentPalette
*
* Returns TRUE if the palette is the foreground palette.
*
* History:
* 18-May-1993 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
extern "C" BOOL IsDCCurrentPalette(HDC hdc)
{
BOOL bReturn = FALSE;
DCOBJ dco(hdc);
if (dco.bValid())
{
if ((SAMEHANDLE(dco.hpal(), (HPAL)hForePalette)) ||
((dco.pdc->iGraphicsMode() == GM_COMPATIBLE) &&
(SAMEINDEX(dco.hpal(), hForePalette)) &&
(hForePID == W32GetCurrentProcess())))
{
bReturn = TRUE;
}
}
return(bReturn);
}
/******************************Public*Routine******************************\
* GreSelectPalette
*
* API function for selecting palette into the DC.
*
* Returns previous hpal if successful, (HPALETTE) 0 for failure.
*
* History:
* 17-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
extern "C"
HPALETTE GreSelectPalette(
HDC hdc,
HPALETTE hpalNew,
BOOL bForceBackground)
{
//
// The palette semaphore serializes access to the reference count and
// the linked list of DC's a palette is selected into. We don't want
// 2 people trying to select at the same time. We must hold this between
// the setting of the hsem and the incrementing of the reference count.
//
SEMOBJ semo(ghsemPalette);
//
// Validate and lock down the DC and new palette.
//
DCOBJ dco(hdc);
EPALOBJ palNew(hpalNew);
#if DBG
if (DbgPal >= 2)
{
DbgPrint("GreSelectPalette %p\n",palNew.ppalGet());
}
#endif
if ((!dco.bLocked()) ||
(!palNew.bValid())|| (!palNew.bIsPalDC()))
{
//
// Error code logged by failed lock.
//
WARNING1("GreSelectPalette failed, invalid palette or DC\n");
return((HPALETTE)NULL);
}
if (!bForceBackground)
{
hForePID = W32GetCurrentProcess();
hForePalette = hpalNew;
}
HPAL hpalOld = (HPAL) dco.hpal();
if (SAMEHANDLE(hpalOld,(HPAL)hpalNew))
{
return((HPALETTE)hpalOld);
}
PDEVOBJ po(dco.hdev());
XEPALOBJ palOld(dco.ppal());
//
// Check that we aren't trying to select the palette into a
// device incompatible with a type we are already selected into.
// We need to be able to translate from the DC hpal to the surface hpal
// to do Animate, ect. So we can only be selected into one
// surface with a PAL_MANAGED hpal because we only maintain one
// translate table in the DC hpal.
//
if (!palNew.bIsPalDefault())
{
if (!palNew.bSet_hdev(dco.hdev()))
{
WARNING("GreSelectPalette failed hsemDisplay check\n");
return((HPALETTE)NULL);
}
}
//
// Grab the multi-lock semaphore to run the DC link list.
//
MLOCKFAST mlo;
//
// Take care of the old hpal. Remove from linked list. Decrement cRef.
// Remove the hdc from the linked list of DC's associated with palette.
//
palOld.vRemoveFromList(dco);
//
// Set the new palette in so the old hpal is truly gone.
//
dco.pdc->hpal((HPAL)hpalNew);
dco.pdc->ppal(palNew.ppalGet());
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
//
// Associate the palette with the bitmap for use when converting DDBs
// to DIBs for dynamic mode changes. We don't associate the default
// palette because the normal usage pattern is:
//
// hpalOld = SelectPalette(hdc, hpal);
// RealizePalette(hdc);
// BitBlt(hdc);
// SelectPalette(hdc, hpalOld);
//
if ((dco.bHasSurface()) && (!palNew.bIsPalDefault()))
{
dco.pSurface()->hpalHint(hpalNew);
}
//
// Take care of the new hpal.
//
palNew.vAddToList(dco);
return((HPALETTE)hpalOld);
}
/******************************Public*Routine******************************\
* ulMagicFind - look for given magic color in default palette
*
* Arguments:
*
* clrMagic - COLORREF of color to search for
*
* Return Value:
*
* Index if found, 0xffffffff if not found.
*
* History:
*
* 15-Nov-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
ULONG
ulMagicFind(
PALETTEENTRY peMagic
)
{
XEPALOBJ xePalDefault(ppalDefault);
return(xePalDefault.ulGetMatchFromPalentry(peMagic));
}
/******************************Public*Routine******************************\
* bSetMagicColor - set the specified magic color in both the device
* palette and the default palette
*
* Arguments:
*
* hdev - hdev
* Index - magic color index (8,9,246,247)
* palSurf - surface palette
* palDC - logical palette
* palColor - magic color
*
* Return Value:
*
* Status
*
* History:
*
* 15-Nov-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
extern PPALETTE gppalHalftone;
BOOL
bSetMagicColor(
XEPALOBJ palSurf,
ULONG ulIndex,
PAL_ULONG PalEntry
)
{
BOOL bRet = FALSE;
ASSERTGDI(((ulIndex == 8) || (ulIndex == 9) || (ulIndex == 246) || (ulIndex == 247)),
"bSetMagicColor Error, wrong palette index");
//
// make sure there are 20 reserved entries, and the static
// colors are in use
//
if (
(palSurf.ulNumReserved() == 20) &&
(!palSurf.bIsNoStatic()) &&
(!palSurf.bIsNoStatic256())
)
{
//
// set the entrie in the surface palette
//
PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED;
palSurf.ulEntrySet(ulIndex,PalEntry.ul);
//
// update the palette time stamp
//
palSurf.vUpdateTime();
//
// set colors in the defaukt halftone palette for multimon system
//
if (gppalHalftone)
{
XEPALOBJ palHalftone(gppalHalftone);
palHalftone.ulEntrySet(ulIndex,PalEntry.ul);
}
//
// offset to upper half of default palette if needed
//
if (ulIndex > 10)
{
ulIndex = ulIndex - 236;
}
PalEntry.pal.peFlags = 0;
//
// set colors in the default Logical palette.
//
logDefaultPal.palPalEntry[ulIndex] = PalEntry.pal;
//
// set colors in the default palette and default log palette
//
XEPALOBJ palDefault(ppalDefault);
palDefault.ulEntrySet(ulIndex,PalEntry.ul);
bRet = TRUE;
}
return(bRet);
}
/******************************Public*Routine******************************\
* vResetSurfacePalette - copy the magic colors from the default palette
* to the surface palette, and call the driver to set the palette
*
* NOTE: The devlock and pointer semaphore must already be held!
*
* Arguments:
*
* po - PDEV object
* palSurf - surface palette
*
* Return Value:
*
* Status
*
* History:
*
* 21-Mar-1996 -by- J. Andrew Goossen [andrewgo]
*
\**************************************************************************/
VOID
vResetSurfacePalette(
HDEV hdev
)
{
PDEVOBJ po(hdev);
if (po.bIsPalManaged())
{
XEPALOBJ palSurf(po.ppalSurf());
ASSERTGDI(palSurf.bValid(), "Invalid surface palette");
if (
(palSurf.ulNumReserved() == 20) &&
(!palSurf.bIsNoStatic()) &&
(!palSurf.bIsNoStatic256())
)
{
PAL_ULONG PalEntry;
XEPALOBJ palDefault(ppalDefault);
//
// set the entries in the surface palette
//
PalEntry.pal = palDefault.palentryGet(8);
PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED;
palSurf.ulEntrySet(8,PalEntry.ul);
PalEntry.pal = palDefault.palentryGet(9);
PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED;
palSurf.ulEntrySet(9,PalEntry.ul);
PalEntry.pal = palDefault.palentryGet(246 - 236);
PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED;
palSurf.ulEntrySet(246,PalEntry.ul);
PalEntry.pal = palDefault.palentryGet(247 - 236);
PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED;
palSurf.ulEntrySet(247,PalEntry.ul);
}
if (!po.bDisabled())
{
(*PPFNDRV(po,SetPalette))(
po.dhpdev(),
(PALOBJ *) &palSurf,
0,
0,
palSurf.cEntries());
}
}
}
/******************************Public*Routine******************************\
*
* GreSetMagicColor win95 compatible: set surface and default palette
* "magic" entries. This changes the default palette,
* and will affect bitmaps that think they have the
* correct 20 default colors already...
*
* Arguments:
*
* hdc - DC, specifies device surface
* Index - magic index, 1 of 8,9,246,247
* peMagic - new color
*
* Return Value:
*
* Status
*
* History:
*
* 10-Nov-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
NtGdiSetMagicColors(
HDC hdc,
PALETTEENTRY peMagic,
ULONG Index
)
{
return(GreSetMagicColors(hdc,peMagic,Index));
}
BOOL
GreSetMagicColors(
HDC hdc,
PALETTEENTRY peMagic,
ULONG Index
)
{
DCOBJ dco(hdc);
BOOL bRet = FALSE;
BOOL bPaletteChange = FALSE;
BOOL bChildDriver = FALSE;
if (dco.bValid())
{
if (
(Index == 8) ||
(Index == 9) ||
(Index == 246) ||
(Index == 247)
)
{
PAL_ULONG PalEntry;
PalEntry.pal = peMagic;
//
// must be RGB or PALETTERGB
//
if (
((PalEntry.ul & 0xff000000) == 0) ||
((PalEntry.ul & 0xff000000) == 0x02000000)
)
{
PDEVOBJ po(dco.hdev());
BOOL bSetColor = FALSE;
//
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit. Plus it also protects
// us from a dynamic mode change, which can change the
// bIsPalManaged status.
//
DEVLOCKOBJ dlo(po);
if (po.bIsPalManaged())
{
bSetColor = TRUE;
}
else if (po.bMetaDriver())
{
//
// If this is meta-driver, check if there is any palette device
//
PVDEV pvdev = (VDEV*) po.dhpdev();
PDISPSURF pds = pvdev->pds;
LONG csurf = pvdev->cSurfaces;
do
{
po.vInit(pds->hdev);
if (po.bIsPalManaged())
{
bSetColor = TRUE;
bChildDriver = TRUE;
break;
}
pds = pds->pdsNext;
} while (--csurf);
}
if (bSetColor)
{
XEPALOBJ palSurf(po.ppalSurf());
//
// palette sem scope
//
{
SEMOBJ semPalette(ghsemPalette);
//
// look for color
//
ULONG ulMagicIndex = ulMagicFind(PalEntry.pal);
if (ulMagicIndex != 0xffffffff)
{
//
// found exact match
//
if (ulMagicIndex >= 10)
{
//
// the returned index must be adjusted for surface palette
//
ulMagicIndex += 236;
}
if (ulMagicIndex == Index)
{
if (bChildDriver)
{
// If this is child of meta driver, we still need to call
// driver to update palette. (in the ppalDefault, doesn't
// mean in the child surface palette).
//
// set magic color
//
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry);
bRet = bPaletteChange;
}
else
{
//
// already set
//
bRet = TRUE;
}
}
else
{
//
// make sure RGB is not a non-magic VGA color,
// if there is a match, it can only be a magic
// color
//
if (
(ulMagicIndex == 8) ||
(ulMagicIndex == 9) ||
(ulMagicIndex == 246) ||
(ulMagicIndex == 247)
)
{
//
// set magic color
//
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry);
bRet = bPaletteChange;
}
else
{
//
// bad rgb, restore Index with
// default color
//
if (Index == 8)
{
PalEntry.ul = 0x00C0DCC0;
}
else if (Index == 9)
{
PalEntry.ul = 0x00F0CAA6;
}
else if (Index == 246)
{
PalEntry.ul = 0x00F0FBFF;
}
else
{
PalEntry.ul = 0x00A4A0A0;
}
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry);
bRet = FALSE;
}
}
}
else
{
//
// set magic color
//
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry);
bRet = bPaletteChange;
}
}
if (bPaletteChange)
{
SEMOBJ so(po.hsemPointer());
if (!po.bDisabled())
{
po.pfnSetPalette()(
po.dhpdevParent(),
(PALOBJ *) &palSurf,
0,
0,
palSurf.cEntries());
}
}
}
}
}
}
return(bRet);
}