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( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue,
1043 sal_uLong nNodeIdx )
1044 {
1045 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1046
1047 sal_uInt16 nWhich = pNewValue->Which();
1048 if( (nWhich >= POOLATTR_END)
1049 || (nWhich == RES_TXTATR_FIELD)
1050 || (nWhich == RES_TXTATR_ANNOTATION) )
1051 return;
1052
1053 // no default Attribute?
1054 SwHistoryHint * pHt;
1055 if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) )
1056 {
1057 pHt = new SwHistorySetFmt( pOldValue, nNodeIdx );
1058 }
1059 else
1060 {
1061 pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx );
1062 }
1063 m_SwpHstry.Insert( pHt, Count() );
1064 }
1065
1066
Add(SwTxtAttr * pHint,sal_uLong nNodeIdx,bool bNewAttr)1067 void SwHistory::Add( SwTxtAttr* pHint, sal_uLong nNodeIdx, bool bNewAttr )
1068 {
1069 ASSERT( !m_nEndDiff, "History was not deleted after REDO" );
1070
1071 SwHistoryHint * pHt;
1072 sal_uInt16 nAttrWhich = pHint->Which();
1073
1074 if( !bNewAttr )
1075 {
1076 switch ( nAttrWhich )
1077 {
1078 case RES_TXTATR_FTN:
1079 pHt = new SwHistorySetFootnote(
1080 static_cast<SwTxtFtn*>(pHint), nNodeIdx );
1081 break;
1082 case RES_TXTATR_FLYCNT:
1083 pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint)
1084 ->GetFlyCnt().GetFrmFmt() );
1085 break;
1086 case RES_TXTATR_FIELD:
1087 case RES_TXTATR_ANNOTATION:
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
Add(SwFmtColl * pColl,sal_uLong nNodeIdx,sal_uInt8 nWhichNd)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
Add(const::sw::mark::IMark & rBkmk,bool bSavePos,bool bSaveOtherPos)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
Add(SwFrmFmt & rFmt)1132 void SwHistory::Add( SwFrmFmt& rFmt )
1133 {
1134 SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt );
1135 m_SwpHstry.Insert( pHt, Count() );
1136 }
1137
Add(SwFlyFrmFmt & rFmt,sal_uInt16 & rSetPos)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
Add(const SwTxtFtn & rFtn)1176 void SwHistory::Add( const SwTxtFtn& rFtn )
1177 {
1178 SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn );
1179 m_SwpHstry.Insert( pHt, Count() );
1180 }
1181
1182 // #i27615#
Add(const SfxItemSet & rSet,const SwCharFmt & rFmt)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
Rollback(SwDoc * pDoc,sal_uInt16 nStart)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
TmpRollback(SwDoc * pDoc,sal_uInt16 nStart,bool bToFirst)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
Delete(sal_uInt16 nStart)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
SetTmpEnd(sal_uInt16 nNewTmpEnd)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
CopyFmtAttr(const SfxItemSet & rSet,sal_uLong nNodeIdx)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
CopyAttr(SwpHints * pHts,const sal_uLong nNodeIdx,const xub_StrLen nStart,const xub_StrLen nEnd,const bool bCopyFields)1296 void SwHistory::CopyAttr(
1297 SwpHints* pHts,
1298 const sal_uLong nNodeIdx,
1299 const xub_StrLen nStart,
1300 const xub_StrLen nEnd,
1301 const bool bCopyFields )
1302 {
1303 if( !pHts )
1304 return;
1305
1306 // copy all attributes of the TextNode in the area from nStart to nEnd
1307 SwTxtAttr* pHt;
1308 xub_StrLen nAttrStt;
1309 const xub_StrLen * pEndIdx;
1310 for( sal_uInt16 n = 0; n < pHts->Count(); n++ )
1311 {
1312 pHt = pHts->GetTextHint(n);
1313 nAttrStt = *pHt->GetStart();
1314 if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd )
1315 break;
1316
1317 // Flys und Ftn nie kopieren !!
1318 sal_Bool bNextAttr = sal_False;
1319 switch( pHt->Which() )
1320 {
1321 case RES_TXTATR_FIELD:
1322 case RES_TXTATR_ANNOTATION:
1323 case RES_TXTATR_INPUTFIELD:
1324 if( !bCopyFields )
1325 bNextAttr = sal_True;
1326 break;
1327 case RES_TXTATR_FLYCNT:
1328 case RES_TXTATR_FTN:
1329 bNextAttr = sal_True;
1330 break;
1331 }
1332
1333 if( bNextAttr )
1334 continue;
1335
1336 // save all attributes that are somehow in this area
1337 if ( nStart <= nAttrStt )
1338 {
1339 if ( nEnd > nAttrStt )
1340 {
1341 Add( pHt, nNodeIdx, false );
1342 }
1343 }
1344 else if ( pEndIdx && nStart < *pEndIdx )
1345 {
1346 Add( pHt, nNodeIdx, false );
1347 }
1348 }
1349 }
1350
1351
1352 /*************************************************************************/
1353
1354 // Klasse zum Registrieren der History am Node, Format, HintsArray, ...
1355
SwRegHistory(SwHistory * pHst)1356 SwRegHistory::SwRegHistory( SwHistory* pHst )
1357 : SwClient( 0 )
1358 , m_pHistory( pHst )
1359 , m_nNodeIndex( ULONG_MAX )
1360 {
1361 _MakeSetWhichIds();
1362 }
1363
SwRegHistory(SwModify * pRegIn,const SwNode & rNd,SwHistory * pHst)1364 SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd,
1365 SwHistory* pHst )
1366 : SwClient( pRegIn )
1367 , m_pHistory( pHst )
1368 , m_nNodeIndex( rNd.GetIndex() )
1369 {
1370 _MakeSetWhichIds();
1371 }
1372
SwRegHistory(const SwNode & rNd,SwHistory * pHst)1373 SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst )
1374 : SwClient( 0 )
1375 , m_pHistory( pHst )
1376 , m_nNodeIndex( rNd.GetIndex() )
1377 {
1378 _MakeSetWhichIds();
1379 }
1380
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)1381 void SwRegHistory::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
1382 {
1383 // --> OD 2010-10-05 #i114861#
1384 // Do not handle a "noop" modify
1385 // - e.g. <SwTxtNode::NumRuleChgd()> uses such a "noop" modify
1386 // if ( m_pHistory && ( pOld || pNew ) )
1387 if ( m_pHistory && ( pOld || pNew ) &&
1388 pOld != pNew )
1389 // <--
1390 {
1391 if ( pNew->Which() < POOLATTR_END )
1392 {
1393 m_pHistory->Add( pOld, pNew, m_nNodeIndex );
1394 }
1395 else if ( RES_ATTRSET_CHG == pNew->Which() )
1396 {
1397 SwHistoryHint* pNewHstr;
1398 const SfxItemSet& rSet =
1399 *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet();
1400 if ( 1 < rSet.Count() )
1401 {
1402 pNewHstr =
1403 new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet );
1404 }
1405 else
1406 {
1407 const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem();
1408 if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) )
1409 {
1410 pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex );
1411 }
1412 else
1413 {
1414 pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex );
1415 }
1416 }
1417 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
1418 }
1419 }
1420 }
1421
1422
1423
AddHint(SwTxtAttr * pHt,const bool bNew)1424 void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew )
1425 {
1426 m_pHistory->Add( pHt, m_nNodeIndex, bNew );
1427 }
1428
1429
InsertItems(const SfxItemSet & rSet,xub_StrLen const nStart,xub_StrLen const nEnd,SetAttrMode const nFlags)1430 bool SwRegHistory::InsertItems( const SfxItemSet& rSet,
1431 xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags )
1432 {
1433 if( !rSet.Count() )
1434 return false;
1435
1436 SwTxtNode * const pTxtNode =
1437 dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn()));
1438
1439 ASSERT(pTxtNode, "SwRegHistory not registered at text node?");
1440 if (!pTxtNode)
1441 return false;
1442
1443 if ( pTxtNode->GetpSwpHints() && m_pHistory )
1444 {
1445 pTxtNode->GetpSwpHints()->Register( this );
1446 }
1447
1448 const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags );
1449
1450 // Achtung: Durch das Einfuegen eines Attributs kann das Array
1451 // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes
1452 // loescht, selbst aber nicht eingefuegt werden braucht, weil die
1453 // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert )
1454 if ( pTxtNode->GetpSwpHints() && m_pHistory )
1455 {
1456 pTxtNode->GetpSwpHints()->DeRegister();
1457 }
1458
1459 if ( m_pHistory && bInserted )
1460 {
1461 SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet,
1462 pTxtNode->GetIndex(), nStart, nEnd );
1463 // der NodeIndex kann verschoben sein !!
1464
1465 m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
1466 }
1467
1468 return bInserted;
1469 }
1470
RegisterInModify(SwModify * pRegIn,const SwNode & rNd)1471 void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd )
1472 {
1473 if ( m_pHistory && pRegIn )
1474 {
1475 pRegIn->Add( this );
1476 m_nNodeIndex = rNd.GetIndex();
1477 _MakeSetWhichIds();
1478 }
1479 else if ( m_WhichIdSet.Count() )
1480 {
1481 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
1482 }
1483 }
1484
_MakeSetWhichIds()1485 void SwRegHistory::_MakeSetWhichIds()
1486 {
1487 if (!m_pHistory) return;
1488
1489 if ( m_WhichIdSet.Count() )
1490 {
1491 m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
1492 }
1493
1494 if( GetRegisteredIn() )
1495 {
1496 const SfxItemSet* pSet = 0;
1497 if( GetRegisteredIn()->ISA( SwCntntNode ) )
1498 {
1499 pSet = static_cast<SwCntntNode*>(
1500 const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet();
1501 }
1502 else if ( GetRegisteredIn()->ISA( SwFmt ) )
1503 {
1504 pSet = &static_cast<SwFmt*>(
1505 const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet();
1506 }
1507 if( pSet && pSet->Count() )
1508 {
1509 SfxItemIter aIter( *pSet );
1510 sal_uInt16 nW = aIter.FirstItem()->Which();
1511 while( sal_True )
1512 {
1513 m_WhichIdSet.Insert( nW );
1514 if( aIter.IsAtEnd() )
1515 break;
1516 nW = aIter.NextItem()->Which();
1517 }
1518 }
1519 }
1520 }
1521
1522