1 |
From 7adf5a76404205e3b2f1dbb4bb01a612d78ea0dc Mon Sep 17 00:00:00 2001 |
2 |
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com> |
3 |
Date: Tue, 13 Jan 2015 13:55:58 +0000 |
4 |
Subject: [PATCH] allow comparing documents which only differ by frame contents |
5 |
|
6 |
if two documents have the same number of frames then have an additional stab at |
7 |
comparing the contents of those frames |
8 |
|
9 |
Change-Id: Ie7f1a8906d49d720a74620ad8d69fd97c76304e3 |
10 |
(cherry picked from commit 16916a14a2ce382aa4ff2a25f8e477108aba5a67) |
11 |
--- |
12 |
sw/source/core/doc/doccomp.cxx | 236 +++++++++++++++++++++++++---------------- |
13 |
1 file changed, 144 insertions(+), 92 deletions(-) |
14 |
|
15 |
diff --git a/sw/source/core/doc/doccomp.cxx b/sw/source/core/doc/doccomp.cxx |
16 |
index 8634835..043d2d4 100644 |
17 |
--- a/sw/source/core/doc/doccomp.cxx |
18 |
+++ b/sw/source/core/doc/doccomp.cxx |
19 |
@@ -38,6 +38,7 @@ |
20 |
#include <section.hxx> |
21 |
#include <tox.hxx> |
22 |
#include <docsh.hxx> |
23 |
+#include <fmtcntnt.hxx> |
24 |
|
25 |
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> |
26 |
#include <com/sun/star/document/XDocumentProperties.hpp> |
27 |
@@ -65,18 +66,32 @@ public: |
28 |
|
29 |
class CompareData |
30 |
{ |
31 |
+protected: |
32 |
+ SwDoc& rDoc; |
33 |
+private: |
34 |
size_t* pIndex; |
35 |
bool* pChangedFlag; |
36 |
|
37 |
-protected: |
38 |
+ SwPaM *pInsRing, *pDelRing; |
39 |
+ |
40 |
+ sal_uLong PrevIdx( const SwNode* pNd ); |
41 |
+ sal_uLong NextIdx( const SwNode* pNd ); |
42 |
+ |
43 |
vector< CompareLine* > aLines; |
44 |
sal_uLong nSttLineNum; |
45 |
+ bool m_bRecordDiff; |
46 |
|
47 |
// Truncate beginning and end and add all others to the LinesArray |
48 |
- virtual void CheckRanges( CompareData& ) = 0; |
49 |
+ void CheckRanges( CompareData& ); |
50 |
+ |
51 |
+ virtual const SwNode& GetEndOfContent() = 0; |
52 |
|
53 |
public: |
54 |
- CompareData(); |
55 |
+ CompareData(SwDoc& rD, bool bRecordDiff) |
56 |
+ : rDoc( rD ), pIndex( 0 ), pChangedFlag( 0 ), pInsRing(0), pDelRing(0) |
57 |
+ , nSttLineNum( 0 ), m_bRecordDiff(bRecordDiff) |
58 |
+ { |
59 |
+ } |
60 |
virtual ~CompareData(); |
61 |
|
62 |
// Are there differences? |
63 |
@@ -89,10 +104,10 @@ public: |
64 |
// Displaying the actually content is to be handled by the subclass! |
65 |
sal_uLong ShowDiffs( const CompareData& rData ); |
66 |
|
67 |
- virtual void ShowInsert( sal_uLong nStt, sal_uLong nEnd ); |
68 |
- virtual void ShowDelete( const CompareData& rData, sal_uLong nStt, |
69 |
+ void ShowInsert( sal_uLong nStt, sal_uLong nEnd ); |
70 |
+ void ShowDelete( const CompareData& rData, sal_uLong nStt, |
71 |
sal_uLong nEnd, sal_uLong nInsPos ); |
72 |
- virtual void CheckForChangesInLine( const CompareData& rData, |
73 |
+ void CheckForChangesInLine( const CompareData& rData, |
74 |
sal_uLong& nStt, sal_uLong& nEnd, |
75 |
sal_uLong& nThisStt, sal_uLong& nThisEnd ); |
76 |
|
77 |
@@ -114,6 +129,38 @@ public: |
78 |
{ return aLines[ nLine ]; } |
79 |
void InsertLine( CompareLine* pLine ) |
80 |
{ aLines.push_back( pLine ); } |
81 |
+ |
82 |
+ void SetRedlinesToDoc( bool bUseDocInfo ); |
83 |
+}; |
84 |
+ |
85 |
+class CompareMainText : public CompareData |
86 |
+{ |
87 |
+public: |
88 |
+ CompareMainText(SwDoc &rD, bool bRecordDiff=true) |
89 |
+ : CompareData(rD, bRecordDiff) |
90 |
+ { |
91 |
+ } |
92 |
+ |
93 |
+ virtual const SwNode& GetEndOfContent() SAL_OVERRIDE |
94 |
+ { |
95 |
+ return rDoc.GetNodes().GetEndOfContent(); |
96 |
+ } |
97 |
+}; |
98 |
+ |
99 |
+class CompareFrmFmtText : public CompareData |
100 |
+{ |
101 |
+ const SwNodeIndex &m_rIndex; |
102 |
+public: |
103 |
+ CompareFrmFmtText(SwDoc &rD, const SwNodeIndex &rIndex, bool bRecordDiff=true) |
104 |
+ : CompareData(rD, bRecordDiff) |
105 |
+ , m_rIndex(rIndex) |
106 |
+ { |
107 |
+ } |
108 |
+ |
109 |
+ virtual const SwNode& GetEndOfContent() SAL_OVERRIDE |
110 |
+ { |
111 |
+ return *m_rIndex.GetNode().EndOfSectionNode(); |
112 |
+ } |
113 |
}; |
114 |
|
115 |
class Hash |
116 |
@@ -328,13 +375,21 @@ public: |
117 |
|
118 |
CompareLine::~CompareLine() {} |
119 |
|
120 |
-CompareData::CompareData() |
121 |
- : pIndex( 0 ), pChangedFlag( 0 ), nSttLineNum( 0 ) |
122 |
-{ |
123 |
-} |
124 |
- |
125 |
CompareData::~CompareData() |
126 |
{ |
127 |
+ if( pDelRing ) |
128 |
+ { |
129 |
+ while( pDelRing->GetNext() != pDelRing ) |
130 |
+ delete pDelRing->GetNext(); |
131 |
+ delete pDelRing; |
132 |
+ } |
133 |
+ if( pInsRing ) |
134 |
+ { |
135 |
+ while( pInsRing->GetNext() != pInsRing ) |
136 |
+ delete pInsRing->GetNext(); |
137 |
+ delete pInsRing; |
138 |
+ } |
139 |
+ |
140 |
delete[] pIndex; |
141 |
delete[] pChangedFlag; |
142 |
} |
143 |
@@ -393,9 +448,12 @@ sal_uLong CompareData::ShowDiffs( const CompareData& rData ) |
144 |
while( nStt1 < nLen1 && rData.GetChanged( nStt1 )) ++nStt1; |
145 |
while( nStt2 < nLen2 && GetChanged( nStt2 )) ++nStt2; |
146 |
|
147 |
- // Check if there are changed lines (only slightly different) and |
148 |
- // compare them in detail. |
149 |
- CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 ); |
150 |
+ if (m_bRecordDiff) |
151 |
+ { |
152 |
+ // Check if there are changed lines (only slightly different) and |
153 |
+ // compare them in detail. |
154 |
+ CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 ); |
155 |
+ } |
156 |
|
157 |
++nCnt; |
158 |
} |
159 |
@@ -422,19 +480,6 @@ bool CompareData::HasDiffs( const CompareData& rData ) const |
160 |
return bRet; |
161 |
} |
162 |
|
163 |
-void CompareData::ShowInsert( sal_uLong, sal_uLong ) |
164 |
-{ |
165 |
-} |
166 |
- |
167 |
-void CompareData::ShowDelete( const CompareData&, sal_uLong, sal_uLong, sal_uLong ) |
168 |
-{ |
169 |
-} |
170 |
- |
171 |
-void CompareData::CheckForChangesInLine( const CompareData& , |
172 |
- sal_uLong&, sal_uLong&, sal_uLong&, sal_uLong& ) |
173 |
-{ |
174 |
-} |
175 |
- |
176 |
Hash::Hash( sal_uLong nSize ) |
177 |
: nCount(1) |
178 |
{ |
179 |
@@ -972,30 +1017,6 @@ public: |
180 |
OUString GetText() const; |
181 |
}; |
182 |
|
183 |
-class SwCompareData : public CompareData |
184 |
-{ |
185 |
- SwDoc& rDoc; |
186 |
- SwPaM *pInsRing, *pDelRing; |
187 |
- |
188 |
- sal_uLong PrevIdx( const SwNode* pNd ); |
189 |
- sal_uLong NextIdx( const SwNode* pNd ); |
190 |
- |
191 |
- virtual void CheckRanges( CompareData& ) SAL_OVERRIDE; |
192 |
- virtual void ShowInsert( sal_uLong nStt, sal_uLong nEnd ) SAL_OVERRIDE; |
193 |
- virtual void ShowDelete( const CompareData& rData, sal_uLong nStt, |
194 |
- sal_uLong nEnd, sal_uLong nInsPos ) SAL_OVERRIDE; |
195 |
- |
196 |
- virtual void CheckForChangesInLine( const CompareData& rData, |
197 |
- sal_uLong& nStt, sal_uLong& nEnd, |
198 |
- sal_uLong& nThisStt, sal_uLong& nThisEnd ) SAL_OVERRIDE; |
199 |
- |
200 |
-public: |
201 |
- SwCompareData( SwDoc& rD ) : rDoc( rD ), pInsRing(0), pDelRing(0) {} |
202 |
- virtual ~SwCompareData(); |
203 |
- |
204 |
- void SetRedlinesToDoc( bool bUseDocInfo ); |
205 |
-}; |
206 |
- |
207 |
SwCompareLine::SwCompareLine( const SwNode& rNd ) |
208 |
: rNode( rNd ) |
209 |
{ |
210 |
@@ -1400,23 +1421,7 @@ bool SwCompareLine::ChangesInLine( const SwCompareLine& rLine, |
211 |
return bRet; |
212 |
} |
213 |
|
214 |
-SwCompareData::~SwCompareData() |
215 |
-{ |
216 |
- if( pDelRing ) |
217 |
- { |
218 |
- while( pDelRing->GetNext() != pDelRing ) |
219 |
- delete pDelRing->GetNext(); |
220 |
- delete pDelRing; |
221 |
- } |
222 |
- if( pInsRing ) |
223 |
- { |
224 |
- while( pInsRing->GetNext() != pInsRing ) |
225 |
- delete pInsRing->GetNext(); |
226 |
- delete pInsRing; |
227 |
- } |
228 |
-} |
229 |
- |
230 |
-sal_uLong SwCompareData::NextIdx( const SwNode* pNd ) |
231 |
+sal_uLong CompareData::NextIdx( const SwNode* pNd ) |
232 |
{ |
233 |
if( pNd->IsStartNode() ) |
234 |
{ |
235 |
@@ -1430,7 +1435,7 @@ sal_uLong SwCompareData::NextIdx( const SwNode* pNd ) |
236 |
return pNd->GetIndex() + 1; |
237 |
} |
238 |
|
239 |
-sal_uLong SwCompareData::PrevIdx( const SwNode* pNd ) |
240 |
+sal_uLong CompareData::PrevIdx( const SwNode* pNd ) |
241 |
{ |
242 |
if( pNd->IsEndNode() ) |
243 |
{ |
244 |
@@ -1444,13 +1449,13 @@ sal_uLong SwCompareData::PrevIdx( const SwNode* pNd ) |
245 |
return pNd->GetIndex() - 1; |
246 |
} |
247 |
|
248 |
-void SwCompareData::CheckRanges( CompareData& rData ) |
249 |
+void CompareData::CheckRanges( CompareData& rData ) |
250 |
{ |
251 |
- const SwNodes& rSrcNds = static_cast<SwCompareData&>(rData).rDoc.GetNodes(); |
252 |
+ const SwNodes& rSrcNds = rData.rDoc.GetNodes(); |
253 |
const SwNodes& rDstNds = rDoc.GetNodes(); |
254 |
|
255 |
- const SwNode& rSrcEndNd = rSrcNds.GetEndOfContent(); |
256 |
- const SwNode& rDstEndNd = rDstNds.GetEndOfContent(); |
257 |
+ const SwNode& rSrcEndNd = rData.GetEndOfContent(); |
258 |
+ const SwNode& rDstEndNd = GetEndOfContent(); |
259 |
|
260 |
sal_uLong nSrcSttIdx = NextIdx( rSrcEndNd.StartOfSectionNode() ); |
261 |
sal_uLong nSrcEndIdx = rSrcEndNd.GetIndex(); |
262 |
@@ -1497,7 +1502,7 @@ void SwCompareData::CheckRanges( CompareData& rData ) |
263 |
} |
264 |
} |
265 |
|
266 |
-void SwCompareData::ShowInsert( sal_uLong nStt, sal_uLong nEnd ) |
267 |
+void CompareData::ShowInsert( sal_uLong nStt, sal_uLong nEnd ) |
268 |
{ |
269 |
SwPaM* pTmp = new SwPaM( static_cast<const SwCompareLine*>(GetLine( nStt ))->GetNode(), 0, |
270 |
static_cast<const SwCompareLine*>(GetLine( nEnd-1 ))->GetEndNode(), 0, |
271 |
@@ -1508,7 +1513,7 @@ void SwCompareData::ShowInsert( sal_uLong nStt, sal_uLong nEnd ) |
272 |
// #i65201#: These SwPaMs are calculated smaller than needed, see comment below |
273 |
} |
274 |
|
275 |
-void SwCompareData::ShowDelete( |
276 |
+void CompareData::ShowDelete( |
277 |
const CompareData& rData, |
278 |
sal_uLong nStt, |
279 |
sal_uLong nEnd, |
280 |
@@ -1541,14 +1546,14 @@ void SwCompareData::ShowDelete( |
281 |
} |
282 |
else |
283 |
{ |
284 |
- pLineNd = &rDoc.GetNodes().GetEndOfContent(); |
285 |
+ pLineNd = &GetEndOfContent(); |
286 |
nOffset = 0; |
287 |
} |
288 |
|
289 |
SwNodeIndex aInsPos( *pLineNd, nOffset ); |
290 |
SwNodeIndex aSavePos( aInsPos, -1 ); |
291 |
|
292 |
- static_cast<const SwCompareData&>(rData).rDoc.GetDocumentContentOperationsManager().CopyWithFlyInFly( aRg, 0, aInsPos ); |
293 |
+ rData.rDoc.GetDocumentContentOperationsManager().CopyWithFlyInFly( aRg, 0, aInsPos ); |
294 |
rDoc.getIDocumentState().SetModified(); |
295 |
++aSavePos; |
296 |
|
297 |
@@ -1572,7 +1577,7 @@ void SwCompareData::ShowDelete( |
298 |
} |
299 |
} |
300 |
|
301 |
-void SwCompareData::CheckForChangesInLine( const CompareData& rData, |
302 |
+void CompareData::CheckForChangesInLine( const CompareData& rData, |
303 |
sal_uLong& rStt, sal_uLong& rEnd, |
304 |
sal_uLong& rThisStt, sal_uLong& rThisEnd ) |
305 |
{ |
306 |
@@ -1625,7 +1630,7 @@ void SwCompareData::CheckForChangesInLine( const CompareData& rData, |
307 |
} |
308 |
} |
309 |
|
310 |
-void SwCompareData::SetRedlinesToDoc( bool bUseDocInfo ) |
311 |
+void CompareData::SetRedlinesToDoc( bool bUseDocInfo ) |
312 |
{ |
313 |
SwPaM* pTmp = pDelRing; |
314 |
|
315 |
@@ -1673,7 +1678,7 @@ void SwCompareData::SetRedlinesToDoc( bool bUseDocInfo ) |
316 |
} |
317 |
// #i101009# |
318 |
// prevent redlines that end on structural end node |
319 |
- if (& rDoc.GetNodes().GetEndOfContent() == |
320 |
+ if (& GetEndOfContent() == |
321 |
& pTmp->GetPoint()->nNode.GetNode()) |
322 |
{ |
323 |
pTmp->GetPoint()->nNode--; |
324 |
@@ -1705,7 +1710,7 @@ void SwCompareData::SetRedlinesToDoc( bool bUseDocInfo ) |
325 |
} |
326 |
// #i101009# |
327 |
// prevent redlines that end on structural end node |
328 |
- if (& rDoc.GetNodes().GetEndOfContent() == |
329 |
+ if (& GetEndOfContent() == |
330 |
& pTmp->GetPoint()->nNode.GetNode()) |
331 |
{ |
332 |
pTmp->GetPoint()->nNode--; |
333 |
@@ -1760,6 +1765,48 @@ void SwCompareData::SetRedlinesToDoc( bool bUseDocInfo ) |
334 |
} |
335 |
} |
336 |
|
337 |
+typedef std::shared_ptr<CompareData> CompareDataPtr; |
338 |
+typedef std::pair<CompareDataPtr, CompareDataPtr> CompareDataPtrPair; |
339 |
+typedef std::vector<CompareDataPtrPair> Comparators; |
340 |
+ |
341 |
+namespace |
342 |
+{ |
343 |
+ Comparators buildComparators(SwDoc &rSrcDoc, SwDoc &rDestDoc) |
344 |
+ { |
345 |
+ Comparators aComparisons; |
346 |
+ //compare main text |
347 |
+ aComparisons.push_back(CompareDataPtrPair(CompareDataPtr(new CompareMainText(rSrcDoc)), |
348 |
+ CompareDataPtr(new CompareMainText(rDestDoc)))); |
349 |
+ |
350 |
+ //if we have the same number of frames then try to compare within them |
351 |
+ const SwFrmFmts *pSrcFrmFmts = rSrcDoc.GetSpzFrmFmts(); |
352 |
+ const SwFrmFmts *pDestFrmFmts = rDestDoc.GetSpzFrmFmts(); |
353 |
+ if (pSrcFrmFmts->size() == pDestFrmFmts->size()) |
354 |
+ { |
355 |
+ for (size_t i = 0; i < pSrcFrmFmts->size(); ++i) |
356 |
+ { |
357 |
+ const SwFrmFmt& rSrcFmt = *(*pSrcFrmFmts)[i]; |
358 |
+ const SwFrmFmt& rDestFmt = *(*pDestFrmFmts)[i]; |
359 |
+ const SwNodeIndex* pSrcIdx = rSrcFmt.GetCntnt().GetCntntIdx(); |
360 |
+ const SwNodeIndex* pDestIdx = rDestFmt.GetCntnt().GetCntntIdx(); |
361 |
+ if (!pSrcIdx && !pDestIdx) |
362 |
+ continue; |
363 |
+ if (!pSrcIdx || !pDestIdx) |
364 |
+ break; |
365 |
+ const SwNode* pSrcNode = pSrcIdx->GetNode().EndOfSectionNode(); |
366 |
+ const SwNode* pDestNode = pDestIdx->GetNode().EndOfSectionNode(); |
367 |
+ if (!pSrcNode && !pDestNode) |
368 |
+ continue; |
369 |
+ if (!pSrcNode || !pDestNode) |
370 |
+ break; |
371 |
+ aComparisons.push_back(CompareDataPtrPair(CompareDataPtr(new CompareFrmFmtText(rSrcDoc, *pSrcIdx)), |
372 |
+ CompareDataPtr(new CompareFrmFmtText(rDestDoc, *pDestIdx)))); |
373 |
+ } |
374 |
+ } |
375 |
+ return aComparisons; |
376 |
+ } |
377 |
+} |
378 |
+ |
379 |
// Returns (the difference count?) if something is different |
380 |
long SwDoc::CompareDoc( const SwDoc& rDoc ) |
381 |
{ |
382 |
@@ -1800,19 +1847,26 @@ long SwDoc::CompareDoc( const SwDoc& rDoc ) |
383 |
rSrcDoc.getIDocumentRedlineAccess().SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT ); |
384 |
getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT)); |
385 |
|
386 |
- SwCompareData aD0( rSrcDoc ); |
387 |
- SwCompareData aD1( *this ); |
388 |
- |
389 |
- aD1.CompareLines( aD0 ); |
390 |
+ Comparators aComparisons(buildComparators(rSrcDoc, *this)); |
391 |
|
392 |
- nRet = aD1.ShowDiffs( aD0 ); |
393 |
+ for (auto& a : aComparisons) |
394 |
+ { |
395 |
+ CompareData& rD0 = *a.first.get(); |
396 |
+ CompareData& rD1 = *a.second.get(); |
397 |
+ rD1.CompareLines( rD0 ); |
398 |
+ nRet |= rD1.ShowDiffs( rD0 ); |
399 |
+ } |
400 |
|
401 |
if( nRet ) |
402 |
{ |
403 |
- getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | |
404 |
+ getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | |
405 |
nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE)); |
406 |
|
407 |
- aD1.SetRedlinesToDoc( !bDocWasModified ); |
408 |
+ for (auto& a : aComparisons) |
409 |
+ { |
410 |
+ CompareData& rD1 = *a.second.get(); |
411 |
+ rD1.SetRedlinesToDoc( !bDocWasModified ); |
412 |
+ } |
413 |
getIDocumentState().SetModified(); |
414 |
} |
415 |
|
416 |
@@ -2016,11 +2070,9 @@ long SwDoc::MergeDoc( const SwDoc& rDoc ) |
417 |
rSrcDoc.getIDocumentRedlineAccess().SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_DELETE ); |
418 |
getIDocumentRedlineAccess().SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_DELETE ); |
419 |
|
420 |
- SwCompareData aD0( rSrcDoc ); |
421 |
- SwCompareData aD1( *this ); |
422 |
- |
423 |
+ CompareMainText aD0(rSrcDoc, false); |
424 |
+ CompareMainText aD1(*this, false); |
425 |
aD1.CompareLines( aD0 ); |
426 |
- |
427 |
if( !aD1.HasDiffs( aD0 ) ) |
428 |
{ |
429 |
// we want to get all redlines from the SourceDoc |
430 |
-- |
431 |
1.9.3 |
432 |
|