#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 *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 *_prgIcons; }; CStaticIconList g_IconList; int CStaticIconList::_cx = 0; int CStaticIconList::_cy = 0; CStructArray *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; 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 *pLayouts = NULL; LAYOUT *pLayout; BOOL bLoadedLayout; pLayouts = new CStructArray; 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; 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