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