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