|
|
#include "private.h"
#include "globals.h"
#include "regsvr.h"
#include "catutil.h"
#include "cregkey.h"
#include "assembly.h"
#include "immxutil.h"
#include "osver.h"
#include "internat.h"
#include "cicmutex.h"
#include "imelist.h"
#include "tim.h"
extern CCicMutex g_mutexAsm; extern char g_szAsmListCache[];
extern HRESULT g_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum);
//+---------------------------------------------------------------------------
//
// TF_GetLangIcon
//
//+---------------------------------------------------------------------------
HICON WINAPI TF_GetLangIcon(WORD langid , WCHAR *psz, UINT cchMax) { if (psz) { SYSTHREAD *psfn = GetSYSTHREAD(); CAssemblyList *pAsmList; *psz = L'\0';
if (psfn && (pAsmList = EnsureAssemblyList(psfn))) { CAssembly *pAsm = pAsmList->FindAssemblyByLangId(langid); if (pAsm) { StringCchCopyW(psz, cchMax, pAsm->GetLangName()); } } }
return InatCreateIcon(langid); }
//----------------------------------------------------------------------------
//
// GetSubstituteHKLfromKey
//
//----------------------------------------------------------------------------
HKL GetSubstituteHKLfromKey(CMyRegKey *pkey, LANGID langid) { char sz[16];
if (pkey->QueryValueCch(sz, c_szSubstitutehKL, ARRAYSIZE(sz)) != S_OK) return NULL;
HKL hkl = NULL; if ((sz[0] == '0') && ((sz[1] == 'X') || (sz[1] == 'x'))) { hkl = (HKL)IntToPtr(AsciiToNum(&sz[2])); if (LOWORD(HandleToLong(hkl)) != langid) { //
// bad substitution.
//
Assert(0); hkl = 0; } } return hkl; }
//////////////////////////////////////////////////////////////////////////////
//
// CAssembly
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CAssembly::CAssembly(LANGID langid) { _langid = langid;
if (IsOnNT()) { if (!GetLocaleInfoW(MAKELCID(langid, SORT_DEFAULT), LOCALE_SLANGUAGE, _szLangName, ARRAYSIZE(_szLangName))) { StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), L"Unknown Language"); } else { _szLangName[ARRAYSIZE(_szLangName)-1] = 0; // in case GetLocaleInfoW truncates
} } else { char szLangName[64]; if (GetLocaleInfo(MAKELCID(langid, SORT_DEFAULT), LOCALE_SLANGUAGE, szLangName, sizeof(szLangName))) { szLangName[ARRAYSIZE(szLangName)-1] = 0; // in case GetLocaleInfoW truncates
StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), AtoW(szLangName)); } else { StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), L"Unknown Language"); } }
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CAssembly::~CAssembly() { }
//+---------------------------------------------------------------------------
//
// IsFEIMEActive()
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsFEIMEActive() { int i; if (IsFELangId(GetLangId())) { for (i = 0; i < Count(); i++) { ASSEMBLYITEM *pItem = GetItem(i); if (pItem->fActive && IsPureIMEHKL(pItem->hkl)) { Assert(IsEqualGUID(pItem->clsid, GUID_NULL)); return TRUE; } } }
#ifdef CHECKFEIMESELECTED
if (_fUnknownFEIMESelected) return TRUE; #endif CHECKFEIMESELECTED
return FALSE; }
//+---------------------------------------------------------------------------
//
// FindItemByCategory
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindItemByCategory(REFGUID catid) { int nCnt = _rgAsmItem.Count(); int i; if (IsEqualGUID(catid, GUID_NULL)) return NULL;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (IsEqualGUID(pItemTmp->catid, catid)) return pItemTmp; } return NULL; }
//+---------------------------------------------------------------------------
//
// FindActiveKeyboardItem
//
// Why do you call this if there is no FocusDIM? You should not do.
// fActive is not reliable if there is no FocusDIM.
// Ser SetFocusDIMForAssembly(BOOL fSetFocus) in profiles.cpp. we don't
// change fActive but switch hKL when the focus moves to non DIM control.
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindActiveKeyboardItem() { int nCnt = _rgAsmItem.Count(); int i;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (!pItemTmp->fEnabled) continue;
if (!pItemTmp->fActive) continue;
if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD)) return pItemTmp; } return NULL; }
//+---------------------------------------------------------------------------
//
// FindKeyboardLayoutItem
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindKeyboardLayoutItem(HKL hkl) { int nCnt = _rgAsmItem.Count(); int i;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (!IsEqualGUID(pItemTmp->clsid, GUID_NULL)) continue;
if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD) && (pItemTmp->hkl == hkl)) { return pItemTmp; } } return NULL; }
//+---------------------------------------------------------------------------
//
// FindItemByCategory2
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabledItemByCategory(REFGUID catid) { int nCnt = _rgAsmItem.Count(); int i;
if (IsEqualGUID(catid, GUID_NULL)) return FALSE;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (!IsEqualGUID(pItemTmp->catid, catid) && pItemTmp->fEnabled) return TRUE; } return FALSE; }
//+---------------------------------------------------------------------------
//
// IsEnabledItem
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabledItem() { int nCnt = _rgAsmItem.Count(); int i;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (pItemTmp->fEnabled) return TRUE; } return FALSE; }
//+---------------------------------------------------------------------------
//
// FindPureKbdTipItem
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindPureKbdTipItem() { int nCnt = _rgAsmItem.Count(); int i;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD) && !IsPureIMEHKL(pItemTmp->hkl)) return pItemTmp; } return NULL; }
//+---------------------------------------------------------------------------
//
// IsNonCiceroItem
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsNonCiceroItem() { int nCnt = _rgAsmItem.Count(); int i; BOOL fFound = FALSE;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (!pItemTmp->fEnabled) continue;
if (!IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD)) continue;
if (IsEqualGUID(pItemTmp->clsid, GUID_NULL)) { if (IsFELangId(LOWORD((DWORD)(LONG_PTR)(HKL)pItemTmp->hkl))) { if (!IsPureIMEHKL(pItemTmp->hkl)) { // Assert(0);
continue; } }
return TRUE; } } return FALSE; }
//+---------------------------------------------------------------------------
//
// IsEnabled
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabled(SYSTHREAD *psfn) { CThreadInputMgr *ptim; ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
if (!ptim || !ptim->_GetFocusDocInputMgr()) return IsNonCiceroItem() ? TRUE : FALSE;
return IsEnabledKeyboardItem(psfn); }
//+---------------------------------------------------------------------------
//
// IsEnabledKeyboardItem
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabledKeyboardItem(SYSTHREAD *psfn) { int nCnt = _rgAsmItem.Count(); int i; BOOL fFound = FALSE;
for (i = 0; i < nCnt; i++) { ASSEMBLYITEM *pItemTmp; pItemTmp = _rgAsmItem.GetPtr(i);
if (!pItemTmp->fEnabled) continue;
if (!IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD)) continue;
fFound = TRUE; break; }
return fFound; }
//+---------------------------------------------------------------------------
//
// RebuildSubstitutedHKLList
//
//----------------------------------------------------------------------------
void CAssembly::RebuildSubstitutedHKLList() { int i; _rghklSubstituted.Clear();
for (i = 0; i < Count(); i++) { ASSEMBLYITEM *pItem = GetItem(i);
if (!pItem->fEnabled) continue;
if (!pItem->hklSubstitute) continue;
if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) && !IsEqualGUID(pItem->clsid, GUID_NULL)) { HKL *phkl = _rghklSubstituted.Append(1); if (phkl) *phkl = pItem->hklSubstitute; } }
}
//+---------------------------------------------------------------------------
//
// IsSubstitutedHKL
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsSubstitutedHKL(HKL hkl) { int nCnt = _rghklSubstituted.Count(); int i;
for (i = 0; i < nCnt; i++) { HKL *phkl = _rghklSubstituted.GetPtr(i); if (*phkl == hkl) return TRUE; }
return FALSE; }
//+---------------------------------------------------------------------------
//
// GetSubstituteItem
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::GetSubstituteItem(HKL hKL) { int i; BOOL fCheckActive = TRUE;
TryAgain: for (i = 0; i < Count(); i++) { ASSEMBLYITEM *pItem = GetItem(i);
if (!pItem->fEnabled) continue;
if (!pItem->hklSubstitute) continue;
if (fCheckActive) { if (!pItem->fActive) continue; }
if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) && !IsEqualGUID(pItem->clsid, GUID_NULL)) { if (hKL == pItem->hklSubstitute) { return pItem; } } }
if (fCheckActive) { fCheckActive = FALSE; goto TryAgain; } return NULL; }
//////////////////////////////////////////////////////////////////////////////
//
// CDefaultProfiles
//
// This class is a database for the default profiles and this database is
// created from HKCU\Software\Microsoft\CTF\TIP
//
// however we need to respect the system default hKL setting. If the keyboard
// tip's profile has a substitute hKL and this is not the system default hKL
// we use the system default hKL as a default profile.
//
//////////////////////////////////////////////////////////////////////////////
class CDefaultProfiles { public: CDefaultProfiles(LANGID langid) { _langid = langid; }
~CDefaultProfiles() { _rgDefProfiles.Clear(); }
BOOL Init(HKL *phkl); BOOL FilterProfiles(CAssembly *pAsm);
typedef struct tag_DEFAULTPROFILE { GUID catid; CLSID clsid; GUID guidProfile; HKL hkl; } DEFAULTPROFILE;
BOOL GetDefaultProfile(GUID catid, GUID *pclsid, GUID *pguidProfile, HKL *phkl);
BOOL Append(GUID catid, CLSID clsid, GUID guidProfile, HKL hkl) { DEFAULTPROFILE defpro; DEFAULTPROFILE *pdefpro;
int i; for (i = 0; i < _rgDefProfiles.Count(); i++) { pdefpro = _rgDefProfiles.GetPtr(i); if (!pdefpro) { Assert(0); return FALSE; }
if (IsEqualGUID(catid, pdefpro->catid)) return FALSE; }
defpro.catid = catid; defpro.clsid = clsid; defpro.guidProfile = guidProfile; defpro.hkl = hkl;
pdefpro = _rgDefProfiles.Append(1); if (!pdefpro) return FALSE;
memcpy(pdefpro, &defpro, sizeof(defpro)); return TRUE; }
private: BOOL GetSubstitutedItem(HKL hklSub, DEFAULTPROFILE *pdefpro); LANGID _langid; CStructArray<DEFAULTPROFILE> _rgDefProfiles; };
//+---------------------------------------------------------------------------
//
// Init
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::Init(HKL *phkl) { CMyRegKey key; DWORD dw; char szKey[256]; char szName[CLSID_STRLEN + 1]; HKL hklDef = GetSystemDefaultHKL(); BOOL fFoundKeyboardIteminDefLang = FALSE; DEFAULTPROFILE defpro; DEFAULTPROFILE *pdefpro; DWORD dwIndex;
StringCopyArray(szKey, c_szAsmKey); StringCatArray(szKey, "\\"); StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey)-lstrlen(szKey), "0x%08x", _langid);
if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK) goto Exit;
dwIndex = 0; while (key.EnumKey(dwIndex, szKey, ARRAYSIZE(szKey)) == S_OK) { CMyRegKey subkey;
if (subkey.Open(key, szKey, KEY_READ) != S_OK) goto Next;
StringAToCLSID(szKey, &defpro.catid);
//
// retreive tip clsid.
//
if (subkey.QueryValueCch(szName, c_szDefault, ARRAYSIZE(szName)) != S_OK) goto Next; StringAToCLSID(szName, &defpro.clsid);
//
// retreive guid profile
//
if (subkey.QueryValueCch(szName, c_szProfile, ARRAYSIZE(szName)) != S_OK) goto Next; StringAToCLSID(szName, &defpro.guidProfile);
if (subkey.QueryValue(dw, c_szKeyboardLayout) != S_OK) goto Next;
//
// check the hkl from registry is valid or not.
//
defpro.hkl = (HKL)IntToPtr(dw); if (defpro.hkl) { int i = 0; BOOL fFound = FALSE; while(phkl[i]) { if (defpro.hkl == phkl[i]) { fFound = TRUE; break; } i++; } if (!fFound) goto Next; }
//
// if the system default hKL does not matched with
// the substite hKL of this profile, this profile can not be
// default profile. Instead the system default hKL became a
// default profile item.
//
if ((LOWORD(HandleToLong(hklDef)) == _langid) && IsEqualGUID(defpro.catid, GUID_TFCAT_TIP_KEYBOARD)) { char szTmp[256]; HKL hklSubstitute = NULL; fFoundKeyboardIteminDefLang = TRUE;
if (InitProfileRegKeyStr(szTmp, ARRAYSIZE(szTmp), defpro.clsid, _langid, defpro.guidProfile)) { CMyRegKey keySubstitute;
if (keySubstitute.Open(HKEY_LOCAL_MACHINE, szTmp, KEY_READ) == S_OK) { hklSubstitute = GetSubstituteHKLfromKey(&keySubstitute, _langid); } }
// Removed Chinese specific code for bug#427476
if (IsEqualGUID(defpro.clsid, GUID_NULL) || (hklSubstitute && (hklSubstitute != hklDef))) { defpro.clsid = CLSID_NULL; defpro.guidProfile = GUID_NULL; defpro.hkl = hklDef; } }
pdefpro = _rgDefProfiles.Append(1); if (!pdefpro) return FALSE;
memcpy(pdefpro, &defpro, sizeof(defpro));
#ifdef DEBUG
{ char szDbgCatid[CLSID_STRLEN + 1]; char szDbgClsid[CLSID_STRLEN + 1]; char szDbgguidProfile[CLSID_STRLEN + 1]; CLSIDToStringA(defpro.catid, szDbgCatid); CLSIDToStringA(defpro.clsid, szDbgClsid); CLSIDToStringA(defpro.guidProfile, szDbgguidProfile); TraceMsg(TF_GENERAL, "CDefaultProfiles:: langid %08x", _langid); TraceMsg(TF_GENERAL, " catid %s", szDbgCatid); TraceMsg(TF_GENERAL, " clsid %s", szDbgClsid); TraceMsg(TF_GENERAL, " guidProfile %s", szDbgguidProfile); TraceMsg(TF_GENERAL, " hkl %08x", (DWORD)HandleToLong(defpro.hkl)); } #endif
Next: dwIndex++; }
Exit: if (LOWORD(HandleToLong(hklDef)) == _langid) { if (!fFoundKeyboardIteminDefLang) { //
// Check if the default hkl is a substitute hKL of a TIP's
// profile.
//
if (!GetSubstitutedItem(hklDef, &defpro)) { //
// we could not find TIP profile. Use this hkl as a default
// item.
//
defpro.catid = GUID_TFCAT_TIP_KEYBOARD; defpro.clsid = CLSID_NULL; defpro.guidProfile = GUID_NULL; defpro.hkl = hklDef; }
pdefpro = _rgDefProfiles.Append(1); if (!pdefpro) return FALSE;
memcpy(pdefpro, &defpro, sizeof(defpro)); } }
return TRUE; }
//+---------------------------------------------------------------------------
//
// GetSubstitutedItem
//
// this function walks HKLM\Software\Microsoft\CTF\TIPs to find the
// TIP profile that uses hklSub as its substitute hKL.
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::GetSubstitutedItem(HKL hklSub, DEFAULTPROFILE *pdefpro) { CMyRegKey key; DWORD dwIndex; TCHAR szKey[256]; TCHAR szSubKey[256]; TCHAR szLangKey[256]; TCHAR szValue[256];
StringCopyArray(szKey, c_szCTFTIPKey); if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) != S_OK) { return FALSE; }
// get all profiles from LanguageProfile registry.
//
dwIndex = 0; while (key.EnumKey(dwIndex, szSubKey, ARRAYSIZE(szSubKey)) == S_OK) { CMyRegKey subkey; CLSID clsid; StringAToCLSID(szSubKey, &clsid);
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s", c_szLanguageProfileKey) != S_OK) goto Next0;
if (subkey.Open(key, szSubKey, KEY_READ) != S_OK) goto Next0;
DWORD dwIndexLang = 0; while (subkey.EnumKey(dwIndexLang, szLangKey, ARRAYSIZE(szLangKey)) == S_OK) { CMyRegKey langkey; LANGID langid;
if ((szLangKey[0] != '0') || ((szLangKey[1] != 'X') && (szLangKey[1] != 'x'))) goto Next1;
langid = (LANGID)AsciiToNum(&szLangKey[2]);
//
// The language ID does not meet the given hklSub.
//
if (langid != LANGIDFROMHKL(hklSub)) goto Next1;
if (langkey.Open(subkey, szLangKey, KEY_READ) != S_OK) goto Next1;
DWORD dwProfileIndex = 0; while (langkey.EnumKey(dwProfileIndex, szValue, ARRAYSIZE(szValue)) == S_OK) { GUID guidProfile; CRegKeyMUI keyProfile; if (!StringAToCLSID(szValue, &guidProfile)) goto Next2;
if (keyProfile.Open(langkey, szValue, KEY_READ) == S_OK) { if (hklSub == GetSubstituteHKLfromKey(&keyProfile, langid)) { //
// ok, we found it. Assume it is Keyboard category.
//
pdefpro->catid = GUID_TFCAT_TIP_KEYBOARD; pdefpro->clsid = clsid; pdefpro->guidProfile = guidProfile; pdefpro->hkl = 0;
return TRUE; } }
Next2: dwProfileIndex++; } Next1: dwIndexLang++; }
Next0: dwIndex++; }
return FALSE; }
//+---------------------------------------------------------------------------
//
// FilterProfiles
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::FilterProfiles(CAssembly *pAsm) { int i; int j; Assert(_langid == pAsm->GetLangId());
for (i = _rgDefProfiles.Count() - 1; i >= 0 ; i--) { DEFAULTPROFILE *pdefpro = _rgDefProfiles.GetPtr(i); if (!pdefpro) { Assert(0); return FALSE; }
BOOL fFound = FALSE;
for (j = 0; j < pAsm->Count(); j++) { ASSEMBLYITEM *pItem = pAsm->GetItem(j);
if (IsEqualGUID(pItem->catid, pdefpro->catid) && IsEqualGUID(pItem->clsid, pdefpro->clsid) && IsEqualGUID(pItem->guidProfile, pdefpro->guidProfile)) { fFound = pItem->fEnabled ? TRUE : FALSE; break; }
}
if (!fFound) { _rgDefProfiles.Remove(i, 1); } }
return TRUE; }
//+---------------------------------------------------------------------------
//
// GetDefaultProfile
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::GetDefaultProfile(GUID catid, GUID *pclsid, GUID *pguidProfile, HKL *phkl) { int i; for (i = 0; i < _rgDefProfiles.Count(); i++) { DEFAULTPROFILE *pdefpro = _rgDefProfiles.GetPtr(i); if (!pdefpro) { Assert(0); return FALSE; }
if (IsEqualGUID(catid, pdefpro->catid)) { *pclsid = pdefpro->clsid; *pguidProfile = pdefpro->guidProfile; *phkl = pdefpro->hkl; return TRUE; } }
return FALSE; }
//////////////////////////////////////////////////////////////////////////////
//
// CAssemblyList
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CAssemblyList::CAssemblyList() { }
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CAssemblyList::~CAssemblyList() { ClearAsms(); }
//+---------------------------------------------------------------------------
//
// ClearAsms
//
//----------------------------------------------------------------------------
void CAssemblyList::ClearAsms() { int i = 0; while (i < _rgAsm.Count()) { CAssembly *pAsm = _rgAsm.Get(i); delete pAsm; i++; } _rgAsm.Clear(); }
//+---------------------------------------------------------------------------
//
// FindAndCreateNewAssembly
//
//----------------------------------------------------------------------------
extern INATSYMBOL symInatSymbols[];
CAssembly *CAssemblyList::FindAndCreateNewAssembly(CPtrArray<CAssembly> *prgAsm, CPtrArray<CAssembly> *prgNutralAsm, LANGID langid) { CPtrArray<CAssembly> *prg;
if (langid == 0xffff) prg = prgNutralAsm; else prg = (langid & 0xfc00) ? prgAsm : prgNutralAsm;
//
// do we already have pAsm?
//
CAssembly *pAsm = FindAssemblyByLangIdInArray(prg, langid); if (pAsm == NULL) { pAsm = new CAssembly(langid);
if (pAsm) { CAssembly **ppAsm; ppAsm = prg->Append(1); if (ppAsm) { *ppAsm = pAsm; } else { delete pAsm; pAsm = NULL; } } } return pAsm; }
//+---------------------------------------------------------------------------
//
// AttachOriginalAssembly
//
//----------------------------------------------------------------------------
void CAssemblyList::AttachOriginalAssembly(CPtrArray<CAssembly> *prgAsmOrg) { int i; int j; SYSTHREAD *psfn = GetSYSTHREAD(); CAssembly *pAsm = FindAssemblyByLangId(GetCurrentAssemblyLangId(psfn));
if (!pAsm) return;
for (i = 0; i < prgAsmOrg->Count(); i++) { CAssembly *pAsmOrg = prgAsmOrg->Get(i);
if (pAsm->GetLangId() == pAsmOrg->GetLangId()) { for (j = 0; j < pAsm->Count(); j++) { int nId; ASSEMBLYITEM *pItem = pAsm->GetItem(j);
if (!pItem) continue;
nId = pAsmOrg->Find(pItem); if (nId >= 0) { ASSEMBLYITEM *pItemOrg; pItemOrg = pAsmOrg->GetItem(nId); BOOL fPrevActive = pItem->fActive; if (pItemOrg && (pItemOrg->fActive)) { pItem->fActive = pItemOrg->fActive;
//
// we need to deactivate all other item in the
// category.
//
if (!fPrevActive && pItem->fActive) { for (int k = 0; k < pAsm->Count(); k++) { ASSEMBLYITEM *pItemTemp = pAsm->GetItem(k); if (pItemTemp == pItem) continue;
if (IsEqualGUID(pItemTemp->catid, pItem->catid)) pItemTemp->fActive = FALSE; } } } } }
break; } } }
//+---------------------------------------------------------------------------
//
// Load
//
//----------------------------------------------------------------------------
extern INATSYMBOL symInatSymbols[];
HRESULT CAssemblyList::Load() { CMyRegKey key; CMyRegKey key2; int nhkl; HKL *lphkl = NULL; HKL hklList[2]; LANGID langid; int i; ASSEMBLYITEM ai; DWORD dwIndex; CAssembly *pAsm = NULL; BOOL fFoundActiveNoCic = FALSE; CPtrArray<CAssembly> *prgNutralAsm = NULL; IEnumGUID *pEnumCat = NULL; HRESULT hr; int nAsmCnt; CPtrArray<CAssembly> rgAsmOrg; TCHAR szKey[256]; TCHAR szSubKey[256]; TCHAR szLangKey[256]; TCHAR szValue[256];
//
// backup original assembly in rgAsmOrg;
//
for (i = 0; i < _rgAsm.Count(); i++) { pAsm = _rgAsm.Get(i); if (pAsm) { CAssembly **ppAsm = rgAsmOrg.Append(1); if (ppAsm) *ppAsm = pAsm; } } _rgAsm.Clear();
#ifdef PROFILE_UPDATE_REGISTRY // old code for tip setup.
if (IsUpdated()) { ClearUpdatedFlag(); } else #endif
{ if (LoadFromCache()) { AttachOriginalAssembly(&rgAsmOrg); hr = S_OK; goto Exit; } }
prgNutralAsm = new CPtrArray<CAssembly>; if (!prgNutralAsm) { hr = E_OUTOFMEMORY; goto Exit; }
StringCopyArray(szKey, c_szCTFTIPKey); if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) != S_OK) { hr = E_FAIL; goto Exit; }
nhkl = GetKeyboardLayoutList(0, NULL); if (nhkl) { lphkl = (HKL *)cicMemAllocClear(sizeof(HKL) * (nhkl + 1)); GetKeyboardLayoutList(nhkl, lphkl); } else { hklList[0] = GetKeyboardLayout(NULL); hklList[1] = NULL; lphkl = hklList; }
//
// clear Category cache
//
CCategoryMgr::FreeCatCache();
hr = g_EnumItemsInCategory(GUID_TFCAT_CATEGORY_OF_TIP, &pEnumCat); if (FAILED(hr)) { goto Exit; }
//
// Check all TIP CLSID under HKCU is valid TIP CLSIDs.
//
StringCopyArray(szKey, c_szCTFTIPKey); if (key2.Open(HKEY_CURRENT_USER, szKey, KEY_ALL_ACCESS) == S_OK) { dwIndex = 0; while (key2.EnumKey(dwIndex, szSubKey, ARRAYSIZE(szSubKey)) == S_OK) { CMyRegKey subkey; dwIndex++;
//
// if we could not open the subkey (CLSID key) in HKLM,
// HKCU should not have the subkey.
//
if (subkey.Open(key, szSubKey, KEY_READ) != S_OK) { if (key2.RecurseDeleteKey(szSubKey) == S_OK) dwIndex--; } } }
//
// get all profiles from LanguageProfile registry.
//
dwIndex = 0; while (key.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK) { CMyRegKey subkey; CLSID clsid; StringAToCLSID(szSubKey, &clsid);
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s", c_szLanguageProfileKey) != S_OK) continue;
if (subkey.Open(key, szSubKey, KEY_READ) == S_OK) { DWORD dwIndexLang = 0; while (subkey.EnumKey(dwIndexLang, szLangKey, ARRAYSIZE(szLangKey)) == S_OK) { CMyRegKey langkey;
if ((szLangKey[0] != '0') || ((szLangKey[1] != 'X') && (szLangKey[1] != 'x'))) goto Next;
langid = (LANGID)AsciiToNum(&szLangKey[2]);
//
// do we already have pAsm?
//
pAsm = FindAndCreateNewAssembly(&_rgAsm, prgNutralAsm, langid); if (pAsm == NULL) { hr = E_OUTOFMEMORY; goto Exit; }
if (langkey.Open(subkey, szLangKey, KEY_READ) == S_OK) { DWORD dwProfileIndex = 0; while (langkey.EnumKey(dwProfileIndex, szValue, ARRAYSIZE(szValue)) == S_OK) { GUID guidProfile; CRegKeyMUI keyProfile; if (!StringAToCLSID(szValue, &guidProfile)) goto NextKey;
memset(&ai, 0, ai.GetAlignSize()); ai.InitIconIndex(); ai.clsid = clsid; ai.fActive = FALSE; GetTIPCategory(clsid, &ai.catid, pEnumCat); ai.guidProfile = guidProfile; ai.fEnabled = FALSE; // we will assign proper hKL later.
ai.hkl = NULL;
hr = keyProfile.Open(langkey, szValue, KEY_READ); if (hr == S_OK) { ai.hklSubstitute = GetSubstituteHKLfromKey(&keyProfile, langid);
hr = keyProfile.QueryMUIValueW(ai.szProfile, c_szDescriptionW, c_szMUIDescriptionW, ARRAYSIZE(ai.szProfile)); DWORD dw; if ((keyProfile.QueryValue(dw, c_szDisabledOnTransitory) == S_OK) && dw) ai.fDisabledOnTransitory = TRUE; }
if (hr == S_OK) pAsm->Add(&ai); NextKey: dwProfileIndex++; } } Next: dwIndexLang++; }
} }
//
// check all assembly has KEYBOARD category.
// If not, we load keyboard layout for the assembly.
//
nAsmCnt = _rgAsm.Count(); for (i = 0; i < nAsmCnt; i++) { BOOL bLoaded; int j;
CAssembly *pAsmTmp = _rgAsm.Get(i); if (pAsmTmp->FindItemByCategory(GUID_TFCAT_TIP_KEYBOARD)) continue;
LANGID langidTmp = pAsmTmp->GetLangId();
//
// we can not use IsEnabledItem() here. We have not updated
// the enbaled status of Items yet.
//
// if (!pAsmTmp->IsEnabledItem())
// continue;
//
BOOL fFound = FALSE; for (j = 0; j < pAsmTmp->Count(); j++) { ASSEMBLYITEM *pItem = pAsmTmp->GetItem(j); if (pItem->fEnabled || IsEnabledLanguageProfileFromReg(pItem->clsid, pAsmTmp->_langid, pItem->guidProfile)) { fFound = TRUE; break; } }
if (!fFound) continue;
//
// Load a proper keyboard layout....
//
GetProperHKL(langidTmp, lphkl, &bLoaded);
if (bLoaded) { //
// re-create the keyboard layout list.
//
nhkl = GetKeyboardLayoutList(0, NULL); if (nhkl) { if (lphkl && (lphkl != hklList)) cicMemFree(lphkl); lphkl = (HKL *)cicMemAllocClear(sizeof(HKL) * (nhkl + 1)); GetKeyboardLayoutList(nhkl, lphkl); } else { hklList[0] = GetKeyboardLayout(NULL); hklList[1] = NULL; lphkl = hklList; } } }
//
// get all hKLs.
//
if (lphkl) { HKL *lphklCur = lphkl; DWORD *pdwPreload = NULL; UINT uPreloadCnt;
//
// load preload layouts infomation.
//
uPreloadCnt = GetPreloadListForNT(NULL, 0); if (uPreloadCnt) { Assert(IsOnNT()); pdwPreload = new DWORD[uPreloadCnt]; if (pdwPreload) GetPreloadListForNT(pdwPreload, uPreloadCnt); }
while (*lphklCur) { BOOL fIsDefaultHKLinPreload = FALSE; WORD wLayout = HIWORD((DWORD)(LONG_PTR)(*lphklCur)); langid = (LANGID)((DWORD)(LONG_PTR)(*lphklCur) & 0x0000ffff); //
// do we already have pAsm?
//
pAsm = FindAndCreateNewAssembly(&_rgAsm, prgNutralAsm, langid); if (pAsm == NULL) { hr = E_OUTOFMEMORY; goto Exit; }
//
// See Preload to check if this default hKL is real dummy or not.
// The default FE layout is not a dummy hKL if it is in Preload
// list.
//
if (IsFELangId(langid)) { if (wLayout == (WORD)langid) { UINT uCur; for (uCur = 0; uCur < uPreloadCnt; uCur++) { //
// check if we have 0x00000411 in preload.
//
if (pdwPreload[uCur] == (DWORD)(wLayout)) { fIsDefaultHKLinPreload = TRUE; break; } } } else if ((wLayout & 0xf000) != 0xe000) { fIsDefaultHKLinPreload = TRUE; } }
//
// we skip dummy FE hKL.
//
if (!IsFELangId(langid) || IsPureIMEHKL(*lphklCur) || fIsDefaultHKLinPreload || !pAsm->FindPureKbdTipItem()) { TF_InitMlngInfo(); MLNGINFO mlInfo; if (pAsm == NULL) pAsm = new CAssembly(langid); memset(&ai, 0, ai.GetAlignSize()); ai.InitIconIndex(); ai.hkl = *lphklCur; ai.clsid = GUID_NULL; ai.catid = GUID_TFCAT_TIP_KEYBOARD; ai.fActive = FALSE; ai.fEnabled = TRUE; if (GetMlngInfoByhKL(ai.hkl, &mlInfo) == -1) mlInfo.SetDesc(L""); ai.guidProfile = GUID_NULL; StringCopyArrayW(ai.szProfile, mlInfo.GetDesc());
pAsm->Add(&ai); } lphklCur++; } if (pdwPreload) delete pdwPreload; }
//
// filter neutral langiage assembly
//
while (prgNutralAsm->Count()) { pAsm = prgNutralAsm->Get(0); langid = pAsm->GetLangId();
Assert((langid == 0xffff) || !(langid & 0xFC00));
//
// find valid langid ang merge there.
//
for (i = 0; i < _rgAsm.Count(); i++) { CAssembly *pAsmDst = _rgAsm.Get(i); LANGID langidDst = pAsmDst->GetLangId(); Assert(langidDst & 0xFC00);
//
// we found a valid langid.
//
if ((langid == 0xffff) || (PRIMARYLANGID(langid) == PRIMARYLANGID(langidDst))) { int j; for (j = 0; j < pAsm->Count(); j++) { ASSEMBLYITEM *pItem = pAsm->GetItem(j); pItem->fActive = FALSE; pItem->fActiveNoCic = FALSE;
// we will assign proper hKL later.
pItem->hkl = NULL;
pAsmDst->Add(pItem); } } }
//
// we don't need a neutral lang assembly.
//
prgNutralAsm->Remove(0, 1); delete pAsm; }
//
// It is time to decide this profile should be activated by default.
//
for (i = 0; i < _rgAsm.Count(); i++) { int j; pAsm = _rgAsm.Get(i);
CDefaultProfiles defProfiles(pAsm->_langid); defProfiles.Init(lphkl);
//
// update Enable status.
//
// this must be done before filtering the default profiles.
// disabled item should not be the default proble.
//
for (j = 0; j < pAsm->Count(); j++) { ASSEMBLYITEM *pItem = pAsm->GetItem(j); if (!pItem->fEnabled) pItem->fEnabled = IsEnabledLanguageProfileFromReg(pItem->clsid, pAsm->_langid, pItem->guidProfile); }
//
// check if the default profile is enabled.
//
defProfiles.FilterProfiles(pAsm);
for (j = 0; j < pAsm->Count(); j++) { ASSEMBLYITEM *pItem = pAsm->GetItem(j); CLSID clsid; GUID guidProfile; HKL hkl;
//
// If the item is not categoried, we activate it.
//
if (IsEqualGUID(pItem->catid, GUID_NULL)) { pItem->fActive = TRUE; continue; }
//
// if this item is enabled, load proper hkl.
//
if (pItem->fEnabled && IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) && !pItem->hkl) pItem->hkl = GetProperHKL(pAsm->_langid, lphkl, NULL);
//
// init fActivate to false by default.
//
pItem->fActive = FALSE;
if (pItem->fEnabled) { //
// GetDefaultProfile() may return NULL in hkl if someone calls
// ITfInputProcessorProfiles::SetDefaultLanguageProfile() method
// from outside. We should not check hkl value then.
//
if (defProfiles.GetDefaultProfile(pItem->catid, &clsid, &guidProfile, &hkl)) {
//
// ok this item is not default profile.
//
if (!IsEqualCLSID(pItem->clsid, clsid) || !IsEqualCLSID(pItem->guidProfile, guidProfile) || (hkl && (pItem->hkl != hkl))) continue;
pItem->fActive = TRUE; } else if (defProfiles.Append(pItem->catid, pItem->clsid, pItem->guidProfile, pItem->hkl)) { pItem->fActive = TRUE; } } }
#ifdef DEBUG
for (j = 0; j < pAsm->Count(); j++) { ASSEMBLYITEM *pItem = pAsm->GetItem(j); int k; if (!pItem->fActive) { UINT uCnt = 0;
for (k = 0; k < pAsm->Count(); k++) { ASSEMBLYITEM *pItemTemp = pAsm->GetItem(k); if (IsEqualGUID(pItemTemp->catid, pItem->catid)) uCnt += (pItemTemp->fActive) ? 1 : 0; } Assert(uCnt <= 1); } } #endif
}
//
// we should create cache before attaching the original assembly active
// status.
// AttachOriginalAssembly() is just for the current thread.
//
if (IsAsmCache()) CreateCache();
if (rgAsmOrg.Count()) AttachOriginalAssembly(&rgAsmOrg);
hr = S_OK;
Exit:
if (lphkl && (lphkl != hklList)) cicMemFree(lphkl);
if (prgNutralAsm) { Assert(!prgNutralAsm->Count()) delete prgNutralAsm; }
if (pEnumCat) pEnumCat->Release();
//
// clean up original assemblies.
//
for (i = 0; i < rgAsmOrg.Count(); i++) { pAsm = rgAsmOrg.Get(i); delete pAsm; } rgAsmOrg.Clear();
return hr; }
//+---------------------------------------------------------------------------
//
// GetDefaultAssembly
//
//----------------------------------------------------------------------------
CAssembly *CAssemblyList::GetDefaultAssembly() { CAssembly *pAsm = NULL; int nAsmCnt = _rgAsm.Count(); DWORD langid;
if (!nAsmCnt) return NULL;
langid = (LANGID)LOWORD(HandleToLong(GetSystemDefaultHKL())); if (!langid) return _rgAsm.Get(0);
int nCurAsm = 0;
while (nCurAsm < nAsmCnt) { CAssembly *pAsmTmp = _rgAsm.Get(nCurAsm); if (pAsmTmp->_langid == langid) { pAsm = pAsmTmp; break; } nCurAsm++; }
if (!pAsm) pAsm = _rgAsm.Get(0);
return pAsm; }
//+---------------------------------------------------------------------------
//
// CreateCache
//
//----------------------------------------------------------------------------
typedef struct tag_ASSEMBLY_ROOT { DWORD dwAssemblyCount; // ASSEMBLYHDR[]
static size_t GetAlignSize() { return Align(sizeof(struct tag_ASSEMBLY_ROOT)); } } ASSEMBLY_ROOT;
typedef struct tag_ASSEMBLYHDR { DWORD dwCnt; LANGID langid; // ASSEMBLYITEM[]
static size_t GetAlignSize() { return Align(sizeof(struct tag_ASSEMBLYHDR)); } } ASSEMBLYHDR;
CCicFileMapping *g_pcfmAsmCache = NULL;
BOOL EnsureAsmCacheFileMap() { if (!g_pcfmAsmCache) g_pcfmAsmCache = new CCicFileMapping();
return g_pcfmAsmCache ? TRUE : FALSE; }
BOOL UninitAsmCacheFileMap() { if (g_pcfmAsmCache) { delete g_pcfmAsmCache; g_pcfmAsmCache = NULL; } return TRUE; }
BOOL IsAsmCache() { return g_pcfmAsmCache ? TRUE : FALSE; }
//+---------------------------------------------------------------------------
//
// CreateCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::CreateCache() { int nAsmCnt = _rgAsm.Count(); int nCurAsm = 0; HANDLE hfm = NULL; DWORD cbSize = 0; BYTE *pv; BOOL bRet = FALSE; CCicSecAttr sa;
if (!g_pcfmAsmCache) return TRUE;
if (!g_pcfmAsmCache->Enter()) return FALSE;
g_pcfmAsmCache->Close();
g_pcfmAsmCache->Init(g_szAsmListCache, &g_mutexAsm);
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
cbSize += ASSEMBLY_ROOT::GetAlignSize(); while (nCurAsm < nAsmCnt) { CAssembly *pAsm = _rgAsm.Get(nCurAsm); cbSize += ASSEMBLYHDR::GetAlignSize(); cbSize += (pAsm->Count() * ASSEMBLYITEM::GetAlignSize()); nCurAsm++; }
pv = (BYTE *)g_pcfmAsmCache->Create(sa, cbSize, NULL); if (!pv) goto Exit;
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv; pasm_root->dwAssemblyCount = nAsmCnt; pv += ASSEMBLY_ROOT::GetAlignSize();
nCurAsm = 0; while (nCurAsm < nAsmCnt) { ASSEMBLYHDR *pAsmHdr; CAssembly *pAsm = _rgAsm.Get(nCurAsm);
pAsmHdr = (ASSEMBLYHDR *)pv; pAsmHdr->dwCnt = pAsm->Count(); pAsmHdr->langid = pAsm->GetLangId(); pv += ASSEMBLYHDR::GetAlignSize();
int nItemCnt = pAsm->Count(); int nCurItem = 0;
while (nCurItem < nItemCnt) { ASSEMBLYITEM *pItem = pAsm->GetItem(nCurItem);
memcpy(pv, pItem, ASSEMBLYITEM::GetAlignSize()); pv += ASSEMBLYITEM::GetAlignSize();
nCurItem++; }
nCurAsm++; }
bRet = TRUE;
Exit:
g_pcfmAsmCache->Leave(); return bRet; }
//+---------------------------------------------------------------------------
//
// LoadFromCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::LoadFromCache() { HANDLE hfm = NULL; BYTE *pv; int nAsmCnt; int nCurAsm = 0; BOOL bRet = FALSE;
CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
if (!cfm.Enter()) return FALSE;
pv = (BYTE *)cfm.Open(); if (!pv) goto Exit;
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
cfm.Flush(ASSEMBLY_ROOT::GetAlignSize());
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv; nAsmCnt = pasm_root->dwAssemblyCount; pv += ASSEMBLY_ROOT::GetAlignSize();
if (!nAsmCnt) goto Exit;
while (nCurAsm < nAsmCnt) { ASSEMBLYHDR *pAsmHdr; CAssembly *pAsm; int nItemCnt; int nCurItem = 0;
pAsmHdr = (ASSEMBLYHDR *)pv; nItemCnt = pAsmHdr->dwCnt; pAsm = new CAssembly(pAsmHdr->langid); pv += ASSEMBLYHDR::GetAlignSize();
while (nCurItem < nItemCnt) { ASSEMBLYITEM *pItem = (ASSEMBLYITEM *)pv; pItem->InitIconIndex();
if (pAsm) pAsm->Add(pItem);
pv += ASSEMBLYITEM::GetAlignSize(); nCurItem++; }
if (pAsm) { CAssembly **ppAsm; ppAsm = _rgAsm.Append(1); if (ppAsm) { *ppAsm = pAsm; } else { delete pAsm; }
}
nCurAsm++; }
bRet = TRUE; Exit: cfm.Leave(); return bRet; }
//+---------------------------------------------------------------------------
//
// InvalidCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::InvalidCache() { HANDLE hfm = NULL; DWORD *pv; BOOL bRet = FALSE;
CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
if (!cfm.Enter()) return FALSE;
pv = (DWORD *)cfm.Open(); if (!pv) goto Exit;
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
if (pv) { ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv; pasm_root->dwAssemblyCount = 0;
cfm.Flush(ASSEMBLY_ROOT::GetAlignSize()); bRet = TRUE; }
Exit: cfm.Leave(); return bRet; }
//+---------------------------------------------------------------------------
//
// SetDefaultTIPInAssemblyForCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::SetDefaultTIPInAssemblyForCache(LANGID langid, REFGUID catid, REFCLSID clsid, HKL hKL, REFGUID guidProfile) { BYTE *pv; int nAsmCnt; int nCurAsm = 0; BOOL bRet = FALSE;
CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
if (!cfm.Enter()) return FALSE;
pv = (BYTE *)cfm.Open(); if (!pv) goto Exit;
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv; nAsmCnt = pasm_root->dwAssemblyCount; pv += ASSEMBLY_ROOT::GetAlignSize();
if (!nAsmCnt) goto Exit;
while (nCurAsm < nAsmCnt) { ASSEMBLYHDR *pAsmHdr; int nItemCnt; int nCurItem = 0;
pAsmHdr = (ASSEMBLYHDR *)pv; BOOL fTargetLang = (pAsmHdr->langid == langid) ? TRUE : FALSE;
nItemCnt = pAsmHdr->dwCnt; pv += ASSEMBLYHDR::GetAlignSize();
while (nCurItem < nItemCnt) { if (fTargetLang) { ASSEMBLYITEM *pItem = (ASSEMBLYITEM *)pv;
if (IsEqualGUID(pItem->catid, catid)) { if (IsEqualGUID(pItem->clsid, clsid) && IsEqualGUID(pItem->guidProfile, guidProfile) && (!hKL || (hKL == pItem->hkl))) { pItem->fActive = TRUE; } else { pItem->fActive = FALSE; } } }
pv += ASSEMBLYITEM::GetAlignSize(); nCurItem++; }
if (fTargetLang) break;
nCurAsm++; }
bRet = TRUE;
Exit: cfm.Leave(); return bRet; }
#ifdef PROFILE_UPDATE_REGISTRY // old code for tip setup.
//+---------------------------------------------------------------------------
//
// IsUpdated
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::IsUpdated() { CMyRegKey key;
if (key.Open(HKEY_LOCAL_MACHINE, c_szCTFKey, KEY_READ) != S_OK) return FALSE;
char szName[16]; DWORD dwCnt = sizeof(szName); if (key.QueryValue(szName, c_szUpdateProfile, &dwCnt) != S_OK) return FALSE;
return (szName[0] == '1') ? TRUE : FALSE; }
//+---------------------------------------------------------------------------
//
// ClearUpdatedFlag
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::ClearUpdatedFlag() { CMyRegKey key;
if (key.Open(HKEY_LOCAL_MACHINE, c_szCTFKey) != S_OK) return FALSE;
if (key.DeleteValue(c_szUpdateProfile) != S_OK) return FALSE;
return TRUE; } #endif
//+---------------------------------------------------------------------------
//
// CheckLangSupport
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::CheckLangSupport(REFCLSID rclsid, LANGID langid) { CMyRegKey key; TCHAR szKey[256]; TCHAR szLang[256]; int i = 0;
StringCopyArray(szKey, c_szCTFTIPKey); CLSIDToStringA(rclsid, szKey + lstrlen(szKey)); StringCatArray(szKey, "\\"); StringCatArray(szKey, c_szLanguageProfileKey);
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) == S_OK) { CMyRegKey subkey;
//
// Check a valid language id.
//
StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x%08x", LOWORD(langid)); StringCopyArray(szKey, szLang); if (subkey.Open(key, szKey, KEY_READ) == S_OK) return TRUE;
//
// Check a primary language id.
//
StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x%08x", LOWORD(PRIMARYLANGID(langid))); StringCopyArray(szKey, szLang); if (subkey.Open(key, szKey, KEY_READ) == S_OK) return TRUE;
//
// Check a neutral language id.
//
StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x0000ffff"); StringCopyArray(szKey, szLang); if (subkey.Open(key, szKey, KEY_READ) == S_OK) return TRUE; }
return FALSE; }
//+---------------------------------------------------------------------------
//
// GetTIPCategory
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::GetTIPCategory(REFCLSID clsid, GUID *pcatid, IEnumGUID *pEnumCat) { HRESULT hr; BOOL fFound = FALSE;
*pcatid = GUID_NULL; hr = pEnumCat->Reset();
if (SUCCEEDED(hr)) { GUID guidCat; while (!fFound && (pEnumCat->Next(1, &guidCat, NULL) == S_OK)) { IEnumGUID *pEnumTip; hr = g_EnumItemsInCategory(guidCat, &pEnumTip); if (SUCCEEDED(hr) && pEnumTip) { GUID guidTip; while (!fFound && (pEnumTip->Next(1, &guidTip, NULL) == S_OK)) { if (IsEqualGUID(clsid, guidTip)) { *pcatid = guidCat; fFound = TRUE; } } pEnumTip->Release(); } } }
return fFound; }
//+---------------------------------------------------------------------------
//
// GetDefaultTIPInAssembly
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::GetDefaultTIPInAssembly(LANGID langid, REFGUID catid, CLSID *pclsid, HKL *phKL, GUID *pguidProfile) { CMyRegKey key; DWORD dw; char szKey[256]; char szName[CLSID_STRLEN + 1];
StringCopyArray(szKey, c_szAsmKey); StringCatArray(szKey, "\\"); StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey) - lstrlen(szKey), "0x%08x", langid); StringCatArray(szKey, "\\"); CLSIDToStringA(catid, szKey + lstrlen(szKey));
*pclsid = GUID_NULL;
if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK) return FALSE;
if (key.QueryValueCch(szName, c_szDefault, ARRAYSIZE(szName)) != S_OK) return FALSE;
StringAToCLSID(szName, pclsid);
if (key.QueryValueCch(szName, c_szProfile, ARRAYSIZE(szName)) != S_OK) return FALSE;
StringAToCLSID(szName, pguidProfile);
if (phKL) { *phKL = NULL;
if (key.QueryValue(dw, c_szKeyboardLayout) != S_OK) return FALSE;
*phKL = (HKL)IntToPtr(dw); }
return TRUE; }
//+---------------------------------------------------------------------------
//
// SetDefaultTIPInAssemblyInternal
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::SetDefaultTIPInAssemblyInternal(CAssembly *pAsm, ASSEMBLYITEM *pItem, BOOL fChangeDefault) { ASSEMBLYITEM *pItemSub = NULL; BOOL bRet = FALSE; Assert(!pItem->hkl || (pAsm->GetLangId() == LOWORD((DWORD)(LONG_PTR)(HKL)pItem->hkl)));
//
// If given hKL is substituted hKL, we set the original TIP as a default.
//
if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD)) { #if 0
//
// Chienese platform special. We don't set the new default keyboard.
//
if (IsChinesePlatform()) { return TRUE; }
pItemSub = pAsm->GetSubstituteItem(pItem->hkl);
if (fChangeDefault) { //
// try to change the system default hKL.
//
// When TIP that has substitute HKL is selected.
// if the language of the system default hKL is same,
// set the hKL.
//
// When IME is selected.
// if the language of the system default hKL is same, set it.
//
HKL hklNewDef = IsPureIMEHKL(pItem->hkl) ? pItem->hkl : (IsPureIMEHKL(pItem->hklSubstitute) ? pItem->hklSubstitute : pItem->hkl); if (!IsFELangId(LOWORD((WORD)(LONG_PTR)(HKL)pItem->hkl)) || hklNewDef) { HKL hklDef = GetSystemDefaultHKL(); if ((hklDef != hklNewDef) && (LOWORD((WORD)(LONG_PTR)hklDef) == LOWORD((WORD)(LONG_PTR)hklNewDef))) { SetSystemDefaultHKL(hklNewDef); } } } #else
HKL hklDef = GetSystemDefaultHKL(); if (pAsm->GetLangId() == LANGIDFROMHKL(hklDef)) { //
// Now we can set the default layout directly from CPL instead of
// just set language(bug#353989)
//
return TRUE; }
pItemSub = pAsm->GetSubstituteItem(pItem->hkl); #endif
}
if (pItemSub) { bRet = SetDefaultTIPInAssembly(pAsm->GetLangId(), pItemSub->catid, pItemSub->clsid, pItemSub->hkl, pItemSub->guidProfile); } else { bRet = SetDefaultTIPInAssembly(pAsm->GetLangId(), pItem->catid, pItem->clsid, pItem->hkl, pItem->guidProfile); }
return bRet; }
//+---------------------------------------------------------------------------
//
// SetDefaultTIPInAssembly
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::SetDefaultTIPInAssembly(LANGID langid, REFGUID catid, REFCLSID clsid, HKL hKL, REFGUID guidProfile) { CMyRegKey key; char szKey[256]; char szName[256];
StringCopyArray(szKey, c_szAsmKey); StringCatArray(szKey, "\\"); StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey) - lstrlen(szKey), "0x%08x", langid); StringCatArray(szKey, "\\"); CLSIDToStringA(catid, szKey + lstrlen(szKey));
if (key.Create(HKEY_CURRENT_USER, szKey) != S_OK) return FALSE;
CLSIDToStringA(clsid, szName); if (key.SetValue(szName, c_szDefault) != S_OK) return FALSE;
CLSIDToStringA(guidProfile, szName); if (key.SetValue(szName, c_szProfile) != S_OK) return FALSE;
if (key.SetValue((DWORD)(ULONG_PTR)hKL, c_szKeyboardLayout) != S_OK) return FALSE;
return TRUE; }
//+---------------------------------------------------------------------------
//
// IsFEDummyKL
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::IsFEDummyKL(HKL hkl) { char szProfile[256]; char szDummyProfile[256]; static HKL hkl411Dummy = 0; static HKL hkl404Dummy = 0; static HKL hkl412Dummy = 0; static HKL hkl804Dummy = 0; HKL *phklDummy = NULL; BOOL bRet = FALSE;
//
// we don't use DummyHKL under NT.
//
if (IsOnNT()) return FALSE;
switch (LANGIDFROMLCID(hkl)) { case 0x411: phklDummy = &hkl411Dummy; break; case 0x412: phklDummy = &hkl412Dummy; break; case 0x404: phklDummy = &hkl404Dummy; break; case 0x804: phklDummy = &hkl804Dummy; break; default: return FALSE; }
if (!ImmGetDescription(hkl, szProfile, ARRAYSIZE(szProfile))) { return FALSE; }
CicEnterCriticalSection(g_cs);
if (*phklDummy) { bRet = (*phklDummy == hkl) ? TRUE : FALSE; } else { StringCchPrintf(szDummyProfile, ARRAYSIZE(szDummyProfile), "hkl%04x", LOWORD((DWORD)(UINT_PTR)hkl)); if (!lstrcmp(szDummyProfile, szProfile)) { *phklDummy = hkl; bRet = TRUE; } }
CicLeaveCriticalSection(g_cs);
return bRet; }
//+---------------------------------------------------------------------------
//
// CheckKeyboardLayoutReg
//
//
// Hack for IMM32 hard code for "kbdjp.kbd" for Japanese hKL.
// If ImmInstallIME() fails, we try it after patching registry key.
//
//----------------------------------------------------------------------------
HKL CheckKeyboardLayoutReg(LANGID langid) { CMyRegKey key; DWORD dwIndex; TCHAR szValue[MAX_PATH];
//
// This is just for Win9x Kor,CHT,CHS
//
if (IsOnNT()) return NULL;
if ((g_uACP != 936) && (g_uACP != 949) && (g_uACP != 950)) return NULL;
//
// This is for HKL0411 only.
//
if (langid != 0x0411) return NULL;
if (key.Open(HKEY_LOCAL_MACHINE, c_szKeyboardLayoutKey, KEY_READ) != S_OK) return NULL;
dwIndex = 0; while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == S_OK) { CMyRegKey keyHKL; TCHAR szName[13];
if (keyHKL.Open(key, szValue, KEY_ALL_ACCESS) != S_OK) goto Next;
if (keyHKL.QueryValueCch(szName, c_szIMEFile, ARRAYSIZE(szName)) != S_OK) goto Next;
if (!lstrcmpi(szName, "hkl0411.dll")) { //
// patch LayoutFile to kbdus.kbd and load the keyboard layout.
//
if (keyHKL.SetValue(c_szKbdUSName, c_szLayoutFile) != S_OK) return NULL; return LoadKeyboardLayout(szValue, KLF_NOTELLSHELL); } Next: dwIndex++; }
return NULL; }
//+---------------------------------------------------------------------------
//
// GetProperHKL
//
//----------------------------------------------------------------------------
HKL CAssemblyList::GetProperHKL(LANGID langid, HKL *lphkl, BOOL *pfLoaded) { char szhkl[16]; HKL hkl = NULL; BOOL fFELang = IsFELangId(langid) ? TRUE : FALSE;
if (pfLoaded) *pfLoaded = FALSE;
if (lphkl) { while (*lphkl) { if (langid == (LANGID)((DWORD)(UINT_PTR)(*lphkl) & 0x0000ffff)) { //
// Under FE language, we have a specialcase.
//
if (fFELang) { //
// Dummy HKL should be used.
//
if (IsIMEHKL(*lphkl)) { if (IsFEDummyKL(*lphkl)) { hkl = *lphkl; break; } goto Next; } //
// We strongly want to use a primary hKL for FE.
//
if ((HIWORD((DWORD)(UINT_PTR)*lphkl) != langid)) goto Next; } hkl = *lphkl; break; } Next: lphkl++; } }
//
// if we could find any, return.
//
if (hkl) return hkl;
if (!IsOnNT() && IsOnFE() && IsFELangId(langid)) { char szSys[MAX_PATH]; char szDll[MAX_PATH]; char szLayout[16]; GetSystemDirectory(szSys, sizeof(szSys)); StringCchPrintf(szDll, ARRAYSIZE(szDll),"%s\\hkl%04x.dll", szSys, langid); StringCchPrintf(szLayout, ARRAYSIZE(szLayout),"hkl%04x", langid);
hkl = ImmInstallIME(szDll, szLayout); if (!hkl) { hkl = CheckKeyboardLayoutReg(langid); if (hkl) { #if 0
RemoveFEDummyHKLFromPreloadReg(hkl); #endif
goto Exit; }
//
// error to load Dummy hKL.
// we just use a primary English language.
//
StringCchPrintf(szhkl, ARRAYSIZE(szhkl),"%08x", 0x0409); hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL); } #if 0
else { //
// check the dummy HKL from Preload section of registry and remove
// it since ImmInstallIME automatically add hkl to Preload section.
//
RemoveFEDummyHKLFromPreloadReg(hkl); } #endif
goto Exit; }
StringCchPrintf(szhkl, ARRAYSIZE(szhkl),"%08x", langid); hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
//
// if we fail to create a hKL for langid, check this registry entry.
//
// HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\[langid]
//
// without the key, it fails to create a default keyboard layout.
//
Assert(LOWORD(hkl) == langid);
//
// if hkl has NULL value and the current langid is FE, then we try to add
// the default keyboard layout in the system.
//
if (IsFELangId(langid) && ((LOWORD(hkl) != langid) || IsPureIMEHKL(hkl))) { char szKey[256]; CMyRegKey key;
if (IsOn98orNT5()) StringCopyArray(szKey, c_szLocaleInfo); else StringCopyArray(szKey, c_szLocaleInfoNT4);
//
// see if the user has Administrative privileges by checking for
// write permission to the registry key(NLS path).
//
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_WRITE) != S_OK) goto Exit; else { StringCopyArray(szKey, c_szKeyboardLayoutKey);
StringCchPrintf(szhkl, ARRAYSIZE(szhkl), "%08x", langid); StringCatArray(szKey, szhkl);
//
// create new keyboard layout registry key and value.
//
if (key.Create(HKEY_LOCAL_MACHINE, szKey) == S_OK) { char szKbdName[256];
if (IsOnNT()) StringCopyArray(szKbdName, c_szKbdUSNameNT); else StringCopyArray(szKbdName, c_szKbdUSName);
if (key.SetValue(szKbdName, c_szLayoutFile) == S_OK) { //
// now try to reload keyboard layout again.
//
hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL); } } } }
Exit: if (hkl && pfLoaded) *pfLoaded = TRUE;
return hkl;
}
|