update dev300-m58
[ooovba.git] / sw / source / core / undo / unins.cxx
blob9362785ce3703f5e696acf041bb22b4833a3bb4f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unins.cxx,v $
10 * $Revision: 1.33 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
34 #include <unotools/charclass.hxx>
35 #include <sot/storage.hxx>
36 #include <svx/keepitem.hxx>
37 #include <svx/svdobj.hxx>
39 #include <docsh.hxx>
40 #include <fmtcntnt.hxx>
41 #include <fmtanchr.hxx>
42 #include <frmfmt.hxx>
43 #include <doc.hxx>
44 #include <swundo.hxx> // fuer die UndoIds
45 #include <pam.hxx>
46 #include <ndtxt.hxx>
47 #include <undobj.hxx>
48 #include <rolbck.hxx>
49 #include <ndgrf.hxx>
50 #include <ndole.hxx>
51 #include <grfatr.hxx>
52 #include <cntfrm.hxx>
53 #include <flyfrm.hxx>
54 #include <fesh.hxx>
55 #include <swtable.hxx>
56 #include <redline.hxx>
57 #include <docary.hxx>
58 #include <acorrect.hxx>
59 #include <dcontact.hxx>
61 #include <comcore.hrc> // #111827#
62 #include <undo.hrc>
64 using namespace ::com::sun::star;
67 class _UnReplaceData : private SwUndoSaveCntnt
69 String m_sOld, m_sIns;
70 ULONG m_nSttNd, m_nEndNd, m_nOffset;
71 xub_StrLen m_nSttCnt, m_nEndCnt, m_nSetPos, m_nSelEnd;
72 BOOL m_bSplitNext : 1;
73 BOOL m_bRegExp : 1;
74 // metadata references for paragraph and following para (if m_bSplitNext)
75 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
76 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
78 public:
79 _UnReplaceData( const SwPaM& rPam, const String& rIns, BOOL bRegExp );
80 ~_UnReplaceData();
82 void Undo( SwUndoIter& rIter );
83 void Redo( SwUndoIter& rIter );
84 void SetEnd( const SwPaM& rPam );
86 const String & GetOld() const { return m_sOld; }
87 const String & GetIns() const { return m_sIns; }
91 SV_IMPL_PTRARR( _UnReplaceDatas, _UnReplaceData* )
93 //------------------------------------------------------------------
95 inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
97 // zwei Zugriffs-Funktionen
98 inline SwPosition* IterPt( SwUndoIter& rUIter )
99 { return rUIter.pAktPam->GetPoint(); }
100 inline SwPosition* IterMk( SwUndoIter& rUIter )
101 { return rUIter.pAktPam->GetMark(); }
103 //------------------------------------------------------------
105 // INSERT
107 String * SwUndoInsert::GetTxtFromDoc() const
109 String * pResult = NULL;
111 SwNodeIndex aNd( pDoc->GetNodes(), nNode);
112 SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
113 SwPaM aPaM( *pCNd, nCntnt );
115 aPaM.SetMark();
117 if( pCNd->IsTxtNode() )
119 pResult = new String( ((SwTxtNode*)pCNd)->GetTxt().Copy(nCntnt-nLen,
120 nLen ) );
124 return pResult;
127 void SwUndoInsert::Init(const SwNodeIndex & rNd)
129 // Redline beachten
130 pDoc = rNd.GetNode().GetDoc();
131 if( pDoc->IsRedlineOn() )
133 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
134 pDoc->GetRedlineAuthor() );
135 SetRedlineMode( pDoc->GetRedlineMode() );
138 pUndoTxt = GetTxtFromDoc();
140 bCacheComment = false;
143 // #111827#
144 SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd, xub_StrLen nCnt,
145 xub_StrLen nL, BOOL bWDelim )
146 : SwUndo(UNDO_TYPING), pPos( 0 ), pTxt( 0 ), pRedlData( 0 ),
147 nNode( rNd.GetIndex() ), nCntnt(nCnt), nLen(nL),
148 bIsWordDelim( bWDelim ), bIsAppend( FALSE )
150 Init(rNd);
153 // #111827#
154 SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd )
155 : SwUndo(UNDO_SPLITNODE), pPos( 0 ), pTxt( 0 ),
156 pRedlData( 0 ), nNode( rNd.GetIndex() ), nCntnt(0), nLen(1),
157 bIsWordDelim( FALSE ), bIsAppend( TRUE )
159 Init(rNd);
162 // stelle fest, ob das naechste Insert mit dem aktuellen zusammengefasst
163 // werden kann. Wenn ja, dann aender die Laenge und die InsPos.
164 // Dann wird von SwDoc::Insert kein neues Object in die Undoliste gestellt.
166 BOOL SwUndoInsert::CanGrouping( const SwPosition& rInsPos, sal_Unicode cIns )
168 BOOL bRet = FALSE;
169 if( !bIsAppend )
171 ++nCntnt;
172 bRet = CanGrouping( rInsPos );
173 --nCntnt;
174 if( bRet )
175 bRet = CanGrouping( cIns );
177 return bRet;
181 BOOL SwUndoInsert::CanGrouping( sal_Unicode cIns )
183 if( !bIsAppend && bIsWordDelim ==
184 !GetAppCharClass().isLetterNumeric( String( cIns )) )
186 nLen++;
187 nCntnt++;
189 if (pUndoTxt)
190 pUndoTxt->Insert(cIns);
192 return TRUE;
194 return FALSE;
197 BOOL SwUndoInsert::CanGrouping( const SwPosition& rPos )
199 BOOL bRet = FALSE;
200 if( nNode == rPos.nNode.GetIndex() &&
201 nCntnt == rPos.nContent.GetIndex() )
203 // Redline beachten
204 SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
205 if( ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & rDoc.GetRedlineMode() ) ==
206 ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & GetRedlineMode() ) )
208 bRet = TRUE;
210 // dann war oder ist noch Redline an:
211 // pruefe, ob an der InsPosition ein anderer Redline
212 // rumsteht. Wenn der gleiche nur einmalig vorhanden ist,
213 // kann zusammen gefasst werden.
214 const SwRedlineTbl& rTbl = rDoc.GetRedlineTbl();
215 if( rTbl.Count() )
217 SwRedlineData aRData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
218 const SwIndexReg* pIReg = rPos.nContent.GetIdxReg();
219 SwIndex* pIdx;
220 for( USHORT i = 0; i < rTbl.Count(); ++i )
222 SwRedline* pRedl = rTbl[ i ];
223 if( pIReg == (pIdx = &pRedl->End()->nContent)->GetIdxReg() &&
224 nCntnt == pIdx->GetIndex() )
226 if( !pRedl->HasMark() || !pRedlData ||
227 *pRedl != *pRedlData || *pRedl != aRData )
229 bRet = FALSE;
230 break;
237 return bRet;
240 SwUndoInsert::~SwUndoInsert()
242 if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array
244 // Insert speichert den Inhalt in der IconSection
245 SwNodes& rUNds = pPos->nNode.GetNode().GetNodes();
246 if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen
248 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
249 ASSERT( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
250 pTxtNd->Erase( pPos->nContent );
251 pPos->nNode++;
253 pPos->nContent.Assign( 0, 0 );
254 rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
255 pPos->nNode.GetIndex() );
256 delete pPos;
258 else if( pTxt ) // der eingefuegte Text
259 delete pTxt;
260 delete pRedlData;
265 void SwUndoInsert::Undo( SwUndoIter& rUndoIter )
267 SwDoc* pTmpDoc = &rUndoIter.GetDoc();
269 if( bIsAppend )
271 SwPaM* pPam = rUndoIter.pAktPam;
272 pPam->GetPoint()->nNode = nNode;
274 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
276 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
277 pPam->SetMark();
278 pPam->Move( fnMoveBackward );
279 pPam->Exchange();
280 pTmpDoc->DeleteRedline( *pPam, true, USHRT_MAX );
282 pPam->DeleteMark();
283 pTmpDoc->DelFullPara( *pPam );
284 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
286 else
288 ULONG nNd = nNode;
289 xub_StrLen nCnt = nCntnt;
290 if( nLen )
292 SwNodeIndex aNd( pTmpDoc->GetNodes(), nNode);
293 SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
294 SwPaM aPaM( *pCNd, nCntnt );
296 aPaM.SetMark();
298 if( pCNd->IsTxtNode() ) // Text !!
300 aPaM.GetPoint()->nContent -= nLen;
301 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
302 pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
303 RemoveIdxFromRange( aPaM, FALSE );
304 pTxt = new String( ((SwTxtNode*)pCNd)->GetTxt().Copy(
305 nCntnt-nLen, nLen ) );
306 ((SwTxtNode*)pCNd)->Erase( aPaM.GetPoint()->nContent, nLen );
308 else // ansonsten Grafik/OLE/Text/...
310 aPaM.Move(fnMoveBackward);
311 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
312 pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
313 RemoveIdxFromRange( aPaM, FALSE );
316 nNd = aPaM.GetPoint()->nNode.GetIndex();
317 nCnt = aPaM.GetPoint()->nContent.GetIndex();
319 if( !pTxt )
321 pPos = new SwPosition( *aPaM.GetPoint() );
322 MoveToUndoNds( aPaM, &pPos->nNode, &pPos->nContent );
324 nNode = aPaM.GetPoint()->nNode.GetIndex();
325 nCntnt = aPaM.GetPoint()->nContent.GetIndex();
328 // setze noch den Cursor auf den Undo-Bereich
329 rUndoIter.pAktPam->DeleteMark();
331 IterPt(rUndoIter)->nNode = nNd;
332 IterPt(rUndoIter)->nContent.Assign( pTmpDoc->GetNodes()[
333 IterPt(rUndoIter)->nNode ]->GetCntntNode(), nCnt );
334 // SPoint und GetMark auf der gleichen Position
337 DELETEZ(pUndoTxt);
341 void SwUndoInsert::Redo( SwUndoIter& rUndoIter )
343 // setze noch den Cursor auf den Redo-Bereich
344 SwPaM* pPam = rUndoIter.pAktPam;
345 SwDoc* pTmpDoc = pPam->GetDoc();
346 pPam->DeleteMark();
348 if( bIsAppend )
350 pPam->GetPoint()->nNode = nNode - 1;
351 pTmpDoc->AppendTxtNode( *pPam->GetPoint() );
353 pPam->SetMark();
354 pPam->Move( fnMoveBackward );
355 pPam->Exchange();
357 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
359 RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
360 pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
361 pTmpDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
362 pTmpDoc->SetRedlineMode_intern( eOld );
364 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
365 pTmpDoc->GetRedlineTbl().Count() )
366 pTmpDoc->SplitRedline( *pPam );
368 pPam->DeleteMark();
370 else
372 pPam->GetPoint()->nNode = nNode;
373 SwCntntNode* pCNd = pTmpDoc->GetNodes()[ pPam->GetPoint()->nNode ]->GetCntntNode();
374 pPam->GetPoint()->nContent.Assign( pCNd, nCntnt );
376 if( nLen )
378 BOOL bMvBkwrd = MovePtBackward( *pPam );
380 if( pTxt )
382 ASSERT( pCNd->IsTxtNode(), "wo ist mein Textnode ??" );
383 ((SwTxtNode*)pCNd)->Insert( *pTxt, pPam->GetMark()->nContent,
384 INS_EMPTYEXPAND );
385 DELETEZ( pTxt );
387 else
389 // Inhalt wieder einfuegen. (erst pPos abmelden !!)
390 ULONG nMvNd = pPos->nNode.GetIndex();
391 xub_StrLen nMvCnt = pPos->nContent.GetIndex();
392 DELETEZ( pPos );
393 MoveFromUndoNds( *pTmpDoc, nMvNd, nMvCnt, *pPam->GetMark() );
395 nNode = pPam->GetMark()->nNode.GetIndex();
396 nCntnt = pPam->GetMark()->nContent.GetIndex();
398 MovePtForward( *pPam, bMvBkwrd );
399 rUndoIter.pAktPam->Exchange();
400 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
402 RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
403 pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
404 pTmpDoc->AppendRedline( new SwRedline( *pRedlData,
405 *rUndoIter.pAktPam ), true);
406 pTmpDoc->SetRedlineMode_intern( eOld );
408 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
409 pTmpDoc->GetRedlineTbl().Count() )
410 pTmpDoc->SplitRedline( *rUndoIter.pAktPam );
414 pUndoTxt = GetTxtFromDoc();
418 void SwUndoInsert::Repeat( SwUndoIter& rUndoIter )
420 rUndoIter.pLastUndoObj = this;
421 if( !nLen )
422 return;
424 SwDoc& rDoc = rUndoIter.GetDoc();
425 SwNodeIndex aNd( rDoc.GetNodes(), nNode );
426 SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();;
428 if( !bIsAppend && 1 == nLen ) // >1 dann immer nur Text, ansonsten Grafik/OLE/Text/...
430 SwPaM aPaM( *pCNd, nCntnt );
431 aPaM.SetMark();
432 aPaM.Move(fnMoveBackward);
433 pCNd = aPaM.GetCntntNode();
436 // Was passiert mit dem evt. selektierten Bereich ???
438 switch( pCNd->GetNodeType() )
440 case ND_TEXTNODE:
441 if( bIsAppend )
442 rDoc.AppendTxtNode( *rUndoIter.pAktPam->GetPoint() );
443 else
445 String aTxt( ((SwTxtNode*)pCNd)->GetTxt() );
446 BOOL bGroupUndo = rDoc.DoesGroupUndo();
447 rDoc.DoGroupUndo( FALSE );
448 rDoc.Insert( *rUndoIter.pAktPam, aTxt.Copy( nCntnt - nLen, nLen ), true);
449 rDoc.DoGroupUndo( bGroupUndo );
451 break;
452 case ND_GRFNODE:
454 SwGrfNode* pGrfNd = (SwGrfNode*)pCNd;
455 String sFile, sFilter;
456 if( pGrfNd->IsGrfLink() )
457 pGrfNd->GetFileFilterNms( &sFile, &sFilter );
459 rDoc.Insert( *rUndoIter.pAktPam, sFile, sFilter,
460 &pGrfNd->GetGrf(),
461 0/* Grafik-Collection*/, NULL, NULL );
463 break;
465 case ND_OLENODE:
467 // StarView bietet noch nicht die Moeglichkeit ein StarOBJ zu kopieren
468 SvStorageRef aRef = new SvStorage( aEmptyStr );
469 SwOLEObj& rSwOLE = (SwOLEObj&)((SwOLENode*)pCNd)->GetOLEObj();
471 // temporary storage until object is inserted
472 // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing!
473 // TODO/LATER: Copying through the container would copy the replacement image as well
474 comphelper::EmbeddedObjectContainer aCnt;
475 ::rtl::OUString aName = aCnt.CreateUniqueObjectName();
476 if ( aCnt.StoreEmbeddedObject( rSwOLE.GetOleRef(), aName, sal_True ) )
478 uno::Reference < embed::XEmbeddedObject > aNew = aCnt.GetEmbeddedObject( aName );
479 rDoc.Insert( *rUndoIter.pAktPam, svt::EmbeddedObjectRef( aNew, ((SwOLENode*)pCNd)->GetAspect() ), NULL, NULL, NULL );
482 break;
487 // #111827#
488 SwRewriter SwUndoInsert::GetRewriter() const
490 SwRewriter aResult;
491 String * pStr = NULL;
492 bool bDone = false;
494 if (pTxt)
495 pStr = pTxt;
496 else if (pUndoTxt)
497 pStr = pUndoTxt;
499 if (pStr)
501 String aString = ShortenString(DenoteSpecialCharacters(*pStr),
502 nUndoStringLength,
503 String(SW_RES(STR_LDOTS)));
505 aResult.AddRule(UNDO_ARG1, aString);
507 bDone = true;
510 if ( ! bDone )
512 aResult.AddRule(UNDO_ARG1, String("??", RTL_TEXTENCODING_ASCII_US));
515 return aResult;
519 /* \f */
521 SwUndoReplace::SwUndoReplace()
522 : SwUndo( UNDO_REPLACE ), nAktPos( USHRT_MAX )
526 SwUndoReplace::~SwUndoReplace()
530 void SwUndoReplace::Undo( SwUndoIter& rUndoIter )
532 // war dieses nicht die letze Undo-Aktion, dann setze den
533 // Count neu
534 if( rUndoIter.pLastUndoObj != this )
536 nAktPos = aArr.Count();
537 rUndoIter.pLastUndoObj = this;
538 bOldIterFlag = rUndoIter.bWeiter;
539 rUndoIter.bWeiter = TRUE;
542 aArr[ --nAktPos ]->Undo( rUndoIter );
544 if( !nAktPos ) // alten Status wieder zurueck
545 rUndoIter.bWeiter = bOldIterFlag;
549 void SwUndoReplace::Redo( SwUndoIter& rUndoIter )
551 // war dieses nicht die letze Undo-Aktion, dann setze den
552 // Count neu
553 if( rUndoIter.pLastUndoObj != this )
555 ASSERT( !nAktPos, "Redo ohne vorheriges Undo??" );
556 rUndoIter.pLastUndoObj = this;
557 bOldIterFlag = rUndoIter.bWeiter;
558 rUndoIter.bWeiter = TRUE;
561 aArr[ nAktPos ]->Redo( rUndoIter );
563 if( ++nAktPos >= aArr.Count() ) // alten Status wieder zurueck
565 nAktPos = USHRT_MAX;
566 rUndoIter.bWeiter = bOldIterFlag;
570 // #111827#
571 SwRewriter SwUndoReplace::GetRewriter() const
573 SwRewriter aResult;
575 if (aArr.Count() > 1)
577 aResult.AddRule(UNDO_ARG1, String::CreateFromInt32(aArr.Count()));
578 aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_OCCURRENCES_OF)));
580 String aTmpStr;
581 aTmpStr += String(SW_RES(STR_START_QUOTE));
582 aTmpStr += ShortenString(aArr[0]->GetOld(), nUndoStringLength,
583 SW_RES(STR_LDOTS));
584 aTmpStr += String(SW_RES(STR_END_QUOTE));
585 aResult.AddRule(UNDO_ARG3, aTmpStr);
587 else if (aArr.Count() == 1)
590 String aTmpStr;
592 aTmpStr += String(SW_RES(STR_START_QUOTE));
593 // #i33488 #
594 aTmpStr += ShortenString(aArr[0]->GetOld(), nUndoStringLength,
595 SW_RES(STR_LDOTS));
596 aTmpStr += String(SW_RES(STR_END_QUOTE));
597 aResult.AddRule(UNDO_ARG1, aTmpStr);
600 aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_YIELDS)));
603 String aTmpStr;
605 aTmpStr += String(SW_RES(STR_START_QUOTE));
606 // #i33488 #
607 aTmpStr += ShortenString(aArr[0]->GetIns(), nUndoStringLength,
608 SW_RES(STR_LDOTS));
609 aTmpStr += String(SW_RES(STR_END_QUOTE));
610 aResult.AddRule(UNDO_ARG3, aTmpStr);
614 return aResult;
617 void SwUndoReplace::AddEntry( const SwPaM& rPam, const String& rInsert,
618 BOOL bRegExp )
620 _UnReplaceData* pNew = new _UnReplaceData( rPam, rInsert, bRegExp );
621 aArr.C40_INSERT(_UnReplaceData, pNew, aArr.Count() );
624 void SwUndoReplace::SetEntryEnd( const SwPaM& rPam )
626 _UnReplaceData* pEntry = aArr[ aArr.Count()-1 ];
627 pEntry->SetEnd( rPam );
630 _UnReplaceData::_UnReplaceData( const SwPaM& rPam, const String& rIns,
631 BOOL bRgExp )
632 : m_sIns( rIns ), m_nOffset( 0 )
634 m_bRegExp = bRgExp;
636 const SwPosition * pStt( rPam.Start() );
637 const SwPosition * pEnd( rPam.End() );
639 m_nSttNd = m_nEndNd = pStt->nNode.GetIndex();
640 m_nSttCnt = pStt->nContent.GetIndex();
641 m_nSelEnd = m_nEndCnt = pEnd->nContent.GetIndex();
643 m_bSplitNext = m_nSttNd != pEnd->nNode.GetIndex();
645 SwTxtNode* pNd = pStt->nNode.GetNode().GetTxtNode();
646 ASSERT( pNd, "wo ist der TextNode" );
648 pHistory = new SwHistory;
649 DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
651 m_nSetPos = pHistory->Count();
653 ULONG nNewPos = pStt->nNode.GetIndex();
654 m_nOffset = m_nSttNd - nNewPos;
656 if ( pNd->GetpSwpHints() )
658 pHistory->CopyAttr( pNd->GetpSwpHints(), nNewPos, 0,
659 pNd->GetTxt().Len(), true );
662 if ( m_bSplitNext )
664 if( pNd->HasSwAttrSet() )
665 pHistory->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNewPos );
666 pHistory->Add( pNd->GetTxtColl(), nNewPos, ND_TEXTNODE );
668 SwTxtNode* pNext = pEnd->nNode.GetNode().GetTxtNode();
669 ULONG nTmp = pNext->GetIndex();
670 pHistory->CopyAttr( pNext->GetpSwpHints(), nTmp, 0,
671 pNext->GetTxt().Len(), true );
672 if( pNext->HasSwAttrSet() )
673 pHistory->CopyFmtAttr( *pNext->GetpSwAttrSet(), nTmp );
674 pHistory->Add( pNext->GetTxtColl(),nTmp, ND_TEXTNODE );
675 // METADATA: store
676 m_pMetadataUndoStart = pNd ->CreateUndo();
677 m_pMetadataUndoEnd = pNext->CreateUndo();
680 if( !pHistory->Count() )
681 delete pHistory, pHistory = 0;
683 xub_StrLen nECnt = m_bSplitNext ? pNd->GetTxt().Len()
684 : pEnd->nContent.GetIndex();
685 m_sOld = pNd->GetTxt().Copy( m_nSttCnt, nECnt - m_nSttCnt );
688 _UnReplaceData::~_UnReplaceData()
692 void _UnReplaceData::Undo( SwUndoIter& rIter )
694 SwDoc* pDoc = &rIter.GetDoc();
695 SwPaM& rPam = *rIter.pAktPam;
696 rPam.DeleteMark();
698 SwTxtNode* pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
699 ASSERT( pNd, "Wo ist der TextNode geblieben?" )
701 SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord();
702 if( pACEWord )
704 if( 1 == m_sIns.Len() && 1 == m_sOld.Len() )
706 SwPosition aPos( *pNd ); aPos.nContent.Assign( pNd, m_nSttCnt );
707 pACEWord->CheckChar( aPos, m_sOld.GetChar( 0 ) );
709 pDoc->SetAutoCorrExceptWord( 0 );
712 SwIndex aIdx( pNd, m_nSttCnt );
713 if( m_nSttNd == m_nEndNd )
715 pNd->Erase( aIdx, m_sIns.Len() );
717 else
719 rPam.GetPoint()->nNode = *pNd;
720 rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
721 rPam.SetMark();
722 rPam.GetPoint()->nNode = m_nEndNd - m_nOffset;
723 rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), m_nEndCnt );
725 pDoc->DeleteAndJoin( rPam );
726 rPam.DeleteMark();
727 pNd = rPam.GetNode()->GetTxtNode();
728 ASSERT( pNd, "Wo ist der TextNode geblieben?" );
729 aIdx.Assign( pNd, m_nSttCnt );
732 if( m_bSplitNext )
734 SwPosition aPos( *pNd, aIdx );
735 pDoc->SplitNode( aPos, false );
736 pNd->RestoreMetadata(m_pMetadataUndoEnd);
737 pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
738 aIdx.Assign( pNd, m_nSttCnt );
739 // METADATA: restore
740 pNd->RestoreMetadata(m_pMetadataUndoStart);
743 if( m_sOld.Len() )
744 pNd->Insert( m_sOld, aIdx );
746 if( pHistory )
748 if( pNd->GetpSwpHints() )
749 pNd->ClearSwpHintsArr( true );
751 pHistory->TmpRollback( pDoc, m_nSetPos, false );
752 if ( m_nSetPos ) // there were footnotes/FlyFrames
754 // gibts ausser diesen noch andere ?
755 if( m_nSetPos < pHistory->Count() )
757 // dann sicher die Attribute anderen Attribute
758 SwHistory aHstr;
759 aHstr.Move( 0, pHistory, m_nSetPos );
760 pHistory->Rollback( pDoc );
761 pHistory->Move( 0, &aHstr );
763 else
765 pHistory->Rollback( pDoc );
766 DELETEZ( pHistory );
771 rPam.GetPoint()->nNode = m_nSttNd;
772 rPam.GetPoint()->nContent = aIdx;
775 void _UnReplaceData::Redo( SwUndoIter& rIter )
777 SwDoc& rDoc = rIter.GetDoc();
778 BOOL bUndo = rDoc.DoesUndo();
779 rDoc.DoUndo( FALSE );
781 SwPaM& rPam = *rIter.pAktPam;
782 rPam.DeleteMark();
783 rPam.GetPoint()->nNode = m_nSttNd;
785 SwTxtNode* pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
786 ASSERT( pNd, "Wo ist der TextNode geblieben?" )
787 rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
788 rPam.SetMark();
789 if( m_bSplitNext )
791 rPam.GetPoint()->nNode = m_nSttNd + 1;
792 pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
794 rPam.GetPoint()->nContent.Assign( pNd, m_nSelEnd );
796 if( pHistory )
798 SwHistory* pSave = pHistory;
799 SwHistory aHst;
800 pHistory = &aHst;
801 DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
802 m_nSetPos = pHistory->Count();
804 pHistory = pSave;
805 pHistory->Move( 0, &aHst );
807 else
809 pHistory = new SwHistory;
810 DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
811 m_nSetPos = pHistory->Count();
812 if( !m_nSetPos )
813 delete pHistory, pHistory = 0;
816 rDoc.Replace( rPam, m_sIns, m_bRegExp );
817 rPam.DeleteMark();
818 rDoc.DoUndo( bUndo );
821 void _UnReplaceData::SetEnd( const SwPaM& rPam )
823 if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
825 // es wurden mehrere Absaetze eingefuegt
826 const SwPosition* pEnd = rPam.End();
827 m_nEndNd = m_nOffset + pEnd->nNode.GetIndex();
828 m_nEndCnt = pEnd->nContent.GetIndex();
832 /* \f */
835 SwUndoReRead::SwUndoReRead( const SwPaM& rPam, const SwGrfNode& rGrfNd )
836 : SwUndo( UNDO_REREAD ), nPos( rPam.GetPoint()->nNode.GetIndex() )
838 SaveGraphicData( rGrfNd );
842 SwUndoReRead::~SwUndoReRead()
844 delete pGrf;
845 delete pNm;
846 delete pFltr;
850 void SwUndoReRead::SetAndSave( SwUndoIter& rIter )
852 SwDoc& rDoc = rIter.GetDoc();
853 SwGrfNode* pGrfNd = rDoc.GetNodes()[ nPos ]->GetGrfNode();
855 if( !pGrfNd )
856 return ;
858 // die alten Werte zwischen speichern
859 Graphic* pOldGrf = pGrf;
860 String* pOldNm = pNm;
861 String* pOldFltr = pFltr;
862 USHORT nOldMirr = nMirr;
864 SaveGraphicData( *pGrfNd );
865 if( pOldNm )
867 pGrfNd->ReRead( *pOldNm, pFltr ? *pFltr : aEmptyStr, 0, 0, TRUE );
868 delete pOldNm;
869 delete pOldFltr;
871 else
873 pGrfNd->ReRead( aEmptyStr, aEmptyStr, pOldGrf, 0, TRUE );
874 delete pOldGrf;
877 if( RES_MIRROR_GRAPH_DONT != nOldMirr )
878 pGrfNd->SetAttr( SwMirrorGrf() );
880 rIter.pSelFmt = pGrfNd->GetFlyFmt();
884 void SwUndoReRead::Undo( SwUndoIter& rIter )
886 SetAndSave( rIter );
890 void SwUndoReRead::Redo( SwUndoIter& rIter )
892 SetAndSave( rIter );
896 void SwUndoReRead::SaveGraphicData( const SwGrfNode& rGrfNd )
898 if( rGrfNd.IsGrfLink() )
900 pNm = new String;
901 pFltr = new String;
902 rGrfNd.GetFileFilterNms( pNm, pFltr );
903 pGrf = 0;
905 else
907 ((SwGrfNode&)rGrfNd).SwapIn( TRUE );
908 pGrf = new Graphic( rGrfNd.GetGrf() );
909 pNm = pFltr = 0;
911 nMirr = rGrfNd.GetSwAttrSet().GetMirrorGrf().GetValue();
914 /* \f */
916 SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp,
917 const String &rTxt,
918 const String& rSeparator,
919 const String& rNumberSeparator,
920 const BOOL bBef,
921 const USHORT nInitId,
922 const String& rCharacterStyle,
923 const BOOL bCpyBorder )
924 : SwUndo( UNDO_INSERTLABEL ),
925 sText( rTxt ),
926 sSeparator( rSeparator ),
927 sNumberSeparator( rNumberSeparator ),//#i61007# order of captions
928 sCharacterStyle( rCharacterStyle ),
929 nFldId( nInitId ),
930 eType( eTyp ),
931 nLayerId( 0 ),
932 bBefore( bBef ),
933 bCpyBrd( bCpyBorder )
935 bUndoKeep = FALSE;
936 OBJECT.pUndoFly = 0;
937 OBJECT.pUndoAttr = 0;
940 SwUndoInsertLabel::~SwUndoInsertLabel()
942 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
944 delete OBJECT.pUndoFly;
945 delete OBJECT.pUndoAttr;
947 else
948 delete NODE.pUndoInsNd;
951 void SwUndoInsertLabel::Undo( SwUndoIter& rIter )
953 SwDoc& rDoc = rIter.GetDoc();
955 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
957 ASSERT( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" )
958 SwFrmFmt* pFmt;
959 SdrObject *pSdrObj = 0;
960 if( OBJECT.pUndoAttr &&
961 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
962 ( LTYPE_DRAW != eType ||
963 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
965 OBJECT.pUndoAttr->Undo( rIter );
966 OBJECT.pUndoFly->Undo( rIter );
967 if( LTYPE_DRAW == eType )
969 pSdrObj->SetLayer( nLayerId );
973 else if( NODE.nNode )
975 if ( eType == LTYPE_TABLE && bUndoKeep )
977 SwTableNode *pNd = rDoc.GetNodes()[
978 rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
979 if ( pNd )
980 pNd->GetTable().GetFrmFmt()->ResetFmtAttr( RES_KEEP );
982 SwPaM aPam( *rIter.pAktPam->GetPoint() );
983 aPam.GetPoint()->nNode = NODE.nNode;
984 aPam.SetMark();
985 aPam.GetPoint()->nNode = NODE.nNode + 1;
986 NODE.pUndoInsNd = new SwUndoDelete( aPam, TRUE );
991 void SwUndoInsertLabel::Redo( SwUndoIter& rIter )
993 SwDoc& rDoc = rIter.GetDoc();
995 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
997 ASSERT( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" )
998 SwFrmFmt* pFmt;
999 SdrObject *pSdrObj = 0;
1000 if( OBJECT.pUndoAttr &&
1001 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
1002 ( LTYPE_DRAW != eType ||
1003 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
1005 OBJECT.pUndoFly->Redo( rIter );
1006 OBJECT.pUndoAttr->Redo( rIter );
1007 if( LTYPE_DRAW == eType )
1009 pSdrObj->SetLayer( nLayerId );
1010 if( pSdrObj->GetLayer() == rDoc.GetHellId() )
1011 pSdrObj->SetLayer( rDoc.GetHeavenId() );
1012 // OD 02.07.2003 #108784#
1013 else if( pSdrObj->GetLayer() == rDoc.GetInvisibleHellId() )
1014 pSdrObj->SetLayer( rDoc.GetInvisibleHeavenId() );
1018 else if( NODE.pUndoInsNd )
1020 if ( eType == LTYPE_TABLE && bUndoKeep )
1022 SwTableNode *pNd = rDoc.GetNodes()[
1023 rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
1024 if ( pNd )
1025 pNd->GetTable().GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem(TRUE, RES_KEEP) );
1027 NODE.pUndoInsNd->Undo( rIter );
1028 delete NODE.pUndoInsNd, NODE.pUndoInsNd = 0;
1032 void SwUndoInsertLabel::Repeat( SwUndoIter& rIter )
1034 SwDoc& rDoc = rIter.GetDoc();
1035 const SwPosition& rPos = *rIter.pAktPam->GetPoint();
1037 ULONG nIdx = 0;
1039 SwCntntNode* pCNd = rPos.nNode.GetNode().GetCntntNode();
1040 if( pCNd )
1041 switch( eType )
1043 case LTYPE_TABLE:
1045 const SwTableNode* pTNd = pCNd->FindTableNode();
1046 if( pTNd )
1047 nIdx = pTNd->GetIndex();
1049 break;
1051 case LTYPE_FLY:
1052 case LTYPE_OBJECT:
1054 SwFlyFrm* pFly;
1055 SwCntntFrm *pCnt = pCNd->GetFrm();
1056 if( pCnt && 0 != ( pFly = pCnt->FindFlyFrm() ) )
1057 nIdx = pFly->GetFmt()->GetCntnt().GetCntntIdx()->GetIndex();
1059 break;
1060 case LTYPE_DRAW:
1061 break;
1064 if( nIdx )
1066 rDoc.InsertLabel( eType, sText, sSeparator, sNumberSeparator, bBefore,
1067 nFldId, nIdx, sCharacterStyle, bCpyBrd );
1071 // #111827#
1072 SwRewriter SwUndoInsertLabel::GetRewriter() const
1074 SwRewriter aRewriter;
1076 String aTmpStr;
1078 aTmpStr += String(SW_RES(STR_START_QUOTE));
1079 aTmpStr += ShortenString(sText, nUndoStringLength,
1080 String(SW_RES(STR_LDOTS)));
1081 aTmpStr += String(SW_RES(STR_END_QUOTE));
1083 aRewriter.AddRule(UNDO_ARG1, aTmpStr);
1085 return aRewriter;
1088 void SwUndoInsertLabel::SetFlys( SwFrmFmt& rOldFly, SfxItemSet& rChgSet,
1089 SwFrmFmt& rNewFly )
1091 if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
1093 SwUndoFmtAttrHelper aTmp( rOldFly, false );
1094 rOldFly.SetFmtAttr( rChgSet );
1095 if ( aTmp.GetUndo() )
1097 OBJECT.pUndoAttr = aTmp.ReleaseUndo();
1099 OBJECT.pUndoFly = new SwUndoInsLayFmt( &rNewFly,0,0 );
1103 void SwUndoInsertLabel::SetDrawObj( BYTE nLId )
1105 if( LTYPE_DRAW == eType )
1107 nLayerId = nLId;