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 <boost/property_tree/json_parser.hpp> 21 22 #include <sal/config.h> 23 24 #include <comphelper/string.hxx> 25 #include <AnnotationWin.hxx> 26 #include <o3tl/any.hxx> 27 #include <osl/mutex.hxx> 28 #include <vcl/commandevent.hxx> 29 #include <vcl/image.hxx> 30 #include <vcl/vclevent.hxx> 31 #include <vcl/virdev.hxx> 32 #include <vcl/sysdata.hxx> 33 #include <vcl/svapp.hxx> 34 #include <vcl/print.hxx> 35 #include <sfx2/viewfrm.hxx> 36 #include <sfx2/lokhelper.hxx> 37 #include <sfx2/sfxbasecontroller.hxx> 38 #include <sfx2/docfile.hxx> 39 #include <sfx2/msg.hxx> 40 #include <sfx2/msgpool.hxx> 41 #include <sfx2/printer.hxx> 42 #include <toolkit/helper/vclunohelper.hxx> 43 #include <toolkit/awt/vclxdevice.hxx> 44 #include <LibreOfficeKit/LibreOfficeKitEnums.h> 45 #include <sfx2/lokcharthelper.hxx> 46 #include <sfx2/ipclient.hxx> 47 #include <editeng/svxacorr.hxx> 48 #include <editeng/acorrcfg.hxx> 49 #include <cmdid.h> 50 #include <swtypes.hxx> 51 #include <wdocsh.hxx> 52 #include <wrtsh.hxx> 53 #include <pview.hxx> 54 #include <viewsh.hxx> 55 #include <pvprtdat.hxx> 56 #include <printdata.hxx> 57 #include <pagefrm.hxx> 58 #include <rootfrm.hxx> 59 #include <svl/stritem.hxx> 60 #include <unotxdoc.hxx> 61 #include <svl/numuno.hxx> 62 #include <fldbas.hxx> 63 #include <unomap.hxx> 64 #include <unotextbodyhf.hxx> 65 #include <unotextrange.hxx> 66 #include <unotextcursor.hxx> 67 #include <unosett.hxx> 68 #include <unocoll.hxx> 69 #include <unoredlines.hxx> 70 #include <unosrch.hxx> 71 #include <sfx2/dispatch.hxx> 72 #include <sfx2/request.hxx> 73 #include <sfx2/objsh.hxx> 74 #include <unoprnms.hxx> 75 #include <unostyle.hxx> 76 #include <unodraw.hxx> 77 #include <svl/eitem.hxx> 78 #include <pagedesc.hxx> 79 #include <unotools/datetime.hxx> 80 #include <unotools/textsearch.hxx> 81 #include <unocrsr.hxx> 82 #include <unofieldcoll.hxx> 83 #include <unoidxcoll.hxx> 84 #include <unocrsrhelper.hxx> 85 #include <unotxvw.hxx> 86 #include <poolfmt.hxx> 87 #include <globdoc.hxx> 88 #include <viewopt.hxx> 89 #include <unochart.hxx> 90 #include <charatr.hxx> 91 #include <svx/xmleohlp.hxx> 92 #include <globals.hrc> 93 #include <unomid.h> 94 #include <unotools/printwarningoptions.hxx> 95 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp> 96 #include <com/sun/star/lang/DisposedException.hpp> 97 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> 98 #include <com/sun/star/lang/NoSupportException.hpp> 99 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 100 #include <com/sun/star/beans/PropertyAttribute.hpp> 101 #include <com/sun/star/beans/XFastPropertySet.hpp> 102 #include <com/sun/star/document/RedlineDisplayType.hpp> 103 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp> 104 #include <com/sun/star/frame/XController.hpp> 105 #include <com/sun/star/frame/XFrame.hpp> 106 #include <com/sun/star/script/XInvocation.hpp> 107 #include <sfx2/linkmgr.hxx> 108 #include <svx/unofill.hxx> 109 #include <editeng/unolingu.hxx> 110 #include <sfx2/progress.hxx> 111 #include <swmodule.hxx> 112 #include <docstat.hxx> 113 #include <modcfg.hxx> 114 #include <ndtxt.hxx> 115 #include <strings.hrc> 116 #include <bitmaps.hlst> 117 #include <swcont.hxx> 118 #include "unodefaults.hxx" 119 #include "SwXDocumentSettings.hxx" 120 #include <doc.hxx> 121 #include <IDocumentSettingAccess.hxx> 122 #include <IDocumentDeviceAccess.hxx> 123 #include <IDocumentDrawModelAccess.hxx> 124 #include <IDocumentChartDataProviderAccess.hxx> 125 #include <IDocumentLinksAdministration.hxx> 126 #include <IDocumentRedlineAccess.hxx> 127 #include <IDocumentFieldsAccess.hxx> 128 #include <IDocumentStatistics.hxx> 129 #include <IDocumentStylePoolAccess.hxx> 130 #include <IDocumentLayoutAccess.hxx> 131 #include <IDocumentState.hxx> 132 #include <editeng/forbiddencharacterstable.hxx> 133 #include <svl/zforlist.hxx> 134 #include <drawdoc.hxx> 135 #include <SwStyleNameMapper.hxx> 136 #include <osl/file.hxx> 137 #include <comphelper/lok.hxx> 138 #include <comphelper/storagehelper.hxx> 139 #include <cppuhelper/supportsservice.hxx> 140 #include <unotools/saveopt.hxx> 141 #include <swruler.hxx> 142 #include <docufld.hxx> 143 144 145 #include <EnhancedPDFExportHelper.hxx> 146 #include <numrule.hxx> 147 148 #include <editeng/langitem.hxx> 149 #include <docary.hxx> 150 #include <i18nlangtag/languagetag.hxx> 151 #include <i18nutil/searchopt.hxx> 152 153 #include <format.hxx> 154 #include <charfmt.hxx> 155 #include <fmtcol.hxx> 156 #include <istyleaccess.hxx> 157 158 #include <svl/stylepool.hxx> 159 #include <swatrset.hxx> 160 #include <view.hxx> 161 #include <viscrs.hxx> 162 #include <srcview.hxx> 163 #include <edtwin.hxx> 164 #include <swdtflvr.hxx> 165 #include <PostItMgr.hxx> 166 167 #include <svtools/langtab.hxx> 168 #include <map> 169 #include <set> 170 #include <vector> 171 172 #include <editeng/eeitem.hxx> 173 #include <editeng/editeng.hxx> 174 #include <editeng/editview.hxx> 175 #include <svx/svdoutl.hxx> 176 #include <svl/languageoptions.hxx> 177 #include <svx/svdview.hxx> 178 #include <comphelper/servicehelper.hxx> 179 #include <SwSpellDialogChildWindow.hxx> 180 #include <memory> 181 #include <fchrfmt.hxx> 182 #include <redline.hxx> 183 #include <DocumentRedlineManager.hxx> 184 185 #define TWIPS_PER_PIXEL 15 186 187 using namespace ::com::sun::star; 188 using namespace ::com::sun::star::text; 189 using namespace ::com::sun::star::i18n; 190 using namespace ::com::sun::star::uno; 191 using namespace ::com::sun::star::beans; 192 using namespace ::com::sun::star::lang; 193 using namespace ::com::sun::star::container; 194 using namespace ::com::sun::star::document; 195 using ::osl::FileBase; 196 197 static std::unique_ptr<SwPrintUIOptions> lcl_GetPrintUIOptions( 198 SwDocShell * pDocShell, 199 const SfxViewShell * pView ) 200 { 201 if (!pDocShell) 202 return nullptr; 203 204 const bool bWebDoc = nullptr != dynamic_cast< const SwWebDocShell * >(pDocShell); 205 const bool bSwSrcView = nullptr != dynamic_cast< const SwSrcView * >(pView); 206 const SwView * pSwView = dynamic_cast< const SwView * >(pView); 207 const bool bHasSelection = pSwView && pSwView->HasSelection( false ); // check for any selection, not just text selection 208 const bool bHasPostIts = sw_GetPostIts( &pDocShell->GetDoc()->getIDocumentFieldsAccess(), nullptr ); 209 210 // get default values to use in dialog from documents SwPrintData 211 const SwPrintData &rPrintData = pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrintData(); 212 213 // Get current page number 214 sal_uInt16 nCurrentPage = 1; 215 const SwWrtShell* pSh = pDocShell->GetWrtShell(); 216 const SwRootFrame *pFrame = nullptr; 217 if (pSh) 218 { 219 SwPaM* pShellCursor = pSh->GetCursor(); 220 nCurrentPage = pShellCursor->GetPageNum(); 221 pFrame = pSh->GetLayout(); 222 } 223 else if (!bSwSrcView) 224 { 225 const SwPagePreview* pPreview = dynamic_cast< const SwPagePreview* >(pView); 226 OSL_ENSURE(pPreview, "Unexpected type of the view shell"); 227 if (pPreview) 228 { 229 nCurrentPage = pPreview->GetSelectedPage(); 230 pFrame = pPreview->GetViewShell()->GetLayout(); 231 } 232 } 233 234 // If blanks are skipped, account for them in initial page range value 235 if (pFrame && !rPrintData.IsPrintEmptyPages()) 236 { 237 sal_uInt16 nMax = nCurrentPage; 238 const SwPageFrame *pPage = dynamic_cast<const SwPageFrame*>(pFrame->Lower()); 239 while (pPage && nMax-- > 0) 240 { 241 if (pPage->getFrameArea().Height() == 0) 242 nCurrentPage--; 243 pPage = static_cast<const SwPageFrame*>(pPage->GetNext()); 244 } 245 } 246 return std::make_unique<SwPrintUIOptions>( nCurrentPage, bWebDoc, bSwSrcView, bHasSelection, bHasPostIts, rPrintData ); 247 } 248 249 static SwTextFormatColl *lcl_GetParaStyle(const OUString& rCollName, SwDoc* pDoc) 250 { 251 SwTextFormatColl* pColl = pDoc->FindTextFormatCollByName( rCollName ); 252 if( !pColl ) 253 { 254 const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( 255 rCollName, SwGetPoolIdFromName::TxtColl ); 256 if( USHRT_MAX != nId ) 257 pColl = pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( nId ); 258 } 259 return pColl; 260 } 261 262 static void lcl_DisposeView( SfxViewFrame* pToClose, SwDocShell const * pDocShell ) 263 { 264 // check if the view frame still exists 265 SfxViewFrame* pFound = SfxViewFrame::GetFirst( pDocShell, false ); 266 while(pFound) 267 { 268 if( pFound == pToClose) 269 { 270 pToClose->DoClose(); 271 break; 272 } 273 pFound = SfxViewFrame::GetNext( *pFound, pDocShell, false ); 274 } 275 } 276 277 class SwXTextDocument::Impl 278 { 279 private: 280 ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2 281 282 public: 283 ::comphelper::OInterfaceContainerHelper2 m_RefreshListeners; 284 285 Impl() : m_RefreshListeners(m_Mutex) { } 286 287 }; 288 289 namespace 290 { 291 class theSwXTextDocumentUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextDocumentUnoTunnelId > {}; 292 } 293 294 const Sequence< sal_Int8 > & SwXTextDocument::getUnoTunnelId() 295 { 296 return theSwXTextDocumentUnoTunnelId::get().getSeq(); 297 } 298 299 sal_Int64 SAL_CALL SwXTextDocument::getSomething( const Sequence< sal_Int8 >& rId ) 300 { 301 if( rId.getLength() == 16 302 && 0 == memcmp( getUnoTunnelId().getConstArray(), 303 rId.getConstArray(), 16 ) ) 304 { 305 return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); 306 } 307 if( rId.getLength() == 16 308 && 0 == memcmp( SfxObjectShell::getUnoTunnelId().getConstArray(), 309 rId.getConstArray(), 16 ) ) 310 { 311 return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pDocShell )); 312 } 313 314 sal_Int64 nRet = SfxBaseModel::getSomething( rId ); 315 if (nRet) 316 return nRet; 317 318 GetNumberFormatter(); 319 if (!xNumFormatAgg.is()) // may happen if not valid or no SwDoc 320 return 0; 321 Any aNumTunnel = xNumFormatAgg->queryAggregation(cppu::UnoType<XUnoTunnel>::get()); 322 Reference<XUnoTunnel> xNumTunnel; 323 aNumTunnel >>= xNumTunnel; 324 return (xNumTunnel.is()) ? xNumTunnel->getSomething(rId) : 0; 325 } 326 327 Any SAL_CALL SwXTextDocument::queryInterface( const uno::Type& rType ) 328 { 329 Any aRet = SwXTextDocumentBaseClass::queryInterface(rType); 330 if ( !aRet.hasValue() ) 331 aRet = SfxBaseModel::queryInterface(rType); 332 if ( !aRet.hasValue() && 333 rType == cppu::UnoType<lang::XMultiServiceFactory>::get()) 334 { 335 Reference<lang::XMultiServiceFactory> xTmp = this; 336 aRet <<= xTmp; 337 } 338 if ( !aRet.hasValue() && 339 rType == cppu::UnoType<tiledrendering::XTiledRenderable>::get()) 340 { 341 Reference<tiledrendering::XTiledRenderable> xTmp = this; 342 aRet <<= xTmp; 343 } 344 345 if ( !aRet.hasValue() 346 && rType != cppu::UnoType<css::document::XDocumentEventBroadcaster>::get() 347 && rType != cppu::UnoType<css::frame::XController>::get() 348 && rType != cppu::UnoType<css::frame::XFrame>::get() 349 && rType != cppu::UnoType<css::script::XInvocation>::get() 350 && rType != cppu::UnoType<css::beans::XFastPropertySet>::get() 351 && rType != cppu::UnoType<css::awt::XWindow>::get()) 352 { 353 GetNumberFormatter(); 354 if(xNumFormatAgg.is()) 355 aRet = xNumFormatAgg->queryAggregation(rType); 356 } 357 return aRet; 358 } 359 360 void SAL_CALL SwXTextDocument::acquire()throw() 361 { 362 SfxBaseModel::acquire(); 363 } 364 365 void SAL_CALL SwXTextDocument::release()throw() 366 { 367 SfxBaseModel::release(); 368 } 369 370 Reference< XAdapter > SwXTextDocument::queryAdapter( ) 371 { 372 return SfxBaseModel::queryAdapter(); 373 } 374 375 Sequence< uno::Type > SAL_CALL SwXTextDocument::getTypes() 376 { 377 Sequence< uno::Type > aNumTypes; 378 GetNumberFormatter(); 379 if(xNumFormatAgg.is()) 380 { 381 const uno::Type& rProvType = cppu::UnoType<XTypeProvider>::get(); 382 Any aNumProv = xNumFormatAgg->queryAggregation(rProvType); 383 Reference<XTypeProvider> xNumProv; 384 if(aNumProv >>= xNumProv) 385 { 386 aNumTypes = xNumProv->getTypes(); 387 } 388 } 389 return comphelper::concatSequences( 390 SfxBaseModel::getTypes(), 391 SwXTextDocumentBaseClass::getTypes(), 392 aNumTypes, 393 Sequence { 394 cppu::UnoType<lang::XMultiServiceFactory>::get(), 395 cppu::UnoType<tiledrendering::XTiledRenderable>::get()}); 396 } 397 398 SwXTextDocument::SwXTextDocument(SwDocShell* pShell) 399 : SfxBaseModel(pShell) 400 , m_pImpl(new Impl) 401 , 402 pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_DOCUMENT)), 403 404 pDocShell(pShell), 405 406 bObjectValid(pShell != nullptr), 407 408 pDrawPage(nullptr), 409 mxXDrawPage(), 410 pBodyText(nullptr), 411 mxXNumberingRules(), 412 mxXFootnotes(), 413 mxXFootnoteSettings(), 414 mxXEndnotes(), 415 mxXEndnoteSettings(), 416 mxXReferenceMarks(), 417 mxXTextFieldTypes(), 418 mxXTextFieldMasters(), 419 mxXTextSections(), 420 mxXBookmarks(), 421 mxXTextTables(), 422 mxXTextFrames(), 423 mxXGraphicObjects(), 424 mxXEmbeddedObjects(), 425 mxXStyleFamilies(), 426 mxXAutoStyles(), 427 mxXChapterNumbering(), 428 mxXDocumentIndexes(), 429 430 mxXLineNumberingProperties(), 431 mxLinkTargetSupplier(), 432 mxXRedlines(), 433 m_pHiddenViewFrame(nullptr), 434 // #i117783# 435 bApplyPagePrintSettingsFromXPagePrintable( false ) 436 { 437 } 438 439 SdrModel& SwXTextDocument::getSdrModelFromUnoModel() const 440 { 441 OSL_ENSURE(pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(), "No SdrModel in SwDoc, should not happen"); 442 return *pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel(); 443 } 444 445 SwXTextDocument::~SwXTextDocument() 446 { 447 InitNewDoc(); 448 if(xNumFormatAgg.is()) 449 { 450 Reference< XInterface > x0; 451 xNumFormatAgg->setDelegator(x0); 452 xNumFormatAgg = nullptr; 453 } 454 m_pPrintUIOptions.reset(); 455 if (m_pRenderData && m_pRenderData->IsViewOptionAdjust()) 456 { // rhbz#827695: this can happen if the last page is not printed 457 // the SwViewShell has been deleted already by SwView::~SwView 458 // FIXME: replace this awful implementation of XRenderable with 459 // something less insane that has its own view 460 m_pRenderData->ViewOptionAdjustCrashPreventionKludge(); 461 } 462 m_pRenderData.reset(); 463 } 464 465 SwXDocumentPropertyHelper * SwXTextDocument::GetPropertyHelper () 466 { 467 if(!mxPropertyHelper.is()) 468 { 469 mxPropertyHelper = new SwXDocumentPropertyHelper(*pDocShell->GetDoc()); 470 } 471 return mxPropertyHelper.get(); 472 } 473 474 void SwXTextDocument::GetNumberFormatter() 475 { 476 if(IsValid()) 477 { 478 if(!xNumFormatAgg.is()) 479 { 480 if ( pDocShell->GetDoc() ) 481 { 482 SvNumberFormatsSupplierObj* pNumFormat = new SvNumberFormatsSupplierObj( 483 pDocShell->GetDoc()->GetNumberFormatter()); 484 Reference< util::XNumberFormatsSupplier > xTmp = pNumFormat; 485 xNumFormatAgg.set(xTmp, UNO_QUERY); 486 } 487 if(xNumFormatAgg.is()) 488 xNumFormatAgg->setDelegator(static_cast<cppu::OWeakObject*>(static_cast<SwXTextDocumentBaseClass*>(this))); 489 } 490 else 491 { 492 const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get(); 493 Any aNumTunnel = xNumFormatAgg->queryAggregation(rTunnelType); 494 SvNumberFormatsSupplierObj* pNumFormat = nullptr; 495 Reference< XUnoTunnel > xNumTunnel; 496 if(aNumTunnel >>= xNumTunnel) 497 { 498 pNumFormat = reinterpret_cast<SvNumberFormatsSupplierObj*>( 499 xNumTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId())); 500 501 } 502 OSL_ENSURE(pNumFormat, "No number formatter available"); 503 if (pNumFormat && !pNumFormat->GetNumberFormatter()) 504 pNumFormat->SetNumberFormatter(pDocShell->GetDoc()->GetNumberFormatter()); 505 } 506 } 507 } 508 509 Reference< XText > SwXTextDocument::getText() 510 { 511 SolarMutexGuard aGuard; 512 if(!IsValid()) 513 throw DisposedException("", static_cast< XTextDocument* >(this)); 514 if(!xBodyText.is()) 515 { 516 pBodyText = new SwXBodyText(pDocShell->GetDoc()); 517 xBodyText = pBodyText; 518 } 519 return xBodyText; 520 } 521 522 void SwXTextDocument::reformat() 523 { 524 SolarMutexGuard aGuard; 525 if(!IsValid()) 526 throw DisposedException("", static_cast< XTextDocument* >(this)); 527 } 528 529 void SwXTextDocument::lockControllers() 530 { 531 SolarMutexGuard aGuard; 532 if(!IsValid()) 533 throw DisposedException("", static_cast< XTextDocument* >(this)); 534 535 maActionArr.emplace_front(new UnoActionContext(pDocShell->GetDoc())); 536 } 537 538 void SwXTextDocument::unlockControllers() 539 { 540 SolarMutexGuard aGuard; 541 if(maActionArr.empty()) 542 throw RuntimeException("Nothing to unlock"); 543 544 maActionArr.pop_front(); 545 } 546 547 sal_Bool SwXTextDocument::hasControllersLocked() 548 { 549 SolarMutexGuard aGuard; 550 return !maActionArr.empty(); 551 } 552 553 Reference< frame::XController > SwXTextDocument::getCurrentController() 554 { 555 return SfxBaseModel::getCurrentController(); 556 } 557 558 void SwXTextDocument::setCurrentController(const Reference< frame::XController > & xController) 559 { 560 SfxBaseModel::setCurrentController(xController); 561 } 562 563 Reference< XInterface > SwXTextDocument::getCurrentSelection() 564 { 565 SolarMutexGuard aGuard; 566 Reference< XInterface > xRef; 567 if(IsValid()) 568 { 569 SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>)); 570 while(pView && pView->GetObjectShell() != pDocShell) 571 { 572 pView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>)); 573 } 574 if(pView) 575 { 576 Any aRef = pView->GetUNOObject()->getSelection(); 577 aRef >>= xRef; 578 } 579 } 580 return xRef; 581 } 582 583 sal_Bool SwXTextDocument::attachResource(const OUString& aURL, const Sequence< beans::PropertyValue >& aArgs) 584 { 585 return SfxBaseModel::attachResource(aURL, aArgs); 586 } 587 588 OUString SwXTextDocument::getURL() 589 { 590 return SfxBaseModel::getURL(); 591 } 592 593 Sequence< beans::PropertyValue > SwXTextDocument::getArgs() 594 { 595 return SfxBaseModel::getArgs(); 596 } 597 598 void SwXTextDocument::connectController(const Reference< frame::XController > & xController) 599 { 600 SfxBaseModel::connectController(xController); 601 } 602 603 void SwXTextDocument::disconnectController(const Reference< frame::XController > & xController) 604 { 605 SfxBaseModel::disconnectController(xController); 606 } 607 608 void SwXTextDocument::dispose() 609 { 610 SfxBaseModel::dispose(); 611 } 612 613 void SwXTextDocument::close( sal_Bool bDeliverOwnership ) 614 { 615 if(pDocShell) 616 { 617 uno::Sequence< uno::Any > aArgs; 618 pDocShell->CallAutomationDocumentEventSinks( "Close", aArgs ); 619 } 620 SolarMutexGuard aGuard; 621 if(IsValid() && m_pHiddenViewFrame) 622 lcl_DisposeView( m_pHiddenViewFrame, pDocShell); 623 SfxBaseModel::close(bDeliverOwnership); 624 } 625 626 void SwXTextDocument::addEventListener(const Reference< lang::XEventListener > & aListener) 627 { 628 SfxBaseModel::addEventListener(aListener); 629 } 630 631 void SwXTextDocument::removeEventListener(const Reference< lang::XEventListener > & aListener) 632 { 633 SfxBaseModel::removeEventListener(aListener); 634 } 635 636 Reference< XPropertySet > SwXTextDocument::getLineNumberingProperties() 637 { 638 SolarMutexGuard aGuard; 639 if(!IsValid()) 640 throw DisposedException("", static_cast< XTextDocument* >(this)); 641 642 if(!mxXLineNumberingProperties.is()) 643 { 644 mxXLineNumberingProperties = new SwXLineNumberingProperties(pDocShell->GetDoc()); 645 } 646 return mxXLineNumberingProperties; 647 } 648 649 Reference< XIndexReplace > SwXTextDocument::getChapterNumberingRules() 650 { 651 SolarMutexGuard aGuard; 652 if(!IsValid()) 653 throw DisposedException("", static_cast< XTextDocument* >(this)); 654 if(!mxXChapterNumbering.is()) 655 { 656 mxXChapterNumbering = new SwXChapterNumbering(*pDocShell); 657 } 658 return mxXChapterNumbering; 659 } 660 661 Reference< XIndexAccess > SwXTextDocument::getNumberingRules() 662 { 663 SolarMutexGuard aGuard; 664 if(!IsValid()) 665 throw DisposedException("", static_cast< XTextDocument* >(this)); 666 if(!mxXNumberingRules.is() ) 667 { 668 mxXNumberingRules = new SwXNumberingRulesCollection( pDocShell->GetDoc() ); 669 } 670 return mxXNumberingRules; 671 } 672 673 Reference< XIndexAccess > SwXTextDocument::getFootnotes() 674 { 675 SolarMutexGuard aGuard; 676 if(!IsValid()) 677 throw DisposedException("", static_cast< XTextDocument* >(this)); 678 if(!mxXFootnotes.is()) 679 { 680 mxXFootnotes = new SwXFootnotes(false, pDocShell->GetDoc()); 681 } 682 return mxXFootnotes; 683 } 684 685 Reference< XPropertySet > SAL_CALL 686 SwXTextDocument::getFootnoteSettings() 687 { 688 SolarMutexGuard aGuard; 689 if(!IsValid()) 690 throw DisposedException("", static_cast< XTextDocument* >(this)); 691 if(!mxXFootnoteSettings.is()) 692 { 693 mxXFootnoteSettings = new SwXFootnoteProperties(pDocShell->GetDoc()); 694 } 695 return mxXFootnoteSettings; 696 } 697 698 Reference< XIndexAccess > SwXTextDocument::getEndnotes() 699 { 700 SolarMutexGuard aGuard; 701 if(!IsValid()) 702 throw DisposedException("", static_cast< XTextDocument* >(this)); 703 if(!mxXEndnotes.is()) 704 { 705 mxXEndnotes = new SwXFootnotes(true, pDocShell->GetDoc()); 706 } 707 return mxXEndnotes; 708 } 709 710 Reference< XPropertySet > SwXTextDocument::getEndnoteSettings() 711 { 712 SolarMutexGuard aGuard; 713 if(!IsValid()) 714 throw DisposedException("", static_cast< XTextDocument* >(this)); 715 if(!mxXEndnoteSettings.is()) 716 { 717 mxXEndnoteSettings = new SwXEndnoteProperties(pDocShell->GetDoc()); 718 } 719 return mxXEndnoteSettings; 720 } 721 722 Reference< util::XReplaceDescriptor > SwXTextDocument::createReplaceDescriptor() 723 { 724 SolarMutexGuard aGuard; 725 Reference< util::XReplaceDescriptor > xRet = new SwXTextSearch; 726 return xRet; 727 } 728 729 SwUnoCursor* SwXTextDocument::CreateCursorForSearch(Reference< XTextCursor > & xCursor) 730 { 731 getText(); 732 XText *const pText = xBodyText.get(); 733 SwXBodyText* pBText = static_cast<SwXBodyText*>(pText); 734 SwXTextCursor *const pXTextCursor = pBText->CreateTextCursor(true); 735 xCursor.set( static_cast<text::XWordCursor*>(pXTextCursor) ); 736 737 auto& rUnoCursor(pXTextCursor->GetCursor()); 738 rUnoCursor.SetRemainInSection(false); 739 return &rUnoCursor; 740 } 741 742 sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > & xDesc) 743 { 744 SolarMutexGuard aGuard; 745 Reference< XUnoTunnel > xDescTunnel(xDesc, UNO_QUERY_THROW); 746 if(!IsValid() || !xDescTunnel->getSomething(SwXTextSearch::getUnoTunnelId())) 747 throw DisposedException("", static_cast< XTextDocument* >(this)); 748 749 Reference< XTextCursor > xCursor; 750 auto pUnoCursor(CreateCursorForSearch(xCursor)); 751 752 const SwXTextSearch* pSearch = reinterpret_cast<const SwXTextSearch*>( 753 xDescTunnel->getSomething(SwXTextSearch::getUnoTunnelId())); 754 755 int eRanges(FindRanges::InBody|FindRanges::InSelAll); 756 757 i18nutil::SearchOptions2 aSearchOpt; 758 pSearch->FillSearchOptions( aSearchOpt ); 759 760 SwDocPositions eStart = pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start; 761 SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End; 762 763 // Search should take place anywhere 764 pUnoCursor->SetRemainInSection(false); 765 sal_uInt32 nResult; 766 UnoActionContext aContext(pDocShell->GetDoc()); 767 //try attribute search first 768 if(pSearch->HasSearchAttributes()||pSearch->HasReplaceAttributes()) 769 { 770 SfxItemSet aSearch(pDocShell->GetDoc()->GetAttrPool(), 771 svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_END-1, 772 RES_PARATR_BEGIN, RES_PARATR_END-1, 773 RES_FRMATR_BEGIN, RES_FRMATR_END-1>{}); 774 SfxItemSet aReplace(pDocShell->GetDoc()->GetAttrPool(), 775 svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_END-1, 776 RES_PARATR_BEGIN, RES_PARATR_END-1, 777 RES_FRMATR_BEGIN, RES_FRMATR_END-1>{}); 778 pSearch->FillSearchItemSet(aSearch); 779 pSearch->FillReplaceItemSet(aReplace); 780 bool bCancel; 781 nResult = static_cast<sal_Int32>(pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, 782 eStart, eEnd, bCancel, 783 static_cast<FindRanges>(eRanges), 784 !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr, 785 &aReplace )); 786 } 787 else if(pSearch->m_bStyles) 788 { 789 SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc()); 790 SwTextFormatColl *pReplaceColl = lcl_GetParaStyle(pSearch->m_sReplaceText, pUnoCursor->GetDoc()); 791 792 bool bCancel; 793 nResult = pUnoCursor->FindFormat(*pSearchColl, 794 eStart, eEnd, bCancel, 795 static_cast<FindRanges>(eRanges), pReplaceColl ); 796 797 } 798 else 799 { 800 //todo/mba: assuming that notes should be omitted 801 bool bCancel; 802 nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/, 803 eStart, eEnd, bCancel, 804 static_cast<FindRanges>(eRanges), 805 true ); 806 } 807 return static_cast<sal_Int32>(nResult); 808 809 } 810 811 Reference< util::XSearchDescriptor > SwXTextDocument::createSearchDescriptor() 812 { 813 SolarMutexGuard aGuard; 814 Reference< util::XSearchDescriptor > xRet = new SwXTextSearch; 815 return xRet; 816 817 } 818 819 // Used for findAll/First/Next 820 821 SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > & xDesc, 822 Reference< XTextCursor > & xCursor, 823 bool bAll, 824 sal_Int32& nResult, 825 Reference< XInterface > const & xLastResult) 826 { 827 Reference< XUnoTunnel > xDescTunnel(xDesc, UNO_QUERY); 828 if(!IsValid() || !xDescTunnel.is() || !xDescTunnel->getSomething(SwXTextSearch::getUnoTunnelId())) 829 return nullptr; 830 831 auto pUnoCursor(CreateCursorForSearch(xCursor)); 832 const SwXTextSearch* pSearch = reinterpret_cast<const SwXTextSearch*>( 833 xDescTunnel->getSomething(SwXTextSearch::getUnoTunnelId())); 834 835 bool bParentInExtra = false; 836 if(xLastResult.is()) 837 { 838 Reference<XUnoTunnel> xCursorTunnel( xLastResult, UNO_QUERY); 839 OTextCursorHelper* pPosCursor = nullptr; 840 if(xCursorTunnel.is()) 841 { 842 pPosCursor = reinterpret_cast<OTextCursorHelper*>(xCursorTunnel->getSomething( 843 OTextCursorHelper::getUnoTunnelId())); 844 } 845 SwPaM* pCursor = pPosCursor ? pPosCursor->GetPaM() : nullptr; 846 if(pCursor) 847 { 848 *pUnoCursor->GetPoint() = *pCursor->End(); 849 pUnoCursor->DeleteMark(); 850 } 851 else 852 { 853 SwXTextRange* pRange = nullptr; 854 if(xCursorTunnel.is()) 855 { 856 pRange = reinterpret_cast<SwXTextRange*>(xCursorTunnel->getSomething( 857 SwXTextRange::getUnoTunnelId())); 858 } 859 if(!pRange) 860 return nullptr; 861 pRange->GetPositions(*pUnoCursor); 862 if(pUnoCursor->HasMark()) 863 { 864 if(*pUnoCursor->GetPoint() < *pUnoCursor->GetMark()) 865 pUnoCursor->Exchange(); 866 pUnoCursor->DeleteMark(); 867 } 868 } 869 const SwNode& rRangeNode = pUnoCursor->GetNode(); 870 bParentInExtra = rRangeNode.FindFlyStartNode() || 871 rRangeNode.FindFootnoteStartNode() || 872 rRangeNode.FindHeaderStartNode() || 873 rRangeNode.FindFooterStartNode() ; 874 } 875 876 i18nutil::SearchOptions2 aSearchOpt; 877 pSearch->FillSearchOptions( aSearchOpt ); 878 879 /** 880 * The following combinations are allowed: 881 * - Search in the body: -> FindRanges::InBody 882 * - Search all in the body: -> FindRanges::InBodyOnly | FindRanges::InSelAll 883 * - Search in selections: one / all -> FindRanges::InSel [ | FindRanges::InSelAll ] 884 * - Search outside the body: one / all -> FindRanges::InOther [ | FindRanges::InSelAll ] 885 * - Search everywhere all: -> FindRanges::InSelAll 886 */ 887 FindRanges eRanges(FindRanges::InBody); 888 if(bParentInExtra) 889 eRanges = FindRanges::InOther; 890 if(bAll) //always - everywhere? 891 eRanges = FindRanges::InSelAll; 892 SwDocPositions eStart = !bAll ? SwDocPositions::Curr : pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start; 893 SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End; 894 895 nResult = 0; 896 for (int nSearchProc = 0; nSearchProc < 2; ++nSearchProc) 897 { 898 //try attribute search first 899 if(pSearch->HasSearchAttributes()) 900 { 901 SfxItemSet aSearch( 902 pDocShell->GetDoc()->GetAttrPool(), 903 svl::Items< 904 RES_CHRATR_BEGIN, RES_CHRATR_END - 1, 905 RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT, 906 RES_PARATR_BEGIN, RES_PARATR_END - 1, 907 RES_FRMATR_BEGIN, RES_FRMATR_END - 1>{}); 908 pSearch->FillSearchItemSet(aSearch); 909 bool bCancel; 910 nResult = static_cast<sal_Int32>(pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, 911 eStart, eEnd, bCancel, 912 eRanges, 913 !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr )); 914 } 915 else if(pSearch->m_bStyles) 916 { 917 SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc()); 918 //pSearch->sReplaceText 919 SwTextFormatColl *pReplaceColl = nullptr; 920 bool bCancel; 921 nResult = static_cast<sal_Int32>(pUnoCursor->FindFormat(*pSearchColl, 922 eStart, eEnd, bCancel, 923 eRanges, pReplaceColl )); 924 } 925 else 926 { 927 //todo/mba: assuming that notes should be omitted 928 bool bCancel; 929 nResult = static_cast<sal_Int32>(pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/, 930 eStart, eEnd, bCancel, 931 eRanges )); 932 } 933 if(nResult || (eRanges&(FindRanges::InSelAll|FindRanges::InOther))) 934 break; 935 //second step - find in other 936 eRanges = FindRanges::InOther; 937 } 938 return pUnoCursor; 939 } 940 941 Reference< XIndexAccess > 942 SwXTextDocument::findAll(const Reference< util::XSearchDescriptor > & xDesc) 943 { 944 SolarMutexGuard aGuard; 945 Reference< XInterface > xTmp; 946 sal_Int32 nResult = 0; 947 Reference< XTextCursor > xCursor; 948 auto pResultCursor(FindAny(xDesc, xCursor, true, nResult, xTmp)); 949 if(!pResultCursor) 950 throw RuntimeException("No result cursor"); 951 Reference< XIndexAccess > xRet = SwXTextRanges::Create( nResult ? &(*pResultCursor) : nullptr ); 952 return xRet; 953 } 954 955 Reference< XInterface > SwXTextDocument::findFirst(const Reference< util::XSearchDescriptor > & xDesc) 956 { 957 SolarMutexGuard aGuard; 958 Reference< XInterface > xTmp; 959 sal_Int32 nResult = 0; 960 Reference< XTextCursor > xCursor; 961 auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xTmp)); 962 if(!pResultCursor) 963 throw RuntimeException("No result cursor"); 964 Reference< XInterface > xRet; 965 if(nResult) 966 { 967 const uno::Reference< text::XText > xParent = 968 ::sw::CreateParentXText(*pDocShell->GetDoc(), 969 *pResultCursor->GetPoint()); 970 xRet = *new SwXTextCursor(xParent, *pResultCursor); 971 } 972 return xRet; 973 } 974 975 Reference< XInterface > SwXTextDocument::findNext(const Reference< XInterface > & xStartAt, 976 const Reference< util::XSearchDescriptor > & xDesc) 977 { 978 SolarMutexGuard aGuard; 979 sal_Int32 nResult = 0; 980 Reference< XTextCursor > xCursor; 981 if(!xStartAt.is()) 982 throw RuntimeException("xStartAt missing"); 983 auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xStartAt)); 984 if(!pResultCursor) 985 throw RuntimeException("No result cursor"); 986 Reference< XInterface > xRet; 987 if(nResult) 988 { 989 const uno::Reference< text::XText > xParent = 990 ::sw::CreateParentXText(*pDocShell->GetDoc(), 991 *pResultCursor->GetPoint()); 992 993 xRet = *new SwXTextCursor(xParent, *pResultCursor); 994 } 995 return xRet; 996 } 997 998 Sequence< beans::PropertyValue > SwXTextDocument::getPagePrintSettings() 999 { 1000 SolarMutexGuard aGuard; 1001 Sequence< beans::PropertyValue > aSeq(9); 1002 if(!IsValid()) 1003 throw DisposedException("", static_cast< XTextDocument* >(this)); 1004 1005 beans::PropertyValue* pArray = aSeq.getArray(); 1006 SwPagePreviewPrtData aData; 1007 const SwPagePreviewPrtData* pData = pDocShell->GetDoc()->GetPreviewPrtData(); 1008 if(pData) 1009 aData = *pData; 1010 Any aVal; 1011 aVal <<= static_cast<sal_Int16>(aData.GetRow()); 1012 pArray[0] = beans::PropertyValue("PageRows", -1, aVal, PropertyState_DIRECT_VALUE); 1013 aVal <<= static_cast<sal_Int16>(aData.GetCol()); 1014 pArray[1] = beans::PropertyValue("PageColumns", -1, aVal, PropertyState_DIRECT_VALUE); 1015 aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetLeftSpace())); 1016 pArray[2] = beans::PropertyValue("LeftMargin", -1, aVal, PropertyState_DIRECT_VALUE); 1017 aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetRightSpace())); 1018 pArray[3] = beans::PropertyValue("RightMargin", -1, aVal, PropertyState_DIRECT_VALUE); 1019 aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetTopSpace())); 1020 pArray[4] = beans::PropertyValue("TopMargin", -1, aVal, PropertyState_DIRECT_VALUE); 1021 aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetBottomSpace())); 1022 pArray[5] = beans::PropertyValue("BottomMargin", -1, aVal, PropertyState_DIRECT_VALUE); 1023 aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetHorzSpace())); 1024 pArray[6] = beans::PropertyValue("HoriMargin", -1, aVal, PropertyState_DIRECT_VALUE); 1025 aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetVertSpace())); 1026 pArray[7] = beans::PropertyValue("VertMargin", -1, aVal, PropertyState_DIRECT_VALUE); 1027 aVal <<= aData.GetLandscape(); 1028 pArray[8] = beans::PropertyValue("IsLandscape", -1, aVal, PropertyState_DIRECT_VALUE); 1029 1030 return aSeq; 1031 } 1032 1033 static sal_uInt32 lcl_Any_To_ULONG(const Any& rValue, bool& bException) 1034 { 1035 bException = false; 1036 TypeClass eType = rValue.getValueType().getTypeClass(); 1037 1038 sal_uInt32 nRet = 0; 1039 if( eType == TypeClass_UNSIGNED_LONG ) 1040 rValue >>= nRet; 1041 else 1042 { 1043 sal_Int32 nVal=0; 1044 bException = !(rValue >>= nVal); 1045 if( !bException ) 1046 nRet = static_cast<sal_uInt32>(nVal); 1047 } 1048 1049 return nRet; 1050 } 1051 1052 static OUString lcl_CreateOutlineString( size_t nIndex, 1053 const SwOutlineNodes& rOutlineNodes, const SwNumRule* pOutlRule) 1054 { 1055 OUStringBuffer sEntry; 1056 const SwTextNode * pTextNd = rOutlineNodes[ nIndex ]->GetTextNode(); 1057 SwNumberTree::tNumberVector aNumVector = pTextNd->GetNumberVector(); 1058 if( pOutlRule && pTextNd->GetNumRule()) 1059 for( int nLevel = 0; 1060 nLevel <= pTextNd->GetActualListLevel(); 1061 nLevel++ ) 1062 { 1063 long nVal = aNumVector[nLevel]; 1064 nVal ++; 1065 nVal -= pOutlRule->Get(nLevel).GetStart(); 1066 sEntry.append(OUString::number( nVal )); 1067 sEntry.append("."); 1068 } 1069 sEntry.append( rOutlineNodes[ nIndex ]-> 1070 GetTextNode()->GetExpandText(nullptr) ); 1071 return sEntry.makeStringAndClear(); 1072 } 1073 1074 void SwXTextDocument::setPagePrintSettings(const Sequence< beans::PropertyValue >& aSettings) 1075 { 1076 SolarMutexGuard aGuard; 1077 if(!IsValid()) 1078 throw DisposedException("", static_cast< XTextDocument* >(this)); 1079 1080 SwPagePreviewPrtData aData; 1081 //if only a few properties are coming, then use the current settings 1082 const SwPagePreviewPrtData* pData = pDocShell->GetDoc()->GetPreviewPrtData(); 1083 if(pData) 1084 aData = *pData; 1085 const beans::PropertyValue* pProperties = aSettings.getConstArray(); 1086 int nCount = aSettings.getLength(); 1087 for(int i = 0; i < nCount; i++) 1088 { 1089 OUString sName = pProperties[i].Name; 1090 const Any& rVal = pProperties[i].Value; 1091 bool bException; 1092 sal_uInt32 nVal = lcl_Any_To_ULONG(rVal, bException); 1093 if( sName == "PageRows" ) 1094 { 1095 if(!nVal || nVal > 0xff) 1096 throw RuntimeException("Invalid value"); 1097 aData.SetRow(static_cast<sal_uInt8>(nVal)); 1098 } 1099 else if(sName == "PageColumns") 1100 { 1101 if(!nVal || nVal > 0xff) 1102 throw RuntimeException("Invalid value"); 1103 aData.SetCol(static_cast<sal_uInt8>(nVal)); 1104 } 1105 else if(sName == "LeftMargin") 1106 { 1107 aData.SetLeftSpace(convertMm100ToTwip(nVal)); 1108 } 1109 else if(sName == "RightMargin") 1110 { 1111 aData.SetRightSpace(convertMm100ToTwip(nVal)); 1112 } 1113 else if(sName == "TopMargin") 1114 { 1115 aData.SetTopSpace(convertMm100ToTwip(nVal)); 1116 } 1117 else if(sName == "BottomMargin") 1118 { 1119 aData.SetBottomSpace(convertMm100ToTwip(nVal)); 1120 } 1121 else if(sName == "HoriMargin") 1122 { 1123 aData.SetHorzSpace(convertMm100ToTwip(nVal)); 1124 } 1125 else if(sName == "VertMargin") 1126 { 1127 aData.SetVertSpace(convertMm100ToTwip(nVal)); 1128 } 1129 else if(sName == "IsLandscape") 1130 { 1131 auto b = o3tl::tryAccess<bool>(rVal); 1132 bException = !b; 1133 if (b) 1134 { 1135 aData.SetLandscape(*b); 1136 } 1137 } 1138 else 1139 bException = true; 1140 if(bException) 1141 throw RuntimeException(); 1142 } 1143 pDocShell->GetDoc()->SetPreviewPrtData(&aData); 1144 1145 } 1146 1147 void SwXTextDocument::printPages(const Sequence< beans::PropertyValue >& xOptions) 1148 { 1149 SolarMutexGuard aGuard; 1150 if(!IsValid()) 1151 throw DisposedException("", static_cast< XTextDocument* >(this)); 1152 1153 SfxViewFrame* pFrame = SfxViewFrame::LoadHiddenDocument( *pDocShell, SfxInterfaceId(7) ); 1154 SfxRequest aReq(FN_PRINT_PAGEPREVIEW, SfxCallMode::SYNCHRON, 1155 pDocShell->GetDoc()->GetAttrPool()); 1156 aReq.AppendItem(SfxBoolItem(FN_PRINT_PAGEPREVIEW, true)); 1157 1158 for ( int n = 0; n < xOptions.getLength(); ++n ) 1159 { 1160 // get Property-Value from options 1161 const beans::PropertyValue &rProp = xOptions.getConstArray()[n]; 1162 Any aValue( rProp.Value ); 1163 1164 // FileName-Property? 1165 if ( rProp.Name == UNO_NAME_FILE_NAME ) 1166 { 1167 OUString sFileURL; 1168 if ( rProp.Value >>= sFileURL ) 1169 { 1170 // Convert the File URL into a system dependent path, as the SalPrinter expects 1171 OUString sSystemPath; 1172 FileBase::getSystemPathFromFileURL ( sFileURL, sSystemPath ); 1173 aReq.AppendItem(SfxStringItem( SID_FILE_NAME, sSystemPath ) ); 1174 } 1175 else if ( rProp.Value.getValueType() != cppu::UnoType<void>::get() ) 1176 throw IllegalArgumentException(); 1177 } 1178 1179 // CopyCount-Property 1180 else if ( rProp.Name == UNO_NAME_COPY_COUNT ) 1181 { 1182 sal_Int32 nCopies = 0; 1183 aValue >>= nCopies; 1184 aReq.AppendItem(SfxInt16Item( SID_PRINT_COPIES, static_cast<sal_Int16>(nCopies) ) ); 1185 } 1186 1187 // Collate-Property 1188 else if ( rProp.Name == UNO_NAME_COLLATE ) 1189 { 1190 auto b = o3tl::tryAccess<bool>(rProp.Value); 1191 if ( !b ) 1192 throw IllegalArgumentException(); 1193 aReq.AppendItem(SfxBoolItem( SID_PRINT_COLLATE, *b ) ); 1194 1195 } 1196 1197 // Sort-Property 1198 else if ( rProp.Name == UNO_NAME_SORT ) 1199 { 1200 auto b = o3tl::tryAccess<bool>(rProp.Value); 1201 if ( !b ) 1202 throw IllegalArgumentException(); 1203 1204 aReq.AppendItem(SfxBoolItem( SID_PRINT_SORT, *b ) ); 1205 } 1206 1207 // Pages-Property 1208 else if ( rProp.Name == UNO_NAME_PAGES ) 1209 { 1210 OUString sTmp; 1211 if ( !(rProp.Value >>= sTmp) ) 1212 throw IllegalArgumentException(); 1213 1214 aReq.AppendItem( SfxStringItem( SID_PRINT_PAGES, sTmp ) ); 1215 1216 } 1217 } 1218 1219 // #i117783# 1220 bApplyPagePrintSettingsFromXPagePrintable = true; 1221 pFrame->GetViewShell()->ExecuteSlot(aReq); 1222 // Frame close 1223 pFrame->DoClose(); 1224 1225 } 1226 1227 Reference< XNameAccess > SwXTextDocument::getReferenceMarks() 1228 { 1229 SolarMutexGuard aGuard; 1230 if(!IsValid()) 1231 throw DisposedException("", static_cast< XTextDocument* >(this)); 1232 if(!mxXReferenceMarks.is()) 1233 { 1234 mxXReferenceMarks = new SwXReferenceMarks(pDocShell->GetDoc()); 1235 } 1236 return mxXReferenceMarks; 1237 } 1238 1239 Reference< XEnumerationAccess > SwXTextDocument::getTextFields() 1240 { 1241 SolarMutexGuard aGuard; 1242 if(!IsValid()) 1243 throw DisposedException("", static_cast< XTextDocument* >(this)); 1244 if(!mxXTextFieldTypes.is()) 1245 { 1246 mxXTextFieldTypes = new SwXTextFieldTypes(pDocShell->GetDoc()); 1247 } 1248 return mxXTextFieldTypes; 1249 } 1250 1251 Reference< XNameAccess > SwXTextDocument::getTextFieldMasters() 1252 { 1253 SolarMutexGuard aGuard; 1254 if(!IsValid()) 1255 throw DisposedException("", static_cast< XTextDocument* >(this)); 1256 if(!mxXTextFieldMasters.is()) 1257 { 1258 mxXTextFieldMasters = new SwXTextFieldMasters(pDocShell->GetDoc()); 1259 } 1260 return mxXTextFieldMasters; 1261 } 1262 1263 Reference< XNameAccess > SwXTextDocument::getEmbeddedObjects() 1264 { 1265 SolarMutexGuard aGuard; 1266 if(!IsValid()) 1267 throw DisposedException("", static_cast< XTextDocument* >(this)); 1268 if(!mxXEmbeddedObjects.is()) 1269 { 1270 mxXEmbeddedObjects = new SwXTextEmbeddedObjects(pDocShell->GetDoc()); 1271 } 1272 return mxXEmbeddedObjects; 1273 } 1274 1275 Reference< XNameAccess > SwXTextDocument::getBookmarks() 1276 { 1277 SolarMutexGuard aGuard; 1278 if(!IsValid()) 1279 throw DisposedException("", static_cast< XTextDocument* >(this)); 1280 if(!mxXBookmarks.is()) 1281 { 1282 mxXBookmarks = new SwXBookmarks(pDocShell->GetDoc()); 1283 } 1284 return mxXBookmarks; 1285 } 1286 1287 Reference< XNameAccess > SwXTextDocument::getTextSections() 1288 { 1289 SolarMutexGuard aGuard; 1290 if(!IsValid()) 1291 throw DisposedException("", static_cast< XTextDocument* >(this)); 1292 if(!mxXTextSections.is()) 1293 { 1294 mxXTextSections = new SwXTextSections(pDocShell->GetDoc()); 1295 } 1296 return mxXTextSections; 1297 } 1298 1299 Reference< XNameAccess > SwXTextDocument::getTextTables() 1300 { 1301 SolarMutexGuard aGuard; 1302 if(!IsValid()) 1303 throw DisposedException("", static_cast< XTextDocument* >(this)); 1304 if(!mxXTextTables.is()) 1305 { 1306 mxXTextTables = new SwXTextTables(pDocShell->GetDoc()); 1307 } 1308 return mxXTextTables; 1309 } 1310 1311 Reference< XNameAccess > SwXTextDocument::getGraphicObjects() 1312 { 1313 SolarMutexGuard aGuard; 1314 if(!IsValid()) 1315 throw DisposedException("", static_cast< XTextDocument* >(this)); 1316 if(!mxXGraphicObjects.is()) 1317 { 1318 mxXGraphicObjects = new SwXTextGraphicObjects(pDocShell->GetDoc()); 1319 } 1320 return mxXGraphicObjects; 1321 } 1322 1323 Reference< XNameAccess > SwXTextDocument::getTextFrames() 1324 { 1325 SolarMutexGuard aGuard; 1326 if(!IsValid()) 1327 throw DisposedException("", static_cast< XTextDocument* >(this)); 1328 if(!mxXTextFrames.is()) 1329 { 1330 mxXTextFrames = new SwXTextFrames(pDocShell->GetDoc()); 1331 } 1332 return mxXTextFrames; 1333 } 1334 1335 Reference< XNameAccess > SwXTextDocument::getStyleFamilies() 1336 { 1337 SolarMutexGuard aGuard; 1338 if(!IsValid()) 1339 throw DisposedException("", static_cast< XTextDocument* >(this)); 1340 if(!mxXStyleFamilies.is()) 1341 { 1342 mxXStyleFamilies = new SwXStyleFamilies(*pDocShell); 1343 } 1344 return mxXStyleFamilies; 1345 } 1346 1347 uno::Reference< style::XAutoStyles > SwXTextDocument::getAutoStyles( ) 1348 { 1349 SolarMutexGuard aGuard; 1350 if(!IsValid()) 1351 throw DisposedException("", static_cast< XTextDocument* >(this)); 1352 if(!mxXAutoStyles.is()) 1353 { 1354 mxXAutoStyles = new SwXAutoStyles(*pDocShell); 1355 } 1356 return mxXAutoStyles; 1357 1358 } 1359 1360 Reference< drawing::XDrawPage > SwXTextDocument::getDrawPage() 1361 { 1362 SolarMutexGuard aGuard; 1363 if(!IsValid()) 1364 throw DisposedException("", static_cast< XTextDocument* >(this)); 1365 if(!mxXDrawPage.is()) 1366 { 1367 pDrawPage = new SwXDrawPage(pDocShell->GetDoc()); 1368 mxXDrawPage = pDrawPage; 1369 // Create a Reference to trigger the complete initialization of the 1370 // object. Otherwise in some corner cases it would get initialized 1371 // at ::InitNewDoc -> which would get called during 1372 // close() or dispose() -> n#681746 1373 uno::Reference<lang::XComponent> xComp( mxXDrawPage, uno::UNO_QUERY ); 1374 } 1375 return mxXDrawPage; 1376 } 1377 1378 class SwDrawPagesObj : public cppu::WeakImplHelper< 1379 css::drawing::XDrawPages, 1380 css::lang::XServiceInfo> 1381 { 1382 private: 1383 css::uno::Reference< css::drawing::XDrawPageSupplier > m_xDoc; 1384 public: 1385 SwDrawPagesObj(const css::uno::Reference< css::drawing::XDrawPageSupplier >& rxDoc) : m_xDoc(rxDoc) {} 1386 1387 // XDrawPages 1388 virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL 1389 insertNewByIndex(sal_Int32 /*nIndex*/) override { throw css::lang::NoSupportException(); } 1390 1391 virtual void SAL_CALL remove(const css::uno::Reference< css::drawing::XDrawPage >& /*xPage*/) override 1392 { 1393 throw css::lang::NoSupportException(); 1394 } 1395 1396 // XIndexAccess 1397 virtual sal_Int32 SAL_CALL getCount() override { return 1; } 1398 1399 virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override 1400 { 1401 if (Index != 0) 1402 throw css::lang::IndexOutOfBoundsException("Writer documents have only one DrawPage!"); 1403 return css::uno::Any(m_xDoc->getDrawPage()); 1404 } 1405 1406 // XElementAccess 1407 virtual css::uno::Type SAL_CALL getElementType() override 1408 { 1409 SolarMutexGuard aGuard; 1410 return cppu::UnoType<drawing::XDrawPage>::get(); 1411 } 1412 1413 virtual sal_Bool SAL_CALL hasElements() override { return true; } 1414 1415 // XServiceInfo 1416 virtual OUString SAL_CALL getImplementationName() override 1417 { 1418 return OUString("SwDrawPagesObj"); 1419 } 1420 1421 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override 1422 { 1423 return cppu::supportsService(this, ServiceName); 1424 } 1425 1426 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override 1427 { 1428 return { "com.sun.star.drawing.DrawPages" }; 1429 } 1430 }; 1431 1432 // XDrawPagesSupplier 1433 1434 uno::Reference<drawing::XDrawPages> SAL_CALL SwXTextDocument::getDrawPages() 1435 { 1436 SolarMutexGuard aGuard; 1437 return new SwDrawPagesObj(this); 1438 } 1439 1440 void SwXTextDocument::Invalidate() 1441 { 1442 bObjectValid = false; 1443 if(xNumFormatAgg.is()) 1444 { 1445 const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get(); 1446 Any aNumTunnel = xNumFormatAgg->queryAggregation(rTunnelType); 1447 SvNumberFormatsSupplierObj* pNumFormat = nullptr; 1448 Reference< XUnoTunnel > xNumTunnel; 1449 if(aNumTunnel >>= xNumTunnel) 1450 { 1451 pNumFormat = reinterpret_cast<SvNumberFormatsSupplierObj*>( 1452 xNumTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId())); 1453 pNumFormat->SetNumberFormatter(nullptr); 1454 } 1455 OSL_ENSURE(pNumFormat, "No number formatter available"); 1456 } 1457 InitNewDoc(); 1458 pDocShell = nullptr; 1459 lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this)); 1460 m_pImpl->m_RefreshListeners.disposeAndClear(ev); 1461 } 1462 1463 void SwXTextDocument::Reactivate(SwDocShell* pNewDocShell) 1464 { 1465 if(pDocShell && pDocShell != pNewDocShell) 1466 Invalidate(); 1467 pDocShell = pNewDocShell; 1468 bObjectValid = true; 1469 } 1470 1471 void SwXTextDocument::InitNewDoc() 1472 { 1473 // first invalidate all collections, then delete references and Set to zero 1474 if(mxXTextTables.is()) 1475 { 1476 XNameAccess* pTables = mxXTextTables.get(); 1477 static_cast<SwXTextTables*>(pTables)->Invalidate(); 1478 mxXTextTables.clear(); 1479 } 1480 1481 if(mxXTextFrames.is()) 1482 { 1483 XNameAccess* pFrames = mxXTextFrames.get(); 1484 static_cast<SwXTextFrames*>(pFrames)->Invalidate(); 1485 mxXTextFrames.clear(); 1486 } 1487 1488 if(mxXGraphicObjects.is()) 1489 { 1490 XNameAccess* pFrames = mxXGraphicObjects.get(); 1491 static_cast<SwXTextGraphicObjects*>(pFrames)->Invalidate(); 1492 mxXGraphicObjects.clear(); 1493 } 1494 1495 if(mxXEmbeddedObjects.is()) 1496 { 1497 XNameAccess* pOLE = mxXEmbeddedObjects.get(); 1498 static_cast<SwXTextEmbeddedObjects*>(pOLE)->Invalidate(); 1499 mxXEmbeddedObjects.clear(); 1500 } 1501 1502 if(xBodyText.is()) 1503 { 1504 xBodyText = nullptr; 1505 pBodyText = nullptr; 1506 } 1507 1508 if(xNumFormatAgg.is()) 1509 { 1510 const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get(); 1511 Any aNumTunnel = xNumFormatAgg->queryAggregation(rTunnelType); 1512 SvNumberFormatsSupplierObj* pNumFormat = nullptr; 1513 Reference< XUnoTunnel > xNumTunnel; 1514 if(aNumTunnel >>= xNumTunnel) 1515 { 1516 pNumFormat = reinterpret_cast<SvNumberFormatsSupplierObj*>( 1517 xNumTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId())); 1518 1519 } 1520 OSL_ENSURE(pNumFormat, "No number formatter available"); 1521 if (pNumFormat) 1522 pNumFormat->SetNumberFormatter(nullptr); 1523 } 1524 1525 if(mxXTextFieldTypes.is()) 1526 { 1527 XEnumerationAccess* pT = mxXTextFieldTypes.get(); 1528 static_cast<SwXTextFieldTypes*>(pT)->Invalidate(); 1529 mxXTextFieldTypes.clear(); 1530 } 1531 1532 if(mxXTextFieldMasters.is()) 1533 { 1534 XNameAccess* pT = mxXTextFieldMasters.get(); 1535 static_cast<SwXTextFieldMasters*>(pT)->Invalidate(); 1536 mxXTextFieldMasters.clear(); 1537 } 1538 1539 if(mxXTextSections.is()) 1540 { 1541 XNameAccess* pSect = mxXTextSections.get(); 1542 static_cast<SwXTextSections*>(pSect)->Invalidate(); 1543 mxXTextSections.clear(); 1544 } 1545 1546 if(mxXDrawPage.is()) 1547 { 1548 // #i91798#, #i91895# 1549 // dispose XDrawPage here. We are the owner and know that it is no longer in a valid condition. 1550 uno::Reference<lang::XComponent> xComp( mxXDrawPage, uno::UNO_QUERY ); 1551 xComp->dispose(); 1552 pDrawPage->InvalidateSwDoc(); 1553 mxXDrawPage.clear(); 1554 } 1555 1556 if ( mxXNumberingRules.is() ) 1557 { 1558 XIndexAccess* pNum = mxXNumberingRules.get(); 1559 static_cast<SwXNumberingRulesCollection*>(pNum)->Invalidate(); 1560 mxXNumberingRules.clear(); 1561 } 1562 1563 if(mxXFootnotes.is()) 1564 { 1565 XIndexAccess* pFootnote = mxXFootnotes.get(); 1566 static_cast<SwXFootnotes*>(pFootnote)->Invalidate(); 1567 mxXFootnotes.clear(); 1568 } 1569 1570 if(mxXEndnotes.is()) 1571 { 1572 XIndexAccess* pFootnote = mxXEndnotes.get(); 1573 static_cast<SwXFootnotes*>(pFootnote)->Invalidate(); 1574 mxXEndnotes.clear(); 1575 } 1576 1577 if(mxXDocumentIndexes.is()) 1578 { 1579 XIndexAccess* pIdxs = mxXDocumentIndexes.get(); 1580 static_cast<SwXDocumentIndexes*>(pIdxs)->Invalidate(); 1581 mxXDocumentIndexes.clear(); 1582 } 1583 1584 if(mxXStyleFamilies.is()) 1585 { 1586 XNameAccess* pStyles = mxXStyleFamilies.get(); 1587 static_cast<SwXStyleFamilies*>(pStyles)->Invalidate(); 1588 mxXStyleFamilies.clear(); 1589 } 1590 if(mxXAutoStyles.is()) 1591 { 1592 XNameAccess* pStyles = mxXAutoStyles.get(); 1593 static_cast<SwXAutoStyles*>(pStyles)->Invalidate(); 1594 mxXAutoStyles.clear(); 1595 } 1596 1597 if(mxXBookmarks.is()) 1598 { 1599 XNameAccess* pBm = mxXBookmarks.get(); 1600 static_cast<SwXBookmarks*>(pBm)->Invalidate(); 1601 mxXBookmarks.clear(); 1602 } 1603 1604 if(mxXChapterNumbering.is()) 1605 { 1606 XIndexReplace* pCh = mxXChapterNumbering.get(); 1607 static_cast<SwXChapterNumbering*>(pCh)->Invalidate(); 1608 mxXChapterNumbering.clear(); 1609 } 1610 1611 if(mxXFootnoteSettings.is()) 1612 { 1613 XPropertySet* pFntSet = mxXFootnoteSettings.get(); 1614 static_cast<SwXFootnoteProperties*>(pFntSet)->Invalidate(); 1615 mxXFootnoteSettings.clear(); 1616 } 1617 1618 if(mxXEndnoteSettings.is()) 1619 { 1620 XPropertySet* pEndSet = mxXEndnoteSettings.get(); 1621 static_cast<SwXEndnoteProperties*>(pEndSet)->Invalidate(); 1622 mxXEndnoteSettings.clear(); 1623 } 1624 1625 if(mxXLineNumberingProperties.is()) 1626 { 1627 XPropertySet* pLine = mxXLineNumberingProperties.get(); 1628 static_cast<SwXLineNumberingProperties*>(pLine)->Invalidate(); 1629 mxXLineNumberingProperties.clear(); 1630 } 1631 if(mxXReferenceMarks.is()) 1632 { 1633 XNameAccess* pMarks = mxXReferenceMarks.get(); 1634 static_cast<SwXReferenceMarks*>(pMarks)->Invalidate(); 1635 mxXReferenceMarks.clear(); 1636 } 1637 if(mxLinkTargetSupplier.is()) 1638 { 1639 XNameAccess* pAccess = mxLinkTargetSupplier.get(); 1640 static_cast<SwXLinkTargetSupplier*>(pAccess)->Invalidate(); 1641 mxLinkTargetSupplier.clear(); 1642 } 1643 if(mxXRedlines.is()) 1644 { 1645 XEnumerationAccess* pMarks = mxXRedlines.get(); 1646 static_cast<SwXRedlines*>(pMarks)->Invalidate(); 1647 mxXRedlines.clear(); 1648 } 1649 if(mxPropertyHelper.is()) 1650 { 1651 mxPropertyHelper->Invalidate(); 1652 mxPropertyHelper.clear(); 1653 } 1654 } 1655 1656 css::uno::Reference<css::uno::XInterface> SwXTextDocument::create( 1657 OUString const & rServiceName, 1658 css::uno::Sequence<css::uno::Any> const * arguments) 1659 { 1660 SolarMutexGuard aGuard; 1661 if (!IsValid()) 1662 throw DisposedException("", static_cast< XTextDocument* >(this)); 1663 1664 const SwServiceType nType = SwXServiceProvider::GetProviderType(rServiceName); 1665 if (nType != SwServiceType::Invalid) 1666 { 1667 return SwXServiceProvider::MakeInstance(nType, *pDocShell->GetDoc()); 1668 } 1669 if (rServiceName == "com.sun.star.drawing.DashTable") 1670 { 1671 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Dash); 1672 } 1673 if (rServiceName == "com.sun.star.drawing.GradientTable") 1674 { 1675 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Gradient); 1676 } 1677 if (rServiceName == "com.sun.star.drawing.HatchTable") 1678 { 1679 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Hatch); 1680 } 1681 if (rServiceName == "com.sun.star.drawing.BitmapTable") 1682 { 1683 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Bitmap); 1684 } 1685 if (rServiceName == "com.sun.star.drawing.TransparencyGradientTable") 1686 { 1687 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::TransGradient); 1688 } 1689 if (rServiceName == "com.sun.star.drawing.MarkerTable") 1690 { 1691 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Marker); 1692 } 1693 if (rServiceName == "com.sun.star.drawing.Defaults") 1694 { 1695 return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Defaults); 1696 } 1697 if (rServiceName == "com.sun.star.document.Settings") 1698 { 1699 return Reference<XInterface>(*new SwXDocumentSettings(this)); 1700 } 1701 if (rServiceName == "com.sun.star.document.ImportEmbeddedObjectResolver") 1702 { 1703 return static_cast<cppu::OWeakObject *>( 1704 new SvXMLEmbeddedObjectHelper( 1705 *pDocShell, SvXMLEmbeddedObjectHelperMode::Read)); 1706 } 1707 if (rServiceName == "com.sun.star.text.DocumentSettings") 1708 { 1709 return Reference<XInterface>(*new SwXDocumentSettings(this)); 1710 } 1711 if (rServiceName == "com.sun.star.chart2.data.DataProvider") 1712 { 1713 return Reference<XInterface>( 1714 dynamic_cast<chart2::data::XDataProvider *>( 1715 pDocShell->getIDocumentChartDataProviderAccess(). 1716 GetChartDataProvider())); 1717 } 1718 if (!rServiceName.startsWith("com.sun.star.") 1719 || rServiceName.endsWith(".OLE2Shape")) 1720 { 1721 // We do not want to insert OLE2 Shapes (e.g., 1722 // "com.sun.star.drawing.OLE2Shape", ...) like this (by creating them 1723 // with the documents factory and adding the shapes to the draw page); 1724 // for inserting OLE objects the proper way is to use 1725 // "com.sun.star.text.TextEmbeddedObject": 1726 throw ServiceNotRegisteredException(); 1727 } 1728 // The XML import is allowed to create instances of 1729 // "com.sun.star.drawing.OLE2Shape"; thus, a temporary service name is 1730 // introduced to make this possible: 1731 OUString aTmpServiceName(rServiceName); 1732 if (rServiceName == "com.sun.star.drawing.temporaryForXMLImportOLE2Shape") 1733 { 1734 aTmpServiceName = "com.sun.star.drawing.OLE2Shape"; 1735 } 1736 Reference<XInterface> xTmp( 1737 arguments == nullptr 1738 ? SvxFmMSFactory::createInstance(aTmpServiceName) 1739 : SvxFmMSFactory::createInstanceWithArguments( 1740 aTmpServiceName, *arguments)); 1741 if (rServiceName == "com.sun.star.drawing.GroupShape" 1742 || rServiceName == "com.sun.star.drawing.Shape3DSceneObject") 1743 { 1744 return *new SwXGroupShape(xTmp, pDocShell->GetDoc()); 1745 } 1746 if (rServiceName.startsWith("com.sun.star.drawing.")) 1747 { 1748 return *new SwXShape(xTmp, pDocShell->GetDoc()); 1749 } 1750 return xTmp; 1751 } 1752 1753 Reference< XInterface > SwXTextDocument::createInstance(const OUString& rServiceName) 1754 { 1755 return create(rServiceName, nullptr); 1756 } 1757 1758 Reference< XInterface > SwXTextDocument::createInstanceWithArguments( 1759 const OUString& ServiceSpecifier, 1760 const Sequence< Any >& Arguments) 1761 { 1762 return create(ServiceSpecifier, &Arguments); 1763 } 1764 1765 Sequence< OUString > SwXTextDocument::getAvailableServiceNames() 1766 { 1767 static Sequence< OUString > aServices; 1768 if ( !aServices.hasElements() ) 1769 { 1770 Sequence< OUString > aRet = SvxFmMSFactory::getAvailableServiceNames(); 1771 OUString* pRet = aRet.getArray(); 1772 for ( sal_Int32 i = 0; i < aRet.getLength(); ++i ) 1773 { 1774 if ( pRet[i] == "com.sun.star.drawing.OLE2Shape" ) 1775 { 1776 pRet[i] = pRet[aRet.getLength() - 1]; 1777 aRet.realloc( aRet.getLength() - 1 ); // <pRet> no longer valid. 1778 break; 1779 } 1780 } 1781 Sequence< OUString > aOwn = SwXServiceProvider::GetAllServiceNames(); 1782 aServices = SvxFmMSFactory::concatServiceNames(aRet, aOwn); 1783 } 1784 1785 return aServices; 1786 } 1787 1788 OUString SwXTextDocument::getImplementationName() 1789 { 1790 return OUString("SwXTextDocument"); 1791 /* // Matching the .component information: 1792 return dynamic_cast<SwGlobalDocShell*>( pDocShell ) != nullptr 1793 ? OUString("com.sun.star.comp.Writer.GlobalDocument") 1794 : dynamic_cast<SwWebDocShell*>( pDocShell ) != nullptr 1795 ? OUString("com.sun.star.comp.Writer.WebDocument") 1796 : OUString("com.sun.star.comp.Writer.TextDocument"); 1797 */ 1798 } 1799 1800 sal_Bool SwXTextDocument::supportsService(const OUString& rServiceName) 1801 { 1802 return cppu::supportsService(this, rServiceName); 1803 } 1804 1805 Sequence< OUString > SwXTextDocument::getSupportedServiceNames() 1806 { 1807 bool bWebDoc = (dynamic_cast<SwWebDocShell*>( pDocShell) != nullptr ); 1808 bool bGlobalDoc = (dynamic_cast<SwGlobalDocShell*>( pDocShell) != nullptr ); 1809 bool bTextDoc = (!bWebDoc && !bGlobalDoc); 1810 1811 Sequence< OUString > aRet (3); 1812 OUString* pArray = aRet.getArray(); 1813 1814 pArray[0] = "com.sun.star.document.OfficeDocument"; 1815 pArray[1] = "com.sun.star.text.GenericTextDocument"; 1816 1817 if (bTextDoc) 1818 pArray[2] = "com.sun.star.text.TextDocument"; 1819 else if (bWebDoc) 1820 pArray[2] = "com.sun.star.text.WebDocument"; 1821 else if (bGlobalDoc) 1822 pArray[2] = "com.sun.star.text.GlobalDocument"; 1823 1824 return aRet; 1825 } 1826 1827 Reference< XIndexAccess > SwXTextDocument::getDocumentIndexes() 1828 { 1829 SolarMutexGuard aGuard; 1830 if(!IsValid()) 1831 throw DisposedException("", static_cast< XTextDocument* >(this)); 1832 1833 if(!mxXDocumentIndexes.is()) 1834 { 1835 mxXDocumentIndexes = new SwXDocumentIndexes(pDocShell->GetDoc()); 1836 } 1837 return mxXDocumentIndexes; 1838 } 1839 1840 Reference< XPropertySetInfo > SwXTextDocument::getPropertySetInfo() 1841 { 1842 static Reference< XPropertySetInfo > xRet = pPropSet->getPropertySetInfo(); 1843 return xRet; 1844 } 1845 1846 void SwXTextDocument::setPropertyValue(const OUString& rPropertyName, const Any& aValue) 1847 { 1848 SolarMutexGuard aGuard; 1849 if(!IsValid()) 1850 throw DisposedException("", static_cast< XTextDocument* >(this)); 1851 1852 const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); 1853 1854 if(!pEntry) 1855 throw UnknownPropertyException(); 1856 if(pEntry->nFlags & PropertyAttribute::READONLY) 1857 throw PropertyVetoException(); 1858 switch(pEntry->nWID) 1859 { 1860 case WID_DOC_CHAR_COUNT : 1861 case WID_DOC_PARA_COUNT : 1862 case WID_DOC_WORD_COUNT : 1863 throw RuntimeException( 1864 "bad WID", 1865 static_cast< cppu::OWeakObject * >( 1866 static_cast< SwXTextDocumentBaseClass * >(this))); 1867 case WID_DOC_WORD_SEPARATOR : 1868 { 1869 OUString sDelim; 1870 aValue >>= sDelim; 1871 SW_MOD()->GetModuleConfig()->SetWordDelimiter(sDelim); 1872 } 1873 break; 1874 case WID_DOC_CHANGES_RECORD: 1875 case WID_DOC_CHANGES_SHOW: 1876 { 1877 bool bSet = *o3tl::doAccess<bool>(aValue); 1878 RedlineFlags eMode = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags(); 1879 if(WID_DOC_CHANGES_SHOW == pEntry->nWID) 1880 { 1881 eMode |= RedlineFlags(RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); 1882 if( !bSet ) 1883 pDocShell->GetDoc()->GetDocumentRedlineManager().SetHideRedlines(true); 1884 } 1885 else if(WID_DOC_CHANGES_RECORD == pEntry->nWID) 1886 { 1887 eMode = bSet ? eMode|RedlineFlags::On : eMode&~RedlineFlags::On; 1888 } 1889 pDocShell->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eMode ); 1890 } 1891 break; 1892 case WID_DOC_CHANGES_PASSWORD: 1893 { 1894 Sequence <sal_Int8> aNew; 1895 if(aValue >>= aNew) 1896 { 1897 SwDoc* pDoc = pDocShell->GetDoc(); 1898 pDoc->getIDocumentRedlineAccess().SetRedlinePassword(aNew); 1899 if(aNew.hasElements()) 1900 { 1901 RedlineFlags eMode = pDoc->getIDocumentRedlineAccess().GetRedlineFlags(); 1902 eMode |= RedlineFlags::On; 1903 pDoc->getIDocumentRedlineAccess().SetRedlineFlags( eMode ); 1904 } 1905 } 1906 } 1907 break; 1908 case WID_DOC_AUTO_MARK_URL : 1909 { 1910 OUString sURL; 1911 aValue >>= sURL; 1912 pDocShell->GetDoc()->SetTOIAutoMarkURL(sURL); 1913 } 1914 break; 1915 case WID_DOC_HIDE_TIPS : 1916 SW_MOD()->GetModuleConfig()->SetHideFieldTips(*o3tl::doAccess<bool>(aValue)); 1917 break; 1918 case WID_DOC_REDLINE_DISPLAY: 1919 { 1920 RedlineFlags eRedMode = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags(); 1921 eRedMode = eRedMode & (~RedlineFlags::ShowMask); 1922 sal_Int16 nSet = 0; 1923 aValue >>= nSet; 1924 switch(nSet) 1925 { 1926 case RedlineDisplayType::NONE: break; 1927 case RedlineDisplayType::INSERTED: eRedMode |= RedlineFlags::ShowInsert; break; 1928 case RedlineDisplayType::REMOVED: eRedMode |= RedlineFlags::ShowDelete; break; 1929 case RedlineDisplayType:: 1930 INSERTED_AND_REMOVED: eRedMode |= RedlineFlags::ShowInsert|RedlineFlags::ShowDelete; 1931 break; 1932 default: throw IllegalArgumentException(); 1933 } 1934 pDocShell->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags(eRedMode); 1935 } 1936 break; 1937 case WID_DOC_TWO_DIGIT_YEAR: 1938 { 1939 sal_Int16 nYear = 0; 1940 aValue >>= nYear; 1941 SfxRequest aRequest ( SID_ATTR_YEAR2000, SfxCallMode::SLOT, pDocShell->GetDoc()->GetAttrPool()); 1942 aRequest.AppendItem(SfxUInt16Item( SID_ATTR_YEAR2000, static_cast < sal_uInt16 > ( nYear ) ) ); 1943 pDocShell->Execute ( aRequest ); 1944 } 1945 break; 1946 case WID_DOC_AUTOMATIC_CONTROL_FOCUS: 1947 { 1948 SwDrawModel * pDrawDoc; 1949 bool bAuto = *o3tl::doAccess<bool>(aValue); 1950 1951 if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) 1952 pDrawDoc->SetAutoControlFocus( bAuto ); 1953 else if (bAuto) 1954 { 1955 // if setting to true, and we don't have an 1956 // SdrModel, then we are changing the default and 1957 // must thus create an SdrModel, if we don't have an 1958 // SdrModel and we are leaving the default at false, 1959 // we don't need to make an SdrModel and can do nothing 1960 // #i52858# - method name changed 1961 pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); 1962 pDrawDoc->SetAutoControlFocus ( bAuto ); 1963 } 1964 } 1965 break; 1966 case WID_DOC_APPLY_FORM_DESIGN_MODE: 1967 { 1968 SwDrawModel * pDrawDoc; 1969 bool bMode = *o3tl::doAccess<bool>(aValue); 1970 1971 if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) 1972 pDrawDoc->SetOpenInDesignMode( bMode ); 1973 else if (!bMode) 1974 { 1975 // if setting to false, and we don't have an 1976 // SdrModel, then we are changing the default and 1977 // must thus create an SdrModel, if we don't have an 1978 // SdrModel and we are leaving the default at true, 1979 // we don't need to make an SdrModel and can do 1980 // nothing 1981 // #i52858# - method name changed 1982 pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); 1983 pDrawDoc->SetOpenInDesignMode ( bMode ); 1984 } 1985 } 1986 break; 1987 // #i42634# New property to set the bInReading 1988 // flag at the document, used during binary import 1989 case WID_DOC_LOCK_UPDATES : 1990 { 1991 SwDoc* pDoc = pDocShell->GetDoc(); 1992 bool bBool (false); 1993 if( aValue >>= bBool ) 1994 pDoc->SetInReading( bBool ); 1995 } 1996 break; 1997 case WID_DOC_BUILDID: 1998 aValue >>= maBuildId; 1999 break; 2000 2001 case WID_DOC_DEFAULT_PAGE_MODE: 2002 { 2003 bool bDefaultPageMode( false ); 2004 aValue >>= bDefaultPageMode; 2005 pDocShell->GetDoc()->SetDefaultPageMode( bDefaultPageMode ); 2006 } 2007 break; 2008 case WID_DOC_INTEROP_GRAB_BAG: 2009 setGrabBagItem(aValue); 2010 break; 2011 2012 default: 2013 { 2014 const SfxPoolItem& rItem = pDocShell->GetDoc()->GetDefault(pEntry->nWID); 2015 std::unique_ptr<SfxPoolItem> pNewItem(rItem.Clone()); 2016 pNewItem->PutValue(aValue, pEntry->nMemberId); 2017 pDocShell->GetDoc()->SetDefault(*pNewItem); 2018 } 2019 } 2020 } 2021 2022 Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName) 2023 { 2024 SolarMutexGuard aGuard; 2025 if(!IsValid()) 2026 throw DisposedException("", static_cast< XTextDocument* >(this)); 2027 2028 const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); 2029 2030 if(!pEntry) 2031 throw UnknownPropertyException(); 2032 Any aAny; 2033 switch(pEntry->nWID) 2034 { 2035 case WID_DOC_ISTEMPLATEID : 2036 aAny <<= pDocShell->IsTemplate(); 2037 break; 2038 case WID_DOC_CHAR_COUNT : 2039 case WID_DOC_PARA_COUNT : 2040 case WID_DOC_WORD_COUNT : 2041 { 2042 const SwDocStat& rStat(pDocShell->GetDoc()->getIDocumentStatistics().GetUpdatedDocStat( false, true )); 2043 sal_Int32 nValue; 2044 switch(pEntry->nWID) 2045 { 2046 case WID_DOC_CHAR_COUNT :nValue = rStat.nChar;break; 2047 case WID_DOC_PARA_COUNT :nValue = rStat.nPara;break; 2048 case WID_DOC_WORD_COUNT :nValue = rStat.nWord;break; 2049 } 2050 aAny <<= nValue; 2051 } 2052 break; 2053 case WID_DOC_WORD_SEPARATOR : 2054 { 2055 aAny <<= SW_MOD()->GetDocStatWordDelim(); 2056 } 2057 break; 2058 case WID_DOC_CHANGES_RECORD: 2059 case WID_DOC_CHANGES_SHOW: 2060 { 2061 const RedlineFlags eMode = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags(); 2062 bool bSet = false; 2063 if(WID_DOC_CHANGES_SHOW == pEntry->nWID) 2064 { 2065 bSet = IDocumentRedlineAccess::IsShowChanges(eMode); 2066 } 2067 else if(WID_DOC_CHANGES_RECORD == pEntry->nWID) 2068 { 2069 bSet = bool(eMode & RedlineFlags::On); 2070 } 2071 aAny <<= bSet; 2072 } 2073 break; 2074 case WID_DOC_CHANGES_PASSWORD: 2075 { 2076 SwDoc* pDoc = pDocShell->GetDoc(); 2077 aAny <<= pDoc->getIDocumentRedlineAccess().GetRedlinePassword(); 2078 } 2079 break; 2080 case WID_DOC_AUTO_MARK_URL : 2081 aAny <<= pDocShell->GetDoc()->GetTOIAutoMarkURL(); 2082 break; 2083 case WID_DOC_HIDE_TIPS : 2084 aAny <<= SW_MOD()->GetModuleConfig()->IsHideFieldTips(); 2085 break; 2086 case WID_DOC_REDLINE_DISPLAY: 2087 { 2088 RedlineFlags eRedMode = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags(); 2089 eRedMode = eRedMode & RedlineFlags::ShowMask; 2090 sal_Int16 nRet = RedlineDisplayType::NONE; 2091 if(RedlineFlags::ShowInsert == eRedMode) 2092 nRet = RedlineDisplayType::INSERTED; 2093 else if(RedlineFlags::ShowDelete == eRedMode) 2094 nRet = RedlineDisplayType::REMOVED; 2095 else if(RedlineFlags::ShowMask == eRedMode) 2096 nRet = RedlineDisplayType::INSERTED_AND_REMOVED; 2097 aAny <<= nRet; 2098 } 2099 break; 2100 case WID_DOC_FORBIDDEN_CHARS: 2101 { 2102 GetPropertyHelper(); 2103 Reference<XForbiddenCharacters> xRet(static_cast<cppu::OWeakObject*>(mxPropertyHelper.get()), UNO_QUERY); 2104 aAny <<= xRet; 2105 } 2106 break; 2107 case WID_DOC_TWO_DIGIT_YEAR: 2108 { 2109 aAny <<= static_cast < sal_Int16 > (pDocShell->GetDoc()->GetNumberFormatter ()->GetYear2000()); 2110 } 2111 break; 2112 case WID_DOC_AUTOMATIC_CONTROL_FOCUS: 2113 { 2114 SwDrawModel * pDrawDoc; 2115 bool bAuto; 2116 if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) 2117 bAuto = pDrawDoc->GetAutoControlFocus(); 2118 else 2119 bAuto = false; 2120 aAny <<= bAuto; 2121 } 2122 break; 2123 case WID_DOC_APPLY_FORM_DESIGN_MODE: 2124 { 2125 SwDrawModel * pDrawDoc; 2126 bool bMode; 2127 if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) 2128 bMode = pDrawDoc->GetOpenInDesignMode(); 2129 else 2130 bMode = true; 2131 aAny <<= bMode; 2132 } 2133 break; 2134 case WID_DOC_BASIC_LIBRARIES: 2135 aAny <<= pDocShell->GetBasicContainer(); 2136 break; 2137 case WID_DOC_DIALOG_LIBRARIES: 2138 aAny <<= pDocShell->GetDialogContainer(); 2139 break; 2140 case WID_DOC_VBA_DOCOBJ: 2141 { 2142 /* #i111553# This property provides the name of the constant that 2143 will be used to store this model in the global Basic manager. 2144 That constant will be equivalent to 'ThisComponent' but for 2145 each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc' 2146 constant can co-exist, as required by VBA. */ 2147 aAny <<= OUString( "ThisWordDoc" ); 2148 } 2149 break; 2150 case WID_DOC_RUNTIME_UID: 2151 aAny <<= getRuntimeUID(); 2152 break; 2153 case WID_DOC_LOCK_UPDATES : 2154 aAny <<= pDocShell->GetDoc()->IsInReading(); 2155 break; 2156 case WID_DOC_BUILDID: 2157 aAny <<= maBuildId; 2158 break; 2159 case WID_DOC_HAS_VALID_SIGNATURES: 2160 aAny <<= hasValidSignatures(); 2161 break; 2162 case WID_DOC_INTEROP_GRAB_BAG: 2163 getGrabBagItem(aAny); 2164 break; 2165 2166 default: 2167 { 2168 const SfxPoolItem& rItem = pDocShell->GetDoc()->GetDefault(pEntry->nWID); 2169 rItem.QueryValue(aAny, pEntry->nMemberId); 2170 } 2171 } 2172 return aAny; 2173 } 2174 2175 void SwXTextDocument::addPropertyChangeListener(const OUString& /*PropertyName*/, 2176 const Reference< XPropertyChangeListener > & /*aListener*/) 2177 { 2178 OSL_FAIL("not implemented"); 2179 } 2180 2181 void SwXTextDocument::removePropertyChangeListener(const OUString& /*PropertyName*/, 2182 const Reference< XPropertyChangeListener > & /*aListener*/) 2183 { 2184 OSL_FAIL("not implemented"); 2185 } 2186 2187 void SwXTextDocument::addVetoableChangeListener(const OUString& /*PropertyName*/, 2188 const Reference< XVetoableChangeListener > & /*aListener*/) 2189 { 2190 OSL_FAIL("not implemented"); 2191 } 2192 2193 void SwXTextDocument::removeVetoableChangeListener(const OUString& /*PropertyName*/, 2194 const Reference< XVetoableChangeListener > & /*aListener*/) 2195 { 2196 OSL_FAIL("not implemented"); 2197 } 2198 2199 Reference< XNameAccess > SwXTextDocument::getLinks() 2200 { 2201 if(!mxLinkTargetSupplier.is()) 2202 { 2203 mxLinkTargetSupplier = new SwXLinkTargetSupplier(*this); 2204 } 2205 return mxLinkTargetSupplier; 2206 } 2207 2208 Reference< XEnumerationAccess > SwXTextDocument::getRedlines( ) 2209 { 2210 if(!mxXRedlines.is()) 2211 { 2212 mxXRedlines = new SwXRedlines(pDocShell->GetDoc()); 2213 } 2214 return mxXRedlines; 2215 } 2216 2217 void SwXTextDocument::NotifyRefreshListeners() 2218 { 2219 // why does SwBaseShell not just call refresh? maybe because it's rSh is 2220 // (sometimes) a different shell than GetWrtShell()? 2221 lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this)); 2222 m_pImpl->m_RefreshListeners.notifyEach( 2223 & util::XRefreshListener::refreshed, ev); 2224 } 2225 2226 void SwXTextDocument::refresh() 2227 { 2228 SolarMutexGuard aGuard; 2229 if(!IsValid()) 2230 throw DisposedException("", static_cast< XTextDocument* >(this)); 2231 2232 SwViewShell *pViewShell = pDocShell->GetWrtShell(); 2233 NotifyRefreshListeners(); 2234 if(pViewShell) 2235 pViewShell->CalcLayout(); 2236 } 2237 2238 void SAL_CALL SwXTextDocument::addRefreshListener( 2239 const Reference<util::XRefreshListener> & xListener) 2240 { 2241 // no need to lock here as m_pImpl is const and container threadsafe 2242 m_pImpl->m_RefreshListeners.addInterface(xListener); 2243 } 2244 2245 void SAL_CALL SwXTextDocument::removeRefreshListener( 2246 const Reference<util::XRefreshListener> & xListener) 2247 { 2248 // no need to lock here as m_pImpl is const and container threadsafe 2249 m_pImpl->m_RefreshListeners.removeInterface(xListener); 2250 } 2251 2252 void SwXTextDocument::updateLinks( ) 2253 { 2254 SolarMutexGuard aGuard; 2255 if(!IsValid()) 2256 throw DisposedException("", static_cast< XTextDocument* >(this)); 2257 2258 SwDoc* pDoc = pDocShell->GetDoc(); 2259 sfx2::LinkManager& rLnkMan = pDoc->getIDocumentLinksAdministration().GetLinkManager(); 2260 if( !rLnkMan.GetLinks().empty() ) 2261 { 2262 UnoActionContext aAction(pDoc); 2263 rLnkMan.UpdateAllLinks( false, true, nullptr ); 2264 } 2265 } 2266 2267 //XPropertyState 2268 PropertyState SAL_CALL SwXTextDocument::getPropertyState( const OUString& rPropertyName ) 2269 { 2270 SolarMutexGuard aGuard; 2271 if(!IsValid()) 2272 throw DisposedException("", static_cast< XTextDocument* >(this)); 2273 2274 const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); 2275 if(!pEntry) 2276 throw UnknownPropertyException(); 2277 return PropertyState_DIRECT_VALUE; 2278 } 2279 2280 Sequence< PropertyState > SAL_CALL SwXTextDocument::getPropertyStates( const Sequence< OUString >& rPropertyNames ) 2281 { 2282 const sal_Int32 nCount = rPropertyNames.getLength(); 2283 const OUString * pNames = rPropertyNames.getConstArray(); 2284 Sequence < PropertyState > aRet ( nCount ); 2285 PropertyState *pState = aRet.getArray(); 2286 2287 for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++) 2288 pState[nIndex] = getPropertyState( pNames[nIndex] ); 2289 2290 return aRet; 2291 } 2292 2293 void SAL_CALL SwXTextDocument::setPropertyToDefault( const OUString& rPropertyName ) 2294 { 2295 SolarMutexGuard aGuard; 2296 if(!IsValid()) 2297 throw DisposedException("", static_cast< XTextDocument* >(this)); 2298 2299 const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); 2300 if(!pEntry) 2301 throw UnknownPropertyException(); 2302 switch(pEntry->nWID) 2303 { 2304 case 0:default:break; 2305 } 2306 } 2307 2308 Any SAL_CALL SwXTextDocument::getPropertyDefault( const OUString& rPropertyName ) 2309 { 2310 SolarMutexGuard aGuard; 2311 if(!IsValid()) 2312 throw DisposedException("", static_cast< XTextDocument* >(this)); 2313 2314 const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); 2315 if(!pEntry) 2316 throw UnknownPropertyException(); 2317 Any aAny; 2318 switch(pEntry->nWID) 2319 { 2320 case 0:default:break; 2321 } 2322 return aAny; 2323 } 2324 2325 static VclPtr< OutputDevice > lcl_GetOutputDevice( const SwPrintUIOptions &rPrintUIOptions ) 2326 { 2327 VclPtr< OutputDevice > pOut; 2328 2329 uno::Any aAny( rPrintUIOptions.getValue( "RenderDevice" )); 2330 uno::Reference< awt::XDevice > xRenderDevice; 2331 aAny >>= xRenderDevice; 2332 if (xRenderDevice.is()) 2333 { 2334 VCLXDevice* pDevice = VCLXDevice::getImplementation( xRenderDevice ); 2335 pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >(); 2336 } 2337 2338 return pOut; 2339 } 2340 2341 static bool lcl_SeqHasProperty( 2342 const uno::Sequence< beans::PropertyValue >& rOptions, 2343 const sal_Char *pPropName ) 2344 { 2345 bool bRes = false; 2346 const sal_Int32 nLen = rOptions.getLength(); 2347 const beans::PropertyValue *pProps = rOptions.getConstArray(); 2348 for (sal_Int32 i = 0; i < nLen && !bRes; ++i) 2349 { 2350 if (pProps[i].Name.equalsAscii( pPropName )) 2351 bRes = true; 2352 } 2353 return bRes; 2354 } 2355 2356 static bool lcl_GetBoolProperty( 2357 const uno::Sequence< beans::PropertyValue >& rOptions, 2358 const sal_Char *pPropName ) 2359 { 2360 bool bRes = false; 2361 const sal_Int32 nLen = rOptions.getLength(); 2362 const beans::PropertyValue *pProps = rOptions.getConstArray(); 2363 for ( sal_Int32 i = 0; i < nLen; ++i ) 2364 { 2365 if ( pProps[i].Name.equalsAscii( pPropName ) ) 2366 { 2367 pProps[i].Value >>= bRes; 2368 break; 2369 } 2370 } 2371 return bRes; 2372 } 2373 2374 SfxViewShell * SwXTextDocument::GetRenderView( 2375 bool &rbIsSwSrcView, 2376 const uno::Sequence< beans::PropertyValue >& rOptions, 2377 bool bIsPDFExport ) 2378 { 2379 // get view shell to use 2380 SfxViewShell *pView = nullptr; 2381 if (bIsPDFExport) 2382 pView = GuessViewShell( rbIsSwSrcView ); 2383 else 2384 { 2385 uno::Any aTmp; 2386 const sal_Int32 nLen = rOptions.getLength(); 2387 const beans::PropertyValue *pProps = rOptions.getConstArray(); 2388 for (sal_Int32 i = 0; i < nLen; ++i) 2389 { 2390 if ( pProps[i].Name == "View" ) 2391 { 2392 aTmp = pProps[i].Value; 2393 break; 2394 } 2395 } 2396 2397 uno::Reference< frame::XController > xController; 2398 if (aTmp >>= xController) 2399 { 2400 OSL_ENSURE( xController.is(), "controller is empty!" ); 2401 pView = GuessViewShell( rbIsSwSrcView, xController ); 2402 } 2403 } 2404 return pView; 2405 } 2406 2407 /* 2408 * GetRenderDoc: 2409 * returns the document to be rendered, usually this will be the 'regular' 2410 * document but in case of PDF export of (multi-)selection it will 2411 * be a temporary document that gets created if not already done. 2412 * The rpView variable will be set (if not already done) to the used 2413 * SfxViewShell. 2414 */ 2415 SwDoc * SwXTextDocument::GetRenderDoc( 2416 SfxViewShell *&rpView, 2417 const uno::Any& rSelection, 2418 bool bIsPDFExport ) 2419 { 2420 SwDoc *pDoc = nullptr; 2421 2422 uno::Reference< frame::XModel > xModel; 2423 rSelection >>= xModel; 2424 if (xModel == pDocShell->GetModel()) 2425 pDoc = pDocShell->GetDoc(); 2426 else 2427 { 2428 OSL_ENSURE( !xModel.is(), "unexpected model found" ); 2429 2430 if (rSelection.hasValue()) // is anything selected ? 2431 { 2432 // this part should only be called when a temporary document needs to be created, 2433 // for example for PDF export or printing of (multi-)selection only. 2434 2435 if (!rpView) 2436 { 2437 bool bIsSwSrcView = false; 2438 // aside from maybe PDF export the view should always have been provided! 2439 OSL_ENSURE( bIsPDFExport, "view is missing, guessing one..." ); 2440 2441 rpView = GuessViewShell( bIsSwSrcView ); 2442 } 2443 OSL_ENSURE( rpView, "SwViewShell missing" ); 2444 // the view shell should be SwView for documents PDF export. 2445 // for the page preview no selection should be possible 2446 // (the export dialog does not allow for this option) 2447 if (auto pSwView = dynamic_cast<SwView *>( rpView )) 2448 { 2449 if (!m_pRenderData) 2450 { 2451 OSL_FAIL("GetRenderDoc: no renderdata"); 2452 return nullptr; 2453 } 2454 SfxObjectShellLock xDocSh(m_pRenderData->GetTempDocShell()); 2455 if (!xDocSh.Is()) 2456 { 2457 xDocSh = pSwView->CreateTmpSelectionDoc(); 2458 m_pRenderData->SetTempDocShell(xDocSh); 2459 } 2460 if (xDocSh.Is()) 2461 { 2462 pDoc = static_cast<SwDocShell*>(&xDocSh)->GetDoc(); 2463 rpView = pDoc->GetDocShell()->GetView(); 2464 } 2465 } 2466 else 2467 { 2468 OSL_FAIL("unexpected SwViewShell" ); 2469 } 2470 } 2471 } 2472 return pDoc; 2473 } 2474 2475 static void lcl_SavePrintUIOptionsToDocumentPrintData( 2476 SwDoc &rDoc, 2477 const SwPrintUIOptions &rPrintUIOptions, 2478 bool bIsPDFEXport ) 2479 { 2480 SwPrintData aDocPrintData( rDoc.getIDocumentDeviceAccess().getPrintData() ); 2481 2482 aDocPrintData.SetPrintGraphic( rPrintUIOptions.IsPrintGraphics() ); 2483 aDocPrintData.SetPrintTable( true ); // for now it was decided that tables should always be printed 2484 aDocPrintData.SetPrintDraw( rPrintUIOptions.IsPrintDrawings() ); 2485 aDocPrintData.SetPrintControl( rPrintUIOptions.IsPrintFormControls() ); 2486 aDocPrintData.SetPrintLeftPage( rPrintUIOptions.IsPrintLeftPages() ); 2487 aDocPrintData.SetPrintRightPage( rPrintUIOptions.IsPrintRightPages() ); 2488 aDocPrintData.SetPrintReverse( false ); /*handled by print dialog now*/ 2489 aDocPrintData.SetPaperFromSetup( rPrintUIOptions.IsPaperFromSetup() ); 2490 aDocPrintData.SetPrintEmptyPages( rPrintUIOptions.IsPrintEmptyPages( bIsPDFEXport ) ); 2491 aDocPrintData.SetPrintPostIts( rPrintUIOptions.GetPrintPostItsType() ); 2492 aDocPrintData.SetPrintProspect( rPrintUIOptions.IsPrintProspect() ); 2493 aDocPrintData.SetPrintProspect_RTL( rPrintUIOptions.IsPrintProspectRTL() ); 2494 aDocPrintData.SetPrintPageBackground( rPrintUIOptions.IsPrintPageBackground() ); 2495 aDocPrintData.SetPrintBlackFont( rPrintUIOptions.IsPrintWithBlackTextColor() ); 2496 // aDocPrintData.SetPrintSingleJobs( b ); handled by File/Print dialog itself 2497 // arDocPrintData.SetFaxName( s ); n/a in File/Print dialog 2498 aDocPrintData.SetPrintHiddenText( rPrintUIOptions.IsPrintHiddenText() ); 2499 aDocPrintData.SetPrintTextPlaceholder( rPrintUIOptions.IsPrintTextPlaceholders() ); 2500 2501 rDoc.getIDocumentDeviceAccess().setPrintData( aDocPrintData ); 2502 } 2503 2504 sal_Int32 SAL_CALL SwXTextDocument::getRendererCount( 2505 const uno::Any& rSelection, 2506 const uno::Sequence< beans::PropertyValue >& rxOptions ) 2507 { 2508 SolarMutexGuard aGuard; 2509 if(!IsValid()) 2510 { 2511 throw DisposedException( OUString(), 2512 static_cast< XTextDocument* >(this) ); 2513 } 2514 2515 const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ); 2516 bool bIsSwSrcView = false; 2517 SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport ); 2518 2519 if (!bIsSwSrcView && !m_pRenderData) 2520 m_pRenderData.reset(new SwRenderData); 2521 if (!m_pPrintUIOptions) 2522 m_pPrintUIOptions = lcl_GetPrintUIOptions( pDocShell, pView ); 2523 bool bFormat = m_pPrintUIOptions->processPropertiesAndCheckFormat( rxOptions ); 2524 2525 SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport ); 2526 OSL_ENSURE( pDoc && pView, "doc or view shell missing!" ); 2527 if (!pDoc || !pView) 2528 return 0; 2529 2530 // save current UI options from the print dialog for the next call to that dialog 2531 lcl_SavePrintUIOptionsToDocumentPrintData( *pDoc, *m_pPrintUIOptions, bIsPDFExport ); 2532 2533 sal_Int32 nRet = 0; 2534 if (bIsSwSrcView) 2535 { 2536 SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView); 2537 VclPtr< OutputDevice> pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions ); 2538 nRet = rSwSrcView.PrintSource( pOutDev, 1 /* dummy */, true /* get page count only */ ); 2539 } 2540 else 2541 { 2542 SwDocShell *pRenderDocShell = pDoc->GetDocShell(); 2543 2544 // TODO/mba: we really need a generic way to get the SwViewShell! 2545 SwViewShell* pViewShell = nullptr; 2546 SwView* pSwView = dynamic_cast<SwView*>( pView ); 2547 if ( pSwView ) 2548 { 2549 pViewShell = pSwView->GetWrtShellPtr(); 2550 } 2551 else 2552 { 2553 if ( bIsPDFExport && bFormat ) 2554 { 2555 //create a hidden view to be able to export as PDF also in print preview 2556 //pView and pSwView are not changed intentionally! 2557 m_pHiddenViewFrame = SfxViewFrame::LoadHiddenDocument( *pRenderDocShell, SFX_INTERFACE_SFXDOCSH ); 2558 pViewShell = static_cast<SwView*>(m_pHiddenViewFrame->GetViewShell())->GetWrtShellPtr(); 2559 } 2560 else 2561 pViewShell = static_cast<SwPagePreview*>(pView)->GetViewShell(); 2562 } 2563 2564 if (!pViewShell || !pViewShell->GetLayout()) 2565 return 0; 2566 2567 if (bFormat) 2568 { 2569 // #i38289 2570 if( pViewShell->GetViewOptions()->getBrowseMode() || 2571 pViewShell->GetViewOptions()->IsWhitespaceHidden() ) 2572 { 2573 SwViewOption aOpt( *pViewShell->GetViewOptions() ); 2574 aOpt.setBrowseMode( false ); 2575 aOpt.SetHideWhitespaceMode( false ); 2576 pViewShell->ApplyViewOptions( aOpt ); 2577 if (pSwView) 2578 { 2579 pSwView->RecheckBrowseMode(); 2580 } 2581 } 2582 2583 // reformatting the document for printing will show the changes in the view 2584 // which is likely to produce many unwanted and not nice to view actions. 2585 // We don't want that! Thus we disable updating of the view. 2586 pViewShell->StartAction(); 2587 2588 if (pSwView) 2589 { 2590 if (m_pRenderData && m_pRenderData->NeedNewViewOptionAdjust( *pViewShell ) ) 2591 m_pRenderData->ViewOptionAdjustStop(); 2592 if (m_pRenderData && !m_pRenderData->IsViewOptionAdjust()) 2593 { 2594 m_pRenderData->ViewOptionAdjustStart( 2595 *pViewShell, *pViewShell->GetViewOptions() ); 2596 } 2597 } 2598 2599 m_pRenderData->MakeSwPrtOptions( pRenderDocShell, 2600 m_pPrintUIOptions.get(), bIsPDFExport ); 2601 2602 if (pSwView) 2603 { 2604 // PDF export should not make use of the SwPrtOptions 2605 const SwPrintData *pPrtOptions = bIsPDFExport 2606 ? nullptr : m_pRenderData->GetSwPrtOptions(); 2607 bool setShowPlaceHoldersInPDF = false; 2608 if(bIsPDFExport) 2609 setShowPlaceHoldersInPDF = lcl_GetBoolProperty( rxOptions, "ExportPlaceholders" ); 2610 m_pRenderData->ViewOptionAdjust( pPrtOptions, setShowPlaceHoldersInPDF ); 2611 } 2612 2613 // since printing now also use the API for PDF export this option 2614 // should be set for printing as well ... 2615 pViewShell->SetPDFExportOption( true ); 2616 2617 // there is some redundancy between those two function calls, but right now 2618 // there is no time to sort this out. 2619 //TODO: check what exactly needs to be done and make just one function for that 2620 pViewShell->CalcLayout(); 2621 pViewShell->CalcPagesForPrint( pViewShell->GetPageCount() ); 2622 2623 2624 // #122919# Force field update before PDF export, but after layout init (tdf#121962) 2625 bool bStateChanged = false; 2626 // check configuration: shall update of printing information in DocInfo set the document to "modified"? 2627 if ( pRenderDocShell->IsEnableSetModified() && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() ) 2628 { 2629 pRenderDocShell->EnableSetModified( false ); 2630 bStateChanged = true; 2631 } 2632 pViewShell->SwViewShell::UpdateFields(true); 2633 if( bStateChanged ) 2634 pRenderDocShell->EnableSetModified(); 2635 2636 pViewShell->SetPDFExportOption( false ); 2637 2638 // enable view again 2639 pViewShell->EndAction(); 2640 } 2641 2642 const sal_Int32 nPageCount = pViewShell->GetPageCount(); 2643 2644 // get number of pages to be rendered 2645 2646 const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" ); 2647 if (bPrintProspect) 2648 { 2649 SwDoc::CalculatePagePairsForProspectPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, nPageCount ); 2650 nRet = m_pRenderData->GetPagePairsForProspectPrinting().size(); 2651 } 2652 else 2653 { 2654 const SwPostItMode nPostItMode = static_cast<SwPostItMode>( m_pPrintUIOptions->getIntValue( "PrintAnnotationMode", 0 ) ); 2655 if (nPostItMode != SwPostItMode::NONE) 2656 { 2657 VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions ); 2658 m_pRenderData->CreatePostItData( pDoc, pViewShell->GetViewOptions(), pOutDev ); 2659 } 2660 2661 // get set of valid document pages (according to the current settings) 2662 // and their start frames 2663 SwDoc::CalculatePagesForPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, bIsPDFExport, nPageCount ); 2664 2665 if (nPostItMode != SwPostItMode::NONE) 2666 { 2667 SwDoc::UpdatePagesForPrintingWithPostItData( *m_pRenderData, 2668 *m_pPrintUIOptions, nPageCount ); 2669 } 2670 2671 nRet = m_pRenderData->GetPagesToPrint().size(); 2672 } 2673 } 2674 OSL_ENSURE( nRet >= 0, "negative number of pages???" ); 2675 2676 return nRet; 2677 } 2678 2679 uno::Sequence< beans::PropertyValue > SAL_CALL SwXTextDocument::getRenderer( 2680 sal_Int32 nRenderer, 2681 const uno::Any& rSelection, 2682 const uno::Sequence< beans::PropertyValue >& rxOptions ) 2683 { 2684 SolarMutexGuard aGuard; 2685 if(!IsValid()) 2686 { 2687 throw DisposedException("", static_cast< XTextDocument* >(this)); 2688 } 2689 2690 const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ); 2691 bool bIsSwSrcView = false; 2692 SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport ); 2693 2694 // m_pRenderData should NOT be created here! 2695 // That should only be done in getRendererCount. If this function is called before 2696 // getRendererCount was called then the caller will probably just retrieve the extra UI options 2697 // and is not interested in getting valid information about the other data that would 2698 // otherwise be provided here! 2699 // if( ! m_pRenderData ) 2700 // m_pRenderData = new SwRenderData; 2701 if (!m_pPrintUIOptions) 2702 m_pPrintUIOptions = lcl_GetPrintUIOptions( pDocShell, pView ); 2703 m_pPrintUIOptions->processProperties( rxOptions ); 2704 const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" ); 2705 const bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport ); 2706 const bool bPrintPaperFromSetup = m_pPrintUIOptions->getBoolValue( "PrintPaperFromSetup" ); 2707 2708 SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport ); 2709 OSL_ENSURE( pDoc && pView, "doc or view shell missing!" ); 2710 if (!pDoc || !pView) 2711 return uno::Sequence< beans::PropertyValue >(); 2712 2713 // due to #110067# (document page count changes sometimes during 2714 // PDF export/printing) we can not check for the upper bound properly. 2715 // Thus instead of throwing the exception we silently return. 2716 if (0 > nRenderer) 2717 throw IllegalArgumentException(); 2718 2719 // TODO/mba: we really need a generic way to get the SwViewShell! 2720 SwViewShell* pVwSh = nullptr; 2721 SwView* pSwView = dynamic_cast<SwView*>( pView ); 2722 if ( pSwView ) 2723 pVwSh = pSwView->GetWrtShellPtr(); 2724 else 2725 pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell(); 2726 2727 sal_Int32 nMaxRenderer = 0; 2728 if (!bIsSwSrcView && m_pRenderData) 2729 { 2730 OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" ); 2731 nMaxRenderer = bPrintProspect? 2732 m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 : 2733 m_pRenderData->GetPagesToPrint().size() - 1; 2734 } 2735 // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print 2736 // we obmit checking of the upper bound in this case. 2737 if (!bIsSwSrcView && m_pRenderData && nRenderer > nMaxRenderer) 2738 return uno::Sequence< beans::PropertyValue >(); 2739 2740 uno::Sequence< beans::PropertyValue > aRenderer; 2741 if (m_pRenderData) 2742 { 2743 // #i114210# 2744 // determine the correct page number from the renderer index 2745 // #i114875 2746 // consider brochure print 2747 const sal_Int32 nPage = bPrintProspect 2748 ? nRenderer + 1 2749 : m_pRenderData->GetPagesToPrint()[ nRenderer ]; 2750 2751 // get paper tray to use ... 2752 sal_Int32 nPrinterPaperTray = -1; 2753 if (! bPrintPaperFromSetup) 2754 { 2755 // ... from individual page style (see the page tab in Format/Page dialog) 2756 const std::map< sal_Int32, sal_Int32 > &rPaperTrays = m_pRenderData->GetPrinterPaperTrays(); 2757 std::map< sal_Int32, sal_Int32 >::const_iterator aIt( rPaperTrays.find( nPage ) ); 2758 if (aIt != rPaperTrays.end()) 2759 nPrinterPaperTray = aIt->second; 2760 } 2761 2762 awt::Size aPageSize; 2763 awt::Point aPagePos; 2764 awt::Size aPreferredPageSize; 2765 Size aTmpSize; 2766 if (bIsSwSrcView || bPrintProspect) 2767 { 2768 // for printing of HTML source code and prospect printing we should use 2769 // the printers paper size since 2770 // a) HTML source view has no page size 2771 // b) prospect printing has a different page size from the documents page 2772 // since two document pages will get rendered on one printer page 2773 2774 // since PageIncludesNonprintableArea will be set to true we can return the 2775 // printers paper size here. 2776 // Sometimes 'getRenderer' is only called to get "ExtraPrintUIOptions", in this 2777 // case we won't get an OutputDevice here, but then the caller also has no need 2778 // for the correct PageSisze right now... 2779 VclPtr< Printer > pPrinter = dynamic_cast< Printer * >(lcl_GetOutputDevice( *m_pPrintUIOptions ).get()); 2780 if (pPrinter) 2781 { 2782 // HTML source view and prospect adapt to the printer's paper size 2783 aTmpSize = pPrinter->GetPaperSize(); 2784 aTmpSize = OutputDevice::LogicToLogic( aTmpSize, 2785 pPrinter->GetMapMode(), MapMode( MapUnit::Map100thMM )); 2786 aPageSize = awt::Size( aTmpSize.Width(), aTmpSize.Height() ); 2787 #if 0 2788 // #i115048# it seems users didn't like getting double the formatted page size 2789 // revert to "old" behavior scaling to the current paper size of the printer 2790 if (bPrintProspect) 2791 { 2792 // we just state what output size we would need 2793 // which may cause vcl to set that page size on the printer 2794 // (if available and not overridden by the user) 2795 aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages ); 2796 aPreferredPageSize = awt::Size ( convertTwipToMm100( 2 * aTmpSize.Width() ), 2797 convertTwipToMm100( aTmpSize.Height() )); 2798 } 2799 #else 2800 if( bPrintProspect ) 2801 { 2802 // just switch to an appropriate portrait/landscape format 2803 // FIXME: brochure printing with landscape pages puts the 2804 // pages next to each other, so landscape is currently always 2805 // the better choice 2806 if( aPageSize.Width < aPageSize.Height ) 2807 { 2808 aPreferredPageSize.Width = aPageSize.Height; 2809 aPreferredPageSize.Height = aPageSize.Width; 2810 } 2811 } 2812 #endif 2813 } 2814 } 2815 else 2816 { 2817 aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages ); 2818 aPageSize = awt::Size ( convertTwipToMm100( aTmpSize.Width() ), 2819 convertTwipToMm100( aTmpSize.Height() )); 2820 Point aPoint = pVwSh->GetPagePos(nPage); 2821 aPagePos = awt::Point(convertTwipToMm100(aPoint.X()), convertTwipToMm100(aPoint.Y())); 2822 } 2823 2824 sal_Int32 nLen = 3; 2825 aRenderer.realloc(3); 2826 aRenderer[0].Name = "PageSize"; 2827 aRenderer[0].Value <<= aPageSize; 2828 aRenderer[1].Name = "PageIncludesNonprintableArea"; 2829 aRenderer[1].Value <<= true; 2830 aRenderer[2].Name = "PagePos"; 2831 aRenderer[2].Value <<= aPagePos; 2832 if (aPreferredPageSize.Width && aPreferredPageSize.Height) 2833 { 2834 ++nLen; 2835 aRenderer.realloc( nLen ); 2836 aRenderer[ nLen - 1 ].Name = "PreferredPageSize"; 2837 aRenderer[ nLen - 1 ].Value <<= aPreferredPageSize; 2838 } 2839 if (nPrinterPaperTray >= 0) 2840 { 2841 ++nLen; 2842 aRenderer.realloc( nLen ); 2843 aRenderer[ nLen - 1 ].Name = "PrinterPaperTray"; 2844 aRenderer[ nLen - 1 ].Value <<= nPrinterPaperTray; 2845 } 2846 } 2847 2848 // #i117783# 2849 if ( bApplyPagePrintSettingsFromXPagePrintable ) 2850 { 2851 const SwPagePreviewPrtData* pPagePrintSettings = 2852 pDocShell->GetDoc()->GetPreviewPrtData(); 2853 if ( pPagePrintSettings && 2854 ( pPagePrintSettings->GetRow() > 1 || 2855 pPagePrintSettings->GetCol() > 1 ) ) 2856 { 2857 // extend render data by page print settings attributes 2858 sal_Int32 nLen = aRenderer.getLength(); 2859 const sal_Int32 nRenderDataIdxStart = nLen; 2860 nLen += 9; 2861 aRenderer.realloc( nLen ); 2862 // put page print settings attribute into render data 2863 const sal_Int32 nRow = pPagePrintSettings->GetRow(); 2864 aRenderer[ nRenderDataIdxStart + 0 ].Name = "NUpRows"; 2865 aRenderer[ nRenderDataIdxStart + 0 ].Value <<= std::max<sal_Int32>( nRow, 1); 2866 const sal_Int32 nCol = pPagePrintSettings->GetCol(); 2867 aRenderer[ nRenderDataIdxStart + 1 ].Name = "NUpColumns"; 2868 aRenderer[ nRenderDataIdxStart + 1 ].Value <<= std::max<sal_Int32>( nCol, 1); 2869 aRenderer[ nRenderDataIdxStart + 2 ].Name = "NUpPageMarginLeft"; 2870 aRenderer[ nRenderDataIdxStart + 2 ].Value <<= pPagePrintSettings->GetLeftSpace(); 2871 aRenderer[ nRenderDataIdxStart + 3 ].Name = "NUpPageMarginRight"; 2872 aRenderer[ nRenderDataIdxStart + 3 ].Value <<= pPagePrintSettings->GetRightSpace(); 2873 aRenderer[ nRenderDataIdxStart + 4 ].Name = "NUpPageMarginTop"; 2874 aRenderer[ nRenderDataIdxStart + 4 ].Value <<= pPagePrintSettings->GetTopSpace(); 2875 aRenderer[ nRenderDataIdxStart + 5 ].Name = "NUpPageMarginBottom"; 2876 aRenderer[ nRenderDataIdxStart + 5 ].Value <<= pPagePrintSettings->GetBottomSpace(); 2877 aRenderer[ nRenderDataIdxStart + 6 ].Name = "NUpHorizontalSpacing"; 2878 aRenderer[ nRenderDataIdxStart + 6 ].Value <<= pPagePrintSettings->GetHorzSpace(); 2879 aRenderer[ nRenderDataIdxStart + 7 ].Name = "NUpVerticalSpacing"; 2880 aRenderer[ nRenderDataIdxStart + 7 ].Value <<= pPagePrintSettings->GetVertSpace(); 2881 { 2882 Printer* pPrinter = pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrinter( false ); 2883 if ( pPrinter ) 2884 { 2885 awt::Size aNewPageSize; 2886 const Size aPageSize = pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM ) ); 2887 aNewPageSize = awt::Size( aPageSize.Width(), aPageSize.Height() ); 2888 if ( ( pPagePrintSettings->GetLandscape() && 2889 aPageSize.Width() < aPageSize.Height() ) || 2890 ( !pPagePrintSettings->GetLandscape() && 2891 aPageSize.Width() > aPageSize.Height() ) ) 2892 { 2893 aNewPageSize = awt::Size( aPageSize.Height(), aPageSize.Width() ); 2894 } 2895 aRenderer[ nRenderDataIdxStart + 8 ].Name = "NUpPaperSize"; 2896 aRenderer[ nRenderDataIdxStart + 8 ].Value <<= aNewPageSize; 2897 } 2898 } 2899 } 2900 2901 bApplyPagePrintSettingsFromXPagePrintable = false; 2902 } 2903 2904 m_pPrintUIOptions->appendPrintUIOptions( aRenderer ); 2905 2906 return aRenderer; 2907 } 2908 2909 SfxViewShell * SwXTextDocument::GuessViewShell( 2910 /* out */ bool &rbIsSwSrcView, 2911 const uno::Reference< css::frame::XController >& rController ) 2912 { 2913 // #130810# SfxViewShell::Current() / SfxViewShell::GetObjectShell() 2914 // must not be used (see comment from MBA) 2915 2916 SfxViewShell *pView = nullptr; 2917 SwView *pSwView = nullptr; 2918 SwPagePreview *pSwPagePreview = nullptr; 2919 SwSrcView *pSwSrcView = nullptr; 2920 SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pDocShell, false ); 2921 2922 // look for the view shell with the same controller in use, 2923 // otherwise look for a suitable view, preferably a SwView, 2924 // if that one is not found use a SwPagePreview if found. 2925 while (pFrame) 2926 { 2927 pView = pFrame->GetViewShell(); 2928 pSwView = dynamic_cast< SwView * >(pView); 2929 pSwSrcView = dynamic_cast< SwSrcView * >(pView); 2930 if (!pSwPagePreview) 2931 pSwPagePreview = dynamic_cast< SwPagePreview * >(pView); 2932 if (rController.is()) 2933 { 2934 if (pView && pView->GetController() == rController) 2935 break; 2936 } 2937 else if (pSwView || pSwSrcView) 2938 break; 2939 pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell, false ); 2940 } 2941 2942 OSL_ENSURE( pSwView || pSwPagePreview || pSwSrcView, "failed to get view shell" ); 2943 if (pView) 2944 rbIsSwSrcView = pSwSrcView != nullptr; 2945 return pView; 2946 } 2947 2948 void SAL_CALL SwXTextDocument::render( 2949 sal_Int32 nRenderer, 2950 const uno::Any& rSelection, 2951 const uno::Sequence< beans::PropertyValue >& rxOptions ) 2952 { 2953 SolarMutexGuard aGuard; 2954 if(!IsValid()) 2955 { 2956 throw DisposedException( OUString(), 2957 static_cast< XTextDocument* >(this) ); 2958 } 2959 2960 // due to #110067# (document page count changes sometimes during 2961 // PDF export/printing) we can not check for the upper bound properly. 2962 // Thus instead of throwing the exception we silently return. 2963 if (0 > nRenderer) 2964 throw IllegalArgumentException(); 2965 2966 const bool bHasPDFExtOutDevData = lcl_SeqHasProperty( rxOptions, "HasPDFExtOutDevData" ); 2967 const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ) || bHasPDFExtOutDevData; 2968 bool bIsSwSrcView = false; 2969 SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport ); 2970 2971 OSL_ENSURE( m_pRenderData, "data should have been created already in getRendererCount..." ); 2972 OSL_ENSURE( m_pPrintUIOptions, "data should have been created already in getRendererCount..." ); 2973 if (!bIsSwSrcView && !m_pRenderData) 2974 m_pRenderData.reset(new SwRenderData); 2975 if (!m_pPrintUIOptions) 2976 m_pPrintUIOptions = lcl_GetPrintUIOptions( pDocShell, pView ); 2977 m_pPrintUIOptions->processProperties( rxOptions ); 2978 const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" ); 2979 const bool bLastPage = m_pPrintUIOptions->getBoolValue( "IsLastPage" ); 2980 2981 SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport ); 2982 OSL_ENSURE( pDoc && pView, "doc or view shell missing!" ); 2983 if (pDoc && pView) 2984 { 2985 sal_Int32 nMaxRenderer = 0; 2986 if (!bIsSwSrcView) 2987 { 2988 OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" ); 2989 nMaxRenderer = bPrintProspect? 2990 m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 : 2991 m_pRenderData->GetPagesToPrint().size() - 1; 2992 } 2993 // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print 2994 // we obmit checking of the upper bound in this case. 2995 if (bIsSwSrcView || nRenderer <= nMaxRenderer) 2996 { 2997 if (bIsSwSrcView) 2998 { 2999 SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView); 3000 VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions ); 3001 rSwSrcView.PrintSource(pOutDev, nRenderer + 1, false); 3002 } 3003 else 3004 { 3005 // the view shell should be SwView for documents PDF export 3006 // or SwPagePreview for PDF export of the page preview 3007 SwViewShell* pVwSh = nullptr; 3008 // TODO/mba: we really need a generic way to get the SwViewShell! 3009 const SwView* pSwView = dynamic_cast<const SwView*>(pView); 3010 if (pSwView) 3011 pVwSh = pSwView->GetWrtShellPtr(); 3012 else 3013 pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell(); 3014 3015 // get output device to use 3016 VclPtr< OutputDevice > pOut = lcl_GetOutputDevice( *m_pPrintUIOptions ); 3017 3018 if(pVwSh && pOut && m_pRenderData->HasSwPrtOptions()) 3019 { 3020 const OUString aPageRange = m_pPrintUIOptions->getStringValue( "PageRange" ); 3021 const bool bFirstPage = m_pPrintUIOptions->getBoolValue( "IsFirstPage" ); 3022 bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport ); 3023 3024 OSL_ENSURE((pSwView && m_pRenderData->IsViewOptionAdjust()) 3025 || (!pSwView && !m_pRenderData->IsViewOptionAdjust()), 3026 "SwView / SwViewOptionAdjust_Impl availability mismatch" ); 3027 3028 // since printing now also use the API for PDF export this option 3029 // should be set for printing as well ... 3030 pVwSh->SetPDFExportOption( true ); 3031 3032 // #i12836# enhanced pdf export 3033 3034 // First, we have to export hyperlinks, notes, and outline to pdf. 3035 // During this process, additional information required for tagging 3036 // the pdf file are collected, which are evaulated during painting. 3037 3038 SwWrtShell* pWrtShell = pSwView ? pSwView->GetWrtShellPtr() : nullptr; 3039 3040 SwPrintData const& rSwPrtOptions = 3041 *m_pRenderData->GetSwPrtOptions(); 3042 3043 if (bIsPDFExport && (bFirstPage || bHasPDFExtOutDevData) && pWrtShell) 3044 { 3045 SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, false, rSwPrtOptions ); 3046 } 3047 3048 if (bPrintProspect) 3049 pVwSh->PrintProspect( pOut, rSwPrtOptions, nRenderer ); 3050 else // normal printing and PDF export 3051 pVwSh->PrintOrPDFExport( pOut, rSwPrtOptions, nRenderer, bIsPDFExport ); 3052 3053 // #i35176# 3054 3055 // After printing the last page, we take care for the links coming 3056 // from the EditEngine. The links are generated during the painting 3057 // process, but the destinations are still missing. 3058 3059 if (bIsPDFExport && bLastPage && pWrtShell) 3060 { 3061 SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, true, rSwPrtOptions ); 3062 } 3063 3064 pVwSh->SetPDFExportOption( false ); 3065 3066 // last page to be rendered? (not necessarily the last page of the document) 3067 // -> do clean-up of data 3068 if (bLastPage) 3069 { 3070 // #i96167# haggai: delete ViewOptionsAdjust here because it makes use 3071 // of the shell, which might get destroyed in lcl_DisposeView! 3072 if (m_pRenderData->IsViewOptionAdjust()) 3073 m_pRenderData->ViewOptionAdjustStop(); 3074 3075 if (m_pRenderData->HasPostItData()) 3076 m_pRenderData->DeletePostItData(); 3077 if (m_pHiddenViewFrame) 3078 { 3079 lcl_DisposeView( m_pHiddenViewFrame, pDocShell ); 3080 m_pHiddenViewFrame = nullptr; 3081 3082 // prevent crash described in #i108805 3083 SwDocShell *pRenderDocShell = pDoc->GetDocShell(); 3084 SfxItemSet *pSet = pRenderDocShell->GetMedium()->GetItemSet(); 3085 pSet->Put( SfxBoolItem( SID_HIDDEN, false ) ); 3086 3087 } 3088 } 3089 } 3090 } 3091 } 3092 } 3093 if( bLastPage ) 3094 { 3095 m_pRenderData.reset(); 3096 m_pPrintUIOptions.reset(); 3097 } 3098 } 3099 3100 // xforms::XFormsSupplier 3101 Reference<XNameContainer> SAL_CALL SwXTextDocument::getXForms() 3102 { 3103 SolarMutexGuard aGuard; 3104 if ( !pDocShell ) 3105 throw DisposedException( OUString(), static_cast< XTextDocument* >( this ) ); 3106 SwDoc* pDoc = pDocShell->GetDoc(); 3107 return pDoc->getXForms(); 3108 } 3109 3110 uno::Reference< text::XFlatParagraphIterator > SAL_CALL SwXTextDocument::getFlatParagraphIterator(::sal_Int32 nTextMarkupType, sal_Bool bAutomatic) 3111 { 3112 SolarMutexGuard aGuard; 3113 if (!IsValid()) 3114 { 3115 throw DisposedException("SwXTextDocument not valid", 3116 static_cast<XTextDocument*>(this)); 3117 } 3118 3119 return SwUnoCursorHelper::CreateFlatParagraphIterator( 3120 *pDocShell->GetDoc(), nTextMarkupType, bAutomatic); 3121 } 3122 3123 uno::Reference< util::XCloneable > SwXTextDocument::createClone( ) 3124 { 3125 SolarMutexGuard aGuard; 3126 if(!IsValid()) 3127 throw DisposedException("", static_cast< XTextDocument* >(this)); 3128 3129 // create a new document - hidden - copy the storage and return it 3130 // SfxObjectShellRef is used here, since the model should control object lifetime after creation 3131 // and thus SfxObjectShellLock is not allowed here 3132 // the model holds reference to the shell, so the shell will not destructed at the end of method 3133 SfxObjectShellRef pShell = pDocShell->GetDoc()->CreateCopy(false, false); 3134 uno::Reference< frame::XModel > xNewModel = pShell->GetModel(); 3135 uno::Reference< embed::XStorage > xNewStorage = ::comphelper::OStorageHelper::GetTemporaryStorage( ); 3136 uno::Sequence< beans::PropertyValue > aTempMediaDescriptor; 3137 storeToStorage( xNewStorage, aTempMediaDescriptor ); 3138 uno::Reference< document::XStorageBasedDocument > xStorageDoc( xNewModel, uno::UNO_QUERY ); 3139 xStorageDoc->loadFromStorage( xNewStorage, aTempMediaDescriptor ); 3140 return uno::Reference< util::XCloneable >( xNewModel, UNO_QUERY ); 3141 } 3142 3143 void SwXTextDocument::addPasteEventListener(const uno::Reference<text::XPasteListener>& xListener) 3144 { 3145 SolarMutexGuard aGuard; 3146 3147 if (IsValid() && xListener.is()) 3148 pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener); 3149 } 3150 3151 void SwXTextDocument::removePasteEventListener( 3152 const uno::Reference<text::XPasteListener>& xListener) 3153 { 3154 SolarMutexGuard aGuard; 3155 3156 if (IsValid() && xListener.is()) 3157 pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener); 3158 } 3159 3160 void SwXTextDocument::paintTile( VirtualDevice &rDevice, 3161 int nOutputWidth, int nOutputHeight, 3162 int nTilePosX, int nTilePosY, 3163 long nTileWidth, long nTileHeight ) 3164 { 3165 SwViewShell* pViewShell = pDocShell->GetWrtShell(); 3166 pViewShell->PaintTile(rDevice, nOutputWidth, nOutputHeight, 3167 nTilePosX, nTilePosY, nTileWidth, nTileHeight); 3168 3169 LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight, 3170 nTilePosX, nTilePosY, nTileWidth, nTileHeight); 3171 } 3172 3173 Size SwXTextDocument::getDocumentSize() 3174 { 3175 SwViewShell* pViewShell = pDocShell->GetWrtShell(); 3176 Size aDocSize = pViewShell->GetDocSize(); 3177 3178 return Size(aDocSize.Width() + 2 * DOCUMENTBORDER, 3179 aDocSize.Height() + 2 * DOCUMENTBORDER); 3180 } 3181 3182 void SwXTextDocument::setPart(int nPart) 3183 { 3184 SolarMutexGuard aGuard; 3185 3186 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3187 if (!pWrtShell) 3188 return; 3189 3190 pWrtShell->GotoPage(nPart + 1, true); 3191 } 3192 3193 int SwXTextDocument::getParts() 3194 { 3195 SolarMutexGuard aGuard; 3196 3197 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3198 if (!pWrtShell) 3199 return 0; 3200 3201 return pWrtShell->GetPageCnt(); 3202 } 3203 3204 OUString SwXTextDocument::getPartPageRectangles() 3205 { 3206 SolarMutexGuard aGuard; 3207 3208 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3209 if (!pWrtShell) 3210 return OUString(); 3211 3212 return pWrtShell->getPageRectangles(); 3213 } 3214 3215 void SwXTextDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard) 3216 { 3217 SolarMutexGuard aGuard; 3218 3219 pDocShell->GetView()->GetEditWin().SetClipboard(xClipboard); 3220 } 3221 3222 bool SwXTextDocument::isMimeTypeSupported() 3223 { 3224 SolarMutexGuard aGuard; 3225 3226 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3227 if (!pWrtShell) 3228 return false; 3229 3230 TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(&pWrtShell->GetView().GetEditWin())); 3231 if (SdrView* pSdrView = pWrtShell->GetDrawView()) 3232 { 3233 if (pSdrView->GetTextEditObject()) 3234 // Editing shape text 3235 return EditEngine::HasValidData(aDataHelper.GetTransferable()); 3236 } 3237 3238 return aDataHelper.GetXTransferable().is() && SwTransferable::IsPaste(*pWrtShell, aDataHelper); 3239 } 3240 3241 void SwXTextDocument::setClientVisibleArea(const tools::Rectangle& rRectangle) 3242 { 3243 if (SwView* pView = pDocShell->GetView()) 3244 { 3245 // set the PgUp/PgDown offset 3246 pView->ForcePageUpDownOffset(2 * rRectangle.GetHeight() / 3); 3247 } 3248 3249 if (SwViewShell* pViewShell = pDocShell->GetWrtShell()) 3250 { 3251 pViewShell->setLOKVisibleArea(rRectangle); 3252 } 3253 } 3254 3255 void SwXTextDocument::setClientZoom(int nTilePixelWidth_, int /*nTilePixelHeight_*/, 3256 int nTileTwipWidth_, int /*nTileTwipHeight_*/) 3257 { 3258 // Here we set the zoom value as it has been set by the user in the client. 3259 // This value is used in postMouseEvent and setGraphicSelection methods 3260 // for in place chart editing. We assume that x and y scale is roughly 3261 // the same. 3262 // Indeed we could set mnTilePixelWidth, mnTilePixelHeight, mnTileTwipWidth, 3263 // mnTileTwipHeight data members of this class but they are not very useful 3264 // since we need to be able to retrieve the zoom value for each view shell. 3265 SfxInPlaceClient* pIPClient = pDocShell->GetView()->GetIPClient(); 3266 if (pIPClient) 3267 { 3268 SwViewShell* pWrtViewShell = pDocShell->GetWrtShell(); 3269 double fScale = nTilePixelWidth_ * TWIPS_PER_PIXEL / (nTileTwipWidth_ * 1.0); 3270 SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); 3271 if (aOption.GetZoom() != fScale * 100) 3272 { 3273 aOption.SetZoom(fScale * 100); 3274 pWrtViewShell->ApplyViewOptions(aOption); 3275 3276 // Changing the zoom value doesn't always trigger the updating of 3277 // the client ole object area, so we call it directly. 3278 pIPClient->VisAreaChanged(); 3279 } 3280 } 3281 } 3282 3283 PointerStyle SwXTextDocument::getPointer() 3284 { 3285 SolarMutexGuard aGuard; 3286 3287 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3288 if (!pWrtShell) 3289 return PointerStyle::Arrow; 3290 3291 return pWrtShell->GetView().GetEditWin().GetPointer(); 3292 } 3293 3294 OUString SwXTextDocument::getTrackedChanges() 3295 { 3296 boost::property_tree::ptree aTrackedChanges; 3297 3298 // Disable since usability is very low beyond some small number of changes. 3299 static bool bDisableRedlineComments = getenv("DISABLE_REDLINE") != nullptr; 3300 if (!bDisableRedlineComments) 3301 { 3302 const SwRedlineTable& rRedlineTable 3303 = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); 3304 for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i) 3305 { 3306 boost::property_tree::ptree aTrackedChange; 3307 aTrackedChange.put("index", rRedlineTable[i]->GetId()); 3308 aTrackedChange.put("author", rRedlineTable[i]->GetAuthorString(1).toUtf8().getStr()); 3309 aTrackedChange.put("type", SwRedlineTypeToOUString( 3310 rRedlineTable[i]->GetRedlineData().GetType()) 3311 .toUtf8() 3312 .getStr()); 3313 aTrackedChange.put("comment", 3314 rRedlineTable[i]->GetRedlineData().GetComment().toUtf8().getStr()); 3315 aTrackedChange.put("description", rRedlineTable[i]->GetDescr().toUtf8().getStr()); 3316 OUString sDateTime = utl::toISO8601( 3317 rRedlineTable[i]->GetRedlineData().GetTimeStamp().GetUNODateTime()); 3318 aTrackedChange.put("dateTime", sDateTime.toUtf8().getStr()); 3319 3320 SwContentNode* pContentNd = rRedlineTable[i]->GetContentNode(); 3321 SwView* pView = dynamic_cast<SwView*>(SfxViewShell::Current()); 3322 if (pView && pContentNd) 3323 { 3324 SwShellCursor aCursor(pView->GetWrtShell(), *(rRedlineTable[i]->Start())); 3325 aCursor.SetMark(); 3326 aCursor.GetMark()->nNode = *pContentNd; 3327 aCursor.GetMark()->nContent.Assign(pContentNd, 3328 rRedlineTable[i]->End()->nContent.GetIndex()); 3329 3330 aCursor.FillRects(); 3331 3332 SwRects* pRects(&aCursor); 3333 std::vector<OString> aRects; 3334 for (SwRect& rNextRect : *pRects) 3335 aRects.push_back(rNextRect.SVRect().toString()); 3336 3337 const OString sRects = comphelper::string::join("; ", aRects); 3338 aTrackedChange.put("textRange", sRects.getStr()); 3339 } 3340 3341 aTrackedChanges.push_back(std::make_pair("", aTrackedChange)); 3342 } 3343 } 3344 3345 boost::property_tree::ptree aTree; 3346 aTree.add_child("redlines", aTrackedChanges); 3347 std::stringstream aStream; 3348 boost::property_tree::write_json(aStream, aTree); 3349 3350 return OUString::fromUtf8(aStream.str().c_str()); 3351 } 3352 3353 OUString SwXTextDocument::getTrackedChangeAuthors() 3354 { 3355 return SW_MOD()->GetRedlineAuthorInfo(); 3356 } 3357 3358 OUString SwXTextDocument::getRulerState() 3359 { 3360 SwView* pView = pDocShell->GetView(); 3361 return OUString::fromUtf8(dynamic_cast<SwCommentRuler&>(pView->GetHRuler()).CreateJsonNotification().c_str()); 3362 } 3363 3364 OUString SwXTextDocument::getPostIts() 3365 { 3366 SolarMutexGuard aGuard; 3367 boost::property_tree::ptree aAnnotations; 3368 for (auto const& sidebarItem : *pDocShell->GetView()->GetPostItMgr()) 3369 { 3370 sw::annotation::SwAnnotationWin* pWin = sidebarItem->pPostIt.get(); 3371 3372 const SwPostItField* pField = pWin->GetPostItField(); 3373 const SwRect& aRect = pWin->GetAnchorRect(); 3374 const tools::Rectangle aSVRect(aRect.Pos().getX(), 3375 aRect.Pos().getY(), 3376 aRect.Pos().getX() + aRect.SSize().Width(), 3377 aRect.Pos().getY() + aRect.SSize().Height()); 3378 std::vector<OString> aRects; 3379 for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges()) 3380 { 3381 const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight()); 3382 aRects.push_back(rect.SVRect().toString()); 3383 } 3384 const OString sRects = comphelper::string::join("; ", aRects); 3385 3386 boost::property_tree::ptree aAnnotation; 3387 aAnnotation.put("id", pField->GetPostItId()); 3388 aAnnotation.put("parent", pWin->CalcParent()); 3389 aAnnotation.put("author", pField->GetPar1().toUtf8().getStr()); 3390 aAnnotation.put("text", pField->GetPar2().toUtf8().getStr()); 3391 aAnnotation.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime())); 3392 aAnnotation.put("anchorPos", aSVRect.toString()); 3393 aAnnotation.put("textRange", sRects.getStr()); 3394 3395 aAnnotations.push_back(std::make_pair("", aAnnotation)); 3396 } 3397 3398 boost::property_tree::ptree aTree; 3399 aTree.add_child("comments", aAnnotations); 3400 std::stringstream aStream; 3401 boost::property_tree::write_json(aStream, aTree); 3402 3403 return OUString::fromUtf8(aStream.str().c_str()); 3404 } 3405 3406 int SwXTextDocument::getPart() 3407 { 3408 SolarMutexGuard aGuard; 3409 3410 SwView* pView = pDocShell->GetView(); 3411 if (!pView) 3412 return 0; 3413 3414 return pView->getPart(); 3415 } 3416 3417 OUString SwXTextDocument::getPartName(int nPart) 3418 { 3419 SolarMutexGuard aGuard; 3420 3421 return SwResId(STR_PAGE) + OUString::number(nPart + 1); 3422 } 3423 3424 OUString SwXTextDocument::getPartHash(int nPart) 3425 { 3426 SolarMutexGuard aGuard; 3427 OUString sPart(SwResId(STR_PAGE) + OUString::number(nPart + 1)); 3428 3429 return OUString::number(sPart.hashCode()); 3430 } 3431 3432 VclPtr<vcl::Window> SwXTextDocument::getDocWindow() 3433 { 3434 SolarMutexGuard aGuard; 3435 VclPtr<vcl::Window> pWindow; 3436 SwView* pView = pDocShell->GetView(); 3437 if (pView) 3438 pWindow = &(pView->GetEditWin()); 3439 3440 LokChartHelper aChartHelper(pView); 3441 VclPtr<vcl::Window> pChartWindow = aChartHelper.GetWindow(); 3442 if (pChartWindow) 3443 pWindow = pChartWindow; 3444 3445 return pWindow; 3446 } 3447 3448 void SwXTextDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments) 3449 { 3450 SolarMutexGuard aGuard; 3451 3452 SwViewShell* pViewShell = pDocShell->GetWrtShell(); 3453 3454 SwView* pView = pDocShell->GetView(); 3455 if (!pView) 3456 return; 3457 3458 pView->SetViewLayout(1/*nColumns*/, false/*bBookMode*/, true); 3459 3460 // Tiled rendering defaults. 3461 SwViewOption aViewOption(*pViewShell->GetViewOptions()); 3462 aViewOption.SetHardBlank(false); 3463 for (sal_Int32 i = 0; i < rArguments.getLength(); ++i) 3464 { 3465 const beans::PropertyValue& rValue = rArguments[i]; 3466 if (rValue.Name == ".uno:HideWhitespace" && rValue.Value.has<bool>()) 3467 aViewOption.SetHideWhitespaceMode(rValue.Value.get<bool>()); 3468 else if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>()) 3469 SwViewOption::SetAppearanceFlag(ViewOptFlags::Shadow , rValue.Value.get<bool>()); 3470 else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>()) 3471 { 3472 // Store the author name in the view. 3473 pView->SetRedlineAuthor(rValue.Value.get<OUString>()); 3474 // Let the actual author name pick up the value from the current 3475 // view, which would normally happen only during the next view 3476 // switch. 3477 pDocShell->SetView(pView); 3478 } 3479 } 3480 3481 // Set the initial zoom value to 1; usually it is set in setClientZoom and 3482 // SwViewShell::PaintTile; zoom value is used for chart in place 3483 // editing, see postMouseEvent and setGraphicSelection methods. 3484 aViewOption.SetZoom(1 * 100); 3485 3486 aViewOption.SetPostIts(comphelper::LibreOfficeKit::isTiledAnnotations()); 3487 pViewShell->ApplyViewOptions(aViewOption); 3488 3489 // position the pages again after setting view options. Eg: if postit 3490 // rendering is false, then there would be no sidebar, so width of the 3491 // document needs to be adjusted 3492 pViewShell->GetLayout()->CheckViewLayout( pViewShell->GetViewOptions(), nullptr ); 3493 3494 // Disable map mode, so that it's possible to send mouse event coordinates 3495 // directly in twips. 3496 SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin(); 3497 rEditWin.EnableMapMode(false); 3498 3499 // when the "This document may contain formatting or content that cannot 3500 // be saved..." dialog appears, it is auto-cancelled with tiled rendering, 3501 // causing 'Save' being disabled; so let's always save to the original 3502 // format 3503 SvtSaveOptions().SetWarnAlienFormat(false); 3504 3505 // disable word auto-completion suggestions, the tooltips are not visible, 3506 // and the editeng-like auto-completion is annoying 3507 SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags().bAutoCompleteWords = false; 3508 3509 // don't change the whitespace at the beginning of paragraphs, this is 3510 // annoying when taking minutes without further formatting 3511 SwEditShell::GetAutoFormatFlags()->bAFormatByInpDelSpacesAtSttEnd = false; 3512 } 3513 3514 void SwXTextDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode) 3515 { 3516 SolarMutexGuard aGuard; 3517 SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode); 3518 } 3519 3520 void SwXTextDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier) 3521 { 3522 SolarMutexGuard aGuard; 3523 3524 SwViewShell* pWrtViewShell = pDocShell->GetWrtShell(); 3525 SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); 3526 double fScale = aOption.GetZoom() / (TWIPS_PER_PIXEL * 100.0); 3527 3528 // check if user hit a chart which is being edited by him 3529 SfxViewShell* pViewShell = pDocShell->GetView(); 3530 LokChartHelper aChartHelper(pViewShell); 3531 if (aChartHelper.postMouseEvent(nType, nX, nY, 3532 nCount, nButtons, nModifier, 3533 fScale, fScale)) 3534 return; 3535 3536 // check if the user hit a chart which is being edited by someone else 3537 // and, if so, skip current mouse event 3538 if (nType != LOK_MOUSEEVENT_MOUSEMOVE) 3539 { 3540 if (LokChartHelper::HitAny(Point(nX, nY))) 3541 return; 3542 } 3543 3544 SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin(); 3545 SfxLokHelper::postMouseEventAsync(&rEditWin, nType, 3546 Point(nX, nY), nCount, 3547 MouseEventModifiers::SIMPLECLICK, 3548 nButtons, nModifier); 3549 } 3550 3551 void SwXTextDocument::setTextSelection(int nType, int nX, int nY) 3552 { 3553 SolarMutexGuard aGuard; 3554 3555 SfxViewShell* pViewShell = pDocShell->GetView(); 3556 LokChartHelper aChartHelper(pViewShell); 3557 if (aChartHelper.setTextSelection(nType, nX, nY)) 3558 return; 3559 3560 SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin(); 3561 switch (nType) 3562 { 3563 case LOK_SETTEXTSELECTION_START: 3564 rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/false, /*bClearMark=*/false); 3565 break; 3566 case LOK_SETTEXTSELECTION_END: 3567 rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/false); 3568 break; 3569 case LOK_SETTEXTSELECTION_RESET: 3570 rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/true); 3571 break; 3572 default: 3573 assert(false); 3574 break; 3575 } 3576 } 3577 3578 uno::Reference<datatransfer::XTransferable> SwXTextDocument::getSelection() 3579 { 3580 SolarMutexGuard aGuard; 3581 3582 uno::Reference<datatransfer::XTransferable> xTransferable; 3583 3584 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3585 if (SdrView* pSdrView = pWrtShell->GetDrawView()) 3586 { 3587 if (pSdrView->GetTextEditObject()) 3588 { 3589 // Editing shape text 3590 EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); 3591 xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection()); 3592 } 3593 } 3594 3595 if (SwPostItMgr* pPostItMgr = pDocShell->GetView()->GetPostItMgr()) 3596 { 3597 if (sw::annotation::SwAnnotationWin* pWin = pPostItMgr->GetActiveSidebarWin()) 3598 { 3599 // Editing postit text. 3600 EditView& rEditView = pWin->GetOutlinerView()->GetEditView(); 3601 xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection()); 3602 } 3603 } 3604 3605 if (!xTransferable.is()) 3606 xTransferable = new SwTransferable(*pWrtShell); 3607 3608 return xTransferable; 3609 } 3610 3611 void SwXTextDocument::setGraphicSelection(int nType, int nX, int nY) 3612 { 3613 SolarMutexGuard aGuard; 3614 3615 SwViewShell* pWrtViewShell = pDocShell->GetWrtShell(); 3616 SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); 3617 double fScale = aOption.GetZoom() / (TWIPS_PER_PIXEL * 100.0); 3618 3619 SfxViewShell* pViewShell = pDocShell->GetView(); 3620 LokChartHelper aChartHelper(pViewShell); 3621 if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale)) 3622 return; 3623 3624 SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin(); 3625 switch (nType) 3626 { 3627 case LOK_SETGRAPHICSELECTION_START: 3628 rEditWin.SetGraphicTwipPosition(/*bStart=*/true, Point(nX, nY)); 3629 break; 3630 case LOK_SETGRAPHICSELECTION_END: 3631 rEditWin.SetGraphicTwipPosition(/*bStart=*/false, Point(nX, nY)); 3632 break; 3633 default: 3634 assert(false); 3635 break; 3636 } 3637 } 3638 3639 void SwXTextDocument::resetSelection() 3640 { 3641 SolarMutexGuard aGuard; 3642 3643 SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); 3644 pWrtShell->ResetSelect(nullptr, false); 3645 } 3646 3647 void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) 3648 { 3649 SystemGraphicsData aData; 3650 aData.nSize = sizeof(SystemGraphicsData); 3651 #if defined(_WIN32) 3652 sal_Int64 nWindowHandle; 3653 Parent >>= nWindowHandle; 3654 aData.hWnd = reinterpret_cast<HWND>(nWindowHandle); 3655 ScopedVclPtrInstance<VirtualDevice> xDevice(&aData, Size(1, 1), DeviceFormat::DEFAULT); 3656 paintTile(*xDevice, nOutputWidth, nOutputHeight, nTilePosX, nTilePosY, nTileWidth, nTileHeight); 3657 #else 3658 // TODO: support other platforms 3659 (void)Parent; 3660 (void)nOutputWidth; 3661 (void)nOutputHeight; 3662 (void)nTilePosX; 3663 (void)nTilePosY; 3664 (void)nTileWidth; 3665 (void)nTileHeight; 3666 #endif 3667 } 3668 3669 /** 3670 * retrieve languages already used in current document 3671 */ 3672 uno::Sequence< lang::Locale > SAL_CALL SwXTextDocument::getDocumentLanguages( 3673 ::sal_Int16 nScriptTypes, 3674 ::sal_Int16 nMaxCount ) 3675 { 3676 SolarMutexGuard aGuard; 3677 3678 // possible canonical values for nScriptTypes 3679 // any bit wise combination is allowed 3680 const sal_Int16 nLatin = 0x001; 3681 const sal_Int16 nAsian = 0x002; 3682 const sal_Int16 nComplex = 0x004; 3683 3684 // script types for which to get the languages 3685 const bool bLatin = 0 != (nScriptTypes & nLatin); 3686 const bool bAsian = 0 != (nScriptTypes & nAsian); 3687 const bool bComplex = 0 != (nScriptTypes & nComplex); 3688 3689 if (nScriptTypes < nLatin || nScriptTypes > (nLatin | nAsian | nComplex)) 3690 throw IllegalArgumentException("nScriptTypes ranges from 1 to 7!", Reference< XInterface >(), 1); 3691 if (!pDocShell) 3692 throw DisposedException(); 3693 SwDoc* pDoc = pDocShell->GetDoc(); 3694 3695 // avoid duplicate values 3696 std::set< LanguageType > aAllLangs; 3697 3698 //USER STYLES 3699 3700 const SwCharFormats *pFormats = pDoc->GetCharFormats(); 3701 for(size_t i = 0; i < pFormats->size(); ++i) 3702 { 3703 const SwAttrSet &rAttrSet = (*pFormats)[i]->GetAttrSet(); 3704 LanguageType nLang = LANGUAGE_DONTKNOW; 3705 if (bLatin) 3706 { 3707 nLang = rAttrSet.GetLanguage( false ).GetLanguage(); 3708 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3709 aAllLangs.insert( nLang ); 3710 } 3711 if (bAsian) 3712 { 3713 nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage(); 3714 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3715 aAllLangs.insert( nLang ); 3716 } 3717 if (bComplex) 3718 { 3719 nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage(); 3720 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3721 aAllLangs.insert( nLang ); 3722 } 3723 } 3724 3725 const SwTextFormatColls *pColls = pDoc->GetTextFormatColls(); 3726 for (size_t i = 0; i < pColls->size(); ++i) 3727 { 3728 const SwAttrSet &rAttrSet = (*pColls)[i]->GetAttrSet(); 3729 LanguageType nLang = LANGUAGE_DONTKNOW; 3730 if (bLatin) 3731 { 3732 nLang = rAttrSet.GetLanguage( false ).GetLanguage(); 3733 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3734 aAllLangs.insert( nLang ); 3735 } 3736 if (bAsian) 3737 { 3738 nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage(); 3739 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3740 aAllLangs.insert( nLang ); 3741 } 3742 if (bComplex) 3743 { 3744 nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage(); 3745 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3746 aAllLangs.insert( nLang ); 3747 } 3748 } 3749 3750 //AUTO STYLES 3751 const IStyleAccess::SwAutoStyleFamily aFam[2] = 3752 { 3753 IStyleAccess::AUTO_STYLE_CHAR, 3754 IStyleAccess::AUTO_STYLE_PARA 3755 }; 3756 for (IStyleAccess::SwAutoStyleFamily i : aFam) 3757 { 3758 std::vector< std::shared_ptr<SfxItemSet> > rStyles; 3759 pDoc->GetIStyleAccess().getAllStyles(rStyles, i); 3760 while (!rStyles.empty()) 3761 { 3762 std::shared_ptr<SfxItemSet> pStyle = rStyles.back(); 3763 rStyles.pop_back(); 3764 const SfxItemSet *pSet = dynamic_cast< const SfxItemSet * >(pStyle.get()); 3765 3766 LanguageType nLang = LANGUAGE_DONTKNOW; 3767 if (bLatin) 3768 { 3769 assert(pSet); 3770 nLang = dynamic_cast< const SvxLanguageItem & >(pSet->Get( RES_CHRATR_LANGUAGE, false )).GetLanguage(); 3771 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3772 aAllLangs.insert( nLang ); 3773 } 3774 if (bAsian) 3775 { 3776 assert(pSet); 3777 nLang = dynamic_cast< const SvxLanguageItem & >(pSet->Get( RES_CHRATR_CJK_LANGUAGE, false )).GetLanguage(); 3778 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3779 aAllLangs.insert( nLang ); 3780 } 3781 if (bComplex) 3782 { 3783 assert(pSet); 3784 nLang = dynamic_cast< const SvxLanguageItem & >(pSet->Get( RES_CHRATR_CTL_LANGUAGE, false )).GetLanguage(); 3785 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3786 aAllLangs.insert( nLang ); 3787 } 3788 } 3789 } 3790 3791 //TODO/mba: it's a strange concept that a view is needed to retrieve core data 3792 SwWrtShell *pWrtSh = pDocShell->GetWrtShell(); 3793 SdrView *pSdrView = pWrtSh->GetDrawView(); 3794 3795 if( pSdrView ) 3796 { 3797 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner(); 3798 if(pOutliner) 3799 { 3800 EditEngine& rEditEng = const_cast<EditEngine&>(pOutliner->GetEditEngine()); 3801 sal_Int32 nParCount = pOutliner->GetParagraphCount(); 3802 for (sal_Int32 nPar=0; nPar<nParCount; nPar++) 3803 { 3804 //every paragraph 3805 std::vector<sal_Int32> aPortions; 3806 rEditEng.GetPortions( nPar, aPortions ); 3807 3808 for ( size_t nPos = aPortions.size(); nPos; ) 3809 { 3810 //every position 3811 --nPos; 3812 sal_Int32 nEnd = aPortions[ nPos ]; 3813 sal_Int32 nStart = nPos ? aPortions[ nPos - 1 ] : 0; 3814 ESelection aSelection( nPar, nStart, nPar, nEnd ); 3815 SfxItemSet aAttr = rEditEng.GetAttribs( aSelection ); 3816 3817 LanguageType nLang = LANGUAGE_DONTKNOW; 3818 if (bLatin) 3819 { 3820 nLang = dynamic_cast< const SvxLanguageItem & >(aAttr.Get( EE_CHAR_LANGUAGE, false )).GetLanguage(); 3821 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3822 aAllLangs.insert( nLang ); 3823 } 3824 if (bAsian) 3825 { 3826 nLang = dynamic_cast< const SvxLanguageItem & >(aAttr.Get( EE_CHAR_LANGUAGE_CJK, false )).GetLanguage(); 3827 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3828 aAllLangs.insert( nLang ); 3829 } 3830 if (bComplex) 3831 { 3832 nLang = dynamic_cast< const SvxLanguageItem & >(aAttr.Get( EE_CHAR_LANGUAGE_CTL, false )).GetLanguage(); 3833 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) 3834 aAllLangs.insert( nLang ); 3835 } 3836 } 3837 } 3838 } 3839 } 3840 // less than nMaxCount languages 3841 if (nMaxCount > static_cast< sal_Int16 >( aAllLangs.size() )) 3842 nMaxCount = static_cast< sal_Int16 >( aAllLangs.size() ); 3843 3844 // build return value 3845 uno::Sequence< lang::Locale > aLanguages( nMaxCount ); 3846 lang::Locale* pLanguage = aLanguages.getArray(); 3847 if (nMaxCount > 0) 3848 { 3849 sal_Int32 nCount = 0; 3850 for (const auto& rLang : aAllLangs) 3851 { 3852 if (nCount >= nMaxCount) 3853 break; 3854 if (LANGUAGE_NONE != rLang) 3855 { 3856 pLanguage[nCount] = LanguageTag::convertToLocale( rLang ); 3857 pLanguage[nCount].Language = SvtLanguageTable::GetLanguageString( rLang ); 3858 nCount += 1; 3859 } 3860 } 3861 } 3862 3863 return aLanguages; 3864 } 3865 3866 SwXLinkTargetSupplier::SwXLinkTargetSupplier(SwXTextDocument& rxDoc) : 3867 pxDoc(&rxDoc) 3868 { 3869 sTables = SwResId(STR_CONTENT_TYPE_TABLE); 3870 sFrames = SwResId(STR_CONTENT_TYPE_FRAME); 3871 sGraphics = SwResId(STR_CONTENT_TYPE_GRAPHIC); 3872 sOLEs = SwResId(STR_CONTENT_TYPE_OLE); 3873 sSections = SwResId(STR_CONTENT_TYPE_REGION); 3874 sOutlines = SwResId(STR_CONTENT_TYPE_OUTLINE); 3875 sBookmarks = SwResId(STR_CONTENT_TYPE_BOOKMARK); 3876 } 3877 3878 SwXLinkTargetSupplier::~SwXLinkTargetSupplier() 3879 { 3880 } 3881 3882 Any SwXLinkTargetSupplier::getByName(const OUString& rName) 3883 { 3884 Any aRet; 3885 if(!pxDoc) 3886 throw RuntimeException("No document available"); 3887 OUString sSuffix("|"); 3888 if(rName == sTables) 3889 { 3890 sSuffix += "table"; 3891 3892 Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( 3893 pxDoc->getTextTables(), rName, sSuffix ); 3894 aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); 3895 } 3896 else if(rName == sFrames) 3897 { 3898 sSuffix += "frame"; 3899 Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( 3900 pxDoc->getTextFrames(), rName, sSuffix ); 3901 aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); 3902 } 3903 else if(rName == sSections) 3904 { 3905 sSuffix += "region"; 3906 Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( 3907 pxDoc->getTextSections(), rName, sSuffix ); 3908 aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); 3909 } 3910 else if(rName == sGraphics) 3911 { 3912 sSuffix += "graphic"; 3913 Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( 3914 pxDoc->getGraphicObjects(), rName, sSuffix ); 3915 aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); 3916 } 3917 else if(rName == sOLEs) 3918 { 3919 sSuffix += "ole"; 3920 Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( 3921 pxDoc->getEmbeddedObjects(), rName, sSuffix ); 3922 aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); 3923 } 3924 else if(rName == sOutlines) 3925 { 3926 sSuffix += "outline"; 3927 Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( 3928 *pxDoc, rName, sSuffix ); 3929 aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); 3930 } 3931 else if(rName == sBookmarks) 3932 { 3933 sSuffix.clear(); 3934 Reference< XNameAccess > xBkms = new SwXLinkNameAccessWrapper( 3935 pxDoc->getBookmarks(), rName, sSuffix ); 3936 aRet <<= Reference< XPropertySet >(xBkms, UNO_QUERY); 3937 } 3938 else 3939 throw NoSuchElementException(); 3940 return aRet; 3941 } 3942 3943 Sequence< OUString > SwXLinkTargetSupplier::getElementNames() 3944 { 3945 Sequence< OUString > aRet(7); 3946 OUString* pNames = aRet.getArray(); 3947 pNames[0] = sTables; 3948 pNames[1] = sFrames ; 3949 pNames[2] = sGraphics; 3950 pNames[3] = sOLEs ; 3951 pNames[4] = sSections; 3952 pNames[5] = sOutlines; 3953 pNames[6] = sBookmarks; 3954 return aRet; 3955 } 3956 3957 sal_Bool SwXLinkTargetSupplier::hasByName(const OUString& rName) 3958 { 3959 if( rName == sTables || 3960 rName == sFrames || 3961 rName == sGraphics|| 3962 rName == sOLEs || 3963 rName == sSections || 3964 rName == sOutlines || 3965 rName == sBookmarks ) 3966 return true; 3967 return false; 3968 } 3969 3970 uno::Type SwXLinkTargetSupplier::getElementType() 3971 { 3972 return cppu::UnoType<XPropertySet>::get(); 3973 3974 } 3975 3976 sal_Bool SwXLinkTargetSupplier::hasElements() 3977 { 3978 return nullptr != pxDoc; 3979 } 3980 3981 OUString SwXLinkTargetSupplier::getImplementationName() 3982 { 3983 return OUString("SwXLinkTargetSupplier"); 3984 } 3985 3986 sal_Bool SwXLinkTargetSupplier::supportsService(const OUString& rServiceName) 3987 { 3988 return cppu::supportsService(this, rServiceName); 3989 } 3990 3991 Sequence< OUString > SwXLinkTargetSupplier::getSupportedServiceNames() 3992 { 3993 Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" }; 3994 return aRet; 3995 } 3996 3997 SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper( 3998 Reference< XNameAccess > const & xAccess, const OUString& rLinkDisplayName, const OUString& sSuffix ) : 3999 xRealAccess(xAccess), 4000 pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), 4001 sLinkSuffix(sSuffix), 4002 sLinkDisplayName(rLinkDisplayName), 4003 pxDoc(nullptr) 4004 { 4005 } 4006 4007 SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(SwXTextDocument& rxDoc, 4008 const OUString& rLinkDisplayName, const OUString& sSuffix) : 4009 pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), 4010 sLinkSuffix(sSuffix), 4011 sLinkDisplayName(rLinkDisplayName), 4012 pxDoc(&rxDoc) 4013 { 4014 } 4015 4016 SwXLinkNameAccessWrapper::~SwXLinkNameAccessWrapper() 4017 { 4018 } 4019 4020 Any SwXLinkNameAccessWrapper::getByName(const OUString& rName) 4021 { 4022 Any aRet; 4023 bool bFound = false; 4024 //cut link extension and call the real NameAccess 4025 OUString sParam = rName; 4026 OUString sSuffix(sLinkSuffix); 4027 if(sParam.getLength() > sSuffix.getLength() ) 4028 { 4029 OUString sCmp = sParam.copy(sParam.getLength() - sSuffix.getLength(), 4030 sSuffix.getLength()); 4031 if(sCmp == sSuffix) 4032 { 4033 if(pxDoc) 4034 { 4035 sParam = sParam.copy(0, sParam.getLength() - sSuffix.getLength()); 4036 if(!pxDoc->GetDocShell()) 4037 throw RuntimeException("No document shell available"); 4038 SwDoc* pDoc = pxDoc->GetDocShell()->GetDoc(); 4039 const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size(); 4040 4041 for (size_t i = 0; i < nOutlineCount && !bFound; ++i) 4042 { 4043 const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); 4044 const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); 4045 if(sParam == lcl_CreateOutlineString(i, rOutlineNodes, pOutlRule)) 4046 { 4047 Reference< XPropertySet > xOutline = new SwXOutlineTarget(sParam); 4048 aRet <<= xOutline; 4049 bFound = true; 4050 } 4051 } 4052 } 4053 else 4054 { 4055 aRet = xRealAccess->getByName(sParam.copy(0, sParam.getLength() - sSuffix.getLength())); 4056 Reference< XInterface > xInt; 4057 if(!(aRet >>= xInt)) 4058 throw RuntimeException("Could not retrieve property"); 4059 Reference< XPropertySet > xProp(xInt, UNO_QUERY); 4060 aRet <<= xProp; 4061 bFound = true; 4062 } 4063 } 4064 } 4065 if(!bFound) 4066 throw NoSuchElementException(); 4067 return aRet; 4068 } 4069 4070 Sequence< OUString > SwXLinkNameAccessWrapper::getElementNames() 4071 { 4072 Sequence< OUString > aRet; 4073 if(pxDoc) 4074 { 4075 if(!pxDoc->GetDocShell()) 4076 throw RuntimeException("No document shell available"); 4077 4078 SwDoc* pDoc = pxDoc->GetDocShell()->GetDoc(); 4079 const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); 4080 const size_t nOutlineCount = rOutlineNodes.size(); 4081 aRet.realloc(nOutlineCount); 4082 OUString* pResArr = aRet.getArray(); 4083 const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); 4084 for (size_t i = 0; i < nOutlineCount; ++i) 4085 { 4086 OUString sEntry = lcl_CreateOutlineString(i, rOutlineNodes, pOutlRule); 4087 sEntry += "|outline"; 4088 pResArr[i] = sEntry; 4089 } 4090 } 4091 else 4092 { 4093 Sequence< OUString > aOrg = xRealAccess->getElementNames(); 4094 const OUString* pOrgArr = aOrg.getConstArray(); 4095 aRet.realloc(aOrg.getLength()); 4096 OUString* pResArr = aRet.getArray(); 4097 for(long i = 0; i < aOrg.getLength(); i++) 4098 { 4099 pResArr[i] = pOrgArr[i] + sLinkSuffix; 4100 } 4101 } 4102 return aRet; 4103 } 4104 4105 sal_Bool SwXLinkNameAccessWrapper::hasByName(const OUString& rName) 4106 { 4107 bool bRet = false; 4108 OUString sParam(rName); 4109 if(sParam.getLength() > sLinkSuffix.getLength() ) 4110 { 4111 OUString sCmp = sParam.copy(sParam.getLength() - sLinkSuffix.getLength(), 4112 sLinkSuffix.getLength()); 4113 if(sCmp == sLinkSuffix) 4114 { 4115 sParam = sParam.copy(0, sParam.getLength() - sLinkSuffix.getLength()); 4116 if(pxDoc) 4117 { 4118 if(!pxDoc->GetDocShell()) 4119 throw RuntimeException("No document shell available"); 4120 SwDoc* pDoc = pxDoc->GetDocShell()->GetDoc(); 4121 const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size(); 4122 4123 for (size_t i = 0; i < nOutlineCount && !bRet; ++i) 4124 { 4125 const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); 4126 const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); 4127 if(sParam == 4128 lcl_CreateOutlineString(i, rOutlineNodes, pOutlRule)) 4129 { 4130 bRet = true; 4131 } 4132 } 4133 } 4134 else 4135 { 4136 bRet = xRealAccess->hasByName(sParam); 4137 } 4138 } 4139 } 4140 return bRet; 4141 } 4142 4143 uno::Type SwXLinkNameAccessWrapper::getElementType() 4144 { 4145 return cppu::UnoType<XPropertySet>::get(); 4146 } 4147 4148 sal_Bool SwXLinkNameAccessWrapper::hasElements() 4149 { 4150 bool bRet = false; 4151 if(pxDoc) 4152 { 4153 OSL_FAIL("not implemented"); 4154 } 4155 else 4156 { 4157 bRet = xRealAccess->hasElements(); 4158 } 4159 return bRet; 4160 } 4161 4162 Reference< XPropertySetInfo > SwXLinkNameAccessWrapper::getPropertySetInfo() 4163 { 4164 static Reference< XPropertySetInfo > xRet = pPropSet->getPropertySetInfo(); 4165 return xRet; 4166 } 4167 4168 void SwXLinkNameAccessWrapper::setPropertyValue( 4169 const OUString& , const Any& ) 4170 { 4171 throw UnknownPropertyException(); 4172 } 4173 4174 static Any lcl_GetDisplayBitmap(const OUString& _sLinkSuffix) 4175 { 4176 Any aRet; 4177 OUString sLinkSuffix = _sLinkSuffix; 4178 if(!sLinkSuffix.isEmpty()) 4179 sLinkSuffix = sLinkSuffix.copy(1); 4180 OUString sImgId; 4181 4182 if(sLinkSuffix == "outline") 4183 sImgId = RID_BMP_NAVI_OUTLINE; 4184 else if(sLinkSuffix == "table") 4185 sImgId = RID_BMP_NAVI_TABLE; 4186 else if(sLinkSuffix == "frame") 4187 sImgId = RID_BMP_NAVI_FRAME; 4188 else if(sLinkSuffix == "graphic") 4189 sImgId = RID_BMP_NAVI_GRAPHIC; 4190 else if(sLinkSuffix == "ole") 4191 sImgId = RID_BMP_NAVI_OLE; 4192 else if(sLinkSuffix.isEmpty()) 4193 sImgId = RID_BMP_NAVI_BOOKMARK; 4194 else if(sLinkSuffix == "region") 4195 sImgId = RID_BMP_NAVI_REGION; 4196 4197 if (!sImgId.isEmpty()) 4198 { 4199 aRet <<= VCLUnoHelper::CreateBitmap(BitmapEx(sImgId)); 4200 } 4201 return aRet; 4202 } 4203 4204 Any SwXLinkNameAccessWrapper::getPropertyValue(const OUString& rPropertyName) 4205 { 4206 Any aRet; 4207 if( rPropertyName == UNO_LINK_DISPLAY_NAME ) 4208 { 4209 aRet <<= sLinkDisplayName; 4210 } 4211 else if( rPropertyName == UNO_LINK_DISPLAY_BITMAP ) 4212 { 4213 aRet = lcl_GetDisplayBitmap(sLinkSuffix); 4214 } 4215 else 4216 throw UnknownPropertyException(); 4217 return aRet; 4218 } 4219 4220 void SwXLinkNameAccessWrapper::addPropertyChangeListener( 4221 const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) 4222 {} 4223 4224 void SwXLinkNameAccessWrapper::removePropertyChangeListener( 4225 const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) 4226 {} 4227 4228 void SwXLinkNameAccessWrapper::addVetoableChangeListener( 4229 const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) 4230 {} 4231 4232 void SwXLinkNameAccessWrapper::removeVetoableChangeListener( 4233 const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) 4234 {} 4235 4236 Reference< XNameAccess > SwXLinkNameAccessWrapper::getLinks() 4237 { 4238 return this; 4239 } 4240 4241 OUString SwXLinkNameAccessWrapper::getImplementationName() 4242 { 4243 return OUString("SwXLinkNameAccessWrapper"); 4244 } 4245 4246 sal_Bool SwXLinkNameAccessWrapper::supportsService(const OUString& rServiceName) 4247 { 4248 return cppu::supportsService(this, rServiceName); 4249 } 4250 4251 Sequence< OUString > SwXLinkNameAccessWrapper::getSupportedServiceNames() 4252 { 4253 Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" }; 4254 return aRet; 4255 } 4256 4257 SwXOutlineTarget::SwXOutlineTarget(const OUString& rOutlineText) : 4258 pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), 4259 sOutlineText(rOutlineText) 4260 { 4261 } 4262 4263 SwXOutlineTarget::~SwXOutlineTarget() 4264 { 4265 } 4266 4267 Reference< XPropertySetInfo > SwXOutlineTarget::getPropertySetInfo() 4268 { 4269 static Reference< XPropertySetInfo > xRet = pPropSet->getPropertySetInfo(); 4270 return xRet; 4271 } 4272 4273 void SwXOutlineTarget::setPropertyValue( 4274 const OUString& /*PropertyName*/, const Any& /*aValue*/) 4275 { 4276 throw UnknownPropertyException(); 4277 } 4278 4279 Any SwXOutlineTarget::getPropertyValue(const OUString& rPropertyName) 4280 { 4281 if(rPropertyName != UNO_LINK_DISPLAY_NAME) 4282 throw UnknownPropertyException(); 4283 4284 return Any(sOutlineText); 4285 } 4286 4287 void SwXOutlineTarget::addPropertyChangeListener( 4288 const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) 4289 { 4290 } 4291 4292 void SwXOutlineTarget::removePropertyChangeListener( 4293 const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) 4294 { 4295 } 4296 4297 void SwXOutlineTarget::addVetoableChangeListener( 4298 const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) 4299 { 4300 } 4301 4302 void SwXOutlineTarget::removeVetoableChangeListener( 4303 const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) 4304 { 4305 } 4306 4307 OUString SwXOutlineTarget::getImplementationName() 4308 { 4309 return OUString("SwXOutlineTarget"); 4310 } 4311 4312 sal_Bool SwXOutlineTarget::supportsService(const OUString& ServiceName) 4313 { 4314 return cppu::supportsService(this, ServiceName); 4315 } 4316 4317 Sequence< OUString > SwXOutlineTarget::getSupportedServiceNames() 4318 { 4319 Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" }; 4320 4321 return aRet; 4322 } 4323 4324 SwXDocumentPropertyHelper::SwXDocumentPropertyHelper(SwDoc& rDoc) : 4325 SvxUnoForbiddenCharsTable ( rDoc.getIDocumentSettingAccess().getForbiddenCharacterTable() ) 4326 ,m_pDoc(&rDoc) 4327 { 4328 } 4329 4330 SwXDocumentPropertyHelper::~SwXDocumentPropertyHelper() 4331 { 4332 } 4333 4334 Reference<XInterface> SwXDocumentPropertyHelper::GetDrawTable(SwCreateDrawTable nWhich) 4335 { 4336 Reference<XInterface> xRet; 4337 if(m_pDoc) 4338 { 4339 switch(nWhich) 4340 { 4341 // #i52858# 4342 // assure that Draw model is created, if it doesn't exist. 4343 case SwCreateDrawTable::Dash : 4344 if(!xDashTable.is()) 4345 xDashTable = SvxUnoDashTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); 4346 xRet = xDashTable; 4347 break; 4348 case SwCreateDrawTable::Gradient : 4349 if(!xGradientTable.is()) 4350 xGradientTable = SvxUnoGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); 4351 xRet = xGradientTable; 4352 break; 4353 case SwCreateDrawTable::Hatch : 4354 if(!xHatchTable.is()) 4355 xHatchTable = SvxUnoHatchTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); 4356 xRet = xHatchTable; 4357 break; 4358 case SwCreateDrawTable::Bitmap : 4359 if(!xBitmapTable.is()) 4360 xBitmapTable = SvxUnoBitmapTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); 4361 xRet = xBitmapTable; 4362 break; 4363 case SwCreateDrawTable::TransGradient: 4364 if(!xTransGradientTable.is()) 4365 xTransGradientTable = SvxUnoTransGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); 4366 xRet = xTransGradientTable; 4367 break; 4368 case SwCreateDrawTable::Marker : 4369 if(!xMarkerTable.is()) 4370 xMarkerTable = SvxUnoMarkerTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); 4371 xRet = xMarkerTable; 4372 break; 4373 case SwCreateDrawTable::Defaults: 4374 if(!xDrawDefaults.is()) 4375 xDrawDefaults = static_cast<cppu::OWeakObject*>(new SwSvxUnoDrawPool(m_pDoc)); 4376 xRet = xDrawDefaults; 4377 break; 4378 #if OSL_DEBUG_LEVEL > 0 4379 default: OSL_FAIL("which table?"); 4380 #endif 4381 } 4382 } 4383 return xRet; 4384 } 4385 4386 void SwXDocumentPropertyHelper::Invalidate() 4387 { 4388 xDashTable = nullptr; 4389 xGradientTable = nullptr; 4390 xHatchTable = nullptr; 4391 xBitmapTable = nullptr; 4392 xTransGradientTable = nullptr; 4393 xMarkerTable = nullptr; 4394 xDrawDefaults = nullptr; 4395 m_pDoc = nullptr; 4396 SvxUnoForbiddenCharsTable::mxForbiddenChars.reset(); 4397 } 4398 4399 void SwXDocumentPropertyHelper::onChange() 4400 { 4401 if(m_pDoc) 4402 m_pDoc->getIDocumentState().SetModified(); 4403 } 4404 4405 SwViewOptionAdjust_Impl::SwViewOptionAdjust_Impl( 4406 SwViewShell& rSh, const SwViewOption &rViewOptions) 4407 : m_pShell(&rSh) 4408 , m_aOldViewOptions( rViewOptions ) 4409 { 4410 } 4411 4412 SwViewOptionAdjust_Impl::~SwViewOptionAdjust_Impl() 4413 { 4414 if (m_pShell) 4415 { 4416 m_pShell->ApplyViewOptions( m_aOldViewOptions ); 4417 } 4418 } 4419 4420 void 4421 SwViewOptionAdjust_Impl::AdjustViewOptions(SwPrintData const*const pPrtOptions, bool setShowPlaceHoldersInPDF) 4422 { 4423 // to avoid unnecessary reformatting the view options related to the content 4424 // below should only change if necessary, that is if respective content is present 4425 const bool bContainsHiddenChars = m_pShell->GetDoc()->ContainsHiddenChars(); 4426 const SwFieldType* pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText ); 4427 const bool bContainsHiddenFields = pFieldType && pFieldType->HasWriterListeners(); 4428 pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenPara ); 4429 const bool bContainsHiddenParagraphs = pFieldType && pFieldType->HasWriterListeners(); 4430 pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::JumpEdit ); 4431 const bool bContainsPlaceHolders = pFieldType && pFieldType->HasWriterListeners(); 4432 const bool bContainsFields = m_pShell->IsAnyFieldInDoc(); 4433 4434 SwViewOption aRenderViewOptions( m_aOldViewOptions ); 4435 4436 // disable anything in the view that should not be printed (or exported to PDF) by default 4437 // (see also dialog "Tools/Options - StarOffice Writer - Formatting Aids" 4438 // in section "Display of ...") 4439 aRenderViewOptions.SetParagraph( false ); // paragraph end 4440 aRenderViewOptions.SetSoftHyph( false ); // aka custom hyphens 4441 aRenderViewOptions.SetBlank( false ); // spaces 4442 aRenderViewOptions.SetHardBlank( false ); // non-breaking spaces 4443 aRenderViewOptions.SetTab( false ); // tabs 4444 aRenderViewOptions.SetLineBreak( false ); // breaks (type 1) 4445 aRenderViewOptions.SetPageBreak( false ); // breaks (type 2) 4446 aRenderViewOptions.SetColumnBreak( false ); // breaks (type 3) 4447 bool bVal = pPrtOptions && pPrtOptions->m_bPrintHiddenText; 4448 if (bContainsHiddenChars) 4449 aRenderViewOptions.SetShowHiddenChar( bVal ); // hidden text 4450 if (bContainsHiddenFields) 4451 aRenderViewOptions.SetShowHiddenField( bVal ); 4452 if (bContainsHiddenParagraphs) 4453 aRenderViewOptions.SetShowHiddenPara( bVal ); 4454 4455 if (bContainsPlaceHolders) 4456 { 4457 // should always be printed in PDF export! 4458 bVal = !pPrtOptions ? setShowPlaceHoldersInPDF : pPrtOptions->m_bPrintTextPlaceholder; 4459 aRenderViewOptions.SetShowPlaceHolderFields( bVal ); 4460 } 4461 4462 if (bContainsFields) 4463 aRenderViewOptions.SetFieldName( false ); 4464 4465 // we need to set this flag in order to get to see the visible effect of 4466 // some of the above settings (needed for correct rendering) 4467 aRenderViewOptions.SetViewMetaChars( true ); 4468 4469 if (m_aOldViewOptions != aRenderViewOptions) // check if reformatting is necessary 4470 { 4471 aRenderViewOptions.SetPrinting( pPrtOptions != nullptr ); 4472 m_pShell->ApplyViewOptions( aRenderViewOptions ); 4473 } 4474 } 4475 4476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 4477
