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