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