/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <config_features.h>
#include <string>
#include <stdlib.h>
#include <hintids.hxx>
#include <comphelper/string.hxx>
#include <o3tl/any.hxx>
#include <officecfg/Office/Common.hxx>
#include <vcl/graph.hxx>
#include <vcl/inputctx.hxx>
#include <basic/sbxobj.hxx>
#include <svl/eitem.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/lingucfg.hxx>
#include <unotools/useroptions.hxx>
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/printer.hxx>
#include <sfx2/request.hxx>
#include <svx/ruler.hxx>
#include <svx/srchdlg.hxx>
#include <editeng/protitem.hxx>
#include <svx/fmshell.hxx>
#include <svx/extrusionbar.hxx>
#include <svx/fontworkbar.hxx>
#include <unotxvw.hxx>
#include <cmdid.h>
#include <svl/hint.hxx>
#include <swmodule.hxx>
#include <inputwin.hxx>
#include <chartins.hxx>
#include <uivwimp.hxx>
#include <uitool.hxx>
#include <edtwin.hxx>
#include <textsh.hxx>
#include <listsh.hxx>
#include <tabsh.hxx>
#include <grfsh.hxx>
#include <mediash.hxx>
#include <docsh.hxx>
#include <frmsh.hxx>
#include <olesh.hxx>
#include <drawsh.hxx>
#include <drawbase.hxx>
#include <drformsh.hxx>
#include <drwtxtsh.hxx>
#include <beziersh.hxx>
#include <navsh.hxx>
#include <globdoc.hxx>
#include <scroll.hxx>
#include <navipi.hxx>
#include <gloshdl.hxx>
#include <usrpref.hxx>
#include <srcview.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <DocumentFieldsManager.hxx>
#include <IDocumentState.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <drawdoc.hxx>
#include <wdocsh.hxx>
#include <wview.hxx>
#include <workctrl.hxx>
#include <wrtsh.hxx>
#include <barcfg.hxx>
#include <pview.hxx>
#include <swdtflvr.hxx>
#include <cfgitems.hxx>
#include <prtopt.hxx>
#include <linguistic/lngprops.hxx>
#include <editeng/unolingu.hxx>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/scanner/ScannerContext.hpp>
#include <com/sun/star/scanner/XScannerManager2.hpp>
#include <toolkit/helper/vclunohelper.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <sax/tools/converter.hxx>
#include <formatclipboard.hxx>
#include <PostItMgr.hxx>
#include <annotsh.hxx>
#include <swruler.hxx>
#include <fldbas.hxx>
#include <unomid.h>
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <svl/cjkoptions.hxx>
#include <comphelper/propertyvalue.hxx>
#include <sfx2/lokhelper.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <svtools/embedhlp.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::scanner;
#define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
// Statics. OMG.
bool bDocSzUpdated = true;
SvxSearchItem* SwView::m_pSrchItem = nullptr;
bool SwView::m_bExtra = false;
bool SwView::m_bFound = false;
bool SwView::m_bJustOpened = false;
SearchAttrItemList* SwView::m_pSrchList = nullptr;
SearchAttrItemList* SwView::m_pReplList = nullptr;
SfxDispatcher &SwView::GetDispatcher()
{
return *GetViewFrame()->GetDispatcher();
}
void SwView::ImpSetVerb( SelectionType nSelType )
{
bool bResetVerbs = m_bVerbsActive;
if ( !GetViewFrame()->GetFrame().IsInPlace() &&
(SelectionType::Ole|SelectionType::Graphic) & nSelType )
{
if ( m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE )
{
if ( nSelType & SelectionType::Ole )
{
SetVerbs( GetWrtShell().GetOLEObject()->getSupportedVerbs() );
m_bVerbsActive = true;
bResetVerbs = false;
}
}
}
if ( bResetVerbs )
{
SetVerbs( Sequence< embed::VerbDescriptor >() );
m_bVerbsActive = false;
}
}
// Called by the SwEditWin when it gets the focus.
void SwView::GotFocus() const
{
// if we got the focus, and the form shell *is* on the top of the dispatcher
// stack, then we need to rebuild the stack (the form shell doesn't belong to
// the top then)
const SfxDispatcher& rDispatcher = const_cast< SwView* >( this )->GetDispatcher();
SfxShell* pTopShell = rDispatcher.GetShell( 0 );
FmFormShell* pAsFormShell = dynamic_cast<FmFormShell*>( pTopShell );
if ( pAsFormShell )
{
pAsFormShell->ForgetActiveControl();
const_cast< SwView* >( this )->AttrChangedNotify( m_pWrtShell.get() );
}
else if ( m_pPostItMgr )
{
SwAnnotationShell* pAsAnnotationShell = dynamic_cast<SwAnnotationShell*>( pTopShell );
if ( pAsAnnotationShell )
{
m_pPostItMgr->SetActiveSidebarWin(nullptr);
const_cast< SwView* >( this )->AttrChangedNotify( m_pWrtShell.get() );
}
}
if( GetWrtShellPtr() )
{
SwWrtShell& rWrtShell = GetWrtShell();
rWrtShell.GetDoc()->getIDocumentLayoutAccess().SetCurrentViewShell( GetWrtShellPtr() );
rWrtShell.GetDoc()->getIDocumentSettingAccess().set( DocumentSettingId::BROWSE_MODE,
rWrtShell.GetViewOptions()->getBrowseMode() );
}
}
// called by the FormShell when a form control is focused. This is
// a request to put the form shell on the top of the dispatcher stack
IMPL_LINK_NOARG(SwView, FormControlActivated, LinkParamNone*, void)
{
// if a form control has been activated, and the form shell is not on the top
// of the dispatcher stack, then we need to activate it
const SfxDispatcher& rDispatcher = GetDispatcher();
const SfxShell* pTopShell = rDispatcher.GetShell( 0 );
const FmFormShell* pAsFormShell = dynamic_cast<const FmFormShell*>( pTopShell );
if ( !pAsFormShell )
{
// if we're editing text currently, cancel this
SdrView *pSdrView = m_pWrtShell ? m_pWrtShell->GetDrawView() : nullptr;
if ( pSdrView && pSdrView->IsTextEdit() )
pSdrView->SdrEndTextEdit( true );
AttrChangedNotify( m_pWrtShell.get() );
}
}
namespace
{
uno::Reference<frame::XLayoutManager> getLayoutManager(const SfxViewFrame& rViewFrame)
{
uno::Reference<frame::XLayoutManager> xLayoutManager;
uno::Reference<beans::XPropertySet> xPropSet(rViewFrame.GetFrame().GetFrameInterface(),
uno::UNO_QUERY);
if (xPropSet.is())
{
try
{
xLayoutManager.set(xPropSet->getPropertyValue("LayoutManager"), uno::UNO_QUERY);
}
catch (const Exception& e)
{
SAL_WARN("sw.ui", "Failure getting layout manager: " + e.Message);
}
}
return xLayoutManager;
}
}
void SwView::ShowUIElement(const OUString& sElementURL) const
{
if (auto xLayoutManager = getLayoutManager(*GetViewFrame()))
{
if (!xLayoutManager->getElement(sElementURL).is())
{
xLayoutManager->createElement(sElementURL);
xLayoutManager->showElement(sElementURL);
}
}
}
void SwView::SelectShell()
{
// Attention: Maintain the SelectShell for the WebView additionally
if(m_bInDtor)
return;
// Decision if the UpdateTable has to be called
bool bUpdateTable = false;
const SwFrameFormat* pCurTableFormat = m_pWrtShell->GetTableFormat();
if(pCurTableFormat && pCurTableFormat != m_pLastTableFormat)
{
bUpdateTable = true; // can only be executed later
}
m_pLastTableFormat = pCurTableFormat;
//SEL_TBL and SEL_TBL_CELLS can be ORed!
SelectionType nNewSelectionType = (m_pWrtShell->GetSelectionType()
& ~SelectionType::TableCell);
if ( m_pFormShell && m_pFormShell->IsActiveControl() )
nNewSelectionType |= SelectionType::FormControl;
if ( nNewSelectionType == m_nSelectionType )
{
GetViewFrame()->GetBindings().InvalidateAll( false );
if ( m_nSelectionType & SelectionType::Ole ||
m_nSelectionType & SelectionType::Graphic )
// For graphs and OLE the verb can be modified of course!
ImpSetVerb( nNewSelectionType );
}
else
{
SfxDispatcher &rDispatcher = GetDispatcher();
SwToolbarConfigItem *pBarCfg = SW_MOD()->GetToolbarConfig();
if ( m_pShell )
{
rDispatcher.Flush(); // Really erase all cached shells
//Remember to the old selection which toolbar was visible
ToolbarId eId = rDispatcher.GetObjectBarId(SFX_OBJECTBAR_OBJECT);
if (eId != ToolbarId::None)
pBarCfg->SetTopToolbar(m_nSelectionType, eId);
for ( sal_uInt16 i = 0; true; ++i )
{
SfxShell *pSfxShell = rDispatcher.GetShell( i );
if ( dynamic_cast< const SwBaseShell *>( pSfxShell ) != nullptr
|| dynamic_cast< const SwDrawTextShell *>( pSfxShell ) != nullptr
|| dynamic_cast< const svx::ExtrusionBar*>( pSfxShell ) != nullptr
|| dynamic_cast< const svx::FontworkBar*>( pSfxShell ) != nullptr
|| dynamic_cast< const SwAnnotationShell *>( pSfxShell ) != nullptr
)
{
rDispatcher.Pop( *pSfxShell, SfxDispatcherPopFlags::POP_DELETE );
}
else if ( dynamic_cast< const FmFormShell *>( pSfxShell ) != nullptr )
{
rDispatcher.Pop( *pSfxShell );
}
else
break;
}
}
bool bInitFormShell = false;
if (!m_pFormShell)
{
bInitFormShell = true;
m_pFormShell = new FmFormShell( this );
m_pFormShell->SetControlActivationHandler( LINK( this, SwView, FormControlActivated ) );
StartListening(*m_pFormShell);
}
bool bSetExtInpCntxt = false;
m_nSelectionType = nNewSelectionType;
ShellMode eShellMode;
if ( !( m_nSelectionType & SelectionType::FormControl ) )
rDispatcher.Push( *m_pFormShell );
m_pShell = new SwNavigationShell( *this );
rDispatcher.Push( *m_pShell );
if ( m_nSelectionType & SelectionType::Ole )
{
eShellMode = ShellMode::Object;
m_pShell = new SwOleShell( *this );
rDispatcher.Push( *m_pShell );
}
else if ( m_nSelectionType & SelectionType::Frame
|| m_nSelectionType & SelectionType::Graphic)
{
eShellMode = ShellMode::Frame;
m_pShell = new SwFrameShell( *this );
rDispatcher.Push( *m_pShell );
if(m_nSelectionType & SelectionType::Graphic )
{
eShellMode = ShellMode::Graphic;
m_pShell = new SwGrfShell( *this );
rDispatcher.Push( *m_pShell );
}
}
else if ( m_nSelectionType & SelectionType::DrawObject )
{
eShellMode = ShellMode::Draw;
m_pShell = new SwDrawShell( *this );
rDispatcher.Push( *m_pShell );
if ( m_nSelectionType & SelectionType::Ornament )
{
eShellMode = ShellMode::Bezier;
m_pShell = new SwBezierShell( *this );
rDispatcher.Push( *m_pShell );
}
#if HAVE_FEATURE_AVMEDIA
else if( m_nSelectionType & SelectionType::Media )
{
eShellMode = ShellMode::Media;
m_pShell = new SwMediaShell( *this );
rDispatcher.Push( *m_pShell );
}
#endif
if (m_nSelectionType & SelectionType::ExtrudedCustomShape)
{
eShellMode = ShellMode::ExtrudedCustomShape;
m_pShell = new svx::ExtrusionBar(this);
rDispatcher.Push( *m_pShell );
}
if (m_nSelectionType & SelectionType::FontWork)
{
eShellMode = ShellMode::FontWork;
m_pShell = new svx::FontworkBar(this);
rDispatcher.Push( *m_pShell );
}
}
else if ( m_nSelectionType & SelectionType::DbForm )
{
eShellMode = ShellMode::DrawForm;
m_pShell = new SwDrawFormShell( *this );
rDispatcher.Push( *m_pShell );
}
else if ( m_nSelectionType & SelectionType::DrawObjectEditMode )
{
bSetExtInpCntxt = true;
eShellMode = ShellMode::DrawText;
rDispatcher.Push( *(new SwBaseShell( *this )) );
m_pShell = new SwDrawTextShell( *this );
rDispatcher.Push( *m_pShell );
}
else if ( m_nSelectionType & SelectionType::PostIt )
{
eShellMode = ShellMode::PostIt;
m_pShell = new SwAnnotationShell( *this );
rDispatcher.Push( *m_pShell );
}
else
{
bSetExtInpCntxt = true;
eShellMode = ShellMode::Text;
if ( m_nSelectionType & SelectionType::NumberList )
{
eShellMode = ShellMode::ListText;
m_pShell = new SwListShell( *this );
rDispatcher.Push( *m_pShell );
}
m_pShell = new SwTextShell(*this);
rDispatcher.Push( *m_pShell );
if ( m_nSelectionType & SelectionType::Table )
{
eShellMode = eShellMode == ShellMode::ListText ? ShellMode::TableListText
: ShellMode::TableText;
m_pShell = new SwTableShell( *this );
rDispatcher.Push( *m_pShell );
}
}
if ( m_nSelectionType & SelectionType::FormControl )
rDispatcher.Push( *m_pFormShell );
m_pViewImpl->SetShellMode(eShellMode);
ImpSetVerb( m_nSelectionType );
if( !GetDocShell()->IsReadOnly() )
{
if( bSetExtInpCntxt && GetWrtShell().HasReadonlySel() )
bSetExtInpCntxt = false;
InputContext aCntxt( GetEditWin().GetInputContext() );
aCntxt.SetOptions( bSetExtInpCntxt
? (aCntxt.GetOptions() |
( InputContextFlags::Text |
InputContextFlags::ExtText ))
: (aCntxt.GetOptions() & ~
InputContextFlags( InputContextFlags::Text |
InputContextFlags::ExtText )) );
GetEditWin().SetInputContext( aCntxt );
}
// Show Mail Merge toolbar initially for documents with Database fields
if (!m_bInitOnceCompleted && GetWrtShell().IsAnyDatabaseFieldInDoc())
ShowUIElement("private:resource/toolbar/mailmerge");
// Activate the toolbar to the new selection which also was active last time.
// Before a flush () must be, but does not affect the UI according to MBA and
// is not a performance problem.
// TODO/LATER: maybe now the Flush() command is superfluous?!
rDispatcher.Flush();
Point aPnt = GetEditWin().OutputToScreenPixel(GetEditWin().GetPointerPosPixel());
aPnt = GetEditWin().PixelToLogic(aPnt);
GetEditWin().UpdatePointer(aPnt);
SdrView* pDView = GetWrtShell().GetDrawView();
if ( bInitFormShell && pDView )
m_pFormShell->SetView(dynamic_cast<FmFormView*>( pDView) );
}
// Opportune time for the communication with OLE objects?
if ( GetDocShell()->GetDoc()->IsOLEPrtNotifyPending() )
GetDocShell()->GetDoc()->PrtOLENotify( false );
// now the table-update
if(bUpdateTable)
m_pWrtShell->UpdateTable();
GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
m_bInitOnceCompleted = true;
}
// Interaction: AttrChangedNotify() and TimeoutHdl.
// No Update if actions are still open, since the cursor on the core side
// can be somewhere in no man's land.
// But since we can no longer supply status and we want instead lock
// the dispatcher.
extern "C"
{
static int lcl_CmpIds( const void *pFirst, const void *pSecond)
{
return *static_cast<sal_uInt16 const *>(pFirst) - *static_cast<sal_uInt16 const *>(pSecond);
}
}
IMPL_LINK_NOARG(SwView, AttrChangedNotify, SwCursorShell*, void)
{
if ( GetEditWin().IsChainMode() )
GetEditWin().SetChainMode( false );
//Opt: Not if PaintLocked. During unlock a notify will be once more triggered.
if( !m_pWrtShell->IsPaintLocked() && !g_bNoInterrupt &&
GetDocShell()->IsReadOnly() )
CheckReadonlyState();
if( !m_pWrtShell->IsPaintLocked() && !g_bNoInterrupt )
CheckReadonlySelection();
if( !m_bAttrChgNotified )
{
if (m_pWrtShell->ActionPend() || g_bNoInterrupt ||
GetDispatcher().IsLocked() || //do not confuse the SFX
GetViewFrame()->GetBindings().IsInUpdate() )//do not confuse the SFX
{
m_bAttrChgNotified = true;
m_aTimer.Start();
const SfxPoolItem *pItem;
if ( SfxItemState::SET != GetObjectShell()->GetMedium()->GetItemSet()->
GetItemState( SID_HIDDEN, false, &pItem ) ||
!static_cast<const SfxBoolItem*>(pItem)->GetValue() )
{
GetViewFrame()->GetBindings().ENTERREGISTRATIONS();
m_bAttrChgNotifiedWithRegistrations = true;
}
}
else
SelectShell();
}
// change ui if cursor is at a SwPostItField
if (m_pPostItMgr)
{
// only perform the code that is needed to determine, if at the
// actual cursor position is a post-it field
m_pPostItMgr->SetShadowState( m_pWrtShell->GetPostItFieldAtCursor() );
}
}
IMPL_LINK_NOARG(SwView, TimeoutHdl, Timer *, void)
{
if (m_pWrtShell->ActionPend() || g_bNoInterrupt)
{
m_aTimer.Start();
return;
}
if ( m_bAttrChgNotifiedWithRegistrations )
{
GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
m_bAttrChgNotifiedWithRegistrations = false;
}
CheckReadonlyState();
CheckReadonlySelection();
bool bOldUndo = m_pWrtShell->DoesUndo();
m_pWrtShell->DoUndo( false );
SelectShell();
m_pWrtShell->DoUndo( bOldUndo );
m_bAttrChgNotified = false;
GetViewImpl()->GetUNOObject_Impl()->NotifySelChanged();
}
void SwView::CheckReadonlyState()
{
SfxDispatcher &rDis = GetDispatcher();
// To be able to recognize if it is already disabled!
SfxItemState eStateRO, eStateProtAll;
const SfxPoolItem *pItem;
// Query the status from a slot which is only known to us.
// Otherwise the slot is known from other; like the BasicIde
eStateRO = rDis.QueryState( FN_INSERT_BOOKMARK, pItem );
eStateProtAll = rDis.QueryState( FN_EDIT_REGION, pItem );
bool bChgd = false;
if ( !m_pWrtShell->IsCursorReadonly() )
{
static sal_uInt16 aROIds[] =
{
SID_DELETE, FN_BACKSPACE, FN_SHIFT_BACKSPACE,
SID_UNDO,
SID_REDO, SID_REPEAT, SID_PASTE,
SID_PASTE_UNFORMATTED,
SID_PASTE_SPECIAL, SID_SBA_BRW_INSERT,
SID_BACKGROUND_COLOR, FN_INSERT_BOOKMARK, SID_CHARMAP_CONTROL,
SID_CHARMAP, SID_EMOJI_CONTROL, FN_INSERT_SOFT_HYPHEN,
FN_INSERT_HARDHYPHEN, FN_INSERT_HARD_SPACE, FN_INSERT_BREAK,
FN_INSERT_LINEBREAK, FN_INSERT_COLUMN_BREAK, FN_INSERT_BREAK_DLG,
FN_DELETE_SENT, FN_DELETE_BACK_SENT, FN_DELETE_WORD,
FN_DELETE_BACK_WORD, FN_DELETE_LINE, FN_DELETE_BACK_LINE,
FN_DELETE_PARA, FN_DELETE_BACK_PARA, FN_DELETE_WHOLE_LINE,
FN_CALCULATE, FN_FORMAT_RESET,
FN_POSTIT, FN_JAVAEDIT, SID_ATTR_PARA_ADJUST_LEFT,
SID_ATTR_PARA_ADJUST_RIGHT, SID_ATTR_PARA_ADJUST_CENTER,SID_ATTR_PARA_ADJUST_BLOCK,
SID_ATTR_PARA_LINESPACE_10, SID_ATTR_PARA_LINESPACE_15, SID_ATTR_PARA_LINESPACE_20,
SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_COLOR_BACKGROUND,
SID_ATTR_CHAR_COLOR_BACKGROUND_EXT, SID_ATTR_CHAR_COLOR_EXT,
SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_WEIGHT, SID_ATTR_CHAR_POSTURE,
SID_ATTR_CHAR_OVERLINE,
SID_ATTR_CHAR_UNDERLINE, SID_ATTR_FLASH, SID_ATTR_CHAR_STRIKEOUT,
FN_UNDERLINE_DOUBLE, SID_ATTR_CHAR_CONTOUR, SID_ATTR_CHAR_SHADOWED,
SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_ESCAPEMENT, FN_SET_SUPER_SCRIPT,
FN_SET_SUB_SCRIPT, SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_LANGUAGE,
SID_ATTR_CHAR_KERNING, SID_CHAR_DLG, SID_ATTR_CHAR_WORDLINEMODE,
FN_GROW_FONT_SIZE, FN_SHRINK_FONT_SIZE, FN_TXTATR_INET,
FN_FORMAT_DROPCAPS, SID_ATTR_PARA_ADJUST, SID_ATTR_PARA_LINESPACE,
SID_ATTR_PARA_SPLIT, SID_ATTR_PARA_KEEP, SID_ATTR_PARA_WIDOWS,
SID_ATTR_PARA_ORPHANS,
SID_ATTR_PARA_MODEL, SID_PARA_DLG,
FN_SELECT_PARA, SID_DEC_INDENT,
SID_INC_INDENT
};
static bool bFirst = true;
if ( bFirst )
{
qsort( static_cast<void*>(aROIds), SAL_N_ELEMENTS(aROIds), sizeof(sal_uInt16), lcl_CmpIds );
bFirst = false;
}
if ( SfxItemState::DISABLED == eStateRO )
{
rDis.SetSlotFilter( SfxSlotFilterState::ENABLED_READONLY, aROIds );
bChgd = true;
}
}
else if( m_pWrtShell->IsAllProtect() )
{
if ( SfxItemState::DISABLED == eStateProtAll )
{
static sal_uInt16 aAllProtIds[] = { SID_SAVEDOC, FN_EDIT_REGION };
static bool bAllProtFirst = true;
if ( bAllProtFirst )
{
qsort( static_cast<void*>(aAllProtIds), SAL_N_ELEMENTS(aAllProtIds), sizeof(sal_uInt16), lcl_CmpIds );
bAllProtFirst = false;
}
rDis.SetSlotFilter( SfxSlotFilterState::ENABLED_READONLY, aAllProtIds );
bChgd = true;
}
}
else if ( SfxItemState::DISABLED != eStateRO ||
SfxItemState::DISABLED != eStateProtAll )
{
bChgd = true;
rDis.SetSlotFilter();
}
if ( bChgd )
GetViewFrame()->GetBindings().InvalidateAll(true);
}
void SwView::CheckReadonlySelection()
{
SfxDisableFlags nDisableFlags = SfxDisableFlags::NONE;
SfxDispatcher &rDis = GetDispatcher();
if( m_pWrtShell->HasReadonlySel() &&
( !m_pWrtShell->GetDrawView() ||
!m_pWrtShell->GetDrawView()->GetMarkedObjectList().GetMarkCount() ))
nDisableFlags |= SfxDisableFlags::SwOnProtectedCursor;
if( (SfxDisableFlags::SwOnProtectedCursor & nDisableFlags ) !=
(SfxDisableFlags::SwOnProtectedCursor & rDis.GetDisableFlags() ) )
{
// Additionally move at the Window the InputContext, so that
// in japanese / chinese versions the external input will be
// turned on or off. This but only if the correct shell is on
// the stack.
switch( m_pViewImpl->GetShellMode() )
{
case ShellMode::Text:
case ShellMode::ListText:
case ShellMode::TableText:
case ShellMode::TableListText:
{
// Temporary solution!!! Should set the font of the current insertion point
// at each cursor movement, so outside of this "if". But TH does not
// evaluates the font at this time and the "purchase" appears to me
// as too expensive.
// Moreover, we don't have a font, but only attributes from which the
// text formatting and the correct font will be build together.
InputContext aCntxt( GetEditWin().GetInputContext() );
aCntxt.SetOptions( SfxDisableFlags::SwOnProtectedCursor & nDisableFlags
? (aCntxt.GetOptions() & ~
InputContextFlags( InputContextFlags::Text |
InputContextFlags::ExtText ))
: (aCntxt.GetOptions() |
( InputContextFlags::Text |
InputContextFlags::ExtText )) );
GetEditWin().SetInputContext( aCntxt );
}
break;
default:
;
}
}
if( nDisableFlags != rDis.GetDisableFlags() )
{
rDis.SetDisableFlags( nDisableFlags );
GetViewFrame()->GetBindings().InvalidateAll( true );
}
}
SwView::SwView( SfxViewFrame *_pFrame, SfxViewShell* pOldSh )
: SfxViewShell( _pFrame, SWVIEWFLAGS ),
m_nNewPage(USHRT_MAX),
m_nOldPageNum(0),
m_pNumRuleNodeFromDoc(nullptr),
m_pEditWin( VclPtr<SwEditWin>::Create( &_pFrame->GetWindow(), *this ) ),
m_pShell(nullptr),
m_pFormShell(nullptr),
m_pHScrollbar(nullptr),
m_pVScrollbar(nullptr),
m_pScrollFill(VclPtr<ScrollBarBox>::Create( &_pFrame->GetWindow(), WB_SIZEABLE )),
m_pVRuler(VclPtr<SvxRuler>::Create(&GetViewFrame()->GetWindow(), m_pEditWin,
SvxRulerSupportFlags::TABS | SvxRulerSupportFlags::PARAGRAPH_MARGINS_VERTICAL|
SvxRulerSupportFlags::BORDERS | SvxRulerSupportFlags::REDUCED_METRIC,
GetViewFrame()->GetBindings(),
WB_VSCROLL | WB_EXTRAFIELD | WB_BORDER )),
m_pTogglePageBtn(nullptr),
m_pLastTableFormat(nullptr),
m_pFormatClipboard(new SwFormatClipboard()),
m_nSelectionType( SelectionType::All ),
m_nPageCnt(0),
m_nDrawSfxId( USHRT_MAX ),
m_nFormSfxId( USHRT_MAX ),
m_nLastPasteDestination( static_cast<SotExchangeDest>(0xFFFF) ),
m_nLeftBorderDistance( 0 ),
m_nRightBorderDistance( 0 ),
m_eLastSearchCommand( static_cast<SvxSearchCmd>(0xFFFF) ),
m_bWheelScrollInProgress(false),
m_bInMailMerge(false),
m_bInDtor(false),
m_bOldShellWasPagePreview(false),
m_bIsPreviewDoubleClick(false),
m_nLOKPageUpDownOffset(0)
{
static bool bRequestDoubleBuffering = getenv("VCL_DOUBLEBUFFERING_ENABLE");
if (bRequestDoubleBuffering)
m_pEditWin->RequestDoubleBuffering(true);
// According to discussion with MBA and further
// investigations, no old SfxViewShell will be set as parameter <pOldSh>,
// if function "New Window" is performed to open an additional view beside
// an already existing one.
// If the view is switch from one to another, the 'old' view is given by
// parameter <pOldSh>.
m_bCenterCursor = m_bTopCursor = m_bTabColFromDoc = m_bTabRowFromDoc =
m_bSetTabColFromDoc = m_bSetTabRowFromDoc = m_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations =
m_bVerbsActive = m_bDrawRotate = m_bInOuterResizePixel = m_bInInnerResizePixel =
m_bPasteState = m_bPasteSpecialState = m_bMakeSelectionVisible = false;
m_bShowAtResize = m_bDrawSelMode = bDocSzUpdated = true;
CreateScrollbar( true );
CreateScrollbar( false );
m_pViewImpl.reset(new SwView_Impl(this));
SetName("View");
SetWindow( m_pEditWin );
m_aTimer.SetTimeout( 120 );
SwDocShell& rDocSh = dynamic_cast<SwDocShell&>(*_pFrame->GetObjectShell());
bool bOldModifyFlag = rDocSh.IsEnableSetModified();
if (bOldModifyFlag)
rDocSh.EnableSetModified( false );
// HACK: SwDocShell has some cached font info, VCL informs about font updates,
// but loading of docs with embedded fonts happens after SwDocShell is created
// but before SwEditWin (which handles the VCL event) is created. So update
// manually.
if (rDocSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS ))
rDocSh.UpdateFontList();
bool bWebDShell = dynamic_cast<const SwWebDocShell*>(&rDocSh) != nullptr;
const SwMasterUsrPref *pUsrPref = SW_MOD()->GetUsrPref(bWebDShell);
SwViewOption aUsrPref( *pUsrPref);
//! get lingu options without loading lingu DLL
SvtLinguOptions aLinguOpt;
SvtLinguConfig().GetOptions( aLinguOpt );
aUsrPref.SetOnlineSpell( aLinguOpt.bIsSpellAuto );
bool bOldShellWasSrcView = false;
// determine if there is an existing view for
// document
SfxViewShell* pExistingSh = nullptr;
if ( pOldSh )
{
pExistingSh = pOldSh;
// determine type of existing view
if (SwPagePreview* pPagePreview = dynamic_cast<SwPagePreview *>(pExistingSh))
{
m_sSwViewData = pPagePreview->GetPrevSwViewData();
m_sNewCursorPos = pPagePreview->GetNewCursorPos();
m_nNewPage = pPagePreview->GetNewPage();
m_bOldShellWasPagePreview = true;
m_bIsPreviewDoubleClick = !m_sNewCursorPos.isEmpty() || m_nNewPage != USHRT_MAX;
}
else if (dynamic_cast<const SwSrcView *>(pExistingSh) != nullptr)
bOldShellWasSrcView = true;
}
SAL_INFO( "sw.ui", "before create WrtShell" );
if (SwView *pView = dynamic_cast<SwView*>(pExistingSh))
{
m_pWrtShell.reset(new SwWrtShell(*pView->m_pWrtShell, m_pEditWin, *this));
}
else if (SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(rDocSh.GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()))
{
m_pWrtShell.reset(new SwWrtShell(*pWrtShell, m_pEditWin, *this));
}
else
{
SwDoc& rDoc = *rDocSh.GetDoc();
if( !bOldShellWasSrcView && bWebDShell && !m_bOldShellWasPagePreview )
aUsrPref.setBrowseMode( true );
else
aUsrPref.setBrowseMode( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) );
//For the BrowseMode we do not assume a factor.
if( aUsrPref.getBrowseMode() && aUsrPref.GetZoomType() != SvxZoomType::PERCENT )
{
aUsrPref.SetZoomType( SvxZoomType::PERCENT );
aUsrPref.SetZoom( 100 );
}
if (rDocSh.IsPreview())
{
aUsrPref.SetZoomType( SvxZoomType::WHOLEPAGE );
aUsrPref.SetViewLayoutBookMode( false );
aUsrPref.SetViewLayoutColumns( 1 );
}
m_pWrtShell.reset(new SwWrtShell(rDoc, m_pEditWin, *this, &aUsrPref));
// creating an SwView from a SwPagePreview needs to
// add the SwViewShell to the ring of the other SwViewShell(s)
if(m_bOldShellWasPagePreview)
{
SwViewShell& rPreviewViewShell = *static_cast<SwPagePreview*>(pExistingSh)->GetViewShell();
m_pWrtShell->MoveTo(&rPreviewViewShell);
// to update the field command et.al. if necessary
const SwViewOption* pPreviewOpt = rPreviewViewShell.GetViewOptions();
if( pPreviewOpt->IsFieldName() != aUsrPref.IsFieldName() ||
pPreviewOpt->IsShowHiddenField() != aUsrPref.IsShowHiddenField() ||
pPreviewOpt->IsShowHiddenPara() != aUsrPref.IsShowHiddenPara() ||
pPreviewOpt->IsShowHiddenChar() != aUsrPref.IsShowHiddenChar() )
rPreviewViewShell.ApplyViewOptions(aUsrPref);
// reset design mode at draw view for form
// shell, if needed.
if ( static_cast<SwPagePreview*>(pExistingSh)->ResetFormDesignMode() &&
m_pWrtShell->HasDrawView() )
{
SdrView* pDrawView = m_pWrtShell->GetDrawView();
pDrawView->SetDesignMode( static_cast<SwPagePreview*>(pExistingSh)->FormDesignModeToReset() );
}
}
}
SAL_INFO( "sw.ui", "after create WrtShell" );
m_pHRuler = VclPtr<SwCommentRuler>::Create(m_pWrtShell.get(), &GetViewFrame()->GetWindow(), m_pEditWin,
SvxRulerSupportFlags::TABS |
SvxRulerSupportFlags::PARAGRAPH_MARGINS |
SvxRulerSupportFlags::BORDERS |
SvxRulerSupportFlags::NEGATIVE_MARGINS|
SvxRulerSupportFlags::REDUCED_METRIC,
GetViewFrame()->GetBindings(),
WB_STDRULER | WB_EXTRAFIELD | WB_BORDER);
// assure that modified state of document
// isn't reset, if document is already modified.
const bool bIsDocModified = m_pWrtShell->GetDoc()->getIDocumentState().IsModified();
// Thus among other things, the HRuler is not displayed in the read-only case.
aUsrPref.SetReadonly( m_pWrtShell->GetViewOptions()->IsReadonly() );
// no margin for OLE!
Size aBrwsBorder;
if( SfxObjectCreateMode::EMBEDDED != rDocSh.GetCreateMode() )
aBrwsBorder = GetMargin();
m_pWrtShell->SetBrowseBorder( aBrwsBorder );
// In CTOR no shell changes may take place, which must be temporarily stored
// with the timer. Otherwise, the SFX removes them from the stack!
bool bOld = g_bNoInterrupt;
g_bNoInterrupt = true;
m_pHRuler->SetActive();
m_pVRuler->SetActive();
SfxViewFrame* pViewFrame = GetViewFrame();
StartListening(*pViewFrame, DuplicateHandling::Prevent);
StartListening(rDocSh, DuplicateHandling::Prevent);
// Set Zoom-factor from HRuler
Fraction aZoomFract( aUsrPref.GetZoom(), 100 );
m_pHRuler->SetZoom( aZoomFract );
m_pVRuler->SetZoom( aZoomFract );
m_pHRuler->SetDoubleClickHdl(LINK( this, SwView, ExecRulerClick ));
FieldUnit eMetric = pUsrPref->GetHScrollMetric();
m_pHRuler->SetUnit( eMetric );
eMetric = pUsrPref->GetVScrollMetric();
m_pVRuler->SetUnit( eMetric );
m_pHRuler->SetCharWidth( 371 ); // default character width
m_pVRuler->SetLineHeight( 551 ); // default line height
// Set DocShell
m_xGlueDocShell.reset(new SwViewGlueDocShell(*this, rDocSh));
m_pPostItMgr.reset(new SwPostItMgr(this));
// Check and process the DocSize. Via the handler, the shell could not
// be found, because the shell is not known in the SFX management
// within the CTOR phase.
DocSzChgd( m_pWrtShell->GetDocSize() );
// Set AttrChangedNotify link
m_pWrtShell->SetChgLnk(LINK(this, SwView, AttrChangedNotify));
if (rDocSh.GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
!rDocSh.GetVisArea(ASPECT_CONTENT).IsEmpty())
SetVisArea(rDocSh.GetVisArea(ASPECT_CONTENT),false);
SAL_WARN_IF(
officecfg::Office::Common::Undo::Steps::get() <= 0,
"sw.ui", "/org.openoffice.Office.Common/Undo/Steps <= 0");
if (!utl::ConfigManager::IsFuzzing() && 0 < officecfg::Office::Common::Undo::Steps::get())
{
m_pWrtShell->DoUndo();
}
const bool bBrowse = m_pWrtShell->GetViewOptions()->getBrowseMode();
// Disable "multiple window"
SetNewWindowAllowed(!bBrowse);
// End of disabled multiple window
m_bVScrollbarEnabled = aUsrPref.IsViewVScrollBar();
m_bHScrollbarEnabled = aUsrPref.IsViewHScrollBar();
m_pHScrollbar->SetAuto(bBrowse);
if( aUsrPref.IsViewHRuler() )
CreateTab();
if( aUsrPref.IsViewVRuler() )
CreateVRuler();
m_pWrtShell->SetUIOptions( aUsrPref );
m_pWrtShell->SetReadOnlyAvailable( aUsrPref.IsCursorInProtectedArea() );
m_pWrtShell->ApplyAccessiblityOptions(SW_MOD()->GetAccessibilityOptions());
if( m_pWrtShell->GetDoc()->getIDocumentState().IsUpdateExpField() )
{
if (m_pWrtShell->GetDoc()->GetDocumentFieldsManager().containsUpdatableFields())
{
SET_CURR_SHELL(m_pWrtShell.get());
m_pWrtShell->StartAction();
m_pWrtShell->CalcLayout();
m_pWrtShell->GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
m_pWrtShell->EndAction();
}
m_pWrtShell->GetDoc()->getIDocumentState().SetUpdateExpFieldStat( false );
}
// Update all tables if necessary:
if( m_pWrtShell->GetDoc()->IsUpdateTOX() )
{
SfxRequest aSfxRequest( FN_UPDATE_TOX, SfxCallMode::SLOT, GetPool() );
Execute( aSfxRequest );
m_pWrtShell->GetDoc()->SetUpdateTOX( false ); // reset again
m_pWrtShell->SttEndDoc(true);
}
// No ResetModified, if there is already a view to this doc.
SfxViewFrame* pVFrame = GetViewFrame();
SfxViewFrame* pFirst = SfxViewFrame::GetFirst(&rDocSh);
// Currently(360) the view is registered firstly after the CTOR,
// the following expression is also working if this changes.
// If the modification cannot be canceled by undo, then do NOT set
// the modify back.
// no reset of modified state, if document
// was already modified.
if (!m_pWrtShell->GetDoc()->GetIDocumentUndoRedo().IsUndoNoResetModified() &&
( !pFirst || pFirst == pVFrame ) &&
!bIsDocModified )
{
m_pWrtShell->ResetModified();
}
g_bNoInterrupt = bOld;
// If a new GlobalDoc will be created, the navigator will also be generated.
if( dynamic_cast<const SwGlobalDocShell*>(&rDocSh) != nullptr &&
!pVFrame->GetChildWindow( SID_NAVIGATOR ))
{
SfxBoolItem aNavi(SID_NAVIGATOR, true);
GetDispatcher().ExecuteList(SID_NAVIGATOR, SfxCallMode::ASYNCHRON, { &aNavi });
}
uno::Reference< frame::XFrame > xFrame = pVFrame->GetFrame().GetFrameInterface();
uno::Reference< frame::XFrame > xBeamerFrame = xFrame->findFrame(
"_beamer", frame::FrameSearchFlag::CHILDREN);
if(xBeamerFrame.is())
{
SwDBData aData = m_pWrtShell->GetDBData();
SwModule::ShowDBObj( *this, aData );
}
// has anybody calls the attrchanged handler in the constructor?
if( m_bAttrChgNotifiedWithRegistrations )
{
GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
if( m_aTimer.IsActive() )
m_aTimer.Stop();
}
m_aTimer.SetInvokeHandler(LINK(this, SwView, TimeoutHdl));
m_aTimer.SetDebugName( "sw::SwView m_aTimer" );
m_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations = false;
if (bOldModifyFlag)
rDocSh.EnableSetModified();
InvalidateBorder();
if( !m_pHScrollbar->IsVisible( true ) )
ShowHScrollbar( false );
if( !m_pVScrollbar->IsVisible( true ) )
ShowVScrollbar( false );
GetViewFrame()->GetWindow().AddChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
}
SwViewGlueDocShell::SwViewGlueDocShell(SwView& rView, SwDocShell& rDocSh)
: m_rView(rView)
{
// Set DocShell
rDocSh.SetView(&m_rView);
SW_MOD()->SetView(&m_rView);
}
SwViewGlueDocShell::~SwViewGlueDocShell()
{
SwDocShell* pDocSh = m_rView.GetDocShell();
if (pDocSh && pDocSh->GetView() == &m_rView)
pDocSh->SetView(nullptr);
if (SW_MOD()->GetView() == &m_rView)
SW_MOD()->SetView(nullptr);
}
SwView::~SwView()
{
// Notify other LOK views that we are going away.
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", "false");
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", "");
SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY");
GetViewFrame()->GetWindow().RemoveChildEventListener( LINK( this, SwView, WindowChildEventListener ) );
m_pPostItMgr.reset();
m_bInDtor = true;
m_pEditWin->Hide(); // prevent problems with painting
// Set pointer in SwDocShell to the view again
m_xGlueDocShell.reset();
if( m_aTimer.IsActive() && m_bAttrChgNotifiedWithRegistrations )
GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
// the last view must end the text edit
SdrView *pSdrView = m_pWrtShell ? m_pWrtShell->GetDrawView() : nullptr;
if( pSdrView && pSdrView->IsTextEdit() )
pSdrView->SdrEndTextEdit( true );
SetWindow( nullptr );
m_pViewImpl->Invalidate();
EndListening(*GetViewFrame());
EndListening(*GetDocShell());
m_pScrollFill.disposeAndClear();
m_pWrtShell.reset(); // reset here so that it is not accessible by the following dtors.
m_pHScrollbar.disposeAndClear();
m_pVScrollbar.disposeAndClear();
m_pHRuler.disposeAndClear();
m_pVRuler.disposeAndClear();
m_pTogglePageBtn.disposeAndClear();
m_pGlosHdl.reset();
m_pViewImpl.reset();
// If this was enabled in the ctor for the frame, then disable it here.
static bool bRequestDoubleBuffering = getenv("VCL_DOUBLEBUFFERING_ENABLE");
if (bRequestDoubleBuffering)
m_pEditWin->RequestDoubleBuffering(false);
m_pEditWin.disposeAndClear();
m_pFormatClipboard.reset();
}
SwDocShell* SwView::GetDocShell()
{
SfxObjectShell* pDocShell = GetViewFrame()->GetObjectShell();
return dynamic_cast<SwDocShell*>( pDocShell );
}
// Remember CursorPos
void SwView::WriteUserData( OUString &rUserData, bool bBrowse )
{
// The browse flag will be passed from Sfx when documents are browsed
// (not to be confused with the BrowseMode).
// Then that stored data are not persistent!
const SwRect& rRect = m_pWrtShell->GetCharRect();
const tools::Rectangle& rVis = GetVisArea();
rUserData = OUString::number( rRect.Left() );
rUserData += ";";
rUserData += OUString::number( rRect.Top() );
rUserData += ";";
rUserData += OUString::number( m_pWrtShell->GetViewOptions()->GetZoom() );
rUserData += ";";
rUserData += OUString::number( rVis.Left() );
rUserData += ";";
rUserData += OUString::number( rVis.Top() );
rUserData += ";";
rUserData += OUString::number( bBrowse ? SAL_MIN_INT32 : rVis.Right());
rUserData += ";";
rUserData += OUString::number( bBrowse ? SAL_MIN_INT32 : rVis.Bottom());
rUserData += ";";
rUserData += OUString::number(
static_cast<sal_uInt16>(m_pWrtShell->GetViewOptions()->GetZoomType()));//eZoom;
rUserData += ";";
rUserData += FrameTypeFlags::NONE == m_pWrtShell->GetSelFrameType() ? OUString("0") : OUString("1");
}
// Set CursorPos
static bool lcl_IsOwnDocument( SwView& rView )
{
uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
rView.GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
uno::Reference<document::XDocumentProperties> xDocProps
= xDPS->getDocumentProperties();
OUString Created = xDocProps->getAuthor();
OUString Changed = xDocProps->getModifiedBy();
OUString FullName = SW_MOD()->GetUserOptions().GetFullName();
return (!FullName.isEmpty() &&
(!Changed.isEmpty() && Changed == FullName )) ||
(Changed.isEmpty() && !Created.isEmpty() && Created == FullName );
}
void SwView::ReadUserData( const OUString &rUserData, bool bBrowse )
{
if ( comphelper::string::getTokenCount(rUserData, ';') > 1 &&
// For document without layout only in the onlinelayout or
// while forward/backward
(!m_pWrtShell->IsNewLayout() || m_pWrtShell->GetViewOptions()->getBrowseMode() || bBrowse) )
{
bool bIsOwnDocument = lcl_IsOwnDocument( *this );
SET_CURR_SHELL(m_pWrtShell.get());
sal_Int32 nPos = 0;
// No it is *not* a good idea to call GetToken within Point constr. immediately,
// because which parameter is evaluated first?
long nX = rUserData.getToken( 0, ';', nPos ).toInt32(),
nY = rUserData.getToken( 0, ';', nPos ).toInt32();
Point aCursorPos( nX, nY );
sal_uInt16 nZoomFactor =
static_cast< sal_uInt16 >( rUserData.getToken(0, ';', nPos ).toInt32() );
long nLeft = rUserData.getToken(0, ';', nPos ).toInt32(),
nTop = rUserData.getToken(0, ';', nPos ).toInt32(),
nRight = rUserData.getToken(0, ';', nPos ).toInt32(),
nBottom= rUserData.getToken(0, ';', nPos ).toInt32();
const long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
if ( nBottom <= (m_pWrtShell->GetDocSize().Height()+nAdd) )
{
m_pWrtShell->EnableSmooth( false );
const tools::Rectangle aVis( nLeft, nTop, nRight, nBottom );
sal_Int32 nOff = 0;
SvxZoomType eZoom;
if( !m_pWrtShell->GetViewOptions()->getBrowseMode() )
eZoom = static_cast<SvxZoomType>(static_cast<sal_uInt16>(rUserData.getToken(nOff, ';', nPos ).toInt32()));
else
{
eZoom = SvxZoomType::PERCENT;
++nOff;
}
bool bSelectObj = (0 != rUserData.getToken( nOff, ';', nPos ).toInt32())
&& m_pWrtShell->IsObjSelectable( aCursorPos );
// restore editing position
m_pViewImpl->SetRestorePosition(aCursorPos, bSelectObj);
// set flag value to avoid macro execution.
bool bSavedFlagValue = m_pWrtShell->IsMacroExecAllowed();
m_pWrtShell->SetMacroExecAllowed( false );
// os: changed: The user data has to be read if the view is switched back from page preview
// go to the last editing position when opening own files
if(m_bOldShellWasPagePreview || bIsOwnDocument)
{
m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
if( bSelectObj )
{
m_pWrtShell->SelectObj( aCursorPos );
m_pWrtShell->EnterSelFrameMode( &aCursorPos );
}
}
// reset flag value
m_pWrtShell->SetMacroExecAllowed( bSavedFlagValue );
// set visible area before applying
// information from print preview. Otherwise, the applied information
// is lost.
// os: changed: The user data has to be read if the view is switched back from page preview
// go to the last editing position when opening own files
if(m_bOldShellWasPagePreview || bIsOwnDocument )
{
if ( bBrowse )
SetVisArea( aVis.TopLeft() );
else
SetVisArea( aVis );
}
//apply information from print preview - if available
if( !m_sNewCursorPos.isEmpty() )
{
long nXTmp = m_sNewCursorPos.getToken( 0, ';' ).toInt32(),
nYTmp = m_sNewCursorPos.getToken( 1, ';' ).toInt32();
Point aCursorPos2( nXTmp, nYTmp );
bSelectObj = m_pWrtShell->IsObjSelectable( aCursorPos2 );
m_pWrtShell->SwCursorShell::SetCursor( aCursorPos2 );
if( bSelectObj )
{
m_pWrtShell->SelectObj( aCursorPos2 );
m_pWrtShell->EnterSelFrameMode( &aCursorPos2 );
}
m_pWrtShell->MakeSelVisible();
m_sNewCursorPos.clear();
}
else if(USHRT_MAX != m_nNewPage)
{
m_pWrtShell->GotoPage(m_nNewPage, true);
m_nNewPage = USHRT_MAX;
}
SelectShell();
m_pWrtShell->StartAction();
const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
if( pVOpt->GetZoom() != nZoomFactor || pVOpt->GetZoomType() != eZoom )
SetZoom( eZoom, nZoomFactor);
m_pWrtShell->LockView( true );
m_pWrtShell->EndAction();
m_pWrtShell->LockView( false );
m_pWrtShell->EnableSmooth( true );
}
}
}
void SwView::ReadUserDataSequence ( const uno::Sequence < beans::PropertyValue >& rSequence )
{
if(GetDocShell()->IsPreview()||m_bIsPreviewDoubleClick)
return;
bool bIsOwnDocument = lcl_IsOwnDocument( *this );
sal_Int32 nLength = rSequence.getLength();
if (!nLength)
return;
SET_CURR_SHELL(m_pWrtShell.get());
const beans::PropertyValue *pValue = rSequence.getConstArray();
const SwRect& rRect = m_pWrtShell->GetCharRect();
const tools::Rectangle &rVis = GetVisArea();
const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
sal_Int64 nX = rRect.Left(), nY = rRect.Top(), nLeft = rVis.Left(), nTop = rVis.Top();
sal_Int64 nRight = LONG_MIN;
sal_Int64 nBottom = LONG_MIN;
sal_Int16 nZoomType = static_cast< sal_Int16 >(pVOpt->GetZoomType());
sal_Int16 nZoomFactor = static_cast < sal_Int16 > (pVOpt->GetZoom());
bool bViewLayoutBookMode = pVOpt->IsViewLayoutBookMode();
sal_Int16 nViewLayoutColumns = pVOpt->GetViewLayoutColumns();
bool bSelectedFrame = ( m_pWrtShell->GetSelFrameType() != FrameTypeFlags::NONE ),
bGotVisibleLeft = false,
bGotVisibleTop = false, bGotVisibleRight = false,
bGotVisibleBottom = false, bGotZoomType = false,
bGotZoomFactor = false, bGotIsSelectedFrame = false,
bGotViewLayoutColumns = false, bGotViewLayoutBookMode = false,
bBrowseMode = false, bGotBrowseMode = false;
for (sal_Int32 i = 0 ; i < nLength; i++)
{
if ( pValue->Name == "ViewLeft" )
{
pValue->Value >>= nX;
nX = convertMm100ToTwip( nX );
}
else if ( pValue->Name == "ViewTop" )
{
pValue->Value >>= nY;
nY = convertMm100ToTwip( nY );
}
else if ( pValue->Name == "VisibleLeft" )
{
pValue->Value >>= nLeft;
nLeft = convertMm100ToTwip( nLeft );
bGotVisibleLeft = true;
}
else if ( pValue->Name == "VisibleTop" )
{
pValue->Value >>= nTop;
nTop = convertMm100ToTwip( nTop );
bGotVisibleTop = true;
}
else if ( pValue->Name == "VisibleRight" )
{
pValue->Value >>= nRight;
nRight = convertMm100ToTwip( nRight );
bGotVisibleRight = true;
}
else if ( pValue->Name == "VisibleBottom" )
{
pValue->Value >>= nBottom;
nBottom = convertMm100ToTwip( nBottom );
bGotVisibleBottom = true;
}
else if ( pValue->Name == "ZoomType" )
{
pValue->Value >>= nZoomType;
bGotZoomType = true;
}
else if ( pValue->Name == "ZoomFactor" )
{
pValue->Value >>= nZoomFactor;
bGotZoomFactor = true;
}
else if ( pValue->Name == "ViewLayoutColumns" )
{
pValue->Value >>= nViewLayoutColumns;
bGotViewLayoutColumns = true;
}
else if ( pValue->Name == "ViewLayoutBookMode" )
{
bViewLayoutBookMode = *o3tl::doAccess<bool>(pValue->Value);
bGotViewLayoutBookMode = true;
}
else if ( pValue->Name == "IsSelectedFrame" )
{
pValue->Value >>= bSelectedFrame;
bGotIsSelectedFrame = true;
}
else if (pValue->Name == "ShowOnlineLayout")
{
pValue->Value >>= bBrowseMode;
bGotBrowseMode = true;
}
// Fallback to common SdrModel processing
else GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->ReadUserDataSequenceValue(pValue);
pValue++;
}
if (bGotBrowseMode)
{
// delegate further
GetViewImpl()->GetUNOObject_Impl()->getViewSettings()->setPropertyValue("ShowOnlineLayout", uno::Any(bBrowseMode));
}
if (bGotVisibleBottom)
{
Point aCursorPos( nX, nY );
const long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
if (nBottom <= (m_pWrtShell->GetDocSize().Height()+nAdd) )
{
m_pWrtShell->EnableSmooth( false );
const tools::Rectangle aVis( nLeft, nTop, nRight, nBottom );
SvxZoomType eZoom;
if ( !m_pWrtShell->GetViewOptions()->getBrowseMode() )
eZoom = static_cast < SvxZoomType > ( nZoomType );
else
{
eZoom = SvxZoomType::PERCENT;
}
if (bGotIsSelectedFrame)
{
bool bSelectObj = bSelectedFrame && m_pWrtShell->IsObjSelectable( aCursorPos );
// set flag value to avoid macro execution.
bool bSavedFlagValue = m_pWrtShell->IsMacroExecAllowed();
m_pWrtShell->SetMacroExecAllowed( false );
// os: changed: The user data has to be read if the view is switched back from page preview
// go to the last editing position when opening own files
m_pViewImpl->SetRestorePosition(aCursorPos, bSelectObj);
if(m_bOldShellWasPagePreview|| bIsOwnDocument)
{
m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
// Update the shell to toggle Header/Footer edit if needed
bool bInHeader = true;
if ( m_pWrtShell->IsInHeaderFooter( &bInHeader ) )
{
if ( !bInHeader )
{
m_pWrtShell->SetShowHeaderFooterSeparator( Footer, true );
m_pWrtShell->SetShowHeaderFooterSeparator( Header, false );
}
else
{
m_pWrtShell->SetShowHeaderFooterSeparator( Header, true );
m_pWrtShell->SetShowHeaderFooterSeparator( Footer, false );
}
// Force repaint
m_pWrtShell->GetWin()->Invalidate();
}
if ( m_pWrtShell->IsInHeaderFooter() != m_pWrtShell->IsHeaderFooterEdit() )
m_pWrtShell->ToggleHeaderFooterEdit();
if( bSelectObj )
{
m_pWrtShell->SelectObj( aCursorPos );
m_pWrtShell->EnterSelFrameMode( &aCursorPos );
}
}
// reset flag value
m_pWrtShell->SetMacroExecAllowed( bSavedFlagValue );
}
SelectShell();
// Set ViewLayoutSettings
const bool bSetViewLayoutSettings = bGotViewLayoutColumns && bGotViewLayoutBookMode &&
( pVOpt->GetViewLayoutColumns() != nViewLayoutColumns || pVOpt->IsViewLayoutBookMode() != bViewLayoutBookMode );
const bool bSetViewSettings = bGotZoomType && bGotZoomFactor &&
( pVOpt->GetZoom() != nZoomFactor || pVOpt->GetZoomType() != eZoom );
// In case we have a 'fixed' view layout of 2 or more columns,
// we have to apply the view options *before* starting the action.
// Otherwise the SetZoom function cannot work correctly, because
// the view layout hasn't been calculated.
const bool bZoomNeedsViewLayout = bSetViewLayoutSettings &&
1 < nViewLayoutColumns &&
bSetViewSettings &&
eZoom != SvxZoomType::PERCENT;
if ( !bZoomNeedsViewLayout )
m_pWrtShell->StartAction();
if ( bSetViewLayoutSettings )
SetViewLayout( nViewLayoutColumns, bViewLayoutBookMode, true );
if ( bZoomNeedsViewLayout )
m_pWrtShell->StartAction();
if ( bSetViewSettings )
SetZoom( eZoom, nZoomFactor, true );
// os: changed: The user data has to be read if the view is switched back from page preview
// go to the last editing position when opening own files
if(m_bOldShellWasPagePreview||bIsOwnDocument)
{
if ( bGotVisibleLeft && bGotVisibleTop )
{
Point aTopLeft(aVis.TopLeft());
// make sure the document is still centered
const SwTwips lBorder = IsDocumentBorder() ? DOCUMENTBORDER : 2 * DOCUMENTBORDER;
SwTwips nEditWidth = GetEditWin().GetOutputSize().Width();
if(nEditWidth > (m_aDocSz.Width() + lBorder ))
aTopLeft.setX( ( m_aDocSz.Width() + lBorder - nEditWidth ) / 2 );
else
{
//check if the values are possible
long nXMax = m_pHScrollbar->GetRangeMax() - m_pHScrollbar->GetVisibleSize();
if( aTopLeft.X() > nXMax )
aTopLeft.setX( nXMax < 0 ? 0 : nXMax );
}
SetVisArea( aTopLeft );
}
else if (bGotVisibleLeft && bGotVisibleTop && bGotVisibleRight && bGotVisibleBottom )
SetVisArea( aVis );
}
m_pWrtShell->LockView( true );
m_pWrtShell->EndAction();
m_pWrtShell->LockView( false );
m_pWrtShell->EnableSmooth( true );
}
}
}
void SwView::WriteUserDataSequence ( uno::Sequence < beans::PropertyValue >& rSequence )
{
const SwRect& rRect = m_pWrtShell->GetCharRect();
const tools::Rectangle& rVis = GetVisArea();
std::vector<beans::PropertyValue> aVector;
sal_uInt16 nViewID( GetViewFrame()->GetCurViewId());
aVector.push_back(comphelper::makePropertyValue("ViewId", "view" + OUString::number(nViewID)));
aVector.push_back(comphelper::makePropertyValue("ViewLeft", convertTwipToMm100 ( rRect.Left() )));
aVector.push_back(comphelper::makePropertyValue("ViewTop", convertTwipToMm100 ( rRect.Top() )));
aVector.push_back(comphelper::makePropertyValue("VisibleLeft", convertTwipToMm100 ( rVis.Left() )));
aVector.push_back(comphelper::makePropertyValue("VisibleTop", convertTwipToMm100 ( rVis.Top() )));
aVector.push_back(comphelper::makePropertyValue("VisibleRight", convertTwipToMm100 ( rVis.Right() )));
aVector.push_back(comphelper::makePropertyValue("VisibleBottom", convertTwipToMm100 ( rVis.Bottom() )));
const sal_Int16 nZoomType = static_cast< sal_Int16 >(m_pWrtShell->GetViewOptions()->GetZoomType());
aVector.push_back(comphelper::makePropertyValue("ZoomType", nZoomType));
const sal_Int16 nViewLayoutColumns = static_cast< sal_Int16 >(m_pWrtShell->GetViewOptions()->GetViewLayoutColumns());
aVector.push_back(comphelper::makePropertyValue("ViewLayoutColumns", nViewLayoutColumns));
aVector.push_back(comphelper::makePropertyValue("ViewLayoutBookMode", m_pWrtShell->GetViewOptions()->IsViewLayoutBookMode()));
aVector.push_back(comphelper::makePropertyValue("ZoomFactor", static_cast < sal_Int16 > (m_pWrtShell->GetViewOptions()->GetZoom())));
aVector.push_back(comphelper::makePropertyValue("IsSelectedFrame", FrameTypeFlags::NONE != m_pWrtShell->GetSelFrameType()));
rSequence = comphelper::containerToSequence(aVector);
// Common SdrModel processing
GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->WriteUserDataSequence(rSequence);
}
void SwView::ShowCursor( bool bOn )
{
//don't scroll the cursor into the visible area
bool bUnlockView = !m_pWrtShell->IsViewLocked();
m_pWrtShell->LockView( true ); //lock visible section
if( !bOn )
m_pWrtShell->HideCursor();
else if( !m_pWrtShell->IsFrameSelected() && !m_pWrtShell->IsObjSelected() )
m_pWrtShell->ShowCursor();
if( bUnlockView )
m_pWrtShell->LockView( false );
}
ErrCode SwView::DoVerb( long nVerb )
{
if ( !GetViewFrame()->GetFrame().IsInPlace() )
{
SwWrtShell &rSh = GetWrtShell();
const SelectionType nSel = rSh.GetSelectionType();
if ( nSel & SelectionType::Ole )
rSh.LaunchOLEObj( nVerb );
}
return ERRCODE_NONE;
}
// only return true for a text selection
bool SwView::HasSelection( bool bText ) const
{
return bText ? GetWrtShell().SwCursorShell::HasSelection()
: GetWrtShell().HasSelection();
}
OUString SwView::GetSelectionText( bool bCompleteWrds )
{
return GetSelectionTextParam( bCompleteWrds, true );
}
OUString SwView::GetSelectionTextParam( bool bCompleteWrds, bool bEraseTrail )
{
OUString sReturn;
if( bCompleteWrds && !GetWrtShell().HasSelection() )
GetWrtShell().SelWrd();
GetWrtShell().GetSelectedText( sReturn );
if( bEraseTrail )
sReturn = comphelper::string::stripEnd(sReturn, ' ');
return sReturn;
}
SwGlossaryHdl* SwView::GetGlosHdl()
{
if(!m_pGlosHdl)
m_pGlosHdl.reset(new SwGlossaryHdl(GetViewFrame(), m_pWrtShell.get()));
return m_pGlosHdl.get();
}
void SwView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
bool bCallBase = true;
if(dynamic_cast<const FmDesignModeChangedHint*>(&rHint))
{
bool bDesignMode = static_cast<const FmDesignModeChangedHint&>(rHint).GetDesignMode();
if (!bDesignMode && GetDrawFuncPtr())
{
GetDrawFuncPtr()->Deactivate();
SetDrawFuncPtr(nullptr);
LeaveDrawCreate();
AttrChangedNotify(m_pWrtShell.get());
}
}
else
{
SfxHintId nId = rHint.GetId();
switch ( nId )
{
// sub shells will be destroyed by the
// dispatcher, if the view frame is dying. Thus, reset member <pShell>.
case SfxHintId::Dying:
{
if ( &rBC == GetViewFrame() )
{
ResetSubShell();
}
}
break;
case SfxHintId::ModeChanged:
{
// Modal mode change-over?
bool bModal = GetDocShell()->IsInModalMode();
m_pHRuler->SetActive( !bModal );
m_pVRuler->SetActive( !bModal );
}
SAL_FALLTHROUGH;
case SfxHintId::TitleChanged:
if ( GetDocShell()->IsReadOnly() != GetWrtShell().GetViewOptions()->IsReadonly() )
{
SwWrtShell &rSh = GetWrtShell();
rSh.SetReadonlyOption( GetDocShell()->IsReadOnly() );
if ( rSh.GetViewOptions()->IsViewVRuler() )
CreateVRuler();
else
KillVRuler();
if ( rSh.GetViewOptions()->IsViewHRuler() )
CreateTab();
else
KillTab();
bool bReadonly = GetDocShell()->IsReadOnly();
// if document is to be opened in alive-mode then this has to be
// regarded while switching from readonly-mode to edit-mode
if( !bReadonly )
{
SwDrawModel * pDrawDoc = GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
if (pDrawDoc)
{
if( !pDrawDoc->GetOpenInDesignMode() )
break;// don't touch the design mode
}
}
SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadonly);
GetDispatcher().ExecuteList(SID_FM_DESIGN_MODE,
SfxCallMode::ASYNCHRON, { &aItem });
}
break;
case SfxHintId::SwDrawViewsCreated:
{
bCallBase = false;
if ( GetFormShell() )
{
GetFormShell()->SetView(dynamic_cast<FmFormView*>(GetWrtShell().GetDrawView()));
SfxBoolItem aItem( SID_FM_DESIGN_MODE, !GetDocShell()->IsReadOnly());
GetDispatcher().ExecuteList(SID_FM_DESIGN_MODE,
SfxCallMode::SYNCHRON, { &aItem });
}
}
break;
case SfxHintId::RedlineChanged:
{
static sal_uInt16 const aSlotRedLine[] = {
FN_REDLINE_NEXT_CHANGE,
FN_REDLINE_PREV_CHANGE,
FN_REDLINE_ACCEPT_DIRECT,
FN_REDLINE_REJECT_DIRECT,
FN_REDLINE_ACCEPT_ALL,
FN_REDLINE_REJECT_ALL,
0
};
GetViewFrame()->GetBindings().Invalidate(aSlotRedLine);
}
break;
default: break;
}
}
if ( bCallBase )
SfxViewShell::Notify(rBC, rHint);
}
#if defined(_WIN32) || defined UNX
void SwView::ScannerEventHdl()
{
uno::Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
if( xScanMgr.is() )
{
const ScannerContext aContext( xScanMgr->getAvailableScanners().getConstArray()[ 0 ] );
const ScanError eError = xScanMgr->getError( aContext );
if( ScanError_ScanErrorNone == eError )
{
const uno::Reference< awt::XBitmap > xBitmap( xScanMgr->getBitmap( aContext ) );
if( xBitmap.is() )
{
const BitmapEx aScanBmp( VCLUnoHelper::GetBitmap( xBitmap ) );
if( !!aScanBmp )
{
Graphic aGrf(aScanBmp);
m_pWrtShell->Insert( OUString(), OUString(), aGrf );
}
}
}
}
SfxBindings& rBind = GetViewFrame()->GetBindings();
rBind.Invalidate( SID_TWAIN_SELECT );
rBind.Invalidate( SID_TWAIN_TRANSFER );
}
#endif
void SwView::StopShellTimer()
{
if(m_aTimer.IsActive())
{
m_aTimer.Stop();
if ( m_bAttrChgNotifiedWithRegistrations )
{
GetViewFrame()->GetBindings().LEAVEREGISTRATIONS();
m_bAttrChgNotifiedWithRegistrations = false;
}
SelectShell();
m_bAttrChgNotified = false;
}
}
bool SwView::PrepareClose( bool bUI )
{
SfxViewFrame* pVFrame = GetViewFrame();
pVFrame->SetChildWindow( SwInputChild::GetChildWindowId(), false );
if( pVFrame->GetDispatcher()->IsLocked() )
pVFrame->GetDispatcher()->Lock(false);
if ( m_pFormShell && !m_pFormShell->PrepareClose( bUI ) )
{
return false;
}
return SfxViewShell::PrepareClose( bUI );
}
// status methods for clipboard.
// Status changes now notified from the clipboard.
bool SwView::IsPasteAllowed()
{
SotExchangeDest nPasteDestination = SwTransferable::GetSotDestination( *m_pWrtShell );
if( m_nLastPasteDestination != nPasteDestination )
{
TransferableDataHelper aDataHelper(
TransferableDataHelper::CreateFromSystemClipboard(
&GetEditWin()) );
if( aDataHelper.GetXTransferable().is() )
{
m_bPasteState = SwTransferable::IsPaste( *m_pWrtShell, aDataHelper );
m_bPasteSpecialState = SwTransferable::IsPasteSpecial(
*m_pWrtShell, aDataHelper );
}
else
m_bPasteState = m_bPasteSpecialState = false;
if( static_cast<SotExchangeDest>(0xFFFF) == m_nLastPasteDestination ) // the init value
m_pViewImpl->AddClipboardListener();
m_nLastPasteDestination = nPasteDestination;
}
return m_bPasteState;
}
bool SwView::IsPasteSpecialAllowed()
{
if ( m_pFormShell && m_pFormShell->IsActiveControl() )
return false;
SotExchangeDest nPasteDestination = SwTransferable::GetSotDestination( *m_pWrtShell );
if( m_nLastPasteDestination != nPasteDestination )
{
TransferableDataHelper aDataHelper(
TransferableDataHelper::CreateFromSystemClipboard(
&GetEditWin()) );
if( aDataHelper.GetXTransferable().is() )
{
m_bPasteState = SwTransferable::IsPaste( *m_pWrtShell, aDataHelper );
m_bPasteSpecialState = SwTransferable::IsPasteSpecial(
*m_pWrtShell, aDataHelper );
}
else
m_bPasteState = m_bPasteSpecialState = false;
if( static_cast<SotExchangeDest>(0xFFFF) == m_nLastPasteDestination ) // the init value
m_pViewImpl->AddClipboardListener();
}
return m_bPasteSpecialState;
}
void SwView::NotifyDBChanged()
{
GetViewImpl()->GetUNOObject_Impl()->NotifyDBChanged();
}
// Printing
SfxObjectShellLock SwView::CreateTmpSelectionDoc()
{
SwXTextView *const pTempImpl = GetViewImpl()->GetUNOObject_Impl();
return pTempImpl->BuildTmpSelectionDoc();
}
void SwView::AddTransferable(SwTransferable& rTransferable)
{
GetViewImpl()->AddTransferable(rTransferable);
}
namespace sw {
void InitPrintOptionsFromApplication(SwPrintData & o_rData, bool const bWeb)
{
o_rData = *SW_MOD()->GetPrtOptions(bWeb);
}
} // namespace sw
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V560 A part of conditional expression is always true: bGotVisibleBottom.