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.
2149 lines
57 KiB
2149 lines
57 KiB
//
|
|
// profiles.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "tim.h"
|
|
#include "ic.h"
|
|
#include "dim.h"
|
|
#include "assembly.h"
|
|
#include "nuictrl.h"
|
|
#include "nuihkl.h"
|
|
#include "imelist.h"
|
|
#include "xstring.h"
|
|
#include "profiles.h"
|
|
#include "lbaddin.h"
|
|
|
|
BOOL MyGetTIPCategory(REFCLSID clsid, GUID *pcatid);
|
|
|
|
DBG_ID_INSTANCE(CEnumLanguageProfiles);
|
|
|
|
typedef struct _PENDING_ASSEMBLY_ITEM
|
|
{
|
|
LANGID langid;
|
|
HKL hkl;
|
|
CLSID clsid;
|
|
GUID guidProfile;
|
|
DWORD dwFlags;
|
|
} PENDING_ASSEMBLY_ITEM;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// static functions
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UpdateSystemLangBarItems()
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UpdateSystemLangBarItems(SYSTHREAD *psfn, HKL hNewKL, BOOL fNotify)
|
|
{
|
|
if (psfn->plbim == NULL)
|
|
return;
|
|
|
|
if (psfn->plbim->_GetLBarItemDeviceTypeArray())
|
|
{
|
|
int nCnt = psfn->plbim->_GetLBarItemDeviceTypeArray()->Count();
|
|
int i;
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
CLBarItemDeviceType *plbi = psfn->plbim->_GetLBarItemDeviceTypeArray()->Get(i);
|
|
plbi->ShowOrHide(fNotify);
|
|
}
|
|
}
|
|
|
|
if (psfn->plbim->_GetLBarItemCtrl())
|
|
psfn->plbim->_GetLBarItemCtrl()->_UpdateLangIcon(hNewKL, fNotify);
|
|
|
|
if (psfn->plbim->_GetLBarItemReconv())
|
|
psfn->plbim->_GetLBarItemReconv()->ShowOrHide(fNotify);
|
|
|
|
//
|
|
// If this function is called, someone needs to make
|
|
// notification later.
|
|
//
|
|
if (psfn->plbim->InAssemblyChange())
|
|
{
|
|
Assert(!fNotify);
|
|
psfn->plbim->SetItemChange();
|
|
}
|
|
|
|
UpdateLangBarAddIns();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateAssemblyPostCleanupCallback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void ActivateAssemblyPostCleanupCallback(BOOL fAbort, LONG_PTR lPrivate)
|
|
{
|
|
SYSTHREAD *psfn;
|
|
LANGID langid = HIWORD(lPrivate);
|
|
ACTASM actasm = (ACTASM)LOWORD(lPrivate);
|
|
|
|
if (fAbort)
|
|
return; // nothing to cleanup...
|
|
|
|
if (psfn = GetSYSTHREAD())
|
|
{
|
|
SyncActivateAssembly(psfn, langid, actasm);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DeactivateRemovedTipinAssembly
|
|
//
|
|
// Deactivate active TIPs that are not in the assembly list. This can happen
|
|
// someone remove the profile from the control panel during the tip is
|
|
// running on some application.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void DeactivateRemovedTipInAssembly(CThreadInputMgr *ptim, CAssembly *pAsm)
|
|
{
|
|
int nAsmCnt = pAsm->Count();
|
|
TfGuidAtom *patom;
|
|
int i;
|
|
UINT j;
|
|
|
|
if (!ptim)
|
|
return;
|
|
|
|
if (!nAsmCnt)
|
|
return;
|
|
|
|
patom = new TfGuidAtom[nAsmCnt];
|
|
if (!patom)
|
|
return;
|
|
|
|
for (i = 0; i < nAsmCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
|
|
patom[i] = TF_INVALID_GUIDATOM;
|
|
if (pItem && pItem->fEnabled && !IsEqualGUID(pItem->clsid, GUID_NULL))
|
|
MyRegisterGUID(pItem->clsid, &patom[i]);
|
|
}
|
|
|
|
for (j = 0; j < ptim->_GetTIPCount(); j++)
|
|
{
|
|
const CTip *ptip = ptim->_GetCTip(j);
|
|
if (ptip && ptip->_fActivated)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
|
|
for (i = 0; i < nAsmCnt; i++)
|
|
{
|
|
if (ptip->_guidatom == patom[i])
|
|
fFound = TRUE;
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
CLSID clsid;
|
|
if (SUCCEEDED(MyGetGUID(ptip->_guidatom, &clsid)))
|
|
ptim->ActivateInputProcessor(clsid,
|
|
GUID_NULL,
|
|
NULL,
|
|
FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
delete patom;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetAssemblyChangeHKL
|
|
//
|
|
// --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
|
|
//
|
|
// GetAssemblyChangeHKL and SyncActivateAssembly must have exactly
|
|
// same logic. Otherwise HKL will be corrupted.
|
|
//
|
|
// --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HKL GetAssemblyChangeHKL(SYSTHREAD *psfn, LANGID langid, BOOL fTimActivateLayout)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
BOOL fRet = FALSE;
|
|
ULONG ul;
|
|
ULONG ulCount = 0;
|
|
int nAsmCnt;
|
|
int i;
|
|
BOOL fActivated = FALSE;
|
|
BOOL fActiveNoCic = FALSE;
|
|
BOOL fActivateFEIMEHKLOnCic = FALSE;
|
|
BOOL fCiceroClient= FALSE;
|
|
CAssembly *pAsm;
|
|
CAssemblyList *pAsmList;
|
|
HKL hNewKL = NULL;
|
|
HKL hCurrKL = GetKeyboardLayout(0);
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return NULL;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return NULL;
|
|
|
|
nAsmCnt = pAsm->Count();
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
//
|
|
// Check if we're in Cicero aware focus.
|
|
//
|
|
if (ptim && ptim->_GetFocusDocInputMgr())
|
|
fCiceroClient = TRUE;
|
|
|
|
fActivateFEIMEHKLOnCic = pAsm->IsFEIMEActive();
|
|
|
|
TryAgain:
|
|
for (i = 0; i < nAsmCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
|
|
|
|
if (!pItem->fEnabled)
|
|
continue;
|
|
|
|
if (fActiveNoCic)
|
|
{
|
|
if (fCiceroClient)
|
|
{
|
|
if (!pItem->fActiveNoCic)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (fActivated)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!pItem->fActive)
|
|
continue;
|
|
}
|
|
|
|
|
|
if (!IsEqualGUID(pItem->clsid, GUID_NULL))
|
|
{
|
|
BOOL fFound = FALSE;
|
|
ul = 0;
|
|
|
|
//
|
|
// if fTimActivateLayout is true, we load TIPs.
|
|
//
|
|
if (!fCiceroClient && !fTimActivateLayout)
|
|
continue;
|
|
|
|
//
|
|
// skip to activate cicero tip because we will activate
|
|
// FEIMEHKL.
|
|
//
|
|
if (fActivateFEIMEHKLOnCic)
|
|
continue;
|
|
|
|
if (pItem->hkl)
|
|
{
|
|
HKL hKL = pItem->hkl;
|
|
|
|
//
|
|
// If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (hKL != hCurrKL)
|
|
hNewKL = hKL;
|
|
}
|
|
|
|
fActivated = TRUE;
|
|
}
|
|
else if (pItem->hkl)
|
|
{
|
|
HKL hKL = pItem->hkl;
|
|
|
|
//
|
|
// skip substituted hKL on Cicero aware control.
|
|
//
|
|
if (fCiceroClient && pAsm->GetSubstituteItem(hKL))
|
|
continue;
|
|
|
|
//
|
|
// If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (hKL != hCurrKL)
|
|
hNewKL = hKL;
|
|
|
|
fActivated = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fActivated && !fActiveNoCic)
|
|
{
|
|
fActiveNoCic = TRUE;
|
|
goto TryAgain;
|
|
}
|
|
|
|
return hNewKL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateAssembly
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL ActivateAssembly(LANGID langid, ACTASM actasm)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
SYSTHREAD *psfn;
|
|
LONG_PTR lParam;
|
|
CLEANUPCONTEXT cc;
|
|
BOOL bRet = FALSE;
|
|
BOOL fTimActivateLayout = (actasm == ACTASM_ONTIMACTIVE) ? TRUE : FALSE;
|
|
BOOL fOnShellLangChange = (actasm == ACTASM_ONSHELLLANGCHANGE) ? TRUE : FALSE;
|
|
|
|
psfn = GetSYSTHREAD();
|
|
if (!psfn)
|
|
return FALSE;
|
|
|
|
if (psfn->fInActivateAssembly)
|
|
return FALSE;
|
|
|
|
psfn->fInActivateAssembly = TRUE;
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
//
|
|
// if the client is no Cicero aware, we just post
|
|
// WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (!ptim || (!fTimActivateLayout && !ptim->_GetFocusDocInputMgr()))
|
|
{
|
|
//
|
|
// If we don't requires any hKL change to activate this new
|
|
// assembly, we can call SyncActivateAssembly now.
|
|
// Otherwise we need to wait until WM_INPUTLANGUAGECHANGEREQUEST
|
|
// is processed.
|
|
//
|
|
HKL hKL = GetAssemblyChangeHKL(psfn, langid, fTimActivateLayout);
|
|
if (fOnShellLangChange || !hKL || (hKL == GetKeyboardLayout(0)))
|
|
SyncActivateAssembly(psfn, langid, actasm);
|
|
else
|
|
PostInputLangRequest(psfn, hKL, TRUE);
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
lParam = ((DWORD)langid << 16);
|
|
lParam |= actasm;
|
|
|
|
cc.fSync = fTimActivateLayout;
|
|
cc.pCatId = NULL;
|
|
cc.langid = langid;
|
|
cc.pfnPostCleanup = ActivateAssemblyPostCleanupCallback;
|
|
cc.lPrivate = lParam;
|
|
|
|
ptim->_CleanupContexts(&cc);
|
|
|
|
bRet = TRUE;
|
|
Exit:
|
|
psfn->fInActivateAssembly = FALSE;
|
|
return bRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SyncActivateAssembly
|
|
//
|
|
// --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
|
|
//
|
|
// GetAssemblyChangeHKL and SyncActivateAssembly must have exactly
|
|
// same logic. Otherwise HKL will be corrupted.
|
|
//
|
|
// --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SyncActivateAssembly(SYSTHREAD *psfn, LANGID langid, ACTASM actasm)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
BOOL fRet = FALSE;
|
|
ULONG ul;
|
|
ULONG ulCount = 0;
|
|
int nAsmCnt;
|
|
int i;
|
|
BOOL fActivated = FALSE;
|
|
BOOL fActiveNoCic = FALSE;
|
|
BOOL fIconUpdated = FALSE;
|
|
BOOL fActivateFEIMEHKLOnCic = FALSE;
|
|
BOOL fCallLeaveAssembly = FALSE;
|
|
BOOL fCiceroClient= FALSE;
|
|
CAssembly *pAsm;
|
|
CAssemblyList *pAsmList;
|
|
HKL hNewKL = NULL;
|
|
BOOL fTimActivateLayout = (actasm == ACTASM_ONTIMACTIVE) ? TRUE : FALSE;
|
|
BOOL fOnShellLangChange = (actasm == ACTASM_ONSHELLLANGCHANGE) ? TRUE : FALSE;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return FALSE;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return FALSE;
|
|
|
|
#ifdef CHECKFEIMESELECTED
|
|
pAsm->_fUnknownFEIMESelected = FALSE;
|
|
#endif CHECKFEIMESELECTED
|
|
|
|
if (psfn->pipp)
|
|
{
|
|
if (!psfn->pipp->_OnLanguageChange(FALSE, pAsm->GetLangId()))
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Enter assembly change notification section.
|
|
// We delay the notificaiton untill LeaveAssemblyChange() is called.
|
|
//
|
|
if (psfn->plbim)
|
|
{
|
|
fCallLeaveAssembly = TRUE;
|
|
psfn->plbim->EnterAssemblyChange();
|
|
}
|
|
|
|
nAsmCnt = pAsm->Count();
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
//
|
|
// Check if we're in Cicero aware focus.
|
|
//
|
|
if (ptim && ptim->_GetFocusDocInputMgr())
|
|
fCiceroClient = TRUE;
|
|
|
|
for (i = 0; i < nAsmCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
|
|
pItem->fSkipToActivate = FALSE;
|
|
pItem->fSkipToNotify = FALSE;
|
|
}
|
|
|
|
if (ptim)
|
|
{
|
|
CAssembly *pAsmCur;
|
|
pAsmCur = GetCurrentAssembly(psfn);
|
|
if (pAsmCur)
|
|
{
|
|
int nAsmCurCnt = pAsmCur->Count();
|
|
|
|
DeactivateRemovedTipInAssembly(ptim, pAsmCur);
|
|
|
|
//
|
|
// check if we will activate FEIMEHKL. If so, we will disable
|
|
// all Cicero tip.
|
|
//
|
|
fActivateFEIMEHKLOnCic = pAsm->IsFEIMEActive();
|
|
|
|
for (int j = 0; j < nAsmCurCnt; j++)
|
|
{
|
|
ASSEMBLYITEM *pItemCur = pAsmCur->GetItem(j);
|
|
|
|
if (!pItemCur->fEnabled)
|
|
continue;
|
|
|
|
BOOL fSkipToActivate = FALSE;
|
|
BOOL fSkipToNotify = FALSE;
|
|
|
|
if (ptim->_IsActiveInputProcessor(pItemCur->clsid) != S_OK)
|
|
continue;
|
|
|
|
for (i = 0; i < nAsmCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
|
|
|
|
if (!pItem->fEnabled)
|
|
continue;
|
|
|
|
if (pItem->fActive &&
|
|
!fActivateFEIMEHKLOnCic &&
|
|
IsEqualCLSID(pItem->clsid, pItemCur->clsid))
|
|
{
|
|
if (IsEqualCLSID(pItem->guidProfile, pItemCur->guidProfile))
|
|
{
|
|
pItem->fSkipToNotify = TRUE;
|
|
fSkipToNotify = TRUE;
|
|
}
|
|
pItem->fSkipToActivate = TRUE;
|
|
fSkipToActivate = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fSkipToNotify)
|
|
{
|
|
if (fSkipToActivate)
|
|
ptim->NotifyActivateInputProcessor(pItemCur->clsid, pItemCur->guidProfile, FALSE);
|
|
else
|
|
ptim->ActivateInputProcessor(pItemCur->clsid, pItemCur->guidProfile, pItemCur->hklSubstitute, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if the current assembly is gone, we deactivate all tips.
|
|
//
|
|
for (ul = 0; ul < ptim->_GetTIPCount(); ul++)
|
|
{
|
|
const CTip *ptip = ptim->_GetCTip(ul);
|
|
if (ptip->_fActivated)
|
|
{
|
|
CLSID clsid;
|
|
if (SUCCEEDED(MyGetGUID(ptip->_guidatom, &clsid)))
|
|
ptim->ActivateInputProcessor(clsid, GUID_NULL, NULL, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SetCurrentAssemblyLangId(psfn, pAsm->GetLangId());
|
|
|
|
TryAgain:
|
|
for (i = 0; i < nAsmCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem = pAsm->GetItem(i);
|
|
|
|
if (!pItem)
|
|
{
|
|
Assert(0);
|
|
continue;
|
|
}
|
|
|
|
if (!pItem->fEnabled)
|
|
continue;
|
|
|
|
if (fActiveNoCic)
|
|
{
|
|
if (fCiceroClient)
|
|
{
|
|
if (!pItem->fActiveNoCic)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (fActivated)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!pItem->fActive)
|
|
continue;
|
|
}
|
|
|
|
|
|
if (!IsEqualGUID(pItem->clsid, GUID_NULL))
|
|
{
|
|
BOOL fFound = FALSE;
|
|
ul = 0;
|
|
|
|
//
|
|
// if fTimActivateLayout is true, we load TIPs.
|
|
//
|
|
if (!fCiceroClient && !fTimActivateLayout)
|
|
continue;
|
|
|
|
//
|
|
// skip to activate cicero tip because we will activate
|
|
// FEIMEHKL.
|
|
//
|
|
if (fActivateFEIMEHKLOnCic)
|
|
continue;
|
|
|
|
if (pItem->hkl)
|
|
{
|
|
HKL hKL = pItem->hkl;
|
|
HKL hCurrKL = GetKeyboardLayout(0);
|
|
|
|
//
|
|
// If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (hKL != hCurrKL)
|
|
{
|
|
//
|
|
// If we're not on Cicero aware focus,
|
|
// we won't set AssemblyLangId here
|
|
// but we post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (!fOnShellLangChange)
|
|
PostInputLangRequest(psfn, hKL,
|
|
!fTimActivateLayout && !fCiceroClient);
|
|
hNewKL = hKL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check if this TIP is already activated.
|
|
//
|
|
if (pItem->fSkipToActivate)
|
|
{
|
|
if (!pItem->fSkipToNotify)
|
|
ptim->NotifyActivateInputProcessor(pItem->clsid, pItem->guidProfile, TRUE);
|
|
pItem->fSkipToActivate = FALSE;
|
|
pItem->fSkipToNotify = FALSE;
|
|
}
|
|
else
|
|
ptim->ActivateInputProcessor(pItem->clsid, pItem->guidProfile, pItem->hklSubstitute, TRUE);
|
|
|
|
fActivated = TRUE;
|
|
}
|
|
else if (pItem->hkl)
|
|
{
|
|
HKL hKL = pItem->hkl;
|
|
HKL hCurrKL = GetKeyboardLayout(0);
|
|
|
|
//
|
|
// skip substituted hKL on Cicero aware control.
|
|
//
|
|
if (fCiceroClient && pAsm->GetSubstituteItem(hKL))
|
|
continue;
|
|
|
|
//
|
|
// If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (hKL != hCurrKL)
|
|
{
|
|
//
|
|
// If we're not on Cicero aware focus,
|
|
// we won't set AssemblyLangId here
|
|
// but we post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
if (!fOnShellLangChange)
|
|
PostInputLangRequest(psfn, hKL,
|
|
!fTimActivateLayout && !fCiceroClient);
|
|
hNewKL = hKL;
|
|
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
|
|
}
|
|
|
|
//
|
|
// Notify to profile.
|
|
//
|
|
if (ptim)
|
|
{
|
|
ptim->NotifyActivateInputProcessor(pItem->clsid,
|
|
pItem->guidProfile,
|
|
TRUE);
|
|
}
|
|
|
|
//
|
|
// Now we activated this pItem.
|
|
//
|
|
fActivated = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if (!fActivated && !fActiveNoCic)
|
|
{
|
|
fActiveNoCic = TRUE;
|
|
goto TryAgain;
|
|
}
|
|
|
|
UpdateSystemLangBarItems(psfn, hNewKL, FALSE);
|
|
|
|
|
|
fRet = TRUE;
|
|
|
|
if (psfn->pipp)
|
|
{
|
|
psfn->pipp->_OnLanguageChange(TRUE, 0);
|
|
}
|
|
|
|
if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
|
|
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateNextAssembly
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL ActivateNextAssembly(BOOL bPrev)
|
|
{
|
|
SYSTHREAD *psfn;
|
|
CAssemblyList *pAsmList;
|
|
CAssembly *pAsmNext = NULL;
|
|
BOOL bRet = FALSE;
|
|
LANGID langidCur;
|
|
|
|
if ((psfn = GetSYSTHREAD()) == NULL)
|
|
return FALSE;
|
|
|
|
if ((pAsmList = EnsureAssemblyList(psfn)) == NULL)
|
|
return FALSE;
|
|
|
|
int i;
|
|
int nCnt = pAsmList->Count();
|
|
Assert(nCnt > 0);
|
|
|
|
langidCur = GetCurrentAssemblyLangId(psfn);
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
CAssembly *pAsm = pAsmList->GetAssembly(i);
|
|
if (pAsm->GetLangId() == langidCur)
|
|
{
|
|
int nNext;
|
|
int nCur = i;
|
|
|
|
CheckNext:
|
|
if (bPrev)
|
|
{
|
|
nNext = i - 1;
|
|
if (nNext < 0)
|
|
nNext = nCnt - 1;
|
|
}
|
|
else
|
|
{
|
|
nNext = i + 1;
|
|
if (nNext >= nCnt)
|
|
nNext = 0;
|
|
}
|
|
|
|
pAsmNext = pAsmList->GetAssembly(nNext);
|
|
if (!pAsmNext->IsEnabled(psfn))
|
|
{
|
|
i = nNext;
|
|
|
|
if (i == nCur)
|
|
{
|
|
//
|
|
// we cound not find Asm.
|
|
// we don't have to change the assembly.
|
|
//
|
|
pAsmNext = NULL;
|
|
break;
|
|
}
|
|
|
|
goto CheckNext;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pAsmNext && pAsmNext->GetLangId() != langidCur)
|
|
{
|
|
bRet = ActivateAssembly(pAsmNext->GetLangId(), ACTASM_NONE);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateNextKeyTip
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL ActivateNextKeyTip(BOOL bPrev)
|
|
{
|
|
SYSTHREAD *psfn;
|
|
CThreadInputMgr *ptim;
|
|
CAssembly *pAsm;
|
|
ASSEMBLYITEM *pItemFirst = NULL;
|
|
ASSEMBLYITEM *pItemCur = NULL;
|
|
ASSEMBLYITEM *pItemNext = NULL;
|
|
BOOL bCatchNext = FALSE;
|
|
int i;
|
|
BOOL fTransitory = FALSE;
|
|
BOOL fCiceroClient = FALSE;
|
|
|
|
if ((psfn = GetSYSTHREAD()) == NULL)
|
|
return FALSE;
|
|
|
|
if ((pAsm = GetCurrentAssembly(psfn)) == NULL)
|
|
return FALSE;
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
if (ptim && ptim->_GetFocusDocInputMgr())
|
|
{
|
|
pAsm->RebuildSubstitutedHKLList();
|
|
CInputContext *pic = ptim->_GetFocusDocInputMgr()->_GetTopIC();
|
|
if (pic)
|
|
{
|
|
TF_STATUS dcs;
|
|
if (SUCCEEDED(pic->GetStatus(&dcs)) &&
|
|
(dcs.dwStaticFlags & TF_SS_TRANSITORY))
|
|
fTransitory = TRUE;
|
|
}
|
|
fCiceroClient = TRUE;
|
|
}
|
|
else
|
|
pAsm->ClearSubstitutedHKLList();
|
|
|
|
HKL hkl = GetKeyboardLayout(0);
|
|
int nCnt = pAsm->Count();
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItemTemp;
|
|
|
|
if (!bPrev)
|
|
pItemTemp = pAsm->GetItem(i);
|
|
else
|
|
pItemTemp = pAsm->GetItem(nCnt - i - 1);
|
|
|
|
if (!pItemTemp->fEnabled)
|
|
continue;
|
|
|
|
if (pItemTemp->fDisabledOnTransitory && fTransitory)
|
|
continue;
|
|
|
|
if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
|
|
{
|
|
if (!fCiceroClient)
|
|
{
|
|
if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
{
|
|
if (pAsm->IsSubstitutedHKL(pItemTemp->hkl))
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!pItemFirst)
|
|
pItemFirst = pItemTemp;
|
|
|
|
if (bCatchNext)
|
|
{
|
|
pItemNext = pItemTemp;
|
|
break;
|
|
}
|
|
|
|
if (pItemTemp->fActive ||
|
|
((!fCiceroClient || IsPureIMEHKL(hkl)) && (hkl == pItemTemp->hkl)))
|
|
{
|
|
pItemCur = pItemTemp;
|
|
bCatchNext = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pItemNext)
|
|
{
|
|
pItemNext = pItemFirst;
|
|
}
|
|
|
|
if (pItemNext)
|
|
{
|
|
ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItemNext, AAIF_CHANGEDEFAULT);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetCurrentAssembly
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
CAssembly *GetCurrentAssembly(SYSTHREAD *psfn)
|
|
{
|
|
LANGID langid = 0;
|
|
|
|
if (!psfn)
|
|
{
|
|
if ((psfn = GetSYSTHREAD()) == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
CAssemblyList *pAsmList = EnsureAssemblyList(psfn);
|
|
|
|
if (!pAsmList)
|
|
return NULL;
|
|
|
|
if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
|
|
langid = GetCurrentAssemblyLangId(psfn);
|
|
|
|
return pAsmList->FindAssemblyByLangId(langid);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateAssemblyItemPostCleanupCallback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void ActivateAssemblyItemPostCleanupCallback(BOOL fAbort, LONG_PTR lPrivate)
|
|
{
|
|
PENDING_ASSEMBLY_ITEM *pas = (PENDING_ASSEMBLY_ITEM *)lPrivate;
|
|
SYSTHREAD *psfn;
|
|
CAssemblyList *pAsmList;
|
|
CAssembly *pAsm;
|
|
ASSEMBLYITEM *pItem;
|
|
int i;
|
|
|
|
if (fAbort) // just a cleanup?
|
|
goto Exit;
|
|
|
|
if ((psfn = GetSYSTHREAD()) == NULL)
|
|
goto Exit;
|
|
|
|
if ((pAsmList = EnsureAssemblyList(psfn)) == NULL)
|
|
{
|
|
Assert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
if ((pAsm = pAsmList->FindAssemblyByLangId(pas->langid)) == NULL)
|
|
{
|
|
Assert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// we need to make sure the pItem is valid.
|
|
//
|
|
for (i = 0; i < pAsm->Count(); i++)
|
|
{
|
|
pItem = pAsm->GetItem(i);
|
|
|
|
if (pItem->IsEqual(pas->hkl, pas->clsid, pas->guidProfile))
|
|
{
|
|
SyncActivateAssemblyItem(psfn, pas->langid, pItem, pas->dwFlags);
|
|
break;
|
|
}
|
|
}
|
|
Assert(i < pAsm->Count()); // should have found the item we were looking for...
|
|
|
|
Exit:
|
|
cicMemFree(pas);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateAssemblyItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL ActivateAssemblyItem(SYSTHREAD *psfn, LANGID langid, ASSEMBLYITEM *pItem, DWORD dwFlags)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
PENDING_ASSEMBLY_ITEM *pas;
|
|
CLEANUPCONTEXT cc;
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
if (ptim == NULL)
|
|
{
|
|
return SyncActivateAssemblyItem(psfn, langid, pItem, dwFlags);
|
|
}
|
|
|
|
if ((pas = (PENDING_ASSEMBLY_ITEM *)cicMemAlloc(sizeof(PENDING_ASSEMBLY_ITEM))) == NULL)
|
|
return FALSE;
|
|
|
|
pas->langid = langid;
|
|
pas->hkl = pItem->hkl;
|
|
pas->clsid = pItem->clsid;
|
|
pas->guidProfile = pItem->guidProfile;
|
|
pas->dwFlags = dwFlags;
|
|
|
|
cc.fSync = FALSE;
|
|
cc.pCatId = &pItem->catid;
|
|
cc.langid = langid;
|
|
cc.pfnPostCleanup = ActivateAssemblyItemPostCleanupCallback;
|
|
cc.lPrivate = (LONG_PTR)pas;
|
|
|
|
ptim->_CleanupContexts(&cc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SyncActivateAssemblyItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SyncActivateAssemblyItem(SYSTHREAD *psfn, LANGID langid, ASSEMBLYITEM *pItem, DWORD dwFlags)
|
|
{
|
|
int i;
|
|
int nCnt;
|
|
BOOL fActivateFEIMEHKL = FALSE;
|
|
BOOL fPrevActivateFEIMEHKL = FALSE;
|
|
BOOL fCallLeaveAssembly = FALSE;
|
|
BOOL fSkipActivate = FALSE;
|
|
BOOL fSkipNotify = FALSE;
|
|
BOOL fCiceroClient = FALSE;
|
|
CThreadInputMgr *ptim;
|
|
CAssembly *pAsm;
|
|
CAssemblyList *pAsmList;
|
|
HKL hNewKL = NULL;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return FALSE;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return FALSE;
|
|
|
|
ptim = psfn->ptim;
|
|
|
|
//
|
|
// Check if we're in Cicero aware focus.
|
|
//
|
|
if (ptim && ptim->_GetFocusDocInputMgr())
|
|
fCiceroClient = TRUE;
|
|
|
|
if (IsEqualGUID(pItem->clsid, GUID_NULL))
|
|
{
|
|
if (IsPureIMEHKL(pItem->hkl))
|
|
{
|
|
fActivateFEIMEHKL = TRUE;
|
|
}
|
|
}
|
|
else if (!fCiceroClient)
|
|
{
|
|
//
|
|
// we should not activate TIPs in the focus is already changed to
|
|
// non cicero aware DIM.
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
if (psfn->plbim)
|
|
{
|
|
fCallLeaveAssembly = TRUE;
|
|
psfn->plbim->EnterAssemblyChange();
|
|
}
|
|
|
|
#ifdef CHECKFEIMESELECTED
|
|
if (pAsm->_fUnknownFEIMESelected)
|
|
{
|
|
pAsm->_fUnknownFEIMESelected = FALSE;
|
|
fPrevActivateFEIMEHKL = TRUE;
|
|
}
|
|
#endif CHECKFEIMESELECTED
|
|
|
|
//
|
|
// deactivate all tip in the same category or diactivate all tips
|
|
// when FE-IME is activated.
|
|
//
|
|
nCnt = pAsm->Count();
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
|
|
|
|
if (!pItemTemp->fActive)
|
|
continue;
|
|
|
|
if (IsEqualGUID(pItem->catid, pItemTemp->catid))
|
|
{
|
|
if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
{
|
|
if (ptim)
|
|
{
|
|
if (IsEqualGUID(pItemTemp->clsid, pItem->clsid))
|
|
{
|
|
if (IsEqualGUID(pItemTemp->guidProfile, pItem->guidProfile))
|
|
fSkipNotify = TRUE;
|
|
|
|
if (!fSkipNotify)
|
|
ptim->NotifyActivateInputProcessor(pItemTemp->clsid, pItemTemp->guidProfile, FALSE);
|
|
fSkipActivate = TRUE;
|
|
}
|
|
else
|
|
ptim->ActivateInputProcessor(pItemTemp->clsid, pItemTemp->guidProfile, pItemTemp->hklSubstitute, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsPureIMEHKL(pItemTemp->hkl))
|
|
fPrevActivateFEIMEHKL = TRUE;
|
|
|
|
if (ptim)
|
|
ptim->NotifyActivateInputProcessor(pItemTemp->clsid,
|
|
pItemTemp->guidProfile,
|
|
FALSE);
|
|
}
|
|
|
|
pItemTemp->fActive = FALSE;
|
|
}
|
|
else if (fActivateFEIMEHKL)
|
|
{
|
|
//
|
|
// FEIMEHKL will be activated so deactivate all tips.
|
|
//
|
|
if (ptim)
|
|
{
|
|
if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
ptim->ActivateInputProcessor(pItemTemp->clsid,
|
|
pItemTemp->guidProfile,
|
|
pItemTemp->hklSubstitute,
|
|
FALSE);
|
|
else
|
|
ptim->NotifyActivateInputProcessor(pItemTemp->clsid,
|
|
pItemTemp->guidProfile,
|
|
FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
pItem->fActive = TRUE;
|
|
|
|
if (pItem->hkl && (pItem->hkl != GetKeyboardLayout(0)))
|
|
{
|
|
//
|
|
// If we're not on Cicero aware focus,
|
|
// we won't set AssemblyLangId here
|
|
// but we post WM_INPUTLANGCHANGEREQUEST.
|
|
//
|
|
PostInputLangRequest(psfn, pItem->hkl, !fCiceroClient);
|
|
hNewKL = pItem->hkl;
|
|
}
|
|
|
|
//
|
|
// Update assembly reg before making notify.
|
|
//
|
|
pAsmList->SetDefaultTIPInAssemblyInternal(pAsm, pItem, dwFlags & AAIF_CHANGEDEFAULT);
|
|
|
|
if (!fActivateFEIMEHKL)
|
|
{
|
|
if (ptim)
|
|
{
|
|
if (!fSkipNotify)
|
|
{
|
|
if (fSkipActivate || IsEqualGUID(pItem->clsid, GUID_NULL))
|
|
ptim->NotifyActivateInputProcessor(pItem->clsid, pItem->guidProfile, TRUE);
|
|
else
|
|
ptim->ActivateInputProcessor(pItem->clsid, pItem->guidProfile, pItem->hklSubstitute, TRUE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// if the previous activated item was FEIMEHKL,
|
|
// restore all tips in the other categories.
|
|
//
|
|
if (fPrevActivateFEIMEHKL)
|
|
{
|
|
nCnt = pAsm->Count();
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
|
|
|
|
if (!pItemTemp->fEnabled)
|
|
continue;
|
|
|
|
if (!pItemTemp->fActive)
|
|
continue;
|
|
|
|
if (ptim && !IsEqualGUID(pItem->catid, pItemTemp->catid))
|
|
{
|
|
ptim->ActivateInputProcessor(pItemTemp->clsid, pItemTemp->guidProfile, pItemTemp->hklSubstitute, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ptim)
|
|
ptim->NotifyActivateInputProcessor(pItem->clsid,
|
|
pItem->guidProfile,
|
|
TRUE);
|
|
}
|
|
|
|
UpdateSystemLangBarItems(psfn, hNewKL, FALSE);
|
|
|
|
if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
|
|
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetFocusDIMForAssembly
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SetFocusDIMForAssembly(BOOL fSetFocus)
|
|
{
|
|
SYSTHREAD *psfn = GetSYSTHREAD();
|
|
CThreadInputMgr *ptim;
|
|
CAssembly *pAsm;
|
|
int nCnt;
|
|
int i;
|
|
HKL hNewKL = NULL;
|
|
BOOL fCallLeaveAssembly = FALSE;
|
|
|
|
if (!psfn)
|
|
{
|
|
Assert(0);
|
|
return FALSE;
|
|
}
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
if (!ptim)
|
|
{
|
|
Assert(0);
|
|
return FALSE;
|
|
}
|
|
|
|
pAsm = GetCurrentAssembly(psfn);
|
|
if (!pAsm)
|
|
{
|
|
Assert(0);
|
|
return FALSE;
|
|
}
|
|
|
|
if (fSetFocus)
|
|
{
|
|
//
|
|
// If the substitute hKL is activated now, we move to Cicero mode
|
|
// completely.
|
|
//
|
|
HKL hKL = GetKeyboardLayout(0);
|
|
|
|
ActivateAssembly(LOWORD(hKL), ACTASM_NONE);
|
|
|
|
//
|
|
// make sure the substituing item will be activated.
|
|
// we need to use hKL that was before calling ActivateAssembly().
|
|
//
|
|
ASSEMBLYITEM *pItem = pAsm->GetSubstituteItem(hKL);
|
|
if (pItem)
|
|
{
|
|
if (!ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItem, 0))
|
|
return FALSE;
|
|
|
|
ptim->NotifyActivateInputProcessor(pItem->clsid,
|
|
pItem->guidProfile,
|
|
TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pAsm->IsEnabled(psfn))
|
|
{
|
|
//
|
|
// if the crruent active TIP has a substitute hKL, we activate it.
|
|
//
|
|
nCnt = pAsm->Count();
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
|
|
|
|
Assert(!pItemTemp->hkl || (LOWORD((HKL)pItemTemp->hkl) == pAsm->GetLangId()));
|
|
|
|
if (!pItemTemp->fEnabled)
|
|
continue;
|
|
|
|
if (!pItemTemp->fActive)
|
|
continue;
|
|
|
|
if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
|
|
{
|
|
//
|
|
// we activate the substitute hkl.
|
|
//
|
|
if (pItemTemp->hklSubstitute)
|
|
{
|
|
PostInputLangRequest(psfn, pItemTemp->hklSubstitute, FALSE);
|
|
ptim->NotifyActivateInputProcessor(GUID_NULL,
|
|
GUID_NULL,
|
|
TRUE);
|
|
hNewKL = pItemTemp->hklSubstitute;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
//
|
|
// If the current language does not have an Item can run
|
|
// under non-Cicero control, we need to swtich the languiage to
|
|
// system default input locale.
|
|
//
|
|
|
|
CAssembly *pAsmTemp;
|
|
CAssemblyList *pAsmList;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
pAsmTemp = pAsmList->GetDefaultAssembly();
|
|
if (pAsmTemp)
|
|
ActivateAssembly(pAsmTemp->GetLangId(), ACTASM_NONE);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enter assembly change notification section.
|
|
// We delay the notificaiton untill LeaveAssemblyChange() is called.
|
|
//
|
|
if (psfn->plbim)
|
|
{
|
|
fCallLeaveAssembly = TRUE;
|
|
psfn->plbim->EnterAssemblyChange();
|
|
}
|
|
|
|
UpdateSystemLangBarItems(psfn, hNewKL, FALSE);
|
|
|
|
if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
|
|
psfn->plbim->_GetLBarItemCtrl()->_AsmListUpdated(FALSE);
|
|
|
|
if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
|
|
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetKeyboardItemNum
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
UINT GetKeyboardItemNum()
|
|
{
|
|
SYSTHREAD *psfn;
|
|
CThreadInputMgr *ptim;
|
|
CAssembly *pAsm;
|
|
int i;
|
|
|
|
psfn = GetSYSTHREAD();
|
|
|
|
if (psfn == NULL)
|
|
return 0;
|
|
|
|
pAsm = GetCurrentAssembly(psfn);
|
|
|
|
if (!pAsm)
|
|
return 0;
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
if (ptim && ptim->_GetFocusDocInputMgr())
|
|
pAsm->RebuildSubstitutedHKLList();
|
|
else
|
|
pAsm->ClearSubstitutedHKLList();
|
|
|
|
int nCnt = 0;
|
|
|
|
for (i = 0; i < pAsm->Count(); i++)
|
|
{
|
|
ASSEMBLYITEM *pItemTemp;
|
|
|
|
pItemTemp = pAsm->GetItem(i);
|
|
|
|
if (!pItemTemp->fEnabled)
|
|
continue;
|
|
|
|
if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
|
|
{
|
|
if (!ptim || !ptim->_GetFocusDocInputMgr())
|
|
{
|
|
if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
continue;
|
|
}
|
|
|
|
if (IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
{
|
|
if (pAsm->IsSubstitutedHKL(pItemTemp->hkl))
|
|
continue;
|
|
}
|
|
nCnt++;
|
|
}
|
|
}
|
|
|
|
return nCnt;
|
|
}
|
|
|
|
#ifdef CHECKFEIMESELECTED
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnknownFEIMESelectedPostCleanupCallback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UnknownFEIMESelectedPostCleanupCallback(BOOL fAbort, LONG_PTR lPrivate)
|
|
{
|
|
SYSTHREAD *psfn;
|
|
LANGID langid = (LANGID)lPrivate;
|
|
|
|
if (fAbort)
|
|
return; // nothing to cleanup...
|
|
|
|
if (psfn = GetSYSTHREAD())
|
|
{
|
|
SyncUnknownFEIMESelected(psfn, langid);
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnknownFEIMESelected
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL UnknownFEIMESelected(LANGID langid)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
SYSTHREAD *psfn;
|
|
CLEANUPCONTEXT cc;
|
|
|
|
psfn = GetSYSTHREAD();
|
|
if (!psfn)
|
|
return FALSE;
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
|
|
if (ptim == NULL)
|
|
return TRUE;
|
|
|
|
cc.fSync = FALSE;
|
|
cc.pCatId = NULL;
|
|
cc.langid = langid;
|
|
cc.pfnPostCleanup = UnknownFEIMESelectedPostCleanupCallback;
|
|
cc.lPrivate = langid;
|
|
|
|
ptim->_CleanupContexts(&cc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SyncUnknownFEIMESelected
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL SyncUnknownFEIMESelected(SYSTHREAD *psfn, LANGID langid)
|
|
{
|
|
int i;
|
|
int nCnt;
|
|
// BOOL fActivateFEIMEHKL = FALSE;
|
|
// BOOL fPrevActivateFEIMEHKL = FALSE;
|
|
BOOL fCallLeaveAssembly = FALSE;
|
|
// BOOL fSkipActivate = FALSE;
|
|
// BOOL fSkipNotify = FALSE;
|
|
// BOOL fCiceroClient = FALSE;
|
|
CThreadInputMgr *ptim;
|
|
CAssembly *pAsm;
|
|
CAssemblyList *pAsmList;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return FALSE;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return FALSE;
|
|
|
|
ptim = psfn->ptim;
|
|
|
|
if (psfn->plbim)
|
|
{
|
|
fCallLeaveAssembly = TRUE;
|
|
psfn->plbim->EnterAssemblyChange();
|
|
}
|
|
|
|
pAsm->_fUnknownFEIMESelected = TRUE;
|
|
//
|
|
// deactivate all tip in the same category or diactivate all tips
|
|
// when FE-IME is activated.
|
|
//
|
|
nCnt = pAsm->Count();
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
|
|
|
|
if (!pItemTemp->fActive)
|
|
continue;
|
|
|
|
//
|
|
// FEIMEHKL will be activated so deactivate all tips.
|
|
//
|
|
if (ptim && !IsEqualGUID(pItemTemp->clsid, GUID_NULL))
|
|
ptim->ActivateInputProcessor(pItemTemp->clsid,
|
|
pItemTemp->guidProfile,
|
|
pItemTemp->hklSubstitute,
|
|
FALSE);
|
|
|
|
if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
|
|
pItemTemp->fActive = FALSE;
|
|
}
|
|
|
|
UpdateSystemLangBarItems(psfn, NULL, FALSE);
|
|
|
|
if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
|
|
psfn->plbim->_GetLBarItemCtrl()->_AsmListUpdated(FALSE);
|
|
|
|
if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
|
|
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
|
|
|
|
return TRUE;
|
|
}
|
|
#endif CHECKFEIMESELECTED
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CEnumLanguageProfiles
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CEnumLanguageProfiles::CEnumLanguageProfiles()
|
|
{
|
|
_langid = 0;
|
|
_iCur = 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CEnumLanguageProfiles::~CEnumLanguageProfiles()
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
// !!!WARNING WARNING WARNING!!!
|
|
//
|
|
// LanguageProfile enumrator is not focus DIM sensitive. Some caller
|
|
// want to know which TIP will be activated if the focus is moved to
|
|
// Cicero aware (or AIMM12).
|
|
// Don't check the current focus or patch fActive flag.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CEnumLanguageProfiles::Init(LANGID langid)
|
|
{
|
|
CAssemblyList *pAsmList;
|
|
int nCntAsm;
|
|
int i;
|
|
SYSTHREAD *psfn = GetSYSTHREAD();
|
|
|
|
if (psfn == NULL)
|
|
return FALSE;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
|
|
if (pAsmList == NULL)
|
|
return FALSE;
|
|
|
|
nCntAsm = pAsmList->Count();
|
|
if (!nCntAsm)
|
|
return FALSE;
|
|
|
|
for (i = 0;i < nCntAsm; i++)
|
|
{
|
|
CAssembly *pAsm = pAsmList->GetAssembly(i);
|
|
if (!pAsm)
|
|
continue;
|
|
|
|
if (!langid || langid == pAsm->GetLangId())
|
|
{
|
|
int j;
|
|
int nCntList = pAsm->Count();
|
|
BOOL fActivateFEIMEHKLOnCic = pAsm->IsFEIMEActive();
|
|
|
|
for (j = 0; j < nCntList; j++)
|
|
{
|
|
ASSEMBLYITEM *pItem;
|
|
TF_LANGUAGEPROFILE *pprofile;
|
|
pItem = pAsm->GetItem(j);
|
|
|
|
if (!pItem)
|
|
continue;
|
|
|
|
if (IsEqualCLSID(pItem->clsid, GUID_NULL))
|
|
continue;
|
|
|
|
pprofile = _rgProfiles.Append(1);
|
|
if (!pprofile)
|
|
continue;
|
|
|
|
pprofile->clsid = pItem->clsid;
|
|
pprofile->langid = pAsm->GetLangId();
|
|
pprofile->guidProfile = pItem->guidProfile;
|
|
pprofile->catid = pItem->catid;
|
|
|
|
if (fActivateFEIMEHKLOnCic)
|
|
pprofile->fActive = FALSE;
|
|
else
|
|
{
|
|
//
|
|
// we need to return TRUE even if the current focus is
|
|
// not Cicero aware as above comments.
|
|
//
|
|
pprofile->fActive = pItem->fActive;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_langid = langid;
|
|
|
|
return _rgProfiles.Count() ? TRUE : FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Clone
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CEnumLanguageProfiles::Clone(IEnumTfLanguageProfiles **ppEnum)
|
|
{
|
|
CEnumLanguageProfiles *pEnum = NULL;
|
|
|
|
if (!ppEnum)
|
|
return E_INVALIDARG;
|
|
|
|
*ppEnum = NULL;
|
|
|
|
pEnum = new CEnumLanguageProfiles();
|
|
if (!pEnum)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (!pEnum->Init(_langid))
|
|
{
|
|
pEnum->Release();
|
|
return E_FAIL;
|
|
}
|
|
|
|
*ppEnum = pEnum;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Next
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CEnumLanguageProfiles::Next(ULONG ulCount, TF_LANGUAGEPROFILE *rgLanguageProfiles, ULONG *pcFetched)
|
|
{
|
|
ULONG cFetched;
|
|
|
|
if (pcFetched == NULL)
|
|
{
|
|
pcFetched = &cFetched;
|
|
}
|
|
*pcFetched = 0;
|
|
|
|
while (_iCur < _rgProfiles.Count() && *pcFetched < ulCount)
|
|
{
|
|
TF_LANGUAGEPROFILE *pprofile;
|
|
pprofile = _rgProfiles.GetPtr(_iCur);
|
|
*rgLanguageProfiles = *pprofile;
|
|
rgLanguageProfiles++;
|
|
*pcFetched = *pcFetched + 1;
|
|
_iCur++;
|
|
}
|
|
|
|
return *pcFetched == ulCount ? S_OK : S_FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Reset
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CEnumLanguageProfiles::Reset()
|
|
{
|
|
_iCur = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Skip
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CEnumLanguageProfiles::Skip(ULONG ulCount)
|
|
{
|
|
_iCur += ulCount;
|
|
|
|
return (_iCur > _rgProfiles.Count()) ? S_FALSE : S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CInputProcessorProfiles
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetLanguageList
|
|
//
|
|
// This function is not TIM sensitive.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::GetLanguageList(LANGID **ppLangId, ULONG *pulCount)
|
|
{
|
|
CAssemblyList *pAsmList;
|
|
int i;
|
|
SYSTHREAD *psfn = GetSYSTHREAD();
|
|
|
|
if (pulCount != NULL)
|
|
{
|
|
*pulCount = 0;
|
|
}
|
|
if (ppLangId != NULL)
|
|
{
|
|
*ppLangId = NULL;
|
|
}
|
|
|
|
if (!pulCount)
|
|
return E_INVALIDARG;
|
|
if (!ppLangId)
|
|
return E_INVALIDARG;
|
|
|
|
if (psfn == NULL)
|
|
return E_FAIL;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return E_FAIL;
|
|
|
|
if (!pAsmList->Count())
|
|
return S_OK;
|
|
|
|
*ppLangId = (LANGID *)CoTaskMemAlloc(sizeof(LANGID) * pAsmList->Count());
|
|
if (!*ppLangId)
|
|
{
|
|
*pulCount = 0;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
for (i = 0;i < pAsmList->Count(); i++)
|
|
{
|
|
CAssembly *pAsm = pAsmList->GetAssembly(i);
|
|
|
|
//
|
|
// At least one keyboard Item must be enabled to be in the list.
|
|
//
|
|
if (pAsm->IsEnabledKeyboardItem(psfn))
|
|
{
|
|
(*ppLangId)[*pulCount] = pAsm->GetLangId();
|
|
(*pulCount)++;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnumLanguageProfiles
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::EnumLanguageProfiles(LANGID langid, IEnumTfLanguageProfiles **ppEnum)
|
|
{
|
|
CEnumLanguageProfiles *pEnum;
|
|
|
|
if (!ppEnum)
|
|
return E_INVALIDARG;
|
|
|
|
*ppEnum = NULL;
|
|
|
|
pEnum = new CEnumLanguageProfiles();
|
|
if (!pEnum)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (!pEnum->Init(langid))
|
|
{
|
|
pEnum->Release();
|
|
return E_FAIL;
|
|
}
|
|
|
|
*ppEnum = pEnum;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ActivateLanguageProfile
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::ActivateLanguageProfile(REFCLSID rclsid, LANGID langid, REFGUID guidProfile)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
CAssemblyList *pAsmList;
|
|
CAssembly *pAsm;
|
|
SYSTHREAD *psfn;
|
|
BOOL fFound = FALSE;
|
|
BOOL fNoCategory = FALSE;
|
|
GUID catid;
|
|
BOOL fSkipActivate = FALSE;
|
|
|
|
if (!langid)
|
|
return E_INVALIDARG;
|
|
|
|
psfn = GetSYSTHREAD();
|
|
if (!psfn)
|
|
return E_FAIL;
|
|
|
|
if (!(ptim = psfn->ptim))
|
|
return E_UNEXPECTED;
|
|
|
|
if (langid != GetCurrentAssemblyLangId(psfn))
|
|
return E_INVALIDARG;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return E_OUTOFMEMORY;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return E_FAIL;
|
|
|
|
fNoCategory = MyGetTIPCategory(rclsid, &catid) ? FALSE : TRUE;
|
|
|
|
int nCntList = pAsm->Count();
|
|
int i;
|
|
ASSEMBLYITEM *pItemActivate = NULL;
|
|
for (i = 0; i < nCntList; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem;
|
|
pItem = pAsm->GetItem(i);
|
|
|
|
if (!pItem->fEnabled)
|
|
continue;
|
|
|
|
if (fNoCategory || IsEqualGUID(catid, pItem->catid))
|
|
{
|
|
if (IsEqualGUID(pItem->guidProfile, guidProfile) &&
|
|
IsEqualGUID(rclsid, pItem->clsid))
|
|
{
|
|
if (pItem->fActive)
|
|
{
|
|
fSkipActivate = TRUE;
|
|
}
|
|
pItemActivate = pItem;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// we could not find the given profile in the assembly.
|
|
//
|
|
if (!pItemActivate)
|
|
return E_INVALIDARG;
|
|
|
|
if (fSkipActivate)
|
|
{
|
|
//
|
|
// the clsid is now activated. We skip to call activate
|
|
// but make a notification.
|
|
//
|
|
ptim->NotifyActivateInputProcessor(pItemActivate->clsid, pItemActivate->guidProfile, FALSE);
|
|
|
|
for (i = 0; i < nCntList; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem;
|
|
pItem = pAsm->GetItem(i);
|
|
|
|
if (!pItem->fEnabled)
|
|
continue;
|
|
|
|
if (!pItem->fActive)
|
|
continue;
|
|
|
|
if (!fNoCategory && !IsEqualGUID(catid, pItem->catid))
|
|
continue;
|
|
|
|
if (IsEqualGUID(rclsid, pItem->clsid))
|
|
{
|
|
pItem->fActive = FALSE;
|
|
}
|
|
}
|
|
|
|
pAsmList->SetDefaultTIPInAssemblyInternal(pAsm, pItemActivate, TRUE);
|
|
pItemActivate->fActive = TRUE;
|
|
ptim->NotifyActivateInputProcessor(pItemActivate->clsid, pItemActivate->guidProfile, TRUE);
|
|
|
|
UpdateSystemLangBarItems(psfn, NULL, FALSE);
|
|
|
|
MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
|
|
}
|
|
else if (!pItemActivate->fActive)
|
|
{
|
|
if (!IsEqualGUID(pItemActivate->clsid, GUID_NULL) &&
|
|
!ptim->_GetFocusDocInputMgr())
|
|
{
|
|
//
|
|
// We don't want to support this. It is better to return ERROR.
|
|
// However TIP and Apps may want to call this method
|
|
// on Non-Cicero aware control such as DialogBox.
|
|
//
|
|
pAsmList->SetDefaultTIPInAssemblyInternal(pAsm, pItemActivate, TRUE);
|
|
ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItemActivate, AAIF_CHANGEDEFAULT);
|
|
if (IsEqualGUID(pItemActivate->catid, GUID_TFCAT_TIP_KEYBOARD))
|
|
{
|
|
pItemActivate->fActive = TRUE;
|
|
SetFocusDIMForAssembly(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItemActivate, AAIF_CHANGEDEFAULT);
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetActiveLanguageProfile
|
|
//
|
|
// WARNING!!!
|
|
//
|
|
// Which GetActiveLanguageProfile() or GetDefaultLanguageProfile() should
|
|
// we use?
|
|
//
|
|
// This function is FocusDIM sensetive. So we can call any function
|
|
// to check TIM or FocusDIM.
|
|
//
|
|
// If you don't want to care about TIM and FocusDIM, try
|
|
// GetDefaultLanguageProfile.
|
|
//
|
|
// if clsid is TIP's category ID, this returns the activated profiles in the
|
|
// category.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::GetActiveLanguageProfile(REFCLSID clsid, LANGID *plangid, GUID *pguid)
|
|
{
|
|
CThreadInputMgr *ptim;
|
|
CAssemblyList *pAsmList;
|
|
CAssembly *pAsm;
|
|
SYSTHREAD *psfn;
|
|
LANGID langid;
|
|
BOOL fFound = FALSE;
|
|
|
|
if (!plangid)
|
|
return E_INVALIDARG;
|
|
|
|
if (!pguid)
|
|
return E_INVALIDARG;
|
|
|
|
*plangid = 0;
|
|
*pguid = GUID_NULL;
|
|
|
|
psfn = GetSYSTHREAD();
|
|
if (!psfn)
|
|
return E_FAIL;
|
|
|
|
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
|
|
if (!ptim || !ptim->_GetFocusDocInputMgr())
|
|
{
|
|
//
|
|
// Special Service!
|
|
//
|
|
// GetActiveLanguageProfile(GUID_TFCAT_TIP_KEYBOARD) works
|
|
// without TIM, it can returns, the current keyboard layout.
|
|
//
|
|
if (IsEqualGUID(clsid, GUID_TFCAT_TIP_KEYBOARD))
|
|
{
|
|
HKL hkl;
|
|
|
|
if (psfn->hklBeingActivated)
|
|
hkl = psfn->hklBeingActivated;
|
|
else
|
|
hkl = GetKeyboardLayout(0);
|
|
|
|
*plangid = LOWORD((DWORD)(UINT_PTR)hkl);
|
|
*((DWORD *)pguid) = (DWORD)(UINT_PTR)hkl;
|
|
return S_OK;
|
|
}
|
|
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
langid = GetCurrentAssemblyLangId(psfn);
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return E_OUTOFMEMORY;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return E_FAIL;
|
|
|
|
int nCntList = pAsm->Count();
|
|
int i;
|
|
for (i = 0; i < nCntList; i++)
|
|
{
|
|
ASSEMBLYITEM *pItem;
|
|
pItem = pAsm->GetItem(i);
|
|
|
|
if (!pItem->fEnabled)
|
|
continue;
|
|
|
|
if (pItem->fActive)
|
|
{
|
|
if (IsEqualGUID(clsid, pItem->catid) ||
|
|
IsEqualGUID(clsid, pItem->clsid))
|
|
{
|
|
fFound = TRUE;
|
|
*plangid = langid;
|
|
if (!IsEqualCLSID(pItem->clsid, CLSID_NULL))
|
|
*pguid = pItem->guidProfile;
|
|
else
|
|
*((DWORD *)pguid) = (DWORD)(UINT_PTR)(HKL)(pItem->hkl);
|
|
}
|
|
}
|
|
}
|
|
|
|
return fFound ? S_OK : S_FALSE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetCurrentLanguage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::GetCurrentLanguage(LANGID *plangid)
|
|
{
|
|
if (!plangid)
|
|
return E_INVALIDARG;
|
|
|
|
*plangid = GetCurrentAssemblyLangId(NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ChangeCurrentLanguage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::ChangeCurrentLanguage(LANGID langid)
|
|
{
|
|
CAssemblyList *pAsmList;
|
|
CAssembly *pAsm;
|
|
SYSTHREAD *psfn;
|
|
|
|
if (CThreadInputMgr::_GetThis() == NULL)
|
|
return E_UNEXPECTED;
|
|
|
|
psfn = GetSYSTHREAD();
|
|
if (!psfn)
|
|
return E_FAIL;
|
|
|
|
if (langid == GetCurrentAssemblyLangId(psfn))
|
|
return S_OK;
|
|
|
|
pAsmList = EnsureAssemblyList(psfn);
|
|
if (!pAsmList)
|
|
return E_OUTOFMEMORY;
|
|
|
|
pAsm = pAsmList->FindAssemblyByLangId(langid);
|
|
if (!pAsm)
|
|
return E_INVALIDARG;
|
|
|
|
return ActivateAssembly(pAsm->GetLangId(), ACTASM_NONE) ? S_OK : E_FAIL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AdviseSink
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
|
|
{
|
|
const IID *rgiid = &IID_ITfLanguageProfileNotifySink;
|
|
|
|
return GenericAdviseSink(riid, punk, &rgiid, &_rgNotifySinks, 1, pdwCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// UnadviseSink
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CInputProcessorProfiles::UnadviseSink(DWORD dwCookie)
|
|
{
|
|
return GenericUnadviseSink(&_rgNotifySinks, 1, dwCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnLanguageChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CInputProcessorProfiles::_OnLanguageChange(BOOL fChanged, LANGID langid)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < _rgNotifySinks.Count(); i++)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (!fChanged)
|
|
{
|
|
BOOL fAccept;
|
|
hr = ((ITfLanguageProfileNotifySink *)_rgNotifySinks.GetPtr(i)->pSink)->OnLanguageChange(langid, &fAccept);
|
|
if (SUCCEEDED(hr) && !fAccept)
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
((ITfLanguageProfileNotifySink *)_rgNotifySinks.GetPtr(i)->pSink)->OnLanguageChanged();
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|