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.

379 lines
9.6 KiB

  1. //
  2. // rprange.cpp
  3. //
  4. #include "private.h"
  5. #include "ic.h"
  6. #include "rprop.h"
  7. #include "range.h"
  8. #include "tim.h"
  9. #include "rngsink.h"
  10. #include "immxutil.h"
  11. //+---------------------------------------------------------------------------
  12. //
  13. // GetData
  14. //
  15. //----------------------------------------------------------------------------
  16. HRESULT CProperty::_GetDataInternal(IAnchor *paStart, IAnchor *paEnd, VARIANT *pvarValue)
  17. {
  18. HRESULT hr;
  19. PROPERTYLIST *pPropList;
  20. if (pvarValue == NULL)
  21. return E_INVALIDARG;
  22. QuickVariantInit(pvarValue);
  23. pPropList = _FindPropList(paStart, paEnd);
  24. if (pPropList)
  25. {
  26. if (!pPropList->_pPropStore)
  27. {
  28. if (FAILED(hr = LoadData(pPropList)))
  29. goto Exit;
  30. }
  31. hr = pPropList->_pPropStore->GetData(pvarValue);
  32. }
  33. else
  34. {
  35. // property has no value over the range
  36. hr = S_FALSE;
  37. }
  38. Exit:
  39. return hr;
  40. }
  41. //+---------------------------------------------------------------------------
  42. //
  43. // _SetStoreInternal
  44. //
  45. //----------------------------------------------------------------------------
  46. HRESULT CProperty::_SetStoreInternal(TfEditCookie ec, CRange *pRange, ITfPropertyStore *pPropStore, BOOL fInternal)
  47. {
  48. GUID guidStore;
  49. if (pPropStore == NULL)
  50. return E_INVALIDARG;
  51. if (!fInternal)
  52. {
  53. //
  54. // Make sure this property is not using System's StaticPropStore.
  55. //
  56. if (GetPropStyle() != TFPROPSTYLE_CUSTOM && GetPropStyle() != TFPROPSTYLE_CUSTOM_COMPACT)
  57. return E_FAIL;
  58. }
  59. if (IsEqualAnchor(pRange->_GetStart(), pRange->_GetEnd()))
  60. return E_INVALIDARG;
  61. //
  62. // Check type of PropertyStore.
  63. //
  64. if (FAILED(pPropStore->GetType(&guidStore)))
  65. return E_FAIL;
  66. if (!MyIsEqualTfGuidAtom(GetPropGuidAtom(), guidStore))
  67. return E_FAIL;
  68. return Set(pRange->_GetStart(), pRange->_GetEnd(), pPropStore);
  69. }
  70. //+---------------------------------------------------------------------------
  71. //
  72. // _SetDataInternal
  73. //
  74. //----------------------------------------------------------------------------
  75. HRESULT CProperty::_SetDataInternal(TfEditCookie ec, IAnchor *paStart, IAnchor *paEnd, const VARIANT *pvarValue)
  76. {
  77. CGeneralPropStore *store;
  78. HRESULT hr;
  79. Assert(!IsEqualAnchor(paStart, paEnd)); // caller should have checked
  80. switch (GetPropStyle())
  81. {
  82. case TFPROPSTYLE_STATIC:
  83. case TFPROPSTYLE_STATICCOMPACT:
  84. if ((store = new CStaticPropStore) == NULL)
  85. return E_OUTOFMEMORY;
  86. break;
  87. case TFPROPSTYLE_CUSTOM:
  88. case TFPROPSTYLE_CUSTOM_COMPACT:
  89. //
  90. // This property is not using System's StaticPropStore.
  91. // so we use a default range property sink.
  92. //
  93. if ((store = new CGeneralPropStore) == NULL)
  94. return E_OUTOFMEMORY;
  95. break;
  96. default:
  97. Assert(0); // bogus style!
  98. return E_UNEXPECTED;
  99. }
  100. if (!store->_Init(GetPropGuidAtom(), pvarValue, _dwPropFlags))
  101. {
  102. store->Release();
  103. return E_FAIL;
  104. }
  105. hr = Set(paStart, paEnd, store);
  106. store->Release();
  107. return hr;
  108. }
  109. //+---------------------------------------------------------------------------
  110. //
  111. // ClearInternal
  112. //
  113. //----------------------------------------------------------------------------
  114. HRESULT CProperty::_ClearInternal(TfEditCookie ec, IAnchor *paStart, IAnchor *paEnd)
  115. {
  116. PROPERTYLIST *pPropertyList;
  117. LONG nCur;
  118. if (paStart != NULL)
  119. {
  120. Assert(paEnd != NULL);
  121. if (IsEqualAnchor(paStart, paEnd))
  122. return S_OK;
  123. Clear(paStart, paEnd, 0, FALSE);
  124. Find(paStart, &nCur, FALSE);
  125. if (nCur >= 0)
  126. _DefragAfterThis(nCur);
  127. }
  128. else
  129. {
  130. // Clear(NULL, NULL) means wipe all instances
  131. for (nCur=0; nCur<_rgProp.Count(); nCur++)
  132. {
  133. pPropertyList = _rgProp.Get(nCur);
  134. if (CompareAnchors(pPropertyList->_paStart, pPropertyList->_paEnd) <= 0)
  135. {
  136. PropertyUpdated(pPropertyList->_paStart, pPropertyList->_paEnd);
  137. }
  138. else
  139. {
  140. // crossed anchors
  141. PropertyUpdated(pPropertyList->_paEnd, pPropertyList->_paEnd);
  142. }
  143. _FreePropertyList(pPropertyList);
  144. }
  145. _rgProp.Clear();
  146. }
  147. return S_OK;
  148. }
  149. //+---------------------------------------------------------------------------
  150. //
  151. // _FindPropList
  152. //
  153. //----------------------------------------------------------------------------
  154. PROPERTYLIST *CProperty::_FindPropList(IAnchor *paStart, IAnchor *paEnd)
  155. {
  156. PROPERTYLIST *pPropList;
  157. LONG nCur;
  158. if (CompareAnchors(paStart, paEnd) == 0)
  159. return NULL;
  160. //
  161. // The range does not have to be exactly matched.
  162. // we can return pPropList covers the given range.
  163. //
  164. Find(paStart, &nCur, FALSE);
  165. if (nCur < 0)
  166. return NULL;
  167. pPropList = SafeGetPropList(nCur);
  168. if (!pPropList)
  169. {
  170. Assert(0);
  171. return NULL;
  172. }
  173. Assert(CompareAnchors(paStart, pPropList->_paStart) >= 0);
  174. if (CompareAnchors(paEnd, pPropList->_paEnd) <= 0)
  175. return pPropList;
  176. return NULL;
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // _FindPropListAndDivide
  181. //
  182. //----------------------------------------------------------------------------
  183. PROPERTYLIST *CProperty::_FindPropListAndDivide(IAnchor *paStart, IAnchor *paEnd)
  184. {
  185. PROPERTYLIST *pPropList = NULL;
  186. LONG nCur;
  187. ITfPropertyStore *pNewPropStore;
  188. IAnchor *paTmp = NULL;
  189. BOOL fExactMatch;
  190. HRESULT hr;
  191. if (CompareAnchors(paStart, paEnd) == 0)
  192. return NULL;
  193. fExactMatch = (Find(paStart, &nCur, FALSE) != NULL);
  194. if (nCur < 0)
  195. goto Exit;
  196. pPropList = SafeGetPropList(nCur);
  197. if (!pPropList)
  198. {
  199. Assert(0);
  200. goto Exit;
  201. }
  202. if (_propStyle == TFPROPSTYLE_STATICCOMPACT ||
  203. _propStyle == TFPROPSTYLE_CUSTOM_COMPACT)
  204. {
  205. Assert(CompareAnchors(paStart, pPropList->_paStart) >= 0);
  206. if (CompareAnchors(paEnd, pPropList->_paEnd) <= 0)
  207. return pPropList;
  208. pPropList = NULL;
  209. goto Exit;
  210. }
  211. if (!fExactMatch)
  212. {
  213. if (CompareAnchors(paStart, pPropList->_paEnd) >= 0)
  214. {
  215. // query span begins at or after pPropList end-of-span
  216. // is there a following property?
  217. if ((pPropList = SafeGetPropList(nCur+1)) == NULL)
  218. goto Exit;
  219. // there is, does the query span cover it?
  220. if (CompareAnchors(paEnd, pPropList->_paStart) <= 0)
  221. {
  222. pPropList = NULL;
  223. goto Exit; // nope
  224. }
  225. // okay, our left edge will be the start of the following property
  226. }
  227. else
  228. {
  229. Assert(CompareAnchors(paStart, pPropList->_paStart) > 0);
  230. pNewPropStore = NULL;
  231. hr = pPropList->_paEnd->Clone(&paTmp);
  232. if (FAILED(hr) || !paTmp)
  233. {
  234. pPropList = NULL;
  235. goto Exit;
  236. }
  237. hr = _Divide(pPropList, paStart, paStart, &pNewPropStore);
  238. if ((hr == S_OK) && pNewPropStore)
  239. {
  240. _CreateNewProp(paStart,
  241. paTmp,
  242. pNewPropStore,
  243. NULL);
  244. pNewPropStore->Release();
  245. }
  246. else
  247. {
  248. pPropList = NULL;
  249. goto Exit;
  250. }
  251. pPropList = Find(paStart, NULL, FALSE);
  252. if (!pPropList)
  253. {
  254. Assert(0);
  255. goto Exit;
  256. }
  257. }
  258. }
  259. Assert(CompareAnchors(paStart, pPropList->_paStart) == 0);
  260. SafeReleaseClear(paTmp);
  261. if (CompareAnchors(paEnd, pPropList->_paEnd) < 0)
  262. {
  263. pNewPropStore = NULL;
  264. hr = pPropList->_paEnd->Clone(&paTmp);
  265. if (FAILED(hr) || !paTmp)
  266. {
  267. pPropList = NULL;
  268. goto Exit;
  269. }
  270. hr = _Divide(pPropList, paEnd, paEnd, &pNewPropStore);
  271. if ((hr == S_OK) && pNewPropStore)
  272. {
  273. _CreateNewProp(paEnd,
  274. paTmp,
  275. pNewPropStore,
  276. NULL);
  277. pNewPropStore->Release();
  278. }
  279. else
  280. {
  281. pPropList = NULL;
  282. goto Exit;
  283. }
  284. pPropList = Find(paStart, NULL, FALSE);
  285. if (!pPropList)
  286. {
  287. Assert(0);
  288. goto Exit;
  289. }
  290. }
  291. Assert(CompareAnchors(paStart, pPropList->_paStart) == 0);
  292. Assert(CompareAnchors(paEnd, pPropList->_paEnd) == 0);
  293. Exit:
  294. SafeRelease(paTmp);
  295. return pPropList;
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // SetPropertyLoader
  300. //
  301. //----------------------------------------------------------------------------
  302. HRESULT CProperty::_SetPropertyLoaderInternal(TfEditCookie ec, CRange *pRange, CPropertyLoad *pPropLoad)
  303. {
  304. if (IsEqualAnchor(pRange->_GetStart(), pRange->_GetEnd()))
  305. return S_OK;
  306. return SetLoader(pRange->_GetStart(), pRange->_GetEnd(), pPropLoad);
  307. }