1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sw.hxx"
24
25 #include <hintids.hxx>
26 #include <svl/whiter.hxx>
27 #include <editeng/colritem.hxx>
28 #include <editeng/brshitem.hxx>
29 #include <editeng/bolnitem.hxx>
30 #include <editeng/boxitem.hxx>
31 #include <svx/xtable.hxx>
32 #include <fmtpdsc.hxx>
33 #include <pagedesc.hxx>
34 #include <charfmt.hxx>
35 #include <doc.hxx>
36 #include <node.hxx>
37 #include <paratr.hxx> // fuer SetModifyAtAttr
38 #include <cellatr.hxx> // fuer SetModifyAtAttr
39 #ifndef _CMDID_H
40 #include <cmdid.h>
41 #endif
42 #include <istyleaccess.hxx>
43 #include <numrule.hxx>
44 #include <list.hxx>
45 #include <svx/svdpool.hxx>
46 #include <svx/sxenditm.hxx>
47 #include <svx/sdsxyitm.hxx>
48 #include <editeng/editeng.hxx>
49
SwAttrPool(SwDoc * pD)50 SwAttrPool::SwAttrPool( SwDoc* pD )
51 : SfxItemPool( String::CreateFromAscii(
52 RTL_CONSTASCII_STRINGPARAM( "SWG" )),
53 POOLATTR_BEGIN, POOLATTR_END-1,
54 aSlotTab, aAttrTab ),
55 pDoc( pD )
56 {
57 SetVersionMap( 1, 1, 60, pVersionMap1 );
58 SetVersionMap( 2, 1, 75, pVersionMap2 );
59 SetVersionMap( 3, 1, 86, pVersionMap3 );
60 SetVersionMap( 4, 1,121, pVersionMap4 );
61 // OD 2004-01-21 #i18732# - apply new version map
62 SetVersionMap( 5, 1,130, pVersionMap5 );
63 SetVersionMap( 6, 1,136, pVersionMap6 );
64
65 //UUUU create secondary pools immediately
66 createAndAddSecondaryPools();
67 }
68
~SwAttrPool()69 SwAttrPool::~SwAttrPool()
70 {
71 //UUUU cleanup secondary pools first
72 removeAndDeleteSecondaryPools();
73 }
74
75 //UUUU
createAndAddSecondaryPools()76 void SwAttrPool::createAndAddSecondaryPools()
77 {
78 const SfxItemPool* pCheckAlreadySet = GetSecondaryPool();
79
80 if(pCheckAlreadySet)
81 {
82 OSL_ENSURE(false, "SwAttrPool already has a secondary pool (!)");
83 return;
84 }
85
86 // create SfxItemPool and EditEngine pool and add these in a chain. These
87 // belomg us and will be removed/destroyed in removeAndDeleteSecondaryPools() used from
88 // the destructor
89 SfxItemPool *pSdrPool = new SdrItemPool(this);
90
91 // #75371# change DefaultItems for the SdrEdgeObj distance items
92 // to TWIPS.
93 if(pSdrPool)
94 {
95 // 1/100th mm in twips
96 const long nDefEdgeDist = ((500 * 72) / 127);
97
98 pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
99 pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
100 pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
101 pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
102
103 // #i33700# // Set shadow distance defaults as PoolDefaultItems
104 pSdrPool->SetPoolDefaultItem(SdrShadowXDistItem((300 * 72) / 127));
105 pSdrPool->SetPoolDefaultItem(SdrShadowYDistItem((300 * 72) / 127));
106 }
107
108 SfxItemPool *pEEgPool = EditEngine::CreatePool(sal_False);
109
110 pSdrPool->SetSecondaryPool(pEEgPool);
111
112 if(!GetFrozenIdRanges())
113 {
114 FreezeIdRanges();
115 }
116 else
117 {
118 pSdrPool->FreezeIdRanges();
119 }
120 }
121
122 //UUUU
removeAndDeleteSecondaryPools()123 void SwAttrPool::removeAndDeleteSecondaryPools()
124 {
125 SfxItemPool *pSdrPool = GetSecondaryPool();
126
127 if(!pSdrPool)
128 {
129 OSL_ENSURE(false, "SwAttrPool has no secondary pool, it's missing (!)");
130 return;
131 }
132
133 SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
134
135 if(!pEEgPool)
136 {
137 OSL_ENSURE(false, "i don't accept additional pools");
138 return;
139 }
140
141 // first delete the items, then break the linking
142 pSdrPool->Delete();
143
144 SetSecondaryPool(0);
145 pSdrPool->SetSecondaryPool(0);
146
147 // final cleanup of secondary pool(s)
148 SfxItemPool::Free(pSdrPool);
149 SfxItemPool::Free(pEEgPool);
150 }
151
SwAttrSet(SwAttrPool & rPool,sal_uInt16 nWh1,sal_uInt16 nWh2)152 SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 )
153 : SfxItemSet( rPool, nWh1, nWh2 ), pOldSet( 0 ), pNewSet( 0 )
154 {
155 }
156
157
SwAttrSet(SwAttrPool & rPool,const sal_uInt16 * nWhichPairTable)158 SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable )
159 : SfxItemSet( rPool, nWhichPairTable ), pOldSet( 0 ), pNewSet( 0 )
160 {
161 }
162
163
SwAttrSet(const SwAttrSet & rSet)164 SwAttrSet::SwAttrSet( const SwAttrSet& rSet )
165 : SfxItemSet( rSet ), pOldSet( 0 ), pNewSet( 0 )
166 {
167 }
168
Clone(sal_Bool bItems,SfxItemPool * pToPool) const169 SfxItemSet* SwAttrSet::Clone( sal_Bool bItems, SfxItemPool *pToPool ) const
170 {
171 if ( pToPool && pToPool != GetPool() )
172 {
173 SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool);
174 SfxItemSet* pTmpSet = 0;
175 if ( !pAttrPool )
176 pTmpSet = SfxItemSet::Clone( bItems, pToPool );
177 else
178 {
179 pTmpSet = new SwAttrSet( *pAttrPool, GetRanges() );
180 if ( bItems )
181 {
182 SfxWhichIter aIter(*pTmpSet);
183 sal_uInt16 nWhich = aIter.FirstWhich();
184 while ( nWhich )
185 {
186 const SfxPoolItem* pItem;
187 if ( SFX_ITEM_SET == GetItemState( nWhich, sal_False, &pItem ) )
188 pTmpSet->Put( *pItem, pItem->Which() );
189 nWhich = aIter.NextWhich();
190 }
191 }
192 }
193 return pTmpSet;
194 }
195 else
196 return bItems
197 ? new SwAttrSet( *this )
198 : new SwAttrSet( *GetPool(), GetRanges() );
199 }
200
Put_BC(const SfxPoolItem & rAttr,SwAttrSet * pOld,SwAttrSet * pNew)201 int SwAttrSet::Put_BC( const SfxPoolItem& rAttr,
202 SwAttrSet* pOld, SwAttrSet* pNew )
203 {
204 pNewSet = pNew;
205 pOldSet = pOld;
206 int nRet = 0 != SfxItemSet::Put( rAttr );
207 pOldSet = pNewSet = 0;
208 return nRet;
209 }
210
211
Put_BC(const SfxItemSet & rSet,SwAttrSet * pOld,SwAttrSet * pNew)212 int SwAttrSet::Put_BC( const SfxItemSet& rSet,
213 SwAttrSet* pOld, SwAttrSet* pNew )
214 {
215 pNewSet = pNew;
216 pOldSet = pOld;
217 int nRet = 0 != SfxItemSet::Put( rSet );
218 pOldSet = pNewSet = 0;
219 return nRet;
220 }
221
222
223
ClearItem_BC(sal_uInt16 nWhich,SwAttrSet * pOld,SwAttrSet * pNew)224 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich,
225 SwAttrSet* pOld, SwAttrSet* pNew )
226 {
227 pNewSet = pNew;
228 pOldSet = pOld;
229 sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich );
230 pOldSet = pNewSet = 0;
231 return nRet;
232 }
233
234
ClearItem_BC(sal_uInt16 nWhich1,sal_uInt16 nWhich2,SwAttrSet * pOld,SwAttrSet * pNew)235 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2,
236 SwAttrSet* pOld, SwAttrSet* pNew )
237 {
238 ASSERT( nWhich1 <= nWhich2, "kein gueltiger Bereich" );
239 pNewSet = pNew;
240 pOldSet = pOld;
241 sal_uInt16 nRet = 0;
242 for( ; nWhich1 <= nWhich2; ++nWhich1 )
243 nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
244 pOldSet = pNewSet = 0;
245 return nRet;
246 }
247
248
249
Intersect_BC(const SfxItemSet & rSet,SwAttrSet * pOld,SwAttrSet * pNew)250 int SwAttrSet::Intersect_BC( const SfxItemSet& rSet,
251 SwAttrSet* pOld, SwAttrSet* pNew )
252 {
253 pNewSet = pNew;
254 pOldSet = pOld;
255 SfxItemSet::Intersect( rSet );
256 pOldSet = pNewSet = 0;
257 return pNew ? pNew->Count() : ( pOld ? pOld->Count() : 0 );
258 }
259
260 // Notification-Callback
Changed(const SfxPoolItem & rOld,const SfxPoolItem & rNew)261 void SwAttrSet::Changed( const SfxPoolItem& rOld,
262 const SfxPoolItem& rNew )
263 {
264 if( pOldSet )
265 pOldSet->PutChgd( rOld );
266
267 if( pNewSet )
268 pNewSet->PutChgd( rNew );
269 }
270
271
272 // ----------------------------------------------------------------
273 // Sonderbehandlung fuer einige Attribute
274 // Setze den Modify-Pointer (alten pDefinedIn) bei folgenden Attributen:
275 // - SwFmtDropCaps
276 // - SwFmtPageDesc
277 // (Wird beim Einfuegen in Formate/Nodes gerufen)
278 // ----------------------------------------------------------------
279
SetModifyAtAttr(const SwModify * pModify)280 bool SwAttrSet::SetModifyAtAttr( const SwModify* pModify )
281 {
282 bool bSet = false;
283
284 const SfxPoolItem* pItem;
285 if( SFX_ITEM_SET == GetItemState( RES_PAGEDESC, sal_False, &pItem ) &&
286 ((SwFmtPageDesc*)pItem)->GetDefinedIn() != pModify )
287 {
288 ((SwFmtPageDesc*)pItem)->ChgDefinedIn( pModify );
289 bSet = true;
290 }
291
292 if( SFX_ITEM_SET == GetItemState( RES_PARATR_DROP, sal_False, &pItem ) &&
293 ((SwFmtDrop*)pItem)->GetDefinedIn() != pModify )
294 {
295 // CharFormat gesetzt und dann noch in unterschiedlichen
296 // Attribut Pools, dann muss das CharFormat kopiert werden!
297 SwCharFmt* pCharFmt;
298 if( 0 != ( pCharFmt = ((SwFmtDrop*)pItem)->GetCharFmt() )
299 && GetPool() != pCharFmt->GetAttrSet().GetPool() )
300 {
301 pCharFmt = GetDoc()->CopyCharFmt( *pCharFmt );
302 ((SwFmtDrop*)pItem)->SetCharFmt( pCharFmt );
303 }
304 ((SwFmtDrop*)pItem)->ChgDefinedIn( pModify );
305 bSet = true;
306 }
307
308 if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False, &pItem ) &&
309 ((SwTblBoxFormula*)pItem)->GetDefinedIn() != pModify )
310 {
311 ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pModify );
312 bSet = true;
313 }
314
315 return bSet;
316 }
317
CopyToModify(SwModify & rMod) const318 void SwAttrSet::CopyToModify( SwModify& rMod ) const
319 {
320 // kopiere die Attribute ggfs. ueber Dokumentgrenzen
321 SwCntntNode* pCNd = PTR_CAST( SwCntntNode, &rMod );
322 SwFmt* pFmt = PTR_CAST( SwFmt, &rMod );
323
324 if( pCNd || pFmt )
325 {
326 if( Count() )
327 {
328 // --> OD 2008-08-15 #i92811#
329 SfxStringItem* pNewListIdItem( 0 );
330 // <--
331
332 const SfxPoolItem* pItem;
333 const SwDoc *pSrcDoc = GetDoc();
334 SwDoc *pDstDoc = pCNd ? pCNd->GetDoc() : pFmt->GetDoc();
335
336 // muss die NumRule kopiert werden?
337 if( pSrcDoc != pDstDoc && SFX_ITEM_SET == GetItemState(
338 RES_PARATR_NUMRULE, sal_False, &pItem ) )
339 {
340 const String& rNm = ((SwNumRuleItem*)pItem)->GetValue();
341 if( rNm.Len() )
342 {
343 SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm );
344 if( pDestRule )
345 pDestRule->SetInvalidRule( sal_True );
346 else
347 pDstDoc->MakeNumRule( rNm,
348 pSrcDoc->FindNumRulePtr( rNm ) );
349 }
350 }
351
352 // --> OD 2008-03-19 #refactorlists#
353 // copy list and if needed also the corresponding list style
354 // for text nodes
355 if ( pSrcDoc != pDstDoc &&
356 pCNd && pCNd->IsTxtNode() &&
357 GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET )
358 {
359 const String& sListId =
360 dynamic_cast<const SfxStringItem*>(pItem)->GetValue();
361 if ( sListId.Len() > 0 &&
362 !pDstDoc->getListByName( sListId ) )
363 {
364 const SwList* pList = pSrcDoc->getListByName( sListId );
365 // copy list style, if needed
366 const String sDefaultListStyleName =
367 pList->GetDefaultListStyleName();
368 // --> OD 2008-08-15 #i92811#
369 const SwNumRule* pDstDocNumRule =
370 pDstDoc->FindNumRulePtr( sDefaultListStyleName );
371 if ( !pDstDocNumRule )
372 {
373 pDstDoc->MakeNumRule( sDefaultListStyleName,
374 pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) );
375 }
376 else
377 {
378 const SwNumRule* pSrcDocNumRule =
379 pSrcDoc->FindNumRulePtr( sDefaultListStyleName );
380 // If list id of text node equals the list style's
381 // default list id in the source document, the same
382 // should be hold in the destination document.
383 // Thus, create new list id item.
384 if ( sListId == pSrcDocNumRule->GetDefaultListId() )
385 {
386 pNewListIdItem = new SfxStringItem (
387 RES_PARATR_LIST_ID,
388 pDstDocNumRule->GetDefaultListId() );
389 }
390 }
391 // check again, if list exist, because <SwDoc::MakeNumRule(..)>
392 // could have also created it.
393 if ( pNewListIdItem == 0 &&
394 !pDstDoc->getListByName( sListId ) )
395 {
396 // copy list
397 pDstDoc->createList( sListId, sDefaultListStyleName );
398 }
399 // <--
400 }
401 }
402 // <--
403
404 // JP 04.02.99: Task #61467# Seitenvorlagenwechsel mit kopieren
405 // Gegenueber dem alten Verhalten, sie zu entfernen
406 const SwPageDesc* pPgDesc;
407 if( pSrcDoc != pDstDoc && SFX_ITEM_SET == GetItemState(
408 RES_PAGEDESC, sal_False, &pItem ) &&
409 0 != ( pPgDesc = ((SwFmtPageDesc*)pItem)->GetPageDesc()) )
410 {
411 SfxItemSet aTmpSet( *this );
412
413 SwPageDesc* pDstPgDesc = pDstDoc->FindPageDescByName(
414 pPgDesc->GetName() );
415 if( !pDstPgDesc )
416 {
417 // dann kopieren, ansonsten den benutzen
418 pDstPgDesc = &pDstDoc->_GetPageDesc( pDstDoc->MakePageDesc(
419 pPgDesc->GetName() ));
420 pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc );
421 }
422 SwFmtPageDesc aDesc( pDstPgDesc );
423 aDesc.SetNumOffset( ((SwFmtPageDesc*)pItem)->GetNumOffset() );
424 aTmpSet.Put( aDesc );
425
426 if( pCNd )
427 {
428 // --> OD 2008-08-15 #i92811#
429 if ( pNewListIdItem != 0 )
430 {
431 aTmpSet.Put( *pNewListIdItem );
432 }
433 // <--
434 pCNd->SetAttr( aTmpSet );
435 }
436 else
437 pFmt->SetFmtAttr( aTmpSet );
438 }
439 else if( pCNd )
440 {
441 // --> OD 2008-08-15 #i92811#
442 if ( pNewListIdItem != 0 )
443 {
444 SfxItemSet aTmpSet( *this );
445 aTmpSet.Put( *pNewListIdItem );
446 pCNd->SetAttr( aTmpSet );
447 }
448 else
449 {
450 pCNd->SetAttr( *this );
451 }
452 // <--
453 }
454 else
455 pFmt->SetFmtAttr( *this );
456
457 // --> OD 2008-08-15 #i92811#
458 delete pNewListIdItem;
459 pNewListIdItem = 0;
460 // <--
461 }
462 }
463 #ifdef DBG_UTIL
464 else
465 ASSERT( sal_False, "neither format nor ContentNode - no attributes copied");
466 #endif
467 }
468
469 // check if ID is InRange of AttrSet-Ids
IsInRange(const sal_uInt16 * pRange,const sal_uInt16 nId)470 sal_Bool IsInRange( const sal_uInt16* pRange, const sal_uInt16 nId )
471 {
472 while( *pRange )
473 {
474 if( *pRange <= nId && nId <= *(pRange+1) )
475 return sal_True;
476 pRange += 2;
477 }
478 return sal_False;
479 }
480
481