1 /* AbiWord
2  * Copyright (C) 1998 AbiSource, Inc.
3  * Updates by Ben Martin in 2011.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA.
19  */
20 
21 
22 #include "ut_types.h"
23 #include "pf_Frag.h"
24 #include "pt_PieceTable.h"
25 #include "pf_Fragments.h"
26 
pf_Frag(pt_PieceTable * pPT,PFType type,UT_uint32 length)27 pf_Frag::pf_Frag(pt_PieceTable * pPT, PFType type, UT_uint32 length):
28 	m_type(type),
29 	m_pField(NULL),
30 	m_pPieceTable(pPT),
31 	m_indexAP(0),
32 	m_length(length),
33 	m_leftTreeLength(0),
34 	m_iXID(0),
35 	m_pMyNode(NULL)
36 {
37 }
38 
~pf_Frag()39 pf_Frag::~pf_Frag()
40 {
41   xxx_UT_DEBUGMSG(("Delete Frag of Type %d pointer %p \n",getType(),this));
42 }
43 
44 /*!
45    returns true if both content and fmt of the two frags is identical
46 */
operator ==(const pf_Frag & f2) const47 bool pf_Frag::operator == (const pf_Frag & f2) const
48 {
49 	if(getType() != f2.getType())
50 		return false;
51 
52 	// decide if the two frags have same piecetables
53 	if(!m_pPieceTable || !f2.m_pPieceTable)
54 		return false;
55 
56 	if(m_pPieceTable == f2.m_pPieceTable)
57 	{
58 		if(m_indexAP != f2.m_indexAP)
59 			return false;
60 	}
61 	else
62 	{
63 		// different PT, do it the hard way ...
64 		const PP_AttrProp * pAP1;
65 		const PP_AttrProp * pAP2;
66 
67 		m_pPieceTable->getAttrProp(m_indexAP, &pAP1);
68 		f2.m_pPieceTable->getAttrProp(f2.m_indexAP, &pAP2);
69 
70 		UT_return_val_if_fail(pAP1 && pAP2, false);
71 
72 		if(!pAP1->isEquivalent(pAP2))
73 		{
74 			return false;
75 		}
76 	}
77 
78 	return _isContentEqual(f2);
79 }
80 
81 /*!
82     Returns true if the content of the two fragments is identical, but
83     ignores formatting properies.
84 */
isContentEqual(const pf_Frag & f2) const85 bool pf_Frag::isContentEqual(const pf_Frag & f2) const
86 {
87 	if(getType() != f2.getType())
88 		return false;
89 
90 	// check we have PT to fidle with ...
91 	if(!m_pPieceTable || !f2.m_pPieceTable)
92 		return false;
93 
94 	return _isContentEqual(f2);
95 }
96 
getPos(void) const97 PT_DocPosition pf_Frag::getPos(void) const
98 {
99        UT_return_val_if_fail(m_pMyNode,0);
100        pf_Fragments * fragments = &(m_pPieceTable->getFragments());
101        const pf_Fragments::Iterator it(fragments,m_pMyNode);
102        PT_DocPosition pos = fragments->documentPosition(it);
103        return pos;
104 }
105 
106 /*!
107  * Tell the fragments tree that the length of this item changed by
108  * delta.
109  * delta = new_length - old_length
110  */
lengthChanged(UT_sint32 delta)111 void  pf_Frag::lengthChanged(UT_sint32 delta)
112 {
113        UT_return_if_fail(m_pMyNode);
114        pf_Fragments * fragments = &(m_pPieceTable->getFragments());
115        fragments->changeSize(delta);
116        pf_Fragments::Iterator it(fragments,m_pMyNode);
117        fragments->fixSize(it);
118 }
119 
120 	/* We need the following function to accumulate left tree length */
accLeftTreeLength(PT_DocPosition length)121 void  pf_Frag:: accLeftTreeLength(PT_DocPosition length)
122 {
123        m_leftTreeLength += length;
124 }
125 
_setNode(pf_Fragments::Node * pNode)126 void pf_Frag::_setNode(pf_Fragments::Node * pNode)
127 {
128        m_pMyNode = pNode;
129 }
130 
_getNode(void) const131 pf_Fragments::Node * pf_Frag::_getNode(void) const
132 {
133        return m_pMyNode;
134 }
135 
createSpecialChangeRecord(PX_ChangeRecord **,PT_DocPosition) const136 bool pf_Frag::createSpecialChangeRecord(PX_ChangeRecord ** /*ppcr*/,
137 										   PT_DocPosition /*dpos*/) const
138 {
139 	// really this should be declared abstract in pf_Frag,
140 	// but we didn't derrive a sub-class for EOD -- it actually
141 	// uses the base class as is.
142 
143 	// this function must be overloaded for all sub-classes.
144 
145 	UT_ASSERT_HARMLESS(0);
146 	return true;
147 }
148 
getField(void) const149 fd_Field * pf_Frag::getField(void) const
150 {
151     return m_pField;
152 }
153 
getNext(void) const154 pf_Frag* pf_Frag::getNext(void) const
155 {
156         UT_return_val_if_fail(m_pMyNode,NULL);
157  	pf_Fragments::Iterator it(&(m_pPieceTable->getFragments()),m_pMyNode);
158 	it++;
159 	return it.value();
160 }
161 
162 
getPrev(void) const163 pf_Frag* pf_Frag::getPrev(void) const
164 {
165         UT_return_val_if_fail(m_pMyNode,NULL);
166  	pf_Fragments::Iterator it(&(m_pPieceTable->getFragments()),m_pMyNode);
167 	it--;
168 	return it.value();
169 }
170 
171 #include "pf_Frag_Strux.h"
172 
isStuxType(const pf_Frag * const pf,PTStruxType t)173 static bool isStuxType( const pf_Frag* const pf, PTStruxType t )
174 {
175     if( pf->getType() != pf_Frag::PFT_Strux )
176         return false;
177 
178     const pf_Frag_Strux* const pfs = static_cast<const pf_Frag_Strux* const>(pf);
179     return pfs->getStruxType() == t;
180 }
181 
182 /**
183  * Get the next strux of the given type from the document. Note that
184  * the return value can never be this fragment even if this fragment
185  * is also a strux of the sought type.
186  *
187  * This way, you can skip from on PTX_Block to the next in a loop using
188  * pf_Frag* pf = getFragOfType( PTX_Block );
189  * for( ; pf; pf = pf->getNextStrux(PTX_Block) )
190  * {
191  *   ...
192  * }
193  */
getNextStrux(PTStruxType t) const194 pf_Frag_Strux* pf_Frag::getNextStrux(PTStruxType t) const
195 {
196     UT_return_val_if_fail(m_pMyNode,NULL);
197     pf_Fragments& fragments = m_pPieceTable->getFragments();
198  	pf_Fragments::Iterator it(&(fragments),m_pMyNode);
199     // If we are the desired type, move ahead already.
200     if( isStuxType( this, t ))
201     {
202         it++;
203     }
204     for( pf_Fragments::Iterator e = fragments.end(); it != e; ++it )
205     {
206         pf_Frag* pf = it.value();
207         if( !pf )
208             return 0;
209         if( isStuxType( pf, t ))
210         {
211             return static_cast<pf_Frag_Strux*>(pf);
212         }
213     }
214     return 0;
215 }
216 
217 pf_Frag_Strux*
tryDownCastStrux(PTStruxType t) const218 pf_Frag::tryDownCastStrux(PTStruxType t) const
219 {
220     if( getType() == pf_Frag::PFT_Strux )
221     {
222         pf_Fragments& fragments = m_pPieceTable->getFragments();
223         pf_Fragments::Iterator it(&(fragments),m_pMyNode);
224         pf_Frag* pf = it.value();
225         pf_Frag_Strux* pfs = static_cast<pf_Frag_Strux*>(pf);
226         PTStruxType eStruxType = pfs->getStruxType();
227         if( eStruxType == t )
228             return pfs;
229     }
230     return 0;
231 }
232 
tryDownCastStrux(pf_Frag * pf,PTStruxType t)233 pf_Frag_Strux* tryDownCastStrux( pf_Frag* pf, PTStruxType t)
234 {
235     if( !pf )
236         return 0;
237     return pf->tryDownCastStrux( t );
238 }
239 
240 
241 
242 #include "pf_Frag_Object.h"
243 #include "pf_Frag_Strux.h"
244 #include "pd_DocumentRDF.h"
245 
246 std::string
getXMLID() const247 pf_Frag::getXMLID() const
248 {
249     std::string ret = "";
250 
251     const PP_AttrProp* pAP = NULL;
252     m_pPieceTable->getAttrProp( getIndexAP() ,&pAP );
253     if( !pAP )
254         return ret;
255     const char* v = 0;
256 
257     if(getType() == pf_Frag::PFT_Object)
258     {
259         const pf_Frag_Object* pOb = static_cast<const pf_Frag_Object*>(this);
260 
261         if(pOb->getObjectType() == PTO_Bookmark)
262         {
263             if( pAP->getAttribute(PT_XMLID, v) && v)
264             {
265                 ret = v;
266             }
267         }
268         if(pOb->getObjectType() == PTO_RDFAnchor)
269         {
270             RDFAnchor a(pAP);
271             ret = a.getID();
272         }
273     }
274     if(getType() == pf_Frag::PFT_Strux)
275     {
276         const pf_Frag_Strux* pfs = static_cast<const pf_Frag_Strux*>(this);
277         PTStruxType st = pfs->getStruxType();
278         if( st == PTX_Block || st == PTX_SectionCell )
279         {
280             if(pAP->getAttribute("xml:id", v))
281             {
282                 ret = v;
283             }
284         }
285     }
286 
287     return ret;
288 }
289 
290