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