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 :
21 : #include <UndoInsert.hxx>
22 :
23 : #include <hintids.hxx>
24 : #include <unotools/charclass.hxx>
25 : #include <sot/storage.hxx>
26 : #include <editeng/keepitem.hxx>
27 : #include <svx/svdobj.hxx>
28 : #include <xmloff/odffields.hxx>
29 :
30 : #include <docsh.hxx>
31 : #include <fmtcntnt.hxx>
32 : #include <fmtanchr.hxx>
33 : #include <frmfmt.hxx>
34 : #include <doc.hxx>
35 : #include <IDocumentUndoRedo.hxx>
36 : #include <swundo.hxx>
37 : #include <pam.hxx>
38 : #include <ndtxt.hxx>
39 : #include <UndoCore.hxx>
40 : #include <UndoDelete.hxx>
41 : #include <UndoAttribute.hxx>
42 : #include <rolbck.hxx>
43 : #include <ndgrf.hxx>
44 : #include <ndole.hxx>
45 : #include <grfatr.hxx>
46 : #include <cntfrm.hxx>
47 : #include <flyfrm.hxx>
48 : #include <fesh.hxx>
49 : #include <swtable.hxx>
50 : #include <redline.hxx>
51 : #include <docary.hxx>
52 : #include <acorrect.hxx>
53 : #include <dcontact.hxx>
54 :
55 : #include <comcore.hrc> // #111827#
56 : #include <undo.hrc>
57 :
58 : using namespace ::com::sun::star;
59 :
60 :
61 : //------------------------------------------------------------
62 :
63 : // INSERT
64 :
65 3625 : String * SwUndoInsert::GetTxtFromDoc() const
66 : {
67 3625 : String * pResult = NULL;
68 :
69 3625 : SwNodeIndex aNd( pDoc->GetNodes(), nNode);
70 3625 : SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
71 7250 : SwPaM aPaM( *pCNd, nCntnt );
72 :
73 3625 : aPaM.SetMark();
74 :
75 3625 : if( pCNd->IsTxtNode() )
76 : {
77 3625 : OUString sTxt = static_cast<SwTxtNode*>(pCNd)->GetTxt();
78 :
79 3625 : sal_Int32 nStart = nCntnt-nLen;
80 3625 : sal_Int32 nLength = nLen;
81 :
82 3625 : if (nStart < 0)
83 : {
84 15 : nLength += nStart;
85 15 : nStart = 0;
86 : }
87 :
88 3625 : pResult = new String(sTxt.copy(nStart, nLength));
89 : }
90 :
91 7250 : return pResult;
92 : }
93 :
94 3624 : void SwUndoInsert::Init(const SwNodeIndex & rNd)
95 : {
96 : // consider Redline
97 3624 : pDoc = rNd.GetNode().GetDoc();
98 3624 : if( pDoc->IsRedlineOn() )
99 : {
100 : pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
101 0 : pDoc->GetRedlineAuthor() );
102 0 : SetRedlineMode( pDoc->GetRedlineMode() );
103 : }
104 :
105 3624 : pUndoTxt = GetTxtFromDoc();
106 :
107 3624 : bCacheComment = false;
108 3624 : }
109 :
110 : // #111827#
111 3609 : SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd, xub_StrLen nCnt,
112 : xub_StrLen nL,
113 : const IDocumentContentOperations::InsertFlags nInsertFlags,
114 : sal_Bool bWDelim )
115 : : SwUndo(UNDO_TYPING), pTxt( 0 ), pRedlData( 0 ),
116 3609 : nNode( rNd.GetIndex() ), nCntnt(nCnt), nLen(nL),
117 : bIsWordDelim( bWDelim ), bIsAppend( sal_False )
118 : , m_bWithRsid(false)
119 7218 : , m_nInsertFlags(nInsertFlags)
120 : {
121 3609 : Init(rNd);
122 3609 : }
123 :
124 : // #111827#
125 15 : SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd )
126 : : SwUndo(UNDO_SPLITNODE), pTxt( 0 ),
127 15 : pRedlData( 0 ), nNode( rNd.GetIndex() ), nCntnt(0), nLen(1),
128 : bIsWordDelim( sal_False ), bIsAppend( sal_True )
129 : , m_bWithRsid(false)
130 30 : , m_nInsertFlags(IDocumentContentOperations::INS_EMPTYEXPAND)
131 : {
132 15 : Init(rNd);
133 15 : }
134 :
135 : // Check if the next Insert can be combined with the current one. If so
136 : // change the length and InsPos. As a result, SwDoc::Inser will not add a
137 : // new object into the Undo list.
138 :
139 133 : sal_Bool SwUndoInsert::CanGrouping( sal_Unicode cIns )
140 : {
141 532 : if( !bIsAppend && bIsWordDelim ==
142 532 : !GetAppCharClass().isLetterNumeric( OUString( cIns )) )
143 : {
144 130 : nLen++;
145 130 : nCntnt++;
146 :
147 130 : if (pUndoTxt)
148 130 : pUndoTxt->Insert(cIns);
149 :
150 130 : return sal_True;
151 : }
152 3 : return sal_False;
153 : }
154 :
155 47 : sal_Bool SwUndoInsert::CanGrouping( const SwPosition& rPos )
156 : {
157 47 : sal_Bool bRet = sal_False;
158 94 : if( nNode == rPos.nNode.GetIndex() &&
159 47 : nCntnt == rPos.nContent.GetIndex() )
160 : {
161 : // consider Redline
162 46 : SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
163 92 : if( ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & rDoc.GetRedlineMode() ) ==
164 46 : ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & GetRedlineMode() ) )
165 : {
166 46 : bRet = sal_True;
167 :
168 : // than there is or was still an active Redline:
169 : // Check if there is another Redline at the InsPosition. If the
170 : // same exists only once, it can be combined.
171 46 : const SwRedlineTbl& rTbl = rDoc.GetRedlineTbl();
172 46 : if( !rTbl.empty() )
173 : {
174 0 : SwRedlineData aRData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
175 0 : const SwIndexReg* pIReg = rPos.nContent.GetIdxReg();
176 : SwIndex* pIdx;
177 0 : for( sal_uInt16 i = 0; i < rTbl.size(); ++i )
178 : {
179 0 : SwRedline* pRedl = rTbl[ i ];
180 0 : if( pIReg == (pIdx = &pRedl->End()->nContent)->GetIdxReg() &&
181 0 : nCntnt == pIdx->GetIndex() )
182 : {
183 0 : if( !pRedl->HasMark() || !pRedlData ||
184 0 : *pRedl != *pRedlData || *pRedl != aRData )
185 : {
186 0 : bRet = sal_False;
187 0 : break;
188 : }
189 : }
190 0 : }
191 : }
192 : }
193 : }
194 47 : return bRet;
195 : }
196 :
197 10872 : SwUndoInsert::~SwUndoInsert()
198 : {
199 3624 : if (m_pUndoNodeIndex) // delete the section from UndoNodes array
200 : {
201 : // Insert saves the content in IconSection
202 0 : SwNodes& rUNds = m_pUndoNodeIndex->GetNodes();
203 0 : rUNds.Delete(*m_pUndoNodeIndex,
204 0 : rUNds.GetEndOfExtras().GetIndex() - m_pUndoNodeIndex->GetIndex());
205 0 : m_pUndoNodeIndex.reset();
206 : }
207 3624 : else if( pTxt ) // the inserted text
208 2 : delete pTxt;
209 3624 : delete pRedlData;
210 3624 : delete pUndoTxt;
211 7248 : }
212 :
213 3 : void SwUndoInsert::UndoImpl(::sw::UndoRedoContext & rContext)
214 : {
215 3 : SwDoc *const pTmpDoc = & rContext.GetDoc();
216 3 : SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
217 :
218 3 : if( bIsAppend )
219 : {
220 0 : pPam->GetPoint()->nNode = nNode;
221 :
222 0 : if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
223 : {
224 0 : pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
225 0 : pPam->SetMark();
226 0 : pPam->Move( fnMoveBackward );
227 0 : pPam->Exchange();
228 0 : pTmpDoc->DeleteRedline( *pPam, true, USHRT_MAX );
229 : }
230 0 : pPam->DeleteMark();
231 0 : pTmpDoc->DelFullPara( *pPam );
232 0 : pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
233 : }
234 : else
235 : {
236 3 : sal_uLong nNd = nNode;
237 3 : xub_StrLen nCnt = nCntnt;
238 3 : if( nLen )
239 : {
240 3 : SwNodeIndex aNd( pTmpDoc->GetNodes(), nNode);
241 3 : SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
242 6 : SwPaM aPaM( *pCNd, nCntnt );
243 :
244 3 : aPaM.SetMark();
245 :
246 3 : SwTxtNode * const pTxtNode( pCNd->GetTxtNode() );
247 3 : if ( pTxtNode )
248 : {
249 3 : aPaM.GetPoint()->nContent -= nLen;
250 3 : if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
251 0 : pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
252 3 : if (m_bWithRsid)
253 : {
254 : // RSID was added: remove any CHARFMT/AUTOFMT that may be
255 : // set on the deleted text; EraseText will leave empty
256 : // ones behind otherwise
257 : pTxtNode->DeleteAttributes(RES_TXTATR_AUTOFMT,
258 0 : aPaM.GetPoint()->nContent.GetIndex(),
259 0 : aPaM.GetMark()->nContent.GetIndex());
260 : pTxtNode->DeleteAttributes(RES_TXTATR_CHARFMT,
261 0 : aPaM.GetPoint()->nContent.GetIndex(),
262 0 : aPaM.GetMark()->nContent.GetIndex());
263 : }
264 3 : RemoveIdxFromRange( aPaM, sal_False );
265 3 : pTxt = new String( pTxtNode->GetTxt().copy(nCntnt-nLen, nLen) );
266 3 : pTxtNode->EraseText( aPaM.GetPoint()->nContent, nLen );
267 :
268 : // Undo deletes fieldmarks in two step: first the end then the start position.
269 : // Once the start position is deleted, make sure the fieldmark itself is deleted as well.
270 3 : if (nLen == 1)
271 : {
272 0 : IDocumentMarkAccess* const pMarkAccess = pTmpDoc->getIDocumentMarkAccess();
273 0 : for ( IDocumentMarkAccess::const_iterator_t i = pMarkAccess->getMarksBegin(); i != pMarkAccess->getMarksEnd(); ++i)
274 : {
275 0 : sw::mark::IMark* pMark = i->get();
276 0 : if (pMark->GetMarkStart() == *aPaM.GetPoint() && pMark->GetMarkStart().nContent == aPaM.GetPoint()->nContent)
277 : {
278 0 : sw::mark::IFieldmark* pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(pMark);
279 0 : if (pFieldmark && pFieldmark->GetFieldname() == ODF_COMMENTRANGE)
280 : {
281 0 : pTmpDoc->getIDocumentMarkAccess()->deleteMark(pMark);
282 0 : break;
283 : }
284 : }
285 : }
286 : }
287 : }
288 : else // otherwise Graphics/OLE/Text/...
289 : {
290 0 : aPaM.Move(fnMoveBackward);
291 0 : if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
292 0 : pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
293 0 : RemoveIdxFromRange( aPaM, sal_False );
294 : }
295 :
296 3 : nNd = aPaM.GetPoint()->nNode.GetIndex();
297 3 : nCnt = aPaM.GetPoint()->nContent.GetIndex();
298 :
299 3 : if( !pTxt )
300 : {
301 : m_pUndoNodeIndex.reset(
302 0 : new SwNodeIndex(pDoc->GetNodes().GetEndOfContent()));
303 0 : MoveToUndoNds(aPaM, m_pUndoNodeIndex.get());
304 : }
305 3 : nNode = aPaM.GetPoint()->nNode.GetIndex();
306 6 : nCntnt = aPaM.GetPoint()->nContent.GetIndex();
307 : }
308 :
309 : // set cursor to Undo range
310 3 : pPam->DeleteMark();
311 :
312 3 : pPam->GetPoint()->nNode = nNd;
313 3 : pPam->GetPoint()->nContent.Assign(
314 6 : pPam->GetPoint()->nNode.GetNode().GetCntntNode(), nCnt );
315 : }
316 :
317 3 : DELETEZ(pUndoTxt);
318 3 : }
319 :
320 :
321 1 : void SwUndoInsert::RedoImpl(::sw::UndoRedoContext & rContext)
322 : {
323 1 : SwDoc *const pTmpDoc = & rContext.GetDoc();
324 1 : SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
325 1 : pPam->DeleteMark();
326 :
327 1 : if( bIsAppend )
328 : {
329 0 : pPam->GetPoint()->nNode = nNode - 1;
330 0 : pTmpDoc->AppendTxtNode( *pPam->GetPoint() );
331 :
332 0 : pPam->SetMark();
333 0 : pPam->Move( fnMoveBackward );
334 0 : pPam->Exchange();
335 :
336 0 : if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
337 : {
338 0 : RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
339 0 : pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
340 0 : pTmpDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
341 0 : pTmpDoc->SetRedlineMode_intern( eOld );
342 : }
343 0 : else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
344 0 : !pTmpDoc->GetRedlineTbl().empty() )
345 0 : pTmpDoc->SplitRedline( *pPam );
346 :
347 0 : pPam->DeleteMark();
348 : }
349 : else
350 : {
351 1 : pPam->GetPoint()->nNode = nNode;
352 : SwCntntNode *const pCNd =
353 1 : pPam->GetPoint()->nNode.GetNode().GetCntntNode();
354 1 : pPam->GetPoint()->nContent.Assign( pCNd, nCntnt );
355 :
356 1 : if( nLen )
357 : {
358 1 : sal_Bool bMvBkwrd = MovePtBackward( *pPam );
359 :
360 1 : if( pTxt )
361 : {
362 1 : SwTxtNode *const pTxtNode = pCNd->GetTxtNode();
363 : OSL_ENSURE( pTxtNode, "where is my textnode ?" );
364 : OUString const ins(
365 1 : pTxtNode->InsertText( *pTxt, pPam->GetMark()->nContent,
366 2 : m_nInsertFlags) );
367 : assert(ins.getLength() == pTxt->Len()); // must succeed
368 1 : DELETEZ( pTxt );
369 1 : if (m_bWithRsid) // re-insert RSID
370 : {
371 0 : SwPaM pam(*pPam->GetMark(), 0); // mark -> point
372 0 : pTmpDoc->UpdateRsid(pam, ins.getLength());
373 1 : }
374 : }
375 : else
376 : {
377 : // re-insert content again (first detach m_pUndoNodeIndex!)
378 0 : sal_uLong const nMvNd = m_pUndoNodeIndex->GetIndex();
379 0 : m_pUndoNodeIndex.reset();
380 0 : MoveFromUndoNds(*pTmpDoc, nMvNd, *pPam->GetMark());
381 : }
382 1 : nNode = pPam->GetMark()->nNode.GetIndex();
383 1 : nCntnt = pPam->GetMark()->nContent.GetIndex();
384 :
385 1 : MovePtForward( *pPam, bMvBkwrd );
386 1 : pPam->Exchange();
387 1 : if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
388 : {
389 0 : RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
390 0 : pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
391 : pTmpDoc->AppendRedline( new SwRedline( *pRedlData,
392 0 : *pPam ), true);
393 0 : pTmpDoc->SetRedlineMode_intern( eOld );
394 : }
395 2 : else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
396 1 : !pTmpDoc->GetRedlineTbl().empty() )
397 0 : pTmpDoc->SplitRedline(*pPam);
398 : }
399 : }
400 :
401 1 : pUndoTxt = GetTxtFromDoc();
402 1 : }
403 :
404 0 : void SwUndoInsert::RepeatImpl(::sw::RepeatContext & rContext)
405 : {
406 0 : if( !nLen )
407 0 : return;
408 :
409 0 : SwDoc & rDoc = rContext.GetDoc();
410 0 : SwNodeIndex aNd( rDoc.GetNodes(), nNode );
411 0 : SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
412 :
413 0 : if( !bIsAppend && 1 == nLen ) // >1 than always Text, otherwise Graphics/OLE/Text/...
414 : {
415 0 : SwPaM aPaM( *pCNd, nCntnt );
416 0 : aPaM.SetMark();
417 0 : aPaM.Move(fnMoveBackward);
418 0 : pCNd = aPaM.GetCntntNode();
419 : }
420 :
421 : // What happens with the possible selected range ???
422 :
423 0 : switch( pCNd->GetNodeType() )
424 : {
425 : case ND_TEXTNODE:
426 0 : if( bIsAppend )
427 : {
428 0 : rDoc.AppendTxtNode( *rContext.GetRepeatPaM().GetPoint() );
429 : }
430 : else
431 : {
432 0 : OUString const aTxt( static_cast<SwTxtNode*>(pCNd)->GetTxt() );
433 0 : ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
434 0 : rDoc.InsertString( rContext.GetRepeatPaM(),
435 0 : aTxt.copy(nCntnt - nLen, nLen) );
436 : }
437 0 : break;
438 : case ND_GRFNODE:
439 : {
440 0 : SwGrfNode* pGrfNd = (SwGrfNode*)pCNd;
441 0 : String sFile, sFilter;
442 0 : if( pGrfNd->IsGrfLink() )
443 0 : pGrfNd->GetFileFilterNms( &sFile, &sFilter );
444 :
445 0 : rDoc.Insert( rContext.GetRepeatPaM(), sFile, sFilter,
446 0 : &pGrfNd->GetGrf(),
447 0 : 0/* Graphics collection*/, NULL, NULL );
448 : }
449 0 : break;
450 :
451 : case ND_OLENODE:
452 : {
453 : // StarView does not yet provide an option to copy a StarOBJ
454 0 : SvStorageRef aRef = new SvStorage( aEmptyStr );
455 0 : SwOLEObj& rSwOLE = (SwOLEObj&)((SwOLENode*)pCNd)->GetOLEObj();
456 :
457 : // temporary storage until object is inserted
458 : // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing!
459 : // TODO/LATER: Copying through the container would copy the replacement image as well
460 0 : comphelper::EmbeddedObjectContainer aCnt;
461 0 : OUString aName = aCnt.CreateUniqueObjectName();
462 0 : if ( aCnt.StoreEmbeddedObject( rSwOLE.GetOleRef(), aName, sal_True ) )
463 : {
464 0 : uno::Reference < embed::XEmbeddedObject > aNew = aCnt.GetEmbeddedObject( aName );
465 0 : rDoc.Insert( rContext.GetRepeatPaM(),
466 : svt::EmbeddedObjectRef( aNew,
467 : static_cast<SwOLENode*>(pCNd)->GetAspect() ),
468 0 : NULL, NULL, NULL );
469 : }
470 :
471 0 : break;
472 : }
473 0 : }
474 : }
475 :
476 : // #111827#
477 3635 : SwRewriter SwUndoInsert::GetRewriter() const
478 : {
479 3635 : SwRewriter aResult;
480 3635 : String * pStr = NULL;
481 3635 : bool bDone = false;
482 :
483 3635 : if (pTxt)
484 0 : pStr = pTxt;
485 3635 : else if (pUndoTxt)
486 3635 : pStr = pUndoTxt;
487 :
488 3635 : if (pStr)
489 : {
490 : String aString = ShortenString(DenoteSpecialCharacters(*pStr),
491 : nUndoStringLength,
492 3635 : String(SW_RES(STR_LDOTS)));
493 :
494 3635 : aResult.AddRule(UndoArg1, aString);
495 :
496 3635 : bDone = true;
497 : }
498 :
499 3635 : if ( ! bDone )
500 : {
501 0 : aResult.AddRule(UndoArg1, String("??", RTL_TEXTENCODING_ASCII_US));
502 : }
503 :
504 3635 : return aResult;
505 : }
506 :
507 :
508 : // SwUndoReplace /////////////////////////////////////////////////////////
509 :
510 :
511 : class SwUndoReplace::Impl
512 : : private SwUndoSaveCntnt
513 : {
514 : OUString m_sOld;
515 : OUString m_sIns;
516 : sal_uLong m_nSttNd, m_nEndNd, m_nOffset;
517 : xub_StrLen m_nSttCnt, m_nEndCnt, m_nSetPos, m_nSelEnd;
518 : bool m_bSplitNext : 1;
519 : bool m_bRegExp : 1;
520 : // metadata references for paragraph and following para (if m_bSplitNext)
521 : ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
522 : ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
523 :
524 : public:
525 : Impl(SwPaM const& rPam, OUString const& rIns, bool const bRegExp);
526 88 : virtual ~Impl()
527 44 : {
528 88 : }
529 :
530 : virtual void UndoImpl( ::sw::UndoRedoContext & );
531 : virtual void RedoImpl( ::sw::UndoRedoContext & );
532 :
533 : void SetEnd(SwPaM const& rPam);
534 :
535 44 : OUString const& GetOld() const { return m_sOld; }
536 44 : OUString const& GetIns() const { return m_sIns; }
537 : };
538 :
539 :
540 44 : SwUndoReplace::SwUndoReplace(SwPaM const& rPam,
541 : OUString const& rIns, bool const bRegExp)
542 : : SwUndo( UNDO_REPLACE )
543 44 : , m_pImpl(new Impl(rPam, rIns, bRegExp))
544 : {
545 44 : }
546 :
547 88 : SwUndoReplace::~SwUndoReplace()
548 : {
549 88 : }
550 :
551 0 : void SwUndoReplace::UndoImpl(::sw::UndoRedoContext & rContext)
552 : {
553 0 : m_pImpl->UndoImpl(rContext);
554 0 : }
555 :
556 0 : void SwUndoReplace::RedoImpl(::sw::UndoRedoContext & rContext)
557 : {
558 0 : m_pImpl->RedoImpl(rContext);
559 0 : }
560 :
561 : SwRewriter
562 46 : MakeUndoReplaceRewriter(sal_uLong const occurrences,
563 : OUString const& sOld, OUString const& sNew)
564 : {
565 46 : SwRewriter aResult;
566 :
567 46 : if (1 < occurrences)
568 : {
569 2 : aResult.AddRule(UndoArg1, OUString::number(occurrences));
570 2 : aResult.AddRule(UndoArg2, String(SW_RES(STR_OCCURRENCES_OF)));
571 :
572 2 : String aTmpStr;
573 2 : aTmpStr += String(SW_RES(STR_START_QUOTE));
574 4 : aTmpStr += ShortenString(sOld, nUndoStringLength,
575 2 : SW_RES(STR_LDOTS));
576 2 : aTmpStr += String(SW_RES(STR_END_QUOTE));
577 2 : aResult.AddRule(UndoArg3, aTmpStr);
578 : }
579 44 : else if (1 == occurrences)
580 : {
581 : {
582 44 : String aTmpStr;
583 :
584 44 : aTmpStr += String(SW_RES(STR_START_QUOTE));
585 : // #i33488 #
586 88 : aTmpStr += ShortenString(sOld, nUndoStringLength,
587 44 : SW_RES(STR_LDOTS));
588 44 : aTmpStr += String(SW_RES(STR_END_QUOTE));
589 44 : aResult.AddRule(UndoArg1, aTmpStr);
590 : }
591 :
592 44 : aResult.AddRule(UndoArg2, String(SW_RES(STR_YIELDS)));
593 :
594 : {
595 44 : String aTmpStr;
596 :
597 44 : aTmpStr += String(SW_RES(STR_START_QUOTE));
598 : // #i33488 #
599 88 : aTmpStr += ShortenString(sNew, nUndoStringLength,
600 44 : SW_RES(STR_LDOTS));
601 44 : aTmpStr += String(SW_RES(STR_END_QUOTE));
602 44 : aResult.AddRule(UndoArg3, aTmpStr);
603 : }
604 : }
605 :
606 46 : return aResult;
607 : }
608 :
609 : // #111827#
610 44 : SwRewriter SwUndoReplace::GetRewriter() const
611 : {
612 44 : return MakeUndoReplaceRewriter(1, m_pImpl->GetOld(), m_pImpl->GetIns());
613 : }
614 :
615 44 : void SwUndoReplace::SetEnd(SwPaM const& rPam)
616 : {
617 44 : m_pImpl->SetEnd(rPam);
618 44 : }
619 :
620 44 : SwUndoReplace::Impl::Impl(
621 : SwPaM const& rPam, OUString const& rIns, bool const bRegExp)
622 : : m_sIns( rIns )
623 : , m_nOffset( 0 )
624 44 : , m_bRegExp(bRegExp)
625 : {
626 :
627 44 : const SwPosition * pStt( rPam.Start() );
628 44 : const SwPosition * pEnd( rPam.End() );
629 :
630 44 : m_nSttNd = m_nEndNd = pStt->nNode.GetIndex();
631 44 : m_nSttCnt = pStt->nContent.GetIndex();
632 44 : m_nSelEnd = m_nEndCnt = pEnd->nContent.GetIndex();
633 :
634 44 : m_bSplitNext = m_nSttNd != pEnd->nNode.GetIndex();
635 :
636 44 : SwTxtNode* pNd = pStt->nNode.GetNode().GetTxtNode();
637 : OSL_ENSURE( pNd, "Dude, where's my TextNode?" );
638 :
639 44 : pHistory = new SwHistory;
640 44 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
641 :
642 44 : m_nSetPos = pHistory->Count();
643 :
644 44 : sal_uLong nNewPos = pStt->nNode.GetIndex();
645 44 : m_nOffset = m_nSttNd - nNewPos;
646 :
647 44 : if ( pNd->GetpSwpHints() )
648 : {
649 : pHistory->CopyAttr( pNd->GetpSwpHints(), nNewPos, 0,
650 0 : pNd->GetTxt().getLength(), true );
651 : }
652 :
653 44 : if ( m_bSplitNext )
654 : {
655 0 : if( pNd->HasSwAttrSet() )
656 0 : pHistory->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNewPos );
657 0 : pHistory->Add( pNd->GetTxtColl(), nNewPos, ND_TEXTNODE );
658 :
659 0 : SwTxtNode* pNext = pEnd->nNode.GetNode().GetTxtNode();
660 0 : sal_uLong nTmp = pNext->GetIndex();
661 : pHistory->CopyAttr( pNext->GetpSwpHints(), nTmp, 0,
662 0 : pNext->GetTxt().getLength(), true );
663 0 : if( pNext->HasSwAttrSet() )
664 0 : pHistory->CopyFmtAttr( *pNext->GetpSwAttrSet(), nTmp );
665 0 : pHistory->Add( pNext->GetTxtColl(),nTmp, ND_TEXTNODE );
666 : // METADATA: store
667 0 : m_pMetadataUndoStart = pNd ->CreateUndo();
668 0 : m_pMetadataUndoEnd = pNext->CreateUndo();
669 : }
670 :
671 44 : if( !pHistory->Count() )
672 22 : delete pHistory, pHistory = 0;
673 :
674 0 : xub_StrLen nECnt = m_bSplitNext ? pNd->GetTxt().getLength()
675 44 : : pEnd->nContent.GetIndex();
676 44 : m_sOld = pNd->GetTxt().copy( m_nSttCnt, nECnt - m_nSttCnt );
677 44 : }
678 :
679 0 : void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext & rContext)
680 : {
681 0 : SwDoc *const pDoc = & rContext.GetDoc();
682 0 : SwPaM & rPam(rContext.GetCursorSupplier().CreateNewShellCursor());
683 0 : rPam.DeleteMark();
684 :
685 0 : SwTxtNode* pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
686 : OSL_ENSURE( pNd, "Dude, where's my TextNode?" );
687 :
688 0 : SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord();
689 0 : if( pACEWord )
690 : {
691 0 : if ((1 == m_sIns.getLength()) && (1 == m_sOld.getLength()))
692 : {
693 0 : SwPosition aPos( *pNd ); aPos.nContent.Assign( pNd, m_nSttCnt );
694 0 : pACEWord->CheckChar( aPos, m_sOld[ 0 ] );
695 : }
696 0 : pDoc->SetAutoCorrExceptWord( 0 );
697 : }
698 :
699 0 : SwIndex aIdx( pNd, m_nSttCnt );
700 : // don't look at m_sIns for deletion, maybe it was not completely inserted
701 : {
702 0 : rPam.GetPoint()->nNode = *pNd;
703 0 : rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
704 0 : rPam.SetMark();
705 0 : rPam.GetPoint()->nNode = m_nEndNd - m_nOffset;
706 0 : rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), m_nEndCnt );
707 : // move it out of the way so it is not registered at deleted node
708 0 : aIdx.Assign(0, 0);
709 :
710 0 : pDoc->DeleteAndJoin( rPam );
711 0 : rPam.DeleteMark();
712 0 : pNd = rPam.GetNode()->GetTxtNode();
713 : OSL_ENSURE( pNd, "Dude, where's my TextNode?" );
714 0 : aIdx.Assign( pNd, m_nSttCnt );
715 : }
716 :
717 0 : if( m_bSplitNext )
718 : {
719 0 : SwPosition aPos( *pNd, aIdx );
720 0 : pDoc->SplitNode( aPos, false );
721 0 : pNd->RestoreMetadata(m_pMetadataUndoEnd);
722 0 : pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
723 0 : aIdx.Assign( pNd, m_nSttCnt );
724 : // METADATA: restore
725 0 : pNd->RestoreMetadata(m_pMetadataUndoStart);
726 : }
727 :
728 0 : if (!m_sOld.isEmpty())
729 : {
730 0 : OUString const ins( pNd->InsertText( m_sOld, aIdx ) );
731 0 : assert(ins.getLength() == m_sOld.getLength()); // must succeed
732 : }
733 :
734 0 : if( pHistory )
735 : {
736 0 : if( pNd->GetpSwpHints() )
737 0 : pNd->ClearSwpHintsArr( true );
738 :
739 0 : pHistory->TmpRollback( pDoc, m_nSetPos, false );
740 0 : if ( m_nSetPos ) // there were footnotes/FlyFrames
741 : {
742 : // are there others than these?
743 0 : if( m_nSetPos < pHistory->Count() )
744 : {
745 : // than save those attributes as well
746 0 : SwHistory aHstr;
747 0 : aHstr.Move( 0, pHistory, m_nSetPos );
748 0 : pHistory->Rollback( pDoc );
749 0 : pHistory->Move( 0, &aHstr );
750 : }
751 : else
752 : {
753 0 : pHistory->Rollback( pDoc );
754 0 : DELETEZ( pHistory );
755 : }
756 : }
757 : }
758 :
759 0 : rPam.GetPoint()->nNode = m_nSttNd;
760 0 : rPam.GetPoint()->nContent = aIdx;
761 0 : }
762 :
763 0 : void SwUndoReplace::Impl::RedoImpl(::sw::UndoRedoContext & rContext)
764 : {
765 0 : SwDoc & rDoc = rContext.GetDoc();
766 0 : SwPaM & rPam(rContext.GetCursorSupplier().CreateNewShellCursor());
767 0 : rPam.DeleteMark();
768 0 : rPam.GetPoint()->nNode = m_nSttNd;
769 :
770 0 : SwTxtNode* pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
771 : OSL_ENSURE( pNd, "Dude, where's my TextNode?" );
772 0 : rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
773 0 : rPam.SetMark();
774 0 : if( m_bSplitNext )
775 : {
776 0 : rPam.GetPoint()->nNode = m_nSttNd + 1;
777 0 : pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
778 : }
779 0 : rPam.GetPoint()->nContent.Assign( pNd, m_nSelEnd );
780 :
781 0 : if( pHistory )
782 : {
783 0 : SwHistory* pSave = pHistory;
784 0 : SwHistory aHst;
785 0 : pHistory = &aHst;
786 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
787 0 : m_nSetPos = pHistory->Count();
788 :
789 0 : pHistory = pSave;
790 0 : pHistory->Move( 0, &aHst );
791 : }
792 : else
793 : {
794 0 : pHistory = new SwHistory;
795 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
796 0 : m_nSetPos = pHistory->Count();
797 0 : if( !m_nSetPos )
798 0 : delete pHistory, pHistory = 0;
799 : }
800 :
801 0 : rDoc.ReplaceRange( rPam, m_sIns, m_bRegExp );
802 0 : rPam.DeleteMark();
803 0 : }
804 :
805 44 : void SwUndoReplace::Impl::SetEnd(SwPaM const& rPam)
806 : {
807 44 : const SwPosition* pEnd = rPam.End();
808 44 : m_nEndNd = m_nOffset + pEnd->nNode.GetIndex();
809 44 : m_nEndCnt = pEnd->nContent.GetIndex();
810 44 : }
811 :
812 :
813 : // SwUndoReRead //////////////////////////////////////////////////////////
814 :
815 :
816 6 : SwUndoReRead::SwUndoReRead( const SwPaM& rPam, const SwGrfNode& rGrfNd )
817 6 : : SwUndo( UNDO_REREAD ), nPos( rPam.GetPoint()->nNode.GetIndex() )
818 : {
819 6 : SaveGraphicData( rGrfNd );
820 6 : }
821 :
822 :
823 18 : SwUndoReRead::~SwUndoReRead()
824 : {
825 6 : delete pGrf;
826 6 : delete pNm;
827 6 : delete pFltr;
828 12 : }
829 :
830 :
831 0 : void SwUndoReRead::SetAndSave(::sw::UndoRedoContext & rContext)
832 : {
833 0 : SwDoc & rDoc = rContext.GetDoc();
834 0 : SwGrfNode* pGrfNd = rDoc.GetNodes()[ nPos ]->GetGrfNode();
835 :
836 0 : if( !pGrfNd )
837 0 : return ;
838 :
839 : // cache the old values
840 0 : Graphic* pOldGrf = pGrf;
841 0 : String* pOldNm = pNm;
842 0 : String* pOldFltr = pFltr;
843 0 : sal_uInt16 nOldMirr = nMirr;
844 :
845 0 : SaveGraphicData( *pGrfNd );
846 0 : if( pOldNm )
847 : {
848 0 : pGrfNd->ReRead( *pOldNm, pFltr ? *pFltr : aEmptyStr, 0, 0, sal_True );
849 0 : delete pOldNm;
850 0 : delete pOldFltr;
851 : }
852 : else
853 : {
854 0 : pGrfNd->ReRead( aEmptyStr, aEmptyStr, pOldGrf, 0, sal_True );
855 0 : delete pOldGrf;
856 : }
857 :
858 0 : if( RES_MIRROR_GRAPH_DONT != nOldMirr )
859 0 : pGrfNd->SetAttr( SwMirrorGrf() );
860 :
861 0 : rContext.SetSelections(pGrfNd->GetFlyFmt(), 0);
862 : }
863 :
864 :
865 0 : void SwUndoReRead::UndoImpl(::sw::UndoRedoContext & rContext)
866 : {
867 0 : SetAndSave(rContext);
868 0 : }
869 :
870 :
871 0 : void SwUndoReRead::RedoImpl(::sw::UndoRedoContext & rContext)
872 : {
873 0 : SetAndSave(rContext);
874 0 : }
875 :
876 :
877 6 : void SwUndoReRead::SaveGraphicData( const SwGrfNode& rGrfNd )
878 : {
879 6 : if( rGrfNd.IsGrfLink() )
880 : {
881 2 : pNm = new String;
882 2 : pFltr = new String;
883 2 : rGrfNd.GetFileFilterNms( pNm, pFltr );
884 2 : pGrf = 0;
885 : }
886 : else
887 : {
888 4 : ((SwGrfNode&)rGrfNd).SwapIn( sal_True );
889 4 : pGrf = new Graphic( rGrfNd.GetGrf() );
890 4 : pNm = pFltr = 0;
891 : }
892 6 : nMirr = rGrfNd.GetSwAttrSet().GetMirrorGrf().GetValue();
893 6 : }
894 :
895 :
896 0 : SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp,
897 : const String &rTxt,
898 : const String& rSeparator,
899 : const String& rNumberSeparator,
900 : const sal_Bool bBef,
901 : const sal_uInt16 nInitId,
902 : const String& rCharacterStyle,
903 : const sal_Bool bCpyBorder )
904 : : SwUndo( UNDO_INSERTLABEL ),
905 : sText( rTxt ),
906 : sSeparator( rSeparator ),
907 : sNumberSeparator( rNumberSeparator ),//#i61007# order of captions
908 : sCharacterStyle( rCharacterStyle ),
909 : nFldId( nInitId ),
910 : eType( eTyp ),
911 : nLayerId( 0 ),
912 : bBefore( bBef ),
913 0 : bCpyBrd( bCpyBorder )
914 : {
915 0 : bUndoKeep = sal_False;
916 0 : OBJECT.pUndoFly = 0;
917 0 : OBJECT.pUndoAttr = 0;
918 0 : }
919 :
920 0 : SwUndoInsertLabel::~SwUndoInsertLabel()
921 : {
922 0 : if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
923 : {
924 0 : delete OBJECT.pUndoFly;
925 0 : delete OBJECT.pUndoAttr;
926 : }
927 : else
928 0 : delete NODE.pUndoInsNd;
929 0 : }
930 :
931 0 : void SwUndoInsertLabel::UndoImpl(::sw::UndoRedoContext & rContext)
932 : {
933 0 : SwDoc & rDoc = rContext.GetDoc();
934 :
935 0 : if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
936 : {
937 : OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer not initialized" );
938 : SwFrmFmt* pFmt;
939 0 : SdrObject *pSdrObj = 0;
940 0 : if( OBJECT.pUndoAttr &&
941 0 : 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
942 0 : ( LTYPE_DRAW != eType ||
943 : 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
944 : {
945 0 : OBJECT.pUndoAttr->UndoImpl(rContext);
946 0 : OBJECT.pUndoFly->UndoImpl(rContext);
947 0 : if( LTYPE_DRAW == eType )
948 : {
949 0 : pSdrObj->SetLayer( nLayerId );
950 : }
951 0 : }
952 : }
953 0 : else if( NODE.nNode )
954 : {
955 0 : if ( eType == LTYPE_TABLE && bUndoKeep )
956 : {
957 0 : SwTableNode *pNd = rDoc.GetNodes()[
958 0 : rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
959 0 : if ( pNd )
960 0 : pNd->GetTable().GetFrmFmt()->ResetFmtAttr( RES_KEEP );
961 : }
962 0 : SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
963 0 : aPam.GetPoint()->nNode = NODE.nNode;
964 0 : aPam.SetMark();
965 0 : aPam.GetPoint()->nNode = NODE.nNode + 1;
966 0 : NODE.pUndoInsNd = new SwUndoDelete( aPam, sal_True );
967 : }
968 0 : }
969 :
970 :
971 0 : void SwUndoInsertLabel::RedoImpl(::sw::UndoRedoContext & rContext)
972 : {
973 0 : SwDoc & rDoc = rContext.GetDoc();
974 :
975 0 : if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
976 : {
977 : OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer not initialized" );
978 : SwFrmFmt* pFmt;
979 0 : SdrObject *pSdrObj = 0;
980 0 : if( OBJECT.pUndoAttr &&
981 0 : 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
982 0 : ( LTYPE_DRAW != eType ||
983 : 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
984 : {
985 0 : OBJECT.pUndoFly->RedoImpl(rContext);
986 0 : OBJECT.pUndoAttr->RedoImpl(rContext);
987 0 : if( LTYPE_DRAW == eType )
988 : {
989 0 : pSdrObj->SetLayer( nLayerId );
990 0 : if( pSdrObj->GetLayer() == rDoc.GetHellId() )
991 0 : pSdrObj->SetLayer( rDoc.GetHeavenId() );
992 : // OD 02.07.2003 #108784#
993 0 : else if( pSdrObj->GetLayer() == rDoc.GetInvisibleHellId() )
994 0 : pSdrObj->SetLayer( rDoc.GetInvisibleHeavenId() );
995 : }
996 0 : }
997 : }
998 0 : else if( NODE.pUndoInsNd )
999 : {
1000 0 : if ( eType == LTYPE_TABLE && bUndoKeep )
1001 : {
1002 0 : SwTableNode *pNd = rDoc.GetNodes()[
1003 0 : rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
1004 0 : if ( pNd )
1005 0 : pNd->GetTable().GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem(sal_True, RES_KEEP) );
1006 : }
1007 0 : NODE.pUndoInsNd->UndoImpl(rContext);
1008 0 : delete NODE.pUndoInsNd, NODE.pUndoInsNd = 0;
1009 : }
1010 0 : }
1011 :
1012 0 : void SwUndoInsertLabel::RepeatImpl(::sw::RepeatContext & rContext)
1013 : {
1014 0 : SwDoc & rDoc = rContext.GetDoc();
1015 0 : const SwPosition& rPos = *rContext.GetRepeatPaM().GetPoint();
1016 :
1017 0 : sal_uLong nIdx = 0;
1018 :
1019 0 : SwCntntNode* pCNd = rPos.nNode.GetNode().GetCntntNode();
1020 0 : if( pCNd )
1021 0 : switch( eType )
1022 : {
1023 : case LTYPE_TABLE:
1024 : {
1025 0 : const SwTableNode* pTNd = pCNd->FindTableNode();
1026 0 : if( pTNd )
1027 0 : nIdx = pTNd->GetIndex();
1028 : }
1029 0 : break;
1030 :
1031 : case LTYPE_FLY:
1032 : case LTYPE_OBJECT:
1033 : {
1034 : SwFlyFrm* pFly;
1035 0 : SwCntntFrm *pCnt = pCNd->getLayoutFrm( rDoc.GetCurrentLayout() );
1036 0 : if( pCnt && 0 != ( pFly = pCnt->FindFlyFrm() ) )
1037 0 : nIdx = pFly->GetFmt()->GetCntnt().GetCntntIdx()->GetIndex();
1038 : }
1039 0 : break;
1040 : case LTYPE_DRAW:
1041 0 : break;
1042 : }
1043 :
1044 0 : if( nIdx )
1045 : {
1046 : rDoc.InsertLabel( eType, sText, sSeparator, sNumberSeparator, bBefore,
1047 0 : nFldId, nIdx, sCharacterStyle, bCpyBrd );
1048 : }
1049 0 : }
1050 :
1051 : // #111827#
1052 0 : SwRewriter SwUndoInsertLabel::GetRewriter() const
1053 : {
1054 0 : SwRewriter aRewriter;
1055 :
1056 0 : String aTmpStr;
1057 :
1058 0 : aTmpStr += String(SW_RES(STR_START_QUOTE));
1059 0 : aTmpStr += ShortenString(sText, nUndoStringLength,
1060 0 : String(SW_RES(STR_LDOTS)));
1061 0 : aTmpStr += String(SW_RES(STR_END_QUOTE));
1062 :
1063 0 : aRewriter.AddRule(UndoArg1, aTmpStr);
1064 :
1065 0 : return aRewriter;
1066 : }
1067 :
1068 0 : void SwUndoInsertLabel::SetFlys( SwFrmFmt& rOldFly, SfxItemSet& rChgSet,
1069 : SwFrmFmt& rNewFly )
1070 : {
1071 0 : if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
1072 : {
1073 0 : SwUndoFmtAttrHelper aTmp( rOldFly, false );
1074 0 : rOldFly.SetFmtAttr( rChgSet );
1075 0 : if ( aTmp.GetUndo() )
1076 : {
1077 0 : OBJECT.pUndoAttr = aTmp.ReleaseUndo();
1078 : }
1079 0 : OBJECT.pUndoFly = new SwUndoInsLayFmt( &rNewFly,0,0 );
1080 : }
1081 0 : }
1082 :
1083 0 : void SwUndoInsertLabel::SetDrawObj( sal_uInt8 nLId )
1084 : {
1085 0 : if( LTYPE_DRAW == eType )
1086 : {
1087 0 : nLayerId = nLId;
1088 : }
1089 99 : }
1090 :
1091 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|