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 <libxml/xmlwriter.h> 21 #include <hintids.hxx> 22 #include <svl/itemiter.hxx> 23 #include <sfx2/app.hxx> 24 #include <editeng/tstpitem.hxx> 25 #include <editeng/eeitem.hxx> 26 #include <editeng/langitem.hxx> 27 #include <editeng/lrspitem.hxx> 28 #include <editeng/formatbreakitem.hxx> 29 #include <editeng/rsiditem.hxx> 30 #include <editeng/colritem.hxx> 31 #include <svl/whiter.hxx> 32 #include <svl/zforlist.hxx> 33 #include <comphelper/doublecheckedinit.hxx> 34 #include <comphelper/processfactory.hxx> 35 #include <unotools/configmgr.hxx> 36 #include <unotools/misccfg.hxx> 37 #include <sal/log.hxx> 38 #include <com/sun/star/i18n/WordType.hpp> 39 #include <com/sun/star/i18n/XBreakIterator.hpp> 40 #include <fmtpdsc.hxx> 41 #include <fmthdft.hxx> 42 #include <fmtcntnt.hxx> 43 #include <frmatr.hxx> 44 #include <doc.hxx> 45 #include <docfunc.hxx> 46 #include <drawdoc.hxx> 47 #include <MarkManager.hxx> 48 #include <IDocumentDrawModelAccess.hxx> 49 #include <IDocumentUndoRedo.hxx> 50 #include <DocumentContentOperationsManager.hxx> 51 #include <IDocumentFieldsAccess.hxx> 52 #include <IDocumentState.hxx> 53 #include <IDocumentLayoutAccess.hxx> 54 #include <IDocumentStylePoolAccess.hxx> 55 #include <rootfrm.hxx> 56 #include <pagefrm.hxx> 57 #include <txtfrm.hxx> 58 #include <hints.hxx> 59 #include <ndtxt.hxx> 60 #include <pam.hxx> 61 #include <UndoCore.hxx> 62 #include <UndoAttribute.hxx> 63 #include <UndoInsert.hxx> 64 #include <ndgrf.hxx> 65 #include <pagedesc.hxx> 66 #include <rolbck.hxx> 67 #include <mvsave.hxx> 68 #include <txatbase.hxx> 69 #include <swtable.hxx> 70 #include <swtblfmt.hxx> 71 #include <charfmt.hxx> 72 #include <docary.hxx> 73 #include <paratr.hxx> 74 #include <redline.hxx> 75 #include <reffld.hxx> 76 #include <txtinet.hxx> 77 #include <fmtinfmt.hxx> 78 #include <breakit.hxx> 79 #include <SwStyleNameMapper.hxx> 80 #include <fmtautofmt.hxx> 81 #include <istyleaccess.hxx> 82 #include <SwUndoFmt.hxx> 83 #include <UndoManager.hxx> 84 #include <docsh.hxx> 85 #include <swmodule.hxx> 86 #include <modcfg.hxx> 87 #include <memory> 88 89 using namespace ::com::sun::star::i18n; 90 using namespace ::com::sun::star::lang; 91 using namespace ::com::sun::star::uno; 92 93 /* 94 * Internal functions 95 */ 96 97 static void SetTextFormatCollNext( SwTextFormatColl* pTextColl, const SwTextFormatColl* pDel ) 98 { 99 if ( &pTextColl->GetNextTextFormatColl() == pDel ) 100 { 101 pTextColl->SetNextTextFormatColl( *pTextColl ); 102 } 103 } 104 105 static bool lcl_RstAttr( const SwNodePtr& rpNd, void* pArgs ) 106 { 107 const sw::DocumentContentOperationsManager::ParaRstFormat* pPara = static_cast<sw::DocumentContentOperationsManager::ParaRstFormat*>(pArgs); 108 SwContentNode* pNode = rpNd->GetContentNode(); 109 if (pPara->pLayout && pPara->pLayout->IsHideRedlines() 110 && pNode && pNode->GetRedlineMergeFlag() == SwNode::Merge::Hidden) 111 { 112 return true; 113 } 114 if( pNode && pNode->HasSwAttrSet() ) 115 { 116 const bool bLocked = pNode->IsModifyLocked(); 117 pNode->LockModify(); 118 119 SwDoc* pDoc = pNode->GetDoc(); 120 121 // remove unused attribute RES_LR_SPACE 122 // add list attributes 123 SfxItemSet aSavedAttrsSet( 124 pDoc->GetAttrPool(), 125 svl::Items< 126 RES_PARATR_NUMRULE, RES_PARATR_NUMRULE, 127 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1, 128 RES_PAGEDESC, RES_BREAK>{}); 129 const SfxItemSet* pAttrSetOfNode = pNode->GetpSwAttrSet(); 130 131 std::vector<sal_uInt16> aClearWhichIds; 132 // restoring all paragraph list attributes 133 { 134 SfxItemSet aListAttrSet( pDoc->GetAttrPool(), svl::Items<RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1>{} ); 135 aListAttrSet.Set(*pAttrSetOfNode); 136 if ( aListAttrSet.Count() ) 137 { 138 aSavedAttrsSet.Put(aListAttrSet); 139 SfxItemIter aIter( aListAttrSet ); 140 const SfxPoolItem* pItem = aIter.GetCurItem(); 141 while( pItem ) 142 { 143 aClearWhichIds.push_back( pItem->Which() ); 144 pItem = aIter.NextItem(); 145 } 146 } 147 } 148 149 const SfxPoolItem* pItem; 150 151 sal_uInt16 const aSavIds[3] = { RES_PAGEDESC, RES_BREAK, RES_PARATR_NUMRULE }; 152 for (sal_uInt16 aSavId : aSavIds) 153 { 154 if (SfxItemState::SET == pAttrSetOfNode->GetItemState(aSavId, false, &pItem)) 155 { 156 bool bSave = false; 157 switch( aSavId ) 158 { 159 case RES_PAGEDESC: 160 bSave = nullptr != static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc(); 161 break; 162 case RES_BREAK: 163 bSave = SvxBreak::NONE != static_cast<const SvxFormatBreakItem*>(pItem)->GetBreak(); 164 break; 165 case RES_PARATR_NUMRULE: 166 bSave = !static_cast<const SwNumRuleItem*>(pItem)->GetValue().isEmpty(); 167 break; 168 } 169 if( bSave ) 170 { 171 aSavedAttrsSet.Put(*pItem); 172 aClearWhichIds.push_back(aSavId); 173 } 174 } 175 } 176 177 // do not clear items directly from item set and only clear to be kept 178 // attributes, if no deletion item set is found. 179 const bool bKeepAttributes = 180 !pPara || !pPara->pDelSet || pPara->pDelSet->Count() == 0; 181 if ( bKeepAttributes ) 182 { 183 pNode->ResetAttr( aClearWhichIds ); 184 } 185 186 if( !bLocked ) 187 pNode->UnlockModify(); 188 189 if( pPara ) 190 { 191 SwRegHistory aRegH( pNode, *pNode, pPara->pHistory ); 192 193 if( pPara->pDelSet && pPara->pDelSet->Count() ) 194 { 195 OSL_ENSURE( !bKeepAttributes, 196 "<lcl_RstAttr(..)> - certain attributes are kept, but not needed." ); 197 SfxItemIter aIter( *pPara->pDelSet ); 198 pItem = aIter.FirstItem(); 199 while(pItem) 200 { 201 if ( ( pItem->Which() != RES_PAGEDESC && 202 pItem->Which() != RES_BREAK && 203 pItem->Which() != RES_PARATR_NUMRULE ) || 204 ( aSavedAttrsSet.GetItemState( pItem->Which(), false ) != SfxItemState::SET ) ) 205 { 206 pNode->ResetAttr( pItem->Which() ); 207 } 208 if (aIter.IsAtEnd()) 209 break; 210 pItem = aIter.NextItem(); 211 } 212 } 213 else if( pPara->bResetAll ) 214 pNode->ResetAllAttr(); 215 else 216 pNode->ResetAttr( RES_PARATR_BEGIN, POOLATTR_END - 1 ); 217 } 218 else 219 pNode->ResetAllAttr(); 220 221 // only restore saved attributes, if needed 222 if (bKeepAttributes && aSavedAttrsSet.Count()) 223 { 224 pNode->LockModify(); 225 226 pNode->SetAttr(aSavedAttrsSet); 227 228 if( !bLocked ) 229 pNode->UnlockModify(); 230 } 231 } 232 return true; 233 } 234 235 void SwDoc::RstTextAttrs(const SwPaM &rRg, bool bInclRefToxMark, 236 bool bExactRange, SwRootFrame const*const pLayout) 237 { 238 SwHistory* pHst = nullptr; 239 SwDataChanged aTmp( rRg ); 240 if (GetIDocumentUndoRedo().DoesUndo()) 241 { 242 std::unique_ptr<SwUndoResetAttr> pUndo(new SwUndoResetAttr( rRg, RES_CHRFMT )); 243 pHst = &pUndo->GetHistory(); 244 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo)); 245 } 246 const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End(); 247 sw::DocumentContentOperationsManager::ParaRstFormat aPara( 248 pStt, pEnd, pHst, nullptr, pLayout ); 249 aPara.bInclRefToxMark = bInclRefToxMark; 250 aPara.bExactRange = bExactRange; 251 GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1, 252 sw::DocumentContentOperationsManager::lcl_RstTextAttr, &aPara ); 253 getIDocumentState().SetModified(); 254 } 255 256 void SwDoc::ResetAttrs( const SwPaM &rRg, 257 bool bTextAttr, 258 const std::set<sal_uInt16> &rAttrs, 259 const bool bSendDataChangedEvents, 260 SwRootFrame const*const pLayout) 261 { 262 SwPaM* pPam = const_cast<SwPaM*>(&rRg); 263 if( !bTextAttr && !rAttrs.empty() && RES_TXTATR_END > *(rAttrs.begin()) ) 264 bTextAttr = true; 265 266 if( !rRg.HasMark() ) 267 { 268 SwTextNode* pTextNd = rRg.GetPoint()->nNode.GetNode().GetTextNode(); 269 if( !pTextNd ) 270 return ; 271 272 pPam = new SwPaM( *rRg.GetPoint() ); 273 274 SwIndex& rSt = pPam->GetPoint()->nContent; 275 sal_Int32 nMkPos, nPtPos = rSt.GetIndex(); 276 277 // Special case: if the Cursor is located within a URL attribute, we take over it's area 278 SwTextAttr const*const pURLAttr( 279 pTextNd->GetTextAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT)); 280 if (pURLAttr && !pURLAttr->GetINetFormat().GetValue().isEmpty()) 281 { 282 nMkPos = pURLAttr->GetStart(); 283 nPtPos = *pURLAttr->End(); 284 } 285 else 286 { 287 assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is()); 288 Boundary aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary( 289 pTextNd->GetText(), nPtPos, 290 g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ), 291 WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/, 292 true); 293 294 if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos ) 295 { 296 nMkPos = aBndry.startPos; 297 nPtPos = aBndry.endPos; 298 } 299 else 300 { 301 nPtPos = nMkPos = rSt.GetIndex(); 302 if( bTextAttr ) 303 pTextNd->DontExpandFormat( rSt ); 304 } 305 } 306 307 rSt = nMkPos; 308 pPam->SetMark(); 309 pPam->GetPoint()->nContent = nPtPos; 310 } 311 312 // #i96644# 313 std::unique_ptr< SwDataChanged > xDataChanged; 314 if ( bSendDataChangedEvents ) 315 { 316 xDataChanged.reset( new SwDataChanged( *pPam ) ); 317 } 318 SwHistory* pHst = nullptr; 319 if (GetIDocumentUndoRedo().DoesUndo()) 320 { 321 std::unique_ptr<SwUndoResetAttr> pUndo(new SwUndoResetAttr( rRg, 322 bTextAttr ? sal_uInt16(RES_CONDTXTFMTCOLL) : sal_uInt16(RES_TXTFMTCOLL) )); 323 if( !rAttrs.empty() ) 324 { 325 pUndo->SetAttrs( rAttrs ); 326 } 327 pHst = &pUndo->GetHistory(); 328 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo)); 329 } 330 331 const SwPosition *pStt = pPam->Start(), *pEnd = pPam->End(); 332 sw::DocumentContentOperationsManager::ParaRstFormat aPara( 333 pStt, pEnd, pHst, nullptr, pLayout); 334 335 // mst: not including META here; it seems attrs with CH_TXTATR are omitted 336 sal_uInt16 const aResetableSetRange[] { 337 RES_FRMATR_BEGIN, RES_FRMATR_END-1, 338 RES_CHRATR_BEGIN, RES_CHRATR_END-1, 339 RES_PARATR_BEGIN, RES_PARATR_END-1, 340 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1, 341 RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, 342 RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT, 343 RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY, 344 RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER, 345 RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 346 0 347 }; 348 349 SfxItemSet aDelSet( GetAttrPool(), aResetableSetRange ); 350 if( !rAttrs.empty() ) 351 { 352 for( std::set<sal_uInt16>::const_reverse_iterator it = rAttrs.rbegin(); it != rAttrs.rend(); ++it ) 353 { 354 if( POOLATTR_END > *it ) 355 aDelSet.Put( *GetDfltAttr( *it )); 356 } 357 if( aDelSet.Count() ) 358 aPara.pDelSet = &aDelSet; 359 } 360 361 bool bAdd = true; 362 SwNodeIndex aTmpStt( pStt->nNode ); 363 SwNodeIndex aTmpEnd( pEnd->nNode ); 364 if( pStt->nContent.GetIndex() ) // just one part 365 { 366 // set up a later, and all CharFormatAttr -> TextFormatAttr 367 SwTextNode* pTNd = aTmpStt.GetNode().GetTextNode(); 368 if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() ) 369 { 370 if (pHst) 371 { 372 SwRegHistory history(pTNd, *pTNd, pHst); 373 pTNd->FormatToTextAttr(pTNd); 374 } 375 else 376 { 377 pTNd->FormatToTextAttr(pTNd); 378 } 379 } 380 381 ++aTmpStt; 382 } 383 if( pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetContentNode()->Len() ) 384 { 385 // set up a later, and all CharFormatAttr -> TextFormatAttr 386 ++aTmpEnd; 387 bAdd = false; 388 } 389 else if( pStt->nNode != pEnd->nNode || !pStt->nContent.GetIndex() ) 390 { 391 SwTextNode* pTNd = aTmpEnd.GetNode().GetTextNode(); 392 if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() ) 393 { 394 if (pHst) 395 { 396 SwRegHistory history(pTNd, *pTNd, pHst); 397 pTNd->FormatToTextAttr(pTNd); 398 } 399 else 400 { 401 pTNd->FormatToTextAttr(pTNd); 402 } 403 } 404 } 405 406 if( aTmpStt < aTmpEnd ) 407 GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstAttr, &aPara ); 408 else if( !rRg.HasMark() ) 409 { 410 aPara.bResetAll = false ; 411 ::lcl_RstAttr( &pStt->nNode.GetNode(), &aPara ); 412 aPara.bResetAll = true ; 413 } 414 415 if( bTextAttr ) 416 { 417 if( bAdd ) 418 ++aTmpEnd; 419 GetNodes().ForEach( pStt->nNode, aTmpEnd, sw::DocumentContentOperationsManager::lcl_RstTextAttr, &aPara ); 420 } 421 422 getIDocumentState().SetModified(); 423 424 xDataChanged.reset(); //before delete pPam 425 426 if( pPam != &rRg ) 427 delete pPam; 428 } 429 430 /// Set the rsid of the next nLen symbols of rRg to the current session number 431 void SwDoc::UpdateRsid( const SwPaM &rRg, const sal_Int32 nLen ) 432 { 433 if (!SW_MOD()->GetModuleConfig()->IsStoreRsid()) 434 return; 435 436 SwTextNode *pTextNode = rRg.GetPoint()->nNode.GetNode().GetTextNode(); 437 if (!pTextNode) 438 { 439 return; 440 } 441 const sal_Int32 nStart(rRg.GetPoint()->nContent.GetIndex() - nLen); 442 SvxRsidItem aRsid( mnRsid, RES_CHRATR_RSID ); 443 444 SfxItemSet aSet(GetAttrPool(), svl::Items<RES_CHRATR_RSID, RES_CHRATR_RSID>{}); 445 aSet.Put(aRsid); 446 bool const bRet(pTextNode->SetAttr(aSet, nStart, 447 rRg.GetPoint()->nContent.GetIndex())); 448 449 if (bRet && GetIDocumentUndoRedo().DoesUndo()) 450 { 451 SwUndo *const pLastUndo = GetUndoManager().GetLastUndo(); 452 SwUndoInsert *const pUndoInsert(dynamic_cast<SwUndoInsert*>(pLastUndo)); 453 // this function is called after Insert so expects to find SwUndoInsert 454 assert(pUndoInsert); 455 if (pUndoInsert) 456 { 457 pUndoInsert->SetWithRsid(); 458 } 459 } 460 } 461 462 bool SwDoc::UpdateParRsid( SwTextNode *pTextNode, sal_uInt32 nVal ) 463 { 464 if (!SW_MOD()->GetModuleConfig()->IsStoreRsid()) 465 return false; 466 467 if (!pTextNode) 468 { 469 return false; 470 } 471 472 SvxRsidItem aRsid( nVal ? nVal : mnRsid, RES_PARATR_RSID ); 473 return pTextNode->SetAttr( aRsid ); 474 } 475 476 /// Set the attribute according to the stated format. 477 /// If Undo is enabled, the old values is added to the Undo history. 478 void SwDoc::SetAttr( const SfxPoolItem& rAttr, SwFormat& rFormat ) 479 { 480 SfxItemSet aSet( GetAttrPool(), {{rAttr.Which(), rAttr.Which()}} ); 481 aSet.Put( rAttr ); 482 SetAttr( aSet, rFormat ); 483 } 484 485 /// Set the attribute according to the stated format. 486 /// If Undo is enabled, the old values is added to the Undo history. 487 void SwDoc::SetAttr( const SfxItemSet& rSet, SwFormat& rFormat ) 488 { 489 if (GetIDocumentUndoRedo().DoesUndo()) 490 { 491 SwUndoFormatAttrHelper aTmp( rFormat ); 492 rFormat.SetFormatAttr( rSet ); 493 if ( aTmp.GetUndo() ) 494 { 495 GetIDocumentUndoRedo().AppendUndo( aTmp.ReleaseUndo() ); 496 } 497 else 498 { 499 GetIDocumentUndoRedo().ClearRedo(); 500 } 501 } 502 else 503 { 504 rFormat.SetFormatAttr( rSet ); 505 } 506 getIDocumentState().SetModified(); 507 } 508 509 void SwDoc::ResetAttrAtFormat( const sal_uInt16 nWhichId, 510 SwFormat& rChangedFormat ) 511 { 512 std::unique_ptr<SwUndo> pUndo; 513 if (GetIDocumentUndoRedo().DoesUndo()) 514 pUndo.reset(new SwUndoFormatResetAttr( rChangedFormat, nWhichId )); 515 516 const bool bAttrReset = rChangedFormat.ResetFormatAttr( nWhichId ); 517 518 if ( bAttrReset ) 519 { 520 if ( pUndo ) 521 { 522 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) ); 523 } 524 525 getIDocumentState().SetModified(); 526 } 527 } 528 529 static bool lcl_SetNewDefTabStops( SwTwips nOldWidth, SwTwips nNewWidth, 530 SvxTabStopItem& rChgTabStop ) 531 { 532 // Set the default values of all TabStops to the new value. 533 // Attention: we always work with the PoolAttribute here, so that 534 // we don't calculate the same value on the same TabStop (pooled!) for all sets. 535 // We send a FormatChg to modify. 536 537 sal_uInt16 nOldCnt = rChgTabStop.Count(); 538 if( !nOldCnt || nOldWidth == nNewWidth ) 539 return false; 540 541 // Find the default's beginning 542 sal_uInt16 n; 543 for( n = nOldCnt; n ; --n ) 544 if( SvxTabAdjust::Default != rChgTabStop[n - 1].GetAdjustment() ) 545 break; 546 ++n; 547 if( n < nOldCnt ) // delete the DefTabStops 548 rChgTabStop.Remove( n, nOldCnt - n ); 549 return true; 550 } 551 552 /// Set the attribute as new default attribute in this document. 553 /// If Undo is enabled, the old value is added to the Undo history. 554 void SwDoc::SetDefault( const SfxPoolItem& rAttr ) 555 { 556 SfxItemSet aSet( GetAttrPool(), {{rAttr.Which(), rAttr.Which()}} ); 557 aSet.Put( rAttr ); 558 SetDefault( aSet ); 559 } 560 561 void SwDoc::SetDefault( const SfxItemSet& rSet ) 562 { 563 if( !rSet.Count() ) 564 return; 565 566 SwModify aCallMod( nullptr ); 567 SwAttrSet aOld( GetAttrPool(), rSet.GetRanges() ), 568 aNew( GetAttrPool(), rSet.GetRanges() ); 569 SfxItemIter aIter( rSet ); 570 const SfxPoolItem* pItem = aIter.GetCurItem(); 571 SfxItemPool* pSdrPool = GetAttrPool().GetSecondaryPool(); 572 while( true ) 573 { 574 bool bCheckSdrDflt = false; 575 const sal_uInt16 nWhich = pItem->Which(); 576 aOld.Put( GetAttrPool().GetDefaultItem( nWhich ) ); 577 GetAttrPool().SetPoolDefaultItem( *pItem ); 578 aNew.Put( GetAttrPool().GetDefaultItem( nWhich ) ); 579 580 if (isCHRATR(nWhich) || isTXTATR(nWhich)) 581 { 582 aCallMod.Add( mpDfltTextFormatColl.get() ); 583 aCallMod.Add( mpDfltCharFormat.get() ); 584 bCheckSdrDflt = nullptr != pSdrPool; 585 } 586 else if ( isPARATR(nWhich) || 587 isPARATR_LIST(nWhich) ) 588 { 589 aCallMod.Add( mpDfltTextFormatColl.get() ); 590 bCheckSdrDflt = nullptr != pSdrPool; 591 } 592 else if (isGRFATR(nWhich)) 593 { 594 aCallMod.Add( mpDfltGrfFormatColl.get() ); 595 } 596 else if (isFRMATR(nWhich) || isDrawingLayerAttribute(nWhich) ) 597 { 598 aCallMod.Add( mpDfltGrfFormatColl.get() ); 599 aCallMod.Add( mpDfltTextFormatColl.get() ); 600 aCallMod.Add( mpDfltFrameFormat.get() ); 601 } 602 else if (isBOXATR(nWhich)) 603 { 604 aCallMod.Add( mpDfltFrameFormat.get() ); 605 } 606 607 // also copy the defaults 608 if( bCheckSdrDflt ) 609 { 610 sal_uInt16 nEdtWhich, nSlotId; 611 if( 0 != (nSlotId = GetAttrPool().GetSlotId( nWhich ) ) && 612 nSlotId != nWhich && 613 0 != (nEdtWhich = pSdrPool->GetWhich( nSlotId )) && 614 nSlotId != nEdtWhich ) 615 { 616 std::unique_ptr<SfxPoolItem> pCpy(pItem->Clone()); 617 pCpy->SetWhich( nEdtWhich ); 618 pSdrPool->SetPoolDefaultItem( *pCpy ); 619 } 620 } 621 622 if( aIter.IsAtEnd() ) 623 break; 624 pItem = aIter.NextItem(); 625 } 626 627 if( aNew.Count() && aCallMod.HasWriterListeners() ) 628 { 629 if (GetIDocumentUndoRedo().DoesUndo()) 630 { 631 GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDefaultAttr>( aOld, this ) ); 632 } 633 634 const SfxPoolItem* pTmpItem; 635 if( ( SfxItemState::SET == 636 aNew.GetItemState( RES_PARATR_TABSTOP, false, &pTmpItem ) ) && 637 static_cast<const SvxTabStopItem*>(pTmpItem)->Count() ) 638 { 639 // Set the default values of all TabStops to the new value. 640 // Attention: we always work with the PoolAttribute here, so that 641 // we don't calculate the same value on the same TabStop (pooled!) for all sets. 642 // We send a FormatChg to modify. 643 SwTwips nNewWidth = (*static_cast<const SvxTabStopItem*>(pTmpItem))[ 0 ].GetTabPos(), 644 nOldWidth = aOld.Get(RES_PARATR_TABSTOP)[ 0 ].GetTabPos(); 645 646 bool bChg = false; 647 for (const SfxPoolItem* pItem2 : GetAttrPool().GetItemSurrogates(RES_PARATR_TABSTOP)) 648 { 649 auto pTabStopItem = dynamic_cast<const SvxTabStopItem*>(pItem2); 650 if(pTabStopItem) 651 bChg |= lcl_SetNewDefTabStops( nOldWidth, nNewWidth, 652 *const_cast<SvxTabStopItem*>(pTabStopItem) ); 653 } 654 655 aNew.ClearItem( RES_PARATR_TABSTOP ); 656 aOld.ClearItem( RES_PARATR_TABSTOP ); 657 if( bChg ) 658 { 659 SwFormatChg aChgFormat( mpDfltCharFormat.get() ); 660 // notify the frames 661 aCallMod.ModifyNotification( &aChgFormat, &aChgFormat ); 662 } 663 } 664 } 665 666 if( aNew.Count() && aCallMod.HasWriterListeners() ) 667 { 668 SwAttrSetChg aChgOld( aOld, aOld ); 669 SwAttrSetChg aChgNew( aNew, aNew ); 670 aCallMod.ModifyNotification( &aChgOld, &aChgNew ); // all changed are sent 671 } 672 673 // remove the default formats from the object again 674 SwIterator<SwClient, SwModify> aClientIter(aCallMod); 675 for(SwClient* pClient = aClientIter.First(); pClient; pClient = aClientIter.Next()) 676 aCallMod.Remove( pClient ); 677 678 getIDocumentState().SetModified(); 679 } 680 681 /// Get the default attribute in this document 682 const SfxPoolItem& SwDoc::GetDefault( sal_uInt16 nFormatHint ) const 683 { 684 return GetAttrPool().GetDefaultItem( nFormatHint ); 685 } 686 687 /// Delete the formats 688 void SwDoc::DelCharFormat(size_t nFormat, bool bBroadcast) 689 { 690 SwCharFormat * pDel = (*mpCharFormatTable)[nFormat]; 691 692 if (bBroadcast) 693 BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Char, 694 SfxHintId::StyleSheetErased); 695 696 if (GetIDocumentUndoRedo().DoesUndo()) 697 { 698 GetIDocumentUndoRedo().AppendUndo( 699 std::make_unique<SwUndoCharFormatDelete>(pDel, this)); 700 } 701 702 delete (*mpCharFormatTable)[nFormat]; 703 mpCharFormatTable->erase(mpCharFormatTable->begin() + nFormat); 704 705 getIDocumentState().SetModified(); 706 } 707 708 void SwDoc::DelCharFormat( SwCharFormat const *pFormat, bool bBroadcast ) 709 { 710 size_t nFormat = mpCharFormatTable->GetPos( pFormat ); 711 OSL_ENSURE( SIZE_MAX != nFormat, "Format not found," ); 712 DelCharFormat( nFormat, bBroadcast ); 713 } 714 715 void SwDoc::DelFrameFormat( SwFrameFormat *pFormat, bool bBroadcast ) 716 { 717 if( dynamic_cast<const SwTableBoxFormat*>( pFormat) != nullptr || dynamic_cast<const SwTableLineFormat*>( pFormat) != nullptr ) 718 { 719 OSL_ENSURE( false, "Format is not in the DocArray any more, " 720 "so it can be deleted with delete" ); 721 delete pFormat; 722 } 723 else 724 { 725 // The format has to be in the one or the other, we'll see in which one. 726 if (mpFrameFormatTable->ContainsFormat(*pFormat)) 727 { 728 if (bBroadcast) 729 BroadcastStyleOperation(pFormat->GetName(), 730 SfxStyleFamily::Frame, 731 SfxHintId::StyleSheetErased); 732 733 if (GetIDocumentUndoRedo().DoesUndo()) 734 { 735 GetIDocumentUndoRedo().AppendUndo( 736 std::make_unique<SwUndoFrameFormatDelete>(pFormat, this)); 737 } 738 739 mpFrameFormatTable->erase( pFormat ); 740 delete pFormat; 741 } 742 else 743 { 744 bool contains = GetSpzFrameFormats()->ContainsFormat(*pFormat); 745 OSL_ENSURE( contains, "FrameFormat not found." ); 746 if( contains ) 747 { 748 GetSpzFrameFormats()->erase( pFormat ); 749 delete pFormat; 750 } 751 } 752 } 753 } 754 755 void SwDoc::DelTableFrameFormat( SwTableFormat *pFormat ) 756 { 757 SwFrameFormats::const_iterator it = mpTableFrameFormatTable->find( pFormat ); 758 OSL_ENSURE( it != mpTableFrameFormatTable->end(), "Format not found," ); 759 mpTableFrameFormatTable->erase( it ); 760 delete pFormat; 761 } 762 763 /// Create the formats 764 SwFlyFrameFormat *SwDoc::MakeFlyFrameFormat( const OUString &rFormatName, 765 SwFrameFormat *pDerivedFrom ) 766 { 767 SwFlyFrameFormat *pFormat = new SwFlyFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom ); 768 GetSpzFrameFormats()->push_back(pFormat); 769 getIDocumentState().SetModified(); 770 return pFormat; 771 } 772 773 SwDrawFrameFormat *SwDoc::MakeDrawFrameFormat( const OUString &rFormatName, 774 SwFrameFormat *pDerivedFrom ) 775 { 776 SwDrawFrameFormat *pFormat = new SwDrawFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom); 777 GetSpzFrameFormats()->push_back(pFormat); 778 getIDocumentState().SetModified(); 779 return pFormat; 780 } 781 782 size_t SwDoc::GetTableFrameFormatCount(bool bUsed) const 783 { 784 if (!bUsed) 785 { 786 return mpTableFrameFormatTable->size(); 787 } 788 789 SwAutoFormatGetDocNode aGetHt(&GetNodes()); 790 size_t nCount = 0; 791 for (SwFrameFormat* const & pFormat : *mpTableFrameFormatTable) 792 { 793 if (!pFormat->GetInfo(aGetHt)) 794 nCount++; 795 } 796 return nCount; 797 } 798 799 SwFrameFormat& SwDoc::GetTableFrameFormat(size_t nFormat, bool bUsed) const 800 { 801 if (!bUsed) 802 { 803 return *((*mpTableFrameFormatTable)[nFormat]); 804 } 805 806 SwAutoFormatGetDocNode aGetHt(&GetNodes()); 807 808 size_t index = 0; 809 810 for (SwFrameFormat* const & pFormat : *mpTableFrameFormatTable) 811 { 812 if (!pFormat->GetInfo(aGetHt)) 813 { 814 if (index == nFormat) 815 return *pFormat; 816 else 817 index++; 818 } 819 } 820 throw std::out_of_range("Format index out of range."); 821 } 822 823 SwTableFormat* SwDoc::MakeTableFrameFormat( const OUString &rFormatName, 824 SwFrameFormat *pDerivedFrom ) 825 { 826 SwTableFormat* pFormat = new SwTableFormat( GetAttrPool(), rFormatName, pDerivedFrom ); 827 mpTableFrameFormatTable->push_back( pFormat ); 828 getIDocumentState().SetModified(); 829 830 return pFormat; 831 } 832 833 SwFrameFormat *SwDoc::MakeFrameFormat(const OUString &rFormatName, 834 SwFrameFormat *pDerivedFrom, 835 bool bBroadcast, bool bAuto) 836 { 837 SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), rFormatName, pDerivedFrom ); 838 839 pFormat->SetAuto(bAuto); 840 mpFrameFormatTable->push_back( pFormat ); 841 getIDocumentState().SetModified(); 842 843 if (GetIDocumentUndoRedo().DoesUndo()) 844 { 845 GetIDocumentUndoRedo().AppendUndo( 846 std::make_unique<SwUndoFrameFormatCreate>(pFormat, pDerivedFrom, this)); 847 } 848 849 if (bBroadcast) 850 { 851 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Frame, 852 SfxHintId::StyleSheetCreated); 853 } 854 855 return pFormat; 856 } 857 858 SwFormat *SwDoc::MakeFrameFormat_(const OUString &rFormatName, 859 SwFormat *pDerivedFrom, 860 bool bBroadcast, bool bAuto) 861 { 862 SwFrameFormat *pFrameFormat = dynamic_cast<SwFrameFormat*>(pDerivedFrom); 863 pFrameFormat = MakeFrameFormat( rFormatName, pFrameFormat, bBroadcast, bAuto ); 864 return dynamic_cast<SwFormat*>(pFrameFormat); 865 } 866 867 SwCharFormat *SwDoc::MakeCharFormat( const OUString &rFormatName, 868 SwCharFormat *pDerivedFrom, 869 bool bBroadcast ) 870 { 871 SwCharFormat *pFormat = new SwCharFormat( GetAttrPool(), rFormatName, pDerivedFrom ); 872 mpCharFormatTable->push_back( pFormat ); 873 pFormat->SetAuto(false); 874 getIDocumentState().SetModified(); 875 876 if (GetIDocumentUndoRedo().DoesUndo()) 877 { 878 GetIDocumentUndoRedo().AppendUndo( 879 std::make_unique<SwUndoCharFormatCreate>(pFormat, pDerivedFrom, this)); 880 } 881 882 if (bBroadcast) 883 { 884 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Char, 885 SfxHintId::StyleSheetCreated); 886 } 887 888 return pFormat; 889 } 890 891 SwFormat *SwDoc::MakeCharFormat_(const OUString &rFormatName, 892 SwFormat *pDerivedFrom, 893 bool bBroadcast, bool /*bAuto*/) 894 { 895 SwCharFormat *pCharFormat = dynamic_cast<SwCharFormat*>(pDerivedFrom); 896 pCharFormat = MakeCharFormat( rFormatName, pCharFormat, bBroadcast ); 897 return dynamic_cast<SwFormat*>(pCharFormat); 898 } 899 900 /// Create the FormatCollections 901 SwTextFormatColl* SwDoc::MakeTextFormatColl( const OUString &rFormatName, 902 SwTextFormatColl *pDerivedFrom, 903 bool bBroadcast) 904 { 905 SwTextFormatColl *pFormatColl = new SwTextFormatColl( GetAttrPool(), rFormatName, 906 pDerivedFrom ); 907 mpTextFormatCollTable->push_back(pFormatColl); 908 pFormatColl->SetAuto(false); 909 getIDocumentState().SetModified(); 910 911 if (GetIDocumentUndoRedo().DoesUndo()) 912 { 913 GetIDocumentUndoRedo().AppendUndo( 914 std::make_unique<SwUndoTextFormatCollCreate>(pFormatColl, pDerivedFrom, 915 this)); 916 } 917 918 if (bBroadcast) 919 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Para, 920 SfxHintId::StyleSheetCreated); 921 922 return pFormatColl; 923 } 924 925 SwFormat *SwDoc::MakeTextFormatColl_(const OUString &rFormatName, 926 SwFormat *pDerivedFrom, 927 bool bBroadcast, bool /*bAuto*/) 928 { 929 SwTextFormatColl *pTextFormatColl = dynamic_cast<SwTextFormatColl*>(pDerivedFrom); 930 pTextFormatColl = MakeTextFormatColl( rFormatName, pTextFormatColl, bBroadcast ); 931 return dynamic_cast<SwFormat*>(pTextFormatColl); 932 } 933 934 //FEATURE::CONDCOLL 935 SwConditionTextFormatColl* SwDoc::MakeCondTextFormatColl( const OUString &rFormatName, 936 SwTextFormatColl *pDerivedFrom, 937 bool bBroadcast) 938 { 939 SwConditionTextFormatColl*pFormatColl = new SwConditionTextFormatColl( GetAttrPool(), 940 rFormatName, pDerivedFrom ); 941 mpTextFormatCollTable->push_back(pFormatColl); 942 pFormatColl->SetAuto(false); 943 getIDocumentState().SetModified(); 944 945 if (GetIDocumentUndoRedo().DoesUndo()) 946 { 947 GetIDocumentUndoRedo().AppendUndo( 948 std::make_unique<SwUndoCondTextFormatCollCreate>(pFormatColl, pDerivedFrom, 949 this)); 950 } 951 952 if (bBroadcast) 953 BroadcastStyleOperation(rFormatName, SfxStyleFamily::Para, 954 SfxHintId::StyleSheetCreated); 955 956 return pFormatColl; 957 } 958 //FEATURE::CONDCOLL 959 960 // GRF 961 SwGrfFormatColl* SwDoc::MakeGrfFormatColl( const OUString &rFormatName, 962 SwGrfFormatColl *pDerivedFrom ) 963 { 964 SwGrfFormatColl *pFormatColl = new SwGrfFormatColl( GetAttrPool(), rFormatName, 965 pDerivedFrom ); 966 mpGrfFormatCollTable->push_back( pFormatColl ); 967 pFormatColl->SetAuto(false); 968 getIDocumentState().SetModified(); 969 return pFormatColl; 970 } 971 972 void SwDoc::DelTextFormatColl(size_t nFormatColl, bool bBroadcast) 973 { 974 OSL_ENSURE( nFormatColl, "Remove of Coll 0." ); 975 976 // Who has the to-be-deleted as their Next? 977 SwTextFormatColl *pDel = (*mpTextFormatCollTable)[nFormatColl]; 978 if( mpDfltTextFormatColl.get() == pDel ) 979 return; // never delete default! 980 981 if (bBroadcast) 982 BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Para, 983 SfxHintId::StyleSheetErased); 984 985 if (GetIDocumentUndoRedo().DoesUndo()) 986 { 987 std::unique_ptr<SwUndoTextFormatCollDelete> pUndo; 988 if (RES_CONDTXTFMTCOLL == pDel->Which()) 989 { 990 pUndo.reset(new SwUndoCondTextFormatCollDelete(pDel, this)); 991 } 992 else 993 { 994 pUndo.reset(new SwUndoTextFormatCollDelete(pDel, this)); 995 } 996 997 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo)); 998 } 999 1000 // Remove the FormatColl 1001 mpTextFormatCollTable->erase(mpTextFormatCollTable->begin() + nFormatColl); 1002 // Correct next 1003 for( SwTextFormatColls::const_iterator it = mpTextFormatCollTable->begin() + 1; it != mpTextFormatCollTable->end(); ++it ) 1004 SetTextFormatCollNext( *it, pDel ); 1005 delete pDel; 1006 getIDocumentState().SetModified(); 1007 } 1008 1009 void SwDoc::DelTextFormatColl( SwTextFormatColl const *pColl, bool bBroadcast ) 1010 { 1011 size_t nFormat = mpTextFormatCollTable->GetPos( pColl ); 1012 OSL_ENSURE( SIZE_MAX != nFormat, "Collection not found," ); 1013 DelTextFormatColl( nFormat, bBroadcast ); 1014 } 1015 1016 static bool lcl_SetTextFormatColl( const SwNodePtr& rpNode, void* pArgs ) 1017 { 1018 SwContentNode* pCNd = static_cast<SwContentNode*>(rpNode->GetTextNode()); 1019 1020 if( pCNd == nullptr) 1021 return true; 1022 1023 sw::DocumentContentOperationsManager::ParaRstFormat* pPara = static_cast<sw::DocumentContentOperationsManager::ParaRstFormat*>(pArgs); 1024 1025 if (pPara->pLayout && pPara->pLayout->IsHideRedlines()) 1026 { 1027 if (pCNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden) 1028 { 1029 return true; 1030 } 1031 if (pCNd->IsTextNode()) 1032 { 1033 pCNd = sw::GetParaPropsNode(*pPara->pLayout, SwNodeIndex(*pCNd)); 1034 } 1035 } 1036 1037 SwTextFormatColl* pFormat = static_cast<SwTextFormatColl*>(pPara->pFormatColl); 1038 if ( pPara->bReset ) 1039 { 1040 lcl_RstAttr(pCNd, pPara); 1041 1042 // #i62675# check, if paragraph style has changed 1043 if ( pPara->bResetListAttrs && 1044 pFormat != pCNd->GetFormatColl() && 1045 pFormat->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET ) 1046 { 1047 // Check, if the list style of the paragraph will change. 1048 bool bChangeOfListStyleAtParagraph( true ); 1049 SwTextNode& rTNd(dynamic_cast<SwTextNode&>(*pCNd)); 1050 { 1051 SwNumRule* pNumRuleAtParagraph(rTNd.GetNumRule()); 1052 if ( pNumRuleAtParagraph ) 1053 { 1054 const SwNumRuleItem& rNumRuleItemAtParagraphStyle = 1055 pFormat->GetNumRule(); 1056 if ( rNumRuleItemAtParagraphStyle.GetValue() == 1057 pNumRuleAtParagraph->GetName() ) 1058 { 1059 bChangeOfListStyleAtParagraph = false; 1060 } 1061 } 1062 } 1063 1064 if ( bChangeOfListStyleAtParagraph ) 1065 { 1066 std::unique_ptr< SwRegHistory > pRegH; 1067 if ( pPara->pHistory ) 1068 { 1069 pRegH.reset(new SwRegHistory(&rTNd, rTNd, pPara->pHistory)); 1070 } 1071 1072 pCNd->ResetAttr( RES_PARATR_NUMRULE ); 1073 1074 // reset all list attributes 1075 pCNd->ResetAttr( RES_PARATR_LIST_LEVEL ); 1076 pCNd->ResetAttr( RES_PARATR_LIST_ISRESTART ); 1077 pCNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 1078 pCNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 1079 pCNd->ResetAttr( RES_PARATR_LIST_ID ); 1080 } 1081 } 1082 } 1083 1084 // add to History so that old data is saved, if necessary 1085 if( pPara->pHistory ) 1086 pPara->pHistory->Add( pCNd->GetFormatColl(), pCNd->GetIndex(), 1087 SwNodeType::Text ); 1088 1089 pCNd->ChgFormatColl( pFormat ); 1090 1091 pPara->nWhich++; 1092 1093 return true; 1094 } 1095 1096 bool SwDoc::SetTextFormatColl(const SwPaM &rRg, 1097 SwTextFormatColl *pFormat, 1098 const bool bReset, 1099 const bool bResetListAttrs, 1100 SwRootFrame const*const pLayout) 1101 { 1102 SwDataChanged aTmp( rRg ); 1103 const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End(); 1104 SwHistory* pHst = nullptr; 1105 bool bRet = true; 1106 1107 if (GetIDocumentUndoRedo().DoesUndo()) 1108 { 1109 std::unique_ptr<SwUndoFormatColl> pUndo(new SwUndoFormatColl( rRg, pFormat, 1110 bReset, 1111 bResetListAttrs )); 1112 pHst = pUndo->GetHistory(); 1113 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo)); 1114 } 1115 1116 sw::DocumentContentOperationsManager::ParaRstFormat aPara( 1117 pStt, pEnd, pHst, nullptr, pLayout); 1118 aPara.pFormatColl = pFormat; 1119 aPara.bReset = bReset; 1120 // #i62675# 1121 aPara.bResetListAttrs = bResetListAttrs; 1122 1123 GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1, 1124 lcl_SetTextFormatColl, &aPara ); 1125 if( !aPara.nWhich ) 1126 bRet = false; // didn't find a valid Node 1127 1128 if (bRet) 1129 { 1130 getIDocumentState().SetModified(); 1131 } 1132 1133 return bRet; 1134 } 1135 1136 /// Copy the formats to itself 1137 SwFormat* SwDoc::CopyFormat( const SwFormat& rFormat, 1138 const SwFormatsBase& rFormatArr, 1139 FNCopyFormat fnCopyFormat, const SwFormat& rDfltFormat ) 1140 { 1141 // It's no autoformat, default format or collection format, 1142 // then search for it. 1143 if( !rFormat.IsAuto() || !rFormat.GetRegisteredIn() ) 1144 for( size_t n = 0; n < rFormatArr.GetFormatCount(); ++n ) 1145 { 1146 // Does the Doc already contain the template? 1147 if( rFormatArr.GetFormat(n)->GetName()==rFormat.GetName() ) 1148 return rFormatArr.GetFormat(n); 1149 } 1150 1151 // Search for the "parent" first 1152 SwFormat* pParent = const_cast<SwFormat*>(&rDfltFormat); 1153 if( rFormat.DerivedFrom() && pParent != rFormat.DerivedFrom() ) 1154 pParent = CopyFormat( *rFormat.DerivedFrom(), rFormatArr, 1155 fnCopyFormat, rDfltFormat ); 1156 1157 // Create the format and copy the attributes 1158 // #i40550# 1159 SwFormat* pNewFormat = (this->*fnCopyFormat)( rFormat.GetName(), pParent, false, true ); 1160 pNewFormat->SetAuto( rFormat.IsAuto() ); 1161 pNewFormat->CopyAttrs( rFormat ); // copy the attributes 1162 1163 pNewFormat->SetPoolFormatId( rFormat.GetPoolFormatId() ); 1164 pNewFormat->SetPoolHelpId( rFormat.GetPoolHelpId() ); 1165 1166 // Always set the HelpFile Id to default! 1167 pNewFormat->SetPoolHlpFileId( UCHAR_MAX ); 1168 1169 return pNewFormat; 1170 } 1171 1172 /// copy the frame format 1173 SwFrameFormat* SwDoc::CopyFrameFormat( const SwFrameFormat& rFormat ) 1174 { 1175 return static_cast<SwFrameFormat*>(CopyFormat( rFormat, *GetFrameFormats(), &SwDoc::MakeFrameFormat_, 1176 *GetDfltFrameFormat() )); 1177 } 1178 1179 /// copy the char format 1180 SwCharFormat* SwDoc::CopyCharFormat( const SwCharFormat& rFormat ) 1181 { 1182 return static_cast<SwCharFormat*>(CopyFormat( rFormat, *GetCharFormats(), 1183 &SwDoc::MakeCharFormat_, 1184 *GetDfltCharFormat() )); 1185 } 1186 1187 /// copy TextNodes 1188 SwTextFormatColl* SwDoc::CopyTextColl( const SwTextFormatColl& rColl ) 1189 { 1190 SwTextFormatColl* pNewColl = FindTextFormatCollByName( rColl.GetName() ); 1191 if( pNewColl ) 1192 return pNewColl; 1193 1194 // search for the "parent" first 1195 SwTextFormatColl* pParent = mpDfltTextFormatColl.get(); 1196 if( pParent != rColl.DerivedFrom() ) 1197 pParent = CopyTextColl( *static_cast<SwTextFormatColl*>(rColl.DerivedFrom()) ); 1198 1199 //FEATURE::CONDCOLL 1200 if( RES_CONDTXTFMTCOLL == rColl.Which() ) 1201 { 1202 pNewColl = new SwConditionTextFormatColl( GetAttrPool(), rColl.GetName(), 1203 pParent); 1204 mpTextFormatCollTable->push_back( pNewColl ); 1205 pNewColl->SetAuto(false); 1206 getIDocumentState().SetModified(); 1207 1208 // copy the conditions 1209 static_cast<SwConditionTextFormatColl*>(pNewColl)->SetConditions( 1210 static_cast<const SwConditionTextFormatColl&>(rColl).GetCondColls() ); 1211 } 1212 else 1213 //FEATURE::CONDCOLL 1214 pNewColl = MakeTextFormatColl( rColl.GetName(), pParent ); 1215 1216 // copy the auto formats or the attributes 1217 pNewColl->CopyAttrs( rColl ); 1218 1219 if(rColl.IsAssignedToListLevelOfOutlineStyle()) 1220 pNewColl->AssignToListLevelOfOutlineStyle(rColl.GetAssignedOutlineStyleLevel()); 1221 pNewColl->SetPoolFormatId( rColl.GetPoolFormatId() ); 1222 pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() ); 1223 1224 // Always set the HelpFile Id to default! 1225 pNewColl->SetPoolHlpFileId( UCHAR_MAX ); 1226 1227 if( &rColl.GetNextTextFormatColl() != &rColl ) 1228 pNewColl->SetNextTextFormatColl( *CopyTextColl( rColl.GetNextTextFormatColl() )); 1229 1230 // create the NumRule if necessary 1231 if( this != rColl.GetDoc() ) 1232 { 1233 const SfxPoolItem* pItem; 1234 if( SfxItemState::SET == pNewColl->GetItemState( RES_PARATR_NUMRULE, 1235 false, &pItem )) 1236 { 1237 const SwNumRule* pRule; 1238 const OUString& rName = static_cast<const SwNumRuleItem*>(pItem)->GetValue(); 1239 if( !rName.isEmpty() && 1240 nullptr != ( pRule = rColl.GetDoc()->FindNumRulePtr( rName )) && 1241 !pRule->IsAutoRule() ) 1242 { 1243 SwNumRule* pDestRule = FindNumRulePtr( rName ); 1244 if( pDestRule ) 1245 pDestRule->SetInvalidRule( true ); 1246 else 1247 MakeNumRule( rName, pRule ); 1248 } 1249 } 1250 } 1251 return pNewColl; 1252 } 1253 1254 /// copy the graphic nodes 1255 SwGrfFormatColl* SwDoc::CopyGrfColl( const SwGrfFormatColl& rColl ) 1256 { 1257 SwGrfFormatColl* pNewColl = static_cast<SwGrfFormatColl*>(FindFormatByName( static_cast<SwFormatsBase const &>(*mpGrfFormatCollTable), rColl.GetName() )); 1258 if( pNewColl ) 1259 return pNewColl; 1260 1261 // Search for the "parent" first 1262 SwGrfFormatColl* pParent = mpDfltGrfFormatColl.get(); 1263 if( pParent != rColl.DerivedFrom() ) 1264 pParent = CopyGrfColl( *static_cast<SwGrfFormatColl*>(rColl.DerivedFrom()) ); 1265 1266 // if not, copy them 1267 pNewColl = MakeGrfFormatColl( rColl.GetName(), pParent ); 1268 1269 // copy the attributes 1270 pNewColl->CopyAttrs( rColl ); 1271 1272 pNewColl->SetPoolFormatId( rColl.GetPoolFormatId() ); 1273 pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() ); 1274 1275 // Always set the HelpFile Id to default! 1276 pNewColl->SetPoolHlpFileId( UCHAR_MAX ); 1277 1278 return pNewColl; 1279 } 1280 1281 void SwDoc::CopyFormatArr( const SwFormatsBase& rSourceArr, 1282 SwFormatsBase const & rDestArr, 1283 FNCopyFormat fnCopyFormat, 1284 SwFormat& rDfltFormat ) 1285 { 1286 SwFormat* pSrc, *pDest; 1287 1288 // 1st step: Create all formats (skip the 0th - it's the default one) 1289 for( size_t nSrc = rSourceArr.GetFormatCount(); nSrc > 1; ) 1290 { 1291 pSrc = rSourceArr.GetFormat( --nSrc ); 1292 if( pSrc->IsDefault() || pSrc->IsAuto() ) 1293 continue; 1294 1295 if( nullptr == FindFormatByName( rDestArr, pSrc->GetName() ) ) 1296 { 1297 if( RES_CONDTXTFMTCOLL == pSrc->Which() ) 1298 MakeCondTextFormatColl( pSrc->GetName(), static_cast<SwTextFormatColl*>(&rDfltFormat) ); 1299 else 1300 // #i40550# 1301 (this->*fnCopyFormat)( pSrc->GetName(), &rDfltFormat, false, true ); 1302 } 1303 } 1304 1305 // 2nd step: Copy all attributes, set the right parents 1306 for( size_t nSrc = rSourceArr.GetFormatCount(); nSrc > 1; ) 1307 { 1308 pSrc = rSourceArr.GetFormat( --nSrc ); 1309 if( pSrc->IsDefault() || pSrc->IsAuto() ) 1310 continue; 1311 1312 pDest = FindFormatByName( rDestArr, pSrc->GetName() ); 1313 pDest->SetAuto(false); 1314 pDest->DelDiffs( *pSrc ); 1315 1316 // #i94285#: existing <SwFormatPageDesc> instance, before copying attributes 1317 const SfxPoolItem* pItem; 1318 if( &GetAttrPool() != pSrc->GetAttrSet().GetPool() && 1319 SfxItemState::SET == pSrc->GetAttrSet().GetItemState( 1320 RES_PAGEDESC, false, &pItem ) && 1321 static_cast<const SwFormatPageDesc*>(pItem)->GetPageDesc() ) 1322 { 1323 SwFormatPageDesc aPageDesc( *static_cast<const SwFormatPageDesc*>(pItem) ); 1324 const OUString& rNm = aPageDesc.GetPageDesc()->GetName(); 1325 SwPageDesc* pPageDesc = FindPageDesc( rNm ); 1326 if( !pPageDesc ) 1327 { 1328 pPageDesc = MakePageDesc(rNm); 1329 } 1330 aPageDesc.RegisterToPageDesc( *pPageDesc ); 1331 SwAttrSet aTmpAttrSet( pSrc->GetAttrSet() ); 1332 aTmpAttrSet.Put( aPageDesc ); 1333 pDest->SetFormatAttr( aTmpAttrSet ); 1334 } 1335 else 1336 { 1337 pDest->SetFormatAttr( pSrc->GetAttrSet() ); 1338 } 1339 1340 pDest->SetPoolFormatId( pSrc->GetPoolFormatId() ); 1341 pDest->SetPoolHelpId( pSrc->GetPoolHelpId() ); 1342 1343 // Always set the HelpFile Id to default! 1344 pDest->SetPoolHlpFileId( UCHAR_MAX ); 1345 1346 if( pSrc->DerivedFrom() ) 1347 pDest->SetDerivedFrom( FindFormatByName( rDestArr, 1348 pSrc->DerivedFrom()->GetName() ) ); 1349 if( RES_TXTFMTCOLL == pSrc->Which() || 1350 RES_CONDTXTFMTCOLL == pSrc->Which() ) 1351 { 1352 SwTextFormatColl* pSrcColl = static_cast<SwTextFormatColl*>(pSrc), 1353 * pDstColl = static_cast<SwTextFormatColl*>(pDest); 1354 if( &pSrcColl->GetNextTextFormatColl() != pSrcColl ) 1355 pDstColl->SetNextTextFormatColl( *static_cast<SwTextFormatColl*>(FindFormatByName( 1356 rDestArr, pSrcColl->GetNextTextFormatColl().GetName() ) ) ); 1357 1358 if(pSrcColl->IsAssignedToListLevelOfOutlineStyle()) 1359 pDstColl->AssignToListLevelOfOutlineStyle(pSrcColl->GetAssignedOutlineStyleLevel()); 1360 1361 //FEATURE::CONDCOLL 1362 if( RES_CONDTXTFMTCOLL == pSrc->Which() ) 1363 // Copy the conditions, but delete the old ones first! 1364 static_cast<SwConditionTextFormatColl*>(pDstColl)->SetConditions( 1365 static_cast<SwConditionTextFormatColl*>(pSrc)->GetCondColls() ); 1366 //FEATURE::CONDCOLL 1367 } 1368 } 1369 } 1370 1371 void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader, 1372 const SwFrameFormat& rSrcFormat, SwFrameFormat& rDestFormat ) 1373 { 1374 // Treat the header and footer attributes in the right way: 1375 // Copy content nodes across documents! 1376 sal_uInt16 nAttr = bCpyHeader ? sal_uInt16(RES_HEADER) : sal_uInt16(RES_FOOTER); 1377 const SfxPoolItem* pItem; 1378 if( SfxItemState::SET != rSrcFormat.GetAttrSet().GetItemState( nAttr, false, &pItem )) 1379 return ; 1380 1381 // The header only contains the reference to the format from the other document! 1382 std::unique_ptr<SfxPoolItem> pNewItem(pItem->Clone()); 1383 1384 SwFrameFormat* pOldFormat; 1385 if( bCpyHeader ) 1386 pOldFormat = static_cast<SwFormatHeader*>(pNewItem.get())->GetHeaderFormat(); 1387 else 1388 pOldFormat = static_cast<SwFormatFooter*>(pNewItem.get())->GetFooterFormat(); 1389 1390 if( pOldFormat ) 1391 { 1392 SwFrameFormat* pNewFormat = new SwFrameFormat( GetAttrPool(), "CpyDesc", 1393 GetDfltFrameFormat() ); 1394 pNewFormat->CopyAttrs( *pOldFormat ); 1395 1396 if( SfxItemState::SET == pNewFormat->GetAttrSet().GetItemState( 1397 RES_CNTNT, false, &pItem )) 1398 { 1399 const SwFormatContent* pContent = static_cast<const SwFormatContent*>(pItem); 1400 if( pContent->GetContentIdx() ) 1401 { 1402 SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() ); 1403 const SwNodes& rSrcNds = rSrcFormat.GetDoc()->GetNodes(); 1404 SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmpIdx, 1405 bCpyHeader 1406 ? SwHeaderStartNode 1407 : SwFooterStartNode ); 1408 const SwNode& rCSttNd = pContent->GetContentIdx()->GetNode(); 1409 SwNodeRange aRg( rCSttNd, 0, *rCSttNd.EndOfSectionNode() ); 1410 aTmpIdx = *pSttNd->EndOfSectionNode(); 1411 rSrcNds.Copy_( aRg, aTmpIdx ); 1412 aTmpIdx = *pSttNd; 1413 rSrcFormat.GetDoc()->GetDocumentContentOperationsManager().CopyFlyInFlyImpl( aRg, 0, aTmpIdx ); 1414 pNewFormat->SetFormatAttr( SwFormatContent( pSttNd )); 1415 } 1416 else 1417 pNewFormat->ResetFormatAttr( RES_CNTNT ); 1418 } 1419 if( bCpyHeader ) 1420 static_cast<SwFormatHeader*>(pNewItem.get())->RegisterToFormat(*pNewFormat); 1421 else 1422 static_cast<SwFormatFooter*>(pNewItem.get())->RegisterToFormat(*pNewFormat); 1423 rDestFormat.SetFormatAttr( *pNewItem ); 1424 } 1425 } 1426 1427 void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc, 1428 bool bCopyPoolIds ) 1429 { 1430 bool bNotifyLayout = false; 1431 SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout(); 1432 1433 rDstDesc.SetLandscape( rSrcDesc.GetLandscape() ); 1434 rDstDesc.SetNumType( rSrcDesc.GetNumType() ); 1435 if( rDstDesc.ReadUseOn() != rSrcDesc.ReadUseOn() ) 1436 { 1437 rDstDesc.WriteUseOn( rSrcDesc.ReadUseOn() ); 1438 bNotifyLayout = true; 1439 } 1440 1441 if( bCopyPoolIds ) 1442 { 1443 rDstDesc.SetPoolFormatId( rSrcDesc.GetPoolFormatId() ); 1444 rDstDesc.SetPoolHelpId( rSrcDesc.GetPoolHelpId() ); 1445 // Always set the HelpFile Id to default! 1446 rDstDesc.SetPoolHlpFileId( UCHAR_MAX ); 1447 } 1448 1449 if( rSrcDesc.GetFollow() != &rSrcDesc ) 1450 { 1451 const SwPageDesc* pSrcFollow = rSrcDesc.GetFollow(); 1452 SwPageDesc* pFollow = FindPageDesc( pSrcFollow->GetName() ); 1453 if( !pFollow ) 1454 { 1455 // copy 1456 pFollow = MakePageDesc( pSrcFollow->GetName() ); 1457 CopyPageDesc( *pSrcFollow, *pFollow ); 1458 } 1459 rDstDesc.SetFollow( pFollow ); 1460 bNotifyLayout = true; 1461 } 1462 1463 // the header and footer attributes are copied separately 1464 // the content sections have to be copied in their entirety 1465 { 1466 SfxItemSet aAttrSet( rSrcDesc.GetMaster().GetAttrSet() ); 1467 aAttrSet.ClearItem( RES_HEADER ); 1468 aAttrSet.ClearItem( RES_FOOTER ); 1469 1470 rDstDesc.GetMaster().DelDiffs( aAttrSet ); 1471 rDstDesc.GetMaster().SetFormatAttr( aAttrSet ); 1472 1473 aAttrSet.ClearItem(); 1474 aAttrSet.Put( rSrcDesc.GetLeft().GetAttrSet() ); 1475 aAttrSet.ClearItem( RES_HEADER ); 1476 aAttrSet.ClearItem( RES_FOOTER ); 1477 1478 rDstDesc.GetLeft().DelDiffs( aAttrSet ); 1479 rDstDesc.GetLeft().SetFormatAttr( aAttrSet ); 1480 1481 aAttrSet.ClearItem(); 1482 aAttrSet.Put( rSrcDesc.GetFirstMaster().GetAttrSet() ); 1483 aAttrSet.ClearItem( RES_HEADER ); 1484 aAttrSet.ClearItem( RES_FOOTER ); 1485 1486 rDstDesc.GetFirstMaster().DelDiffs( aAttrSet ); 1487 rDstDesc.GetFirstMaster().SetFormatAttr( aAttrSet ); 1488 1489 aAttrSet.ClearItem(); 1490 aAttrSet.Put( rSrcDesc.GetFirstLeft().GetAttrSet() ); 1491 aAttrSet.ClearItem( RES_HEADER ); 1492 aAttrSet.ClearItem( RES_FOOTER ); 1493 1494 rDstDesc.GetFirstLeft().DelDiffs( aAttrSet ); 1495 rDstDesc.GetFirstLeft().SetFormatAttr( aAttrSet ); 1496 } 1497 1498 CopyHeader( rSrcDesc.GetMaster(), rDstDesc.GetMaster() ); 1499 CopyFooter( rSrcDesc.GetMaster(), rDstDesc.GetMaster() ); 1500 if( !rDstDesc.IsHeaderShared() ) 1501 CopyHeader( rSrcDesc.GetLeft(), rDstDesc.GetLeft() ); 1502 else 1503 rDstDesc.GetLeft().SetFormatAttr( rDstDesc.GetMaster().GetHeader() ); 1504 if( !rDstDesc.IsFirstShared() ) 1505 { 1506 CopyHeader( rSrcDesc.GetFirstMaster(), rDstDesc.GetFirstMaster() ); 1507 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetFirstMaster().GetHeader()); 1508 } 1509 else 1510 { 1511 rDstDesc.GetFirstMaster().SetFormatAttr( rDstDesc.GetMaster().GetHeader() ); 1512 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetLeft().GetHeader()); 1513 } 1514 1515 if( !rDstDesc.IsFooterShared() ) 1516 CopyFooter( rSrcDesc.GetLeft(), rDstDesc.GetLeft() ); 1517 else 1518 rDstDesc.GetLeft().SetFormatAttr( rDstDesc.GetMaster().GetFooter() ); 1519 if( !rDstDesc.IsFirstShared() ) 1520 { 1521 CopyFooter( rSrcDesc.GetFirstMaster(), rDstDesc.GetFirstMaster() ); 1522 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetFirstMaster().GetFooter()); 1523 } 1524 else 1525 { 1526 rDstDesc.GetFirstMaster().SetFormatAttr( rDstDesc.GetMaster().GetFooter() ); 1527 rDstDesc.GetFirstLeft().SetFormatAttr(rDstDesc.GetLeft().GetFooter()); 1528 } 1529 1530 if( bNotifyLayout && pTmpRoot ) 1531 { 1532 for( auto aLayout : GetAllLayouts() ) 1533 aLayout->AllCheckPageDescs(); 1534 } 1535 1536 // If foot notes change the pages have to be triggered 1537 if( !(rDstDesc.GetFootnoteInfo() == rSrcDesc.GetFootnoteInfo()) ) 1538 { 1539 sw::PageFootnoteHint aHint; 1540 rDstDesc.SetFootnoteInfo( rSrcDesc.GetFootnoteInfo() ); 1541 rDstDesc.GetMaster().CallSwClientNotify(aHint); 1542 rDstDesc.GetLeft().CallSwClientNotify(aHint); 1543 rDstDesc.GetFirstMaster().CallSwClientNotify(aHint); 1544 rDstDesc.GetFirstLeft().CallSwClientNotify(aHint); 1545 } 1546 } 1547 1548 void SwDoc::ReplaceStyles( const SwDoc& rSource, bool bIncludePageStyles ) 1549 { 1550 ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); 1551 1552 CopyFormatArr( *rSource.mpCharFormatTable, *mpCharFormatTable, 1553 &SwDoc::MakeCharFormat_, *mpDfltCharFormat ); 1554 CopyFormatArr( *rSource.mpFrameFormatTable, *mpFrameFormatTable, 1555 &SwDoc::MakeFrameFormat_, *mpDfltFrameFormat ); 1556 CopyFormatArr( *rSource.mpTextFormatCollTable, *mpTextFormatCollTable, 1557 &SwDoc::MakeTextFormatColl_, *mpDfltTextFormatColl ); 1558 1559 //To-Do: 1560 // a) in rtf export don't export our hideous pgdsctbl 1561 // extension to rtf anymore 1562 // b) in sd rtf import (View::InsertData) don't use 1563 // a super-fragile test for mere presence of \trowd to 1564 // indicate import of rtf into a table 1565 // c) then drop use of bIncludePageStyles 1566 if (bIncludePageStyles) 1567 { 1568 // and now the page templates 1569 SwPageDescs::size_type nCnt = rSource.m_PageDescs.size(); 1570 if( nCnt ) 1571 { 1572 // a different Doc -> Number formatter needs to be merged 1573 SwTableNumFormatMerge aTNFM( rSource, *this ); 1574 1575 // 1st step: Create all formats (skip the 0th - it's the default!) 1576 while( nCnt ) 1577 { 1578 const SwPageDesc &rSrc = *rSource.m_PageDescs[ --nCnt ]; 1579 if( nullptr == FindPageDesc( rSrc.GetName() ) ) 1580 MakePageDesc( rSrc.GetName() ); 1581 } 1582 1583 // 2nd step: Copy all attributes, set the right parents 1584 for (SwPageDescs::size_type i = rSource.m_PageDescs.size(); i; ) 1585 { 1586 const SwPageDesc &rSrc = *rSource.m_PageDescs[ --i ]; 1587 SwPageDesc* pDesc = FindPageDesc( rSrc.GetName() ); 1588 CopyPageDesc( rSrc, *pDesc); 1589 } 1590 } 1591 } 1592 1593 // then there are the numbering templates 1594 const SwNumRuleTable::size_type nCnt = rSource.GetNumRuleTable().size(); 1595 if( nCnt ) 1596 { 1597 const SwNumRuleTable& rArr = rSource.GetNumRuleTable(); 1598 for( SwNumRuleTable::size_type n = 0; n < nCnt; ++n ) 1599 { 1600 const SwNumRule& rR = *rArr[ n ]; 1601 SwNumRule* pNew = FindNumRulePtr( rR.GetName()); 1602 if( pNew ) 1603 pNew->CopyNumRule( this, rR ); 1604 else 1605 { 1606 if( !rR.IsAutoRule() ) 1607 MakeNumRule( rR.GetName(), &rR ); 1608 else 1609 { 1610 // as we reset all styles, there shouldn't be any unknown 1611 // automatic SwNumRules, because all should have been 1612 // created by the style copying! 1613 // So just warn and ignore. 1614 SAL_WARN( "sw.core", "Found unknown auto SwNumRule during reset!" ); 1615 } 1616 } 1617 } 1618 } 1619 1620 if (undoGuard.UndoWasEnabled()) 1621 { 1622 // nodes array was modified! 1623 GetIDocumentUndoRedo().DelAllUndoObj(); 1624 } 1625 1626 getIDocumentState().SetModified(); 1627 } 1628 1629 SwFormat* SwDoc::FindFormatByName( const SwFormatsBase& rFormatArr, 1630 const OUString& rName ) 1631 { 1632 SwFormat* pFnd = nullptr; 1633 for( size_t n = 0; n < rFormatArr.GetFormatCount(); ++n ) 1634 { 1635 // Does the Doc already contain the template? 1636 if( rFormatArr.GetFormat(n)->HasName( rName ) ) 1637 { 1638 pFnd = rFormatArr.GetFormat(n); 1639 break; 1640 } 1641 } 1642 return pFnd; 1643 } 1644 1645 void SwDoc::MoveLeftMargin(const SwPaM& rPam, bool bRight, bool bModulus, 1646 SwRootFrame const*const pLayout) 1647 { 1648 SwHistory* pHistory = nullptr; 1649 if (GetIDocumentUndoRedo().DoesUndo()) 1650 { 1651 std::unique_ptr<SwUndoMoveLeftMargin> pUndo(new SwUndoMoveLeftMargin( rPam, bRight, 1652 bModulus )); 1653 pHistory = &pUndo->GetHistory(); 1654 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) ); 1655 } 1656 1657 const SvxTabStopItem& rTabItem = GetDefault( RES_PARATR_TABSTOP ); 1658 const sal_Int32 nDefDist = rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134; 1659 const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End(); 1660 SwNodeIndex aIdx( rStt.nNode ); 1661 while( aIdx <= rEnd.nNode ) 1662 { 1663 SwTextNode* pTNd = aIdx.GetNode().GetTextNode(); 1664 if( pTNd ) 1665 { 1666 pTNd = sw::GetParaPropsNode(*pLayout, aIdx); 1667 SvxLRSpaceItem aLS( static_cast<const SvxLRSpaceItem&>(pTNd->SwContentNode::GetAttr( RES_LR_SPACE )) ); 1668 1669 // #i93873# See also lcl_MergeListLevelIndentAsLRSpaceItem in thints.cxx 1670 if ( pTNd->AreListLevelIndentsApplicable() ) 1671 { 1672 const SwNumRule* pRule = pTNd->GetNumRule(); 1673 if ( pRule ) 1674 { 1675 const int nListLevel = pTNd->GetActualListLevel(); 1676 if ( nListLevel >= 0 ) 1677 { 1678 const SwNumFormat& rFormat = pRule->Get(static_cast<sal_uInt16>(nListLevel)); 1679 if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 1680 { 1681 aLS.SetTextLeft( rFormat.GetIndentAt() ); 1682 aLS.SetTextFirstLineOfst( static_cast<short>(rFormat.GetFirstLineIndent()) ); 1683 } 1684 } 1685 } 1686 } 1687 1688 long nNext = aLS.GetTextLeft(); 1689 if( bModulus ) 1690 nNext = ( nNext / nDefDist ) * nDefDist; 1691 1692 if( bRight ) 1693 nNext += nDefDist; 1694 else 1695 if(nNext >0) // fdo#75936 set limit for decreasing indent 1696 nNext -= nDefDist; 1697 1698 aLS.SetTextLeft( nNext ); 1699 1700 SwRegHistory aRegH( pTNd, *pTNd, pHistory ); 1701 pTNd->SetAttr( aLS ); 1702 aIdx = *sw::GetFirstAndLastNode(*pLayout, aIdx).second; 1703 } 1704 ++aIdx; 1705 } 1706 getIDocumentState().SetModified(); 1707 } 1708 1709 bool SwDoc::DontExpandFormat( const SwPosition& rPos, bool bFlag ) 1710 { 1711 bool bRet = false; 1712 SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode(); 1713 if( pTextNd ) 1714 { 1715 bRet = pTextNd->DontExpandFormat( rPos.nContent, bFlag ); 1716 if( bRet && GetIDocumentUndoRedo().DoesUndo() ) 1717 { 1718 GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoDontExpandFormat>(rPos) ); 1719 } 1720 } 1721 return bRet; 1722 } 1723 1724 SwTableBoxFormat* SwDoc::MakeTableBoxFormat() 1725 { 1726 SwTableBoxFormat* pFormat = new SwTableBoxFormat( GetAttrPool(), mpDfltFrameFormat.get() ); 1727 getIDocumentState().SetModified(); 1728 return pFormat; 1729 } 1730 1731 SwTableLineFormat* SwDoc::MakeTableLineFormat() 1732 { 1733 SwTableLineFormat* pFormat = new SwTableLineFormat( GetAttrPool(), mpDfltFrameFormat.get() ); 1734 getIDocumentState().SetModified(); 1735 return pFormat; 1736 } 1737 1738 void SwDoc::EnsureNumberFormatter() 1739 { 1740 comphelper::doubleCheckedInit(mpNumberFormatter, []() 1741 { 1742 LanguageType eLang = LANGUAGE_SYSTEM; 1743 SvNumberFormatter* pRet = new SvNumberFormatter(comphelper::getProcessComponentContext(), eLang); 1744 pRet->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT_INTL ); 1745 if (!utl::ConfigManager::IsFuzzing()) 1746 pRet->SetYear2000(static_cast<sal_uInt16>(::utl::MiscCfg().GetYear2000())); 1747 return pRet; 1748 }); 1749 } 1750 1751 SwTableNumFormatMerge::SwTableNumFormatMerge( const SwDoc& rSrc, SwDoc& rDest ) 1752 : pNFormat( nullptr ) 1753 { 1754 // a different Doc -> Number formatter needs to be merged 1755 SvNumberFormatter* pN; 1756 if( &rSrc != &rDest && nullptr != ( pN = const_cast<SwDoc&>(rSrc).GetNumberFormatter( false ) )) 1757 { 1758 pNFormat = rDest.GetNumberFormatter(); 1759 pNFormat->MergeFormatter( *pN ); 1760 } 1761 1762 if( &rSrc != &rDest ) 1763 static_cast<SwGetRefFieldType*>(rSrc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef ))-> 1764 MergeWithOtherDoc( rDest ); 1765 } 1766 1767 SwTableNumFormatMerge::~SwTableNumFormatMerge() 1768 { 1769 if( pNFormat ) 1770 pNFormat->ClearMergeTable(); 1771 } 1772 1773 void SwDoc::SetTextFormatCollByAutoFormat( const SwPosition& rPos, sal_uInt16 nPoolId, 1774 const SfxItemSet* pSet ) 1775 { 1776 SwPaM aPam( rPos ); 1777 SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode(); 1778 assert(pTNd); 1779 1780 if (mbIsAutoFormatRedline) 1781 { 1782 // create the redline object 1783 const SwTextFormatColl& rColl = *pTNd->GetTextColl(); 1784 SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::FmtColl, aPam ); 1785 pRedl->SetMark(); 1786 1787 // Only those items that are not set by the Set again in the Node 1788 // are of interest. Thus, we take the difference. 1789 SwRedlineExtraData_FormatColl aExtraData( rColl.GetName(), 1790 rColl.GetPoolFormatId() ); 1791 if( pSet && pTNd->HasSwAttrSet() ) 1792 { 1793 SfxItemSet aTmp( *pTNd->GetpSwAttrSet() ); 1794 aTmp.Differentiate( *pSet ); 1795 // we handle the adjust item separately 1796 const SfxPoolItem* pItem; 1797 if( SfxItemState::SET == pTNd->GetpSwAttrSet()->GetItemState( 1798 RES_PARATR_ADJUST, false, &pItem )) 1799 aTmp.Put( *pItem ); 1800 aExtraData.SetItemSet( aTmp ); 1801 } 1802 pRedl->SetExtraData( &aExtraData ); 1803 1804 //TODO: Undo is still missing! 1805 getIDocumentRedlineAccess().AppendRedline( pRedl, true ); 1806 } 1807 1808 SetTextFormatColl( aPam, getIDocumentStylePoolAccess().GetTextCollFromPool( nPoolId ) ); 1809 1810 if (pSet && pSet->Count()) 1811 { 1812 aPam.SetMark(); 1813 aPam.GetMark()->nContent.Assign(pTNd, pTNd->GetText().getLength()); 1814 // sw_redlinehide: don't need layout currently because the only caller 1815 // passes in the properties node 1816 assert(static_cast<SwTextFrame const*>(pTNd->getLayoutFrame(nullptr))->GetTextNodeForParaProps() == pTNd); 1817 getIDocumentContentOperations().InsertItemSet( aPam, *pSet ); 1818 } 1819 } 1820 1821 void SwDoc::SetFormatItemByAutoFormat( const SwPaM& rPam, const SfxItemSet& rSet ) 1822 { 1823 SwTextNode* pTNd = rPam.GetPoint()->nNode.GetNode().GetTextNode(); 1824 assert(pTNd); 1825 1826 RedlineFlags eOld = getIDocumentRedlineAccess().GetRedlineFlags(); 1827 1828 if (mbIsAutoFormatRedline) 1829 { 1830 // create the redline object 1831 SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::Format, rPam ); 1832 if( !pRedl->HasMark() ) 1833 pRedl->SetMark(); 1834 1835 // Only those items that are not set by the Set again in the Node 1836 // are of interest. Thus, we take the difference. 1837 SwRedlineExtraData_Format aExtraData( rSet ); 1838 1839 pRedl->SetExtraData( &aExtraData ); 1840 1841 //TODO: Undo is still missing! 1842 getIDocumentRedlineAccess().AppendRedline( pRedl, true ); 1843 1844 getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld | RedlineFlags::Ignore ); 1845 } 1846 1847 const sal_Int32 nEnd(rPam.End()->nContent.GetIndex()); 1848 std::vector<sal_uInt16> whichIds; 1849 SfxItemIter iter(rSet); 1850 for (SfxPoolItem const* pItem = iter.FirstItem(); 1851 pItem; pItem = iter.NextItem()) 1852 { 1853 whichIds.push_back(pItem->Which()); 1854 whichIds.push_back(pItem->Which()); 1855 } 1856 whichIds.push_back(0); 1857 SfxItemSet currentSet(GetAttrPool(), whichIds.data()); 1858 pTNd->GetParaAttr(currentSet, nEnd, nEnd); 1859 for (size_t i = 0; whichIds[i]; i += 2) 1860 { // yuk - want to explicitly set the pool defaults too :-/ 1861 currentSet.Put(currentSet.Get(whichIds[i])); 1862 } 1863 1864 getIDocumentContentOperations().InsertItemSet( rPam, rSet, SetAttrMode::DONTEXPAND ); 1865 1866 // fdo#62536: DONTEXPAND does not work when there is already an AUTOFMT 1867 // here, so insert the old attributes as an empty hint to stop expand 1868 SwPaM endPam(*pTNd, nEnd); 1869 endPam.SetMark(); 1870 getIDocumentContentOperations().InsertItemSet(endPam, currentSet); 1871 1872 getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld ); 1873 } 1874 1875 void SwDoc::ChgFormat(SwFormat & rFormat, const SfxItemSet & rSet) 1876 { 1877 if (GetIDocumentUndoRedo().DoesUndo()) 1878 { 1879 // copying <rSet> to <aSet> 1880 SfxItemSet aSet(rSet); 1881 // remove from <aSet> all items, which are already set at the format 1882 aSet.Differentiate(rFormat.GetAttrSet()); 1883 // <aSet> contains now all *new* items for the format 1884 1885 // copying current format item set to <aOldSet> 1886 SfxItemSet aOldSet(rFormat.GetAttrSet()); 1887 // insert new items into <aOldSet> 1888 aOldSet.Put(aSet); 1889 // invalidate all new items in <aOldSet> in order to clear these items, 1890 // if the undo action is triggered. 1891 { 1892 SfxItemIter aIter(aSet); 1893 1894 const SfxPoolItem * pItem = aIter.FirstItem(); 1895 while (pItem != nullptr) 1896 { 1897 aOldSet.InvalidateItem(pItem->Which()); 1898 1899 pItem = aIter.NextItem(); 1900 } 1901 } 1902 1903 GetIDocumentUndoRedo().AppendUndo( 1904 std::make_unique<SwUndoFormatAttr>(aOldSet, rFormat, /*bSaveDrawPt*/true)); 1905 } 1906 1907 rFormat.SetFormatAttr(rSet); 1908 } 1909 1910 void SwDoc::RenameFormat(SwFormat & rFormat, const OUString & sNewName, 1911 bool bBroadcast) 1912 { 1913 SfxStyleFamily eFamily = SfxStyleFamily::All; 1914 1915 if (GetIDocumentUndoRedo().DoesUndo()) 1916 { 1917 std::unique_ptr<SwUndo> pUndo; 1918 1919 switch (rFormat.Which()) 1920 { 1921 case RES_CHRFMT: 1922 pUndo.reset(new SwUndoRenameCharFormat(rFormat.GetName(), sNewName, this)); 1923 eFamily = SfxStyleFamily::Char; 1924 break; 1925 case RES_TXTFMTCOLL: 1926 pUndo.reset(new SwUndoRenameFormatColl(rFormat.GetName(), sNewName, this)); 1927 eFamily = SfxStyleFamily::Para; 1928 break; 1929 case RES_FRMFMT: 1930 pUndo.reset(new SwUndoRenameFrameFormat(rFormat.GetName(), sNewName, this)); 1931 eFamily = SfxStyleFamily::Frame; 1932 break; 1933 1934 default: 1935 break; 1936 } 1937 1938 if (pUndo) 1939 { 1940 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo)); 1941 } 1942 } 1943 1944 rFormat.SetName(sNewName); 1945 1946 if (bBroadcast) 1947 BroadcastStyleOperation(sNewName, eFamily, SfxHintId::StyleSheetModified); 1948 } 1949 1950 void SwDoc::dumpAsXml(xmlTextWriterPtr pWriter) const 1951 { 1952 bool bOwns = false; 1953 if (!pWriter) 1954 { 1955 pWriter = xmlNewTextWriterFilename("nodes.xml", 0); 1956 xmlTextWriterSetIndent(pWriter,1); 1957 xmlTextWriterSetIndentString(pWriter, BAD_CAST(" ")); 1958 xmlTextWriterStartDocument(pWriter, nullptr, nullptr, nullptr); 1959 bOwns = true; 1960 } 1961 xmlTextWriterStartElement(pWriter, BAD_CAST("SwDoc")); 1962 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); 1963 1964 m_pNodes->dumpAsXml(pWriter); 1965 maDBData.dumpAsXml(pWriter); 1966 mpMarkManager->dumpAsXml(pWriter); 1967 m_pUndoManager->dumpAsXml(pWriter); 1968 getIDocumentFieldsAccess().GetFieldTypes()->dumpAsXml(pWriter); 1969 mpTextFormatCollTable->dumpAsXml(pWriter); 1970 mpCharFormatTable->dumpAsXml(pWriter); 1971 mpFrameFormatTable->dumpAsXml(pWriter, "frmFormatTable"); 1972 mpSpzFrameFormatTable->dumpAsXml(pWriter, "spzFrameFormatTable"); 1973 mpSectionFormatTable->dumpAsXml(pWriter); 1974 mpNumRuleTable->dumpAsXml(pWriter); 1975 getIDocumentRedlineAccess().GetRedlineTable().dumpAsXml(pWriter); 1976 getIDocumentRedlineAccess().GetExtraRedlineTable().dumpAsXml(pWriter); 1977 if (const SdrModel* pModel = getIDocumentDrawModelAccess().GetDrawModel()) 1978 pModel->dumpAsXml(pWriter); 1979 1980 xmlTextWriterStartElement(pWriter, BAD_CAST("mbModified")); 1981 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(getIDocumentState().IsModified()).getStr())); 1982 xmlTextWriterEndElement(pWriter); 1983 1984 xmlTextWriterEndElement(pWriter); 1985 if (bOwns) 1986 { 1987 xmlTextWriterEndDocument(pWriter); 1988 xmlFreeTextWriter(pWriter); 1989 } 1990 } 1991 1992 void SwDBData::dumpAsXml(xmlTextWriterPtr pWriter) const 1993 { 1994 xmlTextWriterStartElement(pWriter, BAD_CAST("SwDBData")); 1995 1996 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("sDataSource"), BAD_CAST(sDataSource.toUtf8().getStr())); 1997 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("sCommand"), BAD_CAST(sCommand.toUtf8().getStr())); 1998 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nCommandType"), BAD_CAST(OString::number(nCommandType).getStr())); 1999 2000 xmlTextWriterEndElement(pWriter); 2001 } 2002 2003 std::set<Color> SwDoc::GetDocColors() 2004 { 2005 std::set<Color> aDocColors; 2006 SwAttrPool& rPool = GetAttrPool(); 2007 const sal_uInt16 pAttribs[] = {RES_CHRATR_COLOR, RES_CHRATR_HIGHLIGHT, RES_BACKGROUND}; 2008 for (sal_uInt16 nAttrib : pAttribs) 2009 { 2010 for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(nAttrib)) 2011 { 2012 auto pColorItem = static_cast<const SvxColorItem*>(pItem); 2013 Color aColor( pColorItem->GetValue() ); 2014 if (COL_AUTO != aColor) 2015 aDocColors.insert(aColor); 2016 } 2017 } 2018 return aDocColors; 2019 } 2020 2021 // #i69627# 2022 namespace docfunc 2023 { 2024 bool HasOutlineStyleToBeWrittenAsNormalListStyle( SwDoc& rDoc ) 2025 { 2026 // If a parent paragraph style of one of the paragraph styles, which 2027 // are assigned to the list levels of the outline style, has a list style 2028 // set or inherits a list style from its parent style, the outline style 2029 // has to be written as a normal list style to the OpenDocument file 2030 // format or the OpenOffice.org file format. 2031 bool bRet( false ); 2032 2033 const SwTextFormatColls* pTextFormatColls( rDoc.GetTextFormatColls() ); 2034 if ( pTextFormatColls ) 2035 { 2036 for ( auto pTextFormatColl : *pTextFormatColls ) 2037 { 2038 if ( pTextFormatColl->IsDefault() || 2039 ! pTextFormatColl->IsAssignedToListLevelOfOutlineStyle() ) 2040 { 2041 continue; 2042 } 2043 2044 const SwTextFormatColl* pParentTextFormatColl = 2045 dynamic_cast<const SwTextFormatColl*>( pTextFormatColl->DerivedFrom()); 2046 if ( !pParentTextFormatColl ) 2047 continue; 2048 2049 if ( SfxItemState::SET == pParentTextFormatColl->GetItemState( RES_PARATR_NUMRULE ) ) 2050 { 2051 // #i106218# consider that the outline style is set 2052 const SwNumRuleItem& rDirectItem = pParentTextFormatColl->GetNumRule(); 2053 if ( rDirectItem.GetValue() != rDoc.GetOutlineNumRule()->GetName() ) 2054 { 2055 bRet = true; 2056 break; 2057 } 2058 } 2059 } 2060 2061 } 2062 return bRet; 2063 } 2064 } 2065 2066 SwFrameFormats::SwFrameFormats() 2067 : m_PosIndex( m_Array.get<0>() ) 2068 , m_TypeAndNameIndex( m_Array.get<1>() ) 2069 { 2070 } 2071 2072 SwFrameFormats::~SwFrameFormats() 2073 { 2074 DeleteAndDestroyAll(); 2075 } 2076 2077 SwFrameFormats::const_iterator SwFrameFormats::find( const value_type& x ) const 2078 { 2079 ByTypeAndName::iterator it = m_TypeAndNameIndex.find( 2080 boost::make_tuple(x->Which(), x->GetName(), x) ); 2081 return m_Array.project<0>( it ); 2082 } 2083 2084 std::pair<SwFrameFormats::const_range_iterator,SwFrameFormats::const_range_iterator> 2085 SwFrameFormats::rangeFind( sal_uInt16 type, const OUString& name ) const 2086 { 2087 return m_TypeAndNameIndex.equal_range( boost::make_tuple(type, name) ); 2088 } 2089 2090 std::pair<SwFrameFormats::const_range_iterator,SwFrameFormats::const_range_iterator> 2091 SwFrameFormats::rangeFind( const value_type& x ) const 2092 { 2093 return rangeFind( x->Which(), x->GetName() ); 2094 } 2095 2096 void SwFrameFormats::DeleteAndDestroyAll( bool keepDefault ) 2097 { 2098 if ( empty() ) 2099 return; 2100 const int _offset = keepDefault ? 1 : 0; 2101 for( const_iterator it = begin() + _offset; it != end(); ++it ) 2102 delete *it; 2103 if ( _offset ) 2104 m_PosIndex.erase( begin() + _offset, end() ); 2105 else 2106 m_Array.clear(); 2107 } 2108 2109 std::pair<SwFrameFormats::const_iterator,bool> SwFrameFormats::push_back( const value_type& x ) 2110 { 2111 SAL_WARN_IF(x->m_ffList != nullptr, "sw.core", "Inserting already assigned item"); 2112 assert(x->m_ffList == nullptr); 2113 x->m_ffList = this; 2114 return m_PosIndex.push_back( x ); 2115 } 2116 2117 bool SwFrameFormats::erase( const value_type& x ) 2118 { 2119 const_iterator const ret = find( x ); 2120 SAL_WARN_IF(x->m_ffList != this, "sw.core", "Removing invalid / unassigned item"); 2121 if (ret != end()) { 2122 assert( x == *ret ); 2123 m_PosIndex.erase( ret ); 2124 x->m_ffList = nullptr; 2125 return true; 2126 } 2127 return false; 2128 } 2129 2130 void SwFrameFormats::erase( size_type index_ ) 2131 { 2132 erase( begin() + index_ ); 2133 } 2134 2135 void SwFrameFormats::erase( const_iterator const& position ) 2136 { 2137 (*position)->m_ffList = nullptr; 2138 m_PosIndex.erase( begin() + (position - begin()) ); 2139 } 2140 2141 bool SwFrameFormats::ContainsFormat(const SwFrameFormat& x) const 2142 { 2143 return (x.m_ffList == this); 2144 } 2145 2146 bool SwFrameFormats::IsAlive(SwFrameFormat const*const p) const 2147 { 2148 return find(const_cast<SwFrameFormat*>(p)) != end(); 2149 } 2150 2151 bool SwFrameFormats::newDefault( const value_type& x ) 2152 { 2153 std::pair<iterator,bool> res = m_PosIndex.push_front( x ); 2154 if( ! res.second ) 2155 newDefault( res.first ); 2156 return res.second; 2157 } 2158 2159 void SwFrameFormats::newDefault( const_iterator const& position ) 2160 { 2161 if (position == begin()) 2162 return; 2163 m_PosIndex.relocate( begin(), position ); 2164 } 2165 2166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 2167
