// // 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; }