bool pt_PieceTable::_deleteObject(pf_Frag_Object * pfo, pf_Frag ** ppfEnd, UT_uint32 * pfragOffsetEnd) { // unlink the object from the fragment list and try to // coalesce the neighboring fragments. xxx_UT_DEBUGMSG(("Deleting Frag object %p \n",pfo)); _unlinkFrag(pfo,ppfEnd,pfragOffsetEnd); delete pfo; return true; }
bool pt_PieceTable::_fmtChangeSpan(pf_Frag_Text * pft, UT_uint32 fragOffset, UT_uint32 length, PT_AttrPropIndex indexNewAP, pf_Frag ** ppfNewEnd, UT_uint32 * pfragOffsetNewEnd) { UT_return_val_if_fail (length > 0,false); UT_return_val_if_fail (fragOffset+length <= pft->getLength(), false); // insert a format change within this text fragment. // TODO for each place in this function where we apply a change // TODO see if the new fragment could be coalesced with something // TODO already in the fragment list. if ((fragOffset == 0) && (length == pft->getLength())) { // we have an exact match (we are changing the entire fragment). // try to coalesce this modified fragment with one of its neighbors. // first we try the pft->next -- if that works, we can stop because // the unlink will take care of checking pft->next with pft->prev. // if it doesn't work, we then try pft->prev. pf_Frag * pfNext = pft->getNext(); if (pfNext && pfNext->getType()==pf_Frag::PFT_Text) { pf_Frag_Text * pftNext = static_cast<pf_Frag_Text *>(pfNext); if ( (pftNext->getIndexAP() == indexNewAP) && (m_varset.isContiguous(pft->getBufIndex(),length,pftNext->getBufIndex()))) { // the pft given and the pft->next can be coalesced. // let's donate all of our document data to pft->next, // set pft to be empty and then let _unlinkFrag() take // care of all the other details (like checking to see // if pft->next and pft->prev can be coalesced after pft // is out of the way....) pftNext->adjustOffsetLength(pft->getBufIndex(),length+pftNext->getLength()); // we could do a: pft->changeLength(0); but it causes an assert and // besides _unlinkFrag() doesn't look at it and we're going to delete it. _unlinkFrag(pft,ppfNewEnd,pfragOffsetNewEnd); delete pft; return true; } } pf_Frag * pfPrev = pft->getPrev(); if (pfPrev && pfPrev->getType()==pf_Frag::PFT_Text) { pf_Frag_Text * pftPrev = static_cast<pf_Frag_Text *>(pfPrev); if ( (pftPrev->getIndexAP() == indexNewAP) && (m_varset.isContiguous(pftPrev->getBufIndex(),pftPrev->getLength(),pft->getBufIndex()))) { // the pft given and the pft->prev can be coalesced. // let's donate all of our document data to the pft->prev, // set pft to be empty and then let _unlinkFrag() take // care of the dirty work. pftPrev->changeLength(pftPrev->getLength()+length); // we could do a: pft->changeLength(0); but it causes an assert and // besides _unlinkFrag() doesn't look at it and we're going to delete it. _unlinkFrag(pft,ppfNewEnd,pfragOffsetNewEnd); delete pft; return true; } } // otherwise, we just overwrite the indexAP on this fragment. pft->setIndexAP(indexNewAP); SETP(ppfNewEnd, pft->getNext()); SETP(pfragOffsetNewEnd, 0); return true; } if (fragOffset == 0) { // the change is at the beginning of the fragment. // we need to split the existing fragment into 2 parts // and apply the new formatting to the new first half. // before we actually create the new one, we see if we // can coalesce the first half (with the new formatting) // with the previous fragment. if not, then we cut // the existing fragment into 2 parts. UT_uint32 len_1 = length; UT_uint32 len_2 = pft->getLength() - len_1; PT_BufIndex bi_1 = m_varset.getBufIndex(pft->getBufIndex(),0); PT_BufIndex bi_2 = m_varset.getBufIndex(pft->getBufIndex(),len_1); pf_Frag * pfPrev = pft->getPrev(); if (pfPrev && pfPrev->getType()==pf_Frag::PFT_Text) { pf_Frag_Text * pftPrev = static_cast<pf_Frag_Text *>(pfPrev); if ( (pftPrev->getIndexAP() == indexNewAP) && (m_varset.isContiguous(pftPrev->getBufIndex(),pftPrev->getLength(),pft->getBufIndex()))) { // yes we can coalesce. move the first half into the previous fragment. pftPrev->changeLength(pftPrev->getLength()+length); pft->adjustOffsetLength(bi_2,len_2); SETP(ppfNewEnd, pft); SETP(pfragOffsetNewEnd, 0); return true; } } // otherwise, we need to actually split this one.... pf_Frag_Text * pftNew = new pf_Frag_Text(this,bi_1,len_1,indexNewAP,pft->getField()); if (!pftNew) return false; pft->adjustOffsetLength(bi_2,len_2); m_fragments.insertFrag(pft->getPrev(),pftNew); SETP(ppfNewEnd, pft); SETP(pfragOffsetNewEnd, 0); return true; } if (fragOffset+length == pft->getLength()) { // the change is at the end of the fragment, we cut // the existing fragment into 2 parts and apply the new // formatting to the new second half. before we actually // create the new one, we see if we can coalesce the // second half (with the new formatting) with the next // fragment. UT_uint32 len_1 = fragOffset; UT_uint32 len_2 = length; PT_BufIndex bi_2 = m_varset.getBufIndex(pft->getBufIndex(),len_1); pf_Frag * pfNext = pft->getNext(); if (pfNext && pfNext->getType()==pf_Frag::PFT_Text) { pf_Frag_Text * pftNext = static_cast<pf_Frag_Text *>(pfNext); if ( (pftNext->getIndexAP() == indexNewAP) && (m_varset.isContiguous(bi_2,len_2,pftNext->getBufIndex()))) { // yes we can coalesce. move the second half into the next fragment. pftNext->adjustOffsetLength(bi_2,len_2+pftNext->getLength()); pft->changeLength(len_1); SETP(ppfNewEnd,pftNext); SETP(pfragOffsetNewEnd,len_2); return true; } } // otherwise, we actually need to split this one.... pf_Frag_Text * pftNew = new pf_Frag_Text(this,bi_2,len_2,indexNewAP,pft->getField()); if (!pftNew) return false; pft->changeLength(len_1); m_fragments.insertFrag(pft,pftNew); SETP(ppfNewEnd, pftNew->getNext()); SETP(pfragOffsetNewEnd, 0); return true; } // otherwise, change is in the middle of the fragment. we // need to cut the existing fragment into 3 parts and apply // the new formatting to the middle one. UT_uint32 len_1 = fragOffset; UT_uint32 len_2 = length; UT_uint32 len_3 = pft->getLength() - (fragOffset+length); PT_BufIndex bi_2 = m_varset.getBufIndex(pft->getBufIndex(),fragOffset); PT_BufIndex bi_3 = m_varset.getBufIndex(pft->getBufIndex(),fragOffset+length); pf_Frag_Text * pft_2 = new pf_Frag_Text(this,bi_2,len_2,indexNewAP,pft->getField()); UT_return_val_if_fail (pft_2, false); pf_Frag_Text * pft_3 = new pf_Frag_Text(this,bi_3,len_3,pft->getIndexAP(),pft->getField()); UT_return_val_if_fail (pft_3, false); pft->changeLength(len_1); m_fragments.insertFrag(pft,pft_2); m_fragments.insertFrag(pft_2,pft_3); SETP(ppfNewEnd, pft_3); SETP(pfragOffsetNewEnd, 0); return true; }