Source code of Windows XP (NT5)
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.

4594 lines
91 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module CUIM.CPP -- Cicero Implementation
  5. *
  6. * Most everything to do with Cicero handling.
  7. *
  8. * Original Author: <nl>
  9. * Hon Wah Chan
  10. *
  11. * History: <nl>
  12. * 11/16/1999 honwch
  13. *
  14. * Copyright (c) 1995-2001, Microsoft Corporation. All rights reserved.
  15. */
  16. #include "_common.h"
  17. #ifndef NOFEPROCESSING
  18. #ifndef NOPRIVATEMESSAGE
  19. #include "_MSREMSG.H"
  20. #endif
  21. #include "_array.h"
  22. #include "msctf.h"
  23. #include "textstor.h"
  24. #include "ctffunc.h"
  25. #include "msctf_g.c"
  26. #include "msctf_i.c"
  27. #include "textstor_i.c"
  28. #include "ctffunc_i.c"
  29. #include "msctfp.h"
  30. #include "msctfp_g.c"
  31. #include "textserv.h"
  32. #include "_cmsgflt.h"
  33. #include "_ime.h"
  34. #include "_cuim.h"
  35. const IID IID_ITfContextRenderingMarkup = {
  36. 0xa305b1c0,
  37. 0xc776,
  38. 0x4523,
  39. {0xbd, 0xa0, 0x7c, 0x5a, 0x2e, 0x0f, 0xef, 0x10}
  40. };
  41. const IID IID_ITfEnableService = {
  42. 0x3035d250,
  43. 0x43b4,
  44. 0x4253,
  45. {0x81, 0xe6, 0xea, 0x87, 0xfd, 0x3e, 0xed, 0x43}
  46. };
  47. const IID IID_IServiceProvider = {
  48. 0x6d5140c1,
  49. 0x7436,
  50. 0x11ce,
  51. {0x80, 0x34, 0x00, 0xaa, 0x00, 0x60, 0x09, 0xfa}
  52. };
  53. // {35D46968-01FF-4cd8-A379-9A87C9CC789F}
  54. const GUID CLSID_MSFTEDIT = {
  55. 0x35d46968,
  56. 0x01ff,
  57. 0x4cd8,
  58. {0xa3,0x79,0x9a,0x87, 0xc9,0xcc,0x78,0x9f}
  59. };
  60. #define CONNECT_E_NOCONNECTION MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0200) // from OLECTL.H
  61. #undef DEFINE_GUID
  62. #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  63. const GUID name \
  64. = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  65. #include "dcattrs.h"
  66. const TS_ATTRID *_arTSAttridSupported[] =
  67. {
  68. &DCATTRID_Font_FaceName, // iattrFacename
  69. &DCATTRID_Font_SizePts, // iattrSize
  70. &DCATTRID_Font_Style_Color, // iattrColor
  71. &DCATTRID_Font_Style_Bold, // iattrBold
  72. &DCATTRID_Font_Style_Italic, // iattrItalic
  73. &DCATTRID_Font_Style_Underline, // iattrUnderline
  74. &DCATTRID_Font_Style_Subscript, // iattrSubscript
  75. &DCATTRID_Font_Style_Superscript, // iattrSuperscript
  76. &DCATTRID_Text_RightToLeft, // iattrRTL
  77. &DCATTRID_Text_VerticalWriting, // iattrVertical
  78. &GUID_PROP_MODEBIAS, // iattrBias
  79. &DCATTRID_Text_Orientation, // iattrTxtOrient
  80. };
  81. enum IATTR_INDEX
  82. {
  83. iattrFacename = 0,
  84. iattrSize,
  85. iattrColor,
  86. iattrBold,
  87. iattrItalic,
  88. iattrUnderline,
  89. iattrSubscript,
  90. iattrSuperscript,
  91. iattrRTL,
  92. iattrVertical,
  93. iattrBias,
  94. iattrTxtOrient,
  95. MAX_ATTR_SUPPORT
  96. };
  97. /* GUID_NULL */
  98. const GUID GUID_NULL = {
  99. 0x00000000,
  100. 0x0000,
  101. 0x0000,
  102. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  103. };
  104. const GUID GUID_DCSERVICE_DATAOBJECT = {
  105. 0x6086fbb5,
  106. 0xe225,
  107. 0x46ce,
  108. {0xa7, 0x70, 0xc1, 0xbb, 0xd3, 0xe0, 0x5d, 0x7b}
  109. };
  110. const GUID GUID_DCSERVICE_ACCESSIBLE = {
  111. 0xf9786200,
  112. 0xa5bf,
  113. 0x4a0f,
  114. {0x8c, 0x24, 0xfb, 0x16, 0xf5, 0xd1, 0xaa, 0xbb}
  115. };
  116. const GUID GUID_DCSERVICE_ACTIVEX = {
  117. 0xea937a50,
  118. 0xc9a6,
  119. 0x4b7d,
  120. {0x89, 0x4a, 0x49, 0xd9, 0x9b, 0x78, 0x48, 0x34}
  121. };
  122. // This array need to match the definition for EM_SETCTFMODEBIAS
  123. const GUID *_arModeBiasSupported[] =
  124. {
  125. &GUID_MODEBIAS_NONE,
  126. &GUID_MODEBIAS_FILENAME,
  127. &GUID_MODEBIAS_NAME,
  128. &GUID_MODEBIAS_READING,
  129. &GUID_MODEBIAS_DATETIME,
  130. &GUID_MODEBIAS_CONVERSATION,
  131. &GUID_MODEBIAS_NUMERIC,
  132. &GUID_MODEBIAS_HIRAGANA,
  133. &GUID_MODEBIAS_KATAKANA,
  134. &GUID_MODEBIAS_HANGUL,
  135. &GUID_MODEBIAS_HALFWIDTHKATAKANA,
  136. &GUID_MODEBIAS_FULLWIDTHALPHANUMERIC,
  137. &GUID_MODEBIAS_HALFWIDTHALPHANUMERIC,
  138. };
  139. /*
  140. * CUIM::CUIM ()
  141. *
  142. * @mfunc
  143. *
  144. *
  145. * @rdesc
  146. *
  147. *
  148. */
  149. CUIM::CUIM(CTextMsgFilter *pTextMsgFilter)
  150. {
  151. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::CUIM");
  152. _crefs = 1;
  153. _pTextMsgFilter = pTextMsgFilter;
  154. };
  155. /*
  156. * CUIM::~CUIM ()
  157. *
  158. * @mfunc
  159. *
  160. *
  161. * @rdesc
  162. *
  163. *
  164. */
  165. CUIM::~CUIM()
  166. {
  167. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::~CUIM");
  168. Uninit();
  169. }
  170. /*
  171. * STDMETHODIMP CUIM::QueryInterface (riid, ppv)
  172. *
  173. * @mfunc
  174. * IUnknown QueryInterface support
  175. *
  176. * @rdesc
  177. * NOERROR if interface supported
  178. *
  179. */
  180. STDMETHODIMP CUIM::QueryInterface (REFIID riid, void ** ppv)
  181. {
  182. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::QueryInterface");
  183. if( IsEqualIID(riid, IID_IUnknown) ||
  184. IsEqualIID(riid, IID_ITextStoreACP) )
  185. *ppv = (ITextStoreACP *)this;
  186. else if(IsEqualIID(riid, IID_ITfContextOwnerCompositionSink) )
  187. *ppv = (ITfContextOwnerCompositionSink *)this;
  188. else if (IsEqualIID(riid, IID_ITfMouseTrackerACP))
  189. *ppv = (ITfMouseTrackerACP *)this;
  190. else if (IsEqualIID(riid, IID_ITfEnableService))
  191. *ppv = (ITfEnableService *)this;
  192. else if (IsEqualIID(riid, IID_IServiceProvider))
  193. *ppv = (IServiceProvider *)this;
  194. else
  195. {
  196. *ppv = NULL;
  197. return E_NOINTERFACE;
  198. }
  199. AddRef();
  200. return NOERROR;
  201. }
  202. /*
  203. * STDMETHODIMP_(ULONG) CUIM::AddRef
  204. *
  205. * @mfunc
  206. * IUnknown AddRef support
  207. *
  208. * @rdesc
  209. * Reference count
  210. */
  211. STDMETHODIMP_(ULONG) CUIM::AddRef()
  212. {
  213. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::AddRef");
  214. return ++_crefs;
  215. }
  216. /*
  217. * STDMETHODIMP_(ULONG) CUIM::Release()
  218. *
  219. * @mfunc
  220. * IUnknown Release support - delete object when reference count is 0
  221. *
  222. * @rdesc
  223. * Reference count
  224. */
  225. STDMETHODIMP_(ULONG) CUIM::Release()
  226. {
  227. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::Release");
  228. _crefs--;
  229. if( _crefs == 0 )
  230. {
  231. delete this;
  232. return 0;
  233. }
  234. return _crefs;
  235. }
  236. /*
  237. * STDMETHODIMP CUIM::AdviseSink()
  238. *
  239. * @mfunc
  240. *
  241. *
  242. * @rdesc
  243. *
  244. */
  245. STDMETHODIMP CUIM::AdviseSink(
  246. REFIID riid,
  247. IUnknown *punk,
  248. DWORD dwMask)
  249. {
  250. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::AdviseSink");
  251. HRESULT hr = E_FAIL;
  252. if (_fShutDown)
  253. return E_UNEXPECTED;
  254. Assert(_ptss == NULL);
  255. if(IsEqualIID(riid, IID_ITextStoreACPSink))
  256. hr = punk->QueryInterface(riid, (void **)&_ptss);
  257. return hr == S_OK ? S_OK : E_UNEXPECTED;
  258. }
  259. /*
  260. * STDMETHODIMP CUIM::UnadviseSink()
  261. *
  262. * @mfunc
  263. *
  264. *
  265. * @rdesc
  266. *
  267. */
  268. STDMETHODIMP CUIM::UnadviseSink(IUnknown *punk)
  269. {
  270. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::UnadviseSink");
  271. Assert(_ptss == punk); // we're dealing with cicero, this should always hold
  272. _ptss->Release();
  273. _ptss = NULL;
  274. return S_OK;
  275. }
  276. /*
  277. * STDMETHODIMP CUIM::RequestLock()
  278. *
  279. * @mfunc
  280. *
  281. *
  282. * @rdesc
  283. *
  284. */
  285. STDMETHODIMP CUIM::RequestLock(
  286. DWORD dwLockFlags,
  287. HRESULT *phrSession)
  288. {
  289. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::RequestLock");
  290. if (!phrSession)
  291. return E_POINTER;
  292. if (_fShutDown)
  293. {
  294. *phrSession = TS_E_SYNCHRONOUS;
  295. return S_OK;
  296. }
  297. Assert(_ptss);
  298. if (_cCallMgrLevels && !_fAllowUIMLock || // Check if we are ready to grant locks
  299. _fReadLockOn || _fWriteLockOn) // We don't allow re-entrance either.
  300. {
  301. // No lock allow
  302. if (dwLockFlags & TS_LF_SYNC)
  303. *phrSession = TS_E_SYNCHRONOUS;
  304. else
  305. {
  306. if (dwLockFlags & TS_LF_READ)
  307. _fReadLockPending = 1;
  308. if ((dwLockFlags & TS_LF_READWRITE) == TS_LF_READWRITE)
  309. _fWriteLockPending = 1;
  310. *phrSession = TS_S_ASYNC;
  311. }
  312. return S_OK;
  313. }
  314. IUnknown *pIUnknown = NULL;
  315. HRESULT hResult = _pTextMsgFilter->_pTextDoc->GetCallManager(&pIUnknown);
  316. if ((dwLockFlags & TS_LF_READWRITE) == TS_LF_READWRITE)
  317. {
  318. _fReadLockPending = 0;
  319. _fWriteLockPending = 0;
  320. _fReadLockOn = 1;
  321. _fWriteLockOn = 1;
  322. }
  323. else if ((dwLockFlags & TS_LF_READ) == TS_LF_READ)
  324. {
  325. _fReadLockPending = 0;
  326. _fReadLockOn = 1;
  327. }
  328. if (_fWriteLockOn)
  329. {
  330. if (W32->IsFECodePage(_pTextMsgFilter->_uKeyBoardCodePage))
  331. _pTextMsgFilter->_pTextDoc->IMEInProgress(tomTrue);
  332. EnterCriticalSection(&g_CriticalSection);
  333. }
  334. *phrSession = _ptss->OnLockGranted(dwLockFlags);
  335. if (_fWriteLockOn)
  336. {
  337. // Check if any text has been added
  338. if (_parITfEnumRange && _parITfEnumRange->Count())
  339. {
  340. int idx;
  341. int idxMax = _parITfEnumRange->Count();
  342. for (idx = 0 ; idx < idxMax; idx++)
  343. {
  344. IEnumTfRanges **ppEnumRange = (IEnumTfRanges **)(_parITfEnumRange->Elem(idx));
  345. if (ppEnumRange && *ppEnumRange)
  346. {
  347. HandleFocusRange(*ppEnumRange);
  348. (*ppEnumRange)->Release();
  349. }
  350. }
  351. _parITfEnumRange->Clear(AF_KEEPMEM);
  352. }
  353. }
  354. if (_fEndTyping)
  355. OnUIMTypingDone();
  356. if (_fWriteLockOn)
  357. {
  358. _pTextMsgFilter->_pTextDoc->IMEInProgress(tomFalse);
  359. LeaveCriticalSection(&g_CriticalSection);
  360. }
  361. _fEndTyping = 0;
  362. _fWriteLockOn = 0;
  363. _fReadLockOn = 0;
  364. _fHoldCTFSelChangeNotify = 1;
  365. if (pIUnknown)
  366. hResult = _pTextMsgFilter->_pTextDoc->ReleaseCallManager(pIUnknown);
  367. _fHoldCTFSelChangeNotify = 0;
  368. return S_OK;
  369. }
  370. /*
  371. * STDMETHODIMP CUIM::GetStatus()
  372. *
  373. * @mfunc
  374. *
  375. *
  376. * @rdesc
  377. *
  378. */
  379. STDMETHODIMP CUIM::GetStatus(
  380. TS_STATUS *pdcs)
  381. {
  382. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetStatus");
  383. if (_fShutDown)
  384. return S_OK;
  385. if (pdcs)
  386. {
  387. LRESULT lresult = 0;
  388. pdcs->dwStaticFlags = (TS_SS_REGIONS | TS_SS_NOHIDDENTEXT);
  389. if ( S_OK == _pTextMsgFilter->_pTextService->TxSendMessage(
  390. EM_GETDOCFLAGS, GDF_ALL, 0, &lresult))
  391. {
  392. if (lresult & GDF_READONLY)
  393. pdcs->dwDynamicFlags = TS_SD_READONLY;
  394. // Don't want to support overtyping in Cicero yet.
  395. // if (lresult & GDF_OVERTYPE)
  396. // dcs.dwDynamicFlags = TS_SD_OVERTYPE;
  397. }
  398. }
  399. return S_OK;
  400. }
  401. /*
  402. * STDMETHODIMP CUIM::QueryInsert()
  403. *
  404. * @mfunc
  405. *
  406. *
  407. * @rdesc
  408. *
  409. */
  410. STDMETHODIMP CUIM::QueryInsert(
  411. LONG acpTestStart,
  412. LONG acpTestEnd,
  413. ULONG cch,
  414. LONG *pacpResultStart,
  415. LONG *pacpResultEnd)
  416. {
  417. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::QueryInsert");
  418. HRESULT hResult;
  419. ITextRange *pTextRange = NULL;
  420. *pacpResultStart = -1;
  421. *pacpResultEnd = -1;
  422. if (_fShutDown)
  423. return S_OK;
  424. hResult = _pTextMsgFilter->_pTextDoc->Range(acpTestStart, acpTestEnd, &pTextRange);
  425. if (hResult != S_OK)
  426. return TS_E_READONLY;
  427. Assert(pTextRange);
  428. if(pTextRange->CanEdit(NULL) == S_FALSE)
  429. {
  430. hResult = TS_E_READONLY;
  431. goto EXIT; // Cannot edit text
  432. }
  433. *pacpResultStart = acpTestStart;
  434. *pacpResultEnd = acpTestEnd;
  435. hResult = S_OK;
  436. EXIT:
  437. pTextRange->Release();
  438. return hResult;
  439. }
  440. /*
  441. * STDMETHODIMP CUIM::GetSelection()
  442. *
  443. * @mfunc
  444. *
  445. *
  446. * @rdesc
  447. *
  448. */
  449. STDMETHODIMP CUIM::GetSelection(
  450. ULONG ulIndex,
  451. ULONG ulCount,
  452. TS_SELECTION_ACP *pSelection,
  453. ULONG *pcFetched)
  454. {
  455. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetSelection");
  456. HRESULT hResult;
  457. ITextSelection *pTextSel = NULL;
  458. if (!pSelection || !pcFetched)
  459. return E_POINTER;
  460. if (!_fReadLockOn)
  461. return TS_E_NOLOCK;
  462. *pcFetched = 0;
  463. if (_fShutDown)
  464. return TS_E_NOSELECTION;
  465. if (ulIndex == TS_DEFAULT_SELECTION)
  466. ulIndex = 0;
  467. else if (ulIndex > 1)
  468. return E_INVALIDARG; // We donnot have discontiguous selection.
  469. if (_fInterimChar)
  470. {
  471. pSelection[0].acpStart = _acpInterimStart;
  472. pSelection[0].acpEnd = _acpInterimEnd;
  473. pSelection[0].style.ase = (TsActiveSelEnd) _ase;
  474. pSelection[0].style.fInterimChar = TRUE;
  475. *pcFetched = 1;
  476. return S_OK;
  477. }
  478. hResult = _pTextMsgFilter->_pTextDoc->GetSelectionEx(&pTextSel);
  479. if (pTextSel)
  480. {
  481. long cpMin = 0, cpMax = 0;
  482. long lFlags = 0;
  483. hResult = pTextSel->GetStart(&cpMin);
  484. hResult = pTextSel->GetEnd(&cpMax);
  485. hResult = pTextSel->GetFlags(&lFlags);
  486. pSelection[0].acpStart = cpMin;
  487. pSelection[0].acpEnd = cpMax;
  488. pSelection[0].style.ase = (lFlags & tomSelStartActive) ? TS_AE_START : TS_AE_END;
  489. pSelection[0].style.fInterimChar = FALSE;
  490. *pcFetched = 1;
  491. pTextSel->Release();
  492. return S_OK;
  493. }
  494. return TS_E_NOSELECTION;
  495. }
  496. /*
  497. * STDMETHODIMP CUIM::SetSelection()
  498. *
  499. * @mfunc
  500. *
  501. *
  502. * @rdesc
  503. *
  504. */
  505. STDMETHODIMP CUIM::SetSelection(
  506. ULONG ulCount,
  507. const TS_SELECTION_ACP *pSelection)
  508. {
  509. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::SetSelection");
  510. HRESULT hResult;
  511. ITextRange *pTextRange = NULL;
  512. if (!pSelection)
  513. return E_POINTER;
  514. if (ulCount <= 0)
  515. return E_INVALIDARG;
  516. if (!_fWriteLockOn)
  517. return TS_E_NOLOCK;
  518. if (_fShutDown)
  519. return S_OK;
  520. if (pSelection->style.fInterimChar)
  521. {
  522. _pTextMsgFilter->_pTextDoc->SetCaretType(tomKoreanBlockCaret); // Set Block caret mode
  523. _acpInterimStart = pSelection[0].acpStart;
  524. _acpInterimEnd = pSelection[0].acpEnd;
  525. _fInterimChar = 1;
  526. _ase = pSelection[0].style.ase;
  527. }
  528. else
  529. {
  530. if (_fInterimChar)
  531. {
  532. _fInterimChar = 0;
  533. _pTextMsgFilter->_pTextDoc->SetCaretType(tomNormalCaret); // Reset Block caret mode
  534. }
  535. hResult = _pTextMsgFilter->_pTextDoc->Range(pSelection[0].acpStart, pSelection[0].acpEnd, &pTextRange);
  536. if (pTextRange)
  537. {
  538. long lCount;
  539. _pTextMsgFilter->_pTextDoc->Freeze(&lCount); // Turn off display
  540. pTextRange->Select();
  541. pTextRange->Release();
  542. _pTextMsgFilter->_pTextDoc->Unfreeze(&lCount); // Turn on display
  543. }
  544. }
  545. return S_OK;
  546. }
  547. /*
  548. * STDMETHODIMP CUIM::GetText()
  549. *
  550. * @mfunc
  551. *
  552. *
  553. * @rdesc
  554. *
  555. */
  556. STDMETHODIMP CUIM::GetText(
  557. LONG acpStart,
  558. LONG acpEnd,
  559. WCHAR *pchPlain,
  560. ULONG cchPlainReq,
  561. ULONG *pcchPlainOut,
  562. TS_RUNINFO *prgRunInfo,
  563. ULONG ulRunInfoReq,
  564. ULONG *pulRunInfoOut,
  565. LONG *pacpNext)
  566. {
  567. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetText");
  568. if (!_fReadLockOn)
  569. return TS_E_NOLOCK;
  570. if (pchPlain == NULL && cchPlainReq != 0 ||
  571. prgRunInfo == NULL && ulRunInfoReq != 0)
  572. return E_INVALIDARG;
  573. BOOL fDoRunInfo = ulRunInfoReq > 0;
  574. LONG acpMaxText = 0;
  575. BOOL fEOP = FALSE;
  576. GetStoryLength(&acpMaxText);
  577. if (acpStart < 0 || acpStart > acpMaxText)
  578. return TS_E_INVALIDPOS;
  579. if (acpEnd < 0)
  580. acpEnd = acpMaxText;
  581. else if (acpEnd < acpStart)
  582. return TS_E_INVALIDPOS;
  583. if (pcchPlainOut)
  584. *pcchPlainOut = 0;
  585. if (pulRunInfoOut)
  586. *pulRunInfoOut = 0;
  587. if (pacpNext)
  588. *pacpNext = acpStart;
  589. if (_fShutDown)
  590. return S_OK;
  591. LRESULT lresult = 0;
  592. if ( S_OK == _pTextMsgFilter->_pTextService->TxSendMessage(
  593. EM_GETDOCFLAGS, GDF_ALL, 0, &lresult))
  594. {
  595. if ((lresult & GDF_RICHTEXT) && acpEnd == acpMaxText)
  596. fEOP = TRUE;
  597. }
  598. if (cchPlainReq || ulRunInfoReq)
  599. {
  600. HRESULT hResult;
  601. ITextRange *pTextRange = NULL;
  602. long fHiddenTextInRange = tomFalse;
  603. BOOL fCopyData = FALSE;
  604. long *pHiddenTxtBlk = NULL;
  605. long cHiddenTxtBlk = 0;
  606. if (cchPlainReq && acpEnd > (long)cchPlainReq + acpStart)
  607. acpEnd = cchPlainReq + acpStart;
  608. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart, acpEnd, &pTextRange);
  609. if (pTextRange)
  610. {
  611. BSTR bstr = NULL;
  612. long cpMin, cpMax;
  613. ULONG cch;
  614. pTextRange->GetStart(&cpMin);
  615. pTextRange->GetEnd(&cpMax);
  616. if (fDoRunInfo)
  617. {
  618. ITextFont *pFont = NULL;
  619. hResult = pTextRange->GetFont(&pFont);
  620. if (pFont)
  621. {
  622. pFont->GetHidden(&fHiddenTextInRange);
  623. pFont->Release();
  624. if (fHiddenTextInRange == tomUndefined) // Some hidden text inside range
  625. BuildHiddenTxtBlks(cpMin, cpMax, &pHiddenTxtBlk, cHiddenTxtBlk);
  626. }
  627. }
  628. hResult = pTextRange->GetText(&bstr);
  629. if (bstr)
  630. {
  631. cch = cpMax - cpMin;
  632. if (cchPlainReq)
  633. {
  634. if (cchPlainReq > cch)
  635. cchPlainReq = cch;
  636. fCopyData = TRUE;
  637. }
  638. else
  639. cchPlainReq = cch;
  640. // Convert character into special Cicero char.
  641. long cpCurrentStart = cpMin;
  642. long cpCurrent = cpMin;
  643. long idx = 0;
  644. ULONG cRunInfo = 0;
  645. BOOL fRunInfoNotEnough = FALSE;
  646. long cpNextHiddenText = tomForward;
  647. if (fDoRunInfo && pHiddenTxtBlk)
  648. cpNextHiddenText = pHiddenTxtBlk[0];
  649. if (fHiddenTextInRange != tomTrue)
  650. {
  651. WCHAR *pText = (WCHAR *)bstr;
  652. while (cpCurrent < cpMax)
  653. {
  654. if (cpCurrent == cpNextHiddenText)
  655. {
  656. // setup run info for current good text
  657. if (cpCurrent != cpCurrentStart)
  658. {
  659. if (cRunInfo >= ulRunInfoReq)
  660. {
  661. fRunInfoNotEnough = TRUE;
  662. break;
  663. }
  664. prgRunInfo[cRunInfo].uCount = cpCurrent - cpCurrentStart;
  665. prgRunInfo[cRunInfo].type = TS_RT_PLAIN;
  666. cRunInfo++;
  667. }
  668. long cchHiddenText = pHiddenTxtBlk[idx+1];
  669. // setup run info for hidden text block
  670. if (cRunInfo >= ulRunInfoReq)
  671. {
  672. fRunInfoNotEnough = TRUE;
  673. break;
  674. }
  675. prgRunInfo[cRunInfo].uCount = cchHiddenText;
  676. prgRunInfo[cRunInfo].type = TS_RT_OPAQUE;
  677. cRunInfo++;
  678. idx += 2;
  679. if (idx < cHiddenTxtBlk)
  680. cpNextHiddenText = pHiddenTxtBlk[idx];
  681. else
  682. cpNextHiddenText = tomForward;
  683. cpCurrent += cchHiddenText;
  684. pText += cchHiddenText;
  685. cpCurrentStart = cpCurrent;
  686. }
  687. else
  688. {
  689. switch (*pText)
  690. {
  691. case WCH_EMBEDDING:
  692. *pText = TS_CHAR_EMBEDDED;
  693. break;
  694. case STARTFIELD:
  695. case ENDFIELD:
  696. *pText = TS_CHAR_REGION;
  697. if (cpCurrent + 1 < cpMax)
  698. {
  699. pText++;
  700. cpCurrent++;
  701. Assert(*pText == 0x000d);
  702. *pText = TS_CHAR_REGION;
  703. }
  704. break;
  705. }
  706. cpCurrent++;
  707. // Convert EOP into TS_CHAR_REGION
  708. if (fEOP && cpCurrent == acpMaxText && *pText == CR)
  709. *pText = TS_CHAR_REGION;
  710. pText++;
  711. }
  712. }
  713. }
  714. if (fDoRunInfo)
  715. {
  716. // setup run info for last chunk of good text
  717. if (cpCurrent != cpCurrentStart && cRunInfo < ulRunInfoReq)
  718. {
  719. prgRunInfo[cRunInfo].uCount = cpCurrent - cpCurrentStart;
  720. prgRunInfo[cRunInfo].type = TS_RT_PLAIN;
  721. cRunInfo++;
  722. }
  723. if (pulRunInfoOut)
  724. *pulRunInfoOut = cRunInfo ? cRunInfo : 1;
  725. // All the text belong to the same run
  726. if (cRunInfo == 0)
  727. {
  728. prgRunInfo[0].uCount = cchPlainReq;
  729. prgRunInfo[0].type = (fHiddenTextInRange == tomTrue) ? TS_RT_OPAQUE : TS_RT_PLAIN;
  730. }
  731. }
  732. if (fRunInfoNotEnough)
  733. {
  734. // Runinfo too small. need to add cch from all valid runs
  735. TS_RUNINFO *prgRunInfoData = prgRunInfo;
  736. ULONG idx;
  737. cchPlainReq = 0;
  738. for (idx=0; idx < cRunInfo; idx++)
  739. {
  740. cchPlainReq += prgRunInfoData->uCount;
  741. prgRunInfoData++;
  742. }
  743. }
  744. if (fCopyData)
  745. // fill in the buffer
  746. memcpy(pchPlain, (LPSTR)bstr, cchPlainReq * sizeof(WCHAR));
  747. if (pcchPlainOut)
  748. *pcchPlainOut = cchPlainReq;
  749. if (pacpNext)
  750. *pacpNext = cpMin + cchPlainReq;
  751. SysFreeString(bstr);
  752. }
  753. pTextRange->Release();
  754. FreePv(pHiddenTxtBlk);
  755. }
  756. }
  757. return S_OK;
  758. }
  759. /*
  760. * STDMETHODIMP CUIM::SetText()
  761. *
  762. * @mfunc
  763. *
  764. *
  765. * @rdesc
  766. *
  767. */
  768. STDMETHODIMP CUIM::SetText(
  769. DWORD dwFlags,
  770. LONG acpStart,
  771. LONG acpEnd,
  772. const WCHAR *pchText,
  773. ULONG cch,
  774. TS_TEXTCHANGE *pChange)
  775. {
  776. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::SetText");
  777. return InsertData(dwFlags, acpStart, acpEnd, pchText, cch, NULL, pChange);
  778. }
  779. /*
  780. * STDMETHODIMP CUIM::InsertData()
  781. *
  782. * @mfunc
  783. *
  784. *
  785. * @rdesc
  786. *
  787. */
  788. STDMETHODIMP CUIM::InsertData(
  789. DWORD dwFlags,
  790. LONG acpStart,
  791. LONG acpEnd,
  792. const WCHAR *pchText,
  793. ULONG cch,
  794. IDataObject *pDataObject,
  795. TS_TEXTCHANGE *pChange)
  796. {
  797. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::InsertData");
  798. HRESULT hResult = S_OK;
  799. ITextRange *pTextRange = NULL;
  800. BOOL fInsertObject = pDataObject != NULL;
  801. if (!_fWriteLockOn)
  802. return TS_E_NOLOCK;
  803. if (_fShutDown)
  804. return S_OK;
  805. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart, acpEnd, &pTextRange);
  806. if (pTextRange)
  807. {
  808. BSTR bstr = NULL;
  809. if(pTextRange->CanEdit(NULL) == S_FALSE)
  810. {
  811. pTextRange->Release();
  812. return TS_E_READONLY; // Cannot edit text
  813. }
  814. LONG cchExced = 0;
  815. BOOL fDelSelection = FALSE;
  816. if ((LONG)cch > (acpEnd - acpStart) &&
  817. _pTextMsgFilter->_pTextDoc->CheckTextLimit((LONG)cch - (acpEnd-acpStart), &cchExced) == NOERROR &&
  818. cchExced > 0)
  819. {
  820. // We reach text limit, beep and exit
  821. _pTextMsgFilter->_pTextDoc->SysBeep();
  822. pTextRange->Release();
  823. return E_FAIL;
  824. }
  825. if (!fInsertObject)
  826. {
  827. bstr = SysAllocStringLen(pchText, cch);
  828. if (!bstr)
  829. {
  830. pTextRange->Release();
  831. return E_OUTOFMEMORY;
  832. }
  833. }
  834. if (!_fAnyWriteOperation)
  835. {
  836. // Start the UIM typing
  837. ITextFont *pCurrentFont = NULL;
  838. BOOL fRestFont = TRUE;
  839. _fAnyWriteOperation = 1;
  840. hResult = pTextRange->GetStart(&_cpMin);
  841. // Hold notification if needed
  842. if (!(_pTextMsgFilter->_fIMEAlwaysNotify))
  843. _pTextMsgFilter->_pTextDoc->SetNotificationMode(tomFalse);
  844. if (!_bstrComposition)
  845. {
  846. if (fRestFont && _pTextFont)
  847. {
  848. _pTextFont->Release();
  849. _pTextFont = NULL;
  850. }
  851. if (acpStart != acpEnd)
  852. {
  853. if (_pTextFont == NULL)
  854. {
  855. ITextRange *pRange = NULL;
  856. // Get font at cpStart+1
  857. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart, acpStart+1, &pRange);
  858. if (pRange)
  859. {
  860. hResult = pRange->GetFont(&pCurrentFont);
  861. if (pCurrentFont)
  862. {
  863. hResult = pCurrentFont->GetDuplicate(&_pTextFont);
  864. pCurrentFont->Release();
  865. pCurrentFont = NULL;
  866. }
  867. pRange->Release();
  868. }
  869. }
  870. // if any current selection, turn on Undo to delete it....
  871. _pTextMsgFilter->_pTextDoc->Undo(tomResume, NULL);
  872. pTextRange->SetText(NULL);
  873. _pTextMsgFilter->_pTextDoc->Undo(tomSuspend, NULL);
  874. fDelSelection = TRUE;
  875. }
  876. else
  877. {
  878. ITextSelection *pTextSel = NULL;
  879. hResult = _pTextMsgFilter->_pTextDoc->GetSelectionEx(&pTextSel);
  880. if (pTextSel)
  881. {
  882. long cpMin = 0;
  883. hResult = pTextSel->GetStart(&cpMin);
  884. if (hResult == S_OK && cpMin == acpStart)
  885. hResult = pTextSel->GetFont(&pCurrentFont);
  886. if (!pCurrentFont)
  887. hResult = pTextRange->GetFont(&pCurrentFont);
  888. if (pCurrentFont)
  889. {
  890. hResult = pCurrentFont->GetDuplicate(&_pTextFont);
  891. pCurrentFont->Release();
  892. pCurrentFont = NULL;
  893. }
  894. pTextSel->Release();
  895. }
  896. }
  897. }
  898. Assert (_pTextFont);
  899. if (_pTextFont)
  900. {
  901. long cpMin;
  902. pTextRange->GetStart(&cpMin);
  903. _pTextMsgFilter->_uKeyBoardCodePage = GetKeyboardCodePage(0x0FFFFFFFF);
  904. CIme::CheckKeyboardFontMatching(cpMin, _pTextMsgFilter, _pTextFont);
  905. }
  906. }
  907. if (fInsertObject)
  908. {
  909. LRESULT lresult;
  910. CHARRANGE charRange = {acpStart, acpEnd};
  911. if (fDelSelection)
  912. charRange.cpMost = acpStart;
  913. hResult = _pTextMsgFilter->_pTextService->TxSendMessage(EM_INSERTOBJ, (WPARAM)&charRange,
  914. (LPARAM)pDataObject, &lresult);
  915. if (hResult == NOERROR && pChange)
  916. {
  917. pChange->acpStart = acpStart;
  918. pChange->acpOldEnd = acpEnd;
  919. pChange->acpNewEnd = acpStart+1;
  920. }
  921. }
  922. else
  923. {
  924. long lCount;
  925. long cpMin, cpMax;
  926. _pTextMsgFilter->_pTextDoc->Freeze(&lCount); // Turn off display
  927. hResult = pTextRange->SetText(bstr);
  928. _pTextMsgFilter->_pTextDoc->Unfreeze(&lCount); // Turn on display
  929. pTextRange->GetStart(&cpMin);
  930. pTextRange->GetEnd(&cpMax);
  931. if (_pTextFont)
  932. pTextRange->SetFont(_pTextFont);
  933. POINT ptBottomPos;
  934. if (_pTextMsgFilter->_uKeyBoardCodePage == CP_KOREAN)
  935. {
  936. if (pTextRange->GetPoint( tomEnd+TA_BOTTOM+TA_LEFT,
  937. &(ptBottomPos.x), &(ptBottomPos.y) ) != NOERROR)
  938. pTextRange->ScrollIntoView(tomEnd);
  939. }
  940. SysFreeString(bstr);
  941. // out params
  942. pChange->acpStart = cpMin;
  943. pChange->acpOldEnd = acpEnd;
  944. pChange->acpNewEnd = cpMax;
  945. hResult = S_OK;
  946. }
  947. pTextRange->Release();
  948. }
  949. return hResult;
  950. }
  951. /*
  952. * STDMETHODIMP CUIM::GetFormattedText()
  953. *
  954. * @mfunc
  955. *
  956. *
  957. * @rdesc
  958. *
  959. */
  960. STDMETHODIMP CUIM::GetFormattedText(
  961. LONG acpStart,
  962. LONG acpEnd,
  963. IDataObject **ppDataObject)
  964. {
  965. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetFormattedText");
  966. return E_NOTIMPL;
  967. }
  968. /*
  969. * STDMETHODIMP CUIM::GetEmbedded()
  970. *
  971. * @mfunc
  972. *
  973. *
  974. * @rdesc
  975. *
  976. */
  977. STDMETHODIMP CUIM::GetEmbedded(
  978. LONG acpPos,
  979. REFGUID rguidService,
  980. REFIID riid,
  981. IUnknown **ppunk)
  982. {
  983. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetEmbedded");
  984. WORD wServiceRequested = 0;
  985. if (!_fReadLockOn)
  986. return TS_E_NOLOCK;
  987. if (!ppunk)
  988. return E_INVALIDARG;
  989. if (IsEqualIID(rguidService, GUID_DCSERVICE_ACTIVEX))
  990. wServiceRequested = 1;
  991. else if (IsEqualIID(rguidService, GUID_DCSERVICE_DATAOBJECT))
  992. wServiceRequested = 2;
  993. else
  994. return E_INVALIDARG;
  995. ITextRange *pTextRange = NULL;
  996. IUnknown *pIUnk = NULL;
  997. HRESULT hResult = _pTextMsgFilter->_pTextDoc->Range(acpPos, acpPos+1, &pTextRange);
  998. if (SUCCEEDED(hResult) && pTextRange)
  999. {
  1000. hResult = pTextRange->GetEmbeddedObject(&pIUnk);
  1001. if (SUCCEEDED(hResult) && pIUnk)
  1002. hResult = pIUnk->QueryInterface(wServiceRequested == 1 ? riid : IID_IDataObject,
  1003. (LPVOID FAR *)ppunk);
  1004. else
  1005. hResult = E_FAIL;
  1006. if (pIUnk)
  1007. pIUnk->Release();
  1008. pTextRange->Release();
  1009. }
  1010. return hResult;
  1011. }
  1012. /*
  1013. * STDMETHODIMP CUIM::InsertEmbedded()
  1014. *
  1015. * @mfunc
  1016. *
  1017. *
  1018. * @rdesc
  1019. *
  1020. */
  1021. STDMETHODIMP CUIM::InsertEmbedded(
  1022. DWORD dwFlags,
  1023. LONG acpStart,
  1024. LONG acpEnd,
  1025. IDataObject *pDataObject,
  1026. TS_TEXTCHANGE *pChange)
  1027. {
  1028. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::InsertEmbedded");
  1029. if (!pDataObject)
  1030. return E_INVALIDARG;
  1031. if (_pTextMsgFilter->_fAllowEmbedded == 0)
  1032. return TS_E_FORMAT; // Client doesn't want insert embedded
  1033. return InsertData(dwFlags, acpStart, acpEnd, NULL, 1, pDataObject, pChange);
  1034. }
  1035. /*
  1036. * STDMETHODIMP CUIM::RequestSupportedAttrs()
  1037. *
  1038. * @mfunc
  1039. *
  1040. *
  1041. * @rdesc
  1042. *
  1043. */
  1044. STDMETHODIMP CUIM::RequestSupportedAttrs(
  1045. DWORD dwFlags,
  1046. ULONG cFilterAttrs,
  1047. const TS_ATTRID *paFilterAttrs)
  1048. {
  1049. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::RequestSupportedAttrs");
  1050. if (_fShutDown)
  1051. return E_NOTIMPL;
  1052. return GetAttrs(0, cFilterAttrs, paFilterAttrs, TRUE);
  1053. }
  1054. /*
  1055. * STDMETHODIMP CUIM::RequestAttrsAtPosition()
  1056. *
  1057. * @mfunc
  1058. *
  1059. *
  1060. * @rdesc
  1061. *
  1062. */
  1063. STDMETHODIMP CUIM::RequestAttrsAtPosition(
  1064. LONG acpPos,
  1065. ULONG cFilterAttrs,
  1066. const TS_ATTRID *paFilterAttrs,
  1067. DWORD dwFlags)
  1068. {
  1069. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::RequestAttrsAtPosition");
  1070. if (_fShutDown)
  1071. return E_NOTIMPL;
  1072. return GetAttrs(acpPos, cFilterAttrs, paFilterAttrs, FALSE);
  1073. }
  1074. /*
  1075. * STDMETHODIMP CUIM::RequestAttrsTransitioningAtPosition()
  1076. *
  1077. * @mfunc
  1078. *
  1079. *
  1080. * @rdesc
  1081. *
  1082. */
  1083. STDMETHODIMP CUIM::RequestAttrsTransitioningAtPosition(
  1084. LONG acpPos,
  1085. ULONG cFilterAttrs,
  1086. const TS_ATTRID *paFilterAttrs,
  1087. DWORD dwFlags)
  1088. {
  1089. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::RequestAttrsTransitioningAtPosition");
  1090. return E_NOTIMPL;
  1091. }
  1092. /*
  1093. * STDMETHODIMP CUIM::FindNextAttrTransition()
  1094. *
  1095. * @mfunc
  1096. *
  1097. *
  1098. * @rdesc
  1099. *
  1100. */
  1101. STDMETHODIMP CUIM::FindNextAttrTransition(
  1102. LONG acpStart,
  1103. LONG acpHalt,
  1104. ULONG cFilterAttrs,
  1105. const TS_ATTRID *paFilterAttrs,
  1106. DWORD dwFlags,
  1107. LONG *pacpNext,
  1108. BOOL *pfFound,
  1109. LONG *plFoundOffset)
  1110. {
  1111. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::FindNextAttrTransition");
  1112. return E_NOTIMPL;
  1113. }
  1114. /*
  1115. * STDMETHODIMP CUIM::RetrieveRequestedAttrs()
  1116. *
  1117. * @mfunc
  1118. *
  1119. *
  1120. * @rdesc
  1121. *
  1122. */
  1123. STDMETHODIMP CUIM::RetrieveRequestedAttrs(
  1124. ULONG ulCount,
  1125. TS_ATTRVAL *paAttrVals,
  1126. ULONG *pcFetched)
  1127. {
  1128. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::RetrieveRequestedAttrs");
  1129. if (!pcFetched)
  1130. return E_INVALIDARG;
  1131. if (_fShutDown)
  1132. return E_NOTIMPL;
  1133. *pcFetched = 0;
  1134. if (_parAttrsVal && _uAttrsValCurrent < _uAttrsValTotal)
  1135. {
  1136. ULONG cFetched = min(ulCount, _uAttrsValTotal - _uAttrsValCurrent);
  1137. if (cFetched)
  1138. {
  1139. memcpy(paAttrVals, &_parAttrsVal[_uAttrsValCurrent], cFetched * sizeof(TS_ATTRVAL));
  1140. memset(&_parAttrsVal[_uAttrsValCurrent], 0, cFetched * sizeof(TS_ATTRVAL));
  1141. _uAttrsValCurrent += cFetched;
  1142. *pcFetched = cFetched;
  1143. // If everything is fetched, clean up
  1144. if (_uAttrsValCurrent == _uAttrsValTotal)
  1145. InitAttrVarArray();
  1146. }
  1147. }
  1148. return S_OK;
  1149. }
  1150. /*
  1151. * STDMETHODIMP CUIM::GetEndACP()
  1152. *
  1153. * @mfunc
  1154. *
  1155. *
  1156. * @rdesc
  1157. *
  1158. */
  1159. STDMETHODIMP CUIM::GetEndACP(LONG *pacp)
  1160. {
  1161. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetEndACP");
  1162. if (!_fReadLockOn)
  1163. return TS_E_NOLOCK;
  1164. if (!pacp)
  1165. return E_INVALIDARG;
  1166. if (_fShutDown)
  1167. return E_NOTIMPL;
  1168. return GetStoryLength(pacp);
  1169. }
  1170. /*
  1171. * STDMETHODIMP CUIM::GetActiveView()
  1172. *
  1173. * @mfunc
  1174. *
  1175. *
  1176. * @rdesc
  1177. *
  1178. */
  1179. STDMETHODIMP CUIM::GetActiveView(TsViewCookie *pvcView)
  1180. {
  1181. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetActiveView");
  1182. if (!pvcView)
  1183. return E_INVALIDARG;
  1184. *pvcView = 0;
  1185. return S_OK;
  1186. }
  1187. /*
  1188. * STDMETHODIMP CUIM::GetACPFromPoint()
  1189. *
  1190. * @mfunc
  1191. *
  1192. *
  1193. * @rdesc
  1194. *
  1195. */
  1196. STDMETHODIMP CUIM::GetACPFromPoint(
  1197. TsViewCookie vcView,
  1198. const POINT *pt,
  1199. DWORD dwFlags,
  1200. LONG *pacp)
  1201. {
  1202. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetACPFromPoint");
  1203. if (!pt || !pacp)
  1204. return E_POINTER;
  1205. if (_fShutDown)
  1206. return E_NOTIMPL;
  1207. ITextRange *pTextRange = NULL;
  1208. HRESULT hResult = _pTextMsgFilter->_pTextDoc->RangeFromPoint(pt->x, pt->y, &pTextRange);
  1209. if (hResult == S_OK && pTextRange)
  1210. hResult = pTextRange->GetStart(pacp);
  1211. if (pTextRange)
  1212. pTextRange->Release();
  1213. return hResult;
  1214. }
  1215. /*
  1216. * STDMETHODIMP CUIM::GetTextExt()
  1217. *
  1218. * @mfunc
  1219. *
  1220. *
  1221. * @rdesc
  1222. *
  1223. */
  1224. STDMETHODIMP CUIM::GetTextExt(
  1225. TsViewCookie vcView,
  1226. LONG acpStart,
  1227. LONG acpEnd,
  1228. RECT *prc,
  1229. BOOL *pfClipped)
  1230. {
  1231. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetTextExt");
  1232. if (!prc)
  1233. return E_POINTER;
  1234. if (_fShutDown)
  1235. return E_NOTIMPL;
  1236. if (pfClipped)
  1237. *pfClipped = TRUE;
  1238. ITextRange *pTextRange = NULL;
  1239. HRESULT hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart, acpEnd, &pTextRange);
  1240. if (hResult == S_OK && pTextRange)
  1241. {
  1242. BOOL fClipped = FALSE;
  1243. POINT ptStart, ptEnd;
  1244. hResult = pTextRange->GetPoint( tomStart+TA_TOP+TA_LEFT,
  1245. &(ptStart.x), &(ptStart.y) );
  1246. if (hResult != S_OK)
  1247. {
  1248. hResult = pTextRange->GetPoint( tomStart+TA_TOP+TA_LEFT+tomAllowOffClient,
  1249. &(ptStart.x), &(ptStart.y) );
  1250. fClipped = TRUE;
  1251. }
  1252. if (hResult == S_OK)
  1253. {
  1254. hResult = pTextRange->GetPoint( acpStart == acpEnd ? tomStart+TA_BOTTOM+TA_LEFT :
  1255. tomEnd+TA_BOTTOM+TA_LEFT,
  1256. &(ptEnd.x), &(ptEnd.y) );
  1257. if (hResult != S_OK)
  1258. {
  1259. hResult = pTextRange->GetPoint( acpStart == acpEnd ? tomStart+TA_BOTTOM+TA_LEFT+tomAllowOffClient :
  1260. tomEnd+TA_BOTTOM+TA_LEFT+tomAllowOffClient,
  1261. &(ptEnd.x), &(ptEnd.y) );
  1262. fClipped = TRUE;
  1263. }
  1264. if (hResult == S_OK)
  1265. {
  1266. prc->left = ptStart.x;
  1267. prc->top = ptStart.y;
  1268. prc->right = ptEnd.x;
  1269. prc->bottom = ptEnd.y;
  1270. if (pfClipped)
  1271. *pfClipped = fClipped;
  1272. }
  1273. }
  1274. }
  1275. if (pTextRange)
  1276. pTextRange->Release();
  1277. return hResult;
  1278. }
  1279. /*
  1280. * STDMETHODIMP CUIM::GetScreenExt()
  1281. *
  1282. * @mfunc
  1283. *
  1284. *
  1285. * @rdesc
  1286. *
  1287. */
  1288. STDMETHODIMP CUIM::GetScreenExt(
  1289. TsViewCookie vcView,
  1290. RECT *prc)
  1291. {
  1292. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetScreenExt");
  1293. if (!prc)
  1294. return E_POINTER;
  1295. return _pTextMsgFilter->_pTextDoc->GetClientRect(tomIncludeInset,
  1296. &(prc->left), &(prc->top), &(prc->right), &(prc->bottom));
  1297. }
  1298. /*
  1299. * STDMETHODIMP CUIM::GetWnd()
  1300. *
  1301. * @mfunc
  1302. *
  1303. *
  1304. * @rdesc
  1305. *
  1306. */
  1307. STDMETHODIMP CUIM::GetWnd(
  1308. TsViewCookie vcView,
  1309. HWND *phwnd)
  1310. {
  1311. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetWnd");
  1312. if (!phwnd)
  1313. return E_INVALIDARG;
  1314. if (_fShutDown)
  1315. return E_NOTIMPL;
  1316. *phwnd = _pTextMsgFilter->_hwnd;
  1317. if (!*phwnd) // Windowless mode...
  1318. {
  1319. long hWnd;
  1320. if (_pTextMsgFilter->_pTextDoc->GetWindow(&hWnd) != S_OK || !hWnd)
  1321. return E_NOTIMPL;
  1322. *phwnd = (HWND)(DWORD_PTR)hWnd;
  1323. }
  1324. return S_OK;
  1325. }
  1326. /*
  1327. * STDMETHODIMP CUIM::QueryInsertEmbedded()
  1328. *
  1329. * @mfunc
  1330. *
  1331. *
  1332. * @rdesc
  1333. *
  1334. */
  1335. STDMETHODIMP CUIM::QueryInsertEmbedded(
  1336. const GUID *pguidService,
  1337. const FORMATETC *pFormatEtc,
  1338. BOOL *pfInsertable)
  1339. {
  1340. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::QueryInsertEmbedded");
  1341. if (!pfInsertable)
  1342. return E_INVALIDARG;
  1343. // Check setting if client wants to support embedded
  1344. *pfInsertable = _pTextMsgFilter->_fAllowEmbedded ? TRUE : FALSE;
  1345. return S_OK;
  1346. }
  1347. /*
  1348. * STDMETHODIMP CUIM::InsertTextAtSelection()
  1349. *
  1350. * @mfunc
  1351. *
  1352. *
  1353. * @rdesc
  1354. *
  1355. */
  1356. STDMETHODIMP CUIM::InsertTextAtSelection(
  1357. DWORD dwFlags,
  1358. const WCHAR *pchText,
  1359. ULONG cch,
  1360. LONG *pacpStart,
  1361. LONG *pacpEnd,
  1362. TS_TEXTCHANGE *pChange)
  1363. {
  1364. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::InsertTextAtSelection");
  1365. TS_SELECTION_ACP acpSelection;
  1366. ULONG cFetched;
  1367. LONG acpResultStart;
  1368. LONG acpResultEnd;
  1369. HRESULT hr;
  1370. if (_fShutDown)
  1371. return E_NOTIMPL;
  1372. if ((dwFlags & TS_IAS_QUERYONLY) || !(dwFlags & TS_IAS_NOQUERY))
  1373. {
  1374. if (!pacpStart || !pacpEnd)
  1375. return E_POINTER;
  1376. }
  1377. hr = GetSelection(TS_DEFAULT_SELECTION, 1, &acpSelection, &cFetched);
  1378. if (hr != S_OK)
  1379. return hr;
  1380. hr = QueryInsert(acpSelection.acpStart, acpSelection.acpEnd, cch,
  1381. &acpResultStart, &acpResultEnd);
  1382. if (hr != S_OK)
  1383. return hr;
  1384. if (dwFlags & TS_IAS_QUERYONLY)
  1385. {
  1386. // Query only, return data
  1387. *pacpStart = acpResultStart;
  1388. *pacpEnd = acpResultEnd;
  1389. return S_OK;
  1390. }
  1391. if (!_fUIMTyping)
  1392. {
  1393. // special case where no OnStartComposition before this call
  1394. _fInsertTextAtSel = 1;
  1395. _pTextMsgFilter->_pTextDoc->Undo(tomSuspend, NULL); // turn off undo
  1396. }
  1397. hr = SetText(0, acpResultStart, acpResultEnd, pchText, cch, pChange);
  1398. if (hr != S_OK)
  1399. {
  1400. if (!_fUIMTyping)
  1401. {
  1402. // SetText fail, reset state before exit
  1403. _fInsertTextAtSel = 0;
  1404. _pTextMsgFilter->_pTextDoc->Undo(tomResume, NULL); // turn on undo
  1405. }
  1406. return hr;
  1407. }
  1408. if (!(dwFlags & TS_IAS_NOQUERY) && pChange)
  1409. {
  1410. *pacpStart = pChange->acpStart;
  1411. *pacpEnd = pChange->acpNewEnd;
  1412. }
  1413. return S_OK;
  1414. }
  1415. /*
  1416. * STDMETHODIMP CUIM::InsertEmbeddedAtSelection()
  1417. *
  1418. * @mfunc
  1419. *
  1420. *
  1421. * @rdesc
  1422. *
  1423. */
  1424. STDMETHODIMP CUIM::InsertEmbeddedAtSelection(
  1425. DWORD dwFlags,
  1426. IDataObject *pDataObject,
  1427. LONG *pacpStart,
  1428. LONG *pacpEnd,
  1429. TS_TEXTCHANGE *pChange)
  1430. {
  1431. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::InsertEmbeddedAtSelection");
  1432. return E_NOTIMPL;
  1433. }
  1434. /*
  1435. * void CUIM::OnPreReplaceRange()
  1436. *
  1437. * @mfunc
  1438. *
  1439. *
  1440. * @rdesc
  1441. *
  1442. */
  1443. void CUIM::OnPreReplaceRange(
  1444. LONG cp, //@parm cp where ReplaceRange starts ("cpMin")
  1445. LONG cchDel, //@parm Count of chars after cp that are deleted
  1446. LONG cchNew, //@parm Count of chars inserted after cp
  1447. LONG cpFormatMin, //@parm cpMin for a formatting change
  1448. LONG cpFormatMax, //@parm cpMost for a formatting change
  1449. NOTIFY_DATA *pNotifyData) //@parm special data to indicate changes
  1450. {
  1451. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnPreReplaceRange");
  1452. return;
  1453. };
  1454. /*
  1455. * void CUIM::OnPostReplaceRange()
  1456. *
  1457. * @mfunc
  1458. *
  1459. *
  1460. * @rdesc
  1461. *
  1462. */
  1463. void CUIM::OnPostReplaceRange(
  1464. LONG cp, //@parm cp where ReplaceRange starts ("cpMin")
  1465. LONG cchDel, //@parm Count of chars after cp that are deleted
  1466. LONG cchNew, //@parm Count of chars inserted after cp
  1467. LONG cpFormatMin, //@parm cpMin for a formatting change
  1468. LONG cpFormatMax, //@parm cpMost for a formatting change
  1469. NOTIFY_DATA *pNotifyData) //@parm special data to indicate changes
  1470. {
  1471. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnPostReplaceRange");
  1472. if (_fShutDown)
  1473. return;
  1474. if (cp != CONVERT_TO_PLAIN && cp != CP_INFINITE && _ptss && !_fWriteLockOn)
  1475. {
  1476. // Forward change notification to UIM
  1477. TS_TEXTCHANGE tsTxtChange;
  1478. tsTxtChange.acpStart = cp;
  1479. if (cchDel == cchNew)
  1480. {
  1481. // text modified
  1482. tsTxtChange.acpNewEnd =
  1483. tsTxtChange.acpOldEnd = cp + cchDel;
  1484. _ptss->OnTextChange(0, &tsTxtChange);
  1485. }
  1486. else
  1487. {
  1488. if (cchDel)
  1489. {
  1490. // text deleted
  1491. tsTxtChange.acpNewEnd = cp;
  1492. tsTxtChange.acpOldEnd = cp + cchDel;
  1493. _ptss->OnTextChange(0, &tsTxtChange);
  1494. }
  1495. if (cchNew)
  1496. {
  1497. // text added
  1498. tsTxtChange.acpOldEnd = cp;
  1499. tsTxtChange.acpNewEnd = cp + cchNew;
  1500. _ptss->OnTextChange(0, &tsTxtChange);
  1501. }
  1502. }
  1503. }
  1504. return;
  1505. };
  1506. /*
  1507. * void CUIM::Zombie()
  1508. *
  1509. * @mfunc
  1510. *
  1511. *
  1512. * @rdesc
  1513. *
  1514. */
  1515. void CUIM::Zombie()
  1516. {
  1517. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::Zombie");
  1518. return;
  1519. };
  1520. /*
  1521. * STDMETHODIMP CUIM::OnStartComposition()
  1522. *
  1523. * @mfunc
  1524. *
  1525. *
  1526. * @rdesc
  1527. *
  1528. */
  1529. STDAPI CUIM::OnStartComposition(
  1530. ITfCompositionView *pComposition,
  1531. BOOL *pfOk)
  1532. {
  1533. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnStartComposition");
  1534. if (_fUIMTyping)
  1535. *pfOk = FALSE;
  1536. else
  1537. {
  1538. BOOL fInsertTextCalled = _fInsertTextAtSel;
  1539. BOOL fRetainFont = _fEndTyping;
  1540. *pfOk = TRUE;
  1541. _fUIMTyping = 1;
  1542. _fAnyWriteOperation = _fAnyWriteOperation && (_fEndTyping || fInsertTextCalled);
  1543. _fEndTyping = 0;
  1544. _fInsertTextAtSel = 0;
  1545. if (!fInsertTextCalled)
  1546. _pTextMsgFilter->_pTextDoc->Undo(tomSuspend, NULL); // turn off undo
  1547. _cchComposition = 0;
  1548. _acpFocusRange = tomForward;
  1549. _cchFocusRange = 0;
  1550. CleanUpComposition();
  1551. if (!fInsertTextCalled && pComposition)
  1552. {
  1553. HRESULT hr;
  1554. ITfRange *pRangeNew = NULL;
  1555. hr = pComposition->GetRange(&pRangeNew);
  1556. if (pRangeNew)
  1557. {
  1558. LONG acpStart;
  1559. LONG cchStart;
  1560. GetExtentAcpPrange(pRangeNew, acpStart, cchStart);
  1561. pRangeNew->Release();
  1562. if (cchStart > 0)
  1563. {
  1564. // Save the original text
  1565. ITextRange *pTextRange = NULL;
  1566. ITextFont *pCurrentFont = NULL;
  1567. HRESULT hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart, acpStart+cchStart, &pTextRange);
  1568. if (!fRetainFont && _pTextFont)
  1569. {
  1570. _pTextFont->Release();
  1571. _pTextFont = NULL;
  1572. }
  1573. if (pTextRange)
  1574. {
  1575. if (fRetainFont && _acpPreFocusRangeLast <= acpStart
  1576. && (acpStart + cchStart) <= (_acpPreFocusRangeLast + _cchFocusRangeLast))
  1577. {
  1578. // Cont'u from previous composition
  1579. _acpFocusRange = _acpPreFocusRangeLast;
  1580. _cchFocusRange = _cchFocusRangeLast;
  1581. }
  1582. else
  1583. {
  1584. hResult = pTextRange->GetText(&_bstrComposition);
  1585. Assert(!_pObjects);
  1586. _cObjects = BuildObject(pTextRange, _bstrComposition, &_pObjects, 0);
  1587. _acpBstrStart = acpStart;
  1588. _cchComposition = cchStart;
  1589. GetEndACP(&_cpEnd);
  1590. }
  1591. if (!_pTextFont)
  1592. {
  1593. hResult = pTextRange->Collapse(tomTrue);
  1594. hResult = pTextRange->Move(1, tomCharacter, NULL);
  1595. hResult = pTextRange->GetFont(&pCurrentFont);
  1596. if (pCurrentFont)
  1597. {
  1598. hResult = pCurrentFont->GetDuplicate(&_pTextFont);
  1599. pCurrentFont->Release();
  1600. if (_pTextFont)
  1601. {
  1602. long cpMin;
  1603. pTextRange->GetStart(&cpMin);
  1604. _pTextMsgFilter->_uKeyBoardCodePage = GetKeyboardCodePage(0x0FFFFFFFF);
  1605. CIme::CheckKeyboardFontMatching(cpMin, _pTextMsgFilter, _pTextFont);
  1606. }
  1607. }
  1608. }
  1609. pTextRange->Release();
  1610. }
  1611. }
  1612. }
  1613. }
  1614. }
  1615. return S_OK;
  1616. }
  1617. /*
  1618. * STDMETHODIMP CUIM::OnUpdateComposition()
  1619. *
  1620. * @mfunc
  1621. *
  1622. *
  1623. * @rdesc
  1624. *
  1625. */
  1626. STDAPI CUIM::OnUpdateComposition(
  1627. ITfCompositionView *pComposition,
  1628. ITfRange *pRangeNew)
  1629. {
  1630. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnUpdateComposition");
  1631. LONG acpStart;
  1632. LONG cchStart;
  1633. if (pRangeNew)
  1634. {
  1635. GetExtentAcpPrange(pRangeNew, acpStart, cchStart);
  1636. if (_bstrComposition)
  1637. {
  1638. long cpEnd;
  1639. GetEndACP(&cpEnd);
  1640. long cpCurrentCompEnd = _acpBstrStart + _cchComposition + cpEnd - _cpEnd;
  1641. long cchExtendAfter = acpStart + cchStart - cpCurrentCompEnd;
  1642. if (_acpBstrStart > acpStart)
  1643. {
  1644. LONG cchExtendBefore = _acpBstrStart - acpStart;
  1645. ITextRange *pTextRange = NULL;
  1646. HRESULT hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart,
  1647. acpStart+cchExtendBefore, &pTextRange);
  1648. if (pTextRange)
  1649. {
  1650. BSTR bstrExtendBefore = NULL;
  1651. hResult = pTextRange->GetText(&bstrExtendBefore);
  1652. if (bstrExtendBefore)
  1653. {
  1654. BSTR bstrNew = SysAllocStringLen(NULL, _cchComposition+cchExtendBefore+1);
  1655. if (bstrNew)
  1656. {
  1657. WCHAR *pNewText = (WCHAR *)bstrNew;
  1658. WCHAR *pText = (WCHAR *)bstrExtendBefore;
  1659. memcpy(pNewText, pText, cchExtendBefore * sizeof(WCHAR));
  1660. pNewText += cchExtendBefore;
  1661. pText = (WCHAR *)_bstrComposition;
  1662. memcpy(pNewText, pText, _cchComposition * sizeof(WCHAR));
  1663. *(pNewText+_cchComposition) = L'\0';
  1664. SysFreeString(_bstrComposition);
  1665. _bstrComposition = bstrNew;
  1666. _cchComposition += cchExtendBefore;
  1667. _acpBstrStart = acpStart;
  1668. }
  1669. SysFreeString(bstrExtendBefore);
  1670. }
  1671. pTextRange->Release();
  1672. }
  1673. }
  1674. if (cchExtendAfter > 0)
  1675. {
  1676. // Extend beyond current composition, append new text to the original text
  1677. ITextRange *pTextRange = NULL;
  1678. HRESULT hResult = _pTextMsgFilter->_pTextDoc->Range(cpCurrentCompEnd,
  1679. cpCurrentCompEnd+cchExtendAfter, &pTextRange);
  1680. if (pTextRange)
  1681. {
  1682. BSTR bstrExtend = NULL;
  1683. hResult = pTextRange->GetText(&bstrExtend);
  1684. if (bstrExtend)
  1685. {
  1686. BSTR bstrNew = SysAllocStringLen(NULL, _cchComposition+cchExtendAfter+1);
  1687. if (bstrNew)
  1688. {
  1689. WCHAR *pNewText = (WCHAR *)bstrNew;
  1690. WCHAR *pText = (WCHAR *)_bstrComposition;
  1691. memcpy(pNewText, pText, _cchComposition * sizeof(WCHAR));
  1692. pNewText += _cchComposition;
  1693. pText = (WCHAR *)bstrExtend;
  1694. memcpy(pNewText, pText, cchExtendAfter * sizeof(WCHAR));
  1695. *(pNewText+cchExtendAfter) = L'\0';
  1696. SysFreeString(_bstrComposition);
  1697. _bstrComposition = bstrNew;
  1698. _cchComposition += cchExtendAfter;
  1699. }
  1700. SysFreeString(bstrExtend);
  1701. }
  1702. pTextRange->Release();
  1703. }
  1704. }
  1705. }
  1706. }
  1707. if (pComposition)
  1708. {
  1709. HRESULT hr;
  1710. ITfRange *pRangeComp = NULL;
  1711. hr = pComposition->GetRange(&pRangeComp);
  1712. if (pRangeComp)
  1713. {
  1714. GetExtentAcpPrange(pRangeComp, _acpFocusRange, _cchFocusRange);
  1715. pRangeComp->Release();
  1716. }
  1717. }
  1718. return S_OK;
  1719. }
  1720. /*
  1721. * STDMETHODIMP CUIM::OnEndComposition()
  1722. *
  1723. * @mfunc
  1724. *
  1725. *
  1726. * @rdesc
  1727. *
  1728. */
  1729. STDAPI CUIM::OnEndComposition(
  1730. ITfCompositionView *pComposition)
  1731. {
  1732. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnEndComposition");
  1733. _fUIMTyping = 0;
  1734. _fEndTyping = 1;
  1735. _acpPreFocusRangeLast = _acpFocusRange;
  1736. _cchFocusRangeLast = _cchFocusRange;
  1737. _acpFocusRange = tomForward;
  1738. _cchFocusRange = 0;
  1739. return S_OK;
  1740. }
  1741. /*
  1742. * STDMETHODIMP CUIM::AdviseMouseSink()
  1743. *
  1744. * @mfunc
  1745. * Setup Mouse Sink to handle mouse operation
  1746. *
  1747. * @rdesc
  1748. * S_OK is mouse trap is added to link list
  1749. * CONNECT_E_NOCONNECTION is not added.
  1750. */
  1751. STDAPI CUIM::AdviseMouseSink(
  1752. ITfRangeACP *pRangeACP,
  1753. ITfMouseSink *pSinkInput,
  1754. DWORD *pdwCookie)
  1755. {
  1756. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::AdviseMouseSink");
  1757. if (_fShutDown)
  1758. return CONNECT_E_NOCONNECTION;
  1759. if (!pRangeACP || !pSinkInput || !pdwCookie)
  1760. return E_POINTER;
  1761. CTFMOUSETRAP *pSinkNew = NULL;
  1762. LONG cpMouseStart, cchMosueComp;
  1763. ITfMouseSink *pSinkMouseInput = NULL;
  1764. if (FAILED(pSinkInput->QueryInterface(IID_ITfMouseSink, (void **)&pSinkMouseInput)))
  1765. return E_FAIL;
  1766. if (GetExtentAcpPrange(pRangeACP, cpMouseStart, cchMosueComp))
  1767. {
  1768. if (!_pSinkList) // No first link
  1769. {
  1770. _pSinkList = new CTFMOUSETRAP;
  1771. pSinkNew = _pSinkList;
  1772. }
  1773. else
  1774. {
  1775. if (!(_pSinkList->pMouseSink)) // The first link is empty
  1776. pSinkNew = _pSinkList;
  1777. else
  1778. {
  1779. pSinkNew = new CTFMOUSETRAP;
  1780. if (pSinkNew) // Add new trap to the bottom of list
  1781. {
  1782. CTFMOUSETRAP *pSink = _pSinkList;
  1783. while (pSink->pNext) // Find the bottom of list
  1784. pSink = pSink->pNext;
  1785. pSink->pNext = pSinkNew;
  1786. }
  1787. }
  1788. }
  1789. if (pSinkNew)
  1790. {
  1791. pSinkNew->dwCookie = *pdwCookie = (DWORD)(DWORD_PTR)pSinkMouseInput;
  1792. pSinkNew->cpMouseStart = cpMouseStart;
  1793. pSinkNew->cchMosueComp = cchMosueComp;
  1794. pSinkNew->pMouseSink = pSinkMouseInput;
  1795. _fMosueSink = 1;
  1796. return S_OK;
  1797. }
  1798. }
  1799. if (pSinkMouseInput)
  1800. pSinkMouseInput->Release();
  1801. return CONNECT_E_NOCONNECTION;
  1802. }
  1803. /*
  1804. * STDMETHODIMP CUIM::UnadviseMouseSink()
  1805. *
  1806. * @mfunc
  1807. * Remove Mouse Sink
  1808. *
  1809. * @rdesc
  1810. *
  1811. */
  1812. STDAPI CUIM::UnadviseMouseSink(
  1813. DWORD dwCookie)
  1814. {
  1815. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::UnadviseMouseSink");
  1816. if (_fShutDown)
  1817. return CONNECT_E_NOCONNECTION;
  1818. if (_fMosueSink == 0)
  1819. return CONNECT_E_NOCONNECTION;
  1820. Assert(_pSinkList);
  1821. CTFMOUSETRAP *pSink = _pSinkList;
  1822. CTFMOUSETRAP *pSinkParent = NULL;
  1823. while (pSink->dwCookie != dwCookie) // Find the cookie
  1824. {
  1825. pSinkParent = pSink;
  1826. pSink = pSink->pNext;
  1827. if (!pSink) // Reach list bottom?
  1828. return CONNECT_E_NOCONNECTION; // cookie not found
  1829. }
  1830. Assert(pSink->pMouseSink);
  1831. if (pSink->pMouseSink)
  1832. pSink->pMouseSink->Release();
  1833. if (pSink == _pSinkList) // Match the first link?
  1834. {
  1835. if (pSink->pNext)
  1836. _pSinkList = pSink->pNext;
  1837. else
  1838. {
  1839. _fMosueSink = 0; // No more mouse trap left
  1840. memset(_pSinkList, 0, sizeof(CTFMOUSETRAP));
  1841. }
  1842. }
  1843. else
  1844. { // Match link other than the first link
  1845. Assert(pSinkParent);
  1846. pSinkParent->pNext = pSink->pNext;
  1847. delete pSink;
  1848. }
  1849. return S_OK;
  1850. }
  1851. /*
  1852. * STDMETHODIMP CUIM::Init()
  1853. *
  1854. * @mfunc
  1855. *
  1856. *
  1857. * @rdesc
  1858. *
  1859. */
  1860. STDMETHODIMP CUIM::Init()
  1861. {
  1862. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::Init");
  1863. HRESULT hResult;
  1864. // Init some CUIM data
  1865. _cCallMgrLevels = 1;
  1866. _fAllowUIMLock = 1;
  1867. hResult = _pTextMsgFilter->_pTim->CreateDocumentMgr(&_pdim);
  1868. if (FAILED(hResult))
  1869. goto ExitError;
  1870. hResult = _pdim->CreateContext(_pTextMsgFilter->_tid, 0, (ITextStoreACP *)this, &_pic, &_editCookie);
  1871. if (FAILED(hResult))
  1872. goto ExitError;
  1873. hResult = _pdim->Push(_pic);
  1874. if (FAILED(hResult))
  1875. goto ExitError;
  1876. // Get the interface for rendering markup
  1877. if (_pic->QueryInterface(IID_ITfContextRenderingMarkup, (void **)&_pContextRenderingMarkup) != S_OK)
  1878. _pContextRenderingMarkup = NULL;
  1879. _pDAM = NULL;
  1880. _pCategoryMgr = NULL;
  1881. hResult = CoCreateInstance(CLSID_TF_DisplayAttributeMgr, NULL, CLSCTX_INPROC_SERVER,
  1882. IID_ITfDisplayAttributeMgr, (void**)&(_pDAM));
  1883. hResult = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER,
  1884. IID_ITfCategoryMgr, (void**)&_pCategoryMgr);
  1885. _pTextEditSink = new CTextEditSink(EndEditCallback, this);
  1886. if (_pTextEditSink)
  1887. {
  1888. if (FAILED(_pTextEditSink->_Advise(_pic)))
  1889. {
  1890. delete _pTextEditSink;
  1891. _pTextEditSink = NULL;
  1892. }
  1893. }
  1894. LRESULT lresult;
  1895. _pTextMsgFilter->_pTextService->TxSendMessage(EM_SETUPNOTIFY, 1, (LPARAM)(ITxNotify *)this, &lresult);
  1896. _fAllowUIMLock = 0;
  1897. return S_OK;
  1898. ExitError:
  1899. Uninit();
  1900. return hResult;
  1901. }
  1902. /*
  1903. * void CUIM::Uninit()
  1904. *
  1905. * @mfunc
  1906. *
  1907. *
  1908. * @rdesc
  1909. *
  1910. */
  1911. void CUIM::Uninit()
  1912. {
  1913. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::Uninit");
  1914. if (_pTextFont)
  1915. {
  1916. _pTextFont->Release();
  1917. _pTextFont = NULL;
  1918. }
  1919. if (_parITfEnumRange)
  1920. {
  1921. int idx = _parITfEnumRange->Count();
  1922. for ( ; idx > 0; idx--)
  1923. {
  1924. IEnumTfRanges **ppEnumRange = (IEnumTfRanges **)(_parITfEnumRange->Elem(idx-1));
  1925. if (ppEnumRange && *ppEnumRange)
  1926. (*ppEnumRange)->Release();
  1927. }
  1928. _parITfEnumRange->Clear(AF_DELETEMEM);
  1929. delete _parITfEnumRange;
  1930. _parITfEnumRange = NULL;
  1931. }
  1932. if (_parAttrsVal)
  1933. {
  1934. InitAttrVarArray(FALSE);
  1935. FreePv (_parAttrsVal);
  1936. _parAttrsVal = NULL;
  1937. }
  1938. if (_pSinkList)
  1939. {
  1940. CTFMOUSETRAP *pSink = _pSinkList;
  1941. _pSinkList = NULL;
  1942. // Delete the Mouse sinks list
  1943. while (1)
  1944. {
  1945. CTFMOUSETRAP *pNext = pSink->pNext;
  1946. if(pSink->pMouseSink)
  1947. pSink->pMouseSink->Release();
  1948. delete pSink;
  1949. if (!pNext) // Any more?
  1950. break; // Done.
  1951. pSink = pNext;
  1952. }
  1953. }
  1954. if (_pContextRenderingMarkup)
  1955. {
  1956. _pContextRenderingMarkup->Release();
  1957. _pContextRenderingMarkup = NULL;
  1958. }
  1959. if (_pDAM)
  1960. {
  1961. _pDAM->Release();
  1962. _pDAM = NULL;
  1963. }
  1964. if (_pCategoryMgr)
  1965. {
  1966. _pCategoryMgr->Release();
  1967. _pCategoryMgr = NULL;
  1968. }
  1969. if (_pTextEditSink)
  1970. {
  1971. _pTextEditSink->_Unadvise();
  1972. delete _pTextEditSink;
  1973. _pTextEditSink = NULL;
  1974. }
  1975. if (_pdim && _pic)
  1976. _pdim->Pop(TF_POPF_ALL);
  1977. if (_pic)
  1978. {
  1979. _pic->Release();
  1980. _pic = NULL;
  1981. }
  1982. if (_pdim)
  1983. {
  1984. _pdim->Release();
  1985. _pdim = NULL;
  1986. }
  1987. if (_pacrUl)
  1988. {
  1989. _pacrUl->Clear(AF_DELETEMEM);
  1990. delete _pacrUl;
  1991. _pacrUl = NULL;
  1992. }
  1993. }
  1994. /*
  1995. * void CreateUIM()
  1996. *
  1997. * @mfunc
  1998. *
  1999. *
  2000. * @rdesc
  2001. *
  2002. */
  2003. BOOL CreateUIM(CTextMsgFilter *pTextMsgFilter)
  2004. {
  2005. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CreateUIM");
  2006. BOOL fCreateUIM = FALSE;
  2007. HRESULT hResult = CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER,
  2008. IID_ITfThreadMgr, (void**)&(pTextMsgFilter->_pTim));
  2009. if (hResult == S_OK)
  2010. {
  2011. // ready to start interacting
  2012. if (pTextMsgFilter->_pTim->Activate(&(pTextMsgFilter->_tid)) == S_OK)
  2013. {
  2014. pTextMsgFilter->_pCUIM = new CUIM(pTextMsgFilter);
  2015. if (pTextMsgFilter->_pCUIM)
  2016. {
  2017. hResult = pTextMsgFilter->_pCUIM->Init();
  2018. if (hResult == S_OK)
  2019. fCreateUIM = TRUE;
  2020. else
  2021. {
  2022. delete pTextMsgFilter->_pCUIM;
  2023. pTextMsgFilter->_pCUIM = NULL;
  2024. }
  2025. }
  2026. }
  2027. if (!fCreateUIM)
  2028. {
  2029. pTextMsgFilter->_pTim->Release();
  2030. pTextMsgFilter->_pTim = NULL;
  2031. }
  2032. else if (GetFocus() == pTextMsgFilter->_hwnd)
  2033. pTextMsgFilter->_pCUIM->OnSetFocus();
  2034. }
  2035. return fCreateUIM;
  2036. }
  2037. /*
  2038. * BOOL CUIM::GetExtentAcpPrange()
  2039. *
  2040. * @mfunc
  2041. *
  2042. *
  2043. * @rdesc
  2044. *
  2045. */
  2046. BOOL CUIM::GetExtentAcpPrange(
  2047. ITfRange *ITfRangeIn,
  2048. long &cpFirst,
  2049. long &cpLim)
  2050. {
  2051. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetExtentAcpPrange");
  2052. ITfRangeACP *prangeACP = NULL;
  2053. if (SUCCEEDED(ITfRangeIn->QueryInterface(IID_ITfRangeACP, (void **)&prangeACP)))
  2054. {
  2055. prangeACP->GetExtent(&cpFirst, &cpLim);
  2056. prangeACP->Release();
  2057. return TRUE;
  2058. }
  2059. return FALSE;
  2060. }
  2061. /*
  2062. * HRESULT CUIM::EndEditCallback()
  2063. *
  2064. * @mfunc
  2065. *
  2066. *
  2067. * @rdesc
  2068. *
  2069. */
  2070. HRESULT CUIM::EndEditCallback(ITfEditRecord *pEditRecord, void *pv)
  2071. {
  2072. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::EndEditCallback");
  2073. HRESULT hr;
  2074. CUIM *_this = (CUIM *)pv;
  2075. IEnumTfRanges *pEnumRanges;
  2076. const GUID *rgGUID[1];
  2077. if (!(_this->_fWriteLockOn))
  2078. {
  2079. _this->HandleTempDispAttr(pEditRecord);
  2080. return S_OK;
  2081. }
  2082. // Get lid changes
  2083. rgGUID[0] = &GUID_PROP_LANGID;
  2084. hr = pEditRecord->GetTextAndPropertyUpdates(0, (const GUID**)rgGUID, 1, &pEnumRanges);
  2085. if (SUCCEEDED(hr))
  2086. {
  2087. _this->HandleLangID (pEnumRanges);
  2088. pEnumRanges->Release();
  2089. }
  2090. // Get attribute changes
  2091. rgGUID[0] = &GUID_PROP_ATTRIBUTE;
  2092. hr = pEditRecord->GetTextAndPropertyUpdates(0, (const GUID**)rgGUID, 1, &pEnumRanges);
  2093. if (SUCCEEDED(hr))
  2094. {
  2095. _this->HandlePropAttrib (pEnumRanges);
  2096. pEnumRanges->Release();
  2097. }
  2098. rgGUID[0] = &GUID_PROP_COMPOSING;
  2099. hr = pEditRecord->GetTextAndPropertyUpdates(0, (const GUID**)rgGUID, 1, &pEnumRanges);
  2100. if (SUCCEEDED(hr))
  2101. {
  2102. // Save the TextDelta to be process after the lock is off
  2103. if (!(_this->_parITfEnumRange))
  2104. _this->_parITfEnumRange = new CITfEnumRange();
  2105. if (_this->_parITfEnumRange)
  2106. {
  2107. LONG idxItem;
  2108. IEnumTfRanges **ppItem;
  2109. ppItem = _this->_parITfEnumRange->Add(1, &idxItem);
  2110. if (ppItem)
  2111. *ppItem = pEnumRanges;
  2112. else
  2113. pEnumRanges->Release(); // Add fail, forget it
  2114. }
  2115. }
  2116. return S_OK;
  2117. }
  2118. /*
  2119. * void CUIM::HandleDispAttr(*pITfRangeProp, var, cp, cch)
  2120. *
  2121. * @mfunc
  2122. *
  2123. *
  2124. * @rdesc
  2125. *
  2126. */
  2127. void CUIM::HandleDispAttr(
  2128. ITfRange *pITfRangeProp,
  2129. VARIANT &var,
  2130. long acpStartRange,
  2131. long cch)
  2132. {
  2133. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::HandleDispAttr");
  2134. HRESULT hResult = TRUE;
  2135. if (pITfRangeProp)
  2136. hResult = GetExtentAcpPrange(pITfRangeProp, acpStartRange, cch);
  2137. if (hResult && cch > 0)
  2138. {
  2139. ITextRange *pTextRange = NULL;
  2140. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStartRange, acpStartRange+cch, &pTextRange);
  2141. if (pTextRange)
  2142. {
  2143. ITextFont *pFont = NULL;
  2144. if (_pTextFont)
  2145. _pTextFont->GetDuplicate(&pFont);
  2146. if (pFont)
  2147. {
  2148. if (var.vt == VT_I4)
  2149. {
  2150. GUID guid;
  2151. ITfDisplayAttributeInfo *pDAI = NULL;
  2152. TF_DISPLAYATTRIBUTE da;
  2153. if (_pCategoryMgr->GetGUID(var.ulVal, &guid) == S_OK &&
  2154. SUCCEEDED(_pDAM->GetDisplayAttributeInfo(guid, &pDAI, NULL)))
  2155. {
  2156. COLORREF cr;
  2157. long lUnderline;
  2158. long idx = 0;
  2159. Assert(pDAI);
  2160. pDAI->GetAttributeInfo(&da);
  2161. if (GetUIMAttributeColor(&da.crText, &cr))
  2162. pFont->SetForeColor(cr);
  2163. if (GetUIMAttributeColor(&da.crBk, &cr))
  2164. pFont->SetBackColor(cr);
  2165. lUnderline = GetUIMUnderline(da, idx, cr);
  2166. if (lUnderline != tomNone)
  2167. {
  2168. if (idx)
  2169. {
  2170. hResult = _pTextMsgFilter->_pTextDoc->SetEffectColor(idx, cr);
  2171. if (hResult == S_OK)
  2172. lUnderline += (idx << 8);
  2173. }
  2174. pFont->SetUnderline(lUnderline);
  2175. }
  2176. }
  2177. if (pDAI)
  2178. pDAI->Release();
  2179. }
  2180. pTextRange->SetFont(pFont);
  2181. pFont->Release();
  2182. }
  2183. pTextRange->Release();
  2184. }
  2185. }
  2186. }
  2187. /*
  2188. * HRESULT CUIM::HandlePropAttrib(ITfEnumTextDeltas *pEnumTextDeltas)
  2189. *
  2190. * @mfunc
  2191. *
  2192. *
  2193. * @rdesc
  2194. *
  2195. */
  2196. HRESULT CUIM::HandlePropAttrib(IEnumTfRanges *pEnumRanges)
  2197. {
  2198. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::HandlePropAttrib");
  2199. ITfRange *pITfRange = NULL;
  2200. if (!_pDAM || !_pCategoryMgr || _fInterimChar)
  2201. return S_OK;
  2202. ITfProperty *pProp = NULL;
  2203. HRESULT hResult = _pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp);
  2204. if (SUCCEEDED(hResult))
  2205. {
  2206. long lCount;
  2207. TS_SELECTION_ACP acpSelection;
  2208. ULONG cFetched;
  2209. GetSelection(0, 0, &acpSelection, &cFetched);
  2210. _pTextMsgFilter->_pTextDoc->Freeze(&lCount); // Turn off display
  2211. while (pEnumRanges->Next(1, &pITfRange, NULL) == S_OK)
  2212. {
  2213. BOOL fAnyPropRange = FALSE;
  2214. IEnumTfRanges *pEnumPropRange = NULL;
  2215. long acpRangeStart, ccpRangeStart;
  2216. VARIANT var;
  2217. GetExtentAcpPrange(pITfRange, acpRangeStart, ccpRangeStart);
  2218. // Create a property Enum for ranges within pITfRange
  2219. if (pProp->EnumRanges(_editCookie, &pEnumPropRange, pITfRange) == S_OK)
  2220. {
  2221. ITfRange *pITfRangeProp = NULL;
  2222. while (pEnumPropRange->Next(1, &pITfRangeProp, NULL) == S_OK)
  2223. {
  2224. VariantInit(&var);
  2225. if (!fAnyPropRange)
  2226. {
  2227. long acpCurrentRange, ccpCurrent;
  2228. if (GetExtentAcpPrange(pITfRangeProp, acpCurrentRange, ccpCurrent))
  2229. {
  2230. if (acpCurrentRange > acpRangeStart)
  2231. HandleDispAttr(NULL, var, acpRangeStart, acpCurrentRange - acpRangeStart);
  2232. }
  2233. fAnyPropRange = TRUE;
  2234. }
  2235. pProp->GetValue(_editCookie, pITfRangeProp, &var);
  2236. HandleDispAttr(pITfRangeProp, var);
  2237. VariantClear(&var);
  2238. pITfRangeProp->Release();
  2239. }
  2240. pEnumPropRange->Release();
  2241. }
  2242. if (!fAnyPropRange)
  2243. {
  2244. // Whole string doesn't contain any disp. attribute.
  2245. VariantInit(&var);
  2246. HandleDispAttr(pITfRange, var);
  2247. }
  2248. pITfRange->Release();
  2249. }
  2250. pProp->Release();
  2251. // Only want to scroll back if its not a selection
  2252. if (acpSelection.acpStart == acpSelection.acpEnd)
  2253. {
  2254. ITextRange *pTextRange;
  2255. hResult = _pTextMsgFilter->_pTextDoc->Range(acpSelection.acpStart, acpSelection.acpEnd, &pTextRange);
  2256. if (pTextRange)
  2257. {
  2258. pTextRange->Select();
  2259. pTextRange->Release();
  2260. }
  2261. }
  2262. _pTextMsgFilter->_pTextDoc->Unfreeze(&lCount); // Turn on display
  2263. }
  2264. return S_OK;
  2265. }
  2266. /*
  2267. * void CUIM::GetUIMUnderline()
  2268. *
  2269. * @mfunc
  2270. *
  2271. *
  2272. * @rdesc
  2273. *
  2274. */
  2275. long CUIM::GetUIMUnderline(
  2276. TF_DISPLAYATTRIBUTE &da,
  2277. long &idx,
  2278. COLORREF &cr)
  2279. {
  2280. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetUIMUnderline");
  2281. long lStyle = tomNone;
  2282. idx = 0;
  2283. if (da.lsStyle != TF_LS_NONE)
  2284. {
  2285. switch(da.lsStyle)
  2286. {
  2287. // case TFLS_SOLID:
  2288. default:
  2289. lStyle = da.fBoldLine ? tomThick : tomSingle;
  2290. break;
  2291. case TF_LS_DOT:
  2292. case TF_LS_DASH: // Dash line should show as dotted line
  2293. lStyle = tomDotted;
  2294. break;
  2295. case TF_LS_SQUIGGLE:
  2296. lStyle = tomWave;
  2297. break;
  2298. }
  2299. if (GetUIMAttributeColor(&da.crLine, &cr))
  2300. {
  2301. if (!_pacrUl) // Create the array if it is not there
  2302. _pacrUl = new CUlColorArray();
  2303. if (_pacrUl)
  2304. {
  2305. LONG idxMax = _pacrUl->Count();
  2306. LONG idxItem;
  2307. COLORREF *pCr;
  2308. // Check if this item is in the array
  2309. for (idxItem=0; idxItem < idxMax; idxItem++)
  2310. {
  2311. pCr = _pacrUl->Elem(idxItem);
  2312. Assert(pCr);
  2313. if (*pCr == cr)
  2314. idx = idxItem + 1; // found it
  2315. }
  2316. if (!idx)
  2317. {
  2318. // Add it to array
  2319. pCr = _pacrUl->Add(1, &idxItem);
  2320. if (pCr)
  2321. {
  2322. *pCr = cr;
  2323. idx = idxItem + 1; // return new idx
  2324. }
  2325. }
  2326. }
  2327. }
  2328. }
  2329. return lStyle;
  2330. }
  2331. /*
  2332. * void CUIM::HandleFinalString(ITfRange *pPropRange, long acpStartRange, long cch)
  2333. * @mfunc
  2334. *
  2335. *
  2336. * @rdesc
  2337. *
  2338. */
  2339. void CUIM::HandleFinalString(
  2340. ITfRange *pPropRange,
  2341. long acpStartRange,
  2342. long cch,
  2343. BOOL fEndComposition)
  2344. {
  2345. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::HandleFinalString");
  2346. HRESULT hResult = TRUE;
  2347. if (pPropRange)
  2348. hResult = GetExtentAcpPrange(pPropRange, acpStartRange, cch);
  2349. if (hResult == TRUE && cch)
  2350. {
  2351. if (_bstrComposition && !fEndComposition)
  2352. return;
  2353. ITextRange *pTextRange = NULL;
  2354. ITextSelection *pTextSel = NULL;
  2355. long cpSelMin = 0, cpSelMax = 0;
  2356. BOOL fTextSel = FALSE;
  2357. // Need to maintain current selection
  2358. hResult = _pTextMsgFilter->_pTextDoc->GetSelectionEx(&pTextSel);
  2359. if (pTextSel)
  2360. {
  2361. hResult = pTextSel->GetStart(&cpSelMin);
  2362. hResult = pTextSel->GetEnd(&cpSelMax);
  2363. pTextSel->Release();
  2364. fTextSel = TRUE;
  2365. }
  2366. if (_bstrComposition)
  2367. {
  2368. long cpEnd;
  2369. GetEndACP(&cpEnd);
  2370. cch = _cchComposition + cpEnd - _cpEnd;
  2371. acpStartRange = _acpBstrStart;
  2372. }
  2373. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStartRange, acpStartRange+cch, &pTextRange);
  2374. if (pTextRange)
  2375. {
  2376. long cEmbeddedObjects = 0;
  2377. BSTR bstr = NULL;
  2378. if (cch)
  2379. hResult = pTextRange->GetText(&bstr);
  2380. if (SUCCEEDED(hResult) && (bstr || cch == 0))
  2381. {
  2382. long lCount;
  2383. BSTR bstrTemp = NULL;
  2384. if (!_fAnyWriteOperation) // No new string
  2385. goto IGNORE_STRING; // no need to insert
  2386. if (_bstrComposition)
  2387. {
  2388. if (bstr)
  2389. {
  2390. WCHAR *pStr1 = _bstrComposition;
  2391. WCHAR *pStr2 = bstr;
  2392. while (*pStr1 != 0 && *pStr1 == *pStr2)
  2393. {
  2394. pStr1++;
  2395. pStr2++;
  2396. }
  2397. if (*pStr1 == *pStr2) // Same data, no need to insert
  2398. {
  2399. if (acpStartRange == cpSelMin)
  2400. {
  2401. pTextRange->Collapse(tomFalse);
  2402. pTextRange->Select();
  2403. }
  2404. goto IGNORE_STRING;
  2405. }
  2406. }
  2407. bstrTemp = _bstrComposition;
  2408. }
  2409. // Build embed object data if necessary
  2410. EMBEDOBJECT arEmbeddObjects[5];
  2411. EMBEDOBJECT *pEmbeddObjects = arEmbeddObjects;
  2412. if (bstr)
  2413. cEmbeddedObjects =
  2414. BuildObject(pTextRange, bstr, &pEmbeddObjects, ARRAY_SIZE(arEmbeddObjects));
  2415. _pTextMsgFilter->_pTextDoc->Freeze(&lCount); // Turn off display
  2416. // We want the final text to be in the undo stack.
  2417. // So, we first delete the final string.
  2418. // Resume undo and add the final string back. Yuk!
  2419. if (bstrTemp && _cObjects)
  2420. {
  2421. long cpMin;
  2422. long cchBstr = SysStringLen(bstrTemp);
  2423. pTextRange->GetStart(&cpMin);
  2424. InsertTextandObject(pTextRange, bstrTemp, _pObjects, _cObjects);
  2425. pTextRange->SetRange(cpMin, cpMin+cchBstr);
  2426. }
  2427. else
  2428. pTextRange->SetText(bstrTemp);
  2429. if (_pTextFont)
  2430. pTextRange->SetFont(_pTextFont);
  2431. _pTextMsgFilter->_pTextDoc->Undo(tomResume, NULL);
  2432. _pTextMsgFilter->_pTextDoc->SetNotificationMode(tomTrue);
  2433. if (cEmbeddedObjects == 0)
  2434. pTextRange->SetText(bstr);
  2435. else
  2436. {
  2437. InsertTextandObject(pTextRange, bstr, pEmbeddObjects, cEmbeddedObjects);
  2438. CleanUpObjects(cEmbeddedObjects, pEmbeddObjects);
  2439. if (pEmbeddObjects != arEmbeddObjects)
  2440. delete pEmbeddObjects;
  2441. }
  2442. _pTextMsgFilter->_pTextDoc->Undo(tomSuspend, NULL);
  2443. // Hold notification if needed
  2444. if (!(_pTextMsgFilter->_fIMEAlwaysNotify))
  2445. _pTextMsgFilter->_pTextDoc->SetNotificationMode(tomFalse);
  2446. if (fTextSel)
  2447. {
  2448. ITextRange *pSelRange = NULL;
  2449. // restore previous selection.
  2450. hResult = _pTextMsgFilter->_pTextDoc->Range(cpSelMin, cpSelMax, &pSelRange);
  2451. if (pSelRange)
  2452. {
  2453. pSelRange->Select();
  2454. pSelRange->Release();
  2455. }
  2456. }
  2457. else
  2458. {
  2459. pTextRange->Collapse(tomFalse);
  2460. pTextRange->Select();
  2461. }
  2462. _pTextMsgFilter->_pTextDoc->Unfreeze(&lCount); // Turn on display
  2463. }
  2464. IGNORE_STRING:
  2465. if (bstr)
  2466. SysFreeString(bstr);
  2467. pTextRange->Release();
  2468. }
  2469. }
  2470. }
  2471. /*
  2472. * HRESULT CUIM::HandleFocusRange(IEnumTfRanges *pEnumRanges)
  2473. * @mfunc
  2474. *
  2475. *
  2476. * @rdesc
  2477. *
  2478. */
  2479. HRESULT CUIM::HandleFocusRange(IEnumTfRanges *pEnumRanges)
  2480. {
  2481. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::HandleFocusRange");
  2482. ITfProperty *pProp = NULL;
  2483. ITfRange *pITfRange;
  2484. HRESULT hResult = _pic->GetProperty(GUID_PROP_COMPOSING, &pProp);
  2485. BOOL fAnyPendingFocusRange = FALSE;
  2486. if (SUCCEEDED(hResult))
  2487. {
  2488. // Enumerate all the changes
  2489. pEnumRanges->Reset();
  2490. while (pEnumRanges->Next(1, &pITfRange, NULL) == S_OK)
  2491. {
  2492. BOOL fAnyPropRange = FALSE;
  2493. IEnumTfRanges *pEnumPropRange = NULL;
  2494. long acpStartRange, ccp;
  2495. GetExtentAcpPrange(pITfRange, acpStartRange, ccp);
  2496. // Create a property Enum for ranges within pITfRange
  2497. if (pProp->EnumRanges(_editCookie, &pEnumPropRange, pITfRange) == S_OK)
  2498. {
  2499. ITfRange *pPropRange = NULL;
  2500. // Try to get a value for the property
  2501. while (pEnumPropRange->Next(1, &pPropRange, NULL) == S_OK)
  2502. {
  2503. VARIANT var;
  2504. VariantInit(&var);
  2505. if (!fAnyPropRange)
  2506. {
  2507. long acpCurrentRange, ccpCurrent;
  2508. GetExtentAcpPrange(pPropRange, acpCurrentRange, ccpCurrent);
  2509. if (acpCurrentRange > acpStartRange)
  2510. {
  2511. // We have a final string before the new string.
  2512. HandleFinalString(NULL, acpStartRange, acpCurrentRange - acpStartRange);
  2513. }
  2514. fAnyPropRange = TRUE;
  2515. }
  2516. hResult = pProp->GetValue(_editCookie, pPropRange, &var);
  2517. if (SUCCEEDED(hResult) && var.vt == VT_I4 && var.ulVal == 0)
  2518. hResult = E_FAIL; // Just as good as not finding the range
  2519. else
  2520. fAnyPendingFocusRange = TRUE;
  2521. VariantClear(&var);
  2522. if (hResult != S_OK)
  2523. HandleFinalString(pPropRange);
  2524. pPropRange->Release();
  2525. }
  2526. pEnumPropRange->Release();
  2527. }
  2528. if (!fAnyPropRange) // Any focus range?
  2529. HandleFinalString(pITfRange); // No --> the whole string is final string
  2530. if (_fEndTyping && _bstrComposition && _acpBstrStart != tomForward)
  2531. HandleFinalString(NULL, _acpBstrStart, _cchComposition, TRUE);
  2532. pITfRange->Release();
  2533. }
  2534. pProp->Release();
  2535. }
  2536. return S_OK;
  2537. }
  2538. /*
  2539. * HRESULT CUIM::HandleLangID(IEnumTfRanges *pEnumRanges)
  2540. *
  2541. * @mfunc
  2542. *
  2543. *
  2544. * @rdesc
  2545. *
  2546. */
  2547. HRESULT CUIM::HandleLangID(IEnumTfRanges *pEnumRanges)
  2548. {
  2549. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::HandleLangID");
  2550. ITfProperty *pProp = NULL;
  2551. ITfRange *pITfRange;
  2552. HRESULT hResult;
  2553. LCID lcid;
  2554. // TODO:
  2555. // if _pTextFont is NULL, setup _pTextFont to handle the langID.
  2556. if (!_pTextFont)
  2557. return S_OK;
  2558. hResult = _pic->GetProperty(GUID_PROP_LANGID, &pProp);
  2559. if (SUCCEEDED(hResult))
  2560. {
  2561. // Enumerate all the changes
  2562. pEnumRanges->Reset();
  2563. while (pEnumRanges->Next(1, &pITfRange, NULL) == S_OK)
  2564. {
  2565. IEnumTfRanges *pEnumPropRange = NULL;
  2566. // Create a property Enum for ranges within pITfRange
  2567. if (pProp->EnumRanges(_editCookie, &pEnumPropRange, pITfRange) == S_OK)
  2568. {
  2569. ITfRange *pPropRange = NULL;
  2570. if (pEnumPropRange->Next(1, &pPropRange, NULL) == S_OK)
  2571. {
  2572. VARIANT var;
  2573. VariantInit(&var);
  2574. hResult = pProp->GetValue(_editCookie, pITfRange, &var);
  2575. if (SUCCEEDED(hResult) && var.vt == VT_I4)
  2576. {
  2577. lcid = (LCID)var.ulVal;
  2578. UINT cpgProp = CodePageFromCharRep(CharRepFromLID(lcid));
  2579. ITextFont *pTextFont=NULL;
  2580. _pTextFont->GetDuplicate(&pTextFont);
  2581. if (pTextFont)
  2582. {
  2583. HRESULT hResult;
  2584. LONG acpStart, cchStart;
  2585. ITextRange *pTextRange;
  2586. UINT cpgTemp = _pTextMsgFilter->_uKeyBoardCodePage;
  2587. GetExtentAcpPrange(pITfRange, acpStart, cchStart);
  2588. if (cchStart)
  2589. {
  2590. _pTextMsgFilter->_uKeyBoardCodePage = cpgProp;
  2591. CIme::CheckKeyboardFontMatching(acpStart, _pTextMsgFilter, pTextFont);
  2592. _pTextMsgFilter->_uKeyBoardCodePage = cpgTemp;
  2593. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStart, acpStart+cchStart, &pTextRange);
  2594. if (pTextRange)
  2595. {
  2596. pTextRange->SetFont(pTextFont);
  2597. pTextRange->Release();
  2598. }
  2599. }
  2600. pTextFont->Release();
  2601. }
  2602. }
  2603. VariantClear(&var);
  2604. pPropRange->Release();
  2605. }
  2606. pEnumPropRange->Release();
  2607. }
  2608. pITfRange->Release();
  2609. }
  2610. pProp->Release();
  2611. }
  2612. return S_OK;
  2613. }
  2614. /*
  2615. * HRESULT CUIM::OnSetFocus(BOOL fEnable)
  2616. *
  2617. * @mfunc
  2618. *
  2619. *
  2620. */
  2621. void CUIM::OnSetFocus(BOOL fEnable)
  2622. {
  2623. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnSetFocus");
  2624. _pTextMsgFilter->_pTim->SetFocus(fEnable ? _pdim : NULL);
  2625. }
  2626. /*
  2627. * HRESULT CUIM::CompleteUIMText()
  2628. *
  2629. * @mfunc
  2630. *
  2631. *
  2632. */
  2633. void CUIM::CompleteUIMText()
  2634. {
  2635. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::CompleteUIMText");
  2636. HRESULT hResult;
  2637. ITfContextOwnerCompositionServices *pCompositionServices;
  2638. _fAllowUIMLock = 1;
  2639. Assert(_pic);
  2640. if (_pic->QueryInterface(IID_ITfContextOwnerCompositionServices, (void **)&pCompositionServices) == S_OK)
  2641. {
  2642. // passing in NULL means "all compositions"
  2643. hResult = pCompositionServices->TerminateComposition(NULL);
  2644. pCompositionServices->Release();
  2645. }
  2646. _fAllowUIMLock = 0;
  2647. }
  2648. /*
  2649. * BOOL CUIM::GetUIMAttributeColor()
  2650. *
  2651. * @mfunc
  2652. * Helper routine to get UIM color
  2653. *
  2654. * @rdesc
  2655. * TRUE if we setup input pcr with the UIM color
  2656. *
  2657. */
  2658. BOOL CUIM::GetUIMAttributeColor(TF_DA_COLOR *pdac, COLORREF *pcr)
  2659. {
  2660. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetUIMAttributeColor");
  2661. BOOL fRetCode = FALSE;
  2662. switch (pdac->type)
  2663. {
  2664. //case TFCT_NONE:
  2665. // return FALSE;
  2666. case TF_CT_SYSCOLOR:
  2667. *pcr = GetSysColor(pdac->nIndex);
  2668. fRetCode = TRUE;
  2669. break;
  2670. case TF_CT_COLORREF:
  2671. *pcr = pdac->cr;
  2672. fRetCode = TRUE;
  2673. break;
  2674. }
  2675. return fRetCode;
  2676. }
  2677. /*
  2678. * void CUIM::OnUIMTypingDone()
  2679. *
  2680. * @mfunc
  2681. * Helper routine to cleanup after UIM Typing is done
  2682. *
  2683. */
  2684. void CUIM::OnUIMTypingDone()
  2685. {
  2686. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::OnUIMTypingDone");
  2687. if (_pTextFont)
  2688. {
  2689. _pTextFont->Release();
  2690. _pTextFont = NULL;
  2691. }
  2692. CleanUpComposition();
  2693. // Reset Korean block caret if needed
  2694. if (_fInterimChar)
  2695. {
  2696. _fInterimChar = 0;
  2697. _pTextMsgFilter->_pTextDoc->SetCaretType(tomNormalCaret); // Reset Block caret mode
  2698. }
  2699. _fAnyWriteOperation = 0;
  2700. _pTextMsgFilter->_pTextDoc->Undo(tomResume, NULL);
  2701. _pTextMsgFilter->_pTextDoc->SetNotificationMode(tomTrue);
  2702. if (_pacrUl)
  2703. _pacrUl->Clear(AF_DELETEMEM);
  2704. };
  2705. /*
  2706. * BOOL CUIM::GetGUIDATOMFromGUID()
  2707. *
  2708. * @mfunc
  2709. * Helper routine to get GUIDATOM from UIM
  2710. *
  2711. */
  2712. BOOL CUIM::GetGUIDATOMFromGUID(
  2713. REFGUID rguid,
  2714. TfGuidAtom *pguidatom)
  2715. {
  2716. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetGUIDATOMFromGUID");
  2717. if (_pCategoryMgr && _pCategoryMgr->RegisterGUID(rguid, pguidatom) == S_OK)
  2718. return TRUE;
  2719. return FALSE;
  2720. }
  2721. /*
  2722. * BOOL CUIM::GetAttrs()
  2723. *
  2724. * @mfunc
  2725. * Helper routine to get Attr
  2726. *
  2727. */
  2728. HRESULT CUIM::GetAttrs(
  2729. LONG acpPos,
  2730. ULONG cFilterAttrs,
  2731. const TS_ATTRID *paFilterAttrs,
  2732. BOOL fGetDefault)
  2733. {
  2734. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetAttrs");
  2735. HRESULT hResult;
  2736. ITextFont *pTextFont = NULL;
  2737. ITextPara *pTextPara = NULL;
  2738. int idx;
  2739. BOOL fRequestedAll = FALSE;
  2740. int idxAttr;
  2741. TS_ATTRVAL *pAttrVal;
  2742. ITextRange *pTextRange = NULL;
  2743. if (cFilterAttrs == 0)
  2744. {
  2745. fRequestedAll = TRUE;
  2746. cFilterAttrs = MAX_ATTR_SUPPORT;
  2747. }
  2748. InitAttrVarArray();
  2749. if (!_parAttrsVal)
  2750. return E_OUTOFMEMORY;
  2751. if (fGetDefault)
  2752. {
  2753. // Get document defaults font and para
  2754. hResult = _pTextMsgFilter->_pTextDoc->GetDocumentFont(&pTextFont);
  2755. if (FAILED(hResult))
  2756. goto EXIT;
  2757. hResult = _pTextMsgFilter->_pTextDoc->GetDocumentPara(&pTextPara);
  2758. if (FAILED(hResult))
  2759. goto EXIT;
  2760. }
  2761. else
  2762. {
  2763. hResult = _pTextMsgFilter->_pTextDoc->Range(acpPos, acpPos, &pTextRange);
  2764. if (FAILED(hResult))
  2765. goto EXIT;
  2766. hResult = pTextRange->GetFont(&pTextFont);
  2767. hResult = pTextRange->GetPara(&pTextPara);
  2768. }
  2769. pAttrVal = _parAttrsVal;
  2770. for (idx = 0; idx < (int)cFilterAttrs; idx++, paFilterAttrs++)
  2771. {
  2772. if (fRequestedAll)
  2773. idxAttr = idx;
  2774. else
  2775. idxAttr = FindGUID(*paFilterAttrs);
  2776. if (idxAttr >= 0)
  2777. {
  2778. if (PackAttrData(idxAttr, pTextFont, pTextPara, pAttrVal))
  2779. {
  2780. _uAttrsValTotal++;
  2781. pAttrVal++;
  2782. if (_uAttrsValTotal == MAX_ATTR_SUPPORT)
  2783. break;
  2784. }
  2785. }
  2786. }
  2787. hResult = S_OK;
  2788. EXIT:
  2789. if (pTextFont)
  2790. pTextFont->Release();
  2791. if (pTextPara)
  2792. pTextPara->Release();
  2793. if (pTextRange)
  2794. pTextRange->Release();
  2795. return hResult;
  2796. }
  2797. /*
  2798. * int CUIM::FindGUID
  2799. *
  2800. * @mfunc
  2801. * Helper routine to check if we supported the requested Attribute GUID
  2802. *
  2803. */
  2804. int CUIM::FindGUID(REFGUID guid)
  2805. {
  2806. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::FindGUID");
  2807. ULONG i;
  2808. for (i=0; i < MAX_ATTR_SUPPORT; i++)
  2809. {
  2810. if (IsEqualIID(*(_arTSAttridSupported[i]), guid))
  2811. return i;
  2812. }
  2813. // not found
  2814. return -1;
  2815. }
  2816. /*
  2817. * int CUIM::PackAttrData
  2818. *
  2819. * @mfunc
  2820. * Helper routine to fill in data for the given Attrib index
  2821. *
  2822. */
  2823. BOOL CUIM::PackAttrData(
  2824. LONG idx,
  2825. ITextFont *pITextFont,
  2826. ITextPara *pITextPara,
  2827. TS_ATTRVAL *pAttrVal)
  2828. {
  2829. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::PackAttrData");
  2830. long lValue;
  2831. float x;
  2832. BSTR bstrName;
  2833. HRESULT hResult;
  2834. const GUID *pGUID;
  2835. TfGuidAtom guidatom;
  2836. if (idx < 0 || idx >= MAX_ATTR_SUPPORT)
  2837. return FALSE;
  2838. if (!pITextFont && idx <= iattrSuperscript)
  2839. return FALSE;
  2840. if (!pITextPara && idx == iattrRTL)
  2841. return FALSE;
  2842. pAttrVal->varValue.vt = VT_BOOL;
  2843. memcpy(&pAttrVal->idAttr, _arTSAttridSupported[idx], sizeof(TS_ATTRID));
  2844. switch(idx)
  2845. {
  2846. case iattrFacename:
  2847. hResult = pITextFont->GetName(&bstrName);
  2848. pAttrVal->varValue.vt = VT_BSTR;
  2849. pAttrVal->varValue.bstrVal = bstrName;
  2850. break;
  2851. case iattrSize:
  2852. x = 0.0;
  2853. hResult = pITextFont->GetSize(&x);
  2854. lValue = (long)x;
  2855. pAttrVal->varValue.vt = VT_I4;
  2856. pAttrVal->varValue.lVal = x;
  2857. break;
  2858. case iattrColor:
  2859. hResult = pITextFont->GetForeColor(&lValue);
  2860. pAttrVal->varValue.vt = VT_I4;
  2861. pAttrVal->varValue.lVal = lValue; // TODO: check for tomAutocolor
  2862. break;
  2863. case iattrBold:
  2864. hResult = pITextFont->GetBold(&lValue);
  2865. pAttrVal->varValue.boolVal = lValue == tomTrue ? tomTrue : VARIANT_FALSE;
  2866. break;
  2867. case iattrItalic:
  2868. hResult = pITextFont->GetItalic(&lValue);
  2869. pAttrVal->varValue.boolVal = lValue == tomTrue ? tomTrue : VARIANT_FALSE;
  2870. break;
  2871. case iattrUnderline:
  2872. hResult = pITextFont->GetUnderline(&lValue);
  2873. pAttrVal->varValue.boolVal = lValue == tomNone ? VARIANT_FALSE : tomTrue;
  2874. break;
  2875. case iattrSubscript:
  2876. hResult = pITextFont->GetSubscript(&lValue);
  2877. pAttrVal->varValue.boolVal = lValue == tomTrue ? tomTrue : VARIANT_FALSE;
  2878. break;
  2879. case iattrSuperscript:
  2880. hResult = pITextFont->GetSuperscript(&lValue);
  2881. pAttrVal->varValue.boolVal = lValue == tomTrue ? tomTrue : VARIANT_FALSE;
  2882. break;
  2883. case iattrRTL:
  2884. {
  2885. LRESULT lres = 0;
  2886. _pTextMsgFilter->_pTextService->TxSendMessage(
  2887. EM_GETPARATXTFLOW, 0, (LPARAM)pITextPara, &lres);
  2888. pAttrVal->varValue.boolVal = lres ? tomTrue : VARIANT_FALSE;
  2889. }
  2890. break;
  2891. case iattrVertical:
  2892. BOOL fAtFont;
  2893. _pTextMsgFilter->_pTextDoc->GetFEFlags(&lValue);
  2894. fAtFont = lValue & tomUseAtFont;
  2895. lValue &= tomTextFlowMask;
  2896. pAttrVal->varValue.boolVal = (fAtFont && lValue == tomTextFlowSW) ? tomTrue : VARIANT_FALSE;
  2897. break;
  2898. case iattrBias:
  2899. pGUID = &GUID_MODEBIAS_NONE;
  2900. if (IN_RANGE(CTFMODEBIAS_DEFAULT, _pTextMsgFilter->_wUIMModeBias, CTFMODEBIAS_HALFWIDTHALPHANUMERIC))
  2901. pGUID = _arModeBiasSupported[_pTextMsgFilter->_wUIMModeBias];
  2902. if (!GetGUIDATOMFromGUID(*pGUID, &guidatom))
  2903. guidatom = TF_INVALID_GUIDATOM;
  2904. pAttrVal->varValue.vt = VT_I4;
  2905. pAttrVal->varValue.lVal = guidatom;
  2906. break;
  2907. case iattrTxtOrient:
  2908. // Get Text flow and setup the text rotation
  2909. _pTextMsgFilter->_pTextDoc->GetFEFlags(&lValue);
  2910. lValue &= tomTextFlowMask;
  2911. pAttrVal->varValue.vt = VT_I4;
  2912. pAttrVal->varValue.lVal = 0;
  2913. if (lValue == tomTextFlowSW)
  2914. pAttrVal->varValue.lVal = 2700;
  2915. else if (lValue == tomTextFlowNE)
  2916. pAttrVal->varValue.lVal = 900;
  2917. break;
  2918. }
  2919. return TRUE;
  2920. }
  2921. /*
  2922. * STDMETHODIMP CUIM::GetStoryLength
  2923. *
  2924. * @mfunc
  2925. * Helper routine to check the attribute filters
  2926. *
  2927. */
  2928. STDMETHODIMP CUIM::GetStoryLength(LONG *pacp)
  2929. {
  2930. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetStoryLength");
  2931. ITextRange *pTextRange = NULL;
  2932. HRESULT hResult = _pTextMsgFilter->_pTextDoc->Range(0, 0, &pTextRange);
  2933. if (hResult == S_OK && pTextRange)
  2934. {
  2935. long Count;
  2936. hResult = pTextRange->GetStoryLength(&Count);
  2937. if (hResult == S_OK)
  2938. *pacp = Count;
  2939. pTextRange->Release();
  2940. }
  2941. return hResult;
  2942. }
  2943. /*
  2944. * void CUIM::InitAttrVarArray
  2945. *
  2946. * @mfunc
  2947. * Helper routine to setup AttrVar Array
  2948. *
  2949. */
  2950. void CUIM::InitAttrVarArray(BOOL fAllocData)
  2951. {
  2952. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::InitAttrVarArray");
  2953. if (_parAttrsVal)
  2954. {
  2955. USHORT uIdx;
  2956. TS_ATTRVAL *pAttrVal = _parAttrsVal;
  2957. for (uIdx = 0; uIdx < _uAttrsValTotal; uIdx++, pAttrVal++)
  2958. VariantClear(&(pAttrVal->varValue));
  2959. memset(_parAttrsVal, 0, _uAttrsValTotal * sizeof(TS_ATTRVAL));
  2960. }
  2961. else if (fAllocData)
  2962. {
  2963. _parAttrsVal= (TS_ATTRVAL *)PvAlloc(sizeof(TS_ATTRVAL) * MAX_ATTR_SUPPORT, GMEM_ZEROINIT);
  2964. Assert(_parAttrsVal);
  2965. }
  2966. _uAttrsValCurrent = 0;
  2967. _uAttrsValTotal = 0;
  2968. }
  2969. /*
  2970. * HRESULT CUIM::MouseCheck(UINT *pmsg, WPARAM *pwparam, LPARAM *plparam, LRESULT *plres)
  2971. *
  2972. * @mfunc
  2973. * Perform UIM mouse check
  2974. *
  2975. * @rdesc
  2976. * int S_OK if handled
  2977. * S_FALSE Don't handle and should be ignored
  2978. *
  2979. */
  2980. HRESULT CUIM::MouseCheck(
  2981. UINT *pmsg,
  2982. WPARAM *pwparam,
  2983. LPARAM *plparam,
  2984. LRESULT *plres)
  2985. {
  2986. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::MouseCheck");
  2987. BOOL fRetCode = FALSE;
  2988. if (_fShutDown)
  2989. return S_FALSE;
  2990. if (_fMosueSink)
  2991. {
  2992. BOOL fTerminateIME;
  2993. long cpCusor = -1;
  2994. CTFMOUSETRAP *pSinkList = _pSinkList;
  2995. Assert(_pSinkList);
  2996. _fAllowUIMLock = 1;
  2997. // Get thru the list until one of the traps has handled the message
  2998. while(fRetCode == FALSE && pSinkList)
  2999. {
  3000. if (cpCusor == -1 || pSinkList->cpMouseStart < cpCusor &&
  3001. cpCusor <= pSinkList->cpMouseStart + pSinkList->cchMosueComp) // Within composition range?
  3002. {
  3003. fRetCode = _pTextMsgFilter->MouseOperation(*pmsg, pSinkList->cpMouseStart,
  3004. pSinkList->cchMosueComp, *pwparam, &(pSinkList->wParamBefore), &fTerminateIME,
  3005. NULL, &cpCusor, pSinkList->pMouseSink);
  3006. }
  3007. pSinkList = pSinkList->pNext;
  3008. }
  3009. _fAllowUIMLock = 0;
  3010. if ( !fRetCode && IsUIMTyping() && WM_MOUSEMOVE != *pmsg )
  3011. _pTextMsgFilter->CompleteUIMTyping(CIme::TERMINATE_NORMAL);
  3012. }
  3013. return fRetCode ? S_OK : S_FALSE;
  3014. }
  3015. /*
  3016. * HRESULT CUIM::Reconverse
  3017. *
  3018. * @mfunc
  3019. * Perform UIM reconversion
  3020. *
  3021. * @rdesc
  3022. * int S_OK if handled
  3023. * S_FALSE Don't handle and should be ignored
  3024. * -1 Don't handle and try IME reconverse
  3025. *
  3026. */
  3027. int CUIM::Reconverse()
  3028. {
  3029. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::Reconverse");
  3030. HRESULT hResult;
  3031. ITfRange *pITfRange = NULL;
  3032. ITfFnReconversion *pITfReconverse = NULL;
  3033. ITfFunctionProvider *pITfFctProvider = NULL;
  3034. TF_SELECTION TFSel = {0};
  3035. ULONG cSel;
  3036. int retCode = -1;
  3037. int fConvertible = FALSE;
  3038. if (_fUIMTyping)
  3039. return S_FALSE;
  3040. _fAllowUIMLock = 1;
  3041. _fHoldCTFSelChangeNotify = 1;
  3042. hResult = _pTextMsgFilter->_pTim->GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, &pITfFctProvider);
  3043. if (SUCCEEDED(hResult))
  3044. {
  3045. hResult = pITfFctProvider->GetFunction(GUID_NULL, IID_ITfFnReconversion, (IUnknown **)&pITfReconverse);
  3046. pITfFctProvider->Release();
  3047. if (SUCCEEDED(hResult))
  3048. {
  3049. int fCurrentLock = _fReadLockOn;
  3050. if (!fCurrentLock)
  3051. _fReadLockOn = 1; // Setup internal read lock
  3052. hResult = _pic->GetSelection(_editCookie, 0, 1, &TFSel, &cSel);
  3053. if (!fCurrentLock)
  3054. _fReadLockOn = 0; // Clear internal read lock
  3055. if (hResult == S_OK && cSel == 1)
  3056. {
  3057. if (pITfReconverse->QueryRange(TFSel.range, &pITfRange, &fConvertible) == S_OK && fConvertible)
  3058. {
  3059. pITfReconverse->Reconvert(pITfRange);
  3060. retCode = S_OK;
  3061. }
  3062. }
  3063. }
  3064. }
  3065. if (TFSel.range)
  3066. TFSel.range->Release();
  3067. if (pITfRange)
  3068. pITfRange->Release();
  3069. if (pITfReconverse)
  3070. pITfReconverse->Release();
  3071. _fAllowUIMLock = 0;
  3072. return retCode;
  3073. }
  3074. /*
  3075. * HRESULT CUIM::FindHiddenText
  3076. *
  3077. * @mfunc
  3078. * Find Hidden text and return the end of the range
  3079. *
  3080. * @rdesc
  3081. *
  3082. */
  3083. HRESULT CUIM::FindHiddenText(
  3084. long cp,
  3085. long cpEnd,
  3086. long &cpRange)
  3087. {
  3088. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::FindHiddenText");
  3089. HRESULT hResult;
  3090. long unitMoved;
  3091. ITextRange *pTextRange = NULL;
  3092. cpRange = cp;
  3093. if (cpRange >= cpEnd)
  3094. return S_OK;
  3095. hResult = _pTextMsgFilter->_pTextDoc->Range(cpRange, cpRange, &pTextRange);
  3096. if (!SUCCEEDED(hResult))
  3097. return hResult;
  3098. hResult = pTextRange->EndOf(tomHidden, tomExtend, &unitMoved);
  3099. if (SUCCEEDED(hResult))
  3100. {
  3101. Assert(unitMoved);
  3102. cpRange = 0;
  3103. hResult = pTextRange->GetEnd(&cpRange);
  3104. Assert(cpRange);
  3105. }
  3106. pTextRange->Release();
  3107. return hResult;
  3108. }
  3109. /*
  3110. * HRESULT CUIM::FindUnhiddenText
  3111. *
  3112. * @mfunc
  3113. * Find Unhidden text and return the end of the range
  3114. *
  3115. * @rdesc
  3116. *
  3117. */
  3118. HRESULT CUIM::FindUnhiddenText(
  3119. long cp,
  3120. long cpEnd,
  3121. long &cpRange)
  3122. {
  3123. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::FindUnhiddenText");
  3124. HRESULT hResult;
  3125. long unitMoved;
  3126. ITextRange *pTextRange = NULL;
  3127. ITextFont *pTextFont = NULL;
  3128. long fHidden;
  3129. cpRange = cp;
  3130. if (cpRange >= cpEnd)
  3131. return S_OK;
  3132. hResult = _pTextMsgFilter->_pTextDoc->Range(cpRange, cpRange, &pTextRange);
  3133. if (!SUCCEEDED(hResult))
  3134. return hResult;
  3135. Assert(pTextRange);
  3136. while (cpRange < cpEnd)
  3137. {
  3138. hResult = pTextRange->MoveEnd(tomCharacter, 1, &unitMoved);
  3139. if (!SUCCEEDED(hResult))
  3140. break;
  3141. if (!unitMoved)
  3142. {
  3143. hResult = E_FAIL;
  3144. break;
  3145. }
  3146. hResult = pTextRange->GetFont(&pTextFont);
  3147. if (!SUCCEEDED(hResult))
  3148. break;
  3149. Assert(pTextFont);
  3150. pTextFont->GetHidden(&fHidden);
  3151. pTextFont->Release();
  3152. if (fHidden)
  3153. break;
  3154. hResult = pTextRange->EndOf(tomCharFormat, tomMove, &unitMoved);
  3155. if (!SUCCEEDED(hResult))
  3156. break;
  3157. if (unitMoved > 0)
  3158. {
  3159. cpRange = 0;
  3160. hResult = pTextRange->GetEnd(&cpRange);
  3161. if (!SUCCEEDED(hResult))
  3162. break;
  3163. Assert(cpRange);
  3164. }
  3165. else
  3166. cpRange = cpEnd;
  3167. }
  3168. pTextRange->Release();
  3169. return hResult;
  3170. }
  3171. /*
  3172. * void CUIM::BuildHiddenTxtBlks
  3173. *
  3174. * @mfunc
  3175. * Build hidden text blocks
  3176. *
  3177. *
  3178. */
  3179. void CUIM::BuildHiddenTxtBlks(
  3180. long &cpMin,
  3181. long &cpMax,
  3182. long **ppHiddenTxtBlk,
  3183. long &cHiddenTxtBlk)
  3184. {
  3185. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::BuildHiddenTxtBlks");
  3186. long cHiddenTxtBlkAlloc = 0;
  3187. long *pHiddenTxtBlk;
  3188. long cpCurrent = cpMin;
  3189. long cpNext;
  3190. HRESULT hResult;
  3191. cHiddenTxtBlkAlloc = 20;
  3192. pHiddenTxtBlk = (long *)PvAlloc(cHiddenTxtBlkAlloc * sizeof(long), GMEM_ZEROINIT);
  3193. if (pHiddenTxtBlk)
  3194. {
  3195. pHiddenTxtBlk[0] = tomForward;
  3196. while (cpCurrent < cpMax)
  3197. {
  3198. hResult = FindUnhiddenText(cpCurrent, cpMax, cpNext);
  3199. if (!SUCCEEDED(hResult))
  3200. break;
  3201. if (cpNext >= cpMax)
  3202. break;
  3203. hResult = FindHiddenText(cpNext, cpMax, cpCurrent);
  3204. if (!SUCCEEDED(hResult))
  3205. break;
  3206. Assert(cpCurrent > cpNext);
  3207. // Save the hidden text block cp and length
  3208. pHiddenTxtBlk[cHiddenTxtBlk] = cpNext;
  3209. cpCurrent = min(cpCurrent, cpMax);
  3210. pHiddenTxtBlk[cHiddenTxtBlk+1] = cpCurrent - cpNext;
  3211. cHiddenTxtBlk += 2;
  3212. if (cHiddenTxtBlk >= cHiddenTxtBlkAlloc)
  3213. {
  3214. cHiddenTxtBlkAlloc += 20;
  3215. pHiddenTxtBlk = (long *)PvReAlloc(pHiddenTxtBlk, cHiddenTxtBlkAlloc * sizeof(long));
  3216. if (!pHiddenTxtBlk)
  3217. break;
  3218. }
  3219. }
  3220. }
  3221. *ppHiddenTxtBlk = pHiddenTxtBlk;
  3222. }
  3223. /*
  3224. * BOOL CUIM::CTFOpenStatus
  3225. *
  3226. * @mfunc
  3227. * Get/Set current CTF open status
  3228. *
  3229. * @rdesc
  3230. * For GetOpenStatus
  3231. * return 1 is Open, 0 if Close or fail
  3232. *
  3233. * For SetOpenStatus
  3234. * return TRUE is set status without problem, FALSE if fail
  3235. *
  3236. */
  3237. BOOL CUIM::CTFOpenStatus(
  3238. BOOL fGetOpenStatus,
  3239. BOOL fOpen)
  3240. {
  3241. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::CTFOpenStatus");
  3242. HRESULT hr;
  3243. VARIANT var;
  3244. BOOL fRet = FALSE;
  3245. ITfCompartment *pComp = NULL;
  3246. ITfCompartmentMgr *pCompMgr = NULL;
  3247. hr = _pTextMsgFilter->_pTim->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr);
  3248. if (SUCCEEDED(hr))
  3249. {
  3250. Assert(pCompMgr);
  3251. hr = pCompMgr->GetCompartment(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, &pComp);
  3252. if (SUCCEEDED(hr))
  3253. {
  3254. Assert(pComp);
  3255. VariantInit(&var);
  3256. if (fGetOpenStatus)
  3257. {
  3258. if (pComp->GetValue(&var) == S_OK)
  3259. {
  3260. Assert(var.vt == VT_I4);
  3261. fRet = var.lVal ? TRUE : FALSE ;
  3262. }
  3263. }
  3264. else
  3265. {
  3266. var.vt = VT_I4;
  3267. var.lVal = fOpen;
  3268. hr = pComp->SetValue(_pTextMsgFilter->_tid, &var);
  3269. fRet = SUCCEEDED(hr);
  3270. }
  3271. VariantClear(&var);
  3272. }
  3273. }
  3274. if (pComp)
  3275. pComp->Release();
  3276. if (pCompMgr)
  3277. pCompMgr->Release();
  3278. return fRet;
  3279. }
  3280. /*
  3281. * BOOL CUIM::BuildObject
  3282. *
  3283. * @mfunc
  3284. * Build an array of embedded objects
  3285. *
  3286. * @rdesc
  3287. * return Number of objects in the array returned in pEmbeddObjects
  3288. *
  3289. */
  3290. int CUIM::BuildObject(
  3291. ITextRange *pTextRange,
  3292. BSTR bstr,
  3293. EMBEDOBJECT **ppEmbeddObjects,
  3294. int cSize)
  3295. {
  3296. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::BuildObject");
  3297. long cpMin;
  3298. HRESULT hResult = pTextRange->GetStart(&cpMin);
  3299. WCHAR *pText = (WCHAR *)bstr;
  3300. EMBEDOBJECT *pEmbeddObjStart = *ppEmbeddObjects;
  3301. EMBEDOBJECT *pEmbeddObj = *ppEmbeddObjects;
  3302. BOOL fAllocateBuffer = FALSE;
  3303. long cObjects = 0;
  3304. long cchBstr = SysStringLen(bstr);
  3305. if (hResult == S_OK)
  3306. {
  3307. for(long i = 0; i < cchBstr; i++, pText++)
  3308. {
  3309. if (*pText == WCH_EMBEDDING)
  3310. {
  3311. // Get IDataObject
  3312. HRESULT hr;
  3313. IDataObject *pIDataObj = NULL;
  3314. BOOL fReadLockOld = _fReadLockOn;
  3315. _fReadLockOn = TRUE;
  3316. hr = GetEmbedded(cpMin+i, GUID_DCSERVICE_DATAOBJECT, IID_IDataObject, (IUnknown **)&pIDataObj);
  3317. _fReadLockOn = fReadLockOld;
  3318. // Store it in the memory
  3319. if (cObjects < cSize)
  3320. {
  3321. pEmbeddObj->cpOffset = i;
  3322. pEmbeddObj->pIDataObj = pIDataObj;
  3323. pEmbeddObj++;
  3324. cObjects++;
  3325. }
  3326. else
  3327. {
  3328. long cNewSize = cSize + 5;
  3329. EMBEDOBJECT *pEmbeddObjTemp;
  3330. if (fAllocateBuffer)
  3331. {
  3332. pEmbeddObjTemp = (EMBEDOBJECT *)PvReAlloc(pEmbeddObjStart, sizeof(EMBEDOBJECT) * cNewSize);
  3333. if (pEmbeddObjTemp)
  3334. {
  3335. pEmbeddObjStart = pEmbeddObjTemp;
  3336. pEmbeddObj = pEmbeddObjStart + cSize;
  3337. cSize = cNewSize;
  3338. pEmbeddObj->cpOffset = i;
  3339. pEmbeddObj->pIDataObj = pIDataObj;
  3340. pEmbeddObj++;
  3341. cObjects++;
  3342. }
  3343. else
  3344. {
  3345. // Cleanup here
  3346. pIDataObj->Release();
  3347. break;
  3348. }
  3349. }
  3350. else
  3351. {
  3352. fAllocateBuffer = TRUE;
  3353. pEmbeddObjTemp = (EMBEDOBJECT *)PvAlloc(sizeof(EMBEDOBJECT) * cNewSize, GMEM_ZEROINIT);
  3354. if (pEmbeddObjTemp)
  3355. {
  3356. if (cSize)
  3357. {
  3358. // Copy previous data to new buffer
  3359. memcpy(pEmbeddObjTemp, pEmbeddObjStart, sizeof(EMBEDOBJECT) * cSize);
  3360. }
  3361. pEmbeddObjStart = pEmbeddObjTemp;
  3362. pEmbeddObj = pEmbeddObjStart + cSize;
  3363. cSize = cNewSize;
  3364. pEmbeddObj->cpOffset = i;
  3365. pEmbeddObj->pIDataObj = pIDataObj;
  3366. pEmbeddObj++;
  3367. cObjects++;
  3368. }
  3369. else
  3370. {
  3371. // Cleanup here
  3372. pIDataObj->Release();
  3373. break;
  3374. }
  3375. }
  3376. }
  3377. }
  3378. }
  3379. }
  3380. *ppEmbeddObjects = pEmbeddObjStart;
  3381. return cObjects;
  3382. }
  3383. /*
  3384. * BOOL CUIM::InsertTextandObject
  3385. *
  3386. * @mfunc
  3387. * Insert text and embedded objects
  3388. *
  3389. */
  3390. void CUIM::InsertTextandObject(
  3391. ITextRange *pTextRange,
  3392. BSTR bstr,
  3393. EMBEDOBJECT *pEmbeddObjects,
  3394. long cEmbeddedObjects)
  3395. {
  3396. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::InsertTextandObject");
  3397. WCHAR *pText = (WCHAR *)bstr;
  3398. WCHAR *pTextStart = pText;
  3399. long cObjects = 0;
  3400. long cchBstr = SysStringLen(bstr);
  3401. HRESULT hr;
  3402. for(long i = 0; i < cchBstr; i++, pText++)
  3403. {
  3404. if (*pText == WCH_EMBEDDING)
  3405. {
  3406. // Insert Text if necessary
  3407. if (pTextStart != pText)
  3408. {
  3409. BSTR bstr = SysAllocStringLen(pTextStart, pText-pTextStart);
  3410. if (bstr)
  3411. {
  3412. hr = pTextRange->SetText(bstr);
  3413. SysFreeString(bstr);
  3414. pTextRange->Collapse(tomFalse);
  3415. }
  3416. }
  3417. if (cObjects < cEmbeddedObjects)
  3418. {
  3419. LRESULT lresult;
  3420. long cpMin = 0, cpMax = 0;
  3421. HRESULT hResult = pTextRange->GetStart(&cpMin);
  3422. hResult = pTextRange->GetEnd(&cpMax);
  3423. CHARRANGE charRange = {cpMin, cpMax};
  3424. hr = _pTextMsgFilter->_pTextService->TxSendMessage(EM_INSERTOBJ, (WPARAM)&charRange,
  3425. (LPARAM)(pEmbeddObjects->pIDataObj), &lresult);
  3426. hr = pTextRange->Move(tomCharacter, 1, NULL); // move over the embedded char
  3427. cObjects++;
  3428. pEmbeddObjects++;
  3429. }
  3430. // Setup for next string after the embedded object
  3431. pTextStart = pText + 1;
  3432. }
  3433. }
  3434. // Insert last Text if necessary
  3435. if (pTextStart != pText)
  3436. {
  3437. BSTR bstr = SysAllocStringLen(pTextStart, pText-pTextStart);
  3438. if (bstr)
  3439. {
  3440. hr = pTextRange->SetText(bstr);
  3441. SysFreeString(bstr);
  3442. }
  3443. }
  3444. }
  3445. /*
  3446. * BOOL CUIM::CleanUpObjects
  3447. *
  3448. * @mfunc
  3449. * Free the objects
  3450. *
  3451. */
  3452. void CUIM::CleanUpObjects(
  3453. long cObjects,
  3454. EMBEDOBJECT *pObjects)
  3455. {
  3456. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::CleanUpObjects");
  3457. for (long i = 0; i < cObjects; i++, pObjects++)
  3458. {
  3459. if (pObjects->pIDataObj)
  3460. pObjects->pIDataObj->Release();
  3461. }
  3462. }
  3463. /*
  3464. * void CUIM::CleanUpComposition
  3465. *
  3466. * @mfunc
  3467. * Free the composition string and objects list
  3468. *
  3469. */
  3470. void CUIM::CleanUpComposition()
  3471. {
  3472. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::CleanUpComposition");
  3473. if (_bstrComposition)
  3474. {
  3475. SysFreeString (_bstrComposition);
  3476. _bstrComposition = NULL;
  3477. }
  3478. _acpBstrStart = tomForward;
  3479. if (_cObjects)
  3480. {
  3481. CleanUpObjects(_cObjects, _pObjects);
  3482. delete _pObjects;
  3483. _cObjects = 0;
  3484. _pObjects = NULL;
  3485. }
  3486. }
  3487. /*
  3488. * BOOL CUIM::HandleTempDispAttr
  3489. *
  3490. * @mfunc
  3491. * This routine handle temp. display attribute that are set
  3492. * outside CTF composition. It is using ITfContextRenderingMarkup
  3493. * to get the range and display data.
  3494. *
  3495. */
  3496. void CUIM::HandleTempDispAttr(
  3497. ITfEditRecord *pEditRecord)
  3498. {
  3499. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::HandleTempDispAttr");
  3500. if (_pContextRenderingMarkup)
  3501. {
  3502. HRESULT hr;
  3503. const GUID *rgGUID[1];
  3504. IEnumTfRanges *pEnumRanges = NULL;
  3505. // Get attribute changes
  3506. rgGUID[0] = &GUID_PROP_ATTRIBUTE;
  3507. hr = pEditRecord->GetTextAndPropertyUpdates(0, (const GUID**)rgGUID, 1, &pEnumRanges);
  3508. if (SUCCEEDED(hr))
  3509. {
  3510. ITfRange *pITfRange = NULL;
  3511. while (pEnumRanges->Next(1, &pITfRange, NULL) == S_OK)
  3512. {
  3513. IEnumTfRenderingMarkup *pEnumMarkup;
  3514. TF_RENDERINGMARKUP tfRenderingMarkup;
  3515. long acpStartRange, cch;
  3516. if (_pContextRenderingMarkup->GetRenderingMarkup(_editCookie, TF_GRM_INCLUDE_PROPERTY, pITfRange, &pEnumMarkup) == S_OK)
  3517. {
  3518. while (pEnumMarkup->Next(1, &tfRenderingMarkup, NULL) == S_OK)
  3519. {
  3520. HRESULT hResult;
  3521. hResult = GetExtentAcpPrange(tfRenderingMarkup.pRange, acpStartRange, cch);
  3522. if (hResult && cch > 0)
  3523. {
  3524. ITextRange *pTextRange = NULL;
  3525. hResult = _pTextMsgFilter->_pTextDoc->Range(acpStartRange, acpStartRange+cch, &pTextRange);
  3526. if (pTextRange)
  3527. {
  3528. ITextFont *pFont = NULL;
  3529. hResult = pTextRange->GetFont(&pFont);
  3530. if (pFont)
  3531. {
  3532. long lStyle;
  3533. COLORREF cr;
  3534. _pTextMsgFilter->_pTextDoc->Undo(tomSuspend, NULL);
  3535. TF_DISPLAYATTRIBUTE da = tfRenderingMarkup.tfDisplayAttr;
  3536. pFont->Reset(tomApplyTmp);
  3537. switch (da.lsStyle)
  3538. {
  3539. // case TFLS_SOLID:
  3540. default:
  3541. lStyle = da.fBoldLine ? tomThick : tomSingle;
  3542. break;
  3543. case TF_LS_DOT:
  3544. case TF_LS_DASH: // Dash line should show as dotted line
  3545. lStyle = tomDotted;
  3546. break;
  3547. case TF_LS_SQUIGGLE:
  3548. lStyle = tomWave;
  3549. break;
  3550. case TF_LS_NONE:
  3551. lStyle = tomNone;
  3552. break;
  3553. }
  3554. if (lStyle != tomNone)
  3555. {
  3556. pFont->SetUnderline(lStyle);
  3557. if (GetUIMAttributeColor(&da.crLine, &cr))
  3558. pFont->SetUnderline(cr | 0x0FF000000);
  3559. }
  3560. if (GetUIMAttributeColor(&da.crText, &cr))
  3561. pFont->SetForeColor(cr);
  3562. if (GetUIMAttributeColor(&da.crBk, &cr))
  3563. pFont->SetBackColor(cr);
  3564. pFont->Reset(tomApplyNow);
  3565. pFont->Release();
  3566. _pTextMsgFilter->_pTextDoc->Undo(tomResume, NULL);
  3567. }
  3568. pTextRange->Release();
  3569. }
  3570. }
  3571. }
  3572. pEnumMarkup->Release();
  3573. }
  3574. pITfRange->Release();
  3575. }
  3576. }
  3577. if (pEnumRanges)
  3578. pEnumRanges->Release();
  3579. }
  3580. }
  3581. /*
  3582. * STDAPI CUIM::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  3583. *
  3584. * @mfunc
  3585. * Handle ITfEnableService::QueryService. Cicero/tip call this interface to obtain
  3586. * IID_ITfEnableService i/f
  3587. *
  3588. * @rdesc
  3589. * S_OK if service supported
  3590. *
  3591. */
  3592. STDAPI CUIM::QueryService(
  3593. REFGUID guidService,
  3594. REFIID riid,
  3595. void **ppv)
  3596. {
  3597. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::QueryService");
  3598. if (ppv == NULL)
  3599. return E_INVALIDARG;
  3600. *ppv = NULL;
  3601. // we support just one service
  3602. if (!IsEqualGUID(guidService, GUID_SERVICE_TEXTSTORE))
  3603. return E_NOINTERFACE;
  3604. if (IsEqualIID(riid, IID_IServiceProvider))
  3605. {
  3606. *ppv = (IServiceProvider *)this;
  3607. }
  3608. else if (IsEqualIID(riid, IID_ITfEnableService))
  3609. {
  3610. *ppv = (ITfEnableService *)this;
  3611. }
  3612. if (*ppv == NULL)
  3613. return E_NOINTERFACE;
  3614. AddRef();
  3615. return S_OK;
  3616. }
  3617. /*
  3618. * STDAPI CUIM::IsEnabled(REFGUID rguidServiceCategory, CLSID clsidService, IUnknown *punkService, BOOL *pfOkToRun)
  3619. *
  3620. * @mfunc
  3621. * Handle ITfEnableService::QueryService. Cicero/tip call this interface to check
  3622. * if we support the service
  3623. *
  3624. * @rdesc
  3625. * S_OK if service supported
  3626. *
  3627. */
  3628. STDAPI CUIM::IsEnabled(
  3629. REFGUID rguidServiceCategory,
  3630. CLSID clsidService,
  3631. IUnknown *punkService,
  3632. BOOL *pfOkToRun)
  3633. {
  3634. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::IsEnabled");
  3635. if (pfOkToRun == NULL)
  3636. return E_INVALIDARG;
  3637. // default is disallow
  3638. *pfOkToRun = FALSE;
  3639. // clsidService identifies the particular tip, but we don't use it here
  3640. // punkService is a custom interface, probably for config, but we don't use it here yet
  3641. if (IsEqualGUID(rguidServiceCategory, GUID_TFCAT_TIP_SMARTTAG))
  3642. {
  3643. *pfOkToRun = _pTextMsgFilter->_fAllowSmartTag ? TRUE : FALSE;
  3644. }
  3645. else if (IsEqualGUID(rguidServiceCategory, GUID_TFCAT_TIP_PROOFING))
  3646. {
  3647. *pfOkToRun = _pTextMsgFilter->_fAllowProofing ? TRUE : FALSE;;
  3648. }
  3649. return S_OK;
  3650. }
  3651. /*
  3652. * STDAPI CUIM::GetId(GUID *pguidId)
  3653. *
  3654. * @mfunc
  3655. * get the RE clid
  3656. *
  3657. * @rdesc
  3658. * S_OK
  3659. *
  3660. */
  3661. STDAPI CUIM::GetId(
  3662. GUID *pguidId)
  3663. {
  3664. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::GetId");
  3665. if (pguidId == NULL)
  3666. return E_INVALIDARG;
  3667. *pguidId = CLSID_MSFTEDIT;
  3668. return S_OK;
  3669. }
  3670. /*
  3671. * void CUIM::NotifyService()
  3672. *
  3673. * @mfunc
  3674. * Notify Cicero about change in services.
  3675. *
  3676. *
  3677. */
  3678. void CUIM::NotifyService()
  3679. {
  3680. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CUIM::NotifyService");
  3681. ITfCompartmentMgr *pCompartmentMgr;
  3682. ITfCompartment *pCompartment;
  3683. VARIANT varValue;
  3684. if (_pic->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr) != S_OK)
  3685. return;
  3686. // give any waiting tips a heads up we've changed our state
  3687. if (pCompartmentMgr->GetCompartment(GUID_COMPARTMENT_ENABLESTATE, &pCompartment) == S_OK)
  3688. {
  3689. varValue.vt = VT_I4;
  3690. varValue.lVal = 1; // arbitrary value, we just want to generate a change event
  3691. pCompartment->SetValue(_pTextMsgFilter->_tid, &varValue);
  3692. pCompartment->Release();
  3693. }
  3694. pCompartmentMgr->Release();
  3695. }
  3696. /*
  3697. * STDAPI CTextEditSink::QueryInterface
  3698. *
  3699. * @mfunc
  3700. * IUnknown QueryInterface support
  3701. *
  3702. * @rdesc
  3703. * NOERROR if interface supported
  3704. *
  3705. */
  3706. STDAPI CTextEditSink::QueryInterface(REFIID riid, void **ppvObj)
  3707. {
  3708. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::QueryInterface");
  3709. *ppvObj = NULL;
  3710. if (IsEqualIID(riid, IID_IUnknown) ||
  3711. IsEqualIID(riid, IID_ITfTextEditSink))
  3712. {
  3713. *ppvObj = (CTextEditSink *)this;
  3714. }
  3715. if (*ppvObj)
  3716. {
  3717. AddRef();
  3718. return S_OK;
  3719. }
  3720. return E_NOINTERFACE;
  3721. }
  3722. /*
  3723. * STDMETHODIMP_(ULONG) CTextEditSink::AddRef
  3724. *
  3725. * @mfunc
  3726. * IUnknown AddRef support
  3727. *
  3728. * @rdesc
  3729. * Reference count
  3730. */
  3731. STDAPI_(ULONG) CTextEditSink::AddRef()
  3732. {
  3733. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::AddRef");
  3734. return ++_cRef;
  3735. }
  3736. /*
  3737. * STDMETHODIMP_(ULONG) CTextEditSink::Release()
  3738. *
  3739. * @mfunc
  3740. * IUnknown Release support - delete object when reference count is 0
  3741. *
  3742. * @rdesc
  3743. * Reference count
  3744. */
  3745. STDAPI_(ULONG) CTextEditSink::Release()
  3746. {
  3747. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::Release");
  3748. long cr;
  3749. cr = --_cRef;
  3750. Assert(cr >= 0);
  3751. if (cr == 0)
  3752. {
  3753. delete this;
  3754. }
  3755. return cr;
  3756. }
  3757. /*
  3758. * CTextEditSink::CTextEditSink()
  3759. *
  3760. * @mfunc
  3761. *
  3762. * ctor
  3763. *
  3764. */
  3765. CTextEditSink::CTextEditSink(PTESCALLBACK pfnCallback, void *pv)
  3766. {
  3767. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::CTextEditSink");
  3768. _cRef = 1;
  3769. _dwCookie = 0x0FFFFFFFF;
  3770. _pfnCallback = pfnCallback;
  3771. _pv = pv;
  3772. }
  3773. /*
  3774. * STDAPI CTextEditSink::OnEndEdit()
  3775. *
  3776. * @mfunc
  3777. *
  3778. *
  3779. * @rdesc
  3780. *
  3781. */
  3782. STDAPI CTextEditSink::OnEndEdit(
  3783. ITfContext *pic,
  3784. TfEditCookie ecReadOnly,
  3785. ITfEditRecord *pEditRecord)
  3786. {
  3787. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::OnEndEdit");
  3788. return _pfnCallback(pEditRecord, _pv);
  3789. }
  3790. /*
  3791. * HRESULT CTextEditSink::_Advise
  3792. *
  3793. * @mfunc
  3794. *
  3795. *
  3796. * @rdesc
  3797. *
  3798. */
  3799. HRESULT CTextEditSink::_Advise(ITfContext *pic)
  3800. {
  3801. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::_Advise");
  3802. HRESULT hr;
  3803. ITfSource *source = NULL;
  3804. _pic = NULL;
  3805. hr = E_FAIL;
  3806. if (FAILED(pic->QueryInterface(IID_ITfSource, (void **)&source)))
  3807. return E_FAIL;
  3808. if (FAILED(source->AdviseSink(IID_ITfTextEditSink, this, &_dwCookie)))
  3809. goto Exit;
  3810. _pic = pic;
  3811. _pic->AddRef();
  3812. hr = S_OK;
  3813. Exit:
  3814. source->Release();
  3815. return hr;
  3816. }
  3817. /*
  3818. * HRESULT CTextEditSink::_Unadvise
  3819. *
  3820. * @mfunc
  3821. *
  3822. *
  3823. * @rdesc
  3824. *
  3825. */
  3826. HRESULT CTextEditSink::_Unadvise()
  3827. {
  3828. TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CTextEditSink::_Unadvise");
  3829. HRESULT hr;
  3830. ITfSource *source = NULL;
  3831. hr = E_FAIL;
  3832. if (_pic == NULL)
  3833. return E_FAIL;
  3834. if (FAILED(_pic->QueryInterface(IID_ITfSource, (void **)&source)))
  3835. return E_FAIL;
  3836. if (FAILED(source->UnadviseSink(_dwCookie)))
  3837. goto Exit;
  3838. hr = S_OK;
  3839. Exit:
  3840. source->Release();
  3841. _pic->Release();
  3842. _pic = NULL;
  3843. return hr;
  3844. }
  3845. #endif // NOFEPROCESSING