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