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