diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /editeng/source/outliner/outlvw.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'editeng/source/outliner/outlvw.cxx')
-rw-r--r-- | editeng/source/outliner/outlvw.cxx | 1481 |
1 files changed, 1481 insertions, 0 deletions
diff --git a/editeng/source/outliner/outlvw.cxx b/editeng/source/outliner/outlvw.cxx new file mode 100644 index 000000000..8d1127e15 --- /dev/null +++ b/editeng/source/outliner/outlvw.cxx @@ -0,0 +1,1481 @@ +/* -*- 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 <com/sun/star/i18n/WordType.hpp> + +#include <svl/itempool.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> + +#include <svl/style.hxx> +#include <svl/languageoptions.hxx> +#include <i18nlangtag/languagetag.hxx> + +#include <editeng/outliner.hxx> +#include "outleeng.hxx" +#include "paralist.hxx" +#include "outlundo.hxx" +#include <editeng/outlobj.hxx> +#include <editeng/flditem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/numitem.hxx> +#include <vcl/window.hxx> +#include <vcl/event.hxx> +#include <vcl/ptrstyle.hxx> +#include <svl/itemset.hxx> +#include <svl/eitem.hxx> +#include <editeng/editstat.hxx> +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <tools/debug.hxx> + +using namespace ::com::sun::star; + + +OutlinerView::OutlinerView( Outliner* pOut, vcl::Window* pWin ) +{ + pOwner = pOut; + pEditView.reset( new EditView( pOut->pEditEngine.get(), pWin ) ); +} + +OutlinerView::~OutlinerView() +{ +} + +void OutlinerView::Paint( const tools::Rectangle& rRect, OutputDevice* pTargetDevice ) +{ + // For the first Paint/KeyInput/Drop an empty Outliner is turned into + // an Outliner with exactly one paragraph. + if( pOwner->bFirstParaIsEmpty ) + pOwner->Insert( OUString() ); + + pEditView->Paint( rRect, pTargetDevice ); +} + +bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFrameWin ) +{ + // For the first Paint/KeyInput/Drop an empty Outliner is turned into + // an Outliner with exactly one paragraph. + if( pOwner->bFirstParaIsEmpty ) + pOwner->Insert( OUString() ); + + bool bKeyProcessed = false; + ESelection aSel( pEditView->GetSelection() ); + bool bSelection = aSel.HasRange(); + vcl::KeyCode aKeyCode = rKEvt.GetKeyCode(); + KeyFuncType eFunc = aKeyCode.GetFunction(); + sal_uInt16 nCode = aKeyCode.GetCode(); + bool bReadOnly = IsReadOnly(); + + if( bSelection && ( nCode != KEY_TAB ) && EditEngine::DoesKeyChangeText( rKEvt ) ) + { + if ( ImpCalcSelectedPages( false ) && !pOwner->ImpCanDeleteSelectedPages( this ) ) + return true; + } + + if ( eFunc != KeyFuncType::DONTKNOW ) + { + switch ( eFunc ) + { + case KeyFuncType::CUT: + { + if ( !bReadOnly ) + { + Cut(); + bKeyProcessed = true; + } + } + break; + case KeyFuncType::COPY: + { + Copy(); + bKeyProcessed = true; + } + break; + case KeyFuncType::PASTE: + { + if ( !bReadOnly ) + { + PasteSpecial(); + bKeyProcessed = true; + } + } + break; + case KeyFuncType::DELETE: + { + if( !bReadOnly && !bSelection && ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TextObject ) ) + { + if( aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) ) + { + Paragraph* pNext = pOwner->pParaList->GetParagraph( aSel.nEndPara+1 ); + if( pNext && pNext->HasFlag(ParaFlag::ISPAGE) ) + { + if( !pOwner->ImpCanDeleteSelectedPages( this, aSel.nEndPara, 1 ) ) + return false; + } + } + } + } + break; + default: // is then possibly edited below. + eFunc = KeyFuncType::DONTKNOW; + } + } + if ( eFunc == KeyFuncType::DONTKNOW ) + { + switch ( nCode ) + { + case KEY_TAB: + { + if ( !bReadOnly && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) + { + if ( ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TextObject ) && + ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TitleObject ) && + ( bSelection || !aSel.nStartPos ) ) + { + Indent( aKeyCode.IsShift() ? -1 : +1 ); + bKeyProcessed = true; + } + else if ( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) && + !bSelection && !aSel.nEndPos && pOwner->ImplHasNumberFormat( aSel.nEndPara ) ) + { + Indent( aKeyCode.IsShift() ? -1 : +1 ); + bKeyProcessed = true; + } + } + } + break; + case KEY_BACKSPACE: + { + if( !bReadOnly && !bSelection && aSel.nEndPara && !aSel.nEndPos ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( aSel.nEndPara ); + Paragraph* pPrev = pOwner->pParaList->GetParagraph( aSel.nEndPara-1 ); + if( !pPrev->IsVisible() ) + return true; + if( !pPara->GetDepth() ) + { + if(!pOwner->ImpCanDeleteSelectedPages(this, aSel.nEndPara , 1 ) ) + return true; + } + } + } + break; + case KEY_RETURN: + { + if ( !bReadOnly ) + { + // Special treatment: hard return at the end of a paragraph, + // which has collapsed subparagraphs. + Paragraph* pPara = pOwner->pParaList->GetParagraph( aSel.nEndPara ); + + if( !aKeyCode.IsShift() ) + { + // ImpGetCursor again??? + if( !bSelection && + aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) ) + { + sal_Int32 nChildren = pOwner->pParaList->GetChildCount(pPara); + if( nChildren && !pOwner->pParaList->HasVisibleChildren(pPara)) + { + pOwner->UndoActionStart( OLUNDO_INSERT ); + sal_Int32 nTemp = aSel.nEndPara; + nTemp += nChildren; + nTemp++; // insert above next Non-Child + SAL_WARN_IF( nTemp < 0, "editeng", "OutlinerView::PostKeyEvent - overflow"); + if (nTemp >= 0) + { + pOwner->Insert( OUString(),nTemp,pPara->GetDepth()); + // Position the cursor + ESelection aTmpSel(nTemp,0,nTemp,0); + pEditView->SetSelection( aTmpSel ); + } + pEditView->ShowCursor(); + pOwner->UndoActionEnd(); + bKeyProcessed = true; + } + } + } + if( !bKeyProcessed && !bSelection && + !aKeyCode.IsShift() && aKeyCode.IsMod1() && + ( aSel.nEndPos == pOwner->pEditEngine->GetTextLen(aSel.nEndPara) ) ) + { + pOwner->UndoActionStart( OLUNDO_INSERT ); + sal_Int32 nTemp = aSel.nEndPara; + nTemp++; + pOwner->Insert( OUString(), nTemp, pPara->GetDepth()+1 ); + + // Position the cursor + ESelection aTmpSel(nTemp,0,nTemp,0); + pEditView->SetSelection( aTmpSel ); + pEditView->ShowCursor(); + pOwner->UndoActionEnd(); + bKeyProcessed = true; + } + } + } + break; + } + } + + return bKeyProcessed || pEditView->PostKeyEvent( rKEvt, pFrameWin ); +} + +sal_Int32 OutlinerView::ImpCheckMousePos(const Point& rPosPix, MouseTarget& reTarget) +{ + sal_Int32 nPara = EE_PARA_NOT_FOUND; + + Point aMousePosWin = pEditView->GetWindow()->PixelToLogic( rPosPix ); + if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + { + reTarget = MouseTarget::Outside; + } + else + { + reTarget = MouseTarget::Text; + + Point aPaperPos( aMousePosWin ); + tools::Rectangle aOutArea = pEditView->GetOutputArea(); + tools::Rectangle aVisArea = pEditView->GetVisArea(); + aPaperPos.AdjustX( -(aOutArea.Left()) ); + aPaperPos.AdjustX(aVisArea.Left() ); + aPaperPos.AdjustY( -(aOutArea.Top()) ); + aPaperPos.AdjustY(aVisArea.Top() ); + + bool bBullet; + if ( pOwner->IsTextPos( aPaperPos, 0, &bBullet ) ) + { + Point aDocPos = pOwner->GetDocPos( aPaperPos ); + nPara = pOwner->pEditEngine->FindParagraph( aDocPos.Y() ); + + if ( bBullet ) + { + reTarget = MouseTarget::Bullet; + } + else + { + // Check for hyperlink + const SvxFieldItem* pFieldItem = pEditView->GetField( aMousePosWin ); + if ( pFieldItem && pFieldItem->GetField() && dynamic_cast< const SvxURLField* >(pFieldItem->GetField()) != nullptr ) + reTarget = MouseTarget::Hypertext; + } + } + } + return nPara; +} + +bool OutlinerView::MouseMove( const MouseEvent& rMEvt ) +{ + if( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->GetEditEngine()->IsInSelectionMode()) + return pEditView->MouseMove( rMEvt ); + + Point aMousePosWin( pEditView->GetWindow()->PixelToLogic( rMEvt.GetPosPixel() ) ); + if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + return false; + + PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() ); + pEditView->GetWindow()->SetPointer( aPointer ); + return pEditView->MouseMove( rMEvt ); +} + + +bool OutlinerView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->GetEditEngine()->IsInSelectionMode() ) + return pEditView->MouseButtonDown( rMEvt ); + + Point aMousePosWin( pEditView->GetWindow()->PixelToLogic( rMEvt.GetPosPixel() ) ); + if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + return false; + + PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() ); + pEditView->GetWindow()->SetPointer( aPointer ); + + MouseTarget eTarget; + sal_Int32 nPara = ImpCheckMousePos( rMEvt.GetPosPixel(), eTarget ); + if ( eTarget == MouseTarget::Bullet ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + bool bHasChildren = (pPara && pOwner->pParaList->HasChildren(pPara)); + if( rMEvt.GetClicks() == 1 ) + { + sal_Int32 nEndPara = nPara; + if ( bHasChildren && pOwner->pParaList->HasVisibleChildren(pPara) ) + nEndPara += pOwner->pParaList->GetChildCount( pPara ); + // The selection is inverted, so that EditEngine does not scroll + ESelection aSel(nEndPara, EE_TEXTPOS_ALL, nPara, 0 ); + pEditView->SetSelection( aSel ); + } + else if( rMEvt.GetClicks() == 2 && bHasChildren ) + ImpToggleExpand( pPara ); + + return true; + } + + // special case for outliner view in impress, check if double click hits the page icon for toggle + if( (nPara == EE_PARA_NOT_FOUND) && (pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineView) && (eTarget == MouseTarget::Text) && (rMEvt.GetClicks() == 2) ) + { + ESelection aSel( pEditView->GetSelection() ); + nPara = aSel.nStartPara; + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + if( (pPara && pOwner->pParaList->HasChildren(pPara)) && pPara->HasFlag(ParaFlag::ISPAGE) ) + { + ImpToggleExpand( pPara ); + } + } + return pEditView->MouseButtonDown( rMEvt ); +} + + +bool OutlinerView::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->GetEditEngine()->IsInSelectionMode() ) + return pEditView->MouseButtonUp( rMEvt ); + + Point aMousePosWin( pEditView->GetWindow()->PixelToLogic( rMEvt.GetPosPixel() ) ); + if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + return false; + + PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() ); + pEditView->GetWindow()->SetPointer( aPointer ); + + return pEditView->MouseButtonUp( rMEvt ); +} + +void OutlinerView::ReleaseMouse() +{ + pEditView->ReleaseMouse(); +} + +void OutlinerView::ImpToggleExpand( Paragraph const * pPara ) +{ + sal_Int32 nPara = pOwner->pParaList->GetAbsPos( pPara ); + pEditView->SetSelection( ESelection( nPara, 0, nPara, 0 ) ); + ImplExpandOrCollaps( nPara, nPara, !pOwner->pParaList->HasVisibleChildren( pPara ) ); + pEditView->ShowCursor(); +} + +void OutlinerView::Select( Paragraph const * pParagraph, bool bSelect ) +{ + sal_Int32 nPara = pOwner->pParaList->GetAbsPos( pParagraph ); + sal_Int32 nEnd = 0; + if ( bSelect ) + nEnd = SAL_MAX_INT32; + + ESelection aSel( nPara, 0, nPara, nEnd ); + pEditView->SetSelection( aSel ); +} + + +void OutlinerView::SetAttribs( const SfxItemSet& rAttrs ) +{ + bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); + pOwner->pEditEngine->SetUpdateMode( false ); + + if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) + pOwner->UndoActionStart( OLUNDO_ATTR ); + + ParaRange aSel = ImpGetSelectedParagraphs( false ); + + pEditView->SetAttribs( rAttrs ); + + // Update Bullet text + for( sal_Int32 nPara= aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + pOwner->ImplCheckNumBulletItem( nPara ); + pOwner->ImplCalcBulletText( nPara, false, false ); + + if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) + pOwner->InsertUndo( std::make_unique<OutlinerUndoCheckPara>( pOwner, nPara ) ); + } + + if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) + pOwner->UndoActionEnd(); + + pEditView->SetEditEngineUpdateMode( bUpdate ); +} + +ParaRange OutlinerView::ImpGetSelectedParagraphs( bool bIncludeHiddenChildren ) +{ + ESelection aSel = pEditView->GetSelection(); + ParaRange aParas( aSel.nStartPara, aSel.nEndPara ); + aParas.Adjust(); + + // Record the invisible Children of the last Parents in the selection + if ( bIncludeHiddenChildren ) + { + Paragraph* pLast = pOwner->pParaList->GetParagraph( aParas.nEndPara ); + if ( pOwner->pParaList->HasHiddenChildren( pLast ) ) + aParas.nEndPara = aParas.nEndPara + pOwner->pParaList->GetChildCount( pLast ); + } + return aParas; +} + +// TODO: Name should be changed! +void OutlinerView::AdjustDepth( short nDX ) +{ + Indent( nDX ); +} + +void OutlinerView::Indent( short nDiff ) +{ + if( !nDiff || ( ( nDiff > 0 ) && ImpCalcSelectedPages( true ) && !pOwner->ImpCanIndentSelectedPages( this ) ) ) + return; + + const bool bOutlinerView = bool(pOwner->pEditEngine->GetControlWord() & EEControlBits::OUTLINER); + bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); + pOwner->pEditEngine->SetUpdateMode( false ); + + bool bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled(); + + if( bUndo ) + pOwner->UndoActionStart( OLUNDO_DEPTH ); + + sal_Int16 nMinDepth = -1; // Optimization: avoid recalculate too many paragraphs if not really needed. + + ParaRange aSel = ImpGetSelectedParagraphs( true ); + for ( sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + + sal_Int16 nOldDepth = pPara->GetDepth(); + sal_Int16 nNewDepth = nOldDepth + nDiff; + + if( bOutlinerView && nPara ) + { + const bool bPage = pPara->HasFlag(ParaFlag::ISPAGE); + if( (bPage && (nDiff == +1)) || (!bPage && (nDiff == -1) && (nOldDepth <= 0)) ) + { + // Notify App + pOwner->nDepthChangedHdlPrevDepth = nOldDepth; + ParaFlag nPrevFlags = pPara->nFlags; + + if( bPage ) + pPara->RemoveFlag( ParaFlag::ISPAGE ); + else + pPara->SetFlag( ParaFlag::ISPAGE ); + + pOwner->DepthChangedHdl(pPara, nPrevFlags); + pOwner->pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); + + if( bUndo ) + pOwner->InsertUndo( std::make_unique<OutlinerUndoChangeParaFlags>( pOwner, nPara, nPrevFlags, pPara->nFlags ) ); + + continue; + } + } + + // do not switch off numeration with tab + if( (nOldDepth == 0) && (nNewDepth == -1) ) + continue; + + // do not indent if there is no numeration enabled + if( nOldDepth == -1 ) + continue; + + if ( nNewDepth < Outliner::gnMinDepth ) + nNewDepth = Outliner::gnMinDepth; + if ( nNewDepth > pOwner->nMaxDepth ) + nNewDepth = pOwner->nMaxDepth; + + if( nOldDepth < nMinDepth ) + nMinDepth = nOldDepth; + if( nNewDepth < nMinDepth ) + nMinDepth = nNewDepth; + + if( nOldDepth != nNewDepth ) + { + if ( ( nPara == aSel.nStartPara ) && aSel.nStartPara && ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TextObject )) + { + // Special case: the predecessor of an indented paragraph is + // invisible and is now on the same level as the visible + // paragraph. In this case, the next visible paragraph is + // searched for and fluffed. +#ifdef DBG_UTIL + Paragraph* _pPara = pOwner->pParaList->GetParagraph( aSel.nStartPara ); + DBG_ASSERT(_pPara->IsVisible(),"Selected Paragraph invisible ?!"); +#endif + Paragraph* pPrev= pOwner->pParaList->GetParagraph( aSel.nStartPara-1 ); + + if( !pPrev->IsVisible() && ( pPrev->GetDepth() == nNewDepth ) ) + { + // Predecessor is collapsed and is on the same level + // => find next visible paragraph and expand it + pPrev = pOwner->pParaList->GetParent( pPrev ); + while( !pPrev->IsVisible() ) + pPrev = pOwner->pParaList->GetParent( pPrev ); + + pOwner->Expand( pPrev ); + pOwner->InvalidateBullet(pOwner->pParaList->GetAbsPos(pPrev)); + } + } + + pOwner->nDepthChangedHdlPrevDepth = nOldDepth; + ParaFlag nPrevFlags = pPara->nFlags; + + pOwner->ImplInitDepth( nPara, nNewDepth, true ); + pOwner->ImplCalcBulletText( nPara, false, false ); + + if ( pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + pOwner->ImplSetLevelDependentStyleSheet( nPara ); + + // Notify App + pOwner->DepthChangedHdl(pPara, nPrevFlags); + } + else + { + // Needs at least a repaint... + pOwner->pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); + } + } + + sal_Int32 nParas = pOwner->pParaList->GetParagraphCount(); + for ( sal_Int32 n = aSel.nEndPara+1; n < nParas; n++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( n ); + if ( pPara->GetDepth() < nMinDepth ) + break; + pOwner->ImplCalcBulletText( n, false, false ); + } + + if ( bUpdate ) + { + pEditView->SetEditEngineUpdateMode( true ); + pEditView->ShowCursor(); + } + + if( bUndo ) + pOwner->UndoActionEnd(); +} + +void OutlinerView::AdjustHeight( long nDY ) +{ + pEditView->MoveParagraphs( nDY ); +} + +tools::Rectangle const & OutlinerView::GetVisArea() const +{ + return pEditView->GetVisArea(); +} + +void OutlinerView::Expand() +{ + ParaRange aParas = ImpGetSelectedParagraphs( false ); + ImplExpandOrCollaps( aParas.nStartPara, aParas.nEndPara, true ); +} + + +void OutlinerView::Collapse() +{ + ParaRange aParas = ImpGetSelectedParagraphs( false ); + ImplExpandOrCollaps( aParas.nStartPara, aParas.nEndPara, false ); +} + + +void OutlinerView::ExpandAll() +{ + ImplExpandOrCollaps( 0, pOwner->pParaList->GetParagraphCount()-1, true ); +} + + +void OutlinerView::CollapseAll() +{ + ImplExpandOrCollaps( 0, pOwner->pParaList->GetParagraphCount()-1, false ); +} + +void OutlinerView::ImplExpandOrCollaps( sal_Int32 nStartPara, sal_Int32 nEndPara, bool bExpand ) +{ + bool bUpdate = pOwner->GetUpdateMode(); + pOwner->SetUpdateMode( false ); + + bool bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled(); + if( bUndo ) + pOwner->UndoActionStart( bExpand ? OLUNDO_EXPAND : OLUNDO_COLLAPSE ); + + for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + bool bDone = bExpand ? pOwner->Expand( pPara ) : pOwner->Collapse( pPara ); + if( bDone ) + { + // The line under the paragraph should disappear ... + pOwner->pEditEngine->QuickMarkToBeRepainted( nPara ); + } + } + + if( bUndo ) + pOwner->UndoActionEnd(); + + if ( bUpdate ) + { + pOwner->SetUpdateMode( true ); + pEditView->ShowCursor(); + } +} + +void OutlinerView::InsertText( const OutlinerParaObject& rParaObj ) +{ + // Like Paste, only EditView::Insert, instead of EditView::Paste. + // Actually not quite true that possible indentations must be corrected, + // but that comes later by a universal import. The indentation level is + // then determined right in the Inserted method. + // Possible structure: + // pImportInfo with DestPara, DestPos, nFormat, pParaObj... + // Possibly problematic: + // EditEngine, RTF => Splitting the area, later join together. + + if ( ImpCalcSelectedPages( false ) && !pOwner->ImpCanDeleteSelectedPages( this ) ) + return; + + pOwner->UndoActionStart( OLUNDO_INSERT ); + + pOwner->pEditEngine->SetUpdateMode( false ); + sal_Int32 nStart, nParaCount; + nParaCount = pOwner->pEditEngine->GetParagraphCount(); + sal_uInt16 nSize = ImpInitPaste( nStart ); + pEditView->InsertText( rParaObj.GetTextObject() ); + ImpPasted( nStart, nParaCount, nSize); + pEditView->SetEditEngineUpdateMode( true ); + + pOwner->UndoActionEnd(); + + pEditView->ShowCursor(); +} + + +void OutlinerView::Cut() +{ + if ( !ImpCalcSelectedPages( false ) || pOwner->ImpCanDeleteSelectedPages( this ) ) { + pEditView->Cut(); + // Chaining handling + aEndCutPasteLink.Call(nullptr); + } +} + +void OutlinerView::PasteSpecial() +{ + Paste( true ); +} + +void OutlinerView::Paste( bool bUseSpecial ) +{ + if ( !(!ImpCalcSelectedPages( false ) || pOwner->ImpCanDeleteSelectedPages( this )) ) + return; + + pOwner->UndoActionStart( OLUNDO_INSERT ); + + pOwner->pEditEngine->SetUpdateMode( false ); + pOwner->bPasting = true; + + if ( bUseSpecial ) + pEditView->PasteSpecial(); + else + pEditView->Paste(); + + if ( pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + { + const sal_Int32 nParaCount = pOwner->pEditEngine->GetParagraphCount(); + + for( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ ) + pOwner->ImplSetLevelDependentStyleSheet( nPara ); + } + + pEditView->SetEditEngineUpdateMode( true ); + pOwner->UndoActionEnd(); + pEditView->ShowCursor(); + + // Chaining handling + // NOTE: We need to do this last because it pEditView may be deleted if a switch of box occurs + aEndCutPasteLink.Call(nullptr); +} + +void OutlinerView::CreateSelectionList (std::vector<Paragraph*> &aSelList) +{ + ParaRange aParas = ImpGetSelectedParagraphs( true ); + + for ( sal_Int32 nPara = aParas.nStartPara; nPara <= aParas.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + aSelList.push_back(pPara); + } +} + +const SfxStyleSheet* OutlinerView::GetStyleSheet() const +{ + return pEditView->GetStyleSheet(); +} + +SfxStyleSheet* OutlinerView::GetStyleSheet() +{ + return pEditView->GetStyleSheet(); +} + +PointerStyle OutlinerView::GetPointer( const Point& rPosPixel ) +{ + MouseTarget eTarget; + ImpCheckMousePos( rPosPixel, eTarget ); + + PointerStyle ePointerStyle = PointerStyle::Arrow; + if ( eTarget == MouseTarget::Text ) + { + ePointerStyle = GetOutliner()->IsVertical() ? PointerStyle::TextVertical : PointerStyle::Text; + } + else if ( eTarget == MouseTarget::Hypertext ) + { + ePointerStyle = PointerStyle::RefHand; + } + else if ( eTarget == MouseTarget::Bullet ) + { + ePointerStyle = PointerStyle::Move; + } + + return ePointerStyle; +} + + +sal_Int32 OutlinerView::ImpInitPaste( sal_Int32& rStart ) +{ + pOwner->bPasting = true; + ESelection aSelection( pEditView->GetSelection() ); + aSelection.Adjust(); + rStart = aSelection.nStartPara; + sal_Int32 nSize = aSelection.nEndPara - aSelection.nStartPara + 1; + return nSize; +} + + +void OutlinerView::ImpPasted( sal_Int32 nStart, sal_Int32 nPrevParaCount, sal_Int32 nSize) +{ + pOwner->bPasting = false; + sal_Int32 nCurParaCount = pOwner->pEditEngine->GetParagraphCount(); + if( nCurParaCount < nPrevParaCount ) + nSize = nSize - ( nPrevParaCount - nCurParaCount ); + else + nSize = nSize + ( nCurParaCount - nPrevParaCount ); + pOwner->ImpTextPasted( nStart, nSize ); +} + + +void OutlinerView::Command( const CommandEvent& rCEvt ) +{ + pEditView->Command( rCEvt ); +} + + +void OutlinerView::SelectRange( sal_Int32 nFirst, sal_Int32 nCount ) +{ + sal_Int32 nLast = nFirst+nCount; + nCount = pOwner->pParaList->GetParagraphCount(); + if( nLast <= nCount ) + nLast = nCount - 1; + ESelection aSel( nFirst, 0, nLast, EE_TEXTPOS_ALL ); + pEditView->SetSelection( aSel ); +} + + +sal_Int32 OutlinerView::ImpCalcSelectedPages( bool bIncludeFirstSelected ) +{ + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + + sal_Int32 nPages = 0; + sal_Int32 nFirstPage = EE_PARA_MAX_COUNT; + sal_Int32 nStartPara = aSel.nStartPara; + if ( !bIncludeFirstSelected ) + nStartPara++; // All paragraphs after StartPara will be deleted + for ( sal_Int32 nPara = nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + DBG_ASSERT(pPara, "ImpCalcSelectedPages: invalid Selection? "); + if( pPara->HasFlag(ParaFlag::ISPAGE) ) + { + nPages++; + if( nFirstPage == EE_PARA_MAX_COUNT ) + nFirstPage = nPara; + } + } + + if( nPages ) + { + pOwner->nDepthChangedHdlPrevDepth = nPages; + pOwner->mnFirstSelPage = nFirstPage; + } + + return nPages; +} + + +void OutlinerView::ToggleBullets() +{ + pOwner->UndoActionStart( OLUNDO_DEPTH ); + + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + + const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); + pOwner->pEditEngine->SetUpdateMode( false ); + + sal_Int16 nNewDepth = -2; + const SvxNumRule* pDefaultBulletNumRule = nullptr; + + for ( sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + DBG_ASSERT(pPara, "OutlinerView::ToggleBullets(), illegal selection?"); + + if( pPara ) + { + if( nNewDepth == -2 ) + { + nNewDepth = (pOwner->GetDepth(nPara) == -1) ? 0 : -1; + if ( nNewDepth == 0 ) + { + // determine default numbering rule for bullets + const ESelection aSelection(nPara, 0); + const SfxItemSet aTmpSet(pOwner->pEditEngine->GetAttribs(aSelection)); + const SfxPoolItem& rPoolItem = aTmpSet.GetPool()->GetDefaultItem( EE_PARA_NUMBULLET ); + const SvxNumBulletItem* pNumBulletItem = dynamic_cast< const SvxNumBulletItem* >(&rPoolItem); + pDefaultBulletNumRule = pNumBulletItem ? pNumBulletItem->GetNumRule() : nullptr; + } + } + + pOwner->SetDepth( pPara, nNewDepth ); + + if( nNewDepth == -1 ) + { + const SfxItemSet& rAttrs = pOwner->GetParaAttribs( nPara ); + if ( rAttrs.GetItemState( EE_PARA_BULLETSTATE ) == SfxItemState::SET ) + { + SfxItemSet aAttrs(rAttrs); + aAttrs.ClearItem( EE_PARA_BULLETSTATE ); + pOwner->SetParaAttribs( nPara, aAttrs ); + } + } + else + { + if ( pDefaultBulletNumRule ) + { + const SvxNumberFormat* pFmt = pOwner ->GetNumberFormat( nPara ); + if ( !pFmt + || ( pFmt->GetNumberingType() != SVX_NUM_BITMAP + && pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) ) + { + SfxItemSet aAttrs( pOwner->GetParaAttribs( nPara ) ); + SvxNumRule aNewNumRule( *pDefaultBulletNumRule ); + aAttrs.Put( SvxNumBulletItem( aNewNumRule, EE_PARA_NUMBULLET ) ); + pOwner->SetParaAttribs( nPara, aAttrs ); + } + } + } + } + } + + const sal_Int32 nParaCount = pOwner->pParaList->GetParagraphCount(); + pOwner->ImplCheckParagraphs( aSel.nStartPara, nParaCount ); + + sal_Int32 nEndPara = (nParaCount > 0) ? nParaCount-1 : nParaCount; + pOwner->pEditEngine->QuickMarkInvalid( ESelection( aSel.nStartPara, 0, nEndPara, 0 ) ); + + pOwner->pEditEngine->SetUpdateMode( bUpdate ); + + pOwner->UndoActionEnd(); +} + + +void OutlinerView::ToggleBulletsNumbering( + const bool bToggle, + const bool bHandleBullets, + const SvxNumRule* pNumRule ) +{ + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + + bool bToggleOn = true; + if ( bToggle ) + { + bToggleOn = false; + const sal_Int16 nBulletNumberingStatus( pOwner->GetBulletsNumberingStatus( aSel.nStartPara, aSel.nEndPara ) ); + if ( nBulletNumberingStatus != 0 && bHandleBullets ) + { + // not all paragraphs have bullets and method called to toggle bullets --> bullets on + bToggleOn = true; + } + else if ( nBulletNumberingStatus != 1 && !bHandleBullets ) + { + // not all paragraphs have numbering and method called to toggle numberings --> numberings on + bToggleOn = true; + } + } + if ( bToggleOn ) + { + // apply bullets/numbering for selected paragraphs + ApplyBulletsNumbering( bHandleBullets, pNumRule, bToggle, true ); + } + else + { + // switch off bullets/numbering for selected paragraphs + SwitchOffBulletsNumbering( true ); + } +} + + +void OutlinerView::ApplyBulletsNumbering( + const bool bHandleBullets, + const SvxNumRule* pNewNumRule, + const bool bCheckCurrentNumRuleBeforeApplyingNewNumRule, + const bool bAtSelection ) +{ + if (!pOwner || !pOwner->pEditEngine || !pOwner->pParaList) + { + return; + } + + pOwner->UndoActionStart(OLUNDO_DEPTH); + const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); + pOwner->pEditEngine->SetUpdateMode(false); + + sal_Int32 nStartPara = 0; + sal_Int32 nEndPara = 0; + if ( bAtSelection ) + { + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + nStartPara = aSel.nStartPara; + nEndPara = aSel.nEndPara; + } + else + { + nStartPara = 0; + nEndPara = pOwner->pParaList->GetParagraphCount() - 1; + } + + for (sal_Int32 nPara = nStartPara; nPara <= nEndPara; ++nPara) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph(nPara); + DBG_ASSERT(pPara, "OutlinerView::ApplyBulletsNumbering(..), illegal selection?"); + + if (pPara) + { + const sal_Int16 nDepth = pOwner->GetDepth(nPara); + if ( nDepth == -1 ) + { + pOwner->SetDepth( pPara, 0 ); + } + + const SfxItemSet& rAttrs = pOwner->GetParaAttribs(nPara); + SfxItemSet aAttrs(rAttrs); + aAttrs.Put(SfxBoolItem(EE_PARA_BULLETSTATE, true)); + + // apply new numbering rule + if ( pNewNumRule ) + { + bool bApplyNumRule = false; + if ( !bCheckCurrentNumRuleBeforeApplyingNewNumRule ) + { + bApplyNumRule = true; + } + else + { + const SvxNumberFormat* pFmt = pOwner ->GetNumberFormat(nPara); + if (!pFmt) + { + bApplyNumRule = true; + } + else + { + sal_Int16 nNumType = pFmt->GetNumberingType(); + if ( bHandleBullets + && nNumType != SVX_NUM_BITMAP && nNumType != SVX_NUM_CHAR_SPECIAL) + { + // Set to Normal bullet, old bullet type is Numbering bullet. + bApplyNumRule = true; + } + else if ( !bHandleBullets + && (nNumType == SVX_NUM_BITMAP || nNumType == SVX_NUM_CHAR_SPECIAL)) + { + // Set to Numbering bullet, old bullet type is Normal bullet. + bApplyNumRule = true; + } + } + } + + if ( bApplyNumRule ) + { + SvxNumRule aNewRule(*pNewNumRule); + + // Get old bullet space. + { + const SfxPoolItem* pPoolItem=nullptr; + SfxItemState eState = rAttrs.GetItemState(EE_PARA_NUMBULLET, false, &pPoolItem); + if (eState != SfxItemState::SET) + { + // Use default value when has not contain bullet item. + ESelection aSelection(nPara, 0); + SfxItemSet aTmpSet(pOwner->pEditEngine->GetAttribs(aSelection)); + pPoolItem = aTmpSet.GetItem(EE_PARA_NUMBULLET); + } + + const SvxNumBulletItem* pNumBulletItem = dynamic_cast< const SvxNumBulletItem* >(pPoolItem); + if (pNumBulletItem) + { + const sal_uInt16 nLevelCnt = std::min(pNumBulletItem->GetNumRule()->GetLevelCount(), aNewRule.GetLevelCount()); + for ( sal_uInt16 nLevel = 0; nLevel < nLevelCnt; ++nLevel ) + { + const SvxNumberFormat* pOldFmt = pNumBulletItem->GetNumRule()->Get(nLevel); + const SvxNumberFormat* pNewFmt = aNewRule.Get(nLevel); + if (pOldFmt && pNewFmt && (pOldFmt->GetFirstLineOffset() != pNewFmt->GetFirstLineOffset() || pOldFmt->GetAbsLSpace() != pNewFmt->GetAbsLSpace())) + { + std::unique_ptr<SvxNumberFormat> pNewFmtClone(new SvxNumberFormat(*pNewFmt)); + pNewFmtClone->SetFirstLineOffset(pOldFmt->GetFirstLineOffset()); + pNewFmtClone->SetAbsLSpace(pOldFmt->GetAbsLSpace()); + aNewRule.SetLevel(nLevel, pNewFmtClone.get()); + } + } + } + } + + aAttrs.Put(SvxNumBulletItem(aNewRule, EE_PARA_NUMBULLET)); + } + } + pOwner->SetParaAttribs(nPara, aAttrs); + } + } + + const sal_uInt16 nParaCount = static_cast<sal_uInt16>(pOwner->pParaList->GetParagraphCount()); + pOwner->ImplCheckParagraphs( nStartPara, nParaCount ); + pOwner->pEditEngine->QuickMarkInvalid( ESelection( nStartPara, 0, nParaCount, 0 ) ); + + pOwner->pEditEngine->SetUpdateMode( bUpdate ); + + pOwner->UndoActionEnd(); +} + + +void OutlinerView::SwitchOffBulletsNumbering( + const bool bAtSelection ) +{ + sal_Int32 nStartPara = 0; + sal_Int32 nEndPara = 0; + if ( bAtSelection ) + { + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + nStartPara = aSel.nStartPara; + nEndPara = aSel.nEndPara; + } + else + { + nStartPara = 0; + nEndPara = pOwner->pParaList->GetParagraphCount() - 1; + } + + pOwner->UndoActionStart( OLUNDO_DEPTH ); + const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); + pOwner->pEditEngine->SetUpdateMode( false ); + + for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; ++nPara ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + DBG_ASSERT(pPara, "OutlinerView::SwitchOffBulletsNumbering(...), illegal paragraph index?"); + + if( pPara ) + { + pOwner->SetDepth( pPara, -1 ); + + const SfxItemSet& rAttrs = pOwner->GetParaAttribs( nPara ); + if (rAttrs.GetItemState( EE_PARA_BULLETSTATE ) == SfxItemState::SET) + { + SfxItemSet aAttrs(rAttrs); + aAttrs.ClearItem( EE_PARA_BULLETSTATE ); + pOwner->SetParaAttribs( nPara, aAttrs ); + } + } + } + + const sal_uInt16 nParaCount = static_cast<sal_uInt16>(pOwner->pParaList->GetParagraphCount()); + pOwner->ImplCheckParagraphs( nStartPara, nParaCount ); + pOwner->pEditEngine->QuickMarkInvalid( ESelection( nStartPara, 0, nParaCount, 0 ) ); + + pOwner->pEditEngine->SetUpdateMode( bUpdate ); + pOwner->UndoActionEnd(); +} + + +void OutlinerView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs ) +{ + RemoveAttribs( bRemoveParaAttribs, true /*keep language attribs*/ ); +} + +void OutlinerView::RemoveAttribs( bool bRemoveParaAttribs, bool bKeepLanguages ) +{ + bool bUpdate = pOwner->GetUpdateMode(); + pOwner->SetUpdateMode( false ); + pOwner->UndoActionStart( OLUNDO_ATTR ); + if (bKeepLanguages) + pEditView->RemoveAttribsKeepLanguages( bRemoveParaAttribs ); + else + pEditView->RemoveAttribs( bRemoveParaAttribs ); + if ( bRemoveParaAttribs ) + { + // Loop through all paragraphs and set indentation and level + ESelection aSel = pEditView->GetSelection(); + aSel.Adjust(); + for ( sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + pOwner->ImplInitDepth( nPara, pPara->GetDepth(), false ); + } + } + pOwner->UndoActionEnd(); + pOwner->SetUpdateMode( bUpdate ); +} + + +// ====================== Simple pass-through ======================= + + +void OutlinerView::InsertText( const OUString& rNew, bool bSelect ) +{ + if( pOwner->bFirstParaIsEmpty ) + pOwner->Insert( OUString() ); + pEditView->InsertText( rNew, bSelect ); +} + +void OutlinerView::SetVisArea( const tools::Rectangle& rRect ) +{ + pEditView->SetVisArea( rRect ); +} + + +void OutlinerView::SetSelection( const ESelection& rSel ) +{ + pEditView->SetSelection( rSel ); +} + +void OutlinerView::GetSelectionRectangles(std::vector<tools::Rectangle>& rLogicRects) const +{ + pEditView->GetSelectionRectangles(rLogicRects); +} + +void OutlinerView::SetReadOnly( bool bReadOnly ) +{ + pEditView->SetReadOnly( bReadOnly ); +} + +bool OutlinerView::IsReadOnly() const +{ + return pEditView->IsReadOnly(); +} + +bool OutlinerView::HasSelection() const +{ + return pEditView->HasSelection(); +} + +void OutlinerView::ShowCursor( bool bGotoCursor, bool bActivate ) +{ + pEditView->ShowCursor( bGotoCursor, /*bForceVisCursor=*/true, bActivate ); +} + +void OutlinerView::HideCursor(bool bDeactivate) +{ + pEditView->HideCursor(bDeactivate); +} + +void OutlinerView::SetWindow( vcl::Window* pWin ) +{ + pEditView->SetWindow( pWin ); +} + +vcl::Window* OutlinerView::GetWindow() const +{ + return pEditView->GetWindow(); +} + +void OutlinerView::SetOutputArea( const tools::Rectangle& rRect ) +{ + pEditView->SetOutputArea( rRect ); +} + +tools::Rectangle const & OutlinerView::GetOutputArea() const +{ + return pEditView->GetOutputArea(); +} + +OUString OutlinerView::GetSelected() const +{ + return pEditView->GetSelected(); +} + +void OutlinerView::StartSpeller() +{ + pEditView->StartSpeller(); +} + +EESpellState OutlinerView::StartThesaurus() +{ + return pEditView->StartThesaurus(); +} + +void OutlinerView::StartTextConversion( + LanguageType nSrcLang, LanguageType nDestLang, const vcl::Font *pDestFont, + sal_Int32 nOptions, bool bIsInteractive, bool bMultipleDoc ) +{ + if ( + (LANGUAGE_KOREAN == nSrcLang && LANGUAGE_KOREAN == nDestLang) || + (LANGUAGE_CHINESE_SIMPLIFIED == nSrcLang && LANGUAGE_CHINESE_TRADITIONAL == nDestLang) || + (LANGUAGE_CHINESE_TRADITIONAL == nSrcLang && LANGUAGE_CHINESE_SIMPLIFIED == nDestLang) + ) + { + pEditView->StartTextConversion( nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc ); + } + else + { + OSL_FAIL( "unexpected language" ); + } +} + + +sal_Int32 OutlinerView::StartSearchAndReplace( const SvxSearchItem& rSearchItem ) +{ + return pEditView->StartSearchAndReplace( rSearchItem ); +} + +void OutlinerView::TransliterateText( TransliterationFlags nTransliterationMode ) +{ + pEditView->TransliterateText( nTransliterationMode ); +} + +ESelection OutlinerView::GetSelection() const +{ + return pEditView->GetSelection(); +} + + +void OutlinerView::Scroll( long nHorzScroll, long nVertScroll ) +{ + pEditView->Scroll( nHorzScroll, nVertScroll ); +} + +void OutlinerView::SetControlWord( EVControlBits nWord ) +{ + pEditView->SetControlWord( nWord ); +} + +EVControlBits OutlinerView::GetControlWord() const +{ + return pEditView->GetControlWord(); +} + +void OutlinerView::SetAnchorMode( EEAnchorMode eMode ) +{ + pEditView->SetAnchorMode( eMode ); +} + +EEAnchorMode OutlinerView::GetAnchorMode() const +{ + return pEditView->GetAnchorMode(); +} + +void OutlinerView::Copy() +{ + pEditView->Copy(); +} + +void OutlinerView::InsertField( const SvxFieldItem& rFld ) +{ + pEditView->InsertField( rFld ); +} + +const SvxFieldItem* OutlinerView::GetFieldUnderMousePointer() const +{ + return pEditView->GetFieldUnderMousePointer(); +} + +const SvxFieldItem* OutlinerView::GetFieldAtSelection() const +{ + return pEditView->GetFieldAtSelection(); +} + +const SvxFieldData* OutlinerView::GetFieldAtCursor() const +{ + return pEditView->GetFieldAtCursor(); +} + +void OutlinerView::SelectFieldAtCursor() +{ + pEditView->SelectFieldAtCursor(); +} + +void OutlinerView::SetInvalidateMore( sal_uInt16 nPixel ) +{ + pEditView->SetInvalidateMore( nPixel ); +} + + +sal_uInt16 OutlinerView::GetInvalidateMore() const +{ + return pEditView->GetInvalidateMore(); +} + + +bool OutlinerView::IsCursorAtWrongSpelledWord() +{ + return pEditView->IsCursorAtWrongSpelledWord(); +} + + +bool OutlinerView::IsWrongSpelledWordAtPos( const Point& rPosPixel, bool bMarkIfWrong ) +{ + return pEditView->IsWrongSpelledWordAtPos( rPosPixel, bMarkIfWrong ); +} + +void OutlinerView::ExecuteSpellPopup( const Point& rPosPixel, Link<SpellCallbackInfo&,void> const * pStartDlg ) +{ + pEditView->ExecuteSpellPopup( rPosPixel, pStartDlg ); +} + +void OutlinerView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs ) +{ + sal_Int32 nOldParaCount = pEditView->GetEditEngine()->GetParagraphCount(); + ESelection aOldSel = pEditView->GetSelection(); + aOldSel.Adjust(); + + pEditView->Read( rInput, eFormat, pHTTPHeaderAttrs ); + + long nParaDiff = pEditView->GetEditEngine()->GetParagraphCount() - nOldParaCount; + sal_Int32 nChangesStart = aOldSel.nStartPara; + sal_Int32 nChangesEnd = nChangesStart + nParaDiff + (aOldSel.nEndPara-aOldSel.nStartPara); + + for ( sal_Int32 n = nChangesStart; n <= nChangesEnd; n++ ) + { + if ( pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + pOwner->ImplSetLevelDependentStyleSheet( n ); + } + + pOwner->ImpFilterIndents( nChangesStart, nChangesEnd ); +} + +void OutlinerView::SetBackgroundColor( const Color& rColor ) +{ + pEditView->SetBackgroundColor( rColor ); +} + +void OutlinerView::RegisterViewShell(OutlinerViewShell* pViewShell) +{ + pEditView->RegisterViewShell(pViewShell); +} + +Color const & OutlinerView::GetBackgroundColor() const +{ + return pEditView->GetBackgroundColor(); +} + +SfxItemSet OutlinerView::GetAttribs() +{ + return pEditView->GetAttribs(); +} + +SvtScriptType OutlinerView::GetSelectedScriptType() const +{ + return pEditView->GetSelectedScriptType(); +} + +OUString OutlinerView::GetSurroundingText() const +{ + return pEditView->GetSurroundingText(); +} + +Selection OutlinerView::GetSurroundingTextSelection() const +{ + return pEditView->GetSurroundingTextSelection(); +} + +// ===== some code for thesaurus sub menu within context menu + + +namespace { + +bool isSingleScriptType( SvtScriptType nScriptType ) +{ + sal_uInt8 nScriptCount = 0; + + if (nScriptType & SvtScriptType::LATIN) + ++nScriptCount; + if (nScriptType & SvtScriptType::ASIAN) + ++nScriptCount; + if (nScriptType & SvtScriptType::COMPLEX) + ++nScriptCount; + + return nScriptCount == 1; +} + +} + +// returns: true if a word for thesaurus look-up was found at the current cursor position. +// The status string will be word + iso language string (e.g. "light#en-US") +bool GetStatusValueForThesaurusFromContext( + OUString &rStatusVal, + LanguageType &rLang, + const EditView &rEditView ) +{ + // get text and locale for thesaurus look up + OUString aText; + EditEngine *pEditEngine = rEditView.GetEditEngine(); + ESelection aTextSel( rEditView.GetSelection() ); + if (!aTextSel.HasRange()) + aTextSel = pEditEngine->GetWord( aTextSel, i18n::WordType::DICTIONARY_WORD ); + aText = pEditEngine->GetText( aTextSel ); + aTextSel.Adjust(); + + if (!isSingleScriptType(pEditEngine->GetScriptType(aTextSel))) + return false; + + LanguageType nLang = pEditEngine->GetLanguage( aTextSel.nStartPara, aTextSel.nStartPos ); + OUString aLangText( LanguageTag::convertToBcp47( nLang ) ); + + // set word and locale to look up as status value + rStatusVal = aText + "#" + aLangText; + rLang = nLang; + + return aText.getLength() > 0; +} + + +void ReplaceTextWithSynonym( EditView &rEditView, const OUString &rSynonmText ) +{ + // get selection to use + ESelection aCurSel( rEditView.GetSelection() ); + if (!rEditView.HasSelection()) + { + // select the same word that was used in GetStatusValueForThesaurusFromContext by calling GetWord. + // (In the end both functions will call ImpEditEngine::SelectWord) + rEditView.SelectCurrentWord( i18n::WordType::DICTIONARY_WORD ); + aCurSel = rEditView.GetSelection(); + } + + // replace word ... + rEditView.InsertText( rSynonmText ); + rEditView.ShowCursor( true, false ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |