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