682 lines
20 KiB
C++
682 lines
20 KiB
C++
|
/****************************** Module*Header *****************************\
|
||
|
* Module Name: rtlmir.c *
|
||
|
* *
|
||
|
* This module contains all the Right-To-Left (RTL) Mirroring support *
|
||
|
* routines which are used across the whole IShell project. It abstracts *
|
||
|
* platform-support routines of RTL mirroring (NT5 and Memphis) and removes *
|
||
|
* linkage depedenency with the Mirroring APIs. *
|
||
|
* *
|
||
|
* Functions prefixed with Mirror, deal with the new Mirroring APIs *
|
||
|
* *
|
||
|
* *
|
||
|
* Created: 01-Feb-1998 8:41:18 pm *
|
||
|
* Author: Samer Arafeh [samera] *
|
||
|
* *
|
||
|
* Copyright (c) 1998 Microsoft Corporation *
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#include "..\stock.h"
|
||
|
|
||
|
#if (WINVER < 0x0500)
|
||
|
#error WINVER setting must be >= 0x0500
|
||
|
#endif
|
||
|
|
||
|
#ifndef DS_BIDI_RTL
|
||
|
#define DS_BIDI_RTL 0x8000
|
||
|
#endif
|
||
|
|
||
|
const DWORD dwNoMirrorBitmap = NOMIRRORBITMAP;
|
||
|
const DWORD dwExStyleRTLMirrorWnd = WS_EX_LAYOUTRTL;
|
||
|
const DWORD dwExStyleNoInheritLayout = WS_EX_NOINHERITLAYOUT;
|
||
|
const DWORD dwPreserveBitmap = LAYOUT_BITMAPORIENTATIONPRESERVED;
|
||
|
|
||
|
/*
|
||
|
* Remove linkage dependecy for the RTL mirroring APIs, by retreiving
|
||
|
* their addresses at runtime.
|
||
|
*/
|
||
|
typedef DWORD (WINAPI *PFNGETLAYOUT)(HDC); // gdi32!GetLayout
|
||
|
typedef DWORD (WINAPI *PFNSETLAYOUT)(HDC, DWORD); // gdi32!SetLayout
|
||
|
typedef BOOL (WINAPI *PFNSETPROCESSDEFLAYOUT)(DWORD); // user32!SetProcessDefaultLayout
|
||
|
typedef BOOL (WINAPI *PFNGETPROCESSDEFLAYOUT)(DWORD*); // user32!GetProcessDefaultLayout
|
||
|
typedef LANGID (WINAPI *PFNGETUSERDEFAULTUILANGUAGE)(void); // kernel32!GetUserDefaultUILanguage
|
||
|
typedef BOOL (WINAPI *PFNENUMUILANGUAGES)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR); // kernel32!EnumUILanguages
|
||
|
|
||
|
typedef struct {
|
||
|
LANGID LangID;
|
||
|
BOOL bInstalled;
|
||
|
} MUIINSTALLLANG, *LPMUIINSTALLLANG;
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
#define ConvertHexStringToInt ConvertHexStringToIntW
|
||
|
#else
|
||
|
#define ConvertHexStringToInt ConvertHexStringToIntA
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* ConvertHexStringToIntA
|
||
|
*
|
||
|
* Converts a hex numeric string into an integer.
|
||
|
*
|
||
|
* History:
|
||
|
* 04-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
BOOL ConvertHexStringToIntA( CHAR *pszHexNum , int *piNum )
|
||
|
{
|
||
|
int n=0L;
|
||
|
CHAR *psz=pszHexNum;
|
||
|
|
||
|
|
||
|
for(n=0 ; ; psz=CharNextA(psz))
|
||
|
{
|
||
|
if( (*psz>='0') && (*psz<='9') )
|
||
|
n = 0x10 * n + *psz - '0';
|
||
|
else
|
||
|
{
|
||
|
CHAR ch = *psz;
|
||
|
int n2;
|
||
|
|
||
|
if(ch >= 'a')
|
||
|
ch -= 'a' - 'A';
|
||
|
|
||
|
n2 = ch - 'A' + 0xA;
|
||
|
if (n2 >= 0xA && n2 <= 0xF)
|
||
|
n = 0x10 * n + n2;
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Update results
|
||
|
*/
|
||
|
*piNum = n;
|
||
|
|
||
|
return (psz != pszHexNum);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* ConvertHexStringToIntW
|
||
|
*
|
||
|
* Converts a hex numeric string into an integer.
|
||
|
*
|
||
|
* History:
|
||
|
* 14-June-1998 msadek Created
|
||
|
\***************************************************************************/
|
||
|
BOOL ConvertHexStringToIntW( WCHAR *pszHexNum , int *piNum )
|
||
|
{
|
||
|
int n=0L;
|
||
|
WCHAR *psz=pszHexNum;
|
||
|
|
||
|
|
||
|
for(n=0 ; ; psz=CharNextW(psz))
|
||
|
{
|
||
|
if( (*psz>='0') && (*psz<='9') )
|
||
|
n = 0x10 * n + *psz - '0';
|
||
|
else
|
||
|
{
|
||
|
WCHAR ch = *psz;
|
||
|
int n2;
|
||
|
|
||
|
if(ch >= 'a')
|
||
|
ch -= 'a' - 'A';
|
||
|
|
||
|
n2 = ch - 'A' + 0xA;
|
||
|
if (n2 >= 0xA && n2 <= 0xF)
|
||
|
n = 0x10 * n + n2;
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Update results
|
||
|
*/
|
||
|
*piNum = n;
|
||
|
|
||
|
return (psz != pszHexNum);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* IsBiDiLocalizedSystemEx
|
||
|
*
|
||
|
* returns TRUE if running on a lozalized BiDi (Arabic/Hebrew) NT5 or Memphis.
|
||
|
* Should be called whenever SetProcessDefaultLayout is to be called.
|
||
|
*
|
||
|
* History:
|
||
|
* 02-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
|
||
|
BOOL IsBiDiLocalizedSystemEx( LANGID *pLangID )
|
||
|
{
|
||
|
int iLCID=0L;
|
||
|
static TRIBIT s_tbBiDi = TRIBIT_UNDEFINED;
|
||
|
static LANGID s_langID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
|
||
|
|
||
|
if (s_tbBiDi == TRIBIT_UNDEFINED)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
if(staticIsOS(OS_WIN2000ORGREATER))
|
||
|
{
|
||
|
/*
|
||
|
* Need to use NT5 detection method (Multiligual UI ID)
|
||
|
*/
|
||
|
s_langID = Mirror_GetUserDefaultUILanguage();
|
||
|
|
||
|
if(s_langID)
|
||
|
{
|
||
|
WCHAR wchLCIDFontSignature[16];
|
||
|
iLCID = MAKELCID(s_langID, SORT_DEFAULT );
|
||
|
|
||
|
/*
|
||
|
* Let's verify this is a RTL (BiDi) locale. Since reg value is a hex string, let's
|
||
|
* convert to decimal value and call GetLocaleInfo afterwards.
|
||
|
* LOCALE_FONTSIGNATURE always gives back 16 WCHARs.
|
||
|
*/
|
||
|
|
||
|
if( GetLocaleInfoW( iLCID ,
|
||
|
LOCALE_FONTSIGNATURE ,
|
||
|
(WCHAR *) &wchLCIDFontSignature[0] ,
|
||
|
(sizeof(wchLCIDFontSignature)/sizeof(WCHAR))) )
|
||
|
{
|
||
|
|
||
|
/* Let's verify the bits we have a BiDi UI locale */
|
||
|
if(( wchLCIDFontSignature[7] & (WCHAR)0x0800) && Mirror_IsUILanguageInstalled(s_langID) )
|
||
|
{
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
* Check if BiDi-Memphis is running with Lozalized Resources (
|
||
|
* i.e. Arabic/Hebrew systems) -It should be enabled ofcourse-.
|
||
|
*/
|
||
|
if( (staticIsOS(OS_WIN98ORGREATER)) && (GetSystemMetrics(SM_MIDEASTENABLED)) )
|
||
|
{
|
||
|
HKEY hKey;
|
||
|
|
||
|
if( RegOpenKeyExA( HKEY_CURRENT_USER ,
|
||
|
"Control Panel\\Desktop\\ResourceLocale" ,
|
||
|
0,
|
||
|
KEY_READ, &hKey) == ERROR_SUCCESS)
|
||
|
{
|
||
|
CHAR szResourceLocale[12];
|
||
|
DWORD dwSize = sizeof(szResourceLocale);
|
||
|
RegQueryValueExA( hKey , "" , 0 , NULL, (LPBYTE)szResourceLocale , &dwSize );
|
||
|
szResourceLocale[(sizeof(szResourceLocale)/sizeof(CHAR))-1] = 0;
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if( ConvertHexStringToIntA( szResourceLocale , &iLCID ) )
|
||
|
{
|
||
|
iLCID = PRIMARYLANGID(LANGIDFROMLCID(iLCID));
|
||
|
if( (LANG_ARABIC == iLCID) || (LANG_HEBREW == iLCID) )
|
||
|
{
|
||
|
bRet = TRUE;
|
||
|
s_langID = LANGIDFROMLCID(iLCID);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
COMPILETIME_ASSERT(sizeof(s_tbBiDi) == sizeof(long));
|
||
|
// close multiproc race on startup
|
||
|
InterlockedExchange((long*)&s_tbBiDi, bRet ? TRIBIT_TRUE : TRIBIT_FALSE);
|
||
|
}
|
||
|
|
||
|
if (s_tbBiDi == TRIBIT_TRUE && pLangID)
|
||
|
{
|
||
|
*pLangID = s_langID;
|
||
|
}
|
||
|
|
||
|
return (s_tbBiDi == TRIBIT_TRUE);
|
||
|
}
|
||
|
|
||
|
BOOL IsBiDiLocalizedSystem( void )
|
||
|
{
|
||
|
return IsBiDiLocalizedSystemEx(NULL);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* IsBiDiLocalizedWin95
|
||
|
*
|
||
|
* returns TRUE if running on a lozalized BiDi (Arabic/Hebrew) Win95.
|
||
|
* Needed for legacy operating system check for needed RTL UI elements
|
||
|
* For example, DefView ListView, TreeView,...etc
|
||
|
* History:
|
||
|
* 12-June-1998 a-msadek Created
|
||
|
\***************************************************************************/
|
||
|
BOOL IsBiDiLocalizedWin95(BOOL bArabicOnly)
|
||
|
{
|
||
|
HKEY hKey;
|
||
|
DWORD dwType;
|
||
|
BOOL bRet = FALSE;
|
||
|
CHAR szResourceLocale[12];
|
||
|
DWORD dwSize = sizeof(szResourceLocale)/sizeof(CHAR);
|
||
|
int iLCID=0L;
|
||
|
|
||
|
/*
|
||
|
* Check if BiDi-Win95 is running with Lozalized Resources (
|
||
|
* i.e. Arabic/Hebrew systems) -It should be enabled ofcourse-.
|
||
|
*/
|
||
|
if( (staticIsOS(OS_WIN95ORGREATER)) && (!staticIsOS(OS_WIN98ORGREATER)) && (GetSystemMetrics(SM_MIDEASTENABLED)) )
|
||
|
{
|
||
|
|
||
|
if( RegOpenKeyExA( HKEY_CURRENT_USER ,
|
||
|
"Control Panel\\Desktop\\ResourceLocale" ,
|
||
|
0,
|
||
|
KEY_READ, &hKey) == ERROR_SUCCESS)
|
||
|
{
|
||
|
RegQueryValueExA( hKey , "" , 0 , &dwType , (LPBYTE)szResourceLocale , &dwSize );
|
||
|
szResourceLocale[(sizeof(szResourceLocale)/sizeof(CHAR))-1] = 0;
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if( ConvertHexStringToIntA( szResourceLocale , &iLCID ) )
|
||
|
{
|
||
|
iLCID = PRIMARYLANGID(LANGIDFROMLCID(iLCID));
|
||
|
//
|
||
|
//If bArabicOnly we will return true if it a Arabic Win95 localized.
|
||
|
//
|
||
|
if( (LANG_ARABIC == iLCID) || ((LANG_HEBREW == iLCID) && !bArabicOnly ))
|
||
|
{
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_IsEnabledOS
|
||
|
*
|
||
|
* returns TRUE if the mirroring APIs are enabled on the current OS.
|
||
|
*
|
||
|
* History:
|
||
|
* 02-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
BOOL Mirror_IsEnabledOS( void )
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
if(staticIsOS(OS_WIN2000ORGREATER))
|
||
|
{
|
||
|
bRet = TRUE;
|
||
|
} else if( staticIsOS(OS_WIN98ORGREATER) && GetSystemMetrics(SM_MIDEASTENABLED)) {
|
||
|
bRet=TRUE;
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_GetUserDefaultUILanguage
|
||
|
*
|
||
|
* Reads the User UI language on NT5
|
||
|
*
|
||
|
* History:
|
||
|
* 22-June-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
LANGID Mirror_GetUserDefaultUILanguage( void )
|
||
|
{
|
||
|
LANGID langId=0;
|
||
|
static PFNGETUSERDEFAULTUILANGUAGE pfnGetUserDefaultUILanguage=NULL;
|
||
|
|
||
|
if( NULL == pfnGetUserDefaultUILanguage )
|
||
|
{
|
||
|
HMODULE hmod = GetModuleHandleA("KERNEL32");
|
||
|
|
||
|
if( hmod )
|
||
|
pfnGetUserDefaultUILanguage = (PFNGETUSERDEFAULTUILANGUAGE)
|
||
|
GetProcAddress(hmod, "GetUserDefaultUILanguage");
|
||
|
}
|
||
|
|
||
|
if( pfnGetUserDefaultUILanguage )
|
||
|
langId = pfnGetUserDefaultUILanguage();
|
||
|
|
||
|
return langId;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_IsUILanguageInstalled
|
||
|
*
|
||
|
* Verifies that the User UI language is installed on W2k
|
||
|
*
|
||
|
* History:
|
||
|
* 14-June-1999 msadek Created
|
||
|
\***************************************************************************/
|
||
|
BOOL Mirror_IsUILanguageInstalled( LANGID langId )
|
||
|
{
|
||
|
|
||
|
MUIINSTALLLANG MUILangInstalled = {0};
|
||
|
MUILangInstalled.LangID = langId;
|
||
|
|
||
|
static PFNENUMUILANGUAGES pfnEnumUILanguages=NULL;
|
||
|
|
||
|
if( NULL == pfnEnumUILanguages )
|
||
|
{
|
||
|
HMODULE hmod = GetModuleHandleA("KERNEL32");
|
||
|
|
||
|
if( hmod )
|
||
|
pfnEnumUILanguages = (PFNENUMUILANGUAGES)
|
||
|
GetProcAddress(hmod, "EnumUILanguagesW");
|
||
|
}
|
||
|
|
||
|
if( pfnEnumUILanguages )
|
||
|
pfnEnumUILanguages(Mirror_EnumUILanguagesProc, 0, (LONG_PTR)&MUILangInstalled);
|
||
|
|
||
|
return MUILangInstalled.bInstalled;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_EnumUILanguagesProc
|
||
|
*
|
||
|
* Enumerates MUI installed languages on W2k
|
||
|
* History:
|
||
|
* 14-June-1999 msadek Created
|
||
|
\***************************************************************************/
|
||
|
|
||
|
BOOL CALLBACK Mirror_EnumUILanguagesProc(LPTSTR lpUILanguageString, LONG_PTR lParam)
|
||
|
{
|
||
|
int langID = 0;
|
||
|
|
||
|
ConvertHexStringToInt(lpUILanguageString, &langID);
|
||
|
|
||
|
if((LANGID)langID == ((LPMUIINSTALLLANG)lParam)->LangID)
|
||
|
{
|
||
|
((LPMUIINSTALLLANG)lParam)->bInstalled = TRUE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_IsWindowMirroredRTL
|
||
|
*
|
||
|
* returns TRUE if the window is RTL mirrored
|
||
|
*
|
||
|
* History:
|
||
|
* 02-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
BOOL Mirror_IsWindowMirroredRTL( HWND hWnd )
|
||
|
{
|
||
|
return (GetWindowLongA( hWnd , GWL_EXSTYLE ) & WS_EX_LAYOUTRTL );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_GetLayout
|
||
|
*
|
||
|
* returns TRUE if the hdc is RTL mirrored
|
||
|
*
|
||
|
* History:
|
||
|
* 02-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
DWORD Mirror_GetLayout( HDC hdc )
|
||
|
{
|
||
|
DWORD dwRet=0;
|
||
|
static PFNGETLAYOUT pfnGetLayout=NULL;
|
||
|
|
||
|
if( NULL == pfnGetLayout )
|
||
|
{
|
||
|
HMODULE hmod = GetModuleHandleA("GDI32");
|
||
|
|
||
|
if( hmod )
|
||
|
pfnGetLayout = (PFNGETLAYOUT)GetProcAddress(hmod, "GetLayout");
|
||
|
}
|
||
|
|
||
|
if( pfnGetLayout )
|
||
|
dwRet = pfnGetLayout( hdc );
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
|
||
|
DWORD Mirror_IsDCMirroredRTL( HDC hdc )
|
||
|
{
|
||
|
return (Mirror_GetLayout( hdc ) & LAYOUT_RTL);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_SetLayout
|
||
|
*
|
||
|
* RTL Mirror the hdc
|
||
|
*
|
||
|
* History:
|
||
|
* 02-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
DWORD Mirror_SetLayout( HDC hdc , DWORD dwLayout )
|
||
|
{
|
||
|
DWORD dwRet=0;
|
||
|
static PFNSETLAYOUT pfnSetLayout=NULL;
|
||
|
|
||
|
if( NULL == pfnSetLayout )
|
||
|
{
|
||
|
HMODULE hmod = GetModuleHandleA("GDI32");
|
||
|
|
||
|
if( hmod )
|
||
|
pfnSetLayout = (PFNSETLAYOUT)GetProcAddress(hmod, "SetLayout");
|
||
|
}
|
||
|
|
||
|
if( pfnSetLayout )
|
||
|
dwRet = pfnSetLayout( hdc , dwLayout );
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
|
||
|
DWORD Mirror_MirrorDC( HDC hdc )
|
||
|
{
|
||
|
return Mirror_SetLayout( hdc , LAYOUT_RTL );
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_SetProcessDefaultLayout
|
||
|
*
|
||
|
* Set the process-default layout.
|
||
|
*
|
||
|
* History:
|
||
|
* 02-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
BOOL Mirror_SetProcessDefaultLayout( DWORD dwDefaultLayout )
|
||
|
{
|
||
|
BOOL bRet=0;
|
||
|
static PFNSETPROCESSDEFLAYOUT pfnSetProcessDefLayout=NULL;
|
||
|
|
||
|
if( NULL == pfnSetProcessDefLayout )
|
||
|
{
|
||
|
HMODULE hmod = GetModuleHandleA("USER32");
|
||
|
|
||
|
if( hmod )
|
||
|
pfnSetProcessDefLayout = (PFNSETPROCESSDEFLAYOUT)
|
||
|
GetProcAddress(hmod, "SetProcessDefaultLayout");
|
||
|
}
|
||
|
|
||
|
if( pfnSetProcessDefLayout )
|
||
|
bRet = pfnSetProcessDefLayout( dwDefaultLayout );
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
BOOL Mirror_MirrorProcessRTL( void )
|
||
|
{
|
||
|
return Mirror_SetProcessDefaultLayout( LAYOUT_RTL );
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* Mirror_GetProcessDefaultLayout
|
||
|
*
|
||
|
* Get the process-default layout.
|
||
|
*
|
||
|
* History:
|
||
|
* 26-Feb-1998 samera Created
|
||
|
\***************************************************************************/
|
||
|
BOOL Mirror_GetProcessDefaultLayout( DWORD *pdwDefaultLayout )
|
||
|
{
|
||
|
BOOL bRet=0;
|
||
|
static PFNGETPROCESSDEFLAYOUT pfnGetProcessDefLayout=NULL;
|
||
|
|
||
|
if( NULL == pfnGetProcessDefLayout )
|
||
|
{
|
||
|
HMODULE hmod = GetModuleHandleA("USER32");
|
||
|
|
||
|
if( hmod )
|
||
|
pfnGetProcessDefLayout = (PFNGETPROCESSDEFLAYOUT)
|
||
|
GetProcAddress(hmod, "GetProcessDefaultLayout");
|
||
|
}
|
||
|
|
||
|
if( pfnGetProcessDefLayout )
|
||
|
bRet = pfnGetProcessDefLayout( pdwDefaultLayout );
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
BOOL Mirror_IsProcessRTL( void )
|
||
|
{
|
||
|
DWORD dwDefLayout=0;
|
||
|
|
||
|
return (Mirror_GetProcessDefaultLayout(&dwDefLayout) && (dwDefLayout&LAYOUT_RTL));
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// Skip_IDorString
|
||
|
//
|
||
|
// Skips string (or ID) and returns the next aligned WORD.
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
PBYTE Skip_IDorString(LPBYTE pb)
|
||
|
{
|
||
|
LPWORD pw = (LPWORD)pb;
|
||
|
|
||
|
if (*pw == 0xFFFF)
|
||
|
return (LPBYTE)(pw + 2);
|
||
|
|
||
|
while (*pw++ != 0)
|
||
|
;
|
||
|
|
||
|
return (LPBYTE)pw;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// Skip_DialogHeader
|
||
|
//
|
||
|
// Skips the dialog header and returns the next aligned WORD.
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
PBYTE Skip_DialogHeader(LPDLGTEMPLATE pdt)
|
||
|
{
|
||
|
LPBYTE pb;
|
||
|
|
||
|
pb = (LPBYTE)(pdt + 1);
|
||
|
|
||
|
// If there is a menu ordinal, add 4 bytes skip it. Otherwise it is a string or just a 0.
|
||
|
pb = Skip_IDorString(pb);
|
||
|
|
||
|
// Skip window class and window text, adjust to next word boundary.
|
||
|
pb = Skip_IDorString(pb); // class
|
||
|
pb = Skip_IDorString(pb); // window text
|
||
|
|
||
|
// Skip font type, size and name, adjust to next dword boundary.
|
||
|
if (pdt->style & DS_SETFONT)
|
||
|
{
|
||
|
pb += sizeof(WORD);
|
||
|
pb = Skip_IDorString(pb);
|
||
|
}
|
||
|
pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3); // DWORD align
|
||
|
|
||
|
return pb;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// EditBiDiDLGTemplate
|
||
|
//
|
||
|
// Edits a dialog template for BiDi stuff.
|
||
|
// Optionally, skipping some controls.
|
||
|
// Works only with DLGTEMPLATE.
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
void EditBiDiDLGTemplate(LPDLGTEMPLATE pdt, DWORD dwFlags, PWORD pwIgnoreList, int cIgnore)
|
||
|
{
|
||
|
LPBYTE pb;
|
||
|
UINT cItems;
|
||
|
|
||
|
if (!pdt)
|
||
|
return;
|
||
|
// we should never get an extended template
|
||
|
ASSERT (((LPDLGTEMPLATEEX)pdt)->wSignature != 0xFFFF);
|
||
|
|
||
|
if(dwFlags & EBDT_NOMIRROR)
|
||
|
{
|
||
|
// Turn off the mirroring styles for the dialog.
|
||
|
pdt->dwExtendedStyle &= ~(WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT);
|
||
|
}
|
||
|
cItems = pdt->cdit;
|
||
|
|
||
|
// skip DLGTEMPLATE part
|
||
|
pb = Skip_DialogHeader(pdt);
|
||
|
|
||
|
while (cItems--)
|
||
|
{
|
||
|
UINT cbCreateParams;
|
||
|
int i = 0;
|
||
|
BOOL bIgnore = FALSE;
|
||
|
|
||
|
if(pwIgnoreList && cIgnore)
|
||
|
{
|
||
|
for(i = 0;i < cIgnore; i++)
|
||
|
{
|
||
|
if((((LPDLGITEMTEMPLATE)pb)->id == *(pwIgnoreList +i)))
|
||
|
{
|
||
|
bIgnore = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if((dwFlags & EBDT_NOMIRROR) && !bIgnore)
|
||
|
{
|
||
|
// Turn off the mirroring styles for this item.
|
||
|
((LPDLGITEMTEMPLATE)pb)->dwExtendedStyle &= ~(WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT);
|
||
|
}
|
||
|
|
||
|
if((dwFlags & EBDT_FLIP) && !bIgnore)
|
||
|
{
|
||
|
((LPDLGITEMTEMPLATE)pb)->x = pdt->cx - (((LPDLGITEMTEMPLATE)pb)->x + ((LPDLGITEMTEMPLATE)pb)->cx);
|
||
|
// BUGBUG: Should we force RTL reading order for title as well ?
|
||
|
// The client has the option of doining this already by PSH_RTLREADING
|
||
|
}
|
||
|
pb += sizeof(DLGITEMTEMPLATE);
|
||
|
|
||
|
// Skip the dialog control class name.
|
||
|
pb = Skip_IDorString(pb);
|
||
|
|
||
|
// Look at window text now.
|
||
|
pb = Skip_IDorString(pb);
|
||
|
|
||
|
cbCreateParams = *((LPWORD)pb);
|
||
|
|
||
|
// skip any CreateParams which include the generated size WORD.
|
||
|
if (cbCreateParams)
|
||
|
pb += cbCreateParams;
|
||
|
|
||
|
pb += sizeof(WORD);
|
||
|
|
||
|
// Point at the next dialog item. (DWORD aligned)
|
||
|
pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3);
|
||
|
|
||
|
bIgnore = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|