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.

501 lines
12 KiB

  1. //
  2. // perange.cpp
  3. //
  4. #include "private.h"
  5. #include "helpers.h"
  6. #include "ic.h"
  7. #include "range.h"
  8. #include "rangebk.h"
  9. #include "rprop.h"
  10. #include "immxutil.h"
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // CRangeBackup
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. //+---------------------------------------------------------------------------
  17. //
  18. // ctor
  19. //
  20. //----------------------------------------------------------------------------
  21. CRangeBackupProperty::CRangeBackupProperty(CRangeBackup *ppr, CProperty *pProp)
  22. {
  23. _ppr = ppr;
  24. _pProp = pProp;
  25. }
  26. //+---------------------------------------------------------------------------
  27. //
  28. // dtor
  29. //
  30. //----------------------------------------------------------------------------
  31. CRangeBackupProperty::~CRangeBackupProperty()
  32. {
  33. int i;
  34. int nCnt = _rgPropRanges.Count();
  35. for (i = 0; i < nCnt; i++)
  36. {
  37. PERSISTPROPERTYRANGE *pPropRange;
  38. pPropRange = _rgPropRanges.GetPtr(i);
  39. Assert(pPropRange);
  40. Assert(pPropRange->_pPropStore);
  41. pPropRange->_pPropStore->Release();
  42. pPropRange->_pPropStore = NULL;
  43. }
  44. }
  45. //+---------------------------------------------------------------------------
  46. //
  47. // Init
  48. //
  49. //----------------------------------------------------------------------------
  50. BOOL CRangeBackupProperty::Init(TfEditCookie ec)
  51. {
  52. IEnumTfRanges *pEnum;
  53. ITfRange *pRange;
  54. HRESULT hr;
  55. hr = _pProp->EnumRanges(ec, &pEnum, (ITfRangeAnchor *)_ppr->_pRange);
  56. if (FAILED(hr) || !pEnum)
  57. return FALSE;
  58. while (pEnum->Next(1, &pRange, NULL) == S_OK)
  59. {
  60. CRange *pCRange;
  61. pCRange = GetCRange_NA(pRange);
  62. if (pCRange)
  63. {
  64. _StoreOneRange(ec, pCRange);
  65. }
  66. pRange->Release();
  67. }
  68. pEnum->Release();
  69. return TRUE;
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // StoreOneRange
  74. //
  75. //----------------------------------------------------------------------------
  76. BOOL CRangeBackupProperty::_StoreOneRange(TfEditCookie ec, CRange *pCRange)
  77. {
  78. PROPERTYLIST *pPropList;
  79. ULONG achStart = 0;
  80. ULONG achEnd = 0;
  81. if (CompareAnchors(pCRange->_GetStart(), _ppr->_pRange->_GetStart()) < 0)
  82. {
  83. if (CompareAnchors(pCRange->_GetEnd(), _ppr->_pRange->_GetEnd()) > 0)
  84. {
  85. pPropList = _pProp->_FindPropListAndDivide(_ppr->_pRange->_GetStart(), _ppr->_pRange->_GetEnd());
  86. achStart = _GetOffset(ec, _ppr->_pRange->_GetStart());
  87. achEnd = _GetOffset(ec, _ppr->_pRange->_GetEnd());
  88. }
  89. else
  90. {
  91. pPropList = _pProp->_FindPropListAndDivide(_ppr->_pRange->_GetStart(), pCRange->_GetEnd());
  92. achStart = _GetOffset(ec, _ppr->_pRange->_GetStart());
  93. achEnd = _GetOffset(ec, pCRange->_GetEnd());
  94. }
  95. }
  96. else if (CompareAnchors(pCRange->_GetEnd(), _ppr->_pRange->_GetEnd()) > 0)
  97. {
  98. pPropList = _pProp->_FindPropListAndDivide(pCRange->_GetStart(), _ppr->_pRange->_GetEnd());
  99. achStart = _GetOffset(ec, pCRange->_GetStart());
  100. achEnd = _GetOffset(ec, _ppr->_pRange->_GetEnd());
  101. }
  102. else
  103. {
  104. pPropList = _pProp->_FindPropListAndDivide(pCRange->_GetStart(), pCRange->_GetEnd());
  105. achStart = _GetOffset(ec, pCRange->_GetStart());
  106. achEnd = _GetOffset(ec, pCRange->_GetEnd());
  107. }
  108. if (pPropList)
  109. {
  110. if (!pPropList->_pPropStore)
  111. _pProp->LoadData(pPropList);
  112. if (pPropList->_pPropStore)
  113. {
  114. HRESULT hr;
  115. PERSISTPROPERTYRANGE *pPropRange;
  116. ITfPropertyStore *pPropStore = NULL;
  117. int nCnt;
  118. hr = pPropList->_pPropStore->Clone(&pPropStore);
  119. if (FAILED(hr) || !pPropStore)
  120. return FALSE;
  121. nCnt = _rgPropRanges.Count();
  122. if (!_rgPropRanges.Insert(nCnt, 1))
  123. {
  124. pPropStore->Release();
  125. return FALSE;
  126. }
  127. pPropRange = _rgPropRanges.GetPtr(nCnt);
  128. pPropRange->achStart = achStart;
  129. pPropRange->achEnd = achEnd;
  130. pPropRange->_pPropStore = pPropStore;
  131. }
  132. }
  133. return TRUE;
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // _GetOffset
  138. //
  139. //----------------------------------------------------------------------------
  140. int CRangeBackupProperty::_GetOffset(TfEditCookie ec, IAnchor *pa)
  141. {
  142. CRange *pCRange;
  143. CRange *pCRangeTmp = NULL;
  144. ULONG cch = 0;
  145. HRESULT hr;
  146. BOOL fEmpty;
  147. pCRange = new CRange;
  148. if (!pCRange)
  149. goto Exit;
  150. if (!pCRange->_InitWithDefaultGravity(_ppr->_pic, COPY_ANCHORS, pa, pa))
  151. goto Exit;
  152. pCRangeTmp = _ppr->_pRange->_Clone();
  153. if (!pCRangeTmp)
  154. goto Exit;
  155. hr = pCRangeTmp->ShiftEndToRange(ec, (ITfRangeAnchor *)pCRange, TF_ANCHOR_START);
  156. if (FAILED(hr))
  157. goto Exit;
  158. fEmpty = FALSE;
  159. while ((pCRangeTmp->IsEmpty(ec, &fEmpty) == S_OK) && !fEmpty)
  160. {
  161. WCHAR sz[256];
  162. ULONG cchTmp;
  163. pCRangeTmp->GetText(ec, TF_TF_MOVESTART, sz, ARRAYSIZE(sz), &cchTmp);
  164. cch += cchTmp;
  165. }
  166. Exit:
  167. SafeRelease(pCRangeTmp);
  168. SafeRelease(pCRange);
  169. return cch;
  170. }
  171. //+---------------------------------------------------------------------------
  172. //
  173. // Restore
  174. //
  175. //----------------------------------------------------------------------------
  176. BOOL CRangeBackupProperty::Restore(TfEditCookie ec)
  177. {
  178. int i;
  179. HRESULT hr;
  180. int nCnt;
  181. CRange *pCRange;
  182. nCnt = _rgPropRanges.Count();
  183. if (!nCnt)
  184. return FALSE;
  185. pCRange = _ppr->_pRange->_Clone();
  186. if (!pCRange)
  187. return FALSE;
  188. for (i = 0; i < nCnt; i++)
  189. {
  190. PERSISTPROPERTYRANGE *pPropRange;
  191. LONG cchStart, cchEnd;
  192. pPropRange = _rgPropRanges.GetPtr(i);
  193. Assert(pPropRange);
  194. Assert(pPropRange->_pPropStore);
  195. hr = pCRange->ShiftStartToRange(ec, (ITfRangeAnchor *)_ppr->_pRange,
  196. TF_ANCHOR_START);
  197. if (FAILED(hr))
  198. goto Next;
  199. hr = pCRange->Collapse(ec, TF_ANCHOR_START);
  200. if (FAILED(hr))
  201. goto Next;
  202. // shift End first.
  203. hr = pCRange->ShiftEnd(ec, pPropRange->achEnd, &cchEnd, NULL);
  204. if (FAILED(hr))
  205. goto Next;
  206. hr = pCRange->ShiftStart(ec, pPropRange->achStart, &cchStart, NULL);
  207. if (FAILED(hr))
  208. goto Next;
  209. _pProp->_SetStoreInternal(ec, pCRange, pPropRange->_pPropStore, TRUE);
  210. Next:
  211. pPropRange->_pPropStore->Release();
  212. pPropRange->_pPropStore = NULL;
  213. }
  214. pCRange->Release();
  215. _rgPropRanges.Clear();
  216. return TRUE;
  217. }
  218. //////////////////////////////////////////////////////////////////////////////
  219. //
  220. // CRangeBackup
  221. //
  222. //////////////////////////////////////////////////////////////////////////////
  223. //+---------------------------------------------------------------------------
  224. //
  225. // ctor
  226. //
  227. //----------------------------------------------------------------------------
  228. CRangeBackup::CRangeBackup(CInputContext *pic)
  229. {
  230. _pic = pic;
  231. Assert(!_pRange);
  232. }
  233. //+---------------------------------------------------------------------------
  234. //
  235. // dtor
  236. //
  237. //----------------------------------------------------------------------------
  238. CRangeBackup::~CRangeBackup()
  239. {
  240. Clear();
  241. }
  242. //+---------------------------------------------------------------------------
  243. //
  244. // Clear
  245. //
  246. //----------------------------------------------------------------------------
  247. void CRangeBackup::Clear()
  248. {
  249. _pic = NULL;
  250. SafeReleaseClear(_pRange);
  251. delete _psz;
  252. _psz = NULL;
  253. int nCnt = _rgProp.Count();
  254. for (int i = 0; i < nCnt; i++)
  255. {
  256. CRangeBackupProperty *pprp = _rgProp.Get(i);
  257. delete pprp;
  258. }
  259. _rgProp.Clear();
  260. }
  261. //+---------------------------------------------------------------------------
  262. //
  263. // Init
  264. //
  265. //----------------------------------------------------------------------------
  266. HRESULT CRangeBackup::Init(TfEditCookie ec, CRange *pRange)
  267. {
  268. ITfRange *pRangeTmp = NULL;
  269. ULONG cch, cchCur;
  270. BOOL fEmpty;
  271. CProperty *pProp;
  272. HRESULT hr;
  273. WCHAR *pszTmp;
  274. Assert(!_pRange);
  275. Assert(!_psz);
  276. _pRange = pRange->_Clone();
  277. hr = _pRange->Clone(&pRangeTmp);
  278. if (FAILED(hr) || !pRangeTmp)
  279. return E_FAIL;
  280. hr = E_FAIL;
  281. //
  282. // Save text.
  283. //
  284. fEmpty = FALSE;
  285. cchCur = 0;
  286. cch = 31;
  287. while ((pRangeTmp->IsEmpty(ec, &fEmpty) == S_OK) && !fEmpty)
  288. {
  289. if (!_psz)
  290. {
  291. Assert(cchCur == 0);
  292. _psz = (WCHAR *)cicMemAlloc((cch + 1) * sizeof(WCHAR));
  293. }
  294. else
  295. {
  296. Assert(cchCur);
  297. pszTmp = (WCHAR *)cicMemReAlloc(_psz, (cchCur + cch + 1) * sizeof(WCHAR));
  298. if (pszTmp != NULL)
  299. {
  300. _psz = pszTmp;
  301. }
  302. else
  303. {
  304. cicMemFree(_psz);
  305. _psz = NULL;
  306. }
  307. }
  308. if (_psz == NULL)
  309. goto Exit;
  310. pRangeTmp->GetText(ec, TF_TF_MOVESTART, _psz + cchCur, cch, &cch);
  311. cchCur += cch;
  312. cch *= 2;
  313. }
  314. if (!cchCur)
  315. {
  316. hr = S_FALSE;
  317. _cch = 0;
  318. if (_psz)
  319. {
  320. cicMemFree(_psz);
  321. _psz = NULL;
  322. }
  323. goto Exit;
  324. }
  325. _cch = cchCur;
  326. _psz[_cch] = L'\0';
  327. //
  328. // Save property.
  329. //
  330. pProp = _pic->_pPropList;
  331. while (pProp)
  332. {
  333. CRangeBackupProperty *pPropRange;
  334. int nCnt = _rgProp.Count();
  335. pPropRange = new CRangeBackupProperty(this, pProp);
  336. if (!pPropRange)
  337. {
  338. hr = E_OUTOFMEMORY;
  339. goto Exit;
  340. }
  341. if (!pPropRange->Init(ec))
  342. {
  343. delete pPropRange;
  344. goto Next;
  345. }
  346. if (!_rgProp.Insert(nCnt, 1))
  347. {
  348. hr = E_OUTOFMEMORY;
  349. delete pPropRange;
  350. goto Next;
  351. }
  352. _rgProp.Set(nCnt, pPropRange);
  353. Next:
  354. pProp = pProp->_pNext;
  355. }
  356. hr = S_OK;
  357. Exit:
  358. SafeRelease(pRangeTmp);
  359. return hr;
  360. }
  361. //+---------------------------------------------------------------------------
  362. //
  363. // Restore
  364. //
  365. //----------------------------------------------------------------------------
  366. STDAPI CRangeBackup::Restore(TfEditCookie ec, ITfRange *pRange)
  367. {
  368. HRESULT hr = E_FAIL;
  369. int i;
  370. int nCnt;
  371. CRange *range;
  372. if (!_pic->_IsValidEditCookie(ec, TF_ES_READWRITE))
  373. {
  374. Assert(0);
  375. return TF_E_NOLOCK;
  376. }
  377. if (pRange)
  378. {
  379. SafeReleaseClear(_pRange);
  380. range = GetCRange_NA(pRange);
  381. if (range == NULL)
  382. return E_INVALIDARG;
  383. if (!VerifySameContext(_pic, range))
  384. return E_INVALIDARG;
  385. range->_QuickCheckCrossedAnchors();
  386. _pRange = range->_Clone();
  387. }
  388. Assert(_pRange);
  389. Assert(_psz || !_cch);
  390. if (!_pic)
  391. return S_OK;
  392. Assert(_pRange);
  393. _pRange->SetText(ec, 0, _psz, _cch);
  394. nCnt = _rgProp.Count();
  395. for (i = 0; i < nCnt; i++)
  396. {
  397. CRangeBackupProperty *pPropRange = _rgProp.Get(i);
  398. Assert(pPropRange);
  399. pPropRange->Restore(ec);
  400. delete pPropRange;
  401. }
  402. _rgProp.Clear();
  403. hr = S_OK;
  404. return hr;
  405. }