summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase/uiview
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/uibase/uiview
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/uibase/uiview')
-rw-r--r--sw/source/uibase/uiview/formatclipboard.cxx590
-rw-r--r--sw/source/uibase/uiview/pview.cxx1905
-rw-r--r--sw/source/uibase/uiview/scroll.cxx116
-rw-r--r--sw/source/uibase/uiview/srcview.cxx839
-rw-r--r--sw/source/uibase/uiview/swcli.cxx193
-rw-r--r--sw/source/uibase/uiview/uivwimp.cxx333
-rw-r--r--sw/source/uibase/uiview/view.cxx2120
-rw-r--r--sw/source/uibase/uiview/view0.cxx770
-rw-r--r--sw/source/uibase/uiview/view1.cxx213
-rw-r--r--sw/source/uibase/uiview/view2.cxx3197
-rw-r--r--sw/source/uibase/uiview/viewcoll.cxx78
-rw-r--r--sw/source/uibase/uiview/viewdlg.cxx66
-rw-r--r--sw/source/uibase/uiview/viewdlg2.cxx305
-rw-r--r--sw/source/uibase/uiview/viewdraw.cxx755
-rw-r--r--sw/source/uibase/uiview/viewfunc.hxx54
-rw-r--r--sw/source/uibase/uiview/viewling.cxx856
-rw-r--r--sw/source/uibase/uiview/viewmdi.cxx791
-rw-r--r--sw/source/uibase/uiview/viewport.cxx1262
-rw-r--r--sw/source/uibase/uiview/viewprt.cxx376
-rw-r--r--sw/source/uibase/uiview/viewsrch.cxx895
-rw-r--r--sw/source/uibase/uiview/viewstat.cxx691
-rw-r--r--sw/source/uibase/uiview/viewtab.cxx2562
22 files changed, 18967 insertions, 0 deletions
diff --git a/sw/source/uibase/uiview/formatclipboard.cxx b/sw/source/uibase/uiview/formatclipboard.cxx
new file mode 100644
index 0000000000..e722c04e90
--- /dev/null
+++ b/sw/source/uibase/uiview/formatclipboard.cxx
@@ -0,0 +1,590 @@
+/* -*- 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 <memory>
+#include <utility>
+
+#include <formatclipboard.hxx>
+
+#include <cmdid.h>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <docstyle.hxx>
+#include <fchrfmt.hxx>
+#include <svx/svdview.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <fmtlsplt.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtrowsplt.hxx>
+#include <frmatr.hxx>
+
+namespace
+{
+
+std::unique_ptr<SfxItemSet> lcl_CreateEmptyItemSet( SelectionType nSelectionType, SfxItemPool& rPool, bool bNoParagraphFormats = false )
+{
+ std::unique_ptr<SfxItemSet> pItemSet;
+ if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ {
+ pItemSet = std::make_unique<SfxItemSetFixed<
+ RES_FRMATR_BEGIN, RES_FILL_ORDER,
+ // no RES_FRM_SIZE
+ RES_PAPER_BIN, RES_SURROUND,
+ // no RES_VERT_ORIENT
+ // no RES_HORI_ORIENT
+ // no RES_ANCHOR
+ RES_BACKGROUND, RES_SHADOW,
+ // no RES_FRMMACRO
+ RES_COL, RES_KEEP,
+ // no RES_URL
+ RES_EDIT_IN_READONLY, RES_LAYOUT_SPLIT,
+ // no RES_CHAIN
+ RES_TEXTGRID, RES_FRMATR_END - 1>>(rPool);
+ }
+ else if( nSelectionType & SelectionType::DrawObject )
+ {
+ //is handled different
+ }
+ else if( nSelectionType & SelectionType::Text )
+ {
+ if( bNoParagraphFormats )
+ pItemSet = std::make_unique<SfxItemSetFixed
+ <RES_CHRATR_BEGIN, RES_CHRATR_END - 1>>(rPool);
+ else
+ pItemSet = std::make_unique<SfxItemSetFixed<
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_FILL_ORDER,
+ // no RES_FRM_SIZE
+ RES_PAPER_BIN, RES_SURROUND,
+ // no RES_VERT_ORIENT
+ // no RES_HORI_ORIENT
+ // no RES_ANCHOR
+ RES_BACKGROUND, RES_SHADOW,
+ // no RES_FRMMACRO
+ RES_COL, RES_KEEP,
+ // no RES_URL
+ RES_EDIT_IN_READONLY, RES_LAYOUT_SPLIT,
+ // no RES_CHAIN
+ RES_TEXTGRID, RES_FRMATR_END - 1>>(rPool);
+ }
+ return pItemSet;
+}
+
+void lcl_getTableAttributes( SfxItemSet& rSet, SwWrtShell &rSh )
+{
+ std::unique_ptr<SvxBrushItem> aBrush(std::make_unique<SvxBrushItem>(RES_BACKGROUND));
+ rSh.GetBoxBackground(aBrush);
+ rSet.Put( *aBrush );
+ if(rSh.GetRowBackground(aBrush))
+ {
+ aBrush->SetWhich(SID_ATTR_BRUSH_ROW);
+ rSet.Put( *aBrush );
+ }
+ else
+ rSet.InvalidateItem(SID_ATTR_BRUSH_ROW);
+ rSh.GetTabBackground(aBrush);
+ aBrush->SetWhich(SID_ATTR_BRUSH_TABLE);
+ rSet.Put( *aBrush );
+
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ rSet.Put(aBoxInfo);
+ rSh.GetTabBorders( rSet );
+
+ std::unique_ptr<SvxFrameDirectionItem> aBoxDirection(std::make_unique<SvxFrameDirectionItem>(SvxFrameDirection::Environment, RES_FRAMEDIR));
+ if(rSh.GetBoxDirection( aBoxDirection ))
+ {
+ aBoxDirection->SetWhich(FN_TABLE_BOX_TEXTORIENTATION);
+ rSet.Put(std::move(aBoxDirection));
+ }
+
+ rSet.Put(SfxUInt16Item(FN_TABLE_SET_VERT_ALIGN, rSh.GetBoxAlign()));
+
+ rSet.Put( SfxUInt16Item( FN_PARAM_TABLE_HEADLINE, rSh.GetRowsToRepeat() ) );
+
+ SwFrameFormat *pFrameFormat = rSh.GetTableFormat();
+ if(pFrameFormat)
+ {
+ rSet.Put( pFrameFormat->GetShadow() );
+ rSet.Put( pFrameFormat->GetBreak() );
+ rSet.Put( pFrameFormat->GetPageDesc() );
+ rSet.Put( pFrameFormat->GetLayoutSplit() );
+ rSet.Put( pFrameFormat->GetKeep() );
+ rSet.Put( pFrameFormat->GetFrameDir() );
+ }
+
+ std::unique_ptr<SwFormatRowSplit> pSplit = rSh.GetRowSplit();
+ if(pSplit)
+ rSet.Put(std::move(pSplit));
+}
+
+void lcl_setTableAttributes( const SfxItemSet& rSet, SwWrtShell &rSh )
+{
+ bool bBorder = ( SfxItemState::SET == rSet.GetItemState( RES_BOX ) ||
+ SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER ) );
+ const SvxBrushItem* pBackgroundItem = rSet.GetItemIfSet( RES_BACKGROUND, false );
+ const SvxBrushItem* pRowItem = rSet.GetItemIfSet( SID_ATTR_BRUSH_ROW, false );
+ const SvxBrushItem* pTableItem = rSet.GetItemIfSet( SID_ATTR_BRUSH_TABLE, false );
+ bool bBackground = pBackgroundItem || pRowItem || pTableItem;
+
+ if(bBackground)
+ {
+ if(pBackgroundItem)
+ rSh.SetBoxBackground( *pBackgroundItem );
+ if(pRowItem)
+ {
+ std::unique_ptr<SvxBrushItem> aBrush(pRowItem->Clone());
+ aBrush->SetWhich(RES_BACKGROUND);
+ rSh.SetRowBackground(*aBrush);
+ }
+ if(pTableItem)
+ {
+ std::unique_ptr<SvxBrushItem> aBrush(pTableItem->Clone());
+ aBrush->SetWhich(RES_BACKGROUND);
+ rSh.SetTabBackground(*aBrush);
+ }
+ }
+ if(bBorder)
+ rSh.SetTabBorders( rSet );
+
+ if( const SfxUInt16Item* pHeadlineItem = rSet.GetItemIfSet( FN_PARAM_TABLE_HEADLINE, false) )
+ rSh.SetRowsToRepeat( pHeadlineItem->GetValue() );
+
+ SwFrameFormat* pFrameFormat = rSh.GetTableFormat();
+ if(pFrameFormat)
+ {
+ //RES_SHADOW
+ const SfxPoolItem* pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_SHADOW), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_BREAK
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_BREAK), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_PAGEDESC
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_PAGEDESC), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_LAYOUT_SPLIT
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_LAYOUT_SPLIT), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_KEEP
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_KEEP), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+
+ //RES_FRAMEDIR
+ pItem = rSet.GetItemIfSet(rSet.GetPool()->GetWhich(RES_FRAMEDIR), false);
+ if(pItem)
+ pFrameFormat->SetFormatAttr( *pItem );
+ }
+
+ if( const SvxFrameDirectionItem* pTextOriItem = rSet.GetItemIfSet( FN_TABLE_BOX_TEXTORIENTATION, false ) )
+ {
+ SvxFrameDirectionItem aDirection( SvxFrameDirection::Environment, RES_FRAMEDIR );
+ aDirection.SetValue(pTextOriItem->GetValue());
+ rSh.SetBoxDirection(aDirection);
+ }
+
+ if( const SfxUInt16Item* pVertAlignItem = rSet.GetItemIfSet( FN_TABLE_SET_VERT_ALIGN, false ))
+ rSh.SetBoxAlign(pVertAlignItem->GetValue());
+
+ if( const SwFormatRowSplit* pSplitItem = rSet.GetItemIfSet( RES_ROW_SPLIT, false ) )
+ rSh.SetRowSplit(*pSplitItem);
+}
+}//end anonymous namespace
+
+SwFormatClipboard::SwFormatClipboard()
+ : m_nSelectionType(SelectionType::NONE)
+ , m_bPersistentCopy(false)
+{
+}
+
+bool SwFormatClipboard::HasContent() const
+{
+ return m_pItemSet_TextAttr!=nullptr
+ || m_pItemSet_ParAttr!=nullptr
+ || m_pTableItemSet != nullptr
+ || !m_aCharStyle.isEmpty()
+ || !m_aParaStyle.isEmpty()
+ ;
+}
+bool SwFormatClipboard::HasContentForThisType( SelectionType nSelectionType ) const
+{
+ if( !HasContent() )
+ return false;
+
+ if( m_nSelectionType == nSelectionType )
+ return true;
+
+ if( ( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ &&
+ ( m_nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ )
+ return true;
+
+ if( nSelectionType & SelectionType::Text && m_nSelectionType & SelectionType::Text )
+ return true;
+
+ return false;
+}
+
+bool SwFormatClipboard::CanCopyThisType( SelectionType nSelectionType )
+{
+ return bool(nSelectionType
+ & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic
+ | SelectionType::Text | SelectionType::DrawObject | SelectionType::Table | SelectionType::TableCell ));
+}
+
+void SwFormatClipboard::Copy( SwWrtShell& rWrtShell, SfxItemPool& rPool, bool bPersistentCopy )
+{
+ // first clear the previously stored attributes
+ Erase();
+ m_bPersistentCopy = bPersistentCopy;
+
+ SelectionType nSelectionType = rWrtShell.GetSelectionType();
+ auto pItemSet_TextAttr = lcl_CreateEmptyItemSet( nSelectionType, rPool, true );
+ auto pItemSet_ParAttr = lcl_CreateEmptyItemSet( nSelectionType, rPool );
+
+ rWrtShell.StartAction();
+ rWrtShell.Push();
+
+ // modify the "Point and Mark" of the cursor
+ // in order to select only the last character of the
+ // selection(s) and then to get the attributes of this single character
+ if( nSelectionType == SelectionType::Text )
+ {
+ // get the current PaM, the cursor
+ // if there several selection it currently point
+ // on the last (sort by there creation time) selection
+ SwPaM* pCursor = rWrtShell.GetCursor();
+
+ bool bHasSelection = pCursor->HasMark();
+ bool bForwardSelection = false;
+
+ if(!bHasSelection && pCursor->IsMultiSelection())
+ {
+ // if cursor has multiple selections
+
+ // clear all the selections except the last
+ rWrtShell.KillPams();
+
+ // reset the cursor to the remaining selection
+ pCursor = rWrtShell.GetCursor();
+ bHasSelection = true;
+ }
+
+ bool dontMove = false;
+ if (bHasSelection)
+ {
+ bForwardSelection = (*pCursor->GetPoint()) > (*pCursor->GetMark());
+
+ // clear the selection leaving just the cursor
+ pCursor->DeleteMark();
+ pCursor->SetMark();
+ }
+ else
+ {
+ bool rightToLeft = rWrtShell.IsInRightToLeftText();
+ // if there were no selection (only a cursor) and the cursor was at
+ // the end of the paragraph then don't move
+ if ( rWrtShell.IsEndPara() && !rightToLeft )
+ dontMove = true;
+
+ // revert left and right
+ if ( rightToLeft )
+ {
+ if (pCursor->GetPoint()->GetContentIndex() == 0)
+ dontMove = true;
+ else
+ bForwardSelection = !bForwardSelection;
+ }
+ }
+
+ // move the cursor in order to select one character
+ if (!dontMove)
+ pCursor->Move( bForwardSelection ? fnMoveBackward : fnMoveForward );
+ }
+
+ if(pItemSet_TextAttr)
+ {
+ if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ rWrtShell.GetFlyFrameAttr(*pItemSet_TextAttr);
+ else
+ {
+ // get the text attributes from named and automatic formatting
+ rWrtShell.GetCurAttr(*pItemSet_TextAttr);
+
+ if( nSelectionType & SelectionType::Text )
+ {
+ // get the paragraph attributes (could be character properties)
+ // from named and automatic formatting
+ rWrtShell.GetCurParAttr(*pItemSet_ParAttr);
+ }
+ }
+ }
+ else if ( nSelectionType & SelectionType::DrawObject )
+ {
+ SdrView* pDrawView = rWrtShell.GetDrawView();
+ if(pDrawView)
+ {
+ if( pDrawView->AreObjectsMarked() )
+ {
+ pItemSet_TextAttr = std::make_unique<SfxItemSet>( pDrawView->GetAttrFromMarked(true/*bOnlyHardAttr*/) );
+ //remove attributes defining the type/data of custom shapes
+ pItemSet_TextAttr->ClearItem(SDRATTR_CUSTOMSHAPE_ENGINE);
+ pItemSet_TextAttr->ClearItem(SDRATTR_CUSTOMSHAPE_DATA);
+ pItemSet_TextAttr->ClearItem(SDRATTR_CUSTOMSHAPE_GEOMETRY);
+ }
+ }
+ }
+
+ if( nSelectionType & SelectionType::TableCell )//only copy table attributes if really cells are selected (not only text in tables)
+ {
+ m_pTableItemSet = std::make_unique<SfxItemSetFixed<
+ RES_PAGEDESC, RES_BREAK,
+ RES_BACKGROUND, RES_SHADOW, // RES_BOX is inbetween
+ RES_KEEP, RES_KEEP,
+ RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_ROW_SPLIT, RES_ROW_SPLIT,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_SHADOW,
+ // SID_ATTR_BORDER_OUTER is inbetween
+ SID_ATTR_BRUSH_ROW, SID_ATTR_BRUSH_TABLE,
+ FN_TABLE_SET_VERT_ALIGN, FN_TABLE_SET_VERT_ALIGN,
+ FN_TABLE_BOX_TEXTORIENTATION, FN_TABLE_BOX_TEXTORIENTATION,
+ FN_PARAM_TABLE_HEADLINE, FN_PARAM_TABLE_HEADLINE>>(rPool);
+ lcl_getTableAttributes( *m_pTableItemSet, rWrtShell );
+ }
+
+ m_nSelectionType = nSelectionType;
+ m_pItemSet_TextAttr = std::move(pItemSet_TextAttr);
+ m_pItemSet_ParAttr = std::move(pItemSet_ParAttr);
+
+ if( nSelectionType & SelectionType::Text )
+ {
+ // if text is selected save the named character format
+ SwFormat* pFormat = rWrtShell.GetCurCharFormat();
+ if( pFormat )
+ m_aCharStyle = pFormat->GetName();
+
+ // and the named paragraph format
+ pFormat = rWrtShell.GetCurTextFormatColl();
+ if( pFormat )
+ m_aParaStyle = pFormat->GetName();
+ }
+
+ rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtShell.EndAction();
+}
+
+typedef std::vector< std::unique_ptr< SfxPoolItem > > ItemVector;
+// collect all PoolItems from the applied styles
+static void lcl_AppendSetItems( ItemVector& rItemVector, const SfxItemSet& rStyleAttrSet )
+{
+ const WhichRangesContainer& pRanges = rStyleAttrSet.GetRanges();
+ for(const auto & rPair : pRanges)
+ {
+ for ( sal_uInt16 nWhich = rPair.first; nWhich <= rPair.second; ++nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == rStyleAttrSet.GetItemState( nWhich, false, &pItem ) )
+ {
+ rItemVector.emplace_back( pItem->Clone() );
+ }
+ }
+ }
+}
+// remove all items that are inherited from the styles
+static void lcl_RemoveEqualItems( SfxItemSet& rTemplateItemSet, const ItemVector& rItemVector )
+{
+ for( const auto& rItem : rItemVector )
+ {
+ const SfxPoolItem* pItem;
+ if( SfxItemState::SET == rTemplateItemSet.GetItemState( rItem->Which(), true, &pItem ) &&
+ *pItem == *rItem )
+ {
+ rTemplateItemSet.ClearItem( rItem->Which() );
+ }
+ }
+}
+
+void SwFormatClipboard::Paste( SwWrtShell& rWrtShell, SfxStyleSheetBasePool* pPool
+ , bool bNoCharacterFormats, bool bNoParagraphFormats )
+{
+ SelectionType nSelectionType = rWrtShell.GetSelectionType();
+ if( !HasContentForThisType(nSelectionType) )
+ {
+ if(!m_bPersistentCopy)
+ Erase();
+ return;
+ }
+
+ rWrtShell.StartAction();
+ rWrtShell.StartUndo(SwUndoId::INSATTR);
+
+ ItemVector aItemVector;
+
+ if (m_pItemSet_TextAttr && !( nSelectionType & SelectionType::DrawObject))
+ {
+ // reset all direct formatting before applying anything
+ o3tl::sorted_vector<sal_uInt16> aAttrs;
+ for (sal_uInt16 nWhich = RES_CHRATR_BEGIN; nWhich < RES_CHRATR_END; nWhich++)
+ aAttrs.insert(nWhich);
+ rWrtShell.ResetAttr({ aAttrs });
+ }
+
+ if( nSelectionType & SelectionType::Text )
+ {
+ // apply the named text and paragraph formatting
+ if( pPool )
+ {
+ // if there is a named text format recorded and the user wants to apply it
+ if(!m_aCharStyle.isEmpty() && !bNoCharacterFormats )
+ {
+ // look for the named text format in the pool
+ SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>(pPool->Find(m_aCharStyle, SfxStyleFamily::Char));
+
+ // if the style is found
+ if( pStyle )
+ {
+ SwFormatCharFormat aFormat(pStyle->GetCharFormat());
+ // store the attributes from this style in aItemVector in order
+ // not to apply them as automatic formatting attributes later in the code
+ lcl_AppendSetItems( aItemVector, aFormat.GetCharFormat()->GetAttrSet());
+
+ // apply the named format
+ rWrtShell.SetAttrItem( aFormat );
+ }
+ }
+
+ // if there is a named paragraph format recorded and the user wants to apply it
+ if(!m_aParaStyle.isEmpty() && !bNoParagraphFormats )
+ {
+ // look for the named paragraph format in the pool
+ SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>(pPool->Find(m_aParaStyle, SfxStyleFamily::Para));
+ if( pStyle )
+ {
+ // store the attributes from this style in aItemVector in order
+ // not to apply them as automatic formatting attributes later in the code
+ lcl_AppendSetItems( aItemVector, pStyle->GetCollection()->GetAttrSet());
+
+ // apply the named format
+ rWrtShell.SetTextFormatColl( pStyle->GetCollection() );
+ }
+ }
+ }
+
+ // apply the paragraph automatic attributes
+ if ( m_pItemSet_ParAttr && m_pItemSet_ParAttr->Count() != 0 && !bNoParagraphFormats )
+ {
+ // temporary SfxItemSet
+ std::unique_ptr<SfxItemSet> pTemplateItemSet(lcl_CreateEmptyItemSet(
+ nSelectionType, *m_pItemSet_ParAttr->GetPool()));
+ // no need to verify the existence of pTemplateItemSet as we
+ // know that here the selection type is SEL_TXT
+
+ pTemplateItemSet->Put( *m_pItemSet_ParAttr );
+
+ // remove attribute that were applied by named text and paragraph formatting
+ lcl_RemoveEqualItems( *pTemplateItemSet, aItemVector );
+
+ // apply the paragraph automatic attributes to all the nodes in the selection
+ rWrtShell.SetAttrSet(*pTemplateItemSet);
+
+ // store the attributes in aItemVector in order not to apply them as
+ // text automatic formatting attributes later in the code
+ lcl_AppendSetItems( aItemVector, *pTemplateItemSet);
+ }
+ }
+
+ if(m_pItemSet_TextAttr)
+ {
+ if( nSelectionType & SelectionType::DrawObject )
+ {
+ SdrView* pDrawView = rWrtShell.GetDrawView();
+ if(pDrawView)
+ {
+ pDrawView->SetAttrToMarked(*m_pItemSet_TextAttr, true/*bReplaceAll*/);
+ }
+ }
+ else
+ {
+ // temporary SfxItemSet
+ std::unique_ptr<SfxItemSet> pTemplateItemSet(lcl_CreateEmptyItemSet(
+ nSelectionType, *m_pItemSet_TextAttr->GetPool(), true ));
+
+ if(pTemplateItemSet)
+ {
+ // copy the stored automatic text attributes in a temporary SfxItemSet
+ pTemplateItemSet->Put( *m_pItemSet_TextAttr );
+
+ // only attributes that were not apply by named style attributes and automatic
+ // paragraph attributes should be applied
+ lcl_RemoveEqualItems( *pTemplateItemSet, aItemVector );
+
+ // apply the character automatic attributes
+ if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) )
+ rWrtShell.SetFlyFrameAttr(*pTemplateItemSet);
+ else if ( !bNoCharacterFormats )
+ {
+ rWrtShell.SetAttrSet(*pTemplateItemSet);
+ }
+ }
+ }
+ }
+
+ if( m_pTableItemSet && nSelectionType & (SelectionType::Table | SelectionType::TableCell) )
+ lcl_setTableAttributes( *m_pTableItemSet, rWrtShell );
+
+ rWrtShell.EndUndo(SwUndoId::INSATTR);
+ rWrtShell.EndAction();
+
+ if(!m_bPersistentCopy)
+ Erase();
+}
+
+void SwFormatClipboard::Erase()
+{
+ m_nSelectionType = SelectionType::NONE;
+
+ m_pItemSet_TextAttr.reset();
+
+ m_pItemSet_ParAttr.reset();
+
+ m_pTableItemSet.reset();
+
+ if( !m_aCharStyle.isEmpty() )
+ m_aCharStyle.clear();
+ if( !m_aParaStyle.isEmpty() )
+ m_aParaStyle.clear();
+
+ m_bPersistentCopy = false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/pview.cxx b/sw/source/uibase/uiview/pview.cxx
new file mode 100644
index 0000000000..0b03a001d0
--- /dev/null
+++ b/sw/source/uibase/uiview/pview.cxx
@@ -0,0 +1,1905 @@
+/* -*- 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_wasm_strip.h>
+
+#include <sfx2/objface.hxx>
+#include <vcl/help.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/weld.hxx>
+
+#include <svl/whiter.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <editeng/paperinf.hxx>
+#include <svx/svdview.hxx>
+#include <svx/viewlayoutitem.hxx>
+#include <svx/zoomslideritem.hxx>
+#include <tools/svborder.hxx>
+#include <osl/diagnose.h>
+
+#include <globdoc.hxx>
+#include <wdocsh.hxx>
+#include <pvprtdat.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <pview.hxx>
+#include <view.hxx>
+#include <scroll.hxx>
+#include <prtopt.hxx>
+#include <usrpref.hxx>
+#include "viewfunc.hxx"
+
+#include <helpids.h>
+#include <cmdid.h>
+#include <strings.hrc>
+
+#define ShellClass_SwPagePreview
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <pagepreviewlayout.hxx>
+
+#include <svx/svxdlg.hxx>
+
+#include <memory>
+#include <vcl/EnumContext.hxx>
+#include <vcl/notebookbar/notebookbar.hxx>
+
+using namespace ::com::sun::star;
+SFX_IMPL_NAMED_VIEWFACTORY(SwPagePreview, "PrintPreview")
+{
+ SFX_VIEW_REGISTRATION(SwDocShell);
+ SFX_VIEW_REGISTRATION(SwWebDocShell);
+ SFX_VIEW_REGISTRATION(SwGlobalDocShell);
+}
+
+SFX_IMPL_INTERFACE(SwPagePreview, SfxViewShell)
+
+void SwPagePreview::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("preview");
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard|SfxVisibilityFlags::Client|SfxVisibilityFlags::FullScreen|SfxVisibilityFlags::ReadonlyDoc,
+ ToolbarId::PView_Toolbox);
+}
+
+
+#define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
+
+#define MIN_PREVIEW_ZOOM 25
+#define MAX_PREVIEW_ZOOM 600
+
+static sal_uInt16 lcl_GetNextZoomStep(sal_uInt16 nCurrentZoom, bool bZoomIn)
+{
+ static const sal_uInt16 aZoomArr[] =
+ {
+ 25, 50, 75, 100, 150, 200, 400, 600
+ };
+ const int nZoomArrSize = static_cast<int>(SAL_N_ELEMENTS(aZoomArr));
+ if (bZoomIn)
+ {
+ for(sal_uInt16 i : aZoomArr)
+ {
+ if(nCurrentZoom < i)
+ return i;
+ }
+ }
+ else
+ {
+ for(int i = nZoomArrSize - 1; i >= 0; --i)
+ {
+ if(nCurrentZoom > aZoomArr[i] || !i)
+ return aZoomArr[i];
+ }
+ }
+ return bZoomIn ? MAX_PREVIEW_ZOOM : MIN_PREVIEW_ZOOM;
+};
+
+static void lcl_InvalidateZoomSlots(SfxBindings& rBindings)
+{
+ static sal_uInt16 const aInval[] =
+ {
+ SID_ATTR_ZOOM, SID_ZOOM_OUT, SID_ZOOM_IN, SID_ATTR_ZOOMSLIDER, FN_PREVIEW_ZOOM, FN_STAT_ZOOM,
+ 0
+ };
+ rBindings.Invalidate( aInval );
+}
+
+namespace {
+
+// At first the zoom dialog
+class SwPreviewZoomDlg : public weld::GenericDialogController
+{
+ SwPagePreviewWin& m_rParent;
+ std::unique_ptr<weld::SpinButton> m_xRowEdit;
+ std::unique_ptr<weld::SpinButton> m_xColEdit;
+
+public:
+ SwPreviewZoomDlg(SwPagePreviewWin& rParent)
+ : GenericDialogController(rParent.GetFrameWeld(), "modules/swriter/ui/previewzoomdialog.ui", "PreviewZoomDialog")
+ , m_rParent(rParent)
+ , m_xRowEdit(m_xBuilder->weld_spin_button("rows"))
+ , m_xColEdit(m_xBuilder->weld_spin_button("cols"))
+ {
+ m_xRowEdit->set_value(rParent.GetRow());
+ m_xColEdit->set_value(rParent.GetCol());
+ }
+
+ void execute()
+ {
+ if (run() == RET_OK)
+ {
+ m_rParent.CalcWish(m_xRowEdit->get_value(), m_xColEdit->get_value());
+ }
+ }
+};
+
+}
+
+// all for SwPagePreviewWin
+SwPagePreviewWin::SwPagePreviewWin( vcl::Window *pParent, SwPagePreview& rPView )
+ : Window(pParent, WinBits(WB_CLIPCHILDREN))
+ , mpViewShell(nullptr)
+ , mrView(rPView)
+ , mbCalcScaleForPreviewLayout(true)
+ , maPaintedPreviewDocRect(tools::Rectangle(0,0,0,0))
+ , mpPgPreviewLayout(nullptr)
+{
+ GetOutDev()->SetOutDevViewType( OutDevViewType::PrintPreview );
+ SetHelpId(HID_PAGEPREVIEW);
+ GetOutDev()->SetFillColor( GetBackground().GetColor() );
+ GetOutDev()->SetLineColor( GetBackground().GetColor());
+ SetMapMode( MapMode(MapUnit::MapTwip) );
+
+ const SwMasterUsrPref *pUsrPref = SW_MOD()->GetUsrPref(false);
+ mnRow = pUsrPref->GetPagePrevRow(); // 1 row
+ mnCol = pUsrPref->GetPagePrevCol(); // 1 column
+ mnSttPage = USHRT_MAX;
+}
+
+SwPagePreviewWin::~SwPagePreviewWin()
+{
+}
+
+void SwPagePreviewWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (!mpViewShell || !mpViewShell->GetLayout())
+ return;
+
+ if (USHRT_MAX == mnSttPage) // was never calculated ? (Init-Phase!)
+ {
+ // This is the size to which I always relate.
+ if (!maPxWinSize.Height() || !maPxWinSize.Width())
+ maPxWinSize = GetOutputSizePixel();
+
+ tools::Rectangle aRect(rRenderContext.LogicToPixel(rRect));
+ mpPgPreviewLayout->Prepare(1, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect);
+ SetSelectedPage(1);
+ mpPgPreviewLayout->Paint(rRenderContext, rRenderContext.PixelToLogic(aRect));
+ SetPagePreview(mnRow, mnCol);
+ }
+ else
+ {
+ MapMode aMM(rRenderContext.GetMapMode());
+ aMM.SetScaleX(maScale);
+ aMM.SetScaleY(maScale);
+ rRenderContext.SetMapMode(aMM);
+ mpPgPreviewLayout->GetParentViewShell().setOutputToWindow(true);
+ mpPgPreviewLayout->Paint(rRenderContext, rRect);
+ mpPgPreviewLayout->GetParentViewShell().setOutputToWindow(false);
+ }
+}
+
+void SwPagePreviewWin::CalcWish( sal_Int16 nNewRow, sal_Int16 nNewCol )
+{
+ if( !mpViewShell || !mpViewShell->GetLayout() )
+ return;
+
+ const sal_Int16 nOldCol = mnCol;
+ mnRow = nNewRow;
+ mnCol = nNewCol;
+ const sal_uInt16 nPages = mnRow * mnCol;
+ const sal_uInt16 nLastSttPg = mrView.GetPageCount()+1 > nPages
+ ? mrView.GetPageCount()+1 - nPages : 0;
+ if( mnSttPage > nLastSttPg )
+ mnSttPage = nLastSttPg;
+
+ mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
+ mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ SetSelectedPage( mnSttPage );
+ SetPagePreview(mnRow, mnCol);
+ maScale = GetMapMode().GetScaleX();
+
+ // If changes have taken place at the columns, the special case "single column"
+ // must be considered and corrected if necessary.
+ if( (1 == nOldCol) != (1 == mnCol) )
+ mrView.ScrollDocSzChg();
+
+ // Order must be maintained!
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_ZOOM, SID_ZOOM_OUT, SID_ZOOM_IN,
+ FN_PREVIEW_ZOOM,
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, FN_STAT_ZOOM,
+ FN_SHOW_TWO_PAGES, FN_SHOW_MULTIPLE_PAGES,
+ 0
+ };
+ SfxBindings& rBindings = mrView.GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ rBindings.Update( FN_SHOW_TWO_PAGES );
+ rBindings.Update( FN_SHOW_MULTIPLE_PAGES );
+ // adjust scrollbars
+ mrView.ScrollViewSzChg();
+}
+
+// mnSttPage is Absolute
+bool SwPagePreviewWin::MovePage( int eMoveMode )
+{
+ // number of pages up
+ const sal_uInt16 nPages = mnRow * mnCol;
+ sal_uInt16 nNewSttPage = mnSttPage;
+ const sal_uInt16 nPageCount = mrView.GetPageCount();
+ const sal_uInt16 nDefSttPg = GetDefSttPage();
+ bool bPaintPageAtFirstCol = true;
+
+ switch( eMoveMode )
+ {
+ case MV_PAGE_UP:
+ {
+ const sal_uInt16 nRelSttPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( mnSttPage );
+ const sal_uInt16 nNewAbsSttPage = nRelSttPage - nPages > 0 ?
+ mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSttPage - nPages ) :
+ nDefSttPg;
+ nNewSttPage = nNewAbsSttPage;
+
+ const sal_uInt16 nRelSelPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( SelectedPage() );
+ const sal_uInt16 nNewRelSelPage = nRelSelPage - nPages > 0 ?
+ nRelSelPage - nPages :
+ 1;
+ SetSelectedPage( mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nNewRelSelPage ) );
+
+ break;
+ }
+ case MV_PAGE_DOWN:
+ {
+ const sal_uInt16 nRelSttPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( mnSttPage );
+ const sal_uInt16 nNewAbsSttPage = mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSttPage + nPages );
+ nNewSttPage = std::min(nNewAbsSttPage, nPageCount);
+
+ const sal_uInt16 nRelSelPage = mpPgPreviewLayout->ConvertAbsoluteToRelativePageNum( SelectedPage() );
+ const sal_uInt16 nNewAbsSelPage = mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nRelSelPage + nPages );
+ SetSelectedPage( std::min(nNewAbsSelPage, nPageCount) );
+
+ break;
+ }
+ case MV_DOC_STT:
+ nNewSttPage = nDefSttPg;
+ SetSelectedPage( mpPgPreviewLayout->ConvertRelativeToAbsolutePageNum( nNewSttPage ? nNewSttPage : 1 ) );
+ break;
+ case MV_DOC_END:
+ // correct calculation of new start page.
+ nNewSttPage = nPageCount;
+ SetSelectedPage( nPageCount );
+ break;
+
+ case MV_SELPAGE:
+ // <nNewSttPage> and <SelectedPage()> are already set.
+ // not start at first column, only if the
+ // complete preview layout columns doesn't fit into window.
+ if ( !mpPgPreviewLayout->DoesPreviewLayoutColsFitIntoWindow() )
+ bPaintPageAtFirstCol = false;
+ break;
+ case MV_SCROLL:
+ // check, if paint page at first column
+ // has to be avoided
+ if ( !mpPgPreviewLayout->DoesPreviewLayoutRowsFitIntoWindow() ||
+ !mpPgPreviewLayout->DoesPreviewLayoutColsFitIntoWindow() )
+ bPaintPageAtFirstCol = false;
+ break;
+ case MV_NEWWINSIZE:
+ // nothing special to do.
+ break;
+ case MV_CALC:
+ // re-init page preview layout.
+ mpPgPreviewLayout->ReInit();
+
+ // correct calculation of new start page.
+ if( nNewSttPage > nPageCount )
+ nNewSttPage = nPageCount;
+
+ // correct selected page number
+ if( SelectedPage() > nPageCount )
+ SetSelectedPage( nNewSttPage ? nNewSttPage : 1 );
+ }
+
+ mpPgPreviewLayout->Prepare( nNewSttPage, Point(0,0), maPxWinSize,
+ nNewSttPage,
+ maPaintedPreviewDocRect, bPaintPageAtFirstCol );
+ if( nNewSttPage == mnSttPage &&
+ eMoveMode != MV_SELPAGE )
+ return false;
+
+ SetPagePreview(mnRow, mnCol);
+ mnSttPage = nNewSttPage;
+
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, 0
+ };
+
+ SfxBindings& rBindings = mrView.GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+
+ return true;
+}
+
+void SwPagePreviewWin::SetWinSize( const Size& rNewSize )
+{
+ // We always want the size as pixel units.
+ maPxWinSize = LogicToPixel( rNewSize );
+
+ if( USHRT_MAX == mnSttPage )
+ {
+ mnSttPage = GetDefSttPage();
+ SetSelectedPage( GetDefSttPage() );
+ }
+
+ if ( mbCalcScaleForPreviewLayout )
+ {
+ mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
+ maScale = GetMapMode().GetScaleX();
+ }
+ mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ if ( mbCalcScaleForPreviewLayout )
+ {
+ SetSelectedPage( mnSttPage );
+ mbCalcScaleForPreviewLayout = false;
+ }
+ SetPagePreview(mnRow, mnCol);
+ maScale = GetMapMode().GetScaleX();
+}
+
+OUString SwPagePreviewWin::GetStatusStr( sal_uInt16 nPageCnt ) const
+{
+ // show physical and virtual page number of
+ // selected page, if it's visible.
+ const sal_uInt16 nPageNum = mpPgPreviewLayout->IsPageVisible( mpPgPreviewLayout->SelectedPage() )
+ ? mpPgPreviewLayout->SelectedPage() : std::max<sal_uInt16>(mnSttPage, 1);
+
+ OUString aStatusStr;
+ const sal_uInt16 nVirtPageNum = mpPgPreviewLayout->GetVirtPageNumByPageNum( nPageNum );
+ if( nVirtPageNum && nVirtPageNum != nPageNum )
+ {
+ aStatusStr = OUString::number(nVirtPageNum) + " " ;
+ }
+ return aStatusStr + OUString::number(nPageNum) + " / " + OUString::number(nPageCnt);
+}
+
+void SwPagePreviewWin::KeyInput( const KeyEvent &rKEvt )
+{
+ const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ bool bHandled = false;
+ if(!rKeyCode.GetModifier())
+ {
+ sal_uInt16 nSlot = 0;
+ switch(rKeyCode.GetCode())
+ {
+ case KEY_ADD : nSlot = SID_ZOOM_IN; break;
+ case KEY_ESCAPE: nSlot = FN_CLOSE_PAGEPREVIEW; break;
+ case KEY_SUBTRACT : nSlot = SID_ZOOM_OUT; break;
+ }
+ if(nSlot)
+ {
+ bHandled = true;
+ mrView.GetViewFrame().GetDispatcher()->Execute(
+ nSlot, SfxCallMode::ASYNCHRON );
+ }
+ }
+ if( !bHandled && !mrView.KeyInput( rKEvt ) )
+ Window::KeyInput( rKEvt );
+}
+
+void SwPagePreviewWin::Command( const CommandEvent& rCEvt )
+{
+ bool bCallBase = true;
+ switch( rCEvt.GetCommand() )
+ {
+ case CommandEventId::ContextMenu:
+ SfxDispatcher::ExecutePopup();
+ bCallBase = false;
+ break;
+
+ case CommandEventId::Wheel:
+ case CommandEventId::StartAutoScroll:
+ case CommandEventId::AutoScroll:
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( pData )
+ {
+ const CommandWheelData aDataNew(pData->GetDelta(),pData->GetNotchDelta(),COMMAND_WHEEL_PAGESCROLL,
+ pData->GetMode(),pData->GetModifier(),pData->IsHorz(), pData->IsDeltaPixel());
+ const CommandEvent aEvent( rCEvt.GetMousePosPixel(),rCEvt.GetCommand(),rCEvt.IsMouseEvent(),&aDataNew);
+ bCallBase = !mrView.HandleWheelCommands( aEvent );
+ }
+ else
+ bCallBase = !mrView.HandleWheelCommands( rCEvt );
+ }
+ break;
+ default:
+ ;
+ }
+
+ if( bCallBase )
+ Window::Command( rCEvt );
+}
+
+void SwPagePreviewWin::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // consider single-click to set selected page
+ if( MOUSE_LEFT != ( rMEvt.GetModifier() + rMEvt.GetButtons() ) )
+ return;
+
+ Point aPreviewPos( PixelToLogic( rMEvt.GetPosPixel() ) );
+ Point aDocPos;
+ bool bPosInEmptyPage;
+ sal_uInt16 nNewSelectedPage;
+ bool bIsDocPos =
+ mpPgPreviewLayout->IsPreviewPosInDocPreviewPage( aPreviewPos,
+ aDocPos, bPosInEmptyPage, nNewSelectedPage );
+ if ( bIsDocPos && rMEvt.GetClicks() == 2 )
+ {
+ // close page preview, set new cursor position and switch to
+ // normal view.
+ OUString sNewCursorPos = OUString::number( aDocPos.X() ) + ";" +
+ OUString::number( aDocPos.Y() ) + ";";
+ mrView.SetNewCursorPos( sNewCursorPos );
+
+ SfxViewFrame& rTmpFrame = mrView.GetViewFrame();
+ rTmpFrame.GetBindings().Execute( SID_VIEWSHELL0, nullptr,
+ SfxCallMode::ASYNCHRON );
+ }
+ else if ( bIsDocPos || bPosInEmptyPage )
+ {
+ // show clicked page as the selected one
+ mpPgPreviewLayout->MarkNewSelectedPage( nNewSelectedPage );
+ GetViewShell()->ShowPreviewSelection( nNewSelectedPage );
+ // adjust position at vertical scrollbar.
+ if ( mpPgPreviewLayout->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ mrView.SetVScrollbarThumbPos( nNewSelectedPage );
+ }
+ // invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = mrView.GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ }
+}
+
+// Set user prefs or view options
+
+void SwPagePreviewWin::SetPagePreview( sal_Int16 nRow, sal_Int16 nCol )
+{
+ SwMasterUsrPref *pOpt = const_cast<SwMasterUsrPref *>(SW_MOD()->GetUsrPref(false));
+
+ if (nRow != pOpt->GetPagePrevRow() || nCol != pOpt->GetPagePrevCol())
+ {
+ pOpt->SetPagePrevRow( nRow );
+ pOpt->SetPagePrevCol( nCol );
+ pOpt->SetModified();
+
+ // Update scrollbar!
+ mrView.ScrollViewSzChg();
+ }
+}
+
+/** get selected page in document preview */
+sal_uInt16 SwPagePreviewWin::SelectedPage() const
+{
+ return mpPgPreviewLayout->SelectedPage();
+}
+
+/** set selected page number in document preview */
+void SwPagePreviewWin::SetSelectedPage( sal_uInt16 _nSelectedPageNum )
+{
+ mpPgPreviewLayout->SetSelectedPage( _nSelectedPageNum );
+}
+
+/** method to enable/disable book preview */
+bool SwPagePreviewWin::SetBookPreviewMode( const bool _bBookPreview )
+{
+ return mpPgPreviewLayout->SetBookPreviewMode( _bBookPreview,
+ mnSttPage,
+ maPaintedPreviewDocRect );
+}
+
+void SwPagePreviewWin::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ switch( rDCEvt.GetType() )
+ {
+ case DataChangedEventType::SETTINGS:
+ // Rearrange the scrollbars or trigger resize, because the
+ // size of the scrollbars may have be changed. Also the
+ // size of the scrollbars has to be retrieved from the settings
+ // out of the resize handler.
+ if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
+ mrView.InvalidateBorder(); // Scrollbar widths
+ // zoom has to be disabled if Accessibility support is switched on
+ lcl_InvalidateZoomSlots(mrView.GetViewFrame().GetBindings());
+ break;
+
+ case DataChangedEventType::PRINTER:
+ case DataChangedEventType::DISPLAY:
+ case DataChangedEventType::FONTS:
+ case DataChangedEventType::FONTSUBSTITUTION:
+ mrView.GetDocShell()->UpdateFontList(); // Font change
+ mpViewShell->InvalidateLayout(true);
+ if ( mpViewShell->GetWin() )
+ mpViewShell->GetWin()->Invalidate();
+ break;
+ default: break;
+ }
+}
+
+/** help method to execute SfxRequest FN_PAGEUP and FN_PAGEDOWN */
+void SwPagePreview::ExecPgUpAndPgDown( const bool _bPgUp,
+ SfxRequest* _pReq )
+{
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ // check, if top/bottom of preview is *not* already visible.
+ if( pPagePreviewLay->GetWinPagesScrollAmount( _bPgUp ? -1 : 1 ) != 0 )
+ {
+ if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() &&
+ pPagePreviewLay->DoesPreviewLayoutColsFitIntoWindow() )
+ {
+ const int eMvMode = _bPgUp ?
+ SwPagePreviewWin::MV_PAGE_UP :
+ SwPagePreviewWin::MV_PAGE_DOWN;
+ if ( ChgPage( eMvMode ) )
+ m_pViewWin->Invalidate();
+ }
+ else
+ {
+ SwTwips nScrollAmount;
+ sal_uInt16 nNewSelectedPageNum = 0;
+ const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
+ if( _bPgUp )
+ {
+ if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ nScrollAmount = pPagePreviewLay->GetWinPagesScrollAmount( -1 );
+ if ( (m_pViewWin->SelectedPage() - nVisPages) > 0 )
+ nNewSelectedPageNum = m_pViewWin->SelectedPage() - nVisPages;
+ else
+ nNewSelectedPageNum = 1;
+ }
+ else
+ nScrollAmount = - std::min( m_pViewWin->GetOutDev()->GetOutputSize().Height(),
+ m_pViewWin->GetPaintedPreviewDocRect().Top() );
+ }
+ else
+ {
+ if ( pPagePreviewLay->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ nScrollAmount = pPagePreviewLay->GetWinPagesScrollAmount( 1 );
+ if ( (m_pViewWin->SelectedPage() + nVisPages) <= mnPageCount )
+ nNewSelectedPageNum = m_pViewWin->SelectedPage() + nVisPages;
+ else
+ nNewSelectedPageNum = mnPageCount;
+ }
+ else
+ nScrollAmount = std::min( m_pViewWin->GetOutDev()->GetOutputSize().Height(),
+ ( pPagePreviewLay->GetPreviewDocSize().Height() -
+ m_pViewWin->GetPaintedPreviewDocRect().Bottom() ) );
+ }
+ m_pViewWin->Scroll( 0, nScrollAmount );
+ if ( nNewSelectedPageNum != 0 )
+ {
+ m_pViewWin->SetSelectedPage( nNewSelectedPageNum );
+ }
+ ScrollViewSzChg();
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ m_pViewWin->Invalidate();
+ }
+ }
+
+ if ( _pReq )
+ _pReq->Done();
+}
+
+// Then all for the SwPagePreview
+void SwPagePreview::Execute( SfxRequest &rReq )
+{
+ int eMvMode = SwPagePreviewWin::MV_DOC_END;
+ sal_Int16 nRow = 1;
+ bool bRefresh = true;
+
+ switch(rReq.GetSlot())
+ {
+ case SID_REFRESH_VIEW:
+ case FN_STAT_PAGE:
+ case FN_STAT_ZOOM:
+ break;
+
+ case FN_SHOW_MULTIPLE_PAGES:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count() >= 2 )
+ {
+ sal_Int16 nCols = pArgs->Get(SID_ATTR_TABLE_COLUMN).GetValue();
+ sal_Int16 nRows = pArgs->Get(SID_ATTR_TABLE_ROW).GetValue();
+ m_pViewWin->CalcWish( nRows, nCols );
+
+ }
+ else
+ {
+ SwPreviewZoomDlg aDlg(*m_pViewWin);
+ aDlg.execute();
+ }
+ }
+ break;
+ case FN_SHOW_BOOKVIEW:
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ bool bBookPreview = GetViewShell()->GetViewOptions()->IsPagePrevBookview();
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( FN_SHOW_BOOKVIEW, false, &pItem ) )
+ {
+ bBookPreview = static_cast< const SfxBoolItem* >( pItem )->GetValue();
+ const_cast<SwViewOption*>(GetViewShell()->GetViewOptions())->SetPagePrevBookview( bBookPreview );
+ // cast is not gentleman like, but it's common use in writer and in this case
+ }
+ if ( m_pViewWin->SetBookPreviewMode( bBookPreview ) )
+ {
+ // book preview mode changed. Thus, adjust scrollbars and
+ // invalidate corresponding states.
+ ScrollViewSzChg();
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, FN_SHOW_BOOKVIEW, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ m_pViewWin->Invalidate();
+ }
+
+ }
+ break;
+ case FN_SHOW_TWO_PAGES:
+ m_pViewWin->CalcWish( nRow, 2 );
+ break;
+
+ case FN_SHOW_SINGLE_PAGE:
+ m_pViewWin->CalcWish( nRow, 1 );
+ break;
+
+ case FN_PREVIEW_ZOOM:
+ case SID_ATTR_ZOOM:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ ScopedVclPtr<AbstractSvxZoomDialog> pDlg;
+ if(!pArgs)
+ {
+ SfxItemSetFixed<SID_ATTR_ZOOM, SID_ATTR_ZOOM> aCoreSet(GetPool());
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ SvxZoomItem aZoom( pVOpt->GetZoomType(), pVOpt->GetZoom() );
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200|
+ SvxZoomEnableFlags::WHOLEPAGE);
+ aCoreSet.Put( aZoom );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSvxZoomDialog(GetViewFrame().GetFrameWeld(), aCoreSet));
+ pDlg->SetLimits( MINZOOM, MAXZOOM );
+
+ if( pDlg->Execute() != RET_CANCEL )
+ pArgs = pDlg->GetOutputItemSet();
+ }
+ if( pArgs )
+ {
+ SvxZoomType eType = SvxZoomType::PERCENT;
+ sal_uInt16 nZoomFactor = USHRT_MAX;
+ if(const SvxZoomItem* pZoomItem = pArgs->GetItemIfSet(SID_ATTR_ZOOM))
+ {
+ eType = pZoomItem->GetType();
+ nZoomFactor = pZoomItem->GetValue();
+ }
+ else if(const SfxUInt16Item* pPreviewItem = pArgs->GetItemIfSet(FN_PREVIEW_ZOOM))
+ nZoomFactor = pPreviewItem->GetValue();
+ if(USHRT_MAX != nZoomFactor)
+ SetZoom(eType, nZoomFactor);
+ }
+ }
+ break;
+ case SID_ATTR_ZOOMSLIDER :
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SvxZoomSliderItem* pItem;
+
+ if ( pArgs && (pItem = pArgs->GetItemIfSet(SID_ATTR_ZOOMSLIDER ) ) )
+ {
+ const sal_uInt16 nCurrentZoom = pItem->GetValue();
+ SetZoom( SvxZoomType::PERCENT, nCurrentZoom );
+ }
+ }
+ break;
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ SetZoom(SvxZoomType::PERCENT,
+ lcl_GetNextZoomStep(pVOpt->GetZoom(), SID_ZOOM_IN == rReq.GetSlot()));
+ }
+ break;
+ case FN_CHAR_LEFT:
+ case FN_CHAR_RIGHT:
+ case FN_LINE_UP:
+ case FN_LINE_DOWN:
+ {
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ sal_uInt16 nNewSelectedPage;
+ sal_uInt16 nNewStartPage;
+ Point aNewStartPos;
+ sal_Int16 nHoriMove = 0;
+ sal_Int16 nVertMove = 0;
+ switch(rReq.GetSlot())
+ {
+ case FN_CHAR_LEFT: nHoriMove = -1; break;
+ case FN_CHAR_RIGHT: nHoriMove = 1; break;
+ case FN_LINE_UP: nVertMove = -1; break;
+ case FN_LINE_DOWN: nVertMove = 1; break;
+ }
+ pPagePreviewLay->CalcStartValuesForSelectedPageMove( nHoriMove, nVertMove,
+ nNewSelectedPage, nNewStartPage, aNewStartPos );
+ if ( m_pViewWin->SelectedPage() != nNewSelectedPage )
+ {
+ if ( pPagePreviewLay->IsPageVisible( nNewSelectedPage ) )
+ {
+ pPagePreviewLay->MarkNewSelectedPage( nNewSelectedPage );
+ // adjust position at vertical scrollbar.
+ SetVScrollbarThumbPos( nNewSelectedPage );
+ bRefresh = false;
+ }
+ else
+ {
+ m_pViewWin->SetSelectedPage( nNewSelectedPage );
+ m_pViewWin->SetSttPage( nNewStartPage );
+ bRefresh = ChgPage( SwPagePreviewWin::MV_SELPAGE );
+ }
+ GetViewShell()->ShowPreviewSelection( nNewSelectedPage );
+ // invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ rReq.Done();
+ }
+ else
+ {
+ bRefresh = false;
+ }
+ break;
+ }
+ case FN_PAGEUP:
+ case FN_PAGEDOWN:
+ {
+ ExecPgUpAndPgDown( rReq.GetSlot() == FN_PAGEUP, &rReq );
+ break;
+ }
+ case SID_JUMP_TO_SPECIFIC_PAGE:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count())
+ {
+ sal_uInt16 nPageNum = static_cast<const SfxUInt16Item &>(pArgs->Get(SID_JUMP_TO_SPECIFIC_PAGE)).GetValue();
+
+ if( nPageNum > 0 && nPageNum <= mnPageCount )
+ {
+ m_pViewWin->SetSttPage( nPageNum);
+ m_pViewWin->SetSelectedPage( nPageNum );
+ ChgPage( SwPagePreviewWin::MV_SPECIFIC_PAGE, false );
+ ScrollViewSzChg();
+ }
+ }
+ }
+ break;
+ case FN_START_OF_LINE:
+ case FN_START_OF_DOCUMENT:
+ eMvMode = SwPagePreviewWin::MV_DOC_STT;
+ [[fallthrough]];
+ case FN_END_OF_LINE:
+ case FN_END_OF_DOCUMENT:
+ m_pViewWin->SetSelectedPage(eMvMode == SwPagePreviewWin::MV_DOC_STT ? 1 : mnPageCount);
+ {
+ bool bRet = ChgPage( eMvMode );
+ // return value for Basic
+ rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), !bRet));
+
+ bRefresh = bRet;
+ rReq.Done();
+ }
+ break;
+
+ case FN_PRINT_PAGEPREVIEW:
+ {
+ const SwPagePreviewPrtData* pPPVPD = m_pViewWin->GetViewShell()->GetDoc()->GetPreviewPrtData();
+ // The thing with the orientation
+ if(pPPVPD)
+ {
+ SfxPrinter* pPrinter = GetPrinter( true );
+ if((pPrinter->GetOrientation() == Orientation::Landscape)
+ != pPPVPD->GetLandscape())
+ pPrinter->SetOrientation(pPPVPD->GetLandscape() ? Orientation::Landscape : Orientation::Portrait);
+ }
+ ::SetAppPrintOptions( m_pViewWin->GetViewShell(), false );
+ m_bNormalPrint = false;
+ rReq.SetSlot( SID_PRINTDOC );
+ SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ rReq.SetSlot( FN_PRINT_PAGEPREVIEW );
+ return;
+ }
+ case SID_PRINTDOCDIRECT:
+ case SID_PRINTDOC:
+ ::SetAppPrintOptions( m_pViewWin->GetViewShell(), false );
+ m_bNormalPrint = true;
+ SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ return;
+ case FN_CLOSE_PAGEPREVIEW:
+ case SID_PRINTPREVIEW:
+ // print preview is now always in the same frame as the tab view
+ // -> always switch this frame back to normal view
+ // (ScTabViewShell ctor reads stored view data)
+ GetViewFrame().GetDispatcher()->Execute( SID_VIEWSHELL0, SfxCallMode::ASYNCHRON );
+ break;
+ case FN_INSERT_BREAK:
+ {
+ sal_uInt16 nSelPage = m_pViewWin->SelectedPage();
+ //if a dummy page is selected (e.g. a non-existing right/left page)
+ //the direct neighbor is used
+ if(GetViewShell()->IsDummyPage( nSelPage ) && GetViewShell()->IsDummyPage( --nSelPage ))
+ nSelPage +=2;
+ m_nNewPage = nSelPage;
+ SfxViewFrame& rTmpFrame = GetViewFrame();
+ rTmpFrame.GetBindings().Execute( SID_VIEWSHELL0, nullptr,
+ SfxCallMode::ASYNCHRON );
+ }
+ break;
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+
+ if( bRefresh )
+ m_pViewWin->Invalidate();
+}
+
+void SwPagePreview::GetState( SfxItemSet& rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ OSL_ENSURE(nWhich, "empty set");
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_START_OF_DOCUMENT:
+ {
+ if ( pPagePreviewLay->IsPageVisible( 1 ) )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_END_OF_DOCUMENT:
+ {
+ if ( pPagePreviewLay->IsPageVisible( mnPageCount ) )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_PAGEUP:
+ {
+ if( pPagePreviewLay->GetWinPagesScrollAmount( -1 ) == 0 )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+ case FN_PAGEDOWN:
+ {
+ if( pPagePreviewLay->GetWinPagesScrollAmount( 1 ) == 0 )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case FN_STAT_PAGE:
+ {
+ std::vector<OUString> aStringList
+ {
+ m_sPageStr + m_pViewWin->GetStatusStr(mnPageCount),
+ OUString()
+ };
+ rSet.Put(SfxStringListItem(FN_STAT_PAGE, &aStringList));
+ }
+ break;
+
+ case SID_ATTR_ZOOM:
+ case FN_STAT_ZOOM:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ SvxZoomItem aZoom(pVOpt->GetZoomType(), pVOpt->GetZoom());
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200);
+ rSet.Put( aZoom );
+ }
+ break;
+ case SID_ATTR_ZOOMSLIDER :
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ const sal_uInt16 nCurrentZoom = pVOpt->GetZoom();
+ SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM );
+ aZoomSliderItem.AddSnappingPoint( 100 );
+ rSet.Put( aZoomSliderItem );
+ }
+ break;
+ case FN_PREVIEW_ZOOM:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ rSet.Put(SfxUInt16Item(nWhich, pVOpt->GetZoom()));
+ }
+ break;
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ const SwViewOption* pVOpt = GetViewShell()->GetViewOptions();
+ if((SID_ZOOM_IN == nWhich && pVOpt->GetZoom() >= MAX_PREVIEW_ZOOM) ||
+ (SID_ZOOM_OUT == nWhich && pVOpt->GetZoom() <= MIN_PREVIEW_ZOOM))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_ATTR_VIEWLAYOUT:
+ {
+ rSet.DisableItem( SID_ATTR_VIEWLAYOUT );
+ }
+ break;
+ case FN_SHOW_MULTIPLE_PAGES:
+ // should never be disabled
+ break;
+ case FN_SHOW_BOOKVIEW:
+ {
+ bool b = GetViewShell()->GetViewOptions()->IsPagePrevBookview();
+ rSet.Put(SfxBoolItem(nWhich, b));
+ }
+ break;
+
+ case FN_SHOW_TWO_PAGES:
+ if( 2 == m_pViewWin->GetCol() && 1 == m_pViewWin->GetRow() )
+ rSet.DisableItem( nWhich );
+ break;
+
+ case FN_PRINT_PAGEPREVIEW:
+ // has the same status like the normal printing
+ {
+ const SfxPoolItem* pItem;
+ SfxItemSetFixed<SID_PRINTDOC, SID_PRINTDOC> aSet( *rSet.GetPool() );
+ GetSlotState( SID_PRINTDOC, SfxViewShell::GetInterface(), &aSet );
+ if( SfxItemState::DISABLED == aSet.GetItemState( SID_PRINTDOC, false ))
+ rSet.DisableItem( nWhich );
+ else if( SfxItemState::SET == aSet.GetItemState( SID_PRINTDOC,
+ false, &pItem ))
+ {
+ const_cast<SfxPoolItem*>(pItem)->SetWhich( FN_PRINT_PAGEPREVIEW );
+ rSet.Put( *pItem );
+ }
+ }
+ break;
+
+ case SID_PRINTPREVIEW:
+ rSet.Put( SfxBoolItem( nWhich, true ) );
+ break;
+
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ GetSlotState( nWhich, SfxViewShell::GetInterface(), &rSet );
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwPagePreview::StateUndo(SfxItemSet& rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwPagePreview::Init()
+{
+ if ( GetViewShell()->HasDrawView() )
+ GetViewShell()->GetDrawView()->SetAnimationEnabled( false );
+
+ m_bNormalPrint = true;
+
+ // Check and process the DocSize. The shell could not be found via
+ // the handler, because the shell is unknown to the SFX management
+ // within the CTOR phase.
+
+ const SwViewOption * pPrefs = SW_MOD()->GetUsrPref(false);
+
+ mbHScrollbarEnabled = pPrefs->IsViewHScrollBar();
+ mbVScrollbarEnabled = pPrefs->IsViewVScrollBar();
+
+ // Update the fields
+ // ATTENTION: Do cast the EditShell up, to use the SS.
+ // At the methods the current shell will be queried!
+ SwEditShell* pESh = dynamic_cast<SwEditShell*>(GetViewShell());
+ bool bIsModified = pESh != nullptr && pESh->IsModified();
+
+ SwViewOption aOpt( *pPrefs );
+ aOpt.SetPagePreview(true);
+ aOpt.SetTab( false );
+ aOpt.SetBlank( false );
+ aOpt.SetHardBlank( false );
+ aOpt.SetParagraph( false );
+ aOpt.SetLineBreak( false );
+ aOpt.SetPageBreak( false );
+ aOpt.SetColumnBreak( false );
+ aOpt.SetSoftHyph( false );
+ aOpt.SetFieldName( false );
+ aOpt.SetPostIts( false );
+ aOpt.SetShowBookmarks( false );
+ aOpt.SetShowHiddenChar( false );
+ aOpt.SetShowHiddenField( false );
+ aOpt.SetShowHiddenPara( false );
+ aOpt.SetViewHRuler( false );
+ aOpt.SetViewVRuler( false );
+ aOpt.SetGraphic( true );
+ aOpt.SetTable( true );
+ aOpt.SetSnap( false );
+ aOpt.SetGridVisible( false );
+ aOpt.SetOnlineSpell( false );
+ aOpt.SetHideWhitespaceMode( false );
+
+ GetViewShell()->ApplyViewOptions( aOpt );
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ GetViewShell()->ApplyAccessibilityOptions();
+#endif
+
+ // adjust view shell option to the same as for print
+ SwPrintData const aPrintOptions = *SW_MOD()->GetPrtOptions(false);
+ GetViewShell()->AdjustOptionsForPagePreview( aPrintOptions );
+
+ GetViewShell()->CalcLayout();
+ DocSzChgd( GetViewShell()->GetDocSize() );
+
+ if( !bIsModified && pESh != nullptr )
+ pESh->ResetModified();
+}
+
+SwPagePreview::SwPagePreview(SfxViewFrame& rViewFrame, SfxViewShell* pOldSh):
+ SfxViewShell(rViewFrame, SWVIEWFLAGS),
+ m_pViewWin( VclPtr<SwPagePreviewWin>::Create(&GetViewFrame().GetWindow(), *this ) ),
+ m_nNewPage(USHRT_MAX),
+ m_sPageStr(SwResId(STR_PAGE)),
+ m_pHScrollbar(nullptr),
+ m_pVScrollbar(nullptr),
+ mnPageCount( 0 ),
+ mbResetFormDesignMode( false ),
+ mbFormDesignModeToReset( false )
+{
+ SetName("PageView");
+ SetWindow( m_pViewWin );
+ CreateScrollbar( true );
+ CreateScrollbar( false );
+
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Printpreview));
+
+ SfxObjectShell* pObjShell = rViewFrame.GetObjectShell();
+ if ( !pOldSh )
+ {
+ // Exists already a view on the document?
+ SfxViewFrame *pF = SfxViewFrame::GetFirst( pObjShell );
+ if (pF == &rViewFrame)
+ pF = SfxViewFrame::GetNext( *pF, pObjShell );
+ if ( pF )
+ pOldSh = pF->GetViewShell();
+ }
+
+ SwViewShell *pVS, *pNew;
+
+ if (SwPagePreview* pPagePreview = dynamic_cast<SwPagePreview*>(pOldSh))
+ pVS = pPagePreview->GetViewShell();
+ else
+ {
+ if (SwView* pView = dynamic_cast<SwView *>(pOldSh))
+ {
+ pVS = pView->GetWrtShellPtr();
+ // save the current ViewData of the previous SwView
+ pOldSh->WriteUserData( m_sSwViewData );
+ }
+ else
+ pVS = GetDocShell()->GetWrtShell();
+ if( pVS )
+ {
+ // Set the current page as the first.
+ sal_uInt16 nPhysPg, nVirtPg;
+ static_cast<SwCursorShell*>(pVS)->GetPageNum( nPhysPg, nVirtPg, true, false );
+ if( 1 != m_pViewWin->GetCol() && 1 == nPhysPg )
+ --nPhysPg;
+ m_pViewWin->SetSttPage( nPhysPg );
+ }
+ }
+
+ // for form shell remember design mode of draw view
+ // of previous view shell
+ if ( pVS && pVS->HasDrawView() )
+ {
+ mbResetFormDesignMode = true;
+ mbFormDesignModeToReset = pVS->GetDrawView()->IsDesignMode();
+ }
+
+ if( pVS )
+ pNew = new SwViewShell( *pVS, m_pViewWin, nullptr, VSHELLFLAG_ISPREVIEW );
+ else
+ pNew = new SwViewShell(
+ *static_cast<SwDocShell*>(rViewFrame.GetObjectShell())->GetDoc(),
+ m_pViewWin, nullptr, nullptr, VSHELLFLAG_ISPREVIEW );
+
+ m_pViewWin->SetViewShell( pNew );
+ pNew->SetSfxViewShell( this );
+ Init();
+}
+
+SwPagePreview::~SwPagePreview()
+{
+ SetWindow( nullptr );
+ SwViewShell* pVShell = m_pViewWin->GetViewShell();
+ pVShell->SetWin(nullptr);
+ delete pVShell;
+
+ m_pViewWin.disposeAndClear();
+ m_pHScrollbar.disposeAndClear();
+ m_pVScrollbar.disposeAndClear();
+}
+
+void SwPagePreview::Activate(bool bMDI)
+{
+ SfxViewShell::Activate(bMDI);
+ SfxShell::Activate(bMDI);
+}
+
+SwDocShell* SwPagePreview::GetDocShell()
+{
+ return dynamic_cast<SwDocShell*>( GetViewFrame().GetObjectShell() );
+}
+
+void SwPagePreview::CreateScrollbar( bool bHori )
+{
+ vcl::Window *pMDI = &GetViewFrame().GetWindow();
+ VclPtr<SwScrollbar>& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar;
+
+ assert(!ppScrollbar); //check beforehand!
+ ppScrollbar = VclPtr<SwScrollbar>::Create( pMDI, bHori );
+
+ ScrollDocSzChg();
+
+ if (bHori)
+ ppScrollbar->SetScrollHdl( LINK( this, SwPagePreview, HoriScrollHdl ));
+ else
+ ppScrollbar->SetScrollHdl( LINK( this, SwPagePreview, VertScrollHdl ));
+
+ InvalidateBorder();
+ ppScrollbar->ExtendedShow();
+}
+
+bool SwPagePreview::ChgPage( int eMvMode, bool bUpdateScrollbar )
+{
+ tools::Rectangle aPixVisArea( m_pViewWin->LogicToPixel( m_aVisArea ) );
+ bool bChg = m_pViewWin->MovePage( eMvMode ) ||
+ eMvMode == SwPagePreviewWin::MV_CALC ||
+ eMvMode == SwPagePreviewWin::MV_NEWWINSIZE;
+ m_aVisArea = m_pViewWin->PixelToLogic( aPixVisArea );
+
+ if( bChg )
+ {
+ // Update statusbar
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+
+ if( bUpdateScrollbar )
+ {
+ ScrollViewSzChg();
+
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT,
+ FN_PAGEUP, FN_PAGEDOWN, 0
+ };
+ rBindings.Invalidate( aInval );
+ }
+ std::vector<OUString> aStringList
+ {
+ m_sPageStr + m_pViewWin->GetStatusStr(mnPageCount),
+ OUString()
+ };
+ rBindings.SetState(SfxStringListItem(FN_STAT_PAGE, &aStringList));
+ }
+ return bChg;
+}
+
+// From here, everything was taken from the SwView.
+void SwPagePreview::CalcAndSetBorderPixel( SvBorder &rToFill )
+{
+ const StyleSettings &rSet = m_pViewWin->GetSettings().GetStyleSettings();
+ const tools::Long nTmp = rSet.GetScrollBarSize();
+ if (m_pVScrollbar->IsScrollbarVisible(true))
+ rToFill.Right() = nTmp;
+ if (m_pHScrollbar->IsScrollbarVisible(true))
+ rToFill.Bottom() = nTmp;
+ SetBorderPixel( rToFill );
+}
+
+void SwPagePreview::InnerResizePixel( const Point &rOfst, const Size &rSize, bool )
+{
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+ tools::Rectangle aRect( rOfst, rSize );
+ aRect += aBorder;
+ ViewResizePixel( *m_pViewWin->GetOutDev(), aRect.TopLeft(), aRect.GetSize(),
+ m_pViewWin->GetOutputSizePixel(),
+ *m_pVScrollbar, *m_pHScrollbar );
+
+ // Never set EditWin !
+ // Never set VisArea !
+}
+
+void SwPagePreview::OuterResizePixel( const Point &rOfst, const Size &rSize )
+{
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+
+ // Never set EditWin !
+
+ Size aTmpSize( m_pViewWin->GetOutputSizePixel() );
+ Point aBottomRight( m_pViewWin->PixelToLogic( Point( aTmpSize.Width(), aTmpSize.Height() ) ) );
+ SetVisArea( tools::Rectangle( Point(), aBottomRight ) );
+
+ // Call of the DocSzChgd-Method of the scrollbars is necessary,
+ // because from the maximum scroll range half the height of the
+ // VisArea is always deducted.
+ if ( m_pVScrollbar && !aTmpSize.IsEmpty() )
+ {
+ ScrollDocSzChg();
+ }
+
+ SvBorder aBorderNew;
+ CalcAndSetBorderPixel( aBorderNew );
+ ViewResizePixel( *m_pViewWin->GetOutDev(), rOfst, rSize, m_pViewWin->GetOutputSizePixel(),
+ *m_pVScrollbar, *m_pHScrollbar );
+}
+
+void SwPagePreview::SetVisArea( const tools::Rectangle &rRect )
+{
+ const Point aTopLeft(AlignToPixel(rRect.TopLeft()));
+ const Point aBottomRight(AlignToPixel(rRect.BottomRight()));
+ tools::Rectangle aLR(aTopLeft,aBottomRight);
+
+ if(aLR == m_aVisArea)
+ return;
+ // No negative position, no negative size
+
+ if(aLR.Top() < 0)
+ {
+ aLR.AdjustBottom(std::abs(aLR.Top()) );
+ aLR.SetTop( 0 );
+ }
+
+ if(aLR.Left() < 0)
+ {
+ aLR.AdjustRight(std::abs(aLR.Left()) );
+ aLR.SetLeft( 0 );
+ }
+ if(aLR.Right() < 0) aLR.SetRight( 0 );
+ if(aLR.Bottom() < 0) aLR.SetBottom( 0 );
+ if(aLR == m_aVisArea ||
+ // Ignore empty rectangle
+ ( 0 == aLR.Bottom() - aLR.Top() && 0 == aLR.Right() - aLR.Left() ) )
+ return;
+
+ if( aLR.Left() > aLR.Right() || aLR.Top() > aLR.Bottom() )
+ return;
+
+ // Before the data can be changed call an update if necessary.
+ // Thereby ensured, that adjacent paints are correctly converted into
+ // document coordinates.
+ // As a precaution, we do this only when at the shell runs an action,
+ // because then we do not really paint but the rectangles are just
+ // bookmarked (in document coordinates).
+ if( GetViewShell()->ActionPend() )
+ m_pViewWin->PaintImmediately();
+
+ // Set at View-Win the current size
+ m_aVisArea = aLR;
+ m_pViewWin->SetWinSize( aLR.GetSize() );
+ ChgPage( SwPagePreviewWin::MV_NEWWINSIZE );
+
+ m_pViewWin->Invalidate();
+}
+
+IMPL_LINK(SwPagePreview, HoriScrollHdl, weld::Scrollbar&, rScrollbar, void)
+{
+ ScrollHdl(rScrollbar, true);
+}
+
+IMPL_LINK(SwPagePreview, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
+{
+ ScrollHdl(rScrollbar, false);
+}
+
+void SwPagePreview::ScrollHdl(weld::Scrollbar& rScrollbar, bool bHori)
+{
+ if(!GetViewShell())
+ return;
+
+ EndScrollHdl(rScrollbar, bHori);
+
+ if( !bHori &&
+ rScrollbar.get_scroll_type() == ScrollType::Drag &&
+ Help::IsQuickHelpEnabled() &&
+ GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow())
+ {
+ // Scroll how many pages??
+ OUString sStateStr(m_sPageStr);
+ tools::Long nThmbPos = rScrollbar.adjustment_get_value();
+ if( 1 == m_pViewWin->GetCol() || !nThmbPos )
+ ++nThmbPos;
+ sStateStr += OUString::number( nThmbPos );
+ Point aPos = m_pVScrollbar->GetParent()->OutputToScreenPixel(
+ m_pVScrollbar->GetPosPixel());
+ aPos.setY( m_pVScrollbar->OutputToScreenPixel(m_pVScrollbar->GetPointerPosPixel()).Y() );
+ tools::Rectangle aRect;
+ aRect.SetLeft( aPos.X() -8 );
+ aRect.SetRight( aRect.Left() );
+ aRect.SetTop( aPos.Y() );
+ aRect.SetBottom( aRect.Top() );
+
+ Help::ShowQuickHelp(m_pVScrollbar, aRect, sStateStr,
+ QuickHelpFlags::Right|QuickHelpFlags::VCenter);
+
+ }
+}
+
+void SwPagePreview::EndScrollHdl(weld::Scrollbar& rScrollbar, bool bHori)
+{
+ if(!GetViewShell())
+ return;
+
+ // boolean to avoid unnecessary invalidation of the window.
+ bool bInvalidateWin = true;
+
+ if (!bHori) // scroll vertically
+ {
+ if ( Help::IsQuickHelpEnabled() )
+ Help::ShowQuickHelp(m_pVScrollbar, tools::Rectangle(), OUString());
+ if ( GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow() )
+ {
+ // Scroll how many pages ??
+ const sal_uInt16 nThmbPos = o3tl::narrowing<sal_uInt16>(rScrollbar.adjustment_get_value());
+ // adjust to new preview functionality
+ if( nThmbPos != m_pViewWin->SelectedPage() )
+ {
+ // consider case that page <nThmbPos>
+ // is already visible
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ if ( pPagePreviewLay->IsPageVisible( nThmbPos ) )
+ {
+ pPagePreviewLay->MarkNewSelectedPage( nThmbPos );
+ // invalidation of window is unnecessary
+ bInvalidateWin = false;
+ }
+ else
+ {
+ // consider whether layout columns
+ // fit or not.
+ if ( !pPagePreviewLay->DoesPreviewLayoutColsFitIntoWindow() )
+ {
+ m_pViewWin->SetSttPage( nThmbPos );
+ m_pViewWin->SetSelectedPage( nThmbPos );
+ ChgPage( SwPagePreviewWin::MV_SCROLL, false );
+ // update scrollbars
+ ScrollViewSzChg();
+ }
+ else
+ {
+ // correct scroll amount
+ const sal_Int16 nPageDiff = nThmbPos - m_pViewWin->SelectedPage();
+ const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
+ sal_Int16 nWinPagesToScroll = nPageDiff / nVisPages;
+ if ( nPageDiff % nVisPages )
+ {
+ // decrease/increase number of preview pages to scroll
+ nPageDiff < 0 ? --nWinPagesToScroll : ++nWinPagesToScroll;
+ }
+ m_pViewWin->SetSelectedPage( nThmbPos );
+ m_pViewWin->Scroll( 0, pPagePreviewLay->GetWinPagesScrollAmount( nWinPagesToScroll ) );
+ }
+ }
+ // update accessibility
+ GetViewShell()->ShowPreviewSelection( nThmbPos );
+ }
+ else
+ {
+ // invalidation of window is unnecessary
+ bInvalidateWin = false;
+ }
+ }
+ else
+ {
+ tools::Long nThmbPos = rScrollbar.adjustment_get_value();
+ m_pViewWin->Scroll(0, nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Top());
+ }
+ }
+ else
+ {
+ tools::Long nThmbPos = rScrollbar.adjustment_get_value();
+ m_pViewWin->Scroll(nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Left(), 0);
+ }
+ // additional invalidate page status.
+ static sal_uInt16 aInval[] =
+ {
+ FN_START_OF_DOCUMENT, FN_END_OF_DOCUMENT, FN_PAGEUP, FN_PAGEDOWN,
+ FN_STAT_PAGE, 0
+ };
+ SfxBindings& rBindings = GetViewFrame().GetBindings();
+ rBindings.Invalidate( aInval );
+ // control invalidation of window
+ if ( bInvalidateWin )
+ {
+ m_pViewWin->Invalidate();
+ }
+}
+
+Point SwPagePreview::AlignToPixel(const Point &rPt) const
+{
+ return m_pViewWin->PixelToLogic( m_pViewWin->LogicToPixel( rPt ) );
+}
+
+void SwPagePreview::DocSzChgd( const Size &rSz )
+{
+ if( m_aDocSize == rSz )
+ return;
+
+ m_aDocSize = rSz;
+
+ // #i96726#
+ // Due to the multiple page layout it is needed to trigger recalculation
+ // of the page preview layout, even if the count of pages is not changing.
+ mnPageCount = GetViewShell()->GetNumPages();
+
+ if( m_aVisArea.GetWidth() )
+ {
+ ChgPage( SwPagePreviewWin::MV_CALC );
+ ScrollDocSzChg();
+
+ m_pViewWin->Invalidate();
+ }
+}
+
+void SwPagePreview::ScrollViewSzChg()
+{
+ if(!GetViewShell())
+ return ;
+
+ bool bShowVScrollbar = false, bShowHScrollbar = false;
+
+ if(m_pVScrollbar)
+ {
+ if(GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow())
+ {
+ //vertical scrolling by row
+ // adjust to new preview functionality
+ const sal_uInt16 nVisPages = m_pViewWin->GetRow() * m_pViewWin->GetCol();
+
+ m_pVScrollbar->SetVisibleSize( nVisPages );
+ // set selected page as scroll bar position,
+ // if it is visible.
+ SwPagePreviewLayout* pPagePreviewLay = GetViewShell()->PagePreviewLayout();
+ if ( pPagePreviewLay->IsPageVisible( m_pViewWin->SelectedPage() ) )
+ {
+ m_pVScrollbar->SetThumbPos( m_pViewWin->SelectedPage() );
+ }
+ else
+ {
+ m_pVScrollbar->SetThumbPos( m_pViewWin->GetSttPage() );
+ }
+ m_pVScrollbar->SetLineSize( m_pViewWin->GetCol() );
+ m_pVScrollbar->SetPageSize( nVisPages );
+ // calculate and set scrollbar range
+ Range aScrollbarRange( 1, mnPageCount );
+ // increase range by one, because left-top-corner is left blank.
+ ++aScrollbarRange.Max();
+ // increase range in order to access all pages
+ aScrollbarRange.Max() += ( nVisPages - 1 );
+ m_pVScrollbar->SetRange( aScrollbarRange );
+
+ bShowVScrollbar = nVisPages < mnPageCount;
+ }
+ else //vertical scrolling by pixel
+ {
+ const tools::Rectangle& rDocRect = m_pViewWin->GetPaintedPreviewDocRect();
+ const Size& rPreviewSize =
+ GetViewShell()->PagePreviewLayout()->GetPreviewDocSize();
+ m_pVScrollbar->SetRangeMax(rPreviewSize.Height()) ;
+ tools::Long nVisHeight = rDocRect.GetHeight();
+ m_pVScrollbar->SetVisibleSize( nVisHeight );
+ m_pVScrollbar->SetThumbPos( rDocRect.Top() );
+ m_pVScrollbar->SetLineSize( nVisHeight / 10 );
+ m_pVScrollbar->SetPageSize( nVisHeight / 2 );
+
+ bShowVScrollbar = true;
+ }
+
+ if (!mbVScrollbarEnabled)
+ bShowVScrollbar = false;
+
+ ShowVScrollbar(bShowVScrollbar);
+ }
+ if(m_pHScrollbar)
+ {
+ const tools::Rectangle& rDocRect = m_pViewWin->GetPaintedPreviewDocRect();
+ const Size& rPreviewSize =
+ GetViewShell()->PagePreviewLayout()->GetPreviewDocSize();
+ Range aRange(0,0);
+
+ if(rDocRect.GetWidth() < rPreviewSize.Width())
+ {
+ bShowHScrollbar = true;
+
+ tools::Long nVisWidth = rDocRect.GetWidth();
+ tools::Long nThumb = rDocRect.Left();
+ aRange = Range(0, rPreviewSize.Width());
+
+ m_pHScrollbar->SetRange( aRange );
+ m_pHScrollbar->SetVisibleSize( nVisWidth );
+ m_pHScrollbar->SetThumbPos( nThumb );
+ m_pHScrollbar->SetLineSize( nVisWidth / 10 );
+ m_pHScrollbar->SetPageSize( nVisWidth / 2 );
+ }
+
+ if (!mbHScrollbarEnabled)
+ bShowHScrollbar = false;
+
+ ShowHScrollbar(bShowHScrollbar);
+ }
+}
+
+void SwPagePreview::ScrollDocSzChg()
+{
+ ScrollViewSzChg();
+}
+
+// All about printing
+SfxPrinter* SwPagePreview::GetPrinter( bool bCreate )
+{
+ return m_pViewWin->GetViewShell()->getIDocumentDeviceAccess().getPrinter( bCreate );
+}
+
+sal_uInt16 SwPagePreview::SetPrinter( SfxPrinter *pNew, SfxPrinterChangeFlags nDiffFlags )
+{
+ SwViewShell &rSh = *GetViewShell();
+ SfxPrinter* pOld = rSh.getIDocumentDeviceAccess().getPrinter( false );
+ if ( pOld && pOld->IsPrinting() )
+ return SFX_PRINTERROR_BUSY;
+
+ SwEditShell &rESh = static_cast<SwEditShell&>(rSh); //Buh...
+ if( ( SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP ) & nDiffFlags )
+ {
+ rSh.getIDocumentDeviceAccess().setPrinter( pNew, true, true );
+ if( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
+ rESh.SetModified();
+ }
+ if ( ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS ) == SfxPrinterChangeFlags::OPTIONS )
+ ::SetPrinter( &rSh.getIDocumentDeviceAccess(), pNew, false );
+
+ const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
+ if ( bChgOri || bChgSize )
+ {
+ rESh.StartAllAction();
+ if ( bChgOri )
+ rSh.ChgAllPageOrientation( pNew->GetOrientation() );
+ if ( bChgSize )
+ {
+ Size aSz( SvxPaperInfo::GetPaperSize( pNew ) );
+ rSh.ChgAllPageSize( aSz );
+ }
+ if( !m_bNormalPrint )
+ m_pViewWin->CalcWish( m_pViewWin->GetRow(), m_pViewWin->GetCol() );
+ rESh.SetModified();
+ rESh.EndAllAction();
+
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_LONG_ULSPACE, SID_ATTR_LONG_LRSPACE,
+ SID_RULER_BORDERS, SID_RULER_PAGE_POS, 0
+ };
+#if OSL_DEBUG_LEVEL > 0
+ {
+ const sal_uInt16* pPtr = aInval + 1;
+ do {
+ OSL_ENSURE( *(pPtr - 1) < *pPtr, "wrong sorting!" );
+ } while( *++pPtr );
+ }
+#endif
+
+ GetViewFrame().GetBindings().Invalidate(aInval);
+ }
+
+ return 0;
+}
+
+bool SwPagePreview::HasPrintOptionsPage() const
+{
+ return true;
+}
+
+std::unique_ptr<SfxTabPage> SwPagePreview::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet &rOptions)
+{
+ return ::CreatePrintOptionsPage(pPage, pController, rOptions, !m_bNormalPrint);
+}
+
+void SwPagePreviewWin::SetViewShell( SwViewShell* pShell )
+{
+ mpViewShell = pShell;
+ if ( mpViewShell && mpViewShell->IsPreview() )
+ {
+ mpPgPreviewLayout = mpViewShell->PagePreviewLayout();
+ }
+}
+
+void SwPagePreviewWin::RepaintCoreRect( const SwRect& rRect )
+{
+ // #i24183#
+ if ( mpPgPreviewLayout->PreviewLayoutValid() )
+ {
+ mpPgPreviewLayout->Repaint( tools::Rectangle( rRect.Pos(), rRect.SSize() ) );
+ }
+}
+
+/** method to adjust preview to a new zoom factor
+
+ #i19975# also consider zoom type - adding parameter <_eZoomType>
+*/
+void SwPagePreviewWin::AdjustPreviewToNewZoom( const sal_uInt16 _nZoomFactor,
+ const SvxZoomType _eZoomType )
+{
+ // #i19975# consider zoom type
+ if ( _eZoomType == SvxZoomType::WHOLEPAGE )
+ {
+ mnRow = 1;
+ mnCol = 1;
+ mpPgPreviewLayout->Init( mnCol, mnRow, maPxWinSize );
+ mpPgPreviewLayout->Prepare( mnSttPage, Point(0,0), maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ SetSelectedPage( mnSttPage );
+ SetPagePreview(mnRow, mnCol);
+ maScale = GetMapMode().GetScaleX();
+ }
+ else if ( _nZoomFactor != 0 )
+ {
+ // calculate new scaling and set mapping mode appropriately.
+ Fraction aNewScale( _nZoomFactor, 100 );
+ MapMode aNewMapMode = GetMapMode();
+ aNewMapMode.SetScaleX( aNewScale );
+ aNewMapMode.SetScaleY( aNewScale );
+ SetMapMode( aNewMapMode );
+
+ // calculate new start position for preview paint
+ Size aNewWinSize = PixelToLogic( maPxWinSize );
+ Point aNewPaintStartPos =
+ mpPgPreviewLayout->GetPreviewStartPosForNewScale( aNewScale, maScale, aNewWinSize );
+
+ // remember new scaling and prepare preview paint
+ // Note: paint of preview will be performed by a corresponding invalidate
+ // due to property changes.
+ maScale = aNewScale;
+ mpPgPreviewLayout->Prepare( 0, aNewPaintStartPos, maPxWinSize,
+ mnSttPage, maPaintedPreviewDocRect );
+ }
+
+}
+
+/**
+ * pixel scrolling - horizontally always or vertically
+ * when less than the desired number of rows fits into
+ * the view
+ */
+void SwPagePreviewWin::Scroll(tools::Long nXMove, tools::Long nYMove, ScrollFlags /*nFlags*/)
+{
+ maPaintedPreviewDocRect.Move(nXMove, nYMove);
+ mpPgPreviewLayout->Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
+ maPxWinSize, mnSttPage,
+ maPaintedPreviewDocRect );
+
+}
+
+bool SwPagePreview::HandleWheelCommands( const CommandEvent& rCEvt )
+{
+ bool bOk = false;
+ const CommandWheelData* pWData = rCEvt.GetWheelData();
+ if( pWData && CommandWheelMode::ZOOM == pWData->GetMode() )
+ {
+ //only the Preference shouldn't control the Zoom, it is better to detect AT tools running. So the bridge can be used here
+ if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport())
+ {
+ sal_uInt16 nFactor = GetViewShell()->GetViewOptions()->GetZoom();
+ const sal_uInt16 nOffset = 10;
+ if( 0L > pWData->GetDelta() )
+ {
+ nFactor -= nOffset;
+ if(nFactor < MIN_PREVIEW_ZOOM)
+ nFactor = MIN_PREVIEW_ZOOM;
+ }
+ else
+ {
+ nFactor += nOffset;
+ if(nFactor > MAX_PREVIEW_ZOOM)
+ nFactor = MAX_PREVIEW_ZOOM;
+ }
+ SetZoom(SvxZoomType::PERCENT, nFactor);
+ }
+ bOk = true;
+ }
+ else
+ bOk = m_pViewWin->HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
+ return bOk;
+}
+
+uno::Reference< css::accessibility::XAccessible >
+ SwPagePreviewWin::CreateAccessible()
+{
+ SolarMutexGuard aGuard; // this should have happened already!!!
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ OSL_ENSURE( GetViewShell() != nullptr, "We need a view shell" );
+ css::uno::Reference< css::accessibility::XAccessible > xAcc = GetAccessible( false );
+ if (xAcc.is())
+ {
+ return xAcc;
+ }
+ if (mpViewShell)
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xAccPreview = mpViewShell->CreateAccessiblePreview();
+ SetAccessible(xAccPreview);
+ }
+#endif
+ return GetAccessible( false );
+}
+
+void SwPagePreview::ApplyAccessibilityOptions()
+{
+ GetViewShell()->ApplyAccessibilityOptions();
+}
+
+void SwPagePreview::ShowHScrollbar(bool bShow)
+{
+ m_pHScrollbar->Show(bShow);
+ InvalidateBorder();
+}
+
+void SwPagePreview::ShowVScrollbar(bool bShow)
+{
+ m_pVScrollbar->Show(bShow);
+ InvalidateBorder();
+}
+
+void SwPagePreview::EnableHScrollbar(bool bEnable)
+{
+ if (mbHScrollbarEnabled != bEnable)
+ {
+ mbHScrollbarEnabled = bEnable;
+ ScrollViewSzChg();
+ }
+}
+
+void SwPagePreview::EnableVScrollbar(bool bEnable)
+{
+ if (mbVScrollbarEnabled != bEnable)
+ {
+ mbVScrollbarEnabled = bEnable;
+ ScrollViewSzChg();
+ }
+}
+
+void SwPagePreview::SetZoom(SvxZoomType eType, sal_uInt16 nFactor)
+{
+ SwViewShell& rSh = *GetViewShell();
+ SwViewOption aOpt(*rSh.GetViewOptions());
+ // perform action only on changes of zoom or zoom type.
+ if ( aOpt.GetZoom() != nFactor ||
+ aOpt.GetZoomType() != eType )
+ {
+ aOpt.SetZoom(nFactor);
+ aOpt.SetZoomType(eType);
+ rSh.ApplyViewOptions( aOpt );
+ lcl_InvalidateZoomSlots(GetViewFrame().GetBindings());
+ // #i19975# also consider zoom type
+ m_pViewWin->AdjustPreviewToNewZoom( nFactor, eType );
+ ScrollViewSzChg();
+ }
+}
+
+/** adjust position of vertical scrollbar */
+void SwPagePreview::SetVScrollbarThumbPos( const sal_uInt16 _nNewThumbPos )
+{
+ if ( m_pVScrollbar )
+ {
+ m_pVScrollbar->SetThumbPos( _nNewThumbPos );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/scroll.cxx b/sw/source/uibase/uiview/scroll.cxx
new file mode 100644
index 0000000000..7b1d7f915a
--- /dev/null
+++ b/sw/source/uibase/uiview/scroll.cxx
@@ -0,0 +1,116 @@
+/* -*- 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 <scroll.hxx>
+
+#define SCROLL_LINE_SIZE 250
+
+SwScrollbar::SwScrollbar(vcl::Window *pWin, bool bHoriz)
+ : ScrollAdaptor(pWin, bHoriz)
+ , m_bAuto(false)
+ , m_bVisible(false)
+ , m_bSizeSet(false)
+{
+ m_xScrollBar->show();
+
+ // No mirroring for horizontal scrollbars
+ if (bHoriz)
+ m_xScrollBar->set_direction(false);
+}
+
+// Will be called after a change of the document size
+// to refresh the range of the scrollbars.
+void SwScrollbar::DocSzChgd( const Size &rSize )
+{
+ m_aDocSz = rSize;
+ SetRange( Range( 0, m_bHori ? rSize.Width() : rSize.Height()) );
+ const tools::Long nVisSize = GetVisibleSize();
+ SetLineSize( SCROLL_LINE_SIZE );
+ SetPageSize( nVisSize * 77 / 100 );
+}
+
+// Will be called after a change of the visible view section.
+void SwScrollbar::ViewPortChgd( const tools::Rectangle &rRect )
+{
+ tools::Long nThumb, nVisible;
+ if( m_bHori )
+ {
+ nThumb = rRect.Left();
+ nVisible = rRect.GetWidth();
+ }
+ else
+ {
+ nThumb = rRect.Top();
+ nVisible = rRect.GetHeight();
+ }
+
+ SetVisibleSize( nVisible );
+ DocSzChgd(m_aDocSz);
+ SetThumbPos( nThumb );
+ if(m_bAuto)
+ AutoShow();
+}
+
+void SwScrollbar::ExtendedShow( bool bSet )
+{
+ m_bVisible = bSet;
+ if( (!bSet || !m_bAuto) && IsUpdateMode() && m_bSizeSet)
+ {
+ ScrollAdaptor::Show(bSet);
+ }
+}
+
+void SwScrollbar::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
+{
+ ScrollAdaptor::SetPosSizePixel(rNewPos, rNewSize);
+ m_bSizeSet = true;
+ if(m_bVisible)
+ ExtendedShow();
+}
+
+void SwScrollbar::SetAuto(bool bSet)
+{
+ if(m_bAuto != bSet)
+ {
+ m_bAuto = bSet;
+
+ // hide automatically - then show
+ if(!m_bAuto && m_bVisible && !ScrollAdaptor::IsVisible())
+ ExtendedShow();
+ else if(m_bAuto)
+ AutoShow(); // or hide automatically
+ }
+}
+
+void SwScrollbar::AutoShow()
+{
+ tools::Long nVis = GetVisibleSize();
+ tools::Long nLen = GetRange().Len();
+ if (nVis >= nLen - 1)
+ {
+ if (ScrollAdaptor::IsVisible())
+ ScrollAdaptor::Show(false);
+ }
+ else if (!ScrollAdaptor::IsVisible())
+ {
+ ScrollAdaptor::Show();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/srcview.cxx b/sw/source/uibase/uiview/srcview.cxx
new file mode 100644
index 0000000000..563dd0b468
--- /dev/null
+++ b/sw/source/uibase/uiview/srcview.cxx
@@ -0,0 +1,839 @@
+/* -*- 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 <rtl/tencinfo.h>
+#include <osl/diagnose.h>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <unotools/tempfile.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/errinf.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/textview.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/undo.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <vcl/transfer.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/docfile.hxx>
+#include <svx/srchdlg.hxx>
+#include <svx/statusitem.hxx>
+#include <svl/srchitem.hxx>
+#include <sfx2/sfxhtml.hxx>
+#include <swtypes.hxx>
+#include <docsh.hxx>
+#include <wdocsh.hxx>
+#include <srcview.hxx>
+#include "viewfunc.hxx"
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentState.hxx>
+#include <sfx2/msg.hxx>
+#include <shellio.hxx>
+
+#include <cmdid.h>
+#include <strings.hrc>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <sfx2/filedlghelper.hxx>
+#define ShellClass_SwSrcView
+#include <swslots.hxx>
+
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::sfx2;
+
+#define SWSRCVIEWFLAGS SfxViewShellFlags::NO_NEWWINDOW
+
+#define SRC_SEARCHOPTIONS (SearchOptionFlags::ALL & ~SearchOptionFlags(SearchOptionFlags::FORMAT|SearchOptionFlags::FAMILIES|SearchOptionFlags::SEARCHALL))
+
+// Printing margins -> like Basic - Ide
+#define LMARGPRN 1700
+#define RMARGPRN 900
+#define TMARGPRN 2000
+#define BMARGPRN 1000
+#define BORDERPRN 300
+
+SFX_IMPL_NAMED_VIEWFACTORY(SwSrcView, "SourceView")
+{
+ SFX_VIEW_REGISTRATION(SwWebDocShell);
+}
+
+SFX_IMPL_SUPERCLASS_INTERFACE(SwSrcView, SfxViewShell)
+
+void SwSrcView::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterPopupMenu("source");
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS,
+ SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server,
+ ToolbarId::Webtools_Toolbox);
+
+ GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId());
+}
+
+
+static void lcl_PrintHeader( vcl::RenderContext &rOutDev, sal_Int32 nPages, sal_Int32 nCurPage, const OUString& rTitle )
+{
+ short nLeftMargin = LMARGPRN;
+ Size aSz = rOutDev.GetOutputSize();
+ short nBorder = BORDERPRN;
+
+ Color aOldFillColor( rOutDev.GetFillColor() );
+ vcl::Font aOldFont( rOutDev.GetFont() );
+
+ rOutDev.SetFillColor( COL_TRANSPARENT );
+
+ vcl::Font aFont( aOldFont );
+ aFont.SetWeight( WEIGHT_BOLD );
+ aFont.SetAlignment( ALIGN_BOTTOM );
+ rOutDev.SetFont( aFont );
+
+ tools::Long nFontHeight = rOutDev.GetTextHeight();
+
+ // 1.Border => Line, 2+3 Border = Space.
+ tools::Long nYTop = TMARGPRN-3*nBorder-nFontHeight;
+
+ tools::Long nXLeft = nLeftMargin-nBorder;
+ tools::Long nXRight = aSz.Width()-RMARGPRN+nBorder;
+
+ rOutDev.DrawRect( tools::Rectangle(
+ Point( nXLeft, nYTop ),
+ Size( nXRight-nXLeft, aSz.Height() - nYTop - BMARGPRN + nBorder ) ) );
+
+ tools::Long nY = TMARGPRN-2*nBorder;
+ Point aPos( nLeftMargin, nY );
+ rOutDev.DrawText( aPos, rTitle );
+ if ( nPages != 1 )
+ {
+ aFont.SetWeight( WEIGHT_NORMAL );
+ rOutDev.SetFont( aFont );
+ OUString aPageStr = " [" + SwResId( STR_PAGE ) + " " + OUString::number( nCurPage ) + "]";
+ aPos.AdjustX(rOutDev.GetTextWidth( rTitle ) );
+ rOutDev.DrawText( aPos, aPageStr );
+ }
+
+ nY = TMARGPRN-nBorder;
+
+ rOutDev.DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) );
+
+ rOutDev.SetFont( aOldFont );
+ rOutDev.SetFillColor( aOldFillColor );
+}
+
+static rtl_TextEncoding lcl_GetStreamCharSet(rtl_TextEncoding eLoadEncoding)
+{
+ rtl_TextEncoding eRet = eLoadEncoding;
+ if(RTL_TEXTENCODING_DONTKNOW == eRet)
+ {
+ eRet = RTL_TEXTENCODING_UTF8;
+ }
+ return eRet;
+}
+
+static OUString lcl_ConvertTabsToSpaces( const OUString& sLine )
+{
+ if (sLine.isEmpty())
+ return sLine;
+
+ OUString aRet = sLine;
+ const sal_Unicode aPadSpaces[4] = {' ', ' ', ' ', ' '};
+ sal_Int32 nPos = 0;
+ for (;;)
+ {
+ nPos = aRet.indexOf('\t', nPos);
+ if (nPos<0)
+ {
+ break;
+ }
+ // Not 4 blanks, but on 4th TabPos:
+ const sal_Int32 nPadLen = 4 - (nPos % 4);
+ aRet = aRet.replaceAt(nPos, 1, std::u16string_view{aPadSpaces, static_cast<size_t>(nPadLen)});
+ nPos += nPadLen;
+ }
+ return aRet;
+}
+
+SwSrcView::SwSrcView(SfxViewFrame& rViewFrame, SfxViewShell*) :
+ SfxViewShell( rViewFrame, SWSRCVIEWFLAGS ),
+ m_aEditWin( VclPtr<SwSrcEditWindow>::Create( &rViewFrame.GetWindow(), this ) ),
+ m_bSourceSaved(false),
+ m_eLoadEncoding(RTL_TEXTENCODING_DONTKNOW)
+{
+ Init();
+}
+
+SwSrcView::~SwSrcView()
+{
+ SwDocShell* pDocShell = GetDocShell();
+ assert(dynamic_cast<SwWebDocShell*>( pDocShell) && "Why no WebDocShell?" );
+ const TextSelection& rSel = m_aEditWin->GetTextView()->GetSelection();
+ static_cast<SwWebDocShell*>(pDocShell)->SetSourcePara( static_cast< sal_uInt16 >( rSel.GetStart().GetPara() ) );
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps
+ = xDPS->getDocumentProperties();
+ OUString url = xDocProps->getAutoloadURL();
+ sal_Int32 delay = xDocProps->getAutoloadSecs();
+ pDocShell->SetAutoLoad(INetURLObject(url), delay,
+ (delay != 0) || !url.isEmpty());
+ EndListening(*pDocShell);
+ m_pSearchItem.reset();
+
+ m_aEditWin.disposeAndClear();
+}
+
+void SwSrcView::SaveContentTo(SfxMedium& rMed)
+{
+ SvStream* pOutStream = rMed.GetOutStream();
+ pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(m_eLoadEncoding));
+ m_aEditWin->Write( *pOutStream );
+}
+
+void SwSrcView::Init()
+{
+ SetName("Source");
+ SetWindow( m_aEditWin.get() );
+ SwDocShell* pDocShell = GetDocShell();
+ // If the doc is still loading, then the DocShell must fire up
+ // the Load if the loading is completed.
+ if(!pDocShell->IsLoading())
+ Load(pDocShell);
+ else
+ {
+ m_aEditWin->SetReadonly(true);
+ }
+
+ SetNewWindowAllowed( false );
+ StartListening(*pDocShell, DuplicateHandling::Prevent);
+}
+
+SwDocShell* SwSrcView::GetDocShell()
+{
+ SfxObjectShell* pObjShell = GetViewFrame().GetObjectShell();
+ return dynamic_cast<SwDocShell*>( pObjShell );
+}
+
+void SwSrcView::SaveContent(const OUString& rTmpFile)
+{
+ SfxMedium aMedium( rTmpFile, StreamMode::WRITE);
+ SvStream* pOutStream = aMedium.GetOutStream();
+ pOutStream->SetStreamCharSet( lcl_GetStreamCharSet(m_eLoadEncoding) );
+ m_aEditWin->Write(*pOutStream);
+ aMedium.Commit();
+}
+
+void SwSrcView::Execute(SfxRequest& rReq)
+{
+ TextView* pTextView = m_aEditWin->GetTextView();
+ switch( rReq.GetSlot() )
+ {
+ case SID_SAVEACOPY:
+ case SID_SAVEASDOC:
+ {
+ // filesave dialog with autoextension
+ FileDialogHelper aDlgHelper(
+ TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, m_aEditWin->GetFrameWeld());
+ uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();
+
+ // search for an html filter for export
+ SfxFilterContainer* pFilterCont = GetObjectShell()->GetFactory().GetFilterContainer();
+ std::shared_ptr<const SfxFilter> pFilter =
+ pFilterCont->GetFilter4Extension( "html", SfxFilterFlags::EXPORT );
+ if ( pFilter )
+ {
+ // filter found -> use its uiname and wildcard
+ const OUString& rUIName = pFilter->GetUIName();
+ const WildCard& rCard = pFilter->GetWildcard();
+ xFP->appendFilter( rUIName, rCard.getGlob() );
+ xFP->setCurrentFilter( rUIName ) ;
+ }
+ else
+ {
+ // filter not found
+ OUString sHtml("HTML");
+ xFP->appendFilter( sHtml, "*.html;*.htm" );
+ xFP->setCurrentFilter( sHtml ) ;
+ }
+
+ if( aDlgHelper.Execute() == ERRCODE_NONE)
+ {
+ SfxMedium aMedium( xFP->getSelectedFiles().getConstArray()[0],
+ StreamMode::WRITE | StreamMode::SHARE_DENYNONE );
+ SvStream* pOutStream = aMedium.GetOutStream();
+ pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(m_eLoadEncoding));
+ m_aEditWin->Write( *pOutStream );
+ aMedium.Commit();
+ }
+ }
+ break;
+ case SID_SAVEDOC:
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ SfxMedium* pMed = nullptr;
+ if(pDocShell->HasName())
+ pMed = pDocShell->GetMedium();
+ else
+ {
+ const SfxPoolItemHolder& rResult(pDocShell->ExecuteSlot(rReq, pDocShell->GetInterface()));
+ const SfxBoolItem* pItem(static_cast<const SfxBoolItem*>(rResult.getItem()));
+ if(pItem && pItem->GetValue())
+ pMed = pDocShell->GetMedium();
+ }
+ if(pMed)
+ {
+ SvStream* pOutStream = pMed->GetOutStream();
+ pOutStream->Seek(0);
+ pOutStream->SetStreamSize(0);
+ pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(m_eLoadEncoding));
+ m_aEditWin->Write( *pOutStream );
+ pMed->CloseOutStream();
+ pMed->Commit();
+ pDocShell->GetDoc()->getIDocumentState().ResetModified();
+ m_bSourceSaved = true;
+ m_aEditWin->ClearModifyFlag();
+ }
+ }
+ break;
+ case FID_SEARCH_NOW:
+ {
+ const SfxItemSet* pTmpArgs = rReq.GetArgs();
+
+ const sal_uInt16 nWhich = pTmpArgs->GetWhichByOffset( 0 );
+ OSL_ENSURE( nWhich, "Which for SearchItem ?" );
+ const SfxPoolItem& rItem = pTmpArgs->Get( nWhich );
+ SetSearchItem( static_cast<const SvxSearchItem&>(rItem));
+ StartSearchAndReplace( static_cast<const SvxSearchItem&>(rItem), rReq.IsAPI() );
+ if(m_aEditWin->IsModified())
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ pDocShell->GetDoc()->getIDocumentState().SetModified();
+ }
+ }
+ break;
+ case FN_REPEAT_SEARCH:
+ {
+ SvxSearchItem* pSrchItem = GetSearchItem();
+ if(pSrchItem)
+ {
+ StartSearchAndReplace( *pSrchItem, rReq.IsAPI() );
+ if(m_aEditWin->IsModified())
+ GetDocShell()->GetDoc()->getIDocumentState().SetModified();
+ }
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ {
+ SfxViewShell::ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ }
+ break;
+ case SID_UNDO:
+ pTextView->Undo();
+ GetViewFrame().GetBindings().InvalidateAll(false);
+ break;
+ case SID_REDO:
+ pTextView->Redo();
+ GetViewFrame().GetBindings().InvalidateAll(false);
+ break;
+ case SID_REPEAT:
+ break;
+ case SID_CUT:
+ if(pTextView->HasSelection())
+ pTextView->Cut();
+ break;
+ case SID_COPY:
+ if(pTextView->HasSelection())
+ pTextView->Copy();
+ break;
+ case SID_PASTE:
+ pTextView->Paste();
+ break;
+ case SID_SELECTALL:
+ pTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
+ break;
+ }
+ m_aEditWin->Invalidate();
+}
+
+void SwSrcView::GetState(SfxItemSet& rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ TextView* pTextView = m_aEditWin->GetTextView();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_SAVEASDOC:
+ rSet.Put(SfxStringItem(nWhich, SwResId(STR_SAVEAS_SRC)));
+ break;
+ case SID_SAVEACOPY:
+ rSet.Put(SfxStringItem(nWhich, SwResId(STR_SAVEACOPY_SRC)));
+ break;
+ case SID_SAVEDOC:
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ if(!pDocShell->IsModified())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ break;
+ case SID_TABLE_CELL:
+ {
+ TextSelection aSel = pTextView->GetSelection();
+ OUString aPos =
+ SwResId(STR_SRCVIEW_ROW)
+ + OUString::number( aSel.GetEnd().GetPara()+1 )
+ + " : "
+ + SwResId(STR_SRCVIEW_COL)
+ + OUString::number( aSel.GetEnd().GetIndex()+1 );
+ SvxStatusItem aItem( SID_TABLE_CELL, aPos, StatusCategory::RowColumn );
+ rSet.Put( aItem );
+ }
+ break;
+ case SID_SEARCH_OPTIONS:
+ {
+ SearchOptionFlags nOpt = SRC_SEARCHOPTIONS;
+ SwDocShell* pDocShell = GetDocShell();
+ assert(pDocShell);
+ if (pDocShell->IsReadOnly())
+ nOpt &= ~SearchOptionFlags(SearchOptionFlags::REPLACE|SearchOptionFlags::REPLACE_ALL);
+
+ rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast<sal_uInt16>(nOpt) ) );
+ }
+ break;
+ case SID_SEARCH_ITEM:
+ {
+ OUString sSelected;
+ if ( !pTextView->HasSelection() )
+ {
+ const TextSelection& rSel = pTextView->GetSelection();
+ sSelected = m_aEditWin->GetTextEngine()->GetWord( rSel.GetStart());
+ }
+ else
+ {
+ sSelected = pTextView->GetSelected();
+ }
+ SvxSearchItem * pSrchItem = GetSearchItem();
+ pSrchItem->SetSearchString( sSelected );
+ rSet.Put( *pSrchItem );
+ }
+ break;
+ case FN_REPEAT_SEARCH:
+ {
+ if(!GetSearchItem())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_UNDO:
+ case SID_REDO:
+ {
+ SfxUndoManager& rMgr = pTextView->GetTextEngine()->GetUndoManager();
+ sal_uInt16 nCount = 0;
+ if(nWhich == SID_UNDO)
+ {
+ nCount = rMgr.GetUndoActionCount();
+ if(nCount)
+ {
+ OUString aStr = SvtResId( STR_UNDO) + rMgr.GetUndoActionComment(--nCount);
+ rSet.Put(SfxStringItem(nWhich, aStr));
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ nCount = rMgr.GetRedoActionCount();
+ if(nCount)
+ {
+ OUString aStr = SvtResId( STR_REDO) + rMgr.GetRedoActionComment(--nCount);
+ rSet.Put(SfxStringItem(nWhich,aStr));
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_MAIL_SENDDOCASPDF:
+ case SID_MAIL_SENDDOC :
+ case SID_EXPORTDOCASPDF:
+ case SID_DIRECTEXPORTDOCASPDF:
+ case SID_EXPORTDOC:
+ case SID_REPEAT:
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_CUT:
+ case SID_COPY:
+ if(!pTextView->HasSelection())
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_PASTE:
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ m_aEditWin.get()) );
+ bool bDisable = !aDataHelper.GetXTransferable().is() ||
+ 0 == aDataHelper.GetFormatCount();
+ if( bDisable )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+SvxSearchItem* SwSrcView::GetSearchItem()
+{
+ if(!m_pSearchItem)
+ {
+ m_pSearchItem.reset(new SvxSearchItem(SID_SEARCH_ITEM));
+ }
+ return m_pSearchItem.get();
+}
+
+void SwSrcView::SetSearchItem( const SvxSearchItem& rItem )
+{
+ m_pSearchItem.reset(rItem.Clone());
+}
+
+void SwSrcView::StartSearchAndReplace(const SvxSearchItem& rSearchItem,
+ bool bApi,
+ bool bRecursive)
+{
+ TextView* pTextView = m_aEditWin->GetTextView();
+ TextPaM aPaM;
+
+ bool bForward = !rSearchItem.GetBackward();
+ bool bAtStart = pTextView->GetSelection() == TextSelection( aPaM, aPaM );
+
+ if( !bForward )
+ aPaM = TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL );
+
+ i18nutil::SearchOptions2 aSearchOpt( rSearchItem.GetSearchOptions() );
+ aSearchOpt.Locale = GetAppLanguageTag().getLocale();
+
+ sal_uInt16 nFound;
+ bool bAll = false;
+ switch( rSearchItem.GetCommand() )
+ {
+ case SvxSearchCmd::FIND:
+ case SvxSearchCmd::FIND_ALL:
+ nFound = pTextView->Search( aSearchOpt, bForward ) ? 1 : 0;
+ break;
+
+ case SvxSearchCmd::REPLACE_ALL: bAll = true;
+ [[fallthrough]];
+ case SvxSearchCmd::REPLACE:
+ nFound = pTextView->Replace( aSearchOpt, bAll, bForward );
+ break;
+
+ default:
+ nFound = 0;
+ }
+
+ if( nFound )
+ return;
+
+ bool bNotFoundMessage = false;
+ if(!bRecursive)
+ {
+ bNotFoundMessage = bAtStart;
+ }
+ else if(bAtStart)
+ {
+ bNotFoundMessage = true;
+ }
+
+ if(bApi)
+ return;
+
+ if(bNotFoundMessage)
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/infonotfounddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xInfoBox(xBuilder->weld_message_dialog("InfoNotFoundDialog"));
+ xInfoBox->run();
+ }
+ else if(!bRecursive)
+ {
+ int nRet;
+
+ if (!bForward)
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/querycontinueenddialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("QueryContinueEndDialog"));
+ nRet = xQueryBox->run();
+ }
+ else
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/querycontinuebegindialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("QueryContinueBeginDialog"));
+ nRet = xQueryBox->run();
+ }
+
+ if (nRet == RET_YES)
+ {
+ pTextView->SetSelection( TextSelection( aPaM, aPaM ) );
+ StartSearchAndReplace( rSearchItem, false, true );
+ }
+ }
+}
+
+sal_uInt16 SwSrcView::SetPrinter(SfxPrinter* pNew, SfxPrinterChangeFlags nDiffFlags )
+{
+ SwDocShell* pDocSh = GetDocShell();
+ assert(pDocSh);
+ if ( (SfxPrinterChangeFlags::JOBSETUP | SfxPrinterChangeFlags::PRINTER) & nDiffFlags )
+ {
+ pDocSh->GetDoc()->getIDocumentDeviceAccess().setPrinter( pNew, true, true );
+ if ( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
+ pDocSh->SetModified();
+ }
+ if ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS )
+ ::SetPrinter( &pDocSh->getIDocumentDeviceAccess(), pNew, true );
+
+ const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
+ if ( bChgOri || bChgSize )
+ {
+ pDocSh->SetModified();
+ }
+ return 0;
+}
+
+SfxPrinter* SwSrcView::GetPrinter( bool bCreate )
+{
+ SwDocShell* pDocSh = GetDocShell();
+ assert(pDocSh);
+ return pDocSh->GetDoc()->getIDocumentDeviceAccess().getPrinter(bCreate);
+}
+
+sal_Int32 SwSrcView::PrintSource(
+ OutputDevice *pOutDev,
+ sal_Int32 nPage,
+ bool bCalcNumPagesOnly )
+{
+ if (!pOutDev || nPage <= 0)
+ return 0;
+
+ //! This algorithm for printing the n-th page is very poor since it
+ //! needs to go over the text of all previous pages to get to the correct one.
+ //! But since HTML source code is expected to be just a small number of pages
+ //! even this poor algorithm should be enough...
+
+ pOutDev->Push();
+
+ TextEngine* pTextEngine = m_aEditWin->GetTextEngine();
+ pOutDev->SetMapMode(MapMode(MapUnit::Map100thMM));
+ vcl::Font aFont( m_aEditWin->GetOutWin()->GetFont() );
+ Size aSize( aFont.GetFontSize() );
+ aSize = m_aEditWin->GetOutWin()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM));
+ aFont.SetFontSize( aSize );
+ aFont.SetColor( COL_BLACK );
+ pOutDev->SetFont( aFont );
+
+ OUString aTitle( GetViewFrame().GetWindow().GetText() );
+
+ const tools::Long nLineHeight = pOutDev->GetTextHeight(); // slightly more
+ const tools::Long nParaSpace = 10;
+
+ Size aPaperSz = pOutDev->GetOutputSize();
+ aPaperSz.AdjustWidth( -(LMARGPRN + RMARGPRN) );
+ aPaperSz.AdjustHeight( -(TMARGPRN + BMARGPRN) );
+
+ // nLinepPage is not true, if lines have to be wrapped...
+ const tools::Long nLinespPage = nLineHeight ? aPaperSz.Height() / nLineHeight : 1;
+ const tools::Long nCharWidth = pOutDev->GetTextWidth("X");
+ const sal_Int32 nCharspLine = nCharWidth ? static_cast<sal_Int32>(aPaperSz.Width() / nCharWidth) : 1;
+ const sal_uInt32 nParas = pTextEngine->GetParagraphCount();
+
+ const sal_Int32 nPages = static_cast<sal_Int32>(nParas / nLinespPage + 1 );
+ sal_Int32 nCurPage = 1;
+
+ // Print header...
+ if (!bCalcNumPagesOnly && nPage == nCurPage)
+ lcl_PrintHeader( *pOutDev, nPages, nCurPage, aTitle );
+ const Point aStartPos( LMARGPRN, TMARGPRN );
+ Point aPos( aStartPos );
+ for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara )
+ {
+ const OUString aLine( lcl_ConvertTabsToSpaces(pTextEngine->GetText( nPara )) );
+ const sal_Int32 nLineLen = aLine.getLength();
+ const sal_Int32 nLines = (nLineLen+nCharspLine-1) / nCharspLine;
+ for ( sal_Int32 nLine = 0; nLine < nLines; ++nLine )
+ {
+ aPos.AdjustY(nLineHeight );
+ if ( aPos.Y() > ( aPaperSz.Height() + TMARGPRN - nLineHeight/2 ) )
+ {
+ ++nCurPage;
+ if (!bCalcNumPagesOnly && nPage == nCurPage)
+ lcl_PrintHeader( *pOutDev, nPages, nCurPage, aTitle );
+ aPos = aStartPos;
+ }
+ if (!bCalcNumPagesOnly && nPage == nCurPage)
+ {
+ const sal_Int32 nStart = nLine * nCharspLine;
+ const sal_Int32 nLen = std::min(nLineLen-nStart, nCharspLine);
+ pOutDev->DrawText( aPos, aLine.copy(nStart, nLen) );
+ }
+ }
+ aPos.AdjustY(nParaSpace );
+ }
+
+ pOutDev->Pop();
+
+ OSL_ENSURE( bCalcNumPagesOnly || nPage <= nCurPage, "page number out of range" );
+ return nCurPage;
+}
+
+void SwSrcView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if (rHint.GetId() == SfxHintId::ModeChanged || rHint.GetId() == SfxHintId::TitleChanged)
+ {
+ const SwDocShell* pDocSh = GetDocShell();
+ assert(pDocSh);
+ if (!(rHint.GetId() == SfxHintId::TitleChanged
+ && (pDocSh->IsReadOnly() || !m_aEditWin->IsReadonly())))
+ {
+ // Broadcast only comes once!
+ const bool bReadonly = pDocSh->IsReadOnly();
+ m_aEditWin->SetReadonly(bReadonly);
+ }
+ }
+ SfxViewShell::Notify(rBC, rHint);
+}
+
+void SwSrcView::Load(SwDocShell* pDocShell)
+{
+ rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_UTF8;
+
+ m_aEditWin->SetReadonly(pDocShell->IsReadOnly());
+ m_aEditWin->SetTextEncoding(eDestEnc);
+ SfxMedium* pMedium = pDocShell->GetMedium();
+
+ std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
+ bool bHtml = pFilter && pFilter->GetUserData() == "HTML";
+ bool bDocModified = pDocShell->IsModified();
+ if(bHtml && !bDocModified && pDocShell->HasName())
+ {
+ SvStream* pStream = pMedium->GetInStream();
+ if(pStream && ERRCODE_NONE == pStream->GetError() )
+ {
+ rtl_TextEncoding eHeaderEnc =
+ SfxHTMLParser::GetEncodingByHttpHeader(
+ pDocShell->GetHeaderAttributes() );
+ if( RTL_TEXTENCODING_DONTKNOW == eHeaderEnc )
+ {
+ const char *pTmpCharSet =
+ rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 );
+ eHeaderEnc = rtl_getTextEncodingFromMimeCharset( pTmpCharSet );
+ }
+ if( RTL_TEXTENCODING_DONTKNOW != eHeaderEnc &&
+ eDestEnc != eHeaderEnc )
+ {
+ eDestEnc = eHeaderEnc;
+ m_aEditWin->SetTextEncoding(eDestEnc);
+ }
+ pStream->SetStreamCharSet( eDestEnc );
+ pStream->Seek(0);
+ TextEngine* pTextEngine = m_aEditWin->GetTextEngine();
+ pTextEngine->EnableUndo(false);
+ m_aEditWin->Read(*pStream);
+ pTextEngine->EnableUndo(true);
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetViewFrame().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_ERR_SRCSTREAM)));
+ xBox->run();
+ }
+ }
+ else
+ {
+ utl::TempFileNamed aTempFile;
+ aTempFile.EnableKillingFile();
+ const OUString sFileURL( aTempFile.GetURL() );
+
+ {
+ SfxMedium aMedium( sFileURL,StreamMode::READWRITE );
+ SwWriter aWriter( aMedium, *pDocShell->GetDoc() );
+ WriterRef xWriter;
+ ::GetHTMLWriter(std::u16string_view(), aMedium.GetBaseURL( true ), xWriter);
+ const OUString sWriteName = pDocShell->HasName()
+ ? pMedium->GetName()
+ : sFileURL;
+ ErrCodeMsg nRes = aWriter.Write(xWriter, &sWriteName);
+ if(nRes)
+ {
+ ErrorHandler::HandleError(nRes);
+ m_aEditWin->SetReadonly(true);
+ }
+ aMedium.Commit();
+ SvStream* pInStream = aMedium.GetInStream();
+ pInStream->Seek(0);
+ pInStream->SetStreamCharSet( eDestEnc );
+
+ m_aEditWin->Read(*pInStream);
+ }
+ }
+ m_aEditWin->ClearModifyFlag();
+
+ m_eLoadEncoding = eDestEnc;
+
+ if(bDocModified)
+ pDocShell->SetModified();// The flag will be reset in between times.
+ // Disable AutoLoad
+ pDocShell->SetAutoLoad(INetURLObject(), 0, false);
+ assert(dynamic_cast<SwWebDocShell*>( pDocShell) && "Why no WebDocShell?" );
+ sal_uInt16 nLine = static_cast<SwWebDocShell*>(pDocShell)->GetSourcePara();
+ m_aEditWin->SetStartLine(nLine);
+ m_aEditWin->GetTextEngine()->ResetUndo();
+ m_aEditWin->GetOutWin()->GrabFocus();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/swcli.cxx b/sw/source/uibase/uiview/swcli.cxx
new file mode 100644
index 0000000000..ea7093516e
--- /dev/null
+++ b/sw/source/uibase/uiview/swcli.cxx
@@ -0,0 +1,193 @@
+/* -*- 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/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+#include <swcli.hxx>
+#include <svtools/embedhlp.hxx>
+#include <osl/diagnose.h>
+
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <ndole.hxx>
+
+using namespace com::sun::star;
+
+SwOleClient::SwOleClient(SwView *pView, SwEditWin *pWin, const svt::EmbeddedObjectRef& xObj)
+ : SfxInPlaceClient( pView, pWin, xObj.GetViewAspect() )
+ , m_IsInDoVerb(false)
+ , m_IsOldCheckForOLEInCaption(pView->GetWrtShell().IsCheckForOLEInCaption())
+{
+ SetObject( xObj.GetObject() );
+}
+
+void SwOleClient::RequestNewObjectArea( tools::Rectangle& aLogRect )
+{
+ // The server wants to change the client size.
+ // We put the desired size in the core. The attributes of the frame
+ // are set to the desired value. This value will be passed on to the
+ // InPlaceClient.
+ // The core accepts or formats the adjusted values not necessarily.
+ // If the Ole-Frame is formatted, then the CalcAndSetScale() of the WrtShell
+ // will be called. There the scaling of the SwOleClient is set if necessary.
+
+ SwWrtShell &rSh = static_cast<SwView*>(GetViewShell())->GetWrtShell();
+
+ rSh.StartAllAction();
+
+ // the aLogRect will get the preliminary size now
+ aLogRect.SetSize( rSh.RequestObjectResize( SwRect( aLogRect ), GetObject() ) );
+
+ // the EndAllAction() call will trigger CalcAndSetScale() call,
+ // so the embedded object must get the correct size before
+ if ( aLogRect.GetSize() != GetScaledObjArea().GetSize() )
+ {
+ // size has changed, so first change visual area of the object before we resize its view
+ // without this the object always would be scaled - now it has the choice
+
+ // TODO/LEAN: getMapUnit can switch object to running state
+ MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( GetObject()->getMapUnit( GetAspect() ) ) );
+ MapMode aClientMap( GetEditWin()->GetMapMode().GetMapUnit() );
+
+ Size aNewObjSize( tools::Long( aLogRect.GetWidth() / GetScaleWidth() ),
+ tools::Long( aLogRect.GetHeight() / GetScaleHeight() ) );
+
+ // convert to logical coordinates of the embedded object
+ Size aNewSize = GetEditWin()->LogicToLogic( aNewObjSize, &aClientMap, &aObjectMap );
+ GetObject()->setVisualAreaSize( GetAspect(), awt::Size( aNewSize.Width(), aNewSize.Height() ) );
+ }
+
+ rSh.EndAllAction();
+
+ SwRect aFrame( rSh.GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, GetObject() )),
+ aPrt( rSh.GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, GetObject() ));
+ aLogRect.SetPos( aPrt.Pos() + aFrame.Pos() );
+ aLogRect.SetSize( aPrt.SSize() );
+}
+
+void SwOleClient::ObjectAreaChanged()
+{
+ SwWrtShell &rSh = static_cast<SwView*>(GetViewShell())->GetWrtShell();
+ SwRect aFrame( rSh.GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, GetObject() ));
+ if ( !aFrame.Overlaps( rSh.VisArea() ) )
+ rSh.MakeVisible( aFrame );
+}
+
+void SwOleClient::ViewChanged()
+{
+ if (m_IsInDoVerb)
+ return;
+
+ if ( GetAspect() == embed::Aspects::MSOLE_ICON )
+ {
+ // the iconified object seems not to need such a scaling handling
+ // since the replacement image and the size a completely controlled by the container
+ // TODO/LATER: when the icon exchange is implemented the scaling handling
+ // might be required again here
+ return;
+ }
+
+ SwWrtShell &rSh = static_cast<SwView*>(GetViewShell())->GetWrtShell();
+
+ // Adjust the size of the object in the core. The Scaling must
+ // be considered. Repercussions on the object are considered by
+ // CalcAndSetScale() of the WrtShell if the size / position of
+ // the frame in the core changes.
+
+ // TODO/LEAN: getMapUnit can switch object to running state
+ awt::Size aSz;
+ try
+ {
+ aSz = GetObject()->getVisualAreaSize( GetAspect() );
+ }
+ catch (const embed::NoVisualAreaSizeException&)
+ {
+ // Nothing will be done
+ }
+ catch (const uno::Exception&)
+ {
+ OSL_FAIL( "Something goes wrong on requesting object size!" );
+ }
+
+ Size aVisSize( aSz.Width, aSz.Height );
+
+ // As long as from the object comes no reasonable size
+ // nothing can be scaled.
+ if( !aVisSize.Width() || !aVisSize.Height() )
+ return;
+
+ // first convert to TWIPS before scaling, because scaling factors are calculated for
+ // the TWIPS mapping and so they will produce the best results if applied to TWIPS based
+ // coordinates
+ const MapMode aMyMap ( MapUnit::MapTwip );
+ const MapMode aObjMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( GetObject()->getMapUnit( GetAspect() ) ) );
+ aVisSize = OutputDevice::LogicToLogic( aVisSize, aObjMap, aMyMap );
+
+ aVisSize.setWidth( tools::Long(aVisSize.Width() * GetScaleWidth()) );
+ aVisSize.setHeight( tools::Long(aVisSize.Height() * GetScaleHeight()) );
+
+ SwRect aRect( Point( LONG_MIN, LONG_MIN ), aVisSize );
+ rSh.LockView( true ); // Prevent scrolling in the EndAction
+ rSh.StartAllAction();
+ rSh.RequestObjectResize( aRect, GetObject() );
+ rSh.EndAllAction();
+ rSh.LockView( false );
+}
+
+void SwOleClient::FormatChanged()
+{
+ const uno::Reference < embed::XEmbeddedObject >& xObj( GetObject() );
+ SwView * pView = dynamic_cast< SwView * >( GetViewShell() );
+ if ( pView && xObj.is() && SotExchange::IsMath( xObj->getClassID() ) )
+ {
+ SwWrtShell & rWrtSh = pView->GetWrtShell();
+ if (rWrtSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ))
+ rWrtSh.AlignFormulaToBaseline( xObj );
+ }
+}
+
+bool SwOleClient::IsProtected() const
+{
+ auto pView = dynamic_cast<SwView*>(GetViewShell());
+ if (!pView)
+ {
+ return false;
+ }
+
+ SwWrtShell& rWrtSh = pView->GetWrtShell();
+ if (rWrtSh.IsTableMode())
+ {
+ return false;
+ }
+
+ SwOLENode* pOLENode = rWrtSh.GetCursor()->GetPointNode().GetOLENode();
+ if (!pOLENode)
+ {
+ return false;
+ }
+
+ return pOLENode->GetOLEObj().IsProtected();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/uivwimp.cxx b/sw/source/uibase/uiview/uivwimp.cxx
new file mode 100644
index 0000000000..ed0c3c68fc
--- /dev/null
+++ b/sw/source/uibase/uiview/uivwimp.cxx
@@ -0,0 +1,333 @@
+/* -*- 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 <config_fuzzers.h>
+
+#include <cmdid.h>
+
+#include <com/sun/star/scanner/XScannerManager2.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+
+#include <sfx2/docinsert.hxx>
+#include <sfx2/request.hxx>
+#include <uivwimp.hxx>
+#include <unotxvw.hxx>
+#include <unodispatch.hxx>
+#include <swmodule.hxx>
+#include <swdtflvr.hxx>
+
+#include <strings.hrc>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::scanner;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::datatransfer::clipboard;
+
+SwView_Impl::SwView_Impl(SwView* pShell)
+ : m_pView(pShell)
+ , m_eShellMode(ShellMode::Text)
+ , m_nParam(0)
+ , m_bSelectObject(false)
+ , m_bEditingPositionSet(false)
+{
+ mxXTextView = new SwXTextView(m_pView);
+ m_xDispatchProviderInterceptor = new SwXDispatchProviderInterceptor(*m_pView);
+}
+
+SwView_Impl::~SwView_Impl()
+{
+ if(m_xDispatchProviderInterceptor)
+ m_xDispatchProviderInterceptor->Invalidate();
+ mxXTextView->Invalidate();
+ mxXTextView.clear();
+
+ if( mxScanEvtLstnr.is() )
+ mxScanEvtLstnr->ViewDestroyed();
+ if( mxClipEvtLstnr.is() )
+ {
+ mxClipEvtLstnr->AddRemoveListener( false );
+ mxClipEvtLstnr->ViewDestroyed();
+ }
+ DisconnectTransferableDDE();
+
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ m_xConfigItem.reset();
+#endif
+ m_pDocInserter.reset();
+ m_pRequest.reset();
+}
+
+void SwView_Impl::SetShellMode(ShellMode eSet)
+{
+ m_eShellMode = eSet;
+}
+
+view::XSelectionSupplier* SwView_Impl::GetUNOObject()
+{
+ return mxXTextView.get();
+}
+
+SwXTextView* SwView_Impl::GetUNOObject_Impl()
+{
+ return mxXTextView.get();
+}
+
+void SwView_Impl::ExecuteScan( SfxRequest& rReq )
+{
+ switch(rReq.GetSlot())
+ {
+ case SID_TWAIN_SELECT:
+ {
+ bool bDone = false;
+ Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
+
+ if( xScanMgr.is() )
+ {
+ try
+ {
+ SwScannerEventListener& rListener = GetScannerEventListener();
+ const Sequence< ScannerContext >
+ aContexts( xScanMgr->getAvailableScanners() );
+
+ if( aContexts.hasElements() )
+ {
+ Reference< XEventListener > xLstner = &rListener;
+ ScannerContext aContext( aContexts.getConstArray()[ 0 ] );
+
+ Reference<lang::XInitialization> xInit(xScanMgr, UNO_QUERY);
+ if (xInit.is())
+ {
+ // initialize dialog
+ weld::Window* pWindow = rReq.GetFrameWeld();
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", pWindow ? uno::Any(pWindow->GetXWindow()) : uno::Any(Reference<awt::XWindow>())}
+ }));
+ xInit->initialize( aSeq );
+ }
+
+ bDone = xScanMgr->configureScannerAndScan( aContext, xLstner );
+ }
+ }
+ catch(...)
+ {
+ }
+
+ }
+ if( bDone )
+ rReq.Done();
+ else
+ {
+ rReq.Ignore();
+ }
+ }
+ break;
+
+ case SID_TWAIN_TRANSFER:
+ {
+ bool bDone = false;
+
+ Reference< XScannerManager2 > xScanMgr = SW_MOD()->GetScannerManager();
+ if( xScanMgr.is() )
+ {
+ SwScannerEventListener& rListener = GetScannerEventListener();
+ try
+ {
+ const Sequence< scanner::ScannerContext >aContexts( xScanMgr->getAvailableScanners() );
+ if( aContexts.hasElements() )
+ {
+ Reference< XEventListener > xLstner = &rListener;
+ xScanMgr->startScan( aContexts.getConstArray()[ 0 ], xLstner );
+ bDone = true;
+ }
+ }
+ catch(...)
+ {
+ }
+ }
+
+ if( !bDone )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(rReq.GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_SCAN_NOSOURCE)));
+ xBox->run();
+ rReq.Ignore();
+ }
+ else
+ {
+ rReq.Done();
+ SfxBindings& rBind = m_pView->GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_TWAIN_SELECT );
+ rBind.Invalidate( SID_TWAIN_TRANSFER );
+ }
+ }
+ break;
+ }
+}
+
+SwScannerEventListener& SwView_Impl::GetScannerEventListener()
+{
+ if(!mxScanEvtLstnr.is())
+ mxScanEvtLstnr = new SwScannerEventListener(*m_pView);
+ return *mxScanEvtLstnr;
+}
+
+void SwView_Impl::AddClipboardListener()
+{
+ if(!mxClipEvtLstnr.is())
+ {
+ mxClipEvtLstnr = new SwClipboardChangeListener( *m_pView );
+ mxClipEvtLstnr->AddRemoveListener( true );
+ }
+}
+
+void SwView_Impl::Invalidate()
+{
+ GetUNOObject_Impl()->Invalidate();
+ for (const auto& xTransferable: mxTransferables)
+ {
+ rtl::Reference<SwTransferable> pTransferable = xTransferable.get();
+ if(pTransferable)
+ pTransferable->Invalidate();
+ }
+}
+
+void SwView_Impl::DisconnectTransferableDDE()
+{
+ for (const auto& xTransferable: mxTransferables)
+ {
+ rtl::Reference<SwTransferable> pTransferable = xTransferable.get();
+ if(pTransferable)
+ pTransferable->DisconnectDDE();
+ }
+}
+
+void SwView_Impl::AddTransferable(SwTransferable& rTransferable)
+{
+ //prevent removing of the non-referenced SwTransferable
+ osl_atomic_increment(&rTransferable.m_refCount);
+ {
+ // Remove previously added, but no longer existing weak references.
+ std::erase_if(mxTransferables,
+ [](const unotools::WeakReference<SwTransferable>& rTunnel) {
+ return !rTunnel.get();
+ });
+
+ mxTransferables.emplace_back(&rTransferable);
+ }
+ osl_atomic_decrement(&rTransferable.m_refCount);
+}
+
+void SwView_Impl::StartDocumentInserter(
+ const OUString& rFactory,
+ const Link<sfx2::FileDialogHelper*,void>& rEndDialogHdl,
+ const sal_uInt16 nSlotId
+)
+{
+ sfx2::DocumentInserter::Mode mode {sfx2::DocumentInserter::Mode::Insert};
+ switch( nSlotId )
+ {
+ case SID_DOCUMENT_MERGE:
+ mode = sfx2::DocumentInserter::Mode::Merge;
+ break;
+ case SID_DOCUMENT_COMPARE:
+ mode = sfx2::DocumentInserter::Mode::Compare;
+ break;
+ default:
+ break;
+ }
+
+ m_pDocInserter.reset(new ::sfx2::DocumentInserter(m_pView->GetFrameWeld(), rFactory, mode));
+ m_pDocInserter->StartExecuteModal( rEndDialogHdl );
+}
+
+std::unique_ptr<SfxMedium> SwView_Impl::CreateMedium()
+{
+ return m_pDocInserter->CreateMedium();
+}
+
+void SwView_Impl::InitRequest( const SfxRequest& rRequest )
+{
+ m_pRequest.reset(new SfxRequest( rRequest ));
+}
+
+SwScannerEventListener::~SwScannerEventListener()
+{
+}
+
+void SAL_CALL SwScannerEventListener::disposing( const EventObject& /*rEventObject*/)
+{
+#if defined(_WIN32) || defined UNX
+ SolarMutexGuard aGuard;
+ if( m_pView )
+ m_pView->ScannerEventHdl();
+#endif
+}
+
+SwClipboardChangeListener::~SwClipboardChangeListener()
+{
+}
+
+void SAL_CALL SwClipboardChangeListener::disposing( const EventObject& /*rEventObject*/ )
+{
+ SolarMutexGuard aGuard;
+ m_pView = nullptr; // so we don't touch the view if changedContents somehow fires afterwards
+}
+
+void SAL_CALL SwClipboardChangeListener::changedContents( const css::datatransfer::clipboard::ClipboardEvent& rEventObject )
+
+{
+ const SolarMutexGuard aGuard;
+ if( !m_pView )
+ return;
+
+ {
+ TransferableDataHelper aDataHelper( rEventObject.Contents );
+ SwWrtShell& rSh = m_pView->GetWrtShell();
+
+ m_pView->m_nLastPasteDestination = SwTransferable::GetSotDestination( rSh );
+ m_pView->m_bPasteState = aDataHelper.GetXTransferable().is() &&
+ SwTransferable::IsPaste( rSh, aDataHelper );
+
+ m_pView->m_bPasteSpecialState = aDataHelper.GetXTransferable().is() &&
+ SwTransferable::IsPasteSpecial( rSh, aDataHelper );
+ }
+
+ SfxBindings& rBind = m_pView->GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_PASTE );
+ rBind.Invalidate( SID_PASTE_SPECIAL );
+ rBind.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
+}
+
+void SwClipboardChangeListener::AddRemoveListener( bool bAdd )
+{
+ m_pView->AddRemoveClipboardListener( Reference< XClipboardListener >( this ), bAdd );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
new file mode 100644
index 0000000000..2d46cd04f2
--- /dev/null
+++ b/sw/source/uibase/uiview/view.cxx
@@ -0,0 +1,2120 @@
+/* -*- 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 <sal/config.h>
+
+#include <string_view>
+
+#include <config_features.h>
+#include <config_wasm_strip.h>
+
+#include <stdlib.h>
+#include <hintids.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/lok.hxx>
+#include <o3tl/any.hxx>
+#include <o3tl/string_view.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/inputctx.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/lingucfg.hxx>
+#include <unotools/useroptions.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/request.hxx>
+#include <svx/ruler.hxx>
+#include <svx/srchdlg.hxx>
+#include <svx/fmshell.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <svx/fmview.hxx>
+#include <unotxvw.hxx>
+#include <cmdid.h>
+#include <svl/hint.hxx>
+#include <swmodule.hxx>
+#include <inputwin.hxx>
+#include <uivwimp.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 <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 <wrtsh.hxx>
+#include <barcfg.hxx>
+#include <pview.hxx>
+#include <swdtflvr.hxx>
+#include <prtopt.hxx>
+#include <unotxdoc.hxx>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/scanner/ScannerContext.hpp>
+#include <com/sun/star/scanner/XScannerManager2.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdb/XDatabaseContext.hpp>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sal/log.hxx>
+
+#include <formatclipboard.hxx>
+#include <PostItMgr.hxx>
+#include <annotsh.hxx>
+#include <swruler.hxx>
+#include <svx/theme/ThemeColorPaletteManager.hxx>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <svtools/embedhlp.hxx>
+#include <tools/UnitConversion.hxx>
+
+#include <svx/sdr/overlay/overlayselection.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <svx/svdview.hxx>
+#include <node2lay.hxx>
+#include <cntfrm.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::scanner;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::sdbc;
+
+#define SWVIEWFLAGS SfxViewShellFlags::HAS_PRINTOPTIONS
+
+// Statics. OMG.
+
+bool bDocSzUpdated = true;
+
+SvxSearchItem* SwView::s_pSrchItem = nullptr;
+
+bool SwView::s_bExtra = false;
+bool SwView::s_bFound = false;
+bool SwView::s_bJustOpened = false;
+
+std::unique_ptr<SearchAttrItemList> SwView::s_xSearchList;
+std::unique_ptr<SearchAttrItemList> SwView::s_xReplaceList;
+
+SfxDispatcher &SwView::GetDispatcher()
+{
+ return *GetViewFrame().GetDispatcher();
+}
+
+void SwView::ImpSetVerb( SelectionType nSelType )
+{
+ bool bResetVerbs = m_bVerbsActive;
+ if ( !GetViewFrame().GetFrame().IsInPlace() &&
+ (SelectionType::Ole|SelectionType::Graphic) & nSelType )
+ {
+ FlyProtectFlags eProtectFlags = m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content);
+ if (eProtectFlags == FlyProtectFlags::NONE || nSelType & SelectionType::Ole)
+ {
+ 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(nullptr);
+ }
+ else if ( m_pPostItMgr )
+ {
+ SwAnnotationShell* pAsAnnotationShell = dynamic_cast<SwAnnotationShell*>( pTopShell );
+ if ( pAsAnnotationShell )
+ {
+ m_pPostItMgr->SetActiveSidebarWin(nullptr);
+ const_cast< SwView* >( this )->AttrChangedNotify(nullptr);
+ }
+ }
+ if (SwWrtShell* pWrtShell = GetWrtShellPtr())
+ {
+ SwWrtShell& rWrtShell = GetWrtShell();
+ rWrtShell.GetDoc()->getIDocumentLayoutAccess().SetCurrentViewShell( pWrtShell );
+ 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(nullptr);
+ }
+}
+
+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
+
+ // In case of m_bDying, our SfxShells are already gone, don't try to select a shell at all.
+ if(m_bInDtor || m_bDying)
+ 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;
+
+ // Determine if a different fly frame was selected.
+ bool bUpdateFly = false;
+ const SwFrameFormat* pCurFlyFormat = nullptr;
+ if (m_pWrtShell->IsSelFrameMode())
+ {
+ pCurFlyFormat = m_pWrtShell->GetFlyFrameFormat();
+ }
+ if (pCurFlyFormat && m_pLastFlyFormat && pCurFlyFormat != m_pLastFlyFormat)
+ {
+ // Only do an explicit update when switching between flys.
+ bUpdateFly = true;
+ }
+ m_pLastFlyFormat = pCurFlyFormat;
+
+ 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 );
+
+ if (bUpdateFly)
+ {
+ SfxViewFrame& rViewFrame = GetViewFrame();
+ uno::Reference<frame::XFrame> xFrame = rViewFrame.GetFrame().GetFrameInterface();
+ if (xFrame.is())
+ {
+ // Invalidate cached dispatch objects.
+ xFrame->contextChanged();
+ }
+ }
+ }
+ 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() && !utl::ConfigManager::IsFuzzing())
+ 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, LinkParamNone*, void)
+{
+ if ( GetEditWin().IsChainMode() )
+ GetEditWin().SetChainMode( false );
+
+ if (!m_pWrtShell || !GetDocShell())
+ {
+ return;
+ }
+
+ //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 SfxBoolItem *pItem =
+ GetObjectShell()->GetMedium()->GetItemSet().
+ GetItemIfSet( SID_HIDDEN, false );
+ if ( !pItem || !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;
+ SfxPoolItemHolder aResult;
+ // 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, aResult);
+ eStateProtAll = rDis.QueryState(FN_EDIT_REGION, aResult);
+ 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, FN_PASTE_NESTED_TABLE, FN_TABLE_PASTE_ROW_BEFORE,
+ FN_TABLE_PASTE_COL_BEFORE, SID_PASTE_SPECIAL, SID_SBA_BRW_INSERT,
+ SID_BACKGROUND_COLOR, FN_INSERT_BOOKMARK, SID_CHARMAP_CONTROL,
+ SID_CHARMAP, FN_INSERT_SOFT_HYPHEN,
+ FN_INSERT_HARDHYPHEN, FN_INSERT_HARD_SPACE, FN_INSERT_NNBSP,
+ FN_INSERT_BREAK, FN_INSERT_LINEBREAK, FN_INSERT_COLUMN_BREAK,
+ FN_INSERT_BREAK_DLG, FN_INSERT_CONTENT_CONTROL, FN_INSERT_CHECKBOX_CONTENT_CONTROL,
+ FN_INSERT_DROPDOWN_CONTENT_CONTROL, FN_INSERT_PICTURE_CONTENT_CONTROL,
+ FN_INSERT_DATE_CONTENT_CONTROL, FN_INSERT_PLAIN_TEXT_CONTENT_CONTROL,
+ FN_INSERT_COMBO_BOX_CONTENT_CONTROL,
+ 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_BACK_COLOR,
+ 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,
+ SID_ULINE_VAL_SINGLE, SID_ULINE_VAL_DOUBLE, SID_ULINE_VAL_DOTTED,
+ 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& _rFrame, SfxViewShell* pOldSh)
+ : SfxViewShell(_rFrame, SWVIEWFLAGS),
+ m_aTimer( "sw::SwView m_aTimer" ),
+ m_nNewPage(USHRT_MAX),
+ m_nOldPageNum(0),
+ m_pNumRuleNodeFromDoc(nullptr),
+ m_pEditWin( VclPtr<SwEditWin>::Create( &_rFrame.GetWindow(), *this ) ),
+ m_pShell(nullptr),
+ m_pFormShell(nullptr),
+ m_pHScrollbar(nullptr),
+ m_pVScrollbar(nullptr),
+ 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_pLastTableFormat(nullptr),
+ m_pLastFlyFormat(nullptr),
+ m_pFormatClipboard(new SwFormatClipboard()),
+ m_nSelectionType( SelectionType::All ),
+ m_nPageCnt(0),
+ m_nDrawSfxId( USHRT_MAX ),
+ m_nFormSfxId( USHRT_MAX ),
+ m_eFormObjKind(SdrObjKind::NONE),
+ m_nLastPasteDestination( static_cast<SotExchangeDest>(0xFFFF) ),
+ m_nLeftBorderDistance( 0 ),
+ m_nRightBorderDistance( 0 ),
+ m_eLastSearchCommand( static_cast<SvxSearchCmd>(0xFFFF) ),
+ m_bWheelScrollInProgress(false),
+ m_bCenterCursor(false),
+ m_bTopCursor(false),
+ m_bTabColFromDoc(false),
+ m_bTabRowFromDoc(false),
+ m_bSetTabColFromDoc(false),
+ m_bSetTabRowFromDoc(false),
+ m_bAttrChgNotified(false),
+ m_bAttrChgNotifiedWithRegistrations(false),
+ m_bVerbsActive(false),
+ m_bDrawRotate(false),
+ m_bDrawSelMode(true),
+ m_bShowAtResize(true),
+ m_bInOuterResizePixel(false),
+ m_bInInnerResizePixel(false),
+ m_bPasteState(false),
+ m_bPasteSpecialState(false),
+ m_bInMailMerge(false),
+ m_bInDtor(false),
+ m_bOldShellWasPagePreview(false),
+ m_bIsPreviewDoubleClick(false),
+ m_bMakeSelectionVisible(false),
+ m_bForceChangesToolbar(true),
+ m_nLOKPageUpDownOffset(0),
+ m_aBringToAttentionBlinkTimer("SwView m_aBringToAttentionBlinkTimer"),
+ m_nBringToAttentionBlinkTimeOutsRemaining(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>.
+
+ bDocSzUpdated = true;
+
+ static bool bFuzzing = utl::ConfigManager::IsFuzzing();
+
+ if (!bFuzzing)
+ {
+ 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&>(*_rFrame.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& rViewFrame = GetViewFrame();
+
+ StartListening(rViewFrame, 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 (!bFuzzing && 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();
+ if (m_pHScrollbar)
+ m_pHScrollbar->SetAuto(bBrowse);
+ if( aUsrPref.IsViewHRuler() )
+ CreateTab();
+ if( aUsrPref.IsViewVRuler() )
+ CreateVRuler();
+
+ m_pWrtShell->SetUIOptions( aUsrPref );
+ m_pWrtShell->SetReadOnlyAvailable( aUsrPref.IsCursorInProtectedArea() );
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ m_pWrtShell->ApplyAccessibilityOptions();
+#endif
+
+ if( m_pWrtShell->GetDoc()->getIDocumentState().IsUpdateExpField() )
+ {
+ if (m_pWrtShell->GetDoc()->GetDocumentFieldsManager().containsUpdatableFields())
+ {
+ CurrShell aCurr(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& rVFrame = 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 == &rVFrame ) &&
+ !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 &&
+ !rVFrame.GetChildWindow( SID_NAVIGATOR ))
+ {
+ SfxBoolItem aNavi(SID_NAVIGATOR, true);
+ GetDispatcher().ExecuteList(SID_NAVIGATOR, SfxCallMode::ASYNCHRON, { &aNavi });
+ }
+
+ uno::Reference< frame::XFrame > xFrame = rVFrame.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_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations = false;
+ if (bOldModifyFlag)
+ rDocSh.EnableSetModified();
+ InvalidateBorder();
+
+ if (!bFuzzing)
+ {
+ if (!m_pHScrollbar->IsScrollbarVisible(true))
+ ShowHScrollbar( false );
+ if (!m_pVScrollbar->IsScrollbarVisible(true))
+ ShowVScrollbar( false );
+ }
+
+ if (m_pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ m_pWrtShell->InvalidateOutlineContentVisibility();
+
+ if (!bFuzzing)
+ GetViewFrame().GetWindow().AddChildEventListener(LINK(this, SwView, WindowChildEventListener));
+
+ m_aBringToAttentionBlinkTimer.SetInvokeHandler(
+ LINK(this, SwView, BringToAttentionBlinkTimerHdl));
+ m_aBringToAttentionBlinkTimer.SetTimeout(350);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ SwXTextDocument* pModel = comphelper::getFromUnoTunnel<SwXTextDocument>(GetCurrentDocument());
+ SfxLokHelper::notifyViewRenderState(this, pModel);
+ }
+}
+
+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"_ostr);
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", ""_ostr);
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"_ostr);
+
+ // Need to remove activated field's button before disposing EditWin.
+ GetWrtShell().getIDocumentMarkAccess()->ClearFieldActivation();
+
+ 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->GetDrawView();
+ if( pSdrView && pSdrView->IsTextEdit() )
+ pSdrView->SdrEndTextEdit( true );
+ else if (pSdrView)
+ {
+ pSdrView->DisposeUndoManager();
+ }
+
+ SetWindow( nullptr );
+
+ m_pViewImpl->Invalidate();
+ EndListening(GetViewFrame());
+ EndListening(*GetDocShell());
+
+ // tdf#155410 speedup shutdown, prevent unnecessary broadcasting during teardown of draw model
+ auto pDrawModel = GetWrtShell().getIDocumentDrawModelAccess().GetDrawModel();
+ const bool bWasLocked = pDrawModel->isLocked();
+ pDrawModel->setLock(true);
+ m_pWrtShell.reset(); // reset here so that it is not accessible by the following dtors.
+ pDrawModel->setLock(bWasLocked);
+
+ m_pHScrollbar.disposeAndClear();
+ m_pVScrollbar.disposeAndClear();
+ m_pHRuler.disposeAndClear();
+ m_pVRuler.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();
+}
+
+void SwView::SetDying()
+{
+ m_bDying = true;
+}
+
+void SwView::afterCallbackRegistered()
+{
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ // common tasks
+ SfxViewShell::afterCallbackRegistered();
+
+ auto* pDocShell = GetDocShell();
+ if (pDocShell)
+ {
+ svx::ThemeColorPaletteManager aManager(pDocShell->GetThemeColors());
+ libreOfficeKitViewCallback(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON());
+ }
+}
+
+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() ? std::u16string_view(u"0") : std::u16string_view(u"1");
+}
+
+// Set CursorPos
+
+static bool lcl_IsOwnDocument( SwView& rView )
+{
+ if (::officecfg::Office::Common::Load::ViewPositionForAnyUser::get())
+ {
+ return true;
+ }
+ 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 == FullName || (Changed.isEmpty() && Created == FullName));
+}
+
+void SwView::ReadUserData( const OUString &rUserData, bool bBrowse )
+{
+ if ( !(rUserData.indexOf(';')>=0 && // more than one token
+ // For document without layout only in the onlinelayout or
+ // while forward/backward
+ (!m_pWrtShell->IsNewLayout() || m_pWrtShell->GetViewOptions()->getBrowseMode() || bBrowse)) )
+ return;
+
+ bool bIsOwnDocument = lcl_IsOwnDocument( *this );
+
+ CurrShell aCurr(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?
+ tools::Long nX = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nY = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos ));
+ Point aCursorPos( nX, nY );
+
+ sal_uInt16 nZoomFactor =
+ static_cast< sal_uInt16 >( o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )) );
+
+ tools::Long nLeft = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nTop = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nRight = o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos )),
+ nBottom= o3tl::toInt32(o3tl::getToken(rUserData, 0, ';', nPos ));
+
+ const tools::Long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
+ if ( nBottom > (m_pWrtShell->GetDocSize().Height()+nAdd) )
+ return;
+
+ 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>(o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rUserData, nOff, ';', nPos ))));
+ else
+ {
+ eZoom = SvxZoomType::PERCENT;
+ ++nOff;
+ }
+
+ bool bSelectObj = (0 != o3tl::toInt32(o3tl::getToken(rUserData, nOff, ';', nPos )))
+ && 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() )
+ {
+ sal_Int32 nIdx{ 0 };
+ const tools::Long nXTmp = o3tl::toInt32(o3tl::getToken(m_sNewCursorPos, 0, ';', nIdx ));
+ const tools::Long nYTmp = o3tl::toInt32(o3tl::getToken(m_sNewCursorPos, 0, ';', nIdx ));
+ 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 );
+
+ CurrShell aCurr(m_pWrtShell.get());
+ 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_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,
+ bGotZoomType = false,
+ bGotZoomFactor = false, bGotIsSelectedFrame = false,
+ bGotViewLayoutColumns = false, bGotViewLayoutBookMode = false,
+ bBrowseMode = false, bGotBrowseMode = false;
+ bool bKeepRatio = pVOpt->IsKeepRatio();
+ bool bGotKeepRatio = false;
+
+ for (const beans::PropertyValue& rValue : rSequence)
+ {
+ if ( rValue.Name == "ViewLeft" )
+ {
+ rValue.Value >>= nX;
+ nX = o3tl::toTwips(nX, o3tl::Length::mm100);
+ }
+ else if ( rValue.Name == "ViewTop" )
+ {
+ rValue.Value >>= nY;
+ nY = o3tl::toTwips(nY, o3tl::Length::mm100);
+ }
+ else if ( rValue.Name == "VisibleLeft" )
+ {
+ rValue.Value >>= nLeft;
+ nLeft = o3tl::toTwips(nLeft, o3tl::Length::mm100);
+ bGotVisibleLeft = true;
+ }
+ else if ( rValue.Name == "VisibleTop" )
+ {
+ rValue.Value >>= nTop;
+ nTop = o3tl::toTwips(nTop, o3tl::Length::mm100);
+ bGotVisibleTop = true;
+ }
+ else if ( rValue.Name == "ZoomType" )
+ {
+ rValue.Value >>= nZoomType;
+ bGotZoomType = true;
+ }
+ else if ( rValue.Name == "ZoomFactor" )
+ {
+ rValue.Value >>= nZoomFactor;
+ bGotZoomFactor = true;
+ }
+ else if ( rValue.Name == "ViewLayoutColumns" )
+ {
+ rValue.Value >>= nViewLayoutColumns;
+ bGotViewLayoutColumns = true;
+ }
+ else if ( rValue.Name == "ViewLayoutBookMode" )
+ {
+ bViewLayoutBookMode = *o3tl::doAccess<bool>(rValue.Value);
+ bGotViewLayoutBookMode = true;
+ }
+ else if ( rValue.Name == "IsSelectedFrame" )
+ {
+ rValue.Value >>= bSelectedFrame;
+ bGotIsSelectedFrame = true;
+ }
+ else if (rValue.Name == "ShowOnlineLayout")
+ {
+ rValue.Value >>= bBrowseMode;
+ bGotBrowseMode = true;
+ }
+ else if (rValue.Name == "KeepRatio")
+ {
+ rValue.Value >>= bKeepRatio;
+ bGotKeepRatio = true;
+ }
+ // Fallback to common SdrModel processing
+ else
+ GetDocShell()->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->ReadUserDataSequenceValue(&rValue);
+ }
+ if (bGotBrowseMode)
+ {
+ // delegate further
+ GetViewImpl()->GetUNOObject_Impl()->getViewSettings()->setPropertyValue("ShowOnlineLayout", uno::Any(bBrowseMode));
+ }
+
+ SelectShell();
+
+ Point aCursorPos( nX, nY );
+
+ m_pWrtShell->EnableSmooth( false );
+
+ 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( FrameControlType::Footer, true );
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Header, false );
+ }
+ else
+ {
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::Header, true );
+ m_pWrtShell->SetShowHeaderFooterSeparator( FrameControlType::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 );
+ }
+
+ if (bGotKeepRatio && bKeepRatio != pVOpt->IsKeepRatio())
+ {
+ // Got a custom value, then it makes sense to trigger notifications.
+ SwViewOption aUsrPref(*pVOpt);
+ aUsrPref.SetKeepRatio(bKeepRatio);
+ SW_MOD()->ApplyUsrPref(aUsrPref, this);
+ }
+
+ // 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(nLeft, nTop);
+ // make sure the document is still centered
+ const SwTwips lBorder = IsDocumentBorder() ? DOCUMENTBORDER : 2 * DOCUMENTBORDER;
+ SwTwips nEditWidth = GetEditWin().GetOutDev()->GetOutputSize().Width();
+ if(nEditWidth > (m_aDocSz.Width() + lBorder ))
+ aTopLeft.setX( ( m_aDocSz.Width() + lBorder - nEditWidth ) / 2 );
+ else
+ {
+ //check if the values are possible
+ tools::Long nXMax = m_pHScrollbar->GetRangeMax() - m_pHScrollbar->GetVisibleSize();
+ if( aTopLeft.X() > nXMax )
+ aTopLeft.setX( nXMax < 0 ? 0 : nXMax );
+ }
+ SetVisArea( aTopLeft );
+ }
+ }
+
+ 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() )));
+
+ auto visibleLeft = convertTwipToMm100 ( rVis.Left() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleLeft", visibleLeft));
+
+ auto visibleTop = convertTwipToMm100 ( rVis.Top() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleTop", visibleTop));
+
+ // We don't read VisibleRight and VisibleBottom anymore, but write them,
+ // because older versions rely on their presence to restore position
+
+ auto visibleRight = rVis.IsWidthEmpty() ? visibleLeft : convertTwipToMm100 ( rVis.Right() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleRight", visibleRight));
+
+ auto visibleBottom = rVis.IsHeightEmpty() ? visibleTop : convertTwipToMm100 ( rVis.Bottom() );
+ aVector.push_back(comphelper::makePropertyValue("VisibleBottom", visibleBottom));
+
+ 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()));
+
+ aVector.push_back(
+ comphelper::makePropertyValue("KeepRatio", m_pWrtShell->GetViewOptions()->IsKeepRatio()));
+
+ 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(sal_Int32 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, bool /*bOnlyASample*/ )
+{
+ 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(auto pChangedHint = dynamic_cast<const FmDesignModeChangedHint*>(&rHint))
+ {
+ bool bDesignMode = pChangedHint->GetDesignMode();
+ if (!bDesignMode && GetDrawFuncPtr())
+ {
+ GetDrawFuncPtr()->Deactivate();
+ SetDrawFuncPtr(nullptr);
+ LeaveDrawCreate();
+ AttrChangedNotify(nullptr);
+ }
+ }
+ 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 );
+ }
+
+ [[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_ACCEPT_DIRECT,
+ FN_REDLINE_REJECT_DIRECT,
+ FN_REDLINE_NEXT_CHANGE,
+ FN_REDLINE_PREV_CHANGE,
+ 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.IsEmpty() )
+ {
+ Graphic aGrf(aScanBmp);
+ m_pWrtShell->InsertGraphic( 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& rVFrame = GetViewFrame();
+ rVFrame.SetChildWindow( SwInputChild::GetChildWindowId(), false );
+ if( rVFrame.GetDispatcher()->IsLocked() )
+ rVFrame.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;
+}
+
+bool SwView::IsPasteSpreadsheet(bool bHasOwnTableCopied)
+{
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is() )
+ {
+ if (bHasOwnTableCopied && SwTransferable::IsPasteOwnFormat( aDataHelper ))
+ return true;
+ return aDataHelper.HasFormat( SotClipboardFormatId::SYLK ) || aDataHelper.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS );
+ }
+ return false;
+}
+
+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);
+}
+
+tools::Rectangle SwView::getLOKVisibleArea() const
+{
+ if (SwViewShell* pVwSh = GetWrtShellPtr())
+ return pVwSh->getLOKVisibleArea();
+ else
+ return tools::Rectangle();
+}
+
+void SwView::flushPendingLOKInvalidateTiles()
+{
+ if (SwWrtShell* pSh = GetWrtShellPtr())
+ pSh->FlushPendingLOKInvalidateTiles();
+}
+
+std::optional<OString> SwView::getLOKPayload(int nType, int nViewId) const
+{
+ if (SwWrtShell* pSh = GetWrtShellPtr())
+ return pSh->getLOKPayload(nType, nViewId);
+ else
+ return std::nullopt;
+}
+
+OUString SwView::GetDataSourceName() const
+{
+ uno::Reference<lang::XMultiServiceFactory> xFactory(GetDocShell()->GetModel(), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xSettings(
+ xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+ OUString sDataSourceName = "";
+ xSettings->getPropertyValue("CurrentDatabaseDataSource") >>= sDataSourceName;
+
+ return sDataSourceName;
+}
+
+bool SwView::IsDataSourceAvailable(const OUString sDataSourceName)
+{
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ Reference< XDatabaseContext> xDatabaseContext = DatabaseContext::create(xContext);
+
+ return xDatabaseContext->hasByName(sDataSourceName);
+}
+
+void SwView::BringToAttention(std::vector<basegfx::B2DRange>&& aRanges)
+{
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ m_aBringToAttentionBlinkTimer.Stop();
+ if (aRanges.empty())
+ m_xBringToAttentionOverlayObject.reset();
+ else
+ {
+ m_xBringToAttentionOverlayObject.reset(
+ new sdr::overlay::OverlaySelection(sdr::overlay::OverlayType::Invert,
+ Color(), std::move(aRanges),
+ true /*unused for Invert type*/));
+ m_nBringToAttentionBlinkTimeOutsRemaining = 4;
+ m_aBringToAttentionBlinkTimer.Start();
+ }
+}
+
+void SwView::BringToAttention(const tools::Rectangle& rRect)
+{
+ std::vector<basegfx::B2DRange> aRanges{ basegfx::B2DRange(rRect.Left(), rRect.Top(),
+ rRect.Right(), rRect.Bottom()) };
+ BringToAttention(std::move(aRanges));
+}
+
+void SwView::BringToAttention(const SwNode* pNode)
+{
+ if (!pNode)
+ return;
+
+ std::vector<basegfx::B2DRange> aRanges;
+ const SwFrame* pFrame;
+ if (pNode->IsContentNode())
+ {
+ pFrame = pNode->GetContentNode()->getLayoutFrame(GetWrtShell().GetLayout());
+ }
+ else
+ {
+ // section and table nodes
+ SwNode2Layout aTmp(*pNode, pNode->GetIndex() - 1);
+ pFrame = aTmp.NextFrame();
+ }
+ while (pFrame)
+ {
+ const SwRect& rFrameRect = pFrame->getFrameArea();
+ if (!rFrameRect.IsEmpty())
+ aRanges.emplace_back(rFrameRect.Left(), rFrameRect.Top() + pFrame->GetTopMargin(),
+ rFrameRect.Right(), rFrameRect.Bottom());
+ if (!pFrame->IsFlowFrame())
+ break;
+ const SwFlowFrame* pFollow = SwFlowFrame::CastFlowFrame(pFrame)->GetFollow();
+ if (!pFollow)
+ break;
+ pFrame = &pFollow->GetFrame();
+ }
+ BringToAttention(std::move(aRanges));
+}
+
+IMPL_LINK_NOARG(SwView, BringToAttentionBlinkTimerHdl, Timer*, void)
+{
+ if (GetDrawView() && m_xBringToAttentionOverlayObject)
+ {
+ if (SdrView* pView = GetDrawView())
+ {
+ if (SdrPaintWindow* pPaintWindow = pView->GetPaintWindow(0))
+ {
+ const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager
+ = pPaintWindow->GetOverlayManager();
+ if (m_nBringToAttentionBlinkTimeOutsRemaining % 2 == 0)
+ xOverlayManager->add(*m_xBringToAttentionOverlayObject);
+ else
+ xOverlayManager->remove(*m_xBringToAttentionOverlayObject);
+ --m_nBringToAttentionBlinkTimeOutsRemaining;
+ }
+ else
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ }
+ else
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ }
+ else
+ m_nBringToAttentionBlinkTimeOutsRemaining = 0;
+ if (m_nBringToAttentionBlinkTimeOutsRemaining == 0)
+ {
+ m_xBringToAttentionOverlayObject.reset();
+ m_aBringToAttentionBlinkTimer.Stop();
+ }
+}
+
+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: */
diff --git a/sw/source/uibase/uiview/view0.cxx b/sw/source/uibase/uiview/view0.cxx
new file mode 100644
index 0000000000..66d8c66597
--- /dev/null
+++ b/sw/source/uibase/uiview/view0.cxx
@@ -0,0 +1,770 @@
+/* -*- 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 <config_wasm_strip.h>
+
+#include <SwSpellDialogChildWindow.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/linguprops.hxx>
+#include <unotools/lingucfg.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <viewopt.hxx>
+#include <globals.h>
+#include <sfx2/infobar.hxx>
+#include <sfx2/request.hxx>
+#include <svl/whiter.hxx>
+#include <svx/srchdlg.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/sidebar/SidebarChildWindow.hxx>
+#include <uivwimp.hxx>
+#include <avmedia/mediaplayer.hxx>
+#include <swmodule.hxx>
+#include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <osl/diagnose.h>
+
+#include <sfx2/objface.hxx>
+#include <wrtsh.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <globals.hrc>
+#include <cmdid.h>
+#include <globdoc.hxx>
+#include <wview.hxx>
+#include <OnlineAccessibilityCheck.hxx>
+
+#define ShellClass_SwView
+#define ShellClass_Text
+#define ShellClass_TextDrawText
+
+#include <sfx2/msg.hxx>
+#include <swslots.hxx>
+#include <PostItMgr.hxx>
+
+#include <unotools/moduleoptions.hxx>
+#include <sfx2/viewfac.hxx>
+
+#include <memory>
+#include <swabstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+SFX_IMPL_NAMED_VIEWFACTORY(SwView, "Default")
+{
+ if (utl::ConfigManager::IsFuzzing() || SvtModuleOptions().IsWriter())
+ {
+ SFX_VIEW_REGISTRATION(SwDocShell);
+ SFX_VIEW_REGISTRATION(SwGlobalDocShell);
+ }
+}
+
+SFX_IMPL_INTERFACE(SwView, SfxViewShell)
+
+void SwView::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterChildWindow(SID_NAVIGATOR, true);
+
+ GetStaticInterface()->RegisterChildWindow(::sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
+
+ GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(SwSpellDialogChildWindow::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(FN_REDLINE_ACCEPT);
+ GetStaticInterface()->RegisterChildWindow(SID_HYPERLINK_DIALOG);
+ GetStaticInterface()->RegisterChildWindow(FN_WORDCOUNT_DIALOG);
+#if HAVE_FEATURE_AVMEDIA
+ GetStaticInterface()->RegisterChildWindow(::avmedia::MediaPlayer::GetChildWindowId());
+#endif
+ GetStaticInterface()->RegisterChildWindow(FN_INSERT_FIELD_DATA_ONLY);
+
+ GetStaticInterface()->RegisterChildWindow(FN_SYNC_LABELS, false, SfxShellFeature::SwChildWindowLabel);
+
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS, SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server,
+ ToolbarId::Tools_Toolbox);
+}
+
+
+ShellMode SwView::GetShellMode() const
+{
+ return m_pViewImpl->GetShellMode();
+}
+
+view::XSelectionSupplier* SwView::GetUNOObject()
+{
+ return m_pViewImpl->GetUNOObject();
+}
+
+void SwView::ApplyAccessibilityOptions()
+{
+#if ENABLE_WASM_STRIP_ACCESSIBILITY
+#else
+ m_pWrtShell->ApplyAccessibilityOptions();
+ //to enable the right state of the selection cursor in readonly documents
+ if(GetDocShell()->IsReadOnly())
+ m_pWrtShell->ShowCursor();
+#endif
+}
+
+void SwView::SetMailMergeConfigItem(std::shared_ptr<SwMailMergeConfigItem> const & rConfigItem)
+{
+ m_pViewImpl->SetMailMergeConfigItem(rConfigItem);
+ UIFeatureChanged();
+}
+
+std::shared_ptr<SwMailMergeConfigItem> const & SwView::GetMailMergeConfigItem() const
+{
+ return m_pViewImpl->GetMailMergeConfigItem();
+}
+
+static bool lcl_IsViewMarks( const SwViewOption& rVOpt )
+{
+ return rVOpt.IsHardBlank() &&
+ rVOpt.IsSoftHyph() &&
+ rVOpt.IsFieldShadings();
+}
+static void lcl_SetViewMarks(SwViewOption& rVOpt, bool bOn )
+{
+ rVOpt.SetHardBlank(bOn);
+ rVOpt.SetSoftHyph(bOn);
+ rVOpt.SetAppearanceFlag(
+ ViewOptFlags::FieldShadings, bOn, true);
+}
+
+static void lcl_SetViewMetaChars( SwViewOption& rVOpt, bool bOn)
+{
+ rVOpt.SetViewMetaChars( bOn );
+ if(bOn && !(rVOpt.IsParagraph() ||
+ rVOpt.IsTab() ||
+ rVOpt.IsLineBreak() ||
+ rVOpt.IsShowHiddenChar() ||
+ rVOpt.IsShowBookmarks() ||
+ rVOpt.IsBlank()))
+ {
+ rVOpt.SetParagraph(bOn);
+ rVOpt.SetTab(bOn);
+ rVOpt.SetLineBreak(bOn);
+ rVOpt.SetBlank(bOn);
+ rVOpt.SetShowHiddenChar(bOn);
+ rVOpt.SetShowBookmarks(bOn);
+ }
+}
+
+void SwView::RecheckBrowseMode()
+{
+ // OS: pay attention to numerical order!
+ static sal_uInt16 const aInva[] =
+ {
+ //SID_NEWWINDOW,/*5620*/
+ SID_BROWSER_MODE, /*6313*/
+ SID_RULER_BORDERS, SID_RULER_PAGE_POS,
+ //SID_ATTR_LONG_LRSPACE,
+ SID_HTML_MODE,
+ SID_RULER_PROTECT, /* 10915 */
+ //SID_AUTOSPELL_CHECK,
+ //SID_AUTOSPELL_MARKOFF,
+ SID_TOGGLE_RESOLVED_NOTES, /* 11672*/
+ FN_RULER, /*20211*/
+ FN_VIEW_GRAPHIC, /*20213*/
+ FN_VIEW_BOUNDS, /**/
+ FN_VIEW_FIELDS, /*20215*/
+ FN_VLINEAL, /*20216*/
+ FN_VSCROLLBAR, /*20217*/
+ FN_HSCROLLBAR, /*20218*/
+ FN_VIEW_SECTION_BOUNDARIES, /*20219*/
+ FN_VIEW_META_CHARS, /**/
+ FN_VIEW_MARKS, /**/
+ //FN_VIEW_FIELDNAME, /**/
+ FN_VIEW_TABLEGRID, /*20227*/
+ FN_PRINT_LAYOUT, /*20237*/
+ FN_QRY_MERGE, /*20364*/
+ FN_SHADOWCURSOR, /**/
+ 0
+ };
+ // the view must not exist!
+ GetViewFrame().GetBindings().Invalidate(aInva);
+ CheckVisArea();
+
+ SvxZoomType eType;
+ if( GetWrtShell().GetViewOptions()->getBrowseMode() && SvxZoomType::PERCENT != (eType =
+ GetWrtShell().GetViewOptions()->GetZoomType()) )
+ SetZoom( eType );
+ InvalidateBorder();
+}
+
+// State of view options
+
+void SwView::StateViewOptions(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ SfxBoolItem aBool;
+ const SwViewOption* pOpt = GetWrtShell().GetViewOptions();
+
+ while(nWhich)
+ {
+ bool bReadonly = GetDocShell()->IsReadOnly();
+ if (bReadonly && nWhich != FN_VIEW_GRAPHIC && nWhich != FN_HIGHLIGHT_CHAR_DF)
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ switch(nWhich)
+ {
+ case FN_RULER:
+ {
+ if(!pOpt->IsViewHRuler(true) && !pOpt->IsViewVRuler(true))
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsViewAnyRuler());
+ }
+ break;
+ case SID_BROWSER_MODE:
+ case FN_PRINT_LAYOUT:
+ {
+ bool bState = pOpt->getBrowseMode();
+ if(FN_PRINT_LAYOUT == nWhich)
+ bState = !bState;
+ aBool.SetValue( bState );
+ }
+ break;
+ case FN_VIEW_BOUNDS:
+ aBool.SetValue( pOpt->IsDocBoundaries()); break;
+ case FN_VIEW_SECTION_BOUNDARIES:
+ aBool.SetValue(pOpt->IsSectionBoundaries()); break;
+ case FN_VIEW_GRAPHIC:
+ aBool.SetValue( pOpt->IsGraphic() ); break;
+ case FN_VIEW_FIELDS:
+ aBool.SetValue( pOpt->IsFieldShadings() ); break;
+ case FN_VIEW_FIELDNAME:
+ aBool.SetValue( pOpt->IsFieldName() ); break;
+ case FN_VIEW_MARKS:
+ aBool.SetValue( lcl_IsViewMarks(*pOpt) ); break;
+ case FN_VIEW_META_CHARS:
+ aBool.SetValue( pOpt->IsViewMetaChars() ); break;
+ case FN_VIEW_TABLEGRID:
+ aBool.SetValue( pOpt->IsTableBoundaries() ); break;
+ case SID_TOGGLE_NOTES:
+ {
+ if (!GetPostItMgr()->HasNotes())
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsPostIts());
+ break;
+ }
+ case SID_TOGGLE_RESOLVED_NOTES:
+ {
+ if (!GetPostItMgr()->HasNotes())
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsResolvedPostIts());
+ break;
+ }
+ case FN_VIEW_HIDDEN_PARA:
+ aBool.SetValue( pOpt->IsShowHiddenPara()); break;
+ case FN_VIEW_HIDE_WHITESPACE:
+ {
+ if (pOpt->getBrowseMode() || !pOpt->CanHideWhitespace())
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue(pOpt->IsHideWhitespaceMode());
+ break;
+ }
+ case FN_VIEW_SHOW_WHITESPACE:
+ {
+ aBool.SetValue(!pOpt->IsHideWhitespaceMode());
+ break;
+ }
+ case SID_GRID_VISIBLE:
+ aBool.SetValue( pOpt->IsGridVisible() ); break;
+ case SID_GRID_USE:
+ aBool.SetValue( pOpt->IsSnap() ); break;
+ case SID_HELPLINES_MOVE:
+ aBool.SetValue( pOpt->IsCrossHair() ); break;
+ case FN_VIEW_SMOOTH_SCROLL:
+ aBool.SetValue( pOpt->IsSmoothScroll()); break;
+ case FN_VLINEAL:
+ aBool.SetValue( StatVRuler() ); break;
+ case FN_HSCROLLBAR:
+ if( pOpt->getBrowseMode() )
+ {
+ rSet.DisableItem(nWhich);
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( IsHScrollbarVisible() );
+ break;
+ case FN_VSCROLLBAR:
+ aBool.SetValue( IsVScrollbarVisible() ); break;
+ case SID_AUTOSPELL_CHECK:
+ aBool.SetValue( pOpt->IsOnlineSpell() );
+ break;
+ case SID_ACCESSIBILITY_CHECK_ONLINE:
+ {
+ bool bOnlineAccessibilityCheck = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get();
+ aBool.SetValue(bOnlineAccessibilityCheck);
+ }
+ break;
+ case FN_SHADOWCURSOR:
+ if ( pOpt->getBrowseMode() )
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = 0;
+ }
+ else
+ aBool.SetValue( pOpt->IsShadowCursor() );
+ break;
+ case FN_SHOW_INLINETOOLTIPS:
+ aBool.SetValue( pOpt->IsShowInlineTooltips() );
+ break;
+ case FN_USE_HEADERFOOTERMENU:
+ aBool.SetValue( pOpt->IsUseHeaderFooterMenu() );
+ break;
+ case FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON:
+ aBool.SetValue( pOpt->IsShowOutlineContentVisibilityButton() );
+ break;
+ case FN_SHOW_CHANGES_IN_MARGIN:
+ aBool.SetValue( pOpt->IsShowChangesInMargin() );
+ break;
+ case FN_HIGHLIGHT_CHAR_DF:
+ aBool.SetValue(m_bIsHighlightCharDF);
+ break;
+ case SID_SPOTLIGHT_PARASTYLES:
+ aBool.SetValue(m_bIsSpotlightParaStyles);
+ break;
+ case SID_SPOTLIGHT_CHARSTYLES:
+ aBool.SetValue(m_bIsSpotlightCharStyles);
+ break;
+ }
+
+ if( nWhich )
+ {
+ aBool.SetWhich( nWhich );
+ rSet.Put( aBool );
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// execute view options
+
+void SwView::ExecViewOptions(SfxRequest &rReq)
+{
+ std::optional<SwViewOption> pOpt( *GetWrtShell().GetViewOptions() );
+ bool bModified = GetWrtShell().IsModified();
+
+ int eState = STATE_TOGGLE;
+ bool bSet = false;
+ bool bBrowseModeChanged = false;
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxPoolItem* pAttr=nullptr;
+
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState( nSlot , false, &pAttr ))
+ {
+ bSet = static_cast<const SfxBoolItem*>(pAttr)->GetValue();
+ eState = bSet ? STATE_ON : STATE_OFF;
+ }
+
+ bool bFlag = STATE_ON == eState;
+ uno::Reference< linguistic2::XLinguProperties > xLngProp( ::GetLinguPropertySet() );
+
+ switch ( nSlot )
+ {
+ case FN_VIEW_GRAPHIC:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsGraphic();
+ pOpt->SetGraphic( bFlag );
+ break;
+
+ case FN_VIEW_FIELDS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsFieldShadings() ;
+ pOpt->SetAppearanceFlag(ViewOptFlags::FieldShadings, bFlag, true );
+ break;
+
+ case FN_VIEW_BOUNDS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsDocBoundaries();
+ pOpt->SetAppearanceFlag(ViewOptFlags::DocBoundaries, bFlag, true );
+ break;
+
+ case FN_VIEW_SECTION_BOUNDARIES:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsSectionBoundaries();
+ pOpt->SetAppearanceFlag(ViewOptFlags::SectionBoundaries, bFlag, true );
+ break;
+
+ case SID_GRID_VISIBLE:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsGridVisible();
+
+ pOpt->SetGridVisible( bFlag );
+ break;
+
+ case SID_GRID_USE:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsSnap();
+
+ pOpt->SetSnap( bFlag );
+ break;
+
+ case SID_HELPLINES_MOVE:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsCrossHair();
+
+ pOpt->SetCrossHair( bFlag );
+ break;
+
+ case SID_BROWSER_MODE:
+ bBrowseModeChanged = !pOpt->getBrowseMode();
+ pOpt->setBrowseMode(true );
+ break;
+
+ case FN_PRINT_LAYOUT:
+ bBrowseModeChanged = pOpt->getBrowseMode();
+ pOpt->setBrowseMode( false );
+ break;
+
+ case SID_TOGGLE_NOTES:
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsPostIts();
+
+ GetPostItMgr()->SetLayout();
+ pOpt->SetPostIts( bFlag );
+ if (pOpt->IsPostIts())
+ GetPostItMgr()->CheckMetaText();
+ break;
+
+ case SID_TOGGLE_RESOLVED_NOTES:
+ if ( STATE_TOGGLE == eState )
+ bFlag = pOpt->IsResolvedPostIts();
+
+ GetPostItMgr()->ShowHideResolvedNotes(!bFlag);
+
+ GetPostItMgr()->SetLayout();
+ pOpt->SetResolvedPostIts( !bFlag );
+
+ break;
+
+ case FN_VIEW_HIDDEN_PARA:
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowHiddenPara();
+
+ pOpt->SetShowHiddenPara( bFlag );
+ break;
+
+ case FN_VIEW_HIDE_WHITESPACE:
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsHideWhitespaceMode();
+
+ pOpt->SetHideWhitespaceMode(bFlag);
+ break;
+
+ case FN_VIEW_SHOW_WHITESPACE:
+ if ( STATE_TOGGLE == eState )
+ bFlag = pOpt->IsHideWhitespaceMode();
+
+ pOpt->SetHideWhitespaceMode(!bFlag);
+ break;
+
+ case FN_VIEW_SMOOTH_SCROLL:
+
+ if ( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsSmoothScroll();
+
+ pOpt->SetSmoothScroll( bFlag );
+ break;
+
+ case FN_VLINEAL:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewVRuler();
+
+ pOpt->SetViewVRuler( bFlag );
+ break;
+
+ case FN_VSCROLLBAR:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewVScrollBar();
+
+ pOpt->SetViewVScrollBar( bFlag );
+ break;
+
+ case FN_HSCROLLBAR:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewHScrollBar();
+
+ pOpt->SetViewHScrollBar( bFlag );
+ break;
+
+ case FN_RULER:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewAnyRuler();
+
+ pOpt->SetViewAnyRuler( bFlag );
+ break;
+
+ case FN_VIEW_TABLEGRID:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsTableBoundaries();
+ pOpt->SetAppearanceFlag(ViewOptFlags::TableBoundaries, bFlag, true );
+ break;
+
+ case FN_VIEW_FIELDNAME:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsFieldName() ;
+
+ pOpt->SetFieldName( bFlag );
+ break;
+
+ case FN_VIEW_MARKS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !lcl_IsViewMarks(*pOpt) ;
+
+ lcl_SetViewMarks( *pOpt, bFlag );
+ break;
+
+ case FN_HIGHLIGHT_CHAR_DF:
+ if (STATE_TOGGLE == eState)
+ bFlag = !m_bIsHighlightCharDF;
+ m_bIsHighlightCharDF = bFlag;
+ break;
+
+ case SID_SPOTLIGHT_PARASTYLES:
+ if (!pArgs || (pArgs && !pArgs->HasItem(FN_PARAM_1)))
+ {
+ const SfxStringItem sDeckName(SID_SIDEBAR_DECK, "StyleListDeck");
+ GetDispatcher().ExecuteList(SID_SIDEBAR_DECK, SfxCallMode::SYNCHRON, { &sDeckName });
+ }
+ if (STATE_TOGGLE == eState)
+ bFlag = !m_bIsSpotlightParaStyles;
+ m_bIsSpotlightParaStyles = bFlag;
+ break;
+
+ case SID_SPOTLIGHT_CHARSTYLES:
+ if (!pArgs || (pArgs && !pArgs->HasItem(FN_PARAM_1)))
+ {
+ const SfxStringItem sDeckName(SID_SIDEBAR_DECK, "StyleListDeck");
+ GetDispatcher().ExecuteList(SID_SIDEBAR_DECK, SfxCallMode::SYNCHRON, { &sDeckName });
+ }
+ if (STATE_TOGGLE == eState)
+ bFlag = !m_bIsSpotlightCharStyles;
+ m_bIsSpotlightCharStyles = bFlag;
+ break;
+
+ case FN_VIEW_META_CHARS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsViewMetaChars();
+
+ lcl_SetViewMetaChars( *pOpt, bFlag );
+ break;
+
+ case SID_AUTOSPELL_CHECK:
+ const SfxPoolItem* pItem;
+
+ if (pArgs && pArgs->HasItem(FN_PARAM_1, &pItem))
+ bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ else if( STATE_TOGGLE == eState )
+ {
+ bFlag = !pOpt->IsOnlineSpell();
+ bSet = bFlag;
+ }
+
+ pOpt->SetOnlineSpell(bSet);
+ {
+ SvtLinguConfig aCfg;
+ aCfg.SetProperty( UPN_IS_SPELL_AUTO, uno::Any( bSet ) );
+
+ if (xLngProp.is())
+ xLngProp->setIsSpellAuto( bSet );
+
+ // for the time being we do not have a specific option for grammarchecking.
+ // thus we'll use the one for spell checking...
+ if (bSet)
+ {
+ SwDocShell *pDocSh = GetDocShell();
+ SwDoc *pDoc = pDocSh? pDocSh->GetDoc() : nullptr;
+
+ // right now we don't have view options for automatic grammar checking. Thus...
+ bool bIsAutoGrammar = false;
+ aCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bIsAutoGrammar;
+
+ if (pDoc && bIsAutoGrammar)
+ pDoc->StartGrammarChecking();
+ }
+ }
+ break;
+
+ case SID_ACCESSIBILITY_CHECK_ONLINE:
+ {
+ if (pArgs && pArgs->HasItem(FN_PARAM_1, &pItem))
+ {
+ bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ }
+ else if (STATE_TOGGLE == eState)
+ {
+ bool bOnlineCheck = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get();
+ bSet = !bOnlineCheck;
+ }
+ std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(bSet, batch);
+ batch->commit();
+
+ SwDocShell *pDocSh = GetDocShell();
+ SwDoc* pDocument = pDocSh? pDocSh->GetDoc() : nullptr;
+ if (pDocument)
+ pDocument->getOnlineAccessibilityCheck()->updateCheckerActivity();
+ }
+ break;
+
+ case FN_SHADOWCURSOR:
+ if( STATE_TOGGLE == eState )
+ {
+ bFlag = !pOpt->IsShadowCursor();
+ bSet = bFlag;
+ }
+
+ pOpt->SetShadowCursor(bSet);
+ break;
+
+ case FN_SHOW_INLINETOOLTIPS:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowInlineTooltips();
+
+ pOpt->SetShowInlineTooltips( bFlag );
+ break;
+
+ case FN_USE_HEADERFOOTERMENU:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsUseHeaderFooterMenu();
+
+ pOpt->SetUseHeaderFooterMenu( bFlag );
+ break;
+
+ case FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON:
+ {
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowOutlineContentVisibilityButton();
+
+ SwWrtShell &rSh = GetWrtShell();
+
+ if (!bFlag) // Outline folding is being turned ON!
+ rSh.MakeAllFoldedOutlineContentVisible();
+
+ pOpt->SetShowOutlineContentVisibilityButton(bFlag);
+
+ // Apply option change here so if toggling the outline folding feature ON
+ // the invalidate function will see this.
+ rSh.StartAction();
+ rSh.ApplyViewOptions(*pOpt);
+ rSh.EndAction();
+
+ if (bFlag) // Outline folding is being turned OFF!
+ rSh.MakeAllFoldedOutlineContentVisible(false);
+
+ break;
+ }
+
+ case FN_SHOW_CHANGES_IN_MARGIN:
+ if( STATE_TOGGLE == eState )
+ bFlag = !pOpt->IsShowChangesInMargin();
+
+ pOpt->SetShowChangesInMargin( bFlag );
+ break;
+
+ default:
+ OSL_FAIL("wrong request method");
+ return;
+ }
+
+ // Set UserPrefs, mark request as modified
+ bool bWebView = dynamic_cast<const SwWebView*>(this) != nullptr;
+ SwWrtShell &rSh = GetWrtShell();
+ rSh.StartAction();
+ SwModule* pModule = SW_MOD();
+ if( *rSh.GetViewOptions() != *pOpt )
+ {
+ rSh.ApplyViewOptions( *pOpt );
+ if( bBrowseModeChanged )
+ {
+ GetDocShell()->ToggleLayoutMode(this);
+ }
+
+ // The UsrPref must be marked as modified.
+ // call for initialization
+ pModule->GetUsrPref(bWebView);
+ SwModule::CheckSpellChanges( pOpt->IsOnlineSpell(), false, false, false );
+ }
+ //OS: Set back modified again, because view/fields sets the Doc modified.
+ if( !bModified )
+ rSh.ResetModified();
+
+ pModule->ApplyUsrPref( *pOpt, this, bWebView ? SvViewOpt::DestWeb : SvViewOpt::DestText );
+
+ // #i6193# let postits know about new spellcheck setting
+ if ( nSlot == SID_AUTOSPELL_CHECK )
+ GetPostItMgr()->SetSpellChecking();
+
+ const bool bLockedView = rSh.IsViewLocked();
+ rSh.LockView( true ); //lock visible section
+ GetWrtShell().EndAction();
+ if( bBrowseModeChanged && !bFlag )
+ CalcVisArea( GetEditWin().GetOutputSizePixel() );
+ rSh.LockView( bLockedView );
+
+ pOpt.reset();
+ Invalidate(rReq.GetSlot());
+ if(!pArgs)
+ rReq.AppendItem(SfxBoolItem(nSlot, bFlag));
+ rReq.Done();
+}
+
+void SwView::ExecFormatFootnote()
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSwFootNoteOptionDlg(GetFrameWeld(), GetWrtShell()));
+ pDlg->Execute();
+}
+
+void SwView::ExecNumberingOutline(SfxItemPool & rPool)
+{
+ SfxItemSetFixed<FN_PARAM_1, FN_PARAM_1> aTmp(rPool);
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateOutlineTabDialog(GetFrameWeld(), &aTmp, GetWrtShell()));
+ pDlg->Execute();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view1.cxx b/sw/source/uibase/uiview/view1.cxx
new file mode 100644
index 0000000000..ca51ceba98
--- /dev/null
+++ b/sw/source/uibase/uiview/view1.cxx
@@ -0,0 +1,213 @@
+/* -*- 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 <svl/eitem.hxx>
+#include <svx/ruler.hxx>
+#include <idxmrk.hxx>
+#include <view.hxx>
+#include <basesh.hxx>
+#include <wrtsh.hxx>
+#include <swmodule.hxx>
+#include <docsh.hxx>
+#include <fldwrap.hxx>
+#include <redlndlg.hxx>
+#include <edtwin.hxx>
+#include <formatclipboard.hxx>
+#include <cmdid.h>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <wordcountdialog.hxx>
+
+void SwView::Activate(bool bMDIActivate)
+{
+ // fdo#40438 Update the layout to make sure everything is correct before showing the content
+ m_pWrtShell->StartAction();
+ m_pWrtShell->EndAction( true );
+
+ // Register the current View at the DocShell.
+ // The view remains active at the DocShell until it will
+ // be destroyed or by Activate a new one will be set.
+ SwDocShell* pDocSh = GetDocShell();
+ if(pDocSh)
+ pDocSh->SetView(this);
+ SwModule* pSwMod = SW_MOD();
+ pSwMod->SetView(this);
+
+ // Document size has changed.
+ if(!bDocSzUpdated)
+ DocSzChgd(m_aDocSz);
+
+ // make selection visible
+ if(m_bMakeSelectionVisible)
+ {
+ m_pWrtShell->MakeSelVisible();
+ m_bMakeSelectionVisible = false;
+ }
+ m_pHRuler->SetActive();
+ m_pVRuler->SetActive();
+
+ if ( bMDIActivate )
+ {
+ if ( m_pShell )
+ {
+ SfxDispatcher &rDispatcher = GetDispatcher();
+ SfxShell *pTopShell = rDispatcher.GetShell( 0 );
+
+ // this SwView is the top-most shell on the stack
+ if ( pTopShell == this )
+ {
+ for ( sal_uInt16 i = 1; true; ++i )
+ {
+ SfxShell *pSfxShell = rDispatcher.GetShell( i );
+ // does the stack contain any shells spawned by this SwView already?
+ if ( ( dynamic_cast< const SwBaseShell *>( pSfxShell ) != nullptr
+ || dynamic_cast< const FmFormShell *>( pSfxShell ) != nullptr )
+ && ( pSfxShell->GetViewShell() == this ) )
+ {
+ // it shouldn't b/c we haven't been activated yet
+ // so assert that 'cause it'll crash during dispose at the latest
+ assert( pSfxShell && "Corrupted shell stack: dependent shell positioned below its view");
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ m_pWrtShell->ShellGetFocus(); // Selections visible
+
+ if( !m_sSwViewData.isEmpty() )
+ {
+ ReadUserData(m_sSwViewData);
+ m_sSwViewData.clear();
+ }
+
+ AttrChangedNotify(nullptr);
+
+ // Initialize Fielddlg newly if necessary (e.g. for TYP_SETVAR)
+ sal_uInt16 nId = SwFieldDlgWrapper::GetChildWindowId();
+ SfxViewFrame& rVFrame = GetViewFrame();
+ SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame.GetChildWindow(nId));
+ if (pWrp)
+ pWrp->ReInitDlg(GetDocShell());
+
+ // Initialize RedlineDlg newly if necessary
+ nId = SwRedlineAcceptChild::GetChildWindowId();
+ SwRedlineAcceptChild *pRed = static_cast<SwRedlineAcceptChild*>(rVFrame.GetChildWindow(nId));
+ if (pRed)
+ pRed->ReInitDlg(GetDocShell());
+
+ // reinit IdxMarkDlg
+ nId = SwInsertIdxMarkWrapper::GetChildWindowId();
+ SwInsertIdxMarkWrapper *pIdxMrk = static_cast<SwInsertIdxMarkWrapper*>(rVFrame.GetChildWindow(nId));
+ if (pIdxMrk)
+ pIdxMrk->ReInitDlg(*m_pWrtShell);
+
+ // reinit AuthMarkDlg
+ nId = SwInsertAuthMarkWrapper::GetChildWindowId();
+ SwInsertAuthMarkWrapper *pAuthMrk = static_cast<SwInsertAuthMarkWrapper*>(rVFrame.
+ GetChildWindow(nId));
+ if (pAuthMrk)
+ pAuthMrk->ReInitDlg(*m_pWrtShell);
+ }
+ else
+ // At least call the Notify (as a precaution because of the SlotFilter).
+ AttrChangedNotify(nullptr);
+
+ SfxViewShell::Activate(bMDIActivate);
+}
+
+void SwView::Deactivate(bool bMDIActivate)
+{
+ GetEditWin().FlushInBuffer(); // Flush characters still in the input buffer.
+
+ if( bMDIActivate )
+ {
+ m_pWrtShell->ShellLoseFocus(); // Selections invisible
+
+ m_pHRuler->SetActive( false );
+ m_pVRuler->SetActive( false );
+ }
+ SfxViewShell::Deactivate(bMDIActivate);
+}
+
+void SwView::MarginChanged()
+{
+ GetWrtShell().SetBrowseBorder( GetMargin() );
+}
+
+void SwView::ExecFormatPaintbrush(SfxRequest const & rReq)
+{
+ if(!m_pFormatClipboard)
+ return;
+
+ if( m_pFormatClipboard->HasContent() )
+ {
+ m_pFormatClipboard->Erase();
+
+ SwApplyTemplate aTemplate;
+ GetEditWin().SetApplyTemplate(aTemplate);
+ }
+ else
+ {
+ bool bPersistentCopy = false;
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count() >= 1 )
+ {
+ bPersistentCopy = pArgs->Get(SID_FORMATPAINTBRUSH).GetValue();
+ }
+
+ m_pFormatClipboard->Copy( GetWrtShell(), GetPool(), bPersistentCopy );
+
+ SwApplyTemplate aTemplate;
+ aTemplate.m_pFormatClipboard = m_pFormatClipboard.get();
+ GetEditWin().SetApplyTemplate(aTemplate);
+ }
+ GetViewFrame().GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
+}
+
+void SwView::StateFormatPaintbrush(SfxItemSet &rSet)
+{
+ if(!m_pFormatClipboard)
+ return;
+
+ const bool bHasContent = m_pFormatClipboard->HasContent();
+ if( !bHasContent &&
+ !SwFormatClipboard::CanCopyThisType( GetWrtShell().GetSelectionType())
+ )
+ {
+ rSet.DisableItem( SID_FORMATPAINTBRUSH );
+ }
+ else
+ rSet.Put(SfxBoolItem(SID_FORMATPAINTBRUSH, bHasContent));
+}
+
+void SwView::UpdateWordCount(SfxShell* pShell, sal_uInt16 nSlot)
+{
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ToggleChildWindow(FN_WORDCOUNT_DIALOG);
+ pShell->Invalidate(nSlot);
+
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(rVFrame.GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->UpdateCounts();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
new file mode 100644
index 0000000000..cc6faf78a3
--- /dev/null
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -0,0 +1,3197 @@
+/* -*- 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 <config_fuzzers.h>
+
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <o3tl/any.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <com/sun/star/sdb/DatabaseContext.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/linguistic2/XDictionary.hpp>
+#include <comphelper/propertyvalue.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <SwCapObjType.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <docary.hxx>
+#include <hintids.hxx>
+#include <SwRewriter.hxx>
+#include <numrule.hxx>
+#include <swundo.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <svl/urihelper.hxx>
+#include <sfx2/passwd.hxx>
+#include <sfx2/sfxdlg.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/linkwarn.hxx>
+#include <svx/statusitem.hxx>
+#include <svx/viewlayoutitem.hxx>
+#include <svx/zoomslideritem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <editeng/lrspitem.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <editeng/unolingu.hxx>
+#include <vcl/weld.hxx>
+#include <editeng/tstpitem.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <editeng/sizeitem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svl/whiter.hxx>
+#include <svl/ptitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/errinf.hxx>
+#include <tools/urlobj.hxx>
+#include <svx/svdview.hxx>
+#include <swtypes.hxx>
+#include <swwait.hxx>
+#include <redlndlg.hxx>
+#include <gotodlg.hxx>
+#include <view.hxx>
+#include <uivwimp.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <printdata.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <DocumentRedlineManager.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <IDocumentOutlineNodes.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <basesh.hxx>
+#include <swmodule.hxx>
+#include <uitool.hxx>
+#include <shellio.hxx>
+#include <fmtinfmt.hxx>
+#include <mdiexp.hxx>
+#include <drawbase.hxx>
+#include <frmatr.hxx>
+#include <frmmgr.hxx>
+#include <pagedesc.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <edtwin.hxx>
+#include <wview.hxx>
+#include <cmdid.h>
+#include <sfx2/strings.hrc>
+#include <sfx2/sfxresid.hxx>
+#include <strings.hrc>
+#include <swerror.h>
+#include <globals.hrc>
+#include <fmtclds.hxx>
+#include <sfx2/templatedlg.hxx>
+#include <dbconfig.hxx>
+#include <dbmgr.hxx>
+#include <reffld.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/docpasswordhelper.hxx>
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+
+#include <PostItMgr.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <svx/svxdlg.hxx>
+#include <swabstdlg.hxx>
+#include <fmthdft.hxx>
+#include <unotextrange.hxx>
+#include <docstat.hxx>
+#include <wordcountdialog.hxx>
+#include <OnlineAccessibilityCheck.hxx>
+#include <sfx2/sidebar/Sidebar.hxx>
+
+#include <vcl/GraphicNativeTransform.hxx>
+#include <vcl/GraphicNativeMetadata.hxx>
+#include <vcl/settings.hxx>
+#include <i18nutil/searchopt.hxx>
+#include <osl/diagnose.h>
+#include <paratr.hxx>
+#include <rootfrm.hxx>
+#include <frameformats.hxx>
+
+#include <viewimp.hxx>
+#include <pagefrm.hxx>
+
+#include <memory>
+#include <string_view>
+#include <svl/slstitm.hxx>
+
+#include <basegfx/utils/zoomtools.hxx>
+
+#include <ndtxt.hxx>
+
+#include <svx/srchdlg.hxx>
+#include <o3tl/string_view.hxx>
+
+const char sStatusDelim[] = " : ";
+
+using namespace sfx2;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::scanner;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::ui::dialogs;
+
+namespace {
+
+class SwNumberInputDlg : public SfxDialogController
+{
+private:
+ std::unique_ptr<weld::Label> m_xLabel1;
+ std::unique_ptr<weld::SpinButton> m_xSpinButton;
+ std::unique_ptr<weld::Label> m_xLabel2;
+ std::unique_ptr<weld::Button> m_xOKButton;
+
+ DECL_LINK(InputModifiedHdl, weld::Entry&, void);
+public:
+ SwNumberInputDlg(weld::Window* pParent, const OUString& rTitle,
+ const OUString& rLabel1, const sal_Int64 nValue, const sal_Int64 min, const sal_Int64 max,
+ OUString rLabel2 = OUString())
+ : SfxDialogController(pParent, "modules/swriter/ui/numberinput.ui", "NumberInputDialog")
+ , m_xLabel1(m_xBuilder->weld_label("label1"))
+ , m_xSpinButton(m_xBuilder->weld_spin_button("spinbutton"))
+ , m_xLabel2(m_xBuilder->weld_label("label2"))
+ , m_xOKButton(m_xBuilder->weld_button("ok"))
+ {
+ m_xDialog->set_title(rTitle);
+ m_xLabel1->set_label(rLabel1);
+ m_xSpinButton->set_value(nValue);
+ m_xSpinButton->set_range(min, max);
+ m_xSpinButton->set_position(-1);
+ m_xSpinButton->select_region(0, -1);
+ m_xSpinButton->connect_changed(LINK(this, SwNumberInputDlg, InputModifiedHdl));
+ if (!rLabel2.isEmpty())
+ {
+ m_xLabel2->set_label(rLabel2);
+ m_xLabel2->show();
+ }
+ }
+
+ auto GetNumber()
+ {
+ return m_xSpinButton->get_text().toInt32();
+ }
+};
+
+IMPL_LINK_NOARG(SwNumberInputDlg, InputModifiedHdl, weld::Entry&, void)
+{
+ m_xOKButton->set_sensitive(!m_xSpinButton->get_text().isEmpty());
+ if (!m_xOKButton->get_sensitive())
+ return;
+
+ auto nValue = m_xSpinButton->get_text().toInt32();
+ if (nValue <= m_xSpinButton->get_min())
+ m_xSpinButton->set_value(m_xSpinButton->get_min());
+ else if (nValue > m_xSpinButton->get_max())
+ m_xSpinButton->set_value(m_xSpinButton->get_max());
+ else
+ m_xSpinButton->set_value(nValue);
+
+ m_xSpinButton->set_position(-1);
+}
+
+}
+
+static void lcl_SetAllTextToDefaultLanguage( SwWrtShell &rWrtSh, TypedWhichId<SvxLanguageItem> nWhichId )
+{
+ if (!(nWhichId == RES_CHRATR_LANGUAGE ||
+ nWhichId == RES_CHRATR_CJK_LANGUAGE ||
+ nWhichId == RES_CHRATR_CTL_LANGUAGE))
+ return;
+
+ rWrtSh.StartAction();
+ rWrtSh.LockView( true );
+ rWrtSh.Push();
+
+ // prepare to apply new language to all text in document
+ rWrtSh.SelAll();
+ rWrtSh.ExtendedSelectAll();
+
+ // set language attribute to default for all text
+ rWrtSh.ResetAttr({ nWhichId });
+
+ rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rWrtSh.LockView( false );
+ rWrtSh.EndAction();
+
+}
+
+/**
+ * Create string for showing the page number in the statusbar
+ *
+ * @param nPhyNum The physical page number
+ * @param nVirtNum The logical page number (user-assigned)
+ * @param rPgStr User-defined page name (will be shown if different from logical page number)
+ *
+ * @return OUString Formatted string: Page 1 of 10 (Page 1 of 8 to print OR Page nVirtNumv/rPgStr)
+ **/
+OUString SwView::GetPageStr(sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, const OUString& rPgStr)
+{
+ // Show user-defined page number in brackets if any.
+ OUString extra;
+ if (!rPgStr.isEmpty() && std::u16string_view(OUString::number(nPhyNum)) != rPgStr)
+ extra = rPgStr;
+ else if (nPhyNum != nVirtNum)
+ extra = OUString::number(nVirtNum);
+
+ sal_uInt16 nPageCount = GetWrtShell().GetPageCnt();
+ sal_uInt16 nPrintedPhyNum = nPhyNum;
+ sal_uInt16 nPrintedPageCount = nPageCount;
+ if (!GetWrtShell().getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages())
+ SwDoc::CalculateNonBlankPages(*m_pWrtShell->GetLayout(), nPrintedPageCount, nPrintedPhyNum);
+ // Show printed page numbers only, when they are different
+ OUString aStr( nPageCount != nPrintedPageCount
+ ? SwResId(STR_PAGE_COUNT_PRINTED)
+ : (extra.isEmpty() ? SwResId(STR_PAGE_COUNT) : SwResId(STR_PAGE_COUNT_CUSTOM)));
+ aStr = aStr.replaceFirst("%1", OUString::number(nPhyNum));
+ aStr = aStr.replaceFirst("%2", OUString::number(nPageCount));
+ if (nPageCount != nPrintedPageCount)
+ {
+ aStr = aStr.replaceFirst("%3", OUString::number(nPrintedPhyNum));
+ aStr = aStr.replaceFirst("%4", OUString::number(nPrintedPageCount));
+ }
+ else
+ aStr = aStr.replaceFirst("%3", extra);
+
+ return aStr;
+}
+
+ErrCode SwView::InsertGraphic( const OUString &rPath, const OUString &rFilter,
+ bool bLink, GraphicFilter *pFilter )
+{
+ SwWait aWait( *GetDocShell(), true );
+
+ Graphic aGraphic;
+ ErrCode aResult = ERRCODE_NONE;
+ if( !pFilter )
+ {
+ pFilter = &GraphicFilter::GetGraphicFilter();
+ }
+ aResult = GraphicFilter::LoadGraphic( rPath, rFilter, aGraphic, pFilter );
+
+ if( ERRCODE_NONE == aResult )
+ {
+ GraphicNativeMetadata aMetadata;
+ if ( aMetadata.read(aGraphic) )
+ {
+ const Degree10 aRotation = aMetadata.getRotation();
+ if (aRotation)
+ {
+ GraphicNativeTransform aTransform( aGraphic );
+ aTransform.rotate( aRotation );
+ }
+ }
+
+ SwFlyFrameAttrMgr aFrameManager( true, GetWrtShellPtr(), Frmmgr_Type::GRF, nullptr );
+ SwWrtShell& rShell = GetWrtShell();
+
+ // #i123922# determine if we really want to insert or replace the graphic at a selected object
+ const bool bReplaceMode(rShell.HasSelection() && SelectionType::Frame == rShell.GetSelectionType());
+
+ if(bReplaceMode)
+ {
+ // #i123922# Do same as in D&D, ReRead graphic and all is done
+ rShell.ReRead(
+ bLink ? rPath : OUString(),
+ bLink ? rFilter : OUString(),
+ &aGraphic);
+ }
+ else
+ {
+ rShell.StartAction();
+ if( bLink )
+ {
+ SwDocShell* pDocSh = GetDocShell();
+ INetURLObject aTemp(
+ pDocSh->HasName() ?
+ pDocSh->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) :
+ OUString());
+
+ OUString sURL = URIHelper::SmartRel2Abs(
+ aTemp, rPath, URIHelper::GetMaybeFileHdl() );
+ aGraphic.setOriginURL(sURL);
+ rShell.InsertGraphic( sURL, rFilter, aGraphic, &aFrameManager );
+ }
+ else
+ {
+ rShell.InsertGraphic( OUString(), OUString(), aGraphic, &aFrameManager );
+ }
+
+ // it is too late after "EndAction" because the Shell can already be destroyed.
+ rShell.EndAction();
+ }
+ }
+ return aResult;
+}
+
+bool SwView::InsertGraphicDlg( SfxRequest& rReq )
+{
+ bool bReturn = false;
+ SwDocShell* pDocShell = GetDocShell();
+ SwDoc* pDoc = pDocShell->GetDoc();
+
+ OUString sGraphicFormat = SwResId(STR_POOLFRM_GRAPHIC);
+
+// No file pickers in a non-desktop (mobile app) build.
+
+#if HAVE_FEATURE_DESKTOP
+ // when in HTML mode insert only as a link
+ const sal_uInt16 nHtmlMode = ::GetHtmlMode(pDocShell);
+ std::unique_ptr<FileDialogHelper> pFileDlg(new FileDialogHelper(
+ ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE,
+ FileDialogFlags::Graphic, GetFrameWeld()));
+ pFileDlg->SetTitle(SwResId(STR_INSERT_GRAPHIC ));
+ pFileDlg->SetContext( FileDialogHelper::WriterInsertImage );
+
+ uno::Reference < XFilePicker3 > xFP = pFileDlg->GetFilePicker();
+ uno::Reference < XFilePickerControlAccess > xCtrlAcc(xFP, UNO_QUERY);
+ if(nHtmlMode & HTMLMODE_ON)
+ {
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, Any(true));
+ xCtrlAcc->enableControl( ExtendedFilePickerElementIds::CHECKBOX_LINK, false);
+ }
+
+ std::vector<OUString> aFormats;
+ const size_t nArrLen = pDoc->GetFrameFormats()->size();
+ for( size_t i = 0; i < nArrLen; ++i )
+ {
+ const SwFrameFormat* pFormat = (*pDoc->GetFrameFormats())[ i ];
+ if(pFormat->IsDefault() || pFormat->IsAuto())
+ continue;
+ aFormats.push_back(pFormat->GetName());
+ }
+
+ // pool formats
+
+ const std::vector<OUString>& rFramePoolArr(
+ SwStyleNameMapper::GetFrameFormatUINameArray());
+ for(const auto & i : rFramePoolArr)
+ {
+ aFormats.push_back(i);
+ }
+
+ std::sort(aFormats.begin(), aFormats.end());
+ aFormats.erase(std::unique(aFormats.begin(), aFormats.end()), aFormats.end());
+
+ Sequence<OUString> aListBoxEntries(aFormats.size());
+ OUString* pEntries = aListBoxEntries.getArray();
+ sal_Int16 nSelect = 0;
+ for( size_t i = 0; i < aFormats.size(); ++i )
+ {
+ pEntries[i] = aFormats[i];
+ if(pEntries[i] == sGraphicFormat)
+ nSelect = i;
+ }
+ try
+ {
+ Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
+
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::ADD_ITEMS , aTemplates );
+
+ Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
+ xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::SET_SELECT_ITEM, aSelectPos );
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("control access failed");
+ }
+#endif
+
+ const SfxStringItem* pName = rReq.GetArg<SfxStringItem>(SID_INSERT_GRAPHIC);
+ bool bShowError = !pName;
+
+ bool bHaveName = pName != nullptr;
+#if HAVE_FEATURE_DESKTOP
+ if (!bHaveName && !Application::IsHeadlessModeEnabled())
+ {
+ // execute file dialog, without capturing mouse (tdf#156033)
+ vcl::Window* pWin = GetWindow();
+ const bool bMouseCaptured = pWin && pWin->IsMouseCaptured();
+ if (bMouseCaptured)
+ pWin->ReleaseMouse();
+ bHaveName = ERRCODE_NONE == pFileDlg->Execute();
+ if (bMouseCaptured)
+ pWin->CaptureMouse();
+ }
+#endif
+ if (bHaveName)
+ {
+
+ OUString aFileName, aFilterName;
+ if ( pName )
+ {
+ aFileName = pName->GetValue();
+ const SfxStringItem* pFilter = rReq.GetArg<SfxStringItem>(FN_PARAM_FILTER);
+ if ( pFilter )
+ aFilterName = pFilter->GetValue();
+ }
+#if HAVE_FEATURE_DESKTOP
+ else
+ {
+ aFileName = pFileDlg->GetPath();
+ aFilterName = pFileDlg->GetCurrentFilter();
+ rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
+ rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
+
+ bool bAsLink = false;
+ if(nHtmlMode & HTMLMODE_ON)
+ bAsLink = true;
+ else
+ {
+ try
+ {
+ Any aVal = xCtrlAcc->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0);
+ OSL_ENSURE(aVal.hasValue(), "Value CBX_INSERT_AS_LINK not found");
+ bAsLink = !aVal.hasValue() || *o3tl::doAccess<bool>(aVal);
+ Any aTemplateValue = xCtrlAcc->getValue(
+ ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::GET_SELECTED_ITEM );
+ OUString sTmpl;
+ aTemplateValue >>= sTmpl;
+ rReq.AppendItem( SfxStringItem( FN_PARAM_2, sTmpl) );
+ }
+ catch (const Exception&)
+ {
+ OSL_FAIL("control access failed");
+ }
+ }
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
+ }
+ const SfxBoolItem* pAsLink = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
+ const SfxStringItem* pStyle = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
+#endif
+
+ bool bAsLink = false;
+
+#if HAVE_FEATURE_DESKTOP
+ if( nHtmlMode & HTMLMODE_ON )
+ bAsLink = true;
+ else
+ {
+ if ( rReq.GetArgs() )
+ {
+ if ( pAsLink )
+ bAsLink = pAsLink->GetValue();
+ if ( pStyle && !pStyle->GetValue().isEmpty() )
+ sGraphicFormat = pStyle->GetValue();
+ }
+ else
+ {
+ Any aVal = xCtrlAcc->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0);
+ OSL_ENSURE(aVal.hasValue(), "Value CBX_INSERT_AS_LINK not found");
+ bAsLink = !aVal.hasValue() || *o3tl::doAccess<bool>(aVal);
+ Any aTemplateValue = xCtrlAcc->getValue(
+ ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE,
+ ListboxControlActions::GET_SELECTED_ITEM );
+ OUString sTmpl;
+ aTemplateValue >>= sTmpl;
+ if( !sTmpl.isEmpty() )
+ sGraphicFormat = sTmpl;
+ rReq.AppendItem( SfxStringItem( FN_PARAM_2, sGraphicFormat ) );
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
+ }
+
+ // really store as link only?
+ if( bAsLink && officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() )
+ {
+ SvxLinkWarningDialog aWarnDlg(GetFrameWeld(), pFileDlg->GetPath());
+ if (aWarnDlg.run() != RET_OK)
+ bAsLink=false; // don't store as link
+ }
+ }
+#endif
+
+ SwWrtShell& rSh = GetWrtShell();
+ rSh.LockPaint(LockPaintReason::InsertGraphic);
+ rSh.StartAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME));
+
+ // #i123922# determine if we really want to insert or replace the graphic at a selected object
+ const bool bReplaceMode(rSh.HasSelection() && SelectionType::Frame == rSh.GetSelectionType());
+
+ rSh.StartUndo(SwUndoId::INSERT, &aRewriter);
+
+ ErrCode nError = InsertGraphic( aFileName, aFilterName, bAsLink, &GraphicFilter::GetGraphicFilter() );
+
+ // format not equal to current filter (with autodetection)
+ if( nError == ERRCODE_GRFILTER_FORMATERROR )
+ nError = InsertGraphic( aFileName, OUString(), bAsLink, &GraphicFilter::GetGraphicFilter() );
+
+ // #i123922# no new FrameFormat for replace mode, only when new object was created,
+ // else this would reset the current setting for the frame holding the graphic
+ if ( !bReplaceMode && rSh.IsFrameSelected() )
+ {
+ SwFrameFormat* pFormat = pDoc->FindFrameFormatByName( sGraphicFormat );
+ if(!pFormat)
+ pFormat = pDoc->MakeFrameFormat(sGraphicFormat,
+ pDocShell->GetDoc()->GetDfltFrameFormat(),
+ true, false);
+ rSh.SetFrameFormat( pFormat );
+ }
+
+ TranslateId pResId;
+ if( nError == ERRCODE_GRFILTER_OPENERROR )
+ pResId = STR_GRFILTER_OPENERROR;
+ else if( nError == ERRCODE_GRFILTER_IOERROR )
+ pResId = STR_GRFILTER_IOERROR;
+ else if( nError ==ERRCODE_GRFILTER_FORMATERROR )
+ pResId = STR_GRFILTER_FORMATERROR;
+ else if( nError ==ERRCODE_GRFILTER_VERSIONERROR )
+ pResId = STR_GRFILTER_VERSIONERROR;
+ else if( nError ==ERRCODE_GRFILTER_FILTERERROR )
+ pResId = STR_GRFILTER_FILTERERROR;
+ else if( nError ==ERRCODE_GRFILTER_TOOBIG )
+ pResId = STR_GRFILTER_TOOBIG;
+
+ rSh.EndAction();
+ rSh.UnlockPaint();
+ if (pResId)
+ {
+ if( bShowError )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(pResId)));
+ xInfoBox->run();
+ }
+ rReq.Ignore();
+ }
+ else
+ {
+ // set the specific graphic attributes to the graphic
+ bReturn = true;
+ AutoCaption( GRAPHIC_CAP );
+ rReq.Done();
+ }
+
+ rSh.EndUndo(); // due to possible change of Shell
+ }
+
+ return bReturn;
+}
+
+void SwView::Execute(SfxRequest &rReq)
+{
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ bool bIgnore = false;
+ switch( nSlot )
+ {
+ case SID_CREATE_SW_DRAWVIEW:
+ m_pWrtShell->getIDocumentDrawModelAccess().GetOrCreateDrawModel();
+ break;
+
+ case FN_LINE_NUMBERING_DLG:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclSwViewDialog(*this));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32){};
+ pDlg->StartExecuteAsync(aContext);
+ break;
+ }
+ case FN_EDIT_LINK_DLG:
+ EditLinkDlg();
+ break;
+ case SID_REFRESH_VIEW:
+ GetEditWin().Invalidate();
+ m_pWrtShell->Reformat();
+ break;
+ case FN_PAGEUP:
+ case FN_PAGEUP_SEL:
+ case FN_PAGEDOWN:
+ case FN_PAGEDOWN_SEL:
+ {
+ tools::Rectangle aVis( GetVisArea() );
+ SwEditWin& rTmpWin = GetEditWin();
+ if ( FN_PAGEUP == nSlot || FN_PAGEUP_SEL == nSlot )
+ PageUpCursor(FN_PAGEUP_SEL == nSlot);
+ else
+ PageDownCursor(FN_PAGEDOWN_SEL == nSlot);
+
+ rReq.SetReturnValue(SfxBoolItem(nSlot,
+ aVis != GetVisArea()));
+ //#i42732# - notify the edit window that from now on we do not use the input language
+ rTmpWin.SetUseInputLanguage( false );
+ }
+ break;
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ sal_uInt16 nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ if (SID_ZOOM_IN == nSlot)
+ nFact = basegfx::zoomtools::zoomIn(nFact);
+ else
+ nFact = basegfx::zoomtools::zoomOut(nFact);
+ SetZoom(SvxZoomType::PERCENT, nFact);
+ }
+ break;
+ case FN_TO_PREV_PAGE:
+ case FN_TO_NEXT_PAGE:
+ {
+ sal_uInt16 nPage = 0;
+ if (m_pWrtShell->IsCursorVisible())
+ nPage = m_pWrtShell->GetCursor()->GetPageNum();
+ else
+ {
+ SwFrame* pPageFrame = m_pWrtShell->Imp()->GetFirstVisPage(m_pWrtShell->GetOut());
+ if (pPageFrame)
+ nPage = pPageFrame->GetPhyPageNum();
+ }
+ if (nPage != 0)
+ {
+ sal_uInt16 nOldPage(nPage);
+ if (FN_TO_PREV_PAGE == nSlot && nPage > 1)
+ nPage--;
+ else if (FN_TO_NEXT_PAGE == nSlot && nPage < m_pWrtShell->GetPageCount())
+ nPage++;
+ if (nPage != nOldPage)
+ {
+ m_pWrtShell->LockPaint(LockPaintReason::GotoPage);
+ if (IsDrawMode())
+ LeaveDrawCreate();
+ m_pWrtShell->EnterStdMode();
+ m_pWrtShell->GotoPage(nPage, true);
+ // set visible area (borrowed from SwView::PhyPageUp/Down)
+ const Point aPt(m_aVisArea.Left(), m_pWrtShell->GetPagePos(nPage).Y());
+ Point aAlPt(AlignToPixel(aPt));
+ if(aPt.Y() != aAlPt.Y())
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic(Size(0, 1)).Height());
+ SetVisArea(aAlPt);
+ m_pWrtShell->UnlockPaint();
+ }
+ }
+ }
+ break;
+ case FN_SELECTION_CYCLE:
+ {
+ if (m_pWrtShell->IsSelFrameMode())
+ break;
+ if (!m_pWrtShell->IsStdMode())
+ m_pWrtShell->EnterStdMode();
+ SwShellCursor *pCursor = m_pWrtShell->SwCursorShell::GetCursor_();
+ Point CurrMarkPt = pCursor->GetMkPos();
+ Point CurrPointPt = pCursor->GetPtPos();
+ sal_uInt16 nStep = m_aSelectCycle.nStep;
+ if (nStep && (CurrMarkPt != m_aSelectCycle.m_MarkPt || CurrPointPt != m_aSelectCycle.m_PointPt))
+ nStep = 0;
+ switch(nStep)
+ {
+ case 0:
+ m_aSelectCycle.m_pInitialCursor = CurrPointPt;
+ m_pWrtShell->SwCursorShell::ClearMark();
+ m_pWrtShell->SelWrd(&CurrPointPt);
+ break;
+ case 1:
+ m_pWrtShell->SelSentence(&CurrPointPt);
+ break;
+ case 2:
+ m_pWrtShell->SelPara(&CurrPointPt);
+ break;
+ case 3:
+ m_pWrtShell->SwCursorShell::ClearMark();
+ m_pWrtShell->SwCursorShell::SetCursor(m_aSelectCycle.m_pInitialCursor);
+ break;
+ }
+ nStep++;
+ nStep %= 4;
+ pCursor = m_pWrtShell->SwCursorShell::GetCursor_();
+ m_aSelectCycle.m_MarkPt = pCursor->GetMkPos();
+ m_aSelectCycle.m_PointPt = pCursor->GetPtPos();
+ m_aSelectCycle.nStep = nStep;
+ }
+ break;
+ case FN_REDLINE_ON:
+ {
+ if( pArgs &&
+ SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem ))
+ {
+ IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess();
+ Sequence <sal_Int8> aPasswd = rIDRA.GetRedlinePassword();
+ if( aPasswd.hasElements() )
+ {
+ OSL_ENSURE( !static_cast<const SfxBoolItem*>(pItem)->GetValue(), "SwView::Execute(): password set and redlining off doesn't match!" );
+
+ // xmlsec05: new password dialog
+ SfxPasswordDialog aPasswdDlg(GetFrameWeld());
+ aPasswdDlg.SetMinLen(1);
+ //#i69751# the result of Execute() can be ignored
+ (void)aPasswdDlg.run();
+ OUString sNewPasswd(aPasswdDlg.GetPassword());
+
+ // password verification
+ bool bPasswordOk = false;
+ if (aPasswd.getLength() == 1 && aPasswd[0] == 1)
+ {
+ // dummy RedlinePassword from OOXML import: get real password info
+ // from the grab-bag to verify the password
+ const css::uno::Sequence< css::beans::PropertyValue > aDocumentProtection =
+ static_cast<SfxObjectShell*>(GetDocShell())->
+ GetDocumentProtectionFromGrabBag();
+
+ bPasswordOk =
+ // password is ok, if there is no DocumentProtection in the GrabBag,
+ // i.e. the dummy RedlinePassword imported from an OpenDocument file
+ !aDocumentProtection.hasElements() ||
+ // verify password with the password info imported from OOXML
+ ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect(sNewPasswd,
+ ::comphelper::DocPasswordHelper::ConvertPasswordInfo ( aDocumentProtection ) );
+ }
+ else
+ {
+ // the simplified RedlinePassword
+ Sequence <sal_Int8> aNewPasswd = rIDRA.GetRedlinePassword();
+ SvPasswordHelper::GetHashPassword( aNewPasswd, sNewPasswd );
+ bPasswordOk = SvPasswordHelper::CompareHashPassword(aPasswd, sNewPasswd);
+ }
+
+ if (bPasswordOk)
+ rIDRA.SetRedlinePassword(Sequence <sal_Int8> ());
+ else
+ { // xmlsec05: message box for wrong password
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SfxResId(RID_SVXSTR_INCORRECT_PASSWORD)));
+ xInfoBox->run();
+ break;
+ }
+ }
+
+ SwDocShell* pDocShell = GetDocShell();
+ pDocShell->SetChangeRecording( static_cast<const SfxBoolItem*>(pItem)->GetValue(), /*bLockAllViews=*/true );
+
+ // Notify all view shells of this document, as the track changes mode is document-global.
+ for (SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pDocShell); pViewFrame; pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pDocShell))
+ {
+ pViewFrame->GetBindings().Invalidate(FN_REDLINE_ON);
+ pViewFrame->GetBindings().Update(FN_REDLINE_ON);
+ }
+ }
+ }
+ break;
+ case FN_REDLINE_PROTECT :
+ {
+ IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess();
+ Sequence <sal_Int8> aPasswd = rIDRA.GetRedlinePassword();
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem )
+ && static_cast<const SfxBoolItem*>(pItem)->GetValue() == aPasswd.hasElements() )
+ break;
+
+ // xmlsec05: new password dialog
+ // message box for wrong password
+ SfxPasswordDialog aPasswdDlg(GetFrameWeld());
+ aPasswdDlg.SetMinLen(1);
+ if (!aPasswd.hasElements())
+ aPasswdDlg.ShowExtras(SfxShowExtras::CONFIRM);
+ if (aPasswdDlg.run())
+ {
+ RedlineFlags nOn = RedlineFlags::On;
+ OUString sNewPasswd(aPasswdDlg.GetPassword());
+ Sequence <sal_Int8> aNewPasswd =
+ rIDRA.GetRedlinePassword();
+ SvPasswordHelper::GetHashPassword( aNewPasswd, sNewPasswd );
+ if(!aPasswd.hasElements())
+ {
+ rIDRA.SetRedlinePassword(aNewPasswd);
+ }
+ else if(SvPasswordHelper::CompareHashPassword(aPasswd, sNewPasswd))
+ {
+ rIDRA.SetRedlinePassword(Sequence <sal_Int8> ());
+ nOn = RedlineFlags::NONE;
+ }
+ const RedlineFlags nMode = rIDRA.GetRedlineFlags();
+ m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn);
+ rReq.AppendItem( SfxBoolItem( FN_REDLINE_PROTECT, !(nMode&RedlineFlags::On) ) );
+ }
+ else
+ bIgnore = true;
+ }
+ break;
+ case FN_REDLINE_SHOW:
+
+ if( pArgs &&
+ SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem))
+ {
+ // tdf#125754 avoid recursive layout
+ // because all views share the layout, have to use AllAction
+ const bool bShow = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ m_pWrtShell->StartAllAction();
+ // always show redline insertions in Hide Changes mode
+ if ( m_pWrtShell->GetViewOptions()->IsShowChangesInMargin() &&
+ m_pWrtShell->GetViewOptions()->IsShowChangesInMargin2() )
+ {
+ GetDocShell()->GetDoc()->GetDocumentRedlineManager().HideAll(/*bDeletion=*/!bShow);
+ }
+ m_pWrtShell->GetLayout()->SetHideRedlines( !bShow );
+ m_pWrtShell->EndAllAction();
+ if (m_pWrtShell->IsRedlineOn())
+ m_pWrtShell->SetInsMode();
+ }
+ break;
+ case FN_MAILMERGE_SENDMAIL_CHILDWINDOW:
+ case FN_REDLINE_ACCEPT:
+ GetViewFrame().ToggleChildWindow(nSlot);
+ break;
+ case FN_REDLINE_ACCEPT_DIRECT:
+ case FN_REDLINE_REJECT_DIRECT:
+ case FN_REDLINE_ACCEPT_TONEXT:
+ case FN_REDLINE_REJECT_TONEXT:
+ {
+ SwDoc *pDoc = m_pWrtShell->GetDoc();
+ SwPaM *pCursor = m_pWrtShell->GetCursor();
+ const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ SwRedlineTable::size_type nRedline = SwRedlineTable::npos;
+ if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
+ {
+ const sal_Int64 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
+ for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i)
+ {
+ if (nChangeId == rRedlineTable[i]->GetId())
+ nRedline = i;
+ }
+ }
+
+ if( pCursor->HasMark() && nRedline == SwRedlineTable::npos)
+ {
+ bool bAccept = FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot;
+ SwUndoId eUndoId = bAccept ? SwUndoId::ACCEPT_REDLINE : SwUndoId::REJECT_REDLINE;
+ SwWrtShell& rSh = GetWrtShell();
+ SwRewriter aRewriter;
+ bool bTableSelection = rSh.IsTableMode();
+ if ( bTableSelection )
+ {
+ aRewriter.AddRule(UndoArg1, SwResId( STR_REDLINE_TABLECHG ));
+ rSh.StartUndo( eUndoId, &aRewriter);
+ }
+ if ( bAccept )
+ m_pWrtShell->AcceptRedlinesInSelection();
+ else
+ m_pWrtShell->RejectRedlinesInSelection();
+ if ( bTableSelection )
+ rSh.EndUndo( eUndoId, &aRewriter);
+ }
+ else
+ {
+ // We check for a redline at the start of the selection/cursor, not the point.
+ // This ensures we work properly with FN_REDLINE_NEXT_CHANGE, which leaves the
+ // point at the *end* of the redline and the mark at the start (so GetRedline
+ // would return NULL if called on the point)
+ const SwRangeRedline* pRedline = nullptr;
+ if (nRedline != SwRedlineTable::npos)
+ {
+ // A redline was explicitly requested by specifying an
+ // index, don't guess based on the cursor position.
+
+ if (nRedline < rRedlineTable.size())
+ pRedline = rRedlineTable[nRedline];
+ }
+ else
+ pRedline = pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), &nRedline);
+
+ // accept or reject table row deletion or insertion
+ bool bTableChange = false;
+ if ( !pRedline && m_pWrtShell->IsCursorInTable() )
+ {
+ nRedline = 0;
+ auto pTabBox = pCursor->Start()->GetNode().GetTableBox();
+ auto pTabLine = pTabBox->GetUpper();
+ const SwTableNode* pTableNd = pCursor->Start()->GetNode().FindTableNode();
+
+ if ( RedlineType::None != pTabLine->GetRedlineType() )
+ {
+ nRedline = pTabLine->UpdateTextChangesOnly(nRedline);
+
+ if ( nRedline != SwRedlineTable::npos )
+ {
+ bTableChange = true;
+
+ SwWrtShell& rSh = GetWrtShell();
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, SwResId(
+ rRedlineTable[nRedline]->GetType() == RedlineType::Delete
+ ? STR_REDLINE_TABLE_ROW_DELETE
+ : STR_REDLINE_TABLE_ROW_INSERT ));
+
+ SwUndoId eUndoId =
+ (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ ? SwUndoId::ACCEPT_REDLINE
+ : SwUndoId::REJECT_REDLINE;
+
+ rSh.StartUndo( eUndoId, &aRewriter);
+ while ( nRedline != SwRedlineTable::npos && nRedline < rRedlineTable.size() )
+ {
+ pRedline = rRedlineTable[nRedline];
+
+ // until next redline is not in the same row
+ SwTableBox* pTableBox = pRedline->Start()->GetNode().GetTableBox();
+ if ( !pTableBox || pTableBox->GetUpper() != pTabLine )
+ break;
+
+ if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ m_pWrtShell->AcceptRedline(nRedline);
+ else
+ m_pWrtShell->RejectRedline(nRedline);
+ }
+ rSh.EndUndo( eUndoId, &aRewriter);
+ }
+ }
+ else if ( RedlineType::None != pTabBox->GetRedlineType() )
+ {
+ nRedline = pTabBox->GetRedline();
+
+ if ( nRedline != SwRedlineTable::npos )
+ {
+ bTableChange = true;
+
+ SwWrtShell& rSh = GetWrtShell();
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UndoArg1, SwResId(
+ rRedlineTable[nRedline]->GetType() == RedlineType::Delete
+ ? STR_REDLINE_TABLE_COLUMN_DELETE
+ : STR_REDLINE_TABLE_COLUMN_INSERT ));
+
+ SwUndoId eUndoId =
+ (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ ? SwUndoId::ACCEPT_REDLINE
+ : SwUndoId::REJECT_REDLINE;
+
+ // change only the cells with the same data
+ SwRedlineData aData(rRedlineTable[nRedline]->GetRedlineData(0));
+
+ // start from the first redline of the table to handle all the
+ // cells of the changed column(s)
+ while ( nRedline )
+ {
+ pRedline = rRedlineTable[nRedline-1];
+ SwTableBox* pTableBox = pRedline->Start()->GetNode().GetTableBox();
+ SwTableNode* pTableNode = pRedline->Start()->GetNode().FindTableNode();
+
+ // previous redline is not in the same table
+ if ( !pTableBox || pTableNode != pTableNd )
+ break;
+
+ --nRedline;
+ }
+
+ rSh.StartUndo( eUndoId, &aRewriter);
+ while ( nRedline != SwRedlineTable::npos && nRedline < rRedlineTable.size() )
+ {
+ pRedline = rRedlineTable[nRedline];
+
+ // until next redline is not in the same table
+ SwTableBox* pTableBox = pRedline->Start()->GetNode().GetTableBox();
+ SwTableNode* pTableNode = pRedline->Start()->GetNode().FindTableNode();
+ if ( !pTableBox || pTableNode != pTableNd )
+ break;
+
+ // skip cells which are not from the same author, same type change
+ // or timestamp, i.e. keep only the cells of the same tracked
+ // column insertion or deletion
+ if ( !pRedline->GetRedlineData(0).CanCombine(aData) ||
+ // not a tracked cell change
+ RedlineType::None == pTableBox->GetRedlineType() )
+ {
+ ++nRedline;
+ continue;
+ }
+
+ if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ m_pWrtShell->AcceptRedline(nRedline);
+ else
+ m_pWrtShell->RejectRedline(nRedline);
+ }
+ rSh.EndUndo( eUndoId, &aRewriter);
+ }
+ }
+ }
+ else
+ {
+ assert(pRedline != nullptr);
+ }
+
+ if (pRedline && !bTableChange)
+ {
+ if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot)
+ m_pWrtShell->AcceptRedline(nRedline);
+ else
+ m_pWrtShell->RejectRedline(nRedline);
+ }
+ }
+ if (FN_REDLINE_ACCEPT_TONEXT == nSlot || FN_REDLINE_REJECT_TONEXT == nSlot)
+ {
+ // Go to next change after accepting or rejecting one (tdf#101977)
+ GetViewFrame().GetDispatcher()->Execute(FN_REDLINE_NEXT_CHANGE, SfxCallMode::ASYNCHRON);
+ }
+ }
+ break;
+
+ case FN_REDLINE_NEXT_CHANGE:
+ {
+ // If a parameter is provided, try going to the nth change, not to
+ // the next one.
+ SwDoc* pDoc = m_pWrtShell->GetDoc();
+ const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ SwRedlineTable::size_type nRedline = SwRedlineTable::npos;
+ if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
+ {
+ const sal_uInt32 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
+ for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i)
+ {
+ if (nChangeId == rRedlineTable[i]->GetId())
+ nRedline = i;
+ }
+ }
+
+ const SwRangeRedline *pNext = nullptr;
+ if (nRedline < rRedlineTable.size())
+ pNext = m_pWrtShell->GotoRedline(nRedline, true);
+ else
+ pNext = m_pWrtShell->SelNextRedline();
+
+ if (pNext)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ sal_uInt32 nRedlineId = pNext->GetId();
+ OString aPayload(".uno:CurrentTrackedChangeId=" + OString::number(nRedlineId));
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+
+ m_pWrtShell->SetInSelect();
+ }
+
+ }
+ break;
+
+ case FN_REDLINE_PREV_CHANGE:
+ {
+ const SwRangeRedline *pPrev = m_pWrtShell->SelPrevRedline();
+
+ if (pPrev)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ sal_uInt32 nRedlineId = pPrev->GetId();
+ OString aPayload(".uno:CurrentTrackedChangeId=" + OString::number(nRedlineId));
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+
+ m_pWrtShell->SetInSelect();
+ }
+ }
+ break;
+
+ case SID_DOCUMENT_COMPARE:
+ case SID_DOCUMENT_MERGE:
+ {
+ OUString sFileName, sFilterName;
+ sal_Int16 nVersion = 0;
+ bool bHasFileName = false;
+ m_pViewImpl->SetParam( 0 );
+ bool bNoAcceptDialog = false;
+
+ if( pArgs )
+ {
+ if( const SfxStringItem* pFileItem = pArgs->GetItemIfSet( SID_FILE_NAME, false ))
+ sFileName = pFileItem->GetValue();
+ bHasFileName = !sFileName.isEmpty();
+
+ if( const SfxStringItem* pFilterNameItem = pArgs->GetItemIfSet( SID_FILTER_NAME, false ))
+ sFilterName = pFilterNameItem->GetValue();
+
+ if( const SfxInt16Item* pVersionItem = pArgs->GetItemIfSet( SID_VERSION, false ))
+ {
+ nVersion = pVersionItem->GetValue();
+ m_pViewImpl->SetParam( nVersion );
+ }
+ if( const SfxBoolItem* pDialogItem = pArgs->GetItemIfSet( SID_NO_ACCEPT_DIALOG, false ))
+ {
+ bNoAcceptDialog = pDialogItem->GetValue();
+ }
+ }
+
+ m_pViewImpl->InitRequest( rReq );
+ tools::Long nFound = InsertDoc( nSlot, sFileName, sFilterName, nVersion );
+
+ if ( bHasFileName )
+ {
+ rReq.SetReturnValue( SfxInt32Item( nSlot, nFound ));
+
+ if (nFound > 0 && !bNoAcceptDialog) // show Redline browser
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ShowChildWindow(FN_REDLINE_ACCEPT);
+
+ // re-initialize the Redline dialog
+ const sal_uInt16 nId = SwRedlineAcceptChild::GetChildWindowId();
+ SwRedlineAcceptChild *pRed = static_cast<SwRedlineAcceptChild*>(
+ rVFrame.GetChildWindow(nId));
+ if (pRed)
+ pRed->ReInitDlg(GetDocShell());
+ }
+ }
+ else
+ bIgnore = true;
+ }
+ break;
+ case FN_SYNC_LABELS:
+ GetViewFrame().ShowChildWindow(nSlot);
+ break;
+ case FN_ESCAPE:
+ {
+ if ( m_pWrtShell->HasDrawViewDrag() )
+ {
+ m_pWrtShell->BreakDrag();
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ else if ( m_pWrtShell->IsDrawCreate() )
+ {
+ GetDrawFuncPtr()->BreakCreate();
+ AttrChangedNotify(nullptr); // shell change if needed
+ }
+ else if ( m_pWrtShell->HasSelection() || IsDrawMode() )
+ {
+ SdrView *pSdrView = m_pWrtShell->HasDrawView() ? m_pWrtShell->GetDrawView() : nullptr;
+ if(pSdrView && pSdrView->AreObjectsMarked() &&
+ pSdrView->GetHdlList().GetFocusHdl())
+ {
+ const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
+ }
+ else
+ {
+ if(pSdrView)
+ {
+ LeaveDrawCreate();
+ Point aPt(LONG_MIN, LONG_MIN);
+ //go out of the frame
+ m_pWrtShell->SelectObj(aPt, SW_LEAVE_FRAME);
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate( SID_ATTR_SIZE );
+ }
+ m_pWrtShell->EnterStdMode();
+ AttrChangedNotify(nullptr); // shell change if necessary
+ }
+ }
+ else if ( GetEditWin().GetApplyTemplate() )
+ {
+ GetEditWin().SetApplyTemplate(SwApplyTemplate());
+ }
+ else if( static_cast<SfxObjectShell*>(GetDocShell())->IsInPlaceActive() )
+ {
+ Escape();
+ }
+ else if ( GetEditWin().IsChainMode() )
+ {
+ GetEditWin().SetChainMode( false );
+ }
+ else if( m_pWrtShell->GetFlyFrameFormat() )
+ {
+ const SwFrameFormat* pFormat = m_pWrtShell->GetFlyFrameFormat();
+ if(m_pWrtShell->GotoFly( pFormat->GetName(), FLYCNTTYPE_FRM ))
+ {
+ m_pWrtShell->HideCursor();
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ }
+ else
+ {
+ SfxBoolItem aItem( SID_WIN_FULLSCREEN, false );
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_WIN_FULLSCREEN,
+ SfxCallMode::RECORD, { &aItem });
+ bIgnore = true;
+ }
+ }
+ break;
+ case SID_ATTR_BORDER_INNER:
+ case SID_ATTR_BORDER_OUTER:
+ case SID_ATTR_BORDER_SHADOW:
+ if(pArgs)
+ m_pWrtShell->SetAttrSet(*pArgs);
+ break;
+
+ case SID_ATTR_PAGE:
+ case SID_ATTR_PAGE_SIZE:
+ case SID_ATTR_PAGE_MAXSIZE:
+ case SID_ATTR_PAGE_PAPERBIN:
+ case SID_ATTR_PAGE_EXT1:
+ case FN_PARAM_FTN_INFO:
+ {
+ if(pArgs)
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ SwPageDesc aPageDesc( m_pWrtShell->GetPageDesc( nCurIdx ) );
+ ::ItemSetToPageDesc( *pArgs, aPageDesc );
+ // change the descriptor of the core
+ m_pWrtShell->ChgPageDesc( nCurIdx, aPageDesc );
+ }
+ }
+ break;
+ case FN_GOTO_PAGE:
+ {
+ SwGotoPageDlg aDlg(GetViewFrame().GetFrameWeld(), GetViewFrame().GetBindings());
+ if (aDlg.run() == RET_OK)
+ GetWrtShell().GotoPage(aDlg.GetPageSelection(), true);
+ }
+ break;
+ case FN_EDIT_CURRENT_TOX:
+ {
+ GetViewFrame().GetDispatcher()->Execute(
+ FN_INSERT_MULTI_TOX, SfxCallMode::ASYNCHRON);
+ }
+ break;
+ case FN_UPDATE_CUR_TOX:
+ {
+ const SwTOXBase* pBase = m_pWrtShell->GetCurTOX();
+ if(pBase)
+ {
+ // tdf#106374: don't jump view on the update
+ const bool bWasLocked = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView(true);
+ m_pWrtShell->StartAction();
+ if(TOX_INDEX == pBase->GetType())
+ m_pWrtShell->ApplyAutoMark();
+ m_pWrtShell->UpdateTableOf( *pBase );
+ m_pWrtShell->EndAction();
+ if (!bWasLocked)
+ m_pWrtShell->LockView(false);
+ }
+ }
+ break;
+ case FN_UPDATE_TOX:
+ {
+ m_pWrtShell->StartAction();
+ m_pWrtShell->EnterStdMode();
+ bool bOldCursorInReadOnly = m_pWrtShell->IsReadOnlyAvailable();
+ m_pWrtShell->SetReadOnlyAvailable( true );
+
+ for( int i = 0; i < 2; ++i )
+ {
+ if( m_pWrtShell->GetTOXCount() == 1 )
+ ++i;
+
+ while( m_pWrtShell->GotoPrevTOXBase() )
+ ; // jump to the first "table of ..."
+
+ // if we are not in one, jump to next
+ const SwTOXBase* pBase = m_pWrtShell->GetCurTOX();
+ if( !pBase )
+ {
+ if (m_pWrtShell->GotoNextTOXBase())
+ pBase = m_pWrtShell->GetCurTOX();
+ }
+
+ bool bAutoMarkApplied = false;
+ while( pBase )
+ {
+ if(TOX_INDEX == pBase->GetType() && !bAutoMarkApplied)
+ {
+ m_pWrtShell->ApplyAutoMark();
+ bAutoMarkApplied = true;
+ }
+ // pBase is needed only for the interface. Should be changed in future! (JP 1996)
+ m_pWrtShell->UpdateTableOf( *pBase );
+
+ if( m_pWrtShell->GotoNextTOXBase() )
+ pBase = m_pWrtShell->GetCurTOX();
+ else
+ pBase = nullptr;
+ }
+ }
+ m_pWrtShell->SetReadOnlyAvailable( bOldCursorInReadOnly );
+ m_pWrtShell->EndAction();
+ }
+ break;
+ case SID_ATTR_BRUSH:
+ {
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(RES_BACKGROUND, false, &pItem))
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ SwPageDesc aDesc( m_pWrtShell->GetPageDesc( nCurIdx ));
+ SwFrameFormat& rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr(*pItem);
+ m_pWrtShell->ChgPageDesc( nCurIdx, aDesc);
+ }
+ }
+ break;
+ case SID_CLEARHISTORY:
+ {
+ m_pWrtShell->DelAllUndoObj();
+ }
+ break;
+ case SID_UNDO:
+ {
+ m_pShell->ExecuteSlot(rReq);
+ }
+ break;
+#if defined(_WIN32) || defined UNX
+ case SID_TWAIN_SELECT:
+ case SID_TWAIN_TRANSFER:
+ GetViewImpl()->ExecuteScan( rReq );
+ break;
+#endif
+
+ case SID_ATTR_DEFTABSTOP:
+ {
+ const SfxUInt16Item* pTabStopItem = nullptr;
+ if(pArgs && (pTabStopItem = pArgs->GetItemIfSet(SID_ATTR_DEFTABSTOP, false)))
+ {
+ SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
+ const sal_uInt16 nTab = pTabStopItem->GetValue();
+ MakeDefTabs( nTab, aDefTabs );
+ m_pWrtShell->SetDefault( aDefTabs );
+ }
+ }
+ break;
+ case SID_ATTR_LANGUAGE :
+ {
+ const SvxLanguageItem* pLangItem;
+ if(pArgs && (pLangItem = pArgs->GetItemIfSet(SID_ATTR_LANGUAGE, false)))
+ {
+ SvxLanguageItem aLang(pLangItem->GetLanguage(), RES_CHRATR_LANGUAGE);
+ m_pWrtShell->SetDefault( aLang );
+ lcl_SetAllTextToDefaultLanguage( *m_pWrtShell, RES_CHRATR_LANGUAGE );
+ }
+ }
+ break;
+ case SID_ATTR_CHAR_CTL_LANGUAGE:
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(RES_CHRATR_CTL_LANGUAGE, false, &pItem))
+ {
+ m_pWrtShell->SetDefault( *pItem );
+ lcl_SetAllTextToDefaultLanguage( *m_pWrtShell, RES_CHRATR_CTL_LANGUAGE );
+ }
+ break;
+ case SID_ATTR_CHAR_CJK_LANGUAGE:
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(RES_CHRATR_CJK_LANGUAGE, false, &pItem))
+ {
+ m_pWrtShell->SetDefault( *pItem );
+ lcl_SetAllTextToDefaultLanguage( *m_pWrtShell, RES_CHRATR_CJK_LANGUAGE );
+ }
+ break;
+ case FN_OUTLINE_LEVELS_SHOWN:
+ {
+ SwWrtShell& rSh = GetWrtShell();
+ int nOutlineLevel = -1;
+ auto nOutlinePos = rSh.GetOutlinePos();
+ if (nOutlinePos != SwOutlineNodes::npos)
+ nOutlineLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
+ SwNumberInputDlg aDlg(GetViewFrame().GetFrameWeld(),
+ SwResId(STR_OUTLINE_LEVELS_SHOWN_TITLE),
+ SwResId(STR_OUTLINE_LEVELS_SHOWN_SPIN_LABEL),
+ nOutlineLevel + 1, 1, 10,
+ SwResId(STR_OUTLINE_LEVELS_SHOWN_HELP_LABEL));
+ if (aDlg.run() == RET_OK)
+ rSh.MakeOutlineLevelsVisible(aDlg.GetNumber());
+ }
+ break;
+ case FN_TOGGLE_OUTLINE_CONTENT_VISIBILITY:
+ {
+ size_t nPos(m_pWrtShell->GetOutlinePos());
+ if (nPos != SwOutlineNodes::npos)
+ GetEditWin().ToggleOutlineContentVisibility(nPos, false);
+ }
+ break;
+ case FN_NAV_ELEMENT:
+ {
+ pArgs->GetItemState(GetPool().GetWhich(FN_NAV_ELEMENT), false, &pItem);
+ if(pItem)
+ {
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+ sal_uInt32 nMoveType(static_cast<const SfxUInt32Item*>(pItem)->GetValue());
+ SwView::SetMoveType(nMoveType);
+ }
+ }
+ break;
+ case FN_SCROLL_PREV:
+ case FN_SCROLL_NEXT:
+ {
+ bool *pbNext = new bool(true);
+ if (nSlot == FN_SCROLL_PREV)
+ *pbNext = false;
+ MoveNavigationHdl(pbNext);
+ }
+ break;
+ case SID_JUMPTOMARK:
+ if( pArgs && SfxItemState::SET == pArgs->GetItemState(SID_JUMPTOMARK, false, &pItem))
+ JumpToSwMark( static_cast<const SfxStringItem*>(pItem)->GetValue() );
+ break;
+ case SID_GALLERY :
+ // First make sure that the sidebar is visible
+ GetViewFrame().ShowChildWindow(SID_SIDEBAR);
+
+ ::sfx2::sidebar::Sidebar::ShowPanel(
+ u"GalleryPanel",
+ GetViewFrame().GetFrame().GetFrameInterface());
+ break;
+ case SID_AVMEDIA_PLAYER :
+ GetViewFrame().ChildWindowExecute(rReq);
+ break;
+ case SID_VIEW_DATA_SOURCE_BROWSER:
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ChildWindowExecute(rReq);
+ if(rVFrame.HasChildWindow(SID_BROWSER))
+ {
+ const SwDBData& rData = GetWrtShell().GetDBData();
+ SwModule::ShowDBObj(*this, rData);
+ }
+ }
+ break;
+ case FN_INSERT_FIELD_DATA_ONLY:
+ {
+ bool bShow = false;
+ if( pArgs &&
+ SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem ))
+ bShow = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ if((bShow && m_bInMailMerge) != GetViewFrame().HasChildWindow(nSlot))
+ GetViewFrame().ToggleChildWindow(nSlot);
+ //if fields have been successfully inserted call the "real"
+ //mail merge dialog
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SwWrtShell &rSh = GetWrtShell();
+ if(m_bInMailMerge && rSh.IsAnyDatabaseFieldInDoc())
+ {
+ SwDBManager* pDBManager = rSh.GetDBManager();
+ if (pDBManager)
+ {
+ SwDBData aData = rSh.GetDBData();
+ rSh.EnterStdMode(); // force change in text shell; necessary for mixing DB fields
+ AttrChangedNotify(nullptr);
+
+ Sequence<PropertyValue> aProperties
+ {
+ comphelper::makePropertyValue("DataSourceName", aData.sDataSource),
+ comphelper::makePropertyValue("Command", aData.sCommand),
+ comphelper::makePropertyValue("CommandType", aData.nCommandType)
+ };
+ pDBManager->ExecuteFormLetter(rSh, aProperties);
+ }
+ }
+#endif
+ m_bInMailMerge &= bShow;
+ GetViewFrame().GetBindings().Invalidate(FN_INSERT_FIELD);
+ }
+ break;
+ case FN_QRY_MERGE:
+ {
+ bool bUseCurrentDocument = true;
+ bool bQuery = !pArgs || SfxItemState::SET != pArgs->GetItemState(nSlot);
+ if(bQuery)
+ {
+ SfxViewFrame& rTmpFrame = GetViewFrame();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractMailMergeCreateFromDlg> pDlg(pFact->CreateMailMergeCreateFromDlg(rTmpFrame.GetFrameWeld()));
+ if (RET_OK == pDlg->Execute())
+ bUseCurrentDocument = pDlg->IsThisDocument();
+ else
+ break;
+ }
+ GenerateFormLetter(bUseCurrentDocument);
+ }
+ break;
+ case SID_RECHECK_DOCUMENT:
+ {
+ SwDocShell* pDocShell = GetDocShell();
+ SwDoc* pDoc = pDocShell->GetDoc();
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( pDoc->GetGCIterator() );
+ if( xGCIterator.is() )
+ {
+ xGCIterator->resetIgnoreRules();
+ }
+ // reset ignore lists
+ pDoc->SpellItAgainSam( true, false, false );
+ // clear ignore dictionary
+ uno::Reference< linguistic2::XDictionary > xDictionary = LinguMgr::GetIgnoreAllList();
+ if( xDictionary.is() )
+ xDictionary->clear();
+ // put cursor to the start of the document
+ m_pWrtShell->StartOfSection();
+ [[fallthrough]]; // call spell/grammar dialog
+ }
+ case FN_SPELL_GRAMMAR_DIALOG:
+ {
+ SfxViewFrame& rViewFrame = GetViewFrame();
+ if (rReq.GetArgs() != nullptr)
+ rViewFrame.SetChildWindow (FN_SPELL_GRAMMAR_DIALOG,
+ static_cast<const SfxBoolItem&>( (rReq.GetArgs()->
+ Get(FN_SPELL_GRAMMAR_DIALOG))).GetValue());
+ else
+ rViewFrame.ToggleChildWindow(FN_SPELL_GRAMMAR_DIALOG);
+
+ rViewFrame.GetBindings().Invalidate(FN_SPELL_GRAMMAR_DIALOG);
+ rReq.Ignore ();
+ }
+ break;
+ case SID_ALIGN_ANY_LEFT :
+ case SID_ALIGN_ANY_HCENTER :
+ case SID_ALIGN_ANY_RIGHT :
+ case SID_ALIGN_ANY_JUSTIFIED:
+ case SID_ALIGN_ANY_TOP :
+ case SID_ALIGN_ANY_VCENTER :
+ case SID_ALIGN_ANY_BOTTOM :
+ case SID_ALIGN_ANY_HDEFAULT :
+ case SID_ALIGN_ANY_VDEFAULT :
+ {
+ sal_uInt16 nAlias = 0;
+ if( m_nSelectionType & (SelectionType::DrawObjectEditMode|SelectionType::Text) )
+ {
+ switch( nSlot )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_ATTR_PARA_ADJUST_LEFT; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_ATTR_PARA_ADJUST_CENTER; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_ATTR_PARA_ADJUST_RIGHT; break;
+ case SID_ALIGN_ANY_JUSTIFIED: nAlias = SID_ATTR_PARA_ADJUST_BLOCK; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_TABLE_VERT_NONE; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_TABLE_VERT_CENTER; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_TABLE_VERT_BOTTOM; break;
+ }
+ }
+ else
+ {
+ switch( nSlot )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_OBJECT_ALIGN_LEFT ; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_OBJECT_ALIGN_CENTER ; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_OBJECT_ALIGN_RIGHT ; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_OBJECT_ALIGN_UP ; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_OBJECT_ALIGN_MIDDLE ; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_OBJECT_ALIGN_DOWN ; break;
+ }
+ }
+ //these slots are either re-mapped to text or object alignment
+ if (nAlias)
+ GetViewFrame().GetDispatcher()->Execute(
+ nAlias, SfxCallMode::ASYNCHRON);
+ }
+ break;
+ case SID_RESTORE_EDITING_VIEW:
+ {
+ //#i33307# restore editing position
+ Point aCursorPos;
+ bool bSelectObj;
+ if(m_pViewImpl->GetRestorePosition(aCursorPos, bSelectObj))
+ {
+ m_pWrtShell->SwCursorShell::SetCursor( aCursorPos, !bSelectObj );
+ if( bSelectObj )
+ {
+ m_pWrtShell->SelectObj( aCursorPos );
+ m_pWrtShell->EnterSelFrameMode( &aCursorPos );
+ }
+ }
+ }
+ break;
+ case SID_INSERT_GRAPHIC:
+ {
+ rReq.SetReturnValue(SfxBoolItem(nSlot, InsertGraphicDlg( rReq )));
+ }
+ break;
+ case SID_MOVE_SHAPE_HANDLE:
+ {
+ if (pArgs && pArgs->Count() >= 3)
+ {
+ SdrView *pSdrView = m_pWrtShell->HasDrawView() ? m_pWrtShell->GetDrawView() : nullptr;
+ if (pSdrView == nullptr)
+ break;
+ const SfxUInt32Item* handleNumItem = rReq.GetArg<SfxUInt32Item>(FN_PARAM_1);
+ const SfxUInt32Item* newPosXTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_2);
+ const SfxUInt32Item* newPosYTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_3);
+ const SfxInt32Item* OrdNum = rReq.GetArg<SfxInt32Item>(FN_PARAM_4);
+
+ const sal_uLong handleNum = handleNumItem->GetValue();
+ const sal_uLong newPosX = newPosXTwips->GetValue();
+ const sal_uLong newPosY = newPosYTwips->GetValue();
+ const Point mPoint(newPosX, newPosY);
+ const SdrHdl* handle = pSdrView->GetHdlList().GetHdl(handleNum);
+ if (!handle)
+ {
+ break;
+ }
+
+ if (handle->GetKind() == SdrHdlKind::Anchor || handle->GetKind() == SdrHdlKind::Anchor_TR)
+ m_pWrtShell->FindAnchorPos(mPoint, /*bMoveIt=*/true);
+ else
+ pSdrView->MoveShapeHandle(handleNum, mPoint, OrdNum ? OrdNum->GetValue() : -1);
+ }
+ break;
+ }
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+ if(!bIgnore)
+ rReq.Done();
+}
+
+bool SwView::IsConditionalFastCall( const SfxRequest &rReq )
+{
+ sal_uInt16 nId = rReq.GetSlot();
+ bool bRet = false;
+
+ if (nId == FN_REDLINE_ACCEPT_DIRECT || nId == FN_REDLINE_REJECT_DIRECT)
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ bRet = true;
+ }
+ return bRet || SfxShell::IsConditionalFastCall(rReq);
+
+}
+
+/// invalidate page numbering field
+void SwView::UpdatePageNums()
+{
+ SfxBindings &rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate(FN_STAT_PAGE);
+}
+
+void SwView::UpdateDocStats()
+{
+ SfxBindings &rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate( FN_STAT_WORDCOUNT );
+ rBnd.Update( FN_STAT_WORDCOUNT );
+}
+
+/// get status of the status line
+void SwView::StateStatusLine(SfxItemSet &rSet)
+{
+ SwWrtShell& rShell = GetWrtShell();
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ OSL_ENSURE( nWhich, "empty set");
+
+ //get section change event
+ const SwSection* CurrSect = rShell.GetCurrSection();
+ if( CurrSect )
+ {
+ const OUString& sCurrentSectionName = CurrSect->GetSectionName();
+ if(sCurrentSectionName != m_sOldSectionName)
+ {
+ SwCursorShell::FireSectionChangeEvent(2, 1);
+ }
+ m_sOldSectionName = sCurrentSectionName;
+ }
+ else if (!m_sOldSectionName.isEmpty())
+ {
+ SwCursorShell::FireSectionChangeEvent(2, 1);
+ m_sOldSectionName= OUString();
+ }
+ //get column change event
+ if(rShell.bColumnChange())
+ {
+ SwCursorShell::FireColumnChangeEvent(2, 1);
+ }
+
+ while( nWhich )
+ {
+ switch( nWhich )
+ {
+ case FN_STAT_PAGE:
+ {
+ OUString aTooltip;
+ OUString aPageStr;
+
+ SwVisiblePageNumbers aVisiblePageNumbers;
+ m_pWrtShell->GetFirstLastVisPageNumbers(aVisiblePageNumbers);
+
+ // convert to strings and define references
+ OUString sFirstPhy = OUString::number(aVisiblePageNumbers.nFirstPhy);
+ OUString sLastPhy = OUString::number(aVisiblePageNumbers.nLastPhy);
+ OUString sFirstVirt = OUString::number(aVisiblePageNumbers.nFirstVirt);
+ OUString sLastVirt = OUString::number(aVisiblePageNumbers.nLastVirt);
+ OUString& sFirstCustomPhy = aVisiblePageNumbers.sFirstCustomPhy;
+ OUString& sLastCustomPhy = aVisiblePageNumbers.sLastCustomPhy;
+ OUString& sFirstCustomVirt = aVisiblePageNumbers.sFirstCustomVirt;
+ OUString& sLastCustomVirt = aVisiblePageNumbers.sLastCustomVirt;
+ OUString sPageCount = OUString::number(m_pWrtShell->GetPageCount());
+
+ if (aVisiblePageNumbers.nFirstPhy == aVisiblePageNumbers.nFirstVirt)
+ {
+ aTooltip = SwResId(STR_BOOKCTRL_HINT);
+ if (aVisiblePageNumbers.nFirstPhy != aVisiblePageNumbers.nLastPhy)
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT_CUSTOM);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%4", sLastCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%5", sPageCount);
+ }
+ }
+ else
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sPageCount);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT_CUSTOM);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ }
+ }
+ }
+ else
+ {
+ aTooltip = SwResId(STR_BOOKCTRL_HINT_EXTENDED);
+ if (aVisiblePageNumbers.nFirstPhy != aVisiblePageNumbers.nLastPhy)
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%4", sFirstVirt);
+ aPageStr = aPageStr.replaceFirst("%5", sLastVirt);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGES_COUNT_CUSTOM_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sLastPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%4", sLastCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%5", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%6", sFirstVirt);
+ aPageStr = aPageStr.replaceFirst("%7", sLastVirt);
+ aPageStr = aPageStr.replaceFirst("%8", sFirstCustomVirt);
+ aPageStr = aPageStr.replaceFirst("%9", sLastCustomVirt);
+ }
+ }
+ else
+ {
+ if (sFirstPhy == sFirstCustomPhy && sLastPhy == sLastCustomPhy)
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%3", sFirstVirt);
+ }
+ else
+ {
+ aPageStr = SwResId(STR_PAGE_COUNT_CUSTOM_EXTENDED);
+ aPageStr = aPageStr.replaceFirst("%1", sFirstPhy);
+ aPageStr = aPageStr.replaceFirst("%2", sFirstCustomPhy);
+ aPageStr = aPageStr.replaceFirst("%3", sPageCount);
+ aPageStr = aPageStr.replaceFirst("%4", sFirstVirt);
+ aPageStr = aPageStr.replaceFirst("%5", sFirstCustomVirt);
+ }
+ }
+ }
+
+ // replace range indicator with two pages conjunction if applicable
+ if ((aVisiblePageNumbers.nLastPhy - aVisiblePageNumbers.nFirstPhy) == 1)
+ aPageStr = aPageStr.replaceAll("-", SwResId(STR_PAGES_TWO_CONJUNCTION));
+
+ // status bar bookmark control string and tooltip
+ std::vector<OUString> aStringList
+ {
+ aPageStr,
+ aTooltip
+ };
+ rSet.Put(SfxStringListItem(FN_STAT_PAGE, &aStringList));
+
+ //if existing page number is not equal to old page number, send out this event.
+ if (m_nOldPageNum != aVisiblePageNumbers.nFirstPhy)
+ {
+ if (m_nOldPageNum != 0)
+ SwCursorShell::FirePageChangeEvent(m_nOldPageNum, aVisiblePageNumbers.nFirstPhy);
+ m_nOldPageNum = aVisiblePageNumbers.nFirstPhy;
+ }
+ const sal_uInt16 nCnt = GetWrtShell().GetPageCnt();
+ if (m_nPageCnt != nCnt) // notify Basic
+ {
+ m_nPageCnt = nCnt;
+ SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwEventPageCount, SwDocShell::GetEventName(STR_SW_EVENT_PAGE_COUNT), GetViewFrame().GetObjectShell()), false);
+ }
+ }
+ break;
+
+ case FN_STAT_WORDCOUNT:
+ {
+ SwDocStat selectionStats;
+ SwDocStat documentStats;
+ rShell.CountWords(selectionStats);
+ documentStats = rShell.GetDoc()->getIDocumentStatistics().GetUpdatedDocStat( true /* complete-async */, false /* don't update fields */ );
+
+ sal_uLong nWord = selectionStats.nWord ? selectionStats.nWord : documentStats.nWord;
+ sal_uLong nChar = selectionStats.nChar ? selectionStats.nChar : documentStats.nChar;
+ TranslateId pResId = selectionStats.nWord ? STR_WORDCOUNT : STR_WORDCOUNT_NO_SELECTION;
+ TranslateNId pWordResId = selectionStats.nWord ? STR_WORDCOUNT_WORDARG : STR_WORDCOUNT_WORDARG_NO_SELECTION;
+ TranslateNId pCharResId = selectionStats.nWord ? STR_WORDCOUNT_CHARARG : STR_WORDCOUNT_CHARARG_NO_SELECTION;
+
+ const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetUILocaleDataWrapper();
+ OUString aWordArg = SwResId(pWordResId, nWord).replaceAll("$1", rLocaleData.getNum(nWord, 0));
+ OUString aCharArg = SwResId(pCharResId, nChar).replaceAll("$1", rLocaleData.getNum(nChar, 0));
+ OUString aWordCount(SwResId(pResId));
+ aWordCount = aWordCount.replaceAll("$1", aWordArg);
+ aWordCount = aWordCount.replaceAll("$2", aCharArg);
+ rSet.Put( SfxStringItem( FN_STAT_WORDCOUNT, aWordCount ) );
+
+ SwPostItMgr* pPostItMgr = rShell.GetPostItMgr();
+ if (pPostItMgr)
+ selectionStats.nComments = pPostItMgr->end() - pPostItMgr->begin();
+
+ SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
+ if (pWrdCnt)
+ pWrdCnt->SetCounts(selectionStats, documentStats);
+ }
+ break;
+ case FN_STAT_ACCESSIBILITY_CHECK:
+ {
+ std::unique_ptr<sw::OnlineAccessibilityCheck> const& rOnlineAccessibilityCheck = rShell.GetDoc()->getOnlineAccessibilityCheck();
+ if (rOnlineAccessibilityCheck)
+ {
+ sal_Int32 nIssues = rOnlineAccessibilityCheck->getNumberOfAccessibilityIssues()
+ + rOnlineAccessibilityCheck->getNumberOfDocumentLevelAccessibilityIssues();
+ rSet.Put(SfxInt32Item(FN_STAT_ACCESSIBILITY_CHECK, nIssues));
+ }
+ }
+ break;
+
+ case FN_STAT_TEMPLATE:
+ {
+ rSet.Put(SfxStringItem( FN_STAT_TEMPLATE,
+ rShell.GetCurPageStyle()));
+
+ }
+ break;
+ case SID_ATTR_ZOOM:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SwViewOption* pVOpt = rShell.GetViewOptions();
+ SvxZoomType eZoom = pVOpt->GetZoomType();
+ SvxZoomItem aZoom(eZoom,
+ pVOpt->GetZoom());
+ if( pVOpt->getBrowseMode() )
+ {
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200);
+ }
+ rSet.Put( aZoom );
+ }
+ else
+ rSet.DisableItem( SID_ATTR_ZOOM );
+ }
+ break;
+ case SID_ATTR_VIEWLAYOUT:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SwViewOption* pVOpt = rShell.GetViewOptions();
+ const sal_uInt16 nColumns = pVOpt->GetViewLayoutColumns();
+ const bool bBookMode = pVOpt->IsViewLayoutBookMode();
+ SvxViewLayoutItem aViewLayout(nColumns, bBookMode);
+ rSet.Put( aViewLayout );
+ }
+ else
+ rSet.DisableItem( SID_ATTR_VIEWLAYOUT );
+ }
+ break;
+ case SID_ATTR_ZOOMSLIDER:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SwViewOption* pVOpt = rShell.GetViewOptions();
+ const sal_uInt16 nCurrentZoom = pVOpt->GetZoom();
+ SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM );
+ aZoomSliderItem.AddSnappingPoint( 100 );
+
+ if ( !m_pWrtShell->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) )
+ {
+ const sal_uInt16 nColumns = pVOpt->GetViewLayoutColumns();
+ const bool bAutomaticViewLayout = 0 == nColumns;
+ const SwPostItMgr* pMgr = GetPostItMgr();
+
+ // snapping points:
+ // automatic mode: 1 Page, 2 Pages, 100%
+ // n Columns mode: n Pages, 100%
+ // n Columns book mode: nPages without gaps, 100%
+ const SwRect aPageRect( m_pWrtShell->GetAnyCurRect( CurRectType::PageCalc ) );
+ const SwRect aRootRect( m_pWrtShell->GetAnyCurRect( CurRectType::PagesArea ) ); // width of columns
+ Size aPageSize( aPageRect.SSize() );
+ aPageSize.AdjustWidth(pMgr->HasNotes() && pMgr->ShowNotes() ?
+ pMgr->GetSidebarWidth() + pMgr->GetSidebarBorderWidth() :
+ 0 );
+
+ Size aRootSize( aRootRect.SSize() );
+
+ const MapMode aTmpMap( MapUnit::MapTwip );
+ const Size& rEditSize = GetEditWin().GetOutputSizePixel();
+ const Size aWindowSize( GetEditWin().PixelToLogic( rEditSize, aTmpMap ) );
+
+ const tools::Long nOf = pVOpt->GetDocumentBorder() * 2;
+ tools::Long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width();
+ nTmpWidth += nOf;
+ aPageSize.AdjustHeight(nOf );
+ tools::Long nFac = aWindowSize.Width() * 100 / nTmpWidth;
+
+ tools::Long nVisPercent = aWindowSize.Height() * 100 / aPageSize.Height();
+ nFac = std::min( nFac, nVisPercent );
+
+ if (nFac >= MINZOOM)
+ {
+ aZoomSliderItem.AddSnappingPoint( nFac );
+ }
+
+ if ( bAutomaticViewLayout )
+ {
+ nTmpWidth += aPageSize.Width() + pVOpt->GetGapBetweenPages();
+ nFac = aWindowSize.Width() * 100 / nTmpWidth;
+ nFac = std::min( nFac, nVisPercent );
+ if (nFac >= MINZOOM)
+ {
+ aZoomSliderItem.AddSnappingPoint( nFac );
+ }
+ }
+ }
+
+ rSet.Put( aZoomSliderItem );
+ }
+ else
+ rSet.DisableItem( SID_ATTR_ZOOMSLIDER );
+ }
+ break;
+ case SID_ATTR_POSITION:
+ case SID_ATTR_SIZE:
+ {
+ if( !rShell.IsFrameSelected() && !rShell.IsObjSelected() )
+ SwBaseShell::SetFrameMode_( FLY_DRAG_END );
+ else
+ {
+ FlyMode eFrameMode = SwBaseShell::GetFrameMode();
+ if ( eFrameMode == FLY_DRAG_START || eFrameMode == FLY_DRAG )
+ {
+ if ( nWhich == SID_ATTR_POSITION )
+ rSet.Put( SfxPointItem( SID_ATTR_POSITION,
+ rShell.GetAnchorObjDiff()));
+ else
+ rSet.Put( SvxSizeItem( SID_ATTR_SIZE,
+ rShell.GetObjSize()));
+ }
+ }
+ }
+ break;
+ case SID_TABLE_CELL:
+
+ if( rShell.IsFrameSelected() || rShell.IsObjSelected() )
+ {
+ // #i39171# Don't put a SvxSizeItem into a slot which is defined as SfxStringItem.
+ // SvxPosSizeStatusBarControl no longer resets to empty display if only one slot
+ // has no item, so SID_TABLE_CELL can remain empty (the SvxSizeItem is supplied
+ // in SID_ATTR_SIZE).
+ }
+ else
+ {
+ StatusCategory eCategory(StatusCategory::NONE);
+ OUString sStr;
+ if( rShell.IsCursorInTable() )
+ {
+ // table name + cell coordinate
+ sStr = rShell.GetTableFormat()->GetName() + ":" + rShell.GetBoxNms();
+ eCategory = StatusCategory::TableCell;
+ }
+ else
+ {
+ const SwSection* pCurrSect = rShell.GetCurrSection();
+ if( pCurrSect )
+ {
+ switch( pCurrSect->GetType() )
+ {
+ case SectionType::ToxHeader:
+ case SectionType::ToxContent:
+ {
+ const SwTOXBase* pTOX = m_pWrtShell->GetCurTOX();
+ if( pTOX )
+ {
+ sStr = pTOX->GetTOXName();
+ eCategory = StatusCategory::TableOfContents;
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "Unknown kind of section" );
+ sStr = pCurrSect->GetSectionName();
+ eCategory = StatusCategory::Section;
+ }
+ }
+ break;
+ default:
+ sStr = pCurrSect->GetSectionName();
+ eCategory = StatusCategory::Section;
+ break;
+ }
+ }
+ }
+
+ const SwNumRule* pNumRule = rShell.GetNumRuleAtCurrCursorPos();
+ const bool bOutlineNum = pNumRule && pNumRule->IsOutlineRule();
+
+ if (pNumRule && !bOutlineNum ) // cursor in numbering
+ {
+ sal_uInt8 nNumLevel = rShell.GetNumLevel();
+ if ( nNumLevel < MAXLEVEL )
+ {
+ if(!pNumRule->IsAutoRule())
+ {
+ SfxItemSetFixed<RES_PARATR_NUMRULE, RES_PARATR_NUMRULE> aSet(GetPool());
+ rShell.GetCurAttr(aSet);
+ if(SfxItemState::DEFAULT <=
+ aSet.GetItemState(RES_PARATR_NUMRULE))
+ {
+ const OUString& rNumStyle =
+ aSet.Get(RES_PARATR_NUMRULE).GetValue();
+ if(!rNumStyle.isEmpty())
+ {
+ if(!sStr.isEmpty())
+ sStr += sStatusDelim;
+ if (eCategory == StatusCategory::NONE)
+ eCategory = StatusCategory::ListStyle;
+ sStr += rNumStyle;
+ }
+ }
+ }
+ if (!sStr.isEmpty())
+ sStr += sStatusDelim;
+ sStr += SwResId(STR_NUM_LEVEL) + OUString::number( nNumLevel + 1 );
+ if (eCategory == StatusCategory::NONE)
+ eCategory = StatusCategory::Numbering;
+ }
+ }
+ const int nOutlineLevel = rShell.GetCurrentParaOutlineLevel();
+ if( nOutlineLevel != 0 )
+ {
+ if (!sStr.isEmpty())
+ sStr += " , ";
+ if( bOutlineNum )
+ {
+ sStr += SwResId(STR_OUTLINE_NUMBERING) +
+ sStatusDelim + SwResId(STR_NUM_LEVEL);
+ }
+ else
+ sStr += SwResId(STR_NUM_OUTLINE);
+ sStr += OUString::number( nOutlineLevel);
+ if (eCategory == StatusCategory::NONE)
+ eCategory = StatusCategory::Numbering;
+ }
+
+ if( rShell.HasReadonlySel() )
+ {
+ if (!sStr.isEmpty())
+ sStr = sStatusDelim + sStr;
+ sStr = SwResId(SW_STR_READONLY) + sStr;
+ }
+ if (!sStr.isEmpty())
+ rSet.Put( SvxStatusItem( SID_TABLE_CELL, sStr, eCategory ));
+ }
+ break;
+ case FN_STAT_SELMODE:
+ {
+ if(rShell.IsStdMode())
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 0));
+ else if(rShell.IsAddMode())
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 2));
+ else if(rShell.IsBlockMode())
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 3));
+ else
+ rSet.Put(SfxUInt16Item(FN_STAT_SELMODE, 1));
+ break;
+ }
+ case SID_ATTR_INSERT:
+ if( rShell.IsRedlineOn() )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ rSet.Put(SfxBoolItem(SID_ATTR_INSERT,rShell.IsInsMode()));
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/** execute method for the status line
+ *
+ * @param rReq ???
+ */
+void SwView::ExecuteStatusLine(SfxRequest &rReq)
+{
+ SwWrtShell &rSh = GetWrtShell();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem=nullptr;
+ bool bUp = false;
+ sal_uInt16 nWhich = rReq.GetSlot();
+ switch( nWhich )
+ {
+ case FN_STAT_PAGE:
+ {
+ GetViewFrame().GetDispatcher()->Execute( FN_GOTO_PAGE,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
+ }
+ break;
+
+ case FN_STAT_WORDCOUNT:
+ {
+ GetViewFrame().GetDispatcher()->Execute(FN_WORDCOUNT_DIALOG,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
+ }
+ break;
+
+ case FN_STAT_ACCESSIBILITY_CHECK:
+ {
+ const SfxStringItem sDeckName(SID_SIDEBAR_DECK, "A11yCheckDeck");
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_SIDEBAR_DECK, SfxCallMode::RECORD,
+ { &sDeckName });
+ }
+ break;
+
+ case FN_STAT_BOOKMARK:
+ if ( pArgs )
+ {
+ if (SfxItemState::SET == pArgs->GetItemState( nWhich, true, &pItem))
+ {
+ const IDocumentMarkAccess* pMarkAccess = rSh.getIDocumentMarkAccess();
+ const sal_Int32 nIdx = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
+ if(nIdx < pMarkAccess->getBookmarksCount())
+ {
+ const IDocumentMarkAccess::const_iterator_t ppBookmark = rSh.getIDocumentMarkAccess()->getBookmarksBegin() + nIdx;
+ rSh.EnterStdMode();
+ rSh.GotoMark( *ppBookmark );
+ }
+ else
+ OSL_FAIL("SwView::ExecuteStatusLine(..)"
+ " - Ignoring out of range bookmark index");
+ }
+ }
+ break;
+
+ case FN_STAT_TEMPLATE:
+ {
+ weld::Window* pDialogParent = GetViewFrame().GetFrameWeld();
+ css::uno::Any aAny(pDialogParent->GetXWindow());
+ SfxUnoAnyItem aDialogParent(SID_DIALOG_PARENT, aAny);
+ const SfxPoolItem* pInternalItems[ 2 ];
+ pInternalItems[ 0 ] = &aDialogParent;
+ pInternalItems[ 1 ] = nullptr;
+ GetViewFrame().GetDispatcher()->Execute(FN_FORMAT_PAGE_DLG,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ nullptr, 0, pInternalItems);
+ }
+ break;
+ case SID_ATTR_ZOOM:
+ {
+ if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() )
+ {
+ const SfxItemSet *pSet = nullptr;
+ ScopedVclPtr<AbstractSvxZoomDialog> pDlg;
+ if ( pArgs )
+ pSet = pArgs;
+ else
+ {
+ const SwViewOption& rViewOptions = *rSh.GetViewOptions();
+ SfxItemSetFixed<SID_ATTR_ZOOM, SID_ATTR_ZOOM, SID_ATTR_VIEWLAYOUT, SID_ATTR_VIEWLAYOUT> aCoreSet(m_pShell->GetPool());
+ SvxZoomItem aZoom( rViewOptions.GetZoomType(), rViewOptions.GetZoom() );
+
+ const bool bBrowseMode = rSh.GetViewOptions()->getBrowseMode();
+ if( bBrowseMode )
+ {
+ aZoom.SetValueSet(
+ SvxZoomEnableFlags::N50|
+ SvxZoomEnableFlags::N75|
+ SvxZoomEnableFlags::N100|
+ SvxZoomEnableFlags::N150|
+ SvxZoomEnableFlags::N200);
+ }
+ aCoreSet.Put( aZoom );
+
+ if ( !bBrowseMode )
+ {
+ const SvxViewLayoutItem aViewLayout( rViewOptions.GetViewLayoutColumns(), rViewOptions.IsViewLayoutBookMode() );
+ aCoreSet.Put( aViewLayout );
+ }
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg.disposeAndReset(pFact->CreateSvxZoomDialog(GetViewFrame().GetFrameWeld(), aCoreSet));
+ pDlg->SetLimits( MINZOOM, MAXZOOM );
+ if( pDlg->Execute() != RET_CANCEL )
+ pSet = pDlg->GetOutputItemSet();
+ }
+
+ const SvxViewLayoutItem* pViewLayoutItem = nullptr;
+ if ( pSet && (pViewLayoutItem = pSet->GetItemIfSet(SID_ATTR_VIEWLAYOUT)))
+ {
+ const sal_uInt16 nColumns = pViewLayoutItem->GetValue();
+ const bool bBookMode = pViewLayoutItem->IsBookMode();
+ SetViewLayout( nColumns, bBookMode );
+ }
+
+ const SvxZoomItem* pZoomItem = nullptr;
+ if ( pSet && (pZoomItem = pSet->GetItemIfSet(SID_ATTR_ZOOM)))
+ {
+ SvxZoomType eType = pZoomItem->GetType();
+ SetZoom( eType, pZoomItem->GetValue() );
+ }
+ bUp = true;
+ if ( pZoomItem )
+ rReq.AppendItem( *pZoomItem );
+ rReq.Done();
+ }
+ }
+ break;
+
+ case SID_ATTR_VIEWLAYOUT:
+ {
+ if ( pArgs && !rSh.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) &&
+ ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) )
+ {
+ if ( const SvxViewLayoutItem* pLayoutItem = pArgs->GetItemIfSet(SID_ATTR_VIEWLAYOUT ))
+ {
+ const sal_uInt16 nColumns = pLayoutItem->GetValue();
+ const bool bBookMode = (0 != nColumns && 0 == (nColumns % 2)) && pLayoutItem->IsBookMode();
+
+ SetViewLayout( nColumns, bBookMode );
+ }
+
+ bUp = true;
+ rReq.Done();
+
+ InvalidateRulerPos();
+ }
+ }
+ break;
+
+ case SID_ATTR_ZOOMSLIDER:
+ {
+ if ( pArgs && ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) )
+ {
+ if ( const SvxZoomSliderItem* pZoomItem = pArgs->GetItemIfSet(SID_ATTR_ZOOMSLIDER) )
+ {
+ const sal_uInt16 nCurrentZoom = pZoomItem->GetValue();
+ SetZoom( SvxZoomType::PERCENT, nCurrentZoom );
+ }
+
+ bUp = true;
+ rReq.Done();
+ }
+ }
+ break;
+
+ case SID_ATTR_SIZE:
+ {
+ sal_uInt16 nId = 0;
+ if( rSh.IsCursorInTable() )
+ nId = FN_FORMAT_TABLE_DLG;
+ else if( rSh.GetCurTOX() )
+ nId = FN_INSERT_MULTI_TOX;
+ else if( rSh.GetCurrSection() )
+ nId = FN_EDIT_REGION;
+ else
+ {
+ const SwNumRule* pNumRule = rSh.GetNumRuleAtCurrCursorPos();
+ if( pNumRule ) // cursor in numbering
+ {
+ if( pNumRule->IsAutoRule() )
+ nId = FN_NUMBER_BULLETS;
+ else
+ {
+ // start dialog of the painter
+ nId = 0;
+ }
+ }
+ else if( rSh.IsFrameSelected() )
+ nId = FN_FORMAT_FRAME_DLG;
+ else if( rSh.IsObjSelected() )
+ nId = SID_ATTR_TRANSFORM;
+ }
+ if( nId )
+ GetViewFrame().GetDispatcher()->Execute(nId,
+ SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
+ }
+ break;
+
+ case FN_STAT_SELMODE:
+ {
+ if ( pArgs )
+ {
+ if (SfxItemState::SET == pArgs->GetItemState( nWhich, true, &pItem))
+ {
+ switch ( static_cast<const SfxUInt16Item *>(pItem)->GetValue() )
+ {
+ case 0: rSh.EnterStdMode(); break;
+ case 1: rSh.EnterExtMode(); break;
+ case 2: rSh.EnterAddMode(); break;
+ case 3: rSh.EnterBlockMode(); break;
+ }
+ }
+ }
+ bUp = true;
+ break;
+ }
+ case FN_SET_ADD_MODE:
+ rSh.ToggleAddMode();
+ nWhich = FN_STAT_SELMODE;
+ bUp = true;
+ break;
+ case FN_SET_BLOCK_MODE:
+ rSh.ToggleBlockMode();
+ nWhich = FN_STAT_SELMODE;
+ bUp = true;
+ break;
+ case FN_SET_EXT_MODE:
+ rSh.ToggleExtMode();
+ nWhich = FN_STAT_SELMODE;
+ bUp = true;
+ break;
+ case SID_ATTR_INSERT:
+ SwPostItMgr* pMgr = GetPostItMgr();
+ if ( pMgr && pMgr->HasActiveSidebarWin() )
+ {
+ pMgr->ToggleInsModeOnActiveSidebarWin();
+ }
+ else
+ rSh.ToggleInsMode();
+ bUp = true;
+ break;
+
+ }
+ if ( bUp )
+ {
+ SfxBindings &rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate(nWhich);
+ rBnd.Update(nWhich);
+ }
+}
+
+void SwView::InsFrameMode(sal_uInt16 nCols)
+{
+ if ( m_pWrtShell->HasWholeTabSelection() )
+ {
+ SwFlyFrameAttrMgr aMgr( true, m_pWrtShell.get(), Frmmgr_Type::TEXT, nullptr );
+
+ const SwFrameFormat &rPageFormat =
+ m_pWrtShell->GetPageDesc(m_pWrtShell->GetCurPageDesc()).GetMaster();
+ SwTwips lWidth = rPageFormat.GetFrameSize().GetWidth();
+ const SvxLRSpaceItem &rLR = rPageFormat.GetLRSpace();
+ lWidth -= rLR.GetLeft() + rLR.GetRight();
+ aMgr.SetSize(Size(lWidth, aMgr.GetSize().Height()));
+ if(nCols > 1)
+ {
+ SwFormatCol aCol;
+ aCol.Init( nCols, aCol.GetGutterWidth(), aCol.GetWishWidth() );
+ aMgr.SetCol( aCol );
+ }
+ aMgr.InsertFlyFrame();
+ }
+ else
+ GetEditWin().InsFrame(nCols);
+}
+
+/// show "edit link" dialog
+void SwView::EditLinkDlg()
+{
+ if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
+ {
+ std::unique_ptr<weld::MessageDialog> xError(
+ Application::CreateMessageDialog(nullptr, VclMessageType::Warning, VclButtonsType::Ok,
+ SvtResId(STR_WARNING_EXTERNAL_LINK_EDIT_DISABLED)));
+ xError->run();
+ return;
+ }
+
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractLinksDialog> pDlg(pFact->CreateLinksDialog(GetViewFrame().GetFrameWeld(), &GetWrtShell().GetLinkManager(), bWeb));
+ pDlg->Execute();
+}
+
+namespace sw {
+
+auto PrepareJumpToTOXMark(SwDoc const& rDoc, std::u16string_view aName)
+ -> std::optional<std::pair<SwTOXMark, sal_Int32>>
+{
+ size_t const first(aName.find(toxMarkSeparator));
+ if (first == std::u16string_view::npos)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: missing separator");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ sal_Int32 const counter(o3tl::toInt32(aName.substr(0, first)));
+ if (counter <= 0)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: invalid counter");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ size_t const second(aName.find(toxMarkSeparator, first + 1));
+ if (second == std::u16string_view::npos)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: missing separator");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ std::u16string_view const entry(aName.substr(first + 1, second - (first + 1)));
+ if (aName.size() < second + 2)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: invalid tox");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ sal_uInt16 const indexType(aName[second + 1]);
+ std::u16string_view const indexName(aName.substr(second + 2));
+ SwTOXType const* pType(nullptr);
+ switch (indexType)
+ {
+ case 'A':
+ pType = rDoc.GetTOXType(TOX_INDEX, 0);
+ assert(pType);
+ break;
+ case 'C':
+ pType = rDoc.GetTOXType(TOX_CONTENT, 0);
+ assert(pType);
+ break;
+ case 'U':
+ for (auto i = rDoc.GetTOXTypeCount(TOX_USER); 0 < i; )
+ {
+ --i;
+ auto const pTmp(rDoc.GetTOXType(TOX_USER, i));
+ if (pTmp->GetTypeName() == indexName)
+ {
+ pType = pTmp;
+ break;
+ }
+ }
+ break;
+ }
+ if (!pType)
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: tox doesn't exist");
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>();
+ }
+ // type and alt text are the search keys
+ SwTOXMark tmp(pType);
+ tmp.SetAlternativeText(OUString(entry));
+ return std::optional<std::pair<SwTOXMark, sal_Int32>>(std::pair<SwTOXMark, sal_Int32>(tmp, counter));
+}
+
+} // namespace sw
+
+static auto JumpToTOXMark(SwWrtShell & rSh, std::u16string_view aName) -> bool
+{
+ std::optional<std::pair<SwTOXMark, sal_Int32>> const tmp(
+ sw::PrepareJumpToTOXMark(*rSh.GetDoc(), aName));
+ if (!tmp)
+ {
+ return false;
+ }
+ SwTOXMark const* pMark(&tmp->first);
+ // hack: check first if one exists
+ // need simple ptr control, else UnitTest CppunitTest_sw_uiwriter3 fails
+ if (!areSfxPoolItemPtrsEqual(&tmp->first, &rSh.GetDoc()->GotoTOXMark(tmp->first, TOX_SAME_NXT, rSh.IsReadOnlyAvailable())))
+ {
+ for (sal_Int32 i = 0; i < tmp->second; ++i)
+ {
+ pMark = &rSh.GotoTOXMark(*pMark, TOX_SAME_NXT);
+ }
+ return true;
+ }
+ else
+ {
+ SAL_WARN("sw.ui", "JumpToTOXMark: tox mark doesn't exist");
+ return false;
+ }
+}
+
+bool SwView::JumpToSwMark( std::u16string_view rMark )
+{
+ bool bRet = false;
+ if( !rMark.empty() )
+ {
+ // place bookmark at top-center
+ bool bSaveCC = m_bCenterCursor;
+ bool bSaveCT = m_bTopCursor;
+ SetCursorAtTop( true );
+
+ // For scrolling the FrameSet, the corresponding shell needs to have the focus.
+ bool bHasShFocus = m_pWrtShell->HasShellFocus();
+ if( !bHasShFocus )
+ m_pWrtShell->ShellGetFocus();
+
+ const SwFormatINetFormat* pINet;
+ OUString sCmp;
+ OUString sMark( INetURLObject::decode( rMark,
+ INetURLObject::DecodeMechanism::WithCharset ));
+
+ sal_Int32 nLastPos, nPos = sMark.indexOf( cMarkSeparator );
+ if( -1 != nPos )
+ while( -1 != ( nLastPos = sMark.indexOf( cMarkSeparator, nPos + 1 )) )
+ nPos = nLastPos;
+
+ IDocumentMarkAccess::const_iterator_t ppMark;
+ IDocumentMarkAccess* const pMarkAccess = m_pWrtShell->getIDocumentMarkAccess();
+ if( -1 != nPos )
+ sCmp = sMark.copy(nPos + 1).replaceAll(" ", "");
+
+ if( !sCmp.isEmpty() )
+ {
+ OUString sName( sMark.copy( 0, nPos ) );
+ sCmp = sCmp.toAsciiLowerCase();
+ FlyCntType eFlyType = FLYCNTTYPE_ALL;
+
+ if (sCmp == "drawingobject")
+ bRet = m_pWrtShell->GotoDrawingObject(sName);
+ else if( sCmp == "region" )
+ {
+ m_pWrtShell->EnterStdMode();
+ bRet = m_pWrtShell->GotoRegion( sName );
+ }
+ else if( sCmp == "outline" )
+ {
+ m_pWrtShell->EnterStdMode();
+ bRet = m_pWrtShell->GotoOutline( sName );
+ }
+ else if( sCmp == "frame" )
+ eFlyType = FLYCNTTYPE_FRM;
+ else if( sCmp == "graphic" )
+ eFlyType = FLYCNTTYPE_GRF;
+ else if( sCmp == "ole" )
+ eFlyType = FLYCNTTYPE_OLE;
+ else if( sCmp == "table" )
+ {
+ m_pWrtShell->EnterStdMode();
+ bRet = m_pWrtShell->GotoTable( sName );
+ }
+ else if( sCmp == "sequence" )
+ {
+ m_pWrtShell->EnterStdMode();
+ sal_Int32 nNoPos = sName.indexOf( cSequenceMarkSeparator );
+ if ( nNoPos != -1 )
+ {
+ sal_uInt16 nSeqNo = o3tl::toInt32(sName.subView( nNoPos + 1 ));
+ sName = sName.copy( 0, nNoPos );
+ bRet = m_pWrtShell->GotoRefMark(sName, REF_SEQUENCEFLD, nSeqNo);
+ }
+ }
+ else if (sCmp == "toxmark")
+ {
+ bRet = JumpToTOXMark(*m_pWrtShell, sName);
+ }
+ else if( sCmp == "text" )
+ {
+ // normal text search
+ m_pWrtShell->EnterStdMode();
+
+ i18nutil::SearchOptions2 aSearchOpt(
+ 0,
+ sName, OUString(),
+ SvtSysLocale().GetLanguageTag().getLocale(),
+ 0,0,0,
+ TransliterationFlags::IGNORE_CASE,
+ SearchAlgorithms2::ABSOLUTE,
+ '\\' );
+
+ //todo/mba: assuming that notes shouldn't be searched
+ if( m_pWrtShell->SearchPattern( aSearchOpt, false/*bSearchInNotes*/, SwDocPositions::Start, SwDocPositions::End ))
+ {
+ m_pWrtShell->EnterStdMode(); // remove the selection
+ bRet = true;
+ }
+ }
+ else if( pMarkAccess->getAllMarksEnd() != (ppMark = pMarkAccess->findMark(sMark)) )
+ {
+ bRet = m_pWrtShell->GotoMark( *ppMark, false );
+ }
+ else if( nullptr != ( pINet = m_pWrtShell->FindINetAttr( sMark ) )) {
+ m_pWrtShell->addCurrentPosition();
+ bRet = m_pWrtShell->GotoINetAttr( *pINet->GetTextINetFormat() );
+ }
+
+ // for all types of Flys
+ if( FLYCNTTYPE_ALL != eFlyType && m_pWrtShell->GotoFly( sName, eFlyType ))
+ {
+ bRet = true;
+ if( FLYCNTTYPE_FRM == eFlyType )
+ {
+ // TextFrames: set Cursor in the frame
+ m_pWrtShell->UnSelectFrame();
+ m_pWrtShell->LeaveSelFrameMode();
+ }
+ else
+ {
+ m_pWrtShell->HideCursor();
+ m_pWrtShell->EnterSelFrameMode();
+ }
+ }
+ }
+ else if( pMarkAccess->getAllMarksEnd() != (ppMark = pMarkAccess->findMark(sMark)))
+ {
+ bRet = m_pWrtShell->GotoMark( *ppMark, false );
+ }
+ else if( nullptr != ( pINet = m_pWrtShell->FindINetAttr( sMark ) ))
+ bRet = m_pWrtShell->GotoINetAttr( *pINet->GetTextINetFormat() );
+
+ // make selection visible later
+ if ( m_aVisArea.IsEmpty() )
+ m_bMakeSelectionVisible = true;
+
+ // reset ViewStatus
+ SetCursorAtTop( bSaveCT, bSaveCC );
+
+ if(!m_pWrtShell->IsFrameSelected() && !m_pWrtShell->IsObjSelected())
+ m_pWrtShell->ShowCursor();
+
+ if( !bHasShFocus )
+ m_pWrtShell->ShellLoseFocus();
+ }
+ return bRet;
+}
+
+// #i67305# Undo after insert from file:
+// Undo "Insert form file" crashes with documents imported from binary filter (.sdw) => disabled
+// Undo "Insert form file" crashes with (.odt) documents crashes if these documents contains
+// page styles with active header/footer => disabled for those documents
+static size_t lcl_PageDescWithHeader( const SwDoc& rDoc )
+{
+ size_t nRet = 0;
+ size_t nCnt = rDoc.GetPageDescCnt();
+ for( size_t i = 0; i < nCnt; ++i )
+ {
+ const SwPageDesc& rPageDesc = rDoc.GetPageDesc( i );
+ const SwFrameFormat& rMaster = rPageDesc.GetMaster();
+ const SwFormatHeader* pHeaderItem = rMaster.GetAttrSet().GetItemIfSet( RES_HEADER, false );
+ const SwFormatFooter* pFooterItem = rMaster.GetAttrSet().GetItemIfSet( RES_FOOTER, false );
+ if( (pHeaderItem && pHeaderItem->IsActive()) ||
+ (pFooterItem && pFooterItem->IsActive()) )
+ ++nRet;
+ }
+ return nRet; // number of page styles with active header/footer
+}
+
+void SwView::ExecuteInsertDoc( SfxRequest& rRequest, const SfxPoolItem* pItem )
+{
+ m_pViewImpl->InitRequest( rRequest );
+ m_pViewImpl->SetParam( pItem ? 1 : 0 );
+ const sal_uInt16 nSlot = rRequest.GetSlot();
+
+ if ( !pItem )
+ {
+ InsertDoc( nSlot, "", "" );
+ }
+ else
+ {
+ OUString sFile, sFilter;
+ sFile = static_cast<const SfxStringItem *>( pItem )->GetValue();
+ if ( SfxItemState::SET == rRequest.GetArgs()->GetItemState( FN_PARAM_1, true, &pItem ) )
+ sFilter = static_cast<const SfxStringItem *>(pItem )->GetValue();
+
+ bool bHasFileName = !sFile.isEmpty();
+ tools::Long nFound = InsertDoc( nSlot, sFile, sFilter );
+
+ if ( bHasFileName )
+ {
+ rRequest.SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) );
+ rRequest.Done();
+ }
+ }
+}
+
+tools::Long SwView::InsertDoc( sal_uInt16 nSlotId, const OUString& rFileName, const OUString& rFilterName, sal_Int16 nVersion )
+{
+ std::unique_ptr<SfxMedium> pMed;
+ SwDocShell* pDocSh = GetDocShell();
+
+ if( !rFileName.isEmpty() )
+ {
+ SfxObjectFactory& rFact = pDocSh->GetFactory();
+ std::shared_ptr<const SfxFilter> pFilter = rFact.GetFilterContainer()->GetFilter4FilterName( rFilterName );
+ if ( !pFilter )
+ {
+ pMed.reset(new SfxMedium(rFileName, StreamMode::READ, nullptr, nullptr ));
+ SfxFilterMatcher aMatcher( rFact.GetFilterContainer()->GetName() );
+ pMed->UseInteractionHandler( true );
+ ErrCode nErr = aMatcher.GuessFilter(*pMed, pFilter, SfxFilterFlags::NONE);
+ if ( nErr )
+ pMed.reset();
+ else
+ pMed->SetFilter( pFilter );
+ }
+ else
+ pMed.reset(new SfxMedium(rFileName, StreamMode::READ, pFilter, nullptr));
+ }
+ else
+ {
+ m_pViewImpl->StartDocumentInserter(
+ // tdf#118578 allow inserting any Writer document except GlobalDoc
+ SwDocShell::Factory().GetFactoryName(),
+ LINK( this, SwView, DialogClosedHdl ),
+ nSlotId
+ );
+ return -1;
+ }
+
+ if( !pMed )
+ return -1;
+
+ return InsertMedium( nSlotId, std::move(pMed), nVersion );
+}
+
+tools::Long SwView::InsertMedium( sal_uInt16 nSlotId, std::unique_ptr<SfxMedium> pMedium, sal_Int16 nVersion )
+{
+ bool bInsert = false, bCompare = false;
+ tools::Long nFound = 0;
+ SwDocShell* pDocSh = GetDocShell();
+
+ switch( nSlotId )
+ {
+ case SID_DOCUMENT_MERGE: break;
+ case SID_DOCUMENT_COMPARE: bCompare = true; break;
+ case SID_INSERTDOC: bInsert = true; break;
+
+ default:
+ OSL_ENSURE( false, "unknown SlotId!" );
+ bInsert = true;
+ break;
+ }
+
+ if( bInsert )
+ {
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ GetViewFrame().GetBindings().GetRecorder();
+ if ( xRecorder.is() )
+ {
+ SfxRequest aRequest(GetViewFrame(), SID_INSERTDOC);
+ aRequest.AppendItem(SfxStringItem(SID_INSERTDOC, pMedium->GetOrigURL()));
+ if(pMedium->GetFilter())
+ aRequest.AppendItem(SfxStringItem(FN_PARAM_1, pMedium->GetFilter()->GetName()));
+ aRequest.Done();
+ }
+
+ SfxObjectShellRef aRef( pDocSh );
+
+ ErrCode nError = SfxObjectShell::HandleFilter( pMedium.get(), pDocSh );
+ // #i16722# aborted?
+ if(nError != ERRCODE_NONE)
+ {
+ return -1;
+ }
+
+ pMedium->Download(); // start download if needed
+ if( aRef.is() && 1 < aRef->GetRefCount() ) // still a valid ref?
+ {
+ SwReaderPtr pRdr;
+ Reader *pRead = pDocSh->StartConvertFrom(*pMedium, pRdr, m_pWrtShell.get());
+ if( pRead ||
+ (pMedium->GetFilter()->GetFilterFlags() & SfxFilterFlags::STARONEFILTER) )
+ {
+ size_t nUndoCheck = 0;
+ SwDoc *pDoc = pDocSh->GetDoc();
+ if( pRead && pDocSh->GetDoc() )
+ nUndoCheck = lcl_PageDescWithHeader( *pDoc );
+ ErrCodeMsg nErrno;
+ { //Scope for SwWait-Object, to be able to execute slots
+ //outside this scope.
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+ if ( m_pWrtShell->HasSelection() )
+ m_pWrtShell->DelRight(); // delete selections
+ if( pRead )
+ {
+ nErrno = pRdr->Read( *pRead ); // and insert document
+ pRdr.reset();
+ }
+ else
+ {
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ rtl::Reference<SwXTextRange> const xInsertPosition(
+ SwXTextRange::CreateXTextRange(*pDoc,
+ *m_pWrtShell->GetCursor()->GetPoint(), nullptr));
+ nErrno = pDocSh->ImportFrom(*pMedium, xInsertPosition)
+ ? ERRCODE_NONE : ERR_SWG_READ_ERROR;
+ }
+
+ }
+
+ // update all "table of ..." sections if needed
+ if( m_pWrtShell->IsUpdateTOX() )
+ {
+ SfxRequest aReq( FN_UPDATE_TOX, SfxCallMode::SLOT, GetPool() );
+ Execute( aReq );
+ m_pWrtShell->SetUpdateTOX( false ); // reset
+ }
+
+ if( pDoc )
+ { // Disable Undo for .sdw or
+ // if the number of page styles with header/footer has changed
+ if( !pRead || nUndoCheck != lcl_PageDescWithHeader( *pDoc ) )
+ {
+ pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+ }
+
+ m_pWrtShell->EndAllAction();
+ if( nErrno )
+ {
+ ErrorHandler::HandleError( nErrno );
+ nFound = nErrno.IsError() ? -1 : 0;
+ }
+ else
+ nFound = 0;
+ }
+ }
+ }
+ else
+ {
+ SfxObjectShellRef xDocSh;
+ SfxObjectShellLock xLockRef;
+
+ const int nRet = SwFindDocShell( xDocSh, xLockRef, pMedium->GetName(), OUString(),
+ OUString(), nVersion, pDocSh );
+ if( nRet )
+ {
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+
+ m_pWrtShell->EnterStdMode(); // delete selections
+
+ if( bCompare )
+ nFound = m_pWrtShell->CompareDoc( *static_cast<SwDocShell*>( xDocSh.get() )->GetDoc() );
+ else
+ nFound = m_pWrtShell->MergeDoc( *static_cast<SwDocShell*>( xDocSh.get() )->GetDoc() );
+
+ m_pWrtShell->EndAllAction();
+
+ if (!bCompare && !nFound)
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_NO_MERGE_ENTRY)));
+ xInfoBox->run();
+ }
+ if( nRet==2 && xDocSh.is() )
+ xDocSh->DoClose();
+ }
+ }
+
+ return nFound;
+}
+
+void SwView::EnableMailMerge()
+{
+ m_bInMailMerge = true;
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate(FN_INSERT_FIELD_DATA_ONLY);
+ rBind.Update(FN_INSERT_FIELD_DATA_ONLY);
+}
+
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+
+namespace
+{
+ bool lcl_NeedAdditionalDataSource( const uno::Reference< XDatabaseContext >& _rDatasourceContext )
+ {
+ Sequence < OUString > aNames = _rDatasourceContext->getElementNames();
+
+ return ( !aNames.hasElements()
+ || ( ( 1 == aNames.getLength() )
+ && aNames.getConstArray()[0] == SW_MOD()->GetDBConfig()->GetBibliographySource().sDataSource
+ )
+ );
+ }
+}
+
+#endif
+
+void SwView::GenerateFormLetter(bool bUseCurrentDocument)
+{
+#if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
+ (void) bUseCurrentDocument;
+#else
+ if(bUseCurrentDocument)
+ {
+ if(!GetWrtShell().IsAnyDatabaseFieldInDoc())
+ {
+ //check availability of data sources (except biblio source)
+ uno::Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext);
+ bool bCallAddressPilot = false;
+ if ( lcl_NeedAdditionalDataSource( xDBContext ) )
+ {
+ // no data sources are available - create a new one
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/datasourcesunavailabledialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("DataSourcesUnavailableDialog"));
+ // no cancel allowed
+ if (RET_OK != xQuery->run())
+ return;
+ bCallAddressPilot = true;
+ }
+ else
+ {
+ //take an existing data source or create a new one?
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractMailMergeFieldConnectionsDlg> pConnectionsDlg(pFact->CreateMailMergeFieldConnectionsDlg(GetFrameWeld()));
+ if(RET_OK == pConnectionsDlg->Execute())
+ bCallAddressPilot = !pConnectionsDlg->IsUseExistingConnections();
+ else
+ return;
+
+ }
+ if(bCallAddressPilot)
+ {
+ GetViewFrame().GetDispatcher()->Execute(
+ SID_ADDRESS_DATA_SOURCE, SfxCallMode::SYNCHRON);
+ if ( lcl_NeedAdditionalDataSource( xDBContext ) )
+ // no additional data source has been created
+ // -> assume that the user has cancelled the pilot
+ return;
+ }
+
+ //call insert fields with database field page available, only
+ SfxViewFrame& rVFrame = GetViewFrame();
+ //at first hide the default field dialog if currently visible
+ rVFrame.SetChildWindow(FN_INSERT_FIELD, false);
+ //enable the status of the db field dialog - it is disabled in the status method
+ //to prevent creation of the dialog without mail merge active
+ EnableMailMerge();
+ //then show the "Data base only" field dialog
+ SfxBoolItem aOn(FN_INSERT_FIELD_DATA_ONLY, true);
+ rVFrame.GetDispatcher()->ExecuteList(FN_INSERT_FIELD_DATA_ONLY,
+ SfxCallMode::SYNCHRON, { &aOn });
+ return;
+ }
+ else
+ {
+ OUString sSource;
+ if(!GetWrtShell().IsFieldDataSourceAvailable(sSource))
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/warndatasourcedialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xWarning(xBuilder->weld_message_dialog("WarnDataSourceDialog"));
+ OUString sTmp(xWarning->get_primary_text());
+ xWarning->set_primary_text(sTmp.replaceFirst("%1", sSource));
+ if (RET_OK == xWarning->run())
+ {
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( nullptr, SID_OPTIONS_DATABASES ));
+ pDlg->Execute();
+ }
+ return ;
+ }
+ }
+ SwDBManager* pDBManager = GetWrtShell().GetDBManager();
+
+ SwDBData aData;
+ SwWrtShell &rSh = GetWrtShell();
+
+ std::vector<OUString> aDBNameList;
+ std::vector<OUString> aAllDBNames;
+ rSh.GetAllUsedDB( aDBNameList, &aAllDBNames );
+ if(!aDBNameList.empty())
+ {
+ OUString sDBName(aDBNameList[0]);
+ sal_Int32 nIdx {0};
+ aData.sDataSource = sDBName.getToken(0, DB_DELIM, nIdx);
+ aData.sCommand = sDBName.getToken(0, DB_DELIM, nIdx);
+ aData.nCommandType = o3tl::toInt32(o3tl::getToken(sDBName, 0, DB_DELIM, nIdx));
+ }
+ rSh.EnterStdMode(); // force change in text shell; necessary for mixing DB fields
+ AttrChangedNotify(nullptr);
+
+ if (pDBManager)
+ {
+ Sequence<PropertyValue> aProperties
+ {
+ comphelper::makePropertyValue("DataSourceName", aData.sDataSource),
+ comphelper::makePropertyValue("Command", aData.sCommand),
+ comphelper::makePropertyValue("CommandType", aData.nCommandType),
+ };
+ pDBManager->ExecuteFormLetter(GetWrtShell(), aProperties);
+ }
+ }
+ else
+ {
+ // call documents and template dialog
+ SfxApplication* pSfxApp = SfxGetpApp();
+ weld::Window* pTopWin = pSfxApp->GetTopWindow();
+
+ SfxTemplateManagerDlg aDocTemplDlg(GetFrameWeld());
+ int nRet = aDocTemplDlg.run();
+ bool bNewWin = false;
+ if ( nRet == RET_OK )
+ {
+ if ( pTopWin != pSfxApp->GetTopWindow() )
+ {
+ // the dialogue opens a document -> a new TopWindow appears
+ pTopWin = pSfxApp->GetTopWindow();
+ bNewWin = true;
+ }
+ }
+
+ if (bNewWin)
+ {
+ // after the destruction of the dialogue its parent comes to top,
+ // but we want that the new document is on top
+ pTopWin->present();
+ }
+ }
+#endif
+}
+
+IMPL_LINK( SwView, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
+{
+ if ( ERRCODE_NONE != _pFileDlg->GetError() )
+ return;
+
+ std::unique_ptr<SfxMedium> pMed = m_pViewImpl->CreateMedium();
+ if ( !pMed )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(RID_SVXSTR_TXTFILTER_FILTERERROR)));
+ xInfoBox->run();
+ return;
+ }
+
+ const sal_uInt16 nSlot = m_pViewImpl->GetRequest()->GetSlot();
+ tools::Long nFound = InsertMedium( nSlot, std::move(pMed), m_pViewImpl->GetParam() );
+
+ if ( SID_INSERTDOC == nSlot )
+ {
+ if ( m_pViewImpl->GetParam() == 0 )
+ {
+ m_pViewImpl->GetRequest()->SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) );
+ m_pViewImpl->GetRequest()->Ignore();
+ }
+ else
+ {
+ m_pViewImpl->GetRequest()->SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) );
+ m_pViewImpl->GetRequest()->Done();
+ }
+ }
+ else if ( SID_DOCUMENT_COMPARE == nSlot || SID_DOCUMENT_MERGE == nSlot )
+ {
+ m_pViewImpl->GetRequest()->SetReturnValue( SfxInt32Item( nSlot, nFound ) );
+
+ if ( nFound > 0 ) // show Redline browser
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ rVFrame.ShowChildWindow(FN_REDLINE_ACCEPT);
+
+ // re-initialize Redline dialog
+ sal_uInt16 nId = SwRedlineAcceptChild::GetChildWindowId();
+ SwRedlineAcceptChild* pRed = static_cast<SwRedlineAcceptChild*>(rVFrame.GetChildWindow( nId ));
+ if ( pRed )
+ pRed->ReInitDlg( GetDocShell() );
+ }
+ }
+}
+
+void SwView::ExecuteScan( SfxRequest& rReq )
+{
+ if (m_pViewImpl)
+ m_pViewImpl->ExecuteScan(rReq) ;
+}
+
+const OUString& SwView::GetOldGrfCat()
+{
+ return GetCachedString(OldGrfCat);
+}
+
+void SwView::SetOldGrfCat(const OUString& sStr)
+{
+ SetCachedString(OldGrfCat, sStr);
+}
+
+const OUString& SwView::GetOldTabCat()
+{
+ return GetCachedString(OldTabCat);
+}
+
+void SwView::SetOldTabCat(const OUString& sStr)
+{
+ SetCachedString(OldTabCat, sStr);
+}
+
+const OUString& SwView::GetOldFrameCat()
+{
+ return GetCachedString(OldFrameCat);
+}
+
+void SwView::SetOldFrameCat(const OUString& sStr)
+{
+ SetCachedString(OldFrameCat, sStr);
+}
+
+const OUString& SwView::GetOldDrwCat()
+{
+ return GetCachedString(OldDrwCat);
+}
+
+void SwView::SetOldDrwCat(const OUString& sStr)
+{
+ SwView::SetCachedString(OldDrwCat, sStr);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewcoll.cxx b/sw/source/uibase/uiview/viewcoll.cxx
new file mode 100644
index 0000000000..9ee42e1e21
--- /dev/null
+++ b/sw/source/uibase/uiview/viewcoll.cxx
@@ -0,0 +1,78 @@
+/* -*- 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 <cmdid.h>
+#include <uiitems.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <svl/stritem.hxx>
+#include <svl/style.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+
+void SwView::ExecColl(SfxRequest const &rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ sal_uInt16 nWhich = rReq.GetSlot();
+ switch( nWhich )
+ {
+ case FN_SET_PAGE:
+ {
+ OSL_ENSURE(false, "Not implemented");
+ }
+ break;
+ case FN_SET_PAGE_STYLE:
+ {
+ if( pArgs )
+ {
+ if (SfxItemState::SET == pArgs->GetItemState( nWhich , true, &pItem ))
+ {
+ if( static_cast<const SfxStringItem*>(pItem)->GetValue() !=
+ GetWrtShell().GetCurPageStyle() )
+ {
+ SfxStringItem aName(SID_STYLE_APPLY,
+ static_cast<const SfxStringItem*>(pItem)->GetValue());
+ SfxUInt16Item aFamItem( SID_STYLE_FAMILY,
+ sal_uInt16(SfxStyleFamily::Page));
+ SwPtrItem aShell(FN_PARAM_WRTSHELL, GetWrtShellPtr());
+ SfxRequest aReq(SID_STYLE_APPLY, SfxCallMode::SLOT, GetPool());
+ aReq.AppendItem(aName);
+ aReq.AppendItem(aFamItem);
+ aReq.AppendItem(aShell);
+ GetCurShell()->ExecuteSlot(aReq);
+ }
+ }
+ }
+ else
+ {
+ SfxRequest aReq(FN_FORMAT_PAGE_DLG, SfxCallMode::SLOT, GetPool());
+ GetCurShell()->ExecuteSlot(aReq);
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("wrong CommandProcessor for Dispatch");
+ return;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewdlg.cxx b/sw/source/uibase/uiview/viewdlg.cxx
new file mode 100644
index 0000000000..041b13bf48
--- /dev/null
+++ b/sw/source/uibase/uiview/viewdlg.cxx
@@ -0,0 +1,66 @@
+/* -*- 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 <sfx2/request.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+
+void SwView::ExecDlg(SfxRequest const &rReq)
+{
+ // Thus, from the basic no dialogues for background views are called:
+ const SfxPoolItem* pItem = nullptr;
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if(pArgs)
+ pArgs->GetItemState( GetPool().GetWhich(nSlot), false, &pItem );
+
+ switch ( nSlot )
+ {
+ case FN_CHANGE_PAGENUM:
+ {
+ if ( pItem )
+ {
+ sal_uInt16 nValue = static_cast<const SfxUInt16Item *>(pItem)->GetValue();
+ sal_uInt16 nOldValue = m_pWrtShell->GetPageOffset();
+ sal_uInt16 nPage, nLogPage;
+ m_pWrtShell->GetPageNum( nPage, nLogPage,
+ m_pWrtShell->IsCursorVisible(), false);
+
+ if(nValue != nOldValue || nValue != nLogPage)
+ {
+ if(!nOldValue)
+ m_pWrtShell->SetNewPageOffset( nValue );
+ else
+ m_pWrtShell->SetPageOffset( nValue );
+ }
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewdlg2.cxx b/sw/source/uibase/uiview/viewdlg2.cxx
new file mode 100644
index 0000000000..597731645e
--- /dev/null
+++ b/sw/source/uibase/uiview/viewdlg2.cxx
@@ -0,0 +1,305 @@
+/* -*- 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 <sfx2/request.hxx>
+#include <sfx2/objface.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdview.hxx>
+#include <osl/diagnose.h>
+#include <fldmgr.hxx>
+#include <expfld.hxx>
+#include <modcfg.hxx>
+
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <wview.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <caption.hxx>
+#include <poolfmt.hxx>
+#include <edtwin.hxx>
+#include <SwStyleNameMapper.hxx>
+
+#include <swabstdlg.hxx>
+
+#include <strings.hrc>
+
+#include <memory>
+
+#include <svl/stritem.hxx>
+
+using namespace css;
+
+void SwView::ExecDlgExt(SfxRequest const& rReq)
+{
+ switch (rReq.GetSlot())
+ {
+ case FN_INSERT_CAPTION:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ VclPtr<VclAbstractDialog> pDialog(
+ pFact->CreateSwCaptionDialog(GetFrameWeld(), *this));
+ pDialog->StartExecuteAsync([pDialog](sal_Int32) {
+ pDialog->disposeOnce();
+ });
+ break;
+ }
+ case SID_INSERT_SIGNATURELINE:
+ case SID_EDIT_SIGNATURELINE:
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ const uno::Reference<frame::XModel> xModel(GetCurrentDocument());
+ ScopedVclPtr<AbstractSignatureLineDialog> pDialog(pFact->CreateSignatureLineDialog(
+ GetFrameWeld(), xModel, rReq.GetSlot() == SID_EDIT_SIGNATURELINE));
+ pDialog->Execute();
+ break;
+ }
+ case SID_INSERT_QRCODE:
+ case SID_EDIT_QRCODE:
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ const uno::Reference<frame::XModel> xModel(GetCurrentDocument());
+ VclPtr<AbstractQrCodeGenDialog> pDialog(pFact->CreateQrCodeGenDialog(
+ GetFrameWeld(), xModel, rReq.GetSlot() == SID_EDIT_QRCODE));
+ pDialog->StartExecuteAsync([pDialog](sal_Int32) {
+ pDialog->disposeOnce();
+ });
+ break;
+ }
+ case SID_ADDITIONS_DIALOG:
+ {
+ OUString sAdditionsTag = "";
+
+ const SfxStringItem* pStringArg = rReq.GetArg<SfxStringItem>(FN_PARAM_ADDITIONS_TAG);
+ if (pStringArg)
+ sAdditionsTag = pStringArg->GetValue();
+
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractAdditionsDialog> pDialog(
+ pFact->CreateAdditionsDialog(GetFrameWeld(), sAdditionsTag));
+ pDialog->Execute();
+ break;
+ }
+ case SID_SIGN_SIGNATURELINE:
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ const uno::Reference<frame::XModel> xModel(GetCurrentDocument());
+ ScopedVclPtr<AbstractSignSignatureLineDialog> pDialog(
+ pFact->CreateSignSignatureLineDialog(GetFrameWeld(), xModel));
+ pDialog->Execute();
+ break;
+ }
+ case FN_EDIT_FOOTNOTE:
+ {
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractInsFootNoteDlg> pDlg(pFact->CreateInsFootNoteDlg(
+ GetFrameWeld(), *m_pWrtShell, true));
+
+ pDlg->SetHelpId(GetStaticInterface()->GetSlot(FN_EDIT_FOOTNOTE)->GetCommand());
+ pDlg->SetText( SwResId(STR_EDIT_FOOTNOTE) );
+ pDlg->Execute();
+ break;
+ }
+ }
+}
+
+bool SwView::isSignatureLineSelected() const
+{
+ SwWrtShell& rSh = GetWrtShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+ if (!pSdrView)
+ return false;
+
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ return false;
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+ if (!pPickObj)
+ return false;
+
+ SdrGrafObj* pGraphic = dynamic_cast<SdrGrafObj*>(pPickObj);
+ if (!pGraphic)
+ return false;
+
+ return pGraphic->isSignatureLine();
+}
+
+bool SwView::isSignatureLineSigned() const
+{
+ SwWrtShell& rSh = GetWrtShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+ if (!pSdrView)
+ return false;
+
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ return false;
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+ if (!pPickObj)
+ return false;
+
+ SdrGrafObj* pGraphic = dynamic_cast<SdrGrafObj*>(pPickObj);
+ if (!pGraphic)
+ return false;
+
+ return pGraphic->isSignatureLineSigned();
+}
+
+bool SwView::isQRCodeSelected() const
+{
+ SwWrtShell& rSh = GetWrtShell();
+ SdrView* pSdrView = rSh.GetDrawView();
+ if (!pSdrView)
+ return false;
+
+ if (pSdrView->GetMarkedObjectCount() != 1)
+ return false;
+
+ SdrObject* pPickObj = pSdrView->GetMarkedObjectByIndex(0);
+ if (!pPickObj)
+ return false;
+
+ SdrGrafObj* pGraphic = dynamic_cast<SdrGrafObj*>(pPickObj);
+ if (!pGraphic)
+ return false;
+
+ return pGraphic->getQrCode() != nullptr;
+}
+
+void SwView::AutoCaption(const sal_uInt16 nType, const SvGlobalName *pOleId)
+{
+ SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+ if (pModOpt->IsInsWithCaption(bWeb))
+ {
+ const InsCaptionOpt *pOpt = pModOpt->GetCapOption(bWeb, static_cast<SwCapObjType>(nType), pOleId);
+ if (pOpt && pOpt->UseCaption())
+ InsertCaption(pOpt);
+ }
+}
+
+void SwView::InsertCaption(const InsCaptionOpt *pOpt)
+{
+ if (!pOpt)
+ return;
+
+ const OUString &rName = pOpt->GetCategory();
+
+ // Is there a pool template with the same name?
+ SwWrtShell &rSh = GetWrtShell();
+ if(!rName.isEmpty())
+ {
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::TxtColl);
+ if( USHRT_MAX != nPoolId )
+ rSh.GetTextCollFromPool(nPoolId);
+ // Pool template does not exist: Does it exist on the document?
+ else if( !rSh.GetParaStyle(rName) )
+ {
+ // It also does not exist in the document: generate
+ SwTextFormatColl* pDerivedFrom = rSh.GetTextCollFromPool(RES_POOLCOLL_LABEL);
+ rSh.MakeTextFormatColl(rName, pDerivedFrom);
+ }
+ }
+
+ SelectionType eType = rSh.GetSelectionType();
+ if (eType & SelectionType::Ole)
+ eType = SelectionType::Graphic;
+
+ const SwLabelType eT = (eType & SelectionType::Table) ? SwLabelType::Table :
+ (eType & SelectionType::Frame) ? SwLabelType::Fly :
+ (eType == SelectionType::Text) ? SwLabelType::Fly :
+ (eType & SelectionType::DrawObject) ? SwLabelType::Draw :
+ SwLabelType::Object;
+
+ SwFieldMgr aMgr(&rSh);
+ SwSetExpFieldType* pFieldType =
+ static_cast<SwSetExpFieldType*>(aMgr.GetFieldType(SwFieldIds::SetExp, rName));
+ if (!pFieldType && !rName.isEmpty() )
+ {
+ // Create new field types
+ SwSetExpFieldType aSwSetExpFieldType(rSh.GetDoc(), rName, nsSwGetSetExpType::GSE_SEQ);
+ aMgr.InsertFieldType(aSwSetExpFieldType);
+ pFieldType = static_cast<SwSetExpFieldType*>(aMgr.GetFieldType(SwFieldIds::SetExp, rName));
+ }
+
+ if (!pOpt->IgnoreSeqOpts())
+ {
+ if (pFieldType)
+ {
+ pFieldType->SetDelimiter(pOpt->GetSeparator());
+ pFieldType->SetOutlineLvl( static_cast< sal_uInt8 >(pOpt->GetLevel()) );
+ }
+ }
+
+ sal_uInt16 nID = USHRT_MAX;
+ SwFieldType* pType = nullptr;
+ const size_t nCount = aMgr.GetFieldTypeCount();
+ if( !rName.isEmpty() )
+ {
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ pType = aMgr.GetFieldType(SwFieldIds::Unknown, i);
+ OUString aTmpName( pType->GetName() );
+ if (aTmpName == rName && pType->Which() == SwFieldIds::SetExp)
+ {
+ nID = i;
+ OSL_ENSURE(nID==i, "Downcasting to sal_uInt16 lost information!");
+ break;
+ }
+ }
+ }
+ rSh.StartAllAction();
+
+ GetWrtShell().InsertLabel( eT,
+ pOpt->GetCaption(),
+ !pOpt->IgnoreSeqOpts() ? OUString() : pOpt->GetSeparator(),
+ pOpt->GetNumSeparator(),
+ !pOpt->GetPos(),
+ nID,
+ pOpt->GetCharacterStyle(),
+ pOpt->CopyAttributes() );
+ // Set Number Format
+ if(pType)
+ static_cast<SwSetExpFieldType*>(pType)->SetSeqFormat(pOpt->GetNumType());
+
+ rSh.UpdateExpFields( true );
+
+ rSh.EndAllAction();
+
+ if ( rSh.IsFrameSelected() )
+ {
+ GetEditWin().StopInsFrame();
+ rSh.EnterSelFrameMode();
+ }
+
+ // remember category
+ if (eType & SelectionType::Graphic)
+ SetOldGrfCat(rName);
+ else if( eType & SelectionType::Table)
+ SetOldTabCat(rName);
+ else if( eType & SelectionType::Frame)
+ SetOldFrameCat(rName);
+ else if( eType == SelectionType::Text)
+ SetOldFrameCat(rName);
+ else if( eType & SelectionType::DrawObject)
+ SetOldDrwCat(rName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewdraw.cxx b/sw/source/uibase/uiview/viewdraw.cxx
new file mode 100644
index 0000000000..956d05f1df
--- /dev/null
+++ b/sw/source/uibase/uiview/viewdraw.cxx
@@ -0,0 +1,755 @@
+/* -*- 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 <hintids.hxx>
+#include <svl/itempool.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/outliner.hxx>
+#include <svx/fmview.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <doc.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <textboxhelper.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/fontworkbar.hxx>
+#include <svx/fontworkgallery.hxx>
+#include <editeng/eeitem.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdetc.hxx>
+#include <editeng/editstat.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/svdoutl.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <osl/diagnose.h>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <cmdid.h>
+#include <drwbassh.hxx>
+#include <beziersh.hxx>
+#include <conrect.hxx>
+#include <conpoly.hxx>
+#include <conarc.hxx>
+#include <conform.hxx>
+#include <concustomshape.hxx>
+#include <dselect.hxx>
+#include <edtwin.hxx>
+
+#include <dcontact.hxx>
+
+#include <svx/svdpagv.hxx>
+#include <svx/extrusionbar.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+using namespace ::com::sun::star;
+
+// Execute Drawing-Ids
+
+void SwView::ExecDraw(const SfxRequest& rReq)
+{
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem;
+ const SfxStringItem* pStringItem = nullptr;
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ bool bDeselect = false;
+
+ sal_uInt16 nSlotId = rReq.GetSlot();
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(GetPool().GetWhich(nSlotId), false, &pItem))
+ pStringItem = dynamic_cast< const SfxStringItem*>(pItem);
+
+ SdrObjKind eNewFormObjKind = SdrObjKind::NONE;
+ if (nSlotId == SID_FM_CREATE_CONTROL)
+ {
+ const SfxUInt16Item* pIdentifierItem = rReq.GetArg<SfxUInt16Item>(SID_FM_CONTROL_IDENTIFIER);
+ if (pIdentifierItem)
+ eNewFormObjKind = static_cast<SdrObjKind>(pIdentifierItem->GetValue());
+ }
+
+ if (nSlotId == SID_OBJECT_SELECT && m_nFormSfxId == nSlotId)
+ {
+ bDeselect = true;
+ }
+ else if (nSlotId == SID_FM_CREATE_CONTROL)
+ {
+ if (eNewFormObjKind == m_eFormObjKind || eNewFormObjKind == SdrObjKind::NONE)
+ {
+ bDeselect = true;
+ GetViewFrame().GetDispatcher()->Execute(SID_FM_LEAVE_CREATE); // Button should popping out
+ }
+ }
+ else if (nSlotId == SID_FM_CREATE_FIELDCONTROL)
+ {
+ FmFormView* pFormView = dynamic_cast<FmFormView*>(pSdrView);
+ if (pFormView)
+ {
+ const SfxUnoAnyItem* pDescriptorItem = rReq.GetArg<SfxUnoAnyItem>(SID_FM_DATACCESS_DESCRIPTOR);
+ OSL_ENSURE( pDescriptorItem, "SwView::ExecDraw(SID_FM_CREATE_FIELDCONTROL): invalid request args!" );
+ if( pDescriptorItem )
+ {
+ svx::ODataAccessDescriptor aDescriptor( pDescriptorItem->GetValue() );
+ rtl::Reference<SdrObject> pObj = pFormView->CreateFieldControl( aDescriptor );
+
+ if ( pObj )
+ {
+ Size aDocSize(m_pWrtShell->GetDocSize());
+ const SwRect& rVisArea = m_pWrtShell->VisArea();
+ Point aStartPos = rVisArea.Center();
+ if(rVisArea.Width() > aDocSize.Width())
+ aStartPos.setX( aDocSize.Width() / 2 + rVisArea.Left() );
+ if(rVisArea.Height() > aDocSize.Height())
+ aStartPos.setY( aDocSize.Height() / 2 + rVisArea.Top() );
+
+ //determine the size of the object
+ if(pObj->IsGroupObject())
+ {
+ const tools::Rectangle& rBoundRect = static_cast<SdrObjGroup*>(pObj.get())->GetCurrentBoundRect();
+ aStartPos.AdjustX( -(rBoundRect.GetWidth()/2) );
+ aStartPos.AdjustY( -(rBoundRect.GetHeight()/2) );
+ }
+
+ // TODO: unmark all other
+ m_pWrtShell->EnterStdMode();
+ m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aStartPos );
+ }
+ }
+ }
+ }
+ else if ( nSlotId == SID_FONTWORK_GALLERY_FLOATER )
+ {
+ vcl::Window& rWin = m_pWrtShell->GetView().GetViewFrame().GetWindow();
+
+ rWin.EnterWait();
+
+ if( !m_pWrtShell->HasDrawView() )
+ m_pWrtShell->MakeDrawView();
+
+ pSdrView = m_pWrtShell->GetDrawView();
+ if (pSdrView)
+ {
+ std::shared_ptr<svx::FontWorkGalleryDialog> pDlg = std::make_shared<svx::FontWorkGalleryDialog>(rWin.GetFrameWeld(), *pSdrView);
+ pDlg->SetSdrObjectRef(&pSdrView->GetModel());
+ weld::DialogController::runAsync(pDlg, [this, pDlg](int) {
+ vcl::Window& rWin2 = m_pWrtShell->GetView().GetViewFrame().GetWindow();
+
+ SdrObject* pObj = pDlg->GetSdrObjectRef();
+ if ( pObj )
+ {
+ Size aDocSize( m_pWrtShell->GetDocSize() );
+ const SwRect& rVisArea = comphelper::LibreOfficeKit::isActive() ?
+ SwRect(m_pWrtShell->getLOKVisibleArea()) : m_pWrtShell->VisArea();
+ Point aPos( rVisArea.Center() );
+ tools::Rectangle aObjRect( pObj->GetLogicRect() );
+
+ if ( rVisArea.Width() > aDocSize.Width())
+ aPos.setX( aDocSize.Width() / 2 + rVisArea.Left() );
+ else if (aPos.getX() > aObjRect.GetWidth() / 2)
+ aPos.AdjustX( -(aObjRect.GetWidth() / 2) );
+
+ if (rVisArea.Height() > aDocSize.Height())
+ aPos.setY( aDocSize.Height() / 2 + rVisArea.Top() );
+ else if (aPos.getY() > aObjRect.GetHeight() / 2)
+ aPos.AdjustY( -(aObjRect.GetHeight() / 2) );
+
+ m_pWrtShell->EnterStdMode();
+ m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aPos );
+ }
+
+ rWin2.LeaveWait();
+ });
+ }
+ else
+ rWin.LeaveWait();
+ }
+ else if ( m_nFormSfxId != USHRT_MAX )
+ GetViewFrame().GetDispatcher()->Execute( SID_FM_LEAVE_CREATE );
+
+ if( nSlotId == SID_DRAW_CS_ID )
+ {
+ //deselect if same custom shape is selected again
+ SwDrawBase* pFuncPtr = GetDrawFuncPtr();
+ if( pFuncPtr && pFuncPtr->GetSlotId() == SID_DRAW_CS_ID )
+ {
+ ConstCustomShape* pConstCustomShape = static_cast<ConstCustomShape*>(pFuncPtr);
+ OUString aNew = ConstCustomShape::GetShapeTypeFromRequest( rReq );
+ const OUString& aOld = pConstCustomShape->GetShapeType();
+ if( aNew == aOld )
+ {
+ bDeselect = true;
+ }
+ }
+ }
+
+ //deselect if same shape is selected again (but different custom shapes do have same slot id)
+ if ( bDeselect || (nSlotId == m_nDrawSfxId &&
+ (!pStringItem || (pStringItem->GetValue() == m_sDrawCustom))
+ && (nSlotId != SID_DRAW_CS_ID) ) )
+ {
+ if (GetDrawFuncPtr())
+ {
+ GetDrawFuncPtr()->Deactivate();
+ SetDrawFuncPtr(nullptr);
+ }
+
+ if (m_pWrtShell->IsObjSelected() && !m_pWrtShell->IsSelFrameMode())
+ m_pWrtShell->EnterSelFrameMode();
+ LeaveDrawCreate();
+
+ AttrChangedNotify(nullptr);
+ return;
+ }
+
+ LeaveDrawCreate();
+
+ if (m_pWrtShell->IsFrameSelected())
+ m_pWrtShell->EnterStdMode(); // because bug #45639
+
+ std::unique_ptr<SwDrawBase> pFuncPtr;
+
+ // for LibreOfficeKit - choosing a shape should construct it directly
+ bool bCreateDirectly = false;
+
+ switch (nSlotId)
+ {
+ case SID_OBJECT_SELECT:
+ case SID_DRAW_SELECT:
+ pFuncPtr.reset( new DrawSelection(m_pWrtShell.get(), m_pEditWin, this) );
+ m_nDrawSfxId = m_nFormSfxId = SID_OBJECT_SELECT;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ case SID_DRAW_MEASURELINE:
+ case SID_DRAW_RECT:
+ case SID_DRAW_ELLIPSE:
+ case SID_DRAW_TEXT:
+ case SID_DRAW_TEXT_VERTICAL:
+ case SID_DRAW_TEXT_MARQUEE:
+ case SID_DRAW_CAPTION:
+ case SID_DRAW_CAPTION_VERTICAL:
+ pFuncPtr.reset( new ConstRectangle(m_pWrtShell.get(), m_pEditWin, this) );
+ bCreateDirectly = comphelper::LibreOfficeKit::isActive();
+ m_nDrawSfxId = nSlotId;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_DRAW_XPOLYGON_NOFILL:
+ case SID_DRAW_XPOLYGON:
+ case SID_DRAW_POLYGON_NOFILL:
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_BEZIER_NOFILL:
+ case SID_DRAW_BEZIER_FILL:
+ case SID_DRAW_FREELINE_NOFILL:
+ case SID_DRAW_FREELINE:
+ pFuncPtr.reset( new ConstPolygon(m_pWrtShell.get(), m_pEditWin, this) );
+ m_nDrawSfxId = nSlotId;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_DRAW_ARC:
+ case SID_DRAW_PIE:
+ case SID_DRAW_CIRCLECUT:
+ pFuncPtr.reset( new ConstArc(m_pWrtShell.get(), m_pEditWin, this) );
+ m_nDrawSfxId = nSlotId;
+ m_sDrawCustom.clear();
+ break;
+
+ case SID_FM_CREATE_CONTROL:
+ {
+ pFuncPtr.reset(new ConstFormControl(m_pWrtShell.get(), m_pEditWin, this, eNewFormObjKind));
+ m_nFormSfxId = nSlotId;
+ m_eFormObjKind = eNewFormObjKind;
+ }
+ break;
+
+ case SID_DRAWTBX_CS_BASIC :
+ case SID_DRAWTBX_CS_SYMBOL :
+ case SID_DRAWTBX_CS_ARROW :
+ case SID_DRAWTBX_CS_FLOWCHART :
+ case SID_DRAWTBX_CS_CALLOUT :
+ case SID_DRAWTBX_CS_STAR :
+ case SID_DRAW_CS_ID :
+ {
+ pFuncPtr.reset( new ConstCustomShape(m_pWrtShell.get(), m_pEditWin, this, rReq ) );
+
+ bCreateDirectly = comphelper::LibreOfficeKit::isActive();
+
+ m_nDrawSfxId = nSlotId;
+ if ( nSlotId != SID_DRAW_CS_ID )
+ {
+ if ( pStringItem )
+ {
+ m_sDrawCustom = pStringItem->GetValue();
+ SfxBindings& rBind = GetViewFrame().GetBindings();
+ rBind.Invalidate( nSlotId );
+ rBind.Update( nSlotId );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ GetViewFrame().GetBindings().Invalidate(SID_ATTRIBUTES_AREA);
+
+ bool bEndTextEdit = true;
+ if (pFuncPtr)
+ {
+ if (GetDrawFuncPtr())
+ {
+ GetDrawFuncPtr()->Deactivate();
+ }
+
+ auto pTempFuncPtr = pFuncPtr.get();
+ SetDrawFuncPtr(std::move(pFuncPtr));
+ AttrChangedNotify(nullptr);
+
+ pTempFuncPtr->Activate(nSlotId);
+ NoRotate();
+ if(rReq.GetModifier() == KEY_MOD1 || bCreateDirectly)
+ {
+ if (bCreateDirectly)
+ GetViewFrame().GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
+ if(SID_OBJECT_SELECT == m_nDrawSfxId )
+ {
+ m_pWrtShell->GotoObj(true);
+ }
+ else if (dynamic_cast<ConstCustomShape*>(pTempFuncPtr))
+ {
+ pTempFuncPtr->CreateDefaultObject();
+ }
+ else
+ {
+ pTempFuncPtr->CreateDefaultObject();
+ pTempFuncPtr->Deactivate();
+ SetDrawFuncPtr(nullptr);
+ LeaveDrawCreate();
+ m_pWrtShell->EnterStdMode();
+ SdrView *pTmpSdrView = m_pWrtShell->GetDrawView();
+ const SdrMarkList& rMarkList = pTmpSdrView->GetMarkedObjectList();
+ if(rMarkList.GetMarkCount() == 1 &&
+ (SID_DRAW_TEXT == nSlotId || SID_DRAW_TEXT_VERTICAL == nSlotId ||
+ SID_DRAW_TEXT_MARQUEE == nSlotId ))
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ BeginTextEdit(pObj);
+ bEndTextEdit = false;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_pWrtShell->IsObjSelected() && !m_pWrtShell->IsSelFrameMode())
+ m_pWrtShell->EnterSelFrameMode();
+ }
+
+ if(bEndTextEdit && pSdrView && pSdrView->IsTextEdit())
+ pSdrView->SdrEndTextEdit( true );
+
+ AttrChangedNotify(nullptr);
+}
+
+// End drawing
+
+void SwView::ExitDraw()
+{
+ NoRotate();
+
+ if(!m_pShell)
+ return;
+
+ // the shell may be invalid at close/reload/SwitchToViewShell
+ SfxDispatcher* pDispatch = GetViewFrame().GetDispatcher();
+ sal_uInt16 nIdx = 0;
+ SfxShell* pTest = nullptr;
+ do
+ {
+ pTest = pDispatch->GetShell(nIdx++);
+ }
+ while( pTest && pTest != this && pTest != m_pShell);
+ if(!(pTest == m_pShell &&
+ // don't call LeaveSelFrameMode() etc. for the below,
+ // because objects may still be selected:
+ dynamic_cast< const SwDrawBaseShell *>( m_pShell ) == nullptr &&
+ dynamic_cast< const SwBezierShell *>( m_pShell ) == nullptr &&
+ dynamic_cast< const svx::ExtrusionBar *>( m_pShell ) == nullptr &&
+ dynamic_cast< const svx::FontworkBar *>( m_pShell ) == nullptr))
+ return;
+
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+
+ if (pSdrView && pSdrView->IsGroupEntered())
+ {
+ pSdrView->LeaveOneGroup();
+ pSdrView->UnmarkAll();
+ GetViewFrame().GetBindings().Invalidate(SID_ENTER_GROUP);
+ }
+
+ if (GetDrawFuncPtr())
+ {
+ if (m_pWrtShell->IsSelFrameMode())
+ m_pWrtShell->LeaveSelFrameMode();
+ GetDrawFuncPtr()->Deactivate();
+
+ SetDrawFuncPtr(nullptr);
+ LeaveDrawCreate();
+
+ GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
+ }
+ GetEditWin().SetPointer(PointerStyle::Text);
+}
+
+// Disable rotate mode
+
+void SwView::NoRotate()
+{
+ if (IsDrawRotate())
+ {
+ m_pWrtShell->SetDragMode(SdrDragMode::Move);
+ FlipDrawRotate();
+
+ const SfxBoolItem aTmp( SID_OBJECT_ROTATE, false );
+ GetViewFrame().GetBindings().SetState( aTmp );
+ }
+}
+
+// Enable DrawTextEditMode
+
+static bool lcl_isTextBox(SdrObject const * pObject)
+{
+ if (SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pObject->GetUserCall()))
+ {
+ if (SwFrameFormat* pFormat = pDrawContact->GetFormat())
+ return SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT);
+ }
+ return false;
+}
+
+bool SwView::EnterDrawTextMode(const Point& aDocPos)
+{
+ SwWrtShell *pSh = &GetWrtShell();
+ SdrView *pSdrView = pSh->GetDrawView();
+ OSL_ENSURE( pSdrView, "EnterDrawTextMode without DrawView?" );
+
+ bool bReturn = false;
+
+ sal_uInt16 nOld = pSdrView->GetHitTolerancePixel();
+ pSdrView->SetHitTolerancePixel( 2 );
+
+ SdrObject* pObj = nullptr;
+ SdrPageView* pPV = nullptr;
+ if (pSdrView->IsMarkedHit(aDocPos) && !pSdrView->PickHandle(aDocPos) && IsTextTool())
+ pObj = pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKTEXTEDIT);
+
+ if (pObj)
+ {
+ // To allow SwDrawVirtObj text objects to be activated, allow their type, too.
+ auto pVirtObj = dynamic_cast<SwDrawVirtObj*>( pObj );
+ if ( (pVirtObj && DynCastSdrTextObj(&pVirtObj->GetReferencedObj() ) != nullptr &&
+ m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) ||
+ DynCastSdrTextObj( pObj ) != nullptr )
+ {
+ // Refuse to edit editeng text of the shape if it has textbox attached.
+ if (!lcl_isTextBox(pObj))
+ bReturn = BeginTextEdit( pObj, pPV, m_pEditWin );
+ }
+ }
+
+ pSdrView->SetHitTolerancePixel( nOld );
+
+ return bReturn;
+}
+
+bool SwView::EnterShapeDrawTextMode(SdrObject* pObject)
+{
+ SdrView* pSdrView = GetWrtShell().GetDrawView();
+ SdrPageView* pPageView = pSdrView->GetSdrPageView();
+ return BeginTextEdit(pObject, pPageView, m_pEditWin);
+}
+
+// Enable DrawTextEditMode
+
+bool SwView::BeginTextEdit(SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin,
+ bool bIsNewObj, bool bSetSelectionToStart)
+{
+ SwWrtShell *pSh = &GetWrtShell();
+ SdrView *pSdrView = pSh->GetDrawView();
+ std::unique_ptr<SdrOutliner> pOutliner = ::SdrMakeOutliner(OutlinerMode::TextObject, pSdrView->GetModel());
+ uno::Reference< linguistic2::XSpellChecker1 > xSpell( ::GetSpellChecker() );
+ if (pOutliner)
+ {
+ pOutliner->SetRefDevice(pSh->getIDocumentDeviceAccess().getReferenceDevice(false));
+ pOutliner->SetSpeller(xSpell);
+ uno::Reference<linguistic2::XHyphenator> xHyphenator( ::GetHyphenator() );
+ pOutliner->SetHyphenator( xHyphenator );
+ pSh->SetCalcFieldValueHdl(pOutliner.get());
+
+ EEControlBits nCntrl = pOutliner->GetControlWord();
+ nCntrl |= EEControlBits::ALLOWBIGOBJS;
+
+ const SwViewOption *pOpt = pSh->GetViewOptions();
+
+ if (pOpt->IsFieldShadings())
+ nCntrl |= EEControlBits::MARKFIELDS;
+ else
+ nCntrl &= ~EEControlBits::MARKFIELDS;
+
+ if (pOpt->IsOnlineSpell())
+ nCntrl |= EEControlBits::ONLINESPELLING;
+ else
+ nCntrl &= ~EEControlBits::ONLINESPELLING;
+
+ pOutliner->SetControlWord(nCntrl);
+ const SvxLanguageItem& rItem = pSh->GetDoc()->GetDefault(RES_CHRATR_LANGUAGE);
+ pOutliner->SetDefaultLanguage(rItem.GetLanguage());
+
+ if( bIsNewObj )
+ pOutliner->SetVertical( SID_DRAW_TEXT_VERTICAL == m_nDrawSfxId ||
+ SID_DRAW_CAPTION_VERTICAL == m_nDrawSfxId );
+
+ // set default horizontal text direction at outliner
+ EEHorizontalTextDirection aDefHoriTextDir =
+ pSh->IsShapeDefaultHoriTextDirR2L() ? EEHorizontalTextDirection::R2L : EEHorizontalTextDirection::L2R;
+ pOutliner->SetDefaultHorizontalTextDirection( aDefHoriTextDir );
+ }
+
+ // To allow editing the referenced object from a SwDrawVirtObj here
+ // the original needs to be fetched eventually. This ATM activates the
+ // text edit mode for the original object.
+ SdrObject* pToBeActivated = pObj;
+
+ // Always the original object is edited. To allow the TextEdit to happen
+ // where the VirtObj is positioned, on demand an occurring offset is set at
+ // the TextEdit object. That offset is used for creating and managing the
+ // OutlinerView.
+ Point aNewTextEditOffset(0, 0);
+
+ if (SwDrawVirtObj* pVirtObj = dynamic_cast<SwDrawVirtObj *>(pObj))
+ {
+ pToBeActivated = &const_cast<SdrObject&>(pVirtObj->GetReferencedObj());
+ aNewTextEditOffset = pVirtObj->GetOffset();
+ }
+
+ // set in each case, thus it will be correct for all objects
+ static_cast<SdrTextObj*>(pToBeActivated)->SetTextEditOffset(aNewTextEditOffset);
+
+ bool bRet(pSdrView->SdrBeginTextEdit( pToBeActivated, pPV, pWin, true, pOutliner.release(), nullptr, false, false, false ));
+
+ // #i7672#
+ // Since SdrBeginTextEdit actually creates the OutlinerView and thus also
+ // sets the background color, an own background color needs to be set
+ // after TextEditing was started. This is now done here.
+ if(bRet)
+ {
+ OutlinerView* pView = pSdrView->GetTextEditOutlinerView();
+
+ if(pView)
+ {
+ Color aBackground(pSh->GetShapeBackground());
+ pView->SetBackgroundColor(aBackground);
+ }
+
+ // editing should start at the end of text, spell checking at the beginning ...
+ ESelection aNewSelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
+ if (bSetSelectionToStart)
+ aNewSelection = ESelection();
+ if (pView)
+ {
+ pView->SetSelection(aNewSelection);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ OString sRect = pView->GetOutputArea().toString();
+ SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_LOCK, "rectangle", sRect);
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// Is a DrawTextObject selected?
+bool SwView::IsTextTool() const
+{
+ SdrObjKind nId;
+ SdrInventor nInvent;
+ SdrView *pSdrView = GetWrtShell().GetDrawView();
+ OSL_ENSURE( pSdrView, "IsTextTool without DrawView?" );
+
+ if (pSdrView->IsCreateMode())
+ pSdrView->SetCreateMode(false);
+
+ pSdrView->TakeCurrentObj(nId,nInvent);
+ return nInvent == SdrInventor::Default;
+}
+
+SdrView* SwView::GetDrawView() const
+{
+ return GetWrtShell().GetDrawView();
+}
+
+bool SwView::IsBezierEditMode() const
+{
+ return (!IsDrawSelMode() && GetWrtShell().GetDrawView()->HasMarkablePoints());
+}
+
+bool SwView::IsFormMode() const
+{
+ if (GetDrawFuncPtr() && GetDrawFuncPtr()->IsCreateObj())
+ {
+ return GetDrawFuncPtr()->IsInsertForm();
+ }
+
+ return AreOnlyFormsSelected();
+}
+
+void SwView::SetDrawFuncPtr(std::unique_ptr<SwDrawBase> pFuncPtr)
+{
+ m_pDrawActual = std::move(pFuncPtr);
+}
+
+void SwView::SetSelDrawSlot()
+{
+ m_nDrawSfxId = SID_OBJECT_SELECT;
+ m_sDrawCustom.clear();
+}
+
+bool SwView::AreOnlyFormsSelected() const
+{
+ if ( GetWrtShell().IsFrameSelected() )
+ return false;
+
+ bool bForm = true;
+
+ SdrView* pSdrView = GetWrtShell().GetDrawView();
+
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ const size_t nCount = rMarkList.GetMarkCount();
+
+ if (nCount)
+ {
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ // Except controls, are still normal draw objects selected?
+ SdrObject *pSdrObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
+ if (!pSdrObj)
+ continue;
+
+ if (!HasOnlyObj(pSdrObj, SdrInventor::FmForm))
+ {
+ bForm = false;
+ break;
+ }
+ }
+ }
+ else
+ bForm = false;
+
+ return bForm;
+}
+
+bool SwView::HasOnlyObj(SdrObject const *pSdrObj, SdrInventor eObjInventor) const
+{
+ bool bRet = false;
+
+ if (pSdrObj->IsGroupObject())
+ {
+ SdrObjList* pList = pSdrObj->GetSubList();
+ for (const rtl::Reference<SdrObject>& pObj : *pList)
+ {
+ bRet = HasOnlyObj(pObj.get(), eObjInventor);
+ if (!bRet)
+ break;
+ }
+ }
+ else if (eObjInventor == pSdrObj->GetObjInventor())
+ return true;
+
+ return bRet;
+}
+
+//#i87414# mod
+IMPL_LINK(SwView, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void)
+{
+ if (rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG)
+ GetViewFrame().GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON);
+ else if (rInfo.nCommand == SpellCallbackCommand::AUTOCORRECT_OPTIONS)
+ GetViewFrame().GetDispatcher()->Execute( SID_AUTO_CORRECT_DLG, SfxCallMode::ASYNCHRON );
+}
+
+bool SwView::ExecDrwTextSpellPopup(const Point& rPt)
+{
+ bool bRet = false;
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
+ Point aPos( GetEditWin().LogicToPixel( rPt ) );
+
+ if (pOLV->IsWrongSpelledWordAtPos( aPos ))
+ {
+ bRet = true;
+ Link<SpellCallbackInfo&,void> aLink = LINK(this, SwView, OnlineSpellCallback);
+ pOLV->ExecuteSpellPopup(aPos, aLink);
+ }
+ return bRet;
+}
+
+bool SwView::IsDrawTextHyphenate()
+{
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ bool bHyphenate = false;
+
+ SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aNewAttr( pSdrView->GetModel().GetItemPool() );
+ pSdrView->GetAttributes( aNewAttr );
+ if( aNewAttr.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT )
+ bHyphenate = aNewAttr.Get( EE_PARA_HYPHENATE ).GetValue();
+
+ return bHyphenate;
+}
+
+void SwView::HyphenateDrawText()
+{
+ SdrView *pSdrView = m_pWrtShell->GetDrawView();
+ bool bHyphenate = IsDrawTextHyphenate();
+
+ SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aSet( GetPool() );
+ aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, !bHyphenate ) );
+ pSdrView->SetAttributes( aSet );
+ GetViewFrame().GetBindings().Invalidate(FN_HYPHENATE_OPT_DLG);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewfunc.hxx b/sw/source/uibase/uiview/viewfunc.hxx
new file mode 100644
index 0000000000..38320f6f39
--- /dev/null
+++ b/sw/source/uibase/uiview/viewfunc.hxx
@@ -0,0 +1,54 @@
+/* -*- 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 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UIBASE_UIVIEW_VIEWFUNC_HXX
+#define INCLUDED_SW_SOURCE_UIBASE_UIVIEW_VIEWFUNC_HXX
+
+#include <vcl/outdev.hxx>
+
+#include <IDocumentDeviceAccess.hxx>
+
+class ImageButton;
+class Point;
+class SfxItemSet;
+class SfxPrinter;
+class SfxTabPage;
+class Size;
+class SvxRuler;
+class SwScrollbar;
+class SwViewShell;
+namespace vcl { class Window; }
+
+// The following functions are available in viewprt.cxx
+void SetPrinter( IDocumentDeviceAccess*, SfxPrinter const *, bool bWeb );
+void SetAppPrintOptions( SwViewShell* pSh, bool bWeb );
+
+// The following functions are available in viewport.cxx
+void ViewResizePixel( const vcl::RenderContext &rRef,
+ const Point &rOfst,
+ const Size &rSize,
+ const Size &rEditSz,
+ SwScrollbar& rVScrollbar,
+ SwScrollbar& rHScrollbar,
+ SvxRuler* pVRuler = nullptr,
+ SvxRuler* pHRuler = nullptr,
+ bool bVRulerRight = false );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewling.cxx b/sw/source/uibase/uiview/viewling.cxx
new file mode 100644
index 0000000000..a9f64d7bf7
--- /dev/null
+++ b/sw/source/uibase/uiview/viewling.cxx
@@ -0,0 +1,856 @@
+/* -*- 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 <hintids.hxx>
+
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <com/sun/star/linguistic2/ProofreadingResult.hpp>
+#include <com/sun/star/linguistic2/XLinguProperties.hpp>
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <comphelper/lok.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/weld.hxx>
+#include <svtools/ehdl.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/svxerr.hxx>
+#include <svx/svxdlg.hxx>
+#include <osl/diagnose.h>
+#include <swwait.hxx>
+#include <uitool.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <swundo.hxx>
+#include <hyp.hxx>
+#include <olmenu.hxx>
+#include <pam.hxx>
+#include <edtwin.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <cmdid.h>
+#include <strings.hrc>
+#include <hhcwrp.hxx>
+
+#include <boost/property_tree/json_parser.hpp>
+
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <com/sun/star/awt/PopupMenuDirection.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <vcl/svapp.hxx>
+#include <rtl/ustring.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include <svtools/langtab.hxx>
+
+#include <editeng/editerr.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <memory>
+
+using namespace sw::mark;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+
+// Lingu-Dispatcher
+
+void SwView::ExecLingu(SfxRequest &rReq)
+{
+ switch(rReq.GetSlot())
+ {
+ case SID_THESAURUS:
+ StartThesaurus();
+ rReq.Ignore();
+ break;
+ case SID_HANGUL_HANJA_CONVERSION:
+ StartTextConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr,
+ i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true );
+ break;
+ case SID_CHINESE_CONVERSION:
+ {
+ //open ChineseTranslationDialog
+ Reference< XComponentContext > xContext(
+ ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
+ if(xContext.is())
+ {
+ Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
+ if(xMCF.is())
+ {
+ Reference< ui::dialogs::XExecutableDialog > xDialog(
+ xMCF->createInstanceWithContext(
+ "com.sun.star.linguistic2.ChineseTranslationDialog", xContext),
+ UNO_QUERY);
+ Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
+ if( xInit.is() )
+ {
+ Reference<awt::XWindow> xParentWindow;
+ if (weld::Window* pParentWindow = rReq.GetFrameWeld())
+ xParentWindow = pParentWindow->GetXWindow();
+ // initialize dialog
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", uno::Any(xParentWindow)}
+ }));
+ xInit->initialize( aSeq );
+
+ //execute dialog
+ sal_Int16 nDialogRet = xDialog->execute();
+ if( RET_OK == nDialogRet )
+ {
+ //get some parameters from the dialog
+ bool bToSimplified = true;
+ bool bUseVariants = true;
+ bool bCommonTerms = true;
+ Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
+ xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
+ xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+
+ //execute translation
+ LanguageType nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED;
+ LanguageType nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL;
+ sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
+ if( !bCommonTerms )
+ nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
+
+ vcl::Font aTargetFont = OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT,
+ nTargetLang, GetDefaultFontFlags::OnlyOne );
+
+ // disallow formatting, updating the view, ... while
+ // converting the document. (saves time)
+ // Also remember the current view and cursor position for later
+ m_pWrtShell->StartAction();
+
+ // remember cursor position data for later restoration of the cursor
+ const SwPosition *pPoint = m_pWrtShell->GetCursor()->GetPoint();
+ bool bRestoreCursor = pPoint->GetNode().IsTextNode();
+ const SwNodeIndex aPointNodeIndex( pPoint->GetNode() );
+ sal_Int32 nPointIndex = pPoint->GetContentIndex();
+
+ // since this conversion is not interactive the whole converted
+ // document should be undone in a single undo step.
+ m_pWrtShell->StartUndo( SwUndoId::OVERWRITE );
+
+ StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, false );
+
+ m_pWrtShell->EndUndo( SwUndoId::OVERWRITE );
+
+ if (bRestoreCursor)
+ {
+ SwTextNode *pTextNode = aPointNodeIndex.GetNode().GetTextNode();
+ // check for unexpected error case
+ OSL_ENSURE(pTextNode && pTextNode->GetText().getLength() >= nPointIndex,
+ "text missing: corrupted node?" );
+ // restore cursor to its original position
+ if (!pTextNode || pTextNode->GetText().getLength() < nPointIndex)
+ m_pWrtShell->GetCursor()->GetPoint()->Assign( aPointNodeIndex );
+ else
+ m_pWrtShell->GetCursor()->GetPoint()->Assign( *pTextNode, nPointIndex );
+ }
+
+ // enable all, restore view and cursor position
+ m_pWrtShell->EndAction();
+ }
+ }
+ Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
+ if( xComponent.is() )
+ xComponent->dispose();
+ }
+ }
+ break;
+ }
+ case FN_HYPHENATE_OPT_DLG:
+ HyphenateDocument();
+ break;
+ default:
+ OSL_ENSURE(false, "wrong Dispatcher");
+ return;
+ }
+}
+
+// start language specific text conversion
+
+void SwView::StartTextConversion(
+ LanguageType nSourceLang,
+ LanguageType nTargetLang,
+ const vcl::Font *pTargetFont,
+ sal_Int32 nOptions,
+ bool bIsInteractive )
+{
+ // do not do text conversion if it is active elsewhere
+ if (SwEditShell::HasConvIter())
+ {
+ return;
+ }
+
+ SpellContext();
+
+ const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
+ const bool bOldIdle = pVOpt->IsIdle();
+ pVOpt->SetIdle( false );
+
+ bool bOldIns = m_pWrtShell->IsInsMode();
+ m_pWrtShell->SetInsMode();
+
+ const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
+ m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
+
+ const bool bStart = bSelection || m_pWrtShell->IsStartOfDoc();
+ const bool bOther = !bSelection && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
+
+ {
+ const uno::Reference< uno::XComponentContext > xContext(
+ comphelper::getProcessComponentContext() );
+ SwHHCWrapper aWrap( this, xContext, nSourceLang, nTargetLang, pTargetFont,
+ nOptions, bIsInteractive,
+ bStart, bOther, bSelection );
+ aWrap.Convert();
+ }
+
+ m_pWrtShell->SetInsMode( bOldIns );
+ pVOpt->SetIdle( bOldIdle );
+ SpellContext(false);
+}
+
+// spellcheck and text conversion related stuff
+
+void SwView::SpellStart( SvxSpellArea eWhich,
+ bool bStartDone, bool bEndDone,
+ SwConversionArgs *pConvArgs )
+{
+ Reference< XLinguProperties > xProp = ::GetLinguPropertySet();
+ bool bIsWrapReverse = !pConvArgs && xProp.is() && xProp->getIsWrapReverse();
+
+ SwDocPositions eStart = SwDocPositions::Start;
+ SwDocPositions eEnd = SwDocPositions::End;
+ SwDocPositions eCurr = SwDocPositions::Curr;
+ switch ( eWhich )
+ {
+ case SvxSpellArea::Body:
+ if( bIsWrapReverse )
+ eCurr = SwDocPositions::End;
+ else
+ eCurr = SwDocPositions::Start;
+ break;
+ case SvxSpellArea::BodyEnd:
+ if( bIsWrapReverse )
+ {
+ if( bStartDone )
+ eStart = SwDocPositions::Curr;
+ eCurr = SwDocPositions::End;
+ }
+ else if( bStartDone )
+ eCurr = SwDocPositions::Start;
+ break;
+ case SvxSpellArea::BodyStart:
+ if( !bIsWrapReverse )
+ {
+ if( bEndDone )
+ eEnd = SwDocPositions::Curr;
+ eCurr = SwDocPositions::Start;
+ }
+ else if( bEndDone )
+ eCurr = SwDocPositions::End;
+ break;
+ case SvxSpellArea::Other:
+ if( bIsWrapReverse )
+ {
+ eStart = SwDocPositions::OtherStart;
+ eEnd = SwDocPositions::OtherEnd;
+ eCurr = SwDocPositions::OtherEnd;
+ }
+ else
+ {
+ eStart = SwDocPositions::OtherStart;
+ eEnd = SwDocPositions::OtherEnd;
+ eCurr = SwDocPositions::OtherStart;
+ }
+ break;
+ default:
+ OSL_ENSURE( false, "SpellStart with unknown Area" );
+ }
+ m_pWrtShell->SpellStart( eStart, eEnd, eCurr, pConvArgs );
+}
+
+// Error message while Spelling
+
+// The passed pointer nlang is itself the value
+void SwView::SpellError(LanguageType eLang)
+{
+ int nPend = 0;
+
+ if ( m_pWrtShell->ActionPend() )
+ {
+ m_pWrtShell->Push();
+ m_pWrtShell->ClearMark();
+ do
+ {
+ m_pWrtShell->EndAction();
+ ++nPend;
+ }
+ while( m_pWrtShell->ActionPend() );
+ }
+ OUString aErr(SvtLanguageTable::GetLanguageString( eLang ) );
+
+ SwEditWin &rEditWin = GetEditWin();
+ int nWaitCnt = 0;
+ while( rEditWin.IsWait() )
+ {
+ rEditWin.LeaveWait();
+ ++nWaitCnt;
+ }
+ if ( LANGUAGE_NONE == eLang )
+ ErrorHandler::HandleError( ERRCODE_SVX_LINGU_NOLANGUAGE );
+ else
+ ErrorHandler::HandleError( ErrCodeMsg( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
+
+ while( nWaitCnt )
+ {
+ rEditWin.EnterWait();
+ --nWaitCnt;
+ }
+
+ if ( nPend )
+ {
+ while( nPend-- )
+ m_pWrtShell->StartAction();
+ m_pWrtShell->Combine();
+ }
+}
+
+// Finish spelling and restore cursor
+
+void SwView::SpellEnd( SwConversionArgs const *pConvArgs )
+{
+ m_pWrtShell->SpellEnd( pConvArgs );
+ if( m_pWrtShell->IsExtMode() )
+ m_pWrtShell->SetMark();
+}
+
+void SwView::HyphStart( SvxSpellArea eWhich )
+{
+ switch ( eWhich )
+ {
+ case SvxSpellArea::Body:
+ m_pWrtShell->HyphStart( SwDocPositions::Start, SwDocPositions::End );
+ break;
+ case SvxSpellArea::BodyEnd:
+ m_pWrtShell->HyphStart( SwDocPositions::Curr, SwDocPositions::End );
+ break;
+ case SvxSpellArea::BodyStart:
+ m_pWrtShell->HyphStart( SwDocPositions::Start, SwDocPositions::Curr );
+ break;
+ case SvxSpellArea::Other:
+ m_pWrtShell->HyphStart( SwDocPositions::OtherStart, SwDocPositions::OtherEnd );
+ break;
+ default:
+ OSL_ENSURE( false, "HyphStart with unknown Area" );
+ }
+}
+
+// Interactive separation
+
+void SwView::HyphenateDocument()
+{
+ // do not hyphenate if interactive hyphenation is active elsewhere
+ if (SwEditShell::HasHyphIter())
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok, SwResId(STR_MULT_INTERACT_HYPH_WARN)));
+ xBox->set_title(SwResId(STR_HYPH_TITLE));
+ xBox->run();
+ return;
+ }
+
+ SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, OUString(), m_pEditWin->GetFrameWeld(),
+ RID_SVXERRCTX, SvxResLocale() );
+
+ Reference< XHyphenator > xHyph( ::GetHyphenator() );
+ if (!xHyph.is())
+ {
+ ErrorHandler::HandleError( ERRCODE_SVX_LINGU_LINGUNOTEXISTS );
+ return;
+ }
+
+ if (m_pWrtShell->GetSelectionType() & (SelectionType::DrawObjectEditMode|SelectionType::DrawObject))
+ {
+ // Hyphenation in a Draw object
+ HyphenateDrawText();
+ }
+ else
+ {
+ SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
+ bool bOldIdle = pVOpt->IsIdle();
+ pVOpt->SetIdle( false );
+
+ Reference< XLinguProperties > xProp( ::GetLinguPropertySet() );
+
+ m_pWrtShell->StartUndo(SwUndoId::INSATTR); // valid later
+
+ bool bHyphSpecial = xProp.is() && xProp->getIsHyphSpecial();
+ bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
+ m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
+ bool bOther = m_pWrtShell->HasOtherCnt() && bHyphSpecial && !bSelection;
+ bool bStart = bSelection || ( !bOther && m_pWrtShell->IsStartOfDoc() );
+ bool bStop = false;
+ if( !bOther && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY) && !bSelection )
+ // turned on no special area
+ {
+ // I want also in special areas hyphenation
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ SwResId(STR_QUERY_SPECIAL_FORCED)));
+ if (xBox->run() == RET_YES)
+ {
+ bOther = true;
+ if (xProp.is())
+ {
+ xProp->setIsHyphSpecial( true );
+ }
+ }
+ else
+ bStop = true; // No hyphenation
+ }
+
+ if( !bStop )
+ {
+ SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
+ aWrap.SpellDocument();
+ m_pWrtShell->EndUndo(SwUndoId::INSATTR);
+ }
+ pVOpt->SetIdle( bOldIdle );
+ }
+}
+
+bool SwView::IsValidSelectionForThesaurus() const
+{
+ // must not be a multi-selection, and if it is a selection it needs
+ // to be within a single paragraph
+
+ const bool bMultiSel = m_pWrtShell->GetCursor()->IsMultiSelection();
+ const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
+ return !bMultiSel && (!bSelection || m_pWrtShell->IsSelOnePara() );
+}
+
+OUString SwView::GetThesaurusLookUpText( bool bSelection ) const
+{
+ return bSelection ? m_pWrtShell->GetSelText() : m_pWrtShell->GetCurWord();
+}
+
+void SwView::InsertThesaurusSynonym( const OUString &rSynonmText, const OUString &rLookUpText, bool bSelection )
+{
+ bool bOldIns = m_pWrtShell->IsInsMode();
+ m_pWrtShell->SetInsMode();
+
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->StartUndo(SwUndoId::DELETE);
+
+ if( !bSelection )
+ {
+ if(m_pWrtShell->IsEndWrd())
+ m_pWrtShell->Left(SwCursorSkipMode::Cells, false, 1, false );
+
+ m_pWrtShell->SelWrd();
+
+ // make sure the selection build later from the data below does not
+ // include "in word" character to the left and right in order to
+ // preserve those. Therefore count those "in words" in order to modify
+ // the selection accordingly.
+ const sal_Unicode* pChar = rLookUpText.getStr();
+ sal_Int32 nLeft = 0;
+ while (*pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = rLookUpText.getLength() ? rLookUpText.getStr() + rLookUpText.getLength() - 1 : nullptr;
+ sal_Int32 nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ // adjust existing selection
+ SwPaM *pCursor = m_pWrtShell->GetCursor();
+ pCursor->GetPoint()->AdjustContent(-nRight);
+ pCursor->GetMark()->AdjustContent(nLeft);
+ }
+
+ m_pWrtShell->Insert( rSynonmText );
+
+ m_pWrtShell->EndUndo(SwUndoId::DELETE);
+ m_pWrtShell->EndAllAction();
+
+ m_pWrtShell->SetInsMode( bOldIns );
+}
+
+// Start thesaurus
+
+void SwView::StartThesaurus()
+{
+ if (!IsValidSelectionForThesaurus())
+ return;
+
+ SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, OUString(), m_pEditWin->GetFrameWeld(),
+ RID_SVXERRCTX, SvxResLocale() );
+
+ // Determine language
+ LanguageType eLang = m_pWrtShell->GetCurLang();
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = GetAppLanguage();
+
+ if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
+ {
+ SpellError( LANGUAGE_NONE );
+ return;
+ }
+
+ SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
+ const bool bOldIdle = pVOpt->IsIdle();
+ pVOpt->SetIdle( false );
+ comphelper::ScopeGuard guard([&]() { pVOpt->SetIdle(bOldIdle); }); // restore when leaving scope
+
+ // get initial LookUp text
+ const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
+ OUString aTmp = GetThesaurusLookUpText( bSelection );
+
+ Reference< XThesaurus > xThes( ::GetThesaurus() );
+
+ if ( !xThes.is() || !xThes->hasLocale( LanguageTag::convertToLocale( eLang ) ) )
+ SpellError( eLang );
+ else
+ {
+ VclPtr<AbstractThesaurusDialog> pDlg;
+ // create dialog
+ { //Scope for SwWait-Object
+ SwWait aWait( *GetDocShell(), true );
+ // load library with dialog only on demand ...
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ pDlg.reset(pFact->CreateThesaurusDialog(GetEditWin().GetFrameWeld(), xThes, aTmp, eLang));
+ }
+
+ if (pDlg)
+ {
+ guard.dismiss(); // ignore, we'll call SetIdle() explicitly after the dialog ends
+
+ pDlg->StartExecuteAsync([aTmp, bSelection, bOldIdle, pDlg, pVOpt, this](sal_Int32 nResult){
+ if (nResult == RET_OK )
+ InsertThesaurusSynonym(pDlg->GetWord(), aTmp, bSelection);
+
+ pVOpt->SetIdle(bOldIdle);
+ pDlg->disposeOnce();
+ });
+ }
+ }
+}
+
+// Offer online suggestions
+
+namespace {
+
+//!! Start of extra code for context menu modifying extensions
+struct ExecuteInfo
+{
+ uno::Reference< frame::XDispatch > xDispatch;
+ util::URL aTargetURL;
+ uno::Sequence< PropertyValue > aArgs;
+};
+
+class AsyncExecute
+{
+public:
+ DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, void );
+};
+
+}
+
+IMPL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, p, void )
+{
+ ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
+ SolarMutexReleaser aReleaser;
+ try
+ {
+ // Asynchronous execution as this can lead to our own destruction!
+ // Framework can recycle our current frame and the layout manager disposes all user interface
+ // elements if a component gets detached from its frame!
+ pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
+ }
+ catch (const Exception&)
+ {
+ }
+
+ delete pExecuteInfo;
+}
+//!! End of extra code for context menu modifying extensions
+
+bool SwView::ExecSpellPopup(const Point& rPt)
+{
+ bool bRet = false;
+ const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
+ if( pVOpt->IsOnlineSpell() &&
+ !m_pWrtShell->IsSelection())
+ {
+ if (m_pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
+ bRet = ExecDrwTextSpellPopup(rPt);
+ else if (!m_pWrtShell->IsSelFrameMode())
+ {
+ const bool bOldViewLock = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ if (!comphelper::LibreOfficeKit::isActive())
+ m_pWrtShell->Push();
+ SwRect aToFill;
+
+ SwCursorShell *pCursorShell = m_pWrtShell.get();
+ SwPaM *pCursor = pCursorShell->GetCursor();
+ SwPosition aPoint(*pCursor->GetPoint());
+ const SwTextNode *pNode = aPoint.GetNode().GetTextNode();
+
+ // Spell-check in case the idle jobs haven't had a chance to kick in.
+ // This makes it possible to suggest spelling corrections for
+ // wrong words independent of the spell-checking idle job.
+ if (pNode && pNode->IsWrongDirty() &&
+ !pCursorShell->IsTableMode() &&
+ !pCursor->HasMark() && !pCursor->IsMultiSelection())
+ {
+ std::pair<Point, bool> const tmp(rPt, false);
+ SwContentFrame *const pContentFrame = pCursor->GetPointContentNode()->getLayoutFrame(
+ pCursorShell->GetLayout(),
+ &aPoint, &tmp);
+ if (pContentFrame)
+ {
+ SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(
+ *pCursor->GetPointContentNode()->GetTextNode(), 0));
+ if (aRepaint.HasArea())
+ m_pWrtShell->InvalidateWindows(aRepaint);
+ }
+ }
+
+ // decide which variant of the context menu to use...
+ // if neither spell checking nor grammar checking provides suggestions use the
+ // default context menu.
+ bool bUseGrammarContext = false;
+ Reference< XSpellAlternatives > xAlt( m_pWrtShell->GetCorrection(&rPt, aToFill) );
+ ProofreadingResult aGrammarCheckRes;
+ sal_Int32 nErrorInResult = -1;
+ uno::Sequence< OUString > aSuggestions;
+ bool bCorrectionRes = false;
+ if (!xAlt.is() || !xAlt->getAlternatives().hasElements())
+ {
+ sal_Int32 nErrorPosInText = -1;
+ bCorrectionRes = m_pWrtShell->GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, &rPt, aToFill );
+ OUString aMessageText;
+ if (nErrorInResult >= 0)
+ aMessageText = aGrammarCheckRes.aErrors[ nErrorInResult ].aShortComment;
+ // we like to use the grammar checking context menu if we either get
+ // some suggestions or at least a comment about the error found...
+ bUseGrammarContext = bCorrectionRes &&
+ (aSuggestions.hasElements() || !aMessageText.isEmpty());
+ }
+
+ // open respective context menu for spell check or grammar errors with correction suggestions...
+ if ((!bUseGrammarContext && xAlt.is()) ||
+ (bUseGrammarContext && bCorrectionRes && aGrammarCheckRes.aErrors.hasElements()))
+ {
+ // get paragraph text
+ OUString aParaText;
+ if (pNode)
+ {
+ pCursorShell->Push();
+ if (!pCursorShell->IsSttPara())
+ {
+ pCursorShell->MovePara(GoCurrPara, fnParaStart);
+ }
+ pCursorShell->SetMark();
+ if (!pCursorShell->IsEndPara())
+ {
+ pCursorShell->MovePara(GoCurrPara, fnParaEnd);
+ }
+ aParaText = pCursorShell->GetSelText();
+ pCursorShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ }
+ else
+ {
+ OSL_FAIL("text node expected but not found" );
+ }
+
+ bRet = true;
+ m_pWrtShell->SttSelect();
+ std::unique_ptr<SwSpellPopup> xPopup(bUseGrammarContext ?
+ new SwSpellPopup(m_pWrtShell.get(), aGrammarCheckRes, nErrorInResult, aSuggestions, aParaText) :
+ new SwSpellPopup(m_pWrtShell.get(), xAlt, aParaText));
+ ui::ContextMenuExecuteEvent aEvent;
+ const Point aPixPos = GetEditWin().LogicToPixel( rPt );
+
+ aEvent.SourceWindow = VCLUnoHelper::GetInterface( m_pEditWin );
+ aEvent.ExecutePosition.X = aPixPos.X();
+ aEvent.ExecutePosition.Y = aPixPos.Y();
+ rtl::Reference<VCLXPopupMenu> xMenu;
+
+ OUString sMenuName = bUseGrammarContext ?
+ OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu");
+ rtl::Reference<VCLXPopupMenu> xMenuInterface = xPopup->CreateMenuInterface();
+ if (TryContextMenuInterception(xMenuInterface, sMenuName, xMenu, aEvent))
+ {
+ //! happy hacking for context menu modifying extensions of this
+ //! 'custom made' menu... *sigh* (code copied from sfx2 and framework)
+ if (xMenu.is())
+ {
+ css::uno::Reference<css::awt::XWindowPeer> xParent(aEvent.SourceWindow, css::uno::UNO_QUERY);
+ const sal_uInt16 nId = xMenu->execute(xParent, css::awt::Rectangle(aPixPos.X(), aPixPos.Y(), 1, 1),
+ css::awt::PopupMenuDirection::EXECUTE_DOWN);
+ OUString aCommand = xMenu->getCommand(nId);
+ if (aCommand.isEmpty() )
+ {
+ if (!ExecuteMenuCommand(xMenu, GetViewFrame(), nId))
+ xPopup->Execute(nId);
+ }
+ else
+ {
+ SfxViewFrame& rSfxViewFrame = GetViewFrame();
+ uno::Reference<frame::XFrame> xFrame = rSfxViewFrame.GetFrame().GetFrameInterface();
+ css::util::URL aURL;
+ uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
+
+ try
+ {
+ uno::Reference< frame::XDispatch > xDispatch;
+ uno::Reference< util::XURLTransformer > xURLTransformer = util::URLTransformer::create(comphelper::getProcessComponentContext());
+
+ aURL.Complete = aCommand;
+ xURLTransformer->parseStrict(aURL);
+ uno::Sequence< beans::PropertyValue > aArgs;
+ xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
+
+ if (xDispatch.is())
+ {
+ // Execute dispatch asynchronously
+ ExecuteInfo* pExecuteInfo = new ExecuteInfo;
+ pExecuteInfo->xDispatch = xDispatch;
+ pExecuteInfo->aTargetURL = aURL;
+ pExecuteInfo->aArgs = aArgs;
+ Application::PostUserEvent( LINK(nullptr, AsyncExecute , ExecuteHdl_Impl), pExecuteInfo );
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+ else
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (SfxViewShell* pViewShell = SfxViewShell::Current())
+ {
+ boost::property_tree::ptree aMenu = SfxDispatcher::fillPopupMenu(xMenuInterface);
+ boost::property_tree::ptree aRoot;
+ aRoot.add_child("menu", aMenu);
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aRoot, true);
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str()));
+ }
+ }
+ else
+ {
+ xPopup->Execute(aToFill.SVRect(), m_pEditWin);
+ }
+ }
+ }
+ }
+
+ if (!comphelper::LibreOfficeKit::isActive())
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->LockView( bOldViewLock );
+ }
+ }
+ return bRet;
+}
+
+/** Function: ExecSmartTagPopup
+
+ This function shows the popup menu for smarttag
+ actions.
+*/
+void SwView::ExecSmartTagPopup( const Point& rPt )
+{
+ const bool bOldViewLock = m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->Push();
+
+ css::uno::Sequence< css::uno::Any > aArgs{
+ css::uno::Any(comphelper::makePropertyValue( "Frame", GetDispatcher().GetFrame()->GetFrame().GetFrameInterface() )),
+ css::uno::Any(comphelper::makePropertyValue( "CommandURL", OUString( ".uno:OpenSmartTagMenuOnCursor" ) ))
+ };
+
+ css::uno::Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
+ css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.svx.SmartTagMenuController", aArgs, xContext ), css::uno::UNO_QUERY );
+
+ css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.awt.PopupMenu", xContext ), css::uno::UNO_QUERY );
+
+ if ( xPopupController.is() && xPopupMenu.is() )
+ {
+ xPopupController->setPopupMenu( xPopupMenu );
+
+ SwRect aToFill;
+ m_pWrtShell->GetSmartTagRect( rPt, aToFill );
+ m_pWrtShell->SttSelect();
+
+ if ( aToFill.HasArea() )
+ xPopupMenu->execute( m_pEditWin->GetComponentInterface(),
+ VCLUnoHelper::ConvertToAWTRect( m_pEditWin->LogicToPixel( aToFill.SVRect() ) ), css::awt::PopupMenuDirection::EXECUTE_DOWN );
+
+ css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->LockView( bOldViewLock );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewmdi.cxx b/sw/source/uibase/uiview/viewmdi.cxx
new file mode 100644
index 0000000000..f07c25e2df
--- /dev/null
+++ b/sw/source/uibase/uiview/viewmdi.cxx
@@ -0,0 +1,791 @@
+/* -*- 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 <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/ruler.hxx>
+#include <editeng/lrspitem.hxx>
+#include <o3tl/safeint.hxx>
+#include <svl/srchitem.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/request.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <frmatr.hxx>
+#include <edtwin.hxx>
+#include <pagedesc.hxx>
+#include <IMark.hxx>
+#include <fldbas.hxx>
+#include <workctrl.hxx>
+#include <usrpref.hxx>
+#include <scroll.hxx>
+#include <wview.hxx>
+
+#include <cmdid.h>
+
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+
+#include <svx/srchdlg.hxx>
+#include <svx/svdview.hxx>
+
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+sal_uInt16 SwView::s_nMoveType = NID_PGE;
+sal_Int32 SwView::s_nActMark = 0;
+
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+void collectUIInformation(const OUString& aFactor)
+{
+ EventDescription aDescription;
+ aDescription.aID = "writer_edit";
+ aDescription.aParameters = {{"ZOOM", aFactor}};
+ aDescription.aAction = "SET";
+ aDescription.aKeyWord = "SwEditWinUIObject";
+ aDescription.aParent = "MainWindow";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+void SwView::SetZoom( SvxZoomType eZoomType, short nFactor, bool bViewOnly )
+{
+ bool const bCursorIsVisible(m_pWrtShell->IsCursorVisible());
+ SetZoom_( GetEditWin().GetOutputSizePixel(), eZoomType, nFactor, bViewOnly );
+ // fdo#40465 force the cursor to stay in view whilst zooming
+ if (bCursorIsVisible)
+ m_pWrtShell->ShowCursor();
+
+ Invalidate(SID_ZOOM_IN);
+ Invalidate(SID_ZOOM_OUT);
+
+ collectUIInformation(OUString::number(nFactor));
+}
+
+void SwView::SetZoom_( const Size &rEditSize, SvxZoomType eZoomType,
+ short nFactor, bool bViewOnly )
+{
+ bool bUnLockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->LockPaint(LockPaintReason::SetZoom);
+
+ { // start of SwActContext scope
+ SwActContext aActContext(m_pWrtShell.get());
+
+ tools::Long nFac = nFactor;
+
+ const bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr;
+ SwMasterUsrPref *pUsrPref = const_cast<SwMasterUsrPref*>(SW_MOD()->GetUsrPref(bWeb));
+
+ const SwPageDesc &rDesc = m_pWrtShell->GetPageDesc( m_pWrtShell->GetCurPageDesc() );
+ const SvxLRSpaceItem &rLRSpace = rDesc.GetMaster().GetLRSpace();
+ const SwViewOption *pOpt = m_pWrtShell->GetViewOptions();
+ tools::Long lLeftMargin = 0;
+
+ if( eZoomType != SvxZoomType::PERCENT )
+ {
+ const bool bAutomaticViewLayout = 0 == pOpt->GetViewLayoutColumns();
+
+ const SwRect aPageRect( m_pWrtShell->GetAnyCurRect( CurRectType::PageCalc ) );
+ const SwRect aRootRect( m_pWrtShell->GetAnyCurRect( CurRectType::PagesArea ) );
+ Size aPageSize( aPageRect.SSize() );
+ Size aRootSize( aRootRect.SSize() );
+
+ //mod #i6193# added sidebar width
+ SwPostItMgr* pPostItMgr = GetPostItMgr();
+ if (pPostItMgr->HasNotes() && pPostItMgr->ShowNotes())
+ aPageSize.AdjustWidth(pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() );
+
+ const MapMode aTmpMap( MapUnit::MapTwip );
+ const Size aWindowSize( GetEditWin().PixelToLogic( rEditSize, aTmpMap ) );
+
+ if( SvxZoomType::OPTIMAL == eZoomType )
+ {
+ // unclear if this is useful for OPTIMAL, or completely useless?
+ if( UseOnPage::Mirror == rDesc.GetUseOn() ) // mirrored pages
+ {
+ const SvxLRSpaceItem &rLeftLRSpace = rDesc.GetLeft().GetLRSpace();
+ aPageSize.AdjustWidth(std::abs( rLeftLRSpace.GetLeft() - rLRSpace.GetLeft() ) );
+ }
+
+ if (!pPostItMgr->HasNotes() || !pPostItMgr->ShowNotes())
+ aPageSize.AdjustWidth( -( rLRSpace.GetLeft() + rLRSpace.GetRight() + nLeftOfst * 2 ) );
+ lLeftMargin = rLRSpace.GetLeft() + DOCUMENTBORDER + nLeftOfst;
+ nFac = aWindowSize.Width() * 100 / aPageSize.Width();
+ }
+ else if(SvxZoomType::WHOLEPAGE == eZoomType || SvxZoomType::PAGEWIDTH == eZoomType )
+ {
+ const tools::Long nOf = DOCUMENTBORDER * 2;
+ tools::Long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width();
+ nTmpWidth += nOf;
+ aPageSize.AdjustHeight(nOf );
+ nFac = aWindowSize.Width() * 100 / nTmpWidth;
+
+ if ( SvxZoomType::WHOLEPAGE == eZoomType )
+ {
+ tools::Long nVisPercent = aWindowSize.Height() * 100 / aPageSize.Height();
+ nFac = std::min( nFac, nVisPercent );
+ }
+ }
+ else
+ {
+ const tools::Long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width();
+ nFac = aWindowSize.Width() * 100 / nTmpWidth;
+ }
+ }
+
+ nFac = std::max( tools::Long( MINZOOM ), nFac );
+ const sal_uInt16 nZoomFac = o3tl::narrowing<sal_uInt16>(nFac);
+
+ SwViewOption aOpt( *pOpt );
+ if ( !GetViewFrame().GetFrame().IsInPlace() )
+ {
+ //Update MasterUsrPrefs and after that update the ViewOptions of the current View.
+ if ( !bViewOnly &&
+ (nZoomFac != pUsrPref->GetZoom() ||
+ eZoomType != pUsrPref->GetZoomType()) )
+ {
+ pUsrPref->SetZoom(nZoomFac);
+ pUsrPref->SetZoomType(eZoomType);
+ SW_MOD()->ApplyUsrPref(*pUsrPref, nullptr);
+ pUsrPref->SetModified();
+ }
+ if ( pOpt->GetZoom() != nZoomFac )
+ {
+ aOpt.SetZoom(nZoomFac);
+ aOpt.SetReadonly(pOpt->IsReadonly());
+ m_pWrtShell->ApplyViewOptions( aOpt );
+ }
+ if ( eZoomType != SvxZoomType::PERCENT )
+ {
+ Point aPos;
+
+ if ( eZoomType == SvxZoomType::WHOLEPAGE )
+ aPos.setY( m_pWrtShell->GetAnyCurRect(CurRectType::Page).Top() - DOCUMENTBORDER );
+ else
+ {
+ // Make sure that the cursor is in the visible range, so that
+ // the scrolling will be performed only once.
+ aPos.setX( lLeftMargin );
+ const SwRect &rCharRect = m_pWrtShell->GetCharRect();
+ if ( rCharRect.Top() > GetVisArea().Bottom() ||
+ rCharRect.Bottom() < aPos.Y() )
+ aPos.setY( rCharRect.Top() - rCharRect.Height() );
+ else
+ aPos.setY( GetVisArea().Top() );
+ }
+ SetVisArea( aPos );
+ }
+ // Compromise solution - Under certain circumstances SetZoom is called
+ // in CalcVisAreas again and thus be set wrong values.
+ const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions())->SetZoomType( eZoomType );
+ CalcVisArea( rEditSize ); // for the recalculation of the viewable area
+ }
+ else if ( nZoomFac != pOpt->GetZoom() )
+ {
+ aOpt.SetZoom( nZoomFac );
+ m_pWrtShell->ApplyViewOptions( aOpt );
+ }
+
+ const Fraction aFrac( nFac, 100 );
+ m_pVRuler->SetZoom( aFrac );
+ m_pVRuler->ForceUpdate();
+ m_pHRuler->SetZoom( aFrac );
+ m_pHRuler->ForceUpdate();
+ const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions())->SetZoomType( eZoomType );
+ } // end of SwActContext scope
+
+ m_pWrtShell->UnlockPaint();
+ if( bUnLockView )
+ m_pWrtShell->LockView( false );
+}
+
+void SwView::SetViewLayout( sal_uInt16 nColumns, bool bBookMode, bool bViewOnly )
+{
+ const bool bUnLockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->LockPaint(LockPaintReason::ViewLayout);
+
+ {
+
+ SwActContext aActContext(m_pWrtShell.get());
+
+ if ( !GetViewFrame().GetFrame().IsInPlace() && !bViewOnly )
+ {
+ const bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr;
+ SwMasterUsrPref *pUsrPref = const_cast<SwMasterUsrPref*>(SW_MOD()->GetUsrPref(bWeb));
+
+ // Update MasterUsrPrefs and after that update the ViewOptions of the current View.
+ if ( nColumns != pUsrPref->GetViewLayoutColumns() ||
+ bBookMode != pUsrPref->IsViewLayoutBookMode() )
+ {
+ pUsrPref->SetViewLayoutColumns(nColumns);
+ pUsrPref->SetViewLayoutBookMode(bBookMode);
+ SW_MOD()->ApplyUsrPref(*pUsrPref, nullptr);
+ pUsrPref->SetModified();
+ }
+ }
+
+ const SwViewOption *pOpt = m_pWrtShell->GetViewOptions();
+
+ if ( nColumns != pOpt->GetViewLayoutColumns() ||
+ bBookMode != pOpt->IsViewLayoutBookMode() )
+ {
+ SwViewOption aOpt( *pOpt );
+ aOpt.SetViewLayoutColumns( nColumns );
+ aOpt.SetViewLayoutBookMode( bBookMode );
+ m_pWrtShell->ApplyViewOptions( aOpt );
+ }
+
+ m_pVRuler->ForceUpdate();
+ m_pHRuler->ForceUpdate();
+
+ }
+
+ m_pWrtShell->UnlockPaint();
+ if( bUnLockView )
+ m_pWrtShell->LockView( false );
+
+ SfxBindings& rBnd = GetViewFrame().GetBindings();
+ rBnd.Invalidate( SID_ATTR_VIEWLAYOUT );
+ rBnd.Invalidate( SID_ATTR_ZOOMSLIDER);
+}
+
+// Scrollbar - Handler
+
+IMPL_LINK( SwView, WindowChildEventListener, VclWindowEvent&, rEvent, void )
+{
+ OSL_ENSURE( rEvent.GetWindow(), "Window???" );
+ vcl::Window* pChildWin = static_cast< vcl::Window* >( rEvent.GetData() );
+
+ switch ( rEvent.GetId() )
+ {
+ case VclEventId::WindowHide:
+ if( pChildWin == m_pHScrollbar )
+ ShowHScrollbar( false );
+ else if( pChildWin == m_pVScrollbar )
+ ShowVScrollbar( false );
+ break;
+ case VclEventId::WindowShow:
+ if( pChildWin == m_pHScrollbar )
+ ShowHScrollbar( true );
+ else if( pChildWin == m_pVScrollbar )
+ ShowVScrollbar( true );
+ break;
+ default: break;
+ }
+}
+
+void SwView::CreateScrollbar( bool bHori )
+{
+ vcl::Window *pMDI = &GetViewFrame().GetWindow();
+ VclPtr<SwScrollbar>& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar;
+
+ assert(!ppScrollbar); //check beforehand!
+
+ ppScrollbar = VclPtr<SwScrollbar>::Create( pMDI, bHori );
+ UpdateScrollbars();
+ if(bHori)
+ ppScrollbar->SetScrollHdl( LINK( this, SwView, HoriScrollHdl ));
+ else
+ ppScrollbar->SetScrollHdl( LINK( this, SwView, VertScrollHdl ));
+
+ if(GetWindow())
+ InvalidateBorder();
+
+ if (!m_bShowAtResize)
+ ppScrollbar->ExtendedShow();
+}
+
+IMPL_LINK( SwView, MoveNavigationHdl, void*, p, void )
+{
+ bool* pbNext = static_cast<bool*>(p);
+ if ( !pbNext )
+ return;
+ const bool bNext = *pbNext;
+ SwWrtShell& rSh = GetWrtShell();
+ if ( NID_SRCH_REP != s_nMoveType)
+ {
+ if ( rSh.GetDrawView()->IsTextEdit() )
+ rSh.EndTextEdit();
+ if ( IsDrawMode() )
+ LeaveDrawCreate();
+ }
+ if ( NID_POSTIT != s_nMoveType && m_pPostItMgr )
+ {
+ sw::annotation::SwAnnotationWin* pActiveSidebarWin = m_pPostItMgr->GetActiveSidebarWin();
+ if (pActiveSidebarWin)
+ pActiveSidebarWin->SwitchToFieldPos();
+ }
+ if (NID_RECENCY != s_nMoveType && NID_PGE != s_nMoveType && NID_SRCH_REP != s_nMoveType)
+ rSh.addCurrentPosition();
+ switch( s_nMoveType )
+ {
+ case NID_PGE:
+ {
+ tools::Long nYPos;
+ SwVisiblePageNumbers aVisiblePageNumbers;
+ rSh.GetFirstLastVisPageNumbers(aVisiblePageNumbers);
+ if ((bNext && aVisiblePageNumbers.nLastPhy + 1 > rSh.GetPageCnt()) ||
+ (!bNext && aVisiblePageNumbers.nFirstPhy == 1))
+ {
+ nYPos = rSh.GetPagePos(bNext ? 1 : rSh.GetPageCnt()).Y();
+ SvxSearchDialogWrapper::SetSearchLabel(bNext ? SearchLabel::EndWrapped :
+ SearchLabel::StartWrapped);
+ }
+ else
+ {
+ auto nPage = bNext ? aVisiblePageNumbers.nLastPhy + 1 :
+ aVisiblePageNumbers.nFirstPhy - 1;
+ nYPos = rSh.GetPagePos(nPage).Y();
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+ }
+ const Point aPt(GetVisArea().Left(), nYPos);
+ Point aAlPt(AlignToPixel(aPt));
+ // If there is a difference, has been truncated --> then add one pixel,
+ // so that no residue of the previous page is visible.
+ if(aPt.Y() != aAlPt.Y())
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic(Size(0, 1)).Height());
+ SetVisArea(aAlPt);
+ }
+ break;
+ case NID_TBL :
+ rSh.EnterStdMode();
+ if(bNext)
+ rSh.MoveTable(GotoNextTable, fnTableStart);
+ else
+ rSh.MoveTable(GotoPrevTable, fnTableStart);
+ break;
+ case NID_FRM :
+ case NID_GRF:
+ case NID_OLE:
+ {
+ GotoObjFlags eType = GotoObjFlags::FlyFrame;
+ if(s_nMoveType == NID_GRF)
+ eType = GotoObjFlags::FlyGrf;
+ else if(s_nMoveType == NID_OLE)
+ eType = GotoObjFlags::FlyOLE;
+ bool bSuccess = bNext ?
+ rSh.GotoNextFly(eType) :
+ rSh.GotoPrevFly(eType);
+ if(bSuccess)
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ }
+ break;
+ case NID_CTRL:
+ if (!rSh.GetView().IsDesignMode())
+ rSh.GetView().GetFormShell()->SetDesignMode(true);
+ [[fallthrough]];
+ case NID_DRW:
+ {
+ bool bSuccess = rSh.GotoObj(bNext,
+ s_nMoveType == NID_DRW ?
+ GotoObjFlags::DrawSimple :
+ GotoObjFlags::DrawControl);
+ if(bSuccess)
+ {
+ rSh.HideCursor();
+ rSh.EnterSelFrameMode();
+ }
+ }
+ break;
+ case NID_REG :
+ rSh.EnterStdMode();
+ if(bNext)
+ rSh.MoveRegion(GotoNextRegion, fnRegionStart);
+ else
+ rSh.MoveRegion(GotoPrevRegion, fnRegionStart);
+
+ break;
+ case NID_BKM :
+ rSh.EnterStdMode();
+ GetViewFrame().GetDispatcher()->Execute(bNext ?
+ FN_NEXT_BOOKMARK :
+ FN_PREV_BOOKMARK);
+ break;
+ case NID_FIELD:
+ {
+ rSh.EnterStdMode();
+ rSh.StartAction();
+ SearchLabel eSearchLabel = SearchLabel::Empty;
+ if (!rSh.MoveFieldType(nullptr, bNext, SwFieldIds::Unknown))
+ {
+ // no field found in the move direction
+ // wrap and try again
+ SwShellCursor* pCursor = rSh.GetCursor_();
+ SwCursorSaveState aSaveState(*pCursor);
+ rSh.SttEndDoc(bNext);
+ // document might have a field at the start of the document
+ SwField* pField = rSh.GetCurField();
+ if ((bNext && pField && pField->GetTypeId() != SwFieldTypesEnum::Postit) ||
+ rSh.MoveFieldType(nullptr, bNext, SwFieldIds::Unknown))
+ {
+ eSearchLabel = bNext ? SearchLabel::EndWrapped : SearchLabel::StartWrapped;
+ }
+ else
+ {
+ // no visible fields found
+ pCursor->RestoreSavePos();
+ eSearchLabel = SearchLabel::NavElementNotFound;
+ }
+ }
+ SvxSearchDialogWrapper::SetSearchLabel(eSearchLabel);
+ rSh.EndAction();
+ }
+ break;
+ case NID_FIELD_BYTYPE:
+ {
+ // see: SwFieldMgr::GoNextPrev
+ SwField* pCurField = rSh.GetCurField(true);
+ if (!pCurField)
+ break;
+ rSh.EnterStdMode();
+ SwFieldType* pTyp = nullptr;
+ const SwFieldTypesEnum nTypeId = pCurField->GetTypeId();
+ if (SwFieldTypesEnum::SetInput == nTypeId || SwFieldTypesEnum::UserInput == nTypeId)
+ pTyp = rSh.GetFieldType(0, SwFieldIds::Input);
+ else
+ pTyp = pCurField->GetTyp();
+ if (pTyp)
+ {
+ if (pTyp->Which() == SwFieldIds::Database)
+ rSh.MoveFieldType(nullptr, bNext, SwFieldIds::Database);
+ else
+ rSh.MoveFieldType(pTyp, bNext);
+ }
+ }
+ break;
+ case NID_OUTL:
+ rSh.EnterStdMode();
+ bNext ? rSh.GotoNextOutline() : rSh.GotoPrevOutline();
+ break;
+ case NID_SEL :
+ rSh.GoNextPrevCursorSetSearchLabel(bNext);
+ break;
+ case NID_FTN:
+ {
+ bool bFrameTypeFootnote(rSh.GetFrameType(nullptr, false) & FrameTypeFlags::FOOTNOTE);
+
+ if (bFrameTypeFootnote)
+ {
+ rSh.LockView(true);
+ rSh.GotoFootnoteAnchor();
+ }
+
+ rSh.EnterStdMode();
+ bNext ?
+ rSh.GotoNextFootnoteAnchor() :
+ rSh.GotoPrevFootnoteAnchor();
+
+ if (bFrameTypeFootnote)
+ {
+ rSh.LockView(false);
+ rSh.GotoFootnoteText();
+ }
+ }
+ break;
+ case NID_MARK:
+ {
+ // unselect
+ rSh.MoveCursor();
+ rSh.EnterStdMode();
+
+ // collect and sort navigator reminder names
+ IDocumentMarkAccess* const pMarkAccess = rSh.getIDocumentMarkAccess();
+ std::vector< OUString > vNavMarkNames;
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
+ ppMark != pMarkAccess->getAllMarksEnd();
+ ++ppMark)
+ {
+ if( IDocumentMarkAccess::GetType(**ppMark) == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER )
+ vNavMarkNames.push_back((*ppMark)->GetName());
+ }
+ std::sort(vNavMarkNames.begin(), vNavMarkNames.end());
+
+ // move
+ if(!vNavMarkNames.empty())
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+
+ if(bNext)
+ {
+ s_nActMark++;
+ if (s_nActMark >= MAX_MARKS || s_nActMark >= static_cast<sal_Int32>(vNavMarkNames.size()))
+ {
+ s_nActMark = 0;
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::ReminderEndWrapped );
+ }
+ }
+ else
+ {
+ s_nActMark--;
+ if (s_nActMark < 0 || o3tl::make_unsigned(s_nActMark) >= vNavMarkNames.size())
+ {
+ s_nActMark = vNavMarkNames.size()-1;
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::ReminderStartWrapped );
+ }
+ }
+ rSh.GotoMark(vNavMarkNames[s_nActMark]);
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ }
+ break;
+
+ case NID_POSTIT:
+ {
+ if (m_pPostItMgr->HasNotes())
+ {
+ rSh.EnterStdMode();
+ m_pPostItMgr->AssureStdModeAtShell();
+ m_pPostItMgr->SetActiveSidebarWin(nullptr);
+ GetEditWin().GrabFocus();
+ SwShellCursor* pCursor = rSh.GetCursor_();
+ SwCursorSaveState aSaveState(*pCursor);
+ SwFieldType* pFieldType = rSh.GetFieldType(0, SwFieldIds::Postit);
+ bool bWrapped = false;
+ bool bFound = false;
+ rSh.StartAction();
+ while (!bFound)
+ {
+ if (!rSh.MoveFieldType(pFieldType, bNext))
+ {
+ if (bWrapped)
+ break;
+ bWrapped = true;
+ rSh.SttEndDoc(bNext);
+ continue;
+ }
+ do
+ {
+ auto pAnnotationWin = m_pPostItMgr->GetAnnotationWin(
+ rSh.GetPostItFieldAtCursor());
+ if (pAnnotationWin && pAnnotationWin->IsVisible())
+ bFound = true;
+ } while (!bFound && rSh.MoveFieldType(pFieldType, bNext));
+ }
+ if (!bFound)
+ {
+ pCursor->RestoreSavePos();
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NavElementNotFound);
+ }
+ rSh.EndAction();
+ if (bFound)
+ {
+ GetViewFrame().GetDispatcher()->Execute(FN_POSTIT);
+ if (bWrapped)
+ SvxSearchDialogWrapper::SetSearchLabel(bNext ? SearchLabel::EndWrapped :
+ SearchLabel::StartWrapped);
+ else
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+ }
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NavElementNotFound);
+ }
+ break;
+
+ case NID_SRCH_REP:
+ if(s_pSrchItem)
+ {
+ bool bBackward = s_pSrchItem->GetBackward();
+ if (rSh.HasSelection() && bNext != rSh.IsCursorPtAtEnd())
+ rSh.SwapPam();
+ s_pSrchItem->SetBackward(!bNext);
+ SfxRequest aReq(FN_REPEAT_SEARCH, SfxCallMode::SLOT, GetPool());
+ ExecSearch(aReq);
+ s_pSrchItem->SetBackward(bBackward);
+ }
+ break;
+ case NID_INDEX_ENTRY:
+ rSh.GotoNxtPrvTOXMark(bNext);
+ break;
+
+ case NID_TABLE_FORMULA:
+ rSh.GotoNxtPrvTableFormula( bNext );
+ break;
+
+ case NID_TABLE_FORMULA_ERROR:
+ rSh.GotoNxtPrvTableFormula( bNext, true );
+ break;
+
+ case NID_RECENCY :
+ rSh.EnterStdMode();
+ bNext ? rSh.GetNavigationMgr().goForward() : rSh.GetNavigationMgr().goBack();
+ break;
+ }
+ if (NID_POSTIT != s_nMoveType)
+ m_pEditWin->GrabFocus();
+ delete pbNext;
+}
+
+void SwView::CreateTab()
+{
+ m_pHRuler->SetActive(GetFrame() && IsActive());
+
+ m_pHRuler->Show();
+ InvalidateBorder();
+}
+
+void SwView::KillTab()
+{
+ m_pHRuler->Hide();
+ InvalidateBorder();
+}
+
+void SwView::ChangeTabMetric( FieldUnit eUnit )
+{
+ if(m_pHRuler->GetUnit() != eUnit )
+ {
+ m_pHRuler->SetUnit( eUnit );
+ m_pHRuler->Invalidate();
+ }
+}
+
+void SwView::ChangeVRulerMetric( FieldUnit eUnit )
+{
+ if(m_pVRuler->GetUnit() != eUnit)
+ {
+ m_pVRuler->SetUnit( eUnit );
+ m_pVRuler->Invalidate();
+ }
+}
+
+void SwView::GetVRulerMetric(FieldUnit& eToFill) const
+{
+ eToFill = m_pVRuler->GetUnit();
+}
+
+void SwView::GetHRulerMetric(FieldUnit& eToFill) const
+{
+ eToFill = m_pHRuler->GetUnit();
+}
+
+void SwView::CreateVRuler()
+{
+ m_pHRuler->SetBorderPos( m_pVRuler->GetSizePixel().Width()-1 );
+
+ m_pVRuler->SetActive(GetFrame() && IsActive());
+ m_pVRuler->Show();
+ InvalidateBorder();
+}
+
+void SwView::KillVRuler()
+{
+ m_pVRuler->Hide();
+ m_pHRuler->SetBorderPos();
+ InvalidateBorder();
+}
+
+IMPL_LINK( SwView, ExecRulerClick, Ruler *, pRuler, void )
+{
+ OUString sDefPage;
+ TypedWhichId<SfxStringItem> nDefDlg = SID_PARA_DLG;
+ switch( pRuler->GetClickType() )
+ {
+ case RulerType::DontKnow:
+ case RulerType::Outside:
+ sDefPage="labelTP_BORDER";
+ break;
+ case RulerType::Indent:
+ sDefPage="labelTP_PARA_STD";
+ break;
+ case RulerType::Margin1:
+ case RulerType::Margin2:
+ nDefDlg= FN_FORMAT_PAGE_DLG;
+ sDefPage = "page";
+ break;
+ default:
+ sDefPage = "labelTP_TABULATOR";
+
+ }
+
+ SfxStringItem aDefPage(nDefDlg, sDefPage);
+ GetViewFrame().GetDispatcher()->ExecuteList(nDefDlg,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aDefPage });
+}
+
+sal_uInt16 SwView::GetMoveType()
+{
+ return s_nMoveType;
+}
+
+void SwView::SetMoveType(sal_uInt16 nSet)
+{
+ s_nMoveType = nSet;
+}
+
+void SwView::SetActMark(sal_Int32 nSet)
+{
+ s_nActMark = nSet;
+}
+
+void SwView::ShowHScrollbar(bool bShow)
+{
+ assert(m_pHScrollbar && "Scrollbar invalid");
+ m_pHScrollbar->ExtendedShow(bShow);
+}
+
+bool SwView::IsHScrollbarVisible()const
+{
+ assert(m_pHScrollbar && "Scrollbar invalid");
+ return m_pHScrollbar->IsScrollbarVisible(false) || m_pHScrollbar->IsAuto();
+}
+
+void SwView::ShowVScrollbar(bool bShow)
+{
+ assert(m_pVScrollbar && "Scrollbar invalid");
+ m_pVScrollbar->ExtendedShow(bShow);
+}
+
+bool SwView::IsVScrollbarVisible()const
+{
+ assert(m_pVScrollbar && "Scrollbar invalid");
+ return m_pVScrollbar->IsScrollbarVisible(false);
+}
+
+void SwView::EnableHScrollbar(bool bEnable)
+{
+ if (m_bHScrollbarEnabled != bEnable)
+ {
+ m_bHScrollbarEnabled = bEnable;
+ InvalidateBorder();
+ }
+}
+
+void SwView::EnableVScrollbar(bool bEnable)
+{
+ if (m_bVScrollbarEnabled != bEnable)
+ {
+ m_bVScrollbarEnabled = bEnable;
+ InvalidateBorder();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewport.cxx b/sw/source/uibase/uiview/viewport.cxx
new file mode 100644
index 0000000000..08d9b0c393
--- /dev/null
+++ b/sw/source/uibase/uiview/viewport.cxx
@@ -0,0 +1,1262 @@
+/* -*- 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 <vcl/commandevent.hxx>
+#include <vcl/help.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/syswin.hxx>
+
+#include <svx/ruler.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <docsh.hxx>
+#include <cmdid.h>
+#include <edtwin.hxx>
+#include <scroll.hxx>
+
+#include <PostItMgr.hxx>
+
+#include <basegfx/utils/zoomtools.hxx>
+#include <comphelper/lok.hxx>
+#include <vcl/weld.hxx>
+#include <tools/svborder.hxx>
+#include <osl/diagnose.h>
+
+#include "viewfunc.hxx"
+
+#include <FrameControlsManager.hxx>
+
+// The SetVisArea of the DocShell must not be called from InnerResizePixel.
+// But our adjustments must take place.
+static bool bProtectDocShellVisArea = false;
+
+static sal_uInt16 nPgNum = 0;
+
+bool SwView::IsDocumentBorder()
+{
+ if (GetDocShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
+ return true;
+
+ if (!m_pWrtShell)
+ return false;
+
+ return m_pWrtShell->GetViewOptions()->getBrowseMode() ||
+ SvxZoomType::PAGEWIDTH_NOBORDER == m_pWrtShell->GetViewOptions()->GetZoomType();
+}
+
+static tools::Long GetLeftMargin( SwView const &rView )
+{
+ SvxZoomType eType = rView.GetWrtShell().GetViewOptions()->GetZoomType();
+ tools::Long lRet = rView.GetWrtShell().GetAnyCurRect(CurRectType::PagePrt).Left();
+ return eType == SvxZoomType::PERCENT ? lRet + DOCUMENTBORDER :
+ eType == SvxZoomType::PAGEWIDTH || eType == SvxZoomType::PAGEWIDTH_NOBORDER ? 0 :
+ lRet + DOCUMENTBORDER + nLeftOfst;
+}
+
+static void lcl_GetPos(SwView const * pView,
+ Point& rPos,
+ const weld::Scrollbar& rScrollbar,
+ bool bHori,
+ bool bBorder)
+{
+ SwWrtShell &rSh = pView->GetWrtShell();
+ const Size aDocSz( rSh.GetDocSize() );
+
+ const tools::Long lBorder = bBorder ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+
+ const tools::Long lPos = rScrollbar.adjustment_get_value() + (bBorder ? DOCUMENTBORDER : 0);
+
+ tools::Long lDelta = lPos - (bHori ? rSh.VisArea().Pos().X() : rSh.VisArea().Pos().Y());
+
+ const tools::Long lSize = (bHori ? aDocSz.Width() : aDocSz.Height()) + lBorder;
+ // Should right or below are too much space,
+ // then they must be subtracted out of the VisArea!
+ tools::Long nTmp = pView->GetVisArea().Right()+lDelta;
+ if ( bHori && nTmp > lSize )
+ lDelta -= nTmp - lSize;
+ nTmp = pView->GetVisArea().Bottom()+lDelta;
+ if ( !bHori && nTmp > lSize )
+ lDelta -= nTmp - lSize;
+
+ bHori ? rPos.AdjustX(lDelta) : rPos.AdjustY(lDelta);
+ if ( bBorder && (bHori ? rPos.X() : rPos.Y()) < DOCUMENTBORDER )
+ bHori ? rPos.setX(DOCUMENTBORDER) : rPos.setY(DOCUMENTBORDER);
+}
+
+// Set zero ruler
+
+void SwView::InvalidateRulerPos()
+{
+ static sal_uInt16 aInval[] =
+ {
+ SID_ATTR_PARA_LRSPACE, SID_RULER_BORDERS, SID_RULER_PAGE_POS,
+ SID_RULER_LR_MIN_MAX, SID_ATTR_LONG_ULSPACE, SID_ATTR_LONG_LRSPACE,
+ SID_RULER_BORDER_DISTANCE,
+ SID_ATTR_PARA_LRSPACE_VERTICAL, SID_RULER_BORDERS_VERTICAL,
+ SID_RULER_TEXT_RIGHT_TO_LEFT,
+ SID_RULER_ROWS, SID_RULER_ROWS_VERTICAL, FN_STAT_PAGE,
+ 0
+ };
+
+ GetViewFrame().GetBindings().Invalidate(aInval);
+
+ assert(m_pHRuler && "Why is the ruler not there?");
+ m_pHRuler->ForceUpdate();
+ m_pVRuler->ForceUpdate();
+}
+
+// Limits the scrolling so far that only a quarter of the
+// screen can be scrolled up before the end of the document.
+
+tools::Long SwView::SetHScrollMax( tools::Long lMax )
+{
+ const tools::Long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+ const tools::Long lSize = GetDocSz().Width() + lBorder - m_aVisArea.GetWidth();
+
+ // At negative values the document is completely visible.
+ // In this case, no scrolling.
+ return std::clamp( lSize, tools::Long(0), lMax );
+}
+
+tools::Long SwView::SetVScrollMax( tools::Long lMax )
+{
+ const tools::Long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+ tools::Long lSize = GetDocSz().Height() + lBorder - m_aVisArea.GetHeight();
+ return std::clamp( lSize, tools::Long(0), lMax ); // see horizontal
+}
+
+Point SwView::AlignToPixel(const Point &rPt) const
+{
+ return GetEditWin().PixelToLogic( GetEditWin().LogicToPixel( rPt ) );
+}
+
+// Document size has changed.
+
+void SwView::DocSzChgd(const Size &rSz)
+{
+ m_aDocSz = rSz;
+
+ if( !m_pWrtShell || m_aVisArea.IsEmpty() ) // no shell -> no change
+ {
+ bDocSzUpdated = false;
+ return;
+ }
+
+ //If text has been deleted, it may be that the VisArea points behind the visible range.
+ tools::Rectangle aNewVisArea( m_aVisArea );
+ bool bModified = false;
+ SwTwips lGreenOffset = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2;
+ SwTwips lTmp = m_aDocSz.Width() + lGreenOffset;
+
+ if ( aNewVisArea.Right() >= lTmp )
+ {
+ lTmp = aNewVisArea.Right() - lTmp;
+ aNewVisArea.AdjustRight( -lTmp );
+ aNewVisArea.AdjustLeft( -lTmp );
+ bModified = true;
+ }
+
+ lTmp = m_aDocSz.Height() + lGreenOffset;
+ if ( aNewVisArea.Bottom() >= lTmp )
+ {
+ lTmp = aNewVisArea.Bottom() - lTmp;
+ aNewVisArea.AdjustBottom( -lTmp );
+ aNewVisArea.AdjustTop( -lTmp );
+ bModified = true;
+ }
+
+ if ( bModified )
+ SetVisArea( aNewVisArea, false );
+
+ if ( UpdateScrollbars() && !m_bInOuterResizePixel && !m_bInInnerResizePixel &&
+ !GetViewFrame().GetFrame().IsInPlace())
+ OuterResizePixel( Point(),
+ GetViewFrame().GetWindow().GetOutputSizePixel() );
+}
+
+// Set VisArea newly
+
+void SwView::SetVisArea( const tools::Rectangle &rRect, bool bUpdateScrollbar )
+{
+ Size aOldSz( m_aVisArea.GetSize() );
+ if (comphelper::LibreOfficeKit::isActive() && m_pWrtShell)
+ // If m_pWrtShell's visible area is the whole document, do the same here.
+ aOldSz = m_pWrtShell->VisArea().SSize();
+
+ if( rRect == m_aVisArea )
+ return;
+
+ const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+
+ // No negative position, no negative size
+ tools::Rectangle aLR = rRect;
+ if( aLR.Top() < lMin )
+ {
+ aLR.AdjustBottom(lMin - aLR.Top() );
+ aLR.SetTop( lMin );
+ }
+ if( aLR.Left() < lMin )
+ {
+ aLR.AdjustRight(lMin - aLR.Left() );
+ aLR.SetLeft( lMin );
+ }
+ if( aLR.Right() < 0 )
+ aLR.SetRight( 0 );
+ if( aLR.Bottom() < 0 )
+ aLR.SetBottom( 0 );
+
+ if( aLR == m_aVisArea )
+ return;
+
+ const Size aSize( aLR.GetSize() );
+ if( aSize.IsEmpty() )
+ return;
+
+ // Before the data can be changed, call an update if necessary. This
+ // ensures that adjacent Paints in document coordinates are converted
+ // correctly.
+ // As a precaution, we do this only when an action is running in the
+ // shell, because then it is not really drawn but the rectangles will
+ // be only marked (in document coordinates).
+ if ( m_pWrtShell && m_pWrtShell->ActionPend() )
+ m_pWrtShell->GetWin()->PaintImmediately();
+
+ m_aVisArea = aLR;
+
+ const bool bOuterResize = bUpdateScrollbar && UpdateScrollbars();
+
+ if ( m_pWrtShell )
+ {
+ m_pWrtShell->VisPortChgd( SwRect(m_aVisArea) );
+ if ( aOldSz != m_pWrtShell->VisArea().SSize() &&
+ ( std::abs(aOldSz.Width() - m_pWrtShell->VisArea().Width()) > 2 ||
+ std::abs(aOldSz.Height() - m_pWrtShell->VisArea().Height()) > 2 ) )
+ m_pWrtShell->InvalidateLayout( false );
+ }
+
+ if ( !bProtectDocShellVisArea )
+ {
+ // If the size of VisArea is unchanged, we extend the size of the VisArea
+ // InternalObject on. By that the transport of errors shall be avoided.
+ tools::Rectangle aVis( m_aVisArea );
+ if ( aVis.GetSize() == aOldSz )
+ aVis.SetSize( GetDocShell()->SfxObjectShell::GetVisArea(ASPECT_CONTENT).GetSize() );
+ // TODO/LATER: why casting?!
+ //GetDocShell()->SfxInPlaceObject::GetVisArea().GetSize() );
+
+ // With embedded always with modify...
+ // TODO/LATER: why casting?!
+ GetDocShell()->SfxObjectShell::SetVisArea( aVis );
+ /*
+ if ( GetDocShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
+ GetDocShell()->SfxInPlaceObject::SetVisArea( aVis );
+ else
+ GetDocShell()->SvEmbeddedObject::SetVisArea( aVis );*/
+ }
+
+ SfxViewShell::VisAreaChanged();
+
+ InvalidateRulerPos();
+
+ if ( bOuterResize && !m_bInOuterResizePixel && !m_bInInnerResizePixel)
+ OuterResizePixel( Point(),
+ GetViewFrame().GetWindow().GetOutputSizePixel() );
+}
+
+// Set Pos VisArea
+
+void SwView::SetVisArea( const Point &rPt, bool bUpdateScrollbar )
+{
+ // Align once, so brushes will be inserted correctly.
+ // This goes wrong in the BrowseView, because the entire document may
+ // not be visible. Since the content in frames is fitting exactly,
+ // align is not possible (better idea?!?!)
+ // (fix: Bild.de, 200%) It does not work completely without alignment
+ // Let's see how far we get with half BrushSize.
+ Point aPt = GetEditWin().LogicToPixel( rPt );
+#if HAVE_FEATURE_DESKTOP
+ const tools::Long nTmp = 8;
+ aPt.AdjustX( -(aPt.X() % nTmp) );
+ aPt.AdjustY( -(aPt.Y() % nTmp) );
+#endif
+ aPt = GetEditWin().PixelToLogic( aPt );
+
+ if ( aPt == m_aVisArea.TopLeft() )
+ return;
+
+ if (GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
+
+ const tools::Long lXDiff = m_aVisArea.Left() - aPt.X();
+ const tools::Long lYDiff = m_aVisArea.Top() - aPt.Y();
+ SetVisArea( tools::Rectangle( aPt,
+ Point( m_aVisArea.Right() - lXDiff, m_aVisArea.Bottom() - lYDiff ) ),
+ bUpdateScrollbar);
+}
+
+void SwView::CheckVisArea()
+{
+ if (m_pHScrollbar)
+ m_pHScrollbar->SetAuto( m_pWrtShell->GetViewOptions()->getBrowseMode() &&
+ !GetViewFrame().GetFrame().IsInPlace() );
+ if ( IsDocumentBorder() )
+ {
+ if ( m_aVisArea.Left() != DOCUMENTBORDER ||
+ m_aVisArea.Top() != DOCUMENTBORDER )
+ {
+ tools::Rectangle aNewVisArea( m_aVisArea );
+ aNewVisArea.Move( DOCUMENTBORDER - m_aVisArea.Left(),
+ DOCUMENTBORDER - m_aVisArea.Top() );
+ SetVisArea( aNewVisArea );
+ }
+ }
+}
+
+/// Calculate the visible range.
+
+// OUT Point *pPt: new position of the visible area
+
+// IN Rectangle &rRect: Rectangle, which should be located
+// within the new visible area.
+// sal_uInt16 nRange optional accurate indication of the
+// range by which to scroll if necessary.
+
+void SwView::CalcPt( Point *pPt, const tools::Rectangle &rRect,
+ sal_uInt16 nRangeX, sal_uInt16 nRangeY)
+{
+
+ const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+
+ tools::Long nYScroll = GetYScroll();
+ tools::Long nDesHeight = rRect.GetHeight();
+ tools::Long nCurHeight = m_aVisArea.GetHeight();
+ nYScroll = std::min(nYScroll, nCurHeight - nDesHeight); // If it is scarce, then scroll not too much.
+ if(nDesHeight > nCurHeight) // the height is not sufficient, then nYScroll is no longer of interest
+ {
+ pPt->setY( rRect.Top() );
+ pPt->setY( std::max( lMin, SwTwips(pPt->Y()) ) );
+ }
+ else if ( rRect.Top() < m_aVisArea.Top() ) // Upward shift
+ {
+ pPt->setY( rRect.Top() - (nRangeY != USHRT_MAX ? nRangeY : nYScroll) );
+ pPt->setY( std::max( lMin, SwTwips(pPt->Y()) ) );
+ }
+ else if( rRect.Bottom() > m_aVisArea.Bottom() ) // Downward shift
+ {
+ pPt->setY( rRect.Bottom() -
+ (m_aVisArea.GetHeight()) + ( nRangeY != USHRT_MAX ?
+ nRangeY : nYScroll ) );
+ pPt->setY( SetVScrollMax( pPt->Y() ) );
+ }
+ tools::Long nXScroll = GetXScroll();
+ if ( rRect.Right() > m_aVisArea.Right() ) // Shift right
+ {
+ pPt->setX( rRect.Right() -
+ (m_aVisArea.GetWidth()) +
+ (nRangeX != USHRT_MAX ? nRangeX : nXScroll) );
+ pPt->setX( SetHScrollMax( pPt->X() ) );
+ }
+ else if ( rRect.Left() < m_aVisArea.Left() ) // Shift left
+ {
+ pPt->setX( rRect.Left() - (nRangeX != USHRT_MAX ? nRangeX : nXScroll) );
+ pPt->setX( std::max( ::GetLeftMargin( *this ) + nLeftOfst, pPt->X() ) );
+ pPt->setX( std::min( rRect.Left() - nScrollX, pPt->X() ) );
+ pPt->setX( std::max( tools::Long(0), pPt->X() ) );
+ }
+}
+
+// Scrolling
+
+bool SwView::IsScroll( const tools::Rectangle &rRect ) const
+{
+ return m_bCenterCursor || m_bTopCursor || !m_aVisArea.Contains(rRect);
+}
+
+void SwView::Scroll( const tools::Rectangle &rRect, sal_uInt16 nRangeX, sal_uInt16 nRangeY )
+{
+ if ( m_aVisArea.IsEmpty() )
+ return;
+
+ tools::Rectangle aOldVisArea( m_aVisArea );
+ tools::Long nDiffY = 0;
+
+ weld::Window* pCareDialog = SwViewShell::GetCareDialog(GetWrtShell());
+ if (pCareDialog)
+ {
+ int x, y, width, height;
+ tools::Rectangle aDlgRect;
+ if (pCareDialog->get_extents_relative_to(*GetEditWin().GetFrameWeld(), x, y, width, height))
+ {
+ AbsoluteScreenPixelPoint aTopLeftAbs(GetEditWin().GetSystemWindow()->OutputToAbsoluteScreenPixel(Point(x, y)));
+ Point aTopLeft = GetEditWin().AbsoluteScreenToOutputPixel(aTopLeftAbs);
+ aDlgRect = GetEditWin().PixelToLogic(tools::Rectangle(aTopLeft, Size(width, height)));
+ }
+
+ // Only if the dialogue is not the VisArea right or left:
+ if ( aDlgRect.Left() < m_aVisArea.Right() &&
+ aDlgRect.Right() > m_aVisArea.Left() )
+ {
+ // If we are not supposed to be centered, lying in the VisArea
+ // and are not covered by the dialogue ...
+ if ( !m_bCenterCursor && aOldVisArea.Contains( rRect )
+ && ( rRect.Left() > aDlgRect.Right()
+ || rRect.Right() < aDlgRect.Left()
+ || rRect.Top() > aDlgRect.Bottom()
+ || rRect.Bottom() < aDlgRect.Top() ) )
+ return;
+
+ // Is above or below the dialogue more space?
+ tools::Long nTopDiff = aDlgRect.Top() - m_aVisArea.Top();
+ tools::Long nBottomDiff = m_aVisArea.Bottom() - aDlgRect.Bottom();
+ if ( nTopDiff < nBottomDiff )
+ {
+ if ( nBottomDiff > 0 ) // Is there room below at all?
+ { // then we move the upper edge and we remember this
+ nDiffY = aDlgRect.Bottom() - m_aVisArea.Top();
+ m_aVisArea.AdjustTop(nDiffY );
+ }
+ }
+ else
+ {
+ if ( nTopDiff > 0 ) // Is there room below at all?
+ m_aVisArea.SetBottom( aDlgRect.Top() ); // Modify the lower edge
+ }
+ }
+ }
+
+ //s.o. !IsScroll()
+ if( !(m_bCenterCursor || m_bTopCursor) && m_aVisArea.Contains( rRect ) )
+ {
+ m_aVisArea = aOldVisArea;
+ return;
+ }
+ // If the rectangle is larger than the visible area -->
+ // upper left corner
+ Size aSize( rRect.GetSize() );
+ const Size aVisSize( m_aVisArea.GetSize() );
+ if( !m_aVisArea.IsEmpty() && (
+ aSize.Width() + GetXScroll() > aVisSize.Width() ||
+ aSize.Height()+ GetYScroll() > aVisSize.Height() ))
+ {
+ Point aPt( m_aVisArea.TopLeft() );
+ aSize.setWidth( std::min( aSize.Width(), aVisSize.Width() ) );
+ aSize.setHeight( std::min( aSize.Height(),aVisSize.Height()) );
+
+ CalcPt( &aPt, tools::Rectangle( rRect.TopLeft(), aSize ),
+ static_cast< sal_uInt16 >((aVisSize.Width() - aSize.Width()) / 2),
+ static_cast< sal_uInt16 >((aVisSize.Height()- aSize.Height())/ 2) );
+
+ if( m_bTopCursor )
+ {
+ const tools::Long nBorder = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+ aPt.setY( std::min( std::max( nBorder, rRect.Top() ),
+ m_aDocSz.Height() + nBorder -
+ m_aVisArea.GetHeight() ) );
+ }
+ aPt.AdjustY( -nDiffY );
+ m_aVisArea = aOldVisArea;
+ SetVisArea( aPt );
+ return;
+ }
+ if( !m_bCenterCursor )
+ {
+ Point aPt( m_aVisArea.TopLeft() );
+ CalcPt( &aPt, rRect, nRangeX, nRangeY );
+
+ if( m_bTopCursor )
+ {
+ const tools::Long nBorder = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+ aPt.setY( std::min( std::max( nBorder, rRect.Top() ),
+ m_aDocSz.Height() + nBorder -
+ m_aVisArea.GetHeight() ) );
+ }
+
+ aPt.AdjustY( -nDiffY );
+ m_aVisArea = aOldVisArea;
+ SetVisArea( aPt );
+ return;
+ }
+
+ //Center cursor
+ Point aPnt( m_aVisArea.TopLeft() );
+ // ... in Y-direction in any case
+ aPnt.AdjustY(( rRect.Top() + rRect.Bottom()
+ - m_aVisArea.Top() - m_aVisArea.Bottom() ) / 2 - nDiffY );
+ // ... in X-direction, only if the rectangle protrudes over the right or left of the VisArea.
+ if ( rRect.Right() > m_aVisArea.Right() || rRect.Left() < m_aVisArea.Left() )
+ {
+ aPnt.AdjustX(( rRect.Left() + rRect.Right()
+ - m_aVisArea.Left() - m_aVisArea.Right() ) / 2 );
+ aPnt.setX( SetHScrollMax( aPnt.X() ) );
+ const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
+ aPnt.setX( std::max( (GetLeftMargin( *this ) - lMin) + nLeftOfst, aPnt.X() ) );
+ }
+ m_aVisArea = aOldVisArea;
+ if (pCareDialog)
+ {
+ // If we want to avoid only a dialogue, we do
+ // not want to go beyond the end of the document.
+ aPnt.setY( SetVScrollMax( aPnt.Y() ) );
+ }
+ SetVisArea( aPnt );
+}
+
+/// Scroll page by page
+// Returns the value by which to be scrolled with PageUp / Down
+
+bool SwView::GetPageScrollUpOffset( SwTwips &rOff ) const
+{
+ // in the LOK case, force the value set by the API
+ if (comphelper::LibreOfficeKit::isActive() && m_nLOKPageUpDownOffset > 0)
+ {
+ rOff = -m_nLOKPageUpDownOffset;
+ return true;
+ }
+
+ if ( !m_aVisArea.Top() || !m_aVisArea.GetHeight() )
+ return false;
+ tools::Long nYScrl = GetYScroll() / 2;
+ rOff = -(m_aVisArea.GetHeight() - nYScrl);
+ // Do not scroll before the beginning of the document.
+ if( m_aVisArea.Top() - rOff < 0 )
+ rOff = rOff - m_aVisArea.Top();
+ else if( GetWrtShell().GetCharRect().Top() < (m_aVisArea.Top() + nYScrl))
+ rOff += nYScrl;
+
+ return true;
+}
+
+bool SwView::GetPageScrollDownOffset( SwTwips &rOff ) const
+{
+ // in the LOK case, force the value set by the API
+ if (comphelper::LibreOfficeKit::isActive() && m_nLOKPageUpDownOffset > 0)
+ {
+ rOff = m_nLOKPageUpDownOffset;
+ return true;
+ }
+
+ if ( !m_aVisArea.GetHeight() ||
+ (m_aVisArea.GetHeight() > m_aDocSz.Height()) )
+ return false;
+ tools::Long nYScrl = GetYScroll() / 2;
+ rOff = m_aVisArea.GetHeight() - nYScrl;
+ // Do not scroll past the end of the document.
+ if ( m_aVisArea.Top() + rOff > m_aDocSz.Height() )
+ rOff = m_aDocSz.Height() - m_aVisArea.Bottom();
+ else if( GetWrtShell().GetCharRect().Bottom() >
+ ( m_aVisArea.Bottom() - nYScrl ))
+ rOff -= nYScrl;
+
+ return rOff > 0;
+}
+
+// Scroll page by page
+bool SwView::PageUp()
+{
+ if (!m_aVisArea.GetHeight())
+ return false;
+
+ Point aPos(m_aVisArea.TopLeft());
+ aPos.AdjustY( -(m_aVisArea.GetHeight() - (GetYScroll() / 2)) );
+ aPos.setY( std::max(tools::Long(0), aPos.Y()) );
+ SetVisArea( aPos );
+ return true;
+}
+
+bool SwView::PageDown()
+{
+ if ( !m_aVisArea.GetHeight() )
+ return false;
+ Point aPos( m_aVisArea.TopLeft() );
+ aPos.AdjustY(m_aVisArea.GetHeight() - (GetYScroll() / 2) );
+ aPos.setY( SetVScrollMax( aPos.Y() ) );
+ SetVisArea( aPos );
+ return true;
+}
+
+void SwView::PhyPageUp()
+{
+ // Check for the currently visible page, do not format
+ sal_uInt16 nActPage = m_pWrtShell->GetNextPrevPageNum( false );
+
+ if( USHRT_MAX != nActPage )
+ {
+ const Point aPt( m_aVisArea.Left(),
+ m_pWrtShell->GetPagePos( nActPage ).Y() );
+ Point aAlPt( AlignToPixel( aPt ) );
+ // If there is a difference, has been truncated --> then add one pixel,
+ // so that no residue of the previous page is visible.
+ if( aPt.Y() != aAlPt.Y() )
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic( Size( 0, 1 ) ).Height() );
+ SetVisArea( aAlPt );
+ }
+}
+
+void SwView::PhyPageDown()
+{
+ // Check for the currently visible page, do not format
+ sal_uInt16 nActPage = m_pWrtShell->GetNextPrevPageNum();
+ // If the last page of the document is visible, do nothing.
+ if( USHRT_MAX != nActPage )
+ {
+ const Point aPt( m_aVisArea.Left(),
+ m_pWrtShell->GetPagePos( nActPage ).Y() );
+ Point aAlPt( AlignToPixel( aPt ) );
+ // If there is a difference, has been truncated --> then add one pixel,
+ // so that no residue of the previous page is visible.
+ if( aPt.Y() != aAlPt.Y() )
+ aAlPt.AdjustY(3 * GetEditWin().PixelToLogic( Size( 0, 1 ) ).Height() );
+ SetVisArea( aAlPt );
+ }
+}
+
+bool SwView::PageUpCursor( bool bSelect )
+{
+ if ( !bSelect )
+ {
+ const FrameTypeFlags eType = m_pWrtShell->GetFrameType(nullptr,true);
+ if ( eType & FrameTypeFlags::FOOTNOTE )
+ {
+ m_pWrtShell->MoveCursor();
+ m_pWrtShell->GotoFootnoteAnchor();
+ m_pWrtShell->Right(SwCursorSkipMode::Chars, false, 1, false );
+ return true;
+ }
+ }
+
+ SwTwips lOff = 0;
+ if ( GetPageScrollUpOffset( lOff ) &&
+ (m_pWrtShell->IsCursorReadonly() ||
+ !m_pWrtShell->PageCursor( lOff, bSelect )) &&
+ PageUp() )
+ {
+ m_pWrtShell->ResetCursorStack();
+ return true;
+ }
+ return false;
+}
+
+bool SwView::PageDownCursor(bool bSelect)
+{
+ SwTwips lOff = 0;
+ if ( GetPageScrollDownOffset( lOff ) &&
+ (m_pWrtShell->IsCursorReadonly() ||
+ !m_pWrtShell->PageCursor( lOff, bSelect )) &&
+ PageDown() )
+ {
+ m_pWrtShell->ResetCursorStack();
+ return true;
+ }
+ return false;
+}
+
+static void HideQuickHelp(vcl::Window* pParent) { Help::ShowQuickHelp(pParent, {}, {}); }
+
+// Handler of the scrollbars
+IMPL_LINK(SwView, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
+{
+ if ( GetWrtShell().ActionPend() )
+ return;
+
+ if (rScrollbar.get_scroll_type() == ScrollType::Drag)
+ m_pWrtShell->EnableSmooth( false );
+
+ bool bHidePending = nPgNum != 0;
+ nPgNum = 0; // avoid flicker from hiding then showing help window again
+ EndScrollHdl(rScrollbar, false);
+
+ if (!m_pWrtShell->GetViewOptions()->getBrowseMode() &&
+ rScrollbar.get_scroll_type() == ScrollType::Drag)
+ {
+ if ( !m_bWheelScrollInProgress && Help::IsQuickHelpEnabled() &&
+ m_pWrtShell->GetViewOptions()->IsShowScrollBarTips())
+ {
+
+ Point aPos( m_aVisArea.TopLeft() );
+ lcl_GetPos(this, aPos, rScrollbar, false, IsDocumentBorder());
+
+ sal_uInt16 nPhNum = 1;
+ sal_uInt16 nVirtNum = 1;
+
+ OUString sDisplay;
+ if(m_pWrtShell->GetPageNumber( aPos.Y(), false, nPhNum, nVirtNum, sDisplay ))
+ {
+ //QuickHelp:
+ if( m_pWrtShell->GetPageCnt() > 1 )
+ {
+ tools::Rectangle aRect;
+ aRect.SetLeft( m_pVScrollbar->GetParent()->OutputToScreenPixel(
+ m_pVScrollbar->GetPosPixel() ).X() -8 );
+ aRect.SetTop( m_pVScrollbar->OutputToScreenPixel(
+ m_pVScrollbar->GetPointerPosPixel() ).Y() );
+ aRect.SetRight( aRect.Left() );
+ aRect.SetBottom( aRect.Top() );
+
+ OUString sPageStr( GetPageStr( nPhNum, nVirtNum, sDisplay ));
+ SwContentAtPos aCnt(IsAttrAtPos::Outline | IsAttrAtPos::AllowContaining);
+ bool bSuccess = m_pWrtShell->GetContentAtPos(aPos, aCnt);
+ if (bSuccess && !aCnt.sStr.isEmpty())
+ {
+ sal_Int32 nChunkLen = std::min<sal_Int32>(aCnt.sStr.getLength(), 80);
+ std::u16string_view sChunk = aCnt.sStr.subView(0, nChunkLen);
+ sPageStr = sPageStr + " - " + sChunk;
+ sPageStr = sPageStr.replace('\t', ' ').replace(0x0a, ' ');
+ }
+
+ Help::ShowQuickHelp(m_pVScrollbar, aRect, sPageStr,
+ QuickHelpFlags::Right|QuickHelpFlags::VCenter);
+ bHidePending = false;
+ nPgNum = nPhNum;
+ }
+ }
+ }
+ }
+
+ if (bHidePending)
+ HideQuickHelp(m_pVScrollbar);
+
+ if (rScrollbar.get_scroll_type() == ScrollType::Drag)
+ m_pWrtShell->EnableSmooth( true );
+}
+
+// Handler of the scrollbars
+void SwView::EndScrollHdl(weld::Scrollbar& rScrollbar, bool bHorizontal)
+{
+ if ( GetWrtShell().ActionPend() )
+ return;
+
+ if(nPgNum)
+ {
+ nPgNum = 0;
+ HideQuickHelp(bHorizontal ? m_pHScrollbar : m_pVScrollbar);
+ }
+ Point aPos( m_aVisArea.TopLeft() );
+ bool bBorder = IsDocumentBorder();
+ lcl_GetPos(this, aPos, rScrollbar, bHorizontal, bBorder);
+ if ( bBorder && aPos == m_aVisArea.TopLeft() )
+ UpdateScrollbars();
+ else
+ SetVisArea( aPos, false );
+
+ GetViewFrame().GetBindings().Update(FN_STAT_PAGE);
+}
+
+IMPL_LINK(SwView, HoriScrollHdl, weld::Scrollbar&, rScrollBar, void)
+{
+ EndScrollHdl(rScrollBar, true);
+}
+
+// Calculates the size of the m_aVisArea in dependency of the size of
+// EditWin on the screen.
+
+void SwView::CalcVisArea( const Size &rOutPixel )
+{
+ Point aTopLeft;
+ tools::Rectangle aRect( aTopLeft, rOutPixel );
+ aRect = GetEditWin().PixelToLogic(aRect);
+
+ // The shifts to the right and/or below can now be incorrect
+ // (e.g. change zoom level, change view size).
+ const tools::Long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER*2;
+ if ( aRect.Left() )
+ {
+ const tools::Long lWidth = GetWrtShell().GetDocSize().Width() + lBorder;
+ if ( aRect.Right() > lWidth )
+ {
+ tools::Long lDelta = aRect.Right() - lWidth;
+ aRect.AdjustLeft( -lDelta );
+ aRect.AdjustRight( -lDelta );
+ }
+ }
+ if ( aRect.Top() )
+ {
+ const tools::Long lHeight = GetWrtShell().GetDocSize().Height() + lBorder;
+ if ( aRect.Bottom() > lHeight )
+ {
+ tools::Long lDelta = aRect.Bottom() - lHeight;
+ aRect.AdjustTop( -lDelta );
+ aRect.AdjustBottom( -lDelta );
+ }
+ }
+ SetVisArea( aRect );
+ GetViewFrame().GetBindings().Invalidate( SID_ATTR_ZOOM );
+ GetViewFrame().GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER ); // for snapping points
+}
+
+// Rearrange control elements
+
+void SwView::CalcAndSetBorderPixel( SvBorder &rToFill )
+{
+ bool bRightVRuler = m_pWrtShell->GetViewOptions()->IsVRulerRight();
+ if ( m_pVRuler->IsVisible() )
+ {
+ tools::Long nWidth = m_pVRuler->GetSizePixel().Width();
+ if(bRightVRuler)
+ rToFill.Right() = nWidth;
+ else
+ rToFill.Left() = nWidth;
+ }
+
+ OSL_ENSURE(m_pHRuler, "Why is the ruler not present?");
+ if ( m_pHRuler->IsVisible() )
+ rToFill.Top() = m_pHRuler->GetSizePixel().Height();
+
+ const StyleSettings &rSet = GetEditWin().GetSettings().GetStyleSettings();
+ const tools::Long nTmp = rSet.GetScrollBarSize();
+ if( m_pVScrollbar->IsScrollbarVisible(true) )
+ {
+ if(bRightVRuler)
+ rToFill.Left() = nTmp;
+ else
+ rToFill.Right() = nTmp;
+ }
+ if ( m_pHScrollbar->IsScrollbarVisible(true) )
+ rToFill.Bottom() = nTmp;
+
+ SetBorderPixel( rToFill );
+}
+
+void ViewResizePixel( const vcl::RenderContext &rRef,
+ const Point &rOfst,
+ const Size &rSize,
+ const Size &rEditSz,
+ SwScrollbar& rVScrollbar,
+ SwScrollbar& rHScrollbar,
+ SvxRuler* pVRuler,
+ SvxRuler* pHRuler,
+ bool bVRulerRight )
+{
+// ViewResizePixel is also used by Preview!!!
+
+ const bool bHRuler = pHRuler && pHRuler->IsVisible();
+ const tools::Long nHLinSzHeight = bHRuler ?
+ pHRuler->GetSizePixel().Height() : 0;
+ const bool bVRuler = pVRuler && pVRuler->IsVisible();
+ const tools::Long nVLinSzWidth = bVRuler ?
+ pVRuler->GetSizePixel().Width() : 0;
+
+ const tools::Long nScrollBarSize = rRef.GetSettings().GetStyleSettings().GetScrollBarSize();
+ const tools::Long nHBSzHeight = rHScrollbar.IsScrollbarVisible(true) ? nScrollBarSize : 0;
+ const tools::Long nVBSzWidth = rVScrollbar.IsScrollbarVisible(true) ? nScrollBarSize : 0;
+
+ if(pVRuler)
+ {
+ WinBits nStyle = pVRuler->GetStyle()&~WB_RIGHT_ALIGNED;
+ Point aPos( rOfst.X(), rOfst.Y()+nHLinSzHeight );
+ if(bVRulerRight)
+ {
+ aPos.AdjustX(rSize.Width() - nVLinSzWidth );
+ nStyle |= WB_RIGHT_ALIGNED;
+ }
+ Size aSize( nVLinSzWidth, rEditSz.Height() );
+ if(!aSize.Width())
+ aSize.setWidth( pVRuler->GetSizePixel().Width() );
+ pVRuler->SetStyle(nStyle);
+ pVRuler->SetPosSizePixel( aPos, aSize );
+ if(!pVRuler->IsVisible())
+ pVRuler->Resize();
+ }
+ // Ruler needs a resize, otherwise it will not work in the invisible condition
+ if(pHRuler)
+ {
+ Size aSize( rSize.Width(), nHLinSzHeight );
+ if ( nVBSzWidth && !bVRulerRight)
+ aSize.AdjustWidth( -nVBSzWidth );
+ if(!aSize.Height())
+ aSize.setHeight( pHRuler->GetSizePixel().Height() );
+ pHRuler->SetPosSizePixel( rOfst, aSize );
+ // VCL calls no resize on invisible windows
+ // but that is not a good idea for the ruler
+ if(!pHRuler->IsVisible())
+ pHRuler->Resize();
+ }
+
+ // Arrange scrollbars and SizeBox
+ Point aScrollFillPos;
+ {
+ Point aPos( rOfst.X(),
+ rOfst.Y()+rSize.Height()-nHBSzHeight );
+ if(bVRulerRight)
+ {
+ aPos.AdjustX(nVBSzWidth );
+ }
+
+ Size aSize( rSize.Width(), nHBSzHeight );
+ if ( nVBSzWidth )
+ aSize.AdjustWidth( -nVBSzWidth );
+ rHScrollbar.SetPosSizePixel( aPos, aSize );
+ aScrollFillPos.setY( aPos.Y() );
+ }
+ {
+ Point aPos( rOfst.X()+rSize.Width()-nVBSzWidth,
+ rOfst.Y() );
+ Size aSize( nVBSzWidth, rSize.Height() );
+ if(bVRulerRight)
+ {
+ aPos.setX( rOfst.X() );
+ if(bHRuler)
+ {
+ aPos.AdjustY(nHLinSzHeight );
+ aSize.AdjustHeight( -nHLinSzHeight );
+ }
+ }
+
+ if ( nHBSzHeight )
+ aSize.AdjustHeight( -nHBSzHeight );
+ rVScrollbar.SetPosSizePixel( aPos, aSize );
+
+ aPos.AdjustY(aSize.Height() );
+
+ aScrollFillPos.setX( aPos.X() );
+ }
+}
+
+void SwView::ShowAtResize()
+{
+ m_bShowAtResize = false;
+ if ( m_pWrtShell->GetViewOptions()->IsViewHRuler() )
+ m_pHRuler->Show();
+}
+
+void SwView::InnerResizePixel( const Point &rOfst, const Size &rSize, bool )
+{
+ Size aObjSize = GetObjectShell()->GetVisArea().GetSize();
+ if ( !aObjSize.IsEmpty() )
+ {
+ SvBorder aBorder( GetBorderPixel() );
+ Size aSize( rSize );
+ aSize.AdjustWidth( -(aBorder.Left() + aBorder.Right()) );
+ aSize.AdjustHeight( -(aBorder.Top() + aBorder.Bottom()) );
+ Size aObjSizePixel = GetWindow()->LogicToPixel(aObjSize, MapMode(MapUnit::MapTwip));
+ SfxViewShell::SetZoomFactor( Fraction( aSize.Width(), aObjSizePixel.Width() ),
+ Fraction( aSize.Height(), aObjSizePixel.Height() ) );
+ }
+
+ m_bInInnerResizePixel = true;
+ const bool bHScrollVisible = m_pHScrollbar->IsScrollbarVisible(true);
+ const bool bVScrollVisible = m_pVScrollbar->IsScrollbarVisible(true);
+ bool bRepeat = false;
+ do
+ {
+ Size aSz( rSize );
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+ if ( GetViewFrame().GetFrame().IsInPlace() )
+ {
+ Size aViewSize( aSz );
+ Point aViewPos( rOfst );
+ aViewSize.AdjustHeight( -(aBorder.Top() + aBorder.Bottom()) );
+ aViewSize.AdjustWidth( -(aBorder.Left() + aBorder.Right()) );
+ aViewPos.AdjustX(aBorder.Left() );
+ aViewPos.AdjustY(aBorder.Top() );
+ GetEditWin().SetPosSizePixel( aViewPos, aViewSize );
+ }
+ else
+ {
+ aSz.AdjustHeight(aBorder.Top() + aBorder.Bottom() );
+ aSz.AdjustWidth(aBorder.Left() + aBorder.Right() );
+ }
+
+ Size aEditSz( GetEditWin().GetOutputSizePixel() );
+ ViewResizePixel( *GetEditWin().GetOutDev(), rOfst, aSz, aEditSz, *m_pVScrollbar,
+ *m_pHScrollbar, m_pVRuler, m_pHRuler,
+ m_pWrtShell->GetViewOptions()->IsVRulerRight());
+ if ( m_bShowAtResize )
+ ShowAtResize();
+
+ if( m_pHRuler->IsVisible() || m_pVRuler->IsVisible() )
+ {
+ const Fraction& rFrac = GetEditWin().GetMapMode().GetScaleX();
+ tools::Long nZoom = 100;
+ if (rFrac.IsValid())
+ nZoom = tools::Long(rFrac * 100);
+
+ const Fraction aFrac( nZoom, 100 );
+ m_pVRuler->SetZoom( aFrac );
+ m_pHRuler->SetZoom( aFrac );
+ InvalidateRulerPos(); // Invalidate content.
+ }
+ // Reset the cursor stack because the cursor positions for PageUp/Down
+ // no longer fit the currently visible area.
+ m_pWrtShell->ResetCursorStack();
+
+ // EditWin never set!
+
+ // Set VisArea, but do not call the SetVisArea of the Docshell there!
+ bProtectDocShellVisArea = true;
+ CalcVisArea( aEditSz );
+ // Visibility changes of the automatic horizontal scrollbar
+ // require to repeat the ViewResizePixel() call - but only once!
+ if(bRepeat)
+ bRepeat = false;
+ else if(bHScrollVisible != m_pHScrollbar->IsScrollbarVisible(true) ||
+ bVScrollVisible != m_pVScrollbar->IsScrollbarVisible(true))
+ bRepeat = true;
+ }while( bRepeat );
+ bProtectDocShellVisArea = false;
+ m_bInInnerResizePixel = false;
+}
+
+void SwView::OuterResizePixel( const Point &rOfst, const Size &rSize )
+{
+ // #i16909# return, if no size (caused by minimize window).
+ if ( m_bInOuterResizePixel || ( !rSize.Width() && !rSize.Height() ) )
+ return;
+ m_bInOuterResizePixel = true;
+
+ // Determine whether scroll bars may be displayed.
+ bool bShowH = true,
+ bShowV = true,
+ bAuto = true,
+ bHAuto = true;
+
+ const SwViewOption *pVOpt = m_pWrtShell->GetViewOptions();
+ if ( !pVOpt->IsReadonly() || pVOpt->IsStarOneSetting() )
+ {
+ bShowH = pVOpt->IsViewHScrollBar();
+ bShowV = pVOpt->IsViewVScrollBar();
+ }
+
+ if (!m_bHScrollbarEnabled)
+ {
+ bHAuto = bShowH = false;
+ }
+ if (!m_bVScrollbarEnabled)
+ {
+ bAuto = bShowV = false;
+ }
+
+ SwDocShell* pDocSh = GetDocShell();
+ bool bIsPreview = pDocSh->IsPreview();
+ if( bIsPreview )
+ {
+ bShowH = bShowV = bHAuto = bAuto = false;
+ }
+ if(m_pHScrollbar->IsScrollbarVisible(false) != bShowH && !bHAuto)
+ ShowHScrollbar(bShowH);
+ m_pHScrollbar->SetAuto( bHAuto );
+ if(m_pVScrollbar->IsScrollbarVisible(false) != bShowV && !bAuto)
+ ShowVScrollbar(bShowV);
+ m_pVScrollbar->SetAuto(bAuto);
+
+ CurrShell aCurr( m_pWrtShell.get() );
+ bool bRepeat = false;
+ tools::Long nCnt = 0;
+
+ bool bUnLockView = !m_pWrtShell->IsViewLocked();
+ m_pWrtShell->LockView( true );
+ m_pWrtShell->LockPaint(LockPaintReason::OuterResize);
+
+ do {
+ ++nCnt;
+ const bool bScroll1 = m_pVScrollbar->IsScrollbarVisible(true);
+ const bool bScroll2 = m_pHScrollbar->IsScrollbarVisible(true);
+ SvBorder aBorder;
+ CalcAndSetBorderPixel( aBorder );
+ const Size aEditSz( GetEditWin().GetOutputSizePixel() );
+ ViewResizePixel( *GetEditWin().GetOutDev(), rOfst, rSize, aEditSz, *m_pVScrollbar,
+ *m_pHScrollbar, m_pVRuler, m_pHRuler,
+ m_pWrtShell->GetViewOptions()->IsVRulerRight() );
+ if ( m_bShowAtResize )
+ ShowAtResize();
+
+ if( m_pHRuler->IsVisible() || m_pVRuler->IsVisible() )
+ InvalidateRulerPos(); // Invalidate content.
+
+ // Reset the cursor stack because the cursor positions for PageUp/Down
+ // no longer fit the currently visible area.
+ m_pWrtShell->ResetCursorStack();
+
+ OSL_ENSURE( !GetEditWin().IsVisible() ||
+ !aEditSz.IsEmpty() || !m_aVisArea.IsEmpty(), "Small world, isn't it?" );
+
+ // Never set EditWin!
+
+ // Of course the VisArea must also be set.
+ // Now is the right time to re-calculate the zoom if it is not a simple factor.
+ m_pWrtShell->StartAction();
+ CalcVisArea( aEditSz );
+
+ //Thus also in the outplace editing the page width will be adjusted immediately.
+ //TODO/LATER: is that still necessary?!
+ /*
+ if ( pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
+ pDocSh->SetVisArea(
+ pDocSh->SfxInPlaceObject::GetVisArea() );*/
+ if ( m_pWrtShell->GetViewOptions()->GetZoomType() != SvxZoomType::PERCENT &&
+ !m_pWrtShell->GetViewOptions()->getBrowseMode() )
+ SetZoom_( aEditSz, m_pWrtShell->GetViewOptions()->GetZoomType(), 100, true );
+ m_pWrtShell->EndAction();
+
+ bRepeat = bScroll1 != m_pVScrollbar->IsScrollbarVisible(true);
+ if ( !bRepeat )
+ bRepeat = bScroll2 != m_pHScrollbar->IsScrollbarVisible(true);
+
+ // Do no infinite loops.
+ // If possible stop when the (auto-) scroll bars are visible.
+ if ( bRepeat &&
+ ( nCnt > 10 || ( nCnt > 3 && bHAuto && bAuto ) )
+ )
+ {
+ bRepeat = false;
+ }
+
+ } while ( bRepeat );
+
+ m_pWrtShell->UnlockPaint();
+ if( bUnLockView )
+ m_pWrtShell->LockView( false );
+
+ m_bInOuterResizePixel = false;
+
+ if ( m_pPostItMgr )
+ {
+ m_pPostItMgr->CalcRects();
+ m_pPostItMgr->LayoutPostIts();
+ }
+}
+
+void SwView::SetZoomFactor( const Fraction &rX, const Fraction &rY )
+{
+ const Fraction &rFrac = rX < rY ? rX : rY;
+ SetZoom( SvxZoomType::PERCENT, static_cast<short>(tools::Long(rFrac * Fraction( 100, 1 ))) );
+
+ // To minimize rounding errors we also adjust the odd values
+ // of the base class if necessary.
+ SfxViewShell::SetZoomFactor( rX, rY );
+}
+
+bool SwView::UpdateScrollbars()
+{
+ bool bRet = false;
+ if ( !m_aVisArea.IsEmpty() )
+ {
+ const bool bBorder = IsDocumentBorder();
+ tools::Rectangle aTmpRect( m_aVisArea );
+ if ( bBorder )
+ {
+ Point aPt( DOCUMENTBORDER, DOCUMENTBORDER );
+ aPt = AlignToPixel( aPt );
+ aTmpRect.Move( -aPt.X(), -aPt.Y() );
+ }
+
+ Size aTmpSz( m_aDocSz );
+ const tools::Long lOfst = bBorder ? 0 : DOCUMENTBORDER * 2;
+ aTmpSz.AdjustWidth(lOfst ); aTmpSz.AdjustHeight(lOfst );
+
+ {
+ const bool bVScrollVisible = m_pVScrollbar->IsScrollbarVisible(true);
+ m_pVScrollbar->DocSzChgd( aTmpSz );
+ m_pVScrollbar->ViewPortChgd( aTmpRect );
+ if ( bVScrollVisible != m_pVScrollbar->IsScrollbarVisible(true) )
+ bRet = true;
+ }
+ {
+ const bool bHScrollVisible = m_pHScrollbar->IsScrollbarVisible(true);
+ m_pHScrollbar->DocSzChgd( aTmpSz );
+ m_pHScrollbar->ViewPortChgd( aTmpRect );
+ if ( bHScrollVisible != m_pHScrollbar->IsScrollbarVisible(true) )
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+void SwView::Move()
+{
+ if ( GetWrtShell().IsInSelect() )
+ GetWrtShell().EndSelect();
+ SfxViewShell::Move();
+}
+
+bool SwView::HandleWheelCommands( const CommandEvent& rCEvt )
+{
+ bool bOk = false;
+ const CommandWheelData* pWData = rCEvt.GetWheelData();
+ if (pWData && CommandWheelMode::ZOOM == pWData->GetMode())
+ {
+ sal_uInt16 nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ if( 0L > pWData->GetDelta() )
+ nFact = std::max(MIN_ZOOM_PERCENT, basegfx::zoomtools::zoomOut( nFact ));
+ else
+ nFact = std::min(MAX_ZOOM_PERCENT, basegfx::zoomtools::zoomIn( nFact ));
+
+ SetZoom( SvxZoomType::PERCENT, nFact );
+ bOk = true;
+ }
+ else
+ {
+ if (pWData && pWData->GetMode()==CommandWheelMode::SCROLL)
+ {
+ // This influences whether quick help is shown
+ m_bWheelScrollInProgress=true;
+ }
+
+ if (pWData && (CommandWheelMode::SCROLL==pWData->GetMode()) &&
+ (COMMAND_WHEEL_PAGESCROLL == pWData->GetScrollLines()))
+ {
+ if (pWData->GetDelta()<0)
+ PhyPageDown();
+ else
+ PhyPageUp();
+ bOk = true;
+ }
+ else
+ bOk = m_pEditWin->HandleScrollCommand(rCEvt, m_pHScrollbar, m_pVScrollbar);
+
+ // Restore default state for case when scroll command comes from dragging scrollbar handle
+ m_bWheelScrollInProgress=false;
+ }
+ return bOk;
+}
+
+bool SwView::HandleGestureZoomCommand(const CommandEvent& rCEvt)
+{
+ const CommandGestureZoomData* pData = rCEvt.GetGestureZoomData();
+
+ if (pData->meEventType == GestureEventZoomType::Begin)
+ {
+ m_fLastZoomScale = pData->mfScaleDelta;
+ return true;
+ }
+
+ if (pData->meEventType == GestureEventZoomType::Update)
+ {
+ double deltaBetweenEvents = (pData->mfScaleDelta - m_fLastZoomScale) / m_fLastZoomScale;
+ m_fLastZoomScale = pData->mfScaleDelta;
+
+ // Accumulate fractional zoom to avoid small zoom changes from being ignored
+ m_fAccumulatedZoom += deltaBetweenEvents;
+ int nZoomChangePercent = m_fAccumulatedZoom * 100;
+ m_fAccumulatedZoom -= nZoomChangePercent / 100.0;
+
+ sal_uInt16 nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ nFact += nZoomChangePercent;
+ nFact = std::clamp<sal_uInt16>(nFact, MIN_ZOOM_PERCENT, MAX_ZOOM_PERCENT);
+ SetZoom(SvxZoomType::PERCENT, nFact);
+
+ return true;
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewprt.cxx b/sw/source/uibase/uiview/viewprt.cxx
new file mode 100644
index 0000000000..bc9c5e19b8
--- /dev/null
+++ b/sw/source/uibase/uiview/viewprt.cxx
@@ -0,0 +1,376 @@
+/* -*- 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 <libxml/xmlwriter.h>
+#include <cmdid.h>
+#include <officecfg/Office/Common.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/paperinf.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/flagitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <osl/diagnose.h>
+#include <svtools/colorcfg.hxx>
+#include <o3tl/unreachable.hxx>
+
+#include <modcfg.hxx>
+#include <edtwin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <viewopt.hxx>
+#include <prtopt.hxx>
+#include <cfgitems.hxx>
+#include "viewfunc.hxx"
+#include <swmodule.hxx>
+#include <wview.hxx>
+#include <IDocumentDeviceAccess.hxx>
+
+#include <globals.hrc>
+#include <strings.hrc>
+#include <swabstdlg.hxx>
+
+#include <uivwimp.hxx>
+
+using namespace ::com::sun::star;
+
+// Hand over the printer to Sfx
+
+SfxPrinter* SwView::GetPrinter( bool bCreate )
+{
+ const IDocumentDeviceAccess& rIDDA = GetWrtShell().getIDocumentDeviceAccess();
+ SfxPrinter *pOld = rIDDA.getPrinter( false );
+ SfxPrinter *pPrt = rIDDA.getPrinter( bCreate );
+ if ( pOld != pPrt )
+ {
+ bool bWeb = dynamic_cast<SwWebView*>(this) != nullptr;
+ ::SetAppPrintOptions( &GetWrtShell(), bWeb );
+ }
+ return pPrt;
+}
+
+// Propagate printer change
+
+void SetPrinter( IDocumentDeviceAccess* pIDDA, SfxPrinter const * pNew, bool bWeb )
+{
+ SwPrintOptions* pOpt = SW_MOD()->GetPrtOptions(bWeb);
+ if( !pOpt)
+ return;
+
+ // Reading Application own printing options from SfxPrinter
+ const SfxItemSet& rSet = pNew->GetOptions();
+
+ const SwAddPrinterItem* pAddPrinterAttr =
+ rSet.GetItemIfSet( FN_PARAM_ADDPRINTER, false );
+ if( pAddPrinterAttr )
+ {
+ if( pIDDA )
+ pIDDA->setPrintData( *pAddPrinterAttr );
+ if( !pAddPrinterAttr->GetFaxName().isEmpty() )
+ pOpt->SetFaxName(pAddPrinterAttr->GetFaxName());
+ }
+}
+
+sal_uInt16 SwView::SetPrinter(SfxPrinter* pNew, SfxPrinterChangeFlags nDiffFlags )
+{
+ SwWrtShell &rSh = GetWrtShell();
+ SfxPrinter* pOld = rSh.getIDocumentDeviceAccess().getPrinter( false );
+ if ( pOld && pOld->IsPrinting() )
+ return SFX_PRINTERROR_BUSY;
+
+ if ( (SfxPrinterChangeFlags::JOBSETUP | SfxPrinterChangeFlags::PRINTER) & nDiffFlags )
+ {
+ rSh.getIDocumentDeviceAccess().setPrinter( pNew, true, true );
+ if ( nDiffFlags & SfxPrinterChangeFlags::PRINTER )
+ rSh.SetModified();
+ }
+ bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr;
+ if ( nDiffFlags & SfxPrinterChangeFlags::OPTIONS )
+ ::SetPrinter( &rSh.getIDocumentDeviceAccess(), pNew, bWeb );
+
+ const bool bChgOri = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ const bool bChgSize = bool(nDiffFlags & SfxPrinterChangeFlags::CHG_SIZE);
+ if ( bChgOri || bChgSize )
+ {
+ rSh.StartAllAction();
+ if ( bChgOri )
+ rSh.ChgAllPageOrientation( pNew->GetOrientation() );
+ if ( bChgSize )
+ {
+ Size aSz( SvxPaperInfo::GetPaperSize( pNew ) );
+ rSh.ChgAllPageSize( aSz );
+ }
+ rSh.SetModified();
+ rSh.EndAllAction();
+ InvalidateRulerPos();
+ }
+ return 0;
+}
+
+bool SwView::HasPrintOptionsPage() const
+{
+ return true;
+}
+
+namespace
+{
+ class SvxPrtQryBox
+ {
+ private:
+ std::unique_ptr<weld::MessageDialog> m_xQueryBox;
+ public:
+ SvxPrtQryBox(weld::Window* pParent)
+ : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, SvxResId(RID_SVXSTR_QRY_PRINT_MSG)))
+ {
+ m_xQueryBox->set_title(SvxResId(RID_SVXSTR_QRY_PRINT_TITLE));
+
+ m_xQueryBox->add_button(SvxResId(RID_SVXSTR_QRY_PRINT_SELECTION), RET_OK);
+ m_xQueryBox->add_button(SvxResId(RID_SVXSTR_QRY_PRINT_ALL), 2);
+ m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
+ m_xQueryBox->set_default_response(RET_OK);
+ }
+ short run() { return m_xQueryBox->run(); }
+ };
+}
+
+// TabPage for application-specific print options
+
+std::unique_ptr<SfxTabPage> SwView::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rSet)
+{
+ return ::CreatePrintOptionsPage(pPage, pController, rSet, false);
+}
+
+// Print dispatcher
+
+void SwView::ExecutePrint(SfxRequest& rReq)
+{
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+ ::SetAppPrintOptions( &GetWrtShell(), bWeb );
+ switch (rReq.GetSlot())
+ {
+ case FN_FAX:
+ {
+ SwPrintOptions* pPrintOptions = SW_MOD()->GetPrtOptions(bWeb);
+ const OUString& sFaxName(pPrintOptions->GetFaxName());
+ if (!sFaxName.isEmpty())
+ {
+ SfxStringItem aPrinterName(SID_PRINTER_NAME, sFaxName);
+ SfxBoolItem aSilent( SID_SILENT, true );
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_PRINTDOC,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aPrinterName, &aSilent });
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_ERR_NO_FAX)));
+ TranslateId pResId = bWeb ? STR_WEBOPTIONS : STR_TEXTOPTIONS;
+ xInfoBox->set_primary_text(xInfoBox->get_primary_text().replaceFirst("%1", SwResId(pResId)));
+ xInfoBox->run();
+ SfxUInt16Item aDefPage(SID_SW_EDITOPTIONS, TP_OPTPRINT_PAGE);
+ GetViewFrame().GetDispatcher()->ExecuteList(SID_SW_EDITOPTIONS,
+ SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
+ { &aDefPage });
+ }
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ {
+ SwWrtShell* pSh = &GetWrtShell();
+ const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
+ bool bSilent = pSilentItem && pSilentItem->GetValue();
+ const SfxBoolItem* pPrintFromMergeItem = rReq.GetArg<SfxBoolItem>(FN_QRY_MERGE);
+ if(pPrintFromMergeItem)
+ rReq.RemoveItem(FN_QRY_MERGE);
+ bool bFromMerge = pPrintFromMergeItem && pPrintFromMergeItem->GetValue();
+ bool bPrintSelection = false;
+ if(!bSilent && !bFromMerge &&
+ SW_MOD()->GetModuleConfig()->IsAskForMailMerge() && pSh->IsAnyDatabaseFieldInDoc())
+ {
+ std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetEditWin().GetFrameWeld(), "modules/swriter/ui/printmergedialog.ui"));
+ std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("PrintMergeDialog"));
+ short nRet = xBox->run();
+ if(RET_NO != nRet)
+ {
+ if(RET_YES == nRet)
+ {
+ SfxBoolItem aBool(FN_QRY_MERGE, true);
+ GetViewFrame().GetDispatcher()->ExecuteList(
+ FN_QRY_MERGE, SfxCallMode::ASYNCHRON,
+ { &aBool });
+ rReq.Ignore();
+ }
+ return;
+ }
+ }
+ else if( rReq.GetSlot() == SID_PRINTDOCDIRECT && ! bSilent )
+ {
+ if( pSh->IsSelection() || pSh->IsFrameSelected() || pSh->IsObjSelected() )
+ {
+ SvxPrtQryBox aBox(GetEditWin().GetFrameWeld());
+ short nBtn = aBox.run();
+ if( RET_CANCEL == nBtn )
+ return;
+
+ if( RET_OK == nBtn )
+ bPrintSelection = true;
+ }
+ }
+
+ //#i61455# if master documents are printed silently without loaded links then update the links now
+ if( bSilent && pSh->IsGlobalDoc() && !pSh->IsGlblDocSaveLinks() )
+ {
+ pSh->GetLinkManager().UpdateAllLinks( false, false, nullptr );
+ }
+ SfxRequest aReq( rReq );
+ SfxBoolItem aBool(SID_SELECTION, bPrintSelection);
+ aReq.AppendItem( aBool );
+ SfxViewShell::ExecuteSlot( aReq, SfxViewShell::GetInterface() );
+ return;
+ }
+ default:
+ OSL_ENSURE(false, "wrong dispatcher");
+ return;
+ }
+}
+
+int SwView::getPart() const
+{
+ return 0;
+}
+
+void SwView::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwView"));
+ SfxViewShell::dumpAsXml(pWriter);
+ if (m_pWrtShell)
+ m_pWrtShell->dumpAsXml(pWriter);
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+void SwView::SetRedlineAuthor(const OUString& rAuthor)
+{
+ m_pViewImpl->m_sRedlineAuthor = rAuthor;
+}
+
+const OUString& SwView::GetRedlineAuthor() const
+{
+ return m_pViewImpl->m_sRedlineAuthor;
+}
+
+void SwView::NotifyCursor(SfxViewShell* pViewShell) const
+{
+ m_pWrtShell->NotifyCursor(pViewShell);
+}
+
+::Color SwView::GetColorConfigColor(svtools::ColorConfigEntry nColorType) const
+{
+ if (const SwViewOption* pViewOptions = GetWrtShell().GetViewOptions())
+ {
+ switch (nColorType)
+ {
+ case svtools::ColorConfigEntry::DOCCOLOR:
+ {
+ return pViewOptions->GetDocColor();
+ }
+ // Should never be called for an unimplemented color type
+ default:
+ {
+ O3TL_UNREACHABLE;
+ }
+ }
+ }
+ else
+ {
+ SAL_WARN("sw", "GetViewOptions() returned nullptr");
+ }
+
+ return {};
+}
+
+// Create page printer/additions for SwView and SwPagePreview
+
+std::unique_ptr<SfxTabPage> CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet &rOptions,
+ bool bPreview)
+{
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc(TP_OPTPRINT_PAGE);
+ OSL_ENSURE(pFact, "No Page Creator");
+ if (!fnCreatePage)
+ return nullptr;
+
+ std::unique_ptr<SfxTabPage> xSfxPage = fnCreatePage(pPage, pController, &rOptions);
+ OSL_ENSURE(xSfxPage, "No page");
+ if (!xSfxPage)
+ return nullptr;
+
+ SfxAllItemSet aSet(*(rOptions.GetPool()));
+ aSet.Put(SfxBoolItem(SID_PREVIEWFLAG_TYPE, bPreview));
+ aSet.Put(SfxBoolItem(SID_FAX_LIST, true));
+ xSfxPage->PageCreated(aSet);
+ return xSfxPage;
+}
+
+void SetAppPrintOptions( SwViewShell* pSh, bool bWeb )
+{
+ const IDocumentDeviceAccess& rIDDA = pSh->getIDocumentDeviceAccess();
+ const SwPrintData& aPrtData = rIDDA.getPrintData();
+
+ if( !rIDDA.getPrinter( false ) )
+ return;
+
+ // Close application own printing options in SfxPrinter.
+ SwAddPrinterItem aAddPrinterItem(aPrtData);
+ SfxItemSetFixed<
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER> aSet( pSh->GetAttrPool() );
+
+ if(bWeb)
+ aSet.Put(SfxUInt16Item(SID_HTML_MODE,
+ ::GetHtmlMode(static_cast<SwWrtShell*>(pSh)->GetView().GetDocShell())));
+ aSet.Put(SfxBoolItem(SID_PRINTER_NOTFOUND_WARN,
+ officecfg::Office::Common::Print::Warning::NotFound::get() ));
+ aSet.Put(aAddPrinterItem);
+ aSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC,
+ static_cast<int>(officecfg::Office::Common::Print::Warning::PaperSize::get()
+ ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE) |
+ static_cast<int>(officecfg::Office::Common::Print::Warning::PaperOrientation::get()
+ ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE )));
+
+ rIDDA.getPrinter( true )->SetOptions( aSet );
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx
new file mode 100644
index 0000000000..5fc92d517b
--- /dev/null
+++ b/sw/source/uibase/uiview/viewsrch.cxx
@@ -0,0 +1,895 @@
+/* -*- 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 <string>
+
+#include <memory>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <hintids.hxx>
+
+#include <sal/log.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+#include <svx/pageitem.hxx>
+#include <svl/whiter.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <svl/srchitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <svx/srchdlg.hxx>
+#include <swmodule.hxx>
+#include <swwait.hxx>
+#include <workctrl.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <swundo.hxx>
+#include <uitool.hxx>
+#include <cmdid.h>
+#include <docsh.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+
+#include <strings.hrc>
+#include <SwRewriter.hxx>
+
+#include <PostItMgr.hxx>
+
+using namespace com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+//Search Parameter
+
+struct SwSearchOptions
+{
+ SwDocPositions eStart, eEnd;
+ bool bDontWrap;
+
+ SwSearchOptions( SwWrtShell const * pSh, bool bBackward );
+};
+
+/// Adds rMatches using rKey as a key to the rTree tree.
+static void lcl_addContainerToJson(boost::property_tree::ptree& rTree, const OString& rKey, const std::vector<OString>& rMatches)
+{
+ boost::property_tree::ptree aChildren;
+
+ for (const OString& rMatch : rMatches)
+ {
+ boost::property_tree::ptree aChild;
+ aChild.put("part", "0");
+ aChild.put("rectangles", rMatch.getStr());
+ aChildren.push_back(std::make_pair("", aChild));
+ }
+
+ rTree.add_child(rKey.getStr(), aChildren);
+}
+
+/// Emits LOK callbacks (count, selection) for search results.
+static void lcl_emitSearchResultCallbacks(SvxSearchItem const * pSearchItem, SwWrtShell const * pWrtShell, bool bHighlightAll)
+{
+ // Emit a callback also about the selection rectangles, grouped by matches.
+ SwPaM* pPaM = pWrtShell->GetCursor();
+ if (!pPaM)
+ return;
+
+ std::vector<OString> aMatches;
+ for (SwPaM& rPaM : pPaM->GetRingContainer())
+ {
+ if (SwShellCursor* pShellCursor = dynamic_cast<SwShellCursor*>(&rPaM))
+ {
+ std::vector<OString> aSelectionRectangles;
+ pShellCursor->SwSelPaintRects::Show(&aSelectionRectangles);
+ std::vector<OString> aRect;
+ for (const OString & rSelectionRectangle : aSelectionRectangles)
+ {
+ if (rSelectionRectangle.isEmpty())
+ continue;
+ aRect.push_back(rSelectionRectangle);
+ }
+ OString sRect = comphelper::string::join("; ", aRect);
+ aMatches.push_back(sRect);
+ }
+ }
+ boost::property_tree::ptree aTree;
+ aTree.put("searchString", pSearchItem->GetSearchString().toUtf8().getStr());
+ aTree.put("highlightAll", bHighlightAll);
+ lcl_addContainerToJson(aTree, "searchResultSelection"_ostr, aMatches);
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ OString aPayload( aStream.str() );
+
+ pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION, aPayload);
+
+ if(bHighlightAll)
+ { // FindAll disables this during find, do it once when done.
+ SfxLokHelper::notifyUpdate(pWrtShell->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION);
+ SfxLokHelper::notifyOtherViewsUpdatePerViewId(pWrtShell->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION);
+ }
+}
+
+void SwView::ExecSearch(SfxRequest& rReq)
+{
+ GetWrtShell().addCurrentPosition();
+
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ bool bQuiet = false;
+ if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SEARCH_QUIET, false, &pItem))
+ bQuiet = static_cast<const SfxBoolItem*>( pItem)->GetValue();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ if (nSlot == FN_REPEAT_SEARCH && !s_pSrchItem)
+ {
+ if(bQuiet)
+ {
+ rReq.SetReturnValue(SfxBoolItem(nSlot, false));
+ nSlot = 0;
+ }
+ }
+ if( m_pWrtShell->IsBlockMode() )
+ m_pWrtShell->LeaveBlockMode();
+ switch (nSlot)
+ {
+ // for now do nothing
+ case SID_SEARCH_ITEM:
+ {
+ delete s_pSrchItem;
+ s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
+ }
+ break;
+
+ case FID_SEARCH_ON:
+ s_bJustOpened = true;
+ GetViewFrame().GetBindings().Invalidate(SID_SEARCH_ITEM);
+ break;
+
+ case FID_SEARCH_OFF:
+ if(pArgs)
+ {
+ // Unregister dialog
+ delete s_pSrchItem;
+ s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
+
+ s_xSearchList.reset();
+ s_xReplaceList.reset();
+
+ SvxSearchDialog *const pSrchDlg(GetSearchDialog());
+ if (pSrchDlg)
+ {
+ // We will remember the search-/replace items.
+ const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList();
+ if( nullptr != pList && pList->Count() )
+ s_xSearchList.reset(new SearchAttrItemList( *pList ));
+
+ pList = pSrchDlg->GetReplaceItemList();
+ if (nullptr != pList && pList->Count())
+ s_xReplaceList.reset(new SearchAttrItemList( *pList ));
+ }
+ }
+ break;
+
+ case FN_REPEAT_SEARCH:
+ case FID_SEARCH_NOW:
+ {
+ sal_uInt16 nMoveType = SwView::GetMoveType();
+ {
+ if(FID_SEARCH_NOW == nSlot && !rReq.IsAPI())
+ SwView::SetMoveType(NID_SRCH_REP);
+ }
+
+ SvxSearchDialog * pSrchDlg(GetSearchDialog());
+ if (pSrchDlg)
+ {
+ s_xSearchList.reset();
+ s_xReplaceList.reset();
+
+ const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList();
+ if( nullptr != pList && pList->Count() )
+ s_xSearchList.reset(new SearchAttrItemList( *pList ));
+
+ pList = pSrchDlg->GetReplaceItemList();
+ if (nullptr != pList && pList->Count())
+ s_xReplaceList.reset(new SearchAttrItemList( *pList ));
+ }
+
+ if (nSlot == FN_REPEAT_SEARCH)
+ {
+ OSL_ENSURE(s_pSrchItem, "SearchItem missing");
+ if( !s_pSrchItem )
+ s_pSrchItem = new SvxSearchItem(SID_SEARCH_ITEM);
+ }
+ else
+ {
+ // Get SearchItem from request
+ OSL_ENSURE(pArgs, "Args missing");
+ if ( pArgs )
+ {
+ delete s_pSrchItem;
+ s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
+ }
+ }
+ SvxSearchCmd eCommand = s_pSrchItem->GetCommand();
+ switch (eCommand)
+ {
+ case SvxSearchCmd::FIND:
+ {
+ bool bRet = SearchAndWrap(bQuiet);
+ if( bRet )
+ {
+ Scroll(m_pWrtShell->GetCharRect().SVRect());
+ if (comphelper::LibreOfficeKit::isActive())
+ lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ false);
+ }
+ rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
+
+ GetDocShell()->Broadcast(SfxHint(SfxHintId::SwNavigatorUpdateTracking));
+ }
+ break;
+ case SvxSearchCmd::FIND_ALL:
+ {
+ // Disable LOK selection notifications during search.
+ m_pWrtShell->GetSfxViewShell()->setTiledSearching(true);
+ const auto nFound = SearchAll();
+ m_pWrtShell->GetSfxViewShell()->setTiledSearching(false);
+
+ GetDocShell()->Broadcast(
+ SfxHint(SfxHintId::SwNavigatorUpdateTracking));
+ GetDocShell()->Broadcast(
+ SfxHint(SfxHintId::SwNavigatorSelectOutlinesWithSelections));
+
+ if (nFound == 0)
+ {
+#if HAVE_FEATURE_DESKTOP
+ if( !bQuiet )
+ {
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+ }
+#endif
+ s_bFound = false;
+ }
+ else
+ {
+ if (comphelper::LibreOfficeKit::isActive())
+ lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ true);
+ if (!bQuiet)
+ {
+ OUString sText(SwResId(STR_SEARCH_KEY_FOUND_TIMES));
+ sText = sText.replaceFirst("%1", OUString::number(nFound));
+ SvxSearchDialogWrapper::SetSearchLabel(sText);
+ }
+ }
+ rReq.SetReturnValue(SfxBoolItem(nSlot, nFound != 0));
+ }
+ break;
+ case SvxSearchCmd::REPLACE:
+ {
+
+ // 1) Replace selection (Not if only attributes should be replaced)
+//JP 27.04.95: Why?
+// what if you only want to assign attributes to the found??
+
+ SvxSearchCmd nCmd = SvxSearchCmd::FIND;
+ if( !s_pSrchItem->GetReplaceString().isEmpty() ||
+ !s_xReplaceList )
+ {
+ // Prevent, that the replaced string will be found again
+ // if the replacement string is containing the search string.
+ bool bBack = s_pSrchItem->GetBackward();
+ if (bBack)
+ m_pWrtShell->Push();
+ OUString aReplace( s_pSrchItem->GetReplaceString() );
+ i18nutil::SearchOptions2 aTmp( s_pSrchItem->GetSearchOptions() );
+ std::optional<OUString> xBackRef = sw::ReplaceBackReferences(aTmp,
+ m_pWrtShell->GetCursor(), m_pWrtShell->GetLayout());
+ if( xBackRef )
+ s_pSrchItem->SetReplaceString( *xBackRef );
+ Replace();
+ if( xBackRef )
+ {
+ s_pSrchItem->SetReplaceString( aReplace );
+ }
+ if (bBack)
+ {
+ m_pWrtShell->Pop();
+ m_pWrtShell->SwapPam();
+ }
+ }
+ else if( s_xReplaceList )
+ nCmd = SvxSearchCmd::REPLACE;
+
+ // 2) Search further (without replacing!)
+
+ SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand();
+ s_pSrchItem->SetCommand( nCmd );
+ bool bRet = SearchAndWrap(bQuiet);
+ if( bRet )
+ Scroll( m_pWrtShell->GetCharRect().SVRect());
+ s_pSrchItem->SetCommand( nOldCmd );
+ rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
+ }
+ break;
+
+ case SvxSearchCmd::REPLACE_ALL:
+ {
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+ s_bExtra = false;
+ sal_uLong nFound;
+
+ { //Scope for SwWait-Object
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+
+ // i#8288 "replace all" should not change cursor
+ // position, so save current cursor
+ m_pWrtShell->Push();
+
+ if (!s_pSrchItem->GetSelection())
+ {
+ // if we don't want to search in the selection...
+ m_pWrtShell->KillSelection(nullptr, false);
+ if (SwDocPositions::Start == aOpts.eEnd)
+ {
+ m_pWrtShell->EndOfSection();
+ }
+ else
+ {
+ m_pWrtShell->StartOfSection();
+ }
+ }
+ nFound = FUNC_Search( aOpts );
+ // create it just to overwrite it with stack cursor
+ m_pWrtShell->CreateCursor();
+ // i#8288 restore the original cursor position
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ m_pWrtShell->EndAllAction();
+ }
+
+ rReq.SetReturnValue(SfxBoolItem(nSlot, nFound != 0 && ULONG_MAX != nFound));
+ if( !nFound )
+ {
+#if HAVE_FEATURE_DESKTOP
+ if( !bQuiet )
+ {
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+ }
+#endif
+ s_bFound = false;
+ SwView::SetMoveType(nMoveType);
+ return;
+ }
+
+ if( !bQuiet && ULONG_MAX != nFound)
+ {
+ OUString sText( SwResId( STR_NB_REPLACED ) );
+ sText = sText.replaceFirst("XX", OUString::number( nFound ));
+ SvxSearchDialogWrapper::SetSearchLabel(sText);
+ }
+ }
+ break;
+ }
+
+ uno::Reference< frame::XDispatchRecorder > xRecorder =
+ GetViewFrame().GetBindings().GetRecorder();
+ //prevent additional dialogs in recorded macros
+ if ( xRecorder.is() )
+ rReq.AppendItem(SfxBoolItem(SID_SEARCH_QUIET, true));
+
+ rReq.Done();
+ m_eLastSearchCommand = s_pSrchItem->GetCommand();
+ SwView::SetMoveType(nMoveType);
+ }
+ break;
+ case FID_SEARCH_SEARCHSET:
+ case FID_SEARCH_REPLACESET:
+ {
+ static const WhichRangesContainer aNormalAttr(svl::Items<
+/* 0 */ RES_CHRATR_CASEMAP, RES_CHRATR_CASEMAP,
+/* 2 */ RES_CHRATR_COLOR, RES_CHRATR_POSTURE,
+/* 4 */ RES_CHRATR_SHADOWED, RES_CHRATR_WORDLINEMODE,
+/* 6 */ RES_CHRATR_BLINK, RES_CHRATR_BLINK,
+/* 8 */ RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND,
+/*10 */ RES_CHRATR_ROTATE, RES_CHRATR_ROTATE,
+/*12 */ RES_CHRATR_SCALEW, RES_CHRATR_RELIEF,
+/*14 */ RES_CHRATR_OVERLINE, RES_CHRATR_OVERLINE,
+/*16 */ RES_PARATR_LINESPACING, RES_PARATR_HYPHENZONE,
+/*18 */ RES_PARATR_REGISTER, RES_PARATR_REGISTER,
+/*20 */ RES_PARATR_VERTALIGN, RES_PARATR_VERTALIGN,
+ RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT,
+ RES_UL_SPACE, RES_UL_SPACE,
+/*24 */ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP
+ >);
+
+ SfxItemSet aSet(m_pWrtShell->GetAttrPool(), aNormalAttr);
+
+ if( SvtCTLOptions::IsCTLFontEnabled() )
+ {
+ aSet.MergeRange(RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_WEIGHT);
+ }
+ if( SvtCJKOptions::IsAnyEnabled() )
+ {
+ aSet.MergeRange(RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_WEIGHT);
+ aSet.MergeRange(RES_CHRATR_EMPHASIS_MARK, RES_CHRATR_TWO_LINES);
+ aSet.MergeRange(RES_PARATR_SCRIPTSPACE, RES_PARATR_FORBIDDEN_RULES);
+ }
+
+ TypedWhichId<SvxSetItem> nWhich = SID_SEARCH_SEARCHSET;
+
+ if ( FID_SEARCH_REPLACESET == nSlot )
+ {
+ nWhich = SID_SEARCH_REPLACESET;
+
+ if ( s_xReplaceList )
+ {
+ s_xReplaceList->Get( aSet );
+ s_xReplaceList.reset();
+ }
+ }
+ else if ( s_xSearchList )
+ {
+ s_xSearchList->Get( aSet );
+ s_xSearchList.reset();
+ }
+ rReq.SetReturnValue( SvxSetItem( nWhich, aSet ) );
+ }
+ break;
+ default:
+ SAL_WARN_IF( nSlot, "sw", "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)" );
+ return;
+ }
+}
+
+bool SwView::SearchAndWrap(bool bApi)
+{
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+
+ // Remember starting position of the search for wraparound
+ // Start- / EndAction perhaps because existing selections of 'search all'
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->Push();
+
+ // After a search all action we place the cursor at the beginning of
+ // the document so that the single search selects the first matching
+ // occurrence in the document instead of the second.
+ if( m_eLastSearchCommand == SvxSearchCmd::FIND_ALL )
+ {
+ if( SwDocPositions::Start == aOpts.eEnd )
+ m_pWrtShell->EndOfSection();
+ else
+ m_pWrtShell->StartOfSection();
+ }
+
+ // fdo#65014 : Ensure that the point of the cursor is at the extremity of the
+ // selection closest to the end being searched to as to exclude the selected
+ // region from the search. (This doesn't work in the case of multiple
+ // selected regions as the cursor doesn't mark the selection in that case.)
+ m_pWrtShell->GetCursor()->Normalize( s_pSrchItem->GetBackward() );
+
+ if (!m_pWrtShell->HasSelection() && (s_pSrchItem->HasStartPoint()))
+ {
+ // No selection -> but we have a start point (top left corner of the
+ // current view), start searching from there, not from the current
+ // cursor position.
+ SwEditShell& rShell = GetWrtShell();
+ Point aPosition(s_pSrchItem->GetStartPointX(), s_pSrchItem->GetStartPointY());
+ rShell.SetCursor(aPosition);
+ }
+
+ // If you want to search in selected areas, they must not be unselected.
+ if (!s_pSrchItem->GetSelection())
+ m_pWrtShell->KillSelection(nullptr, false);
+
+ std::optional<SwWait> oWait( std::in_place, *GetDocShell(), true );
+ if( FUNC_Search( aOpts ) )
+ {
+ s_bFound = true;
+ if(m_pWrtShell->IsSelFrameMode())
+ {
+ m_pWrtShell->UnSelectFrame();
+ m_pWrtShell->LeaveSelFrameMode();
+ }
+ m_pWrtShell->Pop();
+ m_pWrtShell->EndAllAction();
+ return true;
+ }
+ oWait.reset();
+
+ // Search in the specialized areas when no search is present in selections.
+ // When searching selections will already searched in these special areas.
+ bool bHasSrchInOther = s_bExtra;
+ if (!s_pSrchItem->GetSelection() && !s_bExtra )
+ {
+ s_bExtra = true;
+ if( FUNC_Search( aOpts ) )
+ {
+ s_bFound = true;
+ m_pWrtShell->Pop();
+ m_pWrtShell->EndAllAction();
+ return true;
+ }
+ s_bExtra = false;
+ }
+ else
+ s_bExtra = !s_bExtra;
+
+ // If starting position is at the end or beginning of the document.
+ if (aOpts.bDontWrap)
+ {
+ m_pWrtShell->EndAllAction();
+ if( !bApi )
+ {
+#if HAVE_FEATURE_DESKTOP
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+#endif
+ }
+ s_bFound = false;
+ m_pWrtShell->Pop();
+ return false;
+ }
+ m_pWrtShell->EndAllAction();
+ // Try again with WrapAround?
+
+ m_pWrtShell->StartAllAction();
+ m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ oWait.emplace( *GetDocShell(), true );
+
+ bool bSrchBkwrd = SwDocPositions::Start == aOpts.eEnd;
+
+ aOpts.eEnd = bSrchBkwrd ? SwDocPositions::Start : SwDocPositions::End;
+ aOpts.eStart = bSrchBkwrd ? SwDocPositions::End : SwDocPositions::Start;
+
+ if (bHasSrchInOther)
+ {
+ m_pWrtShell->ClearMark();
+ // Select the start or the end of the entire document
+ if (bSrchBkwrd)
+ m_pWrtShell->SttEndDoc(false);
+ else
+ m_pWrtShell->SttEndDoc(true);
+ }
+
+ s_bFound = bool(FUNC_Search( aOpts ));
+
+ // If WrapAround found no matches in the body text, search in the special
+ // sections, too.
+ if (!s_bFound && !s_pSrchItem->GetSelection() && !s_bExtra)
+ {
+ s_bExtra = true;
+ if (FUNC_Search(aOpts))
+ s_bFound = true;
+ else
+ s_bExtra = false;
+ }
+
+ m_pWrtShell->EndAllAction();
+ oWait.reset();
+#if HAVE_FEATURE_DESKTOP
+ if (s_bFound)
+ {
+ if (!bSrchBkwrd)
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::End);
+ else
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Start);
+ }
+ else if(!bApi)
+ {
+ m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8());
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
+ }
+#endif
+ return s_bFound;
+}
+
+sal_uInt16 SwView::SearchAll()
+{
+ SwWait aWait( *GetDocShell(), true );
+ m_pWrtShell->StartAllAction();
+
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+
+ if (!s_pSrchItem->GetSelection())
+ {
+ // Cancel existing selections, if should not be sought in selected areas.
+ m_pWrtShell->KillSelection(nullptr, false);
+
+ if( SwDocPositions::Start == aOpts.eEnd )
+ m_pWrtShell->EndOfSection();
+ else
+ m_pWrtShell->StartOfSection();
+ }
+ s_bExtra = false;
+ sal_uInt16 nFound = o3tl::narrowing<sal_uInt16>(FUNC_Search( aOpts ));
+ s_bFound = 0 != nFound;
+
+ m_pWrtShell->EndAllAction();
+ return nFound;
+}
+
+void SwView::Replace()
+{
+ SwWait aWait( *GetDocShell(), true );
+
+ m_pWrtShell->StartAllAction();
+
+ if( s_pSrchItem->GetPattern() ) // Templates?
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UndoArg1, s_pSrchItem->GetSearchString());
+ aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+ aRewriter.AddRule(UndoArg3, s_pSrchItem->GetReplaceString());
+
+ m_pWrtShell->StartUndo(SwUndoId::UI_REPLACE_STYLE, &aRewriter);
+
+ m_pWrtShell->SetTextFormatColl( m_pWrtShell->GetParaStyle(
+ s_pSrchItem->GetReplaceString(),
+ SwWrtShell::GETSTYLE_CREATESOME ));
+
+ m_pWrtShell->EndUndo();
+ }
+ else
+ {
+ if (GetPostItMgr()->HasActiveSidebarWin())
+ GetPostItMgr()->Replace(s_pSrchItem);
+
+ bool bReqReplace = true;
+
+ if(m_pWrtShell->HasSelection())
+ {
+ /* check that the selection match the search string*/
+ //save state
+ SwPosition aStartPos = * m_pWrtShell->GetCursor()->Start();
+ SwPosition aEndPos = * m_pWrtShell->GetCursor()->End();
+ bool bHasSelection = s_pSrchItem->GetSelection();
+ SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand();
+
+ //set state for checking if current selection has a match
+ s_pSrchItem->SetCommand( SvxSearchCmd::FIND );
+ s_pSrchItem->SetSelection(true);
+
+ //check if it matches
+ SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
+ if( ! FUNC_Search(aOpts) )
+ {
+
+ //no matching therefore should not replace selection
+ // => remove selection
+
+ if(! s_pSrchItem->GetBackward() )
+ {
+ (* m_pWrtShell->GetCursor()->Start()) = aStartPos;
+ (* m_pWrtShell->GetCursor()->End()) = aEndPos;
+ }
+ else
+ {
+ (* m_pWrtShell->GetCursor()->Start()) = aEndPos;
+ (* m_pWrtShell->GetCursor()->End()) = aStartPos;
+ }
+ bReqReplace = false;
+ }
+
+ //set back old search state
+ s_pSrchItem->SetCommand( nOldCmd );
+ s_pSrchItem->SetSelection(bHasSelection);
+ }
+ /*
+ * remove current selection
+ * otherwise it is always replaced
+ * no matter if the search string exists or not in the selection
+ * Now the selection is removed and the next matching string is selected
+ */
+
+ if( bReqReplace )
+ {
+
+ bool bReplaced = m_pWrtShell->SwEditShell::Replace( s_pSrchItem->GetReplaceString(),
+ s_pSrchItem->GetRegExp());
+ if( bReplaced && s_xReplaceList && s_xReplaceList->Count() && m_pWrtShell->HasSelection() )
+ {
+ SfxItemSet aReplSet( m_pWrtShell->GetAttrPool(),
+ aTextFormatCollSetRange );
+ if( s_xReplaceList->Get( aReplSet ).Count() )
+ {
+ ::SfxToSwPageDescAttr( *m_pWrtShell, aReplSet );
+ m_pWrtShell->SwEditShell::SetAttrSet( aReplSet );
+ }
+ }
+ }
+ }
+
+ m_pWrtShell->EndAllAction();
+}
+
+SwSearchOptions::SwSearchOptions( SwWrtShell const * pSh, bool bBackward )
+ : eStart(SwDocPositions::Curr)
+{
+ if( bBackward )
+ {
+ eEnd = SwDocPositions::Start;
+ bDontWrap = pSh->IsEndOfDoc();
+ }
+ else
+ {
+ eEnd = SwDocPositions::End;
+ bDontWrap = pSh->IsStartOfDoc();
+ }
+}
+
+sal_uLong SwView::FUNC_Search( const SwSearchOptions& rOptions )
+{
+#if HAVE_FEATURE_DESKTOP
+ SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
+#endif
+ bool bDoReplace = s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE ||
+ s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL;
+
+ FindRanges eRanges = s_pSrchItem->GetSelection()
+ ? FindRanges::InSel
+ : s_bExtra
+ ? FindRanges::InOther : FindRanges::InBody;
+ if (s_pSrchItem->GetCommand() == SvxSearchCmd::FIND_ALL ||
+ s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL)
+ eRanges |= FindRanges::InSelAll;
+
+ m_pWrtShell->SttSelect();
+
+ static const WhichRangesContainer aSearchAttrRange(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_PARA_MODEL, SID_ATTR_PARA_KEEP
+ >);
+
+ SfxItemSet aSrchSet( m_pWrtShell->GetAttrPool(), aSearchAttrRange);
+ if( s_xSearchList && s_xSearchList->Count() )
+ {
+ s_xSearchList->Get( aSrchSet );
+
+ // -- Page break with page template
+ ::SfxToSwPageDescAttr( *m_pWrtShell, aSrchSet );
+ }
+
+ std::optional<SfxItemSet> xReplSet;
+ if( bDoReplace && s_xReplaceList && s_xReplaceList->Count() )
+ {
+ xReplSet.emplace( m_pWrtShell->GetAttrPool(), aSearchAttrRange );
+ s_xReplaceList->Get( *xReplSet );
+
+ // -- Page break with page template
+ ::SfxToSwPageDescAttr( *m_pWrtShell, *xReplSet );
+
+ if( !xReplSet->Count() ) // too bad, we don't know
+ xReplSet.reset(); // the attributes
+ }
+
+ // build SearchOptions to be used
+
+ i18nutil::SearchOptions2 aSearchOpt( s_pSrchItem->GetSearchOptions() );
+ aSearchOpt.Locale = GetAppLanguageTag().getLocale();
+ if( !bDoReplace )
+ aSearchOpt.replaceString.clear();
+
+ sal_Int32 nFound;
+ if( aSrchSet.Count() || ( xReplSet && xReplSet->Count() ))
+ {
+ nFound = m_pWrtShell->SearchAttr(
+ aSrchSet,
+ !s_pSrchItem->GetPattern(),
+ rOptions.eStart,
+ rOptions.eEnd,
+ eRanges,
+ !s_pSrchItem->GetSearchString().isEmpty() ? &aSearchOpt : nullptr,
+ xReplSet ? &*xReplSet : nullptr );
+ }
+ else if( s_pSrchItem->GetPattern() )
+ {
+ // Searching (and replacing) templates
+ const OUString& sRplStr( s_pSrchItem->GetReplaceString() );
+ nFound = m_pWrtShell->SearchTempl( s_pSrchItem->GetSearchString(),
+ rOptions.eStart,
+ rOptions.eEnd,
+ eRanges,
+ bDoReplace ? &sRplStr : nullptr );
+ }
+ else
+ {
+ // Normal search
+ nFound = m_pWrtShell->SearchPattern(aSearchOpt, s_pSrchItem->GetNotes(),
+ rOptions.eStart,
+ rOptions.eEnd,
+ eRanges,
+ bDoReplace );
+ }
+ m_pWrtShell->EndSelect();
+ return nFound;
+}
+
+SvxSearchDialog* SwView::GetSearchDialog()
+{
+#if HAVE_FEATURE_DESKTOP
+ const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId();
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (!pViewFrm)
+ return nullptr;
+ SvxSearchDialogWrapper *pWrp = static_cast<SvxSearchDialogWrapper*>(pViewFrm->GetChildWindow(nId));
+ if (!pWrp)
+ return nullptr;
+ return pWrp->getDialog();
+#else
+ return nullptr;
+#endif
+}
+
+void SwView::StateSearch(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_SEARCH_OPTIONS:
+ {
+ SearchOptionFlags nOpt = SearchOptionFlags::ALL;
+ if( GetDocShell()->IsReadOnly() )
+ nOpt &= ~SearchOptionFlags( SearchOptionFlags::REPLACE |
+ SearchOptionFlags::REPLACE_ALL );
+ rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast<sal_uInt16>(nOpt) ));
+ }
+ break;
+ case SID_SEARCH_ITEM:
+ {
+ if ( !s_pSrchItem )
+ {
+ s_pSrchItem = new SvxSearchItem( SID_SEARCH_ITEM );
+ s_pSrchItem->SetFamily(SfxStyleFamily::Para);
+ s_pSrchItem->SetSearchString( m_pWrtShell->GetSelText() );
+ }
+
+ if( s_bJustOpened && m_pWrtShell->IsSelection() )
+ {
+ OUString aText;
+ if( 1 == m_pWrtShell->GetCursorCnt() &&
+ !( aText = m_pWrtShell->SwCursorShell::GetSelText() ).isEmpty() )
+ {
+ s_pSrchItem->SetSearchString( aText );
+ s_pSrchItem->SetSelection( false );
+ }
+ else
+ s_pSrchItem->SetSelection( true );
+ }
+
+ s_bJustOpened = false;
+ rSet.Put( *s_pSrchItem );
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewstat.cxx b/sw/source/uibase/uiview/viewstat.cxx
new file mode 100644
index 0000000000..3c624274f4
--- /dev/null
+++ b/sw/source/uibase/uiview/viewstat.cxx
@@ -0,0 +1,691 @@
+/* -*- 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 <memory>
+
+#include <hintids.hxx>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <svl/whiter.hxx>
+#include <svl/cjkoptions.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/imageitm.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <sfx2/htmlmode.hxx>
+#include <swmodule.hxx>
+#include <tox.hxx>
+#include <sfx2/dispatch.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <uitool.hxx>
+#include <viewopt.hxx>
+#include <pagedesc.hxx>
+#include <wview.hxx>
+#include <globdoc.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <svl/visitem.hxx>
+#include <redline.hxx>
+#include <rootfrm.hxx>
+#include <docary.hxx>
+#include <sfx2/infobar.hxx>
+#include <docsh.hxx>
+#include <strings.hrc>
+
+#include <cmdid.h>
+#include <IDocumentRedlineAccess.hxx>
+
+#include <doc.hxx>
+#include <workctrl.hxx>
+
+using namespace ::com::sun::star;
+
+void SwView::GetState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ FrameTypeFlags eFrameType = FrameTypeFlags::NONE;
+ bool bGetFrameType = false;
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+
+ while(nWhich)
+ {
+ switch(nWhich)
+ {
+ case SID_ZOOM_IN:
+ case SID_ZOOM_OUT:
+ {
+ tools::Long nFact = m_pWrtShell->GetViewOptions()->GetZoom();
+ if ((SID_ZOOM_IN == nWhich && nFact >= tools::Long(600)) ||
+ (SID_ZOOM_OUT == nWhich && nFact <= tools::Long(20)))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case FN_TOGGLE_OUTLINE_CONTENT_VISIBILITY:
+ {
+ bool bDisable(true);
+ if (m_pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ SwOutlineNodes::size_type nPos = m_pWrtShell->GetOutlinePos();
+ if (nPos != SwOutlineNodes::npos)
+ bDisable = false;
+ }
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_NAV_ELEMENT:
+ // used to update all instances of this control
+ rSet.InvalidateItem( nWhich );
+ break;
+ case FN_SCROLL_PREV:
+ case FN_SCROLL_NEXT:
+ {
+ if (s_nMoveType == NID_RECENCY)
+ {
+ if (!m_pWrtShell->GetNavigationMgr().forwardEnabled())
+ rSet.DisableItem(FN_SCROLL_NEXT);
+ if (!m_pWrtShell->GetNavigationMgr().backEnabled())
+ rSet.DisableItem(FN_SCROLL_PREV);
+ }
+ }
+ break;
+ case FN_EDIT_LINK_DLG:
+ if( m_pWrtShell->GetLinkManager().GetLinks().empty() )
+ rSet.DisableItem(nWhich);
+ else if( m_pWrtShell->IsSelFrameMode() &&
+ m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE)
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_DRAWTBX_LINES:
+ if ( bWeb )
+ rSet.DisableItem(nWhich);
+ break;
+
+ case SID_INSERT_GRAPHIC:
+ if( m_pWrtShell->CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_INSERT_SIGNATURELINE:
+ if( !( m_nSelectionType & SelectionType::Text ||
+ m_nSelectionType & SelectionType::NumberList ) )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_EDIT_SIGNATURELINE:
+ case SID_SIGN_SIGNATURELINE:
+ if (!isSignatureLineSelected() || isSignatureLineSigned())
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_INSERT_QRCODE:
+ if( !( m_nSelectionType & SelectionType::Text ||
+ m_nSelectionType & SelectionType::NumberList ) )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_EDIT_QRCODE:
+ if (!isQRCodeSelected())
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_INSERT_CAPTION:
+ {
+ // There are captions for graphics, OLE objects, frames and tables
+ if( !bGetFrameType )
+ {
+ eFrameType = m_pWrtShell->GetFrameType(nullptr, true);
+ bGetFrameType = true;
+ }
+ if (! ( ((eFrameType & FrameTypeFlags::FLY_ANY) && m_nSelectionType != SelectionType::DrawObjectEditMode)||
+ m_nSelectionType & SelectionType::Table ||
+ m_nSelectionType & SelectionType::DrawObject) )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else if((m_pWrtShell->IsObjSelected() || m_pWrtShell->IsFrameSelected()) &&
+ (m_pWrtShell->IsSelObjProtected( FlyProtectFlags::Parent) != FlyProtectFlags::NONE ||
+ m_pWrtShell->IsSelObjProtected( FlyProtectFlags::Content ) != FlyProtectFlags::NONE))
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else if( m_pWrtShell->IsTableMode()
+ || isSignatureLineSelected()
+ || m_pWrtShell->CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+
+ case FN_EDIT_FOOTNOTE:
+ {
+ if( !m_pWrtShell->GetCurFootnote() )
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_CHANGE_PAGENUM:
+ {
+ FrameTypeFlags nType = m_pWrtShell->GetFrameType(nullptr,true);
+ if( ( FrameTypeFlags::FLY_ANY | FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER |
+ FrameTypeFlags::FOOTNOTE | FrameTypeFlags::DRAWOBJ ) & nType )
+ rSet.DisableItem(nWhich);
+ else
+ rSet.Put(SfxUInt16Item(nWhich, m_pWrtShell->GetPageOffset()));
+ }
+ break;
+ case SID_PRINTDOC:
+ case SID_PRINTDOCDIRECT:
+ GetSlotState( nWhich, SfxViewShell::GetInterface(), &rSet );
+ break;
+ case SID_ATTR_PAGE_ORIENTATION:
+ case SID_ATTR_PAGE:
+ case SID_ATTR_PAGE_SIZE:
+ case SID_ATTR_PAGE_PAPERBIN:
+ case RES_PAPER_BIN:
+ case FN_PARAM_FTN_INFO:
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ const SwPageDesc& rDesc = m_pWrtShell->GetPageDesc( nCurIdx );
+
+ // set correct parent to get the XFILL_NONE FillStyle as needed
+ if(!rSet.GetParent())
+ {
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+
+ rSet.SetParent(&rMaster.GetDoc()->GetDfltFrameFormat()->GetAttrSet());
+ }
+
+ ::PageDescToItemSet( rDesc, rSet);
+
+ if (nWhich == SID_ATTR_PAGE_ORIENTATION && comphelper::LibreOfficeKit::isActive())
+ {
+ OString aPayload = ".uno:Orientation="_ostr;
+ if (rDesc.GetLandscape())
+ {
+ aPayload += "IsLandscape";
+ }
+ else
+ {
+ aPayload += "IsPortrait";
+ }
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+ }
+ break;
+ case RES_BACKGROUND:
+ case SID_ATTR_BRUSH:
+ {
+ const size_t nCurIdx = m_pWrtShell->GetCurPageDesc();
+ const SwPageDesc& rDesc = m_pWrtShell->GetPageDesc( nCurIdx );
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ const SvxBrushItem& rBrush = rMaster.GetFormatAttr(RES_BACKGROUND);
+ rSet.Put(rBrush);
+ }
+ break;
+ case SID_CLEARHISTORY:
+ {
+ rSet.Put(SfxBoolItem(nWhich, m_pWrtShell->GetLastUndoInfo(nullptr, nullptr)));
+ }
+ break;
+ case SID_UNDO:
+ {
+ // which must not be present, so let them create:
+ if( !m_pShell )
+ SelectShell();
+
+ const SfxPoolItemHolder aResult(m_pShell->GetSlotState(SID_UNDO));
+ if(nullptr != aResult.getItem())
+ rSet.Put(*aResult.getItem());
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_INSERT_OBJ_CTRL:
+ if( bWeb
+ || m_pWrtShell->CursorInsideInputField() )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case FN_UPDATE_TOX:
+ if(!m_pWrtShell->GetTOXCount())
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_EDIT_CURRENT_TOX:
+ case FN_UPDATE_CUR_TOX:
+ {
+ const SwTOXBase* pBase = nullptr;
+ if(nullptr == (pBase = m_pWrtShell->GetCurTOX()) ||
+ (FN_EDIT_CURRENT_TOX == nWhich && pBase->IsTOXBaseInReadonly()))
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case SID_TWAIN_SELECT:
+ case SID_TWAIN_TRANSFER:
+#if defined(_WIN32) || defined UNX
+ {
+ if(!SW_MOD()->GetScannerManager().is())
+ rSet.DisableItem(nWhich);
+ }
+#endif
+ break;
+ case RES_PARATR_TABSTOP:
+ case SID_ATTR_DEFTABSTOP:
+ {
+ const SvxTabStopItem& rDefTabs = m_pWrtShell->GetDefault(RES_PARATR_TABSTOP);
+ rSet.Put( SfxUInt16Item( nWhich,
+ o3tl::narrowing<sal_uInt16>(::GetTabDist(rDefTabs))));
+ }
+ break;
+ case SID_ATTR_LANGUAGE:
+ {
+ rSet.Put(m_pWrtShell->GetDefault(RES_CHRATR_LANGUAGE).CloneSetWhich(SID_ATTR_LANGUAGE));
+ }
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ {
+ rSet.Put(m_pWrtShell->GetDefault(RES_CHRATR_CJK_LANGUAGE)
+ .CloneSetWhich(RES_CHRATR_CJK_LANGUAGE));
+ }
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ {
+ rSet.Put(m_pWrtShell->GetDefault(RES_CHRATR_CTL_LANGUAGE)
+ .CloneSetWhich(RES_CHRATR_CTL_LANGUAGE));
+ }
+ break;
+ case FN_REDLINE_ON:
+ rSet.Put( SfxBoolItem( nWhich, GetDocShell()->IsChangeRecording() ) );
+ // When the view is new (e.g. on load), show the Hidden Track Changes infobar
+ // if Show Changes is disabled, but recording of changes is enabled
+ // or hidden tracked changes are there already in the document.
+ // Note: the infobar won't be shown, if the Track Changes toolbar is already
+ // enabled, see in sfx2.
+ if ( m_bForceChangesToolbar && m_pWrtShell->GetLayout()->IsHideRedlines() )
+ {
+ bool isRecording = GetDocShell()->IsChangeRecording();
+ bool hasRecorded =
+ m_pWrtShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().size();
+ if ( isRecording || hasRecorded )
+ {
+ GetDocShell()->AppendInfoBarWhenReady(
+ "hiddentrackchanges", SwResId(STR_HIDDEN_CHANGES),
+ SwResId( (isRecording && hasRecorded)
+ ? STR_HIDDEN_CHANGES_DETAIL
+ : isRecording
+ ? STR_HIDDEN_CHANGES_DETAIL2
+ : STR_HIDDEN_CHANGES_DETAIL3 ),
+ InfobarType::INFO);
+ }
+ }
+ m_bForceChangesToolbar = false;
+ break;
+ case FN_REDLINE_PROTECT :
+ rSet.Put( SfxBoolItem( nWhich, GetDocShell()->HasChangeRecordProtection() ) );
+ break;
+ case FN_REDLINE_SHOW:
+ {
+ rSet.Put(SfxBoolItem(nWhich, !m_pWrtShell->GetLayout()->IsHideRedlines()));
+ }
+ break;
+ case SID_AVMEDIA_PLAYER :
+ case FN_REDLINE_ACCEPT :
+ {
+ SfxViewFrame& rVFrame = GetViewFrame();
+ if (rVFrame.KnowsChildWindow(nWhich))
+ rSet.Put(SfxBoolItem( nWhich, rVFrame.HasChildWindow(nWhich)));
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ case FN_REDLINE_ACCEPT_DIRECT:
+ case FN_REDLINE_REJECT_DIRECT:
+ case FN_REDLINE_ACCEPT_TONEXT:
+ case FN_REDLINE_REJECT_TONEXT:
+ {
+ SwDoc *pDoc = m_pWrtShell->GetDoc();
+ SwPaM *pCursor = m_pWrtShell->GetCursor();
+ bool bDisable = false;
+ if (GetDocShell()->HasChangeRecordProtection())
+ bDisable = true;
+ else if (pCursor->HasMark())
+ {
+ // If the selection does not contain redlines, disable accepting/rejecting changes.
+ SwRedlineTable::size_type index = 0;
+ const SwRedlineTable& table = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
+ const SwRangeRedline* redline = table.FindAtPosition( *pCursor->Start(), index );
+ if( redline != nullptr && *redline->Start() == *pCursor->End())
+ redline = nullptr;
+ if( redline == nullptr )
+ {
+ // for table selections, GetCursor() gives only PaM of the first cell,
+ // so extend the redline limit to end of last cell of the selection
+ // TODO: adjust this for column selections, where the selected columns
+ // don't contain any redlines and any tracked row changes, but the
+ // adjacent not selected columns do to avoid false Enable
+ std::optional<SwPosition> oSelectionEnd;
+ if ( m_pWrtShell->IsTableMode() &&
+ m_pWrtShell->GetTableCursor()->GetSelectedBoxesCount() )
+ {
+ const SwSelBoxes& rBoxes = m_pWrtShell->GetTableCursor()->GetSelectedBoxes();
+ const SwStartNode *pSttNd = rBoxes.back()->GetSttNd();
+ const SwNode* pEndNode = pSttNd->GetNodes()[pSttNd->EndOfSectionIndex()];
+ oSelectionEnd.emplace(*pEndNode);
+ }
+ else
+ oSelectionEnd.emplace(*pCursor->End());
+
+ for(; index < table.size(); ++index )
+ {
+ const SwRangeRedline* tmp = table[ index ];
+ if( *tmp->Start() >= *oSelectionEnd )
+ break;
+ if( tmp->HasMark() && tmp->IsVisible())
+ {
+ redline = tmp;
+ break;
+ }
+ }
+ }
+ if( redline == nullptr )
+ bDisable = true;
+ }
+ else
+ {
+ // If the cursor position isn't on a redline, disable
+ // accepting/rejecting changes.
+ SwTableBox* pTableBox;
+ if (nullptr == pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), nullptr) &&
+ // except in the case of an inserted or deleted table row
+ ( !m_pWrtShell->IsCursorInTable() ||
+ (pTableBox = pCursor->Start()->GetNode().GetTableBox() ) == nullptr ||
+ (RedlineType::None == pTableBox->GetRedlineType() &&
+ RedlineType::None == pTableBox->GetUpper()->GetRedlineType()) ) )
+ {
+ bDisable = true;
+ }
+ }
+
+ // LibreOfficeKit wants to handle changes by index, so always allow here.
+ if (bDisable)
+ rSet.DisableItem(nWhich);
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ OString aPayload(".uno:TrackedChangeIndex="_ostr);
+ SwRedlineTable::size_type nRedline = 0;
+ if (pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), &nRedline))
+ aPayload += OString::number(nRedline);
+ libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload);
+ }
+ }
+ break;
+
+ case FN_REDLINE_NEXT_CHANGE:
+ case FN_REDLINE_PREV_CHANGE:
+ {
+ // Enable change navigation if we have any redlines. Ideally we should disable
+ // "Next Change" if we're at or past the last change, and similarly for
+ // "Previous Change"
+ if (0 == m_pWrtShell->GetRedlineCount())
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_THESAURUS:
+ {
+ SwWrtShell &rSh = GetWrtShell();
+ if (2 <= rSh.GetCursorCnt()) // multi selection?
+ rSet.DisableItem(nWhich);
+ else
+ {
+ LanguageType nLang = rSh.GetCurLang();
+
+ // disable "Thesaurus" (menu entry and key shortcut) if the
+ // language is not supported (by default it is enabled)
+ uno::Reference< linguistic2::XThesaurus > xThes( ::GetThesaurus() );
+ if (!xThes.is() || nLang == LANGUAGE_NONE ||
+ !xThes->hasLocale( LanguageTag::convertToLocale( nLang ) ))
+ rSet.DisableItem(nWhich);
+ }
+ }
+ break;
+ case SID_HANGUL_HANJA_CONVERSION:
+ case SID_CHINESE_CONVERSION:
+ {
+ if (!SvtCJKOptions::IsAnyEnabled())
+ {
+ GetViewFrame().GetBindings().SetVisibleState( nWhich, false );
+ rSet.DisableItem(nWhich);
+ }
+ else
+ GetViewFrame().GetBindings().SetVisibleState( nWhich, true );
+ }
+ break;
+ case SID_MAIL_SCROLLBODY_PAGEDOWN:
+ {
+ const tools::Long nBottom = m_pWrtShell->GetDocSize().Height() + DOCUMENTBORDER;
+ const tools::Long nAct = GetVisArea().Bottom();
+ rSet.Put(SfxBoolItem(SID_MAIL_SCROLLBODY_PAGEDOWN, nAct < nBottom ));
+ }
+ break;
+
+ case SID_DOCUMENT_COMPARE:
+ case SID_DOCUMENT_MERGE:
+ if( dynamic_cast<const SwGlobalDocShell* >(GetDocShell()) != nullptr||
+ (SID_DOCUMENT_MERGE == nWhich && m_pWrtShell->getIDocumentRedlineAccess().GetRedlinePassword().hasElements()))
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_VIEW_DATA_SOURCE_BROWSER:
+ if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
+ rSet.Put( SfxVisibilityItem( nWhich, false ) );
+ else
+ rSet.Put( SfxBoolItem( nWhich, GetViewFrame().HasChildWindow( SID_BROWSER ) ) );
+ break;
+ case SID_READONLY_MODE:
+ rSet.Put(SfxBoolItem(nWhich,
+ m_pWrtShell->HasReadonlySel()||GetDocShell()->IsReadOnly()));
+ break;
+ case SID_IMAGE_ORIENTATION:
+ {
+ SfxImageItem aImageItem(nWhich);
+ if(m_pWrtShell->IsInVerticalText())
+ aImageItem.SetRotation( 2700_deg10 );
+ if(m_pWrtShell->IsInRightToLeftText())
+ aImageItem.SetMirrored( true );
+ rSet.Put(aImageItem);
+ }
+ break;
+ case FN_INSERT_FIELD_DATA_ONLY :
+ if(!m_bInMailMerge && !GetViewFrame().HasChildWindow(nWhich))
+ rSet.DisableItem(nWhich);
+ break;
+ case FN_MAILMERGE_SENDMAIL_CHILDWINDOW:
+ break;
+ case SID_ALIGN_ANY_LEFT :
+ case SID_ALIGN_ANY_HCENTER :
+ case SID_ALIGN_ANY_RIGHT :
+ case SID_ALIGN_ANY_JUSTIFIED:
+ case SID_ALIGN_ANY_TOP :
+ case SID_ALIGN_ANY_VCENTER :
+ case SID_ALIGN_ANY_BOTTOM :
+ case SID_ALIGN_ANY_HDEFAULT :
+ case SID_ALIGN_ANY_VDEFAULT :
+ {
+ if( !m_pShell )
+ SelectShell();
+ sal_uInt16 nAlias = 0;
+ if( m_nSelectionType & (SelectionType::DrawObjectEditMode|SelectionType::Text) )
+ {
+ switch( nWhich )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_ATTR_PARA_ADJUST_LEFT; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_ATTR_PARA_ADJUST_CENTER; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_ATTR_PARA_ADJUST_RIGHT; break;
+ case SID_ALIGN_ANY_JUSTIFIED: nAlias = SID_ATTR_PARA_ADJUST_BLOCK; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_TABLE_VERT_NONE; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_TABLE_VERT_CENTER; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_TABLE_VERT_BOTTOM; break;
+ }
+ }
+ else
+ {
+ switch( nWhich )
+ {
+ case SID_ALIGN_ANY_LEFT : nAlias = SID_OBJECT_ALIGN_LEFT ; break;
+ case SID_ALIGN_ANY_HCENTER : nAlias = SID_OBJECT_ALIGN_CENTER ; break;
+ case SID_ALIGN_ANY_RIGHT : nAlias = SID_OBJECT_ALIGN_RIGHT ; break;
+ case SID_ALIGN_ANY_TOP : nAlias = SID_OBJECT_ALIGN_UP ; break;
+ case SID_ALIGN_ANY_VCENTER : nAlias = SID_OBJECT_ALIGN_MIDDLE ; break;
+ case SID_ALIGN_ANY_BOTTOM : nAlias = SID_OBJECT_ALIGN_DOWN ; break;
+ }
+ }
+ //these slots are either re-mapped to text or object alignment
+ SfxPoolItemHolder aResult;
+ if(nAlias)
+ GetViewFrame().GetDispatcher()->QueryState(nAlias, aResult);
+ if(nullptr != aResult.getItem())
+ {
+ if (!(m_nSelectionType & SelectionType::DrawObject))
+ {
+ rSet.Put(aResult.getItem()->CloneSetWhich(nWhich));
+ }
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwView::GetDrawState(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter(rSet);
+ bool bWeb = dynamic_cast<SwWebView*>( this ) != nullptr;
+
+ for( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich;
+ nWhich = aIter.NextWhich() )
+ switch(nWhich)
+ {
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ case SID_DRAW_MEASURELINE:
+ case SID_DRAW_RECT:
+ case SID_DRAW_ELLIPSE:
+ case SID_DRAW_XPOLYGON_NOFILL:
+ case SID_DRAW_XPOLYGON:
+ case SID_DRAW_POLYGON_NOFILL:
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_BEZIER_NOFILL:
+ case SID_DRAW_BEZIER_FILL:
+ case SID_DRAW_FREELINE_NOFILL:
+ case SID_DRAW_FREELINE:
+ case SID_DRAW_ARC:
+ case SID_DRAW_PIE:
+ case SID_DRAW_CIRCLECUT:
+ case SID_DRAW_TEXT:
+ case SID_DRAW_CAPTION:
+ if ( bWeb )
+ rSet.DisableItem( nWhich );
+ else
+ if (nWhich != SID_DRAW_TEXT) //tdf#113171
+ rSet.Put( SfxBoolItem( nWhich, m_nDrawSfxId == nWhich ) );
+ break;
+
+ case SID_DRAW_TEXT_VERTICAL:
+ case SID_DRAW_CAPTION_VERTICAL:
+ if ( bWeb || !SvtCJKOptions::IsVerticalTextEnabled() )
+ rSet.DisableItem( nWhich );
+ else
+ if (nWhich != SID_DRAW_TEXT_VERTICAL) //tdf#113171
+ rSet.Put( SfxBoolItem( nWhich, m_nDrawSfxId == nWhich ) );
+ break;
+
+ case SID_DRAW_TEXT_MARQUEE:
+ if (::GetHtmlMode(GetDocShell()) & HTMLMODE_SOME_STYLES)
+ rSet.Put( SfxBoolItem(nWhich, m_nDrawSfxId == nWhich));
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ case SID_OBJECT_SELECT:
+ rSet.Put( SfxBoolItem(nWhich, m_nDrawSfxId == nWhich ||
+ m_nFormSfxId == nWhich));
+ break;
+
+ case SID_INSERT_DRAW:
+ case SID_FONTWORK_GALLERY_FLOATER :
+ case SID_DRAWTBX_ARROWS:
+ {
+ if ( bWeb )
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
+ case SID_DRAWTBX_CS_BASIC :
+ case SID_DRAWTBX_CS_SYMBOL :
+ case SID_DRAWTBX_CS_ARROW :
+ case SID_DRAWTBX_CS_FLOWCHART :
+ case SID_DRAWTBX_CS_CALLOUT :
+ case SID_DRAWTBX_CS_STAR :
+ {
+ if ( bWeb )
+ rSet.DisableItem( nWhich );
+ else
+ rSet.Put( SfxStringItem( nWhich, m_nDrawSfxId == nWhich ? m_sDrawCustom : OUString() ) );
+ }
+ break;
+
+ }
+}
+
+bool SwView::HasUIFeature(SfxShellFeature nFeature) const
+{
+ assert((nFeature & ~SfxShellFeature::SwMask) == SfxShellFeature::NONE);
+ switch(nFeature)
+ {
+ case SfxShellFeature::SwChildWindowLabel:
+ return m_pWrtShell->IsLabelDoc();
+ default:
+ return false;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewtab.cxx b/sw/source/uibase/uiview/viewtab.cxx
new file mode 100644
index 0000000000..52a26eabb6
--- /dev/null
+++ b/sw/source/uibase/uiview/viewtab.cxx
@@ -0,0 +1,2562 @@
+/* -*- 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 <hintids.hxx>
+#include <uitool.hxx>
+#include <svx/rulritem.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xfillit0.hxx>
+#include <tools/UnitConversion.hxx>
+#include <editeng/tstpitem.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/whiter.hxx>
+#include <svx/ruler.hxx>
+#include <editeng/protitem.hxx>
+#include <svl/rectitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtclds.hxx>
+#include <fmtornt.hxx>
+#include <frmatr.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <viewopt.hxx>
+#include <tabcol.hxx>
+#include <frmfmt.hxx>
+#include <pagedesc.hxx>
+#include <wview.hxx>
+#include <fmtcol.hxx>
+#include <section.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <boost/property_tree/json_parser.hpp>
+#include <osl/diagnose.h>
+
+#include <IDocumentSettingAccess.hxx>
+
+using namespace ::com::sun::star;
+
+// Pack columns
+static void lcl_FillSvxColumn(const SwFormatCol& rCol,
+ tools::Long nTotalWidth,
+ SvxColumnItem& rColItem,
+ tools::Long nDistance)
+{
+ const SwColumns& rCols = rCol.GetColumns();
+
+ bool bOrtho = rCol.IsOrtho() && !rCols.empty();
+ tools::Long nInnerWidth = 0;
+ if( bOrtho )
+ {
+ nInnerWidth = nTotalWidth;
+ for (const auto & i : rCols)
+ {
+ nInnerWidth -= i.GetLeft() + i.GetRight();
+ }
+ if( nInnerWidth < 0 )
+ nInnerWidth = 0;
+ else
+ nInnerWidth /= rCols.size();
+ }
+
+ tools::Long nWidth = 0;
+ for ( size_t i = 0; i < rCols.size(); ++i )
+ {
+ const SwColumn* pCol = &rCols[i];
+ const tools::Long nStart = pCol->GetLeft() + nWidth + nDistance;
+ if( bOrtho )
+ nWidth += nInnerWidth + pCol->GetLeft() + pCol->GetRight();
+ else
+ nWidth += rCol.CalcColWidth(i, static_cast< sal_uInt16 >(nTotalWidth));
+ const tools::Long nEnd = nWidth - pCol->GetRight() + nDistance;
+
+ SvxColumnDescription aColDesc(nStart, nEnd, true);
+ rColItem.Append(aColDesc);
+ }
+}
+
+// Transfer ColumnItem in ColumnInfo
+static void lcl_ConvertToCols(const SvxColumnItem& rColItem,
+ tools::Long nTotalWidth,
+ SwFormatCol& rCols)
+{
+ OSL_ENSURE( rCols.GetNumCols() == rColItem.Count(), "Column count mismatch" );
+ // ruler executes that change the columns shortly after the selection has changed
+ // can result in a crash
+ if(rCols.GetNumCols() != rColItem.Count())
+ return;
+
+ sal_uInt16 nLeft = 0;
+ SwTwips nSumAll= 0; // Sum up all columns and margins
+
+ SwColumns& rArr = rCols.GetColumns();
+
+ // Tabcols sequentially
+ for( sal_uInt16 i=0; i < rColItem.Count()-1; ++i )
+ {
+ OSL_ENSURE(rColItem[i+1].nStart >= rColItem[i].nEnd,"overlapping columns" );
+ const tools::Long nStart = std::max(rColItem[i+1].nStart, rColItem[i].nEnd);
+ const sal_uInt16 nRight = o3tl::narrowing<sal_uInt16>((nStart - rColItem[i].nEnd) / 2);
+
+ const tools::Long nWidth = rColItem[i].nEnd - rColItem[i].nStart + nLeft + nRight;
+
+ SwColumn* pCol = &rArr[i];
+ pCol->SetWishWidth( sal_uInt16(tools::Long(rCols.GetWishWidth()) * nWidth / nTotalWidth ));
+ pCol->SetLeft( nLeft );
+ pCol->SetRight( nRight );
+ nSumAll += pCol->GetWishWidth();
+
+ nLeft = nRight;
+ }
+ rArr[rColItem.Count()-1].SetLeft( nLeft );
+
+ // The difference between the total sum of the desired width and the so far
+ // calculated columns and margins should result in the width of the last column.
+ rArr[rColItem.Count()-1].SetWishWidth( rCols.GetWishWidth() - o3tl::narrowing<sal_uInt16>(nSumAll) );
+
+ rCols.SetOrtho(false, 0, 0 );
+}
+
+// Delete tabs
+static void lcl_EraseDefTabs(SvxTabStopItem& rTabStops)
+{
+ // Delete DefTabs
+ for ( sal_uInt16 i = 0; i < rTabStops.Count(); )
+ {
+ // Here also throw out the DefTab to zero
+ if ( SvxTabAdjust::Default == rTabStops[i].GetAdjustment() ||
+ rTabStops[i].GetTabPos() == 0 )
+ {
+ rTabStops.Remove(i);
+ continue;
+ }
+ ++i;
+ }
+}
+
+// Flip page margin
+void SwView::SwapPageMargin(const SwPageDesc& rDesc, SvxLRSpaceItem& rLRSpace)
+{
+ sal_uInt16 nPhyPage, nVirPage;
+ GetWrtShell().GetPageNum( nPhyPage, nVirPage );
+
+ if ( rDesc.GetUseOn() == UseOnPage::Mirror && (nPhyPage % 2) == 0 )
+ {
+ tools::Long nTmp = rLRSpace.GetRight();
+ rLRSpace.SetRight( rLRSpace.GetLeft() );
+ rLRSpace.SetLeft( nTmp );
+ }
+}
+
+// If the frame border is moved, the column separator
+// should stay in the same absolute position.
+static void lcl_Scale(tools::Long& nVal, tools::Long nScale)
+{
+ nVal *= nScale;
+ nVal >>= 8;
+}
+
+static void ResizeFrameCols(SwFormatCol& rCol,
+ tools::Long nOldWidth,
+ tools::Long nNewWidth,
+ tools::Long nLeftDelta )
+{
+ SwColumns& rArr = rCol.GetColumns();
+ tools::Long nWishSum = static_cast<tools::Long>(rCol.GetWishWidth());
+ tools::Long nWishDiff = (nWishSum * 100/nOldWidth * nNewWidth) / 100 - nWishSum;
+ tools::Long nNewWishWidth = nWishSum + nWishDiff;
+ if(nNewWishWidth > 0xffffl)
+ {
+ // If the desired width is getting too large, then all values
+ // must be scaled appropriately.
+ tools::Long nScale = (0xffffl << 8)/ nNewWishWidth;
+ for(SwColumn & i : rArr)
+ {
+ SwColumn* pCol = &i;
+ tools::Long nVal = pCol->GetWishWidth();
+ lcl_Scale(nVal, nScale);
+ pCol->SetWishWidth(o3tl::narrowing<sal_uInt16>(nVal));
+ nVal = pCol->GetLeft();
+ lcl_Scale(nVal, nScale);
+ pCol->SetLeft(o3tl::narrowing<sal_uInt16>(nVal));
+ nVal = pCol->GetRight();
+ lcl_Scale(nVal, nScale);
+ pCol->SetRight(o3tl::narrowing<sal_uInt16>(nVal));
+ }
+ lcl_Scale(nNewWishWidth, nScale);
+ lcl_Scale(nWishDiff, nScale);
+ }
+ rCol.SetWishWidth( o3tl::narrowing<sal_uInt16>(nNewWishWidth) );
+
+ if( nLeftDelta >= 2 || nLeftDelta <= -2)
+ rArr.front().SetWishWidth(rArr.front().GetWishWidth() + o3tl::narrowing<sal_uInt16>(nWishDiff));
+ else
+ rArr.back().SetWishWidth(rArr.back().GetWishWidth() + o3tl::narrowing<sal_uInt16>(nWishDiff));
+ // Reset auto width
+ rCol.SetOrtho(false, 0, 0 );
+}
+
+// Here all changes to the tab bar will be shot again into the model.
+void SwView::ExecTabWin( SfxRequest const & rReq )
+{
+ SwWrtShell &rSh = GetWrtShell();
+ const FrameTypeFlags nFrameType = rSh.IsObjSelected() ?
+ FrameTypeFlags::DRAWOBJ :
+ rSh.GetFrameType(nullptr,true);
+ const bool bFrameSelection = rSh.IsFrameSelected();
+ const bool bBrowse = rSh.GetViewOptions()->getBrowseMode();
+
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ const size_t nDescId = rSh.GetCurPageDesc();
+ const SwPageDesc& rDesc = rSh.GetPageDesc( nDescId );
+
+ const bool bVerticalWriting = rSh.IsInVerticalText();
+ const SwFormatHeader& rHeaderFormat = rDesc.GetMaster().GetHeader();
+ SwFrameFormat *pHeaderFormat = const_cast<SwFrameFormat*>(rHeaderFormat.GetHeaderFormat());
+
+ const SwFormatFooter& rFooterFormat = rDesc.GetMaster().GetFooter();
+ SwFrameFormat *pFooterFormat = const_cast<SwFrameFormat*>(rFooterFormat.GetFooterFormat());
+
+ const SwFormatFrameSize &rFrameSize = rDesc.GetMaster().GetFrameSize();
+
+ const SwRect& rPageRect = rSh.GetAnyCurRect(CurRectType::Page);
+ const tools::Long nPageWidth = bBrowse ? rPageRect.Width() : rFrameSize.GetWidth();
+ const tools::Long nPageHeight = bBrowse ? rPageRect.Height() : rFrameSize.GetHeight();
+
+ bool bUnlockView = false;
+ rSh.StartAllAction();
+ bool bSect = bool(nFrameType & FrameTypeFlags::COLSECT);
+
+ switch (nSlot)
+ {
+ case SID_ATTR_LONG_LRSPACE:
+ if ( pReqArgs )
+ {
+ SvxLongLRSpaceItem aLongLR( pReqArgs->Get( SID_ATTR_LONG_LRSPACE ) );
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ if ( !bSect && (bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY) )
+ {
+ SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded);
+
+ bool bVerticalFrame(false);
+ {
+ bool bRTL;
+ bool bVertL2R;
+ bVerticalFrame = ( bFrameSelection &&
+ rSh.IsFrameVertical(true, bRTL, bVertL2R) ) ||
+ ( !bFrameSelection && bVerticalWriting);
+ }
+ tools::Long nDeltaX = bVerticalFrame ?
+ rRect.Right() - rPageRect.Right() + aLongLR.GetRight() :
+ rPageRect.Left() + aLongLR.GetLeft() - rRect.Left();
+
+ SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_VERT_ORIENT, RES_HORI_ORIENT,
+ RES_COL, RES_COL> aSet( GetPool() );
+
+ if(bVerticalFrame)
+ {
+ SwFormatVertOrient aVertOrient(pFormat->GetVertOrient());
+ aVertOrient.SetVertOrient(text::VertOrientation::NONE);
+ aVertOrient.SetPos(aVertOrient.GetPos() + nDeltaX );
+ aSet.Put( aVertOrient );
+ }
+ else
+ {
+ SwFormatHoriOrient aHoriOrient( pFormat->GetHoriOrient() );
+ aHoriOrient.SetHoriOrient( text::HoriOrientation::NONE );
+ aHoriOrient.SetPos( aHoriOrient.GetPos() + nDeltaX );
+ aSet.Put( aHoriOrient );
+ }
+
+ SwFormatFrameSize aSize( pFormat->GetFrameSize() );
+ tools::Long nOldWidth = aSize.GetWidth();
+
+ if(aSize.GetWidthPercent())
+ {
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+ tools::Long nPrtWidth = aRect.Width();
+ aSize.SetWidthPercent(sal_uInt8((nPageWidth - aLongLR.GetLeft() - aLongLR.GetRight()) * 100 /nPrtWidth));
+ }
+ else
+ aSize.SetWidth( nPageWidth -
+ (aLongLR.GetLeft() + aLongLR.GetRight()));
+
+ if( nFrameType & FrameTypeFlags::COLUMN )
+ {
+ SwFormatCol aCol(pFormat->GetCol());
+
+ ::ResizeFrameCols(aCol, nOldWidth, aSize.GetWidth(), nDeltaX );
+ aSet.Put(aCol);
+ }
+
+ aSet.Put( aSize );
+
+ rSh.StartAction();
+ rSh.Push();
+ rSh.SetFlyFrameAttr( aSet );
+ // Cancel the frame selection
+ if(!bFrameSelection && rSh.IsFrameSelected())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.Pop();
+ rSh.EndAction();
+ }
+ else if ( nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER ))
+ {
+ // Subtract out page margins
+ tools::Long nOld = rDesc.GetMaster().GetLRSpace().GetLeft();
+ aLongLR.SetLeft( nOld > aLongLR.GetLeft() ? 0 : aLongLR.GetLeft() - nOld );
+
+ nOld = rDesc.GetMaster().GetLRSpace().GetRight();
+ aLongLR.SetRight( nOld > aLongLR.GetRight() ? 0 : aLongLR.GetRight() - nOld );
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+
+ if ( nFrameType & FrameTypeFlags::HEADER && pHeaderFormat )
+ pHeaderFormat->SetFormatAttr( aLR );
+ else if( nFrameType & FrameTypeFlags::FOOTER && pFooterFormat )
+ pFooterFormat->SetFormatAttr( aLR );
+ }
+ else if( nFrameType == FrameTypeFlags::DRAWOBJ)
+ {
+ SwRect aRect( rSh.GetObjRect() );
+ aRect.Left( aLongLR.GetLeft() + rPageRect.Left() );
+ aRect.Right( rPageRect.Right() - aLongLR.GetRight());
+ rSh.SetObjRect( aRect );
+ }
+ else if(bSect || rSh.IsDirectlyInSection())
+ {
+ //change the section indents and the columns if available
+ //at first determine the changes
+ SwRect aSectRect = rSh.GetAnyCurRect(CurRectType::SectionPrt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section);
+ aSectRect.Pos() += aTmpRect.Pos();
+ tools::Long nLeftDiff = aLongLR.GetLeft() - static_cast<tools::Long>(aSectRect.Left() - rPageRect.Left() );
+ tools::Long nRightDiff = aLongLR.GetRight() - static_cast<tools::Long>( rPageRect.Right() - aSectRect.Right());
+ //change the LRSpaceItem of the section accordingly
+ const SwSection* pCurrSect = rSh.GetCurrSection();
+ const SwSectionFormat* pSectFormat = pCurrSect->GetFormat();
+ SvxLRSpaceItem aLRTmp = pSectFormat->GetLRSpace();
+ aLRTmp.SetLeft(aLRTmp.GetLeft() + nLeftDiff);
+ aLRTmp.SetRight(aLRTmp.GetRight() + nRightDiff);
+ SfxItemSetFixed<RES_LR_SPACE, RES_LR_SPACE, RES_COL, RES_COL> aSet(rSh.GetAttrPool());
+ aSet.Put(aLRTmp);
+ //change the first/last column
+ if(bSect)
+ {
+ SwFormatCol aCols( pSectFormat->GetCol() );
+ tools::Long nDiffWidth = nLeftDiff + nRightDiff;
+ ::ResizeFrameCols(aCols, aSectRect.Width(), aSectRect.Width() - nDiffWidth, nLeftDiff );
+ aSet.Put( aCols );
+ }
+ SwSectionData aData(*pCurrSect);
+ rSh.UpdateSection(rSh.GetSectionFormatPos(*pSectFormat), aData, &aSet);
+ }
+ else
+ { // Adjust page margins
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwapPageMargin( rDesc, aLR );
+ SwPageDesc aDesc( rDesc );
+ aDesc.GetMaster().SetFormatAttr( aLR );
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ }
+ break;
+
+ // apply new left and right margins to current page style
+ case SID_ATTR_PAGE_LRSPACE:
+ if ( pReqArgs )
+ {
+ const SvxLongLRSpaceItem& aLongLR( pReqArgs->Get( SID_ATTR_PAGE_LRSPACE ) );
+
+ SwPageDesc aDesc( rDesc );
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwapPageMargin( rDesc, aLR );
+ aDesc.GetMaster().SetFormatAttr( aLR );
+ }
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ break;
+
+ case SID_ATTR_LONG_ULSPACE:
+ if ( pReqArgs )
+ {
+ SvxLongULSpaceItem aLongULSpace( pReqArgs->Get( SID_ATTR_LONG_ULSPACE ) );
+
+ if( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ {
+ SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded);
+ const tools::Long nDeltaY = rPageRect.Top() + aLongULSpace.GetUpper() - rRect.Top();
+ const tools::Long nHeight = nPageHeight - (aLongULSpace.GetUpper() + aLongULSpace.GetLower());
+
+ SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_VERT_ORIENT, RES_HORI_ORIENT> aSet( GetPool() );
+ //which of the orientation attributes is to be put depends on the frame's environment
+ bool bRTL;
+ bool bVertL2R;
+ if ( ( bFrameSelection &&
+ rSh.IsFrameVertical(true, bRTL, bVertL2R ) ) ||
+ ( !bFrameSelection && bVerticalWriting ) )
+ {
+ SwFormatHoriOrient aHoriOrient(pFormat->GetHoriOrient());
+ aHoriOrient.SetHoriOrient(text::HoriOrientation::NONE);
+ aHoriOrient.SetPos(aHoriOrient.GetPos() + nDeltaY );
+ aSet.Put( aHoriOrient );
+ }
+ else
+ {
+ SwFormatVertOrient aVertOrient(pFormat->GetVertOrient());
+ aVertOrient.SetVertOrient(text::VertOrientation::NONE);
+ aVertOrient.SetPos(aVertOrient.GetPos() + nDeltaY );
+ aSet.Put( aVertOrient );
+ }
+ SwFormatFrameSize aSize(pFormat->GetFrameSize());
+ if(aSize.GetHeightPercent())
+ {
+ SwRect aRect;
+ rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR);
+ tools::Long nPrtHeight = aRect.Height();
+ aSize.SetHeightPercent(sal_uInt8(nHeight * 100 /nPrtHeight));
+ }
+ else
+ aSize.SetHeight(nHeight );
+
+ aSet.Put( aSize );
+ rSh.SetFlyFrameAttr( aSet );
+ }
+ else if( nFrameType == FrameTypeFlags::DRAWOBJ )
+ {
+ SwRect aRect( rSh.GetObjRect() );
+ aRect.Top( aLongULSpace.GetUpper() + rPageRect.Top() );
+ aRect.Bottom( rPageRect.Bottom() - aLongULSpace.GetLower() );
+ rSh.SetObjRect( aRect ) ;
+ }
+ else if(bVerticalWriting && (bSect || rSh.IsDirectlyInSection()))
+ {
+ //change the section indents and the columns if available
+ //at first determine the changes
+ SwRect aSectRect = rSh.GetAnyCurRect(CurRectType::SectionPrt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section);
+ aSectRect.Pos() += aTmpRect.Pos();
+ const tools::Long nLeftDiff = aLongULSpace.GetUpper() - static_cast<tools::Long>(aSectRect.Top() - rPageRect.Top());
+ const tools::Long nRightDiff = aLongULSpace.GetLower() - static_cast<tools::Long>(nPageHeight - aSectRect.Bottom() + rPageRect.Top());
+ //change the LRSpaceItem of the section accordingly
+ const SwSection* pCurrSect = rSh.GetCurrSection();
+ const SwSectionFormat* pSectFormat = pCurrSect->GetFormat();
+ SvxLRSpaceItem aLR = pSectFormat->GetLRSpace();
+ aLR.SetLeft(aLR.GetLeft() + nLeftDiff);
+ aLR.SetRight(aLR.GetRight() + nRightDiff);
+ SfxItemSetFixed<RES_LR_SPACE, RES_LR_SPACE, RES_COL, RES_COL> aSet(rSh.GetAttrPool());
+ aSet.Put(aLR);
+ //change the first/last column
+ if(bSect)
+ {
+ SwFormatCol aCols( pSectFormat->GetCol() );
+ tools::Long nDiffWidth = nLeftDiff + nRightDiff;
+ ::ResizeFrameCols(aCols, aSectRect.Height(), aSectRect.Height() - nDiffWidth, nLeftDiff );
+ aSet.Put( aCols );
+ }
+ SwSectionData aData(*pCurrSect);
+ rSh.UpdateSection(rSh.GetSectionFormatPos(*pSectFormat), aData, &aSet);
+ }
+ else
+ { SwPageDesc aDesc( rDesc );
+
+ if ( nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER ))
+ {
+
+ const bool bHead = bool(nFrameType & FrameTypeFlags::HEADER);
+ SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ if ( bHead )
+ aUL.SetUpper( o3tl::narrowing<sal_uInt16>(aLongULSpace.GetUpper()) );
+ else
+ aUL.SetLower( o3tl::narrowing<sal_uInt16>(aLongULSpace.GetLower()) );
+ aDesc.GetMaster().SetFormatAttr( aUL );
+
+ if( (bHead && pHeaderFormat) || (!bHead && pFooterFormat) )
+ {
+ SwFormatFrameSize aSz( bHead ? pHeaderFormat->GetFrameSize() :
+ pFooterFormat->GetFrameSize() );
+ aSz.SetHeightSizeType( SwFrameSize::Fixed );
+ aSz.SetHeight(nPageHeight - aLongULSpace.GetLower() -
+ aLongULSpace.GetUpper() );
+ if ( bHead )
+ pHeaderFormat->SetFormatAttr( aSz );
+ else
+ pFooterFormat->SetFormatAttr( aSz );
+ }
+ }
+ else
+ {
+ SvxULSpaceItem aUL(RES_UL_SPACE);
+ aUL.SetUpper(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetUpper()));
+ aUL.SetLower(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetLower()));
+ aDesc.GetMaster().SetFormatAttr(aUL);
+ }
+
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ }
+ break;
+
+ // apply new top and bottom margins to current page style
+ case SID_ATTR_PAGE_ULSPACE:
+ if ( pReqArgs )
+ {
+ const SvxLongULSpaceItem& aLongULSpace( pReqArgs->Get( SID_ATTR_PAGE_ULSPACE ) );
+
+ SwPageDesc aDesc( rDesc );
+ {
+ SvxULSpaceItem aUL(RES_UL_SPACE);
+ aUL.SetUpper(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetUpper()));
+ aUL.SetLower(o3tl::narrowing<sal_uInt16>(aLongULSpace.GetLower()));
+ aDesc.GetMaster().SetFormatAttr(aUL);
+ }
+ rSh.ChgPageDesc( nDescId, aDesc );
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLUMN:
+ if ( pReqArgs )
+ {
+ const SfxInt16Item aColumnItem( static_cast<const SfxInt16Item&>(pReqArgs->Get(nSlot)) );
+ const sal_uInt16 nPageColumnType = aColumnItem.GetValue();
+
+ // nPageColumnType =
+ // 1 - single-columned page
+ // 2 - two-columned page
+ // 3 - three-columned page
+ // 4 - two-columned page with left column width of 2/3 of page width
+ // 5 - two-columned page with right column width of 2/3 of page width
+
+ sal_uInt16 nCount = 2;
+ if ( nPageColumnType == 1 )
+ {
+ nCount = 0;
+ }
+ else if ( nPageColumnType == 3 )
+ {
+ nCount = 3;
+ }
+
+ const sal_uInt16 nGutterWidth = 0;
+
+ const SvxLRSpaceItem aLR( rDesc.GetMaster().GetLRSpace() );
+ const tools::Long nLeft = aLR.GetLeft();
+ const tools::Long nRight = aLR.GetRight();
+ const tools::Long nWidth = nPageWidth - nLeft - nRight;
+
+ SwFormatCol aCols( rDesc.GetMaster().GetCol() );
+ aCols.Init( nCount, nGutterWidth, nWidth );
+ aCols.SetWishWidth( nWidth );
+ aCols.SetGutterWidth( nGutterWidth, nWidth );
+ aCols.SetOrtho( false, nGutterWidth, nWidth );
+
+ tools::Long nColumnLeft = 0;
+ tools::Long nColumnRight = 0;
+ if ( nPageColumnType == 4 )
+ {
+ nColumnRight = static_cast<tools::Long>(nWidth/3);
+ nColumnLeft = nWidth - nColumnRight;
+ aCols.GetColumns()[0].SetWishWidth( nColumnLeft );
+ aCols.GetColumns()[1].SetWishWidth( nColumnRight );
+ }
+ else if ( nPageColumnType == 5 )
+ {
+ nColumnLeft = static_cast<tools::Long>(nWidth/3);
+ nColumnRight = nWidth - nColumnLeft;
+ aCols.GetColumns()[0].SetWishWidth( nColumnLeft );
+ aCols.GetColumns()[1].SetWishWidth( nColumnRight );
+ }
+
+ SwPageDesc aDesc( rDesc );
+ aDesc.GetMaster().SetFormatAttr( aCols );
+ rSh.ChgPageDesc( rSh.GetCurPageDesc(), aDesc );
+ }
+ break;
+
+ case SID_ATTR_TABSTOP_VERTICAL:
+ case SID_ATTR_TABSTOP:
+ if (pReqArgs)
+ {
+ const sal_uInt16 nWhich = GetPool().GetWhich(nSlot);
+ SvxTabStopItem aTabStops( static_cast<const SvxTabStopItem&>(pReqArgs->
+ Get( nWhich )));
+ aTabStops.SetWhich(RES_PARATR_TABSTOP);
+ const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+
+ // Default tab at pos 0
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_FIRSTLINE> aSet(GetPool());
+ rSh.GetCurAttr( aSet );
+ const SvxFirstLineIndentItem & rFirstLine(aSet.Get(RES_MARGIN_FIRSTLINE));
+
+ if (rFirstLine.GetTextFirstLineOffset() < 0)
+ {
+ SvxTabStop aSwTabStop( 0, SvxTabAdjust::Default );
+ aTabStops.Insert( aSwTabStop );
+ }
+
+ // Populate with default tabs.
+ ::MakeDefTabs( ::GetTabDist( rDefTabs ), aTabStops );
+
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aTmp(GetPool());
+ aTmp.Put(aTabStops);
+ rSh.AutoUpdatePara( pColl, aTmp );
+ }
+ else
+ rSh.SetAttrItem( aTabStops );
+ }
+ break;
+ case SID_TABSTOP_ADD_OR_CHANGE:
+ if (pReqArgs)
+ {
+ const auto aIndexItem = static_cast<const SfxInt32Item&>(pReqArgs->Get(SID_TABSTOP_ATTR_INDEX));
+ const auto aPositionItem = static_cast<const SfxInt32Item&>(pReqArgs->Get(SID_TABSTOP_ATTR_POSITION));
+ const auto aRemoveItem = static_cast<const SfxBoolItem&>(pReqArgs->Get(SID_TABSTOP_ATTR_REMOVE));
+ const sal_Int32 nIndex = aIndexItem.GetValue();
+ const sal_Int32 nPosition = aPositionItem.GetValue();
+ const bool bRemove = aRemoveItem.GetValue();
+
+
+
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aItemSet(GetPool());
+ rSh.GetCurAttr(aItemSet);
+ SvxTabStopItem aTabStopItem(aItemSet.Get(RES_PARATR_TABSTOP));
+ lcl_EraseDefTabs(aTabStopItem);
+
+ if (nIndex < aTabStopItem.Count())
+ {
+ if (nIndex == -1)
+ {
+ SvxTabStop aSwTabStop(0, SvxTabAdjust::Default);
+ aTabStopItem.Insert(aSwTabStop);
+
+ const SvxTabStopItem& rDefaultTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+ MakeDefTabs(GetTabDist(rDefaultTabs), aTabStopItem);
+
+ SvxTabStop aTabStop(nPosition);
+ aTabStopItem.Insert(aTabStop);
+ }
+ else
+ {
+ SvxTabStop aTabStop = aTabStopItem.At(nIndex);
+ aTabStopItem.Remove(nIndex);
+ if (!bRemove)
+ {
+ aTabStop.GetTabPos() = nPosition;
+ aTabStopItem.Insert(aTabStop);
+
+ SvxTabStop aSwTabStop(0, SvxTabAdjust::Default);
+ aTabStopItem.Insert(aSwTabStop);
+ }
+ const SvxTabStopItem& rDefaultTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+ MakeDefTabs(GetTabDist(rDefaultTabs), aTabStopItem);
+ }
+ rSh.SetAttrItem(aTabStopItem);
+ }
+ }
+ break;
+ case SID_PARAGRAPH_CHANGE_STATE:
+ {
+ if (pReqArgs)
+ {
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT> aLRSpaceSet(GetPool());
+ rSh.GetCurAttr( aLRSpaceSet );
+
+ if (const SfxStringItem *fLineIndent = pReqArgs->GetItemIfSet(SID_PARAGRAPH_FIRST_LINE_INDENT))
+ {
+ SvxFirstLineIndentItem firstLine(aLRSpaceSet.Get(RES_MARGIN_FIRSTLINE));
+ const OUString ratio = fLineIndent->GetValue();
+ firstLine.SetTextFirstLineOffset(nPageWidth * ratio.toFloat());
+ rSh.SetAttrItem(firstLine);
+ }
+ else if (const SfxStringItem *pLeftIndent = pReqArgs->GetItemIfSet(SID_PARAGRAPH_LEFT_INDENT))
+ {
+ SvxTextLeftMarginItem leftMargin(aLRSpaceSet.Get(RES_MARGIN_TEXTLEFT));
+ const OUString ratio = pLeftIndent->GetValue();
+ // this used to call SetLeft() but was probably a bug
+ leftMargin.SetTextLeft(nPageWidth * ratio.toFloat());
+ rSh.SetAttrItem(leftMargin);
+ }
+ else if (const SfxStringItem *pRightIndent = pReqArgs->GetItemIfSet(SID_PARAGRAPH_RIGHT_INDENT))
+ {
+ SvxRightMarginItem rightMargin(aLRSpaceSet.Get(RES_MARGIN_RIGHT));
+ const OUString ratio = pRightIndent->GetValue();
+ rightMargin.SetRight(nPageWidth * ratio.toFloat());
+ rSh.SetAttrItem(rightMargin);
+ }
+ }
+ break;
+ }
+ case SID_HANGING_INDENT:
+ {
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT> aLRSpaceSet(GetPool());
+ rSh.GetCurAttr( aLRSpaceSet );
+ SvxFirstLineIndentItem firstLine(aLRSpaceSet.Get(RES_MARGIN_FIRSTLINE));
+ SvxTextLeftMarginItem leftMargin(aLRSpaceSet.Get(RES_MARGIN_TEXTLEFT));
+ leftMargin.SetTextLeft(leftMargin.GetTextLeft() + firstLine.GetTextFirstLineOffset());
+ firstLine.SetTextFirstLineOffset((firstLine.GetTextFirstLineOffset()) * -1);
+ firstLine.SetAutoFirst(false); // old code would do this, is it wanted?
+ rSh.SetAttrItem(firstLine);
+ rSh.SetAttrItem(leftMargin);
+ break;
+ }
+
+ case SID_ATTR_PARA_LRSPACE_VERTICAL:
+ case SID_ATTR_PARA_LRSPACE:
+ if ( pReqArgs )
+ {
+ SvxLRSpaceItem aParaMargin(static_cast<const SvxLRSpaceItem&>(pReqArgs->Get(nSlot)));
+
+ aParaMargin.SetRight( aParaMargin.GetRight() - m_nRightBorderDistance );
+ aParaMargin.SetTextLeft(aParaMargin.GetTextLeft() - m_nLeftBorderDistance );
+
+ aParaMargin.SetWhich( RES_LR_SPACE );
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+
+ SvxFirstLineIndentItem firstLine(RES_MARGIN_FIRSTLINE);
+ firstLine.SetTextFirstLineOffset(aParaMargin.GetTextFirstLineOffset(), aParaMargin.GetPropTextFirstLineOffset());
+ firstLine.SetAutoFirst(aParaMargin.IsAutoFirst());
+ SvxTextLeftMarginItem const leftMargin(aParaMargin.GetTextLeft(), RES_MARGIN_TEXTLEFT);
+ SvxRightMarginItem const rightMargin(aParaMargin.GetRight(), RES_MARGIN_RIGHT);
+
+ // #i23726#
+ if (m_pNumRuleNodeFromDoc)
+ {
+ // --> #i42922# Mouse move of numbering label
+ // has to consider the left indent of the paragraph
+ SfxItemSetFixed<RES_MARGIN_TEXTLEFT, RES_MARGIN_TEXTLEFT> aSet( GetPool() );
+ rSh.GetCurAttr( aSet );
+ const SvxTextLeftMarginItem & rLeftMargin(aSet.Get(RES_MARGIN_TEXTLEFT));
+
+ SwPosition aPos(*m_pNumRuleNodeFromDoc);
+ // #i90078#
+ rSh.SetIndent(static_cast<short>(aParaMargin.GetTextLeft() - rLeftMargin.GetTextLeft()), aPos);
+ // #i42921# invalidate state of indent in order to get a ruler update.
+ aParaMargin.SetWhich( nSlot );
+ GetViewFrame().GetBindings().SetState( aParaMargin );
+ }
+ else if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT> aSet(GetPool());
+ aSet.Put(firstLine);
+ aSet.Put(leftMargin);
+ aSet.Put(rightMargin);
+ rSh.AutoUpdatePara( pColl, aSet);
+ }
+ else
+ {
+ rSh.SetAttrItem(firstLine);
+ rSh.SetAttrItem(leftMargin);
+ rSh.SetAttrItem(rightMargin);
+ }
+
+ if ( aParaMargin.GetTextFirstLineOffset() < 0 )
+ {
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aSet( GetPool() );
+
+ rSh.GetCurAttr( aSet );
+ const SvxTabStopItem& rTabStops = aSet.Get(RES_PARATR_TABSTOP);
+
+ // Do we have a tab at position zero?
+ sal_uInt16 i;
+
+ for ( i = 0; i < rTabStops.Count(); ++i )
+ if ( rTabStops[i].GetTabPos() == 0 )
+ break;
+
+ if ( i >= rTabStops.Count() )
+ {
+ // No DefTab
+ std::unique_ptr<SvxTabStopItem> aTabStops(rTabStops.Clone());
+
+ ::lcl_EraseDefTabs(*aTabStops);
+
+ SvxTabStop aSwTabStop( 0, SvxTabAdjust::Default );
+ aTabStops->Insert(aSwTabStop);
+
+ const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+ ::MakeDefTabs( ::GetTabDist(rDefTabs), *aTabStops );
+
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat())
+ {
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP> aSetTmp(GetPool());
+ aSetTmp.Put(std::move(aTabStops));
+ rSh.AutoUpdatePara( pColl, aSetTmp );
+ }
+ else
+ rSh.SetAttrItem( *aTabStops );
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_PARA_ULSPACE:
+ if ( pReqArgs )
+ {
+ SvxULSpaceItem aParaMargin(static_cast<const SvxULSpaceItem&>(pReqArgs->Get(nSlot)));
+
+ aParaMargin.SetUpper( aParaMargin.GetUpper() );
+ aParaMargin.SetLower(aParaMargin.GetLower());
+
+ aParaMargin.SetWhich( RES_UL_SPACE );
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ SfxItemSetFixed<RES_UL_SPACE, RES_UL_SPACE> aSet(GetPool());
+ aSet.Put(aParaMargin);
+ rSh.AutoUpdatePara( pColl, aSet);
+ }
+ else
+ rSh.SetAttrItem( aParaMargin );
+ }
+ break;
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SfxItemSetFixed<RES_UL_SPACE, RES_UL_SPACE> aULSpaceSet( GetPool() );
+ rSh.GetCurAttr( aULSpaceSet );
+ SvxULSpaceItem aULSpace( aULSpaceSet.Get( RES_UL_SPACE ) );
+ sal_uInt16 nUpper = aULSpace.GetUpper();
+ sal_uInt16 nLower = aULSpace.GetLower();
+
+ if ( nSlot == SID_PARASPACE_INCREASE )
+ {
+ nUpper = std::min< sal_uInt16 >( nUpper + 57, 5670 );
+ nLower = std::min< sal_uInt16 >( nLower + 57, 5670 );
+ }
+ else
+ {
+ nUpper = std::max< sal_Int16 >( nUpper - 57, 0 );
+ nLower = std::max< sal_Int16 >( nLower - 57, 0 );
+ }
+
+ aULSpace.SetUpper( nUpper );
+ aULSpace.SetLower( nLower );
+
+ SwTextFormatColl* pColl = rSh.GetCurTextFormatColl();
+ if( pColl && pColl->IsAutoUpdateOnDirectFormat() )
+ {
+ aULSpaceSet.Put( aULSpace );
+ rSh.AutoUpdatePara( pColl, aULSpaceSet );
+ }
+ else
+ rSh.SetAttrItem( aULSpace, SetAttrMode::DEFAULT, true );
+ }
+ break;
+
+ case SID_RULER_CHANGE_STATE:
+ if (pReqArgs)
+ {
+ if ( const SfxStringItem *pMargin1 = pReqArgs->GetItemIfSet(SID_RULER_MARGIN1) )
+ {
+ const OUString ratio = pMargin1->GetValue();
+ GetHRuler().SetValues(RulerChangeType::MARGIN1, GetHRuler().GetPageWidth() * ratio.toFloat());
+ }
+ else if ( const SfxStringItem *pMargin2 = pReqArgs->GetItemIfSet(SID_RULER_MARGIN2) )
+ {
+ const OUString ratio = pMargin2->GetValue();
+ GetHRuler().SetValues(RulerChangeType::MARGIN2, GetHRuler().GetPageWidth() * ratio.toFloat());
+ }
+ }
+ break;
+ case SID_RULER_BORDERS_VERTICAL:
+ case SID_RULER_BORDERS:
+ if ( pReqArgs )
+ {
+ SvxColumnItem aColItem(static_cast<const SvxColumnItem&>(pReqArgs->Get(nSlot)));
+
+ if( m_bSetTabColFromDoc || (!bSect && rSh.GetTableFormat()) )
+ {
+ OSL_ENSURE(aColItem.Count(), "ColDesc is empty!!");
+
+ const bool bSingleLine = rReq.
+ GetArgs()->Get(SID_RULER_ACT_LINE_ONLY).GetValue();
+
+ SwTabCols aTabCols;
+ if ( m_bSetTabColFromDoc )
+ rSh.GetMouseTabCols( aTabCols, m_aTabColFromDocPos );
+ else
+ rSh.GetTabCols(aTabCols);
+
+ // left table border
+ tools::Long nBorder = static_cast<tools::Long>(aColItem.GetLeft() - aTabCols.GetLeftMin());
+ aTabCols.SetLeft( nBorder );
+
+ nBorder = (bVerticalWriting ? nPageHeight : nPageWidth) - aTabCols.GetLeftMin() - aColItem.GetRight();
+
+ if ( aColItem.GetRight() > 0 )
+ aTabCols.SetRight( nBorder );
+
+ // Tabcols sequentially
+ // The last column is defined by the edge.
+ // Columns in right-to-left tables need to be mirrored
+ bool bIsTableRTL =
+ IsTabColFromDoc() ?
+ rSh.IsMouseTableRightToLeft(m_aTabColFromDocPos)
+ : rSh.IsTableRightToLeft();
+ const size_t nColCount = aColItem.Count() - 1;
+ if(bIsTableRTL)
+ {
+ for ( size_t i = 0; i < nColCount && i < aTabCols.Count(); ++i )
+ {
+ const SvxColumnDescription& rCol = aColItem[nColCount - i];
+ aTabCols[i] = aTabCols.GetRight() - rCol.nStart;
+ aTabCols.SetHidden( i, !rCol.bVisible );
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nColCount && i < aTabCols.Count(); ++i )
+ {
+ const SvxColumnDescription& rCol = aColItem[i];
+ aTabCols[i] = rCol.nEnd + aTabCols.GetLeft();
+ aTabCols.SetHidden( i, !rCol.bVisible );
+ }
+ }
+
+ if ( m_bSetTabColFromDoc )
+ {
+ if( !rSh.IsViewLocked() )
+ {
+ bUnlockView = true;
+ rSh.LockView( true );
+ }
+ rSh.SetMouseTabCols( aTabCols, bSingleLine,
+ m_aTabColFromDocPos );
+ }
+ else
+ rSh.SetTabCols(aTabCols, bSingleLine);
+
+ }
+ else
+ {
+ if ( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY || bSect)
+ {
+ SwSectionFormat *pSectFormat = nullptr;
+ SfxItemSetFixed<RES_COL, RES_COL> aSet( GetPool() );
+ if(bSect)
+ {
+ SwSection *pSect = rSh.GetAnySection();
+ OSL_ENSURE( pSect, "Which section?");
+ pSectFormat = pSect->GetFormat();
+ }
+ else
+ {
+ rSh.GetFlyFrameAttr( aSet );
+ }
+ SwFormatCol aCols(
+ bSect ?
+ pSectFormat->GetCol() :
+ aSet.Get( RES_COL, false ));
+ SwRect aCurRect = rSh.GetAnyCurRect(bSect ? CurRectType::SectionPrt : CurRectType::FlyEmbeddedPrt);
+ const tools::Long lWidth = bVerticalWriting ? aCurRect.Height() : aCurRect.Width();
+ ::lcl_ConvertToCols( aColItem, lWidth, aCols );
+ aSet.Put( aCols );
+ if(bSect)
+ rSh.SetSectionAttr( aSet, pSectFormat );
+ else
+ {
+ rSh.StartAction();
+ rSh.Push();
+ rSh.SetFlyFrameAttr( aSet );
+ // Cancel the frame selection again
+ if(!bFrameSelection && rSh.IsFrameSelected())
+ {
+ rSh.UnSelectFrame();
+ rSh.LeaveSelFrameMode();
+ }
+ rSh.Pop();
+ rSh.EndAction();
+ }
+ }
+ else
+ {
+ SwFormatCol aCols( rDesc.GetMaster().GetCol() );
+ const SwRect aPrtRect = rSh.GetAnyCurRect(CurRectType::PagePrt);
+ ::lcl_ConvertToCols( aColItem,
+ bVerticalWriting ? aPrtRect.Height() : aPrtRect.Width(),
+ aCols );
+ SwPageDesc aDesc( rDesc );
+ aDesc.GetMaster().SetFormatAttr( aCols );
+ rSh.ChgPageDesc( rSh.GetCurPageDesc(), aDesc );
+ }
+ }
+ }
+ break;
+
+ case SID_RULER_ROWS :
+ case SID_RULER_ROWS_VERTICAL:
+ if (pReqArgs)
+ {
+ SvxColumnItem aColItem(static_cast<const SvxColumnItem&>(pReqArgs->Get(nSlot)));
+
+ if( m_bSetTabColFromDoc || (!bSect && rSh.GetTableFormat()) )
+ {
+ OSL_ENSURE(aColItem.Count(), "ColDesc is empty!!");
+
+ SwTabCols aTabCols;
+ if ( m_bSetTabRowFromDoc )
+ rSh.GetMouseTabRows( aTabCols, m_aTabColFromDocPos );
+ else
+ rSh.GetTabRows(aTabCols);
+
+ if ( bVerticalWriting )
+ {
+ aTabCols.SetRight(nPageWidth - aColItem.GetRight() - aColItem.GetLeft());
+ aTabCols.SetLeftMin(aColItem.GetLeft());
+ }
+ else
+ {
+ tools::Long nBorder = nPageHeight - aTabCols.GetLeftMin() - aColItem.GetRight();
+ aTabCols.SetRight( nBorder );
+ }
+
+ const size_t nColItems = aColItem.Count() - 1;
+ if(bVerticalWriting)
+ {
+ for ( size_t i = nColItems; i; --i )
+ {
+ const SvxColumnDescription& rCol = aColItem[i - 1];
+ tools::Long nColumnPos = aTabCols.GetRight() - rCol.nEnd ;
+ aTabCols[i - 1] = nColumnPos;
+ aTabCols.SetHidden( i - 1, !rCol.bVisible );
+ }
+ }
+ else
+ {
+ for ( size_t i = 0; i < nColItems; ++i )
+ {
+ const SvxColumnDescription& rCol = aColItem[i];
+ aTabCols[i] = rCol.nEnd + aTabCols.GetLeft();
+ aTabCols.SetHidden( i, !rCol.bVisible );
+ }
+ }
+ bool bSingleLine = false;
+ if( const SfxBoolItem* pSingleLine = rReq.GetArgs()->GetItemIfSet(SID_RULER_ACT_LINE_ONLY, false) )
+ bSingleLine = pSingleLine->GetValue();
+ if ( m_bSetTabRowFromDoc )
+ {
+ if( !rSh.IsViewLocked() )
+ {
+ bUnlockView = true;
+ rSh.LockView( true );
+ }
+ rSh.SetMouseTabRows( aTabCols, bSingleLine, m_aTabColFromDocPos );
+ }
+ else
+ rSh.SetTabRows(aTabCols, bSingleLine);
+ }
+ }
+ break;
+ case SID_TABLE_CHANGE_CURRENT_BORDER_POSITION:
+ {
+ if (pReqArgs)
+ {
+ const SfxStringItem *pBorderType = pReqArgs->GetItemIfSet(SID_TABLE_BORDER_TYPE);
+ const SfxUInt16Item *pIndex = pReqArgs->GetItemIfSet(SID_TABLE_BORDER_INDEX);
+ const SfxInt32Item *pOffset = pReqArgs->GetItemIfSet(SID_TABLE_BORDER_OFFSET);
+ constexpr tools::Long constDistanceOffset = 40;
+
+ if (pBorderType && pIndex && pOffset)
+ {
+ const OUString sType = pBorderType->GetValue();
+ const sal_uInt16 nIndex = pIndex->GetValue();
+ const sal_Int32 nOffset = pOffset->GetValue();
+
+ if (sType.startsWith("column"))
+ {
+ SwTabCols aTabCols;
+ rSh.GetTabCols(aTabCols);
+
+ if (sType == "column-left")
+ {
+ tools::Long nNewPosition = aTabCols.GetLeft() + nOffset;
+ if(aTabCols.Count() > 0)
+ {
+ auto & rEntry = aTabCols.GetEntry(0);
+ nNewPosition = std::min(nNewPosition, rEntry.nPos - constDistanceOffset);
+ }
+ aTabCols.SetLeft(nNewPosition);
+ }
+ else if (sType == "column-right")
+ {
+ tools::Long nNewPosition = aTabCols.GetRight() + nOffset;
+ if(aTabCols.Count() > 0)
+ {
+ auto & rEntry = aTabCols.GetEntry(aTabCols.Count() - 1);
+ nNewPosition = std::max(nNewPosition, rEntry.nPos + constDistanceOffset);
+ }
+ aTabCols.SetRight(nNewPosition);
+ }
+ else if (sType == "column-middle" && nIndex < aTabCols.Count())
+ {
+ auto & rEntry = aTabCols.GetEntry(nIndex);
+ tools::Long nNewPosition = rEntry.nPos + nOffset;
+ nNewPosition = std::clamp(nNewPosition, rEntry.nMin, rEntry.nMax - constDistanceOffset);
+ rEntry.nPos = nNewPosition;
+ }
+
+ rSh.SetTabCols(aTabCols, false);
+ }
+ else if (sType.startsWith("row"))
+ {
+ SwTabCols aTabRows;
+ rSh.GetTabRows(aTabRows);
+
+ if (sType == "row-left")
+ {
+ auto & rEntry = aTabRows.GetEntry(0);
+ tools::Long nNewPosition = aTabRows.GetLeft() + nOffset;
+ nNewPosition = std::min(nNewPosition, rEntry.nPos - constDistanceOffset);
+ aTabRows.SetLeft(nNewPosition);
+ }
+ else if (sType == "row-right")
+ {
+ tools::Long nNewPosition = aTabRows.GetRight() + nOffset;
+ if(aTabRows.Count() > 0)
+ {
+ auto & rEntry = aTabRows.GetEntry(aTabRows.Count() - 1);
+ nNewPosition = std::max(nNewPosition, rEntry.nPos + constDistanceOffset);
+ }
+ aTabRows.SetRight(nNewPosition);
+ }
+ else if (sType == "row-middle" && nIndex < aTabRows.Count())
+ {
+ auto & rEntry = aTabRows.GetEntry(nIndex);
+ tools::Long nNewPosition = rEntry.nPos + nOffset;
+ nNewPosition = std::clamp(nNewPosition, rEntry.nMin, rEntry.nMax - constDistanceOffset);
+ rEntry.nPos = nNewPosition;
+ }
+
+ rSh.SetTabRows(aTabRows, false);
+ }
+ }
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER:
+ {
+ if ( pReqArgs )
+ {
+ const bool bHeaderOn = static_cast<const SfxBoolItem&>(pReqArgs->Get(SID_ATTR_PAGE_HEADER)).GetValue();
+ SwPageDesc aDesc(rDesc);
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr( SwFormatHeader( bHeaderOn ));
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_LRMARGIN:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetHeader().IsActive() )
+ {
+ const SvxLongLRSpaceItem& aLongLR = pReqArgs->Get(SID_ATTR_PAGE_HEADER_LRMARGIN);
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ SwPageDesc aDesc(rDesc);
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetHeader().GetHeaderFormat());
+ pFormat->SetFormatAttr( aLR );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_SPACING:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetHeader().IsActive())
+ {
+ const SvxLongULSpaceItem& aLongUL = pReqArgs->Get(SID_ATTR_PAGE_HEADER_SPACING);
+ SwPageDesc aDesc(rDesc);
+ SvxULSpaceItem aUL(0, aLongUL.GetLower(), RES_UL_SPACE );
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetHeader().GetHeaderFormat());
+ pFormat->SetFormatAttr( aUL );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_HEADER_LAYOUT:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetHeader().IsActive())
+ {
+ const SfxInt16Item& aLayoutItem = pReqArgs->Get(SID_ATTR_PAGE_HEADER_LAYOUT);
+ sal_uInt16 nLayout = aLayoutItem.GetValue();
+ SwPageDesc aDesc(rDesc);
+ aDesc.ChgHeaderShare((nLayout>>1) == 0);
+ aDesc.ChgFirstShare((nLayout % 2) == 0); // FIXME control changes for both header footer - tdf#100287
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER:
+ {
+ if ( pReqArgs )
+ {
+ const bool bFooterOn = static_cast<const SfxBoolItem&>(pReqArgs->Get(SID_ATTR_PAGE_FOOTER)).GetValue();
+ SwPageDesc aDesc(rDesc);
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ rMaster.SetFormatAttr( SwFormatFooter( bFooterOn ));
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_LRMARGIN:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetFooter().IsActive() )
+ {
+ const SvxLongLRSpaceItem& aLongLR = pReqArgs->Get(SID_ATTR_PAGE_FOOTER_LRMARGIN);
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ SwPageDesc aDesc(rDesc);
+ aLR.SetLeft(aLongLR.GetLeft());
+ aLR.SetRight(aLongLR.GetRight());
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetFooter().GetFooterFormat());
+ pFormat->SetFormatAttr( aLR );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_SPACING:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetFooter().IsActive())
+ {
+ const SvxLongULSpaceItem& aLongUL = pReqArgs->Get(SID_ATTR_PAGE_FOOTER_SPACING);
+ SwPageDesc aDesc(rDesc);
+ SvxULSpaceItem aUL(aLongUL.GetUpper(), 0, RES_UL_SPACE );
+ SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(aDesc.GetMaster().GetFooter().GetFooterFormat());
+ pFormat->SetFormatAttr( aUL );
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER_LAYOUT:
+ {
+ if ( pReqArgs && rDesc.GetMaster().GetFooter().IsActive())
+ {
+ const SfxInt16Item& aLayoutItem = pReqArgs->Get(SID_ATTR_PAGE_FOOTER_LAYOUT);
+ sal_uInt16 nLayout = aLayoutItem.GetValue();
+ SwPageDesc aDesc(rDesc);
+ aDesc.ChgFooterShare((nLayout>>1) == 0);
+ aDesc.ChgFirstShare((nLayout % 2) == 0); // FIXME control changes for both header footer - tdf#100287
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ case SID_ATTR_PAGE_FILLSTYLE:
+ case SID_ATTR_PAGE_GRADIENT:
+ case SID_ATTR_PAGE_HATCH:
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ if(pReqArgs)
+ {
+ SwPageDesc aDesc(rDesc);
+ SwFrameFormat &rMaster = aDesc.GetMaster();
+ switch (nSlot)
+ {
+ case SID_ATTR_PAGE_FILLSTYLE:
+ {
+ XFillStyleItem aFSItem( pReqArgs->Get( XATTR_FILLSTYLE ) );
+ drawing::FillStyle eXFS = aFSItem.GetValue();
+
+ if ( eXFS == drawing::FillStyle_NONE )
+ rMaster.SetFormatAttr( XFillStyleItem( eXFS ) );
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ {
+ XFillColorItem aColorItem( pReqArgs->Get( XATTR_FILLCOLOR ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_SOLID ) );
+ rMaster.SetFormatAttr( aColorItem );
+ }
+ break;
+
+ case SID_ATTR_PAGE_GRADIENT:
+ {
+ XFillGradientItem aGradientItem( pReqArgs->Get( XATTR_FILLGRADIENT ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_GRADIENT ) );
+ rMaster.SetFormatAttr( aGradientItem );
+ }
+ break;
+
+ case SID_ATTR_PAGE_HATCH:
+ {
+ XFillHatchItem aHatchItem( pReqArgs->Get( XATTR_FILLHATCH ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_HATCH ) );
+ rMaster.SetFormatAttr( aHatchItem );
+ }
+ break;
+
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ XFillBitmapItem aBitmapItem( pReqArgs->Get( XATTR_FILLBITMAP ) );
+ rMaster.SetFormatAttr( XFillStyleItem( drawing::FillStyle_BITMAP ) );
+ rMaster.SetFormatAttr( aBitmapItem );
+ }
+ break;
+
+ default:
+ break;
+ }
+ rSh.ChgPageDesc(rSh.GetCurPageDesc(), aDesc);
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE( false, "wrong SlotId");
+ }
+ rSh.EndAllAction();
+
+ if( bUnlockView )
+ rSh.LockView( false );
+
+ m_bSetTabColFromDoc = m_bSetTabRowFromDoc = m_bTabColFromDoc = m_bTabRowFromDoc = false;
+ SetNumRuleNodeFromDoc(nullptr);
+}
+
+// Here the status of the tab bar will be determined.
+// This means that all relevant attributes at the CursorPos
+// will be submitted to the tab bar.
+void SwView::StateTabWin(SfxItemSet& rSet)
+{
+ SwWrtShell &rSh = GetWrtShell();
+
+ const Point* pPt = IsTabColFromDoc() || IsTabRowFromDoc() ? &m_aTabColFromDocPos : nullptr;
+ const FrameTypeFlags nFrameType = rSh.IsObjSelected()
+ ? FrameTypeFlags::DRAWOBJ
+ : rSh.GetFrameType( pPt, true );
+
+ const bool bFrameSelection = rSh.IsFrameSelected();
+ const bool bBrowse = rSh.GetViewOptions()->getBrowseMode();
+ // PageOffset/limiter
+ const SwRect& rPageRect = rSh.GetAnyCurRect( CurRectType::Page, pPt );
+ const SwRect& rPagePrtRect = rSh.GetAnyCurRect( CurRectType::PagePrt, pPt );
+ const tools::Long nPageWidth = rPageRect.Width();
+ const tools::Long nPageHeight = rPageRect.Height();
+
+ const SwPageDesc& rDesc = rSh.GetPageDesc(
+ IsTabColFromDoc() || m_bTabRowFromDoc ?
+ rSh.GetMousePageDesc(m_aTabColFromDocPos) : rSh.GetCurPageDesc() );
+
+ const SvxFrameDirectionItem& rFrameDir = rDesc.GetMaster().GetFrameDir();
+ const bool bVerticalWriting = rSh.IsInVerticalText();
+
+ //enable tab stop display on the rulers depending on the writing direction
+ WinBits nRulerStyle = m_pHRuler->GetStyle() & ~WB_EXTRAFIELD;
+ m_pHRuler->SetStyle(bVerticalWriting||bBrowse ? nRulerStyle : nRulerStyle|WB_EXTRAFIELD);
+ nRulerStyle = m_pVRuler->GetStyle() & ~WB_EXTRAFIELD;
+ m_pVRuler->SetStyle(bVerticalWriting ? nRulerStyle|WB_EXTRAFIELD : nRulerStyle);
+
+ //#i24363# tab stops relative to indent
+ bool bRelative = rSh.getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
+ m_pHRuler->SetTabsRelativeToIndent( bRelative );
+ m_pVRuler->SetTabsRelativeToIndent( bRelative );
+
+ SvxLRSpaceItem aPageLRSpace( rDesc.GetMaster().GetLRSpace() );
+ SwapPageMargin( rDesc, aPageLRSpace );
+
+ SfxItemSetFixed<RES_PARATR_TABSTOP, RES_PARATR_TABSTOP,
+ RES_MARGIN_FIRSTLINE, RES_MARGIN_RIGHT,
+ RES_UL_SPACE, RES_UL_SPACE> aCoreSet( GetPool() );
+ // get also the list level indent values, if needed.
+ rSh.GetCurAttr( aCoreSet, true );
+ const SelectionType nSelType = rSh.GetSelectionType();
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while ( nWhich )
+ {
+ switch ( nWhich )
+ {
+
+ case SID_ATTR_PAGE_COLUMN:
+ {
+ sal_uInt16 nColumnType = 0;
+
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ const SwFormatCol& aCol(rMaster.GetCol());
+ const sal_uInt16 nCols = aCol.GetNumCols();
+ if ( nCols == 0 )
+ {
+ nColumnType = 1;
+ }
+ else if ( nCols == 2 )
+ {
+ const sal_uInt16 nColLeft = aCol.CalcPrtColWidth(0, aCol.GetWishWidth());
+ const sal_uInt16 nColRight = aCol.CalcPrtColWidth(1, aCol.GetWishWidth());
+
+ if ( abs(nColLeft - nColRight) <= 10 )
+ {
+ nColumnType = 2;
+ }
+ else if( abs(nColLeft - nColRight*2) < 20 )
+ {
+ nColumnType = 4;
+ }
+ else if( abs(nColLeft*2 - nColRight) < 20 )
+ {
+ nColumnType = 5;
+ }
+ }
+ else if( nCols == 3 )
+ {
+ nColumnType = 3;
+ }
+ else
+ nColumnType = nCols;
+
+ rSet.Put( SfxInt16Item( SID_ATTR_PAGE_COLUMN, nColumnType ) );
+ }
+ break;
+
+ case SID_ATTR_LONG_LRSPACE:
+ {
+ SvxLongLRSpaceItem aLongLR( aPageLRSpace.GetLeft(),
+ aPageLRSpace.GetRight(),
+ SID_ATTR_LONG_LRSPACE);
+ if(bBrowse)
+ {
+ aLongLR.SetLeft(rPagePrtRect.Left());
+ aLongLR.SetRight(nPageWidth - rPagePrtRect.Right());
+ }
+ if ( ( nFrameType & FrameTypeFlags::HEADER || nFrameType & FrameTypeFlags::FOOTER ) &&
+ !(nFrameType & FrameTypeFlags::COLSECT) )
+ {
+ SwFrameFormat *pFormat = const_cast<SwFrameFormat*>((nFrameType & FrameTypeFlags::HEADER) ?
+ rDesc.GetMaster().GetHeader().GetHeaderFormat() :
+ rDesc.GetMaster().GetFooter().GetFooterFormat());
+ if( pFormat )// #i80890# if rDesc is not the one belonging to the current page is might crash
+ {
+ SwRect aRect( rSh.GetAnyCurRect( CurRectType::HeaderFooter, pPt));
+ aRect.Pos() -= rSh.GetAnyCurRect( CurRectType::Page, pPt ).Pos();
+ const SvxLRSpaceItem& aLR = pFormat->GetLRSpace();
+ aLongLR.SetLeft ( aLR.GetLeft() + aRect.Left() );
+ aLongLR.SetRight( nPageWidth - aRect.Right() + aLR.GetRight() );
+ }
+ }
+ else
+ {
+ SwRect aRect;
+ if( !bFrameSelection && ((nFrameType & FrameTypeFlags::COLSECT) || rSh.IsDirectlyInSection()) )
+ {
+ aRect = rSh.GetAnyCurRect(CurRectType::SectionPrt, pPt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section, pPt);
+ aRect.Pos() += aTmpRect.Pos();
+ }
+
+ else if ( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ aRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt);
+ else if( nFrameType & FrameTypeFlags::DRAWOBJ)
+ aRect = rSh.GetObjRect();
+
+ if( aRect.Width() )
+ {
+ // make relative to page position:
+ aLongLR.SetLeft(aRect.Left() - rPageRect.Left());
+ aLongLR.SetRight(rPageRect.Right() - aRect.Right());
+ }
+ }
+ rSet.Put( aLongLR );
+ }
+ break;
+
+ // provide left and right margins of current page style
+ case SID_ATTR_PAGE_LRSPACE:
+ {
+ const SvxLRSpaceItem aTmpPageLRSpace( rDesc.GetMaster().GetLRSpace() );
+ const SvxLongLRSpaceItem aLongLR(
+ aTmpPageLRSpace.GetLeft(),
+ aTmpPageLRSpace.GetRight(),
+ SID_ATTR_PAGE_LRSPACE );
+ rSet.Put( aLongLR );
+ }
+ break;
+
+ case SID_ATTR_LONG_ULSPACE:
+ {
+ // Page margin top bottom
+ SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ SvxLongULSpaceItem aLongUL( static_cast<tools::Long>(aUL.GetUpper()),
+ static_cast<tools::Long>(aUL.GetLower()),
+ SID_ATTR_LONG_ULSPACE);
+
+ if ( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ {
+ // Convert document coordinates into page coordinates.
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt);
+ aLongUL.SetUpper(rRect.Top() - rPageRect.Top());
+ aLongUL.SetLower(rPageRect.Bottom() - rRect.Bottom());
+ }
+ else if ( nFrameType & FrameTypeFlags::HEADER || nFrameType & FrameTypeFlags::FOOTER )
+ {
+ SwRect aRect( rSh.GetAnyCurRect( CurRectType::HeaderFooter, pPt));
+ aRect.Pos() -= rSh.GetAnyCurRect( CurRectType::Page, pPt ).Pos();
+ aLongUL.SetUpper( aRect.Top() );
+ aLongUL.SetLower( nPageHeight - aRect.Bottom() );
+ }
+ else if( nFrameType & FrameTypeFlags::DRAWOBJ)
+ {
+ const SwRect &rRect = rSh.GetObjRect();
+ aLongUL.SetUpper(rRect.Top() - rPageRect.Top());
+ aLongUL.SetLower(rPageRect.Bottom() - rRect.Bottom());
+ }
+ else if(bBrowse)
+ {
+ aLongUL.SetUpper(rPagePrtRect.Top());
+ aLongUL.SetLower(nPageHeight - rPagePrtRect.Bottom());
+ }
+ rSet.Put( aLongUL );
+ }
+ break;
+
+ // provide top and bottom margins of current page style
+ case SID_ATTR_PAGE_ULSPACE:
+ {
+ const SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ SvxLongULSpaceItem aLongUL(
+ static_cast<tools::Long>(aUL.GetUpper()),
+ static_cast<tools::Long>(aUL.GetLower()),
+ SID_ATTR_PAGE_ULSPACE );
+
+ rSet.Put( aLongUL );
+ }
+ break;
+
+ case SID_ATTR_TABSTOP_VERTICAL :
+ case RES_PARATR_TABSTOP:
+ {
+ if ( dynamic_cast< const SwWebView *>( this ) != nullptr ||
+ IsTabColFromDoc() ||
+ IsTabRowFromDoc() ||
+ ( nSelType & SelectionType::Graphic ) ||
+ ( nSelType & SelectionType::Frame ) ||
+ ( nSelType & SelectionType::Ole ) ||
+ (aCoreSet.GetItemState(RES_MARGIN_FIRSTLINE) < SfxItemState::DEFAULT) ||
+ (aCoreSet.GetItemState(RES_MARGIN_TEXTLEFT) < SfxItemState::DEFAULT) ||
+ (!bVerticalWriting && (SID_ATTR_TABSTOP_VERTICAL == nWhich) ) ||
+ ( bVerticalWriting && (RES_PARATR_TABSTOP == nWhich))
+ )
+ rSet.DisableItem( nWhich );
+ else
+ {
+ SvxTabStopItem aTabStops(aCoreSet.Get( RES_PARATR_TABSTOP ));
+
+ const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP);
+
+ OSL_ENSURE(m_pHRuler, "why is there no ruler?");
+ const tools::Long nDefTabDist = ::GetTabDist(rDefTabs);
+ m_pHRuler->SetDefTabDist( nDefTabDist );
+ m_pVRuler->SetDefTabDist( nDefTabDist );
+ ::lcl_EraseDefTabs(aTabStops);
+ aTabStops.SetWhich(nWhich);
+ rSet.Put(aTabStops);
+
+ if (comphelper::LibreOfficeKit::isActive() && nWhich == RES_PARATR_TABSTOP)
+ {
+ boost::property_tree::ptree aRootTree;
+ boost::property_tree::ptree aEntries;
+
+ for (sal_uInt16 i = 0; i < aTabStops.Count(); ++i)
+ {
+ SvxTabStop const & rTabStop = aTabStops[i];
+ boost::property_tree::ptree aEntry;
+ aEntry.put("position", convertTwipToMm100(rTabStop.GetTabPos()));
+ aEntry.put("type", sal_uInt16(rTabStop.GetAdjustment()));
+ aEntry.put("decimal", OUString(rTabStop.GetDecimal()));
+ aEntry.put("fill", OUString(rTabStop.GetFill()));
+ aEntries.push_back(std::make_pair("", aEntry));
+ }
+ aRootTree.push_back(std::make_pair("tabstops", aEntries));
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aRootTree);
+ rSh.GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TAB_STOP_LIST, OString(aStream.str()));
+ }
+ }
+ break;
+ }
+
+ case SID_HANGING_INDENT:
+ {
+ SfxItemState e = aCoreSet.GetItemState(RES_MARGIN_FIRSTLINE);
+ if( e == SfxItemState::DISABLED )
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case SID_ATTR_PARA_LRSPACE_VERTICAL:
+ case SID_ATTR_PARA_LRSPACE:
+ case SID_ATTR_PARA_LEFTSPACE:
+ case SID_ATTR_PARA_RIGHTSPACE:
+ case SID_ATTR_PARA_FIRSTLINESPACE:
+ {
+ if ( nSelType & SelectionType::Graphic ||
+ nSelType & SelectionType::Frame ||
+ nSelType & SelectionType::Ole ||
+ nFrameType == FrameTypeFlags::DRAWOBJ ||
+ (!bVerticalWriting && (SID_ATTR_PARA_LRSPACE_VERTICAL == nWhich)) ||
+ ( bVerticalWriting && (SID_ATTR_PARA_LRSPACE == nWhich))
+ )
+ {
+ rSet.DisableItem(nWhich);
+ }
+ else
+ {
+ std::shared_ptr<SvxLRSpaceItem> aLR(std::make_shared<SvxLRSpaceItem>(RES_LR_SPACE));
+ if ( !IsTabColFromDoc() )
+ {
+ SvxFirstLineIndentItem const& rFirstLine(aCoreSet.Get(RES_MARGIN_FIRSTLINE));
+ SvxTextLeftMarginItem const& rLeftMargin(aCoreSet.Get(RES_MARGIN_TEXTLEFT));
+ SvxRightMarginItem const& rRightMargin(aCoreSet.Get(RES_MARGIN_RIGHT));
+ aLR->SetTextFirstLineOffset(rFirstLine.GetTextFirstLineOffset(), rFirstLine.GetPropTextFirstLineOffset());
+ aLR->SetAutoFirst(rFirstLine.IsAutoFirst());
+ aLR->SetTextLeft(rLeftMargin.GetTextLeft(), rLeftMargin.GetPropLeft());
+ aLR->SetRight(rRightMargin.GetRight(), rRightMargin.GetPropRight());
+
+ // #i23726#
+ if (m_pNumRuleNodeFromDoc)
+ {
+ short nOffset = static_cast< short >(aLR->GetTextLeft() +
+ // #i42922# Mouse move of numbering label
+ // has to consider the left indent of the paragraph
+ m_pNumRuleNodeFromDoc->GetLeftMarginWithNum( true ) );
+
+ short nFLOffset;
+ m_pNumRuleNodeFromDoc->GetFirstLineOfsWithNum( nFLOffset );
+
+ aLR->SetLeft( nOffset + nFLOffset );
+ }
+ }
+ aLR->SetWhich(nWhich);
+ rSet.Put(*aLR);
+ }
+ break;
+ }
+
+ case SID_ATTR_PARA_ULSPACE:
+ case SID_ATTR_PARA_ABOVESPACE:
+ case SID_ATTR_PARA_BELOWSPACE:
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SvxULSpaceItem aUL = aCoreSet.Get(RES_UL_SPACE);
+ SfxItemState e = aCoreSet.GetItemState(RES_UL_SPACE);
+ if( e >= SfxItemState::DEFAULT )
+ {
+ if ( !aUL.GetUpper() && !aUL.GetLower() )
+ rSet.DisableItem( SID_PARASPACE_DECREASE );
+ else if ( aUL.GetUpper() >= 5670 && aUL.GetLower() >= 5670 )
+ rSet.DisableItem( SID_PARASPACE_INCREASE );
+ if ( nWhich == SID_ATTR_PARA_ULSPACE
+ || nWhich == SID_ATTR_PARA_ABOVESPACE
+ || nWhich == SID_ATTR_PARA_BELOWSPACE
+ )
+ {
+ aUL.SetWhich( nWhich );
+ rSet.Put( aUL );
+ }
+ }
+ else
+ {
+ rSet.DisableItem( SID_PARASPACE_INCREASE );
+ rSet.DisableItem( SID_PARASPACE_DECREASE );
+ rSet.InvalidateItem( SID_ATTR_PARA_ULSPACE );
+ rSet.InvalidateItem( SID_ATTR_PARA_ABOVESPACE );
+ rSet.InvalidateItem( SID_ATTR_PARA_BELOWSPACE );
+ }
+ }
+ break;
+
+ case SID_RULER_BORDER_DISTANCE:
+ {
+ m_nLeftBorderDistance = 0;
+ m_nRightBorderDistance = 0;
+ SfxItemSetFixed<RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER> aCoreSet2(GetPool());
+ if ( nSelType & SelectionType::Graphic ||
+ nSelType & SelectionType::Frame ||
+ nSelType & SelectionType::Ole ||
+ nFrameType == FrameTypeFlags::DRAWOBJ )
+ rSet.DisableItem(SID_RULER_BORDER_DISTANCE);
+ else
+ {
+ SvxLRSpaceItem aDistLR(SID_RULER_BORDER_DISTANCE);
+ if(nFrameType & FrameTypeFlags::FLY_ANY)
+ {
+ if( IsTabColFromDoc() )
+ {
+ const SwRect& rFlyPrtRect = rSh.GetAnyCurRect( CurRectType::FlyEmbeddedPrt, pPt );
+ aDistLR.SetLeft(rFlyPrtRect.Left());
+ aDistLR.SetRight(rFlyPrtRect.Left());
+ rSet.Put(aDistLR);
+ }
+ else
+ {
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aCoreSet2.Put(aBoxInfo);
+ rSh.GetFlyFrameAttr(aCoreSet2);
+ const SvxBoxItem& rBox = aCoreSet2.Get(RES_BOX);
+ aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT));
+ rSet.Put(aDistLR);
+
+ //add the paragraph border distance
+ SfxItemSetFixed<RES_BOX, RES_BOX> aCoreSet1( GetPool() );
+ rSh.GetCurAttr( aCoreSet1 );
+ const SvxBoxItem& rParaBox = aCoreSet1.Get(RES_BOX);
+ aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT));
+ }
+ m_nLeftBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetLeft());
+ m_nRightBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetRight());
+ }
+ else if ( IsTabColFromDoc() ||
+ ( rSh.GetTableFormat() && !bFrameSelection &&
+ !(nFrameType & FrameTypeFlags::COLSECT ) ) )
+ {
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aBoxInfo.SetTable(false);
+ aBoxInfo.SetDist(true);
+ aCoreSet2.Put(aBoxInfo);
+ rSh.GetTabBorders( aCoreSet2 );
+ const SvxBoxItem& rBox = aCoreSet2.Get(RES_BOX);
+ aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT));
+ rSet.Put(aDistLR);
+
+ //add the border distance of the paragraph
+ SfxItemSetFixed<RES_BOX, RES_BOX> aCoreSet1( GetPool() );
+ rSh.GetCurAttr( aCoreSet1 );
+ const SvxBoxItem& rParaBox = aCoreSet1.Get(RES_BOX);
+ aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT));
+ m_nLeftBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetLeft());
+ m_nRightBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetRight());
+ }
+ else if ( !rSh.IsDirectlyInSection() )
+ {
+ //get the page/header/footer border distance
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ const SvxBoxItem& rBox = rMaster.GetAttrSet().Get(RES_BOX);
+ aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT));
+
+ const SvxBoxItem* pBox = nullptr;
+ if(nFrameType & FrameTypeFlags::HEADER)
+ {
+ rMaster.GetHeader();
+ const SwFormatHeader& rHeaderFormat = rMaster.GetHeader();
+ SwFrameFormat *pHeaderFormat = const_cast<SwFrameFormat*>(rHeaderFormat.GetHeaderFormat());
+ if( pHeaderFormat )// #i80890# if rDesc is not the one belonging to the current page is might crash
+ pBox = & pHeaderFormat->GetBox();
+ }
+ else if(nFrameType & FrameTypeFlags::FOOTER )
+ {
+ const SwFormatFooter& rFooterFormat = rMaster.GetFooter();
+ SwFrameFormat *pFooterFormat = const_cast<SwFrameFormat*>(rFooterFormat.GetFooterFormat());
+ if( pFooterFormat )// #i80890# if rDesc is not the one belonging to the current page is might crash
+ pBox = & pFooterFormat->GetBox();
+ }
+ if(pBox)
+ {
+ aDistLR.SetLeft(pBox->GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(pBox->GetDistance(SvxBoxItemLine::RIGHT));
+ }
+ rSet.Put(aDistLR);
+
+ //add the border distance of the paragraph
+ rSh.GetCurAttr(aCoreSet2);
+ const SvxBoxItem& rParaBox = aCoreSet2.Get(RES_BOX);
+ aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT));
+ aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT));
+ m_nLeftBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetLeft());
+ m_nRightBorderDistance = static_cast< sal_uInt16 >(aDistLR.GetRight());
+ }
+ }
+ }
+ break;
+
+ case SID_RULER_TEXT_RIGHT_TO_LEFT:
+ {
+ if ( nSelType & SelectionType::Graphic ||
+ nSelType & SelectionType::Frame ||
+ nSelType & SelectionType::Ole ||
+ nFrameType == FrameTypeFlags::DRAWOBJ)
+ rSet.DisableItem(nWhich);
+ else
+ {
+ bool bFlag = rSh.IsInRightToLeftText();
+ rSet.Put(SfxBoolItem(nWhich, bFlag));
+ }
+ }
+ break;
+
+ case SID_RULER_BORDERS_VERTICAL:
+ case SID_RULER_BORDERS:
+ {
+ bool bFrameHasVerticalColumns(false);
+ {
+ bool bFrameRTL;
+ bool bFrameVertL2R;
+ bFrameHasVerticalColumns = rSh.IsFrameVertical(false, bFrameRTL, bFrameVertL2R) &&
+ bFrameSelection;
+ }
+ bool bHasTable = ( IsTabColFromDoc() ||
+ ( rSh.GetTableFormat() && !bFrameSelection &&
+ !(nFrameType & FrameTypeFlags::COLSECT ) ) );
+
+ bool bTableVertical = bHasTable && rSh.IsTableVertical();
+
+ if(((SID_RULER_BORDERS_VERTICAL == nWhich) &&
+ ((bHasTable && !bTableVertical) ||
+ (!bVerticalWriting && !bFrameSelection && !bHasTable ) ||
+ ( bFrameSelection && !bFrameHasVerticalColumns))) ||
+ ((SID_RULER_BORDERS == nWhich) &&
+ ((bHasTable && bTableVertical) ||
+ (bVerticalWriting && !bFrameSelection&& !bHasTable) || bFrameHasVerticalColumns)))
+ rSet.DisableItem(nWhich);
+ else if ( bHasTable )
+ {
+ SwTabCols aTabCols;
+ size_t nNum = 0;
+ m_bSetTabColFromDoc = IsTabColFromDoc();
+ if ( m_bSetTabColFromDoc )
+ {
+ rSh.GetMouseTabCols( aTabCols, m_aTabColFromDocPos );
+ nNum = rSh.GetCurMouseTabColNum( m_aTabColFromDocPos );
+ }
+ else
+ {
+ rSh.GetTabCols( aTabCols );
+ nNum = rSh.GetCurTabColNum();
+ if(rSh.IsTableRightToLeft())
+ nNum = aTabCols.Count() - nNum;
+ }
+
+ OSL_ENSURE(nNum <= aTabCols.Count(), "TabCol not found");
+ const int nLft = aTabCols.GetLeftMin() + aTabCols.GetLeft();
+ const int nRgt = (bTableVertical ? nPageHeight : nPageWidth) -
+ (aTabCols.GetLeftMin() + aTabCols.GetRight());
+
+ const sal_uInt16 nL = static_cast< sal_uInt16 >(std::max(nLft, 0));
+ const sal_uInt16 nR = static_cast< sal_uInt16 >(std::max(nRgt, 0));
+
+ SvxColumnItem aColItem(nNum, nL, nR);
+
+ tools::Long nStart = 0;
+ tools::Long nEnd = 0;
+
+ //columns in right-to-left tables need to be mirrored
+ bool bIsTableRTL =
+ IsTabColFromDoc() ?
+ rSh.IsMouseTableRightToLeft(m_aTabColFromDocPos)
+ : rSh.IsTableRightToLeft();
+ if(bIsTableRTL)
+ {
+ for ( size_t i = aTabCols.Count(); i; --i )
+ {
+ const SwTabColsEntry& rEntry = aTabCols.GetEntry( i - 1 );
+ nEnd = aTabCols.GetRight() - rEntry.nPos;
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ aTabCols.GetRight() - rEntry.nMax,
+ aTabCols.GetRight() - rEntry.nMin,
+ !aTabCols.IsHidden(i - 1) );
+ aColItem.Append(aColDesc);
+ nStart = nEnd;
+ }
+ SvxColumnDescription aColDesc(nStart,
+ aTabCols.GetRight() - aTabCols.GetLeft(), true);
+ aColItem.Append(aColDesc);
+ }
+ else
+ {
+ for ( size_t i = 0; i < aTabCols.Count(); ++i )
+ {
+ const SwTabColsEntry& rEntry = aTabCols.GetEntry( i );
+ nEnd = rEntry.nPos - aTabCols.GetLeft();
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ rEntry.nMin - aTabCols.GetLeft(), rEntry.nMax - aTabCols.GetLeft(),
+ !aTabCols.IsHidden(i) );
+ aColItem.Append(aColDesc);
+ nStart = nEnd;
+ }
+ SvxColumnDescription aColDesc(nStart, aTabCols.GetRight() - aTabCols.GetLeft(),
+ 0, 0, true);
+ aColItem.Append(aColDesc);
+ }
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ else if ( bFrameSelection || nFrameType & ( FrameTypeFlags::COLUMN | FrameTypeFlags::COLSECT ) )
+ {
+ // Out of frame or page?
+ sal_uInt16 nNum = 0;
+ if(bFrameSelection)
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ if(pFormat)
+ nNum = pFormat->GetCol().GetNumCols();
+ }
+ else
+ nNum = rSh.GetCurColNum();
+
+ if(
+ // For that matter FrameTypeFlags::COLSECT should not be included
+ // if the border is selected!
+ !bFrameSelection &&
+ nFrameType & FrameTypeFlags::COLSECT )
+ {
+ const SwSection *pSect = rSh.GetAnySection(false, pPt);
+ OSL_ENSURE( pSect, "Which section?");
+ if( pSect )
+ {
+ SwSectionFormat const *pFormat = pSect->GetFormat();
+ const SwFormatCol& rCol = pFormat->GetCol();
+ if (rSh.IsColRightToLeft())
+ nNum = rCol.GetColumns().size() - nNum;
+ else
+ --nNum;
+ SvxColumnItem aColItem(nNum);
+ SwRect aRect = rSh.GetAnyCurRect(CurRectType::SectionPrt, pPt);
+ const SwRect aTmpRect = rSh.GetAnyCurRect(CurRectType::Section, pPt);
+
+ ::lcl_FillSvxColumn(rCol, bVerticalWriting ? aRect.Height() : aRect.Width(), aColItem, 0);
+
+ if(bVerticalWriting)
+ {
+ aRect.Pos() += Point(aTmpRect.Left(), aTmpRect.Top());
+ aRect.Pos().AdjustY( -(rPageRect.Top()) );
+ aColItem.SetLeft(aRect.Top());
+ aColItem.SetRight(nPageHeight - aRect.Bottom());
+ }
+ else
+ {
+ aRect.Pos() += aTmpRect.Pos();
+
+ // make relative to page position:
+ aColItem.SetLeft (o3tl::narrowing<sal_uInt16>( aRect.Left() - rPageRect.Left() ));
+ aColItem.SetRight(o3tl::narrowing<sal_uInt16>( rPageRect.Right() - aRect.Right()));
+ }
+ aColItem.SetOrtho(aColItem.CalcOrtho());
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ }
+ else if( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY )
+ {
+ // Columns in frame
+ if ( nNum )
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat() ;
+
+ const SwFormatCol& rCol = pFormat->GetCol();
+ if (rSh.IsColRightToLeft())
+ nNum = rCol.GetColumns().size() - nNum;
+ else
+ nNum--;
+ SvxColumnItem aColItem(nNum);
+ const SwRect &rSizeRect = rSh.GetAnyCurRect(CurRectType::FlyEmbeddedPrt, pPt);
+
+ bool bUseVertical = bFrameHasVerticalColumns || (!bFrameSelection && bVerticalWriting);
+ const tools::Long lWidth = bUseVertical ? rSizeRect.Height() : rSizeRect.Width();
+ const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt);
+ tools::Long nDist2 = ((bUseVertical ? rRect.Height() : rRect.Width()) - lWidth) /2;
+ ::lcl_FillSvxColumn(rCol, lWidth, aColItem, nDist2);
+
+ if(bUseVertical)
+ {
+ aColItem.SetLeft(rRect.Top()- rPageRect.Top());
+ aColItem.SetRight(nPageHeight + rPageRect.Top() - rRect.Bottom());
+ }
+ else
+ {
+ aColItem.SetLeft(rRect.Left() - rPageRect.Left());
+ aColItem.SetRight(rPageRect.Right() - rRect.Right());
+ }
+
+ aColItem.SetOrtho(aColItem.CalcOrtho());
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ else
+ { // Columns on the page
+ const SwFrameFormat& rMaster = rDesc.GetMaster();
+ SwFormatCol aCol(rMaster.GetCol());
+ if(rFrameDir.GetValue() == SvxFrameDirection::Horizontal_RL_TB)
+ nNum = aCol.GetColumns().size() - nNum;
+ else
+ nNum--;
+
+ SvxColumnItem aColItem(nNum);
+ const SwRect aPrtRect = rSh.GetAnyCurRect(CurRectType::PagePrt, pPt);
+ const SvxBoxItem& rBox = rMaster.GetFormatAttr(RES_BOX);
+ tools::Long nDist = rBox.GetSmallestDistance();
+
+ lcl_FillSvxColumn(
+ aCol,
+ bVerticalWriting ? aPrtRect.Height() : aPrtRect.Width(),
+ aColItem, nDist);
+
+ if(bBrowse)
+ {
+ if (bVerticalWriting)
+ {
+ aColItem.SetLeft(o3tl::narrowing<sal_uInt16>(rPagePrtRect.Top()));
+ aColItem.SetRight(sal_uInt16(nPageHeight - rPagePrtRect.Bottom()));
+ }
+ else
+ {
+ aColItem.SetLeft(o3tl::narrowing<sal_uInt16>(rPagePrtRect.Left()));
+ aColItem.SetRight(sal_uInt16(nPageWidth - rPagePrtRect.Right()));
+ }
+ }
+ else
+ {
+ if (bVerticalWriting)
+ {
+ SvxULSpaceItem aUL( rDesc.GetMaster().GetULSpace() );
+ aColItem.SetLeft (aUL.GetUpper());
+ aColItem.SetRight(aUL.GetLower());
+ }
+ else
+ {
+ aColItem.SetLeft (aPageLRSpace.GetLeft());
+ aColItem.SetRight(aPageLRSpace.GetRight());
+ }
+ }
+ aColItem.SetOrtho(aColItem.CalcOrtho());
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ }
+ else
+ rSet.DisableItem(nWhich);
+ break;
+ }
+
+ case SID_RULER_ROWS :
+ case SID_RULER_ROWS_VERTICAL:
+ {
+ bool bFrameHasVerticalColumns(false);
+ {
+ bool bFrameRTL;
+ bool bFrameVertL2R;
+ bFrameHasVerticalColumns = rSh.IsFrameVertical(false, bFrameRTL, bFrameVertL2R) &&
+ bFrameSelection;
+ }
+
+ if(((SID_RULER_ROWS == nWhich) &&
+ ((!bVerticalWriting && !bFrameSelection) || (bFrameSelection && !bFrameHasVerticalColumns))) ||
+ ((SID_RULER_ROWS_VERTICAL == nWhich) &&
+ ((bVerticalWriting && !bFrameSelection) || bFrameHasVerticalColumns)))
+ rSet.DisableItem(nWhich);
+ else if ( IsTabRowFromDoc() ||
+ ( rSh.GetTableFormat() && !bFrameSelection &&
+ !(nFrameType & FrameTypeFlags::COLSECT ) ) )
+ {
+ SwTabCols aTabCols;
+ m_bSetTabRowFromDoc = IsTabRowFromDoc();
+ if ( m_bSetTabRowFromDoc )
+ {
+ rSh.GetMouseTabRows( aTabCols, m_aTabColFromDocPos );
+ }
+ else
+ {
+ rSh.GetTabRows( aTabCols );
+ }
+
+ const int nLft = aTabCols.GetLeftMin();
+ const int nRgt = (bVerticalWriting ? nPageWidth : nPageHeight) -
+ (aTabCols.GetLeftMin() + aTabCols.GetRight());
+
+ const sal_uInt16 nL = static_cast< sal_uInt16 >(std::max(nLft, 0));
+ const sal_uInt16 nR = static_cast< sal_uInt16 >(std::max(nRgt, 0));
+
+ SvxColumnItem aColItem(0, nL, nR);
+
+ tools::Long nStart = 0;
+ tools::Long nEnd = 0;
+
+ for ( size_t i = 0; i < aTabCols.Count(); ++i )
+ {
+ const SwTabColsEntry& rEntry = aTabCols.GetEntry( i );
+ if(bVerticalWriting)
+ {
+ nEnd = aTabCols.GetRight() - rEntry.nPos;
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ std::max(tools::Long(0), aTabCols.GetRight() - rEntry.nMax),
+ std::max(tools::Long(0), aTabCols.GetRight() - rEntry.nMin),
+ !aTabCols.IsHidden(i) );
+ aColItem.Append(aColDesc);
+ }
+ else
+ {
+ nEnd = rEntry.nPos - aTabCols.GetLeft();
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ rEntry.nMin - aTabCols.GetLeft(),
+ rEntry.nMax - aTabCols.GetLeft(),
+ !aTabCols.IsHidden(i) );
+ aColItem.Append(aColDesc);
+ }
+ nStart = nEnd;
+ }
+ if(bVerticalWriting)
+ nEnd = aTabCols.GetRight();
+ else
+ nEnd = aTabCols.GetLeft();
+
+ SvxColumnDescription aColDesc( nStart, nEnd,
+ aTabCols.GetRight(),
+ aTabCols.GetRight(),
+ false );
+ aColItem.Append(aColDesc);
+
+ aColItem.SetWhich(nWhich);
+ rSet.Put(aColItem);
+ }
+ else
+ rSet.DisableItem(nWhich);
+ }
+ break;
+
+ case SID_RULER_PAGE_POS:
+ {
+ SvxPagePosSizeItem aPagePosSize(
+ Point( rPageRect.Left(), rPageRect.Top()) , nPageWidth, nPageHeight);
+
+ rSet.Put(aPagePosSize);
+ break;
+ }
+
+ case SID_RULER_LR_MIN_MAX:
+ {
+ tools::Rectangle aRectangle;
+ if( ( nFrameType & FrameTypeFlags::COLSECT ) && !IsTabColFromDoc() &&
+ ( nFrameType & ( FrameTypeFlags::TABLE|FrameTypeFlags::COLUMN ) ) )
+ {
+ if( nFrameType & FrameTypeFlags::TABLE )
+ {
+ const size_t nNum = rSh.GetCurTabColNum();
+ SwTabCols aTabCols;
+ rSh.GetTabCols( aTabCols );
+
+ const int nLft = aTabCols.GetLeftMin() + aTabCols.GetLeft();
+ const int nRgt = nPageWidth -(aTabCols.GetLeftMin() + aTabCols.GetRight());
+
+ const sal_uInt16 nL = static_cast< sal_uInt16 >(std::max(nLft, 0));
+ const sal_uInt16 nR = static_cast< sal_uInt16 >(std::max(nRgt, 0));
+
+ aRectangle.SetLeft( nL );
+ if(nNum > 1)
+ aRectangle.AdjustLeft(aTabCols[nNum - 2] );
+ if(nNum)
+ aRectangle.AdjustLeft(MINLAY );
+ if(aTabCols.Count() <= nNum + 1 )
+ aRectangle.SetRight( nR );
+ else
+ aRectangle.SetRight( nPageWidth - (nL + aTabCols[nNum + 1]) );
+
+ if(nNum < aTabCols.Count())
+ aRectangle.AdjustRight(MINLAY );
+ }
+ else
+ {
+ const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat();
+ const SwFormatCol* pCols = pFormat ? &pFormat->GetCol():
+ &rDesc.GetMaster().GetCol();
+ const SwColumns& rCols = pCols->GetColumns();
+ sal_uInt16 nNum = rSh.GetCurOutColNum();
+ const sal_uInt16 nCount = std::min(sal_uInt16(nNum + 1), sal_uInt16(rCols.size()));
+ const SwRect aRect( rSh.GetAnyCurRect( pFormat
+ ? CurRectType::FlyEmbeddedPrt
+ : CurRectType::PagePrt, pPt ));
+ const SwRect aAbsRect( rSh.GetAnyCurRect( pFormat
+ ? CurRectType::FlyEmbedded
+ : CurRectType::Page, pPt ));
+
+ // The width of the frame or within the page margins.
+ const sal_uInt16 nTotalWidth = o3tl::narrowing<sal_uInt16>(aRect.Width());
+ // The entire frame width - The difference is twice the distance to the edge.
+ const sal_uInt16 nOuterWidth = o3tl::narrowing<sal_uInt16>(aAbsRect.Width());
+ int nWidth = 0,
+ nEnd = 0;
+ aRectangle.SetLeft( 0 );
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ const SwColumn* pCol = &rCols[i];
+ const int nStart = pCol->GetLeft() + nWidth;
+ if(i == nNum - 2)
+ aRectangle.SetLeft( nStart );
+ nWidth += pCols->CalcColWidth( i, nTotalWidth );
+ nEnd = nWidth - pCol->GetRight();
+ }
+ aRectangle.SetRight( rPageRect.Right() - nEnd );
+ aRectangle.AdjustLeft( -(rPageRect.Left()) );
+
+ if(nNum > 1)
+ {
+ aRectangle.AdjustLeft(MINLAY );
+ aRectangle.AdjustLeft(aRect.Left() );
+ }
+ if(pFormat) // Range in frame - here you may up to the edge
+ {
+ aRectangle.SetLeft(0);
+ aRectangle.SetRight(0);
+ }
+ else
+ {
+ // Move the rectangle to the correct absolute position.
+ aRectangle.AdjustLeft(aAbsRect.Left() );
+ aRectangle.AdjustRight( -(aAbsRect.Left()) );
+ // Include distance to the border.
+ aRectangle.AdjustRight( -((nOuterWidth - nTotalWidth) / 2) );
+ }
+
+ if(nNum < rCols.size())
+ {
+ aRectangle.AdjustRight(MINLAY );
+ }
+ else
+ // Right is only the margin now.
+ aRectangle.SetRight( 0 );
+
+ }
+ }
+ else if ( ((nFrameType & FrameTypeFlags::TABLE) || IsTabColFromDoc()) &&
+ !bFrameSelection )
+ {
+ bool bColumn;
+ if ( IsTabColFromDoc() )
+ bColumn = rSh.GetCurMouseColNum( m_aTabColFromDocPos ) != 0;
+ else
+ bColumn = bool(nFrameType & (FrameTypeFlags::COLUMN|FrameTypeFlags::FLY_ANY|FrameTypeFlags::COLSECTOUTTAB));
+
+ if ( !bColumn )
+ {
+ if( nFrameType & FrameTypeFlags::FLY_ANY && IsTabColFromDoc() )
+ {
+ SwRect aRect( rSh.GetAnyCurRect(
+ CurRectType::FlyEmbeddedPrt, pPt ) );
+ aRect.Pos() += rSh.GetAnyCurRect( CurRectType::FlyEmbedded,
+ pPt ).Pos();
+
+ aRectangle.SetLeft( aRect.Left() - rPageRect.Left() );
+ aRectangle.SetRight( rPageRect.Right() - aRect.Right() );
+ }
+ else if( bBrowse )
+ {
+ aRectangle.SetLeft( rPagePrtRect.Left() );
+ aRectangle.SetRight( nPageWidth - rPagePrtRect.Right() );
+ }
+ else
+ {
+ aRectangle.SetLeft( aPageLRSpace.GetLeft() );
+ aRectangle.SetRight( aPageLRSpace.GetRight() );
+ }
+ }
+ else
+ { // Here only for table in multi-column pages and borders.
+ bool bSectOutTable = bool(nFrameType & FrameTypeFlags::TABLE);
+ bool bFrame = bool(nFrameType & FrameTypeFlags::FLY_ANY);
+ bool bColSct = bool(nFrameType & ( bSectOutTable
+ ? FrameTypeFlags::COLSECTOUTTAB
+ : FrameTypeFlags::COLSECT )
+ );
+ //So you can also drag with the mouse, without being in the table.
+ CurRectType eRecType = CurRectType::PagePrt;
+ size_t nNum = IsTabColFromDoc() ?
+ rSh.GetCurMouseColNum( m_aTabColFromDocPos ):
+ rSh.GetCurOutColNum();
+ const SwFrameFormat* pFormat = nullptr;
+ if( bColSct )
+ {
+ eRecType = bSectOutTable ? CurRectType::SectionOutsideTable
+ : CurRectType::Section;
+ const SwSection *pSect = rSh.GetAnySection( bSectOutTable, pPt );
+ OSL_ENSURE( pSect, "Which section?");
+ pFormat = pSect->GetFormat();
+ }
+ else if( bFrame )
+ {
+ pFormat = rSh.GetFlyFrameFormat();
+ eRecType = CurRectType::FlyEmbeddedPrt;
+ }
+
+ const SwFormatCol* pCols = pFormat ? &pFormat->GetCol():
+ &rDesc.GetMaster().GetCol();
+ const SwColumns& rCols = pCols->GetColumns();
+ const sal_uInt16 nBorder = pFormat
+ ? pFormat->GetBox().GetSmallestDistance()
+ : rDesc.GetMaster().GetBox().GetSmallestDistance();
+
+ // RECT_FLY_PRT_EMBEDDED returns the relative position to RECT_FLY_EMBEDDED
+ // the absolute position must be added here
+
+ SwRect aRect( rSh.GetAnyCurRect( eRecType, pPt ) );
+ if(CurRectType::FlyEmbeddedPrt == eRecType)
+ aRect.Pos() += rSh.GetAnyCurRect( CurRectType::FlyEmbedded,
+ pPt ).Pos();
+
+ const sal_uInt16 nTotalWidth = o3tl::narrowing<sal_uInt16>(aRect.Width());
+ // Initialize nStart and nEnd for nNum == 0
+ int nWidth = 0,
+ nStart = 0,
+ nEnd = nTotalWidth;
+
+ if( nNum > rCols.size() )
+ {
+ OSL_ENSURE( false, "wrong FormatCol is being edited!" );
+ nNum = rCols.size();
+ }
+
+ for( size_t i = 0; i < nNum; ++i )
+ {
+ const SwColumn* pCol = &rCols[i];
+ nStart = pCol->GetLeft() + nWidth;
+ nWidth += pCols->CalcColWidth( o3tl::narrowing<sal_uInt16>(i), nTotalWidth );
+ nEnd = nWidth - pCol->GetRight();
+ }
+ if( bFrame || bColSct )
+ {
+ aRectangle.SetLeft( aRect.Left() - rPageRect.Left() + nStart );
+ aRectangle.SetRight( nPageWidth - aRectangle.Left() - nEnd + nStart );
+ }
+ else if(!bBrowse)
+ {
+ aRectangle.SetLeft( aPageLRSpace.GetLeft() + nStart );
+ aRectangle.SetRight( nPageWidth - nEnd - aPageLRSpace.GetLeft() );
+ }
+ else
+ {
+ tools::Long nLeft = rPagePrtRect.Left();
+ aRectangle.SetLeft( nStart + nLeft );
+ aRectangle.SetRight( nPageWidth - nEnd - nLeft );
+ }
+ if(!bFrame)
+ {
+ aRectangle.AdjustLeft(nBorder );
+ aRectangle.AdjustRight( -nBorder );
+ }
+ }
+ }
+ else if ( nFrameType & ( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER ))
+ {
+ aRectangle.SetLeft( aPageLRSpace.GetLeft() );
+ aRectangle.SetRight( aPageLRSpace.GetRight() );
+ }
+ else
+ {
+ aRectangle.SetLeft(0);
+ aRectangle.SetRight(0);
+ }
+
+ SfxRectangleItem aLR( SID_RULER_LR_MIN_MAX , aRectangle);
+ rSet.Put(aLR);
+ }
+ break;
+
+ case SID_RULER_PROTECT:
+ {
+ if(bFrameSelection)
+ {
+ FlyProtectFlags nProtect = m_pWrtShell->IsSelObjProtected( FlyProtectFlags::Size|FlyProtectFlags::Pos|FlyProtectFlags::Content );
+
+ SvxProtectItem aProt(SID_RULER_PROTECT);
+ aProt.SetContentProtect(bool(nProtect & FlyProtectFlags::Content));
+ aProt.SetSizeProtect (bool(nProtect & FlyProtectFlags::Size));
+ aProt.SetPosProtect (bool(nProtect & FlyProtectFlags::Pos));
+ rSet.Put(aProt);
+ }
+ else
+ {
+ SvxProtectItem aProtect(SID_RULER_PROTECT);
+ if(bBrowse && !(nFrameType & (FrameTypeFlags::DRAWOBJ|FrameTypeFlags::COLUMN)) && !rSh.GetTableFormat())
+ {
+ aProtect.SetSizeProtect(true);
+ aProtect.SetPosProtect(true);
+ }
+ rSet.Put(aProtect);
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_HEADER:
+ case SID_ATTR_PAGE_HEADER_LRMARGIN:
+ case SID_ATTR_PAGE_HEADER_SPACING:
+ case SID_ATTR_PAGE_HEADER_LAYOUT:
+ {
+ const SwFormatHeader& rHeader = rDesc.GetMaster().GetHeader();
+ bool bHeaderOn = rHeader.IsActive();
+ rSet.Put( SfxBoolItem(SID_ATTR_PAGE_HEADER, bHeaderOn ) );
+ if(bHeaderOn)
+ {
+ const SvxLRSpaceItem* pLR = rHeader.GetHeaderFormat()->GetAttrSet().GetItem(SID_ATTR_LRSPACE);
+ const SvxULSpaceItem* pUL = rHeader.GetHeaderFormat()->GetAttrSet().GetItem(SID_ATTR_ULSPACE);
+ if (pLR && pUL)
+ {
+ SvxLongLRSpaceItem aLR(pLR->GetLeft(), pLR->GetRight(), SID_ATTR_PAGE_HEADER_LRMARGIN);
+ rSet.Put(aLR);
+ SvxLongULSpaceItem aUL( pUL->GetUpper(), pUL->GetLower(), SID_ATTR_PAGE_HEADER_SPACING);
+ rSet.Put(aUL);
+ }
+
+ bool bShared = !rDesc.IsHeaderShared();
+ bool bFirst = !rDesc.IsFirstShared(); // FIXME control changes for both header footer - tdf#100287
+ sal_uInt16 nLayout = (static_cast<int>(bShared)<<1) + static_cast<int>(bFirst);
+ SfxInt16Item aLayoutItem(SID_ATTR_PAGE_HEADER_LAYOUT, nLayout);
+ rSet.Put(aLayoutItem);
+ }
+ }
+ break;
+ case SID_ATTR_PAGE_FOOTER:
+ case SID_ATTR_PAGE_FOOTER_LRMARGIN:
+ case SID_ATTR_PAGE_FOOTER_SPACING:
+ case SID_ATTR_PAGE_FOOTER_LAYOUT:
+ {
+ const SwFormatFooter& rFooter = rDesc.GetMaster().GetFooter();
+ bool bFooterOn = rFooter.IsActive();
+ rSet.Put( SfxBoolItem(SID_ATTR_PAGE_FOOTER, bFooterOn ) );
+ if (bFooterOn)
+ {
+ if (const SvxLRSpaceItem* rLR = rFooter.GetFooterFormat()->GetAttrSet().GetItem<SvxLRSpaceItem>(SID_ATTR_LRSPACE))
+ {
+ SvxLongLRSpaceItem aLR(rLR->GetLeft(), rLR->GetRight(), SID_ATTR_PAGE_FOOTER_LRMARGIN);
+ rSet.Put(aLR);
+ }
+ if (const SvxULSpaceItem* rUL = rFooter.GetFooterFormat()->GetAttrSet().GetItem<SvxULSpaceItem>(SID_ATTR_ULSPACE))
+ {
+ SvxLongULSpaceItem aUL( rUL->GetUpper(), rUL->GetLower(), SID_ATTR_PAGE_FOOTER_SPACING);
+ rSet.Put(aUL);
+ }
+ bool bShared = !rDesc.IsFooterShared();
+ bool bFirst = !rDesc.IsFirstShared(); // FIXME control changes for both header footer - tdf#100287
+ sal_uInt16 nLayout = (static_cast<int>(bShared)<<1) + static_cast<int>(bFirst);
+ SfxInt16Item aLayoutItem(SID_ATTR_PAGE_FOOTER_LAYOUT, nLayout);
+ rSet.Put(aLayoutItem);
+ }
+ }
+ break;
+
+ case SID_ATTR_PAGE_COLOR:
+ case SID_ATTR_PAGE_FILLSTYLE:
+ case SID_ATTR_PAGE_GRADIENT:
+ case SID_ATTR_PAGE_HATCH:
+ case SID_ATTR_PAGE_BITMAP:
+ {
+ const SfxItemSet& rMasterSet = rDesc.GetMaster().GetAttrSet();
+ if (const auto pFillStyleItem = rMasterSet.GetItem(XATTR_FILLSTYLE))
+ {
+ drawing::FillStyle eXFS = pFillStyleItem->GetValue();
+ XFillStyleItem aFillStyleItem( eXFS );
+ aFillStyleItem.SetWhich( SID_ATTR_PAGE_FILLSTYLE );
+ rSet.Put(aFillStyleItem);
+
+ switch(eXFS)
+ {
+ case drawing::FillStyle_SOLID:
+ {
+ if (const auto pItem = rMasterSet.GetItem<XFillColorItem>(XATTR_FILLCOLOR, false))
+ {
+ Color aColor = pItem->GetColorValue();
+ XFillColorItem aFillColorItem( OUString(), aColor );
+ aFillColorItem.SetWhich( SID_ATTR_PAGE_COLOR );
+ rSet.Put( aFillColorItem );
+ }
+ break;
+ }
+
+ case drawing::FillStyle_GRADIENT:
+ {
+ const basegfx::BGradient& aBGradient = rMasterSet.GetItem<XFillGradientItem>( XATTR_FILLGRADIENT )->GetGradientValue();
+ XFillGradientItem aFillGradientItem( OUString(), aBGradient, SID_ATTR_PAGE_GRADIENT );
+ rSet.Put( aFillGradientItem );
+ }
+ break;
+
+ case drawing::FillStyle_HATCH:
+ {
+ const XFillHatchItem *pFillHatchItem( rMasterSet.GetItem<XFillHatchItem>( XATTR_FILLHATCH ) );
+ XFillHatchItem aFillHatchItem( pFillHatchItem->GetName(), pFillHatchItem->GetHatchValue());
+ aFillHatchItem.SetWhich( SID_ATTR_PAGE_HATCH );
+ rSet.Put( aFillHatchItem );
+ }
+ break;
+
+ case drawing::FillStyle_BITMAP:
+ {
+ const XFillBitmapItem *pFillBitmapItem = rMasterSet.GetItem<XFillBitmapItem>( XATTR_FILLBITMAP );
+ XFillBitmapItem aFillBitmapItem( pFillBitmapItem->GetName(), pFillBitmapItem->GetGraphicObject() );
+ aFillBitmapItem.SetWhich( SID_ATTR_PAGE_BITMAP );
+ rSet.Put( aFillBitmapItem );
+ }
+ break;
+ case drawing::FillStyle_NONE:
+ {
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */