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 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 69 SwAttrPool::~SwAttrPool() 70 { 71 //UUUU cleanup secondary pools first 72 removeAndDeleteSecondaryPools(); 73 } 74 75 //UUUU 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 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 152 SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 ) 153 : SfxItemSet( rPool, nWh1, nWh2 ), pOldSet( 0 ), pNewSet( 0 ) 154 { 155 } 156 157 158 SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable ) 159 : SfxItemSet( rPool, nWhichPairTable ), pOldSet( 0 ), pNewSet( 0 ) 160 { 161 } 162 163 164 SwAttrSet::SwAttrSet( const SwAttrSet& rSet ) 165 : SfxItemSet( rSet ), pOldSet( 0 ), pNewSet( 0 ) 166 { 167 } 168 169 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 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 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 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 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 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 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 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 318 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( !this, "weder Format noch ContentNode - keine Attribute kopiert"); 466 #endif 467 } 468 469 // check if ID is InRange of AttrSet-Ids 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