211 lines
4.8 KiB
C++
211 lines
4.8 KiB
C++
|
/*++
|
||
|
|
||
|
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
|