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 <svx/svdmodel.hxx> 21 #include <cassert> 22 #include <math.h> 23 #include <sal/log.hxx> 24 #include <rtl/ustrbuf.hxx> 25 #include <com/sun/star/lang/XComponent.hpp> 26 #include <com/sun/star/document/XStorageBasedDocument.hpp> 27 #include <com/sun/star/embed/ElementModes.hpp> 28 #include <unotools/configmgr.hxx> 29 #include <unotools/pathoptions.hxx> 30 #include <svl/whiter.hxx> 31 #include <svl/asiancfg.hxx> 32 #include <svx/xbtmpit.hxx> 33 #include <svx/xlndsit.hxx> 34 #include <svx/xlnedit.hxx> 35 #include <svx/xflgrit.hxx> 36 #include <svx/xflftrit.hxx> 37 #include <svx/xflhtit.hxx> 38 #include <svx/xlnstit.hxx> 39 #include <editeng/editeng.hxx> 40 #include <svx/xtable.hxx> 41 #include <svx/svdtrans.hxx> 42 #include <svx/svdpage.hxx> 43 #include <svx/svdlayer.hxx> 44 #include <svx/svdundo.hxx> 45 #include <svx/svdpool.hxx> 46 #include <svx/svdobj.hxx> 47 #include <svx/svdotext.hxx> 48 #include <textchain.hxx> 49 #include <svx/svdetc.hxx> 50 #include <svx/svdoutl.hxx> 51 #include <svx/dialmgr.hxx> 52 #include <svx/strings.hrc> 53 #include <svdoutlinercache.hxx> 54 #include <svx/sdasitm.hxx> 55 #include <officecfg/Office/Common.hxx> 56 #include <editeng/fontitem.hxx> 57 #include <editeng/colritem.hxx> 58 #include <editeng/fhgtitem.hxx> 59 #include <svl/style.hxx> 60 #include <editeng/forbiddencharacterstable.hxx> 61 #include <comphelper/servicehelper.hxx> 62 #include <comphelper/storagehelper.hxx> 63 #include <unotools/localedatawrapper.hxx> 64 #include <unotools/syslocale.hxx> 65 #include <editeng/eeitem.hxx> 66 #include <svl/itemset.hxx> 67 #include <vcl/settings.hxx> 68 #include <vcl/svapp.hxx> 69 #include <memory> 70 #include <libxml/xmlwriter.h> 71 #include <sfx2/viewsh.hxx> 72 #include <o3tl/enumrange.hxx> 73 #include <tools/diagnose_ex.h> 74 #include <tools/UnitConversion.hxx> 75 76 using namespace ::com::sun::star; 77 using namespace ::com::sun::star::uno; 78 using namespace ::com::sun::star::lang; 79 80 81 struct SdrModelImpl 82 { 83 SfxUndoManager* mpUndoManager; 84 SdrUndoFactory* mpUndoFactory; 85 bool mbAnchoredTextOverflowLegacy; // tdf#99729 compatibility flag 86 87 SdrModelImpl() 88 : mpUndoManager(nullptr) 89 , mpUndoFactory(nullptr) 90 , mbAnchoredTextOverflowLegacy(false) 91 {} 92 }; 93 94 95 SdrModel::SdrModel(SfxItemPool* pPool, comphelper::IEmbeddedHelper* pEmbeddedHelper, bool bDisablePropertyFiles) 96 : m_aObjUnit(SdrEngineDefaults::GetMapFraction()) 97 , m_eObjUnit(SdrEngineDefaults::GetMapUnit()) 98 , m_eUIUnit(FieldUnit::MM) 99 , m_aUIScale(Fraction(1,1)) 100 , m_nUIUnitDecimalMark(0) 101 , m_pLayerAdmin(new SdrLayerAdmin) 102 , m_pItemPool(pPool) 103 , m_pEmbeddedHelper(pEmbeddedHelper) 104 , mnDefTextHgt(SdrEngineDefaults::GetFontHeight()) 105 , m_pRefOutDev(nullptr) 106 , m_pDefaultStyleSheet(nullptr) 107 , mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj(nullptr) 108 , m_pLinkManager(nullptr) 109 , m_nUndoLevel(0) 110 , m_bIsWriter(true) 111 , mbUndoEnabled(true) 112 , mbChanged(false) 113 , m_bPagNumsDirty(false) 114 , m_bMPgNumsDirty(false) 115 , m_bTransportContainer(false) 116 , m_bReadOnly(false) 117 , m_bTransparentTextFrames(false) 118 , m_bSwapGraphics(false) 119 , m_bPasteResize(false) 120 , m_bStarDrawPreviewMode(false) 121 , mbDisableTextEditUsesCommonUndoManager(false) 122 , m_nDefaultTabulator(0) 123 , m_nMaxUndoCount(16) 124 , m_pTextChain(new TextChain) 125 , mpImpl(new SdrModelImpl) 126 , mnCharCompressType(CharCompressType::NONE) 127 , mnHandoutPageCount(0) 128 , mbModelLocked(false) 129 , mbKernAsianPunctuation(false) 130 , mbAddExtLeading(false) 131 , mbInDestruction(false) 132 { 133 if (!utl::ConfigManager::IsFuzzing()) 134 { 135 mnCharCompressType = static_cast<CharCompressType>( 136 officecfg::Office::Common::AsianLayout::CompressCharacterDistance::get()); 137 } 138 139 if (m_pItemPool == nullptr) 140 { 141 m_pItemPool = new SdrItemPool(nullptr); 142 // Outliner doesn't have its own Pool, so use the EditEngine's 143 rtl::Reference<SfxItemPool> pOutlPool=EditEngine::CreatePool(); 144 // OutlinerPool as SecondaryPool of SdrPool 145 m_pItemPool->SetSecondaryPool(pOutlPool.get()); 146 // remember that I created both pools myself 147 m_bIsWriter = false; 148 } 149 m_pItemPool->SetDefaultMetric(m_eObjUnit); 150 151 // using static SdrEngineDefaults only if default SvxFontHeight item is not available 152 const SfxPoolItem* pPoolItem = m_pItemPool->GetPoolDefaultItem( EE_CHAR_FONTHEIGHT ); 153 if (pPoolItem) 154 mnDefTextHgt = static_cast<const SvxFontHeightItem*>(pPoolItem)->GetHeight(); 155 156 m_pItemPool->SetPoolDefaultItem( makeSdrTextWordWrapItem( false ) ); 157 158 SetTextDefaults(); 159 m_pLayerAdmin->SetModel(this); 160 ImpSetUIUnit(); 161 162 // can't create DrawOutliner OnDemand, because I can't get the Pool, 163 // then (only from 302 onwards!) 164 m_pDrawOutliner = SdrMakeOutliner(OutlinerMode::TextObject, *this); 165 ImpSetOutlinerDefaults(m_pDrawOutliner.get(), true); 166 167 m_pHitTestOutliner = SdrMakeOutliner(OutlinerMode::TextObject, *this); 168 ImpSetOutlinerDefaults(m_pHitTestOutliner.get(), true); 169 170 /* Start Text Chaining related code */ 171 // Initialize Chaining Outliner 172 m_pChainingOutliner = SdrMakeOutliner( OutlinerMode::TextObject, *this ); 173 ImpSetOutlinerDefaults(m_pChainingOutliner.get(), true); 174 175 ImpCreateTables(bDisablePropertyFiles || utl::ConfigManager::IsFuzzing()); 176 } 177 178 SdrModel::~SdrModel() 179 { 180 mbInDestruction = true; 181 182 Broadcast(SdrHint(SdrHintKind::ModelCleared)); 183 184 mpOutlinerCache.reset(); 185 186 ClearUndoBuffer(); 187 #ifdef DBG_UTIL 188 SAL_WARN_IF(m_pCurrentUndoGroup, "svx", "In the Dtor of the SdrModel there is an open Undo left: \"" 189 << m_pCurrentUndoGroup->GetComment() << '\"'); 190 #endif 191 m_pCurrentUndoGroup.reset(); 192 193 ClearModel(true); 194 195 #ifdef DBG_UTIL 196 // SdrObjectLifetimeWatchDog: 197 if(!maAllIncarnatedObjects.empty()) 198 { 199 SAL_WARN("svx","SdrModel::~SdrModel: Not all incarnations of SdrObjects deleted, possible memory leak (!)"); 200 // calling SdrObject::Free will change maAllIncarnatedObjects, and potentially remove more 201 // than one - do not copy to another container, to not try to free already removed object. 202 do 203 { 204 SdrObject* pCandidate(const_cast<SdrObject*>(*maAllIncarnatedObjects.begin())); 205 SdrObject::Free(pCandidate); 206 } while (!maAllIncarnatedObjects.empty()); 207 } 208 #endif 209 210 m_pLayerAdmin.reset(); 211 212 m_pTextChain.reset(); 213 // Delete DrawOutliner only after deleting ItemPool, because ItemPool 214 // references Items of the DrawOutliner! 215 m_pChainingOutliner.reset(); 216 m_pHitTestOutliner.reset(); 217 m_pDrawOutliner.reset(); 218 219 // delete StyleSheetPool, derived classes should not do this since 220 // the DrawingEngine may need it in its destructor 221 if( mxStyleSheetPool.is() ) 222 { 223 Reference< XComponent > xComponent( static_cast< cppu::OWeakObject* >( mxStyleSheetPool.get() ), UNO_QUERY ); 224 if( xComponent.is() ) try 225 { 226 xComponent->dispose(); 227 } 228 catch( RuntimeException& ) 229 { 230 } 231 mxStyleSheetPool.clear(); 232 } 233 234 mpForbiddenCharactersTable.reset(); 235 236 delete mpImpl->mpUndoFactory; 237 } 238 239 void SdrModel::SetSwapGraphics() 240 { 241 m_bSwapGraphics = true; 242 } 243 244 bool SdrModel::IsReadOnly() const 245 { 246 return m_bReadOnly; 247 } 248 249 void SdrModel::SetReadOnly(bool bYes) 250 { 251 m_bReadOnly=bYes; 252 } 253 254 255 void SdrModel::SetMaxUndoActionCount(sal_uInt32 nCount) 256 { 257 if (nCount<1) nCount=1; 258 m_nMaxUndoCount=nCount; 259 while (m_aUndoStack.size()>m_nMaxUndoCount) 260 m_aUndoStack.pop_back(); 261 } 262 263 void SdrModel::ClearUndoBuffer() 264 { 265 m_aUndoStack.clear(); 266 m_aRedoStack.clear(); 267 } 268 269 bool SdrModel::HasUndoActions() const 270 { 271 return !m_aUndoStack.empty(); 272 } 273 274 bool SdrModel::HasRedoActions() const 275 { 276 return !m_aRedoStack.empty(); 277 } 278 279 void SdrModel::Undo() 280 { 281 if( mpImpl->mpUndoManager ) 282 { 283 OSL_FAIL("svx::SdrModel::Undo(), method not supported with application undo manager!"); 284 } 285 else 286 { 287 if(HasUndoActions()) 288 { 289 SfxUndoAction* pDo = m_aUndoStack.front().get(); 290 const bool bWasUndoEnabled = mbUndoEnabled; 291 mbUndoEnabled = false; 292 pDo->Undo(); 293 std::unique_ptr<SfxUndoAction> p = std::move(m_aUndoStack.front()); 294 m_aUndoStack.pop_front(); 295 m_aRedoStack.emplace_front(std::move(p)); 296 mbUndoEnabled = bWasUndoEnabled; 297 } 298 } 299 } 300 301 void SdrModel::Redo() 302 { 303 if( mpImpl->mpUndoManager ) 304 { 305 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!"); 306 } 307 else 308 { 309 if(HasRedoActions()) 310 { 311 SfxUndoAction* pDo = m_aRedoStack.front().get(); 312 const bool bWasUndoEnabled = mbUndoEnabled; 313 mbUndoEnabled = false; 314 pDo->Redo(); 315 std::unique_ptr<SfxUndoAction> p = std::move(m_aRedoStack.front()); 316 m_aRedoStack.pop_front(); 317 m_aUndoStack.emplace_front(std::move(p)); 318 mbUndoEnabled = bWasUndoEnabled; 319 } 320 } 321 } 322 323 void SdrModel::Repeat(SfxRepeatTarget& rView) 324 { 325 if( mpImpl->mpUndoManager ) 326 { 327 OSL_FAIL("svx::SdrModel::Redo(), method not supported with application undo manager!"); 328 } 329 else 330 { 331 if(HasUndoActions()) 332 { 333 SfxUndoAction* pDo = m_aUndoStack.front().get(); 334 if(pDo->CanRepeat(rView)) 335 { 336 pDo->Repeat(rView); 337 } 338 } 339 } 340 } 341 342 void SdrModel::ImpPostUndoAction(std::unique_ptr<SdrUndoAction> pUndo) 343 { 344 DBG_ASSERT( mpImpl->mpUndoManager == nullptr, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" ); 345 if( !IsUndoEnabled() ) 346 return; 347 348 if (m_aUndoLink) 349 { 350 m_aUndoLink(std::move(pUndo)); 351 } 352 else 353 { 354 m_aUndoStack.emplace_front(std::move(pUndo)); 355 while (m_aUndoStack.size()>m_nMaxUndoCount) 356 { 357 m_aUndoStack.pop_back(); 358 } 359 m_aRedoStack.clear(); 360 } 361 } 362 363 void SdrModel::BegUndo() 364 { 365 if( mpImpl->mpUndoManager ) 366 { 367 ViewShellId nViewShellId(-1); 368 if (SfxViewShell* pViewShell = SfxViewShell::Current()) 369 nViewShellId = pViewShell->GetViewShellId(); 370 mpImpl->mpUndoManager->EnterListAction("","",0,nViewShellId); 371 m_nUndoLevel++; 372 } 373 else if( IsUndoEnabled() ) 374 { 375 if(!m_pCurrentUndoGroup) 376 { 377 m_pCurrentUndoGroup.reset(new SdrUndoGroup(*this)); 378 m_nUndoLevel=1; 379 } 380 else 381 { 382 m_nUndoLevel++; 383 } 384 } 385 } 386 387 void SdrModel::BegUndo(const OUString& rComment) 388 { 389 if( mpImpl->mpUndoManager ) 390 { 391 ViewShellId nViewShellId(-1); 392 if (SfxViewShell* pViewShell = SfxViewShell::Current()) 393 nViewShellId = pViewShell->GetViewShellId(); 394 mpImpl->mpUndoManager->EnterListAction( rComment, "", 0, nViewShellId ); 395 m_nUndoLevel++; 396 } 397 else if( IsUndoEnabled() ) 398 { 399 BegUndo(); 400 if (m_nUndoLevel==1) 401 { 402 m_pCurrentUndoGroup->SetComment(rComment); 403 } 404 } 405 } 406 407 void SdrModel::BegUndo(const OUString& rComment, const OUString& rObjDescr, SdrRepeatFunc eFunc) 408 { 409 if( mpImpl->mpUndoManager ) 410 { 411 OUString aComment(rComment); 412 if( !aComment.isEmpty() && !rObjDescr.isEmpty() ) 413 { 414 aComment = aComment.replaceFirst("%1", rObjDescr); 415 } 416 ViewShellId nViewShellId(-1); 417 if (SfxViewShell* pViewShell = SfxViewShell::Current()) 418 nViewShellId = pViewShell->GetViewShellId(); 419 mpImpl->mpUndoManager->EnterListAction( aComment,"",0,nViewShellId ); 420 m_nUndoLevel++; 421 } 422 else if( IsUndoEnabled() ) 423 { 424 BegUndo(); 425 if (m_nUndoLevel==1) 426 { 427 m_pCurrentUndoGroup->SetComment(rComment); 428 m_pCurrentUndoGroup->SetObjDescription(rObjDescr); 429 m_pCurrentUndoGroup->SetRepeatFunction(eFunc); 430 } 431 } 432 } 433 434 void SdrModel::EndUndo() 435 { 436 DBG_ASSERT(m_nUndoLevel!=0,"SdrModel::EndUndo(): UndoLevel is already 0!"); 437 if( mpImpl->mpUndoManager ) 438 { 439 if( m_nUndoLevel ) 440 { 441 m_nUndoLevel--; 442 mpImpl->mpUndoManager->LeaveListAction(); 443 } 444 } 445 else 446 { 447 if(m_pCurrentUndoGroup!=nullptr && IsUndoEnabled()) 448 { 449 m_nUndoLevel--; 450 if(m_nUndoLevel==0) 451 { 452 if(m_pCurrentUndoGroup->GetActionCount()!=0) 453 { 454 ImpPostUndoAction(std::move(m_pCurrentUndoGroup)); 455 } 456 else 457 { 458 // was empty 459 m_pCurrentUndoGroup.reset(); 460 } 461 } 462 } 463 } 464 } 465 466 void SdrModel::SetUndoComment(const OUString& rComment) 467 { 468 DBG_ASSERT(m_nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!"); 469 470 if( mpImpl->mpUndoManager ) 471 { 472 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" ); 473 } 474 else if( IsUndoEnabled() && m_nUndoLevel==1) 475 { 476 m_pCurrentUndoGroup->SetComment(rComment); 477 } 478 } 479 480 void SdrModel::SetUndoComment(const OUString& rComment, const OUString& rObjDescr) 481 { 482 DBG_ASSERT(m_nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is already 0!"); 483 if( mpImpl->mpUndoManager ) 484 { 485 OSL_FAIL("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" ); 486 } 487 else 488 { 489 if (m_nUndoLevel==1) 490 { 491 m_pCurrentUndoGroup->SetComment(rComment); 492 m_pCurrentUndoGroup->SetObjDescription(rObjDescr); 493 } 494 } 495 } 496 497 void SdrModel::AddUndo(std::unique_ptr<SdrUndoAction> pUndo) 498 { 499 if( mpImpl->mpUndoManager ) 500 { 501 mpImpl->mpUndoManager->AddUndoAction( std::move(pUndo) ); 502 } 503 else if( IsUndoEnabled() ) 504 { 505 if (m_pCurrentUndoGroup) 506 { 507 m_pCurrentUndoGroup->AddAction(std::move(pUndo)); 508 } 509 else 510 { 511 ImpPostUndoAction(std::move(pUndo)); 512 } 513 } 514 } 515 516 void SdrModel::EnableUndo( bool bEnable ) 517 { 518 if( mpImpl->mpUndoManager ) 519 { 520 mpImpl->mpUndoManager->EnableUndo( bEnable ); 521 } 522 else 523 { 524 mbUndoEnabled = bEnable; 525 } 526 } 527 528 bool SdrModel::IsUndoEnabled() const 529 { 530 if( mpImpl->mpUndoManager ) 531 { 532 return mpImpl->mpUndoManager->IsUndoEnabled(); 533 } 534 else 535 { 536 return mbUndoEnabled; 537 } 538 } 539 540 void SdrModel::ImpCreateTables(bool bDisablePropertyFiles) 541 { 542 // use standard path for initial construction 543 const OUString aTablePath(!bDisablePropertyFiles ? SvtPathOptions().GetPalettePath() : ""); 544 545 for( auto i : o3tl::enumrange<XPropertyListType>() ) 546 { 547 maProperties[i] = XPropertyList::CreatePropertyList(i, aTablePath, ""/*TODO?*/ ); 548 } 549 } 550 551 void SdrModel::ClearModel(bool bCalledFromDestructor) 552 { 553 if(bCalledFromDestructor) 554 { 555 mbInDestruction = true; 556 } 557 558 sal_Int32 i; 559 // delete all drawing pages 560 sal_Int32 nCount=GetPageCount(); 561 for (i=nCount-1; i>=0; i--) 562 { 563 DeletePage( static_cast<sal_uInt16>(i) ); 564 } 565 maPages.clear(); 566 PageListChanged(); 567 568 // delete all Masterpages 569 nCount=GetMasterPageCount(); 570 for(i=nCount-1; i>=0; i--) 571 { 572 DeleteMasterPage( static_cast<sal_uInt16>(i) ); 573 } 574 maMasterPages.clear(); 575 MasterPageListChanged(); 576 577 m_pLayerAdmin->ClearLayers(); 578 } 579 580 SdrModel* SdrModel::AllocModel() const 581 { 582 SdrModel* pModel=new SdrModel(); 583 pModel->SetScaleUnit(m_eObjUnit,m_aObjUnit); 584 return pModel; 585 } 586 587 rtl::Reference<SdrPage> SdrModel::AllocPage(bool bMasterPage) 588 { 589 return new SdrPage(*this,bMasterPage); 590 } 591 592 void SdrModel::SetTextDefaults() const 593 { 594 SetTextDefaults( m_pItemPool.get(), mnDefTextHgt ); 595 } 596 597 void SdrModel::SetTextDefaults( SfxItemPool* pItemPool, sal_Int32 nDefTextHgt ) 598 { 599 // set application-language specific dynamic pool language defaults 600 SvxFontItem aSvxFontItem( EE_CHAR_FONTINFO) ; 601 SvxFontItem aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK); 602 SvxFontItem aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL); 603 LanguageType nLanguage; 604 if (!utl::ConfigManager::IsFuzzing()) 605 nLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); 606 else 607 nLanguage = LANGUAGE_ENGLISH_US; 608 609 // get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default 610 vcl::Font aFont(OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne)); 611 aSvxFontItem.SetFamily(aFont.GetFamilyType()); 612 aSvxFontItem.SetFamilyName(aFont.GetFamilyName()); 613 aSvxFontItem.SetStyleName(OUString()); 614 aSvxFontItem.SetPitch( aFont.GetPitch()); 615 aSvxFontItem.SetCharSet( aFont.GetCharSet() ); 616 pItemPool->SetPoolDefaultItem(aSvxFontItem); 617 618 // get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default 619 vcl::Font aFontCJK(OutputDevice::GetDefaultFont(DefaultFontType::CJK_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne)); 620 aSvxFontItemCJK.SetFamily( aFontCJK.GetFamilyType()); 621 aSvxFontItemCJK.SetFamilyName(aFontCJK.GetFamilyName()); 622 aSvxFontItemCJK.SetStyleName(OUString()); 623 aSvxFontItemCJK.SetPitch( aFontCJK.GetPitch()); 624 aSvxFontItemCJK.SetCharSet( aFontCJK.GetCharSet()); 625 pItemPool->SetPoolDefaultItem(aSvxFontItemCJK); 626 627 // get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default 628 vcl::Font aFontCTL(OutputDevice::GetDefaultFont(DefaultFontType::CTL_TEXT, nLanguage, GetDefaultFontFlags::OnlyOne)); 629 aSvxFontItemCTL.SetFamily(aFontCTL.GetFamilyType()); 630 aSvxFontItemCTL.SetFamilyName(aFontCTL.GetFamilyName()); 631 aSvxFontItemCTL.SetStyleName(OUString()); 632 aSvxFontItemCTL.SetPitch( aFontCTL.GetPitch() ); 633 aSvxFontItemCTL.SetCharSet( aFontCTL.GetCharSet()); 634 pItemPool->SetPoolDefaultItem(aSvxFontItemCTL); 635 636 // set dynamic FontHeight defaults 637 pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT ) ); 638 pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CJK ) ); 639 pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CTL ) ); 640 641 // set FontColor defaults 642 pItemPool->SetPoolDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR) ); 643 } 644 645 SdrOutliner& SdrModel::GetDrawOutliner(const SdrTextObj* pObj) const 646 { 647 m_pDrawOutliner->SetTextObj(pObj); 648 return *m_pDrawOutliner; 649 } 650 651 SdrOutliner& SdrModel::GetChainingOutliner(const SdrTextObj* pObj) const 652 { 653 m_pChainingOutliner->SetTextObj(pObj); 654 return *m_pChainingOutliner; 655 } 656 657 const SdrTextObj* SdrModel::GetFormattingTextObj() const 658 { 659 if (m_pDrawOutliner!=nullptr) { 660 return m_pDrawOutliner->GetTextObj(); 661 } 662 return nullptr; 663 } 664 665 void SdrModel::ImpSetOutlinerDefaults( SdrOutliner* pOutliner, bool bInit ) 666 { 667 // Initialization of the Outliners for drawing text and HitTest 668 if( bInit ) 669 { 670 pOutliner->EraseVirtualDevice(); 671 pOutliner->SetUpdateMode(false); 672 pOutliner->SetEditTextObjectPool(m_pItemPool.get()); 673 pOutliner->SetDefTab(m_nDefaultTabulator); 674 } 675 676 pOutliner->SetRefDevice(GetRefDevice()); 677 Outliner::SetForbiddenCharsTable(GetForbiddenCharsTable()); 678 pOutliner->SetAsianCompressionMode( mnCharCompressType ); 679 pOutliner->SetKernAsianPunctuation( IsKernAsianPunctuation() ); 680 pOutliner->SetAddExtLeading( IsAddExtLeading() ); 681 682 if ( !GetRefDevice() ) 683 { 684 MapMode aMapMode(m_eObjUnit, Point(0,0), m_aObjUnit, m_aObjUnit); 685 pOutliner->SetRefMapMode(aMapMode); 686 } 687 } 688 689 void SdrModel::SetRefDevice(OutputDevice* pDev) 690 { 691 m_pRefOutDev=pDev; 692 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 693 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 694 RefDeviceChanged(); 695 } 696 697 void SdrModel::ImpReformatAllTextObjects() 698 { 699 if( isLocked() ) 700 return; 701 702 sal_uInt16 nCount=GetMasterPageCount(); 703 sal_uInt16 nNum; 704 for (nNum=0; nNum<nCount; nNum++) { 705 GetMasterPage(nNum)->ReformatAllTextObjects(); 706 } 707 nCount=GetPageCount(); 708 for (nNum=0; nNum<nCount; nNum++) { 709 GetPage(nNum)->ReformatAllTextObjects(); 710 } 711 } 712 713 /* steps over all available pages and sends notify messages to 714 all edge objects that are connected to other objects so that 715 they may reposition themselves 716 */ 717 void SdrModel::ImpReformatAllEdgeObjects() 718 { 719 if( isLocked() ) 720 return; 721 722 sal_uInt16 nCount=GetMasterPageCount(); 723 sal_uInt16 nNum; 724 for (nNum=0; nNum<nCount; nNum++) 725 { 726 GetMasterPage(nNum)->ReformatAllEdgeObjects(); 727 } 728 nCount=GetPageCount(); 729 for (nNum=0; nNum<nCount; nNum++) 730 { 731 GetPage(nNum)->ReformatAllEdgeObjects(); 732 } 733 } 734 735 uno::Reference<embed::XStorage> SdrModel::GetDocumentStorage() const 736 { 737 uno::Reference<document::XStorageBasedDocument> const xSBD( 738 const_cast<SdrModel*>(this)->getUnoModel(), uno::UNO_QUERY); 739 if (!xSBD.is()) 740 { 741 SAL_WARN("svx", "no UNO model"); 742 return nullptr; 743 } 744 return xSBD->getDocumentStorage(); 745 } 746 747 uno::Reference<io::XInputStream> 748 SdrModel::GetDocumentStream( OUString const& rURL, 749 ::comphelper::LifecycleProxy const & rProxy) const 750 { 751 uno::Reference<embed::XStorage> const xStorage(GetDocumentStorage()); 752 if (!xStorage.is()) 753 { 754 SAL_WARN("svx", "no storage?"); 755 return nullptr; 756 } 757 try { 758 uno::Reference<io::XStream> const xStream( 759 ::comphelper::OStorageHelper::GetStreamAtPackageURL( 760 xStorage, rURL, embed::ElementModes::READ, rProxy)); 761 return (xStream.is()) ? xStream->getInputStream() : nullptr; 762 } 763 catch (container::NoSuchElementException const&) 764 { 765 SAL_INFO("svx", "not found"); 766 } 767 catch (uno::Exception const&) 768 { 769 TOOLS_WARN_EXCEPTION("svx", ""); 770 } 771 return nullptr; 772 } 773 774 // convert template attributes from the string into "hard" attributes 775 void SdrModel::BurnInStyleSheetAttributes() 776 { 777 sal_uInt16 nCount=GetMasterPageCount(); 778 sal_uInt16 nNum; 779 for (nNum=0; nNum<nCount; nNum++) { 780 GetMasterPage(nNum)->BurnInStyleSheetAttributes(); 781 } 782 nCount=GetPageCount(); 783 for (nNum=0; nNum<nCount; nNum++) { 784 GetPage(nNum)->BurnInStyleSheetAttributes(); 785 } 786 } 787 788 void SdrModel::RefDeviceChanged() 789 { 790 Broadcast(SdrHint(SdrHintKind::RefDeviceChange)); 791 ImpReformatAllTextObjects(); 792 } 793 794 void SdrModel::SetDefaultFontHeight(sal_Int32 nVal) 795 { 796 if (nVal!=mnDefTextHgt) { 797 mnDefTextHgt=nVal; 798 ImpReformatAllTextObjects(); 799 } 800 } 801 802 void SdrModel::SetDefaultTabulator(sal_uInt16 nVal) 803 { 804 if (m_nDefaultTabulator!=nVal) { 805 m_nDefaultTabulator=nVal; 806 Outliner& rOutliner=GetDrawOutliner(); 807 rOutliner.SetDefTab(nVal); 808 Broadcast(SdrHint(SdrHintKind::DefaultTabChange)); 809 ImpReformatAllTextObjects(); 810 } 811 } 812 813 void SdrModel::ImpSetUIUnit() 814 { 815 if(0 == m_aUIScale.GetNumerator() || 0 == m_aUIScale.GetDenominator()) 816 { 817 m_aUIScale = Fraction(1,1); 818 } 819 820 m_nUIUnitDecimalMark = 0; 821 822 o3tl::Length eFrom = MapToO3tlLength(m_eObjUnit, o3tl::Length::invalid); 823 o3tl::Length eTo; 824 825 switch (m_eUIUnit) 826 { 827 case FieldUnit::CHAR: 828 case FieldUnit::LINE: 829 eTo = o3tl::Length::invalid; 830 break; 831 case FieldUnit::PERCENT: 832 m_nUIUnitDecimalMark += 2; 833 [[fallthrough]]; 834 default: 835 eTo = FieldToO3tlLength(m_eUIUnit, o3tl::Length::invalid); 836 } // switch 837 838 sal_Int32 nMul = 1, nDiv = 1; 839 if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) 840 { 841 const auto& [mul, div] = o3tl::getConversionMulDiv(eFrom, eTo); 842 nMul = mul; 843 nDiv = div; 844 } 845 // #i89872# take Unit of Measurement into account 846 if(1 != m_aUIScale.GetDenominator() || 1 != m_aUIScale.GetNumerator()) 847 { 848 // divide by UIScale 849 nMul *= m_aUIScale.GetDenominator(); 850 nDiv *= m_aUIScale.GetNumerator(); 851 } 852 853 // shorten trailing zeros for dividend 854 while(0 == (nMul % 10)) 855 { 856 m_nUIUnitDecimalMark--; 857 nMul /= 10; 858 } 859 860 // shorten trailing zeros for divisor 861 while(0 == (nDiv % 10)) 862 { 863 m_nUIUnitDecimalMark++; 864 nDiv /= 10; 865 } 866 867 // end preparations, set member values 868 m_aUIUnitFact = Fraction(sal_Int32(nMul), sal_Int32(nDiv)); 869 m_aUIUnitStr = GetUnitString(m_eUIUnit); 870 } 871 872 void SdrModel::SetScaleUnit(MapUnit eMap, const Fraction& rFrac) 873 { 874 if (m_eObjUnit!=eMap || m_aObjUnit!=rFrac) { 875 m_eObjUnit=eMap; 876 m_aObjUnit=rFrac; 877 m_pItemPool->SetDefaultMetric(m_eObjUnit); 878 ImpSetUIUnit(); 879 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 880 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 881 ImpReformatAllTextObjects(); 882 } 883 } 884 885 void SdrModel::SetScaleUnit(MapUnit eMap) 886 { 887 if (m_eObjUnit!=eMap) { 888 m_eObjUnit=eMap; 889 m_pItemPool->SetDefaultMetric(m_eObjUnit); 890 ImpSetUIUnit(); 891 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 892 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 893 ImpReformatAllTextObjects(); 894 } 895 } 896 897 void SdrModel::SetScaleFraction(const Fraction& rFrac) 898 { 899 if (m_aObjUnit!=rFrac) { 900 m_aObjUnit=rFrac; 901 ImpSetUIUnit(); 902 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 903 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 904 ImpReformatAllTextObjects(); 905 } 906 } 907 908 void SdrModel::SetUIUnit(FieldUnit eUnit) 909 { 910 if (m_eUIUnit!=eUnit) { 911 m_eUIUnit=eUnit; 912 ImpSetUIUnit(); 913 ImpReformatAllTextObjects(); 914 } 915 } 916 917 void SdrModel::SetUIScale(const Fraction& rScale) 918 { 919 if (m_aUIScale!=rScale) { 920 m_aUIScale=rScale; 921 ImpSetUIUnit(); 922 ImpReformatAllTextObjects(); 923 } 924 } 925 926 void SdrModel::SetUIUnit(FieldUnit eUnit, const Fraction& rScale) 927 { 928 if (m_eUIUnit!=eUnit || m_aUIScale!=rScale) { 929 m_eUIUnit=eUnit; 930 m_aUIScale=rScale; 931 ImpSetUIUnit(); 932 ImpReformatAllTextObjects(); 933 } 934 } 935 936 OUString SdrModel::GetUnitString(FieldUnit eUnit) 937 { 938 switch(eUnit) 939 { 940 default: 941 case FieldUnit::NONE : 942 case FieldUnit::CUSTOM : 943 return OUString(); 944 case FieldUnit::MM_100TH: 945 return OUString{"/100mm"}; 946 case FieldUnit::MM : 947 return OUString{"mm"}; 948 case FieldUnit::CM : 949 return OUString{"cm"}; 950 case FieldUnit::M : 951 return OUString{"m"}; 952 case FieldUnit::KM : 953 return OUString{"km"}; 954 case FieldUnit::TWIP : 955 return OUString{"twip"}; 956 case FieldUnit::POINT : 957 return OUString{"pt"}; 958 case FieldUnit::PICA : 959 return OUString{"pica"}; 960 case FieldUnit::INCH : 961 return OUString{"\""}; 962 case FieldUnit::FOOT : 963 return OUString{"ft"}; 964 case FieldUnit::MILE : 965 return OUString{"mile(s)"}; 966 case FieldUnit::PERCENT: 967 return OUString{"%"}; 968 } 969 } 970 971 OUString SdrModel::GetMetricString(tools::Long nVal, bool bNoUnitChars, sal_Int32 nNumDigits) const 972 { 973 // #i22167# 974 // change to double precision usage to not lose decimal places 975 const bool bNegative(nVal < 0); 976 SvtSysLocale aSysLoc; 977 const LocaleDataWrapper& rLoc(aSysLoc.GetLocaleData()); 978 double fLocalValue(double(nVal) * double(m_aUIUnitFact)); 979 980 if(bNegative) 981 { 982 fLocalValue = -fLocalValue; 983 } 984 985 if( -1 == nNumDigits ) 986 { 987 nNumDigits = LocaleDataWrapper::getNumDigits(); 988 } 989 990 sal_Int32 nDecimalMark(m_nUIUnitDecimalMark); 991 992 if(nDecimalMark > nNumDigits) 993 { 994 const sal_Int32 nDiff(nDecimalMark - nNumDigits); 995 const double fFactor(pow(10.0, static_cast<int>(nDiff))); 996 997 fLocalValue /= fFactor; 998 nDecimalMark = nNumDigits; 999 } 1000 else if(nDecimalMark < nNumDigits) 1001 { 1002 const sal_Int32 nDiff(nNumDigits - nDecimalMark); 1003 const double fFactor(pow(10.0, static_cast<int>(nDiff))); 1004 1005 fLocalValue *= fFactor; 1006 nDecimalMark = nNumDigits; 1007 } 1008 1009 OUStringBuffer aBuf; 1010 aBuf.append(static_cast<sal_Int32>(fLocalValue + 0.5)); 1011 1012 if(nDecimalMark < 0) 1013 { 1014 // negative nDecimalMark (decimal point) means: add zeros 1015 sal_Int32 nCount(-nDecimalMark); 1016 1017 for(sal_Int32 i=0; i<nCount; i++) 1018 aBuf.append('0'); 1019 1020 nDecimalMark = 0; 1021 } 1022 1023 // the second condition needs to be <= since inside this loop 1024 // also the leading zero is inserted. 1025 if (nDecimalMark > 0 && aBuf.getLength() <= nDecimalMark) 1026 { 1027 // if necessary, add zeros before the decimal point 1028 sal_Int32 nCount = nDecimalMark - aBuf.getLength(); 1029 1030 if(nCount >= 0 && LocaleDataWrapper::isNumLeadingZero()) 1031 nCount++; 1032 1033 for(sal_Int32 i=0; i<nCount; i++) 1034 aBuf.insert(0, '0'); 1035 } 1036 1037 const sal_Unicode cDec( rLoc.getNumDecimalSep()[0] ); 1038 1039 // insert the decimal mark character 1040 sal_Int32 nBeforeDecimalMark = aBuf.getLength() - nDecimalMark; 1041 1042 if(nDecimalMark > 0) 1043 aBuf.insert(nBeforeDecimalMark, cDec); 1044 1045 if(!LocaleDataWrapper::isNumTrailingZeros()) 1046 { 1047 sal_Int32 aPos=aBuf.getLength()-1; 1048 1049 // Remove all trailing zeros. 1050 while (aPos>=0 && aBuf[aPos]=='0') 1051 --aPos; 1052 1053 // Remove decimal if it's the last character. 1054 if (aPos>=0 && aBuf[aPos]==cDec) 1055 --aPos; 1056 1057 // Adjust aPos to index first char to be truncated, if any 1058 if (++aPos<aBuf.getLength()) 1059 aBuf.truncate(aPos); 1060 } 1061 1062 // if necessary, add separators before every third digit 1063 if( nBeforeDecimalMark > 3 ) 1064 { 1065 const OUString& aThoSep( rLoc.getNumThousandSep() ); 1066 if ( !aThoSep.isEmpty() ) 1067 { 1068 sal_Unicode cTho( aThoSep[0] ); 1069 sal_Int32 i(nBeforeDecimalMark - 3); 1070 1071 while(i > 0) 1072 { 1073 aBuf.insert(i, cTho); 1074 i -= 3; 1075 } 1076 } 1077 } 1078 1079 if (aBuf.isEmpty()) 1080 aBuf.append("0"); 1081 1082 if(bNegative) 1083 { 1084 aBuf.insert(0, "-"); 1085 } 1086 1087 if(!bNoUnitChars) 1088 aBuf.append(m_aUIUnitStr); 1089 1090 return aBuf.makeStringAndClear(); 1091 } 1092 1093 OUString SdrModel::GetAngleString(Degree100 nAngle) 1094 { 1095 bool bNeg = nAngle < 0_deg100; 1096 1097 if(bNeg) 1098 nAngle = -nAngle; 1099 1100 OUStringBuffer aBuf; 1101 aBuf.append(static_cast<sal_Int32>(nAngle)); 1102 1103 SvtSysLocale aSysLoc; 1104 const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData(); 1105 sal_Int32 nCount = 2; 1106 1107 if(LocaleDataWrapper::isNumLeadingZero()) 1108 nCount++; 1109 1110 while(aBuf.getLength() < nCount) 1111 aBuf.insert(0, '0'); 1112 1113 aBuf.insert(aBuf.getLength()-2, rLoc.getNumDecimalSep()[0]); 1114 1115 if(bNeg) 1116 aBuf.insert(0, '-'); 1117 1118 aBuf.append(DEGREE_CHAR); 1119 1120 return aBuf.makeStringAndClear(); 1121 } 1122 1123 OUString SdrModel::GetPercentString(const Fraction& rVal) 1124 { 1125 sal_Int32 nMul(rVal.GetNumerator()); 1126 sal_Int32 nDiv(rVal.GetDenominator()); 1127 bool bNeg {false}; 1128 1129 if (nDiv < 0) 1130 { 1131 bNeg = !bNeg; 1132 nDiv = -nDiv; 1133 } 1134 1135 if (nMul < 0) 1136 { 1137 bNeg = !bNeg; 1138 nMul = -nMul; 1139 } 1140 1141 sal_Int32 nPct = ((nMul*100) + nDiv/2)/nDiv; 1142 1143 if (bNeg) 1144 nPct = -nPct; 1145 1146 return OUString::number(nPct) + "%"; 1147 } 1148 1149 void SdrModel::SetChanged(bool bFlg) 1150 { 1151 mbChanged = bFlg; 1152 } 1153 1154 void SdrModel::RecalcPageNums(bool bMaster) 1155 { 1156 if(bMaster) 1157 { 1158 sal_uInt16 nCount=sal_uInt16(maMasterPages.size()); 1159 sal_uInt16 i; 1160 for (i=0; i<nCount; i++) { 1161 SdrPage* pPg = maMasterPages[i].get(); 1162 pPg->SetPageNum(i); 1163 } 1164 m_bMPgNumsDirty=false; 1165 } 1166 else 1167 { 1168 sal_uInt16 nCount=sal_uInt16(maPages.size()); 1169 sal_uInt16 i; 1170 for (i=0; i<nCount; i++) { 1171 SdrPage* pPg = maPages[i].get(); 1172 pPg->SetPageNum(i); 1173 } 1174 m_bPagNumsDirty=false; 1175 } 1176 } 1177 1178 void SdrModel::InsertPage(SdrPage* pPage, sal_uInt16 nPos) 1179 { 1180 sal_uInt16 nCount = GetPageCount(); 1181 if (nPos > nCount) 1182 nPos = nCount; 1183 1184 maPages.insert(maPages.begin() + nPos, pPage); 1185 PageListChanged(); 1186 pPage->SetInserted(); 1187 pPage->SetPageNum(nPos); 1188 1189 if (mbMakePageObjectsNamesUnique) 1190 pPage->MakePageObjectsNamesUnique(); 1191 1192 if (nPos<nCount) m_bPagNumsDirty=true; 1193 SetChanged(); 1194 SdrHint aHint(SdrHintKind::PageOrderChange, pPage); 1195 Broadcast(aHint); 1196 } 1197 1198 void SdrModel::DeletePage(sal_uInt16 nPgNum) 1199 { 1200 RemovePage(nPgNum); 1201 } 1202 1203 rtl::Reference<SdrPage> SdrModel::RemovePage(sal_uInt16 nPgNum) 1204 { 1205 rtl::Reference<SdrPage> pPg = maPages[nPgNum]; 1206 maPages.erase(maPages.begin()+nPgNum); 1207 PageListChanged(); 1208 if (pPg) { 1209 pPg->SetInserted(false); 1210 } 1211 m_bPagNumsDirty=true; 1212 SetChanged(); 1213 SdrHint aHint(SdrHintKind::PageOrderChange, pPg.get()); 1214 Broadcast(aHint); 1215 return pPg; 1216 } 1217 1218 void SdrModel::MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos) 1219 { 1220 rtl::Reference<SdrPage> pPg = std::move(maPages[nPgNum]); 1221 if (pPg) { 1222 maPages.erase(maPages.begin()+nPgNum); // shortcut to avoid two broadcasts 1223 PageListChanged(); 1224 pPg->SetInserted(false); 1225 InsertPage(pPg.get(), nNewPos); 1226 } 1227 else 1228 RemovePage(nPgNum); 1229 } 1230 1231 void SdrModel::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos) 1232 { 1233 sal_uInt16 nCount=GetMasterPageCount(); 1234 if (nPos>nCount) nPos=nCount; 1235 maMasterPages.insert(maMasterPages.begin()+nPos,pPage); 1236 MasterPageListChanged(); 1237 pPage->SetInserted(); 1238 pPage->SetPageNum(nPos); 1239 1240 if (nPos<nCount) { 1241 m_bMPgNumsDirty=true; 1242 } 1243 1244 SetChanged(); 1245 SdrHint aHint(SdrHintKind::PageOrderChange, pPage); 1246 Broadcast(aHint); 1247 } 1248 1249 void SdrModel::DeleteMasterPage(sal_uInt16 nPgNum) 1250 { 1251 RemoveMasterPage(nPgNum); 1252 } 1253 1254 rtl::Reference<SdrPage> SdrModel::RemoveMasterPage(sal_uInt16 nPgNum) 1255 { 1256 rtl::Reference<SdrPage> pRetPg = std::move(maMasterPages[nPgNum]); 1257 maMasterPages.erase(maMasterPages.begin()+nPgNum); 1258 MasterPageListChanged(); 1259 1260 if(pRetPg) 1261 { 1262 // Now delete the links from the normal drawing pages to the deleted master page. 1263 sal_uInt16 nPageCnt(GetPageCount()); 1264 1265 for(sal_uInt16 np(0); np < nPageCnt; np++) 1266 { 1267 GetPage(np)->TRG_ImpMasterPageRemoved(*pRetPg); 1268 } 1269 1270 pRetPg->SetInserted(false); 1271 } 1272 1273 m_bMPgNumsDirty=true; 1274 SetChanged(); 1275 SdrHint aHint(SdrHintKind::PageOrderChange, pRetPg.get()); 1276 Broadcast(aHint); 1277 return pRetPg; 1278 } 1279 1280 void SdrModel::MoveMasterPage(sal_uInt16 nPgNum, sal_uInt16 nNewPos) 1281 { 1282 rtl::Reference<SdrPage> pPg = std::move(maMasterPages[nPgNum]); 1283 maMasterPages.erase(maMasterPages.begin()+nPgNum); 1284 MasterPageListChanged(); 1285 if (pPg) { 1286 pPg->SetInserted(false); 1287 maMasterPages.insert(maMasterPages.begin()+nNewPos,pPg); 1288 MasterPageListChanged(); 1289 } 1290 m_bMPgNumsDirty=true; 1291 SetChanged(); 1292 SdrHint aHint(SdrHintKind::PageOrderChange, pPg.get()); 1293 Broadcast(aHint); 1294 } 1295 1296 1297 void SdrModel::CopyPages(sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum, 1298 sal_uInt16 nDestPos, 1299 bool bUndo, bool bMoveNoCopy) 1300 { 1301 if( bUndo && !IsUndoEnabled() ) 1302 bUndo = false; 1303 1304 if( bUndo ) 1305 BegUndo(SvxResId(STR_UndoMergeModel)); 1306 1307 sal_uInt16 nPageCnt=GetPageCount(); 1308 sal_uInt16 nMaxPage=nPageCnt; 1309 1310 if (nMaxPage!=0) 1311 nMaxPage--; 1312 if (nFirstPageNum>nMaxPage) 1313 nFirstPageNum=nMaxPage; 1314 if (nLastPageNum>nMaxPage) 1315 nLastPageNum =nMaxPage; 1316 bool bReverse=nLastPageNum<nFirstPageNum; 1317 if (nDestPos>nPageCnt) 1318 nDestPos=nPageCnt; 1319 1320 // at first, save the pointers of the affected pages in an array 1321 sal_uInt16 nPageNum=nFirstPageNum; 1322 sal_uInt16 nCopyCnt=((!bReverse)?(nLastPageNum-nFirstPageNum):(nFirstPageNum-nLastPageNum))+1; 1323 std::unique_ptr<SdrPage*[]> pPagePtrs(new SdrPage*[nCopyCnt]); 1324 sal_uInt16 nCopyNum; 1325 for(nCopyNum=0; nCopyNum<nCopyCnt; nCopyNum++) 1326 { 1327 pPagePtrs[nCopyNum]=GetPage(nPageNum); 1328 if (bReverse) 1329 nPageNum--; 1330 else 1331 nPageNum++; 1332 } 1333 1334 // now copy the pages 1335 sal_uInt16 nDestNum=nDestPos; 1336 for (nCopyNum=0; nCopyNum<nCopyCnt; nCopyNum++) 1337 { 1338 rtl::Reference<SdrPage> pPg = pPagePtrs[nCopyNum]; 1339 sal_uInt16 nPageNum2=pPg->GetPageNum(); 1340 if (!bMoveNoCopy) 1341 { 1342 const SdrPage* pPg1=GetPage(nPageNum2); 1343 1344 // Clone to local model 1345 pPg = pPg1->CloneSdrPage(*this); 1346 1347 InsertPage(pPg.get(), nDestNum); 1348 if (bUndo) 1349 AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg)); 1350 nDestNum++; 1351 } 1352 else 1353 { 1354 // TODO: Move is untested! 1355 if (nDestNum>nPageNum2) 1356 nDestNum--; 1357 1358 if(bUndo) 1359 AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2),nPageNum2,nDestNum)); 1360 1361 pPg=RemovePage(nPageNum2); 1362 InsertPage(pPg.get(), nDestNum); 1363 nDestNum++; 1364 } 1365 1366 if(bReverse) 1367 nPageNum2--; 1368 else 1369 nPageNum2++; 1370 } 1371 1372 pPagePtrs.reset(); 1373 if(bUndo) 1374 EndUndo(); 1375 } 1376 1377 void SdrModel::Merge(SdrModel& rSourceModel, 1378 sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum, 1379 sal_uInt16 nDestPos, 1380 bool bMergeMasterPages, bool bAllMasterPages, 1381 bool bUndo, bool bTreadSourceAsConst) 1382 { 1383 if (&rSourceModel==this) 1384 { 1385 CopyPages(nFirstPageNum,nLastPageNum,nDestPos,bUndo,!bTreadSourceAsConst); 1386 return; 1387 } 1388 1389 if( bUndo && !IsUndoEnabled() ) 1390 bUndo = false; 1391 1392 if (bUndo) 1393 BegUndo(SvxResId(STR_UndoMergeModel)); 1394 1395 sal_uInt16 nSrcPageCnt=rSourceModel.GetPageCount(); 1396 sal_uInt16 nSrcMasterPageCnt=rSourceModel.GetMasterPageCount(); 1397 sal_uInt16 nDstMasterPageCnt=GetMasterPageCount(); 1398 bool bInsPages=(nFirstPageNum<nSrcPageCnt || nLastPageNum<nSrcPageCnt); 1399 sal_uInt16 nMaxSrcPage=nSrcPageCnt; if (nMaxSrcPage!=0) nMaxSrcPage--; 1400 if (nFirstPageNum>nMaxSrcPage) nFirstPageNum=nMaxSrcPage; 1401 if (nLastPageNum>nMaxSrcPage) nLastPageNum =nMaxSrcPage; 1402 bool bReverse=nLastPageNum<nFirstPageNum; 1403 1404 std::unique_ptr<sal_uInt16[]> pMasterMap; 1405 std::unique_ptr<bool[]> pMasterNeed; 1406 sal_uInt16 nMasterNeed=0; 1407 if (bMergeMasterPages && nSrcMasterPageCnt!=0) { 1408 // determine which MasterPages from rSrcModel we need 1409 pMasterMap.reset(new sal_uInt16[nSrcMasterPageCnt]); 1410 pMasterNeed.reset(new bool[nSrcMasterPageCnt]); 1411 memset(pMasterMap.get(),0xFF,nSrcMasterPageCnt*sizeof(sal_uInt16)); 1412 if (bAllMasterPages) { 1413 memset(pMasterNeed.get(), true, nSrcMasterPageCnt * sizeof(bool)); 1414 } else { 1415 memset(pMasterNeed.get(), false, nSrcMasterPageCnt * sizeof(bool)); 1416 sal_uInt16 nStart= bReverse ? nLastPageNum : nFirstPageNum; 1417 sal_uInt16 nEnd= bReverse ? nFirstPageNum : nLastPageNum; 1418 for (sal_uInt16 i=nStart; i<=nEnd; i++) { 1419 const SdrPage* pPg=rSourceModel.GetPage(i); 1420 if(pPg->TRG_HasMasterPage()) 1421 { 1422 SdrPage& rMasterPage = pPg->TRG_GetMasterPage(); 1423 sal_uInt16 nMPgNum(rMasterPage.GetPageNum()); 1424 1425 if(nMPgNum < nSrcMasterPageCnt) 1426 { 1427 pMasterNeed[nMPgNum] = true; 1428 } 1429 } 1430 } 1431 } 1432 // now determine the Mapping of the MasterPages 1433 sal_uInt16 nCurrentMaPagNum=nDstMasterPageCnt; 1434 for (sal_uInt16 i=0; i<nSrcMasterPageCnt; i++) { 1435 if (pMasterNeed[i]) { 1436 pMasterMap[i]=nCurrentMaPagNum; 1437 nCurrentMaPagNum++; 1438 nMasterNeed++; 1439 } 1440 } 1441 } 1442 1443 // get the MasterPages 1444 if (pMasterMap && pMasterNeed && nMasterNeed!=0) { 1445 for (sal_uInt16 i=nSrcMasterPageCnt; i>0;) { 1446 i--; 1447 if (pMasterNeed[i]) 1448 { 1449 // Always Clone to new model 1450 const SdrPage* pPg1(rSourceModel.GetMasterPage(i)); 1451 rtl::Reference<SdrPage> pPg = pPg1->CloneSdrPage(*this); 1452 1453 if(!bTreadSourceAsConst) 1454 { 1455 // if requested, delete original/modify original model 1456 rSourceModel.RemoveMasterPage(i); 1457 } 1458 1459 if (pPg!=nullptr) { 1460 // Now append all of them to the end of the DstModel. 1461 // Don't use InsertMasterPage(), because everything is 1462 // inconsistent until all are in. 1463 maMasterPages.insert(maMasterPages.begin()+nDstMasterPageCnt, pPg); 1464 MasterPageListChanged(); 1465 pPg->SetInserted(); 1466 m_bMPgNumsDirty=true; 1467 if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg)); 1468 } else { 1469 OSL_FAIL("SdrModel::Merge(): MasterPage not found in SourceModel."); 1470 } 1471 } 1472 } 1473 } 1474 1475 // get the drawing pages 1476 if (bInsPages) { 1477 sal_uInt16 nSourcePos=nFirstPageNum; 1478 sal_uInt16 nMergeCount=sal_uInt16(std::abs(static_cast<tools::Long>(static_cast<tools::Long>(nFirstPageNum)-nLastPageNum))+1); 1479 if (nDestPos>GetPageCount()) nDestPos=GetPageCount(); 1480 while (nMergeCount>0) 1481 { 1482 // Always Clone to new model 1483 const SdrPage* pPg1(rSourceModel.GetPage(nSourcePos)); 1484 rtl::Reference<SdrPage> pPg = pPg1->CloneSdrPage(*this); 1485 1486 if(!bTreadSourceAsConst) 1487 { 1488 // if requested, delete original/modify original model 1489 rSourceModel.RemovePage(nSourcePos); 1490 } 1491 1492 if (pPg!=nullptr) { 1493 InsertPage(pPg.get(),nDestPos); 1494 if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg)); 1495 1496 if(pPg->TRG_HasMasterPage()) 1497 { 1498 SdrPage& rMasterPage = pPg->TRG_GetMasterPage(); 1499 sal_uInt16 nMaPgNum(rMasterPage.GetPageNum()); 1500 1501 if (bMergeMasterPages) 1502 { 1503 sal_uInt16 nNewNum(0xFFFF); 1504 1505 if(pMasterMap) 1506 { 1507 nNewNum = pMasterMap[nMaPgNum]; 1508 } 1509 1510 if(nNewNum != 0xFFFF) 1511 { 1512 // tdf#90357 here pPg and the to-be-set new masterpage are parts of the new model 1513 // already, but the currently set masterpage is part of the old model. Remove master 1514 // page from already cloned page to prevent creating wrong undo action that can 1515 // eventually crash the app. 1516 // Do *not* remove it directly after cloning - the old masterpage is still needed 1517 // later to find the new to-be-set masterpage. 1518 pPg->TRG_ClearMasterPage(); 1519 1520 if(bUndo) 1521 { 1522 AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg)); 1523 } 1524 1525 pPg->TRG_SetMasterPage(*GetMasterPage(nNewNum)); 1526 } 1527 DBG_ASSERT(nNewNum!=0xFFFF,"SdrModel::Merge(): Something is crooked with the mapping of the MasterPages."); 1528 } else { 1529 if (nMaPgNum>=nDstMasterPageCnt) { 1530 // This is outside of the original area of the MasterPage of the DstModel. 1531 pPg->TRG_ClearMasterPage(); 1532 } 1533 } 1534 } 1535 1536 } else { 1537 OSL_FAIL("SdrModel::Merge(): Drawing page not found in SourceModel."); 1538 } 1539 nDestPos++; 1540 if (bReverse) nSourcePos--; 1541 else if (bTreadSourceAsConst) nSourcePos++; 1542 nMergeCount--; 1543 } 1544 } 1545 1546 pMasterMap.reset(); 1547 pMasterNeed.reset(); 1548 1549 m_bMPgNumsDirty=true; 1550 m_bPagNumsDirty=true; 1551 1552 SetChanged(); 1553 // TODO: Missing: merging and mapping of layers 1554 // at the objects as well as at the MasterPageDescriptors 1555 if (bUndo) EndUndo(); 1556 } 1557 1558 void SdrModel::SetStarDrawPreviewMode(bool bPreview) 1559 { 1560 if (!bPreview && m_bStarDrawPreviewMode && GetPageCount()) 1561 { 1562 // Resetting is not allowed, because the Model might not be loaded completely 1563 SAL_WARN("svx", "SdrModel::SetStarDrawPreviewMode(): Resetting not allowed, because Model might not be complete."); 1564 } 1565 else 1566 { 1567 m_bStarDrawPreviewMode = bPreview; 1568 } 1569 } 1570 1571 uno::Reference< uno::XInterface > const & SdrModel::getUnoModel() 1572 { 1573 if( !mxUnoModel.is() ) 1574 mxUnoModel = createUnoModel(); 1575 1576 return mxUnoModel; 1577 } 1578 1579 void SdrModel::setUnoModel( const css::uno::Reference< css::uno::XInterface >& xModel ) 1580 { 1581 mxUnoModel = xModel; 1582 } 1583 1584 void SdrModel::adaptSizeAndBorderForAllPages( 1585 const Size& /*rNewSize*/, 1586 tools::Long /*nLeft*/, 1587 tools::Long /*nRight*/, 1588 tools::Long /*nUpper*/, 1589 tools::Long /*nLower*/) 1590 { 1591 // base implementation does currently nothing. It may be added if needed, 1592 // but we are on SdrModel level here, thus probably have not enough information 1593 // to do this for higher-level (derived) Models (e.g. Draw/Impress) 1594 } 1595 1596 uno::Reference< uno::XInterface > SdrModel::createUnoModel() 1597 { 1598 OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" ); 1599 css::uno::Reference< css::uno::XInterface > xInt; 1600 return xInt; 1601 } 1602 1603 void SdrModel::setLock( bool bLock ) 1604 { 1605 if( mbModelLocked != bLock ) 1606 { 1607 // #i120437# need to set first, else ImpReformatAllEdgeObjects will do nothing 1608 mbModelLocked = bLock; 1609 1610 if( !bLock ) 1611 { 1612 ImpReformatAllEdgeObjects(); 1613 } 1614 } 1615 } 1616 1617 1618 void SdrModel::MigrateItemSet( const SfxItemSet* pSourceSet, SfxItemSet* pDestSet, SdrModel* pNewModelel ) 1619 { 1620 assert(pNewModelel != nullptr); 1621 if( !(pSourceSet && pDestSet && (pSourceSet != pDestSet )) ) 1622 return; 1623 1624 SfxWhichIter aWhichIter(*pSourceSet); 1625 sal_uInt16 nWhich(aWhichIter.FirstWhich()); 1626 const SfxPoolItem *pPoolItem; 1627 1628 while(nWhich) 1629 { 1630 if(SfxItemState::SET == pSourceSet->GetItemState(nWhich, false, &pPoolItem)) 1631 { 1632 std::unique_ptr<SfxPoolItem> pResultItem; 1633 1634 switch( nWhich ) 1635 { 1636 case XATTR_FILLBITMAP: 1637 pResultItem = static_cast<const XFillBitmapItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1638 break; 1639 case XATTR_LINEDASH: 1640 pResultItem = static_cast<const XLineDashItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1641 break; 1642 case XATTR_LINESTART: 1643 pResultItem = static_cast<const XLineStartItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1644 break; 1645 case XATTR_LINEEND: 1646 pResultItem = static_cast<const XLineEndItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1647 break; 1648 case XATTR_FILLGRADIENT: 1649 pResultItem = static_cast<const XFillGradientItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1650 break; 1651 case XATTR_FILLFLOATTRANSPARENCE: 1652 // allow all kinds of XFillFloatTransparenceItem to be set 1653 pResultItem = static_cast<const XFillFloatTransparenceItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1654 break; 1655 case XATTR_FILLHATCH: 1656 pResultItem = static_cast<const XFillHatchItem*>(pPoolItem)->checkForUniqueItem( pNewModelel ); 1657 break; 1658 } 1659 1660 // set item 1661 if( pResultItem ) 1662 { 1663 pDestSet->Put(*pResultItem); 1664 pResultItem.reset(); 1665 } 1666 else 1667 pDestSet->Put(*pPoolItem); 1668 } 1669 nWhich = aWhichIter.NextWhich(); 1670 } 1671 } 1672 1673 1674 void SdrModel::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars) 1675 { 1676 mpForbiddenCharactersTable = xForbiddenChars; 1677 1678 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 1679 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 1680 } 1681 1682 1683 void SdrModel::SetCharCompressType( CharCompressType nType ) 1684 { 1685 if( nType != mnCharCompressType ) 1686 { 1687 mnCharCompressType = nType; 1688 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 1689 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 1690 } 1691 } 1692 1693 void SdrModel::SetKernAsianPunctuation( bool bEnabled ) 1694 { 1695 if( mbKernAsianPunctuation != bEnabled ) 1696 { 1697 mbKernAsianPunctuation = bEnabled; 1698 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 1699 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 1700 } 1701 } 1702 1703 void SdrModel::SetAddExtLeading( bool bEnabled ) 1704 { 1705 if( mbAddExtLeading != bEnabled ) 1706 { 1707 mbAddExtLeading = bEnabled; 1708 ImpSetOutlinerDefaults( m_pDrawOutliner.get() ); 1709 ImpSetOutlinerDefaults( m_pHitTestOutliner.get() ); 1710 } 1711 } 1712 1713 void SdrModel::SetAnchoredTextOverflowLegacy(bool bEnabled) 1714 { 1715 mpImpl->mbAnchoredTextOverflowLegacy = bEnabled; 1716 } 1717 1718 bool SdrModel::IsAnchoredTextOverflowLegacy() const 1719 { 1720 return mpImpl->mbAnchoredTextOverflowLegacy; 1721 } 1722 1723 void SdrModel::ReformatAllTextObjects() 1724 { 1725 ImpReformatAllTextObjects(); 1726 } 1727 1728 std::unique_ptr<SdrOutliner> SdrModel::createOutliner( OutlinerMode nOutlinerMode ) 1729 { 1730 if( !mpOutlinerCache ) 1731 mpOutlinerCache.reset(new SdrOutlinerCache(this)); 1732 1733 return mpOutlinerCache->createOutliner( nOutlinerMode ); 1734 } 1735 1736 std::vector<SdrOutliner*> SdrModel::GetActiveOutliners() const 1737 { 1738 std::vector< SdrOutliner* > aRet(mpOutlinerCache ? mpOutlinerCache->GetActiveOutliners() : std::vector< SdrOutliner* >()); 1739 aRet.push_back(m_pDrawOutliner.get()); 1740 aRet.push_back(m_pHitTestOutliner.get()); 1741 1742 return aRet; 1743 } 1744 1745 void SdrModel::disposeOutliner( std::unique_ptr<SdrOutliner> pOutliner ) 1746 { 1747 if( mpOutlinerCache ) 1748 mpOutlinerCache->disposeOutliner( std::move(pOutliner) ); 1749 } 1750 1751 SvxNumType SdrModel::GetPageNumType() const 1752 { 1753 return SVX_NUM_ARABIC; 1754 } 1755 1756 void SdrModel::ReadUserDataSequenceValue(const css::beans::PropertyValue* pValue) 1757 { 1758 if (pValue->Name == "AnchoredTextOverflowLegacy") 1759 { 1760 bool bBool = false; 1761 if (pValue->Value >>= bBool) 1762 { 1763 mpImpl->mbAnchoredTextOverflowLegacy = bBool; 1764 } 1765 } 1766 } 1767 1768 template <typename T> 1769 static void addPair(std::vector< std::pair< OUString, Any > >& aUserData, const OUString& name, const T val) 1770 { 1771 aUserData.push_back(std::pair< OUString, Any >(name, css::uno::makeAny(val))); 1772 } 1773 1774 void SdrModel::WriteUserDataSequence(css::uno::Sequence < css::beans::PropertyValue >& rValues) 1775 { 1776 std::vector< std::pair< OUString, Any > > aUserData; 1777 addPair(aUserData, "AnchoredTextOverflowLegacy", IsAnchoredTextOverflowLegacy()); 1778 1779 const sal_Int32 nOldLength = rValues.getLength(); 1780 rValues.realloc(nOldLength + aUserData.size()); 1781 1782 css::beans::PropertyValue* pValue = &(rValues.getArray()[nOldLength]); 1783 1784 for (const auto &aIter : aUserData) 1785 { 1786 pValue->Name = aIter.first; 1787 pValue->Value = aIter.second; 1788 ++pValue; 1789 } 1790 } 1791 1792 const SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum) const 1793 { 1794 return nPgNum < maPages.size() ? maPages[nPgNum].get() : nullptr; 1795 } 1796 1797 SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum) 1798 { 1799 return nPgNum < maPages.size() ? maPages[nPgNum].get() : nullptr; 1800 } 1801 1802 sal_uInt16 SdrModel::GetPageCount() const 1803 { 1804 return sal_uInt16(maPages.size()); 1805 } 1806 1807 void SdrModel::PageListChanged() 1808 { 1809 } 1810 1811 TextChain *SdrModel::GetTextChain() const 1812 { 1813 return m_pTextChain.get(); 1814 } 1815 1816 const SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) const 1817 { 1818 DBG_ASSERT(nPgNum < maMasterPages.size(), "SdrModel::GetMasterPage: Access out of range (!)"); 1819 return maMasterPages[nPgNum].get(); 1820 } 1821 1822 SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) 1823 { 1824 DBG_ASSERT(nPgNum < maMasterPages.size(), "SdrModel::GetMasterPage: Access out of range (!)"); 1825 return maMasterPages[nPgNum].get(); 1826 } 1827 1828 sal_uInt16 SdrModel::GetMasterPageCount() const 1829 { 1830 return sal_uInt16(maMasterPages.size()); 1831 } 1832 1833 void SdrModel::MasterPageListChanged() 1834 { 1835 } 1836 1837 void SdrModel::SetSdrUndoManager( SfxUndoManager* pUndoManager ) 1838 { 1839 mpImpl->mpUndoManager = pUndoManager; 1840 } 1841 1842 SfxUndoManager* SdrModel::GetSdrUndoManager() const 1843 { 1844 return mpImpl->mpUndoManager; 1845 } 1846 1847 SdrUndoFactory& SdrModel::GetSdrUndoFactory() const 1848 { 1849 if( !mpImpl->mpUndoFactory ) 1850 mpImpl->mpUndoFactory = new SdrUndoFactory; 1851 return *mpImpl->mpUndoFactory; 1852 } 1853 1854 void SdrModel::SetSdrUndoFactory( SdrUndoFactory* pUndoFactory ) 1855 { 1856 if( pUndoFactory && (pUndoFactory != mpImpl->mpUndoFactory) ) 1857 { 1858 delete mpImpl->mpUndoFactory; 1859 mpImpl->mpUndoFactory = pUndoFactory; 1860 } 1861 } 1862 1863 void SdrModel::dumpAsXml(xmlTextWriterPtr pWriter) const 1864 { 1865 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SdrModel")); 1866 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); 1867 1868 sal_uInt16 nPageCount = GetPageCount(); 1869 for (sal_uInt16 i = 0; i < nPageCount; ++i) 1870 { 1871 if (const SdrPage* pPage = GetPage(i)) 1872 pPage->dumpAsXml(pWriter); 1873 } 1874 1875 (void)xmlTextWriterEndElement(pWriter); 1876 } 1877 1878 const css::uno::Sequence< sal_Int8 >& SdrModel::getUnoTunnelId() 1879 { 1880 static const UnoTunnelIdInit theSdrModelUnoTunnelImplementationId; 1881 return theSdrModelUnoTunnelImplementationId.getSeq(); 1882 } 1883 1884 1885 SdrHint::SdrHint(SdrHintKind eNewHint) 1886 : SfxHint(SfxHintId::ThisIsAnSdrHint), 1887 meHint(eNewHint), 1888 mpObj(nullptr), 1889 mpPage(nullptr) 1890 { 1891 } 1892 1893 SdrHint::SdrHint(SdrHintKind eNewHint, const SdrObject& rNewObj) 1894 : SfxHint(SfxHintId::ThisIsAnSdrHint), 1895 meHint(eNewHint), 1896 mpObj(&rNewObj), 1897 mpPage(rNewObj.getSdrPageFromSdrObject()) 1898 { 1899 } 1900 1901 SdrHint::SdrHint(SdrHintKind eNewHint, const SdrPage* pPage) 1902 : SfxHint(SfxHintId::ThisIsAnSdrHint), 1903 meHint(eNewHint), 1904 mpObj(nullptr), 1905 mpPage(pPage) 1906 { 1907 } 1908 1909 SdrHint::SdrHint(SdrHintKind eNewHint, const SdrObject& rNewObj, const SdrPage* pPage) 1910 : SfxHint(SfxHintId::ThisIsAnSdrHint), 1911 meHint(eNewHint), 1912 mpObj(&rNewObj), 1913 mpPage(pPage) 1914 { 1915 } 1916 1917 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1918
