Windows2003-3790/windows/appcompat/shims/specific/office9complexscript.cpp

211 lines
4.8 KiB
C++
Raw Permalink Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
RemoveComplexScriptExtraSpace.cpp
Abstract:
This shim fix regression bug from Win 2K regarding complex script showing problem.
ex) Reversed BiDi text.
Windows XP LPK turn off the complex script handling on the text which has extra spaces.
'Cause extra character space with complex script doesn't make sense. (tarekms)
This is a change from Windows 2000 and based on enabling font fallback for the FE languages.
Then as bug 547349 for Office 2000, we may see BiDi text doesn't appear correctly.
So far, reported problem is only for Hebrew and Arabic localized Office 2000 splash screen on .NET Server.
This shim removes extra space set by SetTextCharacterExtra() for ExtTextOutW and Complex Script text.
Notes:
This is a general shim for the potential generic problem of LPK.DLL on Win XP & .NET Server.
History:
04/18/2002 hioh Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(Office9ComplexScript)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(SetTextCharacterExtra)
APIHOOK_ENUM_ENTRY(ExtTextOutW)
APIHOOK_ENUM_END
CRITICAL_SECTION g_CriticalSection; // For multi thread safe
HDC g_hdc = NULL; // Remember HDC used in SetTextCharacterExtra()
int g_nCharExtra = 0; // Remember extra space value set in SetTextCharacterExtra()
/*++
Remember HDC and extra space value.
--*/
int
APIHOOK(SetTextCharacterExtra)(HDC hdc, int nCharExtra)
{
EnterCriticalSection(&g_CriticalSection);
if (hdc != g_hdc)
{
g_hdc = hdc; // Save hdc
}
g_nCharExtra = nCharExtra; // Save nCharExtra
LeaveCriticalSection(&g_CriticalSection);
return (ORIGINAL_API(SetTextCharacterExtra)(hdc, nCharExtra));
}
/*++
Function Description:
Check if BiDi character is in the string.
Arguments:
IN lpString - Pointer to the string
IN cbCount - Length to check
Return Value:
TRUE if BiDi char exist or FALSE if not
History:
04/17/2002 hioh Created
--*/
BOOL
IsBiDiString(
LPCWSTR lpString,
UINT cbCount
)
{
while (0 < cbCount--)
{
// Check if character is in Hebrew or Arabic code range
if ((0x0590 <= *lpString && *lpString <= 0x05ff) || (0x0600 <= *lpString && *lpString <= 0x06ff))
{
return TRUE;
}
lpString++;
}
return FALSE;
}
/*++
Remove Extra Space when Complex Script.
Revert Extra Space when removed and not Complex Script.
--*/
BOOL
APIHOOK(ExtTextOutW)(
HDC hdc,
int X,
int Y,
UINT fuOptions,
CONST RECT* lprc,
LPCWSTR lpString,
UINT cbCount,
CONST INT* lpDx
)
{
static HDC s_hdc = NULL;
static int s_nCharExtra = 0;
static BOOL s_bRemoveExtra = FALSE;
// Do nothing for ETO_GLYPH_INDEX and ETO_IGNORELANGUAGE
if (fuOptions & ETO_GLYPH_INDEX || fuOptions & ETO_IGNORELANGUAGE)
{
return (ORIGINAL_API(ExtTextOutW)(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx));
}
EnterCriticalSection(&g_CriticalSection);
if (hdc == g_hdc && g_nCharExtra > 0 && hdc != s_hdc)
{
// New handling
s_hdc = g_hdc;
s_nCharExtra = g_nCharExtra;
if (IsBiDiString(lpString, cbCount))
{
// Remove extra space
ORIGINAL_API(SetTextCharacterExtra)(hdc, 0);
s_bRemoveExtra = TRUE;
}
else
{
s_bRemoveExtra = FALSE;
}
}
else if (hdc == s_hdc && s_nCharExtra > 0)
{
// Handled before
if (IsBiDiString(lpString, cbCount))
{
// Remove extra space if not yet
if (!s_bRemoveExtra)
{
ORIGINAL_API(SetTextCharacterExtra)(hdc, 0);
s_bRemoveExtra = TRUE;
}
}
else
{
// Revert extra space if removed
if (s_bRemoveExtra)
{
ORIGINAL_API(SetTextCharacterExtra)(hdc, s_nCharExtra);
s_bRemoveExtra = FALSE;
}
}
}
LeaveCriticalSection(&g_CriticalSection);
return (ORIGINAL_API(ExtTextOutW)(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx));
}
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason
)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
return (InitializeCriticalSectionAndSpinCount(&g_CriticalSection, 0x80000000));
}
return TRUE;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY(GDI32.DLL, SetTextCharacterExtra)
APIHOOK_ENTRY(GDI32.DLL, ExtTextOutW)
HOOK_END
IMPLEMENT_SHIM_END