xref: /trunk/main/sw/source/core/undo/unins.cxx (revision efeef26f)
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