LibreOffice Module sc (master)  1
docuno.cxx
Go to the documentation of this file.
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 <config_feature_opencl.h>
21 
22 #include <scitems.hxx>
23 
25 #include <comphelper/sequence.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <editeng/editview.hxx>
28 #include <editeng/memberids.h>
29 #include <editeng/outliner.hxx>
30 #include <o3tl/any.hxx>
31 #include <o3tl/safeint.hxx>
32 #include <svx/fmview.hxx>
33 #include <svx/svditer.hxx>
34 #include <svx/svdpage.hxx>
35 #include <svx/svxids.hrc>
36 
37 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
39 #include <officecfg/Office/Common.hxx>
40 #include <officecfg/Office/Calc.hxx>
41 #include <svl/numuno.hxx>
42 #include <svl/hint.hxx>
44 #include <sfx2/bindings.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <svx/unopage.hxx>
48 #include <vcl/pdfextoutdevdata.hxx>
49 #include <vcl/print.hxx>
50 #include <vcl/svapp.hxx>
51 #include <tools/json_writer.hxx>
52 #include <tools/multisel.hxx>
53 #include <tools/UnitConversion.hxx>
55 
56 #include <float.h>
57 
58 #include <com/sun/star/beans/PropertyAttribute.hpp>
59 #include <com/sun/star/util/Date.hpp>
60 #include <com/sun/star/sheet/XNamedRanges.hpp>
61 #include <com/sun/star/sheet/XLabelRanges.hpp>
62 #include <com/sun/star/sheet/XSelectedSheetsSupplier.hpp>
63 #include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
64 #include <com/sun/star/i18n/XForbiddenCharacters.hpp>
65 #include <com/sun/star/script/XLibraryContainer.hpp>
66 #include <com/sun/star/lang/XInitialization.hpp>
67 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
68 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
69 #include <com/sun/star/document/IndexedPropertyValues.hpp>
70 #include <com/sun/star/script/XInvocation.hpp>
71 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
72 #include <com/sun/star/beans/XFastPropertySet.hpp>
73 #include <comphelper/lok.hxx>
77 #include <comphelper/string.hxx>
79 #if HAVE_FEATURE_OPENCL
80 #include <opencl/platforminfo.hxx>
81 #endif
82 #include <sfx2/lokhelper.hxx>
85 
86 #include <cellsuno.hxx>
87 #include <columnspanset.hxx>
88 #include <convuno.hxx>
89 #include <datauno.hxx>
90 #include <docfunc.hxx>
91 #include <docoptio.hxx>
92 #include <docsh.hxx>
93 #include <docuno.hxx>
94 #include <drwlayer.hxx>
95 #include <forbiuno.hxx>
96 #include <formulagroup.hxx>
97 #include <gridwin.hxx>
98 #include <hints.hxx>
99 #include <inputhdl.hxx>
100 #include <inputopt.hxx>
101 #include <interpre.hxx>
102 #include <linkuno.hxx>
103 #include <markdata.hxx>
104 #include <miscuno.hxx>
105 #include <nameuno.hxx>
106 #include <notesuno.hxx>
107 #include <optuno.hxx>
108 #include <pfuncache.hxx>
109 #include <postit.hxx>
110 #include <printfun.hxx>
111 #include <rangeutl.hxx>
112 #include <scmod.hxx>
113 #include <scresid.hxx>
114 #include <servuno.hxx>
115 #include <shapeuno.hxx>
116 #include <sheetevents.hxx>
117 #include <styleuno.hxx>
118 #include <tabvwsh.hxx>
119 #include <targuno.hxx>
120 #include <unonames.hxx>
122 #include <editsh.hxx>
123 #include <drawsh.hxx>
124 #include <drtxtob.hxx>
125 #include <transobj.hxx>
126 #include <chgtrack.hxx>
127 #include <table.hxx>
128 #include <appoptio.hxx>
129 #include <formulaopt.hxx>
130 
131 #include <strings.hrc>
132 
133 using namespace com::sun::star;
134 
135 // #i111553# provides the name of the VBA constant for this document type (e.g. 'ThisExcelDoc' for Calc)
136 constexpr OUStringLiteral SC_UNO_VBAGLOBNAME = u"VBAGlobalConstantName";
137 
138 // no Which-ID here, map only for PropertySetInfo
139 
142 {
143  static const SfxItemPropertyMapEntry aDocOptPropertyMap_Impl[] =
144  {
148  { SC_UNO_BASICLIBRARIES, 0, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
149  { SC_UNO_DIALOGLIBRARIES, 0, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0},
150  { SC_UNO_VBAGLOBNAME, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
159  { SC_UNO_FORBIDDEN, 0, cppu::UnoType<i18n::XForbiddenCharacters>::get(), beans::PropertyAttribute::READONLY, 0},
160  { SC_UNO_HASDRAWPAGES, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
176  { SC_UNO_RUNTIMEUID, 0, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0},
177  { SC_UNO_HASVALIDSIGNATURES, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
181  { SC_UNO_ISRECORDCHANGESPROTECTED,0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::READONLY, 0},
185  { SC_UNO_REFERENCEDEVICE, 0, cppu::UnoType<awt::XDevice>::get(), beans::PropertyAttribute::READONLY, 0},
186  {u"BuildId", 0, ::cppu::UnoType<OUString>::get(), 0, 0},
189  { u"", 0, css::uno::Type(), 0, 0 }
190  };
191  return aDocOptPropertyMap_Impl;
192 }
193 
195 
197 {
198  static const SfxItemPropertyMapEntry aColumnsPropertyMap_Impl[] =
199  {
205  { u"", 0, css::uno::Type(), 0, 0 }
206  };
207  return aColumnsPropertyMap_Impl;
208 }
209 
211 {
212  static const SfxItemPropertyMapEntry aRowsPropertyMap_Impl[] =
213  {
222  // not sorted, not used with SfxItemPropertyMapEntry::GetByName
223  { u"", 0, css::uno::Type(), 0, 0 }
224  };
225  return aRowsPropertyMap_Impl;
226 }
227 
228 constexpr OUStringLiteral SCMODELOBJ_SERVICE = u"com.sun.star.sheet.SpreadsheetDocument";
229 constexpr OUStringLiteral SCDOCSETTINGS_SERVICE = u"com.sun.star.sheet.SpreadsheetDocumentSettings";
230 constexpr OUStringLiteral SCDOC_SERVICE = u"com.sun.star.document.OfficeDocument";
231 
232 SC_SIMPLE_SERVICE_INFO( ScAnnotationsObj, "ScAnnotationsObj", "com.sun.star.sheet.CellAnnotations" )
233 SC_SIMPLE_SERVICE_INFO( ScDrawPagesObj, "ScDrawPagesObj", "com.sun.star.drawing.DrawPages" )
234 SC_SIMPLE_SERVICE_INFO( ScScenariosObj, "ScScenariosObj", "com.sun.star.sheet.Scenarios" )
235 SC_SIMPLE_SERVICE_INFO( ScSpreadsheetSettingsObj, "ScSpreadsheetSettingsObj", "com.sun.star.sheet.SpreadsheetDocumentSettings" )
236 SC_SIMPLE_SERVICE_INFO( ScTableColumnsObj, "ScTableColumnsObj", "com.sun.star.table.TableColumns" )
237 SC_SIMPLE_SERVICE_INFO( ScTableRowsObj, "ScTableRowsObj", "com.sun.star.table.TableRows" )
238 SC_SIMPLE_SERVICE_INFO( ScTableSheetsObj, "ScTableSheetsObj", "com.sun.star.sheet.Spreadsheets" )
239 
240 class ScPrintUIOptions : public vcl::PrinterOptionsHelper
241 {
242 public:
244  void SetDefaults();
245 };
246 
248 {
249  const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
250  sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
251  bool bSuppress = rPrintOpt.GetSkipEmpty();
252 
253  sal_Int32 nNumProps= 10, nIdx = 0;
254 
255  m_aUIProperties.resize(nNumProps);
256 
257  // load the writer PrinterOptions into the custom tab
258  m_aUIProperties[nIdx].Name = "OptionsUIFile";
259  m_aUIProperties[nIdx++].Value <<= OUString("modules/scalc/ui/printeroptions.ui");
260 
261  // create Section for spreadsheet (results in an extra tab page in dialog)
262  SvtModuleOptions aOpt;
263  OUString aAppGroupname( ScResId( SCSTR_PRINTOPT_PRODNAME ) );
264  aAppGroupname = aAppGroupname.replaceFirst( "%s", aOpt.GetModuleName( SvtModuleOptions::EModule::CALC ) );
265  m_aUIProperties[nIdx++].Value = setGroupControlOpt("tabcontrol-page2", aAppGroupname, OUString());
266 
267  // show subgroup for pages
268  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("pages", ScResId( SCSTR_PRINTOPT_PAGES ), OUString());
269 
270  // create a bool option for empty pages
271  m_aUIProperties[nIdx++].Value = setBoolControlOpt("suppressemptypages", ScResId( SCSTR_PRINTOPT_SUPPRESSEMPTY ),
272  ".HelpID:vcl:PrintDialog:IsSuppressEmptyPages:CheckBox",
273  "IsSuppressEmptyPages",
274  bSuppress);
275  // show Subgroup for print content
277  aPrintRangeOpt.maGroupHint = "PrintRange";
278  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("printrange", ScResId( SCSTR_PRINTOPT_PAGES ),
279  OUString(),
280  aPrintRangeOpt);
281 
282  // create a choice for the content to create
283  uno::Sequence< OUString > aChoices{
284  ScResId( SCSTR_PRINTOPT_ALLSHEETS ),
285  ScResId( SCSTR_PRINTOPT_SELECTEDSHEETS ),
286  ScResId( SCSTR_PRINTOPT_SELECTEDCELLS )};
287  uno::Sequence< OUString > aHelpIds{
288  ".HelpID:vcl:PrintDialog:PrintContent:ListBox"};
289  m_aUIProperties[nIdx++].Value = setChoiceListControlOpt( "printextrabox", OUString(),
290  aHelpIds, "PrintContent",
291  aChoices, nContent );
292 
293  // show Subgroup for print range
294  aPrintRangeOpt.mbInternalOnly = true;
295  m_aUIProperties[nIdx++].Value = setSubgroupControlOpt("fromwhich", ScResId( SCSTR_PRINTOPT_FROMWHICH ),
296  OUString(),
297  aPrintRangeOpt);
298 
299  // create a choice for the range to print
300  OUString aPrintRangeName( "PrintRange" );
301  aChoices = { ScResId( SCSTR_PRINTOPT_PRINTALLPAGES ), ScResId( SCSTR_PRINTOPT_PRINTPAGES ) };
302  aHelpIds = { ".HelpID:vcl:PrintDialog:PrintRange:RadioButton:0",
303  ".HelpID:vcl:PrintDialog:PrintRange:RadioButton:1" };
304  uno::Sequence< OUString > aWidgetIds{ "rbAllPages", "rbRangePages" };
305  m_aUIProperties[nIdx++].Value = setChoiceRadiosControlOpt(aWidgetIds, OUString(),
306  aHelpIds,
307  aPrintRangeName,
308  aChoices,
309  0 );
310 
311  // create an Edit dependent on "Pages" selected
312  vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, true );
313  m_aUIProperties[nIdx++].Value = setEditControlOpt("pagerange", OUString(),
314  ".HelpID:vcl:PrintDialog:PageRange:Edit",
315  "PageRange", OUString(), aPageRangeOpt);
316 
317  vcl::PrinterOptionsHelper::UIControlOptions aEvenOddOpt(aPrintRangeName, 0, true);
318  m_aUIProperties[ nIdx++ ].Value = setChoiceListControlOpt("evenoddbox",
319  OUString(),
320  uno::Sequence<OUString>(),
321  "EvenOdd",
322  uno::Sequence<OUString>(),
323  0,
324  uno::Sequence< sal_Bool >(),
325  aEvenOddOpt);
326 
327  assert(nIdx == nNumProps);
328 }
329 
331 {
332  // re-initialize the default values from print options
333 
334  const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions();
335  sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1;
336  bool bSuppress = rPrintOpt.GetSkipEmpty();
337 
338  for (beans::PropertyValue & rPropValue : m_aUIProperties)
339  {
340  uno::Sequence<beans::PropertyValue> aUIProp;
341  if ( rPropValue.Value >>= aUIProp )
342  {
343  for (auto& rProp : asNonConstRange(aUIProp))
344  {
345  OUString aName = rProp.Name;
346  if ( aName == "Property" )
347  {
348  beans::PropertyValue aPropertyValue;
349  if ( rProp.Value >>= aPropertyValue )
350  {
351  if ( aPropertyValue.Name == "PrintContent" )
352  {
353  aPropertyValue.Value <<= nContent;
354  rProp.Value <<= aPropertyValue;
355  }
356  else if ( aPropertyValue.Name == "IsSuppressEmptyPages" )
357  {
358  aPropertyValue.Value <<= bSuppress;
359  rProp.Value <<= aPropertyValue;
360  }
361  }
362  }
363  }
364  rPropValue.Value <<= aUIProp;
365  }
366  }
367 }
368 
370 {
371  if (pDocSh)
372  pDocSh->SetBaseModel( new ScModelObj(pDocSh) );
373 }
374 
376 {
377  ScDocument& rDoc(pDocShell->GetDocument());
378 
379  if(!rDoc.GetDrawLayer())
380  {
381  rDoc.InitDrawLayer();
382  }
383 
384  return *rDoc.GetDrawLayer(); // TTTT should be reference
385 }
386 
388  SfxBaseModel( pDocSh ),
389  aPropSet( lcl_GetDocOptPropertyMap() ),
390  pDocShell( pDocSh ),
391  maChangesListeners( m_aMutex )
392 {
393  // pDocShell may be NULL if this is the base of a ScDocOptionsObj
394  if ( pDocShell )
395  {
396  pDocShell->GetDocument().AddUnoObject(*this); // SfxModel is derived from SfxListener
397  }
398 }
399 
401 {
402  SolarMutexGuard g;
403 
404  if (pDocShell)
406 
407  if (xNumberAgg.is())
408  xNumberAgg->setDelegator(uno::Reference<uno::XInterface>());
409 
410  pPrintFuncCache.reset();
411  pPrinterOptions.reset();
412 }
413 
414 uno::Reference< uno::XAggregation> const & ScModelObj::GetFormatter()
415 {
416  // pDocShell may be NULL if this is the base of a ScDocOptionsObj
417  if ( !xNumberAgg.is() && pDocShell )
418  {
419  // setDelegator changes RefCount, so we'd better hold the reference ourselves
420  // (directly in m_refCount, so we don't delete ourselves with release())
421  osl_atomic_increment( &m_refCount );
422  // we need a reference to SvNumberFormatsSupplierObj during queryInterface,
423  // otherwise it'll be deleted
424  uno::Reference<util::XNumberFormatsSupplier> xFormatter(
426  {
427  xNumberAgg.set(uno::Reference<uno::XAggregation>( xFormatter, uno::UNO_QUERY ));
428  // extra block to force deletion of the temporary before setDelegator
429  }
430 
431  // during setDelegator no additional reference should exist
432  xFormatter = nullptr;
433 
434  if (xNumberAgg.is())
435  xNumberAgg->setDelegator( static_cast<cppu::OWeakObject*>(this) );
436  osl_atomic_decrement( &m_refCount );
437  } // if ( !xNumberAgg.is() )
438  return xNumberAgg;
439 }
440 
442 {
443  if (pDocShell)
444  return &pDocShell->GetDocument();
445  return nullptr;
446 }
447 
449 {
450  return pDocShell;
451 }
452 
454 {
455  if (pDocShell)
457 }
458 
460 {
461  if (pDocShell)
463 }
464 
466 {
467  if (pDocShell)
468  pDocShell->AfterXMLLoading(true);
469 }
470 
472 {
473  if (pDocShell)
474  return pDocShell->GetSheetSaveData();
475  return nullptr;
476 }
477 
479 {
480  if (pDocShell)
481  return pDocShell->GetFormatSaveData();
482  return nullptr;
483 }
484 
485 void ScModelObj::RepaintRange( const ScRange& rRange )
486 {
487  if (pDocShell)
489 }
490 
492 {
493  if (pDocShell)
495 }
496 
498  const Fraction& rZoomY,
499  const SCTAB nTab,
500  const ViewShellDocId& rDocId)
501 {
502  constexpr size_t nMaxIter = 5;
503  size_t nIter = 0;
504  for (SfxViewShell* pViewShell = SfxViewShell::GetFirst();
505  pViewShell && nIter < nMaxIter;
506  (pViewShell = SfxViewShell::GetNext(*pViewShell)), ++nIter)
507  {
508  if (pViewShell->GetDocId() != rDocId)
509  continue;
510 
511  ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
512  if (!pTabViewShell)
513  continue;
514 
515  ScViewData& rData = pTabViewShell->GetViewData();
516  if (rData.GetTabNo() == nTab && rData.GetZoomX() == rZoomX && rData.GetZoomY() == rZoomY)
517  return &rData;
518  }
519 
520  return nullptr;
521 }
522 
524  int nOutputWidth, int nOutputHeight,
525  int nTilePosX, int nTilePosY,
526  tools::Long nTileWidth, tools::Long nTileHeight )
527 {
528  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
529 
530  // FIXME: Can this happen? What should we do?
531  if (!pViewShell)
532  return;
533 
534  ScViewData* pActiveViewData = &pViewShell->GetViewData();
535  Fraction aFracX(o3tl::toTwips(nOutputWidth, o3tl::Length::px), nTileWidth);
536  Fraction aFracY(o3tl::toTwips(nOutputHeight, o3tl::Length::px), nTileHeight);
537 
538  // Try to find a view that matches the tile-zoom requested by iterating over
539  // first few shells. This is to avoid switching of zooms in ScGridWindow::PaintTile
540  // and hence avoid grid-offset recomputation on all shapes which is not cheap.
541  ScViewData* pViewData = lcl_getViewMatchingDocZoomTab(aFracX, aFracY,
542  pActiveViewData->GetTabNo(), pViewShell->GetDocId());
543  if (!pViewData)
544  pViewData = pActiveViewData;
545 
546  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
547 
548  // update the size of the area we are painting
549  // FIXME we want to use only the minimal necessary size, like the
550  // following; but for the moment there is too many problems with that and
551  // interaction with editeng used for the cell editing
552  //Size aTileSize(nOutputWidth, nOutputHeight);
553  //if (pGridWindow->GetOutputSizePixel() != aTileSize)
554  // pGridWindow->SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
555  // so instead for now, set the viewport size to document size
556  Size aDocSize = getDocumentSize();
557  pGridWindow->SetOutputSizePixel(Size(aDocSize.Width() * pViewData->GetPPTX(), aDocSize.Height() * pViewData->GetPPTY()));
558 
559  pGridWindow->PaintTile( rDevice, nOutputWidth, nOutputHeight,
560  nTilePosX, nTilePosY, nTileWidth, nTileHeight );
561 
562  // Draw Form controls
563  ScDrawLayer* pDrawLayer = pDocShell->GetDocument().GetDrawLayer();
564  SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(pViewData->GetTabNo()));
565  SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView();
566  tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
567  Size aOutputSize(nOutputWidth, nOutputHeight);
568  LokControlHandler::paintControlTile(pPage, pDrawView, *pGridWindow, rDevice, aOutputSize, aTileRect);
569 }
570 
571 void ScModelObj::setPart( int nPart, bool /*bAllowChangeFocus*/ )
572 {
573  ScViewData* pViewData = ScDocShell::GetViewData();
574  ScTabView* pTabView = pViewData->GetView();
575 
576  if (pTabView)
577  {
578  if (SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView())
579  pDrawView->SetNegativeX(comphelper::LibreOfficeKit::isActive() &&
580  pViewData->GetDocument().IsLayoutRTL(nPart));
581 
582  pTabView->SelectTabPage(nPart + 1);
583  }
584 }
585 
587 {
588  ScDocument& rDoc = pDocShell->GetDocument();
589  return rDoc.GetTableCount();
590 }
591 
593 {
594  ScViewData* pViewData = ScDocShell::GetViewData();
595  return pViewData ? pViewData->GetViewShell()->getPart() : 0;
596 }
597 
598 OUString ScModelObj::getPartInfo( int nPart )
599 {
600  ScViewData* pViewData = ScDocShell::GetViewData();
601  const bool bIsVisible = pViewData->GetDocument().IsVisible(nPart);
602  //FIXME: Implement IsSelected().
603  const bool bIsSelected = false; //pViewData->GetDocument()->IsSelected(nPart);
604  const bool bIsRTLLayout = pViewData->GetDocument().IsLayoutRTL(nPart);
605 
606  OUString aPartInfo = "{ \"visible\": \"" +
607  OUString::number(static_cast<unsigned int>(bIsVisible)) +
608  "\", \"selected\": \"" +
609  OUString::number(static_cast<unsigned int>(bIsSelected)) +
610  "\", \"rtllayout\": \"" +
611  OUString::number(static_cast<unsigned int>(bIsRTLLayout)) +
612  "\" }";
613  return aPartInfo;
614 }
615 
616 OUString ScModelObj::getPartName( int nPart )
617 {
618  OUString sTabName;
619  ScViewData* pViewData = ScDocShell::GetViewData();
620  pViewData->GetDocument().GetName(nPart, sTabName);
621  return sTabName;
622 }
623 
624 OUString ScModelObj::getPartHash( int nPart )
625 {
626  sal_Int64 nHashCode;
627  ScViewData* pViewData = ScDocShell::GetViewData();
628  return (pViewData->GetDocument().GetHashCode(nPart, nHashCode) ? OUString::number(nHashCode) : OUString());
629 }
630 
632 {
633  SolarMutexGuard aGuard;
634 
635  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
636 
637  // FIXME: Can this happen? What should we do?
638  if (!pViewShell)
639  return VclPtr<vcl::Window>();
640 
641  ScViewData* pViewData = &pViewShell->GetViewData();
642 
643  VclPtr<vcl::Window> pWindow;
644  if (pViewData)
645  {
646  pWindow = pViewData->GetActiveWin();
647 
648  LokChartHelper aChartHelper(pViewData->GetViewShell());
649  vcl::Window* pChartWindow = aChartHelper.GetWindow();
650  if (pChartWindow)
651  pWindow = pChartWindow;
652  }
653 
654  return pWindow;
655 }
656 
658 {
659  Size aSize(10, 10); // minimum size
660 
661  ScViewData* pViewData = ScDocShell::GetViewData();
662  if (!pViewData)
663  return aSize;
664 
665  SCTAB nTab = pViewData->GetTabNo();
666  SCCOL nEndCol = 0;
667  SCROW nEndRow = 0;
668  const ScDocument& rDoc = pDocShell->GetDocument();
669 
670  rDoc.GetTiledRenderingArea(nTab, nEndCol, nEndRow);
671 
672  const ScDocument* pThisDoc = &rDoc;
673  const double fPPTX = pViewData->GetPPTX();
674  const double fPPTY = pViewData->GetPPTY();
675 
676  auto GetColWidthPx = [pThisDoc, fPPTX, nTab](SCCOL nCol) {
677  const sal_uInt16 nSize = pThisDoc->GetColWidth(nCol, nTab);
678  return ScViewData::ToPixel(nSize, fPPTX);
679  };
680 
681  tools::Long nDocWidthPixel = pViewData->GetLOKWidthHelper().computePosition(nEndCol, GetColWidthPx);
682  tools::Long nDocHeightPixel = pThisDoc->GetScaledRowHeight(0, nEndRow, nTab, fPPTY);
683 
684  if (nDocWidthPixel > 0 && nDocHeightPixel > 0)
685  {
686  // convert to twips
687  aSize.setWidth(nDocWidthPixel / fPPTX);
688  aSize.setHeight(nDocHeightPixel / fPPTY);
689  }
690  else
691  {
692  // convert to twips
693  aSize.setWidth(rDoc.GetColWidth(0, nEndCol, nTab));
694  aSize.setHeight(rDoc.GetRowHeight(0, nEndRow, nTab));
695  }
696 
697  return aSize;
698 }
699 
700 
701 void ScModelObj::postKeyEvent(int nType, int nCharCode, int nKeyCode)
702 {
703  SolarMutexGuard aGuard;
704  SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode);
705 }
706 
707 void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
708 {
709  SolarMutexGuard aGuard;
710 
711  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
712 
713  // FIXME: Can this happen? What should we do?
714  if (!pViewShell)
715  return;
716 
717  ScViewData* pViewData = &pViewShell->GetViewData();
718 
719  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
720 
721  if (!pGridWindow)
722  return;
723 
724  // check if user hit a chart which is being edited by him
725  ScTabViewShell * pTabViewShell = pViewData->GetViewShell();
726  SCTAB nTab = pViewData->GetTabNo();
727  const ScDocument& rDoc = pDocShell->GetDocument();
728  // In LOK RTL mode draw/svx operates in negative X coordinates
729  // But the coordinates from client is always positive, so negate nX for draw.
730  bool bDrawNegativeX = rDoc.IsNegativePage(nTab);
731  LokChartHelper aChartHelper(pTabViewShell, bDrawNegativeX);
732  int nDrawX = bDrawNegativeX ? -nX : nX;
733  if (aChartHelper.postMouseEvent(nType, nDrawX, nY,
734  nCount, nButtons, nModifier,
735  pViewData->GetPPTX(), pViewData->GetPPTY()))
736  {
737  return;
738  }
739 
740  Point aPointTwip(nX, nY);
741  Point aPointTwipDraw(nDrawX, nY);
742 
743  // check if the user hit a chart which is being edited by someone else
744  // and, if so, skip current mouse event
745  if (nType != LOK_MOUSEEVENT_MOUSEMOVE)
746  {
747  if (LokChartHelper::HitAny(aPointTwipDraw, bDrawNegativeX))
748  return;
749  }
750 
751  // Check if a control is hit
752  Point aPointHMM = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100);
753  Point aPointHMMDraw(bDrawNegativeX ? -aPointHMM.X() : aPointHMM.X(), aPointHMM.Y());
754  ScDrawLayer* pDrawLayer = pDocShell->GetDocument().GetDrawLayer();
755  SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(nTab));
756  SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView();
757  if (LokControlHandler::postMouseEvent(pPage, pDrawView, *pGridWindow, nType, aPointHMMDraw, nCount, nButtons, nModifier))
758  return;
759 
760  if (!pGridWindow->HasChildPathFocus(true))
761  pGridWindow->GrabFocus();
762 
763  // Calc operates in pixels...
764  const Point aPosition(nX * pViewData->GetPPTX() + pGridWindow->GetOutOffXPixel(),
765  nY * pViewData->GetPPTY() + pGridWindow->GetOutOffYPixel());
766 
767  VclEventId aEvent = VclEventId::NONE;
768  MouseEvent aData(aPosition, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
769  aData.setLogicPosition(aPointHMM);
770  switch (nType)
771  {
772  case LOK_MOUSEEVENT_MOUSEBUTTONDOWN:
773  aEvent = VclEventId::WindowMouseButtonDown;
774  break;
775  case LOK_MOUSEEVENT_MOUSEBUTTONUP:
776  aEvent = VclEventId::WindowMouseButtonUp;
777  break;
778  case LOK_MOUSEEVENT_MOUSEMOVE:
779  aEvent = VclEventId::WindowMouseMove;
780  break;
781  default:
782  break;
783  }
784 
785  Application::LOKHandleMouseEvent(aEvent, pGridWindow, &aData);
786 }
787 
788 void ScModelObj::setTextSelection(int nType, int nX, int nY)
789 {
790  SolarMutexGuard aGuard;
791  ScViewData* pViewData = ScDocShell::GetViewData();
792  ScTabViewShell* pViewShell = pViewData->GetViewShell();
793 
794  LokChartHelper aChartHelper(pViewShell);
795  if (aChartHelper.setTextSelection(nType, nX, nY))
796  return;
797 
798  ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewShell);
799  ScDrawView* pDrawView = pViewData->GetScDrawView();
800 
801  bool bHandled = false;
802 
803  if (pInputHandler && pInputHandler->IsInputMode())
804  {
805  // forwarding to editeng - we are editing the cell content
806  EditView* pTableView = pInputHandler->GetTableView();
807  assert(pTableView);
808 
810 
811  if (pTableView->GetOutputArea().Contains(aPoint))
812  {
813  switch (nType)
814  {
815  case LOK_SETTEXTSELECTION_START:
816  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
817  break;
818  case LOK_SETTEXTSELECTION_END:
819  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
820  break;
821  case LOK_SETTEXTSELECTION_RESET:
822  pTableView->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
823  break;
824  default:
825  assert(false);
826  break;
827  }
828  bHandled = true;
829  }
830  }
831  else if (pDrawView && pDrawView->IsTextEdit())
832  {
833  // forwarding to editeng - we are editing the text in shape
834  OutlinerView* pOutlinerView = pDrawView->GetTextEditOutlinerView();
835  EditView& rEditView = pOutlinerView->GetEditView();
836 
838  switch (nType)
839  {
840  case LOK_SETTEXTSELECTION_START:
841  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
842  break;
843  case LOK_SETTEXTSELECTION_END:
844  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
845  break;
846  case LOK_SETTEXTSELECTION_RESET:
847  rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
848  break;
849  default:
850  assert(false);
851  break;
852  }
853  bHandled = true;
854  }
855 
856  if (!bHandled)
857  {
858  // just update the cell selection
859  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
860  if (!pGridWindow)
861  return;
862 
863  // move the cell selection handles
864  pGridWindow->SetCellSelectionPixel(nType, nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
865  }
866 }
867 
868 uno::Reference<datatransfer::XTransferable> ScModelObj::getSelection()
869 {
870  SolarMutexGuard aGuard;
871 
872  TransferableDataHelper aDataHelper;
873  ScViewData* pViewData = ScDocShell::GetViewData();
874  uno::Reference<datatransfer::XTransferable> xTransferable;
875 
876  if ( ScEditShell * pShell = dynamic_cast<ScEditShell*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ) )
877  xTransferable = pShell->GetEditView()->GetTransferable();
878  else if ( nullptr != dynamic_cast<ScDrawTextObjectBar*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ))
879  {
880  ScDrawView* pView = pViewData->GetScDrawView();
881  OutlinerView* pOutView = pView->GetTextEditOutlinerView();
882  if (pOutView)
883  xTransferable = pOutView->GetEditView().GetTransferable();
884  }
885  else if ( ScDrawShell * pDrawShell = dynamic_cast<ScDrawShell*>( pViewData->GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ) )
886  xTransferable = pDrawShell->GetDrawView()->CopyToTransferable();
887  else
888  xTransferable = pViewData->GetViewShell()->CopyToTransferable();
889 
890  if (!xTransferable.is())
891  xTransferable.set( aDataHelper.GetTransferable() );
892 
893  return xTransferable;
894 }
895 
896 void ScModelObj::setGraphicSelection(int nType, int nX, int nY)
897 {
898  SolarMutexGuard aGuard;
899 
900  ScTabViewShell* pViewShell = pDocShell->GetBestViewShell(false);
901 
902  // FIXME: Can this happen? What should we do?
903  if (!pViewShell)
904  return;
905 
906  ScViewData* pViewData = &pViewShell->GetViewData();
907 
908  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
909 
910  double fPPTX = pViewData->GetPPTX();
911  double fPPTY = pViewData->GetPPTY();
912 
913  pViewShell = pViewData->GetViewShell();
914  LokChartHelper aChartHelper(pViewShell);
915  if (aChartHelper.setGraphicSelection(nType, nX, nY, fPPTX, fPPTY))
916  return;
917 
918  int nPixelX = nX * fPPTX;
919  int nPixelY = nY * fPPTY;
920 
921  switch (nType)
922  {
923  case LOK_SETGRAPHICSELECTION_START:
924  {
925  MouseEvent aClickEvent(Point(nPixelX, nPixelY), 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
926  pGridWindow->MouseButtonDown(aClickEvent);
927  MouseEvent aMoveEvent(Point(nPixelX, nPixelY), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
928  pGridWindow->MouseMove(aMoveEvent);
929  }
930  break;
931  case LOK_SETGRAPHICSELECTION_END:
932  {
933  MouseEvent aMoveEvent(Point(nPixelX, nPixelY), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
934  pGridWindow->MouseMove(aMoveEvent);
935  MouseEvent aClickEvent(Point(nPixelX, nPixelY), 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
936  pGridWindow->MouseButtonUp(aClickEvent);
937  }
938  break;
939  default:
940  assert(false);
941  break;
942  }
943 }
944 
946 {
947  SolarMutexGuard aGuard;
948 
949  ScViewData* pViewData = ScDocShell::GetViewData();
950  ScTabViewShell* pViewShell = pViewData->GetViewShell();
951 
952  // deselect the shapes & texts
953  ScDrawView* pDrawView = pViewShell->GetScDrawView();
954  if (pDrawView)
955  {
956  pDrawView->ScEndTextEdit();
957  pDrawView->UnmarkAll();
958  }
959  else
960  pViewShell->Unmark();
961 
962  // and hide the cell and text selection
963  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, "");
964  SfxLokHelper::notifyOtherViews(pViewShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
965 }
966 
967 void ScModelObj::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard)
968 {
969  SolarMutexGuard aGuard;
970 
971  ScViewData* pViewData = ScDocShell::GetViewData();
972  if (!pViewData)
973  return;
974 
975  pViewData->GetActiveWin()->SetClipboard(xClipboard);
976 }
977 
979 {
980  SolarMutexGuard aGuard;
981 
982  ScViewData* pViewData = ScDocShell::GetViewData();
983  if (!pViewData)
984  return false;
985 
986 
988  return EditEngine::HasValidData(aDataHelper.GetTransferable());
989 }
990 
991 static void lcl_sendLOKDocumentBackground(const ScViewData* pViewData)
992 {
993  ScDocShell* pDocSh = pViewData->GetDocShell();
994  ScDocument& rDoc = pDocSh->GetDocument();
995  const ScPatternAttr *pAttr = rDoc.GetDefPattern();
996  const SfxPoolItem& rItem = pAttr->GetItem(ATTR_BACKGROUND);
997  const SvxBrushItem& rBackground = static_cast<const SvxBrushItem&>(rItem);
998  const Color& rColor = rBackground.GetColor();
999 
1000  ScTabViewShell* pViewShell = pViewData->GetViewShell();
1001  pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_BACKGROUND_COLOR, rColor.AsRGBHexString().toUtf8().getStr());
1002 }
1003 
1004 void ScModelObj::setClientZoom(int nTilePixelWidth_, int nTilePixelHeight_, int nTileTwipWidth_, int nTileTwipHeight_)
1005 {
1006  ScViewData* pViewData = ScDocShell::GetViewData();
1007 
1008  if (!pViewData)
1009  return;
1010 
1011  // Currently in LOK clients the doc background cannot be changed, so send this sparingly as possible but for every view.
1012  // FIXME: Find a better place to trigger this callback where it would be called just once per view creation.
1013  // Doing this in ScTabViewShell init code does not work because callbacks do not work at that point for the first view.
1014  lcl_sendLOKDocumentBackground(pViewData);
1015 
1016  const Fraction newZoomX(o3tl::toTwips(nTilePixelWidth_, o3tl::Length::px), nTileTwipWidth_);
1017  const Fraction newZoomY(o3tl::toTwips(nTilePixelHeight_, o3tl::Length::px), nTileTwipHeight_);
1018 
1019  double fDeltaPPTX = std::abs(ScGlobal::nScreenPPTX * static_cast<double>(newZoomX) - pViewData->GetPPTX());
1020  double fDeltaPPTY = std::abs(ScGlobal::nScreenPPTY * static_cast<double>(newZoomY) - pViewData->GetPPTY());
1021  constexpr double fEps = 1E-08;
1022 
1023  if (pViewData->GetZoomX() == newZoomX && pViewData->GetZoomY() == newZoomY && fDeltaPPTX < fEps && fDeltaPPTY < fEps)
1024  return;
1025 
1026  pViewData->SetZoom(newZoomX, newZoomY, true);
1027 
1028  // refresh our view's take on other view's cursors & selections
1029  pViewData->GetActiveWin()->updateKitOtherCursors();
1030  pViewData->GetActiveWin()->updateOtherKitSelections();
1031 
1032  if (ScDrawView* pDrawView = pViewData->GetScDrawView())
1033  pDrawView->resetGridOffsetsForAllSdrPageViews();
1034 }
1035 
1037 {
1038  ScViewData* pViewData = ScDocShell::GetViewData();
1039 
1040  if (!pViewData)
1041  return;
1042 
1043  ScTabView* pTabView = pViewData->GetView();
1044  if (!pTabView)
1045  return;
1046 
1047  pTabView->getRowColumnHeaders(rRectangle, rJsonWriter);
1048 }
1049 
1050 OString ScModelObj::getSheetGeometryData(bool bColumns, bool bRows, bool bSizes, bool bHidden,
1051  bool bFiltered, bool bGroups)
1052 {
1053  ScViewData* pViewData = ScDocShell::GetViewData();
1054 
1055  if (!pViewData)
1056  return "";
1057 
1058  ScTabView* pTabView = pViewData->GetView();
1059  if (!pTabView)
1060  return "";
1061 
1062  return pTabView->getSheetGeometryData(bColumns, bRows, bSizes, bHidden, bFiltered, bGroups);
1063 }
1064 
1066 {
1067  SolarMutexGuard aGuard;
1068 
1069  ScViewData* pViewData = ScDocShell::GetViewData();
1070 
1071  if (!pViewData)
1072  return;
1073 
1074  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1075  if (!pGridWindow)
1076  return;
1077 
1078  rJsonWriter.put("commandName", ".uno:CellCursor");
1079  rJsonWriter.put("commandValues", pGridWindow->getCellCursor());
1080 }
1081 
1083 {
1084  SolarMutexGuard aGuard;
1085 
1086  ScViewData* pViewData = ScDocShell::GetViewData();
1087  if (!pViewData)
1088  return PointerStyle::Arrow;
1089 
1090  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1091  if (!pGridWindow)
1092  return PointerStyle::Arrow;
1093 
1094  return pGridWindow->GetPointer();
1095 }
1096 
1098 {
1099  if (pDocShell)
1100  {
1101  if (ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack())
1102  pChangeTrack->GetChangeTrackInfo(rJson);
1103  }
1104 }
1105 
1107 {
1108  ScViewData* pViewData = ScDocShell::GetViewData();
1109  if (!pViewData)
1110  return;
1111 
1112  // set the PgUp/PgDown offset
1113  pViewData->ForcePageUpDownOffset(rRectangle.GetHeight());
1114 
1115  // Store the visible area so that we can use at places like shape insertion
1116  pViewData->setLOKVisibleArea(rRectangle);
1117 
1119  comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
1120  {
1121  ScTabView* pTabView = pViewData->GetView();
1122  if (pTabView)
1123  pTabView->extendTiledAreaIfNeeded();
1124  }
1125 }
1126 
1127 void ScModelObj::setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden)
1128 {
1129  ScViewData* pViewData = ScDocShell::GetViewData();
1130 
1131  if (!pViewData)
1132  return;
1133 
1134  ScDBFunc* pFunc = pViewData->GetView();
1135 
1136  if (pFunc)
1137  pFunc->SetOutlineState(bColumn, nLevel, nIndex, bHidden);
1138 }
1139 
1141 {
1142  if (!pDocShell)
1143  return;
1144 
1145  ScDocument& rDoc = pDocShell->GetDocument();
1146  std::vector<sc::NoteEntry> aNotes;
1147  rDoc.GetAllNoteEntries(aNotes);
1148 
1149  auto commentsNode = rJsonWriter.startArray("comments");
1150  for (const sc::NoteEntry& aNote : aNotes)
1151  {
1152  auto commentNode = rJsonWriter.startStruct();
1153 
1154  rJsonWriter.put("id", aNote.mpNote->GetId());
1155  rJsonWriter.put("tab", aNote.maPos.Tab());
1156  rJsonWriter.put("author", aNote.mpNote->GetAuthor());
1157  rJsonWriter.put("dateTime", aNote.mpNote->GetDate());
1158  rJsonWriter.put("text", aNote.mpNote->GetText());
1159 
1160  // Calculating the cell cursor position
1161  ScViewData* pViewData = ScDocShell::GetViewData();
1162  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1163  if (pGridWindow)
1164  {
1165  SCCOL nX = aNote.maPos.Col();
1166  SCROW nY = aNote.maPos.Row();
1167  Point aScrPos = pViewData->GetScrPos(nX, nY, pViewData->GetActivePart(), true);
1168  tools::Long nSizeXPix;
1169  tools::Long nSizeYPix;
1170  pViewData->GetMergeSizePixel(nX, nY, nSizeXPix, nSizeYPix);
1171 
1172  double fPPTX = pViewData->GetPPTX();
1173  double fPPTY = pViewData->GetPPTY();
1174  tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
1175  Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
1176 
1177  rJsonWriter.put("cellPos", aRect.toString());
1178  }
1179  }
1180 }
1181 
1183 {
1184  if (!pDocShell)
1185  return;
1186 
1187  ScDocument& rDoc = pDocShell->GetDocument();
1188  std::vector<sc::NoteEntry> aNotes;
1189  rDoc.GetAllNoteEntries(aNotes);
1190 
1191  auto commentsNode = rJsonWriter.startArray("commentsPos");
1192  for (const sc::NoteEntry& aNote : aNotes)
1193  {
1194  auto commentNode = rJsonWriter.startStruct();
1195 
1196  rJsonWriter.put("id", aNote.mpNote->GetId());
1197  rJsonWriter.put("tab", aNote.maPos.Tab());
1198 
1199  // Calculating the cell cursor position
1200  ScViewData* pViewData = ScDocShell::GetViewData();
1201  ScGridWindow* pGridWindow = pViewData->GetActiveWin();
1202  if (pGridWindow)
1203  {
1204  SCCOL nX = aNote.maPos.Col();
1205  SCROW nY = aNote.maPos.Row();
1206  Point aScrPos = pViewData->GetScrPos(nX, nY, pViewData->GetActivePart(), true);
1207  tools::Long nSizeXPix;
1208  tools::Long nSizeYPix;
1209  pViewData->GetMergeSizePixel(nX, nY, nSizeXPix, nSizeYPix);
1210 
1211  double fPPTX = pViewData->GetPPTX();
1212  double fPPTY = pViewData->GetPPTY();
1213  tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
1214  Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
1215 
1216  rJsonWriter.put("cellPos", aRect.toString());
1217  }
1218  }
1219 }
1220 
1221 void ScModelObj::completeFunction(const OUString& rFunctionName)
1222 {
1223  ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1224  if (pHdl)
1225  {
1226  assert(!rFunctionName.isEmpty());
1227  pHdl->LOKPasteFunctionData(rFunctionName);
1228  }
1229 }
1230 
1231 void ScModelObj::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments)
1232 {
1233  SolarMutexGuard aGuard;
1234 
1235  // enable word autocompletion
1236  ScAppOptions aAppOptions(SC_MOD()->GetAppOptions());
1237  aAppOptions.SetAutoComplete(true);
1238  SC_MOD()->SetAppOptions(aAppOptions);
1239 
1240  for (const beans::PropertyValue& rValue : rArguments)
1241  {
1242  if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>())
1243  {
1244  ScDocOptions options = GetDocument()->GetDocOptions();
1245  options.SetAutoSpell(rValue.Value.get<bool>());
1246  GetDocument()->SetDocOptions(options);
1247  }
1248  }
1249 
1250  // show us the text exactly
1251  ScInputOptions aInputOptions(SC_MOD()->GetInputOptions());
1252  aInputOptions.SetTextWysiwyg(true);
1253  aInputOptions.SetReplaceCellsWarn(false);
1254  SC_MOD()->SetInputOptions(aInputOptions);
1256 
1257  // when the "This document may contain formatting or content that cannot
1258  // be saved..." dialog appears, it is auto-cancelled with tiled rendering,
1259  // causing 'Save' being disabled; so let's always save to the original
1260  // format
1261  auto xChanges = comphelper::ConfigurationChanges::create();
1262  officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges);
1263  xChanges->commit();
1264 }
1265 
1267 {
1268  SC_QUERYINTERFACE( sheet::XSpreadsheetDocument )
1269  SC_QUERYINTERFACE( document::XActionLockable )
1270  SC_QUERYINTERFACE( sheet::XCalculatable )
1271  SC_QUERYINTERFACE( util::XProtectable )
1272  SC_QUERYINTERFACE( drawing::XDrawPagesSupplier )
1273  SC_QUERYINTERFACE( sheet::XGoalSeek )
1274  SC_QUERYINTERFACE( sheet::XConsolidatable )
1275  SC_QUERYINTERFACE( sheet::XDocumentAuditing )
1276  SC_QUERYINTERFACE( style::XStyleFamiliesSupplier )
1277  SC_QUERYINTERFACE( view::XRenderable )
1278  SC_QUERYINTERFACE( document::XLinkTargetSupplier )
1279  SC_QUERYINTERFACE( beans::XPropertySet )
1280  SC_QUERYINTERFACE( lang::XMultiServiceFactory )
1281  SC_QUERYINTERFACE( lang::XServiceInfo )
1282  SC_QUERYINTERFACE( util::XChangesNotifier )
1283  SC_QUERYINTERFACE( sheet::opencl::XOpenCLSelection )
1284  SC_QUERYINTERFACE( chart2::XDataProviderAccess )
1285 
1286  uno::Any aRet(SfxBaseModel::queryInterface( rType ));
1287  if ( !aRet.hasValue()
1294  {
1295  GetFormatter();
1296  if ( xNumberAgg.is() )
1297  aRet = xNumberAgg->queryAggregation( rType );
1298  }
1299 
1300  return aRet;
1301 }
1302 
1303 void SAL_CALL ScModelObj::acquire() noexcept
1304 {
1306 }
1307 
1308 void SAL_CALL ScModelObj::release() noexcept
1309 {
1311 }
1312 
1313 uno::Sequence<uno::Type> SAL_CALL ScModelObj::getTypes()
1314 {
1315  static const uno::Sequence<uno::Type> aTypes = [&]()
1316  {
1317  uno::Sequence<uno::Type> aAggTypes;
1318  if ( GetFormatter().is() )
1319  {
1321  uno::Any aNumProv(xNumberAgg->queryAggregation(rProvType));
1322  if(auto xNumProv
1323  = o3tl::tryAccess<uno::Reference<lang::XTypeProvider>>(aNumProv))
1324  {
1325  aAggTypes = (*xNumProv)->getTypes();
1326  }
1327  }
1330  aAggTypes,
1331  uno::Sequence<uno::Type>
1332  {
1349  } );
1350  }();
1351  return aTypes;
1352 }
1353 
1354 uno::Sequence<sal_Int8> SAL_CALL ScModelObj::getImplementationId()
1355 {
1356  return css::uno::Sequence<sal_Int8>();
1357 }
1358 
1359 void ScModelObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1360 {
1361  // Not interested in reference update hints here
1362 
1363  const SfxHintId nId = rHint.GetId();
1364  if ( nId == SfxHintId::Dying )
1365  {
1366  pDocShell = nullptr; // has become invalid
1367  if (xNumberAgg.is())
1368  {
1369  SvNumberFormatsSupplierObj* pNumFmt =
1370  comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(
1371  uno::Reference<util::XNumberFormatsSupplier>(xNumberAgg, uno::UNO_QUERY) );
1372  if ( pNumFmt )
1373  pNumFmt->SetNumberFormatter( nullptr );
1374  }
1375 
1376  pPrintFuncCache.reset(); // must be deleted because it has a pointer to the DocShell
1377  m_pPrintState.reset();
1378  }
1379  else if ( nId == SfxHintId::DataChanged )
1380  {
1381  // cached data for rendering become invalid when contents change
1382  // (if a broadcast is added to SetDrawModified, is has to be tested here, too)
1383 
1384  pPrintFuncCache.reset();
1385  m_pPrintState.reset();
1386 
1387  // handle "OnCalculate" sheet events (search also for VBA event handlers)
1388  if ( pDocShell )
1389  {
1390  ScDocument& rDoc = pDocShell->GetDocument();
1391  if ( rDoc.GetVbaEventProcessor().is() )
1392  {
1393  // If the VBA event processor is set, HasAnyCalcNotification is much faster than HasAnySheetEventScript
1396  }
1397  else
1398  {
1401  }
1402  }
1403  }
1404 
1405  // always call parent - SfxBaseModel might need to handle the same hints again
1406  SfxBaseModel::Notify( rBC, rHint ); // SfxBaseModel is derived from SfxListener
1407 }
1408 
1409 // XSpreadsheetDocument
1410 
1411 uno::Reference<sheet::XSpreadsheets> SAL_CALL ScModelObj::getSheets()
1412 {
1413  SolarMutexGuard aGuard;
1414  if (pDocShell)
1415  return new ScTableSheetsObj(pDocShell);
1416  return nullptr;
1417 }
1418 
1419 css::uno::Reference< ::css::chart2::data::XDataProvider > SAL_CALL ScModelObj::createDataProvider()
1420 {
1421  if (pDocShell)
1422  {
1423  return css::uno::Reference< ::css::chart2::data::XDataProvider > (
1425  }
1426  return nullptr;
1427 }
1428 
1429 // XStyleFamiliesSupplier
1430 
1431 uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getStyleFamilies()
1432 {
1433  SolarMutexGuard aGuard;
1434  if (pDocShell)
1435  return new ScStyleFamiliesObj(pDocShell);
1436  return nullptr;
1437 }
1438 
1439 // XRenderable
1440 
1441 static OutputDevice* lcl_GetRenderDevice( const uno::Sequence<beans::PropertyValue>& rOptions )
1442 {
1443  OutputDevice* pRet = nullptr;
1444  for (const beans::PropertyValue& rProp : rOptions)
1445  {
1446  const OUString & rPropName = rProp.Name;
1447 
1448  if (rPropName == SC_UNONAME_RENDERDEV)
1449  {
1450  uno::Reference<awt::XDevice> xRenderDevice(rProp.Value, uno::UNO_QUERY);
1451  if ( xRenderDevice.is() )
1452  {
1453  VCLXDevice* pDevice = comphelper::getFromUnoTunnel<VCLXDevice>( xRenderDevice );
1454  if ( pDevice )
1455  {
1456  pRet = pDevice->GetOutputDevice().get();
1457  pRet->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
1458  }
1459  }
1460  }
1461  }
1462  return pRet;
1463 }
1464 
1465 static bool lcl_ParseTarget( const OUString& rTarget, ScRange& rTargetRange, tools::Rectangle& rTargetRect,
1466  bool& rIsSheet, ScDocument& rDoc, SCTAB nSourceTab )
1467 {
1468  // test in same order as in SID_CURRENTCELL execute
1469 
1470  ScAddress aAddress;
1471  SCTAB nNameTab;
1472  sal_Int32 nNumeric = 0;
1473 
1474  bool bRangeValid = false;
1475  bool bRectValid = false;
1476 
1477  if ( rTargetRange.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1478  {
1479  bRangeValid = true; // range reference
1480  }
1481  else if ( aAddress.Parse( rTarget, rDoc ) & ScRefFlags::VALID )
1482  {
1483  rTargetRange = aAddress;
1484  bRangeValid = true; // cell reference
1485  }
1486  else if ( ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange ) ||
1487  ScRangeUtil::MakeRangeFromName( rTarget, rDoc, nSourceTab, rTargetRange, RUTL_DBASE ) )
1488  {
1489  bRangeValid = true; // named range or database range
1490  }
1491  else if ( comphelper::string::isdigitAsciiString(rTarget) &&
1492  ( nNumeric = rTarget.toInt32() ) > 0 && nNumeric <= rDoc.MaxRow()+1 )
1493  {
1494  // row number is always mapped to cell A(row) on the same sheet
1495  rTargetRange = ScAddress( 0, static_cast<SCROW>(nNumeric-1), nSourceTab ); // target row number is 1-based
1496  bRangeValid = true; // row number
1497  }
1498  else if ( rDoc.GetTable( rTarget, nNameTab ) )
1499  {
1500  rTargetRange = ScAddress(0,0,nNameTab);
1501  bRangeValid = true; // sheet name
1502  rIsSheet = true; // needs special handling (first page of the sheet)
1503  }
1504  else
1505  {
1506  // look for named drawing object
1507 
1508  ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1509  if ( pDrawLayer )
1510  {
1511  SCTAB nTabCount = rDoc.GetTableCount();
1512  for (SCTAB i=0; i<nTabCount && !bRangeValid; i++)
1513  {
1514  SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(i));
1515  OSL_ENSURE(pPage,"Page ?");
1516  if (pPage)
1517  {
1518  SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
1519  SdrObject* pObject = aIter.Next();
1520  while (pObject && !bRangeValid)
1521  {
1522  if ( ScDrawLayer::GetVisibleName( pObject ) == rTarget )
1523  {
1524  rTargetRect = pObject->GetLogicRect(); // 1/100th mm
1525  rTargetRange = rDoc.GetRange( i, rTargetRect ); // underlying cells
1526  bRangeValid = bRectValid = true; // rectangle is valid
1527  }
1528  pObject = aIter.Next();
1529  }
1530  }
1531  }
1532  }
1533  }
1534  if ( bRangeValid && !bRectValid )
1535  {
1536  // get rectangle for cell range
1537  rTargetRect = rDoc.GetMMRect( rTargetRange.aStart.Col(), rTargetRange.aStart.Row(),
1538  rTargetRange.aEnd.Col(), rTargetRange.aEnd.Row(),
1539  rTargetRange.aStart.Tab() );
1540  }
1541 
1542  return bRangeValid;
1543 }
1544 
1546  const uno::Sequence< beans::PropertyValue >& rOptions,
1547  ScMarkData& rMark,
1548  ScPrintSelectionStatus& rStatus, OUString& rPagesStr,
1549  bool& rbRenderToGraphic ) const
1550 {
1551  OSL_ENSURE( !rMark.IsMarked() && !rMark.IsMultiMarked(), "FillRenderMarkData: MarkData must be empty" );
1552  OSL_ENSURE( pDocShell, "FillRenderMarkData: DocShell must be set" );
1553 
1554  bool bDone = false;
1555 
1556  uno::Reference<frame::XController> xView;
1557 
1558  // defaults when no options are passed: all sheets, include empty pages
1559  bool bSelectedSheetsOnly = false;
1560  bool bSuppressEmptyPages = true;
1561 
1562  bool bHasPrintContent = false;
1563  sal_Int32 nPrintContent = 0; // all sheets / selected sheets / selected cells
1564  sal_Int32 nPrintRange = 0; // all pages / pages
1565  sal_Int32 nEOContent = 0; // even pages / odd pages
1566  OUString aPageRange; // "pages" edit value
1567 
1568  for( const auto& rOption : rOptions )
1569  {
1570  if ( rOption.Name == "IsOnlySelectedSheets" )
1571  {
1572  rOption.Value >>= bSelectedSheetsOnly;
1573  }
1574  else if ( rOption.Name == "IsSuppressEmptyPages" )
1575  {
1576  rOption.Value >>= bSuppressEmptyPages;
1577  }
1578  else if ( rOption.Name == "PageRange" )
1579  {
1580  rOption.Value >>= aPageRange;
1581  }
1582  else if ( rOption.Name == "PrintRange" )
1583  {
1584  rOption.Value >>= nPrintRange;
1585  }
1586  else if ( rOption.Name == "EvenOdd" )
1587  {
1588  rOption.Value >>= nEOContent;
1589  }
1590  else if ( rOption.Name == "PrintContent" )
1591  {
1592  bHasPrintContent = true;
1593  rOption.Value >>= nPrintContent;
1594  }
1595  else if ( rOption.Name == "View" )
1596  {
1597  rOption.Value >>= xView;
1598  }
1599  else if ( rOption.Name == "RenderToGraphic" )
1600  {
1601  rOption.Value >>= rbRenderToGraphic;
1602  }
1603  }
1604 
1605  // "Print Content" selection wins over "Selected Sheets" option
1606  if ( bHasPrintContent )
1607  bSelectedSheetsOnly = ( nPrintContent != 0 );
1608 
1609  uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY);
1610  if ( xInterface.is() )
1611  {
1612  ScCellRangesBase* pSelObj = comphelper::getFromUnoTunnel<ScCellRangesBase>( xInterface );
1613  uno::Reference< drawing::XShapes > xShapes( xInterface, uno::UNO_QUERY );
1614  if ( pSelObj && pSelObj->GetDocShell() == pDocShell )
1615  {
1616  bool bSheet = ( comphelper::getFromUnoTunnel<ScTableSheetObj>( xInterface ) != nullptr );
1617  bool bCursor = pSelObj->IsCursorOnly();
1618  const ScRangeList& rRanges = pSelObj->GetRangeList();
1619 
1620  rMark.MarkFromRangeList( rRanges, false );
1621  rMark.MarkToSimple();
1622 
1623  if ( rMark.IsMultiMarked() )
1624  {
1625  // #i115266# copy behavior of old printing:
1626  // treat multiple selection like a single selection with the enclosing range
1627  const ScRange& aMultiMarkArea = rMark.GetMultiMarkArea();
1628  rMark.ResetMark();
1629  rMark.SetMarkArea( aMultiMarkArea );
1630  }
1631 
1632  if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
1633  {
1634  // a sheet object is treated like an empty selection: print the used area of the sheet
1635 
1636  if ( bCursor || bSheet ) // nothing selected -> use whole tables
1637  {
1638  rMark.ResetMark(); // doesn't change table selection
1640  }
1641  else
1643 
1644  rStatus.SetRanges( rRanges );
1645  bDone = true;
1646  }
1647  // multi selection isn't supported
1648  }
1649  else if( xShapes.is() )
1650  {
1651  //print a selected ole object
1652  // multi selection isn't supported yet
1653  uno::Reference< drawing::XShape > xShape( xShapes->getByIndex(0), uno::UNO_QUERY );
1654  SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
1655  if( pSdrObj && pDocShell )
1656  {
1657  ScDocument& rDoc = pDocShell->GetDocument();
1658  tools::Rectangle aObjRect = pSdrObj->GetCurrentBoundRect();
1659  SCTAB nCurrentTab = ScDocShell::GetCurTab();
1660  ScRange aRange = rDoc.GetRange( nCurrentTab, aObjRect );
1661  rMark.SetMarkArea( aRange );
1662 
1663  if( rMark.IsMarked() && !rMark.IsMultiMarked() )
1664  {
1666  bDone = true;
1667  }
1668  }
1669  }
1670  else if ( comphelper::getFromUnoTunnel<ScModelObj>( xInterface ) == this )
1671  {
1672  // render the whole document
1673  // -> no selection, all sheets
1674 
1675  SCTAB nTabCount = pDocShell->GetDocument().GetTableCount();
1676  for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
1677  rMark.SelectTable( nTab, true );
1679  bDone = true;
1680  }
1681  // other selection types aren't supported
1682  }
1683 
1684  // restrict to selected sheets if a view is available
1685  uno::Reference<sheet::XSelectedSheetsSupplier> xSelectedSheets(xView, uno::UNO_QUERY);
1686  if (bSelectedSheetsOnly && pDocShell && xSelectedSheets.is())
1687  {
1688  const uno::Sequence<sal_Int32> aSelected = xSelectedSheets->getSelectedSheets();
1689  ScMarkData::MarkedTabsType aSelectedTabs;
1690  SCTAB nMaxTab = pDocShell->GetDocument().GetTableCount() -1;
1691  for (const auto& rSelected : aSelected)
1692  {
1693  SCTAB nSelected = static_cast<SCTAB>(rSelected);
1694  if (ValidTab(nSelected, nMaxTab))
1695  aSelectedTabs.insert(nSelected);
1696  }
1697  rMark.SetSelectedTabs(aSelectedTabs);
1698  }
1699 
1700  ScPrintOptions aNewOptions;
1701  aNewOptions.SetSkipEmpty( bSuppressEmptyPages );
1702  aNewOptions.SetAllSheets( !bSelectedSheetsOnly );
1703  rStatus.SetOptions( aNewOptions );
1704 
1705  // "PrintRange" enables (1) or disables (0) the "PageRange" edit
1706  if ( nPrintRange == 1 )
1707  rPagesStr = aPageRange;
1708  else
1709  rPagesStr.clear();
1710 
1711  return bDone;
1712 }
1713 
1714 sal_Int32 SAL_CALL ScModelObj::getRendererCount(const uno::Any& aSelection,
1715  const uno::Sequence<beans::PropertyValue>& rOptions)
1716 {
1717  SolarMutexGuard aGuard;
1718  if (!pDocShell)
1719  {
1720  throw lang::DisposedException( OUString(),
1721  static_cast< sheet::XSpreadsheetDocument* >(this) );
1722  }
1723 
1724  ScMarkData aMark(GetDocument()->GetSheetLimits());
1725  ScPrintSelectionStatus aStatus;
1726  OUString aPagesStr;
1727  bool bRenderToGraphic = false;
1728  if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1729  return 0;
1730 
1731  // The same ScPrintFuncCache object in pPrintFuncCache is used as long as
1732  // the same selection is used (aStatus) and the document isn't changed
1733  // (pPrintFuncCache is cleared in Notify handler)
1734 
1735  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1736  {
1737  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1738  }
1739  sal_Int32 nPages = pPrintFuncCache->GetPageCount();
1740 
1741  m_pPrintState.reset();
1742  maValidPages.clear();
1743 
1744  sal_Int32 nContent = 0;
1745  sal_Int32 nEOContent = 0;
1746  bool bSinglePageSheets = false;
1747  for ( const auto& rValue : rOptions)
1748  {
1749  if ( rValue.Name == "PrintRange" )
1750  {
1751  rValue.Value >>= nContent;
1752  }
1753  else if ( rValue.Name == "SinglePageSheets" )
1754  {
1755  rValue.Value >>= bSinglePageSheets;
1756  }
1757  else if ( rValue.Name == "EvenOdd" )
1758  {
1759  rValue.Value >>= nEOContent;
1760  }
1761  }
1762 
1763  if (bSinglePageSheets)
1764  {
1765  return pDocShell->GetDocument().GetTableCount();
1766  }
1767 
1768  bool bIsPrintEvenPages = (nEOContent != 1 && nContent == 0) || nContent != 0;
1769  bool bIsPrintOddPages = (nEOContent != 2 && nContent == 0) || nContent != 0;
1770 
1771  for ( sal_Int32 nPage = 1; nPage <= nPages; nPage++ )
1772  {
1773  if ( (bIsPrintEvenPages && IsOnEvenPage( nPage )) || (bIsPrintOddPages && !IsOnEvenPage( nPage )) )
1774  maValidPages.push_back( nPage );
1775  }
1776 
1777  sal_Int32 nSelectCount = static_cast<sal_Int32>( maValidPages.size() );
1778 
1779  if ( nEOContent == 1 || nEOContent == 2 ) // even pages / odd pages
1780  return nSelectCount;
1781 
1782  if ( !aPagesStr.isEmpty() )
1783  {
1784  StringRangeEnumerator aRangeEnum( aPagesStr, 0, nPages-1 );
1785  nSelectCount = aRangeEnum.size();
1786  }
1787  return (nSelectCount > 0) ? nSelectCount : 1;
1788 }
1789 
1790 static sal_Int32 lcl_GetRendererNum( sal_Int32 nSelRenderer, std::u16string_view rPagesStr, sal_Int32 nTotalPages )
1791 {
1792  if ( rPagesStr.empty() )
1793  return nSelRenderer;
1794 
1795  StringRangeEnumerator aRangeEnum( rPagesStr, 0, nTotalPages-1 );
1796  StringRangeEnumerator::Iterator aIter = aRangeEnum.begin();
1797  StringRangeEnumerator::Iterator aEnd = aRangeEnum.end();
1798  for ( ; nSelRenderer > 0 && aIter != aEnd; --nSelRenderer )
1799  ++aIter;
1800 
1801  return *aIter; // returns -1 if reached the end
1802 }
1803 
1804 static bool lcl_renderSelectionToGraphic( bool bRenderToGraphic, const ScPrintSelectionStatus& rStatus )
1805 {
1806  return bRenderToGraphic && rStatus.GetMode() == ScPrintSelectionMode::Range;
1807 }
1808 
1809 uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nSelRenderer,
1810  const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& rOptions )
1811 {
1812  SolarMutexGuard aGuard;
1813  if (!pDocShell)
1814  {
1815  throw lang::DisposedException( OUString(),
1816  static_cast< sheet::XSpreadsheetDocument* >(this) );
1817  }
1818 
1820  ScPrintSelectionStatus aStatus;
1821  OUString aPagesStr;
1822  // #i115266# if FillRenderMarkData fails, keep nTotalPages at 0, but still handle getRenderer(0) below
1823  tools::Long nTotalPages = 0;
1824  bool bRenderToGraphic = false;
1825  bool bSinglePageSheets = false;
1826  if ( FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
1827  {
1828  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
1829  {
1830  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
1831  }
1832  nTotalPages = pPrintFuncCache->GetPageCount();
1833  }
1834 
1835  for ( const auto& rValue : rOptions)
1836  {
1837  if ( rValue.Name == "SinglePageSheets" )
1838  {
1839  rValue.Value >>= bSinglePageSheets;
1840  break;
1841  }
1842  }
1843 
1844  if (bSinglePageSheets)
1845  nTotalPages = pDocShell->GetDocument().GetTableCount();
1846 
1847  sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
1848 
1849  if ( nRenderer < 0 )
1850  {
1851  if ( nSelRenderer != 0 )
1852  throw lang::IllegalArgumentException();
1853 
1854  // getRenderer(0) is used to query the settings, so it must always return something
1855 
1856  awt::Size aPageSize;
1857  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1858  {
1859  assert( aMark.IsMarked());
1860  const ScRange& aRange = aMark.GetMarkArea();
1862  aRange.aStart.Col(), aRange.aStart.Row(),
1863  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1864  aPageSize.Width = aMMRect.GetWidth();
1865  aPageSize.Height = aMMRect.GetHeight();
1866  }
1867  else
1868  {
1869  SCTAB const nCurTab = 0;
1870  ScPrintFunc aDefaultFunc( pDocShell, pDocShell->GetPrinter(), nCurTab );
1871  Size aTwips = aDefaultFunc.GetPageSize();
1872  aPageSize.Width = convertTwipToMm100(aTwips.Width());
1873  aPageSize.Height = convertTwipToMm100(aTwips.Height());
1874  }
1875 
1876  uno::Sequence<beans::PropertyValue> aSequence( comphelper::InitPropertySequence({
1877  { SC_UNONAME_PAGESIZE, uno::Any(aPageSize) }
1878  }));
1879 
1880  if( ! pPrinterOptions )
1881  pPrinterOptions.reset(new ScPrintUIOptions);
1882  else
1883  pPrinterOptions->SetDefaults();
1884  pPrinterOptions->appendPrintUIOptions( aSequence );
1885  return aSequence;
1886 
1887  }
1888 
1889  // printer is used as device (just for page layout), draw view is not needed
1890 
1891  SCTAB nTab;
1892  if (bSinglePageSheets)
1893  nTab = nSelRenderer;
1894  else if ( !maValidPages.empty() )
1895  nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
1896  else
1897  nTab = pPrintFuncCache->GetTabForPage( nRenderer );
1898 
1899 
1900  ScRange aRange;
1901  const ScRange* pSelRange = nullptr;
1902  if ( bSinglePageSheets )
1903  {
1904  SCCOL nStartCol;
1905  SCROW nStartRow;
1906  const ScDocument* pDocument = &pDocShell->GetDocument();
1907  pDocument->GetDataStart( nTab, nStartCol, nStartRow );
1908  SCCOL nEndCol;
1909  SCROW nEndRow;
1910  pDocument->GetPrintArea( nTab, nEndCol, nEndRow );
1911 
1912  aRange.aStart = ScAddress(nStartCol, nStartRow, nTab);
1913  aRange.aEnd = ScAddress(nEndCol, nEndRow, nTab);
1914 
1915  table::CellRangeAddress aRangeAddress( nTab,
1916  aRange.aStart.Col(), aRange.aStart.Row(),
1917  aRange.aEnd.Col(), aRange.aEnd.Row() );
1919  aRange.aStart.Col(), aRange.aStart.Row(),
1920  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1921 
1922  const awt::Size aPageSize(aMMRect.GetWidth(), aMMRect.GetHeight());
1923  const awt::Point aCalcPagePos(aMMRect.Left(), aMMRect.Top());
1924 
1925  uno::Sequence<beans::PropertyValue> aSequence
1926  {
1928  // #i111158# all positions are relative to the whole page, including non-printable area
1931  comphelper::makePropertyValue(SC_UNONAME_CALCPAGESIZE, aPageSize), // TODO aPageSize too ?
1933  };
1934 
1935  if( ! pPrinterOptions )
1936  pPrinterOptions.reset(new ScPrintUIOptions);
1937  else
1938  pPrinterOptions->SetDefaults();
1939  pPrinterOptions->appendPrintUIOptions( aSequence );
1940  return aSequence;
1941  }
1942  else if ( aMark.IsMarked() )
1943  {
1944  aRange = aMark.GetMarkArea();
1945  pSelRange = &aRange;
1946  }
1947 
1948  awt::Size aPageSize;
1949  bool bWasCellRange = false;
1950  ScRange aCellRange;
1951  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
1952  {
1953  bWasCellRange = true;
1954  aCellRange = aRange;
1956  aRange.aStart.Col(), aRange.aStart.Row(),
1957  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
1958  aPageSize.Width = aMMRect.GetWidth();
1959  aPageSize.Height = aMMRect.GetHeight();
1960  }
1961  else
1962  {
1963  std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
1964  if (m_pPrintState && m_pPrintState->nPrintTab == nTab)
1965  pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), *m_pPrintState, &aStatus.GetOptions()));
1966  else
1967  pPrintFunc.reset(new ScPrintFunc(pDocShell, pDocShell->GetPrinter(), nTab,
1968  pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
1969  pPrintFunc->SetRenderFlag( true );
1970 
1971  sal_Int32 nContent = 0;
1972  sal_Int32 nEOContent = 0;
1973  for ( const auto& rValue : rOptions)
1974  {
1975  if ( rValue.Name == "PrintRange" )
1976  {
1977  rValue.Value >>= nContent;
1978  }
1979  else if ( rValue.Name == "EvenOdd" )
1980  {
1981  rValue.Value >>= nEOContent;
1982  }
1983  }
1984 
1985  MultiSelection aPage;
1986  aPage.SetTotalRange( Range(0,RANGE_MAX) );
1987 
1988  bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 1 && nEOContent == 2); // even pages or odd pages
1989  // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
1990  // to allow PrinterController::abortJob to spool an empty page as part of
1991  // its abort procedure
1992  if (bOddOrEven && !maValidPages.empty())
1993  aPage.Select( maValidPages.at(nRenderer) );
1994  else
1995  aPage.Select( nRenderer+1 );
1996 
1997  tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
1998  tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
1999 
2000  (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, false, nullptr );
2001 
2002  bWasCellRange = pPrintFunc->GetLastSourceRange( aCellRange );
2003  Size aTwips = pPrintFunc->GetPageSize();
2004 
2005  if (!m_pPrintState)
2006  {
2007  m_pPrintState.reset(new ScPrintState());
2008  pPrintFunc->GetPrintState(*m_pPrintState, true);
2009  }
2010 
2011  aPageSize.Width = convertTwipToMm100(aTwips.Width());
2012  aPageSize.Height = convertTwipToMm100(aTwips.Height());
2013  }
2014 
2015  tools::Long nPropCount = bWasCellRange ? 5 : 4;
2016  uno::Sequence<beans::PropertyValue> aSequence(nPropCount);
2017  beans::PropertyValue* pArray = aSequence.getArray();
2018  pArray[0].Name = SC_UNONAME_PAGESIZE;
2019  pArray[0].Value <<= aPageSize;
2020  // #i111158# all positions are relative to the whole page, including non-printable area
2021  pArray[1].Name = SC_UNONAME_INC_NP_AREA;
2022  pArray[1].Value <<= true;
2023  if ( bWasCellRange )
2024  {
2025  table::CellRangeAddress aRangeAddress( nTab,
2026  aCellRange.aStart.Col(), aCellRange.aStart.Row(),
2027  aCellRange.aEnd.Col(), aCellRange.aEnd.Row() );
2029  aCellRange.aStart.Col(), aCellRange.aStart.Row(),
2030  aCellRange.aEnd.Col(), aCellRange.aEnd.Row(), aCellRange.aStart.Tab()));
2031 
2032  const awt::Size aCalcPageSize(aMMRect.GetWidth(), aMMRect.GetHeight());
2033  const awt::Point aCalcPagePos(aMMRect.Left(), aMMRect.Top());
2034 
2035  pArray[2].Name = SC_UNONAME_SOURCERANGE;
2036  pArray[2].Value <<= aRangeAddress;
2037  pArray[3].Name = SC_UNONAME_CALCPAGESIZE;
2038  pArray[3].Value <<= aCalcPageSize;
2039  pArray[4].Name = SC_UNONAME_CALCPAGEPOS;
2040  pArray[4].Value <<= aCalcPagePos;
2041  }
2042 
2043  if( ! pPrinterOptions )
2044  pPrinterOptions.reset(new ScPrintUIOptions);
2045  else
2046  pPrinterOptions->SetDefaults();
2047  pPrinterOptions->appendPrintUIOptions( aSequence );
2048  return aSequence;
2049 }
2050 
2051 void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelection,
2052  const uno::Sequence<beans::PropertyValue>& rOptions )
2053 {
2054  SolarMutexGuard aGuard;
2055  if (!pDocShell)
2056  {
2057  throw lang::DisposedException( OUString(),
2058  static_cast< sheet::XSpreadsheetDocument* >(this) );
2059  }
2060 
2062  ScPrintSelectionStatus aStatus;
2063  OUString aPagesStr;
2064  bool bRenderToGraphic = false;
2065  bool bSinglePageSheets = false;
2066  if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr, bRenderToGraphic ) )
2067  throw lang::IllegalArgumentException();
2068 
2069  if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) )
2070  {
2071  pPrintFuncCache.reset(new ScPrintFuncCache( pDocShell, aMark, aStatus ));
2072  }
2073  tools::Long nTotalPages = pPrintFuncCache->GetPageCount();
2074 
2075  for ( const auto& rValue : rOptions)
2076  {
2077  if ( rValue.Name == "SinglePageSheets" )
2078  {
2079  rValue.Value >>= bSinglePageSheets;
2080  break;
2081  }
2082  }
2083 
2084  if (bSinglePageSheets)
2085  nTotalPages = pDocShell->GetDocument().GetTableCount();
2086 
2087  sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages );
2088  if ( nRenderer < 0 )
2089  throw lang::IllegalArgumentException();
2090 
2091  OutputDevice* pDev = lcl_GetRenderDevice( rOptions );
2092  if ( !pDev )
2093  throw lang::IllegalArgumentException();
2094 
2095  ScDocument& rDoc = pDocShell->GetDocument();
2096 
2097  ScRange aRange;
2098  const ScRange* pSelRange = nullptr;
2099  if ( bSinglePageSheets )
2100  {
2101  awt::Size aPageSize;
2102  SCCOL nStartCol;
2103  SCROW nStartRow;
2104  rDoc.GetDataStart( nSelRenderer, nStartCol, nStartRow );
2105  SCCOL nEndCol;
2106  SCROW nEndRow;
2107  rDoc.GetPrintArea( nSelRenderer, nEndCol, nEndRow );
2108 
2109  aRange.aStart = ScAddress(nStartCol, nStartRow, nSelRenderer);
2110  aRange.aEnd = ScAddress(nEndCol, nEndRow, nSelRenderer);
2111 
2113  aRange.aStart.Col(), aRange.aStart.Row(),
2114  aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab()));
2115 
2116  aPageSize.Width = aMMRect.GetWidth();
2117  aPageSize.Height = aMMRect.GetHeight();
2118 
2119  //Set visible tab
2120  SCTAB nVisTab = rDoc.GetVisibleTab();
2121  if (nVisTab != nSelRenderer)
2122  {
2123  nVisTab = nSelRenderer;
2124  rDoc.SetVisibleTab(nVisTab);
2125  }
2126 
2127  pDocShell->DoDraw(pDev, Point(0,0), Size(aPageSize.Width, aPageSize.Height), JobSetup());
2128 
2129  return;
2130  }
2131  else if ( aMark.IsMarked() )
2132  {
2133  aRange = aMark.GetMarkArea();
2134  pSelRange = &aRange;
2135  }
2136 
2137  if (lcl_renderSelectionToGraphic( bRenderToGraphic, aStatus))
2138  {
2139  // Similar to as in and when calling ScTransferObj::PaintToDev()
2140 
2141  tools::Rectangle aBound( Point(), pDev->GetOutputSize());
2142 
2143  ScViewData aViewData(rDoc);
2144 
2145  aViewData.SetTabNo( aRange.aStart.Tab() );
2146  aViewData.SetScreen( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() );
2147 
2148  const double nPrintFactor = 1.0; /* XXX: currently (2017-08-28) is not evaluated */
2149  // The bMetaFile argument maybe could be
2150  // pDev->GetConnectMetaFile() != nullptr
2151  // but for some yet unknown reason does not draw cell content if true.
2152  ScPrintFunc::DrawToDev( rDoc, pDev, nPrintFactor, aBound, &aViewData, false /*bMetaFile*/ );
2153 
2154  return;
2155  }
2156 
2157  struct DrawViewKeeper
2158  {
2159  std::unique_ptr<FmFormView> mpDrawView;
2160  DrawViewKeeper() {}
2161  ~DrawViewKeeper()
2162  {
2163  if (mpDrawView)
2164  {
2165  mpDrawView->HideSdrPage();
2166  mpDrawView.reset();
2167  }
2168  }
2169  } aDrawViewKeeper;
2170 
2171  SCTAB nTab;
2172  if ( !maValidPages.empty() )
2173  nTab = pPrintFuncCache->GetTabForPage( maValidPages.at( nRenderer )-1 );
2174  else
2175  nTab = pPrintFuncCache->GetTabForPage( nRenderer );
2176 
2177  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2178 
2179  if( pModel )
2180  {
2181  aDrawViewKeeper.mpDrawView.reset( new FmFormView(
2182  *pModel,
2183  pDev) );
2184  aDrawViewKeeper.mpDrawView->ShowSdrPage(aDrawViewKeeper.mpDrawView->GetModel()->GetPage(nTab));
2185  aDrawViewKeeper.mpDrawView->SetPrintPreview();
2186  }
2187 
2188  // to increase performance, ScPrintState might be used here for subsequent
2189  // pages of the same sheet
2190 
2191 
2192  std::unique_ptr<ScPrintFunc, o3tl::default_delete<ScPrintFunc>> pPrintFunc;
2193  if (m_pPrintState && m_pPrintState->nPrintTab == nTab
2194  && ! pSelRange) // tdf#120161 use selection to set required printed area
2195  pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, *m_pPrintState, &aStatus.GetOptions()));
2196  else
2197  pPrintFunc.reset(new ScPrintFunc(pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions()));
2198 
2199  pPrintFunc->SetDrawView( aDrawViewKeeper.mpDrawView.get() );
2200  pPrintFunc->SetRenderFlag( true );
2202  pPrintFunc->SetExclusivelyDrawOleAndDrawObjects();
2203 
2204  sal_Int32 nContent = 0;
2205  sal_Int32 nEOContent = 0;
2206  for ( const auto& rValue : rOptions)
2207  {
2208  if ( rValue.Name == "PrintRange" )
2209  {
2210  rValue.Value >>= nContent;
2211  }
2212  else if ( rValue.Name == "EvenOdd" )
2213  {
2214  rValue.Value >>= nEOContent;
2215  }
2216  }
2217 
2218  MultiSelection aPage;
2219  aPage.SetTotalRange( Range(0,RANGE_MAX) );
2220 
2221  bool bOddOrEven = (nContent == 0 && nEOContent == 1) || (nContent == 0 && nEOContent == 2); // even pages or odd pages
2222  // tdf#127682 when odd/even allow nRenderer of 0 even when maValidPages is empty
2223  // to allow PrinterController::abortJob to spool an empty page as part of
2224  // its abort procedure
2225  if (bOddOrEven && !maValidPages.empty())
2226  aPage.Select( maValidPages.at( nRenderer ) );
2227  else
2228  aPage.Select( nRenderer+1 );
2229 
2230  tools::Long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab );
2231  tools::Long nTabStart = pPrintFuncCache->GetTabStart( nTab );
2232 
2233  vcl::PDFExtOutDevData* pPDFData = dynamic_cast< vcl::PDFExtOutDevData* >(pDev->GetExtOutDevData() );
2234  if ( nRenderer == nTabStart )
2235  {
2236  // first page of a sheet: add outline item for the sheet name
2237 
2238  if ( pPDFData && pPDFData->GetIsExportBookmarks() )
2239  {
2240  // the sheet starts at the top of the page
2241  tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2242  sal_Int32 nDestID = pPDFData->CreateDest( aArea );
2243  OUString aTabName;
2244  rDoc.GetName( nTab, aTabName );
2245  // top-level
2246  pPDFData->CreateOutlineItem( -1/*nParent*/, aTabName, nDestID );
2247  }
2248  // #i56629# add the named destination stuff
2249  if( pPDFData && pPDFData->GetIsExportNamedDestinations() )
2250  {
2251  tools::Rectangle aArea( pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) ) );
2252  OUString aTabName;
2253  rDoc.GetName( nTab, aTabName );
2254  //need the PDF page number here
2255  pPDFData->CreateNamedDest( aTabName, aArea );
2256  }
2257  }
2258 
2259  (void)pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, true, nullptr );
2260 
2261  if (!m_pPrintState)
2262  {
2263  m_pPrintState.reset(new ScPrintState());
2264  pPrintFunc->GetPrintState(*m_pPrintState, true);
2265  }
2266 
2267  // resolve the hyperlinks for PDF export
2268 
2269  if ( !pPDFData || pPDFData->GetBookmarks().empty() )
2270  return;
2271 
2272  // iterate over the hyperlinks that were output for this page
2273 
2274  std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
2275  for ( const auto& rBookmark : rBookmarks )
2276  {
2277  OUString aBookmark = rBookmark.aBookmark;
2278  if ( aBookmark.toChar() == '#' )
2279  {
2280  // try to resolve internal link
2281 
2282  OUString aTarget( aBookmark.copy( 1 ) );
2283 
2284  ScRange aTargetRange;
2285  tools::Rectangle aTargetRect; // 1/100th mm
2286  bool bIsSheet = false;
2287  bool bValid = lcl_ParseTarget( aTarget, aTargetRange, aTargetRect, bIsSheet, rDoc, nTab );
2288 
2289  if ( bValid )
2290  {
2291  sal_Int32 nPage = -1;
2292  tools::Rectangle aArea;
2293  if ( bIsSheet )
2294  {
2295  // Get first page for sheet (if nothing from that sheet is printed,
2296  // this page can show a different sheet)
2297  nPage = pPrintFuncCache->GetTabStart( aTargetRange.aStart.Tab() );
2298  aArea = pDev->PixelToLogic( tools::Rectangle( 0,0,0,0 ) );
2299  }
2300  else
2301  {
2302  pPrintFuncCache->InitLocations( aMark, pDev ); // does nothing if already initialized
2303 
2304  ScPrintPageLocation aLocation;
2305  if ( pPrintFuncCache->FindLocation( aTargetRange.aStart, aLocation ) )
2306  {
2307  nPage = aLocation.nPage;
2308 
2309  // get the rectangle of the page's cell range in 1/100th mm
2310  ScRange aLocRange = aLocation.aCellRange;
2311  tools::Rectangle aLocationMM = rDoc.GetMMRect(
2312  aLocRange.aStart.Col(), aLocRange.aStart.Row(),
2313  aLocRange.aEnd.Col(), aLocRange.aEnd.Row(),
2314  aLocRange.aStart.Tab() );
2315  tools::Rectangle aLocationPixel = aLocation.aRectangle;
2316 
2317  // Scale and move the target rectangle from aLocationMM to aLocationPixel,
2318  // to get the target rectangle in pixels.
2319  assert(aLocationPixel.GetWidth() != 0 && aLocationPixel.GetHeight() != 0);
2320 
2321  Fraction aScaleX( aLocationPixel.GetWidth(), aLocationMM.GetWidth() );
2322  Fraction aScaleY( aLocationPixel.GetHeight(), aLocationMM.GetHeight() );
2323 
2324  tools::Long nX1 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Left() - aLocationMM.Left(), 1 ) * aScaleX );
2325  tools::Long nX2 = aLocationPixel.Left() + static_cast<tools::Long>( Fraction( aTargetRect.Right() - aLocationMM.Left(), 1 ) * aScaleX );
2326  tools::Long nY1 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Top() - aLocationMM.Top(), 1 ) * aScaleY );
2327  tools::Long nY2 = aLocationPixel.Top() + static_cast<tools::Long>( Fraction( aTargetRect.Bottom() - aLocationMM.Top(), 1 ) * aScaleY );
2328 
2329  if ( nX1 > aLocationPixel.Right() ) nX1 = aLocationPixel.Right();
2330  if ( nX2 > aLocationPixel.Right() ) nX2 = aLocationPixel.Right();
2331  if ( nY1 > aLocationPixel.Bottom() ) nY1 = aLocationPixel.Bottom();
2332  if ( nY2 > aLocationPixel.Bottom() ) nY2 = aLocationPixel.Bottom();
2333 
2334  // The link target area is interpreted using the device's MapMode at
2335  // the time of the CreateDest call, so PixelToLogic can be used here,
2336  // regardless of the MapMode that is actually selected.
2337  aArea = pDev->PixelToLogic( tools::Rectangle( nX1, nY1, nX2, nY2 ) );
2338  }
2339  }
2340 
2341  if ( nPage >= 0 )
2342  pPDFData->SetLinkDest( rBookmark.nLinkId, pPDFData->CreateDest( aArea, nPage ) );
2343  }
2344  }
2345  else
2346  {
2347  // external link, use as-is
2348  pPDFData->SetLinkURL( rBookmark.nLinkId, aBookmark );
2349  }
2350  }
2351  rBookmarks.clear();
2352 }
2353 
2354 // XLinkTargetSupplier
2355 
2356 uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getLinks()
2357 {
2358  SolarMutexGuard aGuard;
2359  if (pDocShell)
2360  return new ScLinkTargetTypesObj(pDocShell);
2361  return nullptr;
2362 }
2363 
2364 // XActionLockable
2365 
2367 {
2368  SolarMutexGuard aGuard;
2369  bool bLocked = false;
2370  if (pDocShell)
2371  bLocked = ( pDocShell->GetLockCount() != 0 );
2372  return bLocked;
2373 }
2374 
2376 {
2377  SolarMutexGuard aGuard;
2378  if (pDocShell)
2380 }
2381 
2383 {
2384  SolarMutexGuard aGuard;
2385  if (pDocShell)
2387 }
2388 
2389 void SAL_CALL ScModelObj::setActionLocks( sal_Int16 nLock )
2390 {
2391  SolarMutexGuard aGuard;
2392  if (pDocShell)
2393  pDocShell->SetLockCount(nLock);
2394 }
2395 
2396 sal_Int16 SAL_CALL ScModelObj::resetActionLocks()
2397 {
2398  SolarMutexGuard aGuard;
2399  sal_uInt16 nRet = 0;
2400  if (pDocShell)
2401  {
2402  nRet = pDocShell->GetLockCount();
2403  pDocShell->SetLockCount(0);
2404  }
2405  return nRet;
2406 }
2407 
2409 {
2410  SolarMutexGuard aGuard;
2412  if (pDocShell)
2413  pDocShell->LockPaint();
2414 }
2415 
2417 {
2418  SolarMutexGuard aGuard;
2419  if (hasControllersLocked())
2420  {
2422  if (pDocShell)
2424  }
2425 }
2426 
2427 // XCalculate
2428 
2429 void SAL_CALL ScModelObj::calculate()
2430 {
2431  SolarMutexGuard aGuard;
2432  if (pDocShell)
2433  {
2434  comphelper::ProfileZone aZone("calculate");
2435  pDocShell->DoRecalc(true);
2436  }
2437  else
2438  {
2439  OSL_FAIL("no DocShell");
2440  }
2441 }
2442 
2444 {
2445  SolarMutexGuard aGuard;
2446  if (pDocShell)
2447  {
2448  comphelper::ProfileZone aZone("calculateAll");
2450  }
2451  else
2452  {
2453  OSL_FAIL("no DocShell");
2454  }
2455 }
2456 
2458 {
2459  SolarMutexGuard aGuard;
2460  if (pDocShell)
2461  return pDocShell->GetDocument().GetAutoCalc();
2462 
2463  OSL_FAIL("no DocShell");
2464  return false;
2465 }
2466 
2468 {
2469  bool bEnabled(bEnabledIn);
2470  SolarMutexGuard aGuard;
2471  if (pDocShell)
2472  {
2473  ScDocument& rDoc = pDocShell->GetDocument();
2474  if ( rDoc.GetAutoCalc() != bEnabled )
2475  {
2476  rDoc.SetAutoCalc( bEnabled );
2478  }
2479  }
2480  else
2481  {
2482  OSL_FAIL("no DocShell");
2483  }
2484 }
2485 
2486 // XProtectable
2487 
2488 void SAL_CALL ScModelObj::protect( const OUString& aPassword )
2489 {
2490  SolarMutexGuard aGuard;
2491  // #i108245# if already protected, don't change anything
2493  {
2494  pDocShell->GetDocFunc().Protect( TABLEID_DOC, aPassword );
2495  }
2496 }
2497 
2498 void SAL_CALL ScModelObj::unprotect( const OUString& aPassword )
2499 {
2500  SolarMutexGuard aGuard;
2501  if (pDocShell)
2502  {
2503  bool bDone = pDocShell->GetDocFunc().Unprotect( TABLEID_DOC, aPassword, true );
2504  if (!bDone)
2505  throw lang::IllegalArgumentException();
2506  }
2507 }
2508 
2510 {
2511  SolarMutexGuard aGuard;
2512  if (pDocShell)
2513  return pDocShell->GetDocument().IsDocProtected();
2514 
2515  OSL_FAIL("no DocShell");
2516  return false;
2517 }
2518 
2519 // XDrawPagesSupplier
2520 
2521 uno::Reference<drawing::XDrawPages> SAL_CALL ScModelObj::getDrawPages()
2522 {
2523  SolarMutexGuard aGuard;
2524  if (pDocShell)
2525  return new ScDrawPagesObj(pDocShell);
2526 
2527  OSL_FAIL("no DocShell");
2528  return nullptr;
2529 }
2530 
2531 // XGoalSeek
2532 
2533 sheet::GoalResult SAL_CALL ScModelObj::seekGoal(
2534  const table::CellAddress& aFormulaPosition,
2535  const table::CellAddress& aVariablePosition,
2536  const OUString& aGoalValue )
2537 {
2538  SolarMutexGuard aGuard;
2539  sheet::GoalResult aResult;
2540  aResult.Divergence = DBL_MAX; // not found
2541  if (pDocShell)
2542  {
2544  ScDocument& rDoc = pDocShell->GetDocument();
2545  double fValue = 0.0;
2546  bool bFound = rDoc.Solver(
2547  static_cast<SCCOL>(aFormulaPosition.Column), static_cast<SCROW>(aFormulaPosition.Row), aFormulaPosition.Sheet,
2548  static_cast<SCCOL>(aVariablePosition.Column), static_cast<SCROW>(aVariablePosition.Row), aVariablePosition.Sheet,
2549  aGoalValue, fValue );
2550  aResult.Result = fValue;
2551  if (bFound)
2552  aResult.Divergence = 0.0;
2553  }
2554  return aResult;
2555 }
2556 
2557 // XConsolidatable
2558 
2559 uno::Reference<sheet::XConsolidationDescriptor> SAL_CALL ScModelObj::createConsolidationDescriptor(
2560  sal_Bool bEmpty )
2561 {
2562  SolarMutexGuard aGuard;
2564  if ( pDocShell && !bEmpty )
2565  {
2566  ScDocument& rDoc = pDocShell->GetDocument();
2567  const ScConsolidateParam* pParam = rDoc.GetConsolidateDlgData();
2568  if (pParam)
2569  pNew->SetParam( *pParam );
2570  }
2571  return pNew;
2572 }
2573 
2575  const uno::Reference<sheet::XConsolidationDescriptor>& xDescriptor )
2576 {
2577  SolarMutexGuard aGuard;
2578  // in theory, this could also be a different object, so use only
2579  // public XConsolidationDescriptor interface to copy the data into
2580  // ScConsolidationDescriptor object
2582 
2584  xImpl->setFunction( xDescriptor->getFunction() );
2585  xImpl->setSources( xDescriptor->getSources() );
2586  xImpl->setStartOutputPosition( xDescriptor->getStartOutputPosition() );
2587  xImpl->setUseColumnHeaders( xDescriptor->getUseColumnHeaders() );
2588  xImpl->setUseRowHeaders( xDescriptor->getUseRowHeaders() );
2589  xImpl->setInsertLinks( xDescriptor->getInsertLinks() );
2590 
2591  if (pDocShell)
2592  {
2593  const ScConsolidateParam& rParam = xImpl->GetParam();
2594  pDocShell->DoConsolidate( rParam );
2595  pDocShell->GetDocument().SetConsolidateDlgData( std::unique_ptr<ScConsolidateParam>(new ScConsolidateParam(rParam)) );
2596  }
2597 }
2598 
2599 // XDocumentAuditing
2600 
2602 {
2603  SolarMutexGuard aGuard;
2604  if (pDocShell)
2606 }
2607 
2608 // XViewDataSupplier
2609 uno::Reference< container::XIndexAccess > SAL_CALL ScModelObj::getViewData( )
2610 {
2611  uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() );
2612 
2613  if( !xRet.is() )
2614  {
2615  SolarMutexGuard aGuard;
2616  if (pDocShell && pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
2617  {
2618  uno::Reference < container::XIndexContainer > xCont = document::IndexedPropertyValues::create( ::comphelper::getProcessComponentContext() );
2619  xRet.set( xCont, uno::UNO_QUERY_THROW );
2620 
2621  OUString sName;
2623  SCCOL nPosLeft = pDocShell->GetDocument().GetPosLeft();
2624  SCROW nPosTop = pDocShell->GetDocument().GetPosTop();
2625  uno::Sequence< beans::PropertyValue > aSeq{
2629  };
2630  xCont->insertByIndex( 0, uno::Any( aSeq ) );
2631  }
2632  }
2633 
2634  return xRet;
2635 }
2636 
2637 // XPropertySet (Doc-Options)
2639 
2640 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScModelObj::getPropertySetInfo()
2641 {
2642  SolarMutexGuard aGuard;
2643  static uno::Reference<beans::XPropertySetInfo> aRef(
2645  return aRef;
2646 }
2647 
2649  const OUString& aPropertyName, const uno::Any& aValue )
2650 {
2651  SolarMutexGuard aGuard;
2652 
2653  if (!pDocShell)
2654  return;
2655 
2656  ScDocument& rDoc = pDocShell->GetDocument();
2657  const ScDocOptions& rOldOpt = rDoc.GetDocOptions();
2658  ScDocOptions aNewOpt = rOldOpt;
2659  // Don't recalculate while loading XML, when the formula text is stored
2660  // Recalculation after loading is handled separately.
2661  bool bHardRecalc = !rDoc.IsImportingXML();
2662 
2663  bool bOpt = ScDocOptionsHelper::setPropertyValue( aNewOpt, aPropSet.getPropertyMap(), aPropertyName, aValue );
2664  if (bOpt)
2665  {
2666  // done...
2667  if ( aPropertyName == SC_UNO_IGNORECASE ||
2668  aPropertyName == SC_UNONAME_REGEXP ||
2669  aPropertyName == SC_UNONAME_WILDCARDS ||
2670  aPropertyName == SC_UNO_LOOKUPLABELS )
2671  bHardRecalc = false;
2672  }
2673  else if ( aPropertyName == SC_UNONAME_CLOCAL )
2674  {
2675  lang::Locale aLocale;
2676  if ( aValue >>= aLocale )
2677  {
2678  LanguageType eLatin, eCjk, eCtl;
2679  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2680  eLatin = ScUnoConversion::GetLanguage(aLocale);
2681  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2682  }
2683  }
2684  else if ( aPropertyName == SC_UNO_CODENAME )
2685  {
2686  OUString sCodeName;
2687  if ( aValue >>= sCodeName )
2688  rDoc.SetCodeName( sCodeName );
2689  }
2690  else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2691  {
2692  lang::Locale aLocale;
2693  if ( aValue >>= aLocale )
2694  {
2695  LanguageType eLatin, eCjk, eCtl;
2696  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2697  eCjk = ScUnoConversion::GetLanguage(aLocale);
2698  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2699  }
2700  }
2701  else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2702  {
2703  lang::Locale aLocale;
2704  if ( aValue >>= aLocale )
2705  {
2706  LanguageType eLatin, eCjk, eCtl;
2707  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2708  eCtl = ScUnoConversion::GetLanguage(aLocale);
2709  rDoc.SetLanguage( eLatin, eCjk, eCtl );
2710  }
2711  }
2712  else if ( aPropertyName == SC_UNO_APPLYFMDES )
2713  {
2714  // model is created if not there
2715  ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2717 
2718  SfxBindings* pBindings = pDocShell->GetViewBindings();
2719  if (pBindings)
2720  pBindings->Invalidate( SID_FM_OPEN_READONLY );
2721  }
2722  else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2723  {
2724  // model is created if not there
2725  ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
2727 
2728  SfxBindings* pBindings = pDocShell->GetViewBindings();
2729  if (pBindings)
2730  pBindings->Invalidate( SID_FM_AUTOCONTROLFOCUS );
2731  }
2732  else if ( aPropertyName == SC_UNO_ISLOADED )
2733  {
2735  }
2736  else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2737  {
2738  bool bUndoEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2739  rDoc.EnableUndo( bUndoEnabled );
2741  bUndoEnabled
2742  ? officecfg::Office::Common::Undo::Steps::get() : 0);
2743  }
2744  else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2745  {
2746  bool bRecordChangesEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue );
2747 
2748  bool bChangeAllowed = true;
2749  if (!bRecordChangesEnabled)
2750  bChangeAllowed = !pDocShell->HasChangeRecordProtection();
2751 
2752  if (bChangeAllowed)
2753  pDocShell->SetChangeRecording(bRecordChangesEnabled);
2754  }
2755  else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2756  {
2757  if( ScUnoHelpFunctions::GetBoolFromAny( aValue ) )
2758  rDoc.UnlockAdjustHeight();
2759  else
2760  rDoc.LockAdjustHeight();
2761  }
2762  else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2763  {
2765  }
2766  else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2767  {
2769  }
2770  else if ( aPropertyName == "BuildId" )
2771  {
2772  aValue >>= maBuildId;
2773  }
2774  else if ( aPropertyName == "SavedObject" ) // set from chart after saving
2775  {
2776  OUString aObjName;
2777  aValue >>= aObjName;
2778  if ( !aObjName.isEmpty() )
2779  rDoc.RestoreChartListener( aObjName );
2780  }
2781  else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2782  {
2783  setGrabBagItem(aValue);
2784  }
2785 
2786  if ( aNewOpt != rOldOpt )
2787  {
2788  rDoc.SetDocOptions( aNewOpt );
2790  if ( bHardRecalc )
2793  }
2794 }
2795 
2796 uno::Any SAL_CALL ScModelObj::getPropertyValue( const OUString& aPropertyName )
2797 {
2798  SolarMutexGuard aGuard;
2799  uno::Any aRet;
2800 
2801  if (pDocShell)
2802  {
2803  ScDocument& rDoc = pDocShell->GetDocument();
2804  const ScDocOptions& rOpt = rDoc.GetDocOptions();
2805  aRet = ScDocOptionsHelper::getPropertyValue( rOpt, aPropSet.getPropertyMap(), aPropertyName );
2806  if ( aRet.hasValue() )
2807  {
2808  // done...
2809  }
2810  else if ( aPropertyName == SC_UNONAME_CLOCAL )
2811  {
2812  LanguageType eLatin, eCjk, eCtl;
2813  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2814 
2815  lang::Locale aLocale;
2816  ScUnoConversion::FillLocale( aLocale, eLatin );
2817  aRet <<= aLocale;
2818  }
2819  else if ( aPropertyName == SC_UNO_CODENAME )
2820  {
2821  aRet <<= rDoc.GetCodeName();
2822  }
2823 
2824  else if ( aPropertyName == SC_UNO_CJK_CLOCAL )
2825  {
2826  LanguageType eLatin, eCjk, eCtl;
2827  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2828 
2829  lang::Locale aLocale;
2830  ScUnoConversion::FillLocale( aLocale, eCjk );
2831  aRet <<= aLocale;
2832  }
2833  else if ( aPropertyName == SC_UNO_CTL_CLOCAL )
2834  {
2835  LanguageType eLatin, eCjk, eCtl;
2836  rDoc.GetLanguage( eLatin, eCjk, eCtl );
2837 
2838  lang::Locale aLocale;
2839  ScUnoConversion::FillLocale( aLocale, eCtl );
2840  aRet <<= aLocale;
2841  }
2842  else if ( aPropertyName == SC_UNO_NAMEDRANGES )
2843  {
2844  aRet <<= uno::Reference<sheet::XNamedRanges>(new ScGlobalNamedRangesObj( pDocShell ));
2845  }
2846  else if ( aPropertyName == SC_UNO_DATABASERNG )
2847  {
2848  aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell ));
2849  }
2850  else if ( aPropertyName == SC_UNO_UNNAMEDDBRNG )
2851  {
2852  aRet <<= uno::Reference<sheet::XUnnamedDatabaseRanges>(new ScUnnamedDatabaseRangesObj(pDocShell));
2853  }
2854  else if ( aPropertyName == SC_UNO_COLLABELRNG )
2855  {
2856  aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, true ));
2857  }
2858  else if ( aPropertyName == SC_UNO_ROWLABELRNG )
2859  {
2860  aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, false ));
2861  }
2862  else if ( aPropertyName == SC_UNO_AREALINKS )
2863  {
2864  aRet <<= uno::Reference<sheet::XAreaLinks>(new ScAreaLinksObj( pDocShell ));
2865  }
2866  else if ( aPropertyName == SC_UNO_DDELINKS )
2867  {
2868  aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
2869  }
2870  else if ( aPropertyName == SC_UNO_EXTERNALDOCLINKS )
2871  {
2872  aRet <<= uno::Reference<sheet::XExternalDocLinks>(new ScExternalDocLinksObj(pDocShell));
2873  }
2874  else if ( aPropertyName == SC_UNO_SHEETLINKS )
2875  {
2876  aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
2877  }
2878  else if ( aPropertyName == SC_UNO_APPLYFMDES )
2879  {
2880  // default for no model is TRUE
2881  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2882  bool bOpenInDesign = pModel == nullptr || pModel->GetOpenInDesignMode();
2883  aRet <<= bOpenInDesign;
2884  }
2885  else if ( aPropertyName == SC_UNO_AUTOCONTFOC )
2886  {
2887  // default for no model is FALSE
2888  ScDrawLayer* pModel = rDoc.GetDrawLayer();
2889  bool bAutoControlFocus = pModel && pModel->GetAutoControlFocus();
2890  aRet <<= bAutoControlFocus;
2891  }
2892  else if ( aPropertyName == SC_UNO_FORBIDDEN )
2893  {
2894  aRet <<= uno::Reference<i18n::XForbiddenCharacters>(new ScForbiddenCharsObj( pDocShell ));
2895  }
2896  else if ( aPropertyName == SC_UNO_HASDRAWPAGES )
2897  {
2898  aRet <<= (pDocShell->GetDocument().GetDrawLayer() != nullptr);
2899  }
2900  else if ( aPropertyName == SC_UNO_BASICLIBRARIES )
2901  {
2902  aRet <<= pDocShell->GetBasicContainer();
2903  }
2904  else if ( aPropertyName == SC_UNO_DIALOGLIBRARIES )
2905  {
2906  aRet <<= pDocShell->GetDialogContainer();
2907  }
2908  else if ( aPropertyName == SC_UNO_VBAGLOBNAME )
2909  {
2910  /* #i111553# This property provides the name of the constant that
2911  will be used to store this model in the global Basic manager.
2912  That constant will be equivalent to 'ThisComponent' but for
2913  each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc'
2914  constant can co-exist, as required by VBA. */
2915  aRet <<= OUString( "ThisExcelDoc" );
2916  }
2917  else if ( aPropertyName == SC_UNO_RUNTIMEUID )
2918  {
2919  aRet <<= getRuntimeUID();
2920  }
2921  else if ( aPropertyName == SC_UNO_HASVALIDSIGNATURES )
2922  {
2923  aRet <<= hasValidSignatures();
2924  }
2925  else if ( aPropertyName == SC_UNO_ISLOADED )
2926  {
2927  aRet <<= !pDocShell->IsEmpty();
2928  }
2929  else if ( aPropertyName == SC_UNO_ISUNDOENABLED )
2930  {
2931  aRet <<= rDoc.IsUndoEnabled();
2932  }
2933  else if ( aPropertyName == SC_UNO_RECORDCHANGES )
2934  {
2935  aRet <<= pDocShell->IsChangeRecording();
2936  }
2937  else if ( aPropertyName == SC_UNO_ISRECORDCHANGESPROTECTED )
2938  {
2940  }
2941  else if ( aPropertyName == SC_UNO_ISADJUSTHEIGHTENABLED )
2942  {
2943  aRet <<= !( rDoc.IsAdjustHeightLocked() );
2944  }
2945  else if ( aPropertyName == SC_UNO_ISEXECUTELINKENABLED )
2946  {
2947  aRet <<= rDoc.IsExecuteLinkEnabled();
2948  }
2949  else if ( aPropertyName == SC_UNO_ISCHANGEREADONLYENABLED )
2950  {
2951  aRet <<= rDoc.IsChangeReadOnlyEnabled();
2952  }
2953  else if ( aPropertyName == SC_UNO_REFERENCEDEVICE )
2954  {
2955  rtl::Reference<VCLXDevice> pXDev = new VCLXDevice();
2956  pXDev->SetOutputDevice( rDoc.GetRefDevice() );
2957  aRet <<= uno::Reference< awt::XDevice >( pXDev );
2958  }
2959  else if ( aPropertyName == "BuildId" )
2960  {
2961  aRet <<= maBuildId;
2962  }
2963  else if ( aPropertyName == "InternalDocument" )
2964  {
2965  aRet <<= (pDocShell->GetCreateMode() == SfxObjectCreateMode::INTERNAL);
2966  }
2967  else if ( aPropertyName == SC_UNO_INTEROPGRABBAG )
2968  {
2969  getGrabBagItem(aRet);
2970  }
2971  }
2972 
2973  return aRet;
2974 }
2975 
2977 
2978 // XMultiServiceFactory
2979 
2980 css::uno::Reference<css::uno::XInterface> ScModelObj::create(
2981  OUString const & aServiceSpecifier,
2982  css::uno::Sequence<css::uno::Any> const * arguments)
2983 {
2985 
2986  uno::Reference<uno::XInterface> xRet;
2988  if ( nType != ServiceType::INVALID )
2989  {
2990  // drawing layer tables must be kept as long as the model is alive
2991  // return stored instance if already set
2992  switch ( nType )
2993  {
2994  case ServiceType::GRADTAB: xRet.set(xDrawGradTab); break;
2995  case ServiceType::HATCHTAB: xRet.set(xDrawHatchTab); break;
2996  case ServiceType::BITMAPTAB: xRet.set(xDrawBitmapTab); break;
2997  case ServiceType::TRGRADTAB: xRet.set(xDrawTrGradTab); break;
2998  case ServiceType::MARKERTAB: xRet.set(xDrawMarkerTab); break;
2999  case ServiceType::DASHTAB: xRet.set(xDrawDashTab); break;
3000  case ServiceType::CHDATAPROV: xRet.set(xChartDataProv); break;
3001  case ServiceType::VBAOBJECTPROVIDER: xRet.set(xObjProvider); break;
3002  default: break;
3003  }
3004 
3005  // #i64497# If a chart is in a temporary document during clipboard paste,
3006  // there should be no data provider, so that own data is used
3007  bool bCreate =
3008  ( nType != ServiceType::CHDATAPROV ||
3009  ( pDocShell->GetCreateMode() != SfxObjectCreateMode::INTERNAL ));
3010  // this should never happen, i.e. the temporary document should never be
3011  // loaded, because this unlinks the data
3012  assert(bCreate);
3013 
3014  if ( !xRet.is() && bCreate )
3015  {
3016  xRet.set(ScServiceProvider::MakeInstance( nType, pDocShell ));
3017 
3018  // store created instance
3019  switch ( nType )
3020  {
3021  case ServiceType::GRADTAB: xDrawGradTab.set(xRet); break;
3022  case ServiceType::HATCHTAB: xDrawHatchTab.set(xRet); break;
3023  case ServiceType::BITMAPTAB: xDrawBitmapTab.set(xRet); break;
3024  case ServiceType::TRGRADTAB: xDrawTrGradTab.set(xRet); break;
3025  case ServiceType::MARKERTAB: xDrawMarkerTab.set(xRet); break;
3026  case ServiceType::DASHTAB: xDrawDashTab.set(xRet); break;
3027  case ServiceType::CHDATAPROV: xChartDataProv.set(xRet); break;
3028  case ServiceType::VBAOBJECTPROVIDER: xObjProvider.set(xRet); break;
3029  default: break;
3030  }
3031  }
3032  }
3033  else
3034  {
3035  // we offload everything we don't know to SvxFmMSFactory,
3036  // it'll throw exception if this isn't okay ...
3037 
3038  try
3039  {
3040  xRet = arguments == nullptr
3041  ? SvxFmMSFactory::createInstance(aServiceSpecifier)
3043  aServiceSpecifier, *arguments);
3044  // extra block to force deletion of the temporary before ScShapeObj ctor (setDelegator)
3045  }
3046  catch ( lang::ServiceNotRegisteredException & )
3047  {
3048  }
3049 
3050  // if the drawing factory created a shape, a ScShapeObj has to be used
3051  // to support own properties like ImageMap:
3052 
3053  uno::Reference<drawing::XShape> xShape( xRet, uno::UNO_QUERY );
3054  if ( xShape.is() )
3055  {
3056  xRet.clear(); // for aggregation, xShape must be the object's only ref
3057  new ScShapeObj( xShape ); // aggregates object and modifies xShape
3058  xRet.set(xShape);
3059  }
3060  }
3061  return xRet;
3062 }
3063 
3064 uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstance(
3065  const OUString& aServiceSpecifier )
3066 {
3067  SolarMutexGuard aGuard;
3068  return create(aServiceSpecifier, nullptr);
3069 }
3070 
3071 uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstanceWithArguments(
3072  const OUString& ServiceSpecifier,
3073  const uno::Sequence<uno::Any>& aArgs )
3074 {
3076 
3077  SolarMutexGuard aGuard;
3078  uno::Reference<uno::XInterface> xInt(create(ServiceSpecifier, &aArgs));
3079 
3080  if ( aArgs.hasElements() )
3081  {
3082  // used only for cell value binding so far - it can be initialized after creating
3083 
3084  uno::Reference<lang::XInitialization> xInit( xInt, uno::UNO_QUERY );
3085  if ( xInit.is() )
3086  xInit->initialize( aArgs );
3087  }
3088 
3089  return xInt;
3090 }
3091 
3092 uno::Sequence<OUString> SAL_CALL ScModelObj::getAvailableServiceNames()
3093 {
3094  SolarMutexGuard aGuard;
3095 
3098 }
3099 
3100 // XServiceInfo
3102 {
3103  return "ScModelObj";
3104  /* // Matching the .component information:
3105  return OUString( "com.sun.star.comp.Calc.SpreadsheetDocument" );
3106  */
3107 }
3108 
3109 sal_Bool SAL_CALL ScModelObj::supportsService( const OUString& rServiceName )
3110 {
3111  return cppu::supportsService(this, rServiceName);
3112 }
3113 
3114 uno::Sequence<OUString> SAL_CALL ScModelObj::getSupportedServiceNames()
3115 {
3117 }
3118 
3119 // XUnoTunnel
3120 
3121 sal_Int64 SAL_CALL ScModelObj::getSomething(
3122  const uno::Sequence<sal_Int8 >& rId )
3123 {
3124  if ( comphelper::isUnoTunnelId<ScModelObj>(rId) )
3125  {
3126  return comphelper::getSomething_cast(this);
3127  }
3128 
3129  if ( comphelper::isUnoTunnelId<SfxObjectShell>(rId) )
3130  {
3132  }
3133 
3134  // aggregated number formats supplier has XUnoTunnel, too
3135  // interface from aggregated object must be obtained via queryAggregation
3136 
3137  sal_Int64 nRet = SfxBaseModel::getSomething( rId );
3138  if ( nRet )
3139  return nRet;
3140 
3141  if ( GetFormatter().is() )
3142  {
3143  const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
3144  uno::Any aNumTunnel(xNumberAgg->queryAggregation(rTunnelType));
3145  if(auto xTunnelAgg = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
3146  aNumTunnel))
3147  {
3148  return (*xTunnelAgg)->getSomething( rId );
3149  }
3150  }
3151 
3152  return 0;
3153 }
3154 
3155 const uno::Sequence<sal_Int8>& ScModelObj::getUnoTunnelId()
3156 {
3157  static const comphelper::UnoIdInit theScModelObjUnoTunnelId;
3158  return theScModelObjUnoTunnelId.getSeq();
3159 }
3160 
3161 // XChangesNotifier
3162 
3163 void ScModelObj::addChangesListener( const uno::Reference< util::XChangesListener >& aListener )
3164 {
3165  SolarMutexGuard aGuard;
3166  maChangesListeners.addInterface( aListener );
3167 }
3168 
3169 void ScModelObj::removeChangesListener( const uno::Reference< util::XChangesListener >& aListener )
3170 {
3171  SolarMutexGuard aGuard;
3172  maChangesListeners.removeInterface( aListener );
3173 }
3174 
3176 {
3177  if ( maChangesListeners.getLength() > 0 )
3178  return true;
3179 
3180  // "change" event set in any sheet?
3182 }
3183 
3184 void ScModelObj::NotifyChanges( const OUString& rOperation, const ScRangeList& rRanges,
3185  const uno::Sequence< beans::PropertyValue >& rProperties )
3186 {
3187  if ( pDocShell && HasChangesListeners() )
3188  {
3189  util::ChangesEvent aEvent;
3190  aEvent.Source.set( static_cast< cppu::OWeakObject* >( this ) );
3191  aEvent.Base <<= aEvent.Source;
3192 
3193  size_t nRangeCount = rRanges.size();
3194  aEvent.Changes.realloc( static_cast< sal_Int32 >( nRangeCount ) );
3195  auto pChanges = aEvent.Changes.getArray();
3196  for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3197  {
3198  uno::Reference< table::XCellRange > xRangeObj;
3199 
3200  ScRange const & rRange = rRanges[ nIndex ];
3201  if ( rRange.aStart == rRange.aEnd )
3202  {
3203  xRangeObj.set( new ScCellObj( pDocShell, rRange.aStart ) );
3204  }
3205  else
3206  {
3207  xRangeObj.set( new ScCellRangeObj( pDocShell, rRange ) );
3208  }
3209 
3210  util::ElementChange& rChange = pChanges[ static_cast< sal_Int32 >( nIndex ) ];
3211  rChange.Accessor <<= rOperation;
3212  rChange.Element <<= rProperties;
3213  rChange.ReplacedElement <<= xRangeObj;
3214  }
3215 
3217  while ( aIter.hasMoreElements() )
3218  {
3219  try
3220  {
3221  aIter.next()->changesOccurred( aEvent );
3222  }
3223  catch( uno::Exception& )
3224  {
3225  }
3226  }
3227  }
3228 
3229  // handle sheet events
3231  if ( !(rOperation == "cell-change" && pDocShell) )
3232  return;
3233 
3235  aMarkData.MarkFromRangeList( rRanges, false );
3236  ScDocument& rDoc = pDocShell->GetDocument();
3237  SCTAB nTabCount = rDoc.GetTableCount();
3238  for (const SCTAB& nTab : aMarkData)
3239  {
3240  if (nTab >= nTabCount)
3241  break;
3242  const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab);
3243  if (pEvents)
3244  {
3245  const OUString* pScript = pEvents->GetScript(ScSheetEventId::CHANGE);
3246  if (pScript)
3247  {
3248  ScRangeList aTabRanges; // collect ranges on this sheet
3249  size_t nRangeCount = rRanges.size();
3250  for ( size_t nIndex = 0; nIndex < nRangeCount; ++nIndex )
3251  {
3252  ScRange const & rRange = rRanges[ nIndex ];
3253  if ( rRange.aStart.Tab() == nTab )
3254  aTabRanges.push_back( rRange );
3255  }
3256  size_t nTabRangeCount = aTabRanges.size();
3257  if ( nTabRangeCount > 0 )
3258  {
3259  uno::Reference<uno::XInterface> xTarget;
3260  if ( nTabRangeCount == 1 )
3261  {
3262  ScRange const & rRange = aTabRanges[ 0 ];
3263  if ( rRange.aStart == rRange.aEnd )
3264  xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellObj( pDocShell, rRange.aStart ) ) );
3265  else
3266  xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangeObj( pDocShell, rRange ) ) );
3267  }
3268  else
3269  xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangesObj( pDocShell, aTabRanges ) ) );
3270 
3271  uno::Sequence<uno::Any> aParams{ uno::Any(xTarget) };
3272 
3273  uno::Any aRet;
3274  uno::Sequence<sal_Int16> aOutArgsIndex;
3275  uno::Sequence<uno::Any> aOutArgs;
3276 
3277  /*ErrCode eRet =*/ pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
3278  }
3279  }
3280  }
3281  }
3282 }
3283 
3285 {
3286  if (!pDocShell)
3287  return;
3288 
3289  ScDocument& rDoc = pDocShell->GetDocument();
3290  // don't call events before the document is visible
3291  // (might also set a flag on SfxEventHintId::LoadFinished and only disable while loading)
3292  if ( rDoc.IsDocVisible() )
3293  {
3294  SCTAB nTabCount = rDoc.GetTableCount();
3295  for (SCTAB nTab = 0; nTab < nTabCount; nTab++)
3296  {
3297  if (rDoc.HasCalcNotification(nTab))
3298  {
3299  if (const ScSheetEvents* pEvents = rDoc.GetSheetEvents( nTab ))
3300  {
3301  if (const OUString* pScript = pEvents->GetScript(ScSheetEventId::CALCULATE))
3302  {
3303  uno::Any aRet;
3304  uno::Sequence<uno::Any> aParams;
3305  uno::Sequence<sal_Int16> aOutArgsIndex;
3306  uno::Sequence<uno::Any> aOutArgs;
3307  pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
3308  }
3309  }
3310 
3311  try
3312  {
3313  uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
3314  uno::Sequence< uno::Any > aArgs{ uno::Any(nTab) };
3315  xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( ScSheetEventId::CALCULATE ), aArgs );
3316  }
3317  catch( uno::Exception& )
3318  {
3319  }
3320  }
3321  }
3322  }
3323  rDoc.ResetCalcNotifications();
3324 }
3325 
3326 // XOpenCLSelection
3327 
3329 {
3331 }
3332 
3334 {
3335  if (ScCalcConfig::isOpenCLEnabled() == static_cast<bool>(bEnable))
3336  return;
3338  return;
3339 
3340  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3341  officecfg::Office::Common::Misc::UseOpenCL::set(bEnable, batch);
3342  batch->commit();
3343 
3345  if (bEnable)
3346  aConfig.setOpenCLConfigToDefault();
3348 
3349 #if HAVE_FEATURE_OPENCL
3350  sc::FormulaGroupInterpreter::switchOpenCLDevice(OUString(), true);
3351 #endif
3352 
3353  ScDocument* pDoc = GetDocument();
3354  pDoc->CheckVectorizationState();
3355 
3356 }
3357 
3359 {
3361  aConfig.mbOpenCLAutoSelect = true;
3363  ScFormulaOptions aOptions = SC_MOD()->GetFormulaOptions();
3364  aOptions.SetCalcConfig(aConfig);
3365  SC_MOD()->SetFormulaOptions(aOptions);
3366 #if !HAVE_FEATURE_OPENCL
3367  (void) bForce;
3368 #else
3369  sc::FormulaGroupInterpreter::switchOpenCLDevice(OUString(), true, bForce);
3370 #endif
3371 }
3372 
3374 {
3376  aConfig.mbOpenCLAutoSelect = false;
3378  ScFormulaOptions aOptions = SC_MOD()->GetFormulaOptions();
3379  aOptions.SetCalcConfig(aConfig);
3380  SC_MOD()->SetFormulaOptions(aOptions);
3381 }
3382 
3383 void ScModelObj::selectOpenCLDevice( sal_Int32 nPlatform, sal_Int32 nDevice )
3384 {
3385  if(nPlatform < 0 || nDevice < 0)
3386  throw uno::RuntimeException();
3387 
3388 #if !HAVE_FEATURE_OPENCL
3389  throw uno::RuntimeException();
3390 #else
3391  std::vector<OpenCLPlatformInfo> aPlatformInfo;
3392  sc::FormulaGroupInterpreter::fillOpenCLInfo(aPlatformInfo);
3393  if(o3tl::make_unsigned(nPlatform) >= aPlatformInfo.size())
3394  throw uno::RuntimeException();
3395 
3396  if(o3tl::make_unsigned(nDevice) >= aPlatformInfo[nPlatform].maDevices.size())
3397  throw uno::RuntimeException();
3398 
3399  OUString aDeviceString = aPlatformInfo[nPlatform].maVendor + " " + aPlatformInfo[nPlatform].maDevices[nDevice].maName;
3400  sc::FormulaGroupInterpreter::switchOpenCLDevice(aDeviceString, false);
3401 #endif
3402 }
3403 
3405 {
3406 #if !HAVE_FEATURE_OPENCL
3407  return -1;
3408 #else
3409  sal_Int32 nPlatformId;
3410  sal_Int32 nDeviceId;
3411  sc::FormulaGroupInterpreter::getOpenCLDeviceInfo(nDeviceId, nPlatformId);
3412  return nPlatformId;
3413 #endif
3414 }
3415 
3417 {
3418 #if !HAVE_FEATURE_OPENCL
3419  return -1;
3420 #else
3421  sal_Int32 nPlatformId;
3422  sal_Int32 nDeviceId;
3423  sc::FormulaGroupInterpreter::getOpenCLDeviceInfo(nDeviceId, nPlatformId);
3424  return nDeviceId;
3425 #endif
3426 }
3427 
3428 uno::Sequence< sheet::opencl::OpenCLPlatform > ScModelObj::getOpenCLPlatforms()
3429 {
3430 #if !HAVE_FEATURE_OPENCL
3431  return uno::Sequence<sheet::opencl::OpenCLPlatform>();
3432 #else
3433  std::vector<OpenCLPlatformInfo> aPlatformInfo;
3434  sc::FormulaGroupInterpreter::fillOpenCLInfo(aPlatformInfo);
3435 
3436  uno::Sequence<sheet::opencl::OpenCLPlatform> aRet(aPlatformInfo.size());
3437  auto aRetRange = asNonConstRange(aRet);
3438  for(size_t i = 0; i < aPlatformInfo.size(); ++i)
3439  {
3440  aRetRange[i].Name = aPlatformInfo[i].maName;
3441  aRetRange[i].Vendor = aPlatformInfo[i].maVendor;
3442 
3443  aRetRange[i].Devices.realloc(aPlatformInfo[i].maDevices.size());
3444  auto pDevices = aRetRange[i].Devices.getArray();
3445  for(size_t j = 0; j < aPlatformInfo[i].maDevices.size(); ++j)
3446  {
3447  const OpenCLDeviceInfo& rDevice = aPlatformInfo[i].maDevices[j];
3448  pDevices[j].Name = rDevice.maName;
3449  pDevices[j].Vendor = rDevice.maVendor;
3450  pDevices[j].Driver = rDevice.maDriver;
3451  }
3452  }
3453 
3454  return aRet;
3455 #endif
3456 }
3457 
3458 namespace {
3459 
3461 void setOpcodeSubsetTest(bool bFlag)
3462 {
3463  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3464  officecfg::Office::Calc::Formula::Calculation::OpenCLSubsetOnly::set(bFlag, batch);
3465  batch->commit();
3466 }
3467 
3468 }
3469 
3471 {
3472  setOpcodeSubsetTest(true);
3473 }
3474 
3476 {
3477  setOpcodeSubsetTest(false);
3478 }
3479 
3481 {
3482  return officecfg::Office::Calc::Formula::Calculation::OpenCLSubsetOnly::get();
3483 }
3484 
3486 {
3487  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
3488  officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::set(number, batch);
3489  batch->commit();
3490 }
3491 
3493 {
3494  return officecfg::Office::Calc::Formula::Calculation::OpenCLMinimumDataSize::get();
3495 }
3496 
3498  pDocShell( pDocSh )
3499 {
3501 }
3502 
3504 {
3505  SolarMutexGuard g;
3506 
3507  if (pDocShell)
3509 }
3510 
3512 {
3513  // we don't care about update of references here
3514 
3515  if ( rHint.GetId() == SfxHintId::Dying )
3516  {
3517  pDocShell = nullptr; // became invalid
3518  }
3519 }
3520 
3521 uno::Reference<drawing::XDrawPage> ScDrawPagesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const
3522 {
3523  if (pDocShell)
3524  {
3525  ScDrawLayer* pDrawLayer = pDocShell->MakeDrawLayer();
3526  OSL_ENSURE(pDrawLayer,"Cannot create Draw-Layer");
3527  if ( pDrawLayer && nIndex >= 0 && nIndex < pDocShell->GetDocument().GetTableCount() )
3528  {
3529  SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nIndex));
3530  OSL_ENSURE(pPage,"Draw-Page not found");
3531  if (pPage)
3532  {
3533  return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY);
3534  }
3535  }
3536  }
3537  return nullptr;
3538 }
3539 
3540 // XDrawPages
3541 
3542 uno::Reference<drawing::XDrawPage> SAL_CALL ScDrawPagesObj::insertNewByIndex( sal_Int32 nPos )
3543 {
3544  SolarMutexGuard aGuard;
3545  uno::Reference<drawing::XDrawPage> xRet;
3546  if (pDocShell)
3547  {
3548  OUString aNewName;
3550  if ( pDocShell->GetDocFunc().InsertTable( static_cast<SCTAB>(nPos),
3551  aNewName, true, true ) )
3552  xRet.set(GetObjectByIndex_Impl( nPos ));
3553  }
3554  return xRet;
3555 }
3556 
3557 void SAL_CALL ScDrawPagesObj::remove( const uno::Reference<drawing::XDrawPage>& xPage )
3558 {
3559  SolarMutexGuard aGuard;
3560  SvxDrawPage* pImp = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage );
3561  if ( pDocShell && pImp )
3562  {
3563  SdrPage* pPage = pImp->GetSdrPage();
3564  if (pPage)
3565  {
3566  SCTAB nPageNum = static_cast<SCTAB>(pPage->GetPageNum());
3567  pDocShell->GetDocFunc().DeleteTable( nPageNum, true );
3568  }
3569  }
3570 }
3571 
3572 // XIndexAccess
3573 
3574 sal_Int32 SAL_CALL ScDrawPagesObj::getCount()
3575 {
3576  SolarMutexGuard aGuard;
3577  if (pDocShell)
3578  return pDocShell->GetDocument().GetTableCount();
3579  return 0;
3580 }
3581 
3582 uno::Any SAL_CALL ScDrawPagesObj::getByIndex( sal_Int32 nIndex )
3583 {
3584  SolarMutexGuard aGuard;
3585  uno::Reference<drawing::XDrawPage> xPage(GetObjectByIndex_Impl(nIndex));
3586  if (!xPage.is())
3587  throw lang::IndexOutOfBoundsException();
3588 
3589  return uno::Any(xPage);
3590 }
3591 
3593 {
3595 }
3596 
3598 {
3599  SolarMutexGuard aGuard;
3600  return ( getCount() != 0 );
3601 }
3602 
3604  pDocShell( pDocSh )
3605 {
3607 }
3608 
3610 {
3611  SolarMutexGuard g;
3612 
3613  if (pDocShell)
3615 }
3616 
3618 {
3619  // we don't care about update of references here
3620 
3621  if ( rHint.GetId() == SfxHintId::Dying )
3622  {
3623  pDocShell = nullptr; // became invalid
3624  }
3625 }
3626 
3627 // XSpreadsheets
3628 
3630 {
3631  if ( pDocShell && nIndex >= 0 && nIndex < pDocShell->GetDocument().GetTableCount() )
3632  return new ScTableSheetObj( pDocShell, static_cast<SCTAB>(nIndex) );
3633 
3634  return nullptr;
3635 }
3636 
3638 {
3639  if (pDocShell)
3640  {
3641  SCTAB nIndex;
3642  if ( pDocShell->GetDocument().GetTable( aName, nIndex ) )
3643  return new ScTableSheetObj( pDocShell, nIndex );
3644  }
3645  return nullptr;
3646 }
3647 
3648 void SAL_CALL ScTableSheetsObj::insertNewByName( const OUString& aName, sal_Int16 nPosition )
3649 {
3650  SolarMutexGuard aGuard;
3651  bool bDone = false;
3652  if (pDocShell)
3653  {
3654  bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName, true, true );
3655  }
3656  if (!bDone)
3657  throw uno::RuntimeException(); // no other exceptions specified
3658 }
3659 
3660 void SAL_CALL ScTableSheetsObj::moveByName( const OUString& aName, sal_Int16 nDestination )
3661 {
3662  SolarMutexGuard aGuard;
3663  bool bDone = false;
3664  if (pDocShell)
3665  {
3666  SCTAB nSource;
3667  if ( pDocShell->GetDocument().GetTable( aName, nSource ) )
3668  bDone = pDocShell->MoveTable( nSource, nDestination, false, true );
3669  }
3670  if (!bDone)
3671  throw uno::RuntimeException(); // no other exceptions specified
3672 }
3673 
3674 void SAL_CALL ScTableSheetsObj::copyByName( const OUString& aName,
3675  const OUString& aCopy, sal_Int16 nDestination )
3676 {
3677  SolarMutexGuard aGuard;
3678  bool bDone = false;
3679  if (pDocShell)
3680  {
3681  SCTAB nSource;
3682  if ( pDocShell->GetDocument().GetTable( aName, nSource ) )
3683  {
3684  bDone = pDocShell->MoveTable( nSource, nDestination, true, true );
3685  if (bDone)
3686  {
3687  // #i92477# any index past the last sheet means "append" in MoveTable
3688  SCTAB nResultTab = static_cast<SCTAB>(nDestination);
3689  SCTAB nTabCount = pDocShell->GetDocument().GetTableCount(); // count after copying
3690  if (nResultTab >= nTabCount)
3691  nResultTab = nTabCount - 1;
3692 
3693  bDone = pDocShell->GetDocFunc().RenameTable( nResultTab, aCopy,
3694  true, true );
3695  }
3696  }
3697  }
3698  if (!bDone)
3699  throw uno::RuntimeException(); // no other exceptions specified
3700 }
3701 
3702 void SAL_CALL ScTableSheetsObj::insertByName( const OUString& aName, const uno::Any& aElement )
3703 {
3704  SolarMutexGuard aGuard;
3705  bool bDone = false;
3706  bool bIllArg = false;
3707 
3709 
3710  if ( pDocShell )
3711  {
3712  uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
3713  if ( xInterface.is() )
3714  {
3715  ScTableSheetObj* pSheetObj = comphelper::getFromUnoTunnel<ScTableSheetObj>( xInterface );
3716  if ( pSheetObj && !pSheetObj->GetDocShell() ) // not inserted yet?
3717  {
3718  ScDocument& rDoc = pDocShell->GetDocument();
3719  SCTAB nDummy;
3720  if ( rDoc.GetTable( aName, nDummy ) )
3721  {
3722  // name already exists
3723  throw container::ElementExistException();
3724  }
3725  SCTAB nPosition = rDoc.GetTableCount();
3726  bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName,
3727  true, true );
3728  if (bDone)
3729  pSheetObj->InitInsertSheet( pDocShell, nPosition );
3730  // set document and new range in the object
3731  }
3732  else
3733  bIllArg = true;
3734  }
3735  else
3736  bIllArg = true;
3737  }
3738 
3739  if (!bDone)
3740  {
3741  if (bIllArg)
3742  throw lang::IllegalArgumentException();
3743  else
3744  throw uno::RuntimeException(); // ElementExistException is handled above
3745  }
3746 }
3747 
3748 void SAL_CALL ScTableSheetsObj::replaceByName( const OUString& aName, const uno::Any& aElement )
3749 {
3750  SolarMutexGuard aGuard;
3751  bool bDone = false;
3752  bool bIllArg = false;
3753 
3755 
3756  if ( pDocShell )
3757  {
3758  uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY);
3759  if ( xInterface.is() )
3760  {
3761  ScTableSheetObj* pSheetObj = comphelper::getFromUnoTunnel<ScTableSheetObj>( xInterface );
3762  if ( pSheetObj && !pSheetObj->GetDocShell() ) // not inserted yet?
3763  {
3764  SCTAB nPosition;
3765  if ( !pDocShell->GetDocument().GetTable( aName, nPosition ) )
3766  {
3767  // not found
3768  throw container::NoSuchElementException();
3769  }
3770 
3771  if ( pDocShell->GetDocFunc().DeleteTable( nPosition, true ) )
3772  {
3773  // InsertTable can't really go wrong now
3774  bDone = pDocShell->GetDocFunc().InsertTable( nPosition, aName, true, true );
3775  if (bDone)
3776  pSheetObj->InitInsertSheet( pDocShell, nPosition );
3777  }
3778 
3779  }
3780  else
3781  bIllArg = true;
3782  }
3783  else
3784  bIllArg = true;
3785  }
3786 
3787  if (!bDone)
3788  {
3789  if (bIllArg)
3790  throw lang::IllegalArgumentException();
3791  else
3792  throw uno::RuntimeException(); // NoSuchElementException is handled above
3793  }
3794 }
3795 
3796 void SAL_CALL ScTableSheetsObj::removeByName( const OUString& aName )
3797 {
3798  SolarMutexGuard aGuard;
3799  bool bDone = false;
3800  if (pDocShell)
3801  {
3802  SCTAB nIndex;
3803  if ( !pDocShell->GetDocument().GetTable( aName, nIndex ) )
3804  throw container::NoSuchElementException(); // not found
3805  bDone = pDocShell->GetDocFunc().DeleteTable( nIndex, true );
3806  }
3807 
3808  if (!bDone)
3809  throw uno::RuntimeException(); // NoSuchElementException is handled above
3810 }
3811 
3813  const uno::Reference < sheet::XSpreadsheetDocument > & xDocSrc,
3814  const OUString& srcName, const sal_Int32 nDestPosition )
3815 {
3816  //pDocShell is the destination
3817  ScDocument& rDocDest = pDocShell->GetDocument();
3818 
3819  // Source document docShell
3820  if ( !xDocSrc.is() )
3821  throw uno::RuntimeException();
3822  ScModelObj* pObj = comphelper::getFromUnoTunnel<ScModelObj>(xDocSrc);
3823  ScDocShell* pDocShellSrc = static_cast<ScDocShell*>(pObj->GetEmbeddedObject());
3824 
3825  // SourceSheet Position and does srcName exists ?
3826  SCTAB nIndexSrc;
3827  if ( !pDocShellSrc->GetDocument().GetTable( srcName, nIndexSrc ) )
3828  throw lang::IllegalArgumentException();
3829 
3830  // Check the validity of destination index.
3831  SCTAB nCount = rDocDest.GetTableCount();
3832  SCTAB nIndexDest = static_cast<SCTAB>(nDestPosition);
3833  if (nIndexDest > nCount || nIndexDest < 0)
3834  throw lang::IndexOutOfBoundsException();
3835 
3836  // Transfer Tab
3838  *pDocShellSrc, nIndexSrc, nIndexDest, true/*bInsertNew*/, true/*bNotifyAndPaint*/ );
3839 
3840  return nIndexDest;
3841 }
3842 
3843 // XCellRangesAccess
3844 
3845 uno::Reference< table::XCell > SAL_CALL ScTableSheetsObj::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow, sal_Int32 nSheet )
3846 {
3847  SolarMutexGuard aGuard;
3848  rtl::Reference<ScTableSheetObj> xSheet = GetObjectByIndex_Impl(static_cast<sal_uInt16>(nSheet));
3849  if (! xSheet.is())
3850  throw lang::IndexOutOfBoundsException();
3851 
3852  return xSheet->getCellByPosition(nColumn, nRow);
3853 }
3854 
3855 uno::Reference< table::XCellRange > SAL_CALL ScTableSheetsObj::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom, sal_Int32 nSheet )
3856 {
3857  SolarMutexGuard aGuard;
3858  rtl::Reference<ScTableSheetObj> xSheet = GetObjectByIndex_Impl(static_cast<sal_uInt16>(nSheet));
3859  if (! xSheet.is())
3860  throw lang::IndexOutOfBoundsException();
3861 
3862  return xSheet->getCellRangeByPosition(nLeft, nTop, nRight, nBottom);
3863 }
3864 
3865 uno::Sequence < uno::Reference< table::XCellRange > > SAL_CALL ScTableSheetsObj::getCellRangesByName( const OUString& aRange )
3866 {
3867  SolarMutexGuard aGuard;
3868  uno::Sequence < uno::Reference < table::XCellRange > > xRet;
3869 
3870  ScRangeList aRangeList;
3871  ScDocument& rDoc = pDocShell->GetDocument();
3873  throw lang::IllegalArgumentException();
3874 
3875  size_t nCount = aRangeList.size();
3876  if (!nCount)
3877  throw lang::IllegalArgumentException();
3878 
3879  xRet.realloc(nCount);
3880  auto pRet = xRet.getArray();
3881  for( size_t nIndex = 0; nIndex < nCount; nIndex++ )
3882  {
3883  const ScRange & rRange = aRangeList[ nIndex ];
3884  pRet[nIndex] = new ScCellRangeObj(pDocShell, rRange);
3885  }
3886 
3887  return xRet;
3888 }
3889 
3890 // XEnumerationAccess
3891 
3892 uno::Reference<container::XEnumeration> SAL_CALL ScTableSheetsObj::createEnumeration()
3893 {
3894  SolarMutexGuard aGuard;
3895  return new ScIndexEnumeration(this, "com.sun.star.sheet.SpreadsheetsEnumeration");
3896 }
3897 
3898 // XIndexAccess
3899 
3900 sal_Int32 SAL_CALL ScTableSheetsObj::getCount()
3901 {
3902  SolarMutexGuard aGuard;
3903  if (pDocShell)
3904  return pDocShell->GetDocument().GetTableCount();
3905  return 0;
3906 }
3907 
3908 uno::Any SAL_CALL ScTableSheetsObj::getByIndex( sal_Int32 nIndex )
3909 {
3910  SolarMutexGuard aGuard;
3911  uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByIndex_Impl(nIndex));
3912  if (!xSheet.is())
3913  throw lang::IndexOutOfBoundsException();
3914 
3915  return uno::Any(xSheet);
3916 
3917 // return uno::Any();
3918 }
3919 
3921 {
3923 }
3924 
3926 {
3927  SolarMutexGuard aGuard;
3928  return ( getCount() != 0 );
3929 }
3930 
3931 // XNameAccess
3932 
3933 uno::Any SAL_CALL ScTableSheetsObj::getByName( const OUString& aName )
3934 {
3935  SolarMutexGuard aGuard;
3936  uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByName_Impl(aName));
3937  if (!xSheet.is())
3938  throw container::NoSuchElementException();
3939 
3940  return uno::Any(xSheet);
3941 }
3942 
3943 uno::Sequence<OUString> SAL_CALL ScTableSheetsObj::getElementNames()
3944 {
3945  SolarMutexGuard aGuard;
3946  if (pDocShell)
3947  {
3948  ScDocument& rDoc = pDocShell->GetDocument();
3949  SCTAB nCount = rDoc.GetTableCount();
3950  OUString aName;
3951  uno::Sequence<OUString> aSeq(nCount);
3952  OUString* pAry = aSeq.getArray();
3953  for (SCTAB i=0; i<nCount; i++)
3954  {
3955  rDoc.GetName( i, aName );
3956  pAry[i] = aName;
3957  }
3958  return aSeq;
3959  }
3960  return uno::Sequence<OUString>();
3961 }
3962 
3963 sal_Bool SAL_CALL ScTableSheetsObj::hasByName( const OUString& aName )
3964 {
3965  SolarMutexGuard aGuard;
3966  if (pDocShell)
3967  {
3968  SCTAB nIndex;
3969  if ( pDocShell->GetDocument().GetTable( aName, nIndex ) )
3970  return true;
3971  }
3972  return false;
3973 }
3974 
3976  pDocShell( pDocSh ),
3977  nTab ( nT ),
3978  nStartCol( nSC ),
3979  nEndCol ( nEC )
3980 {
3982 }
3983 
3985 {
3986  SolarMutexGuard g;
3987 
3988  if (pDocShell)
3990 }
3991 
3993 {
3994  if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
3995  {
3997  }
3998  else if ( rHint.GetId() == SfxHintId::Dying )
3999  {
4000  pDocShell = nullptr; // became invalid
4001  }
4002 }
4003 
4004 // XTableColumns
4005 
4007 {
4008  SCCOL nCol = static_cast<SCCOL>(nIndex) + nStartCol;
4009  if ( pDocShell && nCol <= nEndCol )
4010  return new ScTableColumnObj( pDocShell, nCol, nTab );
4011 
4012  return nullptr; // wrong index
4013 }
4014 
4016 {
4017  SCCOL nCol = 0;
4018  if (pDocShell && ::AlphaToCol(pDocShell->GetDocument(), nCol, aName))
4019  if (nCol >= nStartCol && nCol <= nEndCol)
4020  return new ScTableColumnObj( pDocShell, nCol, nTab );
4021 
4022  return nullptr;
4023 }
4024 
4025 void SAL_CALL ScTableColumnsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount )
4026 {
4027  SolarMutexGuard aGuard;
4028  bool bDone = false;
4029  if ( pDocShell )
4030  {
4031  const ScDocument& rDoc = pDocShell->GetDocument();
4032  if ( nCount > 0 && nPosition >= 0 && nStartCol+nPosition <= nEndCol &&
4033  nStartCol+nPosition+nCount-1 <= rDoc.MaxCol() )
4034  {
4035  ScRange aRange( static_cast<SCCOL>(nStartCol+nPosition), 0, nTab,
4036  static_cast<SCCOL>(nStartCol+nPosition+nCount-1), rDoc.MaxRow(), nTab );
4037  bDone = pDocShell->GetDocFunc().InsertCells( aRange, nullptr, INS_INSCOLS_BEFORE, true, true );
4038  }
4039  }
4040  if (!bDone)
4041  throw uno::RuntimeException(); // no other exceptions specified
4042 }
4043 
4044 void SAL_CALL ScTableColumnsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount )
4045 {
4046  SolarMutexGuard aGuard;
4047  bool bDone = false;
4048  // the range to be deleted has to lie within the object
4049  if ( pDocShell )
4050  {
4051  const ScDocument& rDoc = pDocShell->GetDocument();
4052  if ( nCount > 0 && nIndex >= 0 && nStartCol+nIndex+nCount-1 <= nEndCol )
4053  {
4054  ScRange aRange( static_cast<SCCOL>(nStartCol+nIndex), 0, nTab,
4055  static_cast<SCCOL>(nStartCol+nIndex+nCount-1), rDoc.MaxRow(), nTab );
4056  bDone = pDocShell->GetDocFunc().DeleteCells( aRange, nullptr, DelCellCmd::Cols, true );
4057  }
4058  }
4059  if (!bDone)
4060  throw uno::RuntimeException(); // no other exceptions specified
4061 }
4062 
4063 // XEnumerationAccess
4064 
4065 uno::Reference<container::XEnumeration> SAL_CALL ScTableColumnsObj::createEnumeration()
4066 {
4067  SolarMutexGuard aGuard;
4068  return new ScIndexEnumeration(this, "com.sun.star.table.TableColumnsEnumeration");
4069 }
4070 
4071 // XIndexAccess
4072 
4073 sal_Int32 SAL_CALL ScTableColumnsObj::getCount()
4074 {
4075  SolarMutexGuard aGuard;
4076  return nEndCol - nStartCol + 1;
4077 }
4078 
4079 uno::Any SAL_CALL ScTableColumnsObj::getByIndex( sal_Int32 nIndex )
4080 {
4081  SolarMutexGuard aGuard;
4082  uno::Reference<table::XCellRange> xColumn(GetObjectByIndex_Impl(nIndex));
4083  if (!xColumn.is())
4084  throw lang::IndexOutOfBoundsException();
4085 
4086  return uno::Any(xColumn);
4087 
4088 }
4089 
4091 {
4093 }
4094 
4096 {
4097  SolarMutexGuard aGuard;
4098  return ( getCount() != 0 );
4099 }
4100 
4101 uno::Any SAL_CALL ScTableColumnsObj::getByName( const OUString& aName )
4102 {
4103  SolarMutexGuard aGuard;
4104  uno::Reference<table::XCellRange> xColumn(GetObjectByName_Impl(aName));
4105  if (!xColumn.is())
4106  throw container::NoSuchElementException();
4107 
4108  return uno::Any(xColumn);
4109 }
4110 
4111 uno::Sequence<OUString> SAL_CALL ScTableColumnsObj::getElementNames()
4112 {
4113  SolarMutexGuard aGuard;
4114  SCCOL nCount = nEndCol - nStartCol + 1;
4115  uno::Sequence<OUString> aSeq(nCount);
4116  OUString* pAry = aSeq.getArray();
4117  for (SCCOL i=0; i<nCount; i++)
4118  pAry[i] = ::ScColToAlpha( nStartCol + i );
4119 
4120  return aSeq;
4121 }
4122 
4123 sal_Bool SAL_CALL ScTableColumnsObj::hasByName( const OUString& aName )
4124 {
4125  SolarMutexGuard aGuard;
4126  SCCOL nCol = 0;
4127  if (pDocShell && ::AlphaToCol(pDocShell->GetDocument(), nCol, aName))
4128  if (nCol >= nStartCol && nCol <= nEndCol)
4129  return true;
4130 
4131  return false; // not found
4132 }
4133 
4134 // XPropertySet
4135 
4136 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnsObj::getPropertySetInfo()
4137 {
4138  static uno::Reference<beans::XPropertySetInfo> aRef(
4140  return aRef;
4141 }
4142 
4144  const OUString& aPropertyName, const uno::Any& aValue )
4145 {
4146  SolarMutexGuard aGuard;
4147  if (!pDocShell)
4148  throw uno::RuntimeException();
4149 
4150  std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(nStartCol,nEndCol));
4151  ScDocFunc& rFunc = pDocShell->GetDocFunc();
4152 
4153  if ( aPropertyName == SC_UNONAME_CELLWID )
4154  {
4155  sal_Int32 nNewWidth = 0;
4156  if ( aValue >>= nNewWidth )
4157  rFunc.SetWidthOrHeight(
4158  true, aColArr, nTab, SC_SIZE_ORIGINAL, o3tl::toTwips(nNewWidth, o3tl::Length::mm100), true, true);
4159  }
4160  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4161  {
4162  bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4164  rFunc.SetWidthOrHeight(true, aColArr, nTab, eMode, 0, true, true);
4165  // SC_SIZE_DIRECT with size 0: hide
4166  }
4167  else if ( aPropertyName == SC_UNONAME_OWIDTH )
4168  {
4169  bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4170  if (bOpt)
4171  rFunc.SetWidthOrHeight(
4172  true, aColArr, nTab, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, true, true);
4173  // sal_False for columns currently has no effect
4174  }
4175  else if ( aPropertyName == SC_UNONAME_NEWPAGE || aPropertyName == SC_UNONAME_MANPAGE )
4176  {
4178  bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4179  for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
4180  if (bSet)
4181  rFunc.InsertPageBreak( true, ScAddress(nCol,0,nTab), true, true );
4182  else
4183  rFunc.RemovePageBreak( true, ScAddress(nCol,0,nTab), true, true );
4184  }
4185 }
4186 
4187 uno::Any SAL_CALL ScTableColumnsObj::getPropertyValue( const OUString& aPropertyName )
4188 {
4189  SolarMutexGuard aGuard;
4190  if (!pDocShell)
4191  throw uno::RuntimeException();
4192 
4193  ScDocument& rDoc = pDocShell->GetDocument();
4194  uno::Any aAny;
4195 
4197 
4198  if ( aPropertyName == SC_UNONAME_CELLWID )
4199  {
4200  // for hidden column, return original height
4201  sal_uInt16 nWidth = rDoc.GetOriginalWidth( nStartCol, nTab );
4202  aAny <<= static_cast<sal_Int32>(convertTwipToMm100(nWidth));
4203  }
4204  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4205  {
4206  bool bVis = !rDoc.ColHidden(nStartCol, nTab);
4207  aAny <<= bVis;
4208  }
4209  else if ( aPropertyName == SC_UNONAME_OWIDTH )
4210  {
4211  bool bOpt = !(rDoc.GetColFlags( nStartCol, nTab ) & CRFlags::ManualSize);
4212  aAny <<= bOpt;
4213  }
4214  else if ( aPropertyName == SC_UNONAME_NEWPAGE )
4215  {
4216  ScBreakType nBreak = rDoc.HasColBreak(nStartCol, nTab);
4217  aAny <<= (nBreak != ScBreakType::NONE);
4218  }
4219  else if ( aPropertyName == SC_UNONAME_MANPAGE )
4220  {
4221  ScBreakType nBreak = rDoc.HasColBreak(nStartCol, nTab);
4222  aAny <<= bool(nBreak & ScBreakType::Manual);
4223  }
4224 
4225  return aAny;
4226 }
4227 
4229 
4231  pDocShell( pDocSh ),
4232  nTab ( nT ),
4233  nStartRow( nSR ),
4234  nEndRow ( nER )
4235 {
4236  pDocShell->GetDocument().AddUnoObject(*this);
4237 }
4238 
4240 {
4241  SolarMutexGuard g;
4242 
4243  if (pDocShell)
4245 }
4246 
4248 {
4249  if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4250  {
4252  }
4253  else if ( rHint.GetId() == SfxHintId::Dying )
4254  {
4255  pDocShell = nullptr; // became invalid
4256  }
4257 }
4258 
4259 // XTableRows
4260 
4262 {
4263  SCROW nRow = static_cast<SCROW>(nIndex) + nStartRow;
4264  if ( pDocShell && nRow <= nEndRow )
4265  return new ScTableRowObj( pDocShell, nRow, nTab );
4266 
4267  return nullptr; // wrong index
4268 }
4269 
4270 void SAL_CALL ScTableRowsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount )
4271 {
4272  SolarMutexGuard aGuard;
4273  bool bDone = false;
4274  if ( pDocShell )
4275  {
4276  const ScDocument& rDoc = pDocShell->GetDocument();
4277  if ( nCount > 0 && nPosition >= 0 && nStartRow+nPosition <= nEndRow &&
4278  nStartRow+nPosition+nCount-1 <= rDoc.MaxRow() )
4279  {
4280  ScRange aRange( 0, static_cast<SCROW>(nStartRow+nPosition), nTab,
4281  rDoc.MaxCol(), static_cast<SCROW>(nStartRow+nPosition+nCount-1), nTab );
4282  bDone = pDocShell->GetDocFunc().InsertCells( aRange, nullptr, INS_INSROWS_BEFORE, true, true );
4283  }
4284  }
4285  if (!bDone)
4286  throw uno::RuntimeException(); // no other exceptions specified
4287 }
4288 
4289 void SAL_CALL ScTableRowsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount )
4290 {
4291  SolarMutexGuard aGuard;
4292  bool bDone = false;
4293  // the range to be deleted has to lie within the object
4294  if ( pDocShell && nCount > 0 && nIndex >= 0 && nStartRow+nIndex+nCount-1 <= nEndRow )
4295  {
4296  const ScDocument& rDoc = pDocShell->GetDocument();
4297  ScRange aRange( 0, static_cast<SCROW>(nStartRow+nIndex), nTab,
4298  rDoc.MaxCol(), static_cast<SCROW>(nStartRow+nIndex+nCount-1), nTab );
4299  bDone = pDocShell->GetDocFunc().DeleteCells( aRange, nullptr, DelCellCmd::Rows, true );
4300  }
4301  if (!bDone)
4302  throw uno::RuntimeException(); // no other exceptions specified
4303 }
4304 
4305 // XEnumerationAccess
4306 
4307 uno::Reference<container::XEnumeration> SAL_CALL ScTableRowsObj::createEnumeration()
4308 {
4309  SolarMutexGuard aGuard;
4310  return new ScIndexEnumeration(this, "com.sun.star.table.TableRowsEnumeration");
4311 }
4312 
4313 // XIndexAccess
4314 
4315 sal_Int32 SAL_CALL ScTableRowsObj::getCount()
4316 {
4317  SolarMutexGuard aGuard;
4318  return nEndRow - nStartRow + 1;
4319 }
4320 
4321 uno::Any SAL_CALL ScTableRowsObj::getByIndex( sal_Int32 nIndex )
4322 {
4323  SolarMutexGuard aGuard;
4324  uno::Reference<table::XCellRange> xRow(GetObjectByIndex_Impl(nIndex));
4325  if (!xRow.is())
4326  throw lang::IndexOutOfBoundsException();
4327 
4328  return uno::Any(xRow);
4329 }
4330 
4332 {
4334 }
4335 
4337 {
4338  SolarMutexGuard aGuard;
4339  return ( getCount() != 0 );
4340 }
4341 
4342 // XPropertySet
4343 
4344 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowsObj::getPropertySetInfo()
4345 {
4346  static uno::Reference<beans::XPropertySetInfo> aRef(
4348  return aRef;
4349 }
4350 
4352  const OUString& aPropertyName, const uno::Any& aValue )
4353 {
4354  SolarMutexGuard aGuard;
4355  if (!pDocShell)
4356  throw uno::RuntimeException();
4357 
4358  ScDocFunc& rFunc = pDocShell->GetDocFunc();
4359  ScDocument& rDoc = pDocShell->GetDocument();
4360  std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(nStartRow,nEndRow));
4361 
4362  if ( aPropertyName == SC_UNONAME_OHEIGHT )
4363  {
4364  sal_Int32 nNewHeight = 0;
4365  if ( rDoc.IsImportingXML() && ( aValue >>= nNewHeight ) )
4366  {
4367  // used to set the stored row height for rows with optimal height when loading.
4368 
4369  // TODO: It's probably cleaner to use a different property name
4370  // for this.
4372  }
4373  else
4374  {
4375  bool bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4376  if (bOpt)
4377  rFunc.SetWidthOrHeight(false, aRowArr, nTab, SC_SIZE_OPTIMAL, 0, true, true);
4378  else
4379  {
4381  }
4382  }
4383  }
4384  else if ( aPropertyName == SC_UNONAME_CELLHGT )
4385  {
4386  sal_Int32 nNewHeight = 0;
4387  if ( aValue >>= nNewHeight )
4388  {
4389  if (rDoc.IsImportingXML())
4390  {
4391  // TODO: This is a band-aid fix. Eventually we need to
4392  // re-work ods' style import to get it to set styles to
4393  // ScDocument directly.
4395  rDoc.SetManualHeight( nStartRow, nEndRow, nTab, true );
4396  }
4397  else
4398  rFunc.SetWidthOrHeight(
4399  false, aRowArr, nTab, SC_SIZE_ORIGINAL, o3tl::toTwips(nNewHeight, o3tl::Length::mm100), true, true);
4400  }
4401  }
4402  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4403  {
4404  bool bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4406  rFunc.SetWidthOrHeight(false, aRowArr, nTab, eMode, 0, true, true);
4407  // SC_SIZE_DIRECT with size 0: hide
4408  }
4409  else if ( aPropertyName == SC_UNONAME_VISFLAG )
4410  {
4411  // #i116460# Shortcut to only set the flag, without drawing layer update etc.
4412  // Should only be used from import filters.
4414  }
4415  else if ( aPropertyName == SC_UNONAME_CELLFILT )
4416  {
4418  if (ScUnoHelpFunctions::GetBoolFromAny( aValue ))
4419  rDoc.SetRowFiltered(nStartRow, nEndRow, nTab, true);
4420  else
4421  rDoc.SetRowFiltered(nStartRow, nEndRow, nTab, false);
4422  }
4423  else if ( aPropertyName == SC_UNONAME_NEWPAGE || aPropertyName == SC_UNONAME_MANPAGE )
4424  {
4426  bool bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue );
4427  for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
4428  if (bSet)
4429  rFunc.InsertPageBreak( false, ScAddress(0,nRow,nTab), true, true );
4430  else
4431  rFunc.RemovePageBreak( false, ScAddress(0,nRow,nTab), true, true );
4432  }
4433  else if ( aPropertyName == SC_UNONAME_CELLBACK || aPropertyName == SC_UNONAME_CELLTRAN )
4434  {
4435  // #i57867# Background color is specified for row styles in the file format,
4436  // so it has to be supported along with the row properties (import only).
4437 
4438  // Use ScCellRangeObj to set the property for all cells in the rows
4439  // (this means, the "row attribute" must be set before individual cell attributes).
4440 
4441  ScRange aRange( 0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab );
4442  uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange );
4443  xRangeObj->setPropertyValue( aPropertyName, aValue );
4444  }
4445 }
4446 
4447 uno::Any SAL_CALL ScTableRowsObj::getPropertyValue( const OUString& aPropertyName )
4448 {
4449  SolarMutexGuard aGuard;
4450  if (!pDocShell)
4451  throw uno::RuntimeException();
4452 
4453  ScDocument& rDoc = pDocShell->GetDocument();
4454  uno::Any aAny;
4455 
4457 
4458  if ( aPropertyName == SC_UNONAME_CELLHGT )
4459  {
4460  // for hidden row, return original height
4461  sal_uInt16 nHeight = rDoc.GetOriginalHeight( nStartRow, nTab );
4462  aAny <<= static_cast<sal_Int32>(convertTwipToMm100(nHeight));
4463  }
4464  else if ( aPropertyName == SC_UNONAME_CELLVIS )
4465  {
4466  SCROW nLastRow;
4467  bool bVis = !rDoc.RowHidden(nStartRow, nTab, nullptr, &nLastRow);
4468  aAny <<= bVis;
4469  }
4470  else if ( aPropertyName == SC_UNONAME_CELLFILT )
4471  {
4472  bool bVis = rDoc.RowFiltered(nStartRow, nTab);
4473  aAny <<= bVis;
4474  }
4475  else if ( aPropertyName == SC_UNONAME_OHEIGHT )
4476  {
4477  bool bOpt = !(rDoc.GetRowFlags( nStartRow, nTab ) & CRFlags::ManualSize);
4478  aAny <<= bOpt;
4479  }
4480  else if ( aPropertyName == SC_UNONAME_NEWPAGE )
4481  {
4482  ScBreakType nBreak = rDoc.HasRowBreak(nStartRow, nTab);
4483  aAny <<= (nBreak != ScBreakType::NONE);
4484  }
4485  else if ( aPropertyName == SC_UNONAME_MANPAGE )
4486  {
4487  ScBreakType nBreak = rDoc.HasRowBreak(nStartRow, nTab);
4488  aAny <<= bool(nBreak & ScBreakType::Manual);
4489  }
4490  else if ( aPropertyName == SC_UNONAME_CELLBACK || aPropertyName == SC_UNONAME_CELLTRAN )
4491  {
4492  // Use ScCellRangeObj to get the property from the cell range
4493  // (for completeness only, this is not used by the XML filter).
4494 
4495  ScRange aRange( 0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab );
4496  uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange );
4497  aAny = xRangeObj->getPropertyValue( aPropertyName );
4498  }
4499 
4500  return aAny;
4501 }
4502 
4504 
4506 {
4507 }
4508 
4509 // XPropertySet
4510 
4511 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSpreadsheetSettingsObj::getPropertySetInfo()
4512 {
4513  return nullptr;
4514 }
4515 
4517  const OUString& /* aPropertyName */, const uno::Any& /* aValue */ )
4518 {
4519 }
4520 
4521 uno::Any SAL_CALL ScSpreadsheetSettingsObj::getPropertyValue( const OUString& /* aPropertyName */ )
4522 {
4523  return uno::Any();
4524 }
4525 
4527 
4529  pDocShell( pDocSh ),
4530  nTab( nT )
4531 {
4532  pDocShell->GetDocument().AddUnoObject(*this);
4533 }
4534 
4536 {
4537  SolarMutexGuard g;
4538 
4539  if (pDocShell)
4541 }
4542 
4544 {
4546 
4547  if ( rHint.GetId() == SfxHintId::Dying )
4548  {
4549  pDocShell = nullptr; // became invalid
4550  }
4551 }
4552 
4553 bool ScAnnotationsObj::GetAddressByIndex_Impl( sal_Int32 nIndex, ScAddress& rPos ) const
4554 {
4555  if (!pDocShell)
4556  return false;
4557 
4558  ScDocument& rDoc = pDocShell->GetDocument();
4559  rPos = rDoc.GetNotePosition(nIndex, nTab);
4560  return rPos.IsValid();
4561 }
4562 
4564 {
4565  if (pDocShell)
4566  {
4567  ScAddress aPos;
4568  if ( GetAddressByIndex_Impl( nIndex, aPos ) )
4569  return new ScAnnotationObj( pDocShell, aPos );
4570  }
4571  return nullptr;
4572 }
4573 
4574 // XSheetAnnotations
4575 
4577  const table::CellAddress& aPosition, const OUString& rText )
4578 {
4579  SolarMutexGuard aGuard;
4580  if (pDocShell)
4581  {
4582  OSL_ENSURE( aPosition.Sheet == nTab, "addAnnotation with a wrong Sheet" );
4583  ScAddress aPos( static_cast<SCCOL>(aPosition.Column), static_cast<SCROW>(aPosition.Row), nTab );
4584  pDocShell->GetDocFunc().ReplaceNote( aPos, rText, nullptr, nullptr, true );
4585  }
4586 }
4587 
4588 void SAL_CALL ScAnnotationsObj::removeByIndex( sal_Int32 nIndex )
4589 {
4590  SolarMutexGuard aGuard;
4591  if (pDocShell)
4592  {
4593  ScAddress aPos;
4594  if ( GetAddressByIndex_Impl( nIndex, aPos ) )
4595  {
4597  aMarkData.SelectTable( aPos.Tab(), true );
4598  aMarkData.SetMultiMarkArea( ScRange(aPos) );
4599 
4600  pDocShell->GetDocFunc().DeleteContents( aMarkData, InsertDeleteFlags::NOTE, true, true );
4601  }
4602  }
4603 }
4604 
4605 // XEnumerationAccess
4606 
4607 uno::Reference<container::XEnumeration> SAL_CALL ScAnnotationsObj::createEnumeration()
4608 {
4610 
4611  SolarMutexGuard aGuard;
4612  return new ScIndexEnumeration(this, "com.sun.star.sheet.CellAnnotationsEnumeration");
4613 }
4614 
4615 // XIndexAccess
4616 
4617 sal_Int32 SAL_CALL ScAnnotationsObj::getCount()
4618 {
4619  SolarMutexGuard aGuard;
4620  sal_Int32 nCount = 0;
4621  if (pDocShell)
4622  {
4623  const ScDocument& rDoc = pDocShell->GetDocument();
4624  for (SCCOL nCol : rDoc.GetAllocatedColumnsRange(nTab, 0, rDoc.MaxCol()))
4625  nCount += rDoc.GetNoteCount(nTab, nCol);
4626  }
4627  return nCount;
4628 }
4629 
4630 uno::Any SAL_CALL ScAnnotationsObj::getByIndex( sal_Int32 nIndex )
4631 {
4632  SolarMutexGuard aGuard;
4633  uno::Reference<sheet::XSheetAnnotation> xAnnotation(GetObjectByIndex_Impl(nIndex));
4634  if (!xAnnotation.is())
4635  throw lang::IndexOutOfBoundsException();
4636 
4637  return uno::Any(xAnnotation);
4638 }
4639 
4641 {
4643 }
4644 
4646 {
4647  SolarMutexGuard aGuard;
4648  return ( getCount() != 0 );
4649 }
4650 
4652  pDocShell( pDocSh ),
4653  nTab ( nT )
4654 {
4656 }
4657 
4659 {
4660  SolarMutexGuard g;
4661 
4662  if (pDocShell)
4664 }
4665 
4667 {
4668  if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
4669  {
4671  }
4672  else if ( rHint.GetId() == SfxHintId::Dying )
4673  {
4674  pDocShell = nullptr; // became invalid
4675  }
4676 }
4677 
4678 // XScenarios
4679 
4680 bool ScScenariosObj::GetScenarioIndex_Impl( std::u16string_view rName, SCTAB& rIndex )
4681 {
4683 
4684  if ( pDocShell )
4685  {
4686  OUString aTabName;
4687  ScDocument& rDoc = pDocShell->GetDocument();
4688  SCTAB nCount = static_cast<SCTAB>(getCount());
4689  for (SCTAB i=0; i<nCount; i++)
4690  if (rDoc.GetName( nTab+i+1, aTabName ))
4691  if (aTabName == rName)
4692  {
4693  rIndex = i;
4694  return true;
4695  }
4696  }
4697 
4698  return false;
4699 }
4700 
4702 {
4703  sal_uInt16 nCount = static_cast<sal_uInt16>(getCount());
4704  if ( pDocShell && nIndex >= 0 && nIndex < nCount )
4705  return new ScTableSheetObj( pDocShell, nTab+static_cast<SCTAB>(nIndex)+1 );
4706 
4707  return nullptr; // no document or wrong index
4708 }
4709 
4711 {
4712  SCTAB nIndex;
4713  if ( pDocShell && GetScenarioIndex_Impl( aName, nIndex ) )
4714  return new ScTableSheetObj( pDocShell, nTab+nIndex+1 );
4715 
4716  return nullptr; // not found
4717 }
4718 
4719 void SAL_CALL ScScenariosObj::addNewByName( const OUString& aName,
4720  const uno::Sequence<table::CellRangeAddress>& aRanges,
4721  const OUString& aComment )
4722 {
4723  SolarMutexGuard aGuard;
4724  if ( !pDocShell )
4725  return;
4726 
4728  aMarkData.SelectTable( nTab, true );
4729 
4730  for (const table::CellRangeAddress& rRange : aRanges)
4731  {
4732  OSL_ENSURE( rRange.Sheet == nTab, "addScenario with a wrong Tab" );
4733  ScRange aRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), nTab,
4734  static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), nTab );
4735 
4736  aMarkData.SetMultiMarkArea( aRange );
4737  }
4738 
4741 
4742  pDocShell->MakeScenario( nTab, aName, aComment, COL_LIGHTGRAY, nFlags, aMarkData );
4743 }
4744 
4745 void SAL_CALL ScScenariosObj::removeByName( const OUString& aName )
4746 {
4747  SolarMutexGuard aGuard;
4748  SCTAB nIndex;
4749  if ( pDocShell && GetScenarioIndex_Impl( aName, nIndex ) )
4750  pDocShell->GetDocFunc().DeleteTable( nTab+nIndex+1, true );
4751 }
4752 
4753 // XEnumerationAccess
4754 
4755 uno::Reference<container::XEnumeration> SAL_CALL ScScenariosObj::createEnumeration()
4756 {
4757  SolarMutexGuard aGuard;
4758  return new ScIndexEnumeration(this, "com.sun.star.sheet.ScenariosEnumeration");
4759 }
4760 
4761 // XIndexAccess
4762 
4763 sal_Int32 SAL_CALL ScScenariosObj::getCount()
4764 {
4765  SolarMutexGuard aGuard;
4766  SCTAB nCount = 0;
4767  if ( pDocShell )
4768  {
4769  ScDocument& rDoc = pDocShell->GetDocument();
4770  if (!rDoc.IsScenario(nTab))
4771  {
4772  SCTAB nTabCount = rDoc.GetTableCount();
4773  SCTAB nNext = nTab + 1;
4774  while (nNext < nTabCount && rDoc.IsScenario(nNext))
4775  {
4776  ++nCount;
4777  ++nNext;
4778  }
4779  }
4780  }
4781  return nCount;
4782 }
4783 
4784 uno::Any SAL_CALL ScScenariosObj::getByIndex( sal_Int32 nIndex )
4785 {
4786  SolarMutexGuard aGuard;
4787  uno::Reference<sheet::XScenario> xScen(GetObjectByIndex_Impl(nIndex));
4788  if (!xScen.is())
4789  throw lang::IndexOutOfBoundsException();
4790 
4791  return uno::Any(xScen);
4792 }
4793 
4795 {
4797 }
4798 
4800 {
4801  SolarMutexGuard aGuard;
4802  return ( getCount() != 0 );
4803 }
4804 
4805 uno::Any SAL_CALL ScScenariosObj::getByName( const OUString& aName )
4806 {
4807  SolarMutexGuard aGuard;
4808  uno::Reference<sheet::XScenario> xScen(GetObjectByName_Impl(aName));
4809  if (!xScen.is())
4810  throw container::NoSuchElementException();
4811 
4812  return uno::Any(xScen);
4813 }
4814 
4815 uno::Sequence<OUString> SAL_CALL ScScenariosObj::getElementNames()
4816 {
4817  SolarMutexGuard aGuard;
4818  SCTAB nCount = static_cast<SCTAB>(getCount());
4819  uno::Sequence<OUString> aSeq(nCount);
4820 
4821  if ( pDocShell ) // otherwise Count = 0
4822  {
4823  OUString aTabName;
4824  ScDocument& rDoc = pDocShell->GetDocument();
4825  OUString* pAry = aSeq.getArray();
4826  for (SCTAB i=0; i<nCount; i++)
4827  if (rDoc.GetName( nTab+i+1, aTabName ))
4828  pAry[i] = aTabName;
4829  }
4830 
4831  return aSeq;
4832 }
4833 
4834 sal_Bool SAL_CALL ScScenariosObj::hasByName( const OUString& aName )
4835 {
4836  SolarMutexGuard aGuard;
4837  SCTAB nIndex;
4838  return GetScenarioIndex_Impl( aName, nIndex );
4839 }
4840 
4841 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::sheet::GoalResult SAL_CALL seekGoal(const css::table::CellAddress &aFormulaPosition, const css::table::CellAddress &aVariablePosition, const OUString &aGoalValue) override
XGoalSeek.
Definition: docuno.cxx:2533
OUString AsRGBHexString() const
SC_DLLPUBLIC bool IsDocProtected() const
Definition: documen3.cxx:1902
Stores the selection in the ScPrintFuncCache so it is only used for the same selection again...
Definition: pfuncache.hxx:45
virtual void SAL_CALL lockControllers() override
Definition: docuno.cxx:2408
ScPrintSelectionMode GetMode() const
Definition: pfuncache.hxx:61
SC_DLLPUBLIC bool GetPrintArea(SCTAB nTab, SCCOL &rEndCol, SCROW &rEndRow, bool bNotes=true) const
Definition: documen2.cxx:594
#define SC_UNO_IGNORECASE
Definition: unonames.hxx:507
SCTAB nTab
Collection belongs to the sheet.
Definition: docuno.hxx:670
SfxViewFrame * GetViewFrame() const
virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
Definition: docuno.cxx:4079
OUString const & getRuntimeUID() const
virtual sal_Int32 SAL_CALL getFormulaCellNumberLimit() override
Definition: docuno.cxx:3492
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
XPropertySet.
Definition: docuno.cxx:4344
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
XEnumerationAccess.
Definition: docuno.cxx:4307
bool GetScenarioIndex_Impl(std::u16string_view rName, SCTAB &rIndex)
Definition: docuno.cxx:4680
bool setGraphicSelection(int nType, int nX, int nY, double fScaleX=1.0, double fScaleY=1.0)
virtual void SAL_CALL disableOpcodeSubsetTest() override
Definition: docuno.cxx:3475
void SetAutoComplete(bool bNew)
Definition: appoptio.hxx:53
constexpr sal_Int32 STD_EXTRA_WIDTH
Definition: global.hxx:87
#define SC_UNO_ISADJUSTHEIGHTENABLED
Definition: unonames.hxx:524
virtual css::uno::Type SAL_CALL getElementType() override
XElementAccess.
Definition: docuno.cxx:4331
tools::Long GetOutOffYPixel() const
void SetDigitLanguage(LanguageType)
void setGrabBagItem(const css::uno::Any &rVal)
static void notifyOtherViews(const SfxViewShell *pThisView, int nType, std::string_view rKey, const OString &rPayload)
#define SC_UNO_SPELLONLINE
Definition: unonames.hxx:514
css::uno::Reference< css::uno::XInterface > create(OUString const &aServiceSpecifier, css::uno::Sequence< css::uno::Any > const *arguments)
Definition: docuno.cxx:2980
void UnlockPaint()
Definition: docsh3.cxx:322
virtual void SAL_CALL enableAutomaticDeviceSelection(sal_Bool bForce) override
Definition: docuno.cxx:3358
SfxHintId
bool hasValidSignatures() const
virtual css::uno::Any SAL_CALL getByName(const OUString &aName) override
XNameAccess.
Definition: docuno.cxx:4805
void setOpenCLConfigToDefault()
Definition: calcconfig.cxx:100
void MarkToSimple()
Definition: markdata.cxx:222
virtual void SAL_CALL addChangesListener(const css::uno::Reference< css::util::XChangesListener > &aListener) override
XChangesNotifier.
Definition: docuno.cxx:3163
bool hasValue()
sal_Int32 nIndex
virtual void getCellCursor(tools::JsonWriter &rJsonWriter) override
Definition: docuno.cxx:1065
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: gridwin.cxx:1687
#define PROP_UNO_CALCASSHOWN
Definition: optuno.hxx:25
ScAddress aStart
Definition: address.hxx:497
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
virtual void SAL_CALL lockControllers() override
SC_DLLPUBLIC bool GetDataStart(SCTAB nTab, SCCOL &rStartCol, SCROW &rStartRow) const
Definition: documen2.cxx:662
virtual void SAL_CALL unprotect(const OUString &aPassword) override
Definition: docuno.cxx:2498
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString &aServiceSpecifier) override
XMultiServiceFactory.
Definition: docuno.cxx:3064
void SetConsolidateDlgData(std::unique_ptr< ScConsolidateParam > pData)
Definition: documen2.cxx:1129
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
Definition: docuno.cxx:3582
static bool HasValidData(const css::uno::Reference< css::datatransfer::XTransferable > &rTransferable)
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
Definition: docsh3.cxx:451
virtual css::uno::Reference< css::sheet::XSpreadsheets > SAL_CALL getSheets() override
XSpreadsheetDocument.
Definition: docuno.cxx:1411
virtual void SAL_CALL enableOpenCL(sal_Bool bEnable) override
Definition: docuno.cxx:3333
bool Unprotect(SCTAB nTab, const OUString &rPassword, bool bApi)
Definition: docfunc.cxx:4033
#define SC_UNONAME_VISFLAG
Definition: unonames.hxx:187
Iterator begin(const o3tl::sorted_vector< sal_Int32 > *i_pPossibleValues=nullptr) const
virtual void SAL_CALL removeByIndex(sal_Int32 nIndex, sal_Int32 nCount) override
Definition: docuno.cxx:4044
virtual void completeFunction(const OUString &rFunctionName) override
Definition: docuno.cxx:1221
SC_DLLPUBLIC CRFlags GetColFlags(SCCOL nCol, SCTAB nTab) const
Definition: document.cxx:4378
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
void SetAutoControlFocus(bool _bAutoControlFocus)
SC_DLLPUBLIC ScColumnsRange GetAllocatedColumnsRange(SCTAB nTab, SCCOL nColBegin, SCCOL nColEnd) const
Definition: document.cxx:2562
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
Definition: docuno.cxx:4111
Reference< XRow > xRow
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getLinks() override
XLinkTargetSupplier.
Definition: docuno.cxx:2356
SC_DLLPUBLIC bool DeleteContents(const ScMarkData &rMark, InsertDeleteFlags nFlags, bool bRecord, bool bApi)
Definition: docfunc.cxx:583
rtl::Reference< ScTableColumnObj > GetObjectByIndex_Impl(sal_Int32 nIndex) const
Definition: docuno.cxx:4006
virtual sal_Int32 SAL_CALL getCount() override
XIndexAccess.
Definition: docuno.cxx:3574
SC_DLLPUBLIC bool IsNegativePage(SCTAB nTab) const
Definition: document.cxx:997
virtual void SAL_CALL unlockControllers() override
Definition: docuno.cxx:2416
constexpr auto toTwips(N number, Length from)
static bool MakeRangeFromName(const OUString &rName, const ScDocument &rDoc, SCTAB nCurTab, ScRange &rRange, RutlNameScope eScope=RUTL_NAMES, ScAddress::Details const &rDetails=ScAddress::detailsOOOa1, bool bUseDetailsPos=false)
Definition: rangeutl.cxx:233
virtual sal_Bool SAL_CALL hasByName(const OUString &aName) override
Definition: docuno.cxx:3963
SCROW Row() const
Definition: address.hxx:274
ScDocShell * GetDocShell() const
Definition: cellsuno.hxx:241
void setWidth(tools::Long nWidth)
ScInterpreterContext & GetThreadedContext() const
Definition: document.hxx:621