/* -*- 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 <svx/dialogs.hrc>
#include <math.h>
#include <hintids.hxx>
#include <sot/exchange.hxx>
#include <svx/hdft.hxx>
#include <svx/svdview.hxx>
#include <svl/itemiter.hxx>
#include <tools/bigint.hxx>
#include <svtools/insdlg.hxx>
#include <sfx2/frmdescr.hxx>
#include <sfx2/ipclient.hxx>
#include <svtools/ehdl.hxx>
#include <svtools/soerr.hxx>
#include <unotools/moduleoptions.hxx>
#include <editeng/sizeitem.hxx>
#include <editeng/formatbreakitem.hxx>
#include <editeng/svxacorr.hxx>
#include <editeng/ulspitem.hxx>
#include <vcl/graph.hxx>
#include <sfx2/printer.hxx>
#include <unotools/charclass.hxx>
#include <comphelper/storagehelper.hxx>
#include <svx/svxdlg.hxx>
#include <svx/extrusionbar.hxx>
#include <svx/fontworkbar.hxx>
#include <frmfmt.hxx>
#include <fmtftn.hxx>
#include <fmthdft.hxx>
#include <fmtpdsc.hxx>
#include <wdocsh.hxx>
#include <basesh.hxx>
#include <swmodule.hxx>
#include <wrtsh.hxx>
#include <view.hxx>
#include <uitool.hxx>
#include <cmdid.h>
#include <cfgitems.hxx>
#include <pagedesc.hxx>
#include <frmmgr.hxx>
#include <shellio.hxx>
#include <uinums.hxx>
#include <swundo.hxx>
#include <swcli.hxx>
#include <poolfmt.hxx>
#include <wview.hxx>
#include <edtwin.hxx>
#include <fmtcol.hxx>
#include <swtable.hxx>
#include <caption.hxx>
#include <viscrs.hxx>
#include <swdtflvr.hxx>
#include <doc.hxx>
#include <IDocumentSettingAccess.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>
// -> #111827#
#include <SwRewriter.hxx>
#include <strings.hrc>
// <- #111827#
#include <toolkit/helper/vclunohelper.hxx>
#include <sfx2/viewfrm.hxx>
#include <PostItMgr.hxx>
#include <FrameControlsManager.hxx>
#include <sfx2/msgpool.hxx>
#include <svtools/embedhlp.hxx>
#include <memory>
using namespace sw::mark;
using namespace com::sun::star;
#define COMMON_INI_LIST \
m_fnDrag(&SwWrtShell::BeginDrag),\
m_fnSetCursor(&SwWrtShell::SetCursor),\
m_fnEndDrag(&SwWrtShell::DefaultEndDrag),\
m_fnKillSel(&SwWrtShell::Ignore),\
m_pModeStack(nullptr), \
m_ePageMove(MV_NO),\
m_rView(rShell),\
m_aNavigationMgr(*this), \
m_bDestOnStack(false)
#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::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() )
{
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;
aTmpStr += SwResId(STR_START_QUOTE);
aTmpStr += rStr;
aTmpStr += SwResId(STR_END_QUOTE);
aRewriter.AddRule(UndoArg3, aTmpStr);
}
StartUndo(SwUndoId::REPLACE, &aRewriter);
bStarted = true;
bDeleted = DelRight();
}
bCallIns ?
SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
if( bStarted )
{
EndAllAction();
EndUndo();
}
}
// Maximum height limit not possible, because the maximum height
// of the current frame can not be obtained.
void SwWrtShell::Insert( 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 );
// 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(567);
aSz.setHeight( 567);
pFrameMgr->SetSize( aSz );
}
else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
bSetGrfSize = false;
pFrameMgr->SetHeightSizeType(ATT_FIX_SIZE);
}
// Insert the graphic
SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
if ( bOwnMgr )
pFrameMgr->UpdateAttrMgr();
if( bSetGrfSize )
{
Size aGrfSize, aBound = GetGraphicDefaultSize();
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() );
SAL_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(".uno:");
aCmd += pSlot->GetUnoName();
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
vcl::Window* pWin = GetWin();
ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(pWin ? pWin->GetFrameWeld() : nullptr,
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 )
{
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 an 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::makeAny( aMathData ) );
bActivate = false;
}
catch (const uno::Exception&)
{
}
}
}
}
DelRight();
}
if ( !bStarMath )
SwFEShell::SplitNode( false, false );
EnterSelFrameMode();
SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE );
aFrameMgr.SetHeightSizeType(ATT_FIX_SIZE);
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(), uno::UNO_QUERY );
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::makeAny( false ) );
xProps->setPropertyValue("DisableComplexChartTypes",
uno::makeAny( 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);
return bActivate;
}
// The current selected OLE object will be loaded with the
// verb into the server.
void SwWrtShell::LaunchOLEObj( long nVerb )
{
if ( GetCntType() == CNT_OLE &&
!GetView().GetViewFrame()->GetFrame().IsInPlace() )
{
svt::EmbeddedObjectRef& xRef = GetOLEObject();
OSL_ENSURE( xRef.is(), "OLE not found" );
SfxInPlaceClient* pCli=nullptr;
pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
if ( !pCli )
pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
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
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
{
aArea.Width ( long( aArea.Width() / pCli->GetScaleWidth() ) );
aArea.Height( long( aArea.Height() / pCli->GetScaleHeight() ) );
}
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 ::boost::optional<sal_uInt16>& oPgNum )
{
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);
}
}
// Insert hard page break;
// Selections will be overwritten
void SwWrtShell::InsertLineBreak()
{
ResetCursorStack();
if( CanInsert() )
{
if(HasSelection())
DelRight();
const sal_Unicode cIns = 0x0A;
SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
if( pACorr )
AutoCorrect( *pACorr, cIns );
else
SwWrtShell::Insert( OUString( cIns ) );
}
}
// Insert hard column break;
// Selections will be overwritten
void SwWrtShell::InsertColumnBreak()
{
SwActContext aActContext(this);
ResetCursorStack();
if( CanInsert() )
{
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);
}
}
// Insert footnote
// rStr - optional footnote mark
void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
{
ResetCursorStack();
if( CanInsert() )
{
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);
}
}
// SplitNode; also, because
// - of deleting selected content;
// - of reset of the Cursorstack if necessary.
void SwWrtShell::SplitNode( bool bAutoFormat )
{
ResetCursorStack();
if( CanInsert() )
{
SwActContext aActContext(this);
m_rView.GetEditWin().FlushInBuffer();
bool bHasSel = HasSelection();
if( bHasSel )
{
StartUndo( SwUndoId::INSERT );
DelRight();
}
SwFEShell::SplitNode( bAutoFormat );
if( bHasSel )
EndUndo( SwUndoId::INSERT );
}
}
// 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* pTextNode =
GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
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( static_cast<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( static_cast<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( static_cast<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 );
bContinueFoundNumRule = pNumRule != nullptr;
}
if (pNumRule)
{
SwNumRule aNumRule(*pNumRule);
// do not change found numbering/bullet rule, if it should only be continued.
if ( !bContinueFoundNumRule )
{
SwTextNode * pTextNode = GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
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(static_cast<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(static_cast<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_BUL_LEVEL );
}
const SwTextNode* pTextNode = GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
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)
{
if (pCurNumRule->IsOutlineRule())
{
SwNumRule aNumRule(*pCurNumRule);
SwTextNode * pTextNode =
GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
if (pTextNode)
{
int nLevel = pTextNode->GetActualListLevel();
if (nLevel < 0)
nLevel = 0;
if (nLevel >= MAXLEVEL)
nLevel = MAXLEVEL - 1;
SwNumFormat aFormat(aNumRule.Get(static_cast<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;
}
sal_uInt32 nCheckStatus = 0;
if (svx::checkForSelectedFontWork( GetDrawView(), nCheckStatus ))
{
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);
// 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 =
GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
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(const OUString &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( );
SfxItemSet aCoreSet(
GetAttrPool(),
svl::Items<
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>{});
GetPaMAttr( pCursor, aCoreSet );
bool bReset = false;
SfxItemIter aParaIter( aCoreSet );
const SfxPoolItem* pParaItem = aParaIter.FirstItem();
while( pParaItem )
{
if(!IsInvalidItem(pParaItem))
{
sal_uInt16 nWhich = pParaItem->Which();
if(SfxItemState::SET == aCoreSet.GetItemState(nWhich) &&
SfxItemState::SET == rStyleSet.GetItemState(nWhich))
{
aCoreSet.ClearItem(nWhich);
bReset = true;
}
}
pParaItem = aParaIter.NextItem();
}
StartAction();
if(bReset)
{
ResetAttr( std::set<sal_uInt16>(), 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())
{
bool bStarted = false;
SwRewriter aRewriter;
if(HasSelection())
{
// Only parentheses here, because the regular insert
// is already clipped to the editshell
StartAllAction();
OUString aTmpStr1;
aTmpStr1 += SwResId(STR_START_QUOTE);
aTmpStr1 += GetSelText();
aTmpStr1 += SwResId(STR_END_QUOTE);
OUString aTmpStr3;
aTmpStr3 += SwResId(STR_START_QUOTE);
aTmpStr3 += OUStringLiteral1(cChar);
aTmpStr3 += 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();
}
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 ),
COMMON_INI_LIST
{
BITFLD_INI_LIST
SET_CURR_SHELL( 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),
COMMON_INI_LIST
{
BITFLD_INI_LIST
SET_CURR_SHELL( 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()
{
SET_CURR_SHELL( this );
while(IsModePushed())
PopMode();
while(PopCursor(false))
;
SwTransferable::ClearSelection( *this );
}
bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
{
bool bRet = SwCursorShell::Pop(eDelete);
if( bRet && IsSelection() )
{
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.get())
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(
const OUString& 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.isEmpty() || 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().GetViewFrame()->GetWindow().GetFrameWeld();
short nResult;
if (bHeader) {
nResult = DeleteHeaderDialog(pParent).run();
} else {
nResult = DeleteFooterDialog(pParent).run();
}
bExecute = nResult == RET_YES;
StartAllAction();
}
if( bExecute )
{
bChgd = true;
SwFrameFormat &rMaster = aDesc.GetMaster();
if(bHeader)
rMaster.SetFormatAttr( SwFormatHeader( bOn ));
else
rMaster.SetFormatAttr( SwFormatFooter( bOn ));
if( bOn )
{
SvxULSpaceItem aUL(bHeader ? 0 : MM50, bHeader ? MM50 : 0, RES_UL_SPACE );
SwFrameFormat* pFormat = bHeader ?
const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
pFormat->SetFormatAttr( aUL );
}
}
if( bChgd )
{
ChgPageDesc( nFrom, aDesc );
if( !bCursorSet && bOn )
{
if ( !IsHeaderFooterEdit() )
ToggleHeaderFooterEdit();
bCursorSet = SetCursorInHdFt(
rStyleName.isEmpty() ? 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 );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V773 Visibility scope of the 'pCli' pointer was exited without releasing the memory. A memory leak is possible.
↑ V773 The function was exited without releasing the 'pCli' pointer. A memory leak is possible.
↑ V773 Visibility scope of the 'pClient' pointer was exited without releasing the memory. A memory leak is possible.
↑ V1019 Compound assignment expression is used inside condition.