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