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.
 
 
 
 
 
 

3911 lines
108 KiB

/******************Module*Header********************************************\
* Module Name: dcquery.c *
* *
* Client side stubs for functions that query the DC in the server. *
* *
* Created: 05-Jun-1991 01:43:56 *
* Author: Charles Whitmer [chuckwh] *
* *
* Copyright (c) 1991-1999 Microsoft Corporation *
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#if DBG
FLONG gflDebug = 0;
#endif
// This macro retrieves the current code page, carefully masking off the
// charset:
#define GET_CODE_PAGE(hdc,pDcAttr) \
((!(pDcAttr->ulDirty_ & DIRTY_CHARSET) ? pDcAttr->iCS_CP \
: NtGdiGetCharSet(hdc)) & 0xffff)
BOOL bIsDBCSString(LPCSTR psz, int cc);
/******************************Public*Routine******************************\
* vOutlineTextMetricWToOutlineTextMetricA
*
* Convert from OUTLINETEXTMETRICA (ANSI structure) to OUTLINETEXTMETRICW
* (UNICODE structure).
*
* Note:
* This function is capable of converting in place (in and out buffers
* can be the same).
*
* Returns:
* TTRUE if successful, FALSE otherwise.
*
* History:
* 02-Mar-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID vOutlineTextMetricWToOutlineTextMetricA (
LPOUTLINETEXTMETRICA potma,
OUTLINETEXTMETRICW * potmw,
TMDIFF * ptmd
)
{
// Size.
potma->otmSize = potmw->otmSize;
// Convert the textmetrics.
vTextMetricWToTextMetricStrict(
&potma->otmTextMetrics,
&potmw->otmTextMetrics);
potma->otmTextMetrics.tmFirstChar = ptmd->chFirst;
potma->otmTextMetrics.tmLastChar = ptmd->chLast;
potma->otmTextMetrics.tmDefaultChar = ptmd->chDefault;
potma->otmTextMetrics.tmBreakChar = ptmd->chBreak;
// for Win 64 we need to copy these fields one by one due to alignement difference
potma->otmFiller = potmw->otmFiller;
potma->otmPanoseNumber = potmw->otmPanoseNumber;
potma->otmfsSelection = potmw->otmfsSelection;
potma->otmfsType = potmw->otmfsType;
potma->otmsCharSlopeRise = potmw->otmsCharSlopeRise;
potma->otmsCharSlopeRun = potmw->otmsCharSlopeRun;
potma->otmItalicAngle = potmw->otmItalicAngle;
potma->otmEMSquare = potmw->otmEMSquare;
potma->otmAscent = potmw->otmAscent;
potma->otmDescent = potmw->otmDescent;
potma->otmLineGap = potmw->otmLineGap;
potma->otmsCapEmHeight = potmw->otmsCapEmHeight;
potma->otmsXHeight = potmw->otmsXHeight;
potma->otmrcFontBox = potmw->otmrcFontBox;
potma->otmMacAscent = potmw->otmMacAscent;
potma->otmMacDescent = potmw->otmMacDescent;
potma->otmMacLineGap = potmw->otmMacLineGap;
potma->otmusMinimumPPEM = potmw->otmusMinimumPPEM;
potma->otmptSubscriptSize = potmw->otmptSubscriptSize;
potma->otmptSubscriptOffset = potmw->otmptSubscriptOffset;
potma->otmptSuperscriptSize = potmw->otmptSuperscriptSize;
potma->otmptSuperscriptOffset = potmw->otmptSuperscriptOffset;
potma->otmsStrikeoutSize = potmw->otmsStrikeoutSize;
potma->otmsStrikeoutPosition = potmw->otmsStrikeoutPosition;
potma->otmsUnderscoreSize = potmw->otmsUnderscoreSize;
potma->otmsUnderscorePosition = potmw->otmsUnderscorePosition;
// set the offsets to zero for now, this will be changed later if
// the caller wanted strings as well
potma->otmpFamilyName = NULL;
potma->otmpFaceName = NULL;
potma->otmpStyleName = NULL;
potma->otmpFullName = NULL;
}
/******************************Public*Routine******************************\
*
* vGenerateANSIString
*
* Effects: Generates Ansi string which consists of consecutive ansi chars
* [iFirst, iLast] inclusive. The string is stored in the buffer
* puchBuf that the user must ensure is big enough
*
*
*
* History:
* 24-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID vGenerateAnsiString(UINT iFirst, UINT iLast, PUCHAR puchBuf)
{
// Generate string (terminating NULL not needed).
ASSERTGDI((iFirst <= iLast) && (iLast < 256), "gdi!_vGenerateAnsiString\n");
for ( ; iFirst <= iLast; iFirst++)
*puchBuf++ = (UCHAR) iFirst;
}
/******************************Public*Routine******************************\
*
* bSetUpUnicodeString
*
* Effects:
*
* Warnings:
*
* History:
* 25-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bSetUpUnicodeString(
IN UINT iFirst, // first ansi char
IN UINT iLast, // last char
IN PUCHAR puchTmp, // buffer for an intermediate ansi string
OUT PWCHAR pwc, // output fuffer with a unicode string
IN UINT dwCP // ansi codepage
)
{
UINT c = iLast - iFirst + 1;
vGenerateAnsiString(iFirst,iLast,puchTmp);
return MultiByteToWideChar(
dwCP, 0,
puchTmp,c,
pwc, c*sizeof(WCHAR));
}
/******************************Public*Routine******************************\
* GetAspectRatioFilterEx *
* GetBrushOrgEx *
* *
* Client side stubs which all get mapped to GetPoint. *
* *
* Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] *
* Wrote them. *
\**************************************************************************/
BOOL APIENTRY GetAspectRatioFilterEx(HDC hdc,LPSIZE psizl)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetDCPoint(hdc,DCPT_ASPECTRATIOFILTER,(PPOINTL) psizl));
}
BOOL APIENTRY GetBrushOrgEx(HDC hdc,LPPOINT pptl)
{
BOOL bRet = FALSE;
PDC_ATTR pdcattr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
if ((pdcattr != NULL) && (pptl != (LPPOINT)NULL))
{
*pptl = *((LPPOINT)&pdcattr->ptlBrushOrigin);
bRet = TRUE;
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
}
return(bRet);
}
BOOL APIENTRY GetDCOrgEx(HDC hdc,LPPOINT pptl)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetDCPoint(hdc,DCPT_DCORG,(PPOINTL)pptl));
}
// The old GetDCOrg is here because it was in the Beta and we are afraid
// to remove it now. It would be nice to remove it.
DWORD APIENTRY GetDCOrg(HDC hdc)
{
hdc;
return(0);
}
/******************************Public*Routine******************************\
* Client side stub for GetCurrentPositionEx.
*
* Wed 02-Sep-1992 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCurrentPositionEx(HDC hdc,LPPOINT pptl)
{
BOOL bRet = FALSE;
PDC_ATTR pDcAttr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if ((pDcAttr) && (pptl != (LPPOINT)NULL))
{
bRet = TRUE;
if (pDcAttr->ulDirty_ & DIRTY_PTLCURRENT)
{
// If the logical-space version of the current position is invalid,
// then the device-space version of the current position is
// guaranteed to be valid. So we can reverse the current transform
// on that to compute the logical-space version:
*((POINTL*)pptl) = pDcAttr->ptfxCurrent;
pptl->x = FXTOL(pptl->x);
pptl->y = FXTOL(pptl->y);
bRet = DPtoLP(hdc,pptl,1);
if (bRet)
{
pDcAttr->ptlCurrent = *((POINTL*)pptl);
pDcAttr->ulDirty_ &= ~DIRTY_PTLCURRENT;
}
}
else
{
*((POINTL*)pptl) = pDcAttr->ptlCurrent;
}
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
}
return(bRet);
}
/******************************Public*Routine******************************\
* GetPixel *
* *
* Client side stub. *
* *
* Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
DWORD APIENTRY GetPixel(HDC hdc,int x,int y)
{
PDC_ATTR pdca;
COLORREF ColorRet = CLR_INVALID;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
if (pdca)
{
//
// if the color is not a PaletteIndex and
// ICM is on then translate
//
ColorRet = NtGdiGetPixel(hdc,x,y);
if ( bNeedTranslateColor(pdca)
&&
( IS_32BITS_COLOR(pdca->lIcmMode)
||
((ColorRet != CLR_INVALID) &&
!(ColorRet & 0x01000000))
)
)
{
//
// translate back color to original.
//
COLORREF NewColor;
BOOL bStatus = IcmTranslateCOLORREF(hdc,
pdca,
ColorRet,
&NewColor,
ICM_BACKWARD);
if (bStatus)
{
ColorRet = NewColor;
}
}
}
return(ColorRet);
}
/******************************Public*Routine******************************\
* GetDeviceCaps
*
* We store the device caps for primary display dc and its compatible memory dcs
* in the shared handle table.
*
* for printer dcs and meta dcs, we cache the dev info in the LDC structure.
*
* Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh]
* Wrote it.
\**************************************************************************/
int APIENTRY GetDeviceCaps(HDC hdc,int iCap)
{
BOOL bRet = FALSE;
PDEVCAPS pCachedDevCaps = NULL;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
// For the 16-bit metafile DC, returns only technology. return 0 for win3.1 compat.
if (IS_METADC16_TYPE(hdc))
return(iCap == TECHNOLOGY ? DT_METAFILE : 0);
DC_PLDC(hdc,pldc,bRet);
if (!(pldc->fl & LDC_CACHED_DEVCAPS))
{
bRet = NtGdiGetDeviceCapsAll (hdc, &pldc->DevCaps);
if (bRet)
{
pCachedDevCaps = &pldc->DevCaps;
pldc->fl |= LDC_CACHED_DEVCAPS;
}
}
else
{
pCachedDevCaps = &pldc->DevCaps;
bRet = TRUE;
}
}
else
{
PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr)
{
ULONG fl = pDcAttr->ulDirty_;
if (!(fl & DC_PRIMARY_DISPLAY))
{
return(NtGdiGetDeviceCaps(hdc,iCap));
}
else
{
pCachedDevCaps = pGdiDevCaps;
bRet = TRUE;
}
}
}
if (!bRet)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
// actual code - copied from gre\miscgdi.cxx
switch (iCap)
{
case DRIVERVERSION: // Version = 0100h for now
return(pCachedDevCaps->ulVersion);
case TECHNOLOGY: // Device classification
return(pCachedDevCaps->ulTechnology);
case HORZSIZE: // Horizontal size in millimeters
return(pCachedDevCaps->ulHorzSizeM);
case VERTSIZE: // Vertical size in millimeters
return(pCachedDevCaps->ulVertSizeM);
case HORZRES: // Horizontal width in pixels
return(pCachedDevCaps->ulHorzRes);
case VERTRES: // Vertical height in pixels
return(pCachedDevCaps->ulVertRes);
case BITSPIXEL: // Number of bits per pixel
return(pCachedDevCaps->ulBitsPixel);
case PLANES: // Number of planes
return(pCachedDevCaps->ulPlanes);
case NUMBRUSHES: // Number of brushes the device has
return(-1);
case NUMPENS: // Number of pens the device has
return(pCachedDevCaps->ulNumPens);
case NUMMARKERS: // Number of markers the device has
return(0);
case NUMFONTS: // Number of fonts the device has
return(pCachedDevCaps->ulNumFonts);
case NUMCOLORS: // Number of colors in color table
return(pCachedDevCaps->ulNumColors);
case PDEVICESIZE: // Size required for the device descriptor
return(0);
case CURVECAPS: // Curves capabilities
return(CC_CIRCLES |
CC_PIE |
CC_CHORD |
CC_ELLIPSES |
CC_WIDE |
CC_STYLED |
CC_WIDESTYLED |
CC_INTERIORS |
CC_ROUNDRECT);
case LINECAPS: // Line capabilities
return(LC_POLYLINE |
LC_MARKER |
LC_POLYMARKER |
LC_WIDE |
LC_STYLED |
LC_WIDESTYLED |
LC_INTERIORS);
case POLYGONALCAPS: // Polygonal capabilities
return(PC_POLYGON |
PC_RECTANGLE |
PC_WINDPOLYGON |
PC_TRAPEZOID |
PC_SCANLINE |
PC_WIDE |
PC_STYLED |
PC_WIDESTYLED |
PC_INTERIORS);
case TEXTCAPS: // Text capabilities
return(pCachedDevCaps->ulTextCaps);
case CLIPCAPS: // Clipping capabilities
return(CP_RECTANGLE);
case RASTERCAPS: // Bitblt capabilities
return(pCachedDevCaps->ulRasterCaps);
case SHADEBLENDCAPS: // shade and blend capabilities
return(pCachedDevCaps->ulShadeBlendCaps);
case ASPECTX: // Length of X leg
return(pCachedDevCaps->ulAspectX);
case ASPECTY: // Length of Y leg
return(pCachedDevCaps->ulAspectY);
case ASPECTXY: // Length of hypotenuse
return(pCachedDevCaps->ulAspectXY);
case LOGPIXELSX: // Logical pixels/inch in X
return(pCachedDevCaps->ulLogPixelsX);
case LOGPIXELSY: // Logical pixels/inch in Y
return(pCachedDevCaps->ulLogPixelsY);
case SIZEPALETTE: // # entries in physical palette
return(pCachedDevCaps->ulSizePalette);
case NUMRESERVED: // # reserved entries in palette
return(20);
case COLORRES:
return(pCachedDevCaps->ulColorRes);
case PHYSICALWIDTH: // Physical Width in device units
return(pCachedDevCaps->ulPhysicalWidth);
case PHYSICALHEIGHT: // Physical Height in device units
return(pCachedDevCaps->ulPhysicalHeight);
case PHYSICALOFFSETX: // Physical Printable Area x margin
return(pCachedDevCaps->ulPhysicalOffsetX);
case PHYSICALOFFSETY: // Physical Printable Area y margin
return(pCachedDevCaps->ulPhysicalOffsetY);
case VREFRESH: // Vertical refresh rate of the device
return(pCachedDevCaps->ulVRefresh);
case DESKTOPHORZRES: // Width of entire virtual desktop
return(pCachedDevCaps->ulDesktopHorzRes);
case DESKTOPVERTRES: // Height of entire virtual desktop
return(pCachedDevCaps->ulDesktopVertRes);
case BLTALIGNMENT: // Preferred blt alignment
return(pCachedDevCaps->ulBltAlignment);
case COLORMGMTCAPS: // Color Management capabilities
return(pCachedDevCaps->ulColorManagementCaps);
default:
return(0);
}
}
/******************************Public*Routine******************************\
* GetDeviceCapsP
*
* Private version to get HORSIZE and VERTSIZE in micrometers
* Copied from GetDeviceCaps
*
* \**************************************************************************/
int GetDeviceCapsP(HDC hdc,int iCap)
{
BOOL bRet = FALSE;
PDEVCAPS pCachedDevCaps = NULL;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
DC_PLDC(hdc,pldc,bRet);
if (!(pldc->fl & LDC_CACHED_DEVCAPS))
{
bRet = NtGdiGetDeviceCapsAll (hdc, &pldc->DevCaps);
if (bRet)
{
pCachedDevCaps = &pldc->DevCaps;
pldc->fl |= LDC_CACHED_DEVCAPS;
}
}
else
{
pCachedDevCaps = &pldc->DevCaps;
bRet = TRUE;
}
}
else
{
PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr)
{
ULONG fl = pDcAttr->ulDirty_;
if (!(fl & DC_PRIMARY_DISPLAY))
{
return(NtGdiGetDeviceCaps(hdc,iCap));
}
else
{
pCachedDevCaps = pGdiDevCaps;
bRet = TRUE;
}
}
}
if (!bRet)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return (0);
}
// actual code - copied from gre\miscgdi.cxx
switch (iCap)
{
case HORZSIZEP: // Horizontal size
return(pCachedDevCaps->ulHorzSize);
case VERTSIZEP: // Vertical size
return(pCachedDevCaps->ulVertSize);
default:
return(0);
}
}
/******************************Public*Routine******************************\
* GetNearestColor *
* *
* Client side stub. *
* *
* Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
COLORREF APIENTRY GetNearestColor(HDC hdc,COLORREF color)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetNearestColor(hdc,color));
}
/******************************Public*Routine******************************\
* GetArcDirection
*
* Client side stub.
*
* Fri 09-Apr-1992 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
int APIENTRY GetArcDirection(HDC hdc)
{
FIXUP_HANDLE(hdc);
return(GetDCDWord(hdc,DDW_ARCDIRECTION,0));
}
/******************************Public*Routine******************************\
* GetMiterLimit
*
* Client side stub.
*
* Fri 09-Apr-1992 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
int APIENTRY GetMiterLimit(HDC hdc, PFLOAT peMiterLimit)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetMiterLimit(hdc,FLOATPTRARG(peMiterLimit)));
}
/******************************Public*Routine******************************\
* GetSystemPaletteUse *
* *
* Client side stub. *
* *
* Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
UINT APIENTRY GetSystemPaletteUse(HDC hdc)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetSystemPaletteUse(hdc));
}
/******************************Public*Routine******************************\
* GetClipBox *
* *
* Client side stub. *
* *
* Fri 07-Jun-1991 18:01:50 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
int APIENTRY GetClipBox(HDC hdc,LPRECT prcl)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetAppClipBox(hdc,prcl));
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetTextMetrics(HDC hdc,LPTEXTMETRIC ptm)
*
* calls to the unicode version
*
* History:
* 21-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextMetricsA(HDC hdc,LPTEXTMETRICA ptm)
{
PDC_ATTR pDcAttr;
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr)
{
CFONT * pcf;
TMW_INTERNAL tmw;
ASSERTGDI(pDcAttr->hlfntNew,"GetTextMetricsW - hf is NULL\n");
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)NULL,0, TRUE);
bRet = bGetTextMetricsWInternal(hdc,&tmw,sizeof(tmw),pcf);
// pcfLocateCFONT added a reference so now we need to remove it
if (pcf)
{
DEC_CFONT_REF(pcf);
}
LEAVECRITICALSECTION(&semLocal);
if (bRet)
{
vTextMetricWToTextMetric(ptm, &tmw);
}
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetTextMetricsW(HDC hdc,LPTEXTMETRICW ptmw)
*
* History:
* 21-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextMetricsW(HDC hdc,LPTEXTMETRICW ptmw)
{
PDC_ATTR pDcAttr;
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr)
{
CFONT * pcf;
ASSERTGDI(pDcAttr->hlfntNew,"GetTextMetricsW - hf is NULL\n");
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID) NULL,0, TRUE);
bRet = bGetTextMetricsWInternal(hdc,(TMW_INTERNAL *)ptmw,sizeof(TEXTMETRICW),pcf);
// pcfLocateCFONT added a reference so now we need to remove it
if (pcf)
{
DEC_CFONT_REF(pcf);
}
LEAVECRITICALSECTION(&semLocal);
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetTextMetricsW(HDC hdc,LPTEXTMETRICW ptmw)
*
* History:
* 21-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bGetTextMetricsWInternal(
HDC hdc,
TMW_INTERNAL *ptmw,
int cjTM,
CFONT *pcf
)
{
BOOL bRet = FALSE;
if (ptmw)
{
// if no pcf or we havn't cached the metrics
if ((pcf == NULL) || !(pcf->fl & CFONT_CACHED_METRICS))
{
TMW_INTERNAL tmw;
PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
bRet = NtGdiGetTextMetricsW(hdc,&tmw,sizeof(tmw));
if (bRet)
{
memcpy(ptmw,&tmw,cjTM);
if (pcf)
{
// we succeeded and we have a pcf so cache the data
pcf->tmw = tmw;
pcf->fl |= CFONT_CACHED_METRICS;
}
}
}
else
{
memcpy(ptmw,&pcf->tmw,cjTM);
bRet = TRUE;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* GetTextExtentPoint32A (hdc,psz,c,psizl) *
* GetTextExtentPointA (hdc,psz,c,psizl) *
* *
* Computes the text extent. The new 32 bit version returns the "correct" *
* extent without an extra per for bitmap simulations. The other is *
* Windows 3.1 compatible. Both just set a flag and pass the call to *
* bGetTextExtentA. *
* *
* History: *
* Thu 14-Jan-1993 04:11:26 -by- Charles Whitmer [chuckwh] *
* Added code to compute it on the client side. *
* *
* 07-Aug-1991 -by- Bodin Dresevic [BodinD] *
* Wrote it. *
\**************************************************************************/
// not in kernel, it is ok to do this much on the stack:
#define CAPTURE_STRING_SIZE 130
BOOL GetTextExtentPointAInternal(HDC hdc,LPCSTR psz,int c,LPSIZE psizl, FLONG fl)
{
CFONT *pcf;
INT bRet;
PWSZ pwszCapt;
PDC_ATTR pDcAttr;
DWORD dwCP;
WCHAR awcCaptureBuffer[CAPTURE_STRING_SIZE];
FIXUP_HANDLE(hdc);
if (c <= 0)
{
// empty string, just return 0 for the extent
if (c == 0)
{
psizl->cx = 0;
psizl->cy = 0;
bRet = TRUE;
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
bRet = FALSE;
}
return(bRet);
}
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
bRet = FALSE;
return(bRet);
}
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
if(guintDBCScp == dwCP)
{
QueryFontAssocStatus();
if(fFontAssocStatus &&
((c == 1) || ((c == 2 && *(psz) && *((LPCSTR)(psz + 1)) == '\0'))))
{
//
// If this function is called with only 1 char, and font association
// is enabled, we should forcely convert the chars to Unicode with
// codepage 1252.
// This is for enabling to output Latin-1 chars ( > 0x80 in Ansi codepage )
// Because, normally font association is enabled, we have no way to output
// those charactres, then we provide the way, if user call TextOutA() with
// A character and ansi font, we tempotary disable font association.
// This might be Windows 3.1 (Korean/Taiwanese) version compatibility..
//
dwCP = 1252;
}
}
if((dwCP == CP_ACP) ||
(dwCP == guintAcp) ||
(dwCP == guintDBCScp)
)
{
#ifdef LANGPACK
if (!gbLpk || (*fpLpkUseGDIWidthCache)(hdc, psz, c, pDcAttr->lTextAlign , FALSE))
{
#endif
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)psz,c,TRUE);
if (pcf != NULL)
{
BOOL bExit = TRUE;
if(dwCP == guintDBCScp)
{
if (pcf->wd.sDBCSInc) // dbcs fixed pitch base font
{
bRet = bComputeTextExtentDBCS(pDcAttr,pcf,psz,c,fl,psizl);
}
else if (!bIsDBCSString(psz,c))
{
// linked case, base font is a latin font, but linked font
// perhaps is a FE font. We know that base font is a latin font
// because for FE proportional fonts we would never create pcf.
// We are looking for this special case when the application asked
// for Latin Face Name in the logfont, and a FE charset, but the string
// passed in lackily does not contain DBCS glyphs.
bRet = bComputeTextExtent(pDcAttr,pcf,(PVOID) psz,c,fl,psizl,TRUE);
}
else
{
bExit = FALSE;
}
}
else
{
bRet = bComputeTextExtent(pDcAttr,pcf,(PVOID) psz,c,fl,psizl,TRUE);
}
DEC_CFONT_REF(pcf);
if(bExit)
{
LEAVECRITICALSECTION(&semLocal);
return(bRet);
}
}
LEAVECRITICALSECTION(&semLocal);
#ifdef LANGPACK
}
#endif
}
// Allocate the string buffer
if (c <= CAPTURE_STRING_SIZE)
{
pwszCapt = awcCaptureBuffer;
}
else
{
pwszCapt = LOCALALLOC(c * sizeof(WCHAR));
}
if (pwszCapt)
{
c = MultiByteToWideChar(dwCP, 0, psz,c, pwszCapt, c*sizeof(WCHAR));
if (c)
{
#ifdef LANGPACK
if(gbLpk)
{
bRet = (*fpLpkGetTextExtentExPoint)(hdc, pwszCapt, c, -1, NULL, NULL,
psizl, fl, 0);
}
else
#endif
bRet = NtGdiGetTextExtent(hdc,
(LPWSTR)pwszCapt,
c,
psizl,
fl);
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
bRet = FALSE;
}
if (pwszCapt != awcCaptureBuffer)
LOCALFREE(pwszCapt);
}
else
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
bRet = FALSE;
}
return(bRet);
}
BOOL APIENTRY GetTextExtentPointA(HDC hdc,LPCSTR psz,int c,LPSIZE psizl)
{
return GetTextExtentPointAInternal(hdc,psz,c,psizl,GGTE_WIN3_EXTENT);
}
BOOL APIENTRY GetTextExtentPoint32A(HDC hdc,LPCSTR psz,int c,LPSIZE psizl)
{
return GetTextExtentPointAInternal(hdc,psz,c,psizl,0);
}
/******************************Public*Routine******************************\
*
* DWORD WINAPI GetCharacterPlacementA
*
* Effects:
*
* Warnings:
*
* History:
* 27-Jul-1995 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
DWORD WINAPI GetCharacterPlacementA
(
HDC hdc,
LPCSTR psz,
int nCount,
int nMaxExtent,
LPGCP_RESULTSA pgcpa,
DWORD dwFlags
)
{
#define GCP_GLYPHS 80
WCHAR *pwsz = NULL;
WCHAR awc[GCP_GLYPHS];
GCP_RESULTSW gcpw;
DWORD dwRet;
BOOL bOk = TRUE;
int nBuffer;
SIZE size;
DWORD dwCP;
FIXUP_HANDLE(hdc);
size.cx = size.cy = 0;
// nMaxExtent == -1 means that there is no MaxExtent
if (!psz || (nCount <= 0) || ((nMaxExtent < 0) && (nMaxExtent != -1)))
{
WARNING("gdi!_GetCharactherPlacementA, bad parameters \n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!pgcpa)
{
// just call GetTextExtentA, can usually be done on the client side
if (!GetTextExtentPointA(hdc, psz, nCount, &size))
{
WARNING("GetCharacterPlacementW, GetTextExtentPointA failed\n");
return 0;
}
// now backwards compatible win95 hack, chop off 32 bit values to 16 bits
return (DWORD)((USHORT)size.cx) | (DWORD)(size.cy << 16);
}
// chop off nCount, win95 does it
if (nCount > (int)pgcpa->nGlyphs)
nCount = (int)pgcpa->nGlyphs;
// unicode string buffer will at least be this many WCHAR's long:
nBuffer = nCount;
// now go on to compute the size of the GCP_RESULTSW that is required
// to receive the results. If lpOutString is not NULL the structures
// will have different pointers else they will be the same.
gcpw.lpOrder = pgcpa->lpOrder ;
gcpw.lpDx = pgcpa->lpDx ;
gcpw.lpCaretPos = pgcpa->lpCaretPos;
gcpw.lpClass = pgcpa->lpClass ;
gcpw.lpGlyphs = pgcpa->lpGlyphs ;
gcpw.nGlyphs = pgcpa->nGlyphs ;
gcpw.nMaxFit = pgcpa->nMaxFit ;
if (pgcpa->lpOutString)
{
nBuffer += nBuffer; // take into account space for gcpw.lpOutString
}
else
{
gcpw.lpOutString = NULL;
gcpw.lStructSize = pgcpa->lStructSize;
}
// now allocate memory (if needed) for the unicode string and for
// gcpw.lpOutString if needed.
if (nBuffer <= GCP_GLYPHS)
pwsz = awc;
else
pwsz = LOCALALLOC(nBuffer * sizeof(WCHAR));
if (pwsz)
{
if (pgcpa->lpOutString)
{
gcpw.lpOutString = &pwsz[nCount];
// we have replaced the ansi string by unicode string, this adds
// nCount bytes to the size of the structure.
gcpw.lStructSize = pgcpa->lStructSize + nCount;
}
// convert Ansi To Unicode based on the code page of the font selected in DC
if
(
gcpw.nGlyphs = MultiByteToWideChar((dwCP = GetCodePage(hdc)), 0,
psz, nCount,
pwsz, nCount*sizeof(WCHAR))
)
{
// If this is a DBCS font then we need to patch up the DX array since
// there will be two DX values for each DBCS character. It is okay
// to do this in place since GetCharacterPlacement modifies the DX
// array anyway.
if((dwFlags & GCP_JUSTIFYIN) &&
(gcpw.lpDx) &&
IS_ANY_DBCS_CODEPAGE(dwCP))
{
INT *pDxNew, *pDxOld;
const char *pDBCSString;
for(pDxNew = pDxOld = gcpw.lpDx, pDBCSString = psz;
pDBCSString < psz + nCount;
pDBCSString++
)
{
if(IsDBCSLeadByteEx(dwCP,*pDBCSString))
{
pDBCSString++;
pDxOld++;
}
*pDxNew++ = *pDxOld++;
}
}
#ifdef LANGPACK
if (gbLpk)
{
// If the LPK is loaded then pass the caller nGlyphs because it may generate
// Glyphs more than nCount.
gcpw.nGlyphs = pgcpa->nGlyphs;
dwRet = (*fpLpkGetCharacterPlacement)(hdc, pwsz, nCount,nMaxExtent,
&gcpw, dwFlags, 0);
}
else
#endif
{
dwRet = NtGdiGetCharacterPlacementW(hdc,pwsz,nCount,nMaxExtent,
&gcpw, dwFlags);
}
if (dwRet)
{
// copy out the data.... we use the original value of nCount
// when specifying an output buffer size for the lpOutString buffer
// since nCount on return will be Unicode character count which
// may not be the same as DBCS character count
int nOriginalCount = nCount;
pgcpa->nGlyphs = nCount = gcpw.nGlyphs;
pgcpa->nMaxFit = gcpw.nMaxFit;
if (pgcpa->lpOutString)
{
if
(
!WideCharToMultiByte(
(UINT)dwCP, // UINT CodePage
0, // DWORD dwFlags
gcpw.lpOutString, // LPWSTR lpWideCharStr
gcpw.nMaxFit, // int cchWideChar
pgcpa->lpOutString, // LPSTR lpMultiByteStr
nOriginalCount, // int cchMultiByte
NULL, // LPSTR lpDefaultChar
NULL) // LPBOOL lpUsedDefaultChar
)
{
bOk = FALSE;
}
}
}
else
{
bOk = FALSE;
}
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
bOk = FALSE;
}
if (pwsz != awc)
LOCALFREE(pwsz);
}
else
{
bOk = FALSE;
}
return (bOk ? dwRet : 0);
}
/******************************Public*Routine******************************\
*
* DWORD WINAPI GetCharacterPlacementW
* look at gdi32.def, just points to NtGdiGetCharacterPlacementW
*
* History:
* 26-Jul-1995 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#if LANGPACK
DWORD WINAPI GetCharacterPlacementW
(
HDC hdc,
LPCWSTR pwsz,
int nCount,
int nMaxExtent,
LPGCP_RESULTSW pgcpw,
DWORD dwFlags
)
{
SIZE size;
FIXUP_HANDLE(hdc);
size.cx = size.cy = 0;
// nMaxExtent == -1 means that there is no MaxExtent
if (!pwsz || (nCount <= 0) || ((nMaxExtent < 0) && (nMaxExtent != -1)))
{
WARNING("gdi!_GetCharactherPlacementW, bad parameters \n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!pgcpw)
{
// just call GetTextExtentW, can usually be done on the client side
if (!GetTextExtentPointW(hdc, pwsz, nCount, &size))
{
WARNING("GetCharacterPlacementW, GetTextExtentPointW failed\n");
return 0;
}
// now backwards compatible win95 hack, chop off 32 bit values to 16 bits
return (DWORD)((USHORT)size.cx) | (DWORD)(size.cy << 16);
}
// chop off nCount, win95 does it
if (nCount > (int)pgcpw->nGlyphs)
nCount = (int)pgcpw->nGlyphs;
if(gbLpk)
{
return((*fpLpkGetCharacterPlacement)(hdc,pwsz,nCount,nMaxExtent,pgcpw,
dwFlags,-1));
}
else
{
return NtGdiGetCharacterPlacementW(hdc,
(LPWSTR) pwsz,
nCount,
nMaxExtent,
pgcpw,
dwFlags);
}
}
#endif
/******************************Public*Routine******************************\
* BOOL bGetCharWidthA *
* *
* Client side stub for the various GetCharWidth*A functions. *
* *
* History: *
* Sat 16-Jan-1993 03:08:42 -by- Charles Whitmer [chuckwh] *
* Added code to do it on the client side. *
* *
* 28-Aug-1991 -by- Bodin Dresevic [BodinD] *
* Wrote it. *
\**************************************************************************/
#define GCW_WIN3_INT (GCW_WIN3 | GCW_INT)
#define GCW_WIN3_16INT (GCW_WIN3 | GCW_INT | GCW_16BIT)
#define GCW_SIZE(fl) ((fl >> 16) & 0xffff)
#define GCWFL(fltype,szType) (fltype | (sizeof(szType) << 16))
BOOL bGetCharWidthA
(
HDC hdc,
UINT iFirst,
UINT iLast,
ULONG fl,
PVOID pvBuf
)
{
PDC_ATTR pDcAttr;
LONG cwc;
CFONT *pcf = NULL;
PUCHAR pch;
PWCHAR pwc;
BOOL bRet = FALSE;
ULONG cjWidths;
DWORD dwCP;
BOOL bDBCSCodePage;
WCHAR awc[MAX_PATH];
PVOID pvResultBuffer;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(bRet);
}
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCP);
// do parameter validation, check that in chars are indeed ascii
if ((bDBCSCodePage && !IsValidDBCSRange(iFirst,iLast)) ||
(!bDBCSCodePage &&
((iFirst > iLast) || (iLast & 0xffffff00))) ||
(pvBuf == NULL))
{
WARNING("gdi!_bGetCharWidthA parameters \n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(bRet);
}
cwc = (LONG)(iLast - iFirst + 1);
ENTERCRITICALSECTION(&semLocal);
if ((dwCP == CP_ACP) ||
(dwCP == guintAcp)
|| (dwCP == guintDBCScp)
)
{
pcf = pcfLocateCFONT(hdc,pDcAttr,iFirst,(PVOID) NULL,(UINT) cwc, TRUE);
}
if (pcf != (CFONT *) NULL)
{
BOOL bExit = TRUE;
if(dwCP == guintDBCScp)
{
if (pcf->wd.sDBCSInc) // dbcs fixed pitch base font
{
bRet = bComputeCharWidthsDBCS (pcf,iFirst,iLast,fl,pvBuf);
}
else if (iLast < 0x80)
{
// linked case, base font is a latin font, but linked font
// perhaps is a FE font. We know that base font is a latin font
// because for FE proportional fonts we would never create pcf.
// We are looking for this special case when the application asked
// for Latin Face Name in the logfont, and a FE charset, but the string
// passed in lackily does not contain DBCS glyphs.
bRet = bComputeCharWidths(pcf,iFirst,iLast,fl,pvBuf);
}
else
{
bExit = FALSE;
}
}
else
{
bRet = bComputeCharWidths(pcf,iFirst,iLast,fl,pvBuf);
}
DEC_CFONT_REF(pcf);
if(bExit)
{
LEAVECRITICALSECTION(&semLocal);
return(bRet);
}
}
LEAVECRITICALSECTION(&semLocal);
// Let the server do it.
cjWidths = cwc * GCW_SIZE(fl);
//
// Non kernel mode call
//
// What if user's buffer is set up for 16 bit return?? Then we need
// to allocate buffer for 32 bit date and convert to user's buffer after
// the call
pvResultBuffer = pvBuf;
if (fl & GCW_16BIT)
{
// User's buffer is 16 bit, make 32 a bit
// temp buffer
pvResultBuffer = LOCALALLOC(cwc * sizeof(LONG));
if (pvResultBuffer == NULL) {
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(bRet);
}
}
// Kernel mode, use users buffer for return data
// convert to unicode
if(bDBCSCodePage)
{
bRet = bSetUpUnicodeStringDBCS(iFirst,
iLast,
(PUCHAR) pvResultBuffer,
awc,
dwCP,
GetCurrentDefaultChar(hdc));
}
else
{
bRet = bSetUpUnicodeString(iFirst,iLast,pvResultBuffer,awc,dwCP);
}
if(bRet)
{
bRet = NtGdiGetCharWidthW(hdc,
0,
cwc,
awc,
(LONG)(fl & (GCW_INT | GCW_WIN3)),
pvResultBuffer);
}
if (bRet)
{
//
// May need to convert to 16 bit user buffer
//
if (fl & GCW_16BIT)
{
PWORD pw = pvBuf;
PDWORD pi = (int *)pvResultBuffer;
PDWORD piEnd = pi + cwc;
ASSERTGDI(pvResultBuffer != pvBuf, "Local buffer not allocated properly");
while (pi != piEnd)
{
*pw++ = (WORD)(*pi++);
}
LOCALFREE(pvResultBuffer);
}
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetCharWidthA
*
* History:
* 25-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharWidthA
(
IN HDC hdc,
IN UINT iFirst,
IN UINT iLast,
OUT LPINT lpWidths
)
{
FIXUP_HANDLE(hdc);
return bGetCharWidthA(hdc,iFirst,iLast,GCWFL(GCW_WIN3_INT,int),(PVOID)lpWidths);
}
BOOL APIENTRY GetCharWidth32A
(
IN HDC hdc,
IN UINT iFirst,
IN UINT iLast,
OUT LPINT lpWidths
)
{
FIXUP_HANDLE(hdc);
return bGetCharWidthA(hdc,iFirst,iLast,GCWFL(GCW_INT,int),(PVOID)lpWidths);
}
/******************************Public*Routine******************************\
*
* GetCharWidthFloatA
*
* History:
* 22-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharWidthFloatA
(
IN HDC hdc,
IN UINT iFirst,
IN UINT iLast,
OUT PFLOAT lpWidths
)
{
FIXUP_HANDLE(hdc);
return bGetCharWidthA(hdc,iFirst,iLast,GCWFL(0,FLOAT),(PVOID)lpWidths);
}
/******************************Public*Routine******************************\
*
* BOOL bGetCharWidthW
*
* GetCharWidthW and GetCharWidthFloatW
*
* History:
* 28-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bGetCharWidthW
(
HDC hdc,
UINT iFirst, // unicode value
UINT iLast, // unicode value
ULONG fl,
PVOID pvBuf
)
{
LONG cwc;
BOOL bRet = FALSE;
// do parameter validation, check that in chars are indeed unicode
if ((pvBuf == (PVOID)NULL) || (iFirst > iLast) || (iLast & 0xffff0000))
{
WARNING("gdi!_bGetCharWidthW parameters \n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(bRet);
}
cwc = (LONG)(iLast - iFirst + 1);
if(iLast < 0x80)
{
CFONT *pcf = NULL;
PDC_ATTR pDcAttr;
DWORD dwCP;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
ENTERCRITICALSECTION(&semLocal);
if ((dwCP == CP_ACP) ||
(dwCP == guintAcp)
|| (dwCP == guintDBCScp)
)
{
pcf = pcfLocateCFONT(hdc,pDcAttr,iFirst,(PVOID) NULL,(UINT) cwc, TRUE);
}
if (pcf != NULL)
{
bRet = bComputeCharWidths(pcf,iFirst,iLast,fl,pvBuf);
DEC_CFONT_REF(pcf);
if(bRet)
{
LEAVECRITICALSECTION(&semLocal);
return (bRet);
}
}
LEAVECRITICALSECTION(&semLocal);
}
//
// kernel mode
//
bRet = NtGdiGetCharWidthW(
hdc,
iFirst,
cwc,
NULL,
(LONG)(fl & (GCW_INT | GCW_WIN3)),
pvBuf);
return(bRet);
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetCharWidthFloatW
*
* History:
* 22-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharWidthFloatW
(
HDC hdc,
UINT iFirst,
UINT iLast,
PFLOAT lpWidths
)
{
FIXUP_HANDLE(hdc);
return bGetCharWidthW(hdc,iFirst,iLast,0,(PVOID)lpWidths);
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetCharWidthW
*
* History:
* 25-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharWidthW
(
HDC hdc,
UINT iFirst,
UINT iLast,
LPINT lpWidths
)
{
FIXUP_HANDLE(hdc);
return bGetCharWidthW(hdc,iFirst,iLast,GCW_WIN3_INT,(PVOID)lpWidths);
}
BOOL APIENTRY GetCharWidth32W
(
HDC hdc,
UINT iFirst,
UINT iLast,
LPINT lpWidths
)
{
FIXUP_HANDLE(hdc);
return bGetCharWidthW(hdc,iFirst,iLast,GCW_INT,(PVOID)lpWidths);
}
/******************************Public*Routine******************************\
*
* WINGDIAPI BOOL WINAPI GetCharWidthI(HDC, UINT, UINT, PWCHAR, LPINT);
*
* if pgi == NULL use the consecutive range
* giFirst, giFirst + 1, ...., giFirst + cgi - 1
*
* if pgi != NULL ignore giFirst and use cgi indices pointed to by pgi
*
* History:
* 28-Aug-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL WINAPI GetCharWidthI(
HDC hdc,
UINT giFirst,
UINT cgi,
LPWORD pgi,
LPINT piWidths
)
{
BOOL bRet = FALSE;
// do parameter validation
if (!piWidths || (!pgi && (giFirst & 0xffff0000)))
{
WARNING("gdi! GetCharWidthI parameters \n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(bRet);
}
if (!cgi)
return TRUE; // quick exit
// kernel mode
bRet = NtGdiGetCharWidthW(
hdc,
giFirst,
cgi,
(PWCHAR)pgi,
(GCW_INT | GCW_GLYPH_INDEX),
(PVOID)piWidths);
return bRet;
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetTextExtentPointW(HDC hdc,LPWSTR pwsz,DWORD cwc,LPSIZE psizl)
*
*
* History:
* 07-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#define QUICK_BUFSIZE 0xFF
BOOL GetTextExtentPointWInternal(
HDC hdc,LPCWSTR pwsz,int cwc,LPSIZE psizl, FLONG fl
)
{
WCHAR *pwc;
CFONT *pcf;
INT bRet;
PDC_ATTR pDcAttr;
BOOL bCache;
INT i;
WCHAR wcTest = 0;
int ii = cwc;
FIXUP_HANDLE(hdc);
if (cwc <= 0)
{
// empty string, just return 0 for the extent
if (cwc == 0)
{
psizl->cx = 0;
psizl->cy = 0;
return(TRUE);
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
}
// Let's see if we can take advantage of the ANSI client side GetTextExtent
// code. If we can convert everything from Unicode to ANSI by ignoring the
// high byte and it fits into our quick buffer then we can. In the future
// we will probably want to do a quick Unicode to ANSI conversion using
// something other than sign extension so we don't mess up non 1252 CP locales
// by making them go through the slow code all the time.
// We need to use this performance optimization if an LPK is installed
// and some condiditions are met (LTR text alignment, ..etc)
pwc = (WCHAR *) pwsz;
unroll_here:
switch(ii)
{
default:
wcTest |= pwc[9];
case 9:
wcTest |= pwc[8];
case 8:
wcTest |= pwc[7];
case 7:
wcTest |= pwc[6];
case 6:
wcTest |= pwc[5];
case 5:
wcTest |= pwc[4];
case 4:
wcTest |= pwc[3];
case 3:
wcTest |= pwc[2];
case 2:
wcTest |= pwc[1];
case 1:
wcTest |= pwc[0];
}
if ((ii > 10) && !(wcTest & 0xFF80))
{
ii -= 10;
pwc += 10;
goto unroll_here;
}
if (!(wcTest & 0xFF80))
{
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
#ifdef LANGPACK
if (!gbLpk || (*fpLpkUseGDIWidthCache)(hdc, (LPCSTR) pwsz,cwc, pDcAttr->lTextAlign , TRUE)) {
#endif
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID)pwsz,cwc, FALSE);
if (pcf != NULL)
{
bRet = bComputeTextExtent(pDcAttr,pcf,(PVOID) pwsz,cwc,fl,psizl,FALSE);
DEC_CFONT_REF(pcf);
if(bRet)
{
LEAVECRITICALSECTION(&semLocal);
return (bRet);
}
}
LEAVECRITICALSECTION(&semLocal);
#ifdef LANGPACK
}
#endif
}
#ifdef LANGPACK
if(gbLpk)
{
return(*fpLpkGetTextExtentExPoint)(hdc, pwsz, cwc, -1, NULL, NULL,
psizl, fl, -1);
}
#endif
return NtGdiGetTextExtent(hdc,
(LPWSTR)pwsz,
cwc,
psizl,
fl);
}
BOOL APIENTRY GetTextExtentPointW(HDC hdc,LPCWSTR pwsz,int cwc,LPSIZE psizl)
{
return GetTextExtentPointWInternal(hdc, pwsz, cwc, psizl, GGTE_WIN3_EXTENT);
}
BOOL APIENTRY GetTextExtentPoint32W(HDC hdc,LPCWSTR pwsz,int cwc,LPSIZE psizl)
{
return GetTextExtentPointWInternal(hdc, pwsz, cwc, psizl, 0);
}
/******************************Public*Routine******************************\
*
* GetTextExtentPointI, index version
*
* History:
* 28-Aug-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextExtentPointI(HDC hdc, LPWORD pgiIn, int cgi, LPSIZE psize)
{
return NtGdiGetTextExtent(hdc, (LPWSTR)pgiIn, cgi , psize, GGTE_GLYPH_INDEX);
}
/******************************Public*Routine******************************\
*
* GetFontUnicodeRanges(HDC, LPGLYPHSET)
*
* return Unicode content of the font.
*
* History:
* 28-Aug-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#if 0
DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET pgs)
{
return NtGdiGetFontUnicodeRanges(hdc, pgs);
}
#endif
/******************************Public*Routine******************************\
*
* GetGlyphIndicesA(HDC, LPCSTR, int, LPWORD, DWORD mode);
*
* cmap based conversion, if (mode) indicate that glyph is not supported in the
* font by putting FFFF in the output array
*
* If successfull, the function returns the number of indicies in pgi buffer.
*
* History:
* 28-Aug-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
DWORD WINAPI GetGlyphIndicesA(
HDC hdc,
LPCSTR psz,
int c,
LPWORD pgi,
DWORD iMode)
{
DWORD dwRet = GDI_ERROR;
PWSZ pwszCapt;
PDC_ATTR pDcAttr;
DWORD dwCP;
WCHAR awcCaptureBuffer[CAPTURE_STRING_SIZE];
FIXUP_HANDLE(hdc);
if (c <= 0)
{
// empty string, just return 0 for the extent
if (c == 0)
{
dwRet = 0;
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
dwRet = GDI_ERROR;
}
return(dwRet);
}
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (!pDcAttr)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
dwRet = GDI_ERROR;
return dwRet;
}
dwCP = GET_CODE_PAGE(hdc, pDcAttr);
if(guintDBCScp == dwCP)
{
QueryFontAssocStatus();
if(fFontAssocStatus &&
((c == 1) || ((c == 2 && *(psz) && *((LPCSTR)(psz + 1)) == '\0'))))
{
//
// If this function is called with only 1 char, and font association
// is enabled, we should forcely convert the chars to Unicode with
// codepage 1252.
// This is for enabling to output Latin-1 chars ( > 0x80 in Ansi codepage )
// Because, normally font association is enabled, we have no way to output
// those charactres, then we provide the way, if user call TextOutA() with
// A character and ansi font, we tempotary disable font association.
// This might be Windows 3.1 (Korean/Taiwanese) version compatibility..
//
dwCP = 1252;
}
}
// Allocate the string buffer
if (c <= CAPTURE_STRING_SIZE)
{
pwszCapt = awcCaptureBuffer;
}
else
{
pwszCapt = LOCALALLOC(c * sizeof(WCHAR));
}
if (pwszCapt)
{
c = MultiByteToWideChar(dwCP, 0, psz,c, pwszCapt, c*sizeof(WCHAR));
if (c)
{
dwRet = NtGdiGetGlyphIndicesW(hdc,
(LPWSTR)pwszCapt,
c,
pgi,
iMode);
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
dwRet = GDI_ERROR;
}
if (pwszCapt != awcCaptureBuffer)
LOCALFREE(pwszCapt);
}
else
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
dwRet = GDI_ERROR;
}
return dwRet;
}
/******************************Public*Routine******************************\
*
* GetGlyphIndicesW(HDC, LPCSTR, int, LPWORD, DWORD);
*
* cmap based conversion, if (mode) indicate that glyph is not supported in the
* font by putting FFFF in the output array
*
* History:
* 28-Aug-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#if 0
DWORD WINAPI GetGlyphIndicesW(
HDC hdc,
LPCWSTR pwc,
int cwc,
LPWORD pgi,
DWORD iMode)
{
return NtGdiGetGlyphIndicesW(hdc, pwc, cwc, pgi, iMode);
}
#endif
/******************************Public*Routine******************************\
*
* int APIENTRY GetTextFaceA(HDC hdc,int c,LPSTR psz)
*
* History:
* 30-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
int APIENTRY GetTextFaceA(HDC hdc,int c,LPSTR psz)
{
ULONG cRet = 0;
ULONG cbAnsi = 0;
FIXUP_HANDLE(hdc);
if ( (psz != (LPSTR) NULL) && (c <= 0) )
{
WARNING("gdi!GetTextFaceA(): invalid parameter\n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return cRet;
}
{
//
// Kernel mode, allocate a buffer for WCAHR return
//
// WINBUG #82833 2-7-2000 bhouse Possible cleanup work in GetTextFaceA
// Old Comment:
// - This allocates a temp buffer, then NtGdi does it again
//
PWCHAR pwch = (PWCHAR)NULL;
if (c > 0)
{
pwch = (WCHAR *)LOCALALLOC(c * sizeof(WCHAR));
if (pwch == (WCHAR *)NULL)
{
WARNING("gdi!GetTextFaceA(): Memory allocation error\n");
cRet = 0;
return(cRet);
}
}
cRet = NtGdiGetTextFaceW(hdc,c,(LPWSTR)pwch,FALSE);
if(cRet && (guintDBCScp != 0xFFFFFFFF) && !psz )
{
WCHAR *pwcTmp;
// now we need to actually need to get the string for DBCS code pages
// so that we can compute the proper multi-byte length
if(pwcTmp = (WCHAR*)LOCALALLOC(cRet*sizeof(WCHAR)))
{
UINT cwTmp;
cwTmp = NtGdiGetTextFaceW(hdc,cRet,pwcTmp, FALSE);
RtlUnicodeToMultiByteSize(&cbAnsi,pwcTmp,cwTmp*sizeof(WCHAR));
LOCALFREE(pwcTmp);
}
else
{
WARNING("gdi!GetTextFaceA(): UNICODE to ANSI conversion failed\n");
cRet = 0;
}
}
else
{
cbAnsi = cRet;
}
//
// If successful and non-NULL buffer, convert back to ANSI.
//
if ( (cRet != 0) && (psz != (LPSTR) NULL) && (pwch != (WCHAR*)NULL))
{
if(!(cbAnsi = WideCharToMultiByte(CP_ACP,0,pwch,cRet,psz,c,NULL,NULL)))
{
WARNING("gdi!GetTextFaceA(): UNICODE to ANSI conversion failed\n");
cRet = 0;
}
}
if (pwch != (PWCHAR)NULL)
{
LOCALFREE(pwch);
}
}
//
// return for user and kernel mode
//
return( ((cRet == 0 ) || (psz == NULL) || psz[cbAnsi-1] != 0 ) ? cbAnsi : cbAnsi-1 );
}
/******************************Public*Routine******************************\
*
* DWORD APIENTRY GetTextFaceAliasW(HDC hdc,DWORD c,LPWSTR pwsz)
*
* History:
* 24-Feb-1998 -by- Yung-Jen Tony Tsai [YungT]
* Wrote it.
\**************************************************************************/
int APIENTRY GetTextFaceAliasW(HDC hdc,int c,LPWSTR pwsz)
{
int cRet = 0;
FIXUP_HANDLE(hdc);
if ( (pwsz != (LPWSTR) NULL) && (c == 0) )
{
WARNING("gdi!GetTextFaceAliasW(): invalid parameter\n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return cRet;
}
cRet = NtGdiGetTextFaceW(hdc,c,pwsz,TRUE);
return(cRet);
}
/******************************Public*Routine******************************\
*
* DWORD APIENTRY GetTextFaceW(HDC hdc,DWORD c,LPWSTR pwsz)
*
* History:
* 13-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
int APIENTRY GetTextFaceW(HDC hdc,int c,LPWSTR pwsz)
{
int cRet = 0;
FIXUP_HANDLE(hdc);
if ( (pwsz != (LPWSTR) NULL) && (c <= 0) )
{
WARNING("gdi!GetTextFaceW(): invalid parameter\n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return cRet;
}
cRet = NtGdiGetTextFaceW(hdc,c,pwsz,FALSE);
return(cRet);
}
/******************************Public*Routine******************************\
*
* vTextMetricWToTextMetricStrict (no char conversion)
*
* Effects: return FALSE if UNICODE chars have no ASCI equivalents
*
*
* History:
* 20-Aug-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID FASTCALL vTextMetricWToTextMetricStrict
(
LPTEXTMETRICA ptm,
LPTEXTMETRICW ptmw
)
{
ptm->tmHeight = ptmw->tmHeight ; // DWORD
ptm->tmAscent = ptmw->tmAscent ; // DWORD
ptm->tmDescent = ptmw->tmDescent ; // DWORD
ptm->tmInternalLeading = ptmw->tmInternalLeading ; // DWORD
ptm->tmExternalLeading = ptmw->tmExternalLeading ; // DWORD
ptm->tmAveCharWidth = ptmw->tmAveCharWidth ; // DWORD
ptm->tmMaxCharWidth = ptmw->tmMaxCharWidth ; // DWORD
ptm->tmWeight = ptmw->tmWeight ; // DWORD
ptm->tmOverhang = ptmw->tmOverhang ; // DWORD
ptm->tmDigitizedAspectX = ptmw->tmDigitizedAspectX ; // DWORD
ptm->tmDigitizedAspectY = ptmw->tmDigitizedAspectY ; // DWORD
ptm->tmItalic = ptmw->tmItalic ; // BYTE
ptm->tmUnderlined = ptmw->tmUnderlined ; // BYTE
ptm->tmStruckOut = ptmw->tmStruckOut ; // BYTE
ptm->tmPitchAndFamily = ptmw->tmPitchAndFamily ; // BYTE
ptm->tmCharSet = ptmw->tmCharSet ; // BYTE
}
VOID FASTCALL vTextMetricWToTextMetric
(
LPTEXTMETRICA ptma,
TMW_INTERNAL *ptmi
)
{
vTextMetricWToTextMetricStrict(ptma,&ptmi->tmw);
ptma->tmFirstChar = ptmi->tmdTmw.chFirst ;
ptma->tmLastChar = ptmi->tmdTmw.chLast ;
ptma->tmDefaultChar = ptmi->tmdTmw.chDefault;
ptma->tmBreakChar = ptmi->tmdTmw.chBreak ;
}
/******************************Public*Routine******************************\
* GetTextExtentExPointA
*
* History:
* 06-Jan-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextExtentExPointA (
HDC hdc,
LPCSTR lpszString,
int cchString,
int nMaxExtent,
LPINT lpnFit,
LPINT lpnDx,
LPSIZE lpSize
)
{
WCHAR *pwsz = NULL;
WCHAR awc[GCP_GLYPHS];
INT aiDx[GCP_GLYPHS];
INT *pDx;
BOOL bRet = FALSE;
DWORD dwCP;
BOOL bZeroSize = FALSE;
FIXUP_HANDLE(hdc);
// some parameter checking. In a single check we will both make sure that
// cchString is not negative and if positive, that it is not bigger than
// ULONG_MAX / (sizeof(ULONG) + sizeof(WCHAR)). This restriction is necessary
// for one of the memory allocations in ntgdi.c allocates
// cchString * (sizeof(ULONG) + sizeof(WCHAR)).
// Clearly, the result of this multiplication has to fit in ULONG for the
// alloc to make sense:
// also there is a validity check to be performed on nMaxExtent. -1 is the only
// legal negative value of nMaxExtent, this basically means
// that nMaxExtent can be ignored. All other negative values of nMaxExtent are
// not considered legal input.
if
(
((ULONG)cchString > (ULONG_MAX / (sizeof(ULONG)+sizeof(WCHAR))))
||
(nMaxExtent < -1)
)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return bRet;
}
if(cchString == 0)
bZeroSize = TRUE;
// now allocate memory (if needed) for the unicode string if needed
if (cchString <= GCP_GLYPHS)
{
pwsz = awc;
pDx = aiDx;
}
else
{
pwsz = LOCALALLOC((cchString+1) * (sizeof(WCHAR) + sizeof(INT)));
pDx = (INT*) &pwsz[(cchString+1)&~1];
}
if (pwsz)
{
UINT cwcWideChars;
// convert Ansi To Unicode based on the code page of the font selected in DC
dwCP = GetCodePage(hdc);
if( bZeroSize || ( cwcWideChars = MultiByteToWideChar(dwCP,
0,
lpszString, cchString,
pwsz, cchString*sizeof(WCHAR))) )
{
BOOL bDBCSFont = IS_ANY_DBCS_CODEPAGE(dwCP) ? TRUE : FALSE;
if(bZeroSize){
cwcWideChars = 0;
pwsz[0] = (WCHAR) 0x0;
}
#ifdef LANGPACK
if(gbLpk)
{
bRet = (*fpLpkGetTextExtentExPoint)(hdc, pwsz, cwcWideChars, nMaxExtent,
lpnFit, bDBCSFont ? pDx : lpnDx,
lpSize, 0, 0);
}
else
#endif
bRet = NtGdiGetTextExtentExW(hdc,
pwsz,
cwcWideChars,
nMaxExtent,
lpnFit,
bDBCSFont ? pDx : lpnDx,
lpSize,
0);
if (bDBCSFont && bRet)
{
// if this is a DBCS font then we need to make some adjustments
int i, j;
int cchFit, cwc;
// first compute return the proper fit in multi byte characters
if (lpnFit)
{
cwc = *lpnFit;
cchFit = WideCharToMultiByte(dwCP, 0, pwsz, cwc, NULL, 0, NULL, NULL);
*lpnFit = cchFit;
}
else
{
cwc = cwcWideChars;
cchFit = cchString;
}
// next copy the dx array. we duplicate the dx value for the high
// and low byte of DBCS characters.
if(lpnDx)
{
for(i = 0, j = 0; i < cchFit; j++)
{
if(IsDBCSLeadByteEx(dwCP,lpszString[i]))
{
lpnDx[i++] = pDx[j];
lpnDx[i++] = pDx[j];
}
else
{
lpnDx[i++] = pDx[j];
}
}
// I claim that we should be at exactly at the end of the Unicode
// string once we are here if not we need to examine the above loop
// to make sure it works properly [gerritv]
ASSERTGDI(j == cwc,
"GetTextExtentExPointA: problem converting DX array\n");
}
}
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
}
if (pwsz != awc)
LOCALFREE(pwsz);
}
return bRet;
}
/******************************Public*Routine******************************\
* GetTextExtentExPointW
*
* History:
* 06-Jan-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextExtentExPointW (
HDC hdc,
LPCWSTR lpwszString,
int cwchString,
int nMaxExtent,
LPINT lpnFit,
LPINT lpnDx,
LPSIZE lpSize
)
{
#ifdef LANGPACK
if(gbLpk)
{
return (*fpLpkGetTextExtentExPoint)(hdc, lpwszString, cwchString, nMaxExtent,
lpnFit, lpnDx, lpSize, 0, -1);
}
else
#endif
return NtGdiGetTextExtentExW(hdc,
(LPWSTR)lpwszString,
cwchString,
nMaxExtent,
lpnFit,
lpnDx,
lpSize,
0);
}
/******************************Public*Routine******************************\
*
* GetTextExtentExPointWPri,
* The same as GetTextExtentExPointW, the only difference is that
* lpk is bypassed, whether installed or not. This routine is actually called
* by lpk when it is installed.
*
* History:
* 03-Jun-1997 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextExtentExPointWPri (
HDC hdc,
LPCWSTR lpwszString,
int cwchString,
int nMaxExtent,
LPINT lpnFit,
LPINT lpnDx,
LPSIZE lpSize
)
{
return NtGdiGetTextExtentExW(hdc,
(LPWSTR)lpwszString,
cwchString,
nMaxExtent,
lpnFit,
lpnDx,
lpSize,
0);
}
/******************************Public*Routine******************************\
*
* BOOL APIENTRY GetTextExtentExPointI
*
*
* History:
* 09-Sep-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetTextExtentExPointI (
HDC hdc,
LPWORD lpwszString,
int cwchString,
int nMaxExtent,
LPINT lpnFit,
LPINT lpnDx,
LPSIZE lpSize
)
{
return NtGdiGetTextExtentExW(hdc,
(LPWSTR)lpwszString,
cwchString,
nMaxExtent,
lpnFit,
lpnDx,
lpSize,
GTEEX_GLYPH_INDEX);
}
/******************************Public*Routine******************************\
*
* bGetCharABCWidthsA
*
* works for both floating point and integer version depending on bInt
*
* History:
* 24-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bGetCharABCWidthsA (
HDC hdc,
UINT wFirst,
UINT wLast,
FLONG fl,
PVOID pvBuf // if (fl & GCABCW_INT) pabc else pabcf,
)
{
BOOL bRet = FALSE;
ULONG cjData, cjWCHAR, cjABC;
ULONG cChar = wLast - wFirst + 1;
DWORD dwCP = GetCodePage(hdc);
BOOL bDBCSCodePage;
bDBCSCodePage = IS_ANY_DBCS_CODEPAGE(dwCP);
// Parameter checking.
FIXUP_HANDLE(hdc);
if((pvBuf == (PVOID) NULL) ||
(bDBCSCodePage && !IsValidDBCSRange(wFirst,wLast)) ||
(!bDBCSCodePage && ((wFirst > wLast) || (wLast > 255))))
{
WARNING("gdi!_GetCharABCWidthsA(): bad parameter\n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
// Compute buffer space needed in memory window.
// Buffer will be input array of WCHAR followed by output arrary of ABC.
// Because ABC need 32-bit alignment, cjWCHAR is rounded up to DWORD boundary.
cjABC = cChar * ((fl & GCABCW_INT) ? sizeof(ABC) : sizeof(ABCFLOAT));
cjWCHAR = ALIGN4(cChar * sizeof(WCHAR));
cjData = cjWCHAR + cjABC;
//
// WINBUG 82840 2-7-2000 bhouse Possible cleanup in bGetCharABCWidthsA
// Old Comment:
// - if vSetUpUnicodeString,x could be moved to ntgdi,
// we wouldn't need to allocated temp buffers twice
//
// Allocate memory for temp buffer, fill in with proper char values
//
// Write the unicode string [wFirst,wLast] at the top of the buffer.
// vSetUpUnicodeString requires a tmp CHAR buffer; we'll cheat a little
// and use the ABC return buffer (this assumes that ABC is bigger
// than a CHAR or USHORT in the case of DBCS). We can get away with this b
// because this memory is an output buffer for the server call.
//
{
PUCHAR pjTempBuffer = LOCALALLOC(cjData);
PUCHAR pwcABC = pjTempBuffer + cjWCHAR;
PWCHAR pwcCHAR = (PWCHAR)pjTempBuffer;
if (pjTempBuffer == (PUCHAR)NULL)
{
bRet = FALSE;
}
else
{
if(bDBCSCodePage)
{
bRet = bSetUpUnicodeStringDBCS(wFirst,
wLast,
pwcABC,
pwcCHAR,
dwCP,
GetCurrentDefaultChar(hdc));
}
else
{
bRet = bSetUpUnicodeString(wFirst,
wLast,
pwcABC,
pwcCHAR, dwCP);
}
//
// call GDI
//
if(bRet)
{
bRet = NtGdiGetCharABCWidthsW(hdc,
wFirst,
cChar,
(PWCHAR)pwcCHAR,
(fl & GCABCW_INT),
(PVOID)pwcABC);
}
//
// If OK, then copy return data out of window.
//
if (bRet)
{
RtlCopyMemory((PBYTE) pvBuf,pwcABC, cjABC);
}
LOCALFREE(pjTempBuffer);
}
}
return bRet;
}
/******************************Public*Routine******************************\
* BOOL APIENTRY GetCharABCWidthsA (
*
* We want to get ABC spaces
* for a contiguous set of input codepoints (that range from wFirst to wLast).
* The set of corresponding UNICODE codepoints is not guaranteed to be
* contiguous. Therefore, we will translate the input codepoints here and
* pass the server a buffer of UNICODE codepoints.
*
* History:
* 20-Jan-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharABCWidthsA (
HDC hdc,
UINT wFirst,
UINT wLast,
LPABC lpABC
)
{
return bGetCharABCWidthsA(hdc,wFirst,wLast,GCABCW_INT,(PVOID)lpABC);
}
/******************************Public*Routine******************************\
*
* GetCharABCWidthsFloatA
*
* History:
* 22-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharABCWidthsFloatA
(
IN HDC hdc,
IN UINT iFirst,
IN UINT iLast,
OUT LPABCFLOAT lpABCF
)
{
return bGetCharABCWidthsA(hdc,iFirst,iLast,0,(PVOID)lpABCF);
}
/******************************Public*Routine******************************\
*
* bGetCharABCWidthsW
*
* History:
* 22-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bGetCharABCWidthsW (
IN HDC hdc,
IN UINT wchFirst,
IN UINT wchLast,
IN FLONG fl,
OUT PVOID pvBuf
)
{
BOOL bRet = FALSE;
ULONG cwch = wchLast - wchFirst + 1;
// Parameter checking.
FIXUP_HANDLE(hdc);
if ( (pvBuf == (PVOID)NULL) || (wchFirst > wchLast) )
{
WARNING("gdi!GetCharABCWidthsW(): bad parameter\n");
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
//
// kernel mode
//
bRet = NtGdiGetCharABCWidthsW(
hdc,
wchFirst,
cwch,
(PWCHAR)NULL,
fl,
(PVOID)pvBuf);
return(bRet);
}
/******************************Public*Routine******************************\
* BOOL APIENTRY GetCharABCWidthsW (
* IN HDC hdc,
* IN WORD wchFirst,
* IN WORD wchLast,
* OUT LPABC lpABC
* )
*
* For this case, we can truly assume that we want to get ABC character
* widths for a contiguous set of UNICODE codepoints from wchFirst to
* wchLast (inclusive). So we will call the server using wchFirst, but
* with an empty input buffer.
*
* History:
* 20-Jan-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharABCWidthsW (
HDC hdc,
UINT wchFirst,
UINT wchLast,
LPABC lpABC
)
{
return bGetCharABCWidthsW(hdc,wchFirst,wchLast,GCABCW_INT,(PVOID)lpABC);
}
/******************************Public*Routine******************************\
*
* GetCharABCWidthsFloatW
*
* Effects:
*
* Warnings:
*
* History:
* 22-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharABCWidthsFloatW
(
HDC hdc,
UINT iFirst,
UINT iLast,
LPABCFLOAT lpABCF
)
{
return bGetCharABCWidthsW(hdc,iFirst,iLast,0,(PVOID)lpABCF);
}
/******************************Public*Routine******************************\
*
* GetCharABCWidthsI, index version
*
* if pgi == NULL use the consecutive range
* giFirst, giFirst + 1, ...., giFirst + cgi - 1
*
* if pgi != NULL ignore giFirst and use cgi indices pointed to by pgi
*
* History:
* 28-Aug-1996 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetCharABCWidthsI(
HDC hdc,
UINT giFirst,
UINT cgi,
LPWORD pgi,
LPABC pabc
)
{
return NtGdiGetCharABCWidthsW(hdc,
giFirst,
cgi,
pgi,
GCABCW_INT | GCABCW_GLYPH_INDEX,
pabc
);
}
/******************************Public*Routine******************************\
* GetFontData
*
* Client side stub to GreGetFontData.
*
* History:
* 17-Feb-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
DWORD APIENTRY GetFontData (
HDC hdc,
DWORD dwTable,
DWORD dwOffset,
PVOID pvBuffer,
DWORD cjBuffer
)
{
DWORD dwRet = (DWORD) -1;
FIXUP_HANDLE(hdc);
// if there is no buffer to copy data to, ignore possibly different
// from zero cjBuffer parameter. This is what win95 is doing.
if (cjBuffer && (pvBuffer == NULL))
cjBuffer = 0;
dwRet = NtGdiGetFontData(
hdc,
dwTable,
dwOffset,
pvBuffer,
cjBuffer);
return(dwRet);
}
/******************************Public*Routine******************************\
* GetGlyphOutline
*
* Client side stub to GreGetGlyphOutline.
*
* History:
* 17-Feb-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
DWORD GetGlyphOutlineInternalW (
HDC hdc,
UINT uChar,
UINT fuFormat,
LPGLYPHMETRICS lpgm,
DWORD cjBuffer,
LPVOID pvBuffer,
CONST MAT2 *lpmat2,
BOOL bIgnoreRotation
)
{
DWORD dwRet = (DWORD) -1;
// Parameter validation.
FIXUP_HANDLE(hdc);
if ( (lpmat2 == (LPMAT2) NULL)
|| (lpgm == (LPGLYPHMETRICS) NULL)
)
{
WARNING("gdi!GetGlyphOutlineW(): bad parameter\n");
return (dwRet);
}
if (pvBuffer == NULL)
cjBuffer = 0;
// Compute buffer space needed in memory window.
dwRet = NtGdiGetGlyphOutline(
hdc,
(WCHAR)uChar,
fuFormat,
lpgm,
cjBuffer,
pvBuffer,
(LPMAT2)lpmat2,
bIgnoreRotation);
return(dwRet);
}
DWORD APIENTRY GetGlyphOutlineW (
HDC hdc,
UINT uChar,
UINT fuFormat,
LPGLYPHMETRICS lpgm,
DWORD cjBuffer,
LPVOID pvBuffer,
CONST MAT2 *lpmat2
)
{
return( GetGlyphOutlineInternalW( hdc,
uChar,
fuFormat,
lpgm,
cjBuffer,
pvBuffer,
lpmat2,
FALSE ) );
}
DWORD APIENTRY GetGlyphOutlineInternalA (
HDC hdc,
UINT uChar,
UINT fuFormat,
LPGLYPHMETRICS lpgm,
DWORD cjBuffer,
LPVOID pvBuffer,
CONST MAT2 *lpmat2,
BOOL bIgnoreRotation
)
{
WCHAR wc;
BOOL bRet;
FIXUP_HANDLE(hdc);
// The ANSI interface is compatible with Win 3.1 and is intended
// to take a 2 byte uChar. Since we are 32-bit, this 16-bit UINT
// is now 32-bit. So we are only interested in the least significant
// word of the uChar passed into the 32-bit interface.
if (!(fuFormat & GGO_GLYPH_INDEX))
{
// the conversion needs to be done based on
// the current code page of the font selected in the dc
UCHAR Mbcs[2];
UINT Convert;
DWORD dwCP = GetCodePage(hdc);
if(IS_ANY_DBCS_CODEPAGE(dwCP) &&
IsDBCSLeadByteEx(dwCP, (char) (uChar >> 8)))
{
Mbcs[0] = (uChar >> 8) & 0xFF;
Mbcs[1] = uChar & 0xFF;
Convert = 2;
}
else
{
Mbcs[0] = uChar & 0xFF;
Convert = 1;
}
if(!(bRet = MultiByteToWideChar(dwCP, 0,
(LPCSTR)Mbcs,Convert,
&wc, sizeof(WCHAR))))
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
}
}
else
{
// The uChar value is to be interpreted as glyph index and
// no conversion is necessary
wc = (WCHAR)uChar;
bRet = TRUE;
}
if (bRet)
{
bRet = GetGlyphOutlineInternalW(
hdc,
(UINT) wc,
fuFormat,
lpgm,
cjBuffer,
pvBuffer,
lpmat2,
bIgnoreRotation);
}
return bRet;
}
DWORD APIENTRY GetGlyphOutlineA (
HDC hdc,
UINT uChar,
UINT fuFormat,
LPGLYPHMETRICS lpgm,
DWORD cjBuffer,
LPVOID pvBuffer,
CONST MAT2 *lpmat2
)
{
return( GetGlyphOutlineInternalA( hdc,
uChar,
fuFormat,
lpgm,
cjBuffer,
pvBuffer,
lpmat2,
FALSE ) );
}
DWORD APIENTRY GetGlyphOutlineWow (
HDC hdc,
UINT uChar,
UINT fuFormat,
LPGLYPHMETRICS lpgm,
DWORD cjBuffer,
LPVOID pvBuffer,
CONST MAT2 *lpmat2
)
{
return( GetGlyphOutlineInternalA( hdc,
uChar,
fuFormat,
lpgm,
cjBuffer,
pvBuffer,
lpmat2,
TRUE ) );
}
/******************************Public*Routine******************************\
* GetOutlineTextMetricsW
*
* Client side stub to GreGetOutlineTextMetrics.
*
* History:
*
* Tue 20-Apr-1993 -by- Gerrit van Wingerden [gerritv]
* update: added bTTOnly stuff for Aldus escape in the WOW layer
*
* Thu 28-Jan-1993 -by- Bodin Dresevic [BodinD]
* update: added TMDIFF * stuff
*
* 17-Feb-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsWInternal (
HDC hdc,
UINT cjCopy, // refers to OTMW_INTERNAL, not to OUTLINETEXTMETRICSW
OUTLINETEXTMETRICW * potmw,
TMDIFF * ptmd
)
{
DWORD cjRet = (DWORD) 0;
FIXUP_HANDLE(hdc);
if (potmw == (OUTLINETEXTMETRICW *) NULL)
cjCopy = 0;
cjRet = NtGdiGetOutlineTextMetricsInternalW(
hdc,
cjCopy,
potmw,
ptmd);
return(cjRet);
}
/******************************Public*Routine******************************\
*
* UINT APIENTRY GetOutlineTextMetricsW (
*
* wrote the wrapper to go around the corresponding internal routine
*
* History:
* 28-Jan-1993 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsW (
HDC hdc,
UINT cjCopy,
LPOUTLINETEXTMETRICW potmw
)
{
TMDIFF tmd;
return GetOutlineTextMetricsWInternal(hdc, cjCopy, potmw, &tmd);
}
#define bAnsiSize(a,b,c) (NT_SUCCESS(RtlUnicodeToMultiByteSize((a),(b),(c))))
// vAnsiSize macro should only be used within GetOTMA, where bAnsiSize
// is not supposed to fail [bodind]
#if DBG
#define vAnsiSize(a,b,c) \
{ \
BOOL bTmp = bAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc); \
ASSERTGDI(bTmp, "gdi32!GetOTMA: bAnsiSize failed \n"); \
}
#else
#define vAnsiSize(a,b,c) bAnsiSize(a,b,c)
#endif //, non debug version
/******************************Public*Routine******************************\
* GetOutlineTextMetricsInternalA
*
* Client side stub to GreGetOutlineTextMetrics.
*
* History:
*
* 20-Apr-1993 -by- Gerrit van Wingerden [gerritv]
* Changed to GetOutlineTextMetricsInternalA from GetOutlineTextMetricsA
* to support all fonts mode for Aldus escape.
*
* 17-Feb-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsInternalA (
HDC hdc,
UINT cjCopy,
LPOUTLINETEXTMETRICA potma
)
{
UINT cjRet = 0;
UINT cjotma, cjotmw;
TMDIFF tmd;
OUTLINETEXTMETRICW *potmwTmp;
OUTLINETEXTMETRICA otmaTmp; // tmp buffer on the stack
FIXUP_HANDLE(hdc);
// Because we need to be able to copy cjCopy bytes of data from the
// OUTLINETEXTMETRICA structure, we need to allocate a temporary buffer
// big enough for the entire structure. This is because the UNICODE and
// ANSI versions of OUTLINETEXTMETRIC have mismatched offsets to their
// corresponding fields.
// Determine size of the buffer.
if ((cjotmw = GetOutlineTextMetricsWInternal(hdc, 0, NULL,&tmd)) == 0 )
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): unable to determine size of buffer needed\n");
return (cjRet);
}
// get cjotma from tmd.
cjotma = (UINT)tmd.cjotma;
// if cjotma == 0, this is HONEST to God unicode font, can not convert
// strings to ansi
if (cjotma == 0)
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): unable to determine cjotma\n");
return (cjRet);
}
// Early out. If NULL buffer, then just return the size.
if (potma == (LPOUTLINETEXTMETRICA) NULL)
return (cjotma);
// Allocate temporary buffers.
if ((potmwTmp = (OUTLINETEXTMETRICW*) LOCALALLOC(cjotmw)) == (OUTLINETEXTMETRICW*)NULL)
{
WARNING("gdi!GetOutlineTextMetricA(): memory allocation error OUTLINETEXTMETRICW buffer\n");
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (cjRet);
}
// Call the UNICODE version of the call.
if (GetOutlineTextMetricsWInternal(hdc, cjotmw, potmwTmp,&tmd) == 0 )
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): call to GetOutlineTextMetricsW() failed\n");
LOCALFREE(potmwTmp);
return (cjRet);
}
// Convert from OUTLINETEXTMETRICW to OUTLINETEXTMETRICA
vOutlineTextMetricWToOutlineTextMetricA(&otmaTmp, potmwTmp,&tmd);
// Copy data into return buffer. Do not copy strings.
cjRet = min(cjCopy, sizeof(OUTLINETEXTMETRICA));
RtlMoveMemory(potma,&otmaTmp,cjRet);
// Note that if
// offsetof(OUTLINETEXTMETRICA,otmpFamilyName) < cjCopy <= sizeof(OUTLINETEXTMETRICA)
// the offsets to strings have been set to zero [BodinD]
// If strings wanted, convert the strings to ANSI.
if (cjCopy > sizeof(OUTLINETEXTMETRICA))
{
ULONG cjString,cwc;
ULONG_PTR dpString;
ULONG_PTR dpStringEnd;
PWSZ pwszSrc;
// first have to make sure that we will not overwrite the end
// of the caller's buffer, if that is the case
if (cjCopy < cjotma)
{
// Win 31 spec is ambiguous about this case
// and by looking into the source code, it seems that
// they just overwrite the end of the buffer without
// even doing this check.
GdiSetLastError(ERROR_CAN_NOT_COMPLETE);
cjRet = 0;
goto GOTMA_clean_up;
}
// now we know that all the strings can fit, moreover we know that
// all string operations will succeed since we have called
// cjOTMA to do these same operations on the server side to give us
// cjotma [bodind]
// Note: have to do the backwards compatible casting below because Win 3.1 insists
// on using a PSTR as PTRDIFF (i.e., an offset).
// FAMILY NAME ------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpFamilyName);
cwc = wcslen(pwszSrc) + 1;
vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
// Convert from Unicode to ASCII.
dpString = sizeof(OUTLINETEXTMETRICA);
dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit1\n");
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc))
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n");
cjRet = 0;
goto GOTMA_clean_up;
}
// Store string offset in the return structure.
potma->otmpFamilyName = (PSTR) dpString;
// FACE NAME --------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpFaceName);
cwc = wcslen(pwszSrc) + 1;
vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
dpString = dpStringEnd;
dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit2\n");
// Convert from Unicode to ASCII.
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc))
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n");
cjRet = 0;
goto GOTMA_clean_up;
}
// Store string offset in return structure. Move pointers to next string.
potma->otmpFaceName = (PSTR) dpString;
// STYLE NAME -------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpStyleName);
cwc = wcslen(pwszSrc) + 1;
vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
dpString = dpStringEnd;
dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit3\n");
// Convert from Unicode to ASCII.
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc))
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n");
cjRet = 0;
goto GOTMA_clean_up;
}
// Store string offset in return structure. Move pointers to next string.
potma->otmpStyleName = (PSTR)dpString;
// FULL NAME --------------------------------------------------------------
pwszSrc = (PWSZ) (((PBYTE) potmwTmp) + (ULONG_PTR) potmwTmp->otmpFullName);
cwc = wcslen(pwszSrc) + 1;
vAnsiSize(&cjString, pwszSrc, sizeof(WCHAR) * cwc);
dpString = dpStringEnd;
dpStringEnd = dpString + cjString;
ASSERTGDI(dpStringEnd <= cjCopy, "gdi32!GetOTMA: string can not fit4\n");
// Convert from Unicode to ASCII.
if (!bToASCII_N ((PBYTE)potma + dpString,cjString,pwszSrc,cwc))
{
WARNING("gdi!GetOutlineTextMetricsInternalA(): UNICODE->ASCII conv error \n");
cjRet = 0;
goto GOTMA_clean_up;
}
// Store string offset in return structure.
potma->otmpFullName = (PSTR) dpString;
//Sundown: safe to truncate ULONG
cjRet = (ULONG)dpStringEnd;
ASSERTGDI(cjRet == cjotma, "gdi32!GetOTMA: cjRet != dpStringEnd\n");
}
GOTMA_clean_up:
// Free temporary buffer.
LOCALFREE(potmwTmp);
// Fixup size field.
if (cjCopy >= sizeof(UINT)) // if it is possible to store otmSize
potma->otmSize = cjRet;
// Successful, so return size.
return (cjRet);
}
/******************************Public*Routine******************************\
* GetOutlineTextMetricsA
*
* Client side stub to GreGetOutlineTextMetrics.
*
* History:
* Tue 02-Nov-1993 -by- Bodin Dresevic [BodinD]
\**************************************************************************/
UINT APIENTRY GetOutlineTextMetricsA (
HDC hdc,
UINT cjCopy,
LPOUTLINETEXTMETRICA potma
)
{
return GetOutlineTextMetricsInternalA(hdc, cjCopy, potma);
}
/******************************Public*Routine******************************\
* *
* GetKerningPairs *
* *
* History: *
* Sun 23-Feb-1992 09:48:55 by Kirk Olynyk [kirko] *
* Wrote it. *
\**************************************************************************/
DWORD APIENTRY
GetKerningPairsW(
IN HDC hdc, // handle to application's DC
IN DWORD nPairs, // max no. KERNINGPAIR to be returned
OUT LPKERNINGPAIR lpKernPair // pointer to receiving buffer
)
{
ULONG sizeofMsg;
DWORD cRet = 0;
FIXUP_HANDLE(hdc);
if (nPairs == 0 && lpKernPair != (KERNINGPAIR*) NULL)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(0);
}
cRet = NtGdiGetKerningPairs(
hdc,
nPairs,
lpKernPair);
return(cRet);
}
/******************************Public*Routine******************************\
* GetKerningPairsA
*
* filters out pairs that are not contained in the code page of the font
* selected in DC
*
* History:
* 14-Mar-1996 -by- Xudong Wu [TessieW]
* Wrote it.
\**************************************************************************/
DWORD APIENTRY GetKerningPairsA
(
HDC hdc, // handle to application's DC
DWORD nPairs, // max no. KERNINGPAIR to be returned
LPKERNINGPAIR lpKernPair // pointer to receiving buffer
)
{
#define MAXKERNPAIR 300
DWORD i;
DWORD dwCP;
KERNINGPAIR tmpKernPair[MAXKERNPAIR];
DWORD cRet, cRet1;
KERNINGPAIR *pkp, *pkrn;
KERNINGPAIR UNALIGNED *pkrnLast;
BOOL bDBCS;
FIXUP_HANDLE(hdc);
if ((nPairs == 0) && (lpKernPair != (KERNINGPAIR*) NULL))
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(0);
}
cRet = NtGdiGetKerningPairs(hdc, 0, NULL);
if (cRet == 0)
return(cRet);
if (cRet <= MAXKERNPAIR)
pkrn = tmpKernPair;
else
pkrn = LOCALALLOC(cRet * sizeof(KERNINGPAIR));
if (!pkrn)
{
GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
cRet1 = NtGdiGetKerningPairs(hdc, cRet, pkrn);
if (cRet1 == 0 || cRet1 != cRet)
{
ASSERTGDI(FALSE, "NtGdiGetKerningPairs returns different values\n");
cRet = 0;
goto Cleanup;
}
pkp = pkrn;
pkrnLast = lpKernPair;
cRet = 0;
// GDI has returned iFirst and iSecond of the KERNINGPAIR structure in Unicode
// It is at this point that we translate them to the current code page
dwCP = GetCodePage(hdc);
bDBCS = IS_ANY_DBCS_CODEPAGE(dwCP);
for (i = 0; i < cRet1; i++,pkp++)
{
UCHAR ach[2], ach2[2];
BOOL bUsedDef[2];
ach[0] = ach[1] = 0; // insure zero extension
WideCharToMultiByte(dwCP,
0,
&(pkp->wFirst),
1,
ach,
sizeof(ach),
NULL,
&bUsedDef[0]);
if (!bUsedDef[0])
{
ach2[0] = ach2[1] = 0;
WideCharToMultiByte(dwCP,
0,
&(pkp->wSecond),
1,
ach2,
sizeof(ach2),
NULL,
&bUsedDef[1]);
if (!bUsedDef[1])
{
if (lpKernPair)
{
// do not overwrite the end of the buffer if it is provided
if (cRet >= nPairs)
break;
if (bDBCS)
{
if (IsDBCSLeadByteEx(dwCP,ach[0]))
{
pkrnLast->wFirst = (WORD)(ach[0] << 8 | ach[1]);
}
else
{
pkrnLast->wFirst = ach[0];
}
if (IsDBCSLeadByteEx(dwCP,ach2[0]))
{
pkrnLast->wSecond = (WORD)(ach2[0] << 8 | ach2[1]);
}
else
{
pkrnLast->wSecond = ach2[0];
}
}
else
{
pkrnLast->wFirst = ach[0];
pkrnLast->wSecond = ach2[0];
}
pkrnLast->iKernAmount = pkp->iKernAmount;
pkrnLast++;
}
cRet++;
}
}
}
Cleanup:
if (pkrn != tmpKernPair)
LOCALFREE(pkrn);
return cRet;
}
/*****************************Public*Routine******************************\
* FixBrushOrgEx
*
* for win32s
*
* History:
* 04-Jun-1992 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL FixBrushOrgEx(HDC hdc, int x, int y, LPPOINT ptl)
{
return(FALSE);
}
/******************************Public*Function*****************************\
* GetColorAdjustment
*
* Get the color adjustment data for a given DC.
*
* History:
* 07-Aug-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT pclradj)
{
FIXUP_HANDLE(hdc);
return(NtGdiGetColorAdjustment(hdc,pclradj));
}
/******************************Public*Routine******************************\
* GetETM
*
* Aldus Escape support
*
* History:
* 20-Oct-1993 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GetETM (HDC hdc, EXTTEXTMETRIC * petm)
{
BOOL bRet = FALSE;
FIXUP_HANDLE(hdc);
bRet = NtGdiGetETM(hdc,petm);
// path up the number of KerningPairs to match GetKerningPairsA
if (bRet && petm)
{
petm->etmNKernPairs = (WORD)GetKerningPairsA(hdc, 0, NULL);
}
return(bRet);
}
#if 0
/****************************Public*Routine********************************\
* GetCharWidthInfo
*
* Get the lMaxNegA lMaxNegC and lMinWidthD
*
* History:
* 09-Feb-1996 -by- Xudong Wu [tessiew]
* Wrote it
\***************************************************************************/
BOOL APIENTRY GetCharWidthInfo (HDC hdc, PCHWIDTHINFO pChWidthInfo)
{
return ( NtGdiGetCharWidthInfo(hdc, pChWidthInfo) );
}
#endif
#ifdef LANGPACK
/******************************Public*Routine******************************\
*
* bGetRealizationInfoInternal
*
* Retreives the realization_info from kernel, if not cached in shared
* memory
*
* History:
* 18-Aug-1997 -by- Samer Arafeh [SamerA]
* Wrote it.
\**************************************************************************/
BOOL bGetRealizationInfoInternal(
HDC hdc,
REALIZATION_INFO *pri,
CFONT *pcf
)
{
BOOL bRet = FALSE;
if (pri)
{
// if no pcf or we havn't cached the metrics
if ((pcf == NULL) || !(pcf->fl & CFONT_CACHED_RI) || pcf->timeStamp != pGdiSharedMemory->timeStamp)
{
REALIZATION_INFO ri;
PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if( pcf != NULL && (pcf->fl & CFONT_PUBLIC) )
bRet = NtGdiGetRealizationInfo(hdc,&ri, pcf->hf);
else
bRet = NtGdiGetRealizationInfo(hdc,&ri, 0);
if (bRet)
{
*pri = ri;
if (pcf && !(pcf->fl & CFONT_PUBLIC))
{
// we succeeded and we have a pcf so cache the data
pcf->ri = ri;
pcf->fl |= CFONT_CACHED_RI;
pcf->timeStamp = pGdiSharedMemory->timeStamp;
}
}
}
else
{
*pri = pcf->ri;
bRet = TRUE;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* GdiRealizationInfo
*
* Try retreive the RealizationInfo from shared memory
*
* History:
* 18-Aug-1997 -by- Samer Arafeh [SamerA]
* Wrote it.
\**************************************************************************/
BOOL APIENTRY GdiRealizationInfo(HDC hdc,REALIZATION_INFO *pri)
{
BOOL bRet = FALSE;
PDC_ATTR pDcAttr;
FIXUP_HANDLE(hdc);
PSHARED_GET_VALIDATE(pDcAttr,hdc,DC_TYPE);
if (pDcAttr)
{
CFONT * pcf;
ENTERCRITICALSECTION(&semLocal);
pcf = pcfLocateCFONT(hdc,pDcAttr,0,(PVOID) NULL,0,TRUE);
bRet = bGetRealizationInfoInternal(hdc,pri,pcf);
// pcfLocateCFONT added a reference so now we need to remove it
if (pcf)
{
DEC_CFONT_REF(pcf);
}
LEAVECRITICALSECTION(&semLocal);
}
else
{
// it could a public DC -OBJECT_OWNER_PUBLIC- (in which gpGdiShareMemory[hDC].pUser=NULL)
// so let's do it the expensive way by doing the kernel-transition...
bRet = NtGdiGetRealizationInfo(hdc,pri,0);
}
return(bRet);
}
#endif