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 <cellatr.hxx>
21 : #include <charfmt.hxx>
22 : #include <cmdid.h>
23 : #include <doc.hxx>
24 : #include <IDocumentListsAccess.hxx>
25 : #include <editeng/colritem.hxx>
26 : #include <editeng/brushitem.hxx>
27 : #include <editeng/lineitem.hxx>
28 : #include <editeng/boxitem.hxx>
29 : #include <editeng/editeng.hxx>
30 : #include <fmtanchr.hxx>
31 : #include <fmtpdsc.hxx>
32 : #include <hintids.hxx>
33 : #include <istyleaccess.hxx>
34 : #include <list.hxx>
35 : #include <node.hxx>
36 : #include <numrule.hxx>
37 : #include <pagedesc.hxx>
38 : #include <paratr.hxx>
39 : #include <svl/whiter.hxx>
40 : #include <svx/xtable.hxx>
41 :
42 : #include <svx/svdpool.hxx>
43 : #include <svx/sxenditm.hxx>
44 : #include <svx/sdsxyitm.hxx>
45 :
46 3017 : SwAttrPool::SwAttrPool( SwDoc* pD )
47 : : SfxItemPool( OUString("SWG"),
48 : POOLATTR_BEGIN, POOLATTR_END-1,
49 : aSlotTab, aAttrTab ),
50 3017 : pDoc( pD )
51 : {
52 3017 : SetVersionMap( 1, 1, 60, pVersionMap1 );
53 3017 : SetVersionMap( 2, 1, 75, pVersionMap2 );
54 3017 : SetVersionMap( 3, 1, 86, pVersionMap3 );
55 3017 : SetVersionMap( 4, 1,121, pVersionMap4 );
56 : // #i18732# - apply new version map
57 3017 : SetVersionMap( 5, 1,130, pVersionMap5 );
58 3017 : SetVersionMap( 6, 1,136, pVersionMap6 );
59 3017 : SetVersionMap( 7, 1,144, pVersionMap7 );
60 :
61 : //UUUU create secondary pools immediately
62 3017 : createAndAddSecondaryPools();
63 3017 : }
64 :
65 9024 : SwAttrPool::~SwAttrPool()
66 : {
67 : //UUUU cleanup secondary pools first
68 3008 : removeAndDeleteSecondaryPools();
69 6016 : }
70 :
71 : //UUUU
72 3017 : void SwAttrPool::createAndAddSecondaryPools()
73 : {
74 3017 : const SfxItemPool* pCheckAlreadySet = GetSecondaryPool();
75 :
76 3017 : if(pCheckAlreadySet)
77 : {
78 : OSL_ENSURE(false, "SwAttrPool already has a secondary pool (!)");
79 3017 : return;
80 : }
81 :
82 : // create SfxItemPool and EditEngine pool and add these in a chain. These
83 : // belong us and will be removed/destroyed in removeAndDeleteSecondaryPools() used from
84 : // the destructor
85 3017 : SfxItemPool *pSdrPool = new SdrItemPool(this);
86 :
87 : // #75371# change DefaultItems for the SdrEdgeObj distance items
88 : // to TWIPS.
89 : // 1/100th mm in twips
90 3017 : const long nDefEdgeDist = ((500 * 72) / 127);
91 :
92 3017 : pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
93 3017 : pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
94 3017 : pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
95 3017 : pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
96 :
97 : // #i33700# // Set shadow distance defaults as PoolDefaultItems
98 3017 : pSdrPool->SetPoolDefaultItem(makeSdrShadowXDistItem((300 * 72) / 127));
99 3017 : pSdrPool->SetPoolDefaultItem(makeSdrShadowYDistItem((300 * 72) / 127));
100 :
101 3017 : SfxItemPool *pEEgPool = EditEngine::CreatePool(false);
102 :
103 3017 : pSdrPool->SetSecondaryPool(pEEgPool);
104 :
105 3017 : if(!GetFrozenIdRanges())
106 : {
107 3017 : FreezeIdRanges();
108 : }
109 : else
110 : {
111 0 : pSdrPool->FreezeIdRanges();
112 : }
113 : }
114 :
115 : //UUUU
116 3008 : void SwAttrPool::removeAndDeleteSecondaryPools()
117 : {
118 3008 : SfxItemPool *pSdrPool = GetSecondaryPool();
119 :
120 3008 : if(!pSdrPool)
121 : {
122 : OSL_ENSURE(false, "SwAttrPool has no secondary pool, it's missing (!)");
123 0 : return;
124 : }
125 :
126 3008 : SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
127 :
128 3008 : if(!pEEgPool)
129 : {
130 : OSL_ENSURE(false, "i don't accept additional pools");
131 0 : return;
132 : }
133 :
134 : // first delete the items, then break the linking
135 3008 : pSdrPool->Delete();
136 :
137 3008 : SetSecondaryPool(0);
138 3008 : pSdrPool->SetSecondaryPool(0);
139 :
140 : // final cleanup of secondary pool(s)
141 3008 : SfxItemPool::Free(pSdrPool);
142 3008 : SfxItemPool::Free(pEEgPool);
143 : }
144 :
145 0 : SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 )
146 0 : : SfxItemSet( rPool, nWh1, nWh2 ), pOldSet( 0 ), pNewSet( 0 )
147 : {
148 0 : }
149 :
150 7489299 : SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable )
151 7489299 : : SfxItemSet( rPool, nWhichPairTable ), pOldSet( 0 ), pNewSet( 0 )
152 : {
153 7489299 : }
154 :
155 1277373 : SwAttrSet::SwAttrSet( const SwAttrSet& rSet )
156 1277373 : : SfxItemSet( rSet ), pOldSet( 0 ), pNewSet( 0 )
157 : {
158 1277373 : }
159 :
160 23211 : SfxItemSet* SwAttrSet::Clone( bool bItems, SfxItemPool *pToPool ) const
161 : {
162 23211 : if ( pToPool && pToPool != GetPool() )
163 : {
164 0 : SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool);
165 0 : SfxItemSet* pTmpSet = 0;
166 0 : if ( !pAttrPool )
167 0 : pTmpSet = SfxItemSet::Clone( bItems, pToPool );
168 : else
169 : {
170 0 : pTmpSet = new SwAttrSet( *pAttrPool, GetRanges() );
171 0 : if ( bItems )
172 : {
173 0 : SfxWhichIter aIter(*pTmpSet);
174 0 : sal_uInt16 nWhich = aIter.FirstWhich();
175 0 : while ( nWhich )
176 : {
177 : const SfxPoolItem* pItem;
178 0 : if ( SfxItemState::SET == GetItemState( nWhich, false, &pItem ) )
179 0 : pTmpSet->Put( *pItem, pItem->Which() );
180 0 : nWhich = aIter.NextWhich();
181 0 : }
182 : }
183 : }
184 0 : return pTmpSet;
185 : }
186 : else
187 : return bItems
188 23211 : ? new SwAttrSet( *this )
189 46422 : : new SwAttrSet( *GetPool(), GetRanges() );
190 : }
191 :
192 1744203 : bool SwAttrSet::Put_BC( const SfxPoolItem& rAttr,
193 : SwAttrSet* pOld, SwAttrSet* pNew )
194 : {
195 1744203 : pNewSet = pNew;
196 1744203 : pOldSet = pOld;
197 1744203 : bool nRet = 0 != SfxItemSet::Put( rAttr );
198 1744203 : pOldSet = pNewSet = 0;
199 1744203 : return nRet;
200 : }
201 :
202 329239 : bool SwAttrSet::Put_BC( const SfxItemSet& rSet,
203 : SwAttrSet* pOld, SwAttrSet* pNew )
204 : {
205 329239 : pNewSet = pNew;
206 329239 : pOldSet = pOld;
207 329239 : bool nRet = SfxItemSet::Put( rSet );
208 329239 : pOldSet = pNewSet = 0;
209 329239 : return nRet;
210 : }
211 :
212 41388 : sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich,
213 : SwAttrSet* pOld, SwAttrSet* pNew )
214 : {
215 41388 : pNewSet = pNew;
216 41388 : pOldSet = pOld;
217 41388 : sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich );
218 41388 : pOldSet = pNewSet = 0;
219 41388 : return nRet;
220 : }
221 :
222 1356151 : sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2,
223 : SwAttrSet* pOld, SwAttrSet* pNew )
224 : {
225 : OSL_ENSURE( nWhich1 <= nWhich2, "no valid range" );
226 1356151 : pNewSet = pNew;
227 1356151 : pOldSet = pOld;
228 1356151 : sal_uInt16 nRet = 0;
229 2721583 : for( ; nWhich1 <= nWhich2; ++nWhich1 )
230 1365432 : nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
231 1356151 : pOldSet = pNewSet = 0;
232 1356151 : return nRet;
233 : }
234 :
235 43374 : int SwAttrSet::Intersect_BC( const SfxItemSet& rSet,
236 : SwAttrSet* pOld, SwAttrSet* pNew )
237 : {
238 43374 : pNewSet = pNew;
239 43374 : pOldSet = pOld;
240 43374 : SfxItemSet::Intersect( rSet );
241 43374 : pOldSet = pNewSet = 0;
242 43374 : return pNew ? pNew->Count() : ( pOld ? pOld->Count() : 0 );
243 : }
244 :
245 : /// Notification callback
246 2530594 : void SwAttrSet::Changed( const SfxPoolItem& rOld, const SfxPoolItem& rNew )
247 : {
248 2530594 : if( pOldSet )
249 1792037 : pOldSet->PutChgd( rOld );
250 2530594 : if( pNewSet )
251 1792037 : pNewSet->PutChgd( rNew );
252 2530594 : }
253 :
254 : /** special treatment for some attributes
255 :
256 : Set the Modify pointer (old pDefinedIn) for the following attributes:
257 : - SwFormatDropCaps
258 : - SwFormatPageDesc
259 :
260 : (Is called at inserts into formats/nodes)
261 : */
262 1768900 : bool SwAttrSet::SetModifyAtAttr( const SwModify* pModify )
263 : {
264 1768900 : bool bSet = false;
265 :
266 : const SfxPoolItem* pItem;
267 1792164 : if( SfxItemState::SET == GetItemState( RES_PAGEDESC, false, &pItem ) &&
268 23264 : static_cast<const SwFormatPageDesc*>(pItem)->GetDefinedIn() != pModify )
269 : {
270 23197 : const_cast<SwFormatPageDesc*>(static_cast<const SwFormatPageDesc*>(pItem))->ChgDefinedIn( pModify );
271 23197 : bSet = true;
272 : }
273 :
274 1768936 : if( SfxItemState::SET == GetItemState( RES_PARATR_DROP, false, &pItem ) &&
275 36 : static_cast<const SwFormatDrop*>(pItem)->GetDefinedIn() != pModify )
276 : {
277 : // If CharFormat is set and it is set in different attribute pools then
278 : // the CharFormat has to be copied.
279 : SwCharFormat* pCharFormat;
280 64 : if( 0 != ( pCharFormat = const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->GetCharFormat() )
281 32 : && GetPool() != pCharFormat->GetAttrSet().GetPool() )
282 : {
283 0 : pCharFormat = GetDoc()->CopyCharFormat( *pCharFormat );
284 0 : const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->SetCharFormat( pCharFormat );
285 : }
286 32 : const_cast<SwFormatDrop*>(static_cast<const SwFormatDrop*>(pItem))->ChgDefinedIn( pModify );
287 32 : bSet = true;
288 : }
289 :
290 1768900 : if( SfxItemState::SET == GetItemState( RES_BOXATR_FORMULA, false, &pItem ) &&
291 0 : static_cast<const SwTableBoxFormula*>(pItem)->GetDefinedIn() != pModify )
292 : {
293 0 : const_cast<SwTableBoxFormula*>(static_cast<const SwTableBoxFormula*>(pItem))->ChgDefinedIn( pModify );
294 0 : bSet = true;
295 : }
296 :
297 1768900 : return bSet;
298 : }
299 :
300 3294 : void SwAttrSet::CopyToModify( SwModify& rMod ) const
301 : {
302 : // copy attributes across multiple documents if needed
303 3294 : SwContentNode* pCNd = PTR_CAST( SwContentNode, &rMod );
304 3294 : SwFormat* pFormat = PTR_CAST( SwFormat, &rMod );
305 :
306 3294 : if( pCNd || pFormat )
307 : {
308 3294 : if( Count() )
309 : {
310 : // #i92811#
311 3293 : SfxStringItem* pNewListIdItem( 0 );
312 :
313 : const SfxPoolItem* pItem;
314 3293 : const SwDoc *pSrcDoc = GetDoc();
315 3293 : SwDoc *pDstDoc = pCNd ? pCNd->GetDoc() : pFormat->GetDoc();
316 :
317 : // Does the NumRule has to be copied?
318 3795 : if( pSrcDoc != pDstDoc &&
319 502 : SfxItemState::SET == GetItemState( RES_PARATR_NUMRULE, false, &pItem ) )
320 : {
321 60 : const OUString& rNm = static_cast<const SwNumRuleItem*>(pItem)->GetValue();
322 60 : if( !rNm.isEmpty() )
323 : {
324 60 : SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm );
325 60 : if( pDestRule )
326 49 : pDestRule->SetInvalidRule( true );
327 : else
328 11 : pDstDoc->MakeNumRule( rNm, pSrcDoc->FindNumRulePtr( rNm ) );
329 : }
330 : }
331 :
332 : // copy list and if needed also the corresponding list style
333 : // for text nodes
334 3795 : if ( pSrcDoc != pDstDoc &&
335 4171 : pCNd && pCNd->IsTextNode() &&
336 439 : GetItemState( RES_PARATR_LIST_ID, false, &pItem ) == SfxItemState::SET )
337 : {
338 : const OUString& sListId =
339 60 : dynamic_cast<const SfxStringItem*>(pItem)->GetValue();
340 120 : if ( !sListId.isEmpty() &&
341 60 : !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
342 : {
343 0 : const SwList* pList = pSrcDoc->getIDocumentListsAccess().getListByName( sListId );
344 : // copy list style, if needed
345 : const OUString sDefaultListStyleName =
346 0 : pList->GetDefaultListStyleName();
347 : // #i92811#
348 : const SwNumRule* pDstDocNumRule =
349 0 : pDstDoc->FindNumRulePtr( sDefaultListStyleName );
350 0 : if ( !pDstDocNumRule )
351 : {
352 : pDstDoc->MakeNumRule( sDefaultListStyleName,
353 0 : pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) );
354 : }
355 : else
356 : {
357 : const SwNumRule* pSrcDocNumRule =
358 0 : pSrcDoc->FindNumRulePtr( sDefaultListStyleName );
359 : // If list id of text node equals the list style's
360 : // default list id in the source document, the same
361 : // should be hold in the destination document.
362 : // Thus, create new list id item.
363 0 : if (pSrcDocNumRule && sListId == pSrcDocNumRule->GetDefaultListId())
364 : {
365 : pNewListIdItem = new SfxStringItem (
366 : RES_PARATR_LIST_ID,
367 0 : pDstDocNumRule->GetDefaultListId() );
368 : }
369 : }
370 : // check again, if list exist, because <SwDoc::MakeNumRule(..)>
371 : // could have also created it.
372 0 : if ( pNewListIdItem == 0 &&
373 0 : !pDstDoc->getIDocumentListsAccess().getListByName( sListId ) )
374 : {
375 : // copy list
376 0 : pDstDoc->getIDocumentListsAccess().createList( sListId, sDefaultListStyleName );
377 0 : }
378 : }
379 : }
380 :
381 3293 : boost::scoped_ptr< SfxItemSet > tmpSet;
382 :
383 : const SwPageDesc* pPgDesc;
384 3795 : if( pSrcDoc != pDstDoc && SfxItemState::SET == GetItemState(
385 3316 : RES_PAGEDESC, false, &pItem ) &&
386 23 : 0 != ( pPgDesc = static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc()) )
387 : {
388 23 : if( !tmpSet )
389 23 : tmpSet.reset( new SfxItemSet( *this ));
390 :
391 23 : SwPageDesc* pDstPgDesc = pDstDoc->FindPageDesc(pPgDesc->GetName());
392 23 : if( !pDstPgDesc )
393 : {
394 0 : pDstPgDesc = pDstDoc->MakePageDesc(pPgDesc->GetName());
395 0 : pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc );
396 : }
397 23 : SwFormatPageDesc aDesc( pDstPgDesc );
398 23 : aDesc.SetNumOffset( static_cast<const SwFormatPageDesc*>(pItem)->GetNumOffset() );
399 23 : tmpSet->Put( aDesc );
400 : }
401 :
402 3795 : if( pSrcDoc != pDstDoc && SfxItemState::SET == GetItemState( RES_ANCHOR, false, &pItem )
403 3329 : && static_cast< const SwFormatAnchor* >( pItem )->GetContentAnchor() != NULL )
404 : {
405 18 : if( !tmpSet )
406 18 : tmpSet.reset( new SfxItemSet( *this ));
407 : // Anchors at any node position cannot be copied to another document, because the SwPosition
408 : // would still point to the old document. It needs to be fixed up explicitly.
409 18 : tmpSet->ClearItem( RES_ANCHOR );
410 : }
411 :
412 3293 : if( tmpSet )
413 : {
414 41 : if( pCNd )
415 : {
416 : // #i92811#
417 21 : if ( pNewListIdItem != 0 )
418 : {
419 0 : tmpSet->Put( *pNewListIdItem );
420 : }
421 21 : pCNd->SetAttr( *tmpSet );
422 : }
423 : else
424 : {
425 20 : pFormat->SetFormatAttr( *tmpSet );
426 : }
427 : }
428 3252 : else if( pCNd )
429 : {
430 : // #i92811#
431 3209 : if ( pNewListIdItem != 0 )
432 : {
433 0 : SfxItemSet aTmpSet( *this );
434 0 : aTmpSet.Put( *pNewListIdItem );
435 0 : pCNd->SetAttr( aTmpSet );
436 : }
437 : else
438 : {
439 3209 : pCNd->SetAttr( *this );
440 : }
441 : }
442 : else
443 : {
444 43 : pFormat->SetFormatAttr( *this );
445 : }
446 :
447 : // #i92811#
448 3293 : delete pNewListIdItem;
449 3293 : pNewListIdItem = 0;
450 : }
451 : }
452 : #if OSL_DEBUG_LEVEL > 0
453 : else
454 : OSL_FAIL("neither Format nor ContentNode - no Attributes copied");
455 : #endif
456 3294 : }
457 :
458 : /// check if ID is in range of attribute set IDs
459 22038 : bool IsInRange( const sal_uInt16* pRange, const sal_uInt16 nId )
460 : {
461 104565 : while( *pRange )
462 : {
463 62364 : if( *pRange <= nId && nId <= *(pRange+1) )
464 1875 : return true;
465 60489 : pRange += 2;
466 : }
467 20163 : return false;
468 177 : }
469 :
470 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|