summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/docshell/docsh4.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/docshell/docsh4.cxx')
-rw-r--r--sc/source/ui/docshell/docsh4.cxx2788
1 files changed, 2788 insertions, 0 deletions
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
new file mode 100644
index 000000000..f64ecaeaa
--- /dev/null
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -0,0 +1,2788 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <boost/property_tree/json_parser.hpp>
+
+#include <com/sun/star/frame/Desktop.hpp>
+
+using namespace ::com::sun::star;
+
+#include <scitems.hxx>
+#include <editeng/flstitem.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/infobar.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <svtools/ehdl.hxx>
+#include <svtools/langtab.hxx>
+#include <basic/sbxcore.hxx>
+#include <basic/sberrors.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svx/ofaitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/whiter.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <svx/drawitem.hxx>
+#include <svx/fmshell.hxx>
+#include <sfx2/passwd.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/sfxdlg.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <svl/documentlockfile.hxx>
+#include <svl/sharecontrolfile.hxx>
+#include <unotools/securityoptions.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sal/log.hxx>
+#include <unotools/charclass.hxx>
+#include <tools/diagnose_ex.h>
+#include <o3tl/string_view.hxx>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <docuno.hxx>
+
+#include <docsh.hxx>
+#include "docshimp.hxx"
+#include <docfunc.hxx>
+#include <scres.hrc>
+#include <strings.hrc>
+#include <stlsheet.hxx>
+#include <stlpool.hxx>
+#include <appoptio.hxx>
+#include <globstr.hrc>
+#include <global.hxx>
+#include <dbdocfun.hxx>
+#include <printfun.hxx>
+#include <viewdata.hxx>
+#include <tabvwsh.hxx>
+#include <impex.hxx>
+#include <undodat.hxx>
+#include <undocell.hxx>
+#include <inputhdl.hxx>
+#include <dbdata.hxx>
+#include <servobj.hxx>
+#include <rangenam.hxx>
+#include <scmod.hxx>
+#include <chgviset.hxx>
+#include <reffact.hxx>
+#include <chartlis.hxx>
+#include <chartpos.hxx>
+#include <tablink.hxx>
+#include <drwlayer.hxx>
+#include <docoptio.hxx>
+#include <undostyl.hxx>
+#include <rangeseq.hxx>
+#include <chgtrack.hxx>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <scresid.hxx>
+#include <scabstdlg.hxx>
+#include <sharedocdlg.hxx>
+#include <conditio.hxx>
+#include <sheetevents.hxx>
+#include <formulacell.hxx>
+#include <documentlinkmgr.hxx>
+#include <memory>
+#include <sfx2/notebookbar/SfxNotebookBar.hxx>
+#include <helpids.h>
+#include <editeng/eeitem.hxx>
+#include <editeng/langitem.hxx>
+
+#include <svx/xdef.hxx>
+
+void ScDocShell::SetInitialLinkUpdate( const SfxMedium* pMed )
+{
+ if (pMed)
+ {
+ const SfxUInt16Item* pUpdateDocItem = SfxItemSet::GetItem<SfxUInt16Item>( pMed->GetItemSet(),
+ SID_UPDATEDOCMODE, false);
+ m_nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : css::document::UpdateDocMode::NO_UPDATE;
+ }
+
+ // GetLinkUpdateModeState() evaluates m_nCanUpdate so that must have
+ // been set first. Do not override an already forbidden LinkUpdate (the
+ // default is allow).
+ comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
+ if (rEmbeddedObjectContainer.getUserAllowsLinkUpdate())
+ {
+ // For anything else than LM_ALWAYS we need user confirmation.
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate( GetLinkUpdateModeState() == LM_ALWAYS);
+ }
+}
+
+ScLkUpdMode ScDocShell::GetLinkUpdateModeState() const
+{
+ ScLkUpdMode nSet;
+ if (m_nCanUpdate == css::document::UpdateDocMode::NO_UPDATE)
+ nSet = LM_NEVER;
+ else if (m_nCanUpdate == css::document::UpdateDocMode::FULL_UPDATE)
+ nSet = LM_ALWAYS;
+ else
+ {
+ nSet = GetDocument().GetLinkMode();
+ if (nSet == LM_UNKNOWN)
+ {
+ ScAppOptions aAppOptions = SC_MOD()->GetAppOptions();
+ nSet = aAppOptions.GetLinkMode();
+ }
+ }
+
+ if (nSet == LM_ALWAYS
+ && !(SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks(
+ GetMedium() == nullptr ? OUString() : GetMedium()->GetName())
+ || (IsDocShared()
+ && SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks(
+ GetSharedFileURL()))))
+ {
+ nSet = LM_ON_DEMAND;
+ }
+ if (m_nCanUpdate == css::document::UpdateDocMode::QUIET_UPDATE
+ && nSet == LM_ON_DEMAND)
+ {
+ nSet = LM_NEVER;
+ }
+
+ return nSet;
+}
+
+void ScDocShell::AllowLinkUpdate()
+{
+ m_pDocument->SetLinkFormulaNeedingCheck(false);
+ getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true);
+}
+
+void ScDocShell::ReloadAllLinks()
+{
+ AllowLinkUpdate();
+
+ ReloadTabLinks();
+ weld::Window *pDialogParent = GetActiveDialogParent();
+ m_pDocument->UpdateExternalRefLinks(pDialogParent);
+
+ bool bAnyDde = m_pDocument->GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(pDialogParent);
+
+ if (bAnyDde)
+ {
+ // calculate formulas and paint like in the TrackTimeHdl
+ m_pDocument->TrackFormulas();
+ Broadcast(SfxHint(SfxHintId::ScDataChanged));
+
+ // Should FID_DATACHANGED become asynchronous some time
+ // (e.g., with Invalidate at Window), an update needs to be forced here.
+ }
+
+ m_pDocument->UpdateAreaLinks();
+}
+
+IMPL_LINK_NOARG( ScDocShell, ReloadAllLinksHdl, weld::Button&, void )
+{
+ ReloadAllLinks();
+
+ ScTabViewShell* pViewSh = GetBestViewShell();
+ SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
+ if (pViewFrame)
+ pViewFrame->RemoveInfoBar(u"enablecontent");
+ SAL_WARN_IF(!pViewFrame, "sc", "expected there to be a ViewFrame");
+}
+
+namespace
+{
+ class LinkHelp
+ {
+ public:
+ DECL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, void);
+ };
+}
+
+IMPL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, rBtn, void)
+{
+ if (Help* pHelp = Application::GetHelp())
+ pHelp->Start(HID_UPDATE_LINK_WARNING, &rBtn);
+}
+
+void ScDocShell::Execute( SfxRequest& rReq )
+{
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ SfxBindings* pBindings = GetViewBindings();
+ bool bUndo (m_pDocument->IsUndoEnabled());
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case SID_SC_SETTEXT:
+ {
+ const SfxPoolItem* pColItem;
+ const SfxPoolItem* pRowItem;
+ const SfxPoolItem* pTabItem;
+ const SfxPoolItem* pTextItem;
+ if( pReqArgs && pReqArgs->HasItem( FN_PARAM_1, &pColItem ) &&
+ pReqArgs->HasItem( FN_PARAM_2, &pRowItem ) &&
+ pReqArgs->HasItem( FN_PARAM_3, &pTabItem ) &&
+ pReqArgs->HasItem( SID_SC_SETTEXT, &pTextItem ) )
+ {
+ // parameters are 1-based !!!
+ SCCOL nCol = static_cast<const SfxInt16Item*>(pColItem)->GetValue() - 1;
+ SCROW nRow = static_cast<const SfxInt32Item*>(pRowItem)->GetValue() - 1;
+ SCTAB nTab = static_cast<const SfxInt16Item*>(pTabItem)->GetValue() - 1;
+
+ SCTAB nTabCount = m_pDocument->GetTableCount();
+ if ( m_pDocument->ValidCol(nCol) && m_pDocument->ValidRow(nRow) && ValidTab(nTab,nTabCount) )
+ {
+ if ( m_pDocument->IsBlockEditable( nTab, nCol,nRow, nCol, nRow ) )
+ {
+ OUString aVal = static_cast<const SfxStringItem*>(pTextItem)->GetValue();
+ m_pDocument->SetString( nCol, nRow, nTab, aVal );
+
+ PostPaintCell( nCol, nRow, nTab );
+ SetDocumentModified();
+
+ rReq.Done();
+ break;
+ }
+ else // protected cell
+ {
+#if HAVE_FEATURE_SCRIPTING
+ SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER ); //! which error ?
+#endif
+ break;
+ }
+ }
+ }
+#if HAVE_FEATURE_SCRIPTING
+ SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
+#endif
+ }
+ break;
+
+ case SID_SBA_IMPORT:
+ {
+ if (pReqArgs)
+ {
+ const SfxPoolItem* pItem;
+ svx::ODataAccessDescriptor aDesc;
+ if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
+ {
+ uno::Any aAny = static_cast<const SfxUnoAnyItem*>(pItem)->GetValue();
+ uno::Sequence<beans::PropertyValue> aProperties;
+ if ( aAny >>= aProperties )
+ aDesc.initializeFrom( aProperties );
+ }
+
+ OUString sTarget;
+ if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
+ sTarget = static_cast<const SfxStringItem*>(pItem)->GetValue();
+
+ bool bIsNewArea = true; // Default sal_True (no inquiry)
+ if ( pReqArgs->GetItemState( FN_PARAM_2, true, &pItem ) == SfxItemState::SET )
+ bIsNewArea = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+
+ // if necessary, create new database area
+ bool bMakeArea = false;
+ if (bIsNewArea)
+ {
+ ScDBCollection* pDBColl = m_pDocument->GetDBCollection();
+ if ( !pDBColl || !pDBColl->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(sTarget)) )
+ {
+ ScAddress aPos;
+ if ( aPos.Parse( sTarget, *m_pDocument, m_pDocument->GetAddressConvention() ) & ScRefFlags::VALID )
+ {
+ bMakeArea = true;
+ if (bUndo)
+ {
+ OUString aStrImport = ScResId( STR_UNDO_IMPORTDATA );
+ ViewShellId nViewShellId(-1);
+ if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
+ nViewShellId = pViewSh->GetViewShellId();
+ GetUndoManager()->EnterListAction( aStrImport, aStrImport, 0, nViewShellId );
+ }
+
+ ScDBData* pDBData = GetDBData( ScRange(aPos), SC_DB_IMPORT, ScGetDBSelection::Keep );
+ OSL_ENSURE(pDBData, "Cannot create DB data");
+ sTarget = pDBData->GetName();
+ }
+ }
+ }
+
+ // inquire, before old DB range gets overwritten
+ bool bDo = true;
+ if (!bIsNewArea)
+ {
+ OUString aTemplate = ScResId( STR_IMPORT_REPLACE );
+ OUString aMessage = o3tl::getToken(aTemplate, 0, '#' )
+ + sTarget
+ + o3tl::getToken(aTemplate, 1, '#' );
+
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Question, VclButtonsType::YesNo,
+ aMessage));
+ xQueryBox->set_default_response(RET_YES);
+ bDo = xQueryBox->run() == RET_YES;
+ }
+
+ if (bDo)
+ {
+ ScDBDocFunc(*this).UpdateImport( sTarget, aDesc );
+ rReq.Done();
+
+ // UpdateImport also updates the internal operations
+ }
+ else
+ rReq.Ignore();
+
+ if ( bMakeArea && bUndo)
+ GetUndoManager()->LeaveListAction();
+ }
+ else
+ {
+ OSL_FAIL( "arguments expected" );
+ }
+ }
+ break;
+
+ case SID_CHART_SOURCE:
+ case SID_CHART_ADDSOURCE:
+ if (pReqArgs)
+ {
+ ScDocument& rDoc = GetDocument();
+ const SfxPoolItem* pItem;
+ OUString aChartName, aRangeName;
+
+ ScRange aSingleRange;
+ ScRangeListRef aRangeListRef;
+ bool bMultiRange = false;
+
+ bool bColHeaders = true;
+ bool bRowHeaders = true;
+ bool bColInit = false;
+ bool bRowInit = false;
+ bool bAddRange = (nSlot == SID_CHART_ADDSOURCE);
+
+ if( const SfxStringItem* pChartItem = pReqArgs->GetItemIfSet( SID_CHART_NAME ) )
+ aChartName = pChartItem->GetValue();
+
+ if( const SfxStringItem* pChartItem = pReqArgs->GetItemIfSet( SID_CHART_SOURCE ) )
+ aRangeName = pChartItem->GetValue();
+
+ if( pReqArgs->HasItem( FN_PARAM_1, &pItem ) )
+ {
+ bColHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ bColInit = true;
+ }
+ if( pReqArgs->HasItem( FN_PARAM_2, &pItem ) )
+ {
+ bRowHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ bRowInit = true;
+ }
+
+ ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
+ bool bValid = (aSingleRange.ParseAny(aRangeName, rDoc, aDetails) & ScRefFlags::VALID) != ScRefFlags::ZERO;
+ if (!bValid)
+ {
+ aRangeListRef = new ScRangeList;
+ aRangeListRef->Parse( aRangeName, rDoc, rDoc.GetAddressConvention());
+ if ( !aRangeListRef->empty() )
+ {
+ bMultiRange = true;
+ aSingleRange = aRangeListRef->front(); // for header
+ bValid = true;
+ }
+ else
+ aRangeListRef.clear();
+ }
+
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if (pViewSh && bValid && !aChartName.isEmpty() )
+ {
+ weld::Window* pParent = pViewSh->GetFrameWeld();
+
+ SCCOL nCol1 = aSingleRange.aStart.Col();
+ SCROW nRow1 = aSingleRange.aStart.Row();
+ SCCOL nCol2 = aSingleRange.aEnd.Col();
+ SCROW nRow2 = aSingleRange.aEnd.Row();
+ SCTAB nTab = aSingleRange.aStart.Tab();
+
+ //! limit always or not at all ???
+ if (!bMultiRange)
+ m_pDocument->LimitChartArea( nTab, nCol1,nRow1, nCol2,nRow2 );
+
+ // Dialog for column/row headers
+ bool bOk = true;
+ if ( !bAddRange && ( !bColInit || !bRowInit ) )
+ {
+ ScChartPositioner aChartPositioner( *m_pDocument, nTab, nCol1,nRow1, nCol2,nRow2 );
+ if (!bColInit)
+ bColHeaders = aChartPositioner.HasColHeaders();
+ if (!bRowInit)
+ bRowHeaders = aChartPositioner.HasRowHeaders();
+
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+
+ ScopedVclPtr<AbstractScColRowLabelDlg> pDlg(pFact->CreateScColRowLabelDlg(pParent, bRowHeaders, bColHeaders));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ bColHeaders = pDlg->IsRow();
+ bRowHeaders = pDlg->IsCol();
+
+ rReq.AppendItem(SfxBoolItem(FN_PARAM_1, bColHeaders));
+ rReq.AppendItem(SfxBoolItem(FN_PARAM_2, bRowHeaders));
+ }
+ else
+ bOk = false;
+ }
+
+ if (bOk) // execute
+ {
+ if (bMultiRange)
+ {
+ if (bUndo)
+ {
+ GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoChartData>( this, aChartName, aRangeListRef,
+ bColHeaders, bRowHeaders, bAddRange ) );
+ }
+ m_pDocument->UpdateChartArea( aChartName, aRangeListRef,
+ bColHeaders, bRowHeaders, bAddRange );
+ }
+ else
+ {
+ ScRange aNewRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
+ if (bUndo)
+ {
+ GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoChartData>( this, aChartName, aNewRange,
+ bColHeaders, bRowHeaders, bAddRange ) );
+ }
+ m_pDocument->UpdateChartArea( aChartName, aNewRange,
+ bColHeaders, bRowHeaders, bAddRange );
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL("UpdateChartArea: no ViewShell or wrong data");
+ }
+ rReq.Done();
+ }
+ else
+ {
+ OSL_FAIL("SID_CHART_SOURCE without arguments");
+ }
+ break;
+
+ case FID_AUTO_CALC:
+ {
+ bool bNewVal;
+ const SfxPoolItem* pItem;
+ if ( pReqArgs && SfxItemState::SET == pReqArgs->GetItemState( nSlot, true, &pItem ) )
+ bNewVal = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ else
+ bNewVal = !m_pDocument->GetAutoCalc(); // Toggle for menu
+ m_pDocument->SetAutoCalc( bNewVal );
+ SetDocumentModified();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_AUTO_CALC );
+ }
+ rReq.AppendItem( SfxBoolItem( FID_AUTO_CALC, bNewVal ) );
+ rReq.Done();
+ }
+ break;
+ case FID_RECALC:
+ DoRecalc( rReq.IsAPI() );
+ rReq.Done();
+ break;
+ case FID_HARD_RECALC:
+ DoHardRecalc();
+ rReq.Done();
+ break;
+ case SID_UPDATETABLINKS:
+ {
+ ScLkUpdMode nSet = GetLinkUpdateModeState();
+
+ if (nSet == LM_ALWAYS)
+ {
+ ReloadAllLinks();
+ rReq.Done();
+ }
+ else if (nSet == LM_NEVER)
+ {
+ getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false);
+ rReq.Ignore();
+ }
+ else if (nSet == LM_ON_DEMAND)
+ {
+ ScTabViewShell* pViewSh = GetBestViewShell();
+ SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
+ if (pViewFrame)
+ {
+ pViewFrame->RemoveInfoBar(u"enablecontent");
+ auto pInfoBar = pViewFrame->AppendInfoBar("enablecontent", "", ScResId(STR_RELOAD_TABLES), InfobarType::WARNING);
+ if (pInfoBar)
+ {
+ weld::Button& rHelpBtn = pInfoBar->addButton();
+ rHelpBtn.set_label(GetStandardText(StandardButtonType::Help).replaceFirst("~", ""));
+ rHelpBtn.connect_clicked(LINK(nullptr, LinkHelp, DispatchHelpLinksHdl));
+ weld::Button& rBtn = pInfoBar->addButton();
+ rBtn.set_label(ScResId(STR_ENABLE_CONTENT));
+ rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP));
+ rBtn.connect_clicked(LINK(this, ScDocShell, ReloadAllLinksHdl));
+ }
+ }
+ rReq.Done();
+ }
+ }
+ break;
+
+ case SID_REIMPORT_AFTER_LOAD:
+ {
+ // Is called after loading if there are DB areas with omitted data
+
+ bool bDone = false;
+ ScDBCollection* pDBColl = m_pDocument->GetDBCollection();
+
+ if ((m_nCanUpdate != css::document::UpdateDocMode::NO_UPDATE) &&
+ (m_nCanUpdate != css::document::UpdateDocMode::QUIET_UPDATE))
+ {
+ ScRange aRange;
+ ScTabViewShell* pViewSh = GetBestViewShell();
+ OSL_ENSURE(pViewSh,"SID_REIMPORT_AFTER_LOAD: no View");
+ if (pViewSh && pDBColl)
+ {
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetActiveDialogParent(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ ScResId(STR_REIMPORT_AFTER_LOAD)));
+ xQueryBox->set_default_response(RET_YES);
+ if (xQueryBox->run() == RET_YES)
+ {
+ ScDBCollection::NamedDBs& rDBs = pDBColl->getNamedDBs();
+ for (const auto& rxDB : rDBs)
+ {
+ ScDBData& rDBData = *rxDB;
+ if ( rDBData.IsStripData() &&
+ rDBData.HasImportParam() && !rDBData.HasImportSelection() )
+ {
+ rDBData.GetArea(aRange);
+ pViewSh->MarkRange(aRange);
+
+ // Import and internal operations like SID_REFRESH_DBAREA
+ // (inquiry for import not needed here)
+
+ ScImportParam aImportParam;
+ rDBData.GetImportParam( aImportParam );
+ bool bContinue = pViewSh->ImportData( aImportParam );
+ rDBData.SetImportParam( aImportParam );
+
+ // mark (size may have changed)
+ rDBData.GetArea(aRange);
+ pViewSh->MarkRange(aRange);
+
+ if ( bContinue ) // error at import -> abort
+ {
+ // internal operations, if some where saved
+
+ if ( rDBData.HasQueryParam() || rDBData.HasSortParam() ||
+ rDBData.HasSubTotalParam() )
+ pViewSh->RepeatDB();
+
+ // pivot tables, which have the range as source data
+
+ RefreshPivotTables(aRange);
+ }
+ }
+ }
+ bDone = true;
+ }
+ }
+ }
+
+ if ( !bDone && pDBColl )
+ {
+ // if not, but then update the dependent formulas
+ //! also for individual ranges, which cannot be updated
+
+ m_pDocument->CalcAll(); //! only for the dependent
+ PostDataChanged();
+ }
+
+ if (bDone)
+ rReq.Done();
+ else
+ rReq.Ignore();
+ }
+ break;
+
+ case SID_AUTO_STYLE:
+ OSL_FAIL("use ScAutoStyleHint instead of SID_AUTO_STYLE");
+ break;
+
+ case SID_GET_COLORLIST:
+ {
+ const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE);
+ const XColorListRef& pList = pColItem->GetColorList();
+ rReq.SetReturnValue(OfaXColorListItem(SID_GET_COLORLIST, pList));
+ }
+ break;
+
+ case FID_CHG_RECORD:
+ {
+ ScDocument& rDoc = GetDocument();
+ // get argument (recorded macro)
+ const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FID_CHG_RECORD);
+ bool bDo = true;
+
+ // desired state
+ ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
+ bool bActivateTracking = (pChangeTrack == nullptr); // toggle
+ if ( pItem )
+ bActivateTracking = pItem->GetValue(); // from argument
+
+ if ( !bActivateTracking )
+ {
+ if ( !pItem )
+ {
+ // no dialog on playing the macro
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
+ VclMessageType::Warning, VclButtonsType::YesNo,
+ ScResId(STR_END_REDLINING)));
+ xWarn->set_default_response(RET_NO);
+ bDo = (xWarn->run() == RET_YES );
+ }
+
+ if ( bDo )
+ {
+ if (pChangeTrack)
+ {
+ if ( pChangeTrack->IsProtected() )
+ bDo = ExecuteChangeProtectionDialog();
+ }
+ if ( bDo )
+ {
+ rDoc.EndChangeTracking();
+ PostPaintGridAll();
+ }
+ }
+ }
+ else
+ {
+ rDoc.StartChangeTracking();
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges(true);
+ rDoc.SetChangeViewSettings(aChangeViewSet);
+ }
+
+ if ( bDo )
+ {
+ UpdateAcceptChangesDialog();
+
+ // invalidate slots
+ if (pBindings)
+ pBindings->InvalidateAll(false);
+ if ( !pItem )
+ rReq.AppendItem( SfxBoolItem( FID_CHG_RECORD, bActivateTracking ) );
+ rReq.Done();
+ }
+ else
+ rReq.Ignore();
+ }
+ break;
+
+ case SID_CHG_PROTECT :
+ {
+ if ( ExecuteChangeProtectionDialog() )
+ {
+ rReq.Done();
+ SetDocumentModified();
+ }
+ else
+ rReq.Ignore();
+ }
+ break;
+
+ case SID_DOCUMENT_MERGE:
+ case SID_DOCUMENT_COMPARE:
+ {
+ bool bDo = true;
+ ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
+ if ( pChangeTrack && !m_pImpl->bIgnoreLostRedliningWarning )
+ {
+ if ( nSlot == SID_DOCUMENT_COMPARE )
+ { //! old changes trace will be lost
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
+ VclMessageType::Warning, VclButtonsType::YesNo,
+ ScResId(STR_END_REDLINING)));
+ xWarn->set_default_response(RET_NO);
+ if (xWarn->run() == RET_YES)
+ bDo = ExecuteChangeProtectionDialog( true );
+ else
+ bDo = false;
+ }
+ else // merge might reject some actions
+ bDo = ExecuteChangeProtectionDialog( true );
+ }
+ if ( !bDo )
+ {
+ rReq.Ignore();
+ break;
+ }
+ SfxApplication* pApp = SfxGetpApp();
+ const SfxPoolItem* pItem;
+ const SfxStringItem* pFileNameItem(nullptr);
+ SfxMedium* pMed = nullptr;
+ if (pReqArgs)
+ pFileNameItem = pReqArgs->GetItemIfSet(SID_FILE_NAME);
+ if (pFileNameItem)
+ {
+ OUString aFileName = pFileNameItem->GetValue();
+
+ OUString aFilterName;
+ if (const SfxStringItem* pFilterItem = pReqArgs->GetItemIfSet(SID_FILTER_NAME))
+ {
+ aFilterName = pFilterItem->GetValue();
+ }
+ OUString aOptions;
+ if (const SfxStringItem* pOptionsItem = pReqArgs->GetItemIfSet(SID_FILE_FILTEROPTIONS))
+ {
+ aOptions = pOptionsItem->GetValue();
+ }
+ short nVersion = 0;
+ const SfxInt16Item* pInt16Item(nullptr);
+ if (pReqArgs->GetItemState(SID_VERSION, true, &pItem) == SfxItemState::SET)
+ pInt16Item = dynamic_cast<const SfxInt16Item*>(pItem);
+ if (pInt16Item)
+ {
+ nVersion = pInt16Item->GetValue();
+ }
+
+ // no filter specified -> detection
+ if (aFilterName.isEmpty())
+ ScDocumentLoader::GetFilterName( aFileName, aFilterName, aOptions, true, false );
+
+ // filter name from dialog contains application prefix,
+ // GetFilter needs name without the prefix.
+ ScDocumentLoader::RemoveAppPrefix( aFilterName );
+
+ std::shared_ptr<const SfxFilter> pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( aFilterName );
+ auto pSet = std::make_shared<SfxAllItemSet>( pApp->GetPool() );
+ if (!aOptions.isEmpty())
+ pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
+ if ( nVersion != 0 )
+ pSet->Put( SfxInt16Item( SID_VERSION, nVersion ) );
+ pMed = new SfxMedium( aFileName, StreamMode::STD_READ, pFilter, std::move(pSet) );
+ }
+ else
+ {
+ const sfx2::DocumentInserter::Mode mode { nSlot==SID_DOCUMENT_COMPARE
+ ? sfx2::DocumentInserter::Mode::Compare
+ : sfx2::DocumentInserter::Mode::Merge};
+ // start file dialog asynchronous
+ m_pImpl->bIgnoreLostRedliningWarning = true;
+ m_pImpl->pRequest.reset(new SfxRequest( rReq ));
+ m_pImpl->pDocInserter.reset();
+
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ weld::Window* pParent = pViewSh ? pViewSh->GetFrameWeld() : nullptr;
+ m_pImpl->pDocInserter.reset( new ::sfx2::DocumentInserter(pParent,
+ ScDocShell::Factory().GetFactoryName(), mode ) );
+ m_pImpl->pDocInserter->StartExecuteModal( LINK( this, ScDocShell, DialogClosedHdl ) );
+ return ;
+ }
+
+ // now execute in earnest...
+ SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
+
+ // pOtherDocSh->DoClose() will be called explicitly later, but it is still more safe to use SfxObjectShellLock here
+ ScDocShell* pOtherDocSh = new ScDocShell;
+ SfxObjectShellLock aDocShTablesRef = pOtherDocSh;
+ pOtherDocSh->DoLoad( pMed );
+ ErrCode nErr = pOtherDocSh->GetErrorCode();
+ if (nErr)
+ ErrorHandler::HandleError( nErr ); // also warnings
+
+ if ( !pOtherDocSh->GetError() ) // only errors
+ {
+ bool bHadTrack = ( m_pDocument->GetChangeTrack() != nullptr );
+#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
+ sal_uLong nStart = 0;
+ if ( nSlot == SID_DOCUMENT_MERGE && pChangeTrack )
+ {
+ nStart = pChangeTrack->GetActionMax() + 1;
+ }
+#endif
+ if ( nSlot == SID_DOCUMENT_COMPARE )
+ CompareDocument( pOtherDocSh->GetDocument() );
+ else
+ MergeDocument( pOtherDocSh->GetDocument() );
+
+ // show "accept changes" dialog
+ //! get view for this document!
+ if ( !IsDocShared() )
+ {
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm )
+ {
+ pViewFrm->ShowChildWindow( ScAcceptChgDlgWrapper::GetChildWindowId() ); //@51669
+ }
+ if ( pBindings )
+ {
+ pBindings->Invalidate( FID_CHG_ACCEPT );
+ }
+ }
+
+ rReq.SetReturnValue( SfxInt32Item( nSlot, 0 ) ); //! ???????
+ rReq.Done();
+
+ if (!bHadTrack) // newly turned on -> show as well
+ {
+ ScChangeViewSettings* pOldSet = m_pDocument->GetChangeViewSettings();
+ if ( !pOldSet || !pOldSet->ShowChanges() )
+ {
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges(true);
+ m_pDocument->SetChangeViewSettings(aChangeViewSet);
+ }
+ }
+#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
+ else if ( nSlot == SID_DOCUMENT_MERGE && IsDocShared() && pChangeTrack )
+ {
+ sal_uLong nEnd = pChangeTrack->GetActionMax();
+ if ( nEnd >= nStart )
+ {
+ // only show changes from merged document
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges( true );
+ aChangeViewSet.SetShowAccepted( true );
+ aChangeViewSet.SetHasActionRange();
+ aChangeViewSet.SetTheActionRange( nStart, nEnd );
+ m_pDocument->SetChangeViewSettings( aChangeViewSet );
+
+ // update view
+ PostPaintExtras();
+ PostPaintGridAll();
+ }
+ }
+#endif
+ }
+ pOtherDocSh->DoClose(); // delete happens with the Ref
+ }
+ break;
+
+ case SID_DELETE_SCENARIO:
+ if (pReqArgs)
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
+ {
+ if (const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>(pItem))
+ {
+ const OUString& aName = pStringItem->GetValue();
+ SCTAB nTab;
+ if (m_pDocument->GetTable( aName, nTab ))
+ {
+ // move DeleteTable from viewfunc to docfunc!
+
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ //! omit SetTabNo in DeleteTable?
+ SCTAB nDispTab = pSh->GetViewData().GetTabNo();
+ pSh->DeleteTable( nTab );
+ pSh->SetTabNo(nDispTab);
+ rReq.Done();
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_EDIT_SCENARIO:
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
+ {
+ if (const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>(pItem))
+ {
+ OUString aName = pStringItem->GetValue();
+ SCTAB nTab;
+ if (m_pDocument->GetTable( aName, nTab ))
+ {
+ if (m_pDocument->IsScenario(nTab))
+ {
+ OUString aComment;
+ Color aColor;
+ ScScenarioFlags nFlags;
+ m_pDocument->GetScenarioData( nTab, aComment, aColor, nFlags );
+
+ // Determine if the Sheet that the Scenario was created on
+ // is protected. But first we need to find that Sheet.
+ // Rewind back to the actual sheet.
+ SCTAB nActualTab = nTab;
+ do
+ {
+ nActualTab--;
+ }
+ while(m_pDocument->IsScenario(nActualTab));
+ bool bSheetProtected = m_pDocument->IsTabProtected(nActualTab);
+
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+
+ ScopedVclPtr<AbstractScNewScenarioDlg> pNewDlg(pFact->CreateScNewScenarioDlg(GetActiveDialogParent(), aName, true, bSheetProtected));
+ pNewDlg->SetScenarioData( aName, aComment, aColor, nFlags );
+ if ( pNewDlg->Execute() == RET_OK )
+ {
+ pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
+ ModifyScenario( nTab, aName, aComment, aColor, nFlags );
+ rReq.Done();
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_YEAR2000 :
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
+ {
+ if (const SfxUInt16Item* pInt16Item = dynamic_cast<const SfxUInt16Item*>(pItem))
+ {
+ sal_uInt16 nY2k = pInt16Item->GetValue();
+ // set always to DocOptions, so that it is also saved for S050
+ // (and all inquiries run up until now on it as well).
+ // SetDocOptions propagates that to the NumberFormatter
+ ScDocOptions aDocOpt( m_pDocument->GetDocOptions() );
+ aDocOpt.SetYear2000( nY2k );
+ m_pDocument->SetDocOptions( aDocOpt );
+ // the FormShell shall notice it as well
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ FmFormShell* pFSh = pSh->GetFormShell();
+ if ( pFSh )
+ pFSh->SetY2KState( nY2k );
+ }
+ }
+ }
+ }
+ break;
+
+#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
+ case SID_SHARE_DOC:
+ {
+ ScViewData* pViewData = GetViewData();
+ if ( !pViewData )
+ {
+ rReq.Ignore();
+ break;
+ }
+
+ weld::Window* pWin = GetActiveDialogParent();
+ ScShareDocumentDlg aDlg(pWin, pViewData);
+ if (aDlg.run() == RET_OK)
+ {
+ bool bSetShared = aDlg.IsShareDocumentChecked();
+ if ( bSetShared != IsDocShared() )
+ {
+ if ( bSetShared )
+ {
+ bool bContinue = true;
+ if ( HasName() )
+ {
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin,
+ VclMessageType::Question, VclButtonsType::YesNo,
+ ScResId(STR_DOC_WILLBESAVED)));
+ xQueryBox->set_default_response(RET_YES);
+ if (xQueryBox->run() == RET_NO)
+ {
+ bContinue = false;
+ }
+ }
+ if ( bContinue )
+ {
+ EnableSharedSettings( true );
+
+ SC_MOD()->SetInSharedDocSaving( true );
+ if ( !SwitchToShared( true, true ) )
+ {
+ // TODO/LATER: what should be done in case the switch has failed?
+ // for example in case the user has cancelled the saveAs operation
+ }
+
+ SC_MOD()->SetInSharedDocSaving( false );
+
+ InvalidateName();
+ GetUndoManager()->Clear();
+
+ ScTabView* pTabView = pViewData->GetView();
+ if ( pTabView )
+ {
+ pTabView->UpdateLayerLocks();
+ }
+ }
+ }
+ else
+ {
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ // load shared file
+ xModel.set( LoadSharedDocument(), uno::UNO_SET_THROW );
+ uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
+
+ // check if shared flag is set in shared file
+ bool bShared = false;
+ ScModelObj* pDocObj = comphelper::getFromUnoTunnel<ScModelObj>( xModel );
+ if ( pDocObj )
+ {
+ ScDocShell* pDocShell = dynamic_cast< ScDocShell* >( pDocObj->GetEmbeddedObject() );
+ if ( pDocShell )
+ {
+ bShared = pDocShell->HasSharedXMLFlagSet();
+ }
+ }
+
+ // #i87870# check if shared status was disabled and enabled again
+ bool bOwnEntry = false;
+ try
+ {
+ ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
+ bOwnEntry = aControlFile.HasOwnEntry();
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ if ( bShared && bOwnEntry )
+ {
+ uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
+ if ( xStorable->isReadonly() )
+ {
+ xCloseable->close( true );
+
+ OUString aUserName( ScResId( STR_UNKNOWN_USER ) );
+ try
+ {
+ ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
+ LockFileEntry aData = aLockFile.GetLockData();
+ if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() )
+ {
+ aUserName = aData[LockFileComponent::OOOUSERNAME];
+ }
+ else if ( !aData[LockFileComponent::SYSUSERNAME].isEmpty() )
+ {
+ aUserName = aData[LockFileComponent::SYSUSERNAME];
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ OUString aMessage( ScResId( STR_FILE_LOCKED_TRY_LATER ) );
+ aMessage = aMessage.replaceFirst( "%1", aUserName );
+
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
+ VclMessageType::Warning, VclButtonsType::Ok,
+ aMessage));
+ xWarn->run();
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
+ VclMessageType::Warning, VclButtonsType::YesNo,
+ ScResId(STR_DOC_DISABLESHARED)));
+ xWarn->set_default_response(RET_YES);
+
+ if (xWarn->run() == RET_YES)
+ {
+ xCloseable->close( true );
+
+ if ( !SwitchToShared( false, true ) )
+ {
+ // TODO/LATER: what should be done in case the switch has failed?
+ // for example in case the user has cancelled the saveAs operation
+ }
+
+ EnableSharedSettings( false );
+
+ // Do *not* use dispatch mechanism in this place - we don't want others (extensions etc.) to intercept this.
+ uno::Reference<frame::XStorable> xStorable2(
+ GetModel(), uno::UNO_QUERY_THROW);
+ xStorable2->store();
+
+ ScTabView* pTabView = pViewData->GetView();
+ if ( pTabView )
+ {
+ pTabView->UpdateLayerLocks();
+ }
+ }
+ else
+ {
+ xCloseable->close( true );
+ }
+ }
+ }
+ else
+ {
+ xCloseable->close( true );
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
+ VclMessageType::Warning, VclButtonsType::Ok,
+ ScResId(STR_DOC_NOLONGERSHARED)));
+ xWarn->run();
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sc", "SID_SHARE_DOC" );
+ SC_MOD()->SetInSharedDocSaving( false );
+
+ try
+ {
+ uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
+ xClose->close( true );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+ }
+ rReq.Done();
+ }
+ break;
+#endif
+ case SID_OPEN_CALC:
+ {
+ ScViewData* pViewData = GetViewData();
+ if (pViewData)
+ {
+ SfxStringItem aApp(SID_DOC_SERVICE, "com.sun.star.sheet.SpreadsheetDocument");
+ SfxStringItem aTarget(SID_TARGETNAME, "_blank");
+ pViewData->GetDispatcher().ExecuteList(
+ SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON,
+ { &aApp, &aTarget });
+ }
+ }
+ break;
+ case SID_NOTEBOOKBAR:
+ {
+ const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR );
+
+ if ( pBindings && sfx2::SfxNotebookBar::IsActive() )
+ sfx2::SfxNotebookBar::ExecMethod(*pBindings, pFile ? pFile->GetValue() : "");
+ else if ( pBindings )
+ sfx2::SfxNotebookBar::CloseMethod(*pBindings);
+ }
+ break;
+ case SID_LANGUAGE_STATUS:
+ {
+ OUString aLangText;
+ const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
+ if ( pItem )
+ aLangText = pItem->GetValue();
+
+ if ( !aLangText.isEmpty() )
+ {
+ LanguageType eLang, eLatin, eCjk, eCtl;
+ static const OUStringLiteral aSelectionLangPrefix(u"Current_");
+ static const OUStringLiteral aParagraphLangPrefix(u"Paragraph_");
+ static const OUStringLiteral aDocLangPrefix(u"Default_");
+
+ bool bSelection = false;
+ bool bParagraph = false;
+
+ ScDocument& rDoc = GetDocument();
+ rDoc.GetLanguage( eLatin, eCjk, eCtl );
+
+ sal_Int32 nPos = 0;
+ if ( aLangText == "*" )
+ {
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ScTabViewShell* pSh = GetBestViewShell();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog(pSh ? pSh->GetDialogParent() : nullptr, SID_LANGUAGE_OPTIONS));
+ pDlg->Execute();
+
+ rDoc.GetLanguage( eLang, eCjk, eCtl );
+ }
+ else if ( (nPos = aLangText.indexOf(aDocLangPrefix)) != -1 )
+ {
+ aLangText = aLangText.replaceAt(nPos, aDocLangPrefix.getLength(), u"");
+
+ if ( aLangText == "LANGUAGE_NONE" )
+ {
+ eLang = LANGUAGE_NONE;
+ rDoc.SetLanguage( eLang, eCjk, eCtl );
+ }
+ else if ( aLangText == "RESET_LANGUAGES" )
+ {
+ bool bAutoSpell;
+
+ ScModule::GetSpellSettings(eLang, eCjk, eCtl, bAutoSpell);
+ rDoc.SetLanguage(eLang, eCjk, eCtl);
+ }
+ else
+ {
+ eLang = SvtLanguageTable::GetLanguageType( aLangText );
+ if ( eLang != LANGUAGE_DONTKNOW && SvtLanguageOptions::GetScriptTypeOfLanguage(eLang) == SvtScriptType::LATIN )
+ {
+ rDoc.SetLanguage( eLang, eCjk, eCtl );
+ }
+ else
+ {
+ eLang = eLatin;
+ }
+ }
+ }
+ else if (-1 != (nPos = aLangText.indexOf( aSelectionLangPrefix )))
+ {
+ bSelection = true;
+ aLangText = aLangText.replaceAt( nPos, aSelectionLangPrefix.getLength(), u"" );
+ }
+ else if (-1 != (nPos = aLangText.indexOf( aParagraphLangPrefix )))
+ {
+ bParagraph = true;
+ aLangText = aLangText.replaceAt( nPos, aParagraphLangPrefix.getLength(), u"" );
+ }
+
+ if (bSelection || bParagraph)
+ {
+ ScViewData* pViewData = GetViewData();
+ if (!pViewData)
+ return;
+
+ EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
+ if (!pEditView)
+ return;
+
+ const LanguageType nLangToUse = SvtLanguageTable::GetLanguageType( aLangText );
+ SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse );
+
+ SfxItemSet aAttrs = pEditView->GetEditEngine()->GetEmptyItemSet();
+ if (nScriptType == SvtScriptType::LATIN)
+ aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) );
+ if (nScriptType == SvtScriptType::COMPLEX)
+ aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CTL ) );
+ if (nScriptType == SvtScriptType::ASIAN)
+ aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CJK ) );
+ ESelection aOldSel;
+ if (bParagraph)
+ {
+ ESelection aSel = pEditView->GetSelection();
+ aOldSel = aSel;
+ aSel.nStartPos = 0;
+ aSel.nEndPos = EE_TEXTPOS_ALL;
+ pEditView->SetSelection( aSel );
+ }
+
+ pEditView->SetAttribs( aAttrs );
+ if (bParagraph)
+ pEditView->SetSelection( aOldSel );
+ }
+ else if ( eLang != eLatin )
+ {
+ if ( ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell() )
+ {
+ ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewSh);
+ if ( pInputHandler )
+ pInputHandler->UpdateSpellSettings();
+
+ pViewSh->UpdateDrawTextOutliner();
+ }
+
+ SetDocumentModified();
+ Broadcast(SfxHint(SfxHintId::LanguageChanged));
+ PostPaintGridAll();
+ }
+ }
+ }
+ break;
+ case SID_SPELLCHECK_IGNORE_ALL:
+ {
+ ScViewData* pViewData = GetViewData();
+ if (!pViewData)
+ return;
+
+ EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
+ if (!pEditView)
+ return;
+
+ OUString sIgnoreText;
+ const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pItem2)
+ sIgnoreText = pItem2->GetValue();
+
+ if(sIgnoreText == "Spelling")
+ {
+ ESelection aOldSel = pEditView->GetSelection();
+ pEditView->SpellIgnoreWord();
+ pEditView->SetSelection( aOldSel );
+ }
+ }
+ break;
+ case SID_SPELLCHECK_APPLY_SUGGESTION:
+ {
+ ScViewData* pViewData = GetViewData();
+ if (!pViewData)
+ return;
+
+ EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
+ if (!pEditView)
+ return;
+
+ OUString sApplyText;
+ const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
+ if (pItem2)
+ sApplyText = pItem2->GetValue();
+
+ static const OUStringLiteral sSpellingRule(u"Spelling_");
+ sal_Int32 nPos = 0;
+ if(-1 != (nPos = sApplyText.indexOf( sSpellingRule )))
+ {
+ sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u"");
+ pEditView->InsertText( sApplyText );
+ }
+ }
+ break;
+ case SID_REFRESH_VIEW:
+ {
+ PostPaintGridAll();
+ }
+ break;
+ default:
+ {
+ // small (?) hack -> forwarding of the slots to TabViewShell
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ pSh->Execute( rReq );
+#if HAVE_FEATURE_SCRIPTING
+ else
+ SbxBase::SetError( ERRCODE_BASIC_NO_ACTIVE_OBJECT );
+#endif
+ }
+ }
+}
+
+void UpdateAcceptChangesDialog()
+{
+ // update "accept changes" dialog
+ //! notify all views
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && pViewFrm->HasChildWindow( FID_CHG_ACCEPT ) )
+ {
+ SfxChildWindow* pChild = pViewFrm->GetChildWindow( FID_CHG_ACCEPT );
+ if ( pChild )
+ static_cast<ScAcceptChgDlgWrapper*>(pChild)->ReInitDlg();
+ }
+}
+
+bool ScDocShell::ExecuteChangeProtectionDialog( bool bJustQueryIfProtected )
+{
+ bool bDone = false;
+ ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
+ if ( pChangeTrack )
+ {
+ bool bProtected = pChangeTrack->IsProtected();
+ if ( bJustQueryIfProtected && !bProtected )
+ return true;
+
+ OUString aTitle( ScResId( bProtected ? SCSTR_CHG_UNPROTECT : SCSTR_CHG_PROTECT ) );
+ OUString aText( ScResId( SCSTR_PASSWORD ) );
+ OUString aPassword;
+
+ weld::Window* pWin = ScDocShell::GetActiveDialogParent();
+ SfxPasswordDialog aDlg(pWin, &aText);
+ aDlg.set_title(aTitle);
+ aDlg.SetMinLen(1);
+ aDlg.set_help_id(GetStaticInterface()->GetSlot(SID_CHG_PROTECT)->GetCommand());
+ aDlg.SetEditHelpId( HID_CHG_PROTECT );
+ if ( !bProtected )
+ aDlg.ShowExtras(SfxShowExtras::CONFIRM);
+ if (aDlg.run() == RET_OK)
+ aPassword = aDlg.GetPassword();
+
+ if (!aPassword.isEmpty())
+ {
+ if ( bProtected )
+ {
+ if ( SvPasswordHelper::CompareHashPassword(pChangeTrack->GetProtection(), aPassword) )
+ {
+ if ( bJustQueryIfProtected )
+ bDone = true;
+ else
+ pChangeTrack->SetProtection( {} );
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin,
+ VclMessageType::Info, VclButtonsType::Ok,
+ ScResId(SCSTR_WRONGPASSWORD)));
+ xInfoBox->run();
+ }
+ }
+ else
+ {
+ css::uno::Sequence< sal_Int8 > aPass;
+ SvPasswordHelper::GetHashPassword( aPass, aPassword );
+ pChangeTrack->SetProtection( aPass );
+ }
+ if ( bProtected != pChangeTrack->IsProtected() )
+ {
+ UpdateAcceptChangesDialog();
+ bDone = true;
+ }
+ }
+ }
+ else if ( bJustQueryIfProtected )
+ bDone = true;
+ return bDone;
+}
+
+void ScDocShell::DoRecalc( bool bApi )
+{
+ if (m_pDocument->IsInDocShellRecalc())
+ {
+ SAL_WARN("sc","ScDocShell::DoRecalc tries re-entering while in Recalc; probably Forms->BASIC->Dispatcher.");
+ return;
+ }
+ ScDocShellRecalcGuard aGuard(*m_pDocument);
+ bool bDone = false;
+ ScTabViewShell* pSh = GetBestViewShell();
+ ScInputHandler* pHdl = ( pSh ? SC_MOD()->GetInputHdl( pSh ) : nullptr );
+ if ( pSh )
+ {
+ if ( pHdl && pHdl->IsInputMode() && pHdl->IsFormulaMode() && !bApi )
+ {
+ pHdl->FormulaPreview(); // partial result as QuickHelp
+ bDone = true;
+ }
+ else
+ {
+ ScTabView::UpdateInputLine(); // InputEnterHandler
+ pSh->UpdateInputHandler();
+ }
+ }
+ if (bDone) // otherwise re-calculate document
+ return;
+
+ weld::WaitObject aWaitObj( GetActiveDialogParent() );
+ if ( pHdl )
+ {
+ // tdf97897 set current cell to Dirty to force recalculation of cell
+ ScFormulaCell* pFC = m_pDocument->GetFormulaCell( pHdl->GetCursorPos());
+ if (pFC)
+ pFC->SetDirty();
+ }
+ m_pDocument->CalcFormulaTree();
+ if ( pSh )
+ pSh->UpdateCharts(true);
+
+ m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) );
+
+ // If there are charts, then paint everything, so that PostDataChanged
+ // and the charts do not come one after the other and parts are painted twice.
+
+ ScChartListenerCollection* pCharts = m_pDocument->GetChartListenerCollection();
+ if ( pCharts && pCharts->hasListeners() )
+ PostPaintGridAll();
+ else
+ PostDataChanged();
+}
+
+void ScDocShell::DoHardRecalc()
+{
+ if (m_pDocument->IsInDocShellRecalc())
+ {
+ SAL_WARN("sc","ScDocShell::DoHardRecalc tries re-entering while in Recalc; probably Forms->BASIC->Dispatcher.");
+ return;
+ }
+ auto start = std::chrono::steady_clock::now();
+ ScDocShellRecalcGuard aGuard(*m_pDocument);
+ weld::WaitObject aWaitObj( GetActiveDialogParent() );
+ ScTabViewShell* pSh = GetBestViewShell();
+ if ( pSh )
+ {
+ ScTabView::UpdateInputLine(); // InputEnterHandler
+ pSh->UpdateInputHandler();
+ }
+ m_pDocument->CalcAll();
+ GetDocFunc().DetectiveRefresh(); // creates own Undo
+ if ( pSh )
+ pSh->UpdateCharts(true);
+
+ // set notification flags for "calculate" event (used in SfxHintId::DataChanged broadcast)
+ // (might check for the presence of any formulas on each sheet)
+ SCTAB nTabCount = m_pDocument->GetTableCount();
+ if (m_pDocument->HasAnySheetEventScript( ScSheetEventId::CALCULATE, true )) // search also for VBA handler
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ m_pDocument->SetCalcNotification(nTab);
+
+ // CalcAll doesn't broadcast value changes, so SfxHintId::ScCalcAll is broadcasted globally
+ // in addition to SfxHintId::DataChanged.
+ m_pDocument->BroadcastUno( SfxHint( SfxHintId::ScCalcAll ) );
+ m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) );
+
+ // use hard recalc also to disable stream-copying of all sheets
+ // (somewhat consistent with charts)
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ m_pDocument->SetStreamValid(nTab, false);
+
+ PostPaintGridAll();
+ auto end = std::chrono::steady_clock::now();
+ SAL_INFO("sc.timing", "ScDocShell::DoHardRecalc(): took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms");
+}
+
+void ScDocShell::DoAutoStyle( const ScRange& rRange, const OUString& rStyle )
+{
+ ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
+ ScStyleSheet* pStyleSheet = pStylePool->FindAutoStyle(rStyle);
+ if (!pStyleSheet)
+ return;
+
+ OSL_ENSURE(rRange.aStart.Tab() == rRange.aEnd.Tab(),
+ "DoAutoStyle with several tables");
+ SCTAB nTab = rRange.aStart.Tab();
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCROW nStartRow = rRange.aStart.Row();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ SCROW nEndRow = rRange.aEnd.Row();
+ m_pDocument->ApplyStyleAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, *pStyleSheet );
+ m_pDocument->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
+ PostPaint( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, PaintPartFlags::Grid );
+}
+
+void ScDocShell::NotifyStyle( const SfxStyleSheetHint& rHint )
+{
+ SfxHintId nId = rHint.GetId();
+ const SfxStyleSheetBase* pStyle = rHint.GetStyleSheet();
+ if (!pStyle)
+ return;
+
+ if ( pStyle->GetFamily() == SfxStyleFamily::Page )
+ {
+ if ( nId == SfxHintId::StyleSheetModified )
+ {
+ ScDocShellModificator aModificator( *this );
+
+ const OUString& aNewName = pStyle->GetName();
+ OUString aOldName = aNewName;
+ const SfxStyleSheetModifiedHint* pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint); // name changed?
+ if (pExtendedHint)
+ aOldName = pExtendedHint->GetOldName();
+
+ if ( aNewName != aOldName )
+ m_pDocument->RenamePageStyleInUse( aOldName, aNewName );
+
+ SCTAB nTabCount = m_pDocument->GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ if (m_pDocument->GetPageStyle(nTab) == aNewName) // already adjusted to new
+ {
+ m_pDocument->PageStyleModified( nTab, aNewName );
+ ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ }
+
+ aModificator.SetDocumentModified();
+
+ if (pExtendedHint)
+ {
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_STATUS_PAGESTYLE );
+ pBindings->Invalidate( SID_STYLE_FAMILY4 );
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+ }
+ }
+ }
+ else if ( pStyle->GetFamily() == SfxStyleFamily::Para )
+ {
+ if ( nId == SfxHintId::StyleSheetModified)
+ {
+ const OUString& aNewName = pStyle->GetName();
+ OUString aOldName = aNewName;
+ const SfxStyleSheetModifiedHint* pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint);
+ if (pExtendedHint)
+ aOldName = pExtendedHint->GetOldName();
+ if ( aNewName != aOldName )
+ {
+ for(SCTAB i = 0; i < m_pDocument->GetTableCount(); ++i)
+ {
+ ScConditionalFormatList* pList = m_pDocument->GetCondFormList(i);
+ if (pList)
+ pList->RenameCellStyle( aOldName,aNewName );
+ }
+ }
+ }
+ }
+
+ // everything else goes via slots...
+}
+
+// like in printfun.cxx
+#define ZOOM_MIN 10
+
+void ScDocShell::SetPrintZoom( SCTAB nTab, sal_uInt16 nScale, sal_uInt16 nPages )
+{
+ OUString aStyleName = m_pDocument->GetPageStyle( nTab );
+ ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
+ OSL_ENSURE( pStyleSheet, "PageStyle not found" );
+ if ( !pStyleSheet )
+ return;
+
+ ScDocShellModificator aModificator( *this );
+
+ SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ const bool bUndo(m_pDocument->IsUndoEnabled());
+ if (bUndo)
+ {
+ sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
+ sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
+ GetUndoManager()->AddUndoAction( std::make_unique<ScUndoPrintZoom>(
+ this, nTab, nOldScale, nOldPages, nScale, nPages ) );
+ }
+
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
+
+ ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
+ aPrintFunc.UpdatePages();
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+}
+
+bool ScDocShell::AdjustPrintZoom( const ScRange& rRange )
+{
+ bool bChange = false;
+ SCTAB nTab = rRange.aStart.Tab();
+
+ OUString aStyleName = m_pDocument->GetPageStyle( nTab );
+ ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
+ OSL_ENSURE( pStyleSheet, "PageStyle not found" );
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ bool bHeaders = rSet.Get(ATTR_PAGE_HEADERS).GetValue();
+ sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
+ sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
+ std::optional<ScRange> oRepeatCol = m_pDocument->GetRepeatColRange( nTab );
+ std::optional<ScRange> oRepeatRow = m_pDocument->GetRepeatRowRange( nTab );
+
+ // calculate needed scaling for selection
+
+ sal_uInt16 nNewScale = nOldScale;
+
+ tools::Long nBlkTwipsX = 0;
+ if (bHeaders)
+ nBlkTwipsX += PRINT_HEADER_WIDTH;
+ SCCOL nStartCol = rRange.aStart.Col();
+ SCCOL nEndCol = rRange.aEnd.Col();
+ if ( oRepeatCol && nStartCol >= oRepeatCol->aStart.Col() )
+ {
+ for (SCCOL i=oRepeatCol->aStart.Col(); i<=oRepeatCol->aEnd.Col(); i++ )
+ nBlkTwipsX += m_pDocument->GetColWidth( i, nTab );
+ if ( nStartCol <= oRepeatCol->aEnd.Col() )
+ nStartCol = oRepeatCol->aEnd.Col() + 1;
+ }
+ // legacy compilers' own scope for i
+ {
+ for ( SCCOL i=nStartCol; i<=nEndCol; i++ )
+ nBlkTwipsX += m_pDocument->GetColWidth( i, nTab );
+ }
+
+ tools::Long nBlkTwipsY = 0;
+ if (bHeaders)
+ nBlkTwipsY += PRINT_HEADER_HEIGHT;
+ SCROW nStartRow = rRange.aStart.Row();
+ SCROW nEndRow = rRange.aEnd.Row();
+ if ( oRepeatRow && nStartRow >= oRepeatRow->aStart.Row() )
+ {
+ nBlkTwipsY += m_pDocument->GetRowHeight( oRepeatRow->aStart.Row(),
+ oRepeatRow->aEnd.Row(), nTab );
+ if ( nStartRow <= oRepeatRow->aEnd.Row() )
+ nStartRow = oRepeatRow->aEnd.Row() + 1;
+ }
+ nBlkTwipsY += m_pDocument->GetRowHeight( nStartRow, nEndRow, nTab );
+
+ Size aPhysPage;
+ tools::Long nHdr, nFtr;
+ ScPrintFunc aOldPrFunc( this, GetPrinter(), nTab );
+ aOldPrFunc.GetScaleData( aPhysPage, nHdr, nFtr );
+ nBlkTwipsY += nHdr + nFtr;
+
+ if ( nBlkTwipsX == 0 ) // hidden columns/rows may lead to 0
+ nBlkTwipsX = 1;
+ if ( nBlkTwipsY == 0 )
+ nBlkTwipsY = 1;
+
+ tools::Long nNeeded = std::min( aPhysPage.Width() * 100 / nBlkTwipsX,
+ aPhysPage.Height() * 100 / nBlkTwipsY );
+ if ( nNeeded < ZOOM_MIN )
+ nNeeded = ZOOM_MIN; // boundary
+ if ( nNeeded < static_cast<tools::Long>(nNewScale) )
+ nNewScale = static_cast<sal_uInt16>(nNeeded);
+
+ bChange = ( nNewScale != nOldScale || nOldPages != 0 );
+ if ( bChange )
+ SetPrintZoom( nTab, nNewScale, 0 );
+ }
+ return bChange;
+}
+
+void ScDocShell::PageStyleModified( std::u16string_view rStyleName, bool bApi )
+{
+ ScDocShellModificator aModificator( *this );
+
+ SCTAB nTabCount = m_pDocument->GetTableCount();
+ SCTAB nUseTab = MAXTAB+1;
+ for (SCTAB nTab=0; nTab<nTabCount && nUseTab>MAXTAB; nTab++)
+ if ( m_pDocument->GetPageStyle(nTab) == rStyleName &&
+ ( !bApi || m_pDocument->GetPageSize(nTab).Width() ) )
+ nUseTab = nTab;
+ // at bApi only if breaks already shown
+
+ if (ValidTab(nUseTab)) // not used -> nothing to do
+ {
+ bool bWarn = false;
+
+ ScPrintFunc aPrintFunc( this, GetPrinter(), nUseTab ); //! cope without CountPages
+ if (!aPrintFunc.UpdatePages()) // sets breaks on all tabs
+ bWarn = true;
+
+ if (bWarn && !bApi)
+ {
+ weld::Window* pWin = GetActiveDialogParent();
+ weld::WaitObject aWaitOff(pWin);
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin,
+ VclMessageType::Info, VclButtonsType::Ok,
+ ScResId(STR_PRINT_INVALID_AREA)));
+ xInfoBox->run();
+ }
+ }
+
+ aModificator.SetDocumentModified();
+
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+}
+
+void ScDocShell::ExecutePageStyle( const SfxViewShell& rCaller,
+ SfxRequest& rReq,
+ SCTAB nCurTab )
+{
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+
+ switch ( rReq.GetSlot() )
+ {
+ case SID_STATUS_PAGESTYLE: // click on StatusBar control
+ case SID_FORMATPAGE:
+ {
+ if ( pReqArgs == nullptr )
+ {
+ OUString aOldName = m_pDocument->GetPageStyle( nCurTab );
+ ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet
+ = pStylePool->Find( aOldName, SfxStyleFamily::Page );
+
+ OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ {
+ ScStyleSaveData aOldData;
+ const bool bUndo(m_pDocument->IsUndoEnabled());
+ if (bUndo)
+ aOldData.InitFromStyle( pStyleSheet );
+
+ SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
+ rStyleSet.MergeRange( XATTR_FILL_FIRST, XATTR_FILL_LAST );
+
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScStyleDlg(GetActiveDialogParent(), *pStyleSheet, true));
+
+ auto pRequest = std::make_shared<SfxRequest>(rReq);
+ rReq.Ignore(); // the 'old' request is not relevant any more
+ pDlg->StartExecuteAsync([this, pDlg, pRequest, pStyleSheet, aOldData, aOldName, &rStyleSet, nCurTab, &rCaller, bUndo](sal_Int32 nResult){
+ if ( nResult == RET_OK )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+
+ weld::WaitObject aWait( GetActiveDialogParent() );
+
+ OUString aNewName = pStyleSheet->GetName();
+ if ( aNewName != aOldName &&
+ m_pDocument->RenamePageStyleInUse( aOldName, aNewName ) )
+ {
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ {
+ pBindings->Invalidate( SID_STATUS_PAGESTYLE );
+ pBindings->Invalidate( FID_RESET_PRINTZOOM );
+ }
+ }
+
+ if ( pOutSet )
+ m_pDocument->ModifyStyleSheet( *pStyleSheet, *pOutSet );
+
+ // memorizing for GetState():
+ GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn );
+ rCaller.GetViewFrame()->GetBindings().Invalidate( SID_HFEDIT );
+
+ ScStyleSaveData aNewData;
+ aNewData.InitFromStyle( pStyleSheet );
+ if (bUndo)
+ {
+ GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoModifyStyle>( this, SfxStyleFamily::Page,
+ aOldData, aNewData ) );
+ }
+
+ PageStyleModified( aNewName, false );
+ pRequest->Done();
+ }
+ pDlg->disposeOnce();
+ });
+ }
+ }
+ }
+ break;
+
+ case SID_HFEDIT:
+ {
+ if ( pReqArgs == nullptr )
+ {
+ OUString aStr( m_pDocument->GetPageStyle( nCurTab ) );
+
+ ScStyleSheetPool* pStylePool
+ = m_pDocument->GetStyleSheetPool();
+
+ SfxStyleSheetBase* pStyleSheet
+ = pStylePool->Find( aStr, SfxStyleFamily::Page );
+
+ OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
+
+ SvxPageUsage eUsage = rStyleSet.Get( ATTR_PAGE ).GetPageUsage();
+ bool bShareHeader = rStyleSet
+ .Get(ATTR_PAGE_HEADERSET)
+ .GetItemSet()
+ .Get(ATTR_PAGE_SHARED)
+ .GetValue();
+ bool bShareFooter = rStyleSet
+ .Get(ATTR_PAGE_FOOTERSET)
+ .GetItemSet()
+ .Get(ATTR_PAGE_SHARED)
+ .GetValue();
+ sal_uInt16 nResId = 0;
+
+ switch ( eUsage )
+ {
+ case SvxPageUsage::Left:
+ case SvxPageUsage::Right:
+ {
+ if ( m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT;
+ else if ( SvxPageUsage::Right == eUsage )
+ {
+ if ( !m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
+ else if ( m_bHeaderOn && !m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
+ }
+ else
+ {
+ // #69193a# respect "shared" setting
+ if ( !m_bHeaderOn && m_bFooterOn )
+ nResId = bShareFooter ?
+ RID_SCDLG_HFEDIT_RIGHTFOOTER :
+ RID_SCDLG_HFEDIT_LEFTFOOTER;
+ else if ( m_bHeaderOn && !m_bFooterOn )
+ nResId = bShareHeader ?
+ RID_SCDLG_HFEDIT_RIGHTHEADER :
+ RID_SCDLG_HFEDIT_LEFTHEADER;
+ }
+ }
+ break;
+
+ case SvxPageUsage::Mirror:
+ case SvxPageUsage::All:
+ default:
+ {
+ if ( !bShareHeader && !bShareFooter )
+ {
+ if ( m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_ALL;
+ else if ( !m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_FOOTER;
+ else if ( m_bHeaderOn && !m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_HEADER;
+ }
+ else if ( bShareHeader && bShareFooter )
+ {
+ if ( m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT;
+ else
+ {
+ if ( !m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
+ else if ( m_bHeaderOn && !m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
+ }
+ }
+ else if ( !bShareHeader && bShareFooter )
+ {
+ if ( m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_SFTR;
+ else if ( !m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
+ else if ( m_bHeaderOn && !m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_HEADER;
+ }
+ else if ( bShareHeader && !bShareFooter )
+ {
+ if ( m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_SHDR;
+ else if ( !m_bHeaderOn && m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_FOOTER;
+ else if ( m_bHeaderOn && !m_bFooterOn )
+ nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
+ }
+ }
+ }
+
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScHFEditDlg(
+ GetActiveDialogParent(),
+ rStyleSet,
+ aStr,
+ nResId));
+ auto xRequest = std::make_shared<SfxRequest>(rReq);
+ rReq.Ignore(); // the 'old' request is not relevant any more
+ pDlg->StartExecuteAsync([this, pDlg, pStyleSheet, xRequest](sal_Int32 nResult){
+ if ( nResult == RET_OK )
+ {
+ const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
+
+ if ( pOutSet )
+ m_pDocument->ModifyStyleSheet( *pStyleSheet, *pOutSet );
+
+ SetDocumentModified();
+ xRequest->Done();
+ }
+ pDlg->disposeOnce();
+ });
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void ScDocShell::GetStatePageStyle( SfxItemSet& rSet,
+ SCTAB nCurTab )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ switch (nWhich)
+ {
+ case SID_STATUS_PAGESTYLE:
+ rSet.Put( SfxStringItem( nWhich, m_pDocument->GetPageStyle( nCurTab ) ) );
+ break;
+
+ case SID_HFEDIT:
+ {
+ OUString aStr = m_pDocument->GetPageStyle( nCurTab );
+ ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStr, SfxStyleFamily::Page );
+
+ OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
+ GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn );
+
+ if ( !m_bHeaderOn && !m_bFooterOn )
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void ScDocShell::GetState( SfxItemSet &rSet )
+{
+ bool bTabView = GetBestViewShell() != nullptr;
+
+ SfxWhichIter aIter(rSet);
+ for (sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich())
+ {
+ if (!bTabView)
+ {
+ rSet.DisableItem(nWhich);
+ continue;
+ }
+
+ switch (nWhich)
+ {
+ case FID_AUTO_CALC:
+ if ( m_pDocument->GetHardRecalcState() != ScDocument::HardRecalcState::OFF )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem( nWhich, m_pDocument->GetAutoCalc() ) );
+ break;
+
+ case FID_CHG_RECORD:
+ if ( IsDocShared() )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxBoolItem( nWhich,
+ m_pDocument->GetChangeTrack() != nullptr ) );
+ break;
+
+ case SID_CHG_PROTECT:
+ {
+ ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
+ if ( pChangeTrack && !IsDocShared() )
+ rSet.Put( SfxBoolItem( nWhich,
+ pChangeTrack->IsProtected() ) );
+ else
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_DOCUMENT_COMPARE:
+ {
+ if ( IsDocShared() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ // When a formula is edited, FID_RECALC must be enabled in any case. Recalc for
+ // the doc was disabled once because of a bug if AutoCalc was on, but is now
+ // always enabled because of another bug.
+
+ case SID_TABLES_COUNT:
+ rSet.Put( SfxInt16Item( nWhich, m_pDocument->GetTableCount() ) );
+ break;
+
+ case SID_ATTR_YEAR2000 :
+ rSet.Put( SfxUInt16Item( nWhich,
+ m_pDocument->GetDocOptions().GetYear2000() ) );
+ break;
+
+ case SID_SHARE_DOC:
+ {
+ if ( IsReadOnly() || GetObjectShell()->isExportLocked() )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ }
+ break;
+
+ case SID_ATTR_CHAR_FONTLIST:
+ rSet.Put( SvxFontListItem( m_pImpl->pFontList.get(), nWhich ) );
+ break;
+
+ case SID_NOTEBOOKBAR:
+ {
+ if (GetViewBindings())
+ {
+ bool bVisible = sfx2::SfxNotebookBar::StateMethod(*GetViewBindings(),
+ u"modules/scalc/ui/");
+ rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) );
+ }
+ }
+ break;
+
+ case SID_LANGUAGE_STATUS:
+ {
+ LanguageType eLatin, eCjk, eCtl;
+
+ GetDocument().GetLanguage( eLatin, eCjk, eCtl );
+ OUString sLanguage = SvtLanguageTable::GetLanguageString(eLatin);
+ if (comphelper::LibreOfficeKit::isActive()) {
+ if (eLatin == LANGUAGE_NONE)
+ sLanguage += ";-";
+ else
+ sLanguage += ";" + LanguageTag(eLatin).getBcp47(false);
+ }
+ rSet.Put(SfxStringItem(nWhich, sLanguage));
+ }
+ break;
+
+ default:
+ {
+ }
+ break;
+ }
+ }
+}
+
+void ScDocShell::Draw( OutputDevice* pDev, const JobSetup & /* rSetup */, sal_uInt16 nAspect )
+{
+
+ SCTAB nVisTab = m_pDocument->GetVisibleTab();
+ if (!m_pDocument->HasTable(nVisTab))
+ return;
+
+ vcl::text::ComplexTextLayoutFlags nOldLayoutMode = pDev->GetLayoutMode();
+ pDev->SetLayoutMode( vcl::text::ComplexTextLayoutFlags::Default ); // even if it's the same, to get the metafile action
+
+ if ( nAspect == ASPECT_THUMBNAIL )
+ {
+ tools::Rectangle aBoundRect = GetVisArea( ASPECT_THUMBNAIL );
+ ScViewData aTmpData( *this, nullptr );
+ aTmpData.SetTabNo(nVisTab);
+ SnapVisArea( aBoundRect );
+ aTmpData.SetScreen( aBoundRect );
+ ScPrintFunc::DrawToDev( *m_pDocument, pDev, 1.0, aBoundRect, &aTmpData, true );
+ }
+ else
+ {
+ tools::Rectangle aOldArea = SfxObjectShell::GetVisArea();
+ tools::Rectangle aNewArea = aOldArea;
+ ScViewData aTmpData( *this, nullptr );
+ aTmpData.SetTabNo(nVisTab);
+ SnapVisArea( aNewArea );
+ if ( aNewArea != aOldArea && (m_pDocument->GetPosLeft() > 0 || m_pDocument->GetPosTop() > 0) )
+ SfxObjectShell::SetVisArea( aNewArea );
+ aTmpData.SetScreen( aNewArea );
+ ScPrintFunc::DrawToDev( *m_pDocument, pDev, 1.0, aNewArea, &aTmpData, true );
+ }
+
+ pDev->SetLayoutMode( nOldLayoutMode );
+}
+
+tools::Rectangle ScDocShell::GetVisArea( sal_uInt16 nAspect ) const
+{
+ SfxObjectCreateMode eShellMode = GetCreateMode();
+ if ( eShellMode == SfxObjectCreateMode::ORGANIZER )
+ {
+ // without contents we also don't know how large are the contents;
+ // return empty rectangle, it will then be calculated after the loading
+ return tools::Rectangle();
+ }
+
+ if( nAspect == ASPECT_THUMBNAIL )
+ {
+ SCTAB nVisTab = m_pDocument->GetVisibleTab();
+ if (!m_pDocument->HasTable(nVisTab))
+ {
+ nVisTab = 0;
+ const_cast<ScDocShell*>(this)->m_pDocument->SetVisibleTab(nVisTab);
+ }
+ Size aSize = m_pDocument->GetPageSize(nVisTab);
+ const tools::Long SC_PREVIEW_SIZE_X = 10000;
+ const tools::Long SC_PREVIEW_SIZE_Y = 12400;
+ tools::Rectangle aArea( 0,0, SC_PREVIEW_SIZE_X, SC_PREVIEW_SIZE_Y);
+ if (aSize.Width() > aSize.Height())
+ {
+ aArea.SetRight( SC_PREVIEW_SIZE_Y );
+ aArea.SetBottom( SC_PREVIEW_SIZE_X );
+ }
+
+ bool bNegativePage = m_pDocument->IsNegativePage( m_pDocument->GetVisibleTab() );
+ if ( bNegativePage )
+ ScDrawLayer::MirrorRectRTL( aArea );
+ SnapVisArea( aArea );
+ return aArea;
+ }
+ else if( nAspect == ASPECT_CONTENT && eShellMode != SfxObjectCreateMode::EMBEDDED )
+ {
+ // fetch visarea like after loading
+
+ SCTAB nVisTab = m_pDocument->GetVisibleTab();
+ if (!m_pDocument->HasTable(nVisTab))
+ {
+ nVisTab = 0;
+ const_cast<ScDocShell*>(this)->m_pDocument->SetVisibleTab(nVisTab);
+ }
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ m_pDocument->GetDataStart( nVisTab, nStartCol, nStartRow );
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ m_pDocument->GetPrintArea( nVisTab, nEndCol, nEndRow );
+ if (nStartCol>nEndCol)
+ nStartCol = nEndCol;
+ if (nStartRow>nEndRow)
+ nStartRow = nEndRow;
+ tools::Rectangle aNewArea = m_pDocument
+ ->GetMMRect( nStartCol,nStartRow, nEndCol,nEndRow, nVisTab );
+ return aNewArea;
+ }
+ else
+ return SfxObjectShell::GetVisArea( nAspect );
+}
+
+namespace {
+
+[[nodiscard]]
+tools::Long SnapHorizontal( const ScDocument& rDoc, SCTAB nTab, tools::Long nVal, SCCOL& rStartCol )
+{
+ SCCOL nCol = 0;
+ tools::Long nTwips = o3tl::convert(nVal, o3tl::Length::mm100, o3tl::Length::twip);
+ tools::Long nSnap = 0;
+ while ( nCol<rDoc.MaxCol() )
+ {
+ tools::Long nAdd = rDoc.GetColWidth(nCol, nTab);
+ if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
+ {
+ nSnap += nAdd;
+ ++nCol;
+ }
+ else
+ break;
+ }
+ nVal = o3tl::convert(nSnap, o3tl::Length::twip, o3tl::Length::mm100);
+ rStartCol = nCol;
+ return nVal;
+}
+
+[[nodiscard]]
+tools::Long SnapVertical( const ScDocument& rDoc, SCTAB nTab, tools::Long nVal, SCROW& rStartRow )
+{
+ SCROW nRow = 0;
+ tools::Long nTwips = o3tl::convert(nVal, o3tl::Length::mm100, o3tl::Length::twip);
+ tools::Long nSnap = 0;
+
+ bool bFound = false;
+ for (SCROW i = nRow; i <= rDoc.MaxRow(); ++i)
+ {
+ SCROW nLastRow;
+ if (rDoc.RowHidden(i, nTab, nullptr, &nLastRow))
+ {
+ i = nLastRow;
+ continue;
+ }
+
+ nRow = i;
+ tools::Long nAdd = rDoc.GetRowHeight(i, nTab);
+ if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
+ {
+ nSnap += nAdd;
+ ++nRow;
+ }
+ else
+ {
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound)
+ nRow = rDoc.MaxRow(); // all hidden down to the bottom
+
+ nVal = o3tl::convert(nSnap, o3tl::Length::twip, o3tl::Length::mm100);
+ rStartRow = nRow;
+ return nVal;
+}
+
+}
+
+void ScDocShell::SnapVisArea( tools::Rectangle& rRect ) const
+{
+ SCTAB nTab = m_pDocument->GetVisibleTab();
+ tools::Long nOrigTop = rRect.Top();
+ tools::Long nOrigLeft = rRect.Left();
+ bool bNegativePage = m_pDocument->IsNegativePage( nTab );
+ if ( bNegativePage )
+ ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values
+
+ SCCOL nCol = m_pDocument->GetPosLeft();
+ tools::Long nSetLeft = SnapHorizontal( *m_pDocument, nTab, rRect.Left(), nCol );
+ rRect.SetLeft( nSetLeft );
+ ++nCol; // at least one column
+ tools::Long nCorrectionLeft = (nOrigLeft == 0 && nCol > 0) ? nSetLeft : 0; // initial correction
+ rRect.SetRight( SnapHorizontal( *m_pDocument, nTab, rRect.Right() + nCorrectionLeft, nCol ));
+
+ SCROW nRow = m_pDocument->GetPosTop();
+ tools::Long nSetTop = SnapVertical( *m_pDocument, nTab, rRect.Top(), nRow );
+ rRect.SetTop( nSetTop );
+ ++nRow; // at least one row
+ tools::Long nCorrectionTop = (nOrigTop == 0 && nRow > 0) ? nSetTop : 0; // initial correction
+ rRect.SetBottom( SnapVertical( *m_pDocument, nTab, rRect.Bottom() + nCorrectionTop, nRow ));
+
+ if ( bNegativePage )
+ ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
+}
+
+void ScDocShell::GetPageOnFromPageStyleSet( const SfxItemSet* pStyleSet,
+ SCTAB nCurTab,
+ bool& rbHeader,
+ bool& rbFooter )
+{
+ if ( !pStyleSet )
+ {
+ ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = pStylePool->
+ Find( m_pDocument->GetPageStyle( nCurTab ),
+ SfxStyleFamily::Page );
+
+ OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
+
+ if ( pStyleSheet )
+ pStyleSet = &pStyleSheet->GetItemSet();
+ else
+ rbHeader = rbFooter = false;
+ }
+
+ OSL_ENSURE( pStyleSet, "PageStyle-Set not found! :-(" );
+ if (!pStyleSet)
+ return;
+
+ const SvxSetItem* pSetItem = nullptr;
+ const SfxItemSet* pSet = nullptr;
+
+ pSetItem = &pStyleSet->Get( ATTR_PAGE_HEADERSET );
+ pSet = &pSetItem->GetItemSet();
+ rbHeader = pSet->Get(ATTR_PAGE_ON).GetValue();
+
+ pSetItem = &pStyleSet->Get( ATTR_PAGE_FOOTERSET );
+ pSet = &pSetItem->GetItemSet();
+ rbFooter = pSet->Get(ATTR_PAGE_ON).GetValue();
+}
+
+#if defined(_WIN32)
+bool ScDocShell::DdeGetData( const OUString& rItem,
+ const OUString& rMimeType,
+ css::uno::Any & rValue )
+{
+ SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType );
+ if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
+ {
+ if( rItem.equalsIgnoreAsciiCase( "Format" ) )
+ {
+ OString aFmtByte(OUStringToOString(m_aDdeTextFmt,
+ osl_getThreadTextEncoding()));
+ rValue <<= css::uno::Sequence< sal_Int8 >(
+ reinterpret_cast<const sal_Int8*>(aFmtByte.getStr()),
+ aFmtByte.getLength() + 1 );
+ return true;
+ }
+ ScImportExport aObj( *m_pDocument, rItem );
+ if ( !aObj.IsRef() )
+ return false; // invalid range
+
+ if( m_aDdeTextFmt[0] == 'F' )
+ aObj.SetFormulas( true );
+ if( m_aDdeTextFmt == "SYLK" ||
+ m_aDdeTextFmt == "FSYLK" )
+ {
+ OString aData;
+ if( aObj.ExportByteString( aData, osl_getThreadTextEncoding(),
+ SotClipboardFormatId::SYLK ) )
+ {
+ rValue <<= css::uno::Sequence< sal_Int8 >(
+ reinterpret_cast<const sal_Int8*>(aData.getStr()),
+ aData.getLength() + 1 );
+ return true;
+ }
+ else
+ return false;
+ }
+ if( m_aDdeTextFmt == "CSV" ||
+ m_aDdeTextFmt == "FCSV" )
+ aObj.SetSeparator( ',' );
+ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
+ return aObj.ExportData( rMimeType, rValue );
+ }
+
+ ScImportExport aObj( *m_pDocument, rItem );
+ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
+ return aObj.IsRef() && aObj.ExportData( rMimeType, rValue );
+}
+
+bool ScDocShell::DdeSetData( const OUString& rItem,
+ const OUString& rMimeType,
+ const css::uno::Any & rValue )
+{
+ SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType );
+ if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
+ {
+ if( rItem.equalsIgnoreAsciiCase( "Format" ) )
+ {
+ if ( ScByteSequenceToString::GetString( m_aDdeTextFmt, rValue, osl_getThreadTextEncoding() ) )
+ {
+ m_aDdeTextFmt = m_aDdeTextFmt.toAsciiUpperCase();
+ return true;
+ }
+ return false;
+ }
+ ScImportExport aObj( *m_pDocument, rItem );
+ if( m_aDdeTextFmt[0] == 'F' )
+ aObj.SetFormulas( true );
+ if( m_aDdeTextFmt == "SYLK" ||
+ m_aDdeTextFmt == "FSYLK" )
+ {
+ OUString aData;
+ if ( ScByteSequenceToString::GetString( aData, rValue, osl_getThreadTextEncoding() ) )
+ {
+ return aObj.ImportString( aData, SotClipboardFormatId::SYLK );
+ }
+ return false;
+ }
+ if( m_aDdeTextFmt == "CSV" ||
+ m_aDdeTextFmt == "FCSV" )
+ aObj.SetSeparator( ',' );
+ OSL_ENSURE( false, "Implementation is missing" );
+ return false;
+ }
+ /*ScImportExport aObj( aDocument, rItem );
+ return aObj.IsRef() && ScImportExport::ImportData( rMimeType, rValue );*/
+ OSL_ENSURE( false, "Implementation is missing" );
+ return false;
+}
+#endif
+
+::sfx2::SvLinkSource* ScDocShell::DdeCreateLinkSource( const OUString& rItem )
+{
+ // only check for valid item string - range is parsed again in ScServerObject ctor
+
+ // named range?
+ OUString aPos = rItem;
+ ScRangeName* pRange = m_pDocument->GetRangeName();
+ if( pRange )
+ {
+ const ScRangeData* pData = pRange->findByUpperName(ScGlobal::getCharClass().uppercase(aPos));
+ if (pData)
+ {
+ if( pData->HasType( ScRangeData::Type::RefArea )
+ || pData->HasType( ScRangeData::Type::AbsArea )
+ || pData->HasType( ScRangeData::Type::AbsPos ) )
+ aPos = pData->GetSymbol(); // continue with the name's contents
+ }
+ }
+
+ // Address in DDE function must be always parsed as CONV_OOO so that it
+ // would always work regardless of current address conversion. We do this
+ // because the address item in a DDE entry is *not* normalized when saved
+ // into ODF.
+ ScRange aRange;
+ bool bValid = ( (aRange.Parse(aPos, *m_pDocument, formula::FormulaGrammar::CONV_OOO ) & ScRefFlags::VALID) ||
+ (aRange.aStart.Parse(aPos, *m_pDocument, formula::FormulaGrammar::CONV_OOO) & ScRefFlags::VALID) );
+
+ ScServerObject* pObj = nullptr; // NULL = error
+ if ( bValid )
+ pObj = new ScServerObject( this, rItem );
+
+ // GetLinkManager()->InsertServer() is in the ScServerObject ctor
+
+ return pObj;
+}
+
+void ScDocShell::LOKCommentNotify(LOKCommentNotificationType nType, const ScDocument* pDocument, const ScAddress& rPos, const ScPostIt* pNote)
+{
+ if ( !pDocument->IsDocVisible() || // don't want callbacks until document load
+ !comphelper::LibreOfficeKit::isActive() ||
+ comphelper::LibreOfficeKit::isTiledAnnotations() )
+ return;
+
+ boost::property_tree::ptree aAnnotation;
+ aAnnotation.put("action", (nType == LOKCommentNotificationType::Add ? "Add" :
+ (nType == LOKCommentNotificationType::Remove ? "Remove" :
+ (nType == LOKCommentNotificationType::Modify ? "Modify" : "???"))));
+
+ assert(pNote);
+ aAnnotation.put("id", pNote->GetId());
+ aAnnotation.put("tab", rPos.Tab());
+
+ if (nType != LOKCommentNotificationType::Remove)
+ {
+ aAnnotation.put("author", pNote->GetAuthor());
+ aAnnotation.put("dateTime", pNote->GetDate());
+ aAnnotation.put("text", pNote->GetText());
+
+ // Calculating the cell cursor position
+ ScViewData* pViewData = GetViewData();
+ if (pViewData && pViewData->GetActiveWin())
+ {
+ bool bInPrintTwips = comphelper::LibreOfficeKit::isCompatFlagSet(
+ comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs);
+ OString aRectString;
+ if (bInPrintTwips)
+ {
+ Point aTopLeft = pViewData->GetPrintTwipsPos(rPos.Col(), rPos.Row());
+ tools::Long nSizeX, nSizeY;
+ pViewData->GetMergeSizePrintTwips(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
+ aRectString = tools::Rectangle(aTopLeft, Size(nSizeX - 1, nSizeY - 1)).toString();
+ }
+ else
+ {
+ Point aTopLeft = pViewData->GetScrPos(rPos.Col(), rPos.Row(),
+ pViewData->GetActivePart(), true);
+ tools::Long nSizeXPix, nSizeYPix;
+ pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeXPix, nSizeYPix);
+ const double fPPTX = pViewData->GetPPTX();
+ const double fPPTY = pViewData->GetPPTY();
+ aRectString = tools::Rectangle(Point(aTopLeft.getX() / fPPTX, aTopLeft.getY() / fPPTY),
+ Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY)).toString();
+ }
+ aAnnotation.put("cellPos", aRectString);
+ }
+ }
+
+ boost::property_tree::ptree aTree;
+ aTree.add_child("comment", aAnnotation);
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ std::string aPayload = aStream.str();
+
+ ScViewData* pViewData = GetViewData();
+ SfxViewShell* pThisViewShell = ( pViewData ? pViewData->GetViewShell() : nullptr );
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while (pViewShell)
+ {
+ if (pThisViewShell == nullptr || pViewShell->GetDocId() == pThisViewShell->GetDocId())
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload.c_str());
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+}
+
+ScViewData* ScDocShell::GetViewData()
+{
+ SfxViewShell* pCur = SfxViewShell::Current();
+ ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( pCur );
+ return pViewSh ? &pViewSh->GetViewData() : nullptr;
+}
+
+SCTAB ScDocShell::GetCurTab()
+{
+ //! this must be made non-static and use a ViewShell from this document!
+
+ ScViewData* pViewData = GetViewData();
+
+ return pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
+}
+
+ScTabViewShell* ScDocShell::GetBestViewShell( bool bOnlyVisible )
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ // wrong Doc?
+ if( pViewSh && pViewSh->GetViewData().GetDocShell() != this )
+ pViewSh = nullptr;
+ if( !pViewSh )
+ {
+ // 1. find ViewShell
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this, bOnlyVisible );
+ if( pFrame )
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ pViewSh = dynamic_cast< ScTabViewShell *>( p );
+ }
+ }
+ return pViewSh;
+}
+
+SfxBindings* ScDocShell::GetViewBindings()
+{
+ // used to invalidate slots after changes to this document
+
+ SfxViewShell* pViewSh = GetBestViewShell();
+ if (pViewSh)
+ return &pViewSh->GetViewFrame()->GetBindings();
+ else
+ return nullptr;
+}
+
+ScDocShell* ScDocShell::GetShellByNum( sal_uInt16 nDocNo ) // static
+{
+ ScDocShell* pFound = nullptr;
+ SfxObjectShell* pShell = SfxObjectShell::GetFirst();
+ sal_uInt16 nShellCnt = 0;
+
+ while ( pShell && !pFound )
+ {
+ if ( auto pDocSh = dynamic_cast<ScDocShell*>(pShell) )
+ {
+ if ( nShellCnt == nDocNo )
+ pFound = pDocSh;
+ else
+ ++nShellCnt;
+ }
+ pShell = SfxObjectShell::GetNext( *pShell );
+ }
+
+ return pFound;
+}
+
+IMPL_LINK( ScDocShell, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
+{
+ OSL_ENSURE( _pFileDlg, "ScDocShell::DialogClosedHdl(): no file dialog" );
+ OSL_ENSURE( m_pImpl->pDocInserter, "ScDocShell::DialogClosedHdl(): no document inserter" );
+
+ if ( ERRCODE_NONE == _pFileDlg->GetError() )
+ {
+ sal_uInt16 nSlot = m_pImpl->pRequest->GetSlot();
+ std::unique_ptr<SfxMedium> pMed = m_pImpl->pDocInserter->CreateMedium();
+ // #i87094# If a .odt was selected pMed is NULL.
+ if (pMed)
+ {
+ m_pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
+ if ( SID_DOCUMENT_COMPARE == nSlot )
+ {
+ if ( pMed->GetFilter() )
+ m_pImpl->pRequest->AppendItem(
+ SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
+ OUString sOptions = ScDocumentLoader::GetOptions( *pMed );
+ if ( !sOptions.isEmpty() )
+ m_pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_FILTEROPTIONS, sOptions ) );
+ }
+ const SfxPoolItem* pItem = nullptr;
+ const SfxInt16Item* pInt16Item(nullptr);
+ SfxItemSet* pSet = pMed->GetItemSet();
+ if (pSet && pSet->GetItemState(SID_VERSION, true, &pItem) == SfxItemState::SET)
+ {
+ pInt16Item = dynamic_cast<const SfxInt16Item*>(pItem);
+ }
+ if (pInt16Item)
+ {
+ m_pImpl->pRequest->AppendItem( *pItem );
+ }
+
+ Execute( *(m_pImpl->pRequest) );
+ }
+ }
+
+ m_pImpl->bIgnoreLostRedliningWarning = false;
+}
+
+#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
+
+void ScDocShell::EnableSharedSettings( bool bEnable )
+{
+ SetDocumentModified();
+
+ if ( bEnable )
+ {
+ m_pDocument->EndChangeTracking();
+ m_pDocument->StartChangeTracking();
+
+ // hide accept or reject changes dialog
+ sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId();
+ SfxViewFrame* pViewFrame = SfxViewFrame::Current();
+ if ( pViewFrame && pViewFrame->HasChildWindow( nId ) )
+ {
+ pViewFrame->ToggleChildWindow( nId );
+ SfxBindings* pBindings = GetViewBindings();
+ if ( pBindings )
+ {
+ pBindings->Invalidate( FID_CHG_ACCEPT );
+ }
+ }
+ }
+ else
+ {
+ m_pDocument->EndChangeTracking();
+ }
+
+ ScChangeViewSettings aChangeViewSet;
+ aChangeViewSet.SetShowChanges( false );
+ m_pDocument->SetChangeViewSettings( aChangeViewSet );
+}
+
+uno::Reference< frame::XModel > ScDocShell::LoadSharedDocument()
+{
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ SC_MOD()->SetInSharedDocLoading( true );
+ uno::Reference< frame::XDesktop2 > xLoader = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
+ uno::Sequence aArgs{ comphelper::makePropertyValue("Hidden", true) };
+
+ if ( GetMedium() )
+ {
+ const SfxStringItem* pPasswordItem = SfxItemSet::GetItem<SfxStringItem>(GetMedium()->GetItemSet(), SID_PASSWORD, false);
+ if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
+ {
+ aArgs.realloc( 2 );
+ auto pArgs = aArgs.getArray();
+ pArgs[1].Name = "Password";
+ pArgs[1].Value <<= pPasswordItem->GetValue();
+ }
+ const SfxUnoAnyItem* pEncryptionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(GetMedium()->GetItemSet(), SID_ENCRYPTIONDATA, false);
+ if (pEncryptionItem)
+ {
+ aArgs.realloc(aArgs.getLength() + 1);
+ auto pArgs = aArgs.getArray();
+ pArgs[aArgs.getLength() - 1].Name = "EncryptionData";
+ pArgs[aArgs.getLength() - 1].Value = pEncryptionItem->GetValue();
+ }
+ }
+
+ xModel.set(
+ xLoader->loadComponentFromURL( GetSharedFileURL(), "_blank", 0, aArgs ),
+ uno::UNO_QUERY_THROW );
+ SC_MOD()->SetInSharedDocLoading( false );
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL( "ScDocShell::LoadSharedDocument(): caught exception" );
+ SC_MOD()->SetInSharedDocLoading( false );
+ try
+ {
+ uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
+ xClose->close( true );
+ return uno::Reference< frame::XModel >();
+ }
+ catch ( uno::Exception& )
+ {
+ return uno::Reference< frame::XModel >();
+ }
+ }
+ return xModel;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */