LibreOffice Module sw (master)  1
swatrset.cxx
Go to the documentation of this file.
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 <memory>
21 
22 #include <cellatr.hxx>
23 #include <charfmt.hxx>
24 #include <doc.hxx>
25 #include <IDocumentListsAccess.hxx>
26 #include <editeng/editeng.hxx>
27 #include <fmtanchr.hxx>
28 #include <fmtpdsc.hxx>
29 #include <hintids.hxx>
30 #include <list.hxx>
31 #include <node.hxx>
32 #include <numrule.hxx>
33 #include <pagedesc.hxx>
34 #include <paratr.hxx>
35 #include <osl/diagnose.h>
36 #include <svl/whiter.hxx>
37 
38 #include <svx/svdpool.hxx>
39 #include <svx/sxenditm.hxx>
40 #include <svx/sdsxyitm.hxx>
41 
43  : SfxItemPool( "SWG",
45  aSlotTab, &aAttrTab ),
46  m_pDoc( pD )
47 {
48  // create secondary pools immediately
50 }
51 
53 {
54  // cleanup secondary pools first
56 }
57 
59 {
60  const SfxItemPool* pCheckAlreadySet = GetSecondaryPool();
61 
62  if(pCheckAlreadySet)
63  {
64  OSL_ENSURE(false, "SwAttrPool already has a secondary pool (!)");
65  return;
66  }
67 
68  // create SfxItemPool and EditEngine pool and add these in a chain. These
69  // belong us and will be removed/destroyed in removeAndDeleteSecondaryPools() used from
70  // the destructor
71  SfxItemPool *pSdrPool = new SdrItemPool(this);
72 
73  // #75371# change DefaultItems for the SdrEdgeObj distance items
74  // to TWIPS.
75  // 1/100th mm in twips
76  const long nDefEdgeDist = (500 * 72) / 127;
77 
78  pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
79  pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
80  pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
81  pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
82 
83  // #i33700# // Set shadow distance defaults as PoolDefaultItems
84  pSdrPool->SetPoolDefaultItem(makeSdrShadowXDistItem((300 * 72) / 127));
85  pSdrPool->SetPoolDefaultItem(makeSdrShadowYDistItem((300 * 72) / 127));
86 
87  SfxItemPool *pEEgPool = EditEngine::CreatePool();
88 
89  pSdrPool->SetSecondaryPool(pEEgPool);
90 
91  if(!GetFrozenIdRanges())
92  {
94  }
95  else
96  {
97  pSdrPool->FreezeIdRanges();
98  }
99 }
100 
102 {
103  SfxItemPool *pSdrPool = GetSecondaryPool();
104 
105  if(!pSdrPool)
106  {
107  OSL_ENSURE(false, "SwAttrPool has no secondary pool, it's missing (!)");
108  return;
109  }
110 
111  SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
112 
113  if(!pEEgPool)
114  {
115  OSL_ENSURE(false, "i don't accept additional pools");
116  return;
117  }
118 
119  // first delete the items, then break the linking
120  pSdrPool->Delete();
121 
122  SetSecondaryPool(nullptr);
123  pSdrPool->SetSecondaryPool(nullptr);
124 
125  // final cleanup of secondary pool(s)
126  SfxItemPool::Free(pSdrPool);
127  SfxItemPool::Free(pEEgPool);
128 }
129 
130 SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 )
131  : SfxItemSet( rPool, {{nWh1, nWh2}} ), m_pOldSet( nullptr ), m_pNewSet( nullptr )
132 {
133 }
134 
135 SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable )
136  : SfxItemSet( rPool, nWhichPairTable ), m_pOldSet( nullptr ), m_pNewSet( nullptr )
137 {
138 }
139 
141  : SfxItemSet( rSet ), m_pOldSet( nullptr ), m_pNewSet( nullptr )
142 {
143 }
144 
145 std::unique_ptr<SfxItemSet> SwAttrSet::Clone( bool bItems, SfxItemPool *pToPool ) const
146 {
147  if ( pToPool && pToPool != GetPool() )
148  {
149  SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool);
150  std::unique_ptr<SfxItemSet> pTmpSet;
151  if ( !pAttrPool )
152  pTmpSet = SfxItemSet::Clone( bItems, pToPool );
153  else
154  {
155  pTmpSet.reset(new SwAttrSet( *pAttrPool, GetRanges() ));
156  if ( bItems )
157  {
158  SfxWhichIter aIter(*pTmpSet);
159  sal_uInt16 nWhich = aIter.FirstWhich();
160  while ( nWhich )
161  {
162  const SfxPoolItem* pItem;
163  if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
164  pTmpSet->Put( *pItem );
165  nWhich = aIter.NextWhich();
166  }
167  }
168  }
169  return pTmpSet;
170  }
171  else
172  return std::unique_ptr<SfxItemSet>(
173  bItems
174  ? new SwAttrSet( *this )
175  : new SwAttrSet( *GetPool(), GetRanges() ));
176 }
177 
178 bool SwAttrSet::Put_BC( const SfxPoolItem& rAttr,
179  SwAttrSet* pOld, SwAttrSet* pNew )
180 {
181  m_pNewSet = pNew;
182  m_pOldSet = pOld;
183  bool bRet = nullptr != SfxItemSet::Put( rAttr );
184  m_pOldSet = m_pNewSet = nullptr;
185  return bRet;
186 }
187 
188 bool SwAttrSet::Put_BC( const SfxItemSet& rSet,
189  SwAttrSet* pOld, SwAttrSet* pNew )
190 {
191  m_pNewSet = pNew;
192  m_pOldSet = pOld;
193  bool bRet = SfxItemSet::Put( rSet );
194  m_pOldSet = m_pNewSet = nullptr;
195  return bRet;
196 }
197 
198 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich,
199  SwAttrSet* pOld, SwAttrSet* pNew )
200 {
201  m_pNewSet = pNew;
202  m_pOldSet = pOld;
203  sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich );
204  m_pOldSet = m_pNewSet = nullptr;
205  return nRet;
206 }
207 
208 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2,
209  SwAttrSet* pOld, SwAttrSet* pNew )
210 {
211  OSL_ENSURE( nWhich1 <= nWhich2, "no valid range" );
212  m_pNewSet = pNew;
213  m_pOldSet = pOld;
214  sal_uInt16 nRet = 0;
215  for( ; nWhich1 <= nWhich2; ++nWhich1 )
216  nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
217  m_pOldSet = m_pNewSet = nullptr;
218  return nRet;
219 }
220 
222  SwAttrSet* pOld, SwAttrSet* pNew )
223 {
224  m_pNewSet = pNew;
225  m_pOldSet = pOld;
226  SfxItemSet::Intersect( rSet );
227  m_pOldSet = m_pNewSet = nullptr;
228  return pNew ? pNew->Count() : ( pOld ? pOld->Count() : 0 );
229 }
230 
232 void SwAttrSet::Changed( const SfxPoolItem& rOld, const SfxPoolItem& rNew )
233 {
234  if( m_pOldSet )
235  m_pOldSet->PutChgd( rOld );
236  if( m_pNewSet )
237  m_pNewSet->PutChgd( rNew );
238 }
239 
248 bool SwAttrSet::SetModifyAtAttr( const SwModify* pModify )
249 {
250  bool bSet = false;
251 
252  const SfxPoolItem* pItem;
253  if( SfxItemState::SET == GetItemState( RES_PAGEDESC, false, &pItem ) &&
254  static_cast<const SwFormatPageDesc*>(pItem)->GetDefinedIn() != pModify )
255  {
256  const_cast<SwFormatPageDesc*>(static_cast<const SwFormatPageDesc*>(pItem))->ChgDefinedIn( pModify );
257  bSet = true;
258  }
259 
260  if( SfxItemState::SET == GetItemState( RES_PARATR_DROP, false, &pItem ) &&
261  static_cast<const SwFormatDrop*>(pItem)->GetDefinedIn() != pModify )
262  {
263  // If CharFormat is set and it is set in different attribute pools then
264  // the CharFormat has to be copied.
265  SwCharFormat* pCharFormat;
266  if( nullptr != ( pCharFormat = const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->GetCharFormat() )
267  && GetPool() != pCharFormat->GetAttrSet().GetPool() )
268  {
269  pCharFormat = GetDoc()->CopyCharFormat( *pCharFormat );
270  const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->SetCharFormat( pCharFormat );
271  }
272  const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->ChgDefinedIn( pModify );
273  bSet = true;
274  }
275 
276  if( SfxItemState::SET == GetItemState( RES_BOXATR_FORMULA, false, &pItem ) &&
277  static_cast<const SwTableBoxFormula*>(pItem)->GetDefinedIn() != pModify )
278  {
279  const_cast<SwTableBoxFormula*>(static_cast<const SwTableBoxFormula*>(pItem))->ChgDefinedIn( pModify );
280  bSet = true;
281  }
282 
283  return bSet;
284 }
285 
287 {
288  // copy attributes across multiple documents if needed
289  SwContentNode* pCNd = dynamic_cast<SwContentNode*>( &rMod );
290  SwFormat* pFormat = dynamic_cast<SwFormat*>( &rMod );
291 
292  if( pCNd || pFormat )
293  {
294  if( Count() )
295  {
296  // #i92811#
297  std::unique_ptr<SfxStringItem> pNewListIdItem;
298 
299  const SfxPoolItem* pItem;
300  const SwDoc *pSrcDoc = GetDoc();
301  SwDoc *pDstDoc = pCNd ? pCNd->GetDoc() : pFormat->GetDoc();
302 
303  // Does the NumRule has to be copied?
304  if( pSrcDoc != pDstDoc &&
305  SfxItemState::SET == GetItemState( RES_PARATR_NUMRULE, false, &pItem ) )
306  {
307  const OUString& rNm = static_cast<const SwNumRuleItem*>(pItem)->GetValue();
308  if( !rNm.isEmpty() )
309  {
310  SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm );
311  if( pDestRule )
312  pDestRule->SetInvalidRule( true );
313  else
314  pDstDoc->MakeNumRule( rNm, pSrcDoc->FindNumRulePtr( rNm ) );
315  }
316  }
317 
318  // copy list and if needed also the corresponding list style
319  // for text nodes
320  if ( pSrcDoc != pDstDoc &&
321  pCNd && pCNd->IsTextNode() &&
322  GetItemState( RES_PARATR_LIST_ID, false, &pItem ) == SfxItemState::SET )
323  {
324  auto pStrItem = dynamic_cast<const SfxStringItem*>(pItem);
325  assert(pStrItem);
326  const OUString& sListId = pStrItem->GetValue();
327  if ( !sListId.isEmpty() &&
328  !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
329  {
330  const SwList* pList = pSrcDoc->getIDocumentListsAccess().getListByName( sListId );
331  // copy list style, if needed
332  const OUString& sDefaultListStyleName =
333  pList->GetDefaultListStyleName();
334  // #i92811#
335  const SwNumRule* pDstDocNumRule =
336  pDstDoc->FindNumRulePtr( sDefaultListStyleName );
337  if ( !pDstDocNumRule )
338  {
339  pDstDoc->MakeNumRule( sDefaultListStyleName,
340  pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) );
341  }
342  else
343  {
344  const SwNumRule* pSrcDocNumRule =
345  pSrcDoc->FindNumRulePtr( sDefaultListStyleName );
346  // If list id of text node equals the list style's
347  // default list id in the source document, the same
348  // should be hold in the destination document.
349  // Thus, create new list id item.
350  if (pSrcDocNumRule && sListId == pSrcDocNumRule->GetDefaultListId())
351  {
352  pNewListIdItem.reset(new SfxStringItem (
354  pDstDocNumRule->GetDefaultListId() ));
355  }
356  }
357  // check again, if list exist, because <SwDoc::MakeNumRule(..)>
358  // could have also created it.
359  if ( pNewListIdItem == nullptr &&
360  !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
361  {
362  // copy list
363  pDstDoc->getIDocumentListsAccess().createList( sListId, sDefaultListStyleName );
364  }
365  }
366  }
367 
368  std::unique_ptr< SfxItemSet > tmpSet;
369 
370  const SwPageDesc* pPgDesc;
371  if( pSrcDoc != pDstDoc && SfxItemState::SET == GetItemState(
372  RES_PAGEDESC, false, &pItem ) &&
373  nullptr != ( pPgDesc = static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc()) )
374  {
375  tmpSet.reset(new SfxItemSet(*this));
376 
377  SwPageDesc* pDstPgDesc = pDstDoc->FindPageDesc(pPgDesc->GetName());
378  if( !pDstPgDesc )
379  {
380  pDstPgDesc = pDstDoc->MakePageDesc(pPgDesc->GetName());
381  pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc );
382  }
383  SwFormatPageDesc aDesc( pDstPgDesc );
384  aDesc.SetNumOffset( static_cast<const SwFormatPageDesc*>(pItem)->GetNumOffset() );
385  tmpSet->Put( aDesc );
386  }
387 
388  if( pSrcDoc != pDstDoc && SfxItemState::SET == GetItemState( RES_ANCHOR, false, &pItem )
389  && static_cast< const SwFormatAnchor* >( pItem )->GetContentAnchor() != nullptr )
390  {
391  if( !tmpSet )
392  tmpSet.reset( new SfxItemSet( *this ));
393  // Anchors at any node position cannot be copied to another document, because the SwPosition
394  // would still point to the old document. It needs to be fixed up explicitly.
395  tmpSet->ClearItem( RES_ANCHOR );
396  }
397 
398  if( tmpSet )
399  {
400  if( pCNd )
401  {
402  // #i92811#
403  if ( pNewListIdItem != nullptr )
404  {
405  tmpSet->Put( *pNewListIdItem );
406  }
407  pCNd->SetAttr( *tmpSet );
408  }
409  else
410  {
411  pFormat->SetFormatAttr( *tmpSet );
412  }
413  }
414  else if( pCNd )
415  {
416  // #i92811#
417  if ( pNewListIdItem != nullptr )
418  {
419  SfxItemSet aTmpSet( *this );
420  aTmpSet.Put( *pNewListIdItem );
421  pCNd->SetAttr( aTmpSet );
422  }
423  else
424  {
425  pCNd->SetAttr( *this );
426  }
427  }
428  else
429  {
430  pFormat->SetFormatAttr( *this );
431  }
432  }
433  }
434 #if OSL_DEBUG_LEVEL > 0
435  else
436  OSL_FAIL("neither Format nor ContentNode - no Attributes copied");
437 #endif
438 }
439 
441 bool IsInRange( const sal_uInt16* pRange, const sal_uInt16 nId )
442 {
443  while( *pRange )
444  {
445  if( *pRange <= nId && nId <= *(pRange+1) )
446  return true;
447  pRange += 2;
448  }
449  return false;
450 }
451 
452 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ChgDefinedIn(const SwModify *pNew)
Definition: fmtpdsc.hxx:70
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SW_DLLPUBLIC const OUString & GetDefaultListStyleName() const
Definition: list.cxx:233
virtual void Changed(const SfxPoolItem &rOld, const SfxPoolItem &rNew) override
Notification callback.
Definition: swatrset.cxx:232
std::string GetValue
SfxItemSet(const SfxItemSet &)
SwAttrPool(SwDoc *pDoc)
Definition: swatrset.cxx:42
virtual SwList * createList(const OUString &rListId, const OUString &rDefaultListStyleName)=0
const OUString & GetDefaultListId() const
Definition: numrule.hxx:192
Definition: list.hxx:35
Definition: doc.hxx:185
sal_uInt16 FirstWhich()
#define RES_PARATR_LIST_ID
Definition: hintids.hxx:185
void Delete()
void FreezeIdRanges()
void ChgDefinedIn(const SwModify *pNew)
Definition: paratr.hxx:106
sal_uInt16 NextWhich()
const OUString & GetName() const
Definition: pagedesc.hxx:186
#define POOLATTR_END
Definition: hintids.hxx:64
void PutChgd(const SfxPoolItem &rI)
Definition: swatrset.hxx:169
bool Put_BC(const SfxPoolItem &rAttr, SwAttrSet *pOld, SwAttrSet *pNew)
Definition: swatrset.cxx:178
const sal_uInt16 * GetFrozenIdRanges() const
bool SetModifyAtAttr(const SwModify *pModify)
special treatment for some attributes
Definition: swatrset.cxx:248
void removeAndDeleteSecondaryPools()
Definition: swatrset.cxx:101
void SetNumOffset(const ::boost::optional< sal_uInt16 > &oNum)
Definition: fmtpdsc.hxx:66
bool IsInRange(const sal_uInt16 *pRange, const sal_uInt16 nId)
check if ID is in range of attribute set IDs
Definition: swatrset.cxx:441
#define RES_PARATR_NUMRULE
Definition: hintids.hxx:170
void Intersect(const SfxItemSet &rSet)
SwAttrPool * GetPool() const
Definition: swatrset.hxx:190
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const override
Definition: swatrset.cxx:145
SwPageDesc * FindPageDesc(const OUString &rName, size_t *pPos=nullptr) const
Definition: docdesc.cxx:829
Base class for various Writer styles.
Definition: format.hxx:43
SwAttrSet * m_pNewSet
Definition: swatrset.hxx:164
#define POOLATTR_BEGIN
Definition: hintids.hxx:63
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2423
virtual SwList * getListByName(const OUString &rListId) const =0
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
#define RES_ANCHOR
Definition: hintids.hxx:209
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void CopyToModify(SwModify &rMod) const
Definition: swatrset.cxx:286
SwPageDesc * MakePageDesc(const OUString &rName, const SwPageDesc *pCpy=nullptr, bool bRegardLanguage=true, bool bBroadcast=false)
Definition: docdesc.cxx:646
sal_uInt16 Count() const
SwDoc * GetDoc()
Definition: node.hxx:702
void createAndAddSecondaryPools()
Definition: swatrset.cxx:58
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
void ChgDefinedIn(const SwModify *pNew)
Definition: cellatr.hxx:65
int Intersect_BC(const SfxItemSet &rSet, SwAttrSet *pOld, SwAttrSet *pNew)
Definition: swatrset.cxx:221
SdrMetricItem makeSdrShadowYDistItem(long nDist)
static SfxItemPool * CreatePool()
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
SfxItemPool * GetSecondaryPool() const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
void CopyPageDesc(const SwPageDesc &rSrcDesc, SwPageDesc &rDstDesc, bool bCopyPoolIds=true)
Copy the complete PageDesc - beyond document and "deep"! Optionally copying of PoolFormatId, -HlpId can be prevented.
Definition: docfmt.cxx:1427
static void Free(SfxItemPool *pPool)
void SetInvalidRule(bool bFlag)
Definition: number.cxx:862
virtual bool SetAttr(const SfxPoolItem &)
made virtual
Definition: node.cxx:1485
SfxItemInfo aSlotTab[]
Definition: init.cxx:269
virtual ~SwAttrPool() override
Definition: swatrset.cxx:52
virtual std::unique_ptr< SfxItemSet > Clone(bool bItems=true, SfxItemPool *pToPool=nullptr) const
SwCharFormat * CopyCharFormat(const SwCharFormat &)
copy the char format
Definition: docfmt.cxx:1180
SwDfltAttrTab aAttrTab
const SwFormatPageDesc & GetPageDesc(bool=true) const
Definition: fmtpdsc.hxx:76
const SwDoc * GetDoc() const
Definition: swatrset.hxx:204
sal_uInt16 MakeNumRule(const OUString &rName, const SwNumRule *pCpy=nullptr, bool bBroadcast=false, const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode=SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
Definition: docnum.cxx:2457
SwAttrSet * m_pOldSet
Definition: swatrset.hxx:164
SwAttrSet(SwAttrPool &, sal_uInt16 nWhich1, sal_uInt16 nWhich2)
Definition: swatrset.cxx:130
const sal_uInt16 * GetRanges() const
#define RES_PARATR_DROP
Definition: hintids.hxx:168
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
If SwFormatDrop is a Client, it is the CharFormat that describes the font for the DropCaps...
Definition: paratr.hxx:50
#define RES_PAGEDESC
Definition: hintids.hxx:198
IDocumentListsAccess const & getIDocumentListsAccess() const
Definition: doc.cxx:325
bool IsTextNode() const
Definition: node.hxx:636
sal_uInt16 ClearItem_BC(sal_uInt16 nWhich, SwAttrSet *pOld, SwAttrSet *pNew)
Definition: swatrset.cxx:198
void SetSecondaryPool(SfxItemPool *pPool)
void SetCharFormat(SwCharFormat *pNew)
Definition: paratr.cxx:66
SdrMetricItem makeSdrShadowXDistItem(long nDist)
void SetPoolDefaultItem(const SfxPoolItem &)
#define RES_BOXATR_FORMULA
Definition: hintids.hxx:262