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