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