// // perange.cpp // #include "private.h" #include "helpers.h" #include "ic.h" #include "range.h" #include "rangebk.h" #include "rprop.h" #include "immxutil.h" ////////////////////////////////////////////////////////////////////////////// // // CRangeBackup // ////////////////////////////////////////////////////////////////////////////// //+--------------------------------------------------------------------------- // // ctor // //---------------------------------------------------------------------------- CRangeBackupProperty::CRangeBackupProperty(CRangeBackup *ppr, CProperty *pProp) { _ppr = ppr; _pProp = pProp; } //+--------------------------------------------------------------------------- // // dtor // //---------------------------------------------------------------------------- CRangeBackupProperty::~CRangeBackupProperty() { int i; int nCnt = _rgPropRanges.Count(); for (i = 0; i < nCnt; i++) { PERSISTPROPERTYRANGE *pPropRange; pPropRange = _rgPropRanges.GetPtr(i); Assert(pPropRange); Assert(pPropRange->_pPropStore); pPropRange->_pPropStore->Release(); pPropRange->_pPropStore = NULL; } } //+--------------------------------------------------------------------------- // // Init // //---------------------------------------------------------------------------- BOOL CRangeBackupProperty::Init(TfEditCookie ec) { IEnumTfRanges *pEnum; ITfRange *pRange; HRESULT hr; hr = _pProp->EnumRanges(ec, &pEnum, (ITfRangeAnchor *)_ppr->_pRange); if (FAILED(hr) || !pEnum) return FALSE; while (pEnum->Next(1, &pRange, NULL) == S_OK) { CRange *pCRange; pCRange = GetCRange_NA(pRange); if (pCRange) { _StoreOneRange(ec, pCRange); } pRange->Release(); } pEnum->Release(); return TRUE; } //+--------------------------------------------------------------------------- // // StoreOneRange // //---------------------------------------------------------------------------- BOOL CRangeBackupProperty::_StoreOneRange(TfEditCookie ec, CRange *pCRange) { PROPERTYLIST *pPropList; ULONG achStart = 0; ULONG achEnd = 0; if (CompareAnchors(pCRange->_GetStart(), _ppr->_pRange->_GetStart()) < 0) { if (CompareAnchors(pCRange->_GetEnd(), _ppr->_pRange->_GetEnd()) > 0) { pPropList = _pProp->_FindPropListAndDivide(_ppr->_pRange->_GetStart(), _ppr->_pRange->_GetEnd()); achStart = _GetOffset(ec, _ppr->_pRange->_GetStart()); achEnd = _GetOffset(ec, _ppr->_pRange->_GetEnd()); } else { pPropList = _pProp->_FindPropListAndDivide(_ppr->_pRange->_GetStart(), pCRange->_GetEnd()); achStart = _GetOffset(ec, _ppr->_pRange->_GetStart()); achEnd = _GetOffset(ec, pCRange->_GetEnd()); } } else if (CompareAnchors(pCRange->_GetEnd(), _ppr->_pRange->_GetEnd()) > 0) { pPropList = _pProp->_FindPropListAndDivide(pCRange->_GetStart(), _ppr->_pRange->_GetEnd()); achStart = _GetOffset(ec, pCRange->_GetStart()); achEnd = _GetOffset(ec, _ppr->_pRange->_GetEnd()); } else { pPropList = _pProp->_FindPropListAndDivide(pCRange->_GetStart(), pCRange->_GetEnd()); achStart = _GetOffset(ec, pCRange->_GetStart()); achEnd = _GetOffset(ec, pCRange->_GetEnd()); } if (pPropList) { if (!pPropList->_pPropStore) _pProp->LoadData(pPropList); if (pPropList->_pPropStore) { HRESULT hr; PERSISTPROPERTYRANGE *pPropRange; ITfPropertyStore *pPropStore = NULL; int nCnt; hr = pPropList->_pPropStore->Clone(&pPropStore); if (FAILED(hr) || !pPropStore) return FALSE; nCnt = _rgPropRanges.Count(); if (!_rgPropRanges.Insert(nCnt, 1)) { pPropStore->Release(); return FALSE; } pPropRange = _rgPropRanges.GetPtr(nCnt); pPropRange->achStart = achStart; pPropRange->achEnd = achEnd; pPropRange->_pPropStore = pPropStore; } } return TRUE; } //+--------------------------------------------------------------------------- // // _GetOffset // //---------------------------------------------------------------------------- int CRangeBackupProperty::_GetOffset(TfEditCookie ec, IAnchor *pa) { CRange *pCRange; CRange *pCRangeTmp = NULL; ULONG cch = 0; HRESULT hr; BOOL fEmpty; pCRange = new CRange; if (!pCRange) goto Exit; if (!pCRange->_InitWithDefaultGravity(_ppr->_pic, COPY_ANCHORS, pa, pa)) goto Exit; pCRangeTmp = _ppr->_pRange->_Clone(); if (!pCRangeTmp) goto Exit; hr = pCRangeTmp->ShiftEndToRange(ec, (ITfRangeAnchor *)pCRange, TF_ANCHOR_START); if (FAILED(hr)) goto Exit; fEmpty = FALSE; while ((pCRangeTmp->IsEmpty(ec, &fEmpty) == S_OK) && !fEmpty) { WCHAR sz[256]; ULONG cchTmp; pCRangeTmp->GetText(ec, TF_TF_MOVESTART, sz, ARRAYSIZE(sz), &cchTmp); cch += cchTmp; } Exit: SafeRelease(pCRangeTmp); SafeRelease(pCRange); return cch; } //+--------------------------------------------------------------------------- // // Restore // //---------------------------------------------------------------------------- BOOL CRangeBackupProperty::Restore(TfEditCookie ec) { int i; HRESULT hr; int nCnt; CRange *pCRange; nCnt = _rgPropRanges.Count(); if (!nCnt) return FALSE; pCRange = _ppr->_pRange->_Clone(); if (!pCRange) return FALSE; for (i = 0; i < nCnt; i++) { PERSISTPROPERTYRANGE *pPropRange; LONG cchStart, cchEnd; pPropRange = _rgPropRanges.GetPtr(i); Assert(pPropRange); Assert(pPropRange->_pPropStore); hr = pCRange->ShiftStartToRange(ec, (ITfRangeAnchor *)_ppr->_pRange, TF_ANCHOR_START); if (FAILED(hr)) goto Next; hr = pCRange->Collapse(ec, TF_ANCHOR_START); if (FAILED(hr)) goto Next; // shift End first. hr = pCRange->ShiftEnd(ec, pPropRange->achEnd, &cchEnd, NULL); if (FAILED(hr)) goto Next; hr = pCRange->ShiftStart(ec, pPropRange->achStart, &cchStart, NULL); if (FAILED(hr)) goto Next; _pProp->_SetStoreInternal(ec, pCRange, pPropRange->_pPropStore, TRUE); Next: pPropRange->_pPropStore->Release(); pPropRange->_pPropStore = NULL; } pCRange->Release(); _rgPropRanges.Clear(); return TRUE; } ////////////////////////////////////////////////////////////////////////////// // // CRangeBackup // ////////////////////////////////////////////////////////////////////////////// //+--------------------------------------------------------------------------- // // ctor // //---------------------------------------------------------------------------- CRangeBackup::CRangeBackup(CInputContext *pic) { _pic = pic; Assert(!_pRange); } //+--------------------------------------------------------------------------- // // dtor // //---------------------------------------------------------------------------- CRangeBackup::~CRangeBackup() { Clear(); } //+--------------------------------------------------------------------------- // // Clear // //---------------------------------------------------------------------------- void CRangeBackup::Clear() { _pic = NULL; SafeReleaseClear(_pRange); delete _psz; _psz = NULL; int nCnt = _rgProp.Count(); for (int i = 0; i < nCnt; i++) { CRangeBackupProperty *pprp = _rgProp.Get(i); delete pprp; } _rgProp.Clear(); } //+--------------------------------------------------------------------------- // // Init // //---------------------------------------------------------------------------- HRESULT CRangeBackup::Init(TfEditCookie ec, CRange *pRange) { ITfRange *pRangeTmp = NULL; ULONG cch, cchCur; BOOL fEmpty; CProperty *pProp; HRESULT hr; WCHAR *pszTmp; Assert(!_pRange); Assert(!_psz); _pRange = pRange->_Clone(); hr = _pRange->Clone(&pRangeTmp); if (FAILED(hr) || !pRangeTmp) return E_FAIL; hr = E_FAIL; // // Save text. // fEmpty = FALSE; cchCur = 0; cch = 31; while ((pRangeTmp->IsEmpty(ec, &fEmpty) == S_OK) && !fEmpty) { if (!_psz) { Assert(cchCur == 0); _psz = (WCHAR *)cicMemAlloc((cch + 1) * sizeof(WCHAR)); } else { Assert(cchCur); pszTmp = (WCHAR *)cicMemReAlloc(_psz, (cchCur + cch + 1) * sizeof(WCHAR)); if (pszTmp != NULL) { _psz = pszTmp; } else { cicMemFree(_psz); _psz = NULL; } } if (_psz == NULL) goto Exit; pRangeTmp->GetText(ec, TF_TF_MOVESTART, _psz + cchCur, cch, &cch); cchCur += cch; cch *= 2; } if (!cchCur) { hr = S_FALSE; _cch = 0; if (_psz) { cicMemFree(_psz); _psz = NULL; } goto Exit; } _cch = cchCur; _psz[_cch] = L'\0'; // // Save property. // pProp = _pic->_pPropList; while (pProp) { CRangeBackupProperty *pPropRange; int nCnt = _rgProp.Count(); pPropRange = new CRangeBackupProperty(this, pProp); if (!pPropRange) { hr = E_OUTOFMEMORY; goto Exit; } if (!pPropRange->Init(ec)) { delete pPropRange; goto Next; } if (!_rgProp.Insert(nCnt, 1)) { hr = E_OUTOFMEMORY; delete pPropRange; goto Next; } _rgProp.Set(nCnt, pPropRange); Next: pProp = pProp->_pNext; } hr = S_OK; Exit: SafeRelease(pRangeTmp); return hr; } //+--------------------------------------------------------------------------- // // Restore // //---------------------------------------------------------------------------- STDAPI CRangeBackup::Restore(TfEditCookie ec, ITfRange *pRange) { HRESULT hr = E_FAIL; int i; int nCnt; CRange *range; if (!_pic->_IsValidEditCookie(ec, TF_ES_READWRITE)) { Assert(0); return TF_E_NOLOCK; } if (pRange) { SafeReleaseClear(_pRange); range = GetCRange_NA(pRange); if (range == NULL) return E_INVALIDARG; if (!VerifySameContext(_pic, range)) return E_INVALIDARG; range->_QuickCheckCrossedAnchors(); _pRange = range->_Clone(); } Assert(_pRange); Assert(_psz || !_cch); if (!_pic) return S_OK; Assert(_pRange); _pRange->SetText(ec, 0, _psz, _cch); nCnt = _rgProp.Count(); for (i = 0; i < nCnt; i++) { CRangeBackupProperty *pPropRange = _rgProp.Get(i); Assert(pPropRange); pPropRange->Restore(ec); delete pPropRange; } _rgProp.Clear(); hr = S_OK; return hr; }