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.
1926 lines
47 KiB
1926 lines
47 KiB
#include "private.h"
|
|
#include "globals.h"
|
|
#include "internat.h"
|
|
#include "strary.h"
|
|
#include "xstring.h"
|
|
#include "immxutil.h"
|
|
#include "cregkey.h"
|
|
#include "cmydc.h"
|
|
#include "assembly.h"
|
|
|
|
CStructArray<MLNGINFO> *g_pMlngInfo = NULL;
|
|
|
|
|
|
const TCHAR c_szDefaultUserPreload[] = TEXT(".DEFAULT\\Keyboard Layout\\Preload");
|
|
const TCHAR c_szPreload[] = TEXT("Keyboard Layout\\Preload");
|
|
const TCHAR c_szSubst[] = TEXT("Keyboard Layout\\Substitutes");
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CStaticIconList
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class CStaticIconList
|
|
{
|
|
public:
|
|
void Init(int cx, int cy);
|
|
void RemoveAll(BOOL fInUninit);
|
|
|
|
BOOL IsInited()
|
|
{
|
|
return _cx != 0;
|
|
}
|
|
|
|
int AddIcon(HICON hicon);
|
|
HICON ExtractIcon(int i);
|
|
void GetIconSize(int *cx, int *cy);
|
|
int GetImageCount();
|
|
|
|
private:
|
|
static int _cx;
|
|
static int _cy;
|
|
static CStructArray<HICON> *_prgIcons;
|
|
};
|
|
|
|
CStaticIconList g_IconList;
|
|
int CStaticIconList::_cx = 0;
|
|
int CStaticIconList::_cy = 0;
|
|
CStructArray<HICON> *CStaticIconList::_prgIcons = NULL;
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CStaticIconList::Init(int cx, int cy)
|
|
{
|
|
CicEnterCriticalSection(g_cs);
|
|
_cx = cx;
|
|
_cy = cy;
|
|
CicLeaveCriticalSection(g_cs);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RemoveAll
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CStaticIconList::RemoveAll(BOOL fInUninit)
|
|
{
|
|
int i;
|
|
|
|
//
|
|
// don't have to enter g_cs if we're in DllMain(PROCESS_DETATCH).
|
|
//
|
|
if (!fInUninit)
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (_prgIcons == NULL)
|
|
goto Exit;
|
|
|
|
for (i=0; i<_prgIcons->Count(); i++)
|
|
{
|
|
DestroyIcon(*_prgIcons->GetPtr(i));
|
|
}
|
|
|
|
delete _prgIcons;
|
|
_prgIcons = NULL;
|
|
|
|
Exit:
|
|
if (!fInUninit)
|
|
CicLeaveCriticalSection(g_cs);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AddIcon
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline int CStaticIconList::AddIcon(HICON hicon)
|
|
{
|
|
HICON hIconCopy;
|
|
HICON *pIconDst;
|
|
int nRet = -1;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (!_prgIcons)
|
|
_prgIcons = new CStructArray<HICON>;
|
|
|
|
if (!_prgIcons)
|
|
goto Exit;
|
|
|
|
if ((pIconDst = _prgIcons->Append(1)) == NULL)
|
|
goto Exit;
|
|
|
|
if ((hIconCopy = CopyIcon(hicon)) == 0)
|
|
{
|
|
_prgIcons->Remove(_prgIcons->Count()-1, 1);
|
|
goto Exit;
|
|
}
|
|
|
|
*pIconDst = hIconCopy;
|
|
|
|
nRet = _prgIcons->Count()-1;
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ExtractIcon
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline HICON CStaticIconList::ExtractIcon(int i)
|
|
{
|
|
HICON hIcon = NULL;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (!_prgIcons)
|
|
goto Exit;
|
|
|
|
if (i >= _prgIcons->Count() || i < 0)
|
|
goto Exit;
|
|
|
|
hIcon = CopyIcon(*_prgIcons->GetPtr(i));
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
|
|
return hIcon;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetIconSize
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CStaticIconList::GetIconSize(int *cx, int *cy)
|
|
{
|
|
CicEnterCriticalSection(g_cs);
|
|
*cx = _cx;
|
|
*cy = _cy;
|
|
CicLeaveCriticalSection(g_cs);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetImageCount
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline int CStaticIconList::GetImageCount()
|
|
{
|
|
int nRet = 0;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (_prgIcons == NULL)
|
|
goto Exit;
|
|
|
|
nRet = _prgIcons->Count();
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UninitINAT
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void UninitINAT()
|
|
{
|
|
g_IconList.RemoveAll(TRUE);
|
|
|
|
if (g_pMlngInfo)
|
|
{
|
|
delete g_pMlngInfo;
|
|
g_pMlngInfo = NULL;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InterNAT icon APIs
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if 0
|
|
//
|
|
// ISO 639:1988 Code.
|
|
//
|
|
//
|
|
// Under NT, we use GetLocaleInfoNTString(). It returns ISO 3166.
|
|
//
|
|
INATSYMBOL symInatSymbols[] =
|
|
{
|
|
{0x0436, "AF"}, // Afrikaans
|
|
{0x041c, "SQ"}, // Albanian
|
|
{0x0401, "AR"}, // Arabic
|
|
{0x042d, "EU"}, // Basque
|
|
{0x0423, "BE"}, // Byelorus
|
|
{0x0402, "BG"}, // Bulgaria
|
|
{0x0403, "CA"}, // Catalan
|
|
{0x0404, "CH"}, // China #1
|
|
{0x0804, "CH"}, // China #2
|
|
//#ifdef WINDOWS_PE
|
|
#if 1
|
|
{0x041a, "HR"}, // Croatian
|
|
#else
|
|
{0x041a, "SH"}, // Croatian
|
|
#endif
|
|
{0x0405, "CZ"}, // Czech
|
|
{0x0406, "DA"}, // Danish
|
|
{0x0413, "NL"}, // Dutch
|
|
{0x0813, "NL"}, // Dutch
|
|
{0x0409, "EN"}, // English
|
|
{0x0809, "EN"}, // English
|
|
{0x0c09, "EN"}, // English
|
|
{0x1009, "EN"}, // English
|
|
{0x1409, "EN"}, // English
|
|
{0x1809, "EN"}, // English
|
|
{0x0425, "ET"}, // Estonian
|
|
{0x0429, "FA"}, // Farsi
|
|
{0x040b, "FI"}, // Finnish
|
|
{0x040c, "FR"}, // French
|
|
{0x080c, "FR"}, // French
|
|
{0x0c0c, "FR"}, // French
|
|
{0x0407, "DE"}, // German
|
|
{0x0807, "DE"}, // German
|
|
{0x0c07, "DE"}, // German
|
|
{0x1007, "DE"}, // German
|
|
{0x1407, "DE"}, // German
|
|
{0x0408, "GR"}, // Greek
|
|
{0x040d, "HE"}, // Hebrew
|
|
{0x040e, "HU"}, // Hungary
|
|
{0x040f, "IS"}, // Iceland
|
|
{0x0421, "BA"}, // Indonesia
|
|
{0x0410, "IT"}, // Italy
|
|
{0x0810, "IT"}, // Italy
|
|
{0x0411, "JA"}, // Japan
|
|
{0x0412, "KO"}, // Korea
|
|
{0x0426, "LV"}, // Latvian
|
|
{0x0427, "LT"}, // Lithuanian
|
|
{0x042f, "MK"}, // Former Yugoslav Republic of Macedonia
|
|
{0x0414, "NO"}, // Norway
|
|
{0x0814, "NO"}, // Norway
|
|
{0x0415, "PL"}, // Poland
|
|
{0x0416, "PT"}, // Portugal
|
|
{0x0816, "PT"}, // Portugal
|
|
{0x0417, "RM"}, // Rhaeto
|
|
{0x0418, "RO"}, // Romanian
|
|
{0x0818, "RO"}, // Romanian
|
|
{0x0419, "RU"}, // Russian
|
|
{0x0819, "RU"}, // Russian
|
|
{0x081a, "SR"}, // Serbian
|
|
//#ifdef WINDOWS_PE
|
|
#if 1
|
|
{0x0c1a, "SR"}, // Serbian
|
|
#endif
|
|
{0x041b, "SK"}, // Slovakian
|
|
{0x0424, "SL"}, // Slovenian
|
|
{0x042e, "SB"}, // Sorbian
|
|
{0x040a, "ES"}, // Spanish
|
|
{0x080a, "ES"}, // Spanish
|
|
{0x0c0a, "ES"}, // Spanish
|
|
{0x041d, "SV"}, // Swedish
|
|
{0x041e, "TH"}, // Thai
|
|
{0x041f, "TR"}, // Turkish
|
|
{0x0422, "UK"}, // Ukranian
|
|
{0x0420, "UR"}, // Urdu
|
|
{0x0033, "VE"}, // Venda
|
|
{0x042a, "VN"}, // Vietnamese
|
|
{0x0034, "XH"}, // Xhosa
|
|
{0x0035, "ZU"}, // Zulu
|
|
{0x002b, "ST"}, // Sutu
|
|
{0x002e, "TS"}, // Tsona
|
|
{0x002f, "TN"}, // Tswana
|
|
{0x0000, "??"}
|
|
} ;
|
|
|
|
#define NSYMBOLS ((sizeof(symInatSymbols) / sizeof(INATSYMBOL))-1)
|
|
#endif
|
|
|
|
static const TCHAR c_szLayoutPath[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts");
|
|
static const TCHAR c_szLayoutText[] = TEXT("layout text");
|
|
static const TCHAR c_szLayoutID[] = TEXT("layout id");
|
|
|
|
static const WCHAR c_szMUILayoutTextW[] = L"Layout Display Name";
|
|
static const WCHAR c_szLayoutTextW[] = L"layout text";
|
|
|
|
static const char c_szNamesPath[] = "system\\currentcontrolset\\control\\nls\\Locale";
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetLocaleInfoString
|
|
//
|
|
// this is not a general wrapper for GetLocaleInfo!
|
|
// LCTYPE must be LOCALE_SABBREVLANGNAME or LOCALE_SLANGUAGE.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
int GetLocaleInfoString(LCID lcid, LCTYPE lcType, char *psz, int cch)
|
|
{
|
|
WCHAR achW[64];
|
|
|
|
Assert((lcType & LOCALE_SLANGUAGE) || (lcType & LOCALE_SABBREVLANGNAME));
|
|
|
|
if (IsOnNT())
|
|
{
|
|
if (GetLocaleInfoW(lcid, lcType, achW, ARRAYSIZE(achW)))
|
|
{
|
|
return WideCharToMultiByte(CP_ACP, 0, achW, -1, psz, cch, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return GetLocaleInfo(lcid, lcType, psz, cch);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InatCreateIcon
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
HICON InatCreateIcon(WORD langID)
|
|
{
|
|
LOGFONT lf;
|
|
UINT cxSmIcon;
|
|
UINT cySmIcon;
|
|
|
|
cxSmIcon = GetSystemMetrics( SM_CXSMICON );
|
|
cySmIcon = GetSystemMetrics( SM_CYSMICON );
|
|
|
|
if( !SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
|
|
return NULL;
|
|
|
|
if (cySmIcon < GetPhysicalFontHeight(lf))
|
|
{
|
|
lf.lfHeight = 0 - ((int)cySmIcon * 7 / 10);
|
|
lf.lfWidth = 0;
|
|
}
|
|
|
|
return InatCreateIconBySize(langID, cxSmIcon, cySmIcon, &lf);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InatCreateIconBySize
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
HICON InatCreateIconBySize(WORD langID, int cxSmIcon, int cySmIcon, LOGFONT *plf)
|
|
{
|
|
HBITMAP hbmColour;
|
|
HBITMAP hbmMono;
|
|
HBITMAP hbmOld;
|
|
HICON hicon = NULL;
|
|
ICONINFO ii;
|
|
RECT rc;
|
|
DWORD rgbText;
|
|
DWORD rgbBk = 0;
|
|
HDC hdc;
|
|
HDC hdcScreen;
|
|
HFONT hfont;
|
|
HFONT hfontOld;
|
|
TCHAR szData[20];
|
|
|
|
|
|
//
|
|
// Get the indicator by using the first 2 characters of the
|
|
// abbreviated language name.
|
|
//
|
|
if (GetLocaleInfoString( MAKELCID(langID, SORT_DEFAULT),
|
|
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
|
|
szData,
|
|
sizeof(szData) / sizeof(TCHAR) ))
|
|
{
|
|
//
|
|
// Make Uppercase
|
|
//
|
|
if (!IsOnNT())
|
|
{
|
|
szData[0] -= 0x20;
|
|
szData[1] -= 0x20;
|
|
}
|
|
//
|
|
// Only use the first two characters.
|
|
//
|
|
szData[2] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Id wasn't found. Use question marks.
|
|
//
|
|
szData[0] = TEXT('?');
|
|
szData[1] = TEXT('?');
|
|
szData[2] = TEXT('\0');
|
|
}
|
|
|
|
if( (hfont = CreateFontIndirect(plf)) )
|
|
{
|
|
hdcScreen = GetDC(NULL);
|
|
hdc = CreateCompatibleDC(hdcScreen);
|
|
hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon);
|
|
ReleaseDC( NULL, hdcScreen);
|
|
if (hbmColour && hdc)
|
|
{
|
|
hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL);
|
|
if (hbmMono)
|
|
{
|
|
hbmOld = (HBITMAP)SelectObject( hdc, hbmColour);
|
|
rc.left = 0;
|
|
rc.top = 0;
|
|
rc.right = cxSmIcon;
|
|
rc.bottom = cySmIcon;
|
|
|
|
rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
|
|
rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
|
|
ExtTextOut( hdc, rc.left, rc.top, ETO_OPAQUE, &rc, "", 0, NULL);
|
|
|
|
hfontOld = (HFONT)SelectObject( hdc, hfont);
|
|
DrawText(hdc,
|
|
szData,
|
|
2,
|
|
&rc,
|
|
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
|
|
|
SelectObject( hdc, hbmMono);
|
|
PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS);
|
|
|
|
ii.fIcon = TRUE;
|
|
ii.xHotspot = 0;
|
|
ii.yHotspot = 0;
|
|
ii.hbmColor = hbmColour;
|
|
ii.hbmMask = hbmMono;
|
|
hicon = CreateIconIndirect(&ii);
|
|
|
|
SelectObject(hdc, hbmOld);
|
|
DeleteObject(hbmMono);
|
|
SelectObject(hdc, hfontOld);
|
|
}
|
|
}
|
|
DeleteObject(hbmColour);
|
|
DeleteDC(hdc);
|
|
DeleteObject(hfont);
|
|
}
|
|
|
|
return hicon;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetIconFromFile
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
HICON GetIconFromFile(int cx, int cy, WCHAR *lpszFileName, UINT uIconIndex)
|
|
{
|
|
return GetIconFromFileA(cx, cy, WtoA(lpszFileName), uIconIndex);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetIconFromFileA
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
HICON GetIconFromFileA(int cx, int cy, char *lpszFileName, UINT uIconIndex)
|
|
{
|
|
HICON hicon = NULL;
|
|
|
|
if (cx > GetSystemMetrics(SM_CXSMICON))
|
|
{
|
|
ExtractIconEx(lpszFileName, uIconIndex, &hicon, NULL, 1);
|
|
}
|
|
else
|
|
{
|
|
ExtractIconEx(lpszFileName, uIconIndex, NULL, &hicon, 1);
|
|
}
|
|
|
|
return hicon;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CLayoutsSharedMem
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
extern CCicMutex g_mutexLayouts;
|
|
extern char g_szLayoutsCache[];
|
|
|
|
class CLayoutsSharedMem : public CCicFileMappingStatic
|
|
{
|
|
public:
|
|
void Init()
|
|
{
|
|
CCicFileMappingStatic::Init(g_szLayoutsCache, &g_mutexLayouts);
|
|
}
|
|
|
|
BOOL Start(UINT nNum)
|
|
{
|
|
BOOL fAlreadyExists;
|
|
|
|
CCicSecAttr sa;
|
|
if (Create(sa, sizeof(LAYOUT) * nNum, &fAlreadyExists) == NULL)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LAYOUT *GetPtr() { return (LAYOUT *)_pv; }
|
|
};
|
|
|
|
CLayoutsSharedMem g_smLayouts;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UninitLayoutMappedFile();
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UninitLayoutMappedFile()
|
|
{
|
|
g_smLayouts.Uninit();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// LoadKeyboardLayouts
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL LoadKeyboardLayouts()
|
|
{
|
|
CMyRegKey key;
|
|
DWORD dwIndex;
|
|
BOOL bRet = FALSE;
|
|
TCHAR szValue[MAX_PATH]; // language id (number)
|
|
WCHAR szValueW[MAX_PATH];
|
|
TCHAR szData[MAX_PATH]; // language name
|
|
CStructArray<LAYOUT> *pLayouts = NULL;
|
|
LAYOUT *pLayout;
|
|
BOOL bLoadedLayout;
|
|
|
|
pLayouts = new CStructArray<LAYOUT>;
|
|
if (!pLayouts)
|
|
return FALSE;
|
|
|
|
//
|
|
// Now read all the locales from the registry.
|
|
//
|
|
if (key.Open(HKEY_LOCAL_MACHINE, c_szLayoutPath, KEY_READ) != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
szValue[0] = TEXT('\0');
|
|
while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == ERROR_SUCCESS)
|
|
{
|
|
CRegKeyMUI key1;
|
|
|
|
pLayout = pLayouts->Append(1);
|
|
if (!pLayout)
|
|
goto Exit;
|
|
|
|
pLayout->dwID = AsciiToNum(szValue);
|
|
|
|
if (StringCchPrintf(szData, ARRAYSIZE(szData), "%s\\%s", c_szLayoutPath, szValue) != S_OK)
|
|
goto Next;
|
|
|
|
if (key1.Open(HKEY_LOCAL_MACHINE, szData, KEY_READ) == S_OK)
|
|
{
|
|
//
|
|
// Get the layout name.
|
|
//
|
|
szValue[0] = TEXT('\0');
|
|
bLoadedLayout = FALSE;
|
|
|
|
if (IsOnNT())
|
|
{
|
|
szValueW[0] = 0;
|
|
|
|
if (key1.QueryValueCchW(szValueW,
|
|
c_szMUILayoutTextW,
|
|
ARRAYSIZE(szValueW)) == S_OK)
|
|
{
|
|
bLoadedLayout = TRUE;
|
|
}
|
|
else if (key1.QueryValueCchW(szValueW,
|
|
c_szLayoutTextW,
|
|
ARRAYSIZE(szValueW)) == S_OK)
|
|
{
|
|
bLoadedLayout = TRUE;
|
|
}
|
|
|
|
if (bLoadedLayout)
|
|
{
|
|
wcsncpy(pLayout->wszText,
|
|
szValueW,
|
|
ARRAYSIZE(pLayout->wszText));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (key1.QueryValueCch(szValue,
|
|
c_szLayoutText,
|
|
ARRAYSIZE(szValue)) == S_OK)
|
|
{
|
|
wcsncpy(pLayout->wszText,
|
|
AtoW(szValue),
|
|
ARRAYSIZE(pLayout->wszText));
|
|
|
|
bLoadedLayout = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bLoadedLayout)
|
|
{
|
|
szValue[0] = TEXT('\0');
|
|
pLayout->iSpecialID = 0;
|
|
|
|
if (key1.QueryValueCch(szValue,
|
|
c_szLayoutID,
|
|
ARRAYSIZE(szValue)) == S_OK)
|
|
|
|
{
|
|
//
|
|
// This may not exist!
|
|
//
|
|
pLayout->iSpecialID = (UINT)AsciiToNum(szValue);
|
|
}
|
|
}
|
|
}
|
|
Next:
|
|
dwIndex++;
|
|
szValue[0] = TEXT('\0');
|
|
}
|
|
|
|
pLayout = pLayouts->Append(1);
|
|
if (!pLayout)
|
|
goto Exit;
|
|
|
|
memset(pLayout, 0, sizeof(LAYOUT));
|
|
|
|
if (!g_smLayouts.Enter())
|
|
goto Exit;
|
|
|
|
g_smLayouts.Close();
|
|
|
|
if (g_smLayouts.Start(pLayouts->Count()))
|
|
{
|
|
if (g_smLayouts.GetPtr())
|
|
{
|
|
memcpy(g_smLayouts.GetPtr(),
|
|
pLayouts->GetPtr(0),
|
|
pLayouts->Count() * sizeof(LAYOUT));
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
g_smLayouts.Leave();
|
|
|
|
Exit:
|
|
|
|
if (pLayouts)
|
|
delete pLayouts;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// FindLayoutEntry
|
|
//
|
|
// Gets the name of the given layout.
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
UINT FindLayoutEntry( LAYOUT *pLayout, DWORD dwLayout )
|
|
{
|
|
UINT ctr = 0;
|
|
UINT id;
|
|
WORD wLayout = HIWORD(dwLayout);
|
|
BOOL bIsIME = ((HIWORD(dwLayout) & 0xf000) == 0xe000) ? TRUE : FALSE;
|
|
|
|
//
|
|
// Find the layout in the global structure.
|
|
//
|
|
if ((wLayout & 0xf000) == 0xf000)
|
|
{
|
|
//
|
|
// Layout is special, need to search for the ID
|
|
// number.
|
|
//
|
|
id = wLayout & 0x0fff;
|
|
ctr = 0;
|
|
while (pLayout[ctr].dwID)
|
|
{
|
|
if (id == pLayout[ctr].iSpecialID)
|
|
{
|
|
break;
|
|
}
|
|
ctr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ctr = 0;
|
|
while (pLayout[ctr].dwID)
|
|
{
|
|
//
|
|
// If it is IME, needs to be DWORD comparison.
|
|
//
|
|
if (IsOnFE() && bIsIME && (dwLayout == pLayout[ctr].dwID))
|
|
{
|
|
break;
|
|
}
|
|
else if (wLayout == LOWORD(pLayout[ctr].dwID))
|
|
{
|
|
break;
|
|
}
|
|
ctr++;
|
|
}
|
|
}
|
|
|
|
return ctr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetKbdLayoutName
|
|
//
|
|
// Gets the name of the given layout.
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
void GetKbdLayoutName( DWORD dwLayout, WCHAR *pBuffer, int nBufSize)
|
|
{
|
|
UINT ctr;
|
|
LAYOUT *pLayout;
|
|
|
|
*pBuffer = L'\0';
|
|
|
|
if (!g_smLayouts.Enter())
|
|
return;
|
|
|
|
g_smLayouts.Close();
|
|
g_smLayouts.Init();
|
|
if (!g_smLayouts.Open())
|
|
{
|
|
if (!LoadKeyboardLayouts())
|
|
{
|
|
Assert(0);
|
|
}
|
|
}
|
|
|
|
pLayout = g_smLayouts.GetPtr();
|
|
if (!pLayout)
|
|
goto Exit;
|
|
|
|
ctr = FindLayoutEntry( pLayout, dwLayout );
|
|
|
|
//
|
|
// Make sure there is a match. If not, then simply return without
|
|
// copying anything.
|
|
//
|
|
if (pLayout[ctr].dwID)
|
|
{
|
|
//
|
|
// Separate the Input Locale name and the Layout name with " - ".
|
|
//
|
|
#ifdef ATTACH_LAYOUTNAME
|
|
pBuffer[0] = L' ';
|
|
pBuffer[1] = L'-';
|
|
pBuffer[2] = L' ';
|
|
|
|
wcsncpy(pBuffer + 3, pLayout[ctr].wszText, nBufSize - 3);
|
|
#else
|
|
wcsncpy(pBuffer, pLayout[ctr].wszText, nBufSize);
|
|
#endif
|
|
}
|
|
|
|
Exit:
|
|
g_smLayouts.Leave();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetKbdLayoutId
|
|
//
|
|
// Gets the name of the given layout.
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
DWORD GetKbdLayoutId( DWORD dwLayout)
|
|
{
|
|
UINT ctr;
|
|
DWORD dwId = 0;
|
|
LAYOUT *pLayout;
|
|
|
|
if (!g_smLayouts.Enter())
|
|
return 0;
|
|
|
|
g_smLayouts.Close();
|
|
g_smLayouts.Init();
|
|
if (!g_smLayouts.Open())
|
|
LoadKeyboardLayouts();
|
|
|
|
pLayout = g_smLayouts.GetPtr();
|
|
if (!pLayout)
|
|
goto Exit;
|
|
|
|
ctr = FindLayoutEntry( pLayout, dwLayout );
|
|
|
|
//
|
|
// Make sure there is a match. If not, then simply return without
|
|
// copying anything.
|
|
//
|
|
dwId = pLayout[ctr].dwID;
|
|
|
|
Exit:
|
|
g_smLayouts.Leave();
|
|
|
|
return dwId;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetLocaleInfoString
|
|
//
|
|
// this is not a general wrapper for GetLocaleInfo!
|
|
// LCTYPE must be LOCALE_SABBREVLANGNAME or LOCALE_SLANGUAGE.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
ULONG GetLocaleInfoString(HKL hKL, WCHAR *pszRegText, int nSize)
|
|
{
|
|
ULONG cb = 0;
|
|
DWORD dwRegValue = (DWORD)((LONG_PTR)(hKL) & 0x0000FFFF);
|
|
|
|
*pszRegText = L'\0';
|
|
|
|
if (IsOnNT())
|
|
{
|
|
if (!GetLocaleInfoW(dwRegValue, LOCALE_SLANGUAGE, pszRegText, nSize))
|
|
{
|
|
*pszRegText = L'\0';
|
|
}
|
|
|
|
//
|
|
// Attach the Layout name if it's not the default.
|
|
//
|
|
if (HIWORD(hKL) != LOWORD(hKL))
|
|
{
|
|
#ifdef ATTACH_LAYOUTNAME
|
|
WCHAR *pszRT = pszRegText + wcslen(pszRegText);
|
|
//
|
|
// Pass DWORD value for IME.
|
|
//
|
|
GetKbdLayoutName((DWORD)(LONG_PTR)hKL,
|
|
pszRT,
|
|
nSize - (DWORD)(pszRT - pszRegText));
|
|
#else
|
|
GetKbdLayoutName((DWORD)(LONG_PTR)hKL, pszRegText, nSize);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
CMyRegKey key;
|
|
char szRegKey[128];
|
|
char szRegText[128];
|
|
StringCchPrintf(szRegKey, ARRAYSIZE(szRegKey),"%8.8lx", (DWORD)dwRegValue);
|
|
|
|
*pszRegText = '\0';
|
|
if(key.Open(HKEY_LOCAL_MACHINE,c_szNamesPath, KEY_READ)==ERROR_SUCCESS)
|
|
{
|
|
if(key.QueryValueCch(szRegText, szRegKey, ARRAYSIZE(szRegText)) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwLen = MultiByteToWideChar(CP_ACP,
|
|
MB_ERR_INVALID_CHARS,
|
|
szRegText,
|
|
lstrlen(szRegText),
|
|
pszRegText,
|
|
nSize-1);
|
|
pszRegText[dwLen] = L'\0';
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return wcslen(pszRegText);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetHKLDescription
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int GetHKLDesctription(HKL hKL, WCHAR *pszDesc, int cchDesc, WCHAR *pszIMEFile, int cchIMEFile)
|
|
{
|
|
DWORD dwIMEDesc = 0;
|
|
|
|
if (IsIMEHKL(hKL))
|
|
{
|
|
HKEY hkey;
|
|
DWORD dwIMELayout;
|
|
TCHAR szIMELayout[MAX_PATH];
|
|
TCHAR szIMELayoutPath[MAX_PATH];
|
|
|
|
dwIMELayout = GetSubstitute(hKL);
|
|
StringCchPrintf(szIMELayout, ARRAYSIZE(szIMELayout), "%8.8lx", dwIMELayout);
|
|
|
|
StringCopyArray(szIMELayoutPath, c_szLayoutPath);
|
|
StringCatArray(szIMELayoutPath, TEXT("\\"));
|
|
StringCatArray(szIMELayoutPath, szIMELayout);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szIMELayoutPath, 0, KEY_READ, &hkey)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
if (SHLoadRegUIStringW(hkey,
|
|
c_szMUILayoutTextW,
|
|
pszDesc, cchDesc) == S_OK)
|
|
{
|
|
dwIMEDesc = wcslen(pszDesc);
|
|
}
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
if (!dwIMEDesc)
|
|
{
|
|
dwIMEDesc = ImmGetDescriptionW(hKL,pszDesc,cchDesc);
|
|
if (!dwIMEDesc)
|
|
pszDesc[0] = L'\0';
|
|
}
|
|
}
|
|
|
|
if (dwIMEDesc == 0)
|
|
{
|
|
GetLocaleInfoString(hKL, pszDesc, cchDesc);
|
|
pszIMEFile[0] = L'\0';
|
|
}
|
|
else
|
|
{
|
|
if (!ImmGetIMEFileNameW(hKL, pszIMEFile, cchIMEFile))
|
|
pszIMEFile[0] = L'\0';
|
|
}
|
|
|
|
return wcslen(pszDesc);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MLNGINFO List
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// MlngInfoCount()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
int WINAPI TF_MlngInfoCount()
|
|
{
|
|
if (!g_pMlngInfo)
|
|
return 0;
|
|
|
|
return g_pMlngInfo->Count();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// GetMlngInfo()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
BOOL GetMlngInfo(int n, MLNGINFO *pmlInfo)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
MLNGINFO *pml;
|
|
|
|
if (!g_pMlngInfo)
|
|
return FALSE;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
Assert(g_pMlngInfo);
|
|
|
|
if (n >= g_pMlngInfo->Count())
|
|
goto Exit;
|
|
|
|
pml = g_pMlngInfo->GetPtr(n);
|
|
if (!pml)
|
|
goto Exit;
|
|
|
|
*pmlInfo = *pml;
|
|
bRet = TRUE;
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
return bRet;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// GetMlngInfoByhKL()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
int GetMlngInfoByhKL(HKL hKL, MLNGINFO *pmlInfo)
|
|
{
|
|
int nRet = -1;
|
|
MLNGINFO *pml;
|
|
|
|
if (!g_pMlngInfo)
|
|
return 0;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
int nCnt = g_pMlngInfo->Count();
|
|
int i;
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
pml = g_pMlngInfo->GetPtr(i);
|
|
if (pml->hKL == hKL)
|
|
{
|
|
*pmlInfo = *pml;
|
|
nRet = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
CicLeaveCriticalSection(g_cs);
|
|
return nRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CheckMlngInfo
|
|
//
|
|
// return TRUE, if MlangInfo needs to be updated.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CheckMlngInfo()
|
|
{
|
|
int iLangs;
|
|
BOOL bRet = FALSE;
|
|
HKL *pLanguages = NULL;
|
|
|
|
if (!g_pMlngInfo)
|
|
return TRUE;
|
|
|
|
iLangs = GetKeyboardLayoutList((UINT)0, (HKL FAR *)NULL);
|
|
|
|
if (iLangs != TF_MlngInfoCount())
|
|
return TRUE;
|
|
|
|
if (iLangs)
|
|
{
|
|
int i;
|
|
pLanguages = (HKL *)cicMemAlloc(iLangs * sizeof(HKL));
|
|
if (!pLanguages)
|
|
goto Exit;
|
|
|
|
GetKeyboardLayoutList(iLangs, (HKL FAR *)pLanguages);
|
|
for (i = 0; i < iLangs; i++)
|
|
{
|
|
MLNGINFO *pMlngInfo = g_pMlngInfo->GetPtr(i);
|
|
if (pMlngInfo->hKL != pLanguages[i])
|
|
{
|
|
bRet = TRUE;
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
Exit:
|
|
if (pLanguages)
|
|
cicMemFree(pLanguages);
|
|
return bRet;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void DestroyMlngInfo()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DestroyMlngInfo()
|
|
{
|
|
if (g_pMlngInfo)
|
|
{
|
|
while (g_pMlngInfo->Count())
|
|
{
|
|
g_pMlngInfo->Remove(0, 1);
|
|
}
|
|
delete g_pMlngInfo;
|
|
g_pMlngInfo = NULL;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void CreateMLlngInfo()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void CreateMlngInfo()
|
|
{
|
|
HKL *pLanguages;
|
|
UINT uCount;
|
|
UINT uLangs;
|
|
MLNGINFO *pMlngInfo;
|
|
BOOL fNeedInd = FALSE;
|
|
|
|
uLangs = GetKeyboardLayoutList((UINT)0, (HKL FAR *)NULL);
|
|
|
|
if (!g_pMlngInfo)
|
|
g_pMlngInfo = new CStructArray<MLNGINFO>;
|
|
|
|
if (!g_pMlngInfo)
|
|
return;
|
|
|
|
if (!EnsureIconImageList())
|
|
{
|
|
return;
|
|
}
|
|
|
|
pLanguages = (HKL *)cicMemAllocClear(uLangs * sizeof(HKL));
|
|
if (!pLanguages)
|
|
return;
|
|
|
|
GetKeyboardLayoutList(uLangs, (HKL FAR *)pLanguages);
|
|
|
|
//
|
|
// pLanguages contains all the HKLs in the system
|
|
// Put everything together in the DPA and Image List
|
|
//
|
|
for (uCount = 0; uCount < uLangs; uCount++)
|
|
{
|
|
pMlngInfo = g_pMlngInfo->Append(1);
|
|
if (pMlngInfo)
|
|
{
|
|
pMlngInfo->hKL = pLanguages[uCount];
|
|
pMlngInfo->fInitIcon = FALSE;
|
|
pMlngInfo->fInitDesc = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
cicMemFree(pLanguages);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void InitDesc
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void MLNGINFO::InitDesc()
|
|
{
|
|
MLNGINFO *pml;
|
|
|
|
if (fInitDesc)
|
|
return;
|
|
|
|
WCHAR szRegText[256];
|
|
WCHAR szIMEFile[256];
|
|
|
|
GetHKLDesctription(hKL,
|
|
szRegText, ARRAYSIZE(szRegText),
|
|
szIMEFile, ARRAYSIZE(szIMEFile));
|
|
|
|
fInitDesc = TRUE;
|
|
SetDesc(szRegText);
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
Assert(g_pMlngInfo);
|
|
|
|
int nCnt = g_pMlngInfo->Count();
|
|
int i;
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
pml = g_pMlngInfo->GetPtr(i);
|
|
if (pml->hKL == hKL)
|
|
{
|
|
pml->fInitDesc = TRUE;
|
|
pml->SetDesc(szRegText);
|
|
break;
|
|
}
|
|
}
|
|
|
|
CicLeaveCriticalSection(g_cs);
|
|
return;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void InitIcon
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void MLNGINFO::InitIcon()
|
|
{
|
|
HICON hIcon;
|
|
|
|
if (fInitIcon)
|
|
return;
|
|
|
|
WCHAR szRegText[256];
|
|
WCHAR szIMEFile[256];
|
|
|
|
GetHKLDesctription(hKL,
|
|
szRegText, ARRAYSIZE(szRegText),
|
|
szIMEFile, ARRAYSIZE(szIMEFile));
|
|
|
|
fInitDesc = TRUE;
|
|
SetDesc(szRegText);
|
|
|
|
if (wcslen(szIMEFile))
|
|
{
|
|
int cx, cy;
|
|
|
|
InatGetIconSize(&cx, &cy);
|
|
if ((hIcon = GetIconFromFile(cx, cy, szIMEFile, 0)) == 0)
|
|
{
|
|
goto GetLangIcon;
|
|
}
|
|
}
|
|
else // for non-ime layout
|
|
{
|
|
GetLangIcon:
|
|
hIcon = InatCreateIcon(LOWORD((DWORD)(UINT_PTR)hKL));
|
|
}
|
|
|
|
if (hIcon)
|
|
{
|
|
nIconIndex = InatAddIcon(hIcon);
|
|
DestroyIcon(hIcon);
|
|
}
|
|
|
|
MLNGINFO *pml;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
Assert(g_pMlngInfo);
|
|
|
|
int nCnt = g_pMlngInfo->Count();
|
|
int i;
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
pml = g_pMlngInfo->GetPtr(i);
|
|
if (pml->hKL == hKL)
|
|
{
|
|
pml->fInitDesc = TRUE;
|
|
pml->fInitIcon = TRUE;
|
|
pml->nIconIndex = nIconIndex;
|
|
pml->SetDesc(szRegText);
|
|
break;
|
|
}
|
|
}
|
|
|
|
CicLeaveCriticalSection(g_cs);
|
|
return;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void TF_InitMLlngInfo()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void WINAPI TF_InitMlngInfo()
|
|
{
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (CheckMlngInfo())
|
|
{
|
|
DestroyMlngInfo();
|
|
CreateMlngInfo();
|
|
}
|
|
|
|
CicLeaveCriticalSection(g_cs);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void TF_InitMLlngHKL()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL TF_GetMlngHKL(int nId, HKL *phkl, WCHAR *psz, UINT cch)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
MLNGINFO *pml;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
Assert(g_pMlngInfo);
|
|
|
|
if (nId >= g_pMlngInfo->Count())
|
|
goto Exit;
|
|
|
|
pml = g_pMlngInfo->GetPtr(nId);
|
|
if (!pml)
|
|
goto Exit;
|
|
|
|
if (phkl)
|
|
*phkl = pml->hKL;
|
|
|
|
if (psz)
|
|
wcsncpy(psz, pml->GetDesc(), cch);
|
|
|
|
bRet = TRUE;
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
return bRet;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void TF_GetMlngIconIndex()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
UINT WINAPI TF_GetMlngIconIndex(int nId)
|
|
{
|
|
UINT uIconIndex = (UINT)-1;
|
|
MLNGINFO *pml;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
Assert(g_pMlngInfo);
|
|
|
|
if (nId >= g_pMlngInfo->Count())
|
|
goto Exit;
|
|
|
|
pml = g_pMlngInfo->GetPtr(nId);
|
|
if (!pml)
|
|
goto Exit;
|
|
|
|
uIconIndex = pml->GetIconIndex();
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
return uIconIndex;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// void ClearMlngIconIndex()
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ClearMlngIconIndex()
|
|
{
|
|
int i;
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
Assert(g_pMlngInfo);
|
|
|
|
for (i = 0; i < g_pMlngInfo->Count(); i++)
|
|
{
|
|
MLNGINFO *pml;
|
|
pml = g_pMlngInfo->GetPtr(i);
|
|
if (!pml)
|
|
goto Exit;
|
|
|
|
pml->ClearIconIndex();
|
|
}
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
return;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IconImageList
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// EnsureIconImageList
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL EnsureIconImageList()
|
|
{
|
|
if (g_IconList.IsInited())
|
|
return TRUE;
|
|
|
|
g_IconList.Init(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// InatAddIcon
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
UINT InatAddIcon(HICON hIcon)
|
|
{
|
|
if (!EnsureIconImageList())
|
|
return -1;
|
|
|
|
return g_IconList.AddIcon(hIcon);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// InatExtractIcon
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HICON WINAPI TF_InatExtractIcon(UINT uId)
|
|
{
|
|
return g_IconList.ExtractIcon(uId);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// InatGetIconSize
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL InatGetIconSize(int *pcx, int *pcy)
|
|
{
|
|
g_IconList.GetIconSize(pcx, pcy);
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// InatGetImageCount
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL InatGetImageCount()
|
|
{
|
|
return g_IconList.GetImageCount();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// InatRemoveAll
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void InatRemoveAll()
|
|
{
|
|
if (!g_IconList.IsInited())
|
|
return;
|
|
|
|
g_IconList.RemoveAll(FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HKL API
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// CPreloadRegKey
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class CPreloadRegKey : public CMyRegKey
|
|
{
|
|
public:
|
|
HRESULT Open(BOOL fDefaultUser = FALSE)
|
|
{
|
|
if (fDefaultUser)
|
|
return CMyRegKey::Open(HKEY_USERS, c_szDefaultUserPreload, KEY_ALL_ACCESS);
|
|
else
|
|
return CMyRegKey::Open(HKEY_CURRENT_USER, c_szPreload, KEY_ALL_ACCESS);
|
|
}
|
|
|
|
HKL Get(int n)
|
|
{
|
|
char szValue[16];
|
|
char szValueName[16];
|
|
StringCchPrintf(szValueName, ARRAYSIZE(szValueName), "%d", n);
|
|
|
|
if (IsOnNT())
|
|
{
|
|
if (QueryValueCch(szValue, szValueName, ARRAYSIZE(szValue)) != S_OK)
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
CMyRegKey keySub;
|
|
if (keySub.Open(m_hKey, szValueName, KEY_READ) != S_OK)
|
|
return NULL;
|
|
|
|
if (keySub.QueryValueCch(szValue, NULL, ARRAYSIZE(szValue)) != S_OK)
|
|
return NULL;
|
|
}
|
|
|
|
return (HKL)(LONG_PTR)AsciiToNum(szValue);
|
|
}
|
|
|
|
void Set(int n, HKL hkl)
|
|
{
|
|
char szValue[16];
|
|
char szValueName[16];
|
|
StringCchPrintf(szValueName, ARRAYSIZE(szValueName), "%d", n);
|
|
NumToA((DWORD)(LONG_PTR)hkl, szValue);
|
|
|
|
if (IsOnNT())
|
|
{
|
|
SetValue(szValue, szValueName);
|
|
}
|
|
else
|
|
{
|
|
CMyRegKey keySub;
|
|
if (keySub.Open(m_hKey, szValueName, KEY_ALL_ACCESS) == S_OK)
|
|
keySub.SetValue(szValue, (LPSTR)NULL);
|
|
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Delete(int n)
|
|
{
|
|
char szValueName[16];
|
|
StringCchPrintf(szValueName, ARRAYSIZE(szValueName), "%d", n);
|
|
|
|
if (IsOnNT())
|
|
{
|
|
DeleteValue(szValueName);
|
|
}
|
|
else
|
|
{
|
|
DeleteSubKey(szValueName);
|
|
|
|
}
|
|
return;
|
|
}
|
|
};
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetSubstitute
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD GetSubstitute(HKL hKL)
|
|
{
|
|
CMyRegKey key;
|
|
DWORD dwIndex = 0;
|
|
TCHAR szValue[16];
|
|
TCHAR szValueName[64];
|
|
DWORD dwLayout = HandleToLong(hKL);
|
|
|
|
//
|
|
// it's IME.
|
|
//
|
|
if ((dwLayout & 0xf0000000) == 0xe0000000)
|
|
return dwLayout;
|
|
|
|
//
|
|
// it's default layout.
|
|
//
|
|
if (HIWORD(dwLayout) == LOWORD(dwLayout))
|
|
dwLayout &= 0x0000FFFF;
|
|
else if ((dwLayout & 0xf0000000) == 0xf0000000)
|
|
dwLayout = GetKbdLayoutId(dwLayout);
|
|
|
|
if (key.Open(HKEY_CURRENT_USER, c_szSubst, KEY_READ) != S_OK)
|
|
return dwLayout;
|
|
|
|
if (IsOnNT())
|
|
{
|
|
while (key.EnumValue(dwIndex, szValueName, ARRAYSIZE(szValueName)) == S_OK)
|
|
{
|
|
if (key.QueryValueCch(szValue, szValueName, ARRAYSIZE(szValue)) == S_OK)
|
|
{
|
|
if ((dwLayout & 0x0FFFFFFF) == AsciiToNum(szValue))
|
|
{
|
|
return AsciiToNum(szValueName);
|
|
}
|
|
}
|
|
dwIndex++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (key.EnumKey(dwIndex, szValueName, ARRAYSIZE(szValueName)) == S_OK)
|
|
{
|
|
CMyRegKey keySub;
|
|
if (keySub.Open(key, szValueName, KEY_READ) == S_OK)
|
|
{
|
|
if (key.QueryValueCch(szValue, NULL, ARRAYSIZE(szValue)) == S_OK)
|
|
{
|
|
if ((dwLayout & 0x0FFFFFFF) == AsciiToNum(szValue))
|
|
{
|
|
return AsciiToNum(szValueName);
|
|
}
|
|
}
|
|
}
|
|
dwIndex++;
|
|
}
|
|
}
|
|
|
|
return dwLayout;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetSystemDefaultHKL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SetSystemDefaultHKL(HKL hkl)
|
|
{
|
|
CPreloadRegKey key;
|
|
int n;
|
|
HKL hklFirst;
|
|
BOOL bRet = FALSE;
|
|
DWORD dwLayout;
|
|
|
|
if (key.Open() != S_OK)
|
|
return bRet;
|
|
|
|
dwLayout = GetSubstitute(hkl);
|
|
|
|
n = 1;
|
|
while(1)
|
|
{
|
|
HKL hklCur;
|
|
hklCur = key.Get(n);
|
|
if (!hklCur)
|
|
break;
|
|
|
|
if (n == 1)
|
|
hklFirst = hklCur;
|
|
|
|
if (hklCur == LongToHandle(dwLayout))
|
|
{
|
|
bRet = TRUE;
|
|
if (n != 1)
|
|
{
|
|
key.Set(n, hklFirst);
|
|
key.Set(1, hklCur);
|
|
|
|
}
|
|
bRet = SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
|
|
0,
|
|
(LPVOID)((LPDWORD)&hkl),
|
|
0 );
|
|
|
|
Assert(bRet);
|
|
break;
|
|
}
|
|
|
|
n++;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetPreloadListForNT()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
UINT GetPreloadListForNT(DWORD *pdw, UINT uBufSize)
|
|
{
|
|
CMyRegKey key;
|
|
CMyRegKey key1;
|
|
char szValue[16];
|
|
char szSubstValue[16];
|
|
char szName[16];
|
|
UINT uRet = 0;
|
|
|
|
//
|
|
// this function support only NT.
|
|
// win9x has different formation for Preload registry. Each layout is key.
|
|
//
|
|
if (!IsOnNT())
|
|
return 0;
|
|
|
|
if (key.Open(HKEY_CURRENT_USER, c_szPreload, KEY_READ) != S_OK)
|
|
return uRet;
|
|
|
|
key1.Open(HKEY_CURRENT_USER, c_szSubst, KEY_READ);
|
|
|
|
if (!pdw)
|
|
uBufSize = 1000;
|
|
|
|
while (uRet < uBufSize)
|
|
{
|
|
BOOL fUseSubst = FALSE;
|
|
StringCchPrintf(szName, ARRAYSIZE(szName), "%d", uRet + 1);
|
|
if (key.QueryValueCch(szValue, szName, ARRAYSIZE(szValue)) != S_OK)
|
|
return uRet;
|
|
|
|
if ((HKEY)key1)
|
|
{
|
|
if (key1.QueryValueCch(szSubstValue, szValue, ARRAYSIZE(szSubstValue)) == S_OK)
|
|
fUseSubst = TRUE;
|
|
|
|
}
|
|
|
|
if (pdw)
|
|
{
|
|
*pdw = AsciiToNum(fUseSubst ? szSubstValue : szValue);
|
|
pdw++;
|
|
}
|
|
|
|
uRet++;
|
|
}
|
|
|
|
return uRet;
|
|
}
|
|
|
|
#ifdef LATER_TO_CHECK_DUMMYHKL
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RemoveFEDummyHKLFromPreloadReg()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void RemoveFEDummyHKLFromPreloadReg(HKL hkl, BOOL fDefaultUser)
|
|
{
|
|
CPreloadRegKey key;
|
|
BOOL fReset = FALSE;
|
|
UINT uCount;
|
|
UINT uMatch = 0;
|
|
|
|
if (key.Open(fDefaultUser) != S_OK)
|
|
return;
|
|
|
|
uCount = 1;
|
|
|
|
while(uCount < 1000)
|
|
{
|
|
HKL hklCur;
|
|
hklCur = key.Get(uCount);
|
|
if (!hklCur)
|
|
break;
|
|
|
|
if (hklCur == hkl)
|
|
{
|
|
uMatch++;
|
|
uCount++;
|
|
fReset = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (fReset && uMatch)
|
|
{
|
|
if (uCount <= uMatch)
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// reset the hkl orders from preload section
|
|
//
|
|
key.Set(uCount-uMatch, hklCur);
|
|
}
|
|
|
|
uCount++;
|
|
}
|
|
|
|
while (fReset && uMatch && uCount)
|
|
{
|
|
if (uCount <= uMatch || (uCount - uMatch) <= 1)
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// remove the dummy hkl from preload section
|
|
//
|
|
key.Delete(uCount - uMatch);
|
|
|
|
uMatch--;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// RemoveFEDummyHKLs
|
|
//
|
|
// This function cleans up the FE Dummy HKLs that were added on Win9x.
|
|
// This is called during update setup to Whistler.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void RemoveFEDummyHKLs()
|
|
{
|
|
CMyRegKey key;
|
|
DWORD dwIndex;
|
|
TCHAR szValue[MAX_PATH];
|
|
|
|
//
|
|
// Now read all the locales from the registry.
|
|
//
|
|
if (key.Open(HKEY_LOCAL_MACHINE, c_szLayoutPath) != ERROR_SUCCESS)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
szValue[0] = TEXT('\0');
|
|
while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == ERROR_SUCCESS)
|
|
{
|
|
BOOL fDelete = FALSE;
|
|
CRegKeyMUI key1;
|
|
|
|
if ((szValue[0] != 'e') && (szValue[0] != 'E'))
|
|
goto Next;
|
|
|
|
if (key1.Open(key, szValue) == S_OK)
|
|
{
|
|
TCHAR szValueLayoutText[MAX_PATH];
|
|
|
|
//
|
|
// Get the layout text.
|
|
//
|
|
szValueLayoutText[0] = TEXT('\0');
|
|
|
|
if (key1.QueryValueCch(szValueLayoutText, c_szLayoutText, ARRAYSIZE(szValueLayoutText)) == S_OK)
|
|
{
|
|
char szDummyProfile[256];
|
|
DWORD dw = AsciiToNum(szValue);
|
|
StringCchPrintf(szDummyProfile, ARRAYSIZE(szDummyProfile), "hkl%04x", LOWORD(dw));
|
|
if (!lstrcmpi(szDummyProfile, szValueLayoutText))
|
|
{
|
|
fDelete = TRUE;
|
|
|
|
//
|
|
// Remove dummy HKL from Preload of HKCU and HKU\.DEFAULT.
|
|
// We may need to enum all users in HKU\.DEFAULT.
|
|
//
|
|
RemoveFEDummyHKLFromPreloadReg((HKL)LongToHandle(dw), TRUE);
|
|
RemoveFEDummyHKLFromPreloadReg((HKL)LongToHandle(dw), FALSE);
|
|
}
|
|
}
|
|
|
|
key1.Close();
|
|
}
|
|
|
|
if (fDelete)
|
|
{
|
|
key.RecurseDeleteKey(szValue);
|
|
}
|
|
else
|
|
{
|
|
Next:
|
|
dwIndex++;
|
|
}
|
|
|
|
szValue[0] = TEXT('\0');
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#endif LATER_TO_CHECK_DUMMYHKL
|