Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1748 lines
46 KiB

  1. //
  2. // acp2anch.cpp
  3. //
  4. #include "private.h"
  5. #include "acp2anch.h"
  6. #include "ic.h"
  7. #include "normal.h"
  8. #include "ic.h"
  9. #include "range.h"
  10. #include "anchoref.h"
  11. #include "txtcache.h"
  12. /* 4eb058b0-34ae-11d3-a745-0050040ab407 */
  13. const IID IID_PRIV_ACPWRAP = { 0x4eb058b0, 0x34ae, 0x11d3, {0xa7, 0x45, 0x00, 0x50, 0x04, 0x0a, 0xb4, 0x07} };
  14. DBG_ID_INSTANCE(CLoaderACPWrap);
  15. DBG_ID_INSTANCE(CACPWrap);
  16. void NormalizeAnchor(CAnchorRef *par)
  17. {
  18. CACPWrap *paw;
  19. CAnchor *pa;
  20. paw = par->_GetWrap();
  21. pa = par->_GetAnchor();
  22. if (!pa->IsNormalized())
  23. {
  24. paw->_NormalizeAnchor(pa);
  25. }
  26. }
  27. void NormalizeAnchor(IAnchor *pa)
  28. {
  29. CAnchorRef *par;
  30. if ((par = GetCAnchorRef_NA(pa)) == NULL)
  31. {
  32. Assert(0); // should never get here
  33. return;
  34. }
  35. NormalizeAnchor(par);
  36. }
  37. //+---------------------------------------------------------------------------
  38. //
  39. // ctor
  40. //
  41. //----------------------------------------------------------------------------
  42. CLoaderACPWrap::CLoaderACPWrap(ITfPersistentPropertyLoaderACP *loader)
  43. {
  44. Dbg_MemSetThisNameIDCounter(TEXT("CLoaderACPWrap"), PERF_LOADERACP_COUNTER);
  45. _loader = loader;
  46. _loader->AddRef();
  47. }
  48. //+---------------------------------------------------------------------------
  49. //
  50. // dtor
  51. //
  52. //----------------------------------------------------------------------------
  53. CLoaderACPWrap::~CLoaderACPWrap()
  54. {
  55. _loader->Release();
  56. }
  57. //+---------------------------------------------------------------------------
  58. //
  59. // LoadProperty
  60. //
  61. //----------------------------------------------------------------------------
  62. STDAPI CLoaderACPWrap::LoadProperty(const TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *pHdr, IStream **ppStream)
  63. {
  64. TF_PERSISTENT_PROPERTY_HEADER_ACP phacp;
  65. // always normalize before unserializing
  66. NormalizeAnchor(pHdr->paStart);
  67. NormalizeAnchor(pHdr->paEnd);
  68. if (!CACPWrap::_AnchorHdrToACP(pHdr, &phacp))
  69. return E_FAIL;
  70. return _loader->LoadProperty(&phacp, ppStream);
  71. }
  72. //+---------------------------------------------------------------------------
  73. //
  74. // ctor
  75. //
  76. //----------------------------------------------------------------------------
  77. CACPWrap::CACPWrap(ITextStoreACP *ptsi)
  78. {
  79. Dbg_MemSetThisNameIDCounter(TEXT("CACPWrap"), PERF_ACPWRAP_COUNTER);
  80. _ptsi = ptsi;
  81. ptsi->AddRef();
  82. _cRef = 1;
  83. }
  84. //+---------------------------------------------------------------------------
  85. //
  86. // dtor
  87. //
  88. //----------------------------------------------------------------------------
  89. CACPWrap::~CACPWrap()
  90. {
  91. Assert(_ptsi == NULL); // cleared in Release
  92. Assert(_rgAnchors.Count() == 0); // all anchors should be removed
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // IUnknown
  97. //
  98. //----------------------------------------------------------------------------
  99. STDAPI CACPWrap::QueryInterface(REFIID riid, void **ppvObj)
  100. {
  101. *ppvObj = NULL;
  102. if (IsEqualIID(riid, IID_IUnknown) ||
  103. IsEqualIID(riid, IID_ITextStoreAnchor))
  104. {
  105. *ppvObj = SAFECAST(this, ITextStoreAnchor *);
  106. }
  107. else if (IsEqualIID(riid, IID_ITextStoreACPSink))
  108. {
  109. *ppvObj = SAFECAST(this, ITextStoreACPSink *);
  110. }
  111. else if (IsEqualIID(riid, IID_ITextStoreACPServices))
  112. {
  113. *ppvObj = SAFECAST(this, ITextStoreACPServices *);
  114. }
  115. else if (IsEqualIID(riid, IID_PRIV_ACPWRAP))
  116. {
  117. *ppvObj = SAFECAST(this, CACPWrap *);
  118. }
  119. else if (IsEqualIID(riid, IID_ITfMouseTrackerACP))
  120. {
  121. *ppvObj = SAFECAST(this, ITfMouseTrackerACP *);
  122. }
  123. else if (IsEqualIID(riid, IID_IServiceProvider))
  124. {
  125. *ppvObj = SAFECAST(this, IServiceProvider *);
  126. }
  127. if (*ppvObj)
  128. {
  129. AddRef();
  130. return S_OK;
  131. }
  132. return E_NOINTERFACE;
  133. }
  134. STDAPI_(ULONG) CACPWrap::AddRef()
  135. {
  136. return ++_cRef;
  137. }
  138. STDAPI_(ULONG) CACPWrap::Release()
  139. {
  140. _cRef--;
  141. Assert(_cRef >= 0);
  142. // nb: this obj has 2 ref counters:
  143. // _cRef -> external clients
  144. // _GetAnchorRef -> CAnchorRef's.
  145. // we won't delete until both reach 0
  146. if (_cRef == 0)
  147. {
  148. // clear out text cache before releasing _ptsi
  149. // the memory may be reallocated (this happened!) for a different text store
  150. CProcessTextCache::Invalidate(_ptsi);
  151. // disconnect the ITextStoreACP
  152. SafeReleaseClear(_ptsi);
  153. if (_GetAnchorRef() == 0) // internal ref count
  154. {
  155. delete this;
  156. }
  157. return 0;
  158. }
  159. return _cRef;
  160. }
  161. //+---------------------------------------------------------------------------
  162. //
  163. // OnTextChange
  164. //
  165. //----------------------------------------------------------------------------
  166. STDAPI CACPWrap::OnTextChange(DWORD dwFlags, const TS_TEXTCHANGE *pChange)
  167. {
  168. IAnchor *paStart = NULL;
  169. IAnchor *paEnd = NULL;
  170. HRESULT hr;
  171. HRESULT hr2;
  172. if (pChange == NULL)
  173. return E_INVALIDARG;
  174. if (_pic->_IsInEditSession())
  175. {
  176. Assert(0); // someone other than cicero is editing the doc while cicero holds a lock
  177. return TS_E_NOLOCK;
  178. }
  179. #ifdef DEBUG
  180. _Dbg_fAppHasLock = TRUE;
  181. #endif
  182. // we never call this internally, so the caller must be the app.
  183. // nb: we aren't normalizing the anchors here! They can't be
  184. // normalized until the app releases its lock in OnLockReleased.
  185. // Not a bad thing for perf though! We will merge spans before
  186. // normalizing...
  187. // Issue: we aren't handling the case like:
  188. // "----<a1>ABC<a2>" -> "XX<a1><a2>", where "-" is formatting and <a1> has backwards gravity, <a2> forwards
  189. // in this case we'd like to see "<a1>XX<a2>" as the final result
  190. if (pChange->acpStart == pChange->acpOldEnd &&
  191. pChange->acpOldEnd == pChange->acpNewEnd)
  192. {
  193. // nothing happened
  194. return S_OK;
  195. }
  196. hr = E_OUTOFMEMORY;
  197. if ((paStart = _CreateAnchorACP(pChange->acpStart, TS_GR_BACKWARD)) == NULL)
  198. goto Exit;
  199. if ((paEnd = _CreateAnchorACP(pChange->acpOldEnd, TS_GR_FORWARD)) == NULL)
  200. {
  201. paStart->Release();
  202. goto Exit;
  203. }
  204. _fInOnTextChange = TRUE; // this flag stops us from trying to normalize anchors
  205. // do the alist update
  206. _Update(pChange);
  207. hr = _pic->_OnTextChangeInternal(dwFlags, paStart, paEnd, OWN_ANCHORS);
  208. _fInOnTextChange = FALSE;
  209. // get a lock eventually so we can deal with the changes
  210. _ptsi->RequestLock(TS_LF_READ, &hr2);
  211. Exit:
  212. return hr;
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // OnSelectionChange
  217. //
  218. //----------------------------------------------------------------------------
  219. STDAPI CACPWrap::OnSelectionChange()
  220. {
  221. // we never call this internally, so the caller must be the app.
  222. return _ptss->OnSelectionChange();
  223. }
  224. //+---------------------------------------------------------------------------
  225. //
  226. // OnLockGranted
  227. //
  228. //----------------------------------------------------------------------------
  229. STDAPI CACPWrap::OnLockGranted(DWORD dwLockFlags)
  230. {
  231. int i;
  232. SPAN *pSpan;
  233. int cSpans;
  234. CAnchorRef *parStart;
  235. CAnchorRef *parEnd;
  236. CSpanSet *pSpanSet;
  237. #ifdef DEBUG
  238. _Dbg_fAppHasLock = FALSE;
  239. #endif
  240. //
  241. // After IC is popped, we may be granted the lock...
  242. //
  243. if (!_pic || !_pic->_GetEditRecord())
  244. return E_UNEXPECTED;
  245. // generally the pic's er can contain app or tip changes
  246. // BUT, it will never hold both at the same time. And it will
  247. // only hold app changes (if any) when OnLockGranted is called
  248. pSpanSet = _pic->_GetEditRecord()->_GetTextSpanSet();
  249. // empty out our change cache
  250. if ((cSpans = pSpanSet->GetCount()) > 0)
  251. {
  252. // clean up the anchorlist!
  253. pSpan = pSpanSet->GetSpans();
  254. for (i=0; i<cSpans; i++)
  255. {
  256. parStart = GetCAnchorRef_NA(pSpan->paStart);
  257. parEnd = GetCAnchorRef_NA(pSpan->paEnd);
  258. _Renormalize(parStart->_GetACP(), parEnd->_GetACP());
  259. pSpan++;
  260. }
  261. }
  262. // then pass along the release to the uim
  263. return _ptss->OnLockGranted(dwLockFlags);
  264. }
  265. //+---------------------------------------------------------------------------
  266. //
  267. // OnLayoutChange
  268. //
  269. //----------------------------------------------------------------------------
  270. STDAPI CACPWrap::OnLayoutChange(TsLayoutCode lcode, TsViewCookie vcView)
  271. {
  272. return _ptss->OnLayoutChange(lcode, vcView);
  273. }
  274. //+---------------------------------------------------------------------------
  275. //
  276. // OnStatusChange
  277. //
  278. //----------------------------------------------------------------------------
  279. STDAPI CACPWrap::OnStatusChange(DWORD dwFlags)
  280. {
  281. return _ptss->OnStatusChange(dwFlags);
  282. }
  283. //+---------------------------------------------------------------------------
  284. //
  285. // OnStatusChange
  286. //
  287. //----------------------------------------------------------------------------
  288. STDAPI CACPWrap::OnAttrsChange(LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs)
  289. {
  290. IAnchor *paStart = NULL;
  291. IAnchor *paEnd = NULL;
  292. HRESULT hr;
  293. hr = E_OUTOFMEMORY;
  294. if ((paStart = _CreateAnchorACP(acpStart, TS_GR_BACKWARD)) == NULL)
  295. goto Exit;
  296. if ((paEnd = _CreateAnchorACP(acpEnd, TS_GR_FORWARD)) == NULL)
  297. goto Exit;
  298. hr = _ptss->OnAttrsChange(paStart, paEnd, cAttrs, paAttrs);
  299. Exit:
  300. SafeRelease(paStart);
  301. SafeRelease(paEnd);
  302. return hr;
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // OnStartEditTransaction
  307. //
  308. //----------------------------------------------------------------------------
  309. STDAPI CACPWrap::OnStartEditTransaction()
  310. {
  311. return _ptss->OnStartEditTransaction();
  312. }
  313. //+---------------------------------------------------------------------------
  314. //
  315. // OnEndEditTransaction
  316. //
  317. //----------------------------------------------------------------------------
  318. STDAPI CACPWrap::OnEndEditTransaction()
  319. {
  320. return _ptss->OnEndEditTransaction();
  321. }
  322. //+---------------------------------------------------------------------------
  323. //
  324. // AdviseSink
  325. //
  326. //----------------------------------------------------------------------------
  327. STDAPI CACPWrap::AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask)
  328. {
  329. IServiceProvider *psp;
  330. HRESULT hr;
  331. Assert(_ptss == NULL);
  332. Assert(_pic == NULL);
  333. if (punk->QueryInterface(IID_ITextStoreAnchorSink, (void **)&_ptss) != S_OK)
  334. return E_FAIL;
  335. // use QueryService to get the ic since msaa may be wrapping it
  336. if (punk->QueryInterface(IID_IServiceProvider, (void **)&psp) != S_OK)
  337. {
  338. hr = E_FAIL;
  339. goto ErrorExit;
  340. }
  341. hr = psp->QueryService(GUID_SERVICE_TF, IID_PRIV_CINPUTCONTEXT, (void **)&_pic);
  342. psp->Release();
  343. if (hr != S_OK)
  344. {
  345. hr = E_FAIL;
  346. goto ErrorExit;
  347. }
  348. // advise our wrapped acp
  349. if ((hr = _ptsi->AdviseSink(IID_ITextStoreACPSink, SAFECAST(this, ITextStoreACPSink *), dwMask)) != S_OK)
  350. goto ErrorExit;
  351. return S_OK;
  352. ErrorExit:
  353. SafeReleaseClear(_ptss);
  354. SafeReleaseClear(_pic);
  355. return hr;
  356. }
  357. //+---------------------------------------------------------------------------
  358. //
  359. // UnadviseSink
  360. //
  361. //----------------------------------------------------------------------------
  362. STDAPI CACPWrap::UnadviseSink(IUnknown *punk)
  363. {
  364. Assert(_ptss == punk); // we're dealing with cicero, this should always hold
  365. _ptsi->UnadviseSink(SAFECAST(this, ITextStoreACPSink *));
  366. SafeReleaseClear(_ptss);
  367. SafeReleaseClear(_pic);
  368. return S_OK;
  369. }
  370. //+---------------------------------------------------------------------------
  371. //
  372. // RequestLock
  373. //
  374. //----------------------------------------------------------------------------
  375. STDAPI CACPWrap::RequestLock(DWORD dwLockFlags, HRESULT *phrSession)
  376. {
  377. return _ptsi->RequestLock(dwLockFlags, phrSession);
  378. }
  379. //+---------------------------------------------------------------------------
  380. //
  381. // GetSelection
  382. //
  383. //----------------------------------------------------------------------------
  384. STDAPI CACPWrap::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ANCHOR *pSelection, ULONG *pcFetched)
  385. {
  386. TS_SELECTION_ACP *pSelACP;
  387. HRESULT hr;
  388. ULONG i;
  389. TS_SELECTION_ACP sel;
  390. Assert(pcFetched != NULL); // caller should have caught this
  391. *pcFetched = 0;
  392. if (ulCount == 1)
  393. {
  394. pSelACP = &sel;
  395. }
  396. else if ((pSelACP = (TS_SELECTION_ACP *)cicMemAlloc(ulCount*sizeof(TS_SELECTION_ACP))) == NULL)
  397. return E_OUTOFMEMORY;
  398. hr = _ptsi->GetSelection(ulIndex, ulCount, pSelACP, pcFetched);
  399. if (hr != S_OK)
  400. goto Exit;
  401. _Dbg_AssertNoAppLock();
  402. for (i=0; i<*pcFetched; i++)
  403. {
  404. if ((pSelection[i].paStart = _CreateAnchorACP(pSelACP[i].acpStart, TS_GR_FORWARD)) == NULL ||
  405. (pSelection[i].paEnd = _CreateAnchorACP(pSelACP[i].acpEnd, TS_GR_BACKWARD)) == NULL)
  406. {
  407. SafeRelease(pSelection[i].paStart);
  408. while (i>0)
  409. {
  410. i--;
  411. pSelection[i].paStart->Release();
  412. pSelection[i].paEnd->Release();
  413. }
  414. hr = E_FAIL;
  415. goto Exit;
  416. }
  417. pSelection[i].style = pSelACP[i].style;
  418. }
  419. Exit:
  420. if (pSelACP != &sel)
  421. {
  422. cicMemFree(pSelACP);
  423. }
  424. return hr;
  425. }
  426. //+---------------------------------------------------------------------------
  427. //
  428. // SetSelection
  429. //
  430. //----------------------------------------------------------------------------
  431. STDAPI CACPWrap::SetSelection(ULONG ulCount, const TS_SELECTION_ANCHOR *pSelection)
  432. {
  433. CAnchorRef *par;
  434. TS_SELECTION_ACP *pSelACP;
  435. ULONG i;
  436. HRESULT hr;
  437. TS_SELECTION_ACP sel;
  438. _Dbg_AssertNoAppLock();
  439. if (ulCount == 1)
  440. {
  441. pSelACP = &sel;
  442. }
  443. else if ((pSelACP = (TS_SELECTION_ACP *)cicMemAlloc(ulCount*sizeof(TS_SELECTION_ACP))) == NULL)
  444. return E_OUTOFMEMORY;
  445. hr = E_FAIL;
  446. for (i=0; i<ulCount; i++)
  447. {
  448. if ((par = GetCAnchorRef_NA(pSelection[i].paStart)) == NULL)
  449. goto Exit;
  450. pSelACP[i].acpStart = par->_GetACP();
  451. if (pSelection[i].paEnd == NULL)
  452. {
  453. // implies paEnd is same as paStart
  454. pSelACP[i].acpEnd = pSelACP[i].acpStart;
  455. }
  456. else
  457. {
  458. if ((par = GetCAnchorRef_NA(pSelection[i].paEnd)) == NULL)
  459. goto Exit;
  460. pSelACP[i].acpEnd = par->_GetACP();
  461. }
  462. pSelACP[i].style = pSelection[i].style;
  463. }
  464. hr = _ptsi->SetSelection(ulCount, pSelACP);
  465. Exit:
  466. if (pSelACP != &sel)
  467. {
  468. cicMemFree(pSelACP);
  469. }
  470. return hr;
  471. }
  472. //+---------------------------------------------------------------------------
  473. //
  474. // GetText
  475. //
  476. //----------------------------------------------------------------------------
  477. STDAPI CACPWrap::GetText(DWORD dwFlags, IAnchor *paStart, IAnchor *paEnd, WCHAR *pchText, ULONG cchReq, ULONG *pcch, BOOL fUpdateAnchor)
  478. {
  479. CAnchorRef *parStart;
  480. CAnchorRef *parEnd;
  481. LONG acpStart;
  482. LONG acpEnd;
  483. LONG acpNext;
  484. ULONG cchTotal;
  485. ULONG cchAdjust;
  486. ULONG ulRunInfoOut;
  487. HRESULT hr;
  488. ULONG i;
  489. WCHAR ch;
  490. WCHAR *pchSrc;
  491. WCHAR *pchDst;
  492. TS_RUNINFO rgRunInfo[16];
  493. _Dbg_AssertNoAppLock();
  494. Perf_IncCounter(PERF_ACPWRAP_GETTEXT);
  495. // this upfront check for a nop saves us from
  496. // 1) copying non-existant text based on non-zero run-info
  497. // 2) repositioning the start anchor based on non-zero run-info
  498. if (cchReq == 0)
  499. {
  500. *pcch = 0;
  501. return S_OK;
  502. }
  503. if ((parStart = GetCAnchorRef_NA(paStart)) == NULL)
  504. return E_FAIL;
  505. acpStart = parStart->_GetACP();
  506. acpEnd = -1;
  507. if (paEnd != NULL)
  508. {
  509. if ((parEnd = GetCAnchorRef_NA(paEnd)) == NULL)
  510. {
  511. hr = E_FAIL;
  512. goto Exit;
  513. }
  514. acpEnd = parEnd->_GetACP();
  515. }
  516. cchTotal = 0;
  517. while (TRUE)
  518. {
  519. Perf_IncCounter(PERF_ACPWRAP_GETTEXT_LOOP);
  520. hr = CProcessTextCache::GetText(_ptsi, acpStart, acpEnd, pchText, cchReq, pcch, rgRunInfo, ARRAYSIZE(rgRunInfo), &ulRunInfoOut, &acpNext);
  521. if (hr != S_OK)
  522. goto Exit;
  523. if (ulRunInfoOut == 0) // prevent a loop at eod
  524. break;
  525. // prune out any hidden text
  526. pchSrc = pchText;
  527. pchDst = pchText;
  528. for (i=0; i<ulRunInfoOut; i++)
  529. {
  530. switch (rgRunInfo[i].type)
  531. {
  532. case TS_RT_PLAIN:
  533. Assert(pchDst != NULL);
  534. if (pchSrc != pchDst)
  535. {
  536. memmove(pchDst, pchSrc, rgRunInfo[i].uCount*sizeof(WCHAR));
  537. }
  538. pchSrc += rgRunInfo[i].uCount;
  539. pchDst += rgRunInfo[i].uCount;
  540. break;
  541. case TS_RT_HIDDEN:
  542. pchSrc += rgRunInfo[i].uCount;
  543. *pcch -= rgRunInfo[i].uCount;
  544. Assert((int)(*pcch) >= 0); // app bug if this is less than zero
  545. break;
  546. case TS_RT_OPAQUE:
  547. break;
  548. }
  549. }
  550. // prune out any TS_CHAR_REGIONs
  551. pchSrc = pchText;
  552. pchDst = pchText;
  553. for (i=0; i<*pcch; i++)
  554. {
  555. ch = *pchSrc;
  556. if (ch != TS_CHAR_REGION)
  557. {
  558. if (pchSrc != pchDst)
  559. {
  560. *pchDst = ch;
  561. }
  562. pchDst++;
  563. }
  564. pchSrc++;
  565. }
  566. // dec the count by the number of TS_CHAR_REGIONs we removed
  567. cchAdjust = *pcch - (ULONG)(pchSrc - pchDst);
  568. cchTotal += cchAdjust;
  569. // done?
  570. cchReq -= cchAdjust;
  571. if (cchReq <= 0)
  572. break;
  573. acpStart = acpNext;
  574. if (acpEnd >= 0 && acpStart >= acpEnd)
  575. break;
  576. pchText += cchAdjust;
  577. }
  578. *pcch = cchTotal;
  579. if (fUpdateAnchor)
  580. {
  581. parStart->_SetACP(acpNext);
  582. }
  583. Exit:
  584. return hr;
  585. }
  586. //+---------------------------------------------------------------------------
  587. //
  588. // _PostInsertUpdate
  589. //
  590. //----------------------------------------------------------------------------
  591. void CACPWrap::_PostInsertUpdate(LONG acpStart, LONG acpEnd, ULONG cch, const TS_TEXTCHANGE *ptsTextChange)
  592. {
  593. Assert(ptsTextChange->acpStart <= acpStart); // bogus output from app?
  594. if (ptsTextChange->acpStart < acpStart &&
  595. cch > 0 &&
  596. acpStart != acpEnd)
  597. {
  598. // this is unusual. The original text was like:
  599. // ----ABC "-" is formatting, we replace with "XX"
  600. //
  601. // the new text is like:
  602. // XX problem!
  603. // or possibly
  604. // ----XX no problem
  605. //
  606. // if "----ABC" -> "XX", then paStart will be placed after the ABC
  607. // because it was normalized to start with:
  608. //
  609. // "----<paStart>ABC<paEnd>" -> "XX<paStart><paEnd>"
  610. //
  611. // We need to fix this up.
  612. _DragAnchors(acpStart, ptsTextChange->acpStart);
  613. }
  614. _Update(ptsTextChange);
  615. _Renormalize(ptsTextChange->acpStart, ptsTextChange->acpNewEnd);
  616. }
  617. //+---------------------------------------------------------------------------
  618. //
  619. // SetText
  620. //
  621. //----------------------------------------------------------------------------
  622. STDAPI CACPWrap::SetText(DWORD dwFlags, IAnchor *paStart, IAnchor *paEnd, const WCHAR *pchText, ULONG cch)
  623. {
  624. CAnchorRef *parStart;
  625. CAnchorRef *parEnd;
  626. LONG acpStart;
  627. LONG acpEnd;
  628. TS_TEXTCHANGE dctc;
  629. HRESULT hr;
  630. _Dbg_AssertNoAppLock();
  631. if ((parStart = GetCAnchorRef_NA(paStart)) == NULL)
  632. return E_FAIL;
  633. acpStart = parStart->_GetACP();
  634. if ((parEnd = GetCAnchorRef_NA(paEnd)) == NULL)
  635. return E_FAIL;
  636. acpEnd = parEnd->_GetACP();
  637. // for perf, filter out the nop
  638. if (acpStart == acpEnd && cch == 0)
  639. return S_OK;
  640. // do the work
  641. hr = _ptsi->SetText(dwFlags, acpStart, acpEnd, pchText, cch, &dctc);
  642. // we'll handle the anchor updates -- the app won't give us an OnTextChange callback for our
  643. // own changes
  644. if (hr == S_OK)
  645. {
  646. _PostInsertUpdate(acpStart, acpEnd, cch, &dctc);
  647. }
  648. return hr;
  649. }
  650. //+---------------------------------------------------------------------------
  651. //
  652. // GetFormattedText
  653. //
  654. //----------------------------------------------------------------------------
  655. STDAPI CACPWrap::GetFormattedText(IAnchor *paStart, IAnchor *paEnd, IDataObject **ppDataObject)
  656. {
  657. CAnchorRef *par;
  658. LONG acpStart;
  659. LONG acpEnd;
  660. Assert(*ppDataObject == NULL);
  661. _Dbg_AssertNoAppLock();
  662. if ((par = GetCAnchorRef_NA(paStart)) == NULL)
  663. return E_FAIL;
  664. acpStart = par->_GetACP();
  665. if ((par = GetCAnchorRef_NA(paEnd)) == NULL)
  666. return E_FAIL;
  667. acpEnd = par->_GetACP();
  668. // do the work
  669. return _ptsi->GetFormattedText(acpStart, acpEnd, ppDataObject);
  670. }
  671. //+---------------------------------------------------------------------------
  672. //
  673. // GetEmbedded
  674. //
  675. //----------------------------------------------------------------------------
  676. STDAPI CACPWrap::GetEmbedded(DWORD dwFlags, IAnchor *paPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk)
  677. {
  678. CAnchorRef *par;
  679. LONG acpPos;
  680. if (ppunk == NULL)
  681. return E_INVALIDARG;
  682. *ppunk = NULL;
  683. if (paPos == NULL)
  684. return E_INVALIDARG;
  685. if ((par = GetCAnchorRef_NA(paPos)) == NULL)
  686. return E_FAIL;
  687. if (!par->_GetAnchor()->IsNormalized())
  688. {
  689. // we need to be positioned just before the next char
  690. _NormalizeAnchor(par->_GetAnchor());
  691. }
  692. acpPos = par->_GetACP();
  693. if (!(dwFlags & TS_GEA_HIDDEN))
  694. {
  695. // skip past any hidden text
  696. acpPos = Normalize(_ptsi, acpPos, NORM_SKIP_HIDDEN);
  697. }
  698. return _ptsi->GetEmbedded(acpPos, rguidService, riid, ppunk);
  699. }
  700. //+---------------------------------------------------------------------------
  701. //
  702. // QueryInsertEmbedded
  703. //
  704. //----------------------------------------------------------------------------
  705. STDAPI CACPWrap::QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable)
  706. {
  707. return _ptsi->QueryInsertEmbedded(pguidService, pFormatEtc, pfInsertable);
  708. }
  709. //+---------------------------------------------------------------------------
  710. //
  711. // InsertEmbedded
  712. //
  713. //----------------------------------------------------------------------------
  714. STDAPI CACPWrap::InsertEmbedded(DWORD dwFlags, IAnchor *paStart, IAnchor *paEnd, IDataObject *pDataObject)
  715. {
  716. CAnchorRef *par;
  717. LONG acpStart;
  718. LONG acpEnd;
  719. TS_TEXTCHANGE dctc;
  720. HRESULT hr;
  721. if (paStart == NULL || paEnd == NULL || pDataObject == NULL)
  722. return E_INVALIDARG;
  723. if ((par = GetCAnchorRef_NA(paStart)) == NULL)
  724. return E_FAIL;
  725. acpStart = par->_GetACP();
  726. if ((par = GetCAnchorRef_NA(paEnd)) == NULL)
  727. return E_FAIL;
  728. acpEnd = par->_GetACP();
  729. hr = _ptsi->InsertEmbedded(dwFlags, acpStart, acpEnd, pDataObject, &dctc);
  730. // we'll handle the anchor updates -- the app won't give us an OnTextChange callback for our
  731. // own changes
  732. if (hr == S_OK)
  733. {
  734. _PostInsertUpdate(acpStart, acpEnd, 1 /* cch */, &dctc);
  735. }
  736. return hr;
  737. }
  738. //+---------------------------------------------------------------------------
  739. //
  740. // GetStart
  741. //
  742. //----------------------------------------------------------------------------
  743. STDAPI CACPWrap::GetStart(IAnchor **ppaStart)
  744. {
  745. _Dbg_AssertNoAppLock();
  746. if (ppaStart == NULL)
  747. return E_INVALIDARG;
  748. *ppaStart = NULL;
  749. return (*ppaStart = _CreateAnchorACP(0, TS_GR_FORWARD)) ? S_OK : E_OUTOFMEMORY;
  750. }
  751. //+---------------------------------------------------------------------------
  752. //
  753. // GetEnd
  754. //
  755. //----------------------------------------------------------------------------
  756. STDAPI CACPWrap::GetEnd(IAnchor **ppaEnd)
  757. {
  758. LONG acpEnd;
  759. HRESULT hr;
  760. _Dbg_AssertNoAppLock();
  761. if (ppaEnd == NULL)
  762. return E_INVALIDARG;
  763. *ppaEnd = NULL;
  764. if (FAILED(hr = _ptsi->GetEndACP(&acpEnd)))
  765. return hr;
  766. return (*ppaEnd = _CreateAnchorACP(acpEnd, TS_GR_FORWARD)) ? S_OK : E_OUTOFMEMORY;
  767. }
  768. //+---------------------------------------------------------------------------
  769. //
  770. // GetStatus
  771. //
  772. //----------------------------------------------------------------------------
  773. STDAPI CACPWrap::GetStatus(TS_STATUS *pdcs)
  774. {
  775. return _ptsi->GetStatus(pdcs);
  776. }
  777. //+---------------------------------------------------------------------------
  778. //
  779. // QueryInsert
  780. //
  781. //----------------------------------------------------------------------------
  782. STDAPI CACPWrap::QueryInsert(IAnchor *paTestStart, IAnchor *paTestEnd, ULONG cch, IAnchor **ppaResultStart, IAnchor **ppaResultEnd)
  783. {
  784. LONG acpTestStart;
  785. LONG acpTestEnd;
  786. LONG acpResultStart;
  787. LONG acpResultEnd;
  788. CAnchorRef *par;
  789. HRESULT hr;
  790. if (ppaResultStart != NULL)
  791. {
  792. *ppaResultStart = NULL;
  793. }
  794. if (ppaResultEnd != NULL)
  795. {
  796. *ppaResultEnd = NULL;
  797. }
  798. if (ppaResultStart == NULL || ppaResultEnd == NULL)
  799. return E_INVALIDARG;
  800. if ((par = GetCAnchorRef_NA(paTestStart)) == NULL)
  801. return E_INVALIDARG;
  802. acpTestStart = par->_GetACP();
  803. if ((par = GetCAnchorRef_NA(paTestEnd)) == NULL)
  804. return E_INVALIDARG;
  805. acpTestEnd = par->_GetACP();
  806. hr = _ptsi->QueryInsert(acpTestStart, acpTestEnd, cch, &acpResultStart, &acpResultEnd);
  807. if (hr != S_OK)
  808. return E_FAIL;
  809. if (acpResultStart < 0)
  810. {
  811. *ppaResultStart = NULL;
  812. }
  813. else if ((*ppaResultStart = _CreateAnchorACP(acpResultStart, TS_GR_BACKWARD)) == NULL)
  814. return E_OUTOFMEMORY;
  815. if (acpResultEnd < 0)
  816. {
  817. *ppaResultEnd = NULL;
  818. }
  819. else if ((*ppaResultEnd = _CreateAnchorACP(acpResultEnd, TS_GR_FORWARD)) == NULL)
  820. {
  821. SafeRelease(*ppaResultStart);
  822. return E_OUTOFMEMORY;
  823. }
  824. return S_OK;
  825. }
  826. //+---------------------------------------------------------------------------
  827. //
  828. // GetAnchorFromPoint
  829. //
  830. //----------------------------------------------------------------------------
  831. STDAPI CACPWrap::GetAnchorFromPoint(TsViewCookie vcView, const POINT *pt, DWORD dwFlags, IAnchor **ppaSite)
  832. {
  833. LONG acp;
  834. if (ppaSite != NULL)
  835. {
  836. *ppaSite = NULL;
  837. }
  838. if (pt == NULL || ppaSite == NULL)
  839. return E_INVALIDARG;
  840. if (dwFlags & ~(GXFPF_ROUND_NEAREST | GXFPF_NEAREST))
  841. return E_INVALIDARG;
  842. if (FAILED(_ptsi->GetACPFromPoint(vcView, pt, dwFlags, &acp)))
  843. return E_FAIL;
  844. _Dbg_AssertNoAppLock();
  845. return (*ppaSite = _CreateAnchorACP(acp, TS_GR_FORWARD)) ? S_OK : E_OUTOFMEMORY;
  846. }
  847. //+---------------------------------------------------------------------------
  848. //
  849. // GetTextExt
  850. //
  851. //----------------------------------------------------------------------------
  852. STDAPI CACPWrap::GetTextExt(TsViewCookie vcView, IAnchor *paStart, IAnchor *paEnd, RECT *prc, BOOL *pfClipped)
  853. {
  854. CAnchorRef *par;
  855. LONG acpStart;
  856. LONG acpEnd;
  857. _Dbg_AssertNoAppLock();
  858. if (prc != NULL)
  859. {
  860. memset(prc, 0, sizeof(*prc));
  861. }
  862. if (pfClipped != NULL)
  863. {
  864. *pfClipped = FALSE;
  865. }
  866. if (paStart == NULL || paEnd == NULL || prc == NULL || pfClipped == NULL)
  867. return E_INVALIDARG;
  868. if ((par = GetCAnchorRef_NA(paStart)) == NULL)
  869. return E_FAIL;
  870. acpStart = par->_GetACP();
  871. if ((par = GetCAnchorRef_NA(paEnd)) == NULL)
  872. return E_FAIL;
  873. acpEnd = par->_GetACP();
  874. return _ptsi->GetTextExt(vcView, acpStart, acpEnd, prc, pfClipped);
  875. }
  876. //+---------------------------------------------------------------------------
  877. //
  878. // GetScreenExt
  879. //
  880. //----------------------------------------------------------------------------
  881. STDAPI CACPWrap::GetScreenExt(TsViewCookie vcView, RECT *prc)
  882. {
  883. if (prc == NULL)
  884. return E_INVALIDARG;
  885. return _ptsi->GetScreenExt(vcView, prc);
  886. }
  887. //+---------------------------------------------------------------------------
  888. //
  889. // GetWnd
  890. //
  891. //----------------------------------------------------------------------------
  892. STDAPI CACPWrap::GetWnd(TsViewCookie vcView, HWND *phwnd)
  893. {
  894. if (phwnd == NULL)
  895. return E_INVALIDARG;
  896. return _ptsi->GetWnd(vcView, phwnd);
  897. }
  898. //+---------------------------------------------------------------------------
  899. //
  900. // Serialize
  901. //
  902. //----------------------------------------------------------------------------
  903. STDAPI CACPWrap::Serialize(ITfProperty *pProp, ITfRange *pRange, TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, IStream *pStream)
  904. {
  905. #ifdef LATER
  906. // word won't grant us a sync lock here even though we need one
  907. SERIALIZE_ACP_PARAMS params;
  908. HRESULT hr;
  909. params.pWrap = this;
  910. params.pProp = pProp;
  911. params.pRange = pRange;
  912. params.pHdr = pHdr;
  913. params.pStream = pStream;
  914. // need a sync read lock to do our work
  915. if (_pic->_DoPseudoSyncEditSession(TF_ES_READ, PSEUDO_ESCB_SERIALIZE_ACP, &params, &hr) != S_OK)
  916. {
  917. Assert(0); // app won't give us a sync read lock
  918. return E_FAIL;
  919. }
  920. return hr;
  921. #else
  922. return _Serialize(pProp, pRange, pHdr, pStream);
  923. #endif
  924. }
  925. //+---------------------------------------------------------------------------
  926. //
  927. // _Serialize
  928. //
  929. //----------------------------------------------------------------------------
  930. HRESULT CACPWrap::_Serialize(ITfProperty *pProp, ITfRange *pRange, TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, IStream *pStream)
  931. {
  932. TF_PERSISTENT_PROPERTY_HEADER_ANCHOR phanch;
  933. CProperty *pPropP = NULL;
  934. CRange *pRangeP;
  935. HRESULT hr = E_FAIL;
  936. if ((pPropP = GetCProperty(pProp)) == NULL)
  937. goto Exit;
  938. if ((pRangeP = GetCRange_NA(pRange)) == NULL)
  939. goto Exit;
  940. if (!VerifySameContext(_pic, pRangeP))
  941. goto Exit;
  942. hr = pPropP->_Serialize(pRangeP, &phanch, pStream);
  943. if (hr == S_OK)
  944. {
  945. if (!_AnchorHdrToACP(&phanch, pHdr))
  946. {
  947. memset(pHdr, 0, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP));
  948. hr = E_FAIL;
  949. Assert(0);
  950. }
  951. }
  952. else
  953. {
  954. memset(pHdr, 0, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP));
  955. }
  956. Assert(pHdr->ichStart >= 0);
  957. Assert(pHdr->cch >= 0);
  958. SafeRelease(phanch.paStart);
  959. SafeRelease(phanch.paEnd);
  960. Exit:
  961. SafeRelease(pPropP);
  962. return hr;
  963. }
  964. //+---------------------------------------------------------------------------
  965. //
  966. // Unserialize
  967. //
  968. //----------------------------------------------------------------------------
  969. STDAPI CACPWrap::Unserialize(ITfProperty *pProp, const TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, IStream *pStream, ITfPersistentPropertyLoaderACP *pLoaderACP)
  970. {
  971. UNSERIALIZE_ACP_PARAMS params;
  972. HRESULT hr;
  973. params.pWrap = this;
  974. params.pProp = pProp;
  975. params.pHdr = pHdr;
  976. params.pStream = pStream;
  977. params.pLoaderACP = pLoaderACP;
  978. // need a sync read lock to do our work
  979. if (_pic->_DoPseudoSyncEditSession(TF_ES_READ, PSEUDO_ESCB_UNSERIALIZE_ACP, &params, &hr) != S_OK)
  980. {
  981. Assert(0); // app won't give us a sync read lock
  982. return E_FAIL;
  983. }
  984. return hr;
  985. }
  986. //+---------------------------------------------------------------------------
  987. //
  988. // _Unserialize
  989. //
  990. //----------------------------------------------------------------------------
  991. HRESULT CACPWrap::_Unserialize(ITfProperty *pProp, const TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, IStream *pStream, ITfPersistentPropertyLoaderACP *pLoaderACP)
  992. {
  993. TF_PERSISTENT_PROPERTY_HEADER_ANCHOR hdrAnchor;
  994. CProperty *pPropP = NULL;
  995. CLoaderACPWrap *pLoader;
  996. HRESULT hr = E_FAIL;
  997. Assert(pHdr->ichStart >= 0);
  998. Assert(pHdr->cch > 0);
  999. hdrAnchor.paStart = NULL;
  1000. hdrAnchor.paEnd = NULL;
  1001. if (pHdr->ichStart < 0)
  1002. goto Exit;
  1003. if (pHdr->cch <= 0)
  1004. goto Exit;
  1005. if (_ACPHdrToAnchor(pHdr, &hdrAnchor) != S_OK)
  1006. {
  1007. Assert(0);
  1008. goto Exit;
  1009. }
  1010. if ((pPropP = GetCProperty(pProp)) == NULL)
  1011. goto Exit;
  1012. pLoader = NULL;
  1013. if (pLoaderACP != NULL &&
  1014. (pLoader = new CLoaderACPWrap(pLoaderACP)) == NULL)
  1015. {
  1016. hr = E_OUTOFMEMORY;
  1017. goto Exit;
  1018. }
  1019. hr = pPropP->_Unserialize(&hdrAnchor, pStream, pLoader);
  1020. SafeRelease(pLoader);
  1021. Exit:
  1022. SafeRelease(pPropP);
  1023. SafeRelease(hdrAnchor.paStart);
  1024. SafeRelease(hdrAnchor.paEnd);
  1025. return hr;
  1026. }
  1027. //+---------------------------------------------------------------------------
  1028. //
  1029. // ForceLoadProperty
  1030. //
  1031. //----------------------------------------------------------------------------
  1032. STDAPI CACPWrap::ForceLoadProperty(ITfProperty *pProp)
  1033. {
  1034. CProperty *pPropP;
  1035. HRESULT hr;
  1036. if ((pPropP = GetCProperty(pProp)) == NULL)
  1037. return E_FAIL;
  1038. hr = pPropP->ForceLoad();
  1039. pPropP->Release();
  1040. return hr;
  1041. }
  1042. //+---------------------------------------------------------------------------
  1043. //
  1044. // CreateRange
  1045. //
  1046. //----------------------------------------------------------------------------
  1047. STDAPI CACPWrap::CreateRange(LONG acpStart, LONG acpEnd, ITfRangeACP **ppRange)
  1048. {
  1049. ITfRangeAnchor *rangeAnchor;
  1050. CAnchorRef *paStart;
  1051. CAnchorRef *paEnd;
  1052. HRESULT hr;
  1053. ITextStoreAnchorServices *pserv;
  1054. if (ppRange == NULL)
  1055. return E_INVALIDARG;
  1056. *ppRange = NULL;
  1057. hr = E_FAIL;
  1058. paEnd = NULL;
  1059. Perf_IncCounter(PERF_CREATERANGE_ACP);
  1060. if ((paStart = _CreateAnchorACP(acpStart, TS_GR_BACKWARD)) == NULL)
  1061. goto Exit;
  1062. if ((paEnd = _CreateAnchorACP(acpEnd, TS_GR_BACKWARD)) == NULL)
  1063. goto Exit;
  1064. if ((hr = _ptss->QueryInterface(IID_ITextStoreAnchorServices, (void **)&pserv)) == S_OK)
  1065. {
  1066. hr = pserv->CreateRange(paStart, paEnd, &rangeAnchor);
  1067. pserv->Release();
  1068. }
  1069. if (hr == S_OK)
  1070. {
  1071. *ppRange = (ITfRangeACP *)(CRange *)rangeAnchor;
  1072. }
  1073. Exit:
  1074. SafeRelease(paStart);
  1075. SafeRelease(paEnd);
  1076. return hr;
  1077. }
  1078. //+---------------------------------------------------------------------------
  1079. //
  1080. // _CreateAnchorACP
  1081. //
  1082. //----------------------------------------------------------------------------
  1083. CAnchorRef *CACPWrap::_CreateAnchorACP(LONG acp, TsGravity gravity)
  1084. {
  1085. CAnchorRef *pa;
  1086. if ((pa = new CAnchorRef) == NULL)
  1087. return NULL;
  1088. if (!pa->_Init(this, acp, gravity))
  1089. {
  1090. pa->Release();
  1091. return NULL;
  1092. }
  1093. return pa;
  1094. }
  1095. //+---------------------------------------------------------------------------
  1096. //
  1097. // _CreateAnchorACP
  1098. //
  1099. //----------------------------------------------------------------------------
  1100. CAnchorRef *CACPWrap::_CreateAnchorAnchor(CAnchor *paAnchor, TsGravity gravity)
  1101. {
  1102. CAnchorRef *pa;
  1103. if ((pa = new CAnchorRef) == NULL)
  1104. return NULL;
  1105. if (!pa->_Init(this, paAnchor, gravity))
  1106. {
  1107. pa->Release();
  1108. return NULL;
  1109. }
  1110. return pa;
  1111. }
  1112. //+---------------------------------------------------------------------------
  1113. //
  1114. // _ACPHdrToAnchor
  1115. //
  1116. //----------------------------------------------------------------------------
  1117. HRESULT CACPWrap::_ACPHdrToAnchor(const TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *phanch)
  1118. {
  1119. phanch->paStart = NULL;
  1120. if ((phanch->paStart = _CreateAnchorACP(pHdr->ichStart, TS_GR_FORWARD)) == NULL)
  1121. goto ExitError;
  1122. if ((phanch->paEnd = _CreateAnchorACP(pHdr->ichStart + pHdr->cch, TS_GR_BACKWARD)) == NULL)
  1123. goto ExitError;
  1124. phanch->guidType = pHdr->guidType;
  1125. phanch->cb = pHdr->cb;
  1126. phanch->dwPrivate = pHdr->dwPrivate;
  1127. phanch->clsidTIP = pHdr->clsidTIP;
  1128. return S_OK;
  1129. ExitError:
  1130. SafeRelease(phanch->paStart);
  1131. return E_FAIL;
  1132. }
  1133. //+---------------------------------------------------------------------------
  1134. //
  1135. // _AnchorHdrToACP
  1136. //
  1137. //----------------------------------------------------------------------------
  1138. /* static */
  1139. BOOL CACPWrap::_AnchorHdrToACP(const TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *phanch, TF_PERSISTENT_PROPERTY_HEADER_ACP *phacp)
  1140. {
  1141. CAnchorRef *par;
  1142. if ((par = GetCAnchorRef_NA(phanch->paStart)) == NULL)
  1143. return FALSE;
  1144. NormalizeAnchor(par);
  1145. phacp->ichStart = par->_GetACP();
  1146. if ((par = GetCAnchorRef_NA(phanch->paEnd)) == NULL)
  1147. return FALSE;
  1148. NormalizeAnchor(par);
  1149. phacp->cch = par->_GetACP() - phacp->ichStart;
  1150. phacp->guidType = phanch->guidType;
  1151. phacp->cb = phanch->cb;
  1152. phacp->dwPrivate = phanch->dwPrivate;
  1153. phacp->clsidTIP = phanch->clsidTIP;
  1154. return TRUE;
  1155. }
  1156. //+---------------------------------------------------------------------------
  1157. //
  1158. // RequestSupportedAttrs
  1159. //
  1160. //----------------------------------------------------------------------------
  1161. STDAPI CACPWrap::RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs)
  1162. {
  1163. return _ptsi->RequestSupportedAttrs(dwFlags, cFilterAttrs, paFilterAttrs);
  1164. }
  1165. //+---------------------------------------------------------------------------
  1166. //
  1167. // RequestAttrsAtPosition
  1168. //
  1169. //----------------------------------------------------------------------------
  1170. STDAPI CACPWrap::RequestAttrsAtPosition(IAnchor *paPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
  1171. {
  1172. CAnchorRef *par;
  1173. LONG acpPos;
  1174. if ((par = GetCAnchorRef_NA(paPos)) == NULL)
  1175. return E_INVALIDARG;
  1176. acpPos = par->_GetACP();
  1177. return _ptsi->RequestAttrsAtPosition(acpPos, cFilterAttrs, paFilterAttrs, dwFlags);
  1178. }
  1179. //+---------------------------------------------------------------------------
  1180. //
  1181. // RequestAttrsTransitioningAtPosition
  1182. //
  1183. //----------------------------------------------------------------------------
  1184. STDAPI CACPWrap::RequestAttrsTransitioningAtPosition(IAnchor *paPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
  1185. {
  1186. CAnchorRef *par;
  1187. LONG acpPos;
  1188. if ((par = GetCAnchorRef_NA(paPos)) == NULL)
  1189. return E_INVALIDARG;
  1190. acpPos = par->_GetACP();
  1191. return _ptsi->RequestAttrsTransitioningAtPosition(acpPos, cFilterAttrs, paFilterAttrs, dwFlags);
  1192. }
  1193. //+---------------------------------------------------------------------------
  1194. //
  1195. // FindNextAttrTransition
  1196. //
  1197. //----------------------------------------------------------------------------
  1198. STDAPI CACPWrap::FindNextAttrTransition(IAnchor *paStart, IAnchor *paHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, BOOL *pfFound, LONG *plFoundOffset)
  1199. {
  1200. CAnchorRef *parStart;
  1201. CAnchorRef *parHalt;
  1202. LONG acpStart;
  1203. LONG acpHalt;
  1204. LONG acpNext;
  1205. HRESULT hr;
  1206. if ((parStart = GetCAnchorRef_NA(paStart)) == NULL)
  1207. return E_INVALIDARG;
  1208. acpStart = parStart->_GetACP();
  1209. acpHalt = -1;
  1210. if (paHalt != NULL)
  1211. {
  1212. hr = E_INVALIDARG;
  1213. if ((parHalt = GetCAnchorRef_NA(paHalt)) == NULL)
  1214. goto Exit;
  1215. acpHalt = parHalt->_GetACP();
  1216. }
  1217. hr = _ptsi->FindNextAttrTransition(acpStart, acpHalt, cFilterAttrs, paFilterAttrs, dwFlags, &acpNext, pfFound, plFoundOffset);
  1218. if (hr == S_OK &&
  1219. (dwFlags & TS_ATTR_FIND_UPDATESTART))
  1220. {
  1221. parStart->_SetACP(acpNext);
  1222. }
  1223. Exit:
  1224. return hr;
  1225. }
  1226. //+---------------------------------------------------------------------------
  1227. //
  1228. // RetrieveRequestedAttrs
  1229. //
  1230. //----------------------------------------------------------------------------
  1231. STDAPI CACPWrap::RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched)
  1232. {
  1233. return _ptsi->RetrieveRequestedAttrs(ulCount, paAttrVals, pcFetched);
  1234. }
  1235. //+---------------------------------------------------------------------------
  1236. //
  1237. // AdviseMouseSink
  1238. //
  1239. //----------------------------------------------------------------------------
  1240. STDAPI CACPWrap::AdviseMouseSink(ITfRangeACP *range, ITfMouseSink *pSink, DWORD *pdwCookie)
  1241. {
  1242. ITfMouseTrackerACP *pTrackerACP;
  1243. HRESULT hr;
  1244. if (pdwCookie == NULL)
  1245. return E_INVALIDARG;
  1246. *pdwCookie = 0;
  1247. if (_ptsi->QueryInterface(IID_ITfMouseTrackerACP, (void **)&pTrackerACP) != S_OK)
  1248. return E_NOTIMPL;
  1249. hr = pTrackerACP->AdviseMouseSink(range, pSink, pdwCookie);
  1250. pTrackerACP->Release();
  1251. return hr;
  1252. }
  1253. //+---------------------------------------------------------------------------
  1254. //
  1255. // UnadviseMouseSink
  1256. //
  1257. //----------------------------------------------------------------------------
  1258. STDAPI CACPWrap::UnadviseMouseSink(DWORD dwCookie)
  1259. {
  1260. ITfMouseTrackerACP *pTrackerACP;
  1261. HRESULT hr;
  1262. if (_ptsi->QueryInterface(IID_ITfMouseTrackerACP, (void **)&pTrackerACP) != S_OK)
  1263. return E_NOTIMPL;
  1264. hr = pTrackerACP->UnadviseMouseSink(dwCookie);
  1265. pTrackerACP->Release();
  1266. return hr;
  1267. }
  1268. //+---------------------------------------------------------------------------
  1269. //
  1270. // QueryService
  1271. //
  1272. //----------------------------------------------------------------------------
  1273. STDAPI CACPWrap::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  1274. {
  1275. IServiceProvider *psp;
  1276. HRESULT hr;
  1277. if (ppv == NULL)
  1278. return E_INVALIDARG;
  1279. *ppv = NULL;
  1280. // SVC_E_NOSERVICE is proper return code for wrong service....
  1281. // but it's not defined anywhere. So use E_NOINTERFACE for both
  1282. // cases as trident is rumored to do
  1283. hr = E_NOINTERFACE;
  1284. if (IsEqualGUID(guidService, GUID_SERVICE_TF) &&
  1285. IsEqualIID(riid, IID_PRIV_ACPWRAP))
  1286. {
  1287. *ppv = this;
  1288. AddRef();
  1289. hr = S_OK;
  1290. }
  1291. else if (_ptsi->QueryInterface(IID_IServiceProvider, (void **)&psp) == S_OK)
  1292. {
  1293. // we just pass the request along to the wrapped obj
  1294. hr = psp->QueryService(guidService, riid, ppv);
  1295. psp->Release();
  1296. }
  1297. return hr;
  1298. }
  1299. //+---------------------------------------------------------------------------
  1300. //
  1301. // GetActiveView
  1302. //
  1303. //----------------------------------------------------------------------------
  1304. STDAPI CACPWrap::GetActiveView(TsViewCookie *pvcView)
  1305. {
  1306. if (pvcView == NULL)
  1307. return E_INVALIDARG;
  1308. return _ptsi->GetActiveView(pvcView);
  1309. }
  1310. //+---------------------------------------------------------------------------
  1311. //
  1312. // InsertTextAtSelection
  1313. //
  1314. //----------------------------------------------------------------------------
  1315. STDAPI CACPWrap::InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, IAnchor **ppaStart, IAnchor **ppaEnd)
  1316. {
  1317. LONG acpStart;
  1318. LONG acpEnd;
  1319. TS_TEXTCHANGE dctc;
  1320. HRESULT hr;
  1321. _Dbg_AssertNoAppLock();
  1322. Assert(ppaStart != NULL && ppaEnd != NULL);
  1323. Assert((dwFlags & TS_IAS_QUERYONLY) || pchText != NULL); // caller should have already caught this
  1324. Assert((dwFlags & TS_IAS_QUERYONLY) || cch > 0); // caller should have already caught this
  1325. Assert((dwFlags & (TS_IAS_NOQUERY | TS_IAS_QUERYONLY)) != (TS_IAS_NOQUERY | TS_IAS_QUERYONLY));
  1326. *ppaStart = NULL;
  1327. *ppaEnd = NULL;
  1328. hr = _ptsi->InsertTextAtSelection(dwFlags, pchText, cch, &acpStart, &acpEnd, &dctc);
  1329. // we'll handle the anchor updates -- the app won't give us an OnTextChange callback for our
  1330. // own changes
  1331. if (hr != S_OK)
  1332. return hr;
  1333. if (!(dwFlags & TF_IAS_QUERYONLY))
  1334. {
  1335. _PostInsertUpdate(acpStart, acpEnd, cch, &dctc);
  1336. }
  1337. if (!(dwFlags & TF_IAS_NOQUERY))
  1338. {
  1339. if ((*ppaStart = _CreateAnchorACP(acpStart, TS_GR_BACKWARD)) == NULL)
  1340. goto ExitError;
  1341. if ((*ppaEnd = _CreateAnchorACP(acpEnd, TS_GR_FORWARD)) == NULL)
  1342. goto ExitError;
  1343. }
  1344. return S_OK;
  1345. ExitError:
  1346. SafeReleaseClear(*ppaStart);
  1347. return E_FAIL;
  1348. }
  1349. //+---------------------------------------------------------------------------
  1350. //
  1351. // InsertEmbeddedAtSelection
  1352. //
  1353. //----------------------------------------------------------------------------
  1354. STDAPI CACPWrap::InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, IAnchor **ppaStart, IAnchor **ppaEnd)
  1355. {
  1356. LONG acpStart;
  1357. LONG acpEnd;
  1358. TS_TEXTCHANGE dctc;
  1359. HRESULT hr;
  1360. _Dbg_AssertNoAppLock();
  1361. Assert(ppaStart != NULL && ppaEnd != NULL);
  1362. Assert((dwFlags & (TS_IAS_NOQUERY | TS_IAS_QUERYONLY)) != (TS_IAS_NOQUERY | TS_IAS_QUERYONLY));
  1363. Assert((dwFlags & TS_IAS_QUERYONLY) || pDataObject == NULL);
  1364. *ppaStart = NULL;
  1365. *ppaEnd = NULL;
  1366. hr = _ptsi->InsertEmbeddedAtSelection(dwFlags, pDataObject, &acpStart, &acpEnd, &dctc);
  1367. // we'll handle the anchor updates -- the app won't give us an OnTextChange callback for our
  1368. // own changes
  1369. if (hr != S_OK)
  1370. return hr;
  1371. if (!(dwFlags & TF_IAS_QUERYONLY))
  1372. {
  1373. _PostInsertUpdate(acpStart, acpEnd, 1 /* cch */, &dctc);
  1374. }
  1375. if (!(dwFlags & TF_IAS_NOQUERY))
  1376. {
  1377. if ((*ppaStart = _CreateAnchorACP(acpStart, TS_GR_BACKWARD)) == NULL)
  1378. goto ExitError;
  1379. if ((*ppaEnd = _CreateAnchorACP(acpEnd, TS_GR_FORWARD)) == NULL)
  1380. goto ExitError;
  1381. }
  1382. return S_OK;
  1383. ExitError:
  1384. SafeReleaseClear(*ppaStart);
  1385. return E_FAIL;
  1386. }