Leaked source code of windows server 2003
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

  1. //
  2. // profiles.cpp
  3. //
  4. #include "private.h"
  5. #include "tim.h"
  6. #include "ic.h"
  7. #include "dim.h"
  8. #include "assembly.h"
  9. #include "nuictrl.h"
  10. #include "nuihkl.h"
  11. #include "imelist.h"
  12. #include "xstring.h"
  13. #include "profiles.h"
  14. #include "lbaddin.h"
  15. BOOL MyGetTIPCategory(REFCLSID clsid, GUID *pcatid);
  16. DBG_ID_INSTANCE(CEnumLanguageProfiles);
  17. typedef struct _PENDING_ASSEMBLY_ITEM
  18. {
  19. LANGID langid;
  20. HKL hkl;
  21. CLSID clsid;
  22. GUID guidProfile;
  23. DWORD dwFlags;
  24. } PENDING_ASSEMBLY_ITEM;
  25. //////////////////////////////////////////////////////////////////////////////
  26. //
  27. // static functions
  28. //
  29. //////////////////////////////////////////////////////////////////////////////
  30. //+---------------------------------------------------------------------------
  31. //
  32. // UpdateSystemLangBarItems()
  33. //
  34. //----------------------------------------------------------------------------
  35. void UpdateSystemLangBarItems(SYSTHREAD *psfn, HKL hNewKL, BOOL fNotify)
  36. {
  37. if (psfn->plbim == NULL)
  38. return;
  39. if (psfn->plbim->_GetLBarItemDeviceTypeArray())
  40. {
  41. int nCnt = psfn->plbim->_GetLBarItemDeviceTypeArray()->Count();
  42. int i;
  43. for (i = 0; i < nCnt; i++)
  44. {
  45. CLBarItemDeviceType *plbi = psfn->plbim->_GetLBarItemDeviceTypeArray()->Get(i);
  46. plbi->ShowOrHide(fNotify);
  47. }
  48. }
  49. if (psfn->plbim->_GetLBarItemCtrl())
  50. psfn->plbim->_GetLBarItemCtrl()->_UpdateLangIcon(hNewKL, fNotify);
  51. if (psfn->plbim->_GetLBarItemReconv())
  52. psfn->plbim->_GetLBarItemReconv()->ShowOrHide(fNotify);
  53. //
  54. // If this function is called, someone needs to make
  55. // notification later.
  56. //
  57. if (psfn->plbim->InAssemblyChange())
  58. {
  59. Assert(!fNotify);
  60. psfn->plbim->SetItemChange();
  61. }
  62. UpdateLangBarAddIns();
  63. }
  64. //+---------------------------------------------------------------------------
  65. //
  66. // ActivateAssemblyPostCleanupCallback
  67. //
  68. //----------------------------------------------------------------------------
  69. void ActivateAssemblyPostCleanupCallback(BOOL fAbort, LONG_PTR lPrivate)
  70. {
  71. SYSTHREAD *psfn;
  72. LANGID langid = HIWORD(lPrivate);
  73. ACTASM actasm = (ACTASM)LOWORD(lPrivate);
  74. if (fAbort)
  75. return; // nothing to cleanup...
  76. if (psfn = GetSYSTHREAD())
  77. {
  78. SyncActivateAssembly(psfn, langid, actasm);
  79. }
  80. }
  81. //+---------------------------------------------------------------------------
  82. //
  83. // DeactivateRemovedTipinAssembly
  84. //
  85. // Deactivate active TIPs that are not in the assembly list. This can happen
  86. // someone remove the profile from the control panel during the tip is
  87. // running on some application.
  88. //
  89. //----------------------------------------------------------------------------
  90. void DeactivateRemovedTipInAssembly(CThreadInputMgr *ptim, CAssembly *pAsm)
  91. {
  92. int nAsmCnt = pAsm->Count();
  93. TfGuidAtom *patom;
  94. int i;
  95. UINT j;
  96. if (!ptim)
  97. return;
  98. if (!nAsmCnt)
  99. return;
  100. patom = new TfGuidAtom[nAsmCnt];
  101. if (!patom)
  102. return;
  103. for (i = 0; i < nAsmCnt; i++)
  104. {
  105. ASSEMBLYITEM *pItem = pAsm->GetItem(i);
  106. patom[i] = TF_INVALID_GUIDATOM;
  107. if (pItem && pItem->fEnabled && !IsEqualGUID(pItem->clsid, GUID_NULL))
  108. MyRegisterGUID(pItem->clsid, &patom[i]);
  109. }
  110. for (j = 0; j < ptim->_GetTIPCount(); j++)
  111. {
  112. const CTip *ptip = ptim->_GetCTip(j);
  113. if (ptip && ptip->_fActivated)
  114. {
  115. BOOL fFound = FALSE;
  116. for (i = 0; i < nAsmCnt; i++)
  117. {
  118. if (ptip->_guidatom == patom[i])
  119. fFound = TRUE;
  120. }
  121. if (!fFound)
  122. {
  123. CLSID clsid;
  124. if (SUCCEEDED(MyGetGUID(ptip->_guidatom, &clsid)))
  125. ptim->ActivateInputProcessor(clsid,
  126. GUID_NULL,
  127. NULL,
  128. FALSE);
  129. }
  130. }
  131. }
  132. delete patom;
  133. }
  134. //+---------------------------------------------------------------------------
  135. //
  136. // GetAssemblyChangeHKL
  137. //
  138. // --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
  139. //
  140. // GetAssemblyChangeHKL and SyncActivateAssembly must have exactly
  141. // same logic. Otherwise HKL will be corrupted.
  142. //
  143. // --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
  144. //
  145. //----------------------------------------------------------------------------
  146. HKL GetAssemblyChangeHKL(SYSTHREAD *psfn, LANGID langid, BOOL fTimActivateLayout)
  147. {
  148. CThreadInputMgr *ptim;
  149. BOOL fRet = FALSE;
  150. ULONG ul;
  151. ULONG ulCount = 0;
  152. int nAsmCnt;
  153. int i;
  154. BOOL fActivated = FALSE;
  155. BOOL fActiveNoCic = FALSE;
  156. BOOL fActivateFEIMEHKLOnCic = FALSE;
  157. BOOL fCiceroClient= FALSE;
  158. CAssembly *pAsm;
  159. CAssemblyList *pAsmList;
  160. HKL hNewKL = NULL;
  161. HKL hCurrKL = GetKeyboardLayout(0);
  162. pAsmList = EnsureAssemblyList(psfn);
  163. if (!pAsmList)
  164. return NULL;
  165. pAsm = pAsmList->FindAssemblyByLangId(langid);
  166. if (!pAsm)
  167. return NULL;
  168. nAsmCnt = pAsm->Count();
  169. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  170. //
  171. // Check if we're in Cicero aware focus.
  172. //
  173. if (ptim && ptim->_GetFocusDocInputMgr())
  174. fCiceroClient = TRUE;
  175. fActivateFEIMEHKLOnCic = pAsm->IsFEIMEActive();
  176. TryAgain:
  177. for (i = 0; i < nAsmCnt; i++)
  178. {
  179. ASSEMBLYITEM *pItem = pAsm->GetItem(i);
  180. if (!pItem->fEnabled)
  181. continue;
  182. if (fActiveNoCic)
  183. {
  184. if (fCiceroClient)
  185. {
  186. if (!pItem->fActiveNoCic)
  187. continue;
  188. }
  189. else
  190. {
  191. if (fActivated)
  192. break;
  193. }
  194. }
  195. else
  196. {
  197. if (!pItem->fActive)
  198. continue;
  199. }
  200. if (!IsEqualGUID(pItem->clsid, GUID_NULL))
  201. {
  202. BOOL fFound = FALSE;
  203. ul = 0;
  204. //
  205. // if fTimActivateLayout is true, we load TIPs.
  206. //
  207. if (!fCiceroClient && !fTimActivateLayout)
  208. continue;
  209. //
  210. // skip to activate cicero tip because we will activate
  211. // FEIMEHKL.
  212. //
  213. if (fActivateFEIMEHKLOnCic)
  214. continue;
  215. if (pItem->hkl)
  216. {
  217. HKL hKL = pItem->hkl;
  218. //
  219. // If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
  220. //
  221. if (hKL != hCurrKL)
  222. hNewKL = hKL;
  223. }
  224. fActivated = TRUE;
  225. }
  226. else if (pItem->hkl)
  227. {
  228. HKL hKL = pItem->hkl;
  229. //
  230. // skip substituted hKL on Cicero aware control.
  231. //
  232. if (fCiceroClient && pAsm->GetSubstituteItem(hKL))
  233. continue;
  234. //
  235. // If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
  236. //
  237. if (hKL != hCurrKL)
  238. hNewKL = hKL;
  239. fActivated = TRUE;
  240. }
  241. }
  242. if (!fActivated && !fActiveNoCic)
  243. {
  244. fActiveNoCic = TRUE;
  245. goto TryAgain;
  246. }
  247. return hNewKL;
  248. }
  249. //+---------------------------------------------------------------------------
  250. //
  251. // ActivateAssembly
  252. //
  253. //----------------------------------------------------------------------------
  254. BOOL ActivateAssembly(LANGID langid, ACTASM actasm)
  255. {
  256. CThreadInputMgr *ptim;
  257. SYSTHREAD *psfn;
  258. LONG_PTR lParam;
  259. CLEANUPCONTEXT cc;
  260. BOOL bRet = FALSE;
  261. BOOL fTimActivateLayout = (actasm == ACTASM_ONTIMACTIVE) ? TRUE : FALSE;
  262. BOOL fOnShellLangChange = (actasm == ACTASM_ONSHELLLANGCHANGE) ? TRUE : FALSE;
  263. psfn = GetSYSTHREAD();
  264. if (!psfn)
  265. return FALSE;
  266. if (psfn->fInActivateAssembly)
  267. return FALSE;
  268. psfn->fInActivateAssembly = TRUE;
  269. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  270. //
  271. // if the client is no Cicero aware, we just post
  272. // WM_INPUTLANGCHANGEREQUEST.
  273. //
  274. if (!ptim || (!fTimActivateLayout && !ptim->_GetFocusDocInputMgr()))
  275. {
  276. //
  277. // If we don't requires any hKL change to activate this new
  278. // assembly, we can call SyncActivateAssembly now.
  279. // Otherwise we need to wait until WM_INPUTLANGUAGECHANGEREQUEST
  280. // is processed.
  281. //
  282. HKL hKL = GetAssemblyChangeHKL(psfn, langid, fTimActivateLayout);
  283. if (fOnShellLangChange || !hKL || (hKL == GetKeyboardLayout(0)))
  284. SyncActivateAssembly(psfn, langid, actasm);
  285. else
  286. PostInputLangRequest(psfn, hKL, TRUE);
  287. goto Exit;
  288. }
  289. lParam = ((DWORD)langid << 16);
  290. lParam |= actasm;
  291. cc.fSync = fTimActivateLayout;
  292. cc.pCatId = NULL;
  293. cc.langid = langid;
  294. cc.pfnPostCleanup = ActivateAssemblyPostCleanupCallback;
  295. cc.lPrivate = lParam;
  296. ptim->_CleanupContexts(&cc);
  297. bRet = TRUE;
  298. Exit:
  299. psfn->fInActivateAssembly = FALSE;
  300. return bRet;
  301. }
  302. //+---------------------------------------------------------------------------
  303. //
  304. // SyncActivateAssembly
  305. //
  306. // --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
  307. //
  308. // GetAssemblyChangeHKL and SyncActivateAssembly must have exactly
  309. // same logic. Otherwise HKL will be corrupted.
  310. //
  311. // --------- !!!!!!! WARNING WARNING WARNING !!!!!!! ----------
  312. //
  313. //----------------------------------------------------------------------------
  314. BOOL SyncActivateAssembly(SYSTHREAD *psfn, LANGID langid, ACTASM actasm)
  315. {
  316. CThreadInputMgr *ptim;
  317. BOOL fRet = FALSE;
  318. ULONG ul;
  319. ULONG ulCount = 0;
  320. int nAsmCnt;
  321. int i;
  322. BOOL fActivated = FALSE;
  323. BOOL fActiveNoCic = FALSE;
  324. BOOL fIconUpdated = FALSE;
  325. BOOL fActivateFEIMEHKLOnCic = FALSE;
  326. BOOL fCallLeaveAssembly = FALSE;
  327. BOOL fCiceroClient= FALSE;
  328. CAssembly *pAsm;
  329. CAssemblyList *pAsmList;
  330. HKL hNewKL = NULL;
  331. BOOL fTimActivateLayout = (actasm == ACTASM_ONTIMACTIVE) ? TRUE : FALSE;
  332. BOOL fOnShellLangChange = (actasm == ACTASM_ONSHELLLANGCHANGE) ? TRUE : FALSE;
  333. pAsmList = EnsureAssemblyList(psfn);
  334. if (!pAsmList)
  335. return FALSE;
  336. pAsm = pAsmList->FindAssemblyByLangId(langid);
  337. if (!pAsm)
  338. return FALSE;
  339. #ifdef CHECKFEIMESELECTED
  340. pAsm->_fUnknownFEIMESelected = FALSE;
  341. #endif CHECKFEIMESELECTED
  342. if (psfn->pipp)
  343. {
  344. if (!psfn->pipp->_OnLanguageChange(FALSE, pAsm->GetLangId()))
  345. return TRUE;
  346. }
  347. //
  348. // Enter assembly change notification section.
  349. // We delay the notificaiton untill LeaveAssemblyChange() is called.
  350. //
  351. if (psfn->plbim)
  352. {
  353. fCallLeaveAssembly = TRUE;
  354. psfn->plbim->EnterAssemblyChange();
  355. }
  356. nAsmCnt = pAsm->Count();
  357. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  358. //
  359. // Check if we're in Cicero aware focus.
  360. //
  361. if (ptim && ptim->_GetFocusDocInputMgr())
  362. fCiceroClient = TRUE;
  363. for (i = 0; i < nAsmCnt; i++)
  364. {
  365. ASSEMBLYITEM *pItem = pAsm->GetItem(i);
  366. pItem->fSkipToActivate = FALSE;
  367. pItem->fSkipToNotify = FALSE;
  368. }
  369. if (ptim)
  370. {
  371. CAssembly *pAsmCur;
  372. pAsmCur = GetCurrentAssembly(psfn);
  373. if (pAsmCur)
  374. {
  375. int nAsmCurCnt = pAsmCur->Count();
  376. DeactivateRemovedTipInAssembly(ptim, pAsmCur);
  377. //
  378. // check if we will activate FEIMEHKL. If so, we will disable
  379. // all Cicero tip.
  380. //
  381. fActivateFEIMEHKLOnCic = pAsm->IsFEIMEActive();
  382. for (int j = 0; j < nAsmCurCnt; j++)
  383. {
  384. ASSEMBLYITEM *pItemCur = pAsmCur->GetItem(j);
  385. if (!pItemCur->fEnabled)
  386. continue;
  387. BOOL fSkipToActivate = FALSE;
  388. BOOL fSkipToNotify = FALSE;
  389. if (ptim->_IsActiveInputProcessor(pItemCur->clsid) != S_OK)
  390. continue;
  391. for (i = 0; i < nAsmCnt; i++)
  392. {
  393. ASSEMBLYITEM *pItem = pAsm->GetItem(i);
  394. if (!pItem->fEnabled)
  395. continue;
  396. if (pItem->fActive &&
  397. !fActivateFEIMEHKLOnCic &&
  398. IsEqualCLSID(pItem->clsid, pItemCur->clsid))
  399. {
  400. if (IsEqualCLSID(pItem->guidProfile, pItemCur->guidProfile))
  401. {
  402. pItem->fSkipToNotify = TRUE;
  403. fSkipToNotify = TRUE;
  404. }
  405. pItem->fSkipToActivate = TRUE;
  406. fSkipToActivate = TRUE;
  407. break;
  408. }
  409. }
  410. if (!fSkipToNotify)
  411. {
  412. if (fSkipToActivate)
  413. ptim->NotifyActivateInputProcessor(pItemCur->clsid, pItemCur->guidProfile, FALSE);
  414. else
  415. ptim->ActivateInputProcessor(pItemCur->clsid, pItemCur->guidProfile, pItemCur->hklSubstitute, FALSE);
  416. }
  417. }
  418. }
  419. else
  420. {
  421. //
  422. // if the current assembly is gone, we deactivate all tips.
  423. //
  424. for (ul = 0; ul < ptim->_GetTIPCount(); ul++)
  425. {
  426. const CTip *ptip = ptim->_GetCTip(ul);
  427. if (ptip->_fActivated)
  428. {
  429. CLSID clsid;
  430. if (SUCCEEDED(MyGetGUID(ptip->_guidatom, &clsid)))
  431. ptim->ActivateInputProcessor(clsid, GUID_NULL, NULL, FALSE);
  432. }
  433. }
  434. }
  435. }
  436. SetCurrentAssemblyLangId(psfn, pAsm->GetLangId());
  437. TryAgain:
  438. for (i = 0; i < nAsmCnt; i++)
  439. {
  440. ASSEMBLYITEM *pItem = pAsm->GetItem(i);
  441. if (!pItem)
  442. {
  443. Assert(0);
  444. continue;
  445. }
  446. if (!pItem->fEnabled)
  447. continue;
  448. if (fActiveNoCic)
  449. {
  450. if (fCiceroClient)
  451. {
  452. if (!pItem->fActiveNoCic)
  453. continue;
  454. }
  455. else
  456. {
  457. if (fActivated)
  458. break;
  459. }
  460. }
  461. else
  462. {
  463. if (!pItem->fActive)
  464. continue;
  465. }
  466. if (!IsEqualGUID(pItem->clsid, GUID_NULL))
  467. {
  468. BOOL fFound = FALSE;
  469. ul = 0;
  470. //
  471. // if fTimActivateLayout is true, we load TIPs.
  472. //
  473. if (!fCiceroClient && !fTimActivateLayout)
  474. continue;
  475. //
  476. // skip to activate cicero tip because we will activate
  477. // FEIMEHKL.
  478. //
  479. if (fActivateFEIMEHKLOnCic)
  480. continue;
  481. if (pItem->hkl)
  482. {
  483. HKL hKL = pItem->hkl;
  484. HKL hCurrKL = GetKeyboardLayout(0);
  485. //
  486. // If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
  487. //
  488. if (hKL != hCurrKL)
  489. {
  490. //
  491. // If we're not on Cicero aware focus,
  492. // we won't set AssemblyLangId here
  493. // but we post WM_INPUTLANGCHANGEREQUEST.
  494. //
  495. if (!fOnShellLangChange)
  496. PostInputLangRequest(psfn, hKL,
  497. !fTimActivateLayout && !fCiceroClient);
  498. hNewKL = hKL;
  499. }
  500. }
  501. //
  502. // check if this TIP is already activated.
  503. //
  504. if (pItem->fSkipToActivate)
  505. {
  506. if (!pItem->fSkipToNotify)
  507. ptim->NotifyActivateInputProcessor(pItem->clsid, pItem->guidProfile, TRUE);
  508. pItem->fSkipToActivate = FALSE;
  509. pItem->fSkipToNotify = FALSE;
  510. }
  511. else
  512. ptim->ActivateInputProcessor(pItem->clsid, pItem->guidProfile, pItem->hklSubstitute, TRUE);
  513. fActivated = TRUE;
  514. }
  515. else if (pItem->hkl)
  516. {
  517. HKL hKL = pItem->hkl;
  518. HKL hCurrKL = GetKeyboardLayout(0);
  519. //
  520. // skip substituted hKL on Cicero aware control.
  521. //
  522. if (fCiceroClient && pAsm->GetSubstituteItem(hKL))
  523. continue;
  524. //
  525. // If hKL is different, post WM_INPUTLANGCHANGEREQUEST.
  526. //
  527. if (hKL != hCurrKL)
  528. {
  529. //
  530. // If we're not on Cicero aware focus,
  531. // we won't set AssemblyLangId here
  532. // but we post WM_INPUTLANGCHANGEREQUEST.
  533. //
  534. if (!fOnShellLangChange)
  535. PostInputLangRequest(psfn, hKL,
  536. !fTimActivateLayout && !fCiceroClient);
  537. hNewKL = hKL;
  538. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  539. }
  540. //
  541. // Notify to profile.
  542. //
  543. if (ptim)
  544. {
  545. ptim->NotifyActivateInputProcessor(pItem->clsid,
  546. pItem->guidProfile,
  547. TRUE);
  548. }
  549. //
  550. // Now we activated this pItem.
  551. //
  552. fActivated = TRUE;
  553. }
  554. }
  555. if (!fActivated && !fActiveNoCic)
  556. {
  557. fActiveNoCic = TRUE;
  558. goto TryAgain;
  559. }
  560. UpdateSystemLangBarItems(psfn, hNewKL, FALSE);
  561. fRet = TRUE;
  562. if (psfn->pipp)
  563. {
  564. psfn->pipp->_OnLanguageChange(TRUE, 0);
  565. }
  566. if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
  567. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  568. return fRet;
  569. }
  570. //+---------------------------------------------------------------------------
  571. //
  572. // ActivateNextAssembly
  573. //
  574. //----------------------------------------------------------------------------
  575. BOOL ActivateNextAssembly(BOOL bPrev)
  576. {
  577. SYSTHREAD *psfn;
  578. CAssemblyList *pAsmList;
  579. CAssembly *pAsmNext = NULL;
  580. BOOL bRet = FALSE;
  581. LANGID langidCur;
  582. if ((psfn = GetSYSTHREAD()) == NULL)
  583. return FALSE;
  584. if ((pAsmList = EnsureAssemblyList(psfn)) == NULL)
  585. return FALSE;
  586. int i;
  587. int nCnt = pAsmList->Count();
  588. Assert(nCnt > 0);
  589. langidCur = GetCurrentAssemblyLangId(psfn);
  590. for (i = 0; i < nCnt; i++)
  591. {
  592. CAssembly *pAsm = pAsmList->GetAssembly(i);
  593. if (pAsm->GetLangId() == langidCur)
  594. {
  595. int nNext;
  596. int nCur = i;
  597. CheckNext:
  598. if (bPrev)
  599. {
  600. nNext = i - 1;
  601. if (nNext < 0)
  602. nNext = nCnt - 1;
  603. }
  604. else
  605. {
  606. nNext = i + 1;
  607. if (nNext >= nCnt)
  608. nNext = 0;
  609. }
  610. pAsmNext = pAsmList->GetAssembly(nNext);
  611. if (!pAsmNext->IsEnabled(psfn))
  612. {
  613. i = nNext;
  614. if (i == nCur)
  615. {
  616. //
  617. // we cound not find Asm.
  618. // we don't have to change the assembly.
  619. //
  620. pAsmNext = NULL;
  621. break;
  622. }
  623. goto CheckNext;
  624. }
  625. break;
  626. }
  627. }
  628. if (pAsmNext && pAsmNext->GetLangId() != langidCur)
  629. {
  630. bRet = ActivateAssembly(pAsmNext->GetLangId(), ACTASM_NONE);
  631. }
  632. return bRet;
  633. }
  634. //+---------------------------------------------------------------------------
  635. //
  636. // ActivateNextKeyTip
  637. //
  638. //----------------------------------------------------------------------------
  639. BOOL ActivateNextKeyTip(BOOL bPrev)
  640. {
  641. SYSTHREAD *psfn;
  642. CThreadInputMgr *ptim;
  643. CAssembly *pAsm;
  644. ASSEMBLYITEM *pItemFirst = NULL;
  645. ASSEMBLYITEM *pItemCur = NULL;
  646. ASSEMBLYITEM *pItemNext = NULL;
  647. BOOL bCatchNext = FALSE;
  648. int i;
  649. BOOL fTransitory = FALSE;
  650. BOOL fCiceroClient = FALSE;
  651. if ((psfn = GetSYSTHREAD()) == NULL)
  652. return FALSE;
  653. if ((pAsm = GetCurrentAssembly(psfn)) == NULL)
  654. return FALSE;
  655. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  656. if (ptim && ptim->_GetFocusDocInputMgr())
  657. {
  658. pAsm->RebuildSubstitutedHKLList();
  659. CInputContext *pic = ptim->_GetFocusDocInputMgr()->_GetTopIC();
  660. if (pic)
  661. {
  662. TF_STATUS dcs;
  663. if (SUCCEEDED(pic->GetStatus(&dcs)) &&
  664. (dcs.dwStaticFlags & TF_SS_TRANSITORY))
  665. fTransitory = TRUE;
  666. }
  667. fCiceroClient = TRUE;
  668. }
  669. else
  670. pAsm->ClearSubstitutedHKLList();
  671. HKL hkl = GetKeyboardLayout(0);
  672. int nCnt = pAsm->Count();
  673. for (i = 0; i < nCnt; i++)
  674. {
  675. ASSEMBLYITEM *pItemTemp;
  676. if (!bPrev)
  677. pItemTemp = pAsm->GetItem(i);
  678. else
  679. pItemTemp = pAsm->GetItem(nCnt - i - 1);
  680. if (!pItemTemp->fEnabled)
  681. continue;
  682. if (pItemTemp->fDisabledOnTransitory && fTransitory)
  683. continue;
  684. if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
  685. {
  686. if (!fCiceroClient)
  687. {
  688. if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  689. continue;
  690. }
  691. else
  692. {
  693. if (IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  694. {
  695. if (pAsm->IsSubstitutedHKL(pItemTemp->hkl))
  696. continue;
  697. }
  698. }
  699. if (!pItemFirst)
  700. pItemFirst = pItemTemp;
  701. if (bCatchNext)
  702. {
  703. pItemNext = pItemTemp;
  704. break;
  705. }
  706. if (pItemTemp->fActive ||
  707. ((!fCiceroClient || IsPureIMEHKL(hkl)) && (hkl == pItemTemp->hkl)))
  708. {
  709. pItemCur = pItemTemp;
  710. bCatchNext = TRUE;
  711. }
  712. }
  713. }
  714. if (!pItemNext)
  715. {
  716. pItemNext = pItemFirst;
  717. }
  718. if (pItemNext)
  719. {
  720. ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItemNext, AAIF_CHANGEDEFAULT);
  721. }
  722. return TRUE;
  723. }
  724. //+---------------------------------------------------------------------------
  725. //
  726. // GetCurrentAssembly
  727. //
  728. //+---------------------------------------------------------------------------
  729. CAssembly *GetCurrentAssembly(SYSTHREAD *psfn)
  730. {
  731. LANGID langid = 0;
  732. if (!psfn)
  733. {
  734. if ((psfn = GetSYSTHREAD()) == NULL)
  735. return NULL;
  736. }
  737. CAssemblyList *pAsmList = EnsureAssemblyList(psfn);
  738. if (!pAsmList)
  739. return NULL;
  740. if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
  741. langid = GetCurrentAssemblyLangId(psfn);
  742. return pAsmList->FindAssemblyByLangId(langid);
  743. }
  744. //+---------------------------------------------------------------------------
  745. //
  746. // ActivateAssemblyItemPostCleanupCallback
  747. //
  748. //----------------------------------------------------------------------------
  749. void ActivateAssemblyItemPostCleanupCallback(BOOL fAbort, LONG_PTR lPrivate)
  750. {
  751. PENDING_ASSEMBLY_ITEM *pas = (PENDING_ASSEMBLY_ITEM *)lPrivate;
  752. SYSTHREAD *psfn;
  753. CAssemblyList *pAsmList;
  754. CAssembly *pAsm;
  755. ASSEMBLYITEM *pItem;
  756. int i;
  757. if (fAbort) // just a cleanup?
  758. goto Exit;
  759. if ((psfn = GetSYSTHREAD()) == NULL)
  760. goto Exit;
  761. if ((pAsmList = EnsureAssemblyList(psfn)) == NULL)
  762. {
  763. Assert(0);
  764. goto Exit;
  765. }
  766. if ((pAsm = pAsmList->FindAssemblyByLangId(pas->langid)) == NULL)
  767. {
  768. Assert(0);
  769. goto Exit;
  770. }
  771. //
  772. // we need to make sure the pItem is valid.
  773. //
  774. for (i = 0; i < pAsm->Count(); i++)
  775. {
  776. pItem = pAsm->GetItem(i);
  777. if (pItem->IsEqual(pas->hkl, pas->clsid, pas->guidProfile))
  778. {
  779. SyncActivateAssemblyItem(psfn, pas->langid, pItem, pas->dwFlags);
  780. break;
  781. }
  782. }
  783. Assert(i < pAsm->Count()); // should have found the item we were looking for...
  784. Exit:
  785. cicMemFree(pas);
  786. }
  787. //+---------------------------------------------------------------------------
  788. //
  789. // ActivateAssemblyItem
  790. //
  791. //----------------------------------------------------------------------------
  792. BOOL ActivateAssemblyItem(SYSTHREAD *psfn, LANGID langid, ASSEMBLYITEM *pItem, DWORD dwFlags)
  793. {
  794. CThreadInputMgr *ptim;
  795. PENDING_ASSEMBLY_ITEM *pas;
  796. CLEANUPCONTEXT cc;
  797. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  798. if (ptim == NULL)
  799. {
  800. return SyncActivateAssemblyItem(psfn, langid, pItem, dwFlags);
  801. }
  802. if ((pas = (PENDING_ASSEMBLY_ITEM *)cicMemAlloc(sizeof(PENDING_ASSEMBLY_ITEM))) == NULL)
  803. return FALSE;
  804. pas->langid = langid;
  805. pas->hkl = pItem->hkl;
  806. pas->clsid = pItem->clsid;
  807. pas->guidProfile = pItem->guidProfile;
  808. pas->dwFlags = dwFlags;
  809. cc.fSync = FALSE;
  810. cc.pCatId = &pItem->catid;
  811. cc.langid = langid;
  812. cc.pfnPostCleanup = ActivateAssemblyItemPostCleanupCallback;
  813. cc.lPrivate = (LONG_PTR)pas;
  814. ptim->_CleanupContexts(&cc);
  815. return TRUE;
  816. }
  817. //+---------------------------------------------------------------------------
  818. //
  819. // SyncActivateAssemblyItem
  820. //
  821. //----------------------------------------------------------------------------
  822. BOOL SyncActivateAssemblyItem(SYSTHREAD *psfn, LANGID langid, ASSEMBLYITEM *pItem, DWORD dwFlags)
  823. {
  824. int i;
  825. int nCnt;
  826. BOOL fActivateFEIMEHKL = FALSE;
  827. BOOL fPrevActivateFEIMEHKL = FALSE;
  828. BOOL fCallLeaveAssembly = FALSE;
  829. BOOL fSkipActivate = FALSE;
  830. BOOL fSkipNotify = FALSE;
  831. BOOL fCiceroClient = FALSE;
  832. CThreadInputMgr *ptim;
  833. CAssembly *pAsm;
  834. CAssemblyList *pAsmList;
  835. HKL hNewKL = NULL;
  836. pAsmList = EnsureAssemblyList(psfn);
  837. if (!pAsmList)
  838. return FALSE;
  839. pAsm = pAsmList->FindAssemblyByLangId(langid);
  840. if (!pAsm)
  841. return FALSE;
  842. ptim = psfn->ptim;
  843. //
  844. // Check if we're in Cicero aware focus.
  845. //
  846. if (ptim && ptim->_GetFocusDocInputMgr())
  847. fCiceroClient = TRUE;
  848. if (IsEqualGUID(pItem->clsid, GUID_NULL))
  849. {
  850. if (IsPureIMEHKL(pItem->hkl))
  851. {
  852. fActivateFEIMEHKL = TRUE;
  853. }
  854. }
  855. else if (!fCiceroClient)
  856. {
  857. //
  858. // we should not activate TIPs in the focus is already changed to
  859. // non cicero aware DIM.
  860. //
  861. return TRUE;
  862. }
  863. if (psfn->plbim)
  864. {
  865. fCallLeaveAssembly = TRUE;
  866. psfn->plbim->EnterAssemblyChange();
  867. }
  868. #ifdef CHECKFEIMESELECTED
  869. if (pAsm->_fUnknownFEIMESelected)
  870. {
  871. pAsm->_fUnknownFEIMESelected = FALSE;
  872. fPrevActivateFEIMEHKL = TRUE;
  873. }
  874. #endif CHECKFEIMESELECTED
  875. //
  876. // deactivate all tip in the same category or diactivate all tips
  877. // when FE-IME is activated.
  878. //
  879. nCnt = pAsm->Count();
  880. for (i = 0; i < nCnt; i++)
  881. {
  882. ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
  883. if (!pItemTemp->fActive)
  884. continue;
  885. if (IsEqualGUID(pItem->catid, pItemTemp->catid))
  886. {
  887. if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  888. {
  889. if (ptim)
  890. {
  891. if (IsEqualGUID(pItemTemp->clsid, pItem->clsid))
  892. {
  893. if (IsEqualGUID(pItemTemp->guidProfile, pItem->guidProfile))
  894. fSkipNotify = TRUE;
  895. if (!fSkipNotify)
  896. ptim->NotifyActivateInputProcessor(pItemTemp->clsid, pItemTemp->guidProfile, FALSE);
  897. fSkipActivate = TRUE;
  898. }
  899. else
  900. ptim->ActivateInputProcessor(pItemTemp->clsid, pItemTemp->guidProfile, pItemTemp->hklSubstitute, FALSE);
  901. }
  902. }
  903. else
  904. {
  905. if (IsPureIMEHKL(pItemTemp->hkl))
  906. fPrevActivateFEIMEHKL = TRUE;
  907. if (ptim)
  908. ptim->NotifyActivateInputProcessor(pItemTemp->clsid,
  909. pItemTemp->guidProfile,
  910. FALSE);
  911. }
  912. pItemTemp->fActive = FALSE;
  913. }
  914. else if (fActivateFEIMEHKL)
  915. {
  916. //
  917. // FEIMEHKL will be activated so deactivate all tips.
  918. //
  919. if (ptim)
  920. {
  921. if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  922. ptim->ActivateInputProcessor(pItemTemp->clsid,
  923. pItemTemp->guidProfile,
  924. pItemTemp->hklSubstitute,
  925. FALSE);
  926. else
  927. ptim->NotifyActivateInputProcessor(pItemTemp->clsid,
  928. pItemTemp->guidProfile,
  929. FALSE);
  930. }
  931. }
  932. }
  933. pItem->fActive = TRUE;
  934. if (pItem->hkl && (pItem->hkl != GetKeyboardLayout(0)))
  935. {
  936. //
  937. // If we're not on Cicero aware focus,
  938. // we won't set AssemblyLangId here
  939. // but we post WM_INPUTLANGCHANGEREQUEST.
  940. //
  941. PostInputLangRequest(psfn, pItem->hkl, !fCiceroClient);
  942. hNewKL = pItem->hkl;
  943. }
  944. //
  945. // Update assembly reg before making notify.
  946. //
  947. pAsmList->SetDefaultTIPInAssemblyInternal(pAsm, pItem, dwFlags & AAIF_CHANGEDEFAULT);
  948. if (!fActivateFEIMEHKL)
  949. {
  950. if (ptim)
  951. {
  952. if (!fSkipNotify)
  953. {
  954. if (fSkipActivate || IsEqualGUID(pItem->clsid, GUID_NULL))
  955. ptim->NotifyActivateInputProcessor(pItem->clsid, pItem->guidProfile, TRUE);
  956. else
  957. ptim->ActivateInputProcessor(pItem->clsid, pItem->guidProfile, pItem->hklSubstitute, TRUE);
  958. }
  959. }
  960. //
  961. // if the previous activated item was FEIMEHKL,
  962. // restore all tips in the other categories.
  963. //
  964. if (fPrevActivateFEIMEHKL)
  965. {
  966. nCnt = pAsm->Count();
  967. for (i = 0; i < nCnt; i++)
  968. {
  969. ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
  970. if (!pItemTemp->fEnabled)
  971. continue;
  972. if (!pItemTemp->fActive)
  973. continue;
  974. if (ptim && !IsEqualGUID(pItem->catid, pItemTemp->catid))
  975. {
  976. ptim->ActivateInputProcessor(pItemTemp->clsid, pItemTemp->guidProfile, pItemTemp->hklSubstitute, TRUE);
  977. }
  978. }
  979. }
  980. }
  981. else
  982. {
  983. if (ptim)
  984. ptim->NotifyActivateInputProcessor(pItem->clsid,
  985. pItem->guidProfile,
  986. TRUE);
  987. }
  988. UpdateSystemLangBarItems(psfn, hNewKL, FALSE);
  989. if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
  990. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  991. return TRUE;
  992. }
  993. //+---------------------------------------------------------------------------
  994. //
  995. // SetFocusDIMForAssembly
  996. //
  997. //----------------------------------------------------------------------------
  998. BOOL SetFocusDIMForAssembly(BOOL fSetFocus)
  999. {
  1000. SYSTHREAD *psfn = GetSYSTHREAD();
  1001. CThreadInputMgr *ptim;
  1002. CAssembly *pAsm;
  1003. int nCnt;
  1004. int i;
  1005. HKL hNewKL = NULL;
  1006. BOOL fCallLeaveAssembly = FALSE;
  1007. if (!psfn)
  1008. {
  1009. Assert(0);
  1010. return FALSE;
  1011. }
  1012. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  1013. if (!ptim)
  1014. {
  1015. Assert(0);
  1016. return FALSE;
  1017. }
  1018. pAsm = GetCurrentAssembly(psfn);
  1019. if (!pAsm)
  1020. {
  1021. Assert(0);
  1022. return FALSE;
  1023. }
  1024. if (fSetFocus)
  1025. {
  1026. //
  1027. // If the substitute hKL is activated now, we move to Cicero mode
  1028. // completely.
  1029. //
  1030. HKL hKL = GetKeyboardLayout(0);
  1031. ActivateAssembly(LOWORD(hKL), ACTASM_NONE);
  1032. //
  1033. // make sure the substituing item will be activated.
  1034. // we need to use hKL that was before calling ActivateAssembly().
  1035. //
  1036. ASSEMBLYITEM *pItem = pAsm->GetSubstituteItem(hKL);
  1037. if (pItem)
  1038. {
  1039. if (!ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItem, 0))
  1040. return FALSE;
  1041. ptim->NotifyActivateInputProcessor(pItem->clsid,
  1042. pItem->guidProfile,
  1043. TRUE);
  1044. }
  1045. }
  1046. else
  1047. {
  1048. if (pAsm->IsEnabled(psfn))
  1049. {
  1050. //
  1051. // if the crruent active TIP has a substitute hKL, we activate it.
  1052. //
  1053. nCnt = pAsm->Count();
  1054. for (i = 0; i < nCnt; i++)
  1055. {
  1056. ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
  1057. Assert(!pItemTemp->hkl || (LOWORD((HKL)pItemTemp->hkl) == pAsm->GetLangId()));
  1058. if (!pItemTemp->fEnabled)
  1059. continue;
  1060. if (!pItemTemp->fActive)
  1061. continue;
  1062. if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
  1063. {
  1064. //
  1065. // we activate the substitute hkl.
  1066. //
  1067. if (pItemTemp->hklSubstitute)
  1068. {
  1069. PostInputLangRequest(psfn, pItemTemp->hklSubstitute, FALSE);
  1070. ptim->NotifyActivateInputProcessor(GUID_NULL,
  1071. GUID_NULL,
  1072. TRUE);
  1073. hNewKL = pItemTemp->hklSubstitute;
  1074. }
  1075. break;
  1076. }
  1077. }
  1078. }
  1079. else
  1080. {
  1081. #if 0
  1082. //
  1083. // If the current language does not have an Item can run
  1084. // under non-Cicero control, we need to swtich the languiage to
  1085. // system default input locale.
  1086. //
  1087. CAssembly *pAsmTemp;
  1088. CAssemblyList *pAsmList;
  1089. pAsmList = EnsureAssemblyList(psfn);
  1090. pAsmTemp = pAsmList->GetDefaultAssembly();
  1091. if (pAsmTemp)
  1092. ActivateAssembly(pAsmTemp->GetLangId(), ACTASM_NONE);
  1093. #endif
  1094. }
  1095. }
  1096. //
  1097. // Enter assembly change notification section.
  1098. // We delay the notificaiton untill LeaveAssemblyChange() is called.
  1099. //
  1100. if (psfn->plbim)
  1101. {
  1102. fCallLeaveAssembly = TRUE;
  1103. psfn->plbim->EnterAssemblyChange();
  1104. }
  1105. UpdateSystemLangBarItems(psfn, hNewKL, FALSE);
  1106. if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
  1107. psfn->plbim->_GetLBarItemCtrl()->_AsmListUpdated(FALSE);
  1108. if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
  1109. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  1110. return TRUE;
  1111. }
  1112. //+---------------------------------------------------------------------------
  1113. //
  1114. // GetKeyboardItemNum
  1115. //
  1116. //----------------------------------------------------------------------------
  1117. UINT GetKeyboardItemNum()
  1118. {
  1119. SYSTHREAD *psfn;
  1120. CThreadInputMgr *ptim;
  1121. CAssembly *pAsm;
  1122. int i;
  1123. psfn = GetSYSTHREAD();
  1124. if (psfn == NULL)
  1125. return 0;
  1126. pAsm = GetCurrentAssembly(psfn);
  1127. if (!pAsm)
  1128. return 0;
  1129. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  1130. if (ptim && ptim->_GetFocusDocInputMgr())
  1131. pAsm->RebuildSubstitutedHKLList();
  1132. else
  1133. pAsm->ClearSubstitutedHKLList();
  1134. int nCnt = 0;
  1135. for (i = 0; i < pAsm->Count(); i++)
  1136. {
  1137. ASSEMBLYITEM *pItemTemp;
  1138. pItemTemp = pAsm->GetItem(i);
  1139. if (!pItemTemp->fEnabled)
  1140. continue;
  1141. if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
  1142. {
  1143. if (!ptim || !ptim->_GetFocusDocInputMgr())
  1144. {
  1145. if (!IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  1146. continue;
  1147. }
  1148. if (IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  1149. {
  1150. if (pAsm->IsSubstitutedHKL(pItemTemp->hkl))
  1151. continue;
  1152. }
  1153. nCnt++;
  1154. }
  1155. }
  1156. return nCnt;
  1157. }
  1158. #ifdef CHECKFEIMESELECTED
  1159. //+---------------------------------------------------------------------------
  1160. //
  1161. // UnknownFEIMESelectedPostCleanupCallback
  1162. //
  1163. //----------------------------------------------------------------------------
  1164. void UnknownFEIMESelectedPostCleanupCallback(BOOL fAbort, LONG_PTR lPrivate)
  1165. {
  1166. SYSTHREAD *psfn;
  1167. LANGID langid = (LANGID)lPrivate;
  1168. if (fAbort)
  1169. return; // nothing to cleanup...
  1170. if (psfn = GetSYSTHREAD())
  1171. {
  1172. SyncUnknownFEIMESelected(psfn, langid);
  1173. }
  1174. }
  1175. //+---------------------------------------------------------------------------
  1176. //
  1177. // UnknownFEIMESelected
  1178. //
  1179. //----------------------------------------------------------------------------
  1180. BOOL UnknownFEIMESelected(LANGID langid)
  1181. {
  1182. CThreadInputMgr *ptim;
  1183. SYSTHREAD *psfn;
  1184. CLEANUPCONTEXT cc;
  1185. psfn = GetSYSTHREAD();
  1186. if (!psfn)
  1187. return FALSE;
  1188. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  1189. if (ptim == NULL)
  1190. return TRUE;
  1191. cc.fSync = FALSE;
  1192. cc.pCatId = NULL;
  1193. cc.langid = langid;
  1194. cc.pfnPostCleanup = UnknownFEIMESelectedPostCleanupCallback;
  1195. cc.lPrivate = langid;
  1196. ptim->_CleanupContexts(&cc);
  1197. return TRUE;
  1198. }
  1199. //+---------------------------------------------------------------------------
  1200. //
  1201. // SyncUnknownFEIMESelected
  1202. //
  1203. //----------------------------------------------------------------------------
  1204. BOOL SyncUnknownFEIMESelected(SYSTHREAD *psfn, LANGID langid)
  1205. {
  1206. int i;
  1207. int nCnt;
  1208. // BOOL fActivateFEIMEHKL = FALSE;
  1209. // BOOL fPrevActivateFEIMEHKL = FALSE;
  1210. BOOL fCallLeaveAssembly = FALSE;
  1211. // BOOL fSkipActivate = FALSE;
  1212. // BOOL fSkipNotify = FALSE;
  1213. // BOOL fCiceroClient = FALSE;
  1214. CThreadInputMgr *ptim;
  1215. CAssembly *pAsm;
  1216. CAssemblyList *pAsmList;
  1217. pAsmList = EnsureAssemblyList(psfn);
  1218. if (!pAsmList)
  1219. return FALSE;
  1220. pAsm = pAsmList->FindAssemblyByLangId(langid);
  1221. if (!pAsm)
  1222. return FALSE;
  1223. ptim = psfn->ptim;
  1224. if (psfn->plbim)
  1225. {
  1226. fCallLeaveAssembly = TRUE;
  1227. psfn->plbim->EnterAssemblyChange();
  1228. }
  1229. pAsm->_fUnknownFEIMESelected = TRUE;
  1230. //
  1231. // deactivate all tip in the same category or diactivate all tips
  1232. // when FE-IME is activated.
  1233. //
  1234. nCnt = pAsm->Count();
  1235. for (i = 0; i < nCnt; i++)
  1236. {
  1237. ASSEMBLYITEM *pItemTemp = pAsm->GetItem(i);
  1238. if (!pItemTemp->fActive)
  1239. continue;
  1240. //
  1241. // FEIMEHKL will be activated so deactivate all tips.
  1242. //
  1243. if (ptim && !IsEqualGUID(pItemTemp->clsid, GUID_NULL))
  1244. ptim->ActivateInputProcessor(pItemTemp->clsid,
  1245. pItemTemp->guidProfile,
  1246. pItemTemp->hklSubstitute,
  1247. FALSE);
  1248. if (IsEqualGUID(pItemTemp->catid, GUID_TFCAT_TIP_KEYBOARD))
  1249. pItemTemp->fActive = FALSE;
  1250. }
  1251. UpdateSystemLangBarItems(psfn, NULL, FALSE);
  1252. if (psfn->plbim && psfn->plbim->_GetLBarItemCtrl())
  1253. psfn->plbim->_GetLBarItemCtrl()->_AsmListUpdated(FALSE);
  1254. if (fCallLeaveAssembly && (psfn->plbim->LeaveAssemblyChange()))
  1255. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  1256. return TRUE;
  1257. }
  1258. #endif CHECKFEIMESELECTED
  1259. //////////////////////////////////////////////////////////////////////////////
  1260. //
  1261. // CEnumLanguageProfiles
  1262. //
  1263. //////////////////////////////////////////////////////////////////////////////
  1264. //+---------------------------------------------------------------------------
  1265. //
  1266. // ctor
  1267. //
  1268. //----------------------------------------------------------------------------
  1269. CEnumLanguageProfiles::CEnumLanguageProfiles()
  1270. {
  1271. _langid = 0;
  1272. _iCur = 0;
  1273. }
  1274. //+---------------------------------------------------------------------------
  1275. //
  1276. // dtor
  1277. //
  1278. //----------------------------------------------------------------------------
  1279. CEnumLanguageProfiles::~CEnumLanguageProfiles()
  1280. {
  1281. }
  1282. //+---------------------------------------------------------------------------
  1283. //
  1284. // Init
  1285. //
  1286. // !!!WARNING WARNING WARNING!!!
  1287. //
  1288. // LanguageProfile enumrator is not focus DIM sensitive. Some caller
  1289. // want to know which TIP will be activated if the focus is moved to
  1290. // Cicero aware (or AIMM12).
  1291. // Don't check the current focus or patch fActive flag.
  1292. //
  1293. //----------------------------------------------------------------------------
  1294. BOOL CEnumLanguageProfiles::Init(LANGID langid)
  1295. {
  1296. CAssemblyList *pAsmList;
  1297. int nCntAsm;
  1298. int i;
  1299. SYSTHREAD *psfn = GetSYSTHREAD();
  1300. if (psfn == NULL)
  1301. return FALSE;
  1302. pAsmList = EnsureAssemblyList(psfn);
  1303. if (pAsmList == NULL)
  1304. return FALSE;
  1305. nCntAsm = pAsmList->Count();
  1306. if (!nCntAsm)
  1307. return FALSE;
  1308. for (i = 0;i < nCntAsm; i++)
  1309. {
  1310. CAssembly *pAsm = pAsmList->GetAssembly(i);
  1311. if (!pAsm)
  1312. continue;
  1313. if (!langid || langid == pAsm->GetLangId())
  1314. {
  1315. int j;
  1316. int nCntList = pAsm->Count();
  1317. BOOL fActivateFEIMEHKLOnCic = pAsm->IsFEIMEActive();
  1318. for (j = 0; j < nCntList; j++)
  1319. {
  1320. ASSEMBLYITEM *pItem;
  1321. TF_LANGUAGEPROFILE *pprofile;
  1322. pItem = pAsm->GetItem(j);
  1323. if (!pItem)
  1324. continue;
  1325. if (IsEqualCLSID(pItem->clsid, GUID_NULL))
  1326. continue;
  1327. pprofile = _rgProfiles.Append(1);
  1328. if (!pprofile)
  1329. continue;
  1330. pprofile->clsid = pItem->clsid;
  1331. pprofile->langid = pAsm->GetLangId();
  1332. pprofile->guidProfile = pItem->guidProfile;
  1333. pprofile->catid = pItem->catid;
  1334. if (fActivateFEIMEHKLOnCic)
  1335. pprofile->fActive = FALSE;
  1336. else
  1337. {
  1338. //
  1339. // we need to return TRUE even if the current focus is
  1340. // not Cicero aware as above comments.
  1341. //
  1342. pprofile->fActive = pItem->fActive;
  1343. }
  1344. }
  1345. }
  1346. }
  1347. _langid = langid;
  1348. return _rgProfiles.Count() ? TRUE : FALSE;
  1349. }
  1350. //+---------------------------------------------------------------------------
  1351. //
  1352. // Clone
  1353. //
  1354. //----------------------------------------------------------------------------
  1355. STDAPI CEnumLanguageProfiles::Clone(IEnumTfLanguageProfiles **ppEnum)
  1356. {
  1357. CEnumLanguageProfiles *pEnum = NULL;
  1358. if (!ppEnum)
  1359. return E_INVALIDARG;
  1360. *ppEnum = NULL;
  1361. pEnum = new CEnumLanguageProfiles();
  1362. if (!pEnum)
  1363. return E_OUTOFMEMORY;
  1364. if (!pEnum->Init(_langid))
  1365. {
  1366. pEnum->Release();
  1367. return E_FAIL;
  1368. }
  1369. *ppEnum = pEnum;
  1370. return S_OK;
  1371. }
  1372. //+---------------------------------------------------------------------------
  1373. //
  1374. // Next
  1375. //
  1376. //----------------------------------------------------------------------------
  1377. STDAPI CEnumLanguageProfiles::Next(ULONG ulCount, TF_LANGUAGEPROFILE *rgLanguageProfiles, ULONG *pcFetched)
  1378. {
  1379. ULONG cFetched;
  1380. if (pcFetched == NULL)
  1381. {
  1382. pcFetched = &cFetched;
  1383. }
  1384. *pcFetched = 0;
  1385. while (_iCur < _rgProfiles.Count() && *pcFetched < ulCount)
  1386. {
  1387. TF_LANGUAGEPROFILE *pprofile;
  1388. pprofile = _rgProfiles.GetPtr(_iCur);
  1389. *rgLanguageProfiles = *pprofile;
  1390. rgLanguageProfiles++;
  1391. *pcFetched = *pcFetched + 1;
  1392. _iCur++;
  1393. }
  1394. return *pcFetched == ulCount ? S_OK : S_FALSE;
  1395. }
  1396. //+---------------------------------------------------------------------------
  1397. //
  1398. // Reset
  1399. //
  1400. //----------------------------------------------------------------------------
  1401. STDAPI CEnumLanguageProfiles::Reset()
  1402. {
  1403. _iCur = 0;
  1404. return S_OK;
  1405. }
  1406. //+---------------------------------------------------------------------------
  1407. //
  1408. // Skip
  1409. //
  1410. //----------------------------------------------------------------------------
  1411. STDAPI CEnumLanguageProfiles::Skip(ULONG ulCount)
  1412. {
  1413. _iCur += ulCount;
  1414. return (_iCur > _rgProfiles.Count()) ? S_FALSE : S_OK;
  1415. }
  1416. //////////////////////////////////////////////////////////////////////////////
  1417. //
  1418. // CInputProcessorProfiles
  1419. //
  1420. //////////////////////////////////////////////////////////////////////////////
  1421. //+---------------------------------------------------------------------------
  1422. //
  1423. // GetLanguageList
  1424. //
  1425. // This function is not TIM sensitive.
  1426. //
  1427. //----------------------------------------------------------------------------
  1428. STDAPI CInputProcessorProfiles::GetLanguageList(LANGID **ppLangId, ULONG *pulCount)
  1429. {
  1430. CAssemblyList *pAsmList;
  1431. int i;
  1432. SYSTHREAD *psfn = GetSYSTHREAD();
  1433. if (pulCount != NULL)
  1434. {
  1435. *pulCount = 0;
  1436. }
  1437. if (ppLangId != NULL)
  1438. {
  1439. *ppLangId = NULL;
  1440. }
  1441. if (!pulCount)
  1442. return E_INVALIDARG;
  1443. if (!ppLangId)
  1444. return E_INVALIDARG;
  1445. if (psfn == NULL)
  1446. return E_FAIL;
  1447. pAsmList = EnsureAssemblyList(psfn);
  1448. if (!pAsmList)
  1449. return E_FAIL;
  1450. if (!pAsmList->Count())
  1451. return S_OK;
  1452. *ppLangId = (LANGID *)CoTaskMemAlloc(sizeof(LANGID) * pAsmList->Count());
  1453. if (!*ppLangId)
  1454. {
  1455. *pulCount = 0;
  1456. return E_OUTOFMEMORY;
  1457. }
  1458. for (i = 0;i < pAsmList->Count(); i++)
  1459. {
  1460. CAssembly *pAsm = pAsmList->GetAssembly(i);
  1461. //
  1462. // At least one keyboard Item must be enabled to be in the list.
  1463. //
  1464. if (pAsm->IsEnabledKeyboardItem(psfn))
  1465. {
  1466. (*ppLangId)[*pulCount] = pAsm->GetLangId();
  1467. (*pulCount)++;
  1468. }
  1469. }
  1470. return S_OK;
  1471. }
  1472. //+---------------------------------------------------------------------------
  1473. //
  1474. // EnumLanguageProfiles
  1475. //
  1476. //----------------------------------------------------------------------------
  1477. STDAPI CInputProcessorProfiles::EnumLanguageProfiles(LANGID langid, IEnumTfLanguageProfiles **ppEnum)
  1478. {
  1479. CEnumLanguageProfiles *pEnum;
  1480. if (!ppEnum)
  1481. return E_INVALIDARG;
  1482. *ppEnum = NULL;
  1483. pEnum = new CEnumLanguageProfiles();
  1484. if (!pEnum)
  1485. return E_OUTOFMEMORY;
  1486. if (!pEnum->Init(langid))
  1487. {
  1488. pEnum->Release();
  1489. return E_FAIL;
  1490. }
  1491. *ppEnum = pEnum;
  1492. return S_OK;
  1493. }
  1494. //+---------------------------------------------------------------------------
  1495. //
  1496. // ActivateLanguageProfile
  1497. //
  1498. //----------------------------------------------------------------------------
  1499. STDAPI CInputProcessorProfiles::ActivateLanguageProfile(REFCLSID rclsid, LANGID langid, REFGUID guidProfile)
  1500. {
  1501. CThreadInputMgr *ptim;
  1502. CAssemblyList *pAsmList;
  1503. CAssembly *pAsm;
  1504. SYSTHREAD *psfn;
  1505. BOOL fFound = FALSE;
  1506. BOOL fNoCategory = FALSE;
  1507. GUID catid;
  1508. BOOL fSkipActivate = FALSE;
  1509. if (!langid)
  1510. return E_INVALIDARG;
  1511. psfn = GetSYSTHREAD();
  1512. if (!psfn)
  1513. return E_FAIL;
  1514. if (!(ptim = psfn->ptim))
  1515. return E_UNEXPECTED;
  1516. if (langid != GetCurrentAssemblyLangId(psfn))
  1517. return E_INVALIDARG;
  1518. pAsmList = EnsureAssemblyList(psfn);
  1519. if (!pAsmList)
  1520. return E_OUTOFMEMORY;
  1521. pAsm = pAsmList->FindAssemblyByLangId(langid);
  1522. if (!pAsm)
  1523. return E_FAIL;
  1524. fNoCategory = MyGetTIPCategory(rclsid, &catid) ? FALSE : TRUE;
  1525. int nCntList = pAsm->Count();
  1526. int i;
  1527. ASSEMBLYITEM *pItemActivate = NULL;
  1528. for (i = 0; i < nCntList; i++)
  1529. {
  1530. ASSEMBLYITEM *pItem;
  1531. pItem = pAsm->GetItem(i);
  1532. if (!pItem->fEnabled)
  1533. continue;
  1534. if (fNoCategory || IsEqualGUID(catid, pItem->catid))
  1535. {
  1536. if (IsEqualGUID(pItem->guidProfile, guidProfile) &&
  1537. IsEqualGUID(rclsid, pItem->clsid))
  1538. {
  1539. if (pItem->fActive)
  1540. {
  1541. fSkipActivate = TRUE;
  1542. }
  1543. pItemActivate = pItem;
  1544. break;
  1545. }
  1546. }
  1547. }
  1548. //
  1549. // we could not find the given profile in the assembly.
  1550. //
  1551. if (!pItemActivate)
  1552. return E_INVALIDARG;
  1553. if (fSkipActivate)
  1554. {
  1555. //
  1556. // the clsid is now activated. We skip to call activate
  1557. // but make a notification.
  1558. //
  1559. ptim->NotifyActivateInputProcessor(pItemActivate->clsid, pItemActivate->guidProfile, FALSE);
  1560. for (i = 0; i < nCntList; i++)
  1561. {
  1562. ASSEMBLYITEM *pItem;
  1563. pItem = pAsm->GetItem(i);
  1564. if (!pItem->fEnabled)
  1565. continue;
  1566. if (!pItem->fActive)
  1567. continue;
  1568. if (!fNoCategory && !IsEqualGUID(catid, pItem->catid))
  1569. continue;
  1570. if (IsEqualGUID(rclsid, pItem->clsid))
  1571. {
  1572. pItem->fActive = FALSE;
  1573. }
  1574. }
  1575. pAsmList->SetDefaultTIPInAssemblyInternal(pAsm, pItemActivate, TRUE);
  1576. pItemActivate->fActive = TRUE;
  1577. ptim->NotifyActivateInputProcessor(pItemActivate->clsid, pItemActivate->guidProfile, TRUE);
  1578. UpdateSystemLangBarItems(psfn, NULL, FALSE);
  1579. MakeSetFocusNotify(g_msgThreadItemChange, 0, (LPARAM)GetCurrentThreadId());
  1580. }
  1581. else if (!pItemActivate->fActive)
  1582. {
  1583. if (!IsEqualGUID(pItemActivate->clsid, GUID_NULL) &&
  1584. !ptim->_GetFocusDocInputMgr())
  1585. {
  1586. //
  1587. // We don't want to support this. It is better to return ERROR.
  1588. // However TIP and Apps may want to call this method
  1589. // on Non-Cicero aware control such as DialogBox.
  1590. //
  1591. pAsmList->SetDefaultTIPInAssemblyInternal(pAsm, pItemActivate, TRUE);
  1592. ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItemActivate, AAIF_CHANGEDEFAULT);
  1593. if (IsEqualGUID(pItemActivate->catid, GUID_TFCAT_TIP_KEYBOARD))
  1594. {
  1595. pItemActivate->fActive = TRUE;
  1596. SetFocusDIMForAssembly(FALSE);
  1597. }
  1598. }
  1599. else
  1600. {
  1601. ActivateAssemblyItem(psfn, pAsm->GetLangId(), pItemActivate, AAIF_CHANGEDEFAULT);
  1602. }
  1603. }
  1604. return S_OK;
  1605. }
  1606. //+---------------------------------------------------------------------------
  1607. //
  1608. // GetActiveLanguageProfile
  1609. //
  1610. // WARNING!!!
  1611. //
  1612. // Which GetActiveLanguageProfile() or GetDefaultLanguageProfile() should
  1613. // we use?
  1614. //
  1615. // This function is FocusDIM sensetive. So we can call any function
  1616. // to check TIM or FocusDIM.
  1617. //
  1618. // If you don't want to care about TIM and FocusDIM, try
  1619. // GetDefaultLanguageProfile.
  1620. //
  1621. // if clsid is TIP's category ID, this returns the activated profiles in the
  1622. // category.
  1623. //
  1624. //----------------------------------------------------------------------------
  1625. STDAPI CInputProcessorProfiles::GetActiveLanguageProfile(REFCLSID clsid, LANGID *plangid, GUID *pguid)
  1626. {
  1627. CThreadInputMgr *ptim;
  1628. CAssemblyList *pAsmList;
  1629. CAssembly *pAsm;
  1630. SYSTHREAD *psfn;
  1631. LANGID langid;
  1632. BOOL fFound = FALSE;
  1633. if (!plangid)
  1634. return E_INVALIDARG;
  1635. if (!pguid)
  1636. return E_INVALIDARG;
  1637. *plangid = 0;
  1638. *pguid = GUID_NULL;
  1639. psfn = GetSYSTHREAD();
  1640. if (!psfn)
  1641. return E_FAIL;
  1642. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  1643. if (!ptim || !ptim->_GetFocusDocInputMgr())
  1644. {
  1645. //
  1646. // Special Service!
  1647. //
  1648. // GetActiveLanguageProfile(GUID_TFCAT_TIP_KEYBOARD) works
  1649. // without TIM, it can returns, the current keyboard layout.
  1650. //
  1651. if (IsEqualGUID(clsid, GUID_TFCAT_TIP_KEYBOARD))
  1652. {
  1653. HKL hkl;
  1654. if (psfn->hklBeingActivated)
  1655. hkl = psfn->hklBeingActivated;
  1656. else
  1657. hkl = GetKeyboardLayout(0);
  1658. *plangid = LOWORD((DWORD)(UINT_PTR)hkl);
  1659. *((DWORD *)pguid) = (DWORD)(UINT_PTR)hkl;
  1660. return S_OK;
  1661. }
  1662. return E_UNEXPECTED;
  1663. }
  1664. langid = GetCurrentAssemblyLangId(psfn);
  1665. pAsmList = EnsureAssemblyList(psfn);
  1666. if (!pAsmList)
  1667. return E_OUTOFMEMORY;
  1668. pAsm = pAsmList->FindAssemblyByLangId(langid);
  1669. if (!pAsm)
  1670. return E_FAIL;
  1671. int nCntList = pAsm->Count();
  1672. int i;
  1673. for (i = 0; i < nCntList; i++)
  1674. {
  1675. ASSEMBLYITEM *pItem;
  1676. pItem = pAsm->GetItem(i);
  1677. if (!pItem->fEnabled)
  1678. continue;
  1679. if (pItem->fActive)
  1680. {
  1681. if (IsEqualGUID(clsid, pItem->catid) ||
  1682. IsEqualGUID(clsid, pItem->clsid))
  1683. {
  1684. fFound = TRUE;
  1685. *plangid = langid;
  1686. if (!IsEqualCLSID(pItem->clsid, CLSID_NULL))
  1687. *pguid = pItem->guidProfile;
  1688. else
  1689. *((DWORD *)pguid) = (DWORD)(UINT_PTR)(HKL)(pItem->hkl);
  1690. }
  1691. }
  1692. }
  1693. return fFound ? S_OK : S_FALSE;
  1694. }
  1695. //+---------------------------------------------------------------------------
  1696. //
  1697. // GetCurrentLanguage
  1698. //
  1699. //----------------------------------------------------------------------------
  1700. STDAPI CInputProcessorProfiles::GetCurrentLanguage(LANGID *plangid)
  1701. {
  1702. if (!plangid)
  1703. return E_INVALIDARG;
  1704. *plangid = GetCurrentAssemblyLangId(NULL);
  1705. return S_OK;
  1706. }
  1707. //+---------------------------------------------------------------------------
  1708. //
  1709. // ChangeCurrentLanguage
  1710. //
  1711. //----------------------------------------------------------------------------
  1712. STDAPI CInputProcessorProfiles::ChangeCurrentLanguage(LANGID langid)
  1713. {
  1714. CAssemblyList *pAsmList;
  1715. CAssembly *pAsm;
  1716. SYSTHREAD *psfn;
  1717. if (CThreadInputMgr::_GetThis() == NULL)
  1718. return E_UNEXPECTED;
  1719. psfn = GetSYSTHREAD();
  1720. if (!psfn)
  1721. return E_FAIL;
  1722. if (langid == GetCurrentAssemblyLangId(psfn))
  1723. return S_OK;
  1724. pAsmList = EnsureAssemblyList(psfn);
  1725. if (!pAsmList)
  1726. return E_OUTOFMEMORY;
  1727. pAsm = pAsmList->FindAssemblyByLangId(langid);
  1728. if (!pAsm)
  1729. return E_INVALIDARG;
  1730. return ActivateAssembly(pAsm->GetLangId(), ACTASM_NONE) ? S_OK : E_FAIL;
  1731. }
  1732. //+---------------------------------------------------------------------------
  1733. //
  1734. // AdviseSink
  1735. //
  1736. //----------------------------------------------------------------------------
  1737. STDAPI CInputProcessorProfiles::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
  1738. {
  1739. const IID *rgiid = &IID_ITfLanguageProfileNotifySink;
  1740. return GenericAdviseSink(riid, punk, &rgiid, &_rgNotifySinks, 1, pdwCookie);
  1741. }
  1742. //+---------------------------------------------------------------------------
  1743. //
  1744. // UnadviseSink
  1745. //
  1746. //----------------------------------------------------------------------------
  1747. STDAPI CInputProcessorProfiles::UnadviseSink(DWORD dwCookie)
  1748. {
  1749. return GenericUnadviseSink(&_rgNotifySinks, 1, dwCookie);
  1750. }
  1751. //+---------------------------------------------------------------------------
  1752. //
  1753. // _OnLanguageChange
  1754. //
  1755. //----------------------------------------------------------------------------
  1756. BOOL CInputProcessorProfiles::_OnLanguageChange(BOOL fChanged, LANGID langid)
  1757. {
  1758. int i;
  1759. for (i = 0; i < _rgNotifySinks.Count(); i++)
  1760. {
  1761. HRESULT hr;
  1762. if (!fChanged)
  1763. {
  1764. BOOL fAccept;
  1765. hr = ((ITfLanguageProfileNotifySink *)_rgNotifySinks.GetPtr(i)->pSink)->OnLanguageChange(langid, &fAccept);
  1766. if (SUCCEEDED(hr) && !fAccept)
  1767. return FALSE;
  1768. }
  1769. else
  1770. {
  1771. ((ITfLanguageProfileNotifySink *)_rgNotifySinks.GetPtr(i)->pSink)->OnLanguageChanged();
  1772. }
  1773. }
  1774. return TRUE;
  1775. }