PX_ChangeRecord * PX_ChangeRecord_DocProp::reverse(void) const
{
	PX_ChangeRecord_DocProp * pcr
		= new PX_ChangeRecord_DocProp(getRevType(),m_position,m_indexAP,getXID());
	UT_ASSERT_HARMLESS(pcr);
	return pcr;
}
PX_ChangeRecord * PX_ChangeRecord_Strux::reverse(void) const
{
	PX_ChangeRecord_Strux * pcr
		= new PX_ChangeRecord_Strux(getRevType(),m_position,m_indexAP,getXID(),m_struxType);
	UT_ASSERT_HARMLESS(pcr);
	return pcr;
}
Exemple #3
0
bool pt_PieceTable::_insertObject(pf_Frag * pf,
									 PT_BlockOffset fragOffset,
									 PTObjectType pto,
									 PT_AttrPropIndex indexAP,
                                     pf_Frag_Object * & pfo)
{
	pfo = NULL;
	if (!_createObject(pto,indexAP,&pfo))
		return false;

	pfo->setXID(getXID());
	
	if (fragOffset == 0)
	{
		// we are at the beginning of a fragment, insert the
		// new object immediately prior to it.
		m_fragments.insertFrag(pf->getPrev(),pfo);
	}
	else if (fragOffset == pf->getLength())
	{
		// we are at the end of a fragment, insert the new
		// object immediately after it.
		m_fragments.insertFrag(pf,pfo);
	}
	else
	{
		// if the insert is in the middle of the (text) fragment, we
		// split the current fragment and insert the object between
		// them.

		UT_return_val_if_fail (pf->getType() == pf_Frag::PFT_Text, false);
		pf_Frag_Text * pft = static_cast<pf_Frag_Text *>(pf);
		UT_uint32 lenTail = pft->getLength() - fragOffset;
		PT_BufIndex biTail = m_varset.getBufIndex(pft->getBufIndex(),fragOffset);
		pf_Frag_Text * pftTail = new pf_Frag_Text(this,biTail,lenTail,pft->getIndexAP(),pft->getField());
		if (!pftTail)
			goto MemoryError;

		pft->changeLength(fragOffset);
		m_fragments.insertFrag(pft,pfo);
		m_fragments.insertFrag(pfo,pftTail);
	}

	return true;

MemoryError:
	if (pfo)
		delete pfo;
	return false;
}
bool pf_Frag_Strux::createSpecialChangeRecord(PX_ChangeRecord ** ppcr,
												 PT_DocPosition dpos) const
{
	UT_return_val_if_fail (ppcr,false);
	
	PX_ChangeRecord_Strux * pcr
		= new PX_ChangeRecord_Strux(PX_ChangeRecord::PXT_InsertStrux,
									dpos, m_indexAP, getXID(), m_struxType);
	if (!pcr)
		return false;

	*ppcr = pcr;
	return true;
}
bool pf_Frag_Object::createSpecialChangeRecord(PX_ChangeRecord ** ppcr,
                                                  PT_DocPosition dpos,
                                                  PT_BlockOffset blockOffset)
{
    UT_return_val_if_fail (ppcr,false);
	
    PX_ChangeRecord_Object * pcr
    	 = new PX_ChangeRecord_Object(PX_ChangeRecord::PXT_InsertObject,
                                     dpos, m_indexAP, getXID(), m_objectType,
                                     blockOffset, m_pField,
				      this);

    if (!pcr)
        return false;

    *ppcr = pcr;
    return true;
}
Exemple #6
0
bool pt_PieceTable::_realInsertStrux(PT_DocPosition dpos,
									 PTStruxType pts,
									 const gchar ** attributes,
									 const gchar ** properties,
									 pf_Frag_Strux ** ppfs_ret)
{
	// insert a new structure fragment at the given document position.
	// this function can only be called while editing the document.
	// Also can specify an indexAP to be used for the frag rather
	// than that obtained by default. Very useful for insertting
	// Cells where you can immediately specify the cell position in
	// a table.  this function can only be called while editing the
	// document.

	UT_return_val_if_fail (m_pts==PTS_Editing, false);

	// get the fragment at the doc postion containing the given
	// document position.

	pf_Frag * pf = NULL;
	PT_BlockOffset fragOffset = 0;
	bool bFoundFrag = getFragFromPosition(dpos,&pf,&fragOffset);
	UT_return_val_if_fail (bFoundFrag, false);

	// get the strux containing the given position.

	pf_Frag_Strux * pfsContainer = NULL;
	bool bFoundContainer = _getStruxFromPosition(dpos,&pfsContainer);
	UT_return_val_if_fail (bFoundContainer,false);
	//
	// Can only insert an endTOC into a TOC
	//
	if((pfsContainer->getStruxType() == PTX_SectionTOC) && (pts != PTX_EndTOC))
	{
		bFoundContainer = _getStruxFromPosition(pfsContainer->getPos(),&pfsContainer);
		dpos--;
	}
	if(isEndFootnote(pfsContainer))
	{
		bFoundContainer = _getStruxFromFragSkip(pfsContainer,&pfsContainer);
	}
	// if we are inserting something similar to the previous strux,
	// we will clone the attributes/properties; we assume that the
	// new strux should have the same AP as the one which preceeds us.
	// This is generally true for inserting a paragraph -- it should
	// inherit the style of the one we just broke.

	PT_AttrPropIndex indexAP = 0;
	if (pfsContainer->getStruxType() == pts)
	{
		// TODO paul, add code here to see if this strux has a "followed-by"
		// TODO paul, property (or property in the style) and get the a/p
		// TODO paul, from there rather than just taking the attr/prop
		// TODO paul, of the previous strux.
		indexAP = pfsContainer->getIndexAP();
	}

//
// Look to see if we're in the middle of a hyperlink span now.
//
	pf_Frag * pHype = _findPrevHyperlink(pf);
	if(pHype != NULL && (pts != PTX_SectionFrame) // allow annotations in
	                                              // hyperlinks
	   && (pts != PTX_SectionAnnotation)
	   && (pts != PTX_EndAnnotation)) // frames are always placed
		                                           // at the end of blocks
                                                   // so we don't need this 
	{
//
// We have an open hyperlink! FIXME later we should allow this by terminating
// the hyperlink span just before this strux, then doing the insert strux.
// Instead for now we'll just disallow this insertStrux.
//
// This assert is to remind use to write the code to terminate
// the hyperlink.
//
		pf_Frag * pEndHype = _findNextHyperlink(pf);
		PT_DocPosition posEnd = 0;
		if(pEndHype)
		{
			posEnd = pEndHype->getPos();
		}
		//
		// OK now insert a new end of hyperlink at pf
		//
		insertObject(dpos, PTO_Hyperlink,NULL,NULL);
		m_fragments.cleanFrags();
		dpos++;
		if(posEnd > 0)
		{
			//
			// Now delete the old endhyperlink.
			//
			pf_Frag * pfEnd = NULL;
			UT_uint32 newOff = 0;
			posEnd++; // from the insert
			UT_uint32 offset = 0;
			_deleteObjectWithNotify(posEnd,
									static_cast<pf_Frag_Object*>(pEndHype),
									offset,1,pfsContainer,&pfEnd,&newOff,true);
		}
		m_fragments.cleanFrags();
		bFoundFrag = getFragFromPosition(dpos,&pf,&fragOffset);
		UT_return_val_if_fail (bFoundFrag, false);
	}	

//
// If desired, merge in the specified attributes/properties. This
// enables cells to inherit the properties of the block from which
// they were inserted.
//
	if (attributes || properties)
	{
		PT_AttrPropIndex pAPIold = indexAP;
		bool bMerged = m_varset.mergeAP(PTC_AddFmt,pAPIold,attributes,properties,&indexAP,getDocument());
        UT_UNUSED(bMerged);
		UT_ASSERT_HARMLESS(bMerged);
	}

	pf_Frag_Strux * pfsNew = NULL;
	if (!_createStrux(pts,indexAP,&pfsNew))
		return false;

	pfsNew->setXID(getXID());
	
	// when inserting paragraphs, we try to remember the current
	// span formatting active at the insertion point and add a
	// FmtMark immediately after the block.  this way, if the
	// user keeps typing text, the FmtMark will control it's
	// attr/prop -- if the user warps away and/or edits elsewhere
	// and then comes back to this point (the FmtMark may or may
	// not still be here) new text will either use the FmtMark or
	// look to the right.

	bool bNeedGlob = false;
	PT_AttrPropIndex apFmtMark = 0;
	if (pfsNew->getStruxType() == PTX_Block)
	{
		bNeedGlob = _computeFmtMarkForNewBlock(pfsNew,pf,fragOffset,&apFmtMark);
		if (bNeedGlob)
			beginMultiStepGlob();

		// if we are leaving an empty block (are stealing all it's content) we should
		// put a FmtMark in it to remember the active span fmt at the time.
		// this lets things like hitting two consecutive CR's and then comming
		// back to the first empty paragraph behave as expected.

		// fixme sevior here

		if ((pf->getType()==pf_Frag::PFT_Text) && (fragOffset == 0) &&
			(pf->getPrev()!=NULL) && (pf->getPrev()->getType()==pf_Frag::PFT_Strux))
		{
			pf_Frag_Strux *pfsStrux = static_cast<pf_Frag_Strux *>(pf->getPrev());
			if(pfsStrux->getStruxType() == PTX_Block)
			{
				_insertFmtMarkAfterBlockWithNotify(pfsContainer,dpos,apFmtMark);
			}
		}
	}
	//
	// Look if we're placing an endcell in an empty block. If so, 
	// insert a format mark
	//
	if (pfsNew->getStruxType() == PTX_EndCell)
	{
		if((pf->getPrev()!=NULL) && (pf->getPrev()->getType()==pf_Frag::PFT_Strux))
		{
			pf_Frag_Strux *pfsStrux = static_cast<pf_Frag_Strux *>(pf->getPrev());
			if(pfsStrux->getStruxType() == PTX_Block)
			{
				_insertFmtMarkAfterBlockWithNotify(pfsContainer,dpos,apFmtMark);
			}
		}
	}

	// insert this frag into the fragment list. Update the container strux as needed
	_insertStrux(pf,fragOffset,pfsNew);
	if (ppfs_ret)
		*ppfs_ret = pfsNew;

	// create a change record to describe the change, add
	// it to the history, and let our listeners know about it.
	if(pfsNew->getStruxType() == PTX_SectionFrame)
	{
		// Inserting a sectionFrame screws up dos. It goes just before the next
		// block strux found.
		dpos = pfsNew->getPrev()->getPos() + pfsNew->getPrev()->getLength();
	}
	PX_ChangeRecord_Strux * pcrs
		= new PX_ChangeRecord_Strux(PX_ChangeRecord::PXT_InsertStrux,
									dpos,indexAP,pfsNew->getXID(), pts);
	UT_return_val_if_fail (pcrs,false);

	// add record to history.  we do not attempt to coalesce these.
	m_history.addChangeRecord(pcrs);
	m_pDocument->notifyListeners(pfsContainer,pfsNew,pcrs);

	if (bNeedGlob)
	{
		UT_return_val_if_fail (!pfsNew->getNext() || pfsNew->getNext()->getType()!=pf_Frag::PFT_FmtMark, false);
		_insertFmtMarkAfterBlockWithNotify(pfsNew,dpos+pfsNew->getLength(),apFmtMark);
		endMultiStepGlob();
	}

	return true;
}