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 <rolbck.hxx>
21 : #include <tools/resid.hxx>
22 : #include <svl/itemiter.hxx>
23 : #include <editeng/formatbreakitem.hxx>
24 : #include <hints.hxx>
25 : #include <hintids.hxx>
26 : #include <fmtftn.hxx>
27 : #include <fchrfmt.hxx>
28 : #include <fmtflcnt.hxx>
29 : #include <fmtrfmrk.hxx>
30 : #include <fmtfld.hxx>
31 : #include <fmtpdsc.hxx>
32 : #include <txtfld.hxx>
33 : #include <txtrfmrk.hxx>
34 : #include <txttxmrk.hxx>
35 : #include <txtftn.hxx>
36 : #include <txtflcnt.hxx>
37 : #include <fmtanchr.hxx>
38 : #include <fmtcnct.hxx>
39 : #include <frmfmt.hxx>
40 : #include <ftnidx.hxx>
41 : #include <doc.hxx> // SwDoc.GetNodes()
42 : #include <IDocumentUndoRedo.hxx>
43 : #include <docary.hxx>
44 : #include <ndtxt.hxx> // SwTxtNode
45 : #include <paratr.hxx>
46 : #include <cellatr.hxx>
47 : #include <fldbas.hxx>
48 : #include <pam.hxx>
49 : #include <swtable.hxx>
50 : #include <ndgrf.hxx> // SwGrfNode
51 : #include <UndoCore.hxx>
52 : #include <IMark.hxx>
53 : #include <charfmt.hxx> // #i27615#
54 : #include <comcore.hrc>
55 : #include <undo.hrc>
56 : #include <bookmrk.hxx>
57 :
58 365 : String SwHistoryHint::GetDescription() const
59 : {
60 365 : return String();
61 : }
62 :
63 1582 : SwHistorySetFmt::SwHistorySetFmt( const SfxPoolItem* pFmtHt, sal_uLong nNd )
64 : : SwHistoryHint( HSTRY_SETFMTHNT )
65 1582 : , m_pAttr( pFmtHt->Clone() )
66 3164 : , m_nNodeIndex( nNd )
67 : {
68 1582 : switch ( m_pAttr->Which() )
69 : {
70 : case RES_PAGEDESC:
71 5 : static_cast<SwFmtPageDesc&>(*m_pAttr).ChgDefinedIn( 0 );
72 5 : break;
73 : case RES_PARATR_DROP:
74 0 : static_cast<SwFmtDrop&>(*m_pAttr).ChgDefinedIn( 0 );
75 0 : break;
76 : case RES_BOXATR_FORMULA:
77 : {
78 : // save formulas always in plain text
79 0 : SwTblBoxFormula& rNew = static_cast<SwTblBoxFormula&>(*m_pAttr);
80 0 : if ( rNew.IsIntrnlName() )
81 : {
82 : const SwTblBoxFormula& rOld =
83 0 : *static_cast<const SwTblBoxFormula*>(pFmtHt);
84 0 : const SwNode* pNd = rOld.GetNodeOfFormula();
85 0 : if ( pNd )
86 : {
87 0 : const SwTableNode* pTableNode = pNd->FindTableNode();
88 0 : if (pTableNode)
89 : {
90 0 : SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() );
91 0 : aMsgHnt.eFlags = TBL_BOXNAME;
92 0 : rNew.ChgDefinedIn( rOld.GetDefinedIn() );
93 0 : rNew.ChangeState( &aMsgHnt );
94 : }
95 : }
96 : }
97 0 : rNew.ChgDefinedIn( 0 );
98 : }
99 0 : break;
100 : }
101 1582 : }
102 :
103 30 : String SwHistorySetFmt::GetDescription() const
104 : {
105 30 : String aResult;
106 :
107 30 : sal_uInt16 nWhich = m_pAttr->Which();
108 30 : switch (nWhich)
109 : {
110 : case RES_BREAK:
111 0 : switch ((static_cast<SvxFmtBreakItem &>(*m_pAttr)).GetBreak())
112 : {
113 : case SVX_BREAK_PAGE_BEFORE:
114 : case SVX_BREAK_PAGE_AFTER:
115 : case SVX_BREAK_PAGE_BOTH:
116 0 : aResult = SW_RESSTR(STR_UNDO_PAGEBREAKS);
117 :
118 0 : break;
119 : case SVX_BREAK_COLUMN_BEFORE:
120 : case SVX_BREAK_COLUMN_AFTER:
121 : case SVX_BREAK_COLUMN_BOTH:
122 0 : aResult = SW_RESSTR(STR_UNDO_COLBRKS);
123 :
124 0 : break;
125 : default:
126 0 : break;
127 : }
128 0 : break;
129 : default:
130 30 : break;
131 : }
132 :
133 30 : return aResult;
134 : }
135 :
136 0 : void SwHistorySetFmt::SetInDoc( SwDoc* pDoc, bool bTmpSet )
137 : {
138 0 : SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
139 0 : if ( pNode->IsCntntNode() )
140 : {
141 0 : static_cast<SwCntntNode*>(pNode)->SetAttr( *m_pAttr );
142 : }
143 0 : else if ( pNode->IsTableNode() )
144 : {
145 0 : static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->SetFmtAttr(
146 0 : *m_pAttr );
147 : }
148 0 : else if ( pNode->IsStartNode() && (SwTableBoxStartNode ==
149 0 : static_cast<SwStartNode*>(pNode)->GetStartNodeType()) )
150 : {
151 0 : SwTableNode* pTNd = pNode->FindTableNode();
152 0 : if ( pTNd )
153 : {
154 0 : SwTableBox* pBox = pTNd->GetTable().GetTblBox( m_nNodeIndex );
155 0 : if (pBox)
156 : {
157 0 : pBox->ClaimFrmFmt()->SetFmtAttr( *m_pAttr );
158 : }
159 : }
160 : }
161 :
162 0 : if ( !bTmpSet )
163 : {
164 0 : m_pAttr.reset();
165 : }
166 0 : }
167 :
168 3164 : SwHistorySetFmt::~SwHistorySetFmt()
169 : {
170 3164 : }
171 :
172 892 : SwHistoryResetFmt::SwHistoryResetFmt(const SfxPoolItem* pFmtHt, sal_uLong nNodeIdx)
173 : : SwHistoryHint( HSTRY_RESETFMTHNT )
174 : , m_nNodeIndex( nNodeIdx )
175 892 : , m_nWhich( pFmtHt->Which() )
176 : {
177 892 : }
178 :
179 0 : void SwHistoryResetFmt::SetInDoc( SwDoc* pDoc, bool )
180 : {
181 0 : SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
182 0 : if ( pNode->IsCntntNode() )
183 : {
184 0 : static_cast<SwCntntNode*>(pNode)->ResetAttr( m_nWhich );
185 : }
186 0 : else if ( pNode->IsTableNode() )
187 : {
188 0 : static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->
189 0 : ResetFmtAttr( m_nWhich );
190 : }
191 0 : }
192 :
193 205 : SwHistorySetTxt::SwHistorySetTxt( SwTxtAttr* pTxtHt, sal_uLong nNodePos )
194 : : SwHistoryHint( HSTRY_SETTXTHNT )
195 : , m_nNodeIndex( nNodePos )
196 205 : , m_nStart( *pTxtHt->GetStart() )
197 205 : , m_nEnd( *pTxtHt->GetAnyEnd() )
198 205 : , m_bFormatIgnoreStart(pTxtHt->IsFormatIgnoreStart())
199 820 : , m_bFormatIgnoreEnd (pTxtHt->IsFormatIgnoreEnd ())
200 : {
201 : // Caution: the following attributes generate no format attributes:
202 : // - NoLineBreak, NoHypen, Inserted, Deleted
203 : // These cases must be handled separately !!!
204 :
205 : // a little bit complicated but works: first assign a copy of the
206 : // default value and afterwards the values from text attribute
207 205 : sal_uInt16 nWhich = pTxtHt->Which();
208 205 : if ( RES_TXTATR_CHARFMT == nWhich )
209 : {
210 2 : m_pAttr.reset( new SwFmtCharFmt( pTxtHt->GetCharFmt().GetCharFmt() ) );
211 : }
212 : else
213 : {
214 203 : m_pAttr.reset( pTxtHt->GetAttr().Clone() );
215 : }
216 205 : }
217 :
218 410 : SwHistorySetTxt::~SwHistorySetTxt()
219 : {
220 410 : }
221 :
222 0 : void SwHistorySetTxt::SetInDoc( SwDoc* pDoc, bool )
223 : {
224 0 : if ( !m_pAttr.get() )
225 0 : return;
226 :
227 0 : if ( RES_TXTATR_CHARFMT == m_pAttr->Which() )
228 : {
229 : // ask the Doc if the CharFmt still exists
230 0 : if ( !pDoc->GetCharFmts()->Contains( (static_cast<SwFmtCharFmt&>(*m_pAttr)).GetCharFmt() ) )
231 0 : return; // do not set, format does not exist
232 : }
233 :
234 0 : SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
235 : OSL_ENSURE( pTxtNd, "SwHistorySetTxt::SetInDoc: not a TextNode" );
236 :
237 0 : if ( pTxtNd )
238 : {
239 0 : SwTxtAttr *const pAttr = pTxtNd->InsertItem(*m_pAttr, m_nStart, m_nEnd,
240 : nsSetAttrMode::SETATTR_NOTXTATRCHR |
241 0 : nsSetAttrMode::SETATTR_NOHINTADJUST );
242 : // shouldn't be possible to hit any error/merging path from here
243 : assert(pAttr);
244 0 : if (m_bFormatIgnoreStart)
245 : {
246 0 : pAttr->SetFormatIgnoreStart(true);
247 : }
248 0 : if (m_bFormatIgnoreEnd)
249 : {
250 0 : pAttr->SetFormatIgnoreEnd(true);
251 : }
252 : }
253 : }
254 :
255 22 : SwHistorySetTxtFld::SwHistorySetTxtFld( SwTxtFld* pTxtFld, sal_uLong nNodePos )
256 : : SwHistoryHint( HSTRY_SETTXTFLDHNT )
257 : , m_pFldType( 0 )
258 22 : , m_pFld( new SwFmtFld( *pTxtFld->GetFld().GetFld() ) )
259 : {
260 : // only copy if not Sys-FieldType
261 22 : SwDoc* pDoc = pTxtFld->GetTxtNode().GetDoc();
262 :
263 22 : m_nFldWhich = m_pFld->GetFld()->GetTyp()->Which();
264 65 : if (m_nFldWhich == RES_DBFLD ||
265 42 : m_nFldWhich == RES_USERFLD ||
266 42 : m_nFldWhich == RES_SETEXPFLD ||
267 64 : m_nFldWhich == RES_DDEFLD ||
268 21 : !pDoc->GetSysFldType( m_nFldWhich ))
269 : {
270 1 : m_pFldType.reset( m_pFld->GetFld()->GetTyp()->Copy() );
271 1 : m_pFld->GetFld()->ChgTyp( m_pFldType.get() ); // change field type
272 : }
273 22 : m_nNodeIndex = nNodePos;
274 22 : m_nPos = *pTxtFld->GetStart();
275 22 : }
276 :
277 13 : String SwHistorySetTxtFld::GetDescription() const
278 : {
279 13 : return m_pFld->GetFld()->GetDescription();
280 : }
281 :
282 44 : SwHistorySetTxtFld::~SwHistorySetTxtFld()
283 : {
284 44 : }
285 :
286 0 : void SwHistorySetTxtFld::SetInDoc( SwDoc* pDoc, bool )
287 : {
288 0 : if ( !m_pFld.get() )
289 0 : return;
290 :
291 0 : SwFieldType* pNewFldType = m_pFldType.get();
292 0 : if ( !pNewFldType )
293 : {
294 0 : pNewFldType = pDoc->GetSysFldType( m_nFldWhich );
295 : }
296 : else
297 : {
298 : // register type with the document
299 0 : pNewFldType = pDoc->InsertFldType( *m_pFldType );
300 : }
301 :
302 0 : m_pFld->GetFld()->ChgTyp( pNewFldType ); // change field type
303 :
304 0 : SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
305 : OSL_ENSURE( pTxtNd, "SwHistorySetTxtFld: no TextNode" );
306 :
307 0 : if ( pTxtNd )
308 : {
309 0 : pTxtNd->InsertItem( *m_pFld, m_nPos, m_nPos,
310 0 : nsSetAttrMode::SETATTR_NOTXTATRCHR );
311 : }
312 : }
313 :
314 12 : SwHistorySetRefMark::SwHistorySetRefMark( SwTxtRefMark* pTxtHt, sal_uLong nNodePos )
315 : : SwHistoryHint( HSTRY_SETREFMARKHNT )
316 12 : , m_RefName( pTxtHt->GetRefMark().GetRefName() )
317 : , m_nNodeIndex( nNodePos )
318 12 : , m_nStart( *pTxtHt->GetStart() )
319 36 : , m_nEnd( *pTxtHt->GetAnyEnd() )
320 : {
321 12 : }
322 :
323 0 : void SwHistorySetRefMark::SetInDoc( SwDoc* pDoc, bool )
324 : {
325 0 : SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
326 : OSL_ENSURE( pTxtNd, "SwHistorySetRefMark: no TextNode" );
327 0 : if ( !pTxtNd )
328 0 : return;
329 :
330 0 : SwFmtRefMark aRefMark( m_RefName );
331 :
332 : // if a reference mark without an end already exists here: must not insert!
333 0 : if ( m_nStart != m_nEnd ||
334 0 : !pTxtNd->GetTxtAttrForCharAt( m_nStart, RES_TXTATR_REFMARK ) )
335 : {
336 : pTxtNd->InsertItem( aRefMark, m_nStart, m_nEnd,
337 0 : nsSetAttrMode::SETATTR_NOTXTATRCHR );
338 0 : }
339 : }
340 :
341 13 : SwHistorySetTOXMark::SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, sal_uLong nNodePos )
342 : : SwHistoryHint( HSTRY_SETTOXMARKHNT )
343 13 : , m_TOXMark( pTxtHt->GetTOXMark() )
344 13 : , m_TOXName( m_TOXMark.GetTOXType()->GetTypeName() )
345 13 : , m_eTOXTypes( m_TOXMark.GetTOXType()->GetType() )
346 : , m_nNodeIndex( nNodePos )
347 13 : , m_nStart( *pTxtHt->GetStart() )
348 65 : , m_nEnd( *pTxtHt->GetAnyEnd() )
349 : {
350 13 : m_TOXMark.DeRegister();
351 13 : }
352 :
353 0 : void SwHistorySetTOXMark::SetInDoc( SwDoc* pDoc, bool )
354 : {
355 0 : SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
356 : OSL_ENSURE( pTxtNd, "SwHistorySetTOXMark: no TextNode" );
357 0 : if ( !pTxtNd )
358 0 : return;
359 :
360 : // search for respective TOX type
361 0 : sal_uInt16 nCnt = pDoc->GetTOXTypeCount( m_eTOXTypes );
362 0 : SwTOXType* pToxType = 0;
363 0 : for ( sal_uInt16 n = 0; n < nCnt; ++n )
364 : {
365 0 : pToxType = const_cast<SwTOXType*>(pDoc->GetTOXType( m_eTOXTypes, n ));
366 0 : if ( pToxType->GetTypeName() == m_TOXName )
367 0 : break;
368 0 : pToxType = 0;
369 : }
370 :
371 0 : if ( !pToxType ) // TOX type not found, create new
372 : {
373 : pToxType = const_cast<SwTOXType*>(
374 0 : pDoc->InsertTOXType( SwTOXType( m_eTOXTypes, m_TOXName )));
375 : }
376 :
377 0 : SwTOXMark aNew( m_TOXMark );
378 0 : aNew.RegisterToTOXType( *pToxType );
379 :
380 : pTxtNd->InsertItem( aNew, m_nStart, m_nEnd,
381 0 : nsSetAttrMode::SETATTR_NOTXTATRCHR );
382 : }
383 :
384 0 : int SwHistorySetTOXMark::IsEqual( const SwTOXMark& rCmp ) const
385 : {
386 0 : return m_TOXName == rCmp.GetTOXType()->GetTypeName() &&
387 0 : m_eTOXTypes == rCmp.GetTOXType()->GetType() &&
388 0 : m_TOXMark.GetAlternativeText() == rCmp.GetAlternativeText() &&
389 0 : ( (TOX_INDEX == m_eTOXTypes)
390 0 : ? ( m_TOXMark.GetPrimaryKey() == rCmp.GetPrimaryKey() &&
391 0 : m_TOXMark.GetSecondaryKey() == rCmp.GetSecondaryKey() )
392 0 : : m_TOXMark.GetLevel() == rCmp.GetLevel()
393 0 : );
394 : }
395 :
396 328 : SwHistoryResetTxt::SwHistoryResetTxt( sal_uInt16 nWhich,
397 : xub_StrLen nAttrStart, xub_StrLen nAttrEnd, sal_uLong nNodePos )
398 : : SwHistoryHint( HSTRY_RESETTXTHNT )
399 : , m_nNodeIndex( nNodePos ), m_nStart( nAttrStart ), m_nEnd( nAttrEnd )
400 328 : , m_nAttr( nWhich )
401 : {
402 328 : }
403 :
404 0 : void SwHistoryResetTxt::SetInDoc( SwDoc* pDoc, bool )
405 : {
406 0 : SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
407 : OSL_ENSURE( pTxtNd, "SwHistoryResetTxt: no TextNode" );
408 0 : if ( pTxtNd )
409 : {
410 0 : pTxtNd->DeleteAttributes( m_nAttr, m_nStart, m_nEnd );
411 : }
412 0 : }
413 :
414 13 : SwHistorySetFootnote::SwHistorySetFootnote( SwTxtFtn* pTxtFtn, sal_uLong nNodePos )
415 : : SwHistoryHint( HSTRY_SETFTNHNT )
416 13 : , m_pUndo( new SwUndoSaveSection )
417 13 : , m_FootnoteNumber( pTxtFtn->GetFtn().GetNumStr() )
418 : , m_nNodeIndex( nNodePos )
419 13 : , m_nStart( *pTxtFtn->GetStart() )
420 52 : , m_bEndNote( pTxtFtn->GetFtn().IsEndNote() )
421 : {
422 : OSL_ENSURE( pTxtFtn->GetStartNode(),
423 : "SwHistorySetFootnote: Footnote without Section" );
424 :
425 : // keep the old NodePos (because who knows what later will be saved/deleted
426 : // in SaveSection)
427 13 : SwDoc* pDoc = const_cast<SwDoc*>(pTxtFtn->GetTxtNode().GetDoc());
428 13 : SwNode* pSaveNd = pDoc->GetNodes()[ m_nNodeIndex ];
429 :
430 : // keep pointer to StartNode of FtnSection and reset its attribute for now
431 : // (as a result, its/all Frms will be deleted automatically)
432 13 : SwNodeIndex aSttIdx( *pTxtFtn->GetStartNode() );
433 13 : pTxtFtn->SetStartNode( 0, sal_False );
434 :
435 13 : m_pUndo->SaveSection( pDoc, aSttIdx );
436 13 : m_nNodeIndex = pSaveNd->GetIndex();
437 13 : }
438 :
439 2 : SwHistorySetFootnote::SwHistorySetFootnote( const SwTxtFtn &rTxtFtn )
440 : : SwHistoryHint( HSTRY_SETFTNHNT )
441 : , m_pUndo( 0 )
442 2 : , m_FootnoteNumber( rTxtFtn.GetFtn().GetNumStr() )
443 2 : , m_nNodeIndex( _SwTxtFtn_GetIndex( (&rTxtFtn) ) )
444 2 : , m_nStart( *rTxtFtn.GetStart() )
445 8 : , m_bEndNote( rTxtFtn.GetFtn().IsEndNote() )
446 : {
447 : OSL_ENSURE( rTxtFtn.GetStartNode(),
448 : "SwHistorySetFootnote: Footnote without Section" );
449 2 : }
450 :
451 10 : String SwHistorySetFootnote::GetDescription() const
452 : {
453 10 : return SW_RES(STR_FOOTNOTE);
454 : }
455 :
456 30 : SwHistorySetFootnote::~SwHistorySetFootnote()
457 : {
458 30 : }
459 :
460 0 : void SwHistorySetFootnote::SetInDoc( SwDoc* pDoc, bool )
461 : {
462 0 : SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
463 : OSL_ENSURE( pTxtNd, "SwHistorySetFootnote: no TextNode" );
464 0 : if ( !pTxtNd )
465 0 : return;
466 :
467 0 : if ( m_pUndo.get() )
468 : {
469 : // set the footnote in the TextNode
470 0 : SwFmtFtn aTemp( m_bEndNote );
471 : SwFmtFtn& rNew = const_cast<SwFmtFtn&>(
472 0 : static_cast<const SwFmtFtn&>(pDoc->GetAttrPool().Put(aTemp)) );
473 0 : if ( m_FootnoteNumber.Len() )
474 : {
475 0 : rNew.SetNumStr( m_FootnoteNumber );
476 : }
477 0 : SwTxtFtn* pTxtFtn = new SwTxtFtn( rNew, m_nStart );
478 :
479 : // create the section of the Footnote
480 0 : SwNodeIndex aIdx( *pTxtNd );
481 0 : m_pUndo->RestoreSection( pDoc, &aIdx, SwFootnoteStartNode );
482 0 : pTxtFtn->SetStartNode( &aIdx );
483 0 : if ( m_pUndo->GetHistory() )
484 : {
485 : // create frames only now
486 0 : m_pUndo->GetHistory()->Rollback( pDoc );
487 : }
488 :
489 0 : pTxtNd->InsertHint( pTxtFtn );
490 : }
491 : else
492 : {
493 : SwTxtFtn * const pFtn =
494 : const_cast<SwTxtFtn*>( static_cast<const SwTxtFtn*>(
495 0 : pTxtNd->GetTxtAttrForCharAt( m_nStart )));
496 0 : SwFmtFtn &rFtn = const_cast<SwFmtFtn&>(pFtn->GetFtn());
497 0 : rFtn.SetNumStr( m_FootnoteNumber );
498 0 : if ( rFtn.IsEndNote() != m_bEndNote )
499 : {
500 0 : rFtn.SetEndNote( m_bEndNote );
501 0 : pFtn->CheckCondColl();
502 : }
503 : }
504 : }
505 :
506 41 : SwHistoryChangeFmtColl::SwHistoryChangeFmtColl( SwFmtColl* pFmtColl, sal_uLong nNd,
507 : sal_uInt8 nNodeWhich )
508 : : SwHistoryHint( HSTRY_CHGFMTCOLL )
509 : , m_pColl( pFmtColl )
510 : , m_nNodeIndex( nNd )
511 41 : , m_nNodeType( nNodeWhich )
512 : {
513 41 : }
514 :
515 0 : void SwHistoryChangeFmtColl::SetInDoc( SwDoc* pDoc, bool )
516 : {
517 0 : SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
518 : OSL_ENSURE( pCntntNd, "SwHistoryChangeFmtColl: no ContentNode" );
519 :
520 : // before setting the format, check if it is still available in the
521 : // document. if it has been deleted, there is no undo!
522 0 : if ( pCntntNd && m_nNodeType == pCntntNd->GetNodeType() )
523 : {
524 0 : if ( ND_TEXTNODE == m_nNodeType )
525 : {
526 0 : if ( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos(
527 0 : static_cast<SwTxtFmtColl * const>(m_pColl) ))
528 : {
529 0 : pCntntNd->ChgFmtColl( m_pColl );
530 : }
531 : }
532 0 : else if ( USHRT_MAX != pDoc->GetGrfFmtColls()->GetPos(
533 0 : static_cast<SwGrfFmtColl * const>(m_pColl) ))
534 : {
535 0 : pCntntNd->ChgFmtColl( m_pColl );
536 : }
537 : }
538 0 : }
539 :
540 0 : SwHistoryTxtFlyCnt::SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt )
541 : : SwHistoryHint( HSTRY_FLYCNT )
542 0 : , m_pUndo( new SwUndoDelLayFmt( pFlyFmt ) )
543 : {
544 : OSL_ENSURE( pFlyFmt, "SwHistoryTxtFlyCnt: no Format" );
545 0 : m_pUndo->ChgShowSel( sal_False );
546 0 : }
547 :
548 0 : SwHistoryTxtFlyCnt::~SwHistoryTxtFlyCnt()
549 : {
550 0 : }
551 :
552 0 : void SwHistoryTxtFlyCnt::SetInDoc( SwDoc* pDoc, bool )
553 : {
554 0 : ::sw::IShellCursorSupplier *const pISCS(pDoc->GetIShellCursorSupplier());
555 : OSL_ASSERT(pISCS);
556 0 : ::sw::UndoRedoContext context(*pDoc, *pISCS);
557 0 : m_pUndo->UndoImpl(context);
558 0 : }
559 :
560 1347 : SwHistoryBookmark::SwHistoryBookmark(
561 : const ::sw::mark::IMark& rBkmk,
562 : bool bSavePos,
563 : bool bSaveOtherPos)
564 : : SwHistoryHint(HSTRY_BOOKMARK)
565 1347 : , m_aName(rBkmk.GetName())
566 : , m_aShortName()
567 : , m_aKeycode()
568 : , m_nNode(bSavePos ?
569 1247 : rBkmk.GetMarkPos().nNode.GetIndex() : 0)
570 : , m_nOtherNode(bSaveOtherPos ?
571 1205 : rBkmk.GetOtherMarkPos().nNode.GetIndex() : 0)
572 : , m_nCntnt(bSavePos ?
573 1247 : rBkmk.GetMarkPos().nContent.GetIndex() : 0)
574 : , m_nOtherCntnt(bSaveOtherPos ?
575 1205 : rBkmk.GetOtherMarkPos().nContent.GetIndex() :0)
576 : , m_bSavePos(bSavePos)
577 : , m_bSaveOtherPos(bSaveOtherPos)
578 1347 : , m_bHadOtherPos(rBkmk.IsExpanded())
579 8945 : , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk))
580 : {
581 1347 : const ::sw::mark::IBookmark* const pBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(&rBkmk);
582 1347 : if(pBookmark)
583 : {
584 1270 : m_aKeycode = pBookmark->GetKeyCode();
585 1270 : m_aShortName = pBookmark->GetShortName();
586 :
587 : ::sfx2::Metadatable const*const pMetadatable(
588 1270 : dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
589 1270 : if (pMetadatable)
590 : {
591 1270 : m_pMetadataUndo = pMetadatable->CreateUndo();
592 : }
593 : }
594 1347 : }
595 :
596 0 : void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool )
597 : {
598 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
599 :
600 0 : SwNodes& rNds = pDoc->GetNodes();
601 0 : IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
602 0 : ::std::auto_ptr<SwPaM> pPam;
603 0 : ::sw::mark::IMark* pMark = NULL;
604 :
605 0 : if(m_bSavePos)
606 : {
607 0 : SwCntntNode* const pCntntNd = rNds[m_nNode]->GetCntntNode();
608 : OSL_ENSURE(pCntntNd,
609 : "<SwHistoryBookmark::SetInDoc(..)>"
610 : " - wrong node for a mark");
611 :
612 : // #111660# don't crash when nNode1 doesn't point to content node.
613 0 : if(pCntntNd)
614 0 : pPam = ::std::auto_ptr<SwPaM>(new SwPaM(*pCntntNd, m_nCntnt));
615 : }
616 : else
617 : {
618 0 : pMark = pMarkAccess->findMark(m_aName)->get();
619 0 : pPam = ::std::auto_ptr<SwPaM>(new SwPaM(pMark->GetMarkPos()));
620 : }
621 :
622 0 : if(m_bSaveOtherPos)
623 : {
624 0 : SwCntntNode* const pCntntNd = rNds[m_nOtherNode]->GetCntntNode();
625 : OSL_ENSURE(pCntntNd,
626 : "<SwHistoryBookmark::SetInDoc(..)>"
627 : " - wrong node for a mark");
628 :
629 0 : if(pPam.get() != NULL && pCntntNd)
630 : {
631 0 : pPam->SetMark();
632 0 : pPam->GetMark()->nNode = m_nOtherNode;
633 0 : pPam->GetMark()->nContent.Assign(pCntntNd, m_nOtherCntnt);
634 : }
635 : }
636 0 : else if(m_bHadOtherPos)
637 : {
638 0 : if(!pMark)
639 0 : pMark = pMarkAccess->findMark(m_aName)->get();
640 : OSL_ENSURE(pMark->IsExpanded(),
641 : "<SwHistoryBookmark::SetInDoc(..)>"
642 : " - missing pos on old mark");
643 0 : pPam->SetMark();
644 0 : *pPam->GetMark() = pMark->GetOtherMarkPos();
645 : }
646 :
647 0 : if(pPam.get())
648 : {
649 0 : if(pMark)
650 0 : pMarkAccess->deleteMark(pMark);
651 : ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(
652 0 : pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType));
653 0 : if(pBookmark)
654 : {
655 0 : pBookmark->SetKeyCode(m_aKeycode);
656 0 : pBookmark->SetShortName(m_aShortName);
657 0 : if (m_pMetadataUndo)
658 : {
659 : ::sfx2::Metadatable * const pMeta(
660 0 : dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
661 : OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
662 0 : if (pMeta)
663 : {
664 0 : pMeta->RestoreMetadata(m_pMetadataUndo);
665 : }
666 : }
667 : }
668 0 : }
669 0 : }
670 :
671 0 : bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk)
672 : {
673 0 : return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex()
674 0 : && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex()
675 0 : && m_aName == rBkmk.GetName();
676 : }
677 :
678 1038 : const OUString& SwHistoryBookmark::GetName() const
679 : {
680 1038 : return m_aName;
681 : }
682 :
683 10 : SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet,
684 : sal_uLong nNodePos, const std::set<sal_uInt16> &rSetArr )
685 : : SwHistoryHint( HSTRY_SETATTRSET )
686 : , m_OldSet( rSet )
687 : , m_ResetArray( 0, 4 )
688 10 : , m_nNodeIndex( nNodePos )
689 : {
690 20 : SfxItemIter aIter( m_OldSet ), aOrigIter( rSet );
691 10 : const SfxPoolItem* pItem = aIter.FirstItem(),
692 10 : * pOrigItem = aOrigIter.FirstItem();
693 : do {
694 22 : if( !rSetArr.count( pOrigItem->Which() ))
695 : {
696 0 : m_ResetArray.push_back( pOrigItem->Which() );
697 0 : m_OldSet.ClearItem( pOrigItem->Which() );
698 : }
699 : else
700 : {
701 22 : switch ( pItem->Which() )
702 : {
703 : case RES_PAGEDESC:
704 : static_cast<SwFmtPageDesc*>(
705 0 : const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
706 0 : break;
707 :
708 : case RES_PARATR_DROP:
709 : static_cast<SwFmtDrop*>(
710 0 : const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
711 0 : break;
712 :
713 : case RES_BOXATR_FORMULA:
714 : {
715 : // When a formula is set, never save the value. It
716 : // possibly must be recalculated!
717 : // Save formulas always in plain text
718 0 : m_OldSet.ClearItem( RES_BOXATR_VALUE );
719 :
720 : SwTblBoxFormula& rNew =
721 : *static_cast<SwTblBoxFormula*>(
722 0 : const_cast<SfxPoolItem*>(pItem));
723 0 : if ( rNew.IsIntrnlName() )
724 : {
725 : const SwTblBoxFormula& rOld =
726 : static_cast<const SwTblBoxFormula&>(
727 0 : rSet.Get( RES_BOXATR_FORMULA ));
728 0 : const SwNode* pNd = rOld.GetNodeOfFormula();
729 0 : if ( pNd )
730 : {
731 : const SwTableNode* pTableNode
732 0 : = pNd->FindTableNode();
733 0 : if (pTableNode)
734 : {
735 : SwTableFmlUpdate aMsgHnt(
736 0 : &pTableNode->GetTable() );
737 0 : aMsgHnt.eFlags = TBL_BOXNAME;
738 0 : rNew.ChgDefinedIn( rOld.GetDefinedIn() );
739 0 : rNew.ChangeState( &aMsgHnt );
740 : }
741 : }
742 : }
743 0 : rNew.ChgDefinedIn( 0 );
744 : }
745 0 : break;
746 : }
747 : }
748 :
749 22 : if( aIter.IsAtEnd() )
750 10 : break;
751 12 : pItem = aIter.NextItem();
752 12 : pOrigItem = aOrigIter.NextItem();
753 10 : } while( true );
754 10 : }
755 :
756 0 : void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool )
757 : {
758 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
759 :
760 0 : SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
761 0 : if ( pNode->IsCntntNode() )
762 : {
763 0 : static_cast<SwCntntNode*>(pNode)->SetAttr( m_OldSet );
764 0 : if ( !m_ResetArray.empty() )
765 : {
766 0 : static_cast<SwCntntNode*>(pNode)->ResetAttr( m_ResetArray );
767 : }
768 : }
769 0 : else if ( pNode->IsTableNode() )
770 : {
771 : SwFmt& rFmt =
772 0 : *static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt();
773 0 : rFmt.SetFmtAttr( m_OldSet );
774 0 : if ( !m_ResetArray.empty() )
775 : {
776 0 : rFmt.ResetFmtAttr( m_ResetArray.front() );
777 : }
778 0 : }
779 0 : }
780 :
781 399 : SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet,
782 : sal_uLong nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd )
783 : : SwHistoryHint( HSTRY_RESETATTRSET )
784 : , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd )
785 399 : , m_Array( (sal_uInt8)rSet.Count() )
786 : {
787 399 : SfxItemIter aIter( rSet );
788 399 : bool bAutoStyle = false;
789 :
790 : while( true )
791 : {
792 399 : const sal_uInt16 nWhich = aIter.GetCurItem()->Which();
793 :
794 : #ifdef DBG_UTIL
795 : switch (nWhich)
796 : {
797 : case RES_TXTATR_REFMARK:
798 : case RES_TXTATR_TOXMARK:
799 : if (m_nStart != m_nEnd) break; // else: fall through!
800 : case RES_TXTATR_FIELD:
801 : case RES_TXTATR_FLYCNT:
802 : case RES_TXTATR_FTN:
803 : case RES_TXTATR_META:
804 : case RES_TXTATR_METAFIELD:
805 : OSL_ENSURE(rSet.Count() == 1,
806 : "text attribute with CH_TXTATR, but not the only one:"
807 : "\nnot such a good idea");
808 : break;
809 : }
810 : #endif // DBG_UTIL
811 :
812 : // Character attribute cannot be inserted into the hints array
813 : // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT:
814 399 : if (isCHRATR(nWhich))
815 : {
816 54 : bAutoStyle = true;
817 : }
818 : else
819 : {
820 345 : m_Array.push_back( aIter.GetCurItem()->Which() );
821 : }
822 :
823 399 : if( aIter.IsAtEnd() )
824 399 : break;
825 :
826 0 : aIter.NextItem();
827 : }
828 :
829 399 : if ( bAutoStyle )
830 : {
831 54 : m_Array.push_back( RES_TXTATR_AUTOFMT );
832 399 : }
833 399 : }
834 :
835 0 : void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool )
836 : {
837 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
838 :
839 0 : SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
840 : OSL_ENSURE( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" );
841 :
842 0 : if (pCntntNd)
843 : {
844 0 : std::vector<sal_uInt16>::iterator it;
845 0 : if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart )
846 : {
847 : // no area: use ContentNode
848 0 : for ( it = m_Array.begin(); it != m_Array.end(); ++it )
849 : {
850 0 : pCntntNd->ResetAttr( *it );
851 : }
852 : }
853 : else
854 : {
855 : // area: use TextNode
856 0 : for ( it = m_Array.begin(); it != m_Array.end(); ++it )
857 : {
858 : static_cast<SwTxtNode*>(pCntntNd)->
859 0 : DeleteAttributes( *it, m_nStart, m_nEnd );
860 : }
861 : }
862 0 : }
863 0 : }
864 :
865 0 : SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt )
866 : : SwHistoryHint( HSTRY_CHGFLYANCHOR )
867 : , m_rFmt( rFmt )
868 0 : , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() )
869 0 : , m_nOldContentIndex( (FLY_AT_CHAR == rFmt.GetAnchor().GetAnchorId())
870 0 : ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex()
871 0 : : STRING_MAXLEN )
872 : {
873 0 : }
874 :
875 :
876 0 : void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool )
877 : {
878 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
879 :
880 0 : sal_uInt16 nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt );
881 0 : if ( USHRT_MAX != nPos ) // Format does still exist
882 : {
883 0 : SwFmtAnchor aTmp( m_rFmt.GetAnchor() );
884 :
885 0 : SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ];
886 0 : SwCntntNode* pCNd = pNd->GetCntntNode();
887 0 : SwPosition aPos( *pNd );
888 0 : if ( STRING_MAXLEN != m_nOldContentIndex )
889 : {
890 : OSL_ENSURE(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode");
891 0 : if (pCNd)
892 : {
893 0 : aPos.nContent.Assign( pCNd, m_nOldContentIndex );
894 : }
895 : }
896 0 : aTmp.SetAnchor( &aPos );
897 :
898 : // so the Layout does not get confused
899 0 : if ( !pCNd || !pCNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_False ) )
900 : {
901 0 : m_rFmt.DelFrms();
902 : }
903 :
904 0 : m_rFmt.SetFmtAttr( aTmp );
905 0 : }
906 0 : }
907 :
908 0 : SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt,
909 : const SwFmtChain& rAttr )
910 : : SwHistoryHint( HSTRY_CHGFLYCHAIN )
911 0 : , m_pPrevFmt( rAttr.GetPrev() )
912 0 : , m_pNextFmt( rAttr.GetNext() )
913 0 : , m_pFlyFmt( &rFmt )
914 : {
915 0 : }
916 :
917 0 : void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool )
918 : {
919 0 : if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) )
920 : {
921 0 : SwFmtChain aChain;
922 :
923 0 : if ( m_pPrevFmt &&
924 0 : USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) )
925 : {
926 0 : aChain.SetPrev( m_pPrevFmt );
927 0 : SwFmtChain aTmp( m_pPrevFmt->GetChain() );
928 0 : aTmp.SetNext( m_pFlyFmt );
929 0 : m_pPrevFmt->SetFmtAttr( aTmp );
930 : }
931 :
932 0 : if ( m_pNextFmt &&
933 0 : USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) )
934 : {
935 0 : aChain.SetNext( m_pNextFmt );
936 0 : SwFmtChain aTmp( m_pNextFmt->GetChain() );
937 0 : aTmp.SetPrev( m_pFlyFmt );
938 0 : m_pNextFmt->SetFmtAttr( aTmp );
939 : }
940 :
941 0 : if ( aChain.GetNext() || aChain.GetPrev() )
942 : {
943 0 : m_pFlyFmt->SetFmtAttr( aChain );
944 0 : }
945 : }
946 0 : }
947 :
948 : // -> #i27615#
949 0 : SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet,
950 : const String & sFmt)
951 : : SwHistoryHint(HSTRY_CHGCHARFMT)
952 0 : , m_OldSet(rSet), m_Fmt(sFmt)
953 : {
954 0 : }
955 :
956 0 : void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool )
957 : {
958 0 : SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt);
959 :
960 0 : if (pCharFmt)
961 : {
962 0 : pCharFmt->SetFmtAttr(m_OldSet);
963 : }
964 0 : }
965 : // <- #i27615#
966 :
967 :
968 2429 : SwHistory::SwHistory( sal_uInt16 nInitSz )
969 : : m_SwpHstry()
970 2429 : , m_nEndDiff( 0 )
971 : {
972 2429 : m_SwpHstry.reserve( (sal_uInt8)nInitSz );
973 2429 : }
974 :
975 4858 : SwHistory::~SwHistory()
976 : {
977 2429 : Delete( 0 );
978 2429 : }
979 :
980 1124 : void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue,
981 : sal_uLong nNodeIdx )
982 : {
983 : OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
984 :
985 1124 : sal_uInt16 nWhich = pNewValue->Which();
986 1124 : if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) )
987 1124 : return;
988 :
989 : // no default attribute?
990 : SwHistoryHint * pHt;
991 1124 : if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) )
992 : {
993 1113 : pHt = new SwHistorySetFmt( pOldValue, nNodeIdx );
994 : }
995 : else
996 : {
997 11 : pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx );
998 : }
999 1124 : m_SwpHstry.push_back( pHt );
1000 : }
1001 :
1002 : // FIXME: refactor the following "Add" methods (DRY)?
1003 593 : void SwHistory::Add( SwTxtAttr* pHint, sal_uLong nNodeIdx, bool bNewAttr )
1004 : {
1005 : OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
1006 :
1007 : SwHistoryHint * pHt;
1008 593 : sal_uInt16 nAttrWhich = pHint->Which();
1009 :
1010 593 : if( !bNewAttr )
1011 : {
1012 265 : switch ( nAttrWhich )
1013 : {
1014 : case RES_TXTATR_FTN:
1015 : pHt = new SwHistorySetFootnote(
1016 13 : static_cast<SwTxtFtn*>(pHint), nNodeIdx );
1017 13 : break;
1018 : case RES_TXTATR_FLYCNT:
1019 : pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint)
1020 0 : ->GetFlyCnt().GetFrmFmt() );
1021 0 : break;
1022 : case RES_TXTATR_FIELD:
1023 : pHt = new SwHistorySetTxtFld(
1024 22 : static_cast<SwTxtFld*>(pHint), nNodeIdx );
1025 22 : break;
1026 : case RES_TXTATR_TOXMARK:
1027 : pHt = new SwHistorySetTOXMark(
1028 13 : static_cast<SwTxtTOXMark*>(pHint), nNodeIdx );
1029 13 : break;
1030 : case RES_TXTATR_REFMARK:
1031 : pHt = new SwHistorySetRefMark(
1032 12 : static_cast<SwTxtRefMark*>(pHint), nNodeIdx );
1033 12 : break;
1034 : default:
1035 : pHt = new SwHistorySetTxt(
1036 205 : static_cast<SwTxtAttr*>(pHint), nNodeIdx );
1037 : }
1038 : }
1039 : else
1040 : {
1041 656 : pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(),
1042 656 : *pHint->GetAnyEnd(), nNodeIdx );
1043 : }
1044 593 : m_SwpHstry.push_back( pHt );
1045 593 : }
1046 :
1047 41 : void SwHistory::Add( SwFmtColl* pColl, sal_uLong nNodeIdx, sal_uInt8 nWhichNd )
1048 : {
1049 : OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
1050 :
1051 : SwHistoryHint * pHt =
1052 41 : new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd );
1053 41 : m_SwpHstry.push_back( pHt );
1054 41 : }
1055 :
1056 309 : void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos)
1057 : {
1058 : OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
1059 :
1060 309 : SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos);
1061 309 : m_SwpHstry.push_back( pHt );
1062 309 : }
1063 :
1064 0 : void SwHistory::Add( SwFrmFmt& rFmt )
1065 : {
1066 0 : SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt );
1067 0 : m_SwpHstry.push_back( pHt );
1068 0 : }
1069 :
1070 0 : void SwHistory::Add( SwFlyFrmFmt& rFmt, sal_uInt16& rSetPos )
1071 : {
1072 : OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
1073 :
1074 0 : const sal_uInt16 nWh = rFmt.Which();
1075 0 : if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh )
1076 : {
1077 0 : SwHistoryHint * pHint = new SwHistoryTxtFlyCnt( &rFmt );
1078 0 : m_SwpHstry.push_back( pHint );
1079 :
1080 : const SwFmtChain* pChainItem;
1081 0 : if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, sal_False,
1082 0 : (const SfxPoolItem**)&pChainItem ))
1083 : {
1084 0 : if( pChainItem->GetNext() || pChainItem->GetPrev() )
1085 : {
1086 : SwHistoryHint * pHt =
1087 0 : new SwHistoryChangeFlyChain( rFmt, *pChainItem );
1088 0 : m_SwpHstry.insert( m_SwpHstry.begin() + rSetPos++, pHt );
1089 0 : if ( pChainItem->GetNext() )
1090 : {
1091 0 : SwFmtChain aTmp( pChainItem->GetNext()->GetChain() );
1092 0 : aTmp.SetPrev( 0 );
1093 0 : pChainItem->GetNext()->SetFmtAttr( aTmp );
1094 : }
1095 0 : if ( pChainItem->GetPrev() )
1096 : {
1097 0 : SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() );
1098 0 : aTmp.SetNext( 0 );
1099 0 : pChainItem->GetPrev()->SetFmtAttr( aTmp );
1100 : }
1101 : }
1102 0 : rFmt.ResetFmtAttr( RES_CHAIN );
1103 : }
1104 : }
1105 0 : }
1106 :
1107 2 : void SwHistory::Add( const SwTxtFtn& rFtn )
1108 : {
1109 2 : SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn );
1110 2 : m_SwpHstry.push_back( pHt );
1111 2 : }
1112 :
1113 : // #i27615#
1114 0 : void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt)
1115 : {
1116 0 : SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName());
1117 0 : m_SwpHstry.push_back( pHt );
1118 0 : }
1119 :
1120 0 : bool SwHistory::Rollback( SwDoc* pDoc, sal_uInt16 nStart )
1121 : {
1122 0 : if ( !Count() )
1123 0 : return false;
1124 :
1125 : SwHistoryHint * pHHt;
1126 : sal_uInt16 i;
1127 0 : for ( i = Count(); i > nStart ; )
1128 : {
1129 0 : pHHt = m_SwpHstry[ --i ];
1130 0 : pHHt->SetInDoc( pDoc, false );
1131 0 : delete pHHt;
1132 : }
1133 0 : m_SwpHstry.erase( m_SwpHstry.begin() + nStart, m_SwpHstry.end() );
1134 0 : m_nEndDiff = 0;
1135 0 : return true;
1136 : }
1137 :
1138 0 : bool SwHistory::TmpRollback( SwDoc* pDoc, sal_uInt16 nStart, bool bToFirst )
1139 : {
1140 0 : sal_uInt16 nEnd = Count() - m_nEndDiff;
1141 0 : if ( !Count() || !nEnd || nStart >= nEnd )
1142 0 : return false;
1143 :
1144 : SwHistoryHint * pHHt;
1145 0 : if ( bToFirst )
1146 : {
1147 0 : for ( ; nEnd > nStart; ++m_nEndDiff )
1148 : {
1149 0 : pHHt = m_SwpHstry[ --nEnd ];
1150 0 : pHHt->SetInDoc( pDoc, true );
1151 : }
1152 : }
1153 : else
1154 : {
1155 0 : for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart )
1156 : {
1157 0 : pHHt = m_SwpHstry[ nStart ];
1158 0 : pHHt->SetInDoc( pDoc, true );
1159 : }
1160 : }
1161 0 : return true;
1162 : }
1163 :
1164 2429 : void SwHistory::Delete( sal_uInt16 nStart )
1165 : {
1166 8686 : for ( sal_uInt16 n = Count(); n > nStart; )
1167 : {
1168 3828 : delete m_SwpHstry[ --n ];
1169 3828 : m_SwpHstry.erase( m_SwpHstry.begin() + n );
1170 : }
1171 2429 : m_nEndDiff = 0;
1172 2429 : }
1173 :
1174 0 : sal_uInt16 SwHistory::SetTmpEnd( sal_uInt16 nNewTmpEnd )
1175 : {
1176 : OSL_ENSURE( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" );
1177 :
1178 0 : sal_uInt16 nOld = Count() - m_nEndDiff;
1179 0 : m_nEndDiff = Count() - nNewTmpEnd;
1180 :
1181 : // for every SwHistoryFlyCnt, call the Redo of its UndoObject.
1182 : // this saves the formats of the flys!
1183 0 : for ( sal_uInt16 n = nOld; n < nNewTmpEnd; n++ )
1184 : {
1185 0 : if ( HSTRY_FLYCNT == (*this)[ n ]->Which() )
1186 : {
1187 0 : static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ])
1188 0 : ->GetUDelLFmt()->RedoForRollback();
1189 : }
1190 : }
1191 :
1192 0 : return nOld;
1193 : }
1194 :
1195 51 : void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx )
1196 : {
1197 51 : if( rSet.Count() )
1198 : {
1199 51 : SfxItemIter aIter( rSet );
1200 : do {
1201 1113 : if( (SfxPoolItem*)-1 != aIter.GetCurItem() )
1202 : {
1203 1113 : const SfxPoolItem* pNew = aIter.GetCurItem();
1204 1113 : Add( pNew, pNew, nNodeIdx );
1205 : }
1206 1113 : if( aIter.IsAtEnd() )
1207 51 : break;
1208 1062 : aIter.NextItem();
1209 51 : } while( true );
1210 : }
1211 51 : }
1212 :
1213 566 : void SwHistory::CopyAttr( SwpHints* pHts, sal_uLong nNodeIdx,
1214 : xub_StrLen nStart, xub_StrLen nEnd, bool bFields )
1215 : {
1216 566 : if( !pHts )
1217 1073 : return;
1218 :
1219 : // copy all attributes of the TextNode in the area from nStart to nEnd
1220 : SwTxtAttr* pHt;
1221 : xub_StrLen nAttrStt;
1222 : const xub_StrLen * pEndIdx;
1223 184 : for( sal_uInt16 n = 0; n < pHts->Count(); n++ )
1224 : {
1225 : // nAttrStt must even be set when !pEndIdx
1226 125 : pHt = pHts->GetTextHint(n);
1227 125 : nAttrStt = *pHt->GetStart();
1228 125 : if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd )
1229 0 : break;
1230 :
1231 : // never copy Flys and Ftn !!
1232 125 : bool bNextAttr = false;
1233 125 : switch( pHt->Which() )
1234 : {
1235 : case RES_TXTATR_FIELD:
1236 : // no fields, ... copy ??
1237 24 : if( !bFields )
1238 2 : bNextAttr = true;
1239 24 : break;
1240 : case RES_TXTATR_FLYCNT:
1241 : case RES_TXTATR_FTN:
1242 0 : bNextAttr = true;
1243 0 : break;
1244 : }
1245 :
1246 125 : if( bNextAttr )
1247 2 : continue;
1248 :
1249 : // save all attributes that are somehow in this area
1250 123 : if ( nStart <= nAttrStt )
1251 : {
1252 123 : if ( nEnd > nAttrStt
1253 : )
1254 : {
1255 83 : Add( pHt, nNodeIdx, false );
1256 : }
1257 : }
1258 0 : else if ( pEndIdx && nStart < *pEndIdx )
1259 : {
1260 0 : Add( pHt, nNodeIdx, false );
1261 : }
1262 : }
1263 : }
1264 :
1265 : // Class to register the history at a Node, Format, HintsArray, ...
1266 0 : SwRegHistory::SwRegHistory( SwHistory* pHst )
1267 : : SwClient( 0 )
1268 : , m_pHistory( pHst )
1269 0 : , m_nNodeIndex( ULONG_MAX )
1270 : {
1271 0 : _MakeSetWhichIds();
1272 0 : }
1273 :
1274 16054 : SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd,
1275 : SwHistory* pHst )
1276 : : SwClient( pRegIn )
1277 : , m_pHistory( pHst )
1278 16054 : , m_nNodeIndex( rNd.GetIndex() )
1279 : {
1280 16054 : _MakeSetWhichIds();
1281 16054 : }
1282 :
1283 801 : SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst )
1284 : : SwClient( 0 )
1285 : , m_pHistory( pHst )
1286 801 : , m_nNodeIndex( rNd.GetIndex() )
1287 : {
1288 801 : _MakeSetWhichIds();
1289 801 : }
1290 :
1291 16091 : void SwRegHistory::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
1292 : {
1293 : // #i114861#
1294 : // Do not handle a "noop" modify
1295 : // - e.g. <SwTxtNode::NumRuleChgd()> uses such a "noop" modify
1296 16091 : if ( m_pHistory && ( pOld || pNew ) &&
1297 : pOld != pNew )
1298 : {
1299 1973 : if ( pNew->Which() < POOLATTR_END )
1300 : {
1301 11 : m_pHistory->Add( pOld, pNew, m_nNodeIndex );
1302 : }
1303 1962 : else if ( RES_ATTRSET_CHG == pNew->Which() )
1304 : {
1305 : SwHistoryHint* pNewHstr;
1306 : const SfxItemSet& rSet =
1307 1360 : *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet();
1308 1360 : if ( 1 < rSet.Count() )
1309 : {
1310 : pNewHstr =
1311 10 : new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet );
1312 : }
1313 : else
1314 : {
1315 1350 : const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem();
1316 1350 : if ( m_WhichIdSet.count( pItem->Which() ) )
1317 : {
1318 469 : pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex );
1319 : }
1320 : else
1321 : {
1322 881 : pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex );
1323 : }
1324 : }
1325 1360 : m_pHistory->m_SwpHstry.push_back( pNewHstr );
1326 : }
1327 : }
1328 16091 : }
1329 :
1330 497 : void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew )
1331 : {
1332 497 : m_pHistory->Add( pHt, m_nNodeIndex, bNew );
1333 497 : }
1334 :
1335 10738 : bool SwRegHistory::InsertItems( const SfxItemSet& rSet,
1336 : xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags )
1337 : {
1338 10738 : if( !rSet.Count() )
1339 0 : return false;
1340 :
1341 : SwTxtNode * const pTxtNode =
1342 10738 : dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn()));
1343 :
1344 : OSL_ENSURE(pTxtNode, "SwRegHistory not registered at text node?");
1345 10738 : if (!pTxtNode)
1346 0 : return false;
1347 :
1348 10738 : if ( pTxtNode->GetpSwpHints() && m_pHistory )
1349 : {
1350 258 : pTxtNode->GetpSwpHints()->Register( this );
1351 : }
1352 :
1353 10738 : const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags );
1354 :
1355 : // Caution: The array can be deleted when inserting an attribute!
1356 : // This can happen when the value that should be added first deletes
1357 : // an existing attribute but does not need to be added itself because
1358 : // the paragraph attributes are identical
1359 : // ( -> bForgetAttr in SwpHints::Insert )
1360 10738 : if ( pTxtNode->GetpSwpHints() && m_pHistory )
1361 : {
1362 365 : pTxtNode->GetpSwpHints()->DeRegister();
1363 : }
1364 :
1365 10738 : if ( m_pHistory && bInserted )
1366 : {
1367 : SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet,
1368 399 : pTxtNode->GetIndex(), nStart, nEnd );
1369 : // the NodeIndex might be moved!
1370 :
1371 399 : m_pHistory->m_SwpHstry.push_back( pNewHstr );
1372 : }
1373 :
1374 10738 : return bInserted;
1375 : }
1376 :
1377 0 : void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd )
1378 : {
1379 0 : if ( m_pHistory && pRegIn )
1380 : {
1381 0 : pRegIn->Add( this );
1382 0 : m_nNodeIndex = rNd.GetIndex();
1383 0 : _MakeSetWhichIds();
1384 : }
1385 : else
1386 : {
1387 0 : m_WhichIdSet.clear();
1388 : }
1389 0 : }
1390 :
1391 16855 : void SwRegHistory::_MakeSetWhichIds()
1392 : {
1393 33710 : if (!m_pHistory) return;
1394 :
1395 2722 : m_WhichIdSet.clear();
1396 :
1397 2722 : if( GetRegisteredIn() )
1398 : {
1399 1921 : const SfxItemSet* pSet = 0;
1400 1921 : if( GetRegisteredIn()->ISA( SwCntntNode ) )
1401 : {
1402 : pSet = static_cast<SwCntntNode*>(
1403 1921 : const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet();
1404 : }
1405 0 : else if ( GetRegisteredIn()->ISA( SwFmt ) )
1406 : {
1407 : pSet = &static_cast<SwFmt*>(
1408 0 : const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet();
1409 : }
1410 1921 : if( pSet && pSet->Count() )
1411 : {
1412 1578 : SfxItemIter aIter( *pSet );
1413 1578 : sal_uInt16 nW = aIter.FirstItem()->Which();
1414 : while( true )
1415 : {
1416 21276 : m_WhichIdSet.insert( nW );
1417 21276 : if( aIter.IsAtEnd() )
1418 1578 : break;
1419 19698 : nW = aIter.NextItem()->Which();
1420 1578 : }
1421 : }
1422 : }
1423 : }
1424 :
1425 4858 : SwpHstry::~SwpHstry()
1426 : {
1427 2429 : for(const_iterator it = begin(); it != end(); ++it)
1428 0 : delete *it;
1429 2528 : }
1430 :
1431 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|