1 /* AbiWord
2  * Copyright (C) 1998 AbiSource, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA.
18  */
19 
20 // change-object-related routines for piece table.
21 
22 #include "ut_types.h"
23 #include "ut_misc.h"
24 #include "ut_assert.h"
25 #include "ut_debugmsg.h"
26 #include "ut_growbuf.h"
27 #include "pt_PieceTable.h"
28 #include "pf_Frag.h"
29 #include "pf_Frag_Object.h"
30 #include "pf_Fragments.h"
31 #include "px_ChangeRecord.h"
32 #include "px_CR_Object.h"
33 #include "px_CR_ObjectChange.h"
34 #include "fd_Field.h"
35 
36 #define SETP(p,v)	do { if (p) (*(p)) = (v); } while (0)
37 
38 /****************************************************************/
39 /****************************************************************/
40 
changeObjectFormatNoUpdate(PTChangeFmt ptc,pf_Frag_Object * pfo,const gchar ** attributes,const gchar ** properties)41 bool pt_PieceTable::changeObjectFormatNoUpdate(PTChangeFmt ptc ,pf_Frag_Object * pfo, const gchar ** attributes, const gchar ** properties)
42 {
43 	PT_AttrPropIndex indexNewAP;
44 	PT_AttrPropIndex indexOldAP = pfo->getIndexAP();
45 	bool bMerged = m_varset.mergeAP(ptc,indexOldAP,attributes,properties,&indexNewAP,getDocument());
46 	UT_UNUSED(bMerged);
47 	UT_ASSERT_HARMLESS(bMerged);
48 
49 	if (indexOldAP == indexNewAP)		// the requested change will have no effect on this fragment.
50 	{
51 		return true;
52 	}
53 	// actually apply the format change.
54 
55 	pfo->setIndexAP(indexNewAP);
56 	return true;
57 }
58 
_fmtChangeObjectWithNotify(PTChangeFmt ptc,pf_Frag_Object * pfo,UT_uint32 fragOffset,PT_DocPosition dpos,UT_uint32 length,const gchar ** attributes,const gchar ** properties,pf_Frag_Strux * pfs,pf_Frag ** ppfNewEnd,UT_uint32 * pfragOffsetNewEnd,bool bRevisionDelete)59 bool pt_PieceTable::_fmtChangeObjectWithNotify(PTChangeFmt ptc,
60 											   pf_Frag_Object * pfo, UT_uint32 fragOffset,
61 											   PT_DocPosition dpos,
62 											   UT_uint32 length,
63 											   const gchar ** attributes,
64 											   const gchar ** properties,
65 											   pf_Frag_Strux * pfs,
66 											   pf_Frag ** ppfNewEnd,
67 											   UT_uint32 * pfragOffsetNewEnd,
68 											   bool bRevisionDelete)
69 {
70 	// apply a span-level change to the given object.
71 	// create a change record for this change and put it in the history.
72 
73 	UT_return_val_if_fail (length == pfo->getLength(), false);
74 	UT_return_val_if_fail (fragOffset == 0, false);
75 
76 	PT_AttrPropIndex indexNewAP;
77 	PT_AttrPropIndex indexOldAP = pfo->getIndexAP();
78 	bool bMerged = m_varset.mergeAP(ptc,indexOldAP,attributes,properties,&indexNewAP,getDocument());
79 	UT_UNUSED(bMerged);
80 	UT_ASSERT_HARMLESS(bMerged);
81 
82 	if (indexOldAP == indexNewAP)		// the requested change will have no effect on this fragment.
83 	{
84 		SETP(ppfNewEnd, pfo->getNext());
85 		SETP(pfragOffsetNewEnd, 0);
86 		return true;
87 	}
88 
89 	PT_BlockOffset blockOffset = _computeBlockOffset(pfs,pfo) + fragOffset;
90 
91 	// we do this before the actual change because various fields that
92 	// we need may be blown away during the change.  we then notify all
93 	// listeners of the change.
94 
95 	PX_ChangeRecord_ObjectChange * pcr
96 		= new PX_ChangeRecord_ObjectChange(PX_ChangeRecord::PXT_ChangeObject,
97 										   dpos, indexOldAP,indexNewAP,
98 										   pfo->getObjectType(),blockOffset,bRevisionDelete);
99 	UT_return_val_if_fail (pcr, false);
100 
101 	// apply the change to this fragment
102 
103 	_fmtChangeObject(pfo,indexNewAP,ppfNewEnd,pfragOffsetNewEnd);
104 
105 	// add record to history.  we do not attempt to coalesce these.
106 	m_history.addChangeRecord(pcr);
107 	m_pDocument->notifyListeners(pfs,pcr);
108 
109 	return true;
110 }
111 
_fmtChangeObject(pf_Frag_Object * pfo,PT_AttrPropIndex indexNewAP,pf_Frag ** ppfNewEnd,UT_uint32 * pfragOffsetNewEnd)112 bool pt_PieceTable::_fmtChangeObject(pf_Frag_Object * pfo,
113 										PT_AttrPropIndex indexNewAP,
114 										pf_Frag ** ppfNewEnd,
115 										UT_uint32 * pfragOffsetNewEnd)
116 {
117 	// actually apply the format change.
118 
119 	pfo->setIndexAP(indexNewAP);
120     //    if (pfo->getField()) pfo->getField()->update();
121 	SETP(ppfNewEnd, pfo->getNext());
122 	SETP(pfragOffsetNewEnd, 0);
123 	return true;
124 }
125 
126 
127