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