1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 32 #include <hintids.hxx> 33 #include <svl/whiter.hxx> 34 #include <editeng/colritem.hxx> 35 #include <editeng/brshitem.hxx> 36 #include <editeng/bolnitem.hxx> 37 #include <editeng/boxitem.hxx> 38 #include <svx/xtable.hxx> 39 #include <fmtpdsc.hxx> 40 #include <pagedesc.hxx> 41 #include <charfmt.hxx> 42 #include <doc.hxx> 43 #include <node.hxx> 44 #include <paratr.hxx> // fuer SetModifyAtAttr 45 #include <cellatr.hxx> // fuer SetModifyAtAttr 46 #ifndef _CMDID_H 47 #include <cmdid.h> 48 #endif 49 #include <istyleaccess.hxx> 50 #include <numrule.hxx> 51 // --> OD 2008-03-19 #refactorlists# 52 #include <list.hxx> 53 // <-- 54 55 56 SwAttrPool::SwAttrPool( SwDoc* pD ) 57 : SfxItemPool( String::CreateFromAscii( 58 RTL_CONSTASCII_STRINGPARAM( "SWG" )), 59 POOLATTR_BEGIN, POOLATTR_END-1, 60 aSlotTab, aAttrTab ), 61 pDoc( pD ) 62 { 63 SetVersionMap( 1, 1, 60, pVersionMap1 ); 64 SetVersionMap( 2, 1, 75, pVersionMap2 ); 65 SetVersionMap( 3, 1, 86, pVersionMap3 ); 66 SetVersionMap( 4, 1,121, pVersionMap4 ); 67 // OD 2004-01-21 #i18732# - apply new version map 68 SetVersionMap( 5, 1,130, pVersionMap5 ); 69 SetVersionMap( 6, 1,136, pVersionMap6 ); 70 } 71 72 SwAttrPool::~SwAttrPool() 73 { 74 } 75 76 SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 ) 77 : SfxItemSet( rPool, nWh1, nWh2 ), pOldSet( 0 ), pNewSet( 0 ) 78 { 79 } 80 81 82 SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable ) 83 : SfxItemSet( rPool, nWhichPairTable ), pOldSet( 0 ), pNewSet( 0 ) 84 { 85 } 86 87 88 SwAttrSet::SwAttrSet( const SwAttrSet& rSet ) 89 : SfxItemSet( rSet ), pOldSet( 0 ), pNewSet( 0 ) 90 { 91 } 92 93 SfxItemSet* SwAttrSet::Clone( sal_Bool bItems, SfxItemPool *pToPool ) const 94 { 95 if ( pToPool && pToPool != GetPool() ) 96 { 97 SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool); 98 SfxItemSet* pTmpSet = 0; 99 if ( !pAttrPool ) 100 pTmpSet = SfxItemSet::Clone( bItems, pToPool ); 101 else 102 { 103 pTmpSet = new SwAttrSet( *pAttrPool, GetRanges() ); 104 if ( bItems ) 105 { 106 SfxWhichIter aIter(*pTmpSet); 107 sal_uInt16 nWhich = aIter.FirstWhich(); 108 while ( nWhich ) 109 { 110 const SfxPoolItem* pItem; 111 if ( SFX_ITEM_SET == GetItemState( nWhich, sal_False, &pItem ) ) 112 pTmpSet->Put( *pItem, pItem->Which() ); 113 nWhich = aIter.NextWhich(); 114 } 115 } 116 } 117 return pTmpSet; 118 } 119 else 120 return bItems 121 ? new SwAttrSet( *this ) 122 : new SwAttrSet( *GetPool(), GetRanges() ); 123 } 124 125 int SwAttrSet::Put_BC( const SfxPoolItem& rAttr, 126 SwAttrSet* pOld, SwAttrSet* pNew ) 127 { 128 pNewSet = pNew; 129 pOldSet = pOld; 130 int nRet = 0 != SfxItemSet::Put( rAttr ); 131 pOldSet = pNewSet = 0; 132 return nRet; 133 } 134 135 136 int SwAttrSet::Put_BC( const SfxItemSet& rSet, 137 SwAttrSet* pOld, SwAttrSet* pNew ) 138 { 139 pNewSet = pNew; 140 pOldSet = pOld; 141 int nRet = 0 != SfxItemSet::Put( rSet ); 142 pOldSet = pNewSet = 0; 143 return nRet; 144 } 145 146 147 148 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich, 149 SwAttrSet* pOld, SwAttrSet* pNew ) 150 { 151 pNewSet = pNew; 152 pOldSet = pOld; 153 sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich ); 154 pOldSet = pNewSet = 0; 155 return nRet; 156 } 157 158 159 sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2, 160 SwAttrSet* pOld, SwAttrSet* pNew ) 161 { 162 ASSERT( nWhich1 <= nWhich2, "kein gueltiger Bereich" ); 163 pNewSet = pNew; 164 pOldSet = pOld; 165 sal_uInt16 nRet = 0; 166 for( ; nWhich1 <= nWhich2; ++nWhich1 ) 167 nRet = nRet + SfxItemSet::ClearItem( nWhich1 ); 168 pOldSet = pNewSet = 0; 169 return nRet; 170 } 171 172 173 174 int SwAttrSet::Intersect_BC( const SfxItemSet& rSet, 175 SwAttrSet* pOld, SwAttrSet* pNew ) 176 { 177 pNewSet = pNew; 178 pOldSet = pOld; 179 SfxItemSet::Intersect( rSet ); 180 pOldSet = pNewSet = 0; 181 return pNew ? pNew->Count() : ( pOld ? pOld->Count() : 0 ); 182 } 183 184 // Notification-Callback 185 void SwAttrSet::Changed( const SfxPoolItem& rOld, 186 const SfxPoolItem& rNew ) 187 { 188 if( pOldSet ) 189 pOldSet->PutChgd( rOld ); 190 191 if( pNewSet ) 192 pNewSet->PutChgd( rNew ); 193 } 194 195 196 // ---------------------------------------------------------------- 197 // Sonderbehandlung fuer einige Attribute 198 // Setze den Modify-Pointer (alten pDefinedIn) bei folgenden Attributen: 199 // - SwFmtDropCaps 200 // - SwFmtPageDesc 201 // (Wird beim Einfuegen in Formate/Nodes gerufen) 202 // ---------------------------------------------------------------- 203 204 bool SwAttrSet::SetModifyAtAttr( const SwModify* pModify ) 205 { 206 bool bSet = false; 207 208 const SfxPoolItem* pItem; 209 if( SFX_ITEM_SET == GetItemState( RES_PAGEDESC, sal_False, &pItem ) && 210 ((SwFmtPageDesc*)pItem)->GetDefinedIn() != pModify ) 211 { 212 ((SwFmtPageDesc*)pItem)->ChgDefinedIn( pModify ); 213 bSet = true; 214 } 215 216 if( SFX_ITEM_SET == GetItemState( RES_PARATR_DROP, sal_False, &pItem ) && 217 ((SwFmtDrop*)pItem)->GetDefinedIn() != pModify ) 218 { 219 // CharFormat gesetzt und dann noch in unterschiedlichen 220 // Attribut Pools, dann muss das CharFormat kopiert werden! 221 SwCharFmt* pCharFmt; 222 if( 0 != ( pCharFmt = ((SwFmtDrop*)pItem)->GetCharFmt() ) 223 && GetPool() != pCharFmt->GetAttrSet().GetPool() ) 224 { 225 pCharFmt = GetDoc()->CopyCharFmt( *pCharFmt ); 226 ((SwFmtDrop*)pItem)->SetCharFmt( pCharFmt ); 227 } 228 ((SwFmtDrop*)pItem)->ChgDefinedIn( pModify ); 229 bSet = true; 230 } 231 232 if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False, &pItem ) && 233 ((SwTblBoxFormula*)pItem)->GetDefinedIn() != pModify ) 234 { 235 ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pModify ); 236 bSet = true; 237 } 238 239 return bSet; 240 } 241 242 void SwAttrSet::CopyToModify( SwModify& rMod ) const 243 { 244 // kopiere die Attribute ggfs. ueber Dokumentgrenzen 245 SwCntntNode* pCNd = PTR_CAST( SwCntntNode, &rMod ); 246 SwFmt* pFmt = PTR_CAST( SwFmt, &rMod ); 247 248 if( pCNd || pFmt ) 249 { 250 if( Count() ) 251 { 252 // --> OD 2008-08-15 #i92811# 253 SfxStringItem* pNewListIdItem( 0 ); 254 // <-- 255 256 const SfxPoolItem* pItem; 257 const SwDoc *pSrcDoc = GetDoc(); 258 SwDoc *pDstDoc = pCNd ? pCNd->GetDoc() : pFmt->GetDoc(); 259 260 // muss die NumRule kopiert werden? 261 if( pSrcDoc != pDstDoc && SFX_ITEM_SET == GetItemState( 262 RES_PARATR_NUMRULE, sal_False, &pItem ) ) 263 { 264 const String& rNm = ((SwNumRuleItem*)pItem)->GetValue(); 265 if( rNm.Len() ) 266 { 267 SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm ); 268 if( pDestRule ) 269 pDestRule->SetInvalidRule( sal_True ); 270 else 271 pDstDoc->MakeNumRule( rNm, 272 pSrcDoc->FindNumRulePtr( rNm ) ); 273 } 274 } 275 276 // --> OD 2008-03-19 #refactorlists# 277 // copy list and if needed also the corresponding list style 278 // for text nodes 279 if ( pSrcDoc != pDstDoc && 280 pCNd && pCNd->IsTxtNode() && 281 GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET ) 282 { 283 const String& sListId = 284 dynamic_cast<const SfxStringItem*>(pItem)->GetValue(); 285 if ( sListId.Len() > 0 && 286 !pDstDoc->getListByName( sListId ) ) 287 { 288 const SwList* pList = pSrcDoc->getListByName( sListId ); 289 // copy list style, if needed 290 const String sDefaultListStyleName = 291 pList->GetDefaultListStyleName(); 292 // --> OD 2008-08-15 #i92811# 293 const SwNumRule* pDstDocNumRule = 294 pDstDoc->FindNumRulePtr( sDefaultListStyleName ); 295 if ( !pDstDocNumRule ) 296 { 297 pDstDoc->MakeNumRule( sDefaultListStyleName, 298 pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) ); 299 } 300 else 301 { 302 const SwNumRule* pSrcDocNumRule = 303 pSrcDoc->FindNumRulePtr( sDefaultListStyleName ); 304 // If list id of text node equals the list style's 305 // default list id in the source document, the same 306 // should be hold in the destination document. 307 // Thus, create new list id item. 308 if ( sListId == pSrcDocNumRule->GetDefaultListId() ) 309 { 310 pNewListIdItem = new SfxStringItem ( 311 RES_PARATR_LIST_ID, 312 pDstDocNumRule->GetDefaultListId() ); 313 } 314 } 315 // check again, if list exist, because <SwDoc::MakeNumRule(..)> 316 // could have also created it. 317 if ( pNewListIdItem == 0 && 318 !pDstDoc->getListByName( sListId ) ) 319 { 320 // copy list 321 pDstDoc->createList( sListId, sDefaultListStyleName ); 322 } 323 // <-- 324 } 325 } 326 // <-- 327 328 // JP 04.02.99: Task #61467# Seitenvorlagenwechsel mit kopieren 329 // Gegenueber dem alten Verhalten, sie zu entfernen 330 const SwPageDesc* pPgDesc; 331 if( pSrcDoc != pDstDoc && SFX_ITEM_SET == GetItemState( 332 RES_PAGEDESC, sal_False, &pItem ) && 333 0 != ( pPgDesc = ((SwFmtPageDesc*)pItem)->GetPageDesc()) ) 334 { 335 SfxItemSet aTmpSet( *this ); 336 337 SwPageDesc* pDstPgDesc = pDstDoc->FindPageDescByName( 338 pPgDesc->GetName() ); 339 if( !pDstPgDesc ) 340 { 341 // dann kopieren, ansonsten den benutzen 342 pDstPgDesc = &pDstDoc->_GetPageDesc( pDstDoc->MakePageDesc( 343 pPgDesc->GetName() )); 344 pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc ); 345 } 346 SwFmtPageDesc aDesc( pDstPgDesc ); 347 aDesc.SetNumOffset( ((SwFmtPageDesc*)pItem)->GetNumOffset() ); 348 aTmpSet.Put( aDesc ); 349 350 if( pCNd ) 351 { 352 // --> OD 2008-08-15 #i92811# 353 if ( pNewListIdItem != 0 ) 354 { 355 aTmpSet.Put( *pNewListIdItem ); 356 } 357 // <-- 358 pCNd->SetAttr( aTmpSet ); 359 } 360 else 361 pFmt->SetFmtAttr( aTmpSet ); 362 } 363 else if( pCNd ) 364 { 365 // --> OD 2008-08-15 #i92811# 366 if ( pNewListIdItem != 0 ) 367 { 368 SfxItemSet aTmpSet( *this ); 369 aTmpSet.Put( *pNewListIdItem ); 370 pCNd->SetAttr( aTmpSet ); 371 } 372 else 373 { 374 pCNd->SetAttr( *this ); 375 } 376 // <-- 377 } 378 else 379 pFmt->SetFmtAttr( *this ); 380 381 // --> OD 2008-08-15 #i92811# 382 delete pNewListIdItem; 383 pNewListIdItem = 0; 384 // <-- 385 } 386 } 387 #ifdef DBG_UTIL 388 else 389 ASSERT( !this, "weder Format noch ContentNode - keine Attribute kopiert"); 390 #endif 391 } 392 393 // check if ID is InRange of AttrSet-Ids 394 sal_Bool IsInRange( const sal_uInt16* pRange, const sal_uInt16 nId ) 395 { 396 while( *pRange ) 397 { 398 if( *pRange <= nId && nId <= *(pRange+1) ) 399 return sal_True; 400 pRange += 2; 401 } 402 return sal_False; 403 } 404 405