summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase/wrtsh/wrtsh1.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/uibase/wrtsh/wrtsh1.cxx')
-rw-r--r--sw/source/uibase/wrtsh/wrtsh1.cxx2572
1 files changed, 2572 insertions, 0 deletions
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx
new file mode 100644
index 000000000..fdf3f6082
--- /dev/null
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -0,0 +1,2572 @@
+/* -*- 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 <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+
+#include <hintids.hxx>
+#include <sot/exchange.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/hdft.hxx>
+#include <svx/svdview.hxx>
+#include <svl/itemiter.hxx>
+#include <tools/bigint.hxx>
+#include <svtools/insdlg.hxx>
+#include <sfx2/ipclient.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/ulspitem.hxx>
+#include <vcl/graph.hxx>
+#include <unotools/charclass.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <dialoghelp.hxx>
+#include <frmfmt.hxx>
+#include <fmtftn.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <txtfrm.hxx>
+#include <wdocsh.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <cmdid.h>
+#include <pagedesc.hxx>
+#include <frmmgr.hxx>
+#include <swundo.hxx>
+#include <swcli.hxx>
+#include <poolfmt.hxx>
+#include <edtwin.hxx>
+#include <fmtcol.hxx>
+#include <swtable.hxx>
+#include <viscrs.hxx>
+#include <swdtflvr.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <SwCapObjType.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <sfx2/request.hxx>
+#include <paratr.hxx>
+#include <ndtxt.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <IMark.hxx>
+#include <sfx2/bindings.hxx>
+#include <flyfrm.hxx>
+
+// -> #111827#
+#include <SwRewriter.hxx>
+#include <strings.hrc>
+// <- #111827#
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/unit_conversion.hxx>
+
+#include <PostItMgr.hxx>
+#include <FrameControlsManager.hxx>
+#include <fldmgr.hxx>
+#include <docufld.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <fmtfld.hxx>
+
+#include <sfx2/msgpool.hxx>
+#include <sfx2/msg.hxx>
+#include <svtools/embedhlp.hxx>
+#include <svx/postattr.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zformat.hxx>
+#include <memory>
+
+#include "../../core/crsr/callnk.hxx"
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+
+#include <IDocumentUndoRedo.hxx>
+#include <UndoInsert.hxx>
+#include <UndoCore.hxx>
+#include <formatlinebreak.hxx>
+#include <formatcontentcontrol.hxx>
+
+using namespace sw::mark;
+using namespace com::sun::star;
+namespace {
+
+void collectUIInformation(const OUString& rAction, const OUString& aParameters)
+{
+ EventDescription aDescription;
+ aDescription.aAction = rAction;
+ aDescription.aParameters = {{"parameters", aParameters}};
+ aDescription.aID = "writer_edit";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ aDescription.aParent = "MainWindow";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+sal_uInt32 MakeAllOutlineContentTemporarilyVisible::nLock = 0;
+
+static bool lcl_IsAllowed(const SwWrtShell* rSh)
+{
+ if (rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && rSh->IsEndPara())
+ {
+ SwTextNode* pTextNode = rSh->GetCursor()->GetNode().GetTextNode();
+ if (pTextNode && pTextNode->IsOutline())
+ {
+ // disallow if this is an outline node having folded content
+ bool bVisible = true;
+ pTextNode->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ return false;
+ }
+ }
+ return true;
+}
+
+#define BITFLD_INI_LIST \
+ m_bClearMark = \
+ m_bIns = true;\
+ m_bAddMode = \
+ m_bBlockMode = \
+ m_bExtMode = \
+ m_bInSelect = \
+ m_bLayoutMode = \
+ m_bSelWrd = \
+ m_bSelLn = \
+ m_bRetainSelection = false; \
+ m_bIsInClickToEdit = false;
+
+static SvxAutoCorrect* lcl_IsAutoCorr()
+{
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
+ if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
+ ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
+ ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect ))
+ pACorr = nullptr;
+ return pACorr;
+}
+
+void SwWrtShell::NoEdit(bool bHideCursor)
+{
+ if(bHideCursor)
+ HideCursor();
+}
+
+void SwWrtShell::Edit()
+{
+ if (CanInsert())
+ {
+ ShowCursor();
+ }
+}
+
+bool SwWrtShell::IsEndWrd()
+{
+ SwMvContext aMvContext(this);
+ if(IsEndPara() && !IsSttPara())
+ return true;
+
+ return IsEndWord();
+}
+
+// Insert string
+void SwWrtShell::InsertByWord( const OUString & rStr)
+{
+ if( rStr.isEmpty() )
+ return;
+
+ bool bDelim = GetAppCharClass().isLetterNumeric( rStr, 0 );
+ sal_Int32 nPos = 0, nStt = 0;
+ for( ; nPos < rStr.getLength(); nPos++ )
+ {
+ bool bTmpDelim = GetAppCharClass().isLetterNumeric( rStr, nPos );
+ if( bTmpDelim != bDelim )
+ {
+ Insert( rStr.copy( nStt, nPos - nStt ));
+ nStt = nPos;
+ }
+ }
+ if( nStt != nPos )
+ Insert( rStr.copy( nStt, nPos - nStt ));
+}
+
+void SwWrtShell::Insert( const OUString &rStr )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ bool bStarted = false;
+ bool bHasSel = HasSelection(),
+ bCallIns = m_bIns /*|| bHasSel*/;
+ bool bDeleted = false;
+
+ if( bHasSel || ( !m_bIns && SelectHiddenRange() ) )
+ {
+ // Only here parenthesizing, because the normal
+ // insert is already in parentheses at Editshell.
+ StartAllAction();
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, GetCursorDescr());
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ {
+ OUString aTmpStr = SwResId(STR_START_QUOTE) +
+ rStr + SwResId(STR_END_QUOTE);
+
+ aRewriter.AddRule(UndoArg3, aTmpStr);
+ }
+
+ StartUndo(SwUndoId::REPLACE, &aRewriter);
+ bStarted = true;
+ Push();
+ // let's interpret a selection within the same node as "replace"
+ bDeleted = DelRight(GetCursor()->GetPoint()->nNode == GetCursor()->GetMark()->nNode);
+ Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore selection (if tracking changes)
+ NormalizePam(false); // tdf#127635 put point at the end of deletion
+ ClearMark();
+ }
+
+ bCallIns ?
+ SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
+
+ if( bStarted )
+ {
+ EndUndo();
+ EndAllAction();
+ }
+}
+
+// Maximum height limit not possible, because the maximum height
+// of the current frame can not be obtained.
+
+void SwWrtShell::InsertGraphic( const OUString &rPath, const OUString &rFilter,
+ const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr,
+ RndStdIds nAnchorType )
+{
+ ResetCursorStack();
+ if ( !CanInsert() )
+ return;
+
+ StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC));
+
+ StartUndo(SwUndoId::INSERT, &aRewriter);
+
+ if ( HasSelection() )
+ DelRight();
+ // Inserted graphics in its own paragraph,
+ // if at the end of a non-empty paragraph.
+ //For i120928,avoid to split node
+
+ EnterSelFrameMode();
+
+ bool bSetGrfSize = true;
+ bool bOwnMgr = false;
+
+ if ( !pFrameMgr )
+ {
+ bOwnMgr = true;
+ pFrameMgr = new SwFlyFrameAttrMgr( true, this, Frmmgr_Type::GRF, nullptr );
+
+ // CAUTION
+ // GetAttrSet makes an adjustment
+ // While pasting is a SwFrameSize present
+ // because of the DEF-Framesize
+ // These must be removed explicitly for the optimal size.
+ pFrameMgr->DelAttr(RES_FRM_SIZE);
+
+ if (nAnchorType != RndStdIds::FLY_AT_PARA)
+ // Something other than at-para was requested.
+ pFrameMgr->SetAnchor(nAnchorType);
+ }
+ else
+ {
+ Size aSz( pFrameMgr->GetSize() );
+ if ( !aSz.Width() || !aSz.Height() )
+ {
+ aSz.setWidth(o3tl::toTwips(1, o3tl::Length::cm));
+ aSz.setHeight(o3tl::toTwips(1, o3tl::Length::cm));
+ pFrameMgr->SetSize( aSz );
+ }
+ else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
+ bSetGrfSize = false;
+
+ pFrameMgr->SetHeightSizeType(SwFrameSize::Fixed);
+ }
+
+ // during change tracking, insert the image anchored as character
+ // (to create an SwRangeRedline on its anchor point)
+ if ( IsRedlineOn() && nAnchorType != RndStdIds::FLY_AS_CHAR )
+ pFrameMgr->SetAnchor( RndStdIds::FLY_AS_CHAR );
+
+ // Insert the graphic
+ SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
+ if ( bOwnMgr )
+ pFrameMgr->UpdateAttrMgr();
+
+ if( bSetGrfSize )
+ {
+ Size aSizePixel = rGrf.GetSizePixel();
+ Size aBound = GetGraphicDefaultSize();
+
+ sal_Int32 nPreferredDPI = mxDoc->getIDocumentSettingAccess().getImagePreferredDPI();
+ Size aGrfSize;
+
+ if (nPreferredDPI > 0)
+ {
+ auto nWidth = o3tl::toTwips(aSizePixel.Width() / double(nPreferredDPI), o3tl::Length::in);
+ auto nHeight = o3tl::toTwips(aSizePixel.Height() / double(nPreferredDPI), o3tl::Length::in);
+ aGrfSize = Size(nWidth, nHeight);
+ }
+ else
+ {
+ GetGrfSize(aGrfSize);
+ }
+
+ // Add the margin attributes to GrfSize,
+ // because these counts at the margin additionally
+ aGrfSize.AdjustWidth(pFrameMgr->CalcWidthBorder() );
+ aGrfSize.AdjustHeight(pFrameMgr->CalcHeightBorder() );
+
+ const BigInt aTempWidth( aGrfSize.Width() );
+ const BigInt aTempHeight( aGrfSize.Height());
+
+ // Fit width if necessary, scale down the height proportional thereafter.
+ if( aGrfSize.Width() > aBound.Width() )
+ {
+ aGrfSize.setWidth( aBound.Width() );
+ aGrfSize.setHeight( BigInt(aBound.Width()) * aTempHeight / aTempWidth );
+ }
+ // Fit height if necessary, scale down the width proportional thereafter.
+ if( aGrfSize.Height() > aBound.Height() )
+ {
+ aGrfSize.setHeight( aBound.Height() );
+ aGrfSize.setWidth( BigInt(aBound.Height()) * aTempWidth / aTempHeight );
+ }
+ pFrameMgr->SetSize( aGrfSize );
+ pFrameMgr->UpdateFlyFrame();
+ }
+ if ( bOwnMgr )
+ delete pFrameMgr;
+
+ EndUndo();
+ EndAllAction();
+}
+
+// Insert an OLE-Object into the CORE.
+// if no object is transferred, then one will be created.
+
+void SwWrtShell::InsertObject( const svt::EmbeddedObjectRef& xRef, SvGlobalName const *pName,
+ sal_uInt16 nSlotId )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ if( !xRef.is() )
+ {
+ // temporary storage
+ svt::EmbeddedObjectRef xObj;
+ uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetTemporaryStorage();
+ bool bDoVerb = true;
+ if ( pName )
+ {
+ comphelper::EmbeddedObjectContainer aCnt( xStor );
+ OUString aName;
+ // TODO/LATER: get aspect?
+ xObj.Assign( aCnt.CreateEmbeddedObject( pName->GetByteSequence(), aName ), embed::Aspects::MSOLE_CONTENT );
+ }
+ else
+ {
+ SvObjectServerList aServerList;
+ switch (nSlotId)
+ {
+ case SID_INSERT_OBJECT:
+ {
+ aServerList.FillInsertObjects();
+ aServerList.Remove( SwDocShell::Factory().GetClassId() );
+ [[fallthrough]];
+ }
+
+ // TODO/LATER: recording! Convert properties to items
+ case SID_INSERT_FLOATINGFRAME:
+ {
+ SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
+ const SfxSlot* pSlot = pSlotPool->GetSlot(nSlotId);
+ OString aCmd = OString::Concat(".uno:") + pSlot->GetUnoName();
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(GetFrameWeld(mxDoc->GetDocShell()),
+ OUString::fromUtf8( aCmd ), xStor, &aServerList));
+ if (pDlg)
+ {
+ pDlg->Execute();
+ bDoVerb = pDlg->IsCreateNew();
+ OUString aIconMediaType;
+ uno::Reference< io::XInputStream > xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
+ xObj.Assign( pDlg->GetObject(),
+ xIconMetaFile.is() ? embed::Aspects::MSOLE_ICON : embed::Aspects::MSOLE_CONTENT );
+ if ( xIconMetaFile.is() )
+ xObj.SetGraphicStream( xIconMetaFile, aIconMediaType );
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ if ( xObj.is() )
+ {
+ if( InsertOleObject( xObj ) && bDoVerb )
+ {
+ SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
+ if ( !pClient )
+ {
+ pClient = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
+ SetCheckForOLEInCaption( true );
+ }
+
+ if ( xObj.GetViewAspect() == embed::Aspects::MSOLE_ICON )
+ {
+ SwRect aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
+ aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
+ MapMode aMapMode( MapUnit::MapTwip );
+ Size aSize = xObj.GetSize( &aMapMode );
+ aArea.Width( aSize.Width() );
+ aArea.Height( aSize.Height() );
+ RequestObjectResize( aArea, xObj.GetObject() );
+ }
+ else
+ CalcAndSetScale( xObj );
+
+ //#50270# We don't need to handle error, this is handled by the
+ //DoVerb in the SfxViewShell
+ pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
+
+ // TODO/LATER: set document name - should be done in Client
+ }
+ }
+ }
+ else
+ {
+ if( HasSelection() )
+ DelRight();
+ InsertOleObject( xRef );
+ }
+}
+
+// Insert object into the Core.
+// From ClipBoard or Insert
+
+bool SwWrtShell::InsertOleObject( const svt::EmbeddedObjectRef& xRef, SwFlyFrameFormat **pFlyFrameFormat )
+{
+ //tdf#125100 Ensure that ole object is initially shown as pictogram
+ comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mxDoc->GetDocShell()->getEmbeddedObjectContainer();
+ bool bSaveUserAllowsLinkUpdate = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
+
+ ResetCursorStack();
+ StartAllAction();
+
+ StartUndo(SwUndoId::INSERT);
+
+ //Some differences between StarMath and any other objects:
+ //1. Selections should be deleted. For StarMath the Text should be
+ // passed to the Object
+ //2. If the cursor is at the end of a non empty paragraph a paragraph
+ // break should be inserted. StarMath objects are character bound and
+ // no break should be inserted.
+ //3. If an selection is passed to a StarMath object, this object should
+ // not be activated. false should be returned then.
+ bool bStarMath = true;
+ bool bActivate = true;
+
+ // set parent to get correct VisArea(in case of object needing parent printer)
+ uno::Reference < container::XChild > xChild( xRef.GetObject(), uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( mxDoc->GetDocShell()->GetModel() );
+
+ SvGlobalName aCLSID( xRef->getClassID() );
+ bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
+ if( IsSelection() )
+ {
+ if( bStarMath )
+ {
+ OUString aMathData;
+ GetSelectedText( aMathData, ParaBreakType::ToOnlyCR );
+
+ if( !aMathData.isEmpty() && svt::EmbeddedObjectRef::TryRunningState( xRef.GetObject() ) )
+ {
+ uno::Reference < beans::XPropertySet > xSet( xRef->getComponent(), uno::UNO_QUERY );
+ if ( xSet.is() )
+ {
+ try
+ {
+ xSet->setPropertyValue("Formula", uno::Any( aMathData ) );
+ bActivate = false;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ }
+ }
+ DelRight();
+ }
+
+ if ( !bStarMath )
+ SwFEShell::SplitNode( false, false );
+
+ EnterSelFrameMode();
+
+ const SvGlobalName* pName = nullptr;
+ SvGlobalName aObjClsId;
+ if (xRef.is())
+ {
+ aObjClsId = SvGlobalName(xRef.GetObject()->getClassID());
+ pName = &aObjClsId;
+ }
+ SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE, pName );
+ aFrameMgr.SetHeightSizeType(SwFrameSize::Fixed);
+
+ SwRect aBound;
+ CalcBoundRect( aBound, aFrameMgr.GetAnchor() );
+
+ //The Size should be suggested by the OLE server
+ MapMode aMapMode( MapUnit::MapTwip );
+ Size aSz = xRef.GetSize( &aMapMode );
+
+ //Object size can be limited
+ if ( aSz.Width() > aBound.Width() )
+ {
+ //Always limit proportional.
+ aSz.setHeight( aSz.Height() * aBound.Width() / aSz.Width() );
+ aSz.setWidth( aBound.Width() );
+ }
+ aFrameMgr.SetSize( aSz );
+ SwFlyFrameFormat *pFormat = SwFEShell::InsertObject( xRef, &aFrameMgr.GetAttrSet() );
+
+ // --> #i972#
+ if ( bStarMath && mxDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) )
+ AlignFormulaToBaseline( xRef.GetObject() );
+
+ if (pFlyFrameFormat)
+ *pFlyFrameFormat = pFormat;
+
+ if ( SotExchange::IsChart( aCLSID ) )
+ {
+ uno::Reference< embed::XEmbeddedObject > xEmbeddedObj = xRef.GetObject();
+ if ( xEmbeddedObj.is() )
+ {
+ bool bDisableDataTableDialog = false;
+ svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
+ uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
+ if ( xProps.is() &&
+ ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
+ bDisableDataTableDialog )
+ {
+ xProps->setPropertyValue("DisableDataTableDialog",
+ uno::Any( false ) );
+ xProps->setPropertyValue("DisableComplexChartTypes",
+ uno::Any( false ) );
+ uno::Reference< util::XModifiable > xModifiable( xProps, uno::UNO_QUERY );
+ if ( xModifiable.is() )
+ {
+ xModifiable->setModified( true );
+ }
+ }
+ }
+ }
+
+ EndAllAction();
+ GetView().AutoCaption(OLE_CAP, &aCLSID);
+
+ SwRewriter aRewriter;
+
+ if ( bStarMath )
+ aRewriter.AddRule(UndoArg1, SwResId(STR_MATH_FORMULA));
+ else if ( SotExchange::IsChart( aCLSID ) )
+ aRewriter.AddRule(UndoArg1, SwResId(STR_CHART));
+ else
+ aRewriter.AddRule(UndoArg1, SwResId(STR_OLE));
+
+ EndUndo(SwUndoId::INSERT, &aRewriter);
+
+ rEmbeddedObjectContainer.setUserAllowsLinkUpdate(bSaveUserAllowsLinkUpdate);
+
+ return bActivate;
+}
+
+// The current selected OLE object will be loaded with the
+// verb into the server.
+void SwWrtShell::LaunchOLEObj(sal_Int32 nVerb)
+{
+ if ( GetCntType() != CNT_OLE ||
+ GetView().GetViewFrame()->GetFrame().IsInPlace() )
+ return;
+
+ svt::EmbeddedObjectRef& xRef = GetOLEObject();
+ OSL_ENSURE( xRef.is(), "OLE not found" );
+
+ // LOK: we don't want to handle any other embedded objects than
+ // charts, there are too many problems with eg. embedded spreadsheets
+ // (like it creates a separate view for the calc sheet)
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ const auto classId = xRef->getClassID();
+ if (!SotExchange::IsChart(classId) && !SotExchange::IsMath(classId))
+ return;
+ }
+
+ SfxInPlaceClient* pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
+ if ( !pCli )
+ pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
+
+ uno::Reference<lang::XInitialization> xOLEInit(xRef.GetObject(), uno::UNO_QUERY);
+ if (xOLEInit.is())
+ {
+ uno::Sequence<beans::PropertyValue> aArguments
+ = { comphelper::makePropertyValue("ReadOnly", pCli->IsProtected()) };
+ xOLEInit->initialize({ uno::Any(aArguments) });
+ }
+
+ static_cast<SwOleClient*>(pCli)->SetInDoVerb( true );
+
+ CalcAndSetScale( xRef );
+ pCli->DoVerb( nVerb );
+
+ static_cast<SwOleClient*>(pCli)->SetInDoVerb( false );
+ CalcAndSetScale( xRef );
+}
+
+void SwWrtShell::MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset )
+{
+ try
+ {
+ sal_Int32 nState = xObj->getCurrentState();
+ if ( nState == css::embed::EmbedStates::INPLACE_ACTIVE
+ || nState == css::embed::EmbedStates::UI_ACTIVE )
+ {
+ SfxInPlaceClient* pCli =
+ GetView().FindIPClient( xObj.GetObject(), &(GetView().GetEditWin()) );
+ if ( pCli )
+ {
+ tools::Rectangle aArea = pCli->GetObjArea();
+ aArea += rOffset;
+ pCli->SetObjArea( aArea );
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ }
+}
+
+void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
+ const SwRect *pFlyPrtRect,
+ const SwRect *pFlyFrameRect,
+ const bool bNoTextFramePrtAreaChanged )
+{
+ // Setting the scale of the client. This arises from the difference
+ // between the VisArea of the object and the ObjArea.
+ OSL_ENSURE( xObj.is(), "ObjectRef not valid" );
+
+ sal_Int64 nAspect = xObj.GetViewAspect();
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ return; // the replacement image is completely controlled by container in this case
+
+ sal_Int64 nMisc = 0;
+ bool bLinkingChart = false;
+
+ try
+ {
+ nMisc = xObj->getStatus( nAspect );
+
+ // This can surely only be a non-active object, if desired they
+ // get the new size set as VisArea (StarChart).
+ if( embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE & nMisc )
+ {
+ // TODO/MBA: testing
+ SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
+ : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
+ if( !aRect.IsEmpty() )
+ {
+ // TODO/LEAN: getMapUnit can switch object to running state
+ // xObj.TryRunningState();
+
+ MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+
+ // TODO/LATER: needs complete VisArea?!
+ Size aSize( OutputDevice::LogicToLogic(aRect.SVRect(), MapMode(MapUnit::MapTwip), MapMode(aUnit)).GetSize() );
+ awt::Size aSz;
+ aSz.Width = aSize.Width();
+ aSz.Height = aSize.Height();
+
+ // Action 'setVisualAreaSize' doesn't have to turn on the
+ // modified state of the document, either.
+ bool bModified = false;
+ uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
+ if (xModifiable.is())
+ bModified = xModifiable->isModified();
+ xObj->setVisualAreaSize( nAspect, aSz );
+ xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
+ if (xModifiable.is() && xModifiable->isModified() && !bModified)
+ xModifiable->setModified(bModified);
+
+ // #i48419# - action 'UpdateReplacement' doesn't
+ // have to change the modified state of the document.
+ // This is only a workaround for the defect, that this action
+ // modifies a document after load, because unnecessarily the
+ // replacement graphic is updated, in spite of the fact that
+ // nothing has been changed.
+ // If the replacement graphic changes by this action, the document
+ // will be already modified via other mechanisms.
+ {
+ bool bResetEnableSetModified(false);
+ if ( GetDoc()->GetDocShell()->IsEnableSetModified() )
+ {
+ GetDoc()->GetDocShell()->EnableSetModified( false );
+ bResetEnableSetModified = true;
+ }
+
+ //#i79576# don't destroy chart replacement images on load
+ //#i79578# don't request a new replacement image for charts to often
+ //a chart sends a modified call to the framework if it was changed
+ //thus the replacement update is already handled elsewhere
+ if ( !SotExchange::IsChart( xObj->getClassID() ) )
+ xObj.UpdateReplacement();
+
+ if ( bResetEnableSetModified )
+ {
+ GetDoc()->GetDocShell()->EnableSetModified();
+ }
+ }
+ }
+
+ // TODO/LATER: this is only a workaround,
+ uno::Reference< chart2::XChartDocument > xChartDocument( xObj->getComponent(), uno::UNO_QUERY );
+ bLinkingChart = ( xChartDocument.is() && !xChartDocument->hasInternalDataProvider() );
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // TODO/LATER: handle the error
+ return;
+ }
+
+ SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
+ if ( !pCli )
+ {
+ if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc)
+ || bLinkingChart
+ // --> OD #i117189# - refine condition for non-resizable objects
+ // non-resizable objects need to be set the size back by this method
+ || ( bNoTextFramePrtAreaChanged && nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
+ {
+ pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
+ }
+ else
+ return;
+ }
+
+ // TODO/LEAN: getMapUnit can switch object to running state
+ // xObj.TryRunningState();
+
+ awt::Size aSize;
+ try
+ {
+ aSize = xObj->getVisualAreaSize( nAspect );
+ }
+ catch (const embed::NoVisualAreaSizeException&)
+ {
+ OSL_FAIL("Can't get visual area size!" );
+ // the scaling will not be done
+ }
+ catch (const uno::Exception&)
+ {
+ // TODO/LATER: handle the error
+ OSL_FAIL("Can't get visual area size!" );
+ return;
+ }
+
+ Size _aVisArea( aSize.Width, aSize.Height );
+
+ Fraction aScaleWidth( 1, 1 );
+ Fraction aScaleHeight( 1, 1 );
+
+ bool bUseObjectSize = false;
+
+ // As long as there comes no reasonable size from the object,
+ // nothing can be scaled.
+ if( _aVisArea.Width() && _aVisArea.Height() )
+ {
+ const MapMode aTmp( MapUnit::MapTwip );
+ MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+ _aVisArea = OutputDevice::LogicToLogic(_aVisArea, MapMode(aUnit), aTmp);
+ Size aObjArea;
+ if ( pFlyPrtRect )
+ aObjArea = pFlyPrtRect->SSize();
+ else
+ aObjArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ).SSize();
+
+ // differ the aObjArea and _aVisArea by 1 Pixel then set new VisArea
+ tools::Long nX, nY;
+ SwSelPaintRects::Get1PixelInLogic( *this, &nX, &nY );
+ if( !( _aVisArea.Width() - nX <= aObjArea.Width() &&
+ _aVisArea.Width() + nX >= aObjArea.Width() &&
+ _aVisArea.Height()- nY <= aObjArea.Height()&&
+ _aVisArea.Height()+ nY >= aObjArea.Height() ))
+ {
+ if ( nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE )
+ {
+ // the object must not be scaled,
+ // the size stored in object must be used for restoring
+ bUseObjectSize = true;
+ }
+ else
+ {
+ aScaleWidth = Fraction( aObjArea.Width(), _aVisArea.Width() );
+ aScaleHeight = Fraction( aObjArea.Height(), _aVisArea.Height());
+ }
+ }
+ }
+
+ // Now is the favorable time to set the ObjArea.
+ // The Scaling must be considered.
+ SwRect aArea;
+ if ( pFlyPrtRect )
+ {
+ aArea = *pFlyPrtRect;
+ aArea += pFlyFrameRect->Pos();
+ }
+ else
+ {
+ aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
+ aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
+ }
+
+ if ( bUseObjectSize )
+ {
+ // --> this moves non-resizable object so that when adding borders the baseline remains the same
+ const SwFlyFrameFormat *pFlyFrameFormat = dynamic_cast< const SwFlyFrameFormat * >( GetFlyFrameFormat() );
+ OSL_ENSURE( pFlyFrameFormat, "Could not find fly frame." );
+ if ( pFlyFrameFormat )
+ {
+ const Point &rPoint = pFlyFrameFormat->GetLastFlyFramePrtRectPos();
+ SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
+ : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
+ aArea += rPoint - aRect.Pos(); // adjust area by diff of printing area position in order to keep baseline alignment correct.
+ }
+ aArea.Width ( _aVisArea.Width() );
+ aArea.Height( _aVisArea.Height() );
+ RequestObjectResize( aArea, xObj.GetObject() );
+ }
+ else
+ {
+ tools::Long nWidth(pCli->GetScaleWidth());
+ tools::Long nHeight(pCli->GetScaleHeight());
+ if (nWidth && nHeight)
+ {
+ aArea.Width ( aArea.Width() / nWidth );
+ aArea.Height( aArea.Height() / nHeight );
+ }
+ }
+
+ pCli->SetObjAreaAndScale( aArea.SVRect(), aScaleWidth, aScaleHeight );
+}
+
+void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt,
+ const SwRect &rFrame )
+{
+ SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin());
+ if ( !pCli )
+ new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
+ CalcAndSetScale( xObj, &rPrt, &rFrame );
+}
+
+// Insert hard page break;
+// Selections will be overwritten
+void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::std::optional<sal_uInt16>& oPgNum )
+{
+ if (!lcl_IsAllowed(this))
+ return;
+
+ ResetCursorStack();
+ if( CanInsert() )
+ {
+ SwActContext aActContext(this);
+ StartUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
+
+ if ( !IsCursorInTable() )
+ {
+ if(HasSelection())
+ DelRight();
+ SwFEShell::SplitNode();
+ // delete the numbered attribute of the last line if the last line is empty
+ GetDoc()->ClearLineNumAttrs( *GetCursor()->GetPoint() );
+ }
+
+ const SwPageDesc *pDesc = pPageDesc
+ ? FindPageDescByName( *pPageDesc, true ) : nullptr;
+ if( pDesc )
+ {
+ SwFormatPageDesc aDesc( pDesc );
+ aDesc.SetNumOffset( oPgNum );
+ SetAttrItem( aDesc );
+ }
+ else
+ SetAttrItem( SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK) );
+ EndUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
+ }
+ collectUIInformation("BREAK_PAGE", "parameter");
+}
+
+// Insert hard page break;
+// Selections will be overwritten
+
+void SwWrtShell::InsertLineBreak(std::optional<SwLineBreakClear> oClear)
+{
+ if (!lcl_IsAllowed(this))
+ return;
+
+ ResetCursorStack();
+ if( CanInsert() )
+ {
+ if(HasSelection())
+ DelRight();
+
+ const sal_Unicode cIns = 0x0A;
+ SwLineBreakClear eClear = SwLineBreakClear::NONE;
+ if (oClear.has_value())
+ {
+ eClear = *oClear;
+ }
+ SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
+ if (pACorr && eClear == SwLineBreakClear::NONE)
+ AutoCorrect( *pACorr, cIns );
+ else
+ {
+ if (eClear == SwLineBreakClear::NONE)
+ {
+ SwWrtShell::Insert(OUString(cIns));
+ }
+ else
+ {
+ SwFormatLineBreak aLineBreak(eClear);
+ SetAttrItem(aLineBreak);
+ }
+ }
+ }
+}
+
+// Insert hard column break;
+// Selections will be overwritten
+
+void SwWrtShell::InsertColumnBreak()
+{
+ if (!lcl_IsAllowed(this))
+ return;
+
+ SwActContext aActContext(this);
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ StartUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
+
+ if ( !IsCursorInTable() )
+ {
+ if(HasSelection())
+ DelRight();
+ SwFEShell::SplitNode( false, false );
+ }
+ SetAttrItem(SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
+
+ EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
+}
+
+void SwWrtShell::InsertContentControl(SwContentControlType eType)
+{
+ if (!lcl_IsAllowed(this))
+ {
+ return;
+ }
+
+ ResetCursorStack();
+ if (!CanInsert())
+ {
+ return;
+ }
+
+ auto pContentControl = std::make_shared<SwContentControl>(nullptr);
+ OUString aPlaceholder;
+ switch (eType)
+ {
+ case SwContentControlType::RICH_TEXT:
+ {
+ pContentControl->SetShowingPlaceHolder(true);
+ if (!HasSelection())
+ {
+ aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER);
+ }
+ break;
+ }
+ case SwContentControlType::CHECKBOX:
+ {
+ pContentControl->SetCheckbox(true);
+ // Ballot Box with X
+ pContentControl->SetCheckedState(u"\u2612");
+ // Ballot Box
+ pContentControl->SetUncheckedState(OUString(u"\u2610"));
+ aPlaceholder = u"\u2610";
+ break;
+ }
+ case SwContentControlType::DROP_DOWN_LIST:
+ {
+ pContentControl->SetShowingPlaceHolder(true);
+ if (!HasSelection())
+ {
+ aPlaceholder = SwResId(STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER);
+ }
+ SwContentControlListItem aListItem;
+ aListItem.m_aValue = aPlaceholder;
+ pContentControl->SetListItems({ aListItem });
+ break;
+ }
+ case SwContentControlType::PICTURE:
+ {
+ // Set up the picture content control.
+ pContentControl->SetShowingPlaceHolder(true);
+ pContentControl->SetPicture(true);
+
+ // Create the placeholder bitmap.
+ BitmapEx aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP);
+ Color aColor = SvtOptionsDrawinglayer::getHilightColor();
+ aColor.IncreaseLuminance(255 * 0.75);
+ aBitmap.Erase(aColor);
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME));
+ StartUndo(SwUndoId::INSERT, &aRewriter);
+ LockPaint();
+ StartAction();
+ InsertGraphic(OUString(), OUString(), aBitmap, nullptr, RndStdIds::FLY_AS_CHAR);
+
+ // Set properties on the bitmap.
+ SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE> aSet(GetDoc()->GetAttrPool());
+ GetFlyFrameAttr(aSet);
+ SwFormatFrameSize aSize(SwFrameSize::Fixed, 3000, 3000);
+ aSet.Put(aSize);
+ SetFlyFrameAttr(aSet);
+ SwFrameFormat* pFrameFormat = GetFlyFrameFormat();
+ EndAction();
+ UnlockPaint();
+ EndUndo();
+
+ // Go after the anchor position.
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ {
+ SwCursor* pCursor = getShellCursor(true);
+ pCursor->DeleteMark();
+ const SwPosition* pAnchor = pFrameFormat->GetAnchor().GetContentAnchor();
+ pCursor->GetPoint()->nContent = pAnchor->nContent;
+ ++pCursor->GetPoint()->nContent;
+ }
+
+ // Select before the anchor position.
+ Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false);
+ break;
+ }
+ case SwContentControlType::DATE:
+ {
+ pContentControl->SetShowingPlaceHolder(true);
+ pContentControl->SetDate(true);
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+ sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE);
+ const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
+ pContentControl->SetDateFormat(pFormat->GetFormatstring());
+ pContentControl->SetDateLanguage(LanguageTag(pFormat->GetLanguage()).getBcp47());
+ if (!HasSelection())
+ {
+ aPlaceholder = SwResId(STR_DATE_CONTENT_CONTROL_PLACEHOLDER);
+ }
+ break;
+ }
+ }
+ if (aPlaceholder.getLength())
+ {
+ Insert(aPlaceholder);
+ Left(CRSR_SKIP_CHARS, /*bSelect=*/true, aPlaceholder.getLength(),
+ /*bBasicCall=*/false);
+ }
+ SwFormatContentControl aContentControl(pContentControl, RES_TXTATR_CONTENTCONTROL);
+ SetAttrItem(aContentControl);
+}
+
+// Insert footnote
+// rStr - optional footnote mark
+
+void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ if(HasSelection())
+ {
+ //collapse cursor to the end
+ if(!IsCursorPtAtEnd())
+ SwapPam();
+ ClearMark();
+ }
+ SwPosition aPos = *GetCursor()->GetPoint();
+ SwFormatFootnote aFootNote( bEndNote );
+ if(!rStr.isEmpty())
+ aFootNote.SetNumStr( rStr );
+
+ SetAttrItem(aFootNote);
+
+ if( bEdit )
+ {
+ // For editing the footnote text.
+ Left(CRSR_SKIP_CHARS, false, 1, false );
+ GotoFootnoteText();
+ }
+ m_aNavigationMgr.addEntry(aPos);
+}
+
+// tdf#141634
+static bool lcl_FoldedOutlineNodeEndOfParaSplit(SwWrtShell *pThis)
+{
+ SwTextNode* pTextNode = pThis->GetCursor()->GetNode().GetTextNode();
+ if (pTextNode && pTextNode->IsOutline())
+ {
+ bool bVisible = true;
+ pTextNode->GetAttrOutlineContentVisible(bVisible);
+ if (!bVisible)
+ {
+ const SwNodes& rNodes = pThis->GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+ SwOutlineNodes::size_type nPos;
+ (void) rOutlineNodes.Seek_Entry(pTextNode, &nPos);
+
+ SwNode* pSttNd = rOutlineNodes[nPos];
+
+ // determine end node of folded outline content
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ if (pThis->GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
+ {
+ // get the next outline node after the folded outline content (iPos)
+ // it is the next outline node with the same level or less
+ int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
+ SwOutlineNodes::size_type iPos = nPos;
+ while (++iPos < rOutlineNodes.size() &&
+ rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel);
+
+ // get the correct end node
+ // the outline node may be in frames, headers, footers special section of doc model
+ SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
+ while (pStartOfSectionNodeSttNd->StartOfSectionNode()
+ != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
+ }
+ pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
+
+ if (iPos < rOutlineNodes.size())
+ {
+ SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
+ while (pStartOfSectionNode->StartOfSectionNode()
+ != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
+ }
+ if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
+ pEndNd = rOutlineNodes[iPos];
+ }
+ }
+
+ // table, text box, header, footer
+ if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
+ {
+ // insert before section end node
+ if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
+ {
+ SwNodeIndex aIdx(*pSttNd->EndOfSectionNode());
+ while (aIdx.GetNode().IsEndNode())
+ --aIdx;
+ ++aIdx;
+ pEndNd = &aIdx.GetNode();
+ }
+ }
+ // if pSttNd isn't in table but pEndNd is then insert after table
+ else if (pEndNd->GetTableBox())
+ {
+ pEndNd = pEndNd->FindTableNode();
+ SwNodeIndex aIdx(*pEndNd, -1);
+ // account for nested tables
+ while (aIdx.GetNode().GetTableBox())
+ {
+ pEndNd = aIdx.GetNode().FindTableNode();
+ aIdx.Assign(*pEndNd, -1);
+ }
+ aIdx.Assign(*pEndNd->EndOfSectionNode(), +1);
+ pEndNd = &aIdx.GetNode();
+ }
+ // end node determined
+
+ // now insert the new outline node
+ SwDoc* pDoc = pThis->GetDoc();
+
+ // insert at end of tablebox doesn't work correct without
+ MakeAllOutlineContentTemporarilyVisible a(pDoc);
+
+ SwTextNode* pNd = pDoc->GetNodes().MakeTextNode(*pEndNd, pTextNode->GetTextColl(), true);
+
+ (void) rOutlineNodes.Seek_Entry(pNd, &nPos);
+ pThis->GotoOutline(nPos);
+
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pDoc->GetIDocumentUndoRedo().ClearRedo();
+ pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsert>(*pNd));
+ pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoFormatColl>
+ (*pNd, pNd->GetTextColl(), true, true));
+ }
+
+ pThis->SetModified();
+ return true;
+ }
+ }
+ return false;
+}
+
+// SplitNode; also, because
+// - of deleting selected content;
+// - of reset of the Cursorstack if necessary.
+
+void SwWrtShell::SplitNode( bool bAutoFormat )
+{
+ ResetCursorStack();
+ if( !CanInsert() )
+ return;
+
+ SwActContext aActContext(this);
+
+ m_rView.GetEditWin().FlushInBuffer();
+ StartUndo(SwUndoId::SPLITNODE);
+
+ bool bHasSel = HasSelection();
+ if (bHasSel)
+ DelRight();
+
+ bool bHandled = false;
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton() && IsEndPara())
+ bHandled = lcl_FoldedOutlineNodeEndOfParaSplit(this);
+
+ if (!bHandled)
+ SwFEShell::SplitNode( bAutoFormat );
+
+ EndUndo(SwUndoId::SPLITNODE);
+}
+
+// Turn on numbering
+// Parameter: Optional specification of a name for the named list;
+// this indicates a position if it is possible to convert them
+// into a number and less than nMaxRules.
+
+// To test the CharFormats at the numbering
+// external void SetNumChrFormat( SwWrtShell*, SwNumRules& );
+
+// -> #i40041#
+// Preconditions (as far as OD has figured out):
+// - <SwEditShell::HasNumber()> is false, if <bNum> is true
+// - <SwEditShell::HasBullet()> is false, if <bNum> is false
+// Behavior of method is determined by the current situation at the current
+// cursor position in the document.
+void SwWrtShell::NumOrBulletOn(bool bNum)
+{
+ // determine numbering rule found at current cursor position in the document.
+ const SwNumRule* pCurRule = GetNumRuleAtCurrCursorPos();
+
+ StartUndo(SwUndoId::NUMORNONUM);
+
+ const SwNumRule * pNumRule = pCurRule;
+
+ // - activate outline rule respectively turning on outline rule for
+ // current text node. But, only for turning on a numbering (<bNum> == true).
+ // - overwrite found numbering rule at current cursor position, if
+ // no numbering rule can be retrieved from the paragraph style.
+ bool bContinueFoundNumRule( false );
+ bool bActivateOutlineRule( false );
+ int nActivateOutlineLvl( MAXLEVEL ); // only relevant, if <bActivateOutlineRule> == true
+ SwTextFormatColl * pColl = GetCurTextFormatColl();
+ if ( pColl )
+ {
+ // retrieve numbering rule at paragraph
+ // style, which is found at current cursor position in the document.
+ SwNumRule* pCollRule = mxDoc->FindNumRulePtr(pColl->GetNumRule().GetValue());
+ // #125993# - The outline numbering rule isn't allowed
+ // to be derived from a parent paragraph style to a derived one.
+ // Thus check, if the found outline numbering rule is directly
+ // set at the paragraph style <pColl>. If not, set <pCollRule> to NULL
+ if ( pCollRule && pCollRule == GetDoc()->GetOutlineNumRule() )
+ {
+ const SwNumRule* pDirectCollRule =
+ mxDoc->FindNumRulePtr(pColl->GetNumRule( false ).GetValue());
+ if ( !pDirectCollRule )
+ {
+ pCollRule = nullptr;
+ }
+ }
+
+ if ( !pCollRule )
+ {
+ pNumRule = pCollRule;
+ }
+ // no activation or continuation of outline numbering in Writer/Web document
+ else if ( bNum &&
+ !dynamic_cast<SwWebDocShell*>(GetDoc()->GetDocShell()) &&
+ pCollRule == GetDoc()->GetOutlineNumRule() )
+ {
+ if ( pNumRule == pCollRule )
+ {
+ // check, if text node at current cursor positioned is counted.
+ // If not, let it been counted. Then it has to be checked,
+ // of the outline numbering has to be activated or continued.
+ SwTextNode const*const pTextNode = sw::GetParaPropsNode(
+ *GetLayout(), GetCursor()->GetPoint()->nNode);
+ if ( pTextNode && !pTextNode->IsCountedInList() )
+ {
+ // check, if numbering of the outline level of the paragraph
+ // style is active. If not, activate this outline level.
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
+ "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
+ if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
+ pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
+ == SVX_NUM_NUMBER_NONE )
+ {
+ // activate outline numbering
+ bActivateOutlineRule = true;
+ }
+ else
+ {
+ // turning on outline numbering at current cursor position
+ bContinueFoundNumRule = true;
+ }
+ }
+ else
+ {
+ // #i101234#
+ // activate outline numbering, because from the precondition
+ // it's known, that <SwEdit::HasNumber()> == false
+ bActivateOutlineRule = true;
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ }
+ }
+ else if ( !pNumRule )
+ {
+ // #i101234#
+ // Check, if corresponding list level of the outline numbering
+ // has already a numbering format set.
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ if ( pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
+ == SVX_NUM_NUMBER_NONE )
+ {
+ // activate outline numbering, because from the precondition
+ // it's known, that <SwEdit::HasNumber()> == false
+ bActivateOutlineRule = true;
+ }
+ else
+ {
+ // turning on outline numbering at current cursor position
+ bContinueFoundNumRule = true;
+ }
+ }
+ else
+ {
+ // check, if numbering of the outline level of the paragraph
+ // style is active. If not, activate this outline level.
+ nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
+ OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
+ "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
+ if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
+ pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
+ == SVX_NUM_NUMBER_NONE )
+ {
+ // activate outline numbering
+ bActivateOutlineRule = true;
+ }
+ else
+ {
+ // turning on outline numbering at current cursor position
+ bContinueFoundNumRule = true;
+ }
+ }
+ pNumRule = pCollRule;
+ }
+ }
+
+ // Only automatic numbering/bullet rules should be changed.
+ // Note: The outline numbering rule is also an automatic one. It's only
+ // changed, if it has to be activated.
+ if ( pNumRule )
+ {
+ if ( !pNumRule->IsAutoRule() )
+ {
+ pNumRule = nullptr;
+ }
+ else if ( pNumRule == GetDoc()->GetOutlineNumRule() &&
+ !bActivateOutlineRule && !bContinueFoundNumRule )
+ {
+ pNumRule = nullptr;
+ }
+ }
+
+ // Search for a previous numbering/bullet rule to continue it.
+ OUString sContinuedListId;
+ if ( !pNumRule )
+ {
+ pNumRule = GetDoc()->SearchNumRule( *GetCursor()->GetPoint(),
+ false, bNum, false, 0,
+ sContinuedListId, GetLayout() );
+ bContinueFoundNumRule = pNumRule != nullptr;
+ }
+
+ if (pNumRule)
+ {
+ SwNumRule aNumRule(*pNumRule);
+
+ // do not change found numbering/bullet rule, if it should only be continued.
+ if ( !bContinueFoundNumRule )
+ {
+ SwTextNode const*const pTextNode = sw::GetParaPropsNode(
+ *GetLayout(), GetCursor()->GetPoint()->nNode);
+
+ if (pTextNode)
+ {
+ // use above retrieve outline level, if outline numbering has to be activated.
+ int nLevel = bActivateOutlineRule
+ ? nActivateOutlineLvl
+ : pTextNode->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
+
+ if (bNum)
+ aFormat.SetNumberingType(SVX_NUM_ARABIC);
+ else
+ {
+ // #i63395# Only apply user defined default bullet font
+ if ( numfunc::IsDefBulletFontUserDefined() )
+ {
+ const vcl::Font* pFnt = &numfunc::GetDefBulletFont();
+ aFormat.SetBulletFont( pFnt );
+ }
+ aFormat.SetBulletChar( numfunc::GetBulletChar(static_cast<sal_uInt8>(nLevel)));
+ aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ // #i93908# clear suffix for bullet lists
+ aFormat.SetPrefix(OUString());
+ aFormat.SetSuffix(OUString());
+ }
+ aNumRule.Set(o3tl::narrowing<sal_uInt16>(nLevel), aFormat);
+ }
+ }
+
+ // reset indent attribute on applying list style
+ SetCurNumRule( aNumRule, false, sContinuedListId, true );
+ }
+ else
+ {
+ // #i95907#
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ numfunc::GetDefaultPositionAndSpaceMode() );
+ SwNumRule aNumRule( GetUniqueNumRuleName(), ePosAndSpaceMode );
+ // Append the character template at the numbering.
+ SwCharFormat* pChrFormat;
+ SwDocShell* pDocSh = GetView().GetDocShell();
+ // #i63395#
+ // Only apply user defined default bullet font
+ const vcl::Font* pFnt = numfunc::IsDefBulletFontUserDefined()
+ ? &numfunc::GetDefBulletFont()
+ : nullptr;
+
+ if (bNum)
+ {
+ pChrFormat = GetCharFormatFromPool( RES_POOLCHR_NUM_LEVEL );
+ }
+ else
+ {
+ pChrFormat = GetCharFormatFromPool( RES_POOLCHR_BULLET_LEVEL );
+ }
+
+ const SwTextNode *const pTextNode = sw::GetParaPropsNode(*GetLayout(),
+ GetCursor()->GetPoint()->nNode);
+ const SwTwips nWidthOfTabs = pTextNode
+ ? pTextNode->GetWidthOfLeadingTabs()
+ : 0;
+ GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace( *GetCursor()->GetPoint() );
+
+ const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) != nullptr;
+ const bool bRightToLeft = IsInRightToLeftText();
+ for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
+ {
+ SwNumFormat aFormat( aNumRule.Get( nLvl ) );
+ aFormat.SetCharFormat( pChrFormat );
+
+ if (! bNum)
+ {
+ // #i63395#
+ // Only apply user defined default bullet font
+ if ( pFnt )
+ {
+ aFormat.SetBulletFont( pFnt );
+ }
+ aFormat.SetBulletChar( numfunc::GetBulletChar(nLvl) );
+ aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ // #i93908# clear suffix for bullet lists
+ aFormat.SetPrefix(OUString());
+ aFormat.SetSuffix(OUString());
+ }
+
+ // #i95907#
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ if(bHtml && nLvl)
+ {
+ // 1/2" for HTML
+ aFormat.SetAbsLSpace(nLvl * 720);
+ }
+ else if ( nWidthOfTabs > 0 )
+ {
+ aFormat.SetAbsLSpace(nWidthOfTabs + nLvl * 720);
+ }
+ }
+
+ // #i38904# Default alignment for
+ // numbering/bullet should be rtl in rtl paragraph:
+ if ( bRightToLeft )
+ {
+ aFormat.SetNumAdjust( SvxAdjust::Right );
+ }
+
+ aNumRule.Set( nLvl, aFormat );
+ }
+
+ // #i95907#
+ if ( pTextNode &&
+ ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+
+ const SwTwips nTextNodeIndent = pTextNode->GetAdditionalIndentForStartingNewList();
+ if ( ( nTextNodeIndent + nWidthOfTabs ) != 0 )
+ {
+ // #i111172#/fdo#85666
+ // If text node is already inside a list, assure that the indents
+ // are the same. Thus, adjust the indent change value by subtracting
+ // indents of to be applied list style.
+ SwTwips nIndentChange = nTextNodeIndent + nWidthOfTabs;
+ if ( pTextNode->GetNumRule() )
+ {
+ int nLevel = pTextNode->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ const SwNumFormat& aFormat( aNumRule.Get( nLevel ) );
+ if ( aFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nIndentChange -= aFormat.GetIndentAt() + aFormat.GetFirstLineIndent();
+ }
+ }
+ aNumRule.ChangeIndent( nIndentChange );
+ }
+ }
+ // reset indent attribute on applying list style
+ // start new list
+ SetCurNumRule( aNumRule, true, OUString(), true );
+ }
+
+ EndUndo(SwUndoId::NUMORNONUM);
+}
+// <- #i40041#
+
+void SwWrtShell::NumOn()
+{
+ NumOrBulletOn(true);
+}
+
+void SwWrtShell::NumOrBulletOff()
+{
+ const SwNumRule * pCurNumRule = GetNumRuleAtCurrCursorPos();
+
+ if (!pCurNumRule)
+ return;
+
+ if (pCurNumRule->IsOutlineRule())
+ {
+ SwNumRule aNumRule(*pCurNumRule);
+
+ SwTextNode * pTextNode =
+ sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
+
+ if (pTextNode)
+ {
+ int nLevel = pTextNode->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
+
+ aFormat.SetNumberingType(SVX_NUM_NUMBER_NONE);
+ aNumRule.Set(nLevel, aFormat);
+
+ // no start or continuation of a list - the outline style is only changed.
+ SetCurNumRule( aNumRule, false );
+ }
+ }
+ else
+ {
+ DelNumRules();
+ }
+
+ // #126346# - Cursor can not be anymore in front of
+ // a label, because numbering/bullet is switched off.
+ SetInFrontOfLabel( false );
+}
+// <- #i29560#
+
+// Request Default-Bulletlist
+
+void SwWrtShell::BulletOn()
+{
+ NumOrBulletOn(false);
+}
+
+SelectionType SwWrtShell::GetSelectionType() const
+{
+ // ContentType cannot be determined within a Start-/EndAction.
+ // Because there is no invalid value TEXT will be returned.
+ // The value does not matter, it may be updated in EndAction anyway.
+
+ if (ActionPend())
+ return IsSelFrameMode() ? SelectionType::Frame : SelectionType::Text;
+
+ SwView &_rView = const_cast<SwView&>(GetView());
+ if (_rView.GetPostItMgr() && _rView.GetPostItMgr()->HasActiveSidebarWin() )
+ return SelectionType::PostIt;
+
+ // Inserting a frame is not a DrawMode
+ SelectionType nCnt;
+ if ( !_rView.GetEditWin().IsFrameAction() &&
+ (IsObjSelected() || (_rView.IsDrawMode() && !IsFrameSelected()) ))
+ {
+ if (GetDrawView()->IsTextEdit())
+ nCnt = SelectionType::DrawObjectEditMode;
+ else
+ {
+ if (GetView().IsFormMode()) // Only Form selected
+ nCnt = SelectionType::DbForm;
+ else
+ nCnt = SelectionType::DrawObject; // Any draw object
+
+ if (_rView.IsBezierEditMode())
+ nCnt |= SelectionType::Ornament;
+ else if( GetDrawView()->GetContext() == SdrViewContext::Media )
+ nCnt |= SelectionType::Media;
+
+ if (svx::checkForSelectedCustomShapes( GetDrawView(), true /* bOnlyExtruded */ ))
+ {
+ nCnt |= SelectionType::ExtrudedCustomShape;
+ }
+
+ if (svx::checkForSelectedFontWork( GetDrawView() ))
+ {
+ nCnt |= SelectionType::FontWork;
+ }
+ }
+
+ return nCnt;
+ }
+
+ nCnt = static_cast<SelectionType>(GetCntType());
+
+ if ( IsFrameSelected() )
+ {
+ if (_rView.IsDrawMode())
+ _rView.LeaveDrawCreate(); // clean up (Bug #45639)
+ if ( !(nCnt & (SelectionType::Graphic | SelectionType::Ole)) )
+ return SelectionType::Frame;
+ }
+
+ if ( IsCursorInTable() )
+ nCnt |= SelectionType::Table;
+
+ if ( IsTableMode() )
+ {
+ nCnt |= SelectionType::Table | SelectionType::TableCell;
+ SwTable::SearchType eTableSel = GetEnhancedTableSelection();
+ if ( eTableSel == SwTable::SEARCH_ROW )
+ nCnt |= SelectionType::TableRow;
+ else if ( eTableSel == SwTable::SEARCH_COL )
+ nCnt |= SelectionType::TableCol;
+ }
+
+ // Do not pop up numbering toolbar, if the text node has a numbering of type SVX_NUM_NUMBER_NONE.
+ const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
+ if ( pNumRule )
+ {
+ const SwTextNode* pTextNd =
+ sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
+
+ if ( pTextNd && pTextNd->IsInList() )
+ {
+ int nLevel = pTextNd->GetActualListLevel();
+
+ if (nLevel < 0)
+ nLevel = 0;
+
+ if (nLevel >= MAXLEVEL)
+ nLevel = MAXLEVEL - 1;
+
+ const SwNumFormat& rFormat = pNumRule->Get(nLevel);
+ if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
+ nCnt |= SelectionType::NumberList;
+ }
+ }
+
+ return nCnt;
+}
+
+// Find the text collection with the name rCollname
+// Returns: Pointer at the collection or 0, if no
+// text collection with this name exists, or
+// this is a default template.
+
+SwTextFormatColl *SwWrtShell::GetParaStyle(const OUString &rCollName, GetStyle eCreate )
+{
+ SwTextFormatColl* pColl = FindTextFormatCollByName( rCollName );
+ if( !pColl && GETSTYLE_NOCREATE != eCreate )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCollName, SwGetPoolIdFromName::TxtColl );
+ if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
+ pColl = GetTextCollFromPool( nId );
+ }
+ return pColl;
+}
+
+// Find the text collection with the name rCollname
+// Returns: Pointer at the collection or 0, if no
+// character template with this name exists, or
+// this is a default template or template is automatic.
+
+SwCharFormat *SwWrtShell::GetCharStyle(const OUString &rFormatName, GetStyle eCreate )
+{
+ SwCharFormat* pFormat = FindCharFormatByName( rFormatName );
+ if( !pFormat && GETSTYLE_NOCREATE != eCreate )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rFormatName, SwGetPoolIdFromName::ChrFmt );
+ if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
+ pFormat = static_cast<SwCharFormat*>(GetFormatFromPool( nId ));
+ }
+ return pFormat;
+}
+
+// Find the table format with the name rFormatname
+// Returns: Pointer at the collection or 0, if no
+// frame format with this name exists or
+// this is a default format or the format is automatic.
+
+SwFrameFormat *SwWrtShell::GetTableStyle(std::u16string_view rFormatName)
+{
+ for( size_t i = GetTableFrameFormatCount(); i; )
+ {
+ SwFrameFormat *pFormat = &GetTableFrameFormat( --i );
+ if( !pFormat->IsDefault() &&
+ pFormat->GetName() == rFormatName && IsUsed( *pFormat ) )
+ return pFormat;
+ }
+ return nullptr;
+}
+
+void SwWrtShell::addCurrentPosition() {
+ SwPaM* pPaM = GetCursor();
+ m_aNavigationMgr.addEntry(*pPaM->GetPoint());
+}
+
+// Applying templates
+
+void SwWrtShell::SetPageStyle(const OUString &rCollName)
+{
+ if( !SwCursorShell::HasSelection() && !IsSelFrameMode() && !IsObjSelected() )
+ {
+ SwPageDesc* pDesc = FindPageDescByName( rCollName, true );
+ if( pDesc )
+ ChgCurPageDesc( *pDesc );
+ }
+}
+
+// Access templates
+
+OUString const & SwWrtShell::GetCurPageStyle() const
+{
+ return GetPageDesc(GetCurPageDesc( false/*bCalcFrame*/ )).GetName();
+}
+
+// Change the current template referring to the existing change.
+
+void SwWrtShell::QuickUpdateStyle()
+{
+ SwTextFormatColl *pColl = GetCurTextFormatColl();
+
+ // Default cannot be changed
+ if(pColl && !pColl->IsDefault())
+ {
+ FillByEx(pColl);
+ // Also apply the template to remove hard attribute assignment.
+ SetTextFormatColl(pColl);
+ }
+}
+
+void SwWrtShell::AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM )
+{
+ SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
+ SfxItemSetFixed<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ SID_ATTR_TABSTOP_DEFAULTS,SID_ATTR_TABSTOP_OFFSET,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
+ SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM> aCoreSet( GetAttrPool() );
+ GetPaMAttr( pCursor, aCoreSet );
+ bool bReset = false;
+ SfxItemIter aParaIter( aCoreSet );
+ for (auto pParaItem = aParaIter.GetCurItem(); pParaItem; pParaItem = aParaIter.NextItem())
+ {
+ if(!IsInvalidItem(pParaItem))
+ {
+ sal_uInt16 nWhich = pParaItem->Which();
+ if(SfxItemState::SET == aParaIter.GetItemState() &&
+ SfxItemState::SET == rStyleSet.GetItemState(nWhich))
+ {
+ aParaIter.ClearItem();
+ bReset = true;
+ }
+ }
+ }
+ StartAction();
+ if(bReset)
+ {
+ ResetAttr({}, pCursor);
+ SetAttrSet(aCoreSet, SetAttrMode::DEFAULT, pCursor);
+ }
+ mxDoc->ChgFormat(*pColl, rStyleSet );
+ EndAction();
+}
+
+void SwWrtShell::AutoUpdateFrame( SwFrameFormat* pFormat, const SfxItemSet& rStyleSet )
+{
+ StartAction();
+
+ ResetFlyFrameAttr( &rStyleSet );
+ pFormat->SetFormatAttr( rStyleSet );
+
+ EndAction();
+}
+
+void SwWrtShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar )
+{
+ ResetCursorStack();
+ if(!CanInsert())
+ return;
+
+ bool bStarted = false;
+ SwRewriter aRewriter;
+
+ if(HasSelection())
+ {
+ // Only parentheses here, because the regular insert
+ // is already clipped to the editshell
+ StartAllAction();
+
+ OUString aTmpStr1 = SwResId(STR_START_QUOTE) +
+ GetSelText() +
+ SwResId(STR_END_QUOTE);
+ OUString aTmpStr3 = SwResId(STR_START_QUOTE) +
+ OUStringChar(cChar) +
+ SwResId(STR_END_QUOTE);
+ aRewriter.AddRule( UndoArg1, aTmpStr1 );
+ aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
+ aRewriter.AddRule( UndoArg3, aTmpStr3 );
+
+ StartUndo( SwUndoId::REPLACE, &aRewriter );
+ bStarted = true;
+ DelRight(true);
+ }
+ SwEditShell::AutoCorrect( rACorr, IsInsMode(), cChar );
+
+ if(bStarted)
+ {
+ EndAllAction();
+ EndUndo( SwUndoId::REPLACE, &aRewriter );
+ }
+}
+
+// Some kind of controlled copy ctor
+
+SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell )
+ : SwFEShell(rSh, _pWin)
+ , m_rView(rShell)
+ , m_aNavigationMgr(*this)
+{
+ BITFLD_INI_LIST
+ CurrShell aCurr( this );
+
+ SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
+ SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
+
+ // place the cursor on the first field...
+ IFieldmark *pBM = nullptr;
+ if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
+ GotoFieldmark(pBM);
+ }
+}
+
+SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell,
+ const SwViewOption *pViewOpt )
+ : SwFEShell(rDoc, _pWin, pViewOpt)
+ , m_rView(rShell)
+ , m_aNavigationMgr(*this)
+{
+ BITFLD_INI_LIST
+ CurrShell aCurr( this );
+ SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
+ SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
+
+ // place the cursor on the first field...
+ IFieldmark *pBM = nullptr;
+ if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
+ GotoFieldmark(pBM);
+ }
+}
+
+SwWrtShell::~SwWrtShell()
+{
+ CurrShell aCurr( this );
+ while(IsModePushed())
+ PopMode();
+ while(PopCursor(false))
+ ;
+ SwTransferable::ClearSelection( *this );
+}
+
+bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
+{
+ ::std::unique_ptr<SwCallLink> pLink(::std::make_unique<SwCallLink>(*this));
+ return Pop(eDelete, ::std::move(pLink));
+}
+
+bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete, ::std::unique_ptr<SwCallLink> pLink)
+{
+ bool bRet = SwCursorShell::Pop(eDelete, ::std::move(pLink));
+ if( bRet && IsSelection() )
+ {
+ if (!IsAddMode())
+ {
+ m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
+ m_fnKillSel = &SwWrtShell::ResetSelect;
+ }
+ }
+ return bRet;
+}
+
+bool SwWrtShell::CanInsert()
+{
+ if(IsSelFrameMode())
+ {
+ return false;
+ }
+
+ if(IsObjSelected())
+ {
+ return false;
+ }
+
+ if(GetView().GetDrawFuncPtr())
+ {
+ return false;
+ }
+
+ if(GetView().GetPostItMgr()->GetActiveSidebarWin())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void SwWrtShell::ChgDBData(const SwDBData& aDBData)
+{
+ SwEditShell::ChgDBData(aDBData);
+ //notify the db-beamer if available
+ GetView().NotifyDBChanged();
+}
+
+OUString SwWrtShell::GetSelDescr() const
+{
+ OUString aResult;
+
+ SelectionType nSelType = GetSelectionType();
+ switch (nSelType)
+ {
+ case SelectionType::Graphic:
+ aResult = SwResId(STR_GRAPHIC);
+
+ break;
+ case SelectionType::Frame:
+ {
+ const SwFrameFormat * pFrameFormat = GetSelectedFrameFormat();
+
+ if (pFrameFormat)
+ aResult = pFrameFormat->GetDescription();
+ }
+ break;
+ case SelectionType::DrawObject:
+ {
+ aResult = SwResId(STR_DRAWING_OBJECTS);
+ }
+ break;
+ default:
+ if (mxDoc)
+ aResult = GetCursorDescr();
+ }
+
+ return aResult;
+}
+
+void SwWrtShell::ApplyViewOptions( const SwViewOption &rOpt )
+{
+ SwFEShell::ApplyViewOptions( rOpt );
+ //#i115062# invalidate meta character slot
+ GetView().GetViewFrame()->GetBindings().Invalidate( FN_VIEW_META_CHARS );
+}
+
+void SwWrtShell::SetReadonlyOption(bool bSet)
+{
+ GetView().GetEditWin().GetFrameControlsManager().SetReadonlyControls( bSet );
+ SwViewShell::SetReadonlyOption( bSet );
+}
+
+// Switch on/off header or footer of a page style - if an empty name is
+// given all styles are changed
+
+void SwWrtShell::ChangeHeaderOrFooter(
+ std::u16string_view rStyleName, bool bHeader, bool bOn, bool bShowWarning)
+{
+ SdrView *const pSdrView = GetDrawView();
+ if (pSdrView && pSdrView->IsTextEdit())
+ { // tdf#107474 deleting header may delete active drawing object
+ pSdrView->SdrEndTextEdit(true);
+ }
+ addCurrentPosition();
+ StartAllAction();
+ StartUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
+ bool bExecute = true;
+ bool bCursorSet = false;
+ for( size_t nFrom = 0, nTo = GetPageDescCnt();
+ nFrom < nTo; ++nFrom )
+ {
+ SwPageDesc aDesc( GetPageDesc( nFrom ));
+ OUString sTmp(aDesc.GetName());
+ if( rStyleName.empty() || rStyleName == sTmp )
+ {
+ bool bChgd = false;
+
+ if( bShowWarning && !bOn && GetActiveView() && GetActiveView() == &GetView() &&
+ ( (bHeader && aDesc.GetMaster().GetHeader().IsActive()) ||
+ (!bHeader && aDesc.GetMaster().GetFooter().IsActive()) ) )
+ {
+ bShowWarning = false;
+ //Actions have to be closed while the dialog is showing
+ EndAllAction();
+
+ weld::Window* pParent = GetView().GetFrameWeld();
+ short nResult;
+ if (bHeader) {
+ nResult = DeleteHeaderDialog(pParent).run();
+ } else {
+ nResult = DeleteFooterDialog(pParent).run();
+ }
+
+ bExecute = nResult == RET_YES;
+ StartAllAction();
+ if (nResult == RET_YES)
+ ToggleHeaderFooterEdit();
+ }
+ if( bExecute )
+ {
+ bChgd = true;
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ if(bHeader)
+ rMaster.SetFormatAttr( SwFormatHeader( bOn ));
+ else
+ rMaster.SetFormatAttr( SwFormatFooter( bOn ));
+ if( bOn )
+ {
+ constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
+ SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm, bHeader ? constTwips_5mm : 0, RES_UL_SPACE );
+ SwFrameFormat* pFormat = bHeader ?
+ const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
+ const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
+ pFormat->SetFormatAttr( aUL );
+ XFillStyleItem aFill(drawing::FillStyle_NONE);
+ pFormat->SetFormatAttr(aFill);
+ }
+ }
+ if( bChgd )
+ {
+ ChgPageDesc( nFrom, aDesc );
+
+ if( !bCursorSet && bOn )
+ {
+ if ( !IsHeaderFooterEdit() )
+ ToggleHeaderFooterEdit();
+ bCursorSet = SetCursorInHdFt(
+ rStyleName.empty() ? SIZE_MAX : nFrom,
+ bHeader );
+ }
+ }
+ }
+ }
+ EndUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
+ EndAllAction();
+}
+
+void SwWrtShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow )
+{
+ SwViewShell::SetShowHeaderFooterSeparator( eControl, bShow );
+ if ( !bShow )
+ GetView().GetEditWin().GetFrameControlsManager().HideControls( eControl );
+}
+
+void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq)
+{
+ SwPostItField* pPostIt = dynamic_cast<SwPostItField*>(rFieldMgr.GetCurField());
+ bool bNew = !(pPostIt && pPostIt->GetTyp()->Which() == SwFieldIds::Postit);
+ if (bNew || GetView().GetPostItMgr()->IsAnswer())
+ {
+ const SvxPostItAuthorItem* pAuthorItem = rReq.GetArg<SvxPostItAuthorItem>(SID_ATTR_POSTIT_AUTHOR);
+ OUString sAuthor;
+ if ( pAuthorItem )
+ sAuthor = pAuthorItem->GetValue();
+ else
+ {
+ std::size_t nAuthor = SW_MOD()->GetRedlineAuthor();
+ sAuthor = SW_MOD()->GetRedlineAuthor(nAuthor);
+ }
+
+ const SvxPostItTextItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
+ OUString sText;
+ if ( pTextItem )
+ sText = pTextItem->GetValue();
+
+ // If we have a text already registered for answer, use that
+ if (GetView().GetPostItMgr()->IsAnswer() && !GetView().GetPostItMgr()->GetAnswerText().isEmpty())
+ {
+ sText = GetView().GetPostItMgr()->GetAnswerText();
+ GetView().GetPostItMgr()->RegisterAnswerText(OUString());
+ }
+
+ if ( HasSelection() && !IsTableMode() )
+ {
+ KillPams();
+ }
+
+ // #i120513# Inserting a comment into an autocompletion crashes
+ // --> suggestion has to be removed before
+ GetView().GetEditWin().StopQuickHelp();
+
+ SwInsertField_Data aData(SwFieldTypesEnum::Postit, 0, sAuthor, sText, 0);
+
+ if (IsSelFrameMode())
+ {
+ SwFlyFrame* pFly = GetSelectedFlyFrame();
+
+ // Remember the anchor of the selected object before deletion.
+ std::unique_ptr<SwPosition> pAnchor;
+ if (pFly)
+ {
+ SwFrameFormat* pFormat = pFly->GetFormat();
+ if (pFormat)
+ {
+ RndStdIds eAnchorId = pFormat->GetAnchor().GetAnchorId();
+ if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR) && pFormat->GetAnchor().GetContentAnchor())
+ {
+ pAnchor.reset(new SwPosition(*pFormat->GetAnchor().GetContentAnchor()));
+ }
+ }
+ }
+
+ // A frame is selected, end frame selection.
+ EnterStdMode();
+ GetView().AttrChangedNotify(nullptr);
+
+ // Set up text selection, so the anchor of the frame will be the anchor of the
+ // comment.
+ if (pFly)
+ {
+ if (pAnchor)
+ *GetCurrentShellCursor().GetPoint() = *pAnchor;
+ SwFrameFormat* pFormat = pFly->GetFormat();
+ if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+ {
+ Right(CRSR_SKIP_CELLS, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true);
+ }
+ else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
+ {
+ aData.m_pAnnotationRange.reset(new SwPaM(*GetCurrentShellCursor().Start(),
+ *GetCurrentShellCursor().End()));
+ }
+ }
+ }
+
+ rFieldMgr.InsertField( aData );
+
+ Push();
+ SwCursorShell::Left(1, CRSR_SKIP_CHARS);
+ pPostIt = static_cast<SwPostItField*>(rFieldMgr.GetCurField());
+ Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
+ }
+
+ // Client has disabled annotations rendering, no need to
+ // focus the postit field
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ return;
+
+ if (pPostIt)
+ {
+ SwFieldType* pType = GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
+ if(auto pFormat = pType->FindFormatForField(pPostIt))
+ pFormat->Broadcast( SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::FOCUS, &GetView() ) );
+ }
+}
+
+bool SwWrtShell::IsOutlineContentVisible(const size_t nPos)
+{
+ const SwOutlineNodes& rOutlineNodes = GetDoc()->GetNodes().GetOutLineNds();
+ const SwNode* pOutlineNode = rOutlineNodes[nPos];
+
+ // no layout frame means outline folding is set to include sub levels and the outline node has
+ // a parent outline node with outline content visible attribute false (folded outline content)
+ if (!pOutlineNode->GetTextNode()->getLayoutFrame(nullptr))
+ return false;
+
+ // try the next node to determine if this outline node has visible content
+ SwNodeIndex aIdx(*pOutlineNode, +1);
+ if (&aIdx.GetNode() == &aIdx.GetNodes().GetEndOfContent()) // end of regular content
+ return false;
+
+ if (aIdx.GetNode().IsTextNode() || aIdx.GetNode().IsTableNode() ||
+ aIdx.GetNode().IsSectionNode())
+ {
+ // * sublevels treated as outline content
+ // If next node (aIdx) doesn't have a layout frame
+ // then this outline node does not have visible outline content.
+ // * sublevels NOT treated as outline content
+ // If the next node (aIdx) is the next outline node
+ // then return the outline content visible attribute value.
+ if (!GetViewOptions()->IsTreatSubOutlineLevelsAsContent() &&
+ nPos + 1 < rOutlineNodes.size() &&
+ rOutlineNodes[nPos + 1] == &aIdx.GetNode())
+ return GetAttrOutlineContentVisible(nPos);
+
+ if (aIdx.GetNode().IsTextNode())
+ return aIdx.GetNode().GetTextNode()->getLayoutFrame(nullptr);
+ if (aIdx.GetNode().IsTableNode())
+ {
+ SwTable& rTable = aIdx.GetNode().GetTableNode()->GetTable();
+ return rTable.HasLayout();
+ }
+ if (aIdx.GetNode().IsSectionNode())
+ {
+ const SwSectionFormat* pFormat =
+ aIdx.GetNode().GetSectionNode()->GetSection().GetFormat();
+ if (!pFormat)
+ return false;
+ SwPtrMsgPoolItem aAskItem(RES_CONTENT_VISIBLE, nullptr);
+ pFormat->GetInfo(aAskItem);
+ return aAskItem.pObject;
+ }
+ }
+
+ return true;
+}
+
+void SwWrtShell::MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible)
+{
+ const SwNodes& rNodes = GetNodes();
+ const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+
+ SwNode* pSttNd = rOutlineNodes[nPos];
+
+ // determine end node
+ SwNode* pEndNd = &rNodes.GetEndOfContent();
+ if (rOutlineNodes.size() > nPos + 1)
+ pEndNd = rOutlineNodes[nPos + 1];
+
+ if (GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
+ {
+ // get the last outline node to include (iPos)
+ int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
+ SwOutlineNodes::size_type iPos = nPos;
+ while (++iPos < rOutlineNodes.size() &&
+ rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel);
+
+ // get the correct end node
+ // the outline node may be in frames, headers, footers special section of doc model
+ SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
+ while (pStartOfSectionNodeSttNd->StartOfSectionNode()
+ != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
+ }
+ pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
+
+ if (iPos < rOutlineNodes.size())
+ {
+ SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
+ while (pStartOfSectionNode->StartOfSectionNode()
+ != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
+ {
+ pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
+ }
+ if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
+ pEndNd = rOutlineNodes[iPos];
+ }
+ }
+
+ // table, text box, header, footer
+ if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
+ {
+ // limit to within section
+ if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
+ pEndNd = pSttNd->EndOfSectionNode();
+ }
+ // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table
+ else if (pEndNd->GetTableBox())
+ {
+ pEndNd = &rNodes.GetEndOfContent();
+ for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++)
+ {
+ if (!(rOutlineNodes[nOutlinePos]->GetTableBox()))
+ {
+ pEndNd = rOutlineNodes[nOutlinePos];
+ break;
+ }
+ }
+ }
+ // end node determined
+
+ // Remove content frames from the next node after the starting outline node to
+ // the determined ending node. Always do this to prevent the chance of duplicate
+ // frames being made. They will be remade below if needed.
+ SwNodeIndex aIdx(*pSttNd, +1);
+ while (aIdx != *pEndNd)
+ {
+ SwNode* pNd = &aIdx.GetNode();
+ if (pNd->IsContentNode())
+ pNd->GetContentNode()->DelFrames(nullptr);
+ else if (pNd->IsTableNode())
+ pNd->GetTableNode()->DelFrames(nullptr);
+ aIdx++;
+ }
+
+ if (bMakeVisible) // make outline nodes outline content visible
+ {
+ // reset the index marker and make frames
+ aIdx.Assign(*pSttNd, +1);
+ MakeFrames(GetDoc(), aIdx, *pEndNd);
+
+ pSttNd->GetTextNode()->SetAttrOutlineContentVisible(true);
+
+ // make outline content made visible that have outline visible attribute false not visible
+ while (aIdx != *pEndNd)
+ {
+ SwNode* pNd = &aIdx.GetNode();
+ if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline())
+ {
+ SwTextNode* pTextNd = pNd->GetTextNode();
+ bool bOutlineContentVisibleAttr = true;
+ pTextNd->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
+ if (!bOutlineContentVisibleAttr)
+ {
+ SwOutlineNodes::size_type iPos;
+ if (rOutlineNodes.Seek_Entry(pTextNd, &iPos))
+ {
+ if (pTextNd->getLayoutFrame(nullptr))
+ MakeOutlineContentVisible(iPos, false);
+ }
+ }
+ }
+ aIdx++;
+ }
+ }
+ else
+ pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false);
+}
+
+// make content visible or not visible only if needed
+void SwWrtShell::InvalidateOutlineContentVisibility()
+{
+ GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
+
+ const SwOutlineNodes& rOutlineNds = GetNodes().GetOutLineNds();
+ for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos)
+ {
+ bool bIsOutlineContentVisible = IsOutlineContentVisible(nPos);
+ bool bOutlineContentVisibleAttr = true;
+ rOutlineNds[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
+ if (!bIsOutlineContentVisible && bOutlineContentVisibleAttr)
+ MakeOutlineContentVisible(nPos);
+ else if (bIsOutlineContentVisible && !bOutlineContentVisibleAttr)
+ MakeOutlineContentVisible(nPos, false);
+ }
+}
+
+void SwWrtShell::MakeAllFoldedOutlineContentVisible(bool bMakeVisible)
+{
+ // deselect any drawing or frame and leave editing mode
+ SdrView* pSdrView = GetDrawView();
+ if (pSdrView && pSdrView->IsTextEdit() )
+ {
+ bool bLockView = IsViewLocked();
+ LockView(true);
+ EndTextEdit();
+ LockView(bLockView);
+ }
+
+ if (IsSelFrameMode() || IsObjSelected())
+ {
+ UnSelectFrame();
+ LeaveSelFrameMode();
+ GetView().LeaveDrawCreate();
+ EnterStdMode();
+ DrawSelChanged();
+ GetView().StopShellTimer();
+ }
+ else
+ EnterStdMode();
+
+ SwOutlineNodes::size_type nPos = GetOutlinePos();
+
+ if (bMakeVisible)
+ {
+ // make all content visible
+
+ // When shortcut is assigned to the show outline content visibility button and used to
+ // toggle the feature and the mouse pointer is on an outline frame the button will not
+ // be removed. An easy way to make sure the button does not remain shown is to use the
+ // HideControls function.
+ GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
+
+ // temporarily set outline content visible attribute true for folded outline nodes
+ std::vector<SwNode*> aFoldedOutlineNodeArray;
+ for (SwNode* pNd: GetNodes().GetOutLineNds())
+ {
+ bool bOutlineContentVisibleAttr = true;
+ pNd->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr);
+ if (!bOutlineContentVisibleAttr)
+ {
+ aFoldedOutlineNodeArray.push_back(pNd);
+ pNd->GetTextNode()->SetAttrOutlineContentVisible(true);
+ }
+ }
+
+ StartAction();
+ InvalidateOutlineContentVisibility();
+ EndAction();
+
+ // restore outline content visible attribute for folded outline nodes
+ for (SwNode* pNd: aFoldedOutlineNodeArray)
+ pNd->GetTextNode()->SetAttrOutlineContentVisible(false);
+ }
+ else
+ {
+ StartAction();
+ InvalidateOutlineContentVisibility();
+ EndAction();
+
+ // If needed, find visible outline node to place cursor.
+ if (nPos != SwOutlineNodes::npos && !IsOutlineContentVisible(nPos))
+ {
+ while (nPos != SwOutlineNodes::npos && !GetNodes().GetOutLineNds()[nPos]->GetTextNode()->getLayoutFrame(nullptr))
+ --nPos;
+ if (nPos != SwOutlineNodes::npos)
+ GotoOutline(nPos);
+ }
+ }
+ GetView().GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
+}
+
+bool SwWrtShell::GetAttrOutlineContentVisible(const size_t nPos)
+{
+ bool bVisibleAttr = true;
+ GetNodes().GetOutLineNds()[nPos]->GetTextNode()->GetAttrOutlineContentVisible(bVisibleAttr);
+ return bVisibleAttr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */