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.
 
 
 
 
 
 

928 lines
28 KiB

/******************************Module*Header*******************************\
* Module Name: nlsconv.c *
* *
* DBCS specific routines *
* *
* Created: 15-Mar-1994 15:56:30 *
* Author: Gerrit van Wingerden [gerritv] *
* *
* Copyright (c) 1994-1999 Microsoft Corporation *
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
UINT fFontAssocStatus = 0;
BYTE cLowTrailByteSet1 = 0xff;
BYTE cHighTrailByteSet1 = 0x0;
BYTE cLowTrailByteSet2 = 0xff;
BYTE cHighTrailByteSet2 = 0x0;
/******************************Public*Routine******************************\
* *
* DBCS Trailling Byte validate check functions. *
* *
\**************************************************************************/
#define IS_DBCS_TRAIL_BYTE(Char) (\
((Char >= cLowTrailByteSet1) && (Char <= cHighTrailByteSet1)) \
||((Char >= cLowTrailByteSet2) && (Char <= cHighTrailByteSet2)) \
)
/**************************************************************************\
* *
* SHIFT-JIS (Japanese) character set : CodePage 932 *
* *
* Valid LeadByte Range | Valid TailByte Range *
* -----------------------+--------------------- *
* From -> To | From -> To *
* - - - - - - - - - - - - - - - - - - - - - - - *
* 0x81 -> 0x9F | 0x40 -> 0xFC *
* 0xE0 -> 0xFC | *
* *
\**************************************************************************/
/**************************************************************************\
* *
* WANSANG (Korean) character set : CodePage 949 *
* *
* Valid LeadByte Range | Valid TailByte Range *
* -----------------------+--------------------- *
* From -> To | From -> To *
* - - - - - - - - - - - - - - - - - - - - - - - *
* 0xA1 -> 0xAC | 0x40 -> 0xFC *
* 0xB0 -> 0xC8 | *
* 0xCA -> 0xFD | *
* *
\**************************************************************************/
/**************************************************************************\
* *
* GB2312 (PRC Chinese) character set : CodePage 936 *
* *
* Valid LeadByte Range | Valid TailByte Range *
* -----------------------+--------------------- *
* From -> To | From -> To *
* - - - - - - - - - - - - - - - - - - - - - - - *
* 0xA1 -> 0xA9 | 0xA1 -> 0xFE *
* 0xB0 -> 0xF7 | *
* *
\**************************************************************************/
/**************************************************************************\
* *
* Big 5 (Taiwan,Hong Kong Chinese) character set : CodePage 950 *
* *
* Valid LeadByte Range | Valid TailByte Range *
* -----------------------+--------------------- *
* From -> To | From -> To *
* - - - - - - - - - - - - - - - - - - - - - - - *
* 0x81 -> 0xFE | 0x40 -> 0x7E *
* | 0xA1 -> 0xFE *
* *
\**************************************************************************/
/******************************Public*Routine******************************\
* vSetCheckDBCSTrailByte()
*
* This function setup function for the DBCS trailling byte validation of
* specified character with specified Fareast codepage.
*
* Thu-15-Feb-1996 11:59:00 -by- Gerrit van Wingerden
* Moved function pointer out of CFONT and into a global variable.
*
* Wed 20-Dec-1994 10:00:00 -by- Hideyuki Nagase [hideyukn]
* Write it.
\**************************************************************************/
VOID vSetCheckDBCSTrailByte(DWORD dwCodePage)
{
switch( dwCodePage )
{
case 932:
cLowTrailByteSet1 = (CHAR) 0x40;
cHighTrailByteSet1 = (CHAR) 0xfc;
cLowTrailByteSet2 = (CHAR) 0x40;
cHighTrailByteSet2 = (CHAR) 0xfc;
break;
case 949:
cLowTrailByteSet1 = (CHAR) 0x40;
cHighTrailByteSet1 = (CHAR) 0xfc;
cLowTrailByteSet2 = (CHAR) 0x40;
cHighTrailByteSet2 = (CHAR) 0xfc;
break;
case 936:
cLowTrailByteSet1 = (CHAR) 0xa1;
cHighTrailByteSet1 = (CHAR) 0xfe;
cLowTrailByteSet2 = (CHAR) 0xa1;
cHighTrailByteSet2 = (CHAR) 0xfe;
break;
case 950:
cLowTrailByteSet1 = (CHAR) 0x40;
cHighTrailByteSet1 = (CHAR) 0x7e;
cLowTrailByteSet2 = (CHAR) 0xa1;
cHighTrailByteSet2 = (CHAR) 0xfe;
break;
default:
cLowTrailByteSet1 = (CHAR) 0xff;
cHighTrailByteSet1 = (CHAR) 0x0;
cLowTrailByteSet2 = (CHAR) 0xff;
cHighTrailByteSet2 = (CHAR) 0x0;
WARNING("GDI32!INVALID DBCS codepage\n");
break;
}
}
/******************************Public*Routine******************************\
* bComputeCharWidthsDBCS
*
* Client side version of GetCharWidth for DBCS fonts
*
* Wed 18-Aug-1993 10:00:00 -by- Gerrit van Wingerden [gerritv]
* Stole it and converted for DBCS use.
*
* Sat 16-Jan-1993 04:27:19 -by- Charles Whitmer [chuckwh]
* Wrote bComputeCharWidths on which this is based.
\**************************************************************************/
BOOL bComputeCharWidthsDBCS
(
CFONT *pcf,
UINT iFirst,
UINT iLast,
ULONG fl,
PVOID pv
)
{
USHORT *ps;
USHORT ausWidths[256];
UINT ii, cc;
if( iLast - iFirst > 0xFF )
{
WARNING("bComputeCharWidthsDBCS iLast - iFirst > 0xFF" );
return(FALSE);
}
if( iLast < iFirst )
{
WARNING("bComputeCharWidthsDBCS iLast < iFirst" );
return(FALSE);
}
// We want to compute the same widths that would be computed if
// vSetUpUnicodeStringx were called with this first and last and then
// GetCharWidthsW was called. The logic may be wierd but I assume it is
// there for Win 3.1J char widths compatability. To do this first fill
// in the plain widths in ausWidths and then do all the neccesary
// computation on them.
if ( gpwcDBCSCharSet[(UCHAR)(iFirst>>8)] == 0xFFFF )
{
for( cc = 0 ; cc <= iLast - iFirst; cc++ )
{
// If this is a legitimate DBCS character then use
// MaxCharInc.
ausWidths[cc] = pcf->wd.sDBCSInc;
}
}
else
{
for( ii = (iFirst & 0x00FF), cc = 0; ii <= (iLast & 0x00FF); cc++, ii++ )
{
// Just treat everything as a single byte unless we
// encounter a DBCS lead byte which we will treat as a
// default character.
if( gpwcDBCSCharSet[ii] == 0xFFFF )
{
ausWidths[cc] = pcf->wd.sDefaultInc;
}
else
{
ausWidths[cc] = pcf->sWidth[ii];
}
}
}
switch (fl & (GCW_INT | GCW_16BIT))
{
case GCW_INT: // Get LONG widths.
{
LONG *pl = (LONG *) pv;
LONG fxOverhang = 0;
// Check for Win 3.1 compatibility.
if (fl & GCW_WIN3)
fxOverhang = pcf->wd.sOverhang;
// Do the trivial no-transform case.
if (bIsOneSixteenthEFLOAT(pcf->efDtoWBaseline))
{
fxOverhang += 8; // To round the final result.
// for (ii=iFirst; ii<=iLast; ii++)
// *pl++ = (pcf->sWidth[ii] + fxOverhang) >> 4;
ps = ausWidths;
ii = iLast - iFirst;
unroll_1:
switch(ii)
{
default:
pl[4] = (ps[4] + fxOverhang) >> 4;
case 3:
pl[3] = (ps[3] + fxOverhang) >> 4;
case 2:
pl[2] = (ps[2] + fxOverhang) >> 4;
case 1:
pl[1] = (ps[1] + fxOverhang) >> 4;
case 0:
pl[0] = (ps[0] + fxOverhang) >> 4;
}
if (ii > 4)
{
ii -= 5;
pl += 5;
ps += 5;
goto unroll_1;
}
return(TRUE);
}
// Otherwise use the back transform.
else
{
for (ii=0; ii<=iLast-iFirst; ii++)
*pl++ = lCvt(pcf->efDtoWBaseline,ausWidths[ii] + fxOverhang);
return(TRUE);
}
}
case GCW_INT+GCW_16BIT: // Get SHORT widths.
{
USHORT *psDst = (USHORT *) pv;
USHORT fsOverhang = 0;
// Check for Win 3.1 compatibility.
if (fl & GCW_WIN3)
fsOverhang = pcf->wd.sOverhang;
// Do the trivial no-transform case.
if (bIsOneSixteenthEFLOAT(pcf->efDtoWBaseline))
{
fsOverhang += 8; // To round the final result.
// for (ii=iFirst; ii<=iLast; ii++)
// *psDst++ = (pcf->sWidth[ii] + fsOverhang) >> 4;
ps = ausWidths;
ii = iLast - iFirst;
unroll_2:
switch(ii)
{
default:
psDst[4] = (ps[4] + fsOverhang) >> 4;
case 3:
psDst[3] = (ps[3] + fsOverhang) >> 4;
case 2:
psDst[2] = (ps[2] + fsOverhang) >> 4;
case 1:
psDst[1] = (ps[1] + fsOverhang) >> 4;
case 0:
psDst[0] = (ps[0] + fsOverhang) >> 4;
}
if (ii > 4)
{
ii -= 5;
psDst += 5;
ps += 5;
goto unroll_2;
}
return(TRUE);
}
// Otherwise use the back transform.
else
{
for (ii=0; ii<=iLast-iFirst; ii++)
{
*psDst++ = (USHORT)
lCvt
(
pcf->efDtoWBaseline,
(LONG) (ausWidths[ii] + fsOverhang)
);
}
return(TRUE);
}
}
case 0: // Get FLOAT widths.
{
LONG *pe = (LONG *) pv; // Cheat to avoid expensive copies.
EFLOAT_S efWidth,efWidthLogical;
for (ii=0; ii<=iLast-iFirst; ii++)
{
vFxToEf((LONG) ausWidths[ii],efWidth);
vMulEFLOAT(efWidthLogical,efWidth,pcf->efDtoWBaseline);
*pe++ = lEfToF(efWidthLogical);
}
return(TRUE);
}
}
RIP("bComputeCharWidths: Don't come here!\n");
return(FALSE);
}
BOOL bIsDBCSString
(
LPCSTR psz,
int cc
)
{
int ii;
BYTE *pc;
pc = (BYTE *) psz;
cc--; // do not go off the edge !
for (ii=0; ii<cc; ii++)
{
// if DBCS lead byte add in DBCS width
if((gpwcDBCSCharSet[pc[ii]] == 0xFFFF)) // is this a DBCS LeadByte
{
return TRUE;
}
}
return FALSE;
}
/******************************Public*Routine******************************\
* bComputeTextExtentDBCS (pldc,pcf,psz,cc,fl,psizl)
*
* A quick function to compute text extents on the client side for DBCS
* fonts.
*
* Tue 17-Aug-1993 10:00:00 -by- Gerrit van Wingerden [gerritv]
* Stole it and converted for DBCS use.
*
* Thu 14-Jan-1993 04:00:57 -by- Charles Whitmer [chuckwh]
* Wrote bComputeTextExtent from which this was stolen.
\**************************************************************************/
BOOL bComputeTextExtentDBCS
(
PDC_ATTR pDcAttr,
CFONT *pcf,
LPCSTR psz,
int cc,
UINT fl,
SIZE *psizl
)
{
LONG fxBasicExtent;
INT lTextExtra,lBreakExtra,cBreak;
INT cChars = 0;
int ii;
BYTE *pc;
FIX fxCharExtra = 0;
FIX fxBreakExtra;
FIX fxExtra = 0;
lTextExtra = pDcAttr->lTextExtra;
lBreakExtra = pDcAttr->lBreakExtra;
cBreak = pDcAttr->cBreak;
pc = (BYTE *) psz;
// Compute the basic extent.
fxBasicExtent = 0;
pc = (BYTE *) psz;
for (ii=0; ii<cc; ii++)
{
// if DBCS lead byte add in DBCS width
if( /* Check the string has two bytes or more ? */
cc - ii - 1 &&
/* Check Is this a DBCS LeadByte ? */
gpwcDBCSCharSet[*pc] == 0xFFFF &&
/* Check Is this a DBCS TrailByte ? */
IS_DBCS_TRAIL_BYTE((*(pc+sizeof(CHAR))))
)
{
ii++;
pc += 2;
fxBasicExtent += pcf->wd.sDBCSInc;
}
else
{
fxBasicExtent += pcf->sWidth[*pc++];
}
cChars += 1;
}
// Adjust for CharExtra.
if (lTextExtra)
{
int cNoBackup = 0;
fxCharExtra = lCvt(pcf->efM11,lTextExtra);
if( fxCharExtra < 0 )
{
// the layout code won't backup a characters past it's origin regardless
// of the value of iTextCharExtra so figure out for how many values
// we will need to ignore fxCharExtra
if( pcf->wd.sCharInc == 0 )
{
for( ii = 0; ii < cc; ii++ )
{
if( gpwcDBCSCharSet[(BYTE)psz[ii]] == 0xFFFF )
{
if( pcf->wd.sDBCSInc + fxCharExtra <= 0 )
{
cNoBackup += 1;
}
ii++;
}
else
{
if( pcf->sWidth[(BYTE)psz[ii]] + fxCharExtra <= 0 )
{
cNoBackup += 1;
}
}
}
}
else
if( pcf->wd.sCharInc + fxCharExtra <= 0 )
{
cNoBackup = cChars;
}
}
if ( (fl & GGTE_WIN3_EXTENT) && (pcf->hdc == 0)
&& (!(pcf->flInfo & FM_INFO_TECH_STROKE)) )
fxExtra = fxCharExtra * ((lTextExtra > 0) ? cChars : (cChars - 1));
else
fxExtra = fxCharExtra * ( cChars - cNoBackup );
}
// Adjust for lBreakExtra.
if (lBreakExtra && cBreak)
{
fxBreakExtra = lCvt(pcf->efM11,lBreakExtra) / cBreak;
// Windows won't let us back up over a break. Set up the BreakExtra
// to just cancel out what we've already got.
if (fxBreakExtra + pcf->wd.sBreak + fxCharExtra < 0)
fxBreakExtra = -(pcf->wd.sBreak + fxCharExtra);
// Add it up for all breaks.
pc = (BYTE *) psz;
for (ii=0; ii<cc; ii++)
{
if (gpwcDBCSCharSet[*pc] == 0xFFFF)
{
ii++;
pc += 2;
}
else if (*pc++ == pcf->wd.iBreak)
{
fxExtra += fxBreakExtra;
}
}
}
// Add in the extra stuff.
fxBasicExtent += fxExtra;
// Add in the overhang for font simulations.
if (fl & GGTE_WIN3_EXTENT)
fxBasicExtent += pcf->wd.sOverhang;
// Transform the result to logical coordinates.
if (bIsOneSixteenthEFLOAT(pcf->efDtoWBaseline))
psizl->cx = (fxBasicExtent + 8) >> 4;
else
psizl->cx = lCvt(pcf->efDtoWBaseline,fxBasicExtent);
psizl->cy = pcf->lHeight;
return(TRUE);
}
/******************************Public*Routine*****************************\
* QueryFontAssocStatus() *
* *
* History: *
* 05-Jan-1994 -by- Pi-Sui Hsu [pisuih] *
* Wrote it. *
\*************************************************************************/
UINT APIENTRY QueryFontAssocStatus( VOID )
{
return(fFontAssocStatus);
}
INT APIENTRY GetFontAssocStatus( HDC hdc )
{
if(hdc == NULL)
{
return(0);
}
else
{
return(NtGdiQueryFontAssocInfo(hdc));
}
}
BOOL bToUnicodeNx(LPWSTR pwsz, LPCSTR psz, DWORD c, UINT codepage)
{
if(fFontAssocStatus &&
((codepage == GetACP() || codepage == CP_ACP)) &&
((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..
//
codepage = 1252;
}
if(MultiByteToWideChar(codepage, 0, psz, c, pwsz, c))
{
return(TRUE);
}
else
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
}
/******************************Public*Routine******************************\
*
* vSetUpUnicodeStringx
*
* Effects:
*
* Warnings:
*
* History:
* 14-Mar-1993 -by- Hideyuki Nagase [hideyukn]
* Change hardcoded default character to defulat char is given as a parameter.
*
* 01-Mar-1993 -by- Takao Kitano [takaok]
* Wrote it.
\**************************************************************************/
BOOL bSetUpUnicodeStringDBCS
(
IN UINT iFirst, // first ansi char
IN UINT iLast, // last char
IN PUCHAR puchTmp, // temporary buffer
OUT PWCHAR pwc, // output fuffer with a unicode string
IN UINT uiCodePage, // ansi codepage
IN CHAR chDefaultChar // default character
)
{
PUCHAR puchBuf;
BOOL bRet = FALSE;
puchBuf = puchTmp;
if(IsDBCSLeadByteEx(uiCodePage,(UCHAR)(iFirst >> 8)))
{
// This is DBCS character strings.
for (; iFirst <= iLast; iFirst++ )
{
*puchBuf++ = (UCHAR)(iFirst >> 8);
*puchBuf++ = (UCHAR)(iFirst);
}
}
else
{
// This is SBCS character strings.
// if Hi-byte of iFirst is not valid DBCS LeadByte , we use only
// lo-byte of it.
for ( ; iFirst <= iLast; iFirst++ )
{
// If this SBCS code in LeadByte area . It replce with default
// character
if ( IsDBCSLeadByteEx(uiCodePage,(UCHAR)iFirst) )
*puchBuf++ = chDefaultChar;
else
*puchBuf++ = (UCHAR)iFirst;
}
}
//Sundown: safe to truncate to DWORD since puchBug - puchTmp won't exceed iLast
bRet = bToUnicodeNx(pwc, puchTmp, (DWORD)(puchBuf - puchTmp), uiCodePage);
return(bRet);
}
BOOL IsValidDBCSRange( UINT iFirst , UINT iLast )
{
// DBCS & SBCS char parameter checking for DBCS font
if( iFirst > 0x00ff )
{
// DBCS char checking for DBCS font
if (
// Check limit
(iFirst > 0xffff) || (iLast > 0xffff) ||
// DBCSLeadByte shoud be same
(iFirst & 0xff00) != (iLast & 0xff00) ||
// DBCSTrailByte of the First should be >= one of the Last
(iFirst & 0x00ff) > (iLast & 0x00ff)
)
{
return(FALSE);
}
}
// DBCS char checking for DBCS font
else if( (iFirst > iLast) || (iLast & 0xffffff00) )
{
return(FALSE);
}
return(TRUE);
}
/******************************Private*Routine*****************************\
* GetCurrentDefaultChar()
*
* History:
*
* Mon 15-Mar-1993 18:14:00 -by- Hideyuki Nagase
* wrote it.
***************************************************************************/
BYTE GetCurrentDefaultChar(HDC hdc)
{
// WINBUG 365031 4-10-2001 pravins Consider optimization in GetCurrentDeafultChar
//
// Old Comment:
// - This is slow for now. We should cache this value locally in the dcattr
// but want to get other things working for now. [gerritv] 2-22-96
TEXTMETRICA tma;
GetTextMetricsA( hdc , &tma );
return(tma.tmDefaultChar);
}
/***************************************************************************
* ConvertDxArray(UINT, char*, INT*, UINT, INT*)
*
* Tue 27-Feb-1996 23:45:00 -by- Gerrit van Wingerden [gerritv]
*
***************************************************************************/
void ConvertDxArray(UINT CodePage,
char *pDBCSString,
INT *pDxDBCS,
UINT Count,
INT *pDxUnicode,
BOOL bPdy
)
{
char *pDBCSStringEnd;
if (!bPdy)
{
for(pDBCSStringEnd = pDBCSString + Count;
pDBCSString < pDBCSStringEnd;
)
{
if(IsDBCSLeadByteEx(CodePage,*pDBCSString))
{
pDBCSString += 2;
*pDxUnicode = *pDxDBCS++;
*pDxUnicode += *pDxDBCS++;
}
else
{
pDBCSString += 1;
*pDxUnicode = *pDxDBCS++;
}
pDxUnicode += 1;
}
}
else
{
POINTL *pdxdyUnicode = (POINTL *)pDxUnicode;
POINTL *pdxdyDBCS = (POINTL *)pDxDBCS;
for(pDBCSStringEnd = pDBCSString + Count;
pDBCSString < pDBCSStringEnd;
)
{
if(IsDBCSLeadByteEx(CodePage,*pDBCSString))
{
pDBCSString += 2;
*pdxdyUnicode = *pdxdyDBCS++;
pdxdyUnicode->x += pdxdyDBCS->x;
pdxdyUnicode->y += pdxdyDBCS->y;
pdxdyDBCS++;
}
else
{
pDBCSString += 1;
*pdxdyUnicode = *pdxdyDBCS++;
}
pdxdyUnicode++;
}
}
}
ULONG APIENTRY EudcLoadLinkW
(
LPCWSTR pBaseFaceName,
LPCWSTR pEudcFontPath,
INT iPriority,
INT iFontLinkType
)
{
return(NtGdiEudcLoadUnloadLink(pBaseFaceName,
(pBaseFaceName) ? wcslen(pBaseFaceName) : 0,
pEudcFontPath,
wcslen(pEudcFontPath),
iPriority,
iFontLinkType,
TRUE));
}
BOOL APIENTRY EudcUnloadLinkW
(
LPCWSTR pBaseFaceName,
LPCWSTR pEudcFontPath
)
{
return(NtGdiEudcLoadUnloadLink(pBaseFaceName,
(pBaseFaceName) ? wcslen(pBaseFaceName) : 0,
pEudcFontPath,
wcslen(pEudcFontPath),
0,
0,
FALSE));
}
ULONG APIENTRY GetEUDCTimeStampExW
(
LPCWSTR pBaseFaceName
)
{
return(NtGdiGetEudcTimeStampEx((LPWSTR) pBaseFaceName,
(pBaseFaceName) ? wcslen(pBaseFaceName) : 0,
FALSE));
}
ULONG APIENTRY GetEUDCTimeStamp()
{
return(NtGdiGetEudcTimeStampEx(NULL,0,TRUE));
}
UINT
GetStringBitmapW(
HDC hdc,
LPWSTR pwc,
UINT cwc,
UINT cbData,
BYTE *pSB
)
{
if(cwc != 1)
{
return(0);
}
return(NtGdiGetStringBitmapW(hdc,pwc,1,(PBYTE) pSB,cbData));
}
UINT
GetStringBitmapA(
HDC hdc,
LPSTR pc,
UINT cch,
UINT cbData,
BYTE *pSB
)
{
WCHAR Character[2];
if(cch > 2 )
{
return(0);
}
if(MultiByteToWideChar(CP_ACP,0,pc,cch,Character,2)!=1)
{
return(0);
}
return(GetStringBitmapW(hdc,Character,1,cbData,pSB));
}
DWORD FontAssocHack(DWORD dwCodePage, CHAR *psz, UINT c)
{
// If a Text 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..
ASSERTGDI(fFontAssocStatus,
"FontAssocHack called with FontAssocStatus turned off\n");
if(((dwCodePage == GetACP() || dwCodePage == CP_ACP)) &&
((c == 1) || ((c == 2 && *(psz) && *((LPCSTR)(psz + 1)) == '\0'))))
{
return(1252);
}
else
{
return(dwCodePage);
}
}