Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <UndoRedline.hxx>
21 : #include <hintids.hxx>
22 : #include <unotools/charclass.hxx>
23 : #include <doc.hxx>
24 : #include <swundo.hxx>
25 : #include <pam.hxx>
26 : #include <ndtxt.hxx>
27 : #include <UndoCore.hxx>
28 : #include <UndoDelete.hxx>
29 : #include <rolbck.hxx>
30 : #include <redline.hxx>
31 : #include <docary.hxx>
32 : #include <sortopt.hxx>
33 :
34 : extern void sw_JoinText( SwPaM& rPam, sal_Bool bJoinPrev );
35 : extern void sw_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev );
36 :
37 0 : SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange )
38 : : SwUndo( UNDO_REDLINE ), SwUndRng( rRange ),
39 : mpRedlData( 0 ), mpRedlSaveData( 0 ), mnUserId( nUsrId ),
40 0 : mbHiddenRedlines( sal_False )
41 : {
42 : // consider Redline
43 0 : SwDoc& rDoc = *rRange.GetDoc();
44 0 : if( rDoc.IsRedlineOn() )
45 : {
46 0 : switch( mnUserId )
47 : {
48 : case UNDO_DELETE:
49 : case UNDO_REPLACE:
50 0 : mpRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_DELETE, rDoc.GetRedlineAuthor() );
51 0 : break;
52 : default:
53 : ;
54 : }
55 0 : SetRedlineMode( rDoc.GetRedlineMode() );
56 : }
57 :
58 0 : sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
59 :
60 0 : mpRedlSaveData = new SwRedlineSaveDatas;
61 0 : if( !FillSaveData( rRange, *mpRedlSaveData, false, UNDO_REJECT_REDLINE != mnUserId ))
62 0 : delete mpRedlSaveData, mpRedlSaveData = 0;
63 : else
64 : {
65 0 : mbHiddenRedlines = HasHiddenRedlines( *mpRedlSaveData );
66 0 : if( mbHiddenRedlines ) // then the NodeIndices of SwUndRng need to be corrected
67 : {
68 0 : nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex();
69 0 : nSttNode -= nEndExtra;
70 0 : nEndNode -= nEndExtra;
71 : }
72 : }
73 0 : }
74 :
75 0 : SwUndoRedline::~SwUndoRedline()
76 : {
77 0 : delete mpRedlData;
78 0 : delete mpRedlSaveData;
79 0 : }
80 :
81 0 : sal_uInt16 SwUndoRedline::GetRedlSaveCount() const
82 : {
83 0 : return mpRedlSaveData ? mpRedlSaveData->size() : 0;
84 : }
85 :
86 0 : void SwUndoRedline::UndoImpl(::sw::UndoRedoContext & rContext)
87 : {
88 0 : SwDoc *const pDoc = & rContext.GetDoc();
89 0 : SwPaM & rPam( AddUndoRedoPaM(rContext) );
90 :
91 0 : UndoRedlineImpl(*pDoc, rPam);
92 :
93 0 : if( mpRedlSaveData )
94 : {
95 0 : sal_uLong nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
96 0 : SetSaveData( *pDoc, *mpRedlSaveData );
97 0 : if( mbHiddenRedlines )
98 : {
99 0 : mpRedlSaveData->DeleteAndDestroyAll();
100 :
101 0 : nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex() - nEndExtra;
102 0 : nSttNode += nEndExtra;
103 0 : nEndNode += nEndExtra;
104 : }
105 0 : SetPaM(rPam, true);
106 : }
107 0 : }
108 :
109 0 : void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext)
110 : {
111 0 : SwDoc *const pDoc = & rContext.GetDoc();
112 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
113 0 : pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
114 :
115 0 : SwPaM & rPam( AddUndoRedoPaM(rContext) );
116 0 : if( mpRedlSaveData && mbHiddenRedlines )
117 : {
118 0 : sal_uLong nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
119 0 : FillSaveData(rPam, *mpRedlSaveData, false, UNDO_REJECT_REDLINE != mnUserId );
120 :
121 0 : nEndExtra -= pDoc->GetNodes().GetEndOfExtras().GetIndex();
122 0 : nSttNode -= nEndExtra;
123 0 : nEndNode -= nEndExtra;
124 : }
125 :
126 0 : RedoRedlineImpl(*pDoc, rPam);
127 :
128 0 : SetPaM(rPam, true);
129 0 : pDoc->SetRedlineMode_intern( eOld );
130 0 : }
131 :
132 0 : void SwUndoRedline::UndoRedlineImpl(SwDoc &, SwPaM &)
133 : {
134 0 : }
135 :
136 : // default: remove redlines
137 0 : void SwUndoRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
138 : {
139 0 : rDoc.DeleteRedline(rPam, true, USHRT_MAX);
140 0 : }
141 :
142 0 : SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUsrId )
143 : : SwUndoRedline( nUsrId ? nUsrId : UNDO_DELETE, rRange ),
144 0 : bCanGroup( sal_False ), bIsDelim( sal_False ), bIsBackspace( sal_False )
145 : {
146 : const SwTxtNode* pTNd;
147 0 : if( UNDO_DELETE == mnUserId &&
148 0 : nSttNode == nEndNode && nSttCntnt + 1 == nEndCntnt &&
149 0 : 0 != (pTNd = rRange.GetNode()->GetTxtNode()) )
150 : {
151 0 : sal_Unicode const cCh = pTNd->GetTxt()[nSttCntnt];
152 0 : if( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
153 : {
154 0 : bCanGroup = sal_True;
155 0 : bIsDelim = !GetAppCharClass().isLetterNumeric( pTNd->GetTxt(),
156 0 : nSttCntnt );
157 0 : bIsBackspace = nSttCntnt == rRange.GetPoint()->nContent.GetIndex();
158 : }
159 : }
160 :
161 0 : bCacheComment = false;
162 0 : }
163 :
164 0 : void SwUndoRedlineDelete::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
165 : {
166 0 : rDoc.DeleteRedline(rPam, true, USHRT_MAX);
167 0 : }
168 :
169 0 : void SwUndoRedlineDelete::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
170 : {
171 0 : if (rPam.GetPoint() != rPam.GetMark())
172 : {
173 0 : rDoc.AppendRedline( new SwRangeRedline(*mpRedlData, rPam), false );
174 : }
175 0 : }
176 :
177 0 : sal_Bool SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete& rNext )
178 : {
179 0 : sal_Bool bRet = sal_False;
180 0 : if( UNDO_DELETE == mnUserId && mnUserId == rNext.mnUserId &&
181 0 : bCanGroup == rNext.bCanGroup &&
182 0 : bIsDelim == rNext.bIsDelim &&
183 0 : bIsBackspace == rNext.bIsBackspace &&
184 0 : nSttNode == nEndNode &&
185 0 : rNext.nSttNode == nSttNode &&
186 0 : rNext.nEndNode == nEndNode )
187 : {
188 0 : int bIsEnd = 0;
189 0 : if( rNext.nSttCntnt == nEndCntnt )
190 0 : bIsEnd = 1;
191 0 : else if( rNext.nEndCntnt == nSttCntnt )
192 0 : bIsEnd = -1;
193 :
194 0 : if( bIsEnd &&
195 0 : (( !mpRedlSaveData && !rNext.mpRedlSaveData ) ||
196 0 : ( mpRedlSaveData && rNext.mpRedlSaveData &&
197 : SwUndo::CanRedlineGroup( *mpRedlSaveData,
198 0 : *rNext.mpRedlSaveData, 1 != bIsEnd )
199 : )))
200 : {
201 0 : if( 1 == bIsEnd )
202 0 : nEndCntnt = rNext.nEndCntnt;
203 : else
204 0 : nSttCntnt = rNext.nSttCntnt;
205 0 : bRet = sal_True;
206 : }
207 : }
208 0 : return bRet;
209 : }
210 :
211 0 : SwUndoRedlineSort::SwUndoRedlineSort( const SwPaM& rRange,
212 : const SwSortOptions& rOpt )
213 : : SwUndoRedline( UNDO_SORT_TXT, rRange ),
214 0 : pOpt( new SwSortOptions( rOpt ) ),
215 0 : nSaveEndNode( nEndNode ), nOffset( 0 ), nSaveEndCntnt( nEndCntnt )
216 : {
217 0 : }
218 :
219 0 : SwUndoRedlineSort::~SwUndoRedlineSort()
220 : {
221 0 : delete pOpt;
222 0 : }
223 :
224 0 : void SwUndoRedlineSort::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
225 : {
226 : // rPam contains the sorted range
227 : // aSaveRange contains copied (i.e. original) range
228 :
229 0 : SwPosition *const pStart = rPam.Start();
230 0 : SwPosition *const pEnd = rPam.End();
231 :
232 0 : SwNodeIndex aPrevIdx( pStart->nNode, -1 );
233 0 : sal_uLong nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
234 :
235 0 : if( 0 == ( nsRedlineMode_t::REDLINE_SHOW_DELETE & rDoc.GetRedlineMode()) )
236 : {
237 : // Search both Redline objects and make them visible to make the nodes
238 : // consistent again. The 'delete' one is hidden, thus search for the
239 : // 'insert' Redline object. The former is located directly after the latter.
240 : sal_uInt16 nFnd = rDoc.GetRedlinePos(
241 0 : *rDoc.GetNodes()[ nSttNode + 1 ],
242 0 : nsRedlineType_t::REDLINE_INSERT );
243 : OSL_ENSURE( USHRT_MAX != nFnd && nFnd+1 < (sal_uInt16)rDoc.GetRedlineTbl().size(),
244 : "could not find an Insert object" );
245 0 : ++nFnd;
246 0 : rDoc.GetRedlineTbl()[nFnd]->Show( 1 );
247 : }
248 :
249 : {
250 0 : SwPaM aTmp( *rPam.GetMark() );
251 0 : aTmp.GetMark()->nContent = 0;
252 0 : aTmp.SetMark();
253 0 : aTmp.GetPoint()->nNode = nSaveEndNode;
254 0 : aTmp.GetPoint()->nContent.Assign( aTmp.GetCntntNode(), nSaveEndCntnt );
255 0 : rDoc.DeleteRedline( aTmp, true, USHRT_MAX );
256 : }
257 :
258 0 : rDoc.DelFullPara(rPam);
259 :
260 0 : SwPaM *const pPam = & rPam;
261 0 : pPam->DeleteMark();
262 0 : pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
263 0 : SwCntntNode* pCNd = pPam->GetCntntNode();
264 0 : pPam->GetPoint()->nContent.Assign(pCNd, 0 );
265 0 : pPam->SetMark();
266 :
267 0 : pPam->GetPoint()->nNode += nOffsetTemp;
268 0 : pCNd = pPam->GetCntntNode();
269 0 : pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
270 :
271 0 : SetValues( *pPam );
272 :
273 0 : SetPaM(rPam);
274 0 : }
275 :
276 0 : void SwUndoRedlineSort::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
277 : {
278 0 : SwPaM* pPam = &rPam;
279 0 : SwPosition* pStart = pPam->Start();
280 0 : SwPosition* pEnd = pPam->End();
281 :
282 0 : SwNodeIndex aPrevIdx( pStart->nNode, -1 );
283 0 : sal_uLong nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
284 0 : const sal_Int32 nCntStt = pStart->nContent.GetIndex();
285 :
286 0 : rDoc.SortText(rPam, *pOpt);
287 :
288 0 : pPam->DeleteMark();
289 0 : pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
290 0 : SwCntntNode* pCNd = pPam->GetCntntNode();
291 0 : sal_Int32 nLen = pCNd->Len();
292 0 : if( nLen > nCntStt )
293 0 : nLen = nCntStt;
294 0 : pPam->GetPoint()->nContent.Assign(pCNd, nLen );
295 0 : pPam->SetMark();
296 :
297 0 : pPam->GetPoint()->nNode += nOffsetTemp;
298 0 : pCNd = pPam->GetCntntNode();
299 0 : pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
300 :
301 0 : SetValues( rPam );
302 :
303 0 : SetPaM( rPam );
304 0 : rPam.GetPoint()->nNode = nSaveEndNode;
305 0 : rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nSaveEndCntnt );
306 0 : }
307 :
308 0 : void SwUndoRedlineSort::RepeatImpl(::sw::RepeatContext & rContext)
309 : {
310 0 : rContext.GetDoc().SortText( rContext.GetRepeatPaM(), *pOpt );
311 0 : }
312 :
313 0 : void SwUndoRedlineSort::SetSaveRange( const SwPaM& rRange )
314 : {
315 0 : const SwPosition& rPos = *rRange.End();
316 0 : nSaveEndNode = rPos.nNode.GetIndex();
317 0 : nSaveEndCntnt = rPos.nContent.GetIndex();
318 0 : }
319 :
320 0 : void SwUndoRedlineSort::SetOffset( const SwNodeIndex& rIdx )
321 : {
322 0 : nOffset = rIdx.GetIndex() - nSttNode;
323 0 : }
324 :
325 0 : SwUndoAcceptRedline::SwUndoAcceptRedline( const SwPaM& rRange )
326 0 : : SwUndoRedline( UNDO_ACCEPT_REDLINE, rRange )
327 : {
328 0 : }
329 :
330 0 : void SwUndoAcceptRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
331 : {
332 0 : rDoc.AcceptRedline(rPam, false);
333 0 : }
334 :
335 0 : void SwUndoAcceptRedline::RepeatImpl(::sw::RepeatContext & rContext)
336 : {
337 0 : rContext.GetDoc().AcceptRedline(rContext.GetRepeatPaM(), true);
338 0 : }
339 :
340 0 : SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM& rRange )
341 0 : : SwUndoRedline( UNDO_REJECT_REDLINE, rRange )
342 : {
343 0 : }
344 :
345 0 : void SwUndoRejectRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
346 : {
347 0 : rDoc.RejectRedline(rPam, false);
348 0 : }
349 :
350 0 : void SwUndoRejectRedline::RepeatImpl(::sw::RepeatContext & rContext)
351 : {
352 0 : rContext.GetDoc().RejectRedline(rContext.GetRepeatPaM(), true);
353 0 : }
354 :
355 0 : SwUndoCompDoc::SwUndoCompDoc( const SwPaM& rRg, sal_Bool bIns )
356 : : SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRg ), pRedlData( 0 ),
357 0 : pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ), bInsert( bIns )
358 : {
359 0 : SwDoc* pDoc = (SwDoc*)rRg.GetDoc();
360 0 : if( pDoc->IsRedlineOn() )
361 : {
362 0 : RedlineType_t eTyp = bInsert ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_DELETE;
363 0 : pRedlData = new SwRedlineData( eTyp, pDoc->GetRedlineAuthor() );
364 0 : SetRedlineMode( pDoc->GetRedlineMode() );
365 : }
366 0 : }
367 :
368 0 : SwUndoCompDoc::SwUndoCompDoc( const SwRangeRedline& rRedl )
369 : : SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRedl ), pRedlData( 0 ),
370 : pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ),
371 : // for MergeDoc the corresponding inverse is needed
372 0 : bInsert( nsRedlineType_t::REDLINE_DELETE == rRedl.GetType() )
373 : {
374 0 : SwDoc* pDoc = (SwDoc*)rRedl.GetDoc();
375 0 : if( pDoc->IsRedlineOn() )
376 : {
377 0 : pRedlData = new SwRedlineData( rRedl.GetRedlineData() );
378 0 : SetRedlineMode( pDoc->GetRedlineMode() );
379 : }
380 :
381 0 : pRedlSaveData = new SwRedlineSaveDatas;
382 0 : if( !FillSaveData( rRedl, *pRedlSaveData, false, true ))
383 0 : delete pRedlSaveData, pRedlSaveData = 0;
384 0 : }
385 :
386 0 : SwUndoCompDoc::~SwUndoCompDoc()
387 : {
388 0 : delete pRedlData;
389 0 : delete pUnDel;
390 0 : delete pUnDel2;
391 0 : delete pRedlSaveData;
392 0 : }
393 :
394 0 : void SwUndoCompDoc::UndoImpl(::sw::UndoRedoContext & rContext)
395 : {
396 0 : SwDoc *const pDoc = & rContext.GetDoc();
397 0 : SwPaM *const pPam( & AddUndoRedoPaM(rContext) );
398 :
399 0 : if( !bInsert )
400 : {
401 : // delete Redlines
402 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
403 0 : pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON));
404 :
405 0 : pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
406 :
407 0 : pDoc->SetRedlineMode_intern( eOld );
408 :
409 : // per definition Point is end (in SwUndRng!)
410 0 : SwCntntNode* pCSttNd = pPam->GetCntntNode( false );
411 0 : SwCntntNode* pCEndNd = pPam->GetCntntNode( true );
412 :
413 : // if start- and end-content is zero, then the doc-compare moves
414 : // complete nodes into the current doc. And then the selection
415 : // must be from end to start, so the delete join into the right
416 : // direction.
417 0 : if( !nSttCntnt && !nEndCntnt )
418 0 : pPam->Exchange();
419 :
420 : sal_Bool bJoinTxt, bJoinPrev;
421 0 : sw_GetJoinFlags( *pPam, bJoinTxt, bJoinPrev );
422 :
423 0 : pUnDel = new SwUndoDelete( *pPam, sal_False );
424 :
425 0 : if( bJoinTxt )
426 0 : sw_JoinText( *pPam, bJoinPrev );
427 :
428 0 : if( pCSttNd && !pCEndNd)
429 : {
430 : // #112139# Do not step behind the end of content.
431 0 : SwNode * pTmp = pPam->GetNode(true);
432 0 : if (pTmp)
433 : {
434 0 : SwNode * pEnd = pDoc->GetNodes().DocumentSectionEndNode(pTmp);
435 :
436 0 : if (pTmp != pEnd)
437 : {
438 0 : pPam->SetMark();
439 0 : pPam->GetPoint()->nNode++;
440 0 : pPam->GetBound( true ).nContent.Assign( 0, 0 );
441 0 : pPam->GetBound( false ).nContent.Assign( 0, 0 );
442 0 : pUnDel2 = new SwUndoDelete( *pPam, sal_True );
443 : }
444 : }
445 : }
446 0 : pPam->DeleteMark();
447 : }
448 : else
449 : {
450 0 : if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
451 : {
452 0 : pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
453 :
454 0 : if( pRedlSaveData )
455 0 : SetSaveData( *pDoc, *pRedlSaveData );
456 : }
457 0 : SetPaM(*pPam, true);
458 : }
459 0 : }
460 :
461 0 : void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
462 : {
463 0 : SwDoc *const pDoc = & rContext.GetDoc();
464 0 : SwPaM *const pPam( & AddUndoRedoPaM(rContext) );
465 :
466 0 : if( bInsert )
467 : {
468 0 : if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
469 : {
470 0 : SwRangeRedline* pTmp = new SwRangeRedline( *pRedlData, *pPam );
471 0 : ((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
472 0 : pTmp->InvalidateRange();
473 : }
474 0 : else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
475 0 : !pDoc->GetRedlineTbl().empty() )
476 0 : pDoc->SplitRedline( *pPam );
477 : }
478 : else
479 : {
480 0 : if( pUnDel2 )
481 : {
482 0 : pUnDel2->UndoImpl(rContext);
483 0 : delete pUnDel2, pUnDel2 = 0;
484 : }
485 0 : pUnDel->UndoImpl(rContext);
486 0 : delete pUnDel, pUnDel = 0;
487 :
488 0 : SetPaM( *pPam );
489 :
490 0 : SwRangeRedline* pTmp = new SwRangeRedline( *pRedlData, *pPam );
491 0 : ((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
492 0 : pTmp->InvalidateRange();
493 : }
494 :
495 0 : SetPaM(*pPam, true);
496 0 : }
497 :
498 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|