    /* -*- 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/embed/XEmbeddedObject.hpp>
    #include <com/sun/star/frame/Desktop.hpp>

    using namespace ::com::sun::star;

    #include <math.h>

    #include <scitems.hxx>
    #include <editeng/flstitem.hxx>
    #include <editeng/langitem.hxx>
    #include <sfx2/fcontnr.hxx>
    #include <sfx2/infobar.hxx>
    #include <sfx2/linkmgr.hxx>
    #include <sfx2/objface.hxx>
    #include <sfx2/docfile.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/whiter.hxx>
    #include <vcl/weld.hxx>
    #include <vcl/waitobj.hxx>
    #include <svx/dataaccessdescriptor.hxx>
    #include <svx/drawitem.hxx>
    #include <svx/fmshell.hxx>
    #include <svx/svdoole2.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 <svl/slstitm.hxx>
    #include <unotools/securityoptions.hxx>
    #include <LibreOfficeKit/LibreOfficeKitEnums.h>
    #include <sal/log.hxx>

    #include <comphelper/lok.hxx>
    #include <comphelper/processfactory.hxx>
    #include <docuno.hxx>

    #include <com/sun/star/sdbc/XResultSet.hpp>
    #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 <attrib.hxx>
    #include <undodat.hxx>
    #include <autostyl.hxx>
    #include <undocell.hxx>
    #include <undotab.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 <waitoff.hxx>
    #include <tablink.hxx>
    #include <drwlayer.hxx>
    #include <docoptio.hxx>
    #include <undostyl.hxx>
    #include <rangeseq.hxx>
    #include <chgtrack.hxx>
    #include <printopt.hxx>
    #include <com/sun/star/document/UpdateDocMode.hpp>
    #include <scresid.hxx>
    #include <scabstdlg.hxx>
    #include <externalrefmgr.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>

    void ScDocShell::ReloadAllLinks()
    {
        m_aDocument.SetLinkFormulaNeedingCheck(false);
        getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true);

        ReloadTabLinks();
        vcl::Window *pDialogParent = GetActiveDialogParent();
        m_aDocument.UpdateExternalRefLinks(pDialogParent);

        bool bAnyDde = m_aDocument.GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(pDialogParent ? pDialogParent->GetFrameWeld() : nullptr);

        if (bAnyDde)
        {
            //  calculate formulas and paint like in the TrackTimeHdl
            m_aDocument.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_aDocument.UpdateAreaLinks();
    }

    IMPL_LINK_NOARG( ScDocShell, ReloadAllLinksHdl, Button*, void )
    {
        ReloadAllLinks();

        ScTabViewShell* pViewSh = GetBestViewShell();
        SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
        if (pViewFrame)
            pViewFrame->RemoveInfoBar("enablecontent");
        SAL_WARN_IF(!pViewFrame, "sc", "expected there to be a ViewFrame");
    }

    void ScDocShell::Execute( SfxRequest& rReq )
    {
        const SfxItemSet* pReqArgs = rReq.GetArgs();
        SfxBindings* pBindings = GetViewBindings();
        bool bUndo (m_aDocument.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_aDocument.GetTableCount();
                    if ( ValidCol(nCol) && ValidRow(nRow) && ValidTab(nTab,nTabCount) )
                    {
                        if ( m_aDocument.IsBlockEditable( nTab, nCol,nRow, nCol, nRow ) )
                        {
                            OUString aVal = static_cast<const SfxStringItem*>(pTextItem)->GetValue();
                            m_aDocument.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_aDocument.GetDBCollection();
                        if ( !pDBColl || !pDBColl->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(sTarget)) )
                        {
                            ScAddress aPos;
                            if ( aPos.Parse( sTarget, &m_aDocument, m_aDocument.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 = aTemplate.getToken( 0, '#' );
                        aMessage += sTarget;
                        aMessage += aTemplate.getToken( 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( pReqArgs->HasItem( SID_CHART_NAME, &pItem ) )
                        aChartName = static_cast<const SfxStringItem*>(pItem)->GetValue();

                    if( pReqArgs->HasItem( SID_CHART_SOURCE, &pItem ) )
                        aRangeName = static_cast<const SfxStringItem*>(pItem)->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 );
                        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_aDocument.LimitChartArea( nTab, nCol1,nRow1, nCol2,nRow2 );

                                            // Dialog for column/row headers
                        bool bOk = true;
                        if ( !bAddRange && ( !bColInit || !bRowInit ) )
                        {
                            ScChartPositioner aChartPositioner( &m_aDocument, 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(
                                        new ScUndoChartData( this, aChartName, aRangeListRef,
                                                                bColHeaders, bRowHeaders, bAddRange ) );
                                }
                                m_aDocument.UpdateChartArea( aChartName, aRangeListRef,
                                                            bColHeaders, bRowHeaders, bAddRange );
                            }
                            else
                            {
                                ScRange aNewRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
                                if (bUndo)
                                {
                                    GetUndoManager()->AddUndoAction(
                                        new ScUndoChartData( this, aChartName, aNewRange,
                                                                bColHeaders, bRowHeaders, bAddRange ) );
                                }
                                m_aDocument.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_aDocument.GetAutoCalc();     // Toggle for menu
                    m_aDocument.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:
                {
                    ScDocument& rDoc = GetDocument();

                    ScLkUpdMode nSet = rDoc.GetLinkMode();

                    if(nSet==LM_UNKNOWN)
                    {
                        ScAppOptions aAppOptions=SC_MOD()->GetAppOptions();
                        nSet=aAppOptions.GetLinkMode();
                    }

                    if (m_nCanUpdate == css::document::UpdateDocMode::NO_UPDATE)
                        nSet = LM_NEVER;
                    else if (m_nCanUpdate == css::document::UpdateDocMode::FULL_UPDATE)
                        nSet = LM_ALWAYS;

                    if (nSet == LM_ALWAYS
                        && !(SvtSecurityOptions()
                             .isTrustedLocationUriForUpdatingLinks(
                                 GetMedium() == nullptr
                                 ? OUString() : GetMedium()->GetName())))
                    {
                        nSet = LM_ON_DEMAND;
                    }
                    if (m_nCanUpdate == css::document::UpdateDocMode::QUIET_UPDATE
                        && nSet == LM_ON_DEMAND)
                    {
                        nSet = LM_NEVER;
                    }

                    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("enablecontent");
                            auto pInfoBar = pViewFrame->AppendInfoBar("enablecontent", ScResId(STR_RELOAD_TABLES), InfoBarType::Warning);
                            if (pInfoBar)
                            {
                                VclPtrInstance<PushButton> xBtn(&pViewFrame->GetWindow());
                                xBtn->SetText(ScResId(STR_ENABLE_CONTENT));
                                xBtn->SetSizePixel(xBtn->GetOptimalSize());
                                xBtn->SetClickHdl(LINK(this, ScDocShell, ReloadAllLinksHdl));
                                pInfoBar->addButton(xBtn);
                            }
                        }
                        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_aDocument.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)
                        {
                            vcl::Window* pWin = GetActiveDialogParent();
                            std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                           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();
                                ScDBCollection::NamedDBs::iterator itr = rDBs.begin(), itrEnd = rDBs.end();
                                for (; itr != itrEnd; ++itr)
                                {
                                    ScDBData& rDBData = **itr;
                                    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_aDocument.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);
                    XColorListRef pList = pColItem->GetColorList();
                    rReq.SetReturnValue(OfaRefItem<XColorList>(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
                            vcl::Window* pWin = GetActiveDialogParent();
                            std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                       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_aDocument.GetChangeTrack();
                    if ( pChangeTrack && !m_pImpl->bIgnoreLostRedliningWarning )
                    {
                        if ( nSlot == SID_DOCUMENT_COMPARE )
                        {   //! old changes trace will be lost
                            vcl::Window* pWin = GetActiveDialogParent();
                            std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                       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* pStringItem(nullptr);
                    SfxMedium* pMed = nullptr;
                    if (pReqArgs && pReqArgs->GetItemState(SID_FILE_NAME, true, &pItem) == SfxItemState::SET)
                    {
                        pStringItem = dynamic_cast<const SfxStringItem*>(pItem);
                    }
                    if (pStringItem)
                    {
                        OUString aFileName = pStringItem->GetValue();

                        OUString aFilterName;
                        pStringItem = nullptr;
                        if (pReqArgs->GetItemState(SID_FILTER_NAME, true, &pItem) == SfxItemState::SET)
                            pStringItem = dynamic_cast<const SfxStringItem*>(pItem);
                        if (pStringItem)
                        {
                            aFilterName = pStringItem->GetValue();
                        }
                        OUString aOptions;
                        pStringItem = nullptr;
                        if (pReqArgs->GetItemState(SID_FILE_FILTEROPTIONS, true, &pItem) == SfxItemState::SET)
                            pStringItem = dynamic_cast<const SfxStringItem*>(pItem);
                        if (pStringItem)
                        {
                            aOptions = pStringItem->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 );
                        std::unique_ptr<SfxItemSet> pSet(new 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();
                        vcl::Window* pParent = pViewSh ? pViewSh->GetDialogParent() : nullptr;

                        m_pImpl->pDocInserter.reset( new ::sfx2::DocumentInserter(pParent ? pParent->GetFrameWeld() : nullptr,
                            ScDocShell::Factory().GetFactoryName(), mode ) );
                        m_pImpl->pDocInserter->StartExecuteModal( LINK( this, ScDocShell, DialogClosedHdl ) );
                        return ;
                    }

                    if ( pMed )     // 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_aDocument.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_aDocument.GetChangeViewSettings();
                                if ( !pOldSet || !pOldSet->ShowChanges() )
                                {
                                    ScChangeViewSettings aChangeViewSet;
                                    aChangeViewSet.SetShowChanges(true);
                                    m_aDocument.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_aDocument.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))
                        {
                            OUString aName = pStringItem->GetValue();
                            SCTAB nTab;
                            if (m_aDocument.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_aDocument.GetTable( aName, nTab ))
                            {
                                if (m_aDocument.IsScenario(nTab))
                                {
                                    OUString aComment;
                                    Color aColor;
                                    ScScenarioFlags nFlags;
                                    m_aDocument.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_aDocument.IsScenario(nActualTab));
                                    bool bSheetProtected = m_aDocument.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_aDocument.GetDocOptions() );
                        aDocOpt.SetYear2000( nY2k );
                        m_aDocument.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;
                    }

                    ScopedVclPtrInstance< ScShareDocumentDlg > aDlg( GetActiveDialogParent(), pViewData );
                    if ( aDlg->Execute() == RET_OK )
                    {
                        bool bSetShared = aDlg->IsShareDocumentChecked();
                        if ( bSetShared != IsDocShared() )
                        {
                            if ( bSetShared )
                            {
                                bool bContinue = true;
                                if ( HasName() )
                                {
                                    vcl::Window* pWin = GetActiveDialogParent();
                                    std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                                   VclMessageType::Question, VclButtonsType::YesNo,
                                                                                   ScResId(STR_REIMPORT_AFTER_LOAD)));
                                    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 = dynamic_cast< ScTabView* >( pViewData->GetView() );
                                    if ( pTabView )
                                    {
                                        pTabView->UpdateLayerLocks();
                                    }
                                }
                            }
                            else
                            {
                                uno::Reference< frame::XModel > xModel;
                                try
                                {
                                    // load shared file
                                    xModel.set( LoadSharedDocument(), uno::UNO_QUERY_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 = ScModelObj::getImplementation( 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 );

                                            vcl::Window* pWin = GetActiveDialogParent();
                                            std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                                       VclMessageType::Warning, VclButtonsType::Ok,
                                                                                       aMessage));
                                            xWarn->run();
                                        }
                                        else
                                        {
                                            vcl::Window* pWin = GetActiveDialogParent();
                                            std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                                       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 );

                                                if ( pBindings )
                                                {
                                                    pBindings->ExecuteSynchron( SID_SAVEDOC );
                                                }

                                                ScTabView* pTabView = dynamic_cast< ScTabView* >( pViewData->GetView() );
                                                if ( pTabView )
                                                {
                                                    pTabView->UpdateLayerLocks();
                                                }
                                            }
                                            else
                                            {
                                                xCloseable->close( true );
                                            }
                                        }
                                    }
                                    else
                                    {
                                        xCloseable->close( true );
                                        vcl::Window* pWin = GetActiveDialogParent();
                                        std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                                   VclMessageType::Warning, VclButtonsType::Ok,
                                                                                   ScResId(STR_DOC_NOLONGERSHARED)));
                                        xWarn->run();
                                    }
                                }
                                catch ( uno::Exception& )
                                {
                                    OSL_FAIL( "SID_SHARE_DOC: caught exception" );
                                    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:
            {
                SfxStringItem aApp(SID_DOC_SERVICE, OUString("com.sun.star.sheet.SpreadsheetDocument"));
                SfxStringItem aTarget(SID_TARGETNAME, OUString("_blank"));
                GetViewData()->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:
            {
                sal_Int32 nPos = 0;
                OUString aLangText;
                const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
                if ( pItem )
                    aLangText = pItem->GetValue();

                if ( !aLangText.isEmpty() )
                {
                    LanguageType eLang, eLatin, eCjk, eCtl;
                    const OUString aDocLangPrefix("Default_");
                    const OUString aNoLang("LANGUAGE_NONE");
                    const OUString aResetLang("RESET_LANGUAGES");

                    ScDocument& rDoc = GetDocument();
                    rDoc.GetLanguage( eLatin, eCjk, eCtl );

                    if ( aLangText == "*" )
                    {
                        SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
                        ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog(GetActiveDialogParent(), SID_LANGUAGE_OPTIONS));
                        pDlg->Execute();

                        rDoc.GetLanguage( eLang, eCjk, eCtl );
                    }
                    else if ( (nPos = aLangText.indexOf(aDocLangPrefix)) != -1 )
                    {
                        aLangText = aLangText.replaceAt(nPos, aDocLangPrefix.getLength(), "");

                        if ( aLangText == aNoLang )
                        {
                            eLang = LANGUAGE_NONE;
                            rDoc.SetLanguage( eLang, eCjk, eCtl );
                        }
                        else if ( aLangText == aResetLang )
                        {
                            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;
                            }
                        }
                    }

                    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;
            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_aDocument.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;

            vcl::Window* pWin = ScDocShell::GetActiveDialogParent();
            SfxPasswordDialog aDlg(pWin ? pWin->GetFrameWeld() : nullptr, &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.execute() == RET_OK)
                aPassword = aDlg.GetPassword();

            if (!aPassword.isEmpty())
            {
                if ( bProtected )
                {
                    if ( SvPasswordHelper::CompareHashPassword(pChangeTrack->GetProtection(), aPassword) )
                    {
                        if ( bJustQueryIfProtected )
                            bDone = true;
                        else
                            pChangeTrack->SetProtection(
                                css::uno::Sequence< sal_Int8 > (0) );
                    }
                    else
                    {
                        std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                                      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 )
    {
        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
        {
            WaitObject aWaitObj( GetActiveDialogParent() );
            if ( pHdl )
            {
                // tdf97897 set current cell to Dirty to force recalculation of cell
                ScFormulaCell* pFC = m_aDocument.GetFormulaCell( pHdl->GetCursorPos());
                if (pFC)
                    pFC->SetDirty();
            }
            m_aDocument.CalcFormulaTree();
            if ( pSh )
                pSh->UpdateCharts(true);

            m_aDocument.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_aDocument.GetChartListenerCollection();
            if ( pCharts && pCharts->hasListeners() )
                PostPaintGridAll();
            else
                PostDataChanged();
        }
    }

    void ScDocShell::DoHardRecalc()
    {
        auto start = std::chrono::steady_clock::now();
        WaitObject aWaitObj( GetActiveDialogParent() );
        ScTabViewShell* pSh = GetBestViewShell();
        if ( pSh )
        {
            ScTabView::UpdateInputLine();     // InputEnterHandler
            pSh->UpdateInputHandler();
        }
        m_aDocument.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_aDocument.GetTableCount();
        if (m_aDocument.HasAnySheetEventScript( ScSheetEventId::CALCULATE, true )) // search also for VBA handler
            for (SCTAB nTab=0; nTab<nTabCount; nTab++)
                m_aDocument.SetCalcNotification(nTab);

        // CalcAll doesn't broadcast value changes, so SfxHintId::ScCalcAll is broadcasted globally
        // in addition to SfxHintId::DataChanged.
        m_aDocument.BroadcastUno( SfxHint( SfxHintId::ScCalcAll ) );
        m_aDocument.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_aDocument.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_aDocument.GetStyleSheetPool();
        ScStyleSheet* pStyleSheet =
            pStylePool->FindCaseIns( rStyle, SfxStyleFamily::Para );
        if (!pStyleSheet)
            pStyleSheet = static_cast<ScStyleSheet*>(
                pStylePool->Find( ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para ));
        if (pStyleSheet)
        {
            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_aDocument.ApplyStyleAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, *pStyleSheet );
            m_aDocument.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 );

                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_aDocument.RenamePageStyleInUse( aOldName, aNewName );

                SCTAB nTabCount = m_aDocument.GetTableCount();
                for (SCTAB nTab=0; nTab<nTabCount; nTab++)
                    if (m_aDocument.GetPageStyle(nTab) == aNewName)   // already adjusted to new
                    {
                        m_aDocument.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)
            {
                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_aDocument.GetTableCount(); ++i)
                    {
                        ScConditionalFormatList* pList = m_aDocument.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_aDocument.GetPageStyle( nTab );
        ScStyleSheetPool* pStylePool = m_aDocument.GetStyleSheetPool();
        SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
        OSL_ENSURE( pStyleSheet, "PageStyle not found" );
        if ( pStyleSheet )
        {
            ScDocShellModificator aModificator( *this );

            SfxItemSet& rSet = pStyleSheet->GetItemSet();
            const bool bUndo(m_aDocument.IsUndoEnabled());
            if (bUndo)
            {
                sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
                sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
                GetUndoManager()->AddUndoAction( new 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_aDocument.GetPageStyle( nTab );
        ScStyleSheetPool* pStylePool = m_aDocument.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();
            const ScRange* pRepeatCol = m_aDocument.GetRepeatColRange( nTab );
            const ScRange* pRepeatRow = m_aDocument.GetRepeatRowRange( nTab );

            //  calculate needed scaling for selection

            sal_uInt16 nNewScale = nOldScale;

            long nBlkTwipsX = 0;
            if (bHeaders)
                nBlkTwipsX += long(PRINT_HEADER_WIDTH);
            SCCOL nStartCol = rRange.aStart.Col();
            SCCOL nEndCol = rRange.aEnd.Col();
            if ( pRepeatCol && nStartCol >= pRepeatCol->aStart.Col() )
            {
                for (SCCOL i=pRepeatCol->aStart.Col(); i<=pRepeatCol->aEnd.Col(); i++ )
                    nBlkTwipsX += m_aDocument.GetColWidth( i, nTab );
                if ( nStartCol <= pRepeatCol->aEnd.Col() )
                    nStartCol = pRepeatCol->aEnd.Col() + 1;
            }
            // legacy compilers' own scope for i
            {
                for ( SCCOL i=nStartCol; i<=nEndCol; i++ )
                    nBlkTwipsX += m_aDocument.GetColWidth( i, nTab );
            }

            long nBlkTwipsY = 0;
            if (bHeaders)
                nBlkTwipsY += long(PRINT_HEADER_HEIGHT);
            SCROW nStartRow = rRange.aStart.Row();
            SCROW nEndRow = rRange.aEnd.Row();
            if ( pRepeatRow && nStartRow >= pRepeatRow->aStart.Row() )
            {
                nBlkTwipsY += m_aDocument.GetRowHeight( pRepeatRow->aStart.Row(),
                        pRepeatRow->aEnd.Row(), nTab );
                if ( nStartRow <= pRepeatRow->aEnd.Row() )
                    nStartRow = pRepeatRow->aEnd.Row() + 1;
            }
            nBlkTwipsY += m_aDocument.GetRowHeight( nStartRow, nEndRow, nTab );

            Size aPhysPage;
            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;

            long nNeeded = std::min( aPhysPage.Width()  * 100 / nBlkTwipsX,
                                aPhysPage.Height() * 100 / nBlkTwipsY );
            if ( nNeeded < ZOOM_MIN )
                nNeeded = ZOOM_MIN;         // boundary
            if ( nNeeded < static_cast<long>(nNewScale) )
                nNewScale = static_cast<sal_uInt16>(nNeeded);

            bChange = ( nNewScale != nOldScale || nOldPages != 0 );
            if ( bChange )
                SetPrintZoom( nTab, nNewScale, 0 );
        }
        return bChange;
    }

    void ScDocShell::PageStyleModified( const OUString& rStyleName, bool bApi )
    {
        ScDocShellModificator aModificator( *this );

        SCTAB nTabCount = m_aDocument.GetTableCount();
        SCTAB nUseTab = MAXTAB+1;
        for (SCTAB nTab=0; nTab<nTabCount && nUseTab>MAXTAB; nTab++)
            if ( m_aDocument.GetPageStyle(nTab) == rStyleName &&
                    ( !bApi || m_aDocument.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)
            {
                vcl::Window* pWin = GetActiveDialogParent();
                ScWaitCursorOff aWaitOff(pWin);
                std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                                              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_aDocument.GetPageStyle( nCurTab );
                        ScStyleSheetPool* pStylePool = m_aDocument.GetStyleSheetPool();
                        SfxStyleSheetBase* pStyleSheet
                            = pStylePool->Find( aOldName, SfxStyleFamily::Page );

                        OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );

                        if ( pStyleSheet )
                        {
                            ScStyleSaveData aOldData;
                            const bool bUndo(m_aDocument.IsUndoEnabled());
                            if (bUndo)
                                aOldData.InitFromStyle( pStyleSheet );

                            SfxItemSet&     rStyleSet = pStyleSheet->GetItemSet();

                            ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();

                            ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScStyleDlg( GetActiveDialogParent(), *pStyleSheet, RID_SCDLG_STYLES_PAGE, RID_SCDLG_STYLES_PAGE ));

                            if ( pDlg->Execute() == RET_OK )
                            {
                                const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();

                                WaitObject aWait( GetActiveDialogParent() );

                                OUString aNewName = pStyleSheet->GetName();
                                if ( aNewName != aOldName &&
                                    m_aDocument.RenamePageStyleInUse( aOldName, aNewName ) )
                                {
                                    SfxBindings* pBindings = GetViewBindings();
                                    if (pBindings)
                                    {
                                        pBindings->Invalidate( SID_STATUS_PAGESTYLE );
                                        pBindings->Invalidate( FID_RESET_PRINTZOOM );
                                    }
                                }

                                if ( pOutSet )
                                    m_aDocument.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(
                                            new ScUndoModifyStyle( this, SfxStyleFamily::Page,
                                                        aOldData, aNewData ) );
                                }

                                PageStyleModified( aNewName, false );
                                rReq.Done();
                            }
                            pDlg.disposeAndClear();
                        }
                    }
                }
                break;

            case SID_HFEDIT:
                {
                    if ( pReqArgs == nullptr )
                    {
                        OUString aStr( m_aDocument.GetPageStyle( nCurTab ) );

                        ScStyleSheetPool* pStylePool
                            = m_aDocument.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();

                            ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScHFEditDlg(
                                                                                    GetActiveDialogParent(),
                                                                                    rStyleSet,
                                                                                    aStr,
                                                                                    nResId));
                            if ( pDlg->Execute() == RET_OK )
                            {
                                const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();

                                if ( pOutSet )
                                    m_aDocument.ModifyStyleSheet( *pStyleSheet, *pOutSet );

                                SetDocumentModified();
                                rReq.Done();
                            }
                        }
                    }
                }
                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_aDocument.GetPageStyle( nCurTab ) ) );
                    break;

                case SID_HFEDIT:
                    {
                        OUString            aStr        = m_aDocument.GetPageStyle( nCurTab );
                        ScStyleSheetPool*   pStylePool  = m_aDocument.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_aDocument.GetHardRecalcState() != ScDocument::HardRecalcState::OFF )
                        rSet.DisableItem( nWhich );
                    else
                        rSet.Put( SfxBoolItem( nWhich, m_aDocument.GetAutoCalc() ) );
                    break;

                case FID_CHG_RECORD:
                    if ( IsDocShared() )
                        rSet.DisableItem( nWhich );
                    else
                        rSet.Put( SfxBoolItem( nWhich,
                            m_aDocument.GetChangeTrack() != nullptr ) );
                    break;

                case SID_CHG_PROTECT:
                    {
                        ScChangeTrack* pChangeTrack = m_aDocument.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_aDocument.GetTableCount() ) );
                    break;

                case SID_ATTR_YEAR2000 :
                    rSet.Put( SfxUInt16Item( nWhich,
                        m_aDocument.GetDocOptions().GetYear2000() ) );
                break;

                case SID_SHARE_DOC:
                    {
                        if ( IsReadOnly() )
                        {
                            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(),
                                                                              "modules/scalc/ui/");
                            rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) );
                        }
                    }
                    break;

                case SID_LANGUAGE_STATUS:
                    {
                        LanguageType eLatin, eCjk, eCtl;

                        GetDocument().GetLanguage( eLatin, eCjk, eCtl );
                        rSet.Put(SfxStringItem(nWhich, SvtLanguageTable::GetLanguageString(eLatin)));
                    }
                    break;

                default:
                    {
                    }
                    break;
            }
        }
    }

    void ScDocShell::Draw( OutputDevice* pDev, const JobSetup & /* rSetup */, sal_uInt16 nAspect )
    {

        SCTAB nVisTab = m_aDocument.GetVisibleTab();
        if (!m_aDocument.HasTable(nVisTab))
            return;

        ComplexTextLayoutFlags nOldLayoutMode = pDev->GetLayoutMode();
        pDev->SetLayoutMode( 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_aDocument, pDev, 1.0, aBoundRect, &aTmpData, true );
        }
        else
        {
            tools::Rectangle aBoundRect = SfxObjectShell::GetVisArea();
            ScViewData aTmpData( this, nullptr );
            aTmpData.SetTabNo(nVisTab);
            SnapVisArea( aBoundRect );
            aTmpData.SetScreen( aBoundRect );
            ScPrintFunc::DrawToDev( &m_aDocument, pDev, 1.0, aBoundRect, &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_aDocument.GetVisibleTab();
            if (!m_aDocument.HasTable(nVisTab))
            {
                nVisTab = 0;
                const_cast<ScDocShell*>(this)->m_aDocument.SetVisibleTab(nVisTab);
            }
            Size aSize = m_aDocument.GetPageSize(nVisTab);
            const long SC_PREVIEW_SIZE_X = 10000;
            const 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_aDocument.IsNegativePage( m_aDocument.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_aDocument.GetVisibleTab();
            if (!m_aDocument.HasTable(nVisTab))
            {
                nVisTab = 0;
                const_cast<ScDocShell*>(this)->m_aDocument.SetVisibleTab(nVisTab);
            }
            SCCOL nStartCol;
            SCROW nStartRow;
            m_aDocument.GetDataStart( nVisTab, nStartCol, nStartRow );
            SCCOL nEndCol;
            SCROW nEndRow;
            m_aDocument.GetPrintArea( nVisTab, nEndCol, nEndRow );
            if (nStartCol>nEndCol)
                nStartCol = nEndCol;
            if (nStartRow>nEndRow)
                nStartRow = nEndRow;
            tools::Rectangle aNewArea = m_aDocument
                                    .GetMMRect( nStartCol,nStartRow, nEndCol,nEndRow, nVisTab );
            //TODO/LATER: different methods for setting VisArea?!
            const_cast<ScDocShell*>(this)->SfxObjectShell::SetVisArea( aNewArea );
            return aNewArea;
        }
        else
            return SfxObjectShell::GetVisArea( nAspect );
    }

    namespace {

    SAL_WARN_UNUSED_RESULT
    long SnapHorizontal( const ScDocument& rDoc, SCTAB nTab, long nVal, SCCOL& rStartCol )
    {
        SCCOL nCol = 0;
        long nTwips = static_cast<long>(nVal / HMM_PER_TWIPS);
        long nSnap = 0;
        while ( nCol<MAXCOL )
        {
            long nAdd = rDoc.GetColWidth(nCol, nTab);
            if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
            {
                nSnap += nAdd;
                ++nCol;
            }
            else
                break;
        }
        nVal = static_cast<long>( nSnap * HMM_PER_TWIPS );
        rStartCol = nCol;
        return nVal;
    }

    SAL_WARN_UNUSED_RESULT
    long SnapVertical( const ScDocument& rDoc, SCTAB nTab, long nVal, SCROW& rStartRow )
    {
        SCROW nRow = 0;
        long nTwips = static_cast<long>(nVal / HMM_PER_TWIPS);
        long nSnap = 0;

        bool bFound = false;
        for (SCROW i = nRow; i <= MAXROW; ++i)
        {
            SCROW nLastRow;
            if (rDoc.RowHidden(i, nTab, nullptr, &nLastRow))
            {
                i = nLastRow;
                continue;
            }

            nRow = i;
            long nAdd = rDoc.GetRowHeight(i, nTab);
            if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
            {
                nSnap += nAdd;
                ++nRow;
            }
            else
            {
                bFound = true;
                break;
            }
        }
        if (!bFound)
            nRow = MAXROW;  // all hidden down to the bottom

        nVal = static_cast<long>( nSnap * HMM_PER_TWIPS );
        rStartRow = nRow;
        return nVal;
    }

    }

    void ScDocShell::SnapVisArea( tools::Rectangle& rRect ) const
    {
        SCTAB nTab = m_aDocument.GetVisibleTab();
        bool bNegativePage = m_aDocument.IsNegativePage( nTab );
        if ( bNegativePage )
            ScDrawLayer::MirrorRectRTL( rRect );        // calculate with positive (LTR) values

        SCCOL nCol = 0;
        rRect.SetLeft( SnapHorizontal( m_aDocument, nTab, rRect.Left(), nCol ) );
        ++nCol;                                         // at least one column
        rRect.SetRight( SnapHorizontal( m_aDocument, nTab, rRect.Right(), nCol ) );

        SCROW nRow = 0;
        rRect.SetTop( SnapVertical( m_aDocument, nTab, rRect.Top(), nRow ) );
        ++nRow;                                         // at least one row
        rRect.SetBottom( SnapVertical( m_aDocument, nTab, rRect.Bottom(), 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_aDocument.GetStyleSheetPool();
            SfxStyleSheetBase* pStyleSheet = pStylePool->
                                                Find( m_aDocument.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_aDocument, 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_aDocument, 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_aDocument, 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_aDocument.GetRangeName();
        if( pRange )
        {
            const ScRangeData* pData = pRange->findByUpperName(ScGlobal::pCharClass->uppercase(aPos));
            if (pData)
            {
                if( pData->HasType( ScRangeData::Type::RefArea    )
                    || pData->HasType( ScRangeData::Type::AbsArea )
                    || pData->HasType( ScRangeData::Type::AbsPos  ) )
                    pData->GetSymbol( aPos );           // 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_aDocument, formula::FormulaGrammar::CONV_OOO ) & ScRefFlags::VALID) ||
                        (aRange.aStart.Parse(aPos, &m_aDocument, 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())
            {
                Point aScrPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), pViewData->GetActivePart(), true);
                long nSizeXPix;
                long nSizeYPix;
                pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeXPix, nSizeYPix);

                const double fPPTX = pViewData->GetPPTX();
                const double fPPTY = pViewData->GetPPTY();
                tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
                                Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));

                aAnnotation.put("cellPos", aRect.toString());
            }
        }

        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();

        SfxViewShell* pViewShell = SfxViewShell::GetFirst();
        while (pViewShell)
        {
            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 ( dynamic_cast<const ScDocShell*>(pShell) != nullptr )
            {
                if ( nShellCnt == nDocNo )
                    pFound = static_cast<ScDocShell*>(pShell);
                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_aDocument.EndChangeTracking();
            m_aDocument.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_aDocument.EndChangeTracking();
        }

        ScChangeViewSettings aChangeViewSet;
        aChangeViewSet.SetShowChanges( false );
        m_aDocument.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 < beans::PropertyValue > aArgs( 1 );
            aArgs[0].Name = "Hidden";
            aArgs[0].Value <<= true;

            if ( GetMedium() )
            {
                const SfxStringItem* pPasswordItem = SfxItemSet::GetItem<SfxStringItem>(GetMedium()->GetItemSet(), SID_PASSWORD, false);
                if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
                {
                    aArgs.realloc( 2 );
                    aArgs[1].Name = "Password";
                    aArgs[1].Value <<= pPasswordItem->GetValue();
                }
                const SfxUnoAnyItem* pEncryptionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(GetMedium()->GetItemSet(), SID_ENCRYPTIONDATA, false);
                if (pEncryptionItem)
                {
                    aArgs.realloc(aArgs.getLength() + 1);
                    aArgs[aArgs.getLength() - 1].Name = "EncryptionData";
                    aArgs[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: */

↑ V764 Possible incorrect order of arguments passed to 'CreateScColRowLabelDlg' function: 'bRowHeaders' and 'bColHeaders'.

↑ V668 There is no sense in testing the 'pMed' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error.