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.

605 lines
17 KiB

  1. //
  2. // rmcoll.cpp
  3. //
  4. // Render markup/collections.
  5. //
  6. #include "private.h"
  7. #include "dam.h"
  8. #include "saa.h"
  9. #include "strary.h"
  10. #include "ic.h"
  11. #include "attr.h"
  12. #include "range.h"
  13. #include "immxutil.h"
  14. #include "rprop.h"
  15. //////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. //
  18. // CRenderMarkupCollection
  19. //
  20. //////////////////////////////////////////////////////////////////////////////
  21. //////////////////////////////////////////////////////////////////////////////
  22. //+---------------------------------------------------------------------------
  23. //
  24. // ctor
  25. //
  26. //----------------------------------------------------------------------------
  27. CRenderMarkupCollection::CRenderMarkupCollection()
  28. {
  29. // always add GUID_PROP_ATTRIBUTE at index 0
  30. if (!_rgGUIDAtom.Append(1))
  31. return;
  32. if (!_rgOther.Append(1))
  33. {
  34. _rgGUIDAtom.Clear();
  35. return;
  36. }
  37. MyRegisterGUID(GUID_PROP_ATTRIBUTE, _rgGUIDAtom.GetPtr(0));
  38. _rgOther.GetPtr(0)->uPriority = TF_DA_PRIORITY_HIGHEST;
  39. _rgOther.GetPtr(0)->gaTip = g_gaSystem;
  40. }
  41. //+---------------------------------------------------------------------------
  42. //
  43. // _Advise
  44. //
  45. //----------------------------------------------------------------------------
  46. void CRenderMarkupCollection::_Advise(ITfTextInputProcessor *tip, TfGuidAtom gaTip)
  47. {
  48. ITfDisplayAttributeCollectionProvider *pProvider;
  49. ULONG uCount;
  50. TF_DA_PROPERTY rgProperty[8];
  51. int i;
  52. int iOldCount;
  53. int iOld;
  54. int iNew;
  55. if (tip->QueryInterface(IID_ITfDisplayAttributeCollectionProvider, (void **)&pProvider) != S_OK)
  56. return;
  57. if (pProvider->GetCollection(ARRAYSIZE(rgProperty), rgProperty, &uCount) != S_OK || uCount == 0)
  58. goto Exit;
  59. iOldCount = _rgGUIDAtom.Count();
  60. Assert(iOldCount == _rgOther.Count());
  61. if (!_rgGUIDAtom.Append(uCount))
  62. goto Exit;
  63. if (!_rgOther.Append(uCount))
  64. {
  65. _rgGUIDAtom.Remove(iOldCount, uCount);
  66. goto Exit;
  67. }
  68. // merge the new guids with the old
  69. // nb: we assume rgProperty is sorted
  70. iNew = uCount-1;
  71. iOld = iOldCount-1;
  72. for (i=iNew + iOld + 1; i>=0; i--)
  73. {
  74. // nb: we put new GUIDs with same priority as existing GUIDs lower in the list
  75. // this makes sure that GUID_PROP_ATTRIBUTE is always at index 0, and keeps
  76. // existing rendering consistent (no change on screen of existing markup)
  77. if (iNew >= 0 &&
  78. rgProperty[iNew].uPriority >= _rgOther.GetPtr(iOld)->uPriority)
  79. {
  80. MyRegisterGUID(rgProperty[iNew].guidProperty, _rgGUIDAtom.GetPtr(i));
  81. _rgOther.GetPtr(i)->uPriority = rgProperty[iNew].uPriority;
  82. _rgOther.GetPtr(i)->gaTip = gaTip;
  83. iNew--;
  84. }
  85. else
  86. {
  87. *_rgGUIDAtom.GetPtr(i) = *_rgGUIDAtom.GetPtr(iOld);
  88. *_rgOther.GetPtr(i) = *_rgOther.GetPtr(iOld);
  89. iOld--;
  90. }
  91. }
  92. Exit:
  93. pProvider->Release();
  94. }
  95. //+---------------------------------------------------------------------------
  96. //
  97. // _Unadvise
  98. //
  99. //----------------------------------------------------------------------------
  100. void CRenderMarkupCollection::_Unadvise(TfGuidAtom gaTip)
  101. {
  102. int iOldCount;
  103. int iNewCount;
  104. int i;
  105. int iDst;
  106. iOldCount = _rgGUIDAtom.Count();
  107. iNewCount = 0;
  108. iDst = -1;
  109. for (i=0; i<iOldCount; i++)
  110. {
  111. if (_rgOther.GetPtr(i)->gaTip == gaTip)
  112. {
  113. if (iDst == -1)
  114. {
  115. iDst = i;
  116. }
  117. }
  118. else if (iDst != -1)
  119. {
  120. *_rgGUIDAtom.GetPtr(iDst) = *_rgGUIDAtom.GetPtr(i);
  121. *_rgOther.GetPtr(iDst) = *_rgOther.GetPtr(i);
  122. iDst++;
  123. iNewCount++;
  124. }
  125. }
  126. if (iDst != -1)
  127. {
  128. _rgGUIDAtom.Remove(iDst, iOldCount - iDst);
  129. _rgOther.Remove(iDst, iOldCount - iDst);
  130. }
  131. Assert(_rgGUIDAtom.Count() == _rgOther.Count());
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // _IsInCollection
  136. //
  137. //----------------------------------------------------------------------------
  138. BOOL CRenderMarkupCollection::_IsInCollection(REFGUID rguidProperty)
  139. {
  140. TfGuidAtom tfGuidAtom;
  141. int i;
  142. if (_rgGUIDAtom.Count() == 0)
  143. return FALSE;
  144. MyRegisterGUID(rguidProperty, &tfGuidAtom);
  145. for (i=0; i<_rgGUIDAtom.Count(); i++)
  146. {
  147. if (*_rgGUIDAtom.GetPtr(i) == tfGuidAtom)
  148. return TRUE;
  149. }
  150. return FALSE;
  151. }
  152. //////////////////////////////////////////////////////////////////////////////
  153. //////////////////////////////////////////////////////////////////////////////
  154. //
  155. // CEnumRenderingMarkup
  156. //
  157. //////////////////////////////////////////////////////////////////////////////
  158. //////////////////////////////////////////////////////////////////////////////
  159. class CEnumRenderingMarkup : public IEnumTfRenderingMarkup,
  160. public CComObjectRootImmx
  161. {
  162. public:
  163. CEnumRenderingMarkup()
  164. {
  165. Dbg_MemSetThisNameIDCounter(TEXT("CEnumRenderingMarkup"), PERF_UBERPROP_COUNTER);
  166. }
  167. ~CEnumRenderingMarkup();
  168. BEGIN_COM_MAP_IMMX(CEnumRenderingMarkup)
  169. COM_INTERFACE_ENTRY(IEnumTfRenderingMarkup)
  170. END_COM_MAP_IMMX()
  171. IMMX_OBJECT_IUNKNOWN_FOR_ATL()
  172. BOOL _Init(DWORD dwFlags, CRange *pRangeCover, CInputContext *pContext);
  173. // IEnumTfRenderingMarkup
  174. STDMETHODIMP Clone(IEnumTfRenderingMarkup **ppClone);
  175. STDMETHODIMP Next(ULONG ulCount, TF_RENDERINGMARKUP *rgMarkup, ULONG *pcFetched);
  176. STDMETHODIMP Reset();
  177. STDMETHODIMP Skip(ULONG ulCount);
  178. private:
  179. int _iCur;
  180. CSharedAnchorArray *_prgAnchors;
  181. CSharedStructArray<TF_DISPLAYATTRIBUTE> *_prgValues;
  182. CInputContext *_pContext;
  183. DBG_ID_DECLARE;
  184. };
  185. DBG_ID_INSTANCE(CEnumRenderingMarkup);
  186. //+---------------------------------------------------------------------------
  187. //
  188. // dtor
  189. //
  190. //----------------------------------------------------------------------------
  191. CEnumRenderingMarkup::~CEnumRenderingMarkup()
  192. {
  193. if (_prgAnchors != NULL)
  194. {
  195. _prgAnchors->_Release();
  196. }
  197. if (_prgValues != NULL)
  198. {
  199. _prgValues->_Release();
  200. }
  201. _pContext->Release();
  202. }
  203. //+---------------------------------------------------------------------------
  204. //
  205. // LookupProperty
  206. //
  207. //----------------------------------------------------------------------------
  208. BOOL LookupProperty(CInputContext *pContext, ITfDisplayAttributeMgr *pDisplayAttrMgr,
  209. TfGuidAtom tfGuidAtom, IAnchor *paStart, IAnchor *paEnd, TF_DISPLAYATTRIBUTE *ptfAttrInfoNext)
  210. {
  211. CProperty *pProperty;
  212. ITfDisplayAttributeInfo *pDisplayAttrInfo;
  213. VARIANT varValue;
  214. GUID guidValue;
  215. BOOL fRet;
  216. // get the property matching the GUID
  217. if ((pProperty = pContext->_FindProperty(tfGuidAtom)) == NULL)
  218. return FALSE;
  219. // get the GUID value of the property
  220. if (pProperty->_GetDataInternal(paStart, paEnd, &varValue) != S_OK) // perf: don't really need paEnd
  221. return FALSE;
  222. Assert(varValue.vt == VT_I4); // should be a GUIDATOM
  223. if (MyGetGUID(varValue.lVal, &guidValue) != S_OK)
  224. return FALSE;
  225. // translate the GUID to a display attribute
  226. if (pDisplayAttrMgr->GetDisplayAttributeInfo(guidValue, &pDisplayAttrInfo, NULL) != S_OK)
  227. return FALSE;
  228. fRet = (pDisplayAttrInfo->GetAttributeInfo(ptfAttrInfoNext) == S_OK);
  229. pDisplayAttrInfo->Release();
  230. return fRet;
  231. }
  232. //+---------------------------------------------------------------------------
  233. //
  234. // _Init
  235. //
  236. //----------------------------------------------------------------------------
  237. BOOL CEnumRenderingMarkup::_Init(DWORD dwFlags, CRange *pRangeCover, CInputContext *pContext)
  238. {
  239. CDisplayAttributeMgr *pDisplayAttrMgr;
  240. CRenderMarkupCollection *pMarkupCollection;
  241. int i;
  242. int j;
  243. TF_DISPLAYATTRIBUTE *ptfAttrInfo;
  244. TF_DISPLAYATTRIBUTE tfAttrInfoNext;
  245. BOOL fNeedLine;
  246. BOOL fNeedText;
  247. BOOL fRet;
  248. ULONG uCount;
  249. const TfGuidAtom *pAtoms;
  250. Assert(_iCur == 0);
  251. Assert(_pContext == NULL);
  252. Assert(_prgAnchors == NULL);
  253. Assert(_prgValues == NULL);
  254. pDisplayAttrMgr = CDisplayAttributeMgr::_GetThis();
  255. if (pDisplayAttrMgr == NULL)
  256. {
  257. Assert(0); // ITfThreadMgr::Activate should ensure the singleton is initialized in tls
  258. return FALSE;
  259. }
  260. fRet = FALSE;
  261. pMarkupCollection = pDisplayAttrMgr->_GetMarkupCollection();
  262. // find the cicero property transitions
  263. if (dwFlags & TF_GRM_INCLUDE_PROPERTY)
  264. {
  265. uCount = pMarkupCollection->_Count();
  266. pAtoms = pMarkupCollection->_GetAtoms();
  267. }
  268. else
  269. {
  270. // skip GUID_PROP_ATTRIBUTE at index 0
  271. Assert(pMarkupCollection->_Count() >= 1);
  272. uCount = pMarkupCollection->_Count() - 1;
  273. pAtoms = pMarkupCollection->_GetAtoms() + 1;
  274. }
  275. _prgAnchors = CalcCicPropertyTrackerAnchors(pContext, pRangeCover->_GetStart(), pRangeCover->_GetEnd(),
  276. pMarkupCollection->_Count(), pMarkupCollection->_GetAtoms());
  277. if (_prgAnchors == NULL)
  278. goto Exit;
  279. Assert(_prgAnchors->Count() > 0); // we should get at least the pRangeCover start anchor
  280. if ((_prgValues = new CSharedStructArray<TF_DISPLAYATTRIBUTE>) == NULL)
  281. goto Exit;
  282. if (_prgAnchors->Count() > 1) // Append(0) will return NULL if the array is empty
  283. { // which is fine, but we don't want to return failure in that case (empty range => empty enum)
  284. if (!_prgValues->Append(_prgAnchors->Count()-1))
  285. goto Exit;
  286. }
  287. // now calculate the TF_DISPLAYATTRIBUTE for each span
  288. for (i=0; i<_prgAnchors->Count()-1; i++)
  289. {
  290. ptfAttrInfo = _prgValues->GetPtr(i);
  291. memset(ptfAttrInfo, 0, sizeof(*ptfAttrInfo));
  292. ptfAttrInfo->bAttr = TF_ATTR_OTHER;
  293. fNeedLine = TRUE;
  294. fNeedText = TRUE;
  295. // examine property values over the single span
  296. // index 0 is always GUID_PROP_ATTRIBUTE, only include it if the TF_GRM_INCLUDE_PROPERTY is set
  297. j = (dwFlags & TF_GRM_INCLUDE_PROPERTY) ? 0 : 1;
  298. for (; j<pMarkupCollection->_Count(); j++)
  299. {
  300. // get the property matching the GUID
  301. if (!LookupProperty(pContext, pDisplayAttrMgr, pMarkupCollection->_GetAtom(j), _prgAnchors->Get(i), _prgAnchors->Get(i+1), &tfAttrInfoNext))
  302. continue;
  303. // we got one
  304. if (fNeedText &&
  305. (tfAttrInfoNext.crText.type != TF_CT_NONE || tfAttrInfoNext.crBk.type != TF_CT_NONE))
  306. {
  307. ptfAttrInfo->crText = tfAttrInfoNext.crText;
  308. ptfAttrInfo->crBk = tfAttrInfoNext.crBk;
  309. fNeedText = FALSE;
  310. }
  311. if (fNeedLine &&
  312. tfAttrInfoNext.lsStyle != TF_LS_NONE)
  313. {
  314. ptfAttrInfo->lsStyle = tfAttrInfoNext.lsStyle;
  315. ptfAttrInfo->crLine = tfAttrInfoNext.crLine;
  316. ptfAttrInfo->fBoldLine = tfAttrInfoNext.fBoldLine;
  317. fNeedLine = FALSE;
  318. }
  319. // we can stop looking at this span if everything lower in the z-order is blocked
  320. if (j == 0 && (!fNeedText || !fNeedLine))
  321. break; // GUID_PROP_ATTRIBUTE is never masked with anything else
  322. if (!fNeedText && !fNeedLine)
  323. break; // couldn't mask in any more attributes
  324. }
  325. }
  326. _pContext = pContext;
  327. _pContext->AddRef();
  328. fRet = TRUE;
  329. Exit:
  330. return fRet;
  331. }
  332. //+---------------------------------------------------------------------------
  333. //
  334. // Clone
  335. //
  336. //----------------------------------------------------------------------------
  337. STDAPI CEnumRenderingMarkup::Clone(IEnumTfRenderingMarkup **ppEnum)
  338. {
  339. CEnumRenderingMarkup *pClone;
  340. if (ppEnum == NULL)
  341. return E_INVALIDARG;
  342. *ppEnum = NULL;
  343. if ((pClone = new CEnumRenderingMarkup) == NULL)
  344. return E_OUTOFMEMORY;
  345. pClone->_iCur = _iCur;
  346. pClone->_prgAnchors = _prgAnchors;
  347. pClone->_prgAnchors->_AddRef();
  348. pClone->_prgValues = _prgValues ;
  349. pClone->_prgValues->_AddRef();
  350. pClone->_pContext = _pContext;
  351. pClone->_pContext->AddRef();
  352. *ppEnum = pClone;
  353. return S_OK;
  354. }
  355. //+---------------------------------------------------------------------------
  356. //
  357. // Next
  358. //
  359. //----------------------------------------------------------------------------
  360. STDAPI CEnumRenderingMarkup::Next(ULONG ulCount, TF_RENDERINGMARKUP *rgMarkup, ULONG *pcFetched)
  361. {
  362. ULONG cFetched;
  363. CRange *range;
  364. IAnchor *paPrev;
  365. IAnchor *pa;
  366. int iCurOld;
  367. if (pcFetched == NULL)
  368. {
  369. pcFetched = &cFetched;
  370. }
  371. *pcFetched = 0;
  372. iCurOld = _iCur;
  373. if (ulCount > 0 && rgMarkup == NULL)
  374. return E_INVALIDARG;
  375. // we should always have at least one anchor (one anchor => empty range for enum, nothing to enum)
  376. Assert(_prgAnchors->Count() >= 1);
  377. paPrev = _prgAnchors->Get(_iCur);
  378. while (_iCur < _prgAnchors->Count()-1 && *pcFetched < ulCount)
  379. {
  380. pa = _prgAnchors->Get(_iCur+1);
  381. if ((range = new CRange) == NULL)
  382. break;
  383. if (!range->_InitWithDefaultGravity(_pContext, COPY_ANCHORS, paPrev, pa))
  384. {
  385. range->Release();
  386. break;
  387. }
  388. // we should never be returning empty ranges, since currently this base
  389. // class is only used for property enums and property spans are never
  390. // empty.
  391. // Similarly, paPrev should always precede pa.
  392. Assert(CompareAnchors(paPrev, pa) < 0);
  393. rgMarkup->pRange = (ITfRangeAnchor *)range;
  394. rgMarkup->tfDisplayAttr = *_prgValues->GetPtr(_iCur);
  395. rgMarkup++;
  396. *pcFetched = *pcFetched + 1;
  397. _iCur++;
  398. paPrev = pa;
  399. }
  400. return *pcFetched == ulCount ? S_OK : S_FALSE;
  401. }
  402. //+---------------------------------------------------------------------------
  403. //
  404. // Reset
  405. //
  406. //----------------------------------------------------------------------------
  407. STDAPI CEnumRenderingMarkup::Reset()
  408. {
  409. _iCur = 0;
  410. return S_OK;
  411. }
  412. //+---------------------------------------------------------------------------
  413. //
  414. // Skip
  415. //
  416. //----------------------------------------------------------------------------
  417. STDAPI CEnumRenderingMarkup::Skip(ULONG ulCount)
  418. {
  419. _iCur += ulCount;
  420. return (_iCur > _prgValues->Count()) ? S_FALSE : S_OK;
  421. }
  422. //////////////////////////////////////////////////////////////////////////////
  423. //////////////////////////////////////////////////////////////////////////////
  424. //
  425. // CDisplayAttributeMgr
  426. //
  427. //////////////////////////////////////////////////////////////////////////////
  428. //////////////////////////////////////////////////////////////////////////////
  429. //+---------------------------------------------------------------------------
  430. //
  431. // EnumCollections
  432. //
  433. //----------------------------------------------------------------------------
  434. STDAPI CDisplayAttributeMgr::EnumCollections(IEnumTfCollection **ppEnum)
  435. {
  436. return E_NOTIMPL;
  437. }
  438. //////////////////////////////////////////////////////////////////////////////
  439. //////////////////////////////////////////////////////////////////////////////
  440. //
  441. // CInputContext
  442. //
  443. //////////////////////////////////////////////////////////////////////////////
  444. //////////////////////////////////////////////////////////////////////////////
  445. //+---------------------------------------------------------------------------
  446. //
  447. // GetRenderingMarkup
  448. //
  449. //----------------------------------------------------------------------------
  450. STDAPI CInputContext::GetRenderingMarkup(TfEditCookie ec, DWORD dwFlags,
  451. ITfRange *pRangeCover,
  452. IEnumTfRenderingMarkup **ppEnum)
  453. {
  454. CEnumRenderingMarkup *pEnum;
  455. CRange *range;
  456. if (ppEnum == NULL)
  457. return E_INVALIDARG;
  458. *ppEnum = NULL;
  459. if (!_IsValidEditCookie(ec, TF_ES_READ))
  460. return TF_E_NOLOCK;
  461. if (dwFlags & ~TF_GRM_INCLUDE_PROPERTY)
  462. return E_INVALIDARG;
  463. if (pRangeCover == NULL)
  464. return E_INVALIDARG;
  465. if ((range = GetCRange_NA(pRangeCover)) == NULL)
  466. return E_INVALIDARG;
  467. if (!_IsConnected())
  468. return TF_E_DISCONNECTED;
  469. if ((pEnum = new CEnumRenderingMarkup) == NULL)
  470. return E_OUTOFMEMORY;
  471. if (!pEnum->_Init(dwFlags, range, this))
  472. {
  473. pEnum->Release();
  474. return E_FAIL;
  475. }
  476. *ppEnum = pEnum;
  477. return S_OK;
  478. }
  479. //+---------------------------------------------------------------------------
  480. //
  481. // FindNextRenderingMarkup
  482. //
  483. //----------------------------------------------------------------------------
  484. STDAPI CInputContext::FindNextRenderingMarkup(TfEditCookie ec, DWORD dwFlags,
  485. ITfRange *pRangeQuery,
  486. TfAnchor tfAnchorQuery,
  487. ITfRange **ppRangeFound,
  488. TF_RENDERINGMARKUP *ptfRenderingMarkup)
  489. {
  490. return E_NOTIMPL;
  491. }