diff options
Diffstat (limited to 'editeng/source/outliner')
-rw-r--r-- | editeng/source/outliner/makefile.mk | 60 | ||||
-rw-r--r-- | editeng/source/outliner/outl_pch.cxx | 31 | ||||
-rw-r--r-- | editeng/source/outliner/outl_pch.hxx | 33 | ||||
-rw-r--r-- | editeng/source/outliner/outleeng.cxx | 244 | ||||
-rw-r--r-- | editeng/source/outliner/outleeng.hxx | 93 | ||||
-rw-r--r-- | editeng/source/outliner/outlin2.cxx | 813 | ||||
-rw-r--r-- | editeng/source/outliner/outliner.cxx | 2181 | ||||
-rw-r--r-- | editeng/source/outliner/outliner.src | 84 | ||||
-rw-r--r-- | editeng/source/outliner/outlobj.cxx | 271 | ||||
-rw-r--r-- | editeng/source/outliner/outlundo.cxx | 234 | ||||
-rw-r--r-- | editeng/source/outliner/outlundo.hxx | 140 | ||||
-rwxr-xr-x | editeng/source/outliner/outlvw.cxx | 1734 | ||||
-rw-r--r-- | editeng/source/outliner/paralist.cxx | 287 | ||||
-rw-r--r-- | editeng/source/outliner/paralist.hxx | 71 |
14 files changed, 6276 insertions, 0 deletions
diff --git a/editeng/source/outliner/makefile.mk b/editeng/source/outliner/makefile.mk new file mode 100644 index 000000000000..df1c795801ae --- /dev/null +++ b/editeng/source/outliner/makefile.mk @@ -0,0 +1,60 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=editeng +TARGET=outliner +AUTOSEG=true +ENABLE_EXCEPTIONS=TRUE + +PROJECTPCH4DLL=TRUE +PROJECTPCH=outl_pch +PROJECTPCHSOURCE=outl_pch + + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Allgemein ---------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/outlundo.obj \ + $(SLO)$/outliner.obj \ + $(SLO)$/outlin2.obj \ + $(SLO)$/paralist.obj \ + $(SLO)$/outlvw.obj \ + $(SLO)$/outleeng.obj \ + $(SLO)$/outlobj.obj + +SRS1NAME=$(TARGET) +SRC1FILES= outliner.src + +.INCLUDE : target.mk + diff --git a/editeng/source/outliner/outl_pch.cxx b/editeng/source/outliner/outl_pch.cxx new file mode 100644 index 000000000000..802af3aa3df4 --- /dev/null +++ b/editeng/source/outliner/outl_pch.cxx @@ -0,0 +1,31 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" +#include <outl_pch.hxx> + diff --git a/editeng/source/outliner/outl_pch.hxx b/editeng/source/outliner/outl_pch.hxx new file mode 100644 index 000000000000..9da7cc120110 --- /dev/null +++ b/editeng/source/outliner/outl_pch.hxx @@ -0,0 +1,33 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <svl/intitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fhgtitem.hxx> diff --git a/editeng/source/outliner/outleeng.cxx b/editeng/source/outliner/outleeng.cxx new file mode 100644 index 000000000000..de0a555f004c --- /dev/null +++ b/editeng/source/outliner/outleeng.cxx @@ -0,0 +1,244 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" +#include <svl/intitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fhgtitem.hxx> + +#define _OUTLINER_CXX +#include <editeng/outliner.hxx> +#include <outleeng.hxx> +#include <paralist.hxx> +#include <editeng/editrids.hrc> +#include <svl/itemset.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editstat.hxx> +#include "outlundo.hxx" + +OutlinerEditEng::OutlinerEditEng( Outliner* pEngOwner, SfxItemPool* pPool ) + : EditEngine( pPool ) +{ + pOwner = pEngOwner; +} + +OutlinerEditEng::~OutlinerEditEng() +{ +} + +void OutlinerEditEng::PaintingFirstLine( USHORT nPara, const Point& rStartPos, long nBaseLineY, const Point& rOrigin, short nOrientation, OutputDevice* pOutDev ) +{ + if( GetControlWord() && EE_CNTRL_OUTLINER ) + { + PaintFirstLineInfo aInfo( nPara, rStartPos, nBaseLineY, rOrigin, nOrientation, pOutDev ); + pOwner->maPaintFirstLineHdl.Call( &aInfo ); + } + + pOwner->PaintBullet( nPara, rStartPos, rOrigin, nOrientation, pOutDev ); +} + +const SvxNumberFormat* OutlinerEditEng::GetNumberFormat( USHORT nPara ) const +{ + const SvxNumberFormat* pFmt = NULL; + if (pOwner) + pFmt = pOwner->GetNumberFormat( nPara ); + return pFmt; +} + + +Rectangle OutlinerEditEng::GetBulletArea( USHORT nPara ) +{ + Rectangle aBulletArea = Rectangle( Point(), Point() ); + if ( nPara < pOwner->pParaList->GetParagraphCount() ) + { + if ( pOwner->ImplHasBullet( nPara ) ) + aBulletArea = pOwner->ImpCalcBulletArea( nPara, FALSE, FALSE ); + } + return aBulletArea; +} + +void OutlinerEditEng::ParagraphInserted( USHORT nNewParagraph ) +{ + pOwner->ParagraphInserted( nNewParagraph ); + + EditEngine::ParagraphInserted( nNewParagraph ); +} + +void OutlinerEditEng::ParagraphDeleted( USHORT nDeletedParagraph ) +{ + pOwner->ParagraphDeleted( nDeletedParagraph ); + + EditEngine::ParagraphDeleted( nDeletedParagraph ); +} + +void OutlinerEditEng::ParagraphConnected( USHORT /*nLeftParagraph*/, USHORT nRightParagraph ) +{ + if( pOwner && pOwner->IsUndoEnabled() && !const_cast<EditEngine&>(pOwner->GetEditEngine()).IsInUndo() ) + { + Paragraph* pPara = pOwner->GetParagraph( nRightParagraph ); + if( pPara && pOwner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) ) + { + pOwner->InsertUndo( new OutlinerUndoChangeParaFlags( pOwner, nRightParagraph, PARAFLAG_ISPAGE, 0 ) ); + } + } +} + + +void OutlinerEditEng::StyleSheetChanged( SfxStyleSheet* pStyle ) +{ + pOwner->StyleSheetChanged( pStyle ); +} + +void OutlinerEditEng::ParaAttribsChanged( USHORT nPara ) +{ + pOwner->ParaAttribsChanged( nPara ); +} + +BOOL OutlinerEditEng::SpellNextDocument() +{ + return pOwner->SpellNextDocument(); +} + +BOOL OutlinerEditEng::ConvertNextDocument() +{ + return pOwner->ConvertNextDocument(); +} + +XubString OutlinerEditEng::GetUndoComment( USHORT nUndoId ) const +{ + switch( nUndoId ) + { + case OLUNDO_DEPTH: + return XubString( EditResId( RID_OUTLUNDO_DEPTH )); + + case OLUNDO_EXPAND: + return XubString( EditResId( RID_OUTLUNDO_EXPAND )); + + case OLUNDO_COLLAPSE: + return XubString( EditResId( RID_OUTLUNDO_COLLAPSE )); + + case OLUNDO_ATTR: + return XubString( EditResId( RID_OUTLUNDO_ATTR )); + + case OLUNDO_INSERT: + return XubString( EditResId( RID_OUTLUNDO_INSERT )); + + default: + return EditEngine::GetUndoComment( nUndoId ); + } +} + +// #101498# +void OutlinerEditEng::DrawingText( const Point& rStartPos, const XubString& rText, USHORT nTextStart, USHORT nTextLen, + const sal_Int32* pDXArray, const SvxFont& rFont, USHORT nPara, USHORT nIndex, BYTE nRightToLeft, + const EEngineData::WrongSpellVector* pWrongSpellVector, + const SvxFieldData* pFieldData, + bool bEndOfLine, + bool bEndOfParagraph, + bool bEndOfBullet, + const ::com::sun::star::lang::Locale* pLocale, + const Color& rOverlineColor, + const Color& rTextLineColor) +{ + // why do bullet here at all? Just use GetEditEnginePtr()->PaintingFirstLine + // inside of ImpEditEngine::Paint which calls pOwner->PaintBullet with the correct + // values for hor and ver. No change for not-layouting (painting). + // changed, bullet rendering now using PaintBullet via +/* if ( nIndex == 0 ) + { + // Dann das Bullet 'malen', dort wird bStrippingPortions ausgewertet + // und Outliner::DrawingText gerufen + + // DrawingText liefert die BaseLine, DrawBullet braucht Top(). + + if(true) + { + // ## + // another error: This call happens when only stripping, but the position + // is already aligned to text output. For bullet rendering, it needs to be reset + // to the correct value in x and y. PaintBullet takes care of X-start offset itself + const Point aDocPosTopLeft(GetDocPosTopLeft( nPara )); + const Point aCorrectedPos(rStartPos.X() - aDocPosTopLeft.X(), aDocPosTopLeft.Y() + GetFirstLineOffset( nPara )); + pOwner->PaintBullet( nPara, aCorrectedPos, Point(), 0, GetRefDevice() ); + } + else + { + Point aCorrectedPos( rStartPos ); + aCorrectedPos.Y() = GetDocPosTopLeft( nPara ).Y(); + aCorrectedPos.Y() += GetFirstLineOffset( nPara ); + pOwner->PaintBullet( nPara, aCorrectedPos, Point(), 0, GetRefDevice() ); + } + } */ + + // #101498# + pOwner->DrawingText(rStartPos,rText,nTextStart,nTextLen,pDXArray,rFont,nPara,nIndex,nRightToLeft, + pWrongSpellVector, pFieldData, bEndOfLine, bEndOfParagraph, bEndOfBullet, pLocale, rOverlineColor, rTextLineColor); +} + +void OutlinerEditEng::FieldClicked( const SvxFieldItem& rField, USHORT nPara, USHORT nPos ) +{ + EditEngine::FieldClicked( rField, nPara, nPos ); // Falls URL + pOwner->FieldClicked( rField, nPara, nPos ); +} + +void OutlinerEditEng::FieldSelected( const SvxFieldItem& rField, USHORT nPara, USHORT nPos ) +{ + pOwner->FieldSelected( rField, nPara, nPos ); +} + +XubString OutlinerEditEng::CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rpTxtColor, Color*& rpFldColor ) +{ + return pOwner->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor ); +} + +void OutlinerEditEng::SetParaAttribs( USHORT nPara, const SfxItemSet& rSet ) +{ + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + if( pPara ) + { + if ( !IsInUndo() && IsUndoEnabled() ) + pOwner->UndoActionStart( OLUNDO_ATTR ); + + EditEngine::SetParaAttribs( (USHORT)nPara, rSet ); + + pOwner->ImplCheckNumBulletItem( (USHORT)nPara ); + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + pOwner->ImplCheckParagraphs( (USHORT)nPara, (USHORT) (pOwner->pParaList->GetParagraphCount()) ); + // <-- + + if ( !IsInUndo() && IsUndoEnabled() ) + pOwner->UndoActionEnd( OLUNDO_ATTR ); + } +} + diff --git a/editeng/source/outliner/outleeng.hxx b/editeng/source/outliner/outleeng.hxx new file mode 100644 index 000000000000..fadbd8779eea --- /dev/null +++ b/editeng/source/outliner/outleeng.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _OUTLEENG_HXX +#define _OUTLEENG_HXX + +#include <editeng/outliner.hxx> +#ifndef _EDITENG_HXX +#include <editeng/editeng.hxx> +#endif + +typedef EENotify* EENotifyPtr; +SV_DECL_PTRARR_DEL( NotifyList, EENotifyPtr, 1, 1 ) + +class OutlinerEditEng : public EditEngine +{ + Outliner* pOwner; + +protected: + + // derived from EditEngine. Allows Outliner objetcs to provide + // bullet access to the EditEngine. + virtual const SvxNumberFormat* GetNumberFormat( USHORT nPara ) const; + +public: + OutlinerEditEng( Outliner* pOwner, SfxItemPool* pPool ); + ~OutlinerEditEng(); + + virtual void PaintingFirstLine( USHORT nPara, const Point& rStartPos, long nBaseLineY, const Point& rOrigin, short nOrientation, OutputDevice* pOutDev ); + + virtual void ParagraphInserted( USHORT nNewParagraph ); + virtual void ParagraphDeleted( USHORT nDeletedParagraph ); + virtual void ParagraphConnected( USHORT nLeftParagraph, USHORT nRightParagraph ); + + // #101498# + virtual void DrawingText( + const Point& rStartPos, const XubString& rText, USHORT nTextStart, USHORT nTextLen, const sal_Int32* pDXArray, const SvxFont& rFont, + USHORT nPara, USHORT nIndex, BYTE nRightToLeft, + const EEngineData::WrongSpellVector* pWrongSpellVector, + const SvxFieldData* pFieldData, + bool bEndOfLine, + bool bEndOfParagraph, + bool bEndOfBullet, + const ::com::sun::star::lang::Locale* pLocale, + const Color& rOverlineColor, + const Color& rTextLineColor); + + virtual void StyleSheetChanged( SfxStyleSheet* pStyle ); + virtual void ParaAttribsChanged( USHORT nPara ); + virtual BOOL SpellNextDocument(); + virtual XubString GetUndoComment( USHORT nUndoId ) const; + + // for text conversion + virtual BOOL ConvertNextDocument(); + + virtual void FieldClicked( const SvxFieldItem& rField, USHORT nPara, USHORT nPos ); + virtual void FieldSelected( const SvxFieldItem& rField, USHORT nPara, USHORT nPos ); + virtual XubString CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor ); + + virtual Rectangle GetBulletArea( USHORT nPara ); + + virtual void SetParaAttribs( USHORT nPara, const SfxItemSet& rSet ); + + // belongs into class Outliner, move there before incompatible update! + Link aOutlinerNotifyHdl; + NotifyList aNotifyCache; +}; + +#endif + diff --git a/editeng/source/outliner/outlin2.cxx b/editeng/source/outliner/outlin2.cxx new file mode 100644 index 000000000000..81db53b3d474 --- /dev/null +++ b/editeng/source/outliner/outlin2.cxx @@ -0,0 +1,813 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <svl/intitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <tools/list.hxx> +#include <svl/style.hxx> +#include <vcl/mapmod.hxx> + +#include <editeng/forbiddencharacterstable.hxx> + +#define _OUTLINER_CXX + +#include <editeng/outliner.hxx> +#include <paralist.hxx> +#include <editeng/outlobj.hxx> +#include <outleeng.hxx> +#include <outlundo.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editstat.hxx> + +DBG_NAMEEX(Outliner) + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::linguistic2; + +// ===================================================================== +// ====================== Einfache Durchreicher ======================= +// ====================================================================== + +void Outliner::SetUpdateMode( BOOL bUpdate ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetUpdateMode( bUpdate ); +} + + +BOOL Outliner::GetUpdateMode() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetUpdateMode(); +} + +const SfxItemSet& Outliner::GetEmptyItemSet() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetEmptyItemSet(); +} + +void Outliner::EnableUndo( BOOL bEnable ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->EnableUndo( bEnable ); +} + +BOOL Outliner::IsUndoEnabled() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsUndoEnabled(); +} + +MapMode Outliner::GetRefMapMode() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetRefMapMode(); +} + +void Outliner::SetRefMapMode( const MapMode& rMMode ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetRefMapMode( rMMode ); +} + +void Outliner::SetBackgroundColor( const Color& rColor ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetBackgroundColor( rColor ); +} + +Color Outliner::GetBackgroundColor() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetBackgroundColor(); +} + + +void Outliner::ClearModifyFlag() +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->ClearModifyFlag(); +} + +BOOL Outliner::IsModified() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsModified(); +} + +ULONG Outliner::GetTextHeight() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetTextHeight(); +} + +void Outliner::SetModifyHdl( const Link& rLink ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetModifyHdl( rLink ); +} + +Link Outliner::GetModifyHdl() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetModifyHdl(); +} + +void Outliner::SetNotifyHdl( const Link& rLink ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->aOutlinerNotifyHdl = rLink; + + if ( rLink.IsSet() ) + pEditEngine->SetNotifyHdl( LINK( this, Outliner, EditEngineNotifyHdl ) ); + else + pEditEngine->SetNotifyHdl( Link() ); + +} + +Link Outliner::GetNotifyHdl() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->aOutlinerNotifyHdl; +} + +void Outliner::SetStatusEventHdl( const Link& rLink ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetStatusEventHdl( rLink ); +} + +Link Outliner::GetStatusEventHdl() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetStatusEventHdl(); +} + +void Outliner::SetDefTab( USHORT nTab ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetDefTab( nTab ); +} + +USHORT Outliner::GetDefTab() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetDefTab(); +} + +BOOL Outliner::IsFlatMode() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsFlatMode(); +} + +BOOL Outliner::UpdateFields() +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->UpdateFields(); +} + +void Outliner::RemoveFields( BOOL bKeepFieldText, TypeId aType ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->RemoveFields( bKeepFieldText, aType ); +} + +void Outliner::SetWordDelimiters( const String& rDelimiters ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetWordDelimiters( rDelimiters ); +} + +String Outliner::GetWordDelimiters() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetWordDelimiters(); +} + +String Outliner::GetWord( USHORT nPara, USHORT nIndex ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetWord( nPara, nIndex ); +} + +void Outliner::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->Draw( pOutDev, rOutRect ); +} + +void Outliner::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect, const Point& rStartDocPos ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->Draw( pOutDev, rOutRect, rStartDocPos ); +} + + +void Outliner::Draw( OutputDevice* pOutDev, const Point& rStartPos, short nOrientation ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->Draw( pOutDev, rStartPos, nOrientation ); +} + +void Outliner::SetPaperSize( const Size& rSize ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetPaperSize( rSize ); +} + +const Size& Outliner::GetPaperSize() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetPaperSize(); +} + +void Outliner::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ) +{ + DBG_CHKTHIS( Outliner, 0 ); + pEditEngine->SetPolygon( rPolyPolygon ); +} + +void Outliner::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon) +{ + DBG_CHKTHIS( Outliner, 0 ); + pEditEngine->SetPolygon( rPolyPolygon, pLinePolyPolygon); +} + +void Outliner::ClearPolygon() +{ + DBG_CHKTHIS( Outliner, 0 ); + pEditEngine->ClearPolygon(); +} + +const PolyPolygon* Outliner::GetPolygon() +{ + DBG_CHKTHIS( Outliner, 0 ); + return pEditEngine->GetPolygon(); +} + +const Size& Outliner::GetMinAutoPaperSize() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetMinAutoPaperSize(); +} + +void Outliner::SetMinAutoPaperSize( const Size& rSz ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetMinAutoPaperSize( rSz ); +} + +const Size& Outliner::GetMaxAutoPaperSize() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetMaxAutoPaperSize(); +} + +void Outliner::SetMaxAutoPaperSize( const Size& rSz ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetMaxAutoPaperSize( rSz ); +} + +BOOL Outliner::IsExpanded( Paragraph* pPara ) const +{ + DBG_CHKTHIS(Outliner,0); + return pParaList->HasVisibleChilds( pPara ); +} + +Paragraph* Outliner::GetParent( Paragraph* pParagraph ) const +{ + DBG_CHKTHIS(Outliner,0); + return pParaList->GetParent( pParagraph ); +} + +ULONG Outliner::GetChildCount( Paragraph* pParent ) const +{ + DBG_CHKTHIS(Outliner,0); + return pParaList->GetChildCount( pParent ); +} + +Size Outliner::CalcTextSize() +{ + DBG_CHKTHIS(Outliner,0); + return Size(pEditEngine->CalcTextWidth(),pEditEngine->GetTextHeight()); +} + +Point Outliner::GetDocPos( Paragraph* pPara ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetDocPosTopLeft( (USHORT)pParaList->GetAbsPos( pPara ) ); +} + +void Outliner::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetStyleSheetPool( pSPool ); +} + +SfxStyleSheetPool* Outliner::GetStyleSheetPool() +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetStyleSheetPool(); +} + +SfxStyleSheet* Outliner::GetStyleSheet( ULONG nPara ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetStyleSheet( (USHORT)nPara ); +} + +BOOL Outliner::IsInSelectionMode() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsInSelectionMode(); +} + +void Outliner::SetControlWord( ULONG nWord ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetControlWord( nWord ); +} + +ULONG Outliner::GetControlWord() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetControlWord(); +} + +void Outliner::SetAsianCompressionMode( USHORT n ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetAsianCompressionMode( n ); +} + +USHORT Outliner::GetAsianCompressionMode() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetAsianCompressionMode(); +} + +void Outliner::SetKernAsianPunctuation( BOOL b ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetKernAsianPunctuation( b ); +} + +BOOL Outliner::IsKernAsianPunctuation() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsKernAsianPunctuation(); +} + +void Outliner::SetAddExtLeading( BOOL bExtLeading ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetAddExtLeading( bExtLeading ); +} + +BOOL Outliner::IsAddExtLeading() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsAddExtLeading(); +} + +void Outliner::UndoActionStart( USHORT nId ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->UndoActionStart( nId ); +} + +void Outliner::UndoActionEnd( USHORT nId ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->UndoActionEnd( nId ); +} + +void Outliner::InsertUndo( EditUndo* pUndo ) +{ +#ifndef SVX_LIGHT + DBG_CHKTHIS(Outliner,0); + pEditEngine->GetUndoManager().AddUndoAction( pUndo, FALSE ); +#endif +} + +BOOL Outliner::IsInUndo() +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsInUndo(); +} + +ULONG Outliner::GetLineCount( ULONG nParagraph ) const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetLineCount( (USHORT)nParagraph ); +} + +USHORT Outliner::GetLineLen( ULONG nParagraph, USHORT nLine ) const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetLineLen( (USHORT)nParagraph, nLine ); +} + +ULONG Outliner::GetLineHeight( ULONG nParagraph, ULONG nLine ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetLineHeight( (USHORT)nParagraph, (USHORT)nLine ); +} + +void Outliner::QuickRemoveCharAttribs( USHORT nPara, USHORT nWhich ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->QuickRemoveCharAttribs( nPara, nWhich ); +} + +EESpellState Outliner::HasSpellErrors() +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->HasSpellErrors(); +} + +sal_Bool Outliner::HasConvertibleTextPortion( LanguageType nLang ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->HasConvertibleTextPortion( nLang ); +} + +BOOL Outliner::ConvertNextDocument() +{ + DBG_CHKTHIS(Outliner,0); + return FALSE; +} + +void Outliner::SetDefaultLanguage( LanguageType eLang ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetDefaultLanguage( eLang ); +} + +LanguageType Outliner::GetDefaultLanguage() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetDefaultLanguage(); +} + +BOOL Outliner::HasOnlineSpellErrors() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->HasOnlineSpellErrors(); +} + +void Outliner::CompleteOnlineSpelling() +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->CompleteOnlineSpelling(); +} + +BOOL Outliner::HasText( const SvxSearchItem& rSearchItem ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->HasText( rSearchItem ); +} + +void Outliner::SetEditTextObjectPool( SfxItemPool* pPool ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetEditTextObjectPool( pPool ); +} + +SfxItemPool* Outliner::GetEditTextObjectPool() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetEditTextObjectPool(); +} + +BOOL Outliner::SpellNextDocument() +{ + DBG_CHKTHIS(Outliner,0); + return FALSE; +} + + +void Outliner::SetSpeller( Reference< XSpellChecker1 > &xSpeller ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetSpeller( xSpeller ); +} +Reference< XSpellChecker1 > Outliner::GetSpeller() +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetSpeller(); +} + +void Outliner::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetForbiddenCharsTable( xForbiddenChars ); +} + +vos::ORef<SvxForbiddenCharactersTable> Outliner::GetForbiddenCharsTable() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetForbiddenCharsTable(); +} + + +Reference< XHyphenator > Outliner::GetHyphenator() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetHyphenator(); +} + +void Outliner::SetHyphenator( Reference< XHyphenator >& xHyph ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetHyphenator( xHyph ); +} + +OutputDevice* Outliner::GetRefDevice() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetRefDevice(); +} + +USHORT Outliner::GetFirstLineOffset( ULONG nParagraph ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetFirstLineOffset( (USHORT)nParagraph ); +} + +ULONG Outliner::GetTextHeight( ULONG nParagraph ) const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetTextHeight((USHORT)nParagraph ); +} + +Point Outliner::GetDocPos( const Point& rPaperPos ) const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetDocPos( rPaperPos ); +} + +Point Outliner::GetDocPosTopLeft( ULONG nParagraph ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetDocPosTopLeft( (USHORT)nParagraph ); +} + +BOOL Outliner::IsTextPos( const Point& rPaperPos, USHORT nBorder ) +{ + return IsTextPos( rPaperPos, nBorder, NULL ); +} + +BOOL Outliner::IsTextPos( const Point& rPaperPos, USHORT nBorder, BOOL* pbBullet ) +{ + DBG_CHKTHIS(Outliner,0); + if ( pbBullet) + *pbBullet = FALSE; + BOOL bTextPos = pEditEngine->IsTextPos( rPaperPos, nBorder ); + if ( !bTextPos ) + { + Point aDocPos = GetDocPos( rPaperPos ); + USHORT nPara = pEditEngine->FindParagraph( aDocPos.Y() ); + if ( ( nPara != EE_PARA_NOT_FOUND ) && ImplHasBullet( nPara ) ) + { + Rectangle aBulArea = ImpCalcBulletArea( nPara, TRUE, TRUE ); + if ( aBulArea.IsInside( rPaperPos ) ) + { + bTextPos = TRUE; + if ( pbBullet) + *pbBullet = TRUE; + } + } + } + + return bTextPos; +} + +void Outliner::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->QuickSetAttribs( rSet, rSel ); +} + +void Outliner::QuickInsertText( const XubString& rText, const ESelection& rSel ) +{ + bFirstParaIsEmpty = FALSE; + pEditEngine->QuickInsertText( rText, rSel ); +} + +void Outliner::QuickDelete( const ESelection& rSel ) +{ + bFirstParaIsEmpty = FALSE; + pEditEngine->QuickDelete( rSel ); +} + +void Outliner::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) +{ + DBG_CHKTHIS(Outliner,0); + bFirstParaIsEmpty = FALSE; + pEditEngine->QuickInsertField( rFld, rSel ); +} + +void Outliner::QuickInsertLineBreak( const ESelection& rSel ) +{ + DBG_CHKTHIS(Outliner,0); + bFirstParaIsEmpty = FALSE; + pEditEngine->QuickInsertLineBreak( rSel ); +} + +void Outliner::QuickFormatDoc( BOOL bFull ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->QuickFormatDoc( bFull ); +} + +void Outliner::SetGlobalCharStretching( USHORT nX, USHORT nY ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetGlobalCharStretching( nX, nY ); +} + +void Outliner::GetGlobalCharStretching( USHORT& rX, USHORT& rY ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->GetGlobalCharStretching( rX, rY ); +} + + +void Outliner::DoStretchChars( USHORT nX, USHORT nY ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->DoStretchChars( nX, nY ); +} + +void Outliner::EraseVirtualDevice() +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->EraseVirtualDevice(); +} + +void Outliner::SetBigTextObjectStart( USHORT nStartAtPortionCount ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetBigTextObjectStart( nStartAtPortionCount ); +} + +USHORT Outliner::GetBigTextObjectStart() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetBigTextObjectStart(); +} + +BOOL Outliner::ShouldCreateBigTextObject() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->ShouldCreateBigTextObject(); +} + +void Outliner::SetVertical( BOOL b ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetVertical( b ); +} + +BOOL Outliner::IsVertical() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsVertical(); +} + +void Outliner::SetFixedCellHeight( BOOL bUseFixedCellHeight ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetFixedCellHeight( bUseFixedCellHeight ); +} + +BOOL Outliner::IsFixedCellHeight() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsFixedCellHeight(); +} + + +void Outliner::SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetDefaultHorizontalTextDirection( eHTextDir ); +} + +EEHorizontalTextDirection Outliner::GetDefaultHorizontalTextDirection() const +{ + return pEditEngine->GetDefaultHorizontalTextDirection(); +} + +USHORT Outliner::GetScriptType( const ESelection& rSelection ) const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetScriptType( rSelection ); +} + +LanguageType Outliner::GetLanguage( USHORT nPara, USHORT nPos ) const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetLanguage( nPara, nPos ); +} + +void Outliner::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich ); +} + +void Outliner::EnableAutoColor( BOOL b ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->EnableAutoColor( b ); +} + +BOOL Outliner::IsAutoColorEnabled() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsAutoColorEnabled(); +} + +void Outliner::ForceAutoColor( BOOL b ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->ForceAutoColor( b ); +} + +BOOL Outliner::IsForceAutoColor() const +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->IsForceAutoColor(); +} +/*-- 13.10.2003 16:56:23--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void Outliner::StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc) +{ + pEditEngine->StartSpelling(rEditView, bMultipleDoc); +} +/*-- 13.10.2003 16:56:23--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void Outliner::EndSpelling() +{ + pEditEngine->EndSpelling(); +} +/*-- 13.10.2003 16:56:23--------------------------------------------------- + + -----------------------------------------------------------------------*/ +bool Outliner::SpellSentence(EditView& rEditView, ::svx::SpellPortions& rToFill, bool bIsGrammarChecking ) +{ + return pEditEngine->SpellSentence(rEditView, rToFill, bIsGrammarChecking ); +} +/*-- 08.09.2008 11:39:05--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void Outliner::PutSpellingToSentenceStart( EditView& rEditView ) +{ + pEditEngine->PutSpellingToSentenceStart( rEditView ); +} +/*-- 13.10.2003 16:56:25--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void Outliner::ApplyChangedSentence(EditView& rEditView, const ::svx::SpellPortions& rNewPortions, bool bRecheck ) +{ + pEditEngine->ApplyChangedSentence( rEditView, rNewPortions, bRecheck ); +} diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx new file mode 100644 index 000000000000..328a762fec54 --- /dev/null +++ b/editeng/source/outliner/outliner.cxx @@ -0,0 +1,2181 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <svl/intitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fhgtitem.hxx> + +#include <math.h> +#include <svl/style.hxx> +#include <vcl/wrkwin.hxx> +#define _OUTLINER_CXX +#include <editeng/outliner.hxx> +#include <paralist.hxx> +#include <editeng/outlobj.hxx> +#include <outleeng.hxx> +#include <outlundo.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editstat.hxx> +#include <editeng/scripttypeitem.hxx> +#include <editeng/editobj.hxx> +#include <svl/itemset.hxx> +#include <svl/whiter.hxx> +#include <vcl/metric.hxx> +#include <editeng/numitem.hxx> +#include <editeng/adjitem.hxx> +#include <vcl/graph.hxx> +#include <vcl/gdimtf.hxx> +#include <vcl/metaact.hxx> +#include <svtools/grfmgr.hxx> +#include <editeng/svxfont.hxx> +#include <editeng/brshitem.hxx> +#include <svl/itempool.hxx> + +// #101498# calculate if it's RTL or not +#include <unicode/ubidi.h> + +#define DEFAULT_SCALE 75 + +static const USHORT nDefStyles = 3; // Sonderbehandlung fuer die ersten 3 Ebenen +static const USHORT nDefBulletIndent = 800; +static const USHORT nDefBulletWidth = 700; +static const USHORT pDefBulletIndents[nDefStyles]= { 1400, 800, 800 }; +static const USHORT pDefBulletWidths[nDefStyles] = { 1000, 850, 700 }; + +USHORT lcl_ImplGetDefBulletWidth( sal_Int16 nDepth ) +{ + return ( nDepth < nDefStyles ) ? pDefBulletWidths[nDepth] : nDefBulletWidth; +} + +USHORT lcl_ImplGetDefBulletIndent( sal_Int16 nDepth ) +{ + USHORT nI = 0; + + if( nDepth >= 0 ) + { + for ( sal_Int16 n = 0; n <= nDepth; n++ ) + nI = nI + + ( ( n < nDefStyles ) ? pDefBulletIndents[n] : nDefBulletIndent ); + } + return nI; +} + + +// ---------------------------------------------------------------------- +// Outliner +// ---------------------------------------------------------------------- +DBG_NAME(Outliner); + +void Outliner::ImplCheckDepth( sal_Int16& rnDepth ) const +{ + if( rnDepth < nMinDepth ) + rnDepth = nMinDepth; + else if( rnDepth > nMaxDepth ) + rnDepth = nMaxDepth; +} + +Paragraph* Outliner::Insert(const XubString& rText, ULONG nAbsPos, sal_Int16 nDepth) +{ + DBG_CHKTHIS(Outliner,0); + DBG_ASSERT(pParaList->GetParagraphCount(),"Insert:No Paras"); + + Paragraph* pPara; + + ImplCheckDepth( nDepth ); + + ULONG nParagraphCount = pParaList->GetParagraphCount(); + if( nAbsPos > nParagraphCount ) + nAbsPos = nParagraphCount; + + if( bFirstParaIsEmpty ) + { + pPara = pParaList->GetParagraph( 0 ); + if( pPara->GetDepth() != nDepth ) + { + nDepthChangedHdlPrevDepth = pPara->GetDepth(); + mnDepthChangeHdlPrevFlags = pPara->nFlags; + pPara->SetDepth( nDepth ); + pHdlParagraph = pPara; + DepthChangedHdl(); + } + pPara->nFlags |= PARAFLAG_HOLDDEPTH; + SetText( rText, pPara ); + } + else + { + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + ImplBlockInsertionCallbacks( TRUE ); + pPara = new Paragraph( nDepth ); + pParaList->Insert( pPara, nAbsPos ); + pEditEngine->InsertParagraph( (USHORT)nAbsPos, String() ); + DBG_ASSERT(pPara==pParaList->GetParagraph(nAbsPos),"Insert:Failed"); + ImplInitDepth( (USHORT)nAbsPos, nDepth, FALSE ); + pHdlParagraph = pPara; + ParagraphInsertedHdl(); + pPara->nFlags |= PARAFLAG_HOLDDEPTH; + SetText( rText, pPara ); + ImplBlockInsertionCallbacks( FALSE ); + pEditEngine->SetUpdateMode( bUpdate ); + } + bFirstParaIsEmpty = FALSE; + DBG_ASSERT(pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(),"SetText failed"); + return pPara; +} + + +void Outliner::ParagraphInserted( USHORT nPara ) +{ + DBG_CHKTHIS(Outliner,0); + + if ( bBlockInsCallback ) + return; + + if( bPasting || pEditEngine->IsInUndo() ) + { + Paragraph* pPara = new Paragraph( -1 ); + pParaList->Insert( pPara, nPara ); + if( pEditEngine->IsInUndo() ) + { + pPara->nFlags = PARAFLAG_SETBULLETTEXT; + pPara->bVisible = TRUE; + const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); + pPara->SetDepth( rLevel.GetValue() ); + } + } + else + { + sal_Int16 nDepth = -1; + Paragraph* pParaBefore = pParaList->GetParagraph( nPara-1 ); + if ( pParaBefore ) + nDepth = pParaBefore->GetDepth(); + + Paragraph* pPara = new Paragraph( nDepth ); + pParaList->Insert( pPara, nPara ); + + if( !pEditEngine->IsInUndo() ) + { + ImplCalcBulletText( nPara, TRUE, FALSE ); + pHdlParagraph = pPara; + ParagraphInsertedHdl(); + } + } +} + +void Outliner::ParagraphDeleted( USHORT nPara ) +{ + DBG_CHKTHIS(Outliner,0); + + if ( bBlockInsCallback || ( nPara == EE_PARA_ALL ) ) + return; + + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (!pPara) + return; + + sal_Int16 nDepth = pPara->GetDepth(); + + if( !pEditEngine->IsInUndo() ) + { + pHdlParagraph = pPara; + ParagraphRemovingHdl(); + } + + pParaList->Remove( nPara ); + delete pPara; + + if( !pEditEngine->IsInUndo() && !bPasting ) + { + pPara = pParaList->GetParagraph( nPara ); + if ( pPara && ( pPara->GetDepth() > nDepth ) ) + { + ImplCalcBulletText( nPara, TRUE, FALSE ); + // naechsten auf gleicher Ebene suchen... + while ( pPara && pPara->GetDepth() > nDepth ) + pPara = pParaList->GetParagraph( ++nPara ); + } + + if ( pPara && ( pPara->GetDepth() == nDepth ) ) + ImplCalcBulletText( nPara, TRUE, FALSE ); + } +} + +void Outliner::Init( USHORT nMode ) +{ + nOutlinerMode = nMode; + + Clear(); + + ULONG nCtrl = pEditEngine->GetControlWord(); + nCtrl &= ~(EE_CNTRL_OUTLINER|EE_CNTRL_OUTLINER2); + + SetMaxDepth( 9 ); + + switch ( ImplGetOutlinerMode() ) + { + case OUTLINERMODE_TEXTOBJECT: + case OUTLINERMODE_TITLEOBJECT: + break; + + case OUTLINERMODE_OUTLINEOBJECT: + nCtrl |= EE_CNTRL_OUTLINER2; + break; + case OUTLINERMODE_OUTLINEVIEW: + nCtrl |= EE_CNTRL_OUTLINER; + break; + + default: DBG_ERROR( "Outliner::Init - Invalid Mode!" ); + } + + pEditEngine->SetControlWord( nCtrl ); + + ImplInitDepth( 0, GetMinDepth(), FALSE ); + + GetUndoManager().Clear(); +} + +void Outliner::SetMaxDepth( sal_Int16 nDepth, BOOL bCheckParagraphs ) +{ + if( nMaxDepth != nDepth ) + { + nMaxDepth = Min( nDepth, (sal_Int16)(SVX_MAX_NUM-1) ); + + if( bCheckParagraphs ) + { + USHORT nParagraphs = (USHORT)pParaList->GetParagraphCount(); + for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ ) + { + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if( pPara && pPara->GetDepth() > nMaxDepth ) + { + SetDepth( pPara, nMaxDepth ); + } + } + } + } +} + +sal_Int16 Outliner::GetDepth( ULONG nPara ) const +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + DBG_ASSERT( pPara, "Outliner::GetDepth - Paragraph not found!" ); + return pPara ? pPara->GetDepth() : -1; +} + +void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth ) +{ + DBG_CHKTHIS(Outliner,0); + + ImplCheckDepth( nNewDepth ); + + if ( nNewDepth != pPara->GetDepth() ) + { + nDepthChangedHdlPrevDepth = pPara->GetDepth(); + mnDepthChangeHdlPrevFlags = pPara->nFlags; + pHdlParagraph = pPara; + + USHORT nPara = (USHORT)GetAbsPos( pPara ); + ImplInitDepth( nPara, nNewDepth, TRUE ); + ImplCalcBulletText( nPara, FALSE, FALSE ); + + if ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) + ImplSetLevelDependendStyleSheet( nPara ); + + DepthChangedHdl(); + } +} + +sal_Int16 Outliner::GetNumberingStartValue( sal_uInt16 nPara ) +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" ); + return pPara ? pPara->GetNumberingStartValue() : -1; +} + +void Outliner::SetNumberingStartValue( sal_uInt16 nPara, sal_Int16 nNumberingStartValue ) +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" ); + if( pPara && pPara->GetNumberingStartValue() != nNumberingStartValue ) + { + if( IsUndoEnabled() && !IsInUndo() ) + InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara, + pPara->GetNumberingStartValue(), nNumberingStartValue, + pPara->IsParaIsNumberingRestart(), pPara->IsParaIsNumberingRestart() ) ); + + pPara->SetNumberingStartValue( nNumberingStartValue ); + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + ImplCheckParagraphs( nPara, (USHORT) (pParaList->GetParagraphCount()) ); + // <-- + pEditEngine->SetModified(); + } +} + +sal_Bool Outliner::IsParaIsNumberingRestart( sal_uInt16 nPara ) +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" ); + return pPara ? pPara->IsParaIsNumberingRestart() : sal_False; +} + +void Outliner::SetParaIsNumberingRestart( sal_uInt16 nPara, sal_Bool bParaIsNumberingRestart ) +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + DBG_ASSERT( pPara, "Outliner::SetParaIsNumberingRestart - Paragraph not found!" ); + if( pPara && (pPara->IsParaIsNumberingRestart() != bParaIsNumberingRestart) ) + { + if( IsUndoEnabled() && !IsInUndo() ) + InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara, + pPara->GetNumberingStartValue(), pPara->GetNumberingStartValue(), + pPara->IsParaIsNumberingRestart(), bParaIsNumberingRestart ) ); + + pPara->SetParaIsNumberingRestart( bParaIsNumberingRestart ); + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + ImplCheckParagraphs( nPara, (USHORT) (pParaList->GetParagraphCount()) ); + // <-- + pEditEngine->SetModified(); + } +} + +OutlinerParaObject* Outliner::CreateParaObject( USHORT nStartPara, USHORT nCount ) const +{ + DBG_CHKTHIS(Outliner,0); + + if ( sal::static_int_cast< ULONG >( nStartPara + nCount ) > + pParaList->GetParagraphCount() ) + nCount = sal::static_int_cast< USHORT >( + pParaList->GetParagraphCount() - nStartPara ); + + // When a new OutlinerParaObject is created because a paragraph is just beeing deleted, + // it can happen that the ParaList is not updated yet... + if ( ( nStartPara + nCount ) > pEditEngine->GetParagraphCount() ) + nCount = pEditEngine->GetParagraphCount() - nStartPara; + + if( !nCount ) + return NULL; + + EditTextObject* pText = pEditEngine->CreateTextObject( nStartPara, nCount ); + const bool bIsEditDoc(OUTLINERMODE_TEXTOBJECT == ImplGetOutlinerMode()); + ParagraphDataVector aParagraphDataVector(nCount); + const sal_uInt16 nLastPara(nStartPara + nCount - 1); + + for(sal_uInt16 nPara(nStartPara); nPara <= nLastPara; nPara++) + { + aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara); + } + + OutlinerParaObject* pPObj = new OutlinerParaObject(*pText, aParagraphDataVector, bIsEditDoc); + pPObj->SetOutlinerMode(GetMode()); + delete pText; + + return pPObj; +} + +void Outliner::SetText( const XubString& rText, Paragraph* pPara ) +{ + DBG_CHKTHIS(Outliner,0); + DBG_ASSERT(pPara,"SetText:No Para"); + + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + ImplBlockInsertionCallbacks( TRUE ); + + USHORT nPara = (USHORT)pParaList->GetAbsPos( pPara ); + + if( !rText.Len() ) + { + pEditEngine->SetText( nPara, rText ); + ImplInitDepth( nPara, pPara->GetDepth(), FALSE ); + } + else + { + XubString aText( rText ); + aText.ConvertLineEnd( LINEEND_LF ); + + if( aText.GetChar( aText.Len()-1 ) == '\x0A' ) + aText.Erase( aText.Len()-1, 1 ); // letzten Umbruch loeschen + + USHORT nCount = aText.GetTokenCount( '\x0A' ); + USHORT nPos = 0; + USHORT nInsPos = nPara+1; + while( nCount > nPos ) + { + XubString aStr = aText.GetToken( nPos, '\x0A' ); + + sal_Int16 nCurDepth; + if( nPos ) + { + pPara = new Paragraph( -1 ); + nCurDepth = -1; + } + else + nCurDepth = pPara->GetDepth(); + + // Im Outliner-Modus die Tabulatoren filtern und die + // Einrueckung ueber ein LRSpaceItem einstellen + // Im EditEngine-Modus ueber Maltes Tabulatoren einruecken + if( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || + ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ) ) + { + // Tabs raus + USHORT nTabs = 0; + while ( ( nTabs < aStr.Len() ) && ( aStr.GetChar( nTabs ) == '\t' ) ) + nTabs++; + if ( nTabs ) + aStr.Erase( 0, nTabs ); + + // Tiefe beibehalten ? (siehe Outliner::Insert) + if( !(pPara->nFlags & PARAFLAG_HOLDDEPTH) ) + { + nCurDepth = nTabs-1; + ImplCheckDepth( nCurDepth ); + pPara->SetDepth( nCurDepth ); + pPara->nFlags &= (~PARAFLAG_HOLDDEPTH); + } + } + if( nPos ) // nicht mit dem ersten Absatz + { + pParaList->Insert( pPara, nInsPos ); + pEditEngine->InsertParagraph( nInsPos, aStr ); + pHdlParagraph = pPara; + ParagraphInsertedHdl(); + } + else + { + nInsPos--; + pEditEngine->SetText( nInsPos, aStr ); + } + ImplInitDepth( nInsPos, nCurDepth, FALSE ); + nInsPos++; + nPos++; + } + } + + DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"SetText failed!"); + bFirstParaIsEmpty = FALSE; + ImplBlockInsertionCallbacks( FALSE ); + pEditEngine->SetUpdateMode( bUpdate ); +} + +// pView == 0 -> Tabulatoren nicht beachten + +bool Outliner::ImpConvertEdtToOut( sal_uInt32 nPara,EditView* pView) +{ + DBG_CHKTHIS(Outliner,0); + + bool bConverted = false; + USHORT nTabs = 0; + ESelection aDelSel; + +// const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( (sal_uInt16)nPara ); +// bool bAlreadyOutliner = rAttrs.GetItemState( EE_PARA_OUTLLRSPACE ) == SFX_ITEM_ON ? true : false; + + XubString aName; + XubString aHeading_US( RTL_CONSTASCII_USTRINGPARAM( "heading" ) ); + XubString aNumber_US( RTL_CONSTASCII_USTRINGPARAM( "Numbering" ) ); + + XubString aStr( pEditEngine->GetText( (USHORT)nPara ) ); + xub_Unicode* pPtr = (xub_Unicode*)aStr.GetBuffer(); + + USHORT nHeadingNumberStart = 0; + USHORT nNumberingNumberStart = 0; + SfxStyleSheet* pStyle= pEditEngine->GetStyleSheet( (USHORT)nPara ); + if( pStyle ) + { + aName = pStyle->GetName(); + USHORT nSearch; + if ( ( nSearch = aName.Search( aHeading_US ) ) != STRING_NOTFOUND ) + nHeadingNumberStart = nSearch + aHeading_US.Len(); + else if ( ( nSearch = aName.Search( aNumber_US ) ) != STRING_NOTFOUND ) + nNumberingNumberStart = nSearch + aNumber_US.Len(); + } + + if ( nHeadingNumberStart || nNumberingNumberStart ) + { + // PowerPoint-Import ? + if( nHeadingNumberStart && ( aStr.Len() >= 2 ) && + ( pPtr[0] != '\t' ) && ( pPtr[1] == '\t' ) ) + { + // Bullet & Tab raus + aDelSel = ESelection( (USHORT)nPara, 0, (USHORT)nPara, 2 ); + } + + USHORT nPos = nHeadingNumberStart ? nHeadingNumberStart : nNumberingNumberStart; + String aLevel = aName.Copy( nPos ); + aLevel.EraseLeadingChars( ' ' ); + nTabs = sal::static_int_cast< USHORT >(aLevel.ToInt32()); + if( nTabs ) + nTabs--; // ebene 0 = "heading 1" + bConverted = TRUE; + } + else + { + // Fuehrende Tabulatoren filtern + while( *pPtr == '\t' ) + { + pPtr++; + nTabs++; + } + // Tabulatoren aus dem Text entfernen + if( nTabs ) + aDelSel = ESelection( (USHORT)nPara, 0, (USHORT)nPara, nTabs ); + } + + if ( aDelSel.HasRange() ) + { + if ( pView ) + { + pView->SetSelection( aDelSel ); + pView->DeleteSelected(); + } + else + pEditEngine->QuickDelete( aDelSel ); + } + + const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( sal::static_int_cast< sal_uInt16 >(nPara), EE_PARA_OUTLLEVEL ); + sal_Int16 nOutlLevel = rLevel.GetValue(); + + ImplCheckDepth( nOutlLevel ); + ImplInitDepth( sal::static_int_cast< sal_uInt16 >(nPara), nOutlLevel, FALSE ); + + return bConverted; +} + +void Outliner::SetText( const OutlinerParaObject& rPObj ) +{ + DBG_CHKTHIS(Outliner,0); + + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + + BOOL bUndo = pEditEngine->IsUndoEnabled(); + EnableUndo( FALSE ); + + Init( rPObj.GetOutlinerMode() ); + + ImplBlockInsertionCallbacks( TRUE ); + pEditEngine->SetText(rPObj.GetTextObject()); + if( rPObj.Count() != pEditEngine->GetParagraphCount() ) + { + int nop=0;nop++; + } + + bFirstParaIsEmpty = FALSE; + + pParaList->Clear( TRUE ); + for( USHORT nCurPara = 0; nCurPara < rPObj.Count(); nCurPara++ ) + { + Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(nCurPara)); + ImplCheckDepth( pPara->nDepth ); + + pParaList->Insert( pPara, LIST_APPEND ); + ImplCheckNumBulletItem( nCurPara ); + } + + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + ImplCheckParagraphs( 0, (USHORT) (pParaList->GetParagraphCount()) ); + // <-- + + EnableUndo( bUndo ); + ImplBlockInsertionCallbacks( FALSE ); + pEditEngine->SetUpdateMode( bUpdate ); + + DBG_ASSERT( pParaList->GetParagraphCount()==rPObj.Count(),"SetText failed"); + DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed"); +} + +void Outliner::AddText( const OutlinerParaObject& rPObj ) +{ + DBG_CHKTHIS(Outliner,0); + Paragraph* pPara; + + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + + ImplBlockInsertionCallbacks( TRUE ); + ULONG nPara; + if( bFirstParaIsEmpty ) + { + pParaList->Clear( TRUE ); + pEditEngine->SetText(rPObj.GetTextObject()); + nPara = 0; + } + else + { + nPara = pParaList->GetParagraphCount(); + pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject() ); + } + bFirstParaIsEmpty = FALSE; + + for( USHORT n = 0; n < rPObj.Count(); n++ ) + { + pPara = new Paragraph( rPObj.GetParagraphData(n) ); + pParaList->Insert( pPara, LIST_APPEND ); + USHORT nP = sal::static_int_cast< USHORT >(nPara+n); + DBG_ASSERT(pParaList->GetAbsPos(pPara)==nP,"AddText:Out of sync"); + ImplInitDepth( nP, pPara->GetDepth(), FALSE ); + } + DBG_ASSERT( pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(), "SetText: OutOfSync" ); + + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + ImplCheckParagraphs( (USHORT)nPara, (USHORT) (pParaList->GetParagraphCount()) ); + // <-- + + ImplBlockInsertionCallbacks( FALSE ); + pEditEngine->SetUpdateMode( bUpdate ); +} + +void __EXPORT Outliner::FieldClicked( const SvxFieldItem& rField, USHORT nPara, USHORT nPos ) +{ + DBG_CHKTHIS(Outliner,0); + + if ( aFieldClickedHdl.IsSet() ) + { + EditFieldInfo aFldInfo( this, rField, nPara, nPos ); + aFldInfo.SetSimpleClick( TRUE ); + aFieldClickedHdl.Call( &aFldInfo ); + } +} + + +void __EXPORT Outliner::FieldSelected( const SvxFieldItem& rField, USHORT nPara, USHORT nPos ) +{ + DBG_CHKTHIS(Outliner,0); + if ( !aFieldClickedHdl.IsSet() ) + return; + + EditFieldInfo aFldInfo( this, rField, nPara, nPos ); + aFldInfo.SetSimpleClick( FALSE ); + aFieldClickedHdl.Call( &aFldInfo ); +} + + +XubString __EXPORT Outliner::CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, Color*& rpTxtColor, Color*& rpFldColor ) +{ + DBG_CHKTHIS(Outliner,0); + if ( !aCalcFieldValueHdl.IsSet() ) + return String( ' ' ); + + EditFieldInfo aFldInfo( this, rField, nPara, nPos ); + // Die FldColor ist mit COL_LIGHTGRAY voreingestellt. + if ( rpFldColor ) + aFldInfo.SetFldColor( *rpFldColor ); + + aCalcFieldValueHdl.Call( &aFldInfo ); + if ( aFldInfo.GetTxtColor() ) + { + delete rpTxtColor; + rpTxtColor = new Color( *aFldInfo.GetTxtColor() ); + } + + delete rpFldColor; + rpFldColor = aFldInfo.GetFldColor() ? new Color( *aFldInfo.GetFldColor() ) : 0; + + return aFldInfo.GetRepresentation(); +} + +void Outliner::SetStyleSheet( ULONG nPara, SfxStyleSheet* pStyle ) +{ + DBG_CHKTHIS(Outliner,0); + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (pPara) + { + pEditEngine->SetStyleSheet( (USHORT)nPara, pStyle ); + pPara->nFlags |= PARAFLAG_SETBULLETTEXT; + ImplCheckNumBulletItem( (USHORT) nPara ); + } +} + +void Outliner::SetVisible( Paragraph* pPara, BOOL bVisible ) +{ + DBG_CHKTHIS(Outliner,0); + DBG_ASSERT( pPara, "SetVisible: pPara = NULL" ); + + if (pPara) + { + pPara->bVisible = bVisible; + ULONG nPara = pParaList->GetAbsPos( pPara ); + pEditEngine->ShowParagraph( (USHORT)nPara, bVisible ); + } +} + +void Outliner::ImplCheckNumBulletItem( USHORT nPara ) +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (pPara) + pPara->aBulSize.Width() = -1; +} + +void Outliner::ImplSetLevelDependendStyleSheet( USHORT nPara, SfxStyleSheet* pLevelStyle ) +{ + DBG_CHKTHIS(Outliner,0); + + DBG_ASSERT( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ), "SetLevelDependendStyleSheet: Wrong Mode!" ); + + SfxStyleSheet* pStyle = pLevelStyle; + if ( !pStyle ) + pStyle = GetStyleSheet( nPara ); + + if ( pStyle ) + { + sal_Int16 nDepth = GetDepth( nPara ); + if( nDepth < 0 ) + nDepth = 0; + + String aNewStyleSheetName( pStyle->GetName() ); + aNewStyleSheetName.Erase( aNewStyleSheetName.Len()-1, 1 ); + aNewStyleSheetName += String::CreateFromInt32( nDepth+1 ); + SfxStyleSheet* pNewStyle = (SfxStyleSheet*)GetStyleSheetPool()->Find( aNewStyleSheetName, pStyle->GetFamily() ); + DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" ); + if ( pNewStyle && ( pNewStyle != GetStyleSheet( nPara ) ) ) + { + SfxItemSet aOldAttrs( GetParaAttribs( nPara ) ); + SetStyleSheet( nPara, pNewStyle ); + if ( aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SFX_ITEM_ON ) + { + SfxItemSet aAttrs( GetParaAttribs( nPara ) ); + aAttrs.Put( aOldAttrs.Get( EE_PARA_NUMBULLET ) ); + SetParaAttribs( nPara, aAttrs ); + } + } + } +} + +void Outliner::ImplInitDepth( USHORT nPara, sal_Int16 nDepth, BOOL bCreateUndo, BOOL bUndoAction ) +{ + DBG_CHKTHIS(Outliner,0); + + DBG_ASSERT( ( nDepth >= nMinDepth ) && ( nDepth <= nMaxDepth ), "ImplInitDepth - Depth is invalid!" ); + + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (!pPara) + return; + sal_Int16 nOldDepth = pPara->GetDepth(); + pPara->SetDepth( nDepth ); + + // Bei IsInUndo brauchen Attribute und Style nicht eingestellt werden, + // dort werden die alten Werte durch die EditEngine restauriert. + + if( !IsInUndo() ) + { + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + + BOOL bUndo = bCreateUndo && IsUndoEnabled(); + if ( bUndo && bUndoAction ) + UndoActionStart( OLUNDO_DEPTH ); + + SfxItemSet aAttrs( pEditEngine->GetParaAttribs( nPara ) ); + aAttrs.Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nDepth ) ); + pEditEngine->SetParaAttribs( nPara, aAttrs ); + ImplCheckNumBulletItem( nPara ); + ImplCalcBulletText( nPara, FALSE, FALSE ); + + if ( bUndo ) + { + InsertUndo( new OutlinerUndoChangeDepth( this, nPara, nOldDepth, nDepth ) ); + if ( bUndoAction ) + UndoActionEnd( OLUNDO_DEPTH ); + } + + pEditEngine->SetUpdateMode( bUpdate ); + } +} + +void Outliner::SetParaAttribs( USHORT nPara, const SfxItemSet& rSet ) +{ + DBG_CHKTHIS(Outliner,0); + + pEditEngine->SetParaAttribs( nPara, rSet ); +} + +BOOL Outliner::Expand( Paragraph* pPara ) +{ + DBG_CHKTHIS(Outliner,0); + + if ( pParaList->HasHiddenChilds( pPara ) ) + { + OLUndoExpand* pUndo = 0; + BOOL bUndo = IsUndoEnabled() && !IsInUndo(); + if( bUndo ) + { + UndoActionStart( OLUNDO_EXPAND ); + pUndo = new OLUndoExpand( this, OLUNDO_EXPAND ); + pUndo->pParas = 0; + pUndo->nCount = (USHORT)pParaList->GetAbsPos( pPara ); + } + pHdlParagraph = pPara; + bIsExpanding = TRUE; + pParaList->Expand( pPara ); + ExpandHdl(); + InvalidateBullet( pPara, pParaList->GetAbsPos(pPara) ); + if( bUndo ) + { + InsertUndo( pUndo ); + UndoActionEnd( OLUNDO_EXPAND ); + } + return TRUE; + } + return FALSE; +} + + +BOOL Outliner::Collapse( Paragraph* pPara ) +{ + DBG_CHKTHIS(Outliner,0); + if ( pParaList->HasVisibleChilds( pPara ) ) // expandiert + { + OLUndoExpand* pUndo = 0; + BOOL bUndo = FALSE; + + if( !IsInUndo() && IsUndoEnabled() ) + bUndo = TRUE; + if( bUndo ) + { + UndoActionStart( OLUNDO_COLLAPSE ); + pUndo = new OLUndoExpand( this, OLUNDO_COLLAPSE ); + pUndo->pParas = 0; + pUndo->nCount = (USHORT)pParaList->GetAbsPos( pPara ); + } + + pHdlParagraph = pPara; + bIsExpanding = FALSE; + pParaList->Collapse( pPara ); + ExpandHdl(); + InvalidateBullet( pPara, pParaList->GetAbsPos(pPara) ); + if( bUndo ) + { + InsertUndo( pUndo ); + UndoActionEnd( OLUNDO_COLLAPSE ); + } + return TRUE; + } + return FALSE; +} + + +Font Outliner::ImpCalcBulletFont( USHORT nPara ) const +{ + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + DBG_ASSERT( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ), "ImpCalcBulletFont: Missing or BitmapBullet!" ); + + Font aStdFont; //#107508# + if ( !pEditEngine->IsFlatMode() ) + { + ESelection aSel( nPara, 0, nPara, 0 ); + aStdFont = EditEngine::CreateFontFromItemSet( pEditEngine->GetAttribs( aSel ), GetScriptType( aSel ) ); + } + else + { + aStdFont = pEditEngine->GetStandardFont( nPara ); + } + + Font aBulletFont; + if ( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ) + { + aBulletFont = *pFmt->GetBulletFont(); + } + else + { + aBulletFont = aStdFont; + aBulletFont.SetUnderline( UNDERLINE_NONE ); + aBulletFont.SetOverline( UNDERLINE_NONE ); + aBulletFont.SetStrikeout( STRIKEOUT_NONE ); + aBulletFont.SetEmphasisMark( EMPHASISMARK_NONE ); + aBulletFont.SetRelief( RELIEF_NONE ); + } + + // #107508# Use original scale... + USHORT nScale = /* pEditEngine->IsFlatMode() ? DEFAULT_SCALE : */ pFmt->GetBulletRelSize(); + ULONG nScaledLineHeight = aStdFont.GetSize().Height(); + nScaledLineHeight *= nScale*10; + nScaledLineHeight /= 1000; + + aBulletFont.SetAlign( ALIGN_BOTTOM ); + aBulletFont.SetSize( Size( 0, nScaledLineHeight ) ); + BOOL bVertical = IsVertical(); + aBulletFont.SetVertical( bVertical ); + aBulletFont.SetOrientation( bVertical ? 2700 : 0 ); + + Color aColor( COL_AUTO ); + if( !pEditEngine->IsFlatMode() && !( pEditEngine->GetControlWord() & EE_CNTRL_NOCOLORS ) ) + { + aColor = pFmt->GetBulletColor(); + } + + if ( ( aColor == COL_AUTO ) || ( IsForceAutoColor() ) ) + aColor = pEditEngine->GetAutoColor(); + + aBulletFont.SetColor( aColor ); + return aBulletFont; +} + +void Outliner::PaintBullet( USHORT nPara, const Point& rStartPos, + const Point& rOrigin, short nOrientation, OutputDevice* pOutDev ) +{ + DBG_CHKTHIS(Outliner,0); + + bool bDrawBullet = false; + if (pEditEngine) + { + const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ); + bDrawBullet = rBulletState.GetValue() ? true : false; + } + + if ( ImplHasBullet( nPara ) && bDrawBullet) + { + BOOL bVertical = IsVertical(); + + BOOL bRightToLeftPara = pEditEngine->IsRightToLeft( nPara ); + + Rectangle aBulletArea( ImpCalcBulletArea( nPara, TRUE, FALSE ) ); + + Paragraph* pPara = pParaList->GetParagraph( nPara ); + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + if ( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) + { + if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) + { + Font aBulletFont( ImpCalcBulletFont( nPara ) ); + // #2338# Use base line + BOOL bSymbol = pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL; + aBulletFont.SetAlign( bSymbol ? ALIGN_BOTTOM : ALIGN_BASELINE ); + Font aOldFont = pOutDev->GetFont(); + pOutDev->SetFont( aBulletFont ); + + ParagraphInfos aParaInfos = pEditEngine->GetParagraphInfos( nPara ); + Point aTextPos; + if ( !bVertical ) + { +// aTextPos.Y() = rStartPos.Y() + aBulletArea.Bottom(); + aTextPos.Y() = rStartPos.Y() + ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent ); + if ( !bRightToLeftPara ) + aTextPos.X() = rStartPos.X() + aBulletArea.Left(); + else + aTextPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left(); + } + else + { +// aTextPos.X() = rStartPos.X() - aBulletArea.Bottom(); + aTextPos.X() = rStartPos.X() - ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent ); + aTextPos.Y() = rStartPos.Y() + aBulletArea.Left(); + } + + if ( nOrientation ) + { + // Sowohl TopLeft als auch BottomLeft nicht ganz richtig, da + // in EditEngine BaseLine... + double nRealOrientation = nOrientation*F_PI1800; + double nCos = cos( nRealOrientation ); + double nSin = sin( nRealOrientation ); + Point aRotatedPos; + // Translation... + aTextPos -= rOrigin; + // Rotation... + aRotatedPos.X()=(long) (nCos*aTextPos.X() + nSin*aTextPos.Y()); + aRotatedPos.Y()=(long) - (nSin*aTextPos.X() - nCos*aTextPos.Y()); + aTextPos = aRotatedPos; + // Translation... + aTextPos += rOrigin; + Font aRotatedFont( aBulletFont ); + aRotatedFont.SetOrientation( nOrientation ); + pOutDev->SetFont( aRotatedFont ); + } + + // #105803# VCL will care for brackets and so on... + ULONG nLayoutMode = pOutDev->GetLayoutMode(); + nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG); + if ( bRightToLeftPara ) + nLayoutMode |= TEXT_LAYOUT_BIDI_RTL; + pOutDev->SetLayoutMode( nLayoutMode ); + + if(bStrippingPortions) + { + const Font aSvxFont(pOutDev->GetFont()); + sal_Int32* pBuf = new sal_Int32[ pPara->GetText().Len() ]; + pOutDev->GetTextArray( pPara->GetText(), pBuf ); + + if(bSymbol) + { + // aTextPos is Bottom, go to Baseline + FontMetric aMetric(pOutDev->GetFontMetric()); + aTextPos.Y() -= aMetric.GetDescent(); + } + + DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().Len(), pBuf, + aSvxFont, nPara, 0xFFFF, 0xFF, 0, 0, false, false, true, 0, Color(), Color()); + + delete[] pBuf; + } + else + { + pOutDev->DrawText( aTextPos, pPara->GetText() ); + } + + pOutDev->SetFont( aOldFont ); + } + else + { + if ( pFmt->GetBrush()->GetGraphicObject() ) + { + Point aBulletPos; + if ( !bVertical ) + { + aBulletPos.Y() = rStartPos.Y() + aBulletArea.Top(); + if ( !bRightToLeftPara ) + aBulletPos.X() = rStartPos.X() + aBulletArea.Left(); + else + aBulletPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right(); + } + else + { + aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom(); + aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left(); + } + + if(bStrippingPortions) + { + if(aDrawBulletHdl.IsSet()) + { + // call something analog to aDrawPortionHdl (if set) and feed it something + // analog to DrawPortionInfo... + // created aDrawBulletHdl, Set/GetDrawBulletHdl. + // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx + DrawBulletInfo aDrawBulletInfo( + *pFmt->GetBrush()->GetGraphicObject(), + aBulletPos, + pPara->aBulSize); + + aDrawBulletHdl.Call(&aDrawBulletInfo); + } + } + else + { + // MT: Remove CAST when KA made the Draw-Method const + ((GraphicObject*)pFmt->GetBrush()->GetGraphicObject())->Draw( pOutDev, aBulletPos, pPara->aBulSize ); + } + } + } + } + + // Bei zusammengeklappten Absaetzen einen Strich vor den Text malen. + if( pParaList->HasChilds(pPara) && !pParaList->HasVisibleChilds(pPara) && + !bStrippingPortions && !nOrientation ) + { + long nWidth = pOutDev->PixelToLogic( Size( 10, 0 ) ).Width(); + + Point aStartPos, aEndPos; + if ( !bVertical ) + { + aStartPos.Y() = rStartPos.Y() + aBulletArea.Bottom(); + if ( !bRightToLeftPara ) + aStartPos.X() = rStartPos.X() + aBulletArea.Right(); + else + aStartPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left(); + aEndPos = aStartPos; + aEndPos.X() += nWidth; + } + else + { + aStartPos.X() = rStartPos.X() - aBulletArea.Bottom(); + aStartPos.Y() = rStartPos.Y() + aBulletArea.Right(); + aEndPos = aStartPos; + aEndPos.Y() += nWidth; + } + + const Color& rOldLineColor = pOutDev->GetLineColor(); + pOutDev->SetLineColor( Color( COL_BLACK ) ); + pOutDev->DrawLine( aStartPos, aEndPos ); + pOutDev->SetLineColor( rOldLineColor ); + } + } +} + +void Outliner::InvalidateBullet( Paragraph* /*pPara*/, ULONG nPara ) +{ + DBG_CHKTHIS(Outliner,0); + + long nLineHeight = (long)pEditEngine->GetLineHeight((USHORT)nPara ); + OutlinerView* pView = aViewList.First(); + while( pView ) + { + Point aPos( pView->pEditView->GetWindowPosTopLeft((USHORT)nPara ) ); + Rectangle aRect( pView->GetOutputArea() ); + aRect.Right() = aPos.X(); + aRect.Top() = aPos.Y(); + aRect.Bottom() = aPos.Y(); + aRect.Bottom() += nLineHeight; + + pView->GetWindow()->Invalidate( aRect ); + pView = aViewList.Next(); + } +} + +ULONG Outliner::Read( SvStream& rInput, const String& rBaseURL, USHORT eFormat, SvKeyValueIterator* pHTTPHeaderAttrs ) +{ + DBG_CHKTHIS(Outliner,0); + + BOOL bOldUndo = pEditEngine->IsUndoEnabled(); + EnableUndo( FALSE ); + + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + + Clear(); + + ImplBlockInsertionCallbacks( TRUE ); + ULONG nRet = pEditEngine->Read( rInput, rBaseURL, (EETextFormat)eFormat, pHTTPHeaderAttrs ); + + bFirstParaIsEmpty = FALSE; + + USHORT nParas = pEditEngine->GetParagraphCount(); + pParaList->Clear( TRUE ); + USHORT n; + for ( n = 0; n < nParas; n++ ) + { + Paragraph* pPara = new Paragraph( 0 ); + pParaList->Insert( pPara, LIST_APPEND ); + + if ( eFormat == EE_FORMAT_BIN ) + { + const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( n ); + const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL ); + sal_Int16 nDepth = rLevel.GetValue(); + ImplInitDepth( n, nDepth, FALSE ); + } + } + + if ( eFormat != EE_FORMAT_BIN ) + { + ImpFilterIndents( 0, nParas-1 ); + } + + ImplBlockInsertionCallbacks( FALSE ); + pEditEngine->SetUpdateMode( bUpdate ); + EnableUndo( bOldUndo ); + + return nRet; +} + + +void Outliner::ImpFilterIndents( ULONG nFirstPara, ULONG nLastPara ) +{ + DBG_CHKTHIS(Outliner,0); + + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + + Paragraph* pLastConverted = NULL; + for( ULONG nPara = nFirstPara; nPara <= nLastPara; nPara++ ) + { + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (pPara) + { + if( ImpConvertEdtToOut( nPara ) ) + { + pLastConverted = pPara; + } + else if ( pLastConverted ) + { + // Normale Absaetze unter der Ueberschrift anordnen... + pPara->SetDepth( pLastConverted->GetDepth() ); + } + + ImplInitDepth( (USHORT)nPara, pPara->GetDepth(), FALSE ); + } + } + + pEditEngine->SetUpdateMode( bUpdate ); +} + +SfxUndoManager& Outliner::GetUndoManager() +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetUndoManager(); +} + +void Outliner::ImpTextPasted( ULONG nStartPara, USHORT nCount ) +{ + DBG_CHKTHIS(Outliner,0); + + BOOL bUpdate = pEditEngine->GetUpdateMode(); + pEditEngine->SetUpdateMode( FALSE ); + + const ULONG nStart = nStartPara; + + Paragraph* pPara = pParaList->GetParagraph( nStartPara ); +// Paragraph* pLastConverted = NULL; +// bool bFirst = true; + + while( nCount && pPara ) + { + if( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) + { + nDepthChangedHdlPrevDepth = pPara->GetDepth(); + mnDepthChangeHdlPrevFlags = pPara->nFlags; + + ImpConvertEdtToOut( nStartPara ); + + pHdlParagraph = pPara; + + if( nStartPara == nStart ) + { + // the existing paragraph has changed depth or flags + if( (pPara->GetDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != mnDepthChangeHdlPrevFlags) ) + DepthChangedHdl(); + } + } + else // EditEngine-Modus + { + sal_Int16 nDepth = -1; + const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( (USHORT)nStartPara ); + if ( rAttrs.GetItemState( EE_PARA_OUTLLEVEL ) == SFX_ITEM_ON ) + { + const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL ); + nDepth = rLevel.GetValue(); + } + if ( nDepth != GetDepth( nStartPara ) ) + ImplInitDepth( (USHORT)nStartPara, nDepth, FALSE ); + } + + nCount--; + nStartPara++; + pPara = pParaList->GetParagraph( nStartPara ); + } + + pEditEngine->SetUpdateMode( bUpdate ); + + DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"ImpTextPasted failed"); +} + +long Outliner::IndentingPagesHdl( OutlinerView* pView ) +{ + DBG_CHKTHIS(Outliner,0); + if( !aIndentingPagesHdl.IsSet() ) + return 1; + return aIndentingPagesHdl.Call( pView ); +} + +BOOL Outliner::ImpCanIndentSelectedPages( OutlinerView* pCurView ) +{ + DBG_CHKTHIS(Outliner,0); + // Die selektierten Seiten muessen vorher durch ImpCalcSelectedPages + // schon eingestellt sein + + // Wenn der erste Absatz auf Ebene 0 liegt darf er auf keinen Fall + // eingerueckt werden, evtl folgen aber weitere auf Ebene 0. + if ( ( mnFirstSelPage == 0 ) && ( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) ) + { + if ( nDepthChangedHdlPrevDepth == 1 ) // ist die einzige Seite + return FALSE; + else + pCurView->ImpCalcSelectedPages( FALSE ); // ohne die erste + } + return (BOOL)IndentingPagesHdl( pCurView ); +} + + +BOOL Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView ) +{ + DBG_CHKTHIS(Outliner,0); + // Die selektierten Seiten muessen vorher durch ImpCalcSelectedPages + // schon eingestellt sein + return (BOOL)RemovingPagesHdl( pCurView ); +} + +Outliner::Outliner( SfxItemPool* pPool, USHORT nMode ) +: nMinDepth( -1 ) +{ + DBG_CTOR( Outliner, 0 ); + + bStrippingPortions = FALSE; + bPasting = FALSE; + + nFirstPage = 1; + bBlockInsCallback = FALSE; + + nMaxDepth = 9; + + pParaList = new ParagraphList; + pParaList->SetVisibleStateChangedHdl( LINK( this, Outliner, ParaVisibleStateChangedHdl ) ); + Paragraph* pPara = new Paragraph( 0 ); + pParaList->Insert( pPara, LIST_APPEND ); + bFirstParaIsEmpty = TRUE; + + pEditEngine = new OutlinerEditEng( this, pPool ); + pEditEngine->SetBeginMovingParagraphsHdl( LINK( this, Outliner, BeginMovingParagraphsHdl ) ); + pEditEngine->SetEndMovingParagraphsHdl( LINK( this, Outliner, EndMovingParagraphsHdl ) ); + pEditEngine->SetBeginPasteOrDropHdl( LINK( this, Outliner, BeginPasteOrDropHdl ) ); + pEditEngine->SetEndPasteOrDropHdl( LINK( this, Outliner, EndPasteOrDropHdl ) ); + + Init( nMode ); +} + +Outliner::~Outliner() +{ + DBG_DTOR(Outliner,0); + + pParaList->Clear( TRUE ); + delete pParaList; + delete pEditEngine; +} + +ULONG Outliner::InsertView( OutlinerView* pView, ULONG nIndex ) +{ + DBG_CHKTHIS(Outliner,0); + + aViewList.Insert( pView, nIndex ); + pEditEngine->InsertView( pView->pEditView, (USHORT)nIndex ); + return aViewList.GetPos( pView ); +} + +OutlinerView* Outliner::RemoveView( OutlinerView* pView ) +{ + DBG_CHKTHIS(Outliner,0); + + ULONG nPos = aViewList.GetPos( pView ); + if ( nPos != LIST_ENTRY_NOTFOUND ) + { + pView->pEditView->HideCursor(); // HACK wg. BugId 10006 + pEditEngine->RemoveView( pView->pEditView ); + aViewList.Remove( nPos ); + } + return NULL; // MT: return ueberfluessig +} + +OutlinerView* Outliner::RemoveView( ULONG nIndex ) +{ + DBG_CHKTHIS(Outliner,0); + + EditView* pEditView = pEditEngine->GetView( (USHORT)nIndex ); + pEditView->HideCursor(); // HACK wg. BugId 10006 + + pEditEngine->RemoveView( (USHORT)nIndex ); + aViewList.Remove( nIndex ); + return NULL; // MT: return ueberfluessig +} + + +OutlinerView* Outliner::GetView( ULONG nIndex ) const +{ + DBG_CHKTHIS(Outliner,0); + return aViewList.GetObject( nIndex ); +} + +ULONG Outliner::GetViewCount() const +{ + DBG_CHKTHIS(Outliner,0); + return aViewList.Count(); +} + +void Outliner::ParagraphInsertedHdl() +{ + DBG_CHKTHIS(Outliner,0); + if( !IsInUndo() ) + aParaInsertedHdl.Call( this ); +} + + +void Outliner::ParagraphRemovingHdl() +{ + DBG_CHKTHIS(Outliner,0); + if( !IsInUndo() ) + aParaRemovingHdl.Call( this ); +} + + +void Outliner::DepthChangedHdl() +{ + DBG_CHKTHIS(Outliner,0); + if( !IsInUndo() ) + aDepthChangedHdl.Call( this ); +} + + +ULONG Outliner::GetAbsPos( Paragraph* pPara ) +{ + DBG_CHKTHIS(Outliner,0); + DBG_ASSERT(pPara,"GetAbsPos:No Para"); + return pParaList->GetAbsPos( pPara ); +} + +ULONG Outliner::GetParagraphCount() const +{ + DBG_CHKTHIS(Outliner,0); + return pParaList->GetParagraphCount(); +} + +Paragraph* Outliner::GetParagraph( ULONG nAbsPos ) const +{ + DBG_CHKTHIS(Outliner,0); + return pParaList->GetParagraph( nAbsPos ); +} + +BOOL Outliner::HasChilds( Paragraph* pParagraph ) const +{ + DBG_CHKTHIS(Outliner,0); + return pParaList->HasChilds( pParagraph ); +} + +BOOL Outliner::ImplHasBullet( USHORT nPara ) const +{ + return GetNumberFormat(nPara) != 0; +} + +const SvxNumberFormat* Outliner::GetNumberFormat( USHORT nPara ) const +{ + const SvxNumberFormat* pFmt = NULL; + + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (pPara == NULL) + return NULL; + + sal_Int16 nDepth = pPara? pPara->GetDepth() : -1; + + if( nDepth >= 0 ) + { + const SvxNumBulletItem& rNumBullet = (const SvxNumBulletItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_NUMBULLET ); + if ( rNumBullet.GetNumRule()->GetLevelCount() > nDepth ) + pFmt = rNumBullet.GetNumRule()->Get( nDepth ); + } + + return pFmt; +} + +Size Outliner::ImplGetBulletSize( USHORT nPara ) +{ + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (!pPara) + return Size(); + + if( pPara->aBulSize.Width() == -1 ) + { + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + DBG_ASSERT( pFmt, "ImplGetBulletSize - no Bullet!" ); + + if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE ) + { + pPara->aBulSize = Size( 0, 0 ); + } + else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) + { + String aBulletText = ImplGetBulletText( nPara ); + OutputDevice* pRefDev = pEditEngine->GetRefDevice(); + Font aBulletFont( ImpCalcBulletFont( nPara ) ); + Font aRefFont( pRefDev->GetFont()); + pRefDev->SetFont( aBulletFont ); + pPara->aBulSize.Width() = pRefDev->GetTextWidth( aBulletText ); + pPara->aBulSize.Height() = pRefDev->GetTextHeight(); + pRefDev->SetFont( aRefFont ); + } + else + { + pPara->aBulSize = OutputDevice::LogicToLogic( pFmt->GetGraphicSize(), MAP_100TH_MM, pEditEngine->GetRefDevice()->GetMapMode() ); + } + } + + return pPara->aBulSize; +} + +void Outliner::ImplCheckParagraphs( USHORT nStart, USHORT nEnd ) +{ + DBG_CHKTHIS( Outliner, 0 ); + + // --> OD 2009-03-10 #i100014# + // assure that the following for-loop does not loop forever + for ( USHORT n = nStart; n < nEnd; n++ ) + // <-- + { + Paragraph* pPara = pParaList->GetParagraph( n ); + if (pPara) + { + pPara->Invalidate(); + ImplCalcBulletText( n, FALSE, FALSE ); + } + } +} + +void Outliner::SetRefDevice( OutputDevice* pRefDev ) +{ + DBG_CHKTHIS(Outliner,0); + pEditEngine->SetRefDevice( pRefDev ); + for ( USHORT n = (USHORT) pParaList->GetParagraphCount(); n; ) + { + Paragraph* pPara = pParaList->GetParagraph( --n ); + pPara->Invalidate(); + } +} + +void Outliner::ParaAttribsChanged( USHORT nPara ) +{ + DBG_CHKTHIS(Outliner,0); + + // Der Outliner hat kein eigenes Undo, wenn Absaetz getrennt/verschmolzen werden. + // Beim ParagraphInserted ist das Attribut EE_PARA_OUTLLEVEL + // ggf. noch nicht eingestellt, dies wird aber benoetigt um die Tiefe + // des Absatzes zu bestimmen. + + if( pEditEngine->IsInUndo() ) + { + if ( pParaList->GetParagraphCount() == pEditEngine->GetParagraphCount() ) + { + Paragraph* pPara = pParaList->GetParagraph( nPara ); + const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); + if ( pPara && pPara->GetDepth() != rLevel.GetValue() ) + { + pPara->SetDepth( rLevel.GetValue() ); + ImplCalcBulletText( nPara, TRUE, TRUE ); + } + } + } +} + +void Outliner::StyleSheetChanged( SfxStyleSheet* pStyle ) +{ + DBG_CHKTHIS(Outliner,0); + + // Die EditEngine ruft StyleSheetChanged auch fuer abgeleitete Styles. + // MT: Hier wurde frueher alle Absaetze durch ein ImpRecalcParaAttribs + // gejagt, die die besagte Vorlage haben, warum? + // => Eigentlich kann sich nur die Bullet-Repraesentation aendern... + + USHORT nParas = (USHORT)pParaList->GetParagraphCount(); + for( USHORT nPara = 0; nPara < nParas; nPara++ ) + { + if ( pEditEngine->GetStyleSheet( nPara ) == pStyle ) + { + ImplCheckNumBulletItem( nPara ); + ImplCalcBulletText( nPara, FALSE, FALSE ); + // #97333# EditEngine formats changed paragraphs before calling this method, + // so they are not reformatted now and use wrong bullet indent + pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); + } + } +} + +Rectangle Outliner::ImpCalcBulletArea( USHORT nPara, BOOL bAdjust, BOOL bReturnPaperPos ) +{ + // Bullet-Bereich innerhalb des Absatzes... + Rectangle aBulletArea; + + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + if ( pFmt ) + { + Point aTopLeft; + Size aBulletSize( ImplGetBulletSize( nPara ) ); + + BOOL bOutlineMode = ( pEditEngine->GetControlWord() & EE_CNTRL_OUTLINER ) != 0; + + // the ODF attribut text:space-before which holds the spacing to add to the left of the label + const short nSpaceBefore = pFmt->GetAbsLSpace() + pFmt->GetFirstLineOffset(); + + const SvxLRSpaceItem& rLR = (const SvxLRSpaceItem&) pEditEngine->GetParaAttrib( nPara, bOutlineMode ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); + aTopLeft.X() = rLR.GetTxtLeft() + rLR.GetTxtFirstLineOfst() + nSpaceBefore; + + long nBulletWidth = Max( (long) -rLR.GetTxtFirstLineOfst(), (long) ((-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance()) ); + if ( nBulletWidth < aBulletSize.Width() ) // Bullet macht sich Platz + nBulletWidth = aBulletSize.Width(); + + if ( bAdjust && !bOutlineMode ) + { + // Bei zentriert/rechtsbuendig anpassen + const SvxAdjustItem& rItem = (const SvxAdjustItem&)pEditEngine->GetParaAttrib( nPara, EE_PARA_JUST ); + if ( ( !pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_LEFT ) ) || + ( pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_RIGHT ) ) ) + { + aTopLeft.X() = pEditEngine->GetFirstLineStartX( nPara ) - nBulletWidth; + } + } + + // Vertikal: + ParagraphInfos aInfos = pEditEngine->GetParagraphInfos( nPara ); + if ( aInfos.bValid ) + { + aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ // #91076# nFirstLineOffset is already added to the StartPos (PaintBullet) from the EditEngine + aInfos.nFirstLineHeight - aInfos.nFirstLineTextHeight + + aInfos.nFirstLineTextHeight / 2 + - aBulletSize.Height() / 2; + // ggf. lieber auf der Baseline ausgeben... + if( ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) ) + { + Font aBulletFont( ImpCalcBulletFont( nPara ) ); + if ( aBulletFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) + { + OutputDevice* pRefDev = pEditEngine->GetRefDevice(); + Font aOldFont = pRefDev->GetFont(); + pRefDev->SetFont( aBulletFont ); + FontMetric aMetric( pRefDev->GetFontMetric() ); + // Leading der ersten Zeile... + aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ aInfos.nFirstLineMaxAscent; + aTopLeft.Y() -= aMetric.GetAscent(); + pRefDev->SetFont( aOldFont ); + } + } + } + + // Horizontal: + if( pFmt->GetNumAdjust() == SVX_ADJUST_RIGHT ) + { + aTopLeft.X() += nBulletWidth - aBulletSize.Width(); + } + else if( pFmt->GetNumAdjust() == SVX_ADJUST_CENTER ) + { + aTopLeft.X() += ( nBulletWidth - aBulletSize.Width() ) / 2; + } + + if ( aTopLeft.X() < 0 ) // dann draengeln + aTopLeft.X() = 0; + + aBulletArea = Rectangle( aTopLeft, aBulletSize ); + } + if ( bReturnPaperPos ) + { + Size aBulletSize( aBulletArea.GetSize() ); + Point aBulletDocPos( aBulletArea.TopLeft() ); + aBulletDocPos.Y() += pEditEngine->GetDocPosTopLeft( nPara ).Y(); + Point aBulletPos( aBulletDocPos ); + + if ( IsVertical() ) + { + aBulletPos.Y() = aBulletDocPos.X(); + aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.Y(); + // Rotate: + aBulletPos.X() -= aBulletSize.Height(); + Size aSz( aBulletSize ); + aBulletSize.Width() = aSz.Height(); + aBulletSize.Height() = aSz.Width(); + } + else if ( pEditEngine->IsRightToLeft( nPara ) ) + { + aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.X() - aBulletSize.Width(); + } + + aBulletArea = Rectangle( aBulletPos, aBulletSize ); + } + return aBulletArea; +} + +void Outliner::ExpandHdl() +{ + DBG_CHKTHIS(Outliner,0); + aExpandHdl.Call( this ); +} + +EBulletInfo Outliner::GetBulletInfo( USHORT nPara ) +{ + EBulletInfo aInfo; + + aInfo.nParagraph = nPara; + aInfo.bVisible = ImplHasBullet( nPara ); + + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + aInfo.nType = pFmt ? pFmt->GetNumberingType() : 0; + + if( pFmt ) + { + if( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) + { + aInfo.aText = ImplGetBulletText( nPara ); + + if( pFmt->GetBulletFont() ) + aInfo.aFont = *pFmt->GetBulletFont(); + } + else if ( pFmt->GetBrush()->GetGraphicObject() ) + { + aInfo.aGraphic = pFmt->GetBrush()->GetGraphicObject()->GetGraphic(); + } + } + + if ( aInfo.bVisible ) + { + aInfo.aBounds = ImpCalcBulletArea( nPara, TRUE, TRUE ); + } + + return aInfo; +} + +XubString Outliner::GetText( Paragraph* pParagraph, ULONG nCount ) const +{ + DBG_CHKTHIS(Outliner,0); + + XubString aText; + USHORT nStartPara = (USHORT) pParaList->GetAbsPos( pParagraph ); + for ( USHORT n = 0; n < nCount; n++ ) + { + aText += pEditEngine->GetText( nStartPara + n ); + if ( (n+1) < (USHORT)nCount ) + aText += '\n'; + } + return aText; +} + +void Outliner::Remove( Paragraph* pPara, ULONG nParaCount ) +{ + DBG_CHKTHIS(Outliner,0); + + ULONG nPos = pParaList->GetAbsPos( pPara ); + if( !nPos && ( nParaCount >= pParaList->GetParagraphCount() ) ) + { + Clear(); + } + else + { + for( USHORT n = 0; n < (USHORT)nParaCount; n++ ) + pEditEngine->RemoveParagraph( (USHORT) nPos ); + } +} + +void Outliner::StripPortions() +{ + DBG_CHKTHIS(Outliner,0); + bStrippingPortions = TRUE; + pEditEngine->StripPortions(); + bStrippingPortions = FALSE; +} + +// #101498# +void Outliner::DrawingText( const Point& rStartPos, const XubString& rText, USHORT nTextStart, USHORT nTextLen, const sal_Int32* pDXArray,const SvxFont& rFont, + USHORT nPara, USHORT nIndex, BYTE nRightToLeft, + const EEngineData::WrongSpellVector* pWrongSpellVector, + const SvxFieldData* pFieldData, + bool bEndOfLine, + bool bEndOfParagraph, + bool bEndOfBullet, + const ::com::sun::star::lang::Locale* pLocale, + const Color& rOverlineColor, + const Color& rTextLineColor) +{ + DBG_CHKTHIS(Outliner,0); + + if(aDrawPortionHdl.IsSet()) + { + // #101498# + DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, nIndex, pDXArray, pWrongSpellVector, + pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, bEndOfLine, bEndOfParagraph, bEndOfBullet); + + aDrawPortionHdl.Call( &aInfo ); + } +} + +long Outliner::RemovingPagesHdl( OutlinerView* pView ) +{ + DBG_CHKTHIS(Outliner,0); + return aRemovingPagesHdl.IsSet() ? aRemovingPagesHdl.Call( pView ) : TRUE; +} + +BOOL Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, USHORT _nFirstPage, USHORT nPages ) +{ + DBG_CHKTHIS(Outliner,0); + + nDepthChangedHdlPrevDepth = nPages; + mnFirstSelPage = _nFirstPage; + pHdlParagraph = 0; + return (BOOL)RemovingPagesHdl( pCurView ); +} + +SfxItemSet Outliner::GetParaAttribs( USHORT nPara ) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->GetParaAttribs( nPara ); +} + +IMPL_LINK( Outliner, ParaVisibleStateChangedHdl, Paragraph*, pPara ) +{ + DBG_CHKTHIS(Outliner,0); + + ULONG nPara = pParaList->GetAbsPos( pPara ); + pEditEngine->ShowParagraph( (USHORT)nPara, pPara->IsVisible() ); + + return 0; +} + +IMPL_LINK( Outliner, BeginMovingParagraphsHdl, MoveParagraphsInfo*, EMPTYARG ) +{ + DBG_CHKTHIS(Outliner,0); + + if( !IsInUndo() ) + GetBeginMovingHdl().Call( this ); + + return 0; +} + +IMPL_LINK( Outliner, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos ) +{ + UndoActionStart( EDITUNDO_DRAGANDDROP ); + maBeginPasteOrDropHdl.Call(pInfos); + return 0; +} + +IMPL_LINK( Outliner, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos ) +{ + bPasting = FALSE; + ImpTextPasted( pInfos->nStartPara, pInfos->nEndPara - pInfos->nStartPara + 1 ); + maEndPasteOrDropHdl.Call( pInfos ); + UndoActionEnd( EDITUNDO_DRAGANDDROP ); + return 0; +} + +IMPL_LINK( Outliner, EndMovingParagraphsHdl, MoveParagraphsInfo*, pInfos ) +{ + DBG_CHKTHIS(Outliner,0); + + pParaList->MoveParagraphs( pInfos->nStartPara, pInfos->nDestPara, pInfos->nEndPara - pInfos->nStartPara + 1 ); + USHORT nChangesStart = Min( pInfos->nStartPara, pInfos->nDestPara ); + USHORT nParas = (USHORT)pParaList->GetParagraphCount(); + for ( USHORT n = nChangesStart; n < nParas; n++ ) + ImplCalcBulletText( n, FALSE, FALSE ); + + if( !IsInUndo() ) + aEndMovingHdl.Call( this ); + + return 0; +} + +static bool isSameNumbering( const SvxNumberFormat& rN1, const SvxNumberFormat& rN2 ) +{ + if( rN1.GetNumberingType() != rN2.GetNumberingType() ) + return false; + + if( rN1.GetNumStr(1) != rN2.GetNumStr(1) ) + return false; + + if( (rN1.GetPrefix() != rN2.GetPrefix()) || (rN1.GetSuffix() != rN2.GetSuffix()) ) + return false; + + return true; +} + +sal_uInt16 Outliner::ImplGetNumbering( USHORT nPara, const SvxNumberFormat* pParaFmt ) +{ + sal_uInt16 nNumber = pParaFmt->GetStart() - 1; + + Paragraph* pPara = pParaList->GetParagraph( nPara ); + const sal_Int16 nParaDepth = pPara->GetDepth(); + + do + { + pPara = pParaList->GetParagraph( nPara ); + const sal_Int16 nDepth = pPara->GetDepth(); + + // ignore paragraphs that are below our paragraph or have no numbering + if( (nDepth > nParaDepth) || (nDepth == -1) ) + continue; + + // stop on paragraphs that are above our paragraph + if( nDepth < nParaDepth ) + break; + + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + + if( pFmt == 0 ) + continue; // ignore paragraphs without bullets + + // check if numbering is the same + if( !isSameNumbering( *pFmt, *pParaFmt ) ) + break; + + const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ); + + if( rBulletState.GetValue() ) + nNumber += 1; + + // same depth, same number format, check for restart + const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue(); + if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() ) + { + if( nNumberingStartValue != -1 ) + nNumber += nNumberingStartValue - 1; + break; + } + } + while( nPara-- ); + + return nNumber; +} + +void Outliner::ImplCalcBulletText( USHORT nPara, BOOL bRecalcLevel, BOOL bRecalcChilds ) +{ + DBG_CHKTHIS(Outliner,0); + + Paragraph* pPara = pParaList->GetParagraph( nPara ); + USHORT nRelPos = 0xFFFF; + + while ( pPara ) + { + XubString aBulletText; + const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); + if( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) ) + { + aBulletText += pFmt->GetPrefix(); + if( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ) + { + aBulletText += pFmt->GetBulletChar(); + } + else if( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) + { + aBulletText += pFmt->GetNumStr( ImplGetNumbering( nPara, pFmt ) ); + } + aBulletText += pFmt->GetSuffix(); + } + + if( aBulletText != pPara->GetText() ) + pPara->SetText( aBulletText ); + + pPara->nFlags &= (~PARAFLAG_SETBULLETTEXT); + + if ( bRecalcLevel ) + { + if ( nRelPos != 0xFFFF ) + nRelPos++; + + sal_Int16 nDepth = pPara->GetDepth(); + pPara = pParaList->GetParagraph( ++nPara ); + if ( !bRecalcChilds ) + { + while ( pPara && ( pPara->GetDepth() > nDepth ) ) + pPara = pParaList->GetParagraph( ++nPara ); + } + + if ( pPara && ( pPara->GetDepth() < nDepth ) ) + pPara = NULL; + } + else + { + pPara = NULL; + } + } +} + +void Outliner::Clear() +{ + DBG_CHKTHIS(Outliner,0); + + if( !bFirstParaIsEmpty ) + { + ImplBlockInsertionCallbacks( TRUE ); + pEditEngine->Clear(); + pParaList->Clear( TRUE ); + pParaList->Insert( new Paragraph( nMinDepth ), LIST_APPEND ); + bFirstParaIsEmpty = TRUE; + ImplBlockInsertionCallbacks( FALSE ); + } + else + { + Paragraph* pPara = pParaList->GetParagraph( 0 ); + if(pPara) + pPara->SetDepth( nMinDepth ); + } +} + +void Outliner::SetFlatMode( BOOL bFlat ) +{ + DBG_CHKTHIS(Outliner,0); + + if( bFlat != pEditEngine->IsFlatMode() ) + { + for ( USHORT nPara = (USHORT)pParaList->GetParagraphCount(); nPara; ) + pParaList->GetParagraph( --nPara )->aBulSize.Width() = -1; + + pEditEngine->SetFlatMode( bFlat ); + } +} + +String Outliner::ImplGetBulletText( USHORT nPara ) +{ + String aRes; + Paragraph* pPara = pParaList->GetParagraph( nPara ); + if (pPara) + { + // MT: Optimierung mal wieder aktivieren... +// if( pPara->nFlags & PARAFLAG_SETBULLETTEXT ) + ImplCalcBulletText( nPara, FALSE, FALSE ); + aRes = pPara->GetText(); + } + return aRes; +} + +// this is needed for StarOffice Api +void Outliner::SetLevelDependendStyleSheet( USHORT nPara ) +{ + SfxItemSet aOldAttrs( pEditEngine->GetParaAttribs( nPara ) ); + ImplSetLevelDependendStyleSheet( nPara ); + pEditEngine->SetParaAttribs( nPara, aOldAttrs ); +} + +SV_IMPL_PTRARR( NotifyList, EENotifyPtr ); + +void Outliner::ImplBlockInsertionCallbacks( BOOL b ) +{ + if ( b ) + { + bBlockInsCallback++; + } + else + { + DBG_ASSERT( bBlockInsCallback, "ImplBlockInsertionCallbacks ?!" ); + bBlockInsCallback--; + if ( !bBlockInsCallback ) + { + // Call blocked notify events... + while ( pEditEngine->aNotifyCache.Count() ) + { + EENotify* pNotify = pEditEngine->aNotifyCache[0]; + // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler... + pEditEngine->aNotifyCache.Remove( 0 ); + pEditEngine->aOutlinerNotifyHdl.Call( pNotify ); + delete pNotify; + } + } + } +} + +IMPL_LINK( Outliner, EditEngineNotifyHdl, EENotify*, pNotify ) +{ + if ( !bBlockInsCallback ) + { + pEditEngine->aOutlinerNotifyHdl.Call( pNotify ); + } + else + { + EENotify* pNewNotify = new EENotify( *pNotify ); + pEditEngine->aNotifyCache.Insert( pNewNotify, pEditEngine->aNotifyCache.Count() ); + } + + return 0; +} + +/** sets a link that is called at the beginning of a drag operation at an edit view */ +void Outliner::SetBeginDropHdl( const Link& rLink ) +{ + pEditEngine->SetBeginDropHdl( rLink ); +} + +Link Outliner::GetBeginDropHdl() const +{ + return pEditEngine->GetBeginDropHdl(); +} + +/** sets a link that is called at the end of a drag operation at an edit view */ +void Outliner::SetEndDropHdl( const Link& rLink ) +{ + pEditEngine->SetEndDropHdl( rLink ); +} + +Link Outliner::GetEndDropHdl() const +{ + return pEditEngine->GetEndDropHdl(); +} + +/** sets a link that is called before a drop or paste operation. */ +void Outliner::SetBeginPasteOrDropHdl( const Link& rLink ) +{ + maBeginPasteOrDropHdl = rLink; +} + +/** sets a link that is called after a drop or paste operation. */ +void Outliner::SetEndPasteOrDropHdl( const Link& rLink ) +{ + maEndPasteOrDropHdl = rLink; +} + +void Outliner::SetParaFlag( Paragraph* pPara, sal_uInt16 nFlag ) +{ + if( pPara && !pPara->HasFlag( nFlag ) ) + { + if( IsUndoEnabled() && !IsInUndo() ) + InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags|nFlag ) ); + + pPara->SetFlag( nFlag ); + } +} + +void Outliner::RemoveParaFlag( Paragraph* pPara, sal_uInt16 nFlag ) +{ + if( pPara && pPara->HasFlag( nFlag ) ) + { + if( IsUndoEnabled() && !IsInUndo() ) + InsertUndo( new OutlinerUndoChangeParaFlags( this, (sal_uInt16)GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags & ~nFlag ) ); + + pPara->RemoveFlag( nFlag ); + } +} + +bool Outliner::HasParaFlag( const Paragraph* pPara, sal_uInt16 nFlag ) const +{ + return pPara && pPara->HasFlag( nFlag ); +} + + +sal_Bool DrawPortionInfo::IsRTL() const +{ + if(0xFF == mnBiDiLevel) + { + // Use Bidi functions from icu 2.0 to calculate if this portion + // is RTL or not. + UErrorCode nError(U_ZERO_ERROR); + UBiDi* pBidi = ubidi_openSized(mrText.Len(), 0, &nError); + nError = U_ZERO_ERROR; + + // I do not have this info here. Is it necessary? I'll have to ask MT. + const BYTE nDefaultDir = UBIDI_LTR; //IsRightToLeft( nPara ) ? UBIDI_RTL : UBIDI_LTR; + + ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(mrText.GetBuffer()), mrText.Len(), nDefaultDir, NULL, &nError); // UChar != sal_Unicode in MinGW + nError = U_ZERO_ERROR; + +// sal_Int32 nCount(ubidi_countRuns(pBidi, &nError)); + + int32_t nStart(0); + int32_t nEnd; + UBiDiLevel nCurrDir; + + ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir); + + ubidi_close(pBidi); + + // remember on-demand calculated state + ((DrawPortionInfo*)this)->mnBiDiLevel = nCurrDir; + } + + return (1 == (mnBiDiLevel % 2)); +} + +// eof diff --git a/editeng/source/outliner/outliner.src b/editeng/source/outliner/outliner.src new file mode 100644 index 000000000000..42f8195407bd --- /dev/null +++ b/editeng/source/outliner/outliner.src @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <editeng/editrids.hrc> + +String RID_OUTLUNDO_HEIGHT +{ + Text [ en-US ] = "Move" ; +}; +String RID_OUTLUNDO_DEPTH +{ + Text [ en-US ] = "Indent" ; +}; +String RID_OUTLUNDO_EXPAND +{ + Text [ en-US ] = "Show subpoints" ; +}; +String RID_OUTLUNDO_COLLAPSE +{ + Text [ en-US ] = "Collapse" ; +}; +String RID_OUTLUNDO_ATTR +{ + Text [ en-US ] = "Apply attributes" ; +}; +String RID_OUTLUNDO_INSERT +{ + Text [ en-US ] = "Insert" ; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/editeng/source/outliner/outlobj.cxx b/editeng/source/outliner/outlobj.cxx new file mode 100644 index 000000000000..79bcf7e6361a --- /dev/null +++ b/editeng/source/outliner/outlobj.cxx @@ -0,0 +1,271 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <outl_pch.hxx> + +#define _OUTLINER_CXX +#include <editeng/outliner.hxx> +#include <editeng/outlobj.hxx> +#include <outleeng.hxx> +#include <editeng/editobj.hxx> +#include <vcl/bitmap.hxx> +#include <tools/stream.hxx> + +////////////////////////////////////////////////////////////////////////////// + +class ImplOutlinerParaObject +{ +public: + // data members + EditTextObject* mpEditTextObject; + ParagraphDataVector maParagraphDataVector; + bool mbIsEditDoc; + + // refcounter + sal_uInt32 mnRefCount; + + // constuctor + ImplOutlinerParaObject(EditTextObject* pEditTextObject, const ParagraphDataVector& rParagraphDataVector, bool bIsEditDoc) + : mpEditTextObject(pEditTextObject), + maParagraphDataVector(rParagraphDataVector), + mbIsEditDoc(bIsEditDoc), + mnRefCount(0) + { + if( (maParagraphDataVector.size() == 0) && (pEditTextObject->GetParagraphCount() != 0) ) + maParagraphDataVector.resize(pEditTextObject->GetParagraphCount()); + } + + // destructor + ~ImplOutlinerParaObject() + { + delete mpEditTextObject; + } + + bool operator==(const ImplOutlinerParaObject& rCandidate) const + { + return (*mpEditTextObject == *rCandidate.mpEditTextObject + && maParagraphDataVector == rCandidate.maParagraphDataVector + && mbIsEditDoc == rCandidate.mbIsEditDoc); + } + + // #i102062# + bool isWrongListEqual(const ImplOutlinerParaObject& rCompare) const + { + return mpEditTextObject->isWrongListEqual(*rCompare.mpEditTextObject); + } +}; + +////////////////////////////////////////////////////////////////////////////// + +void OutlinerParaObject::ImplMakeUnique() +{ + if(mpImplOutlinerParaObject->mnRefCount) + { + ImplOutlinerParaObject* pNew = new ImplOutlinerParaObject( + mpImplOutlinerParaObject->mpEditTextObject->Clone(), + mpImplOutlinerParaObject->maParagraphDataVector, + mpImplOutlinerParaObject->mbIsEditDoc); + mpImplOutlinerParaObject->mnRefCount--; + mpImplOutlinerParaObject = pNew; + } +} + +OutlinerParaObject::OutlinerParaObject(const EditTextObject& rEditTextObject, const ParagraphDataVector& rParagraphDataVector, bool bIsEditDoc) +: mpImplOutlinerParaObject(new ImplOutlinerParaObject(rEditTextObject.Clone(), rParagraphDataVector, bIsEditDoc)) +{ +} + +OutlinerParaObject::OutlinerParaObject(const OutlinerParaObject& rCandidate) +: mpImplOutlinerParaObject(rCandidate.mpImplOutlinerParaObject) +{ + mpImplOutlinerParaObject->mnRefCount++; +} + +OutlinerParaObject::~OutlinerParaObject() +{ + if(mpImplOutlinerParaObject->mnRefCount) + { + mpImplOutlinerParaObject->mnRefCount--; + } + else + { + delete mpImplOutlinerParaObject; + } +} + +OutlinerParaObject& OutlinerParaObject::operator=(const OutlinerParaObject& rCandidate) +{ + if(rCandidate.mpImplOutlinerParaObject != mpImplOutlinerParaObject) + { + if(mpImplOutlinerParaObject->mnRefCount) + { + mpImplOutlinerParaObject->mnRefCount--; + } + else + { + delete mpImplOutlinerParaObject; + } + + mpImplOutlinerParaObject = rCandidate.mpImplOutlinerParaObject; + mpImplOutlinerParaObject->mnRefCount++; + } + + return *this; +} + +bool OutlinerParaObject::operator==(const OutlinerParaObject& rCandidate) const +{ + if(rCandidate.mpImplOutlinerParaObject == mpImplOutlinerParaObject) + { + return true; + } + + return (*rCandidate.mpImplOutlinerParaObject == *mpImplOutlinerParaObject); +} + +// #i102062# +bool OutlinerParaObject::isWrongListEqual(const OutlinerParaObject& rCompare) const +{ + if(rCompare.mpImplOutlinerParaObject == mpImplOutlinerParaObject) + { + return true; + } + + return mpImplOutlinerParaObject->isWrongListEqual(*rCompare.mpImplOutlinerParaObject); +} + +sal_uInt16 OutlinerParaObject::GetOutlinerMode() const +{ + return mpImplOutlinerParaObject->mpEditTextObject->GetUserType(); +} + +void OutlinerParaObject::SetOutlinerMode(sal_uInt16 nNew) +{ + if(mpImplOutlinerParaObject->mpEditTextObject->GetUserType() != nNew) + { + ImplMakeUnique(); + mpImplOutlinerParaObject->mpEditTextObject->SetUserType(nNew); + } +} + +bool OutlinerParaObject::IsVertical() const +{ + return mpImplOutlinerParaObject->mpEditTextObject->IsVertical(); +} + +void OutlinerParaObject::SetVertical(bool bNew) +{ + if((bool)mpImplOutlinerParaObject->mpEditTextObject->IsVertical() != bNew) + { + ImplMakeUnique(); + mpImplOutlinerParaObject->mpEditTextObject->SetVertical(bNew); + } +} + +sal_uInt32 OutlinerParaObject::Count() const +{ + return mpImplOutlinerParaObject->maParagraphDataVector.size(); +} + +sal_Int16 OutlinerParaObject::GetDepth(sal_uInt16 nPara) const +{ + if(nPara < mpImplOutlinerParaObject->maParagraphDataVector.size()) + { + return mpImplOutlinerParaObject->maParagraphDataVector[nPara].getDepth(); + } + else + { + return -1; + } +} + +const EditTextObject& OutlinerParaObject::GetTextObject() const +{ + return *mpImplOutlinerParaObject->mpEditTextObject; +} + +bool OutlinerParaObject::IsEditDoc() const +{ + return mpImplOutlinerParaObject->mbIsEditDoc; +} + +const ParagraphData& OutlinerParaObject::GetParagraphData(sal_uInt32 nIndex) const +{ + if(nIndex < mpImplOutlinerParaObject->maParagraphDataVector.size()) + { + return mpImplOutlinerParaObject->maParagraphDataVector[nIndex]; + } + else + { + OSL_ENSURE(false, "OutlinerParaObject::GetParagraphData: Access out of range (!)"); + static ParagraphData aEmptyParagraphData; + return aEmptyParagraphData; + } +} + +void OutlinerParaObject::ClearPortionInfo() +{ + ImplMakeUnique(); + mpImplOutlinerParaObject->mpEditTextObject->ClearPortionInfo(); +} + +bool OutlinerParaObject::ChangeStyleSheets(const XubString& rOldName, SfxStyleFamily eOldFamily, const XubString& rNewName, SfxStyleFamily eNewFamily) +{ + ImplMakeUnique(); + return mpImplOutlinerParaObject->mpEditTextObject->ChangeStyleSheets(rOldName, eOldFamily, rNewName, eNewFamily); +} + +void OutlinerParaObject::ChangeStyleSheetName(SfxStyleFamily eFamily, const XubString& rOldName, const XubString& rNewName) +{ + ImplMakeUnique(); + mpImplOutlinerParaObject->mpEditTextObject->ChangeStyleSheetName(eFamily, rOldName, rNewName); +} + +void OutlinerParaObject::SetStyleSheets(sal_uInt16 nLevel, const XubString rNewName, const SfxStyleFamily& rNewFamily) +{ + const sal_uInt32 nCount(mpImplOutlinerParaObject->maParagraphDataVector.size()); + + if(nCount) + { + ImplMakeUnique(); + sal_uInt16 nDecrementer(sal::static_int_cast< sal_uInt16 >(nCount)); + + for(;nDecrementer;) + { + if(GetDepth(--nDecrementer) == nLevel) + { + mpImplOutlinerParaObject->mpEditTextObject->SetStyleSheet(nDecrementer, rNewName, rNewFamily); + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/editeng/source/outliner/outlundo.cxx b/editeng/source/outliner/outlundo.cxx new file mode 100644 index 000000000000..624776bc94e4 --- /dev/null +++ b/editeng/source/outliner/outlundo.cxx @@ -0,0 +1,234 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <svl/intitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fhgtitem.hxx> + +#define _OUTLINER_CXX +#include <editeng/outliner.hxx> +#include <outlundo.hxx> + + +OutlinerUndoBase::OutlinerUndoBase( USHORT _nId, Outliner* pOutliner ) + : EditUndo( _nId, NULL ) +{ + DBG_ASSERT( pOutliner, "Undo: Outliner?!" ); + mpOutliner = pOutliner; +} + +OutlinerUndoChangeParaFlags::OutlinerUndoChangeParaFlags( Outliner* pOutliner, sal_uInt16 nPara, sal_uInt16 nOldFlags, sal_uInt16 nNewFlags ) +: OutlinerUndoBase( OLUNDO_DEPTH, pOutliner ) +{ + mnPara = nPara; + mnOldFlags = nOldFlags; + mnNewFlags = nNewFlags; +} + +void OutlinerUndoChangeParaFlags::Undo() +{ + ImplChangeFlags( mnOldFlags ); +} + +void OutlinerUndoChangeParaFlags::Redo() +{ + ImplChangeFlags( mnNewFlags ); +} + +void OutlinerUndoChangeParaFlags::ImplChangeFlags( sal_uInt16 nFlags ) +{ + Outliner* pOutliner = GetOutliner(); + Paragraph* pPara = pOutliner->GetParagraph( mnPara ); + if( pPara ) + { + pOutliner->nDepthChangedHdlPrevDepth = pPara->GetDepth(); + pOutliner->mnDepthChangeHdlPrevFlags = pPara->nFlags; + pOutliner->pHdlParagraph = pPara; + + pPara->nFlags = nFlags; + pOutliner->DepthChangedHdl(); + } +} + +OutlinerUndoChangeParaNumberingRestart::OutlinerUndoChangeParaNumberingRestart( Outliner* pOutliner, sal_uInt16 nPara, + sal_Int16 nOldNumberingStartValue, sal_Int16 nNewNumberingStartValue, + sal_Bool bOldParaIsNumberingRestart, sal_Bool bNewParaIsNumberingRestart ) +: OutlinerUndoBase( OLUNDO_DEPTH, pOutliner ) +{ + mnPara = nPara; + + maUndoData.mnNumberingStartValue = nOldNumberingStartValue; + maUndoData.mbParaIsNumberingRestart = bOldParaIsNumberingRestart; + maRedoData.mnNumberingStartValue = nNewNumberingStartValue; + maRedoData.mbParaIsNumberingRestart = bNewParaIsNumberingRestart; +} + +void OutlinerUndoChangeParaNumberingRestart::Undo() +{ + ImplApplyData( maUndoData ); +} + +void OutlinerUndoChangeParaNumberingRestart::Redo() +{ + ImplApplyData( maRedoData ); +} + +void OutlinerUndoChangeParaNumberingRestart::ImplApplyData( const ParaRestartData& rData ) +{ + Outliner* pOutliner = GetOutliner(); + pOutliner->SetNumberingStartValue( mnPara, rData.mnNumberingStartValue ); + pOutliner->SetParaIsNumberingRestart( mnPara, rData.mbParaIsNumberingRestart ); +} + +OutlinerUndoChangeDepth::OutlinerUndoChangeDepth( Outliner* pOutliner, USHORT nPara, sal_Int16 nOldDepth, sal_Int16 nNewDepth ) + : OutlinerUndoBase( OLUNDO_DEPTH, pOutliner ) +{ + mnPara = nPara; + mnOldDepth = nOldDepth; + mnNewDepth = nNewDepth; +} + +void OutlinerUndoChangeDepth::Undo() +{ + GetOutliner()->ImplInitDepth( mnPara, mnOldDepth, FALSE ); +} + +void OutlinerUndoChangeDepth::Redo() +{ + GetOutliner()->ImplInitDepth( mnPara, mnNewDepth, FALSE ); +} + +void OutlinerUndoChangeDepth::Repeat() +{ + DBG_ERROR( "Repeat not implemented!" ); +} + + +OutlinerUndoCheckPara::OutlinerUndoCheckPara( Outliner* pOutliner, USHORT nPara ) + : OutlinerUndoBase( OLUNDO_DEPTH, pOutliner ) +{ + mnPara = nPara; +} + +void OutlinerUndoCheckPara::Undo() +{ + Paragraph* pPara = GetOutliner()->GetParagraph( mnPara ); + pPara->Invalidate(); + GetOutliner()->ImplCalcBulletText( mnPara, FALSE, FALSE ); +} + +void OutlinerUndoCheckPara::Redo() +{ + Paragraph* pPara = GetOutliner()->GetParagraph( mnPara ); + pPara->Invalidate(); + GetOutliner()->ImplCalcBulletText( mnPara, FALSE, FALSE ); +} + +void OutlinerUndoCheckPara::Repeat() +{ + DBG_ERROR( "Repeat not implemented!" ); +} + +DBG_NAME(OLUndoExpand); + +OLUndoExpand::OLUndoExpand(Outliner* pOut, USHORT _nId ) + : EditUndo( _nId, 0 ) +{ + DBG_CTOR(OLUndoExpand,0); + DBG_ASSERT(pOut,"Undo:No Outliner"); + pOutliner = pOut; + nCount = 0; + pParas = 0; +} + + +OLUndoExpand::~OLUndoExpand() +{ + DBG_DTOR(OLUndoExpand,0); + delete pParas; +} + + +void OLUndoExpand::Restore( BOOL bUndo ) +{ + DBG_CHKTHIS(OLUndoExpand,0); + DBG_ASSERT(pOutliner,"Undo:No Outliner"); + DBG_ASSERT(pOutliner->pEditEngine,"Outliner already deleted"); + Paragraph* pPara; + + BOOL bExpand = FALSE; + USHORT _nId = GetId(); + if((_nId == OLUNDO_EXPAND && !bUndo) || (_nId == OLUNDO_COLLAPSE && bUndo)) + bExpand = TRUE; + if( !pParas ) + { + pPara = pOutliner->GetParagraph( (ULONG)nCount ); + if( bExpand ) + pOutliner->Expand( pPara ); + else + pOutliner->Collapse( pPara ); + } + else + { + for( USHORT nIdx = 0; nIdx < nCount; nIdx++ ) + { + pPara = pOutliner->GetParagraph( (ULONG)(pParas[nIdx]) ); + if( bExpand ) + pOutliner->Expand( pPara ); + else + pOutliner->Collapse( pPara ); + } + } +} + + +void OLUndoExpand::Undo() +{ + DBG_CHKTHIS(OLUndoExpand,0); + Restore( TRUE ); +} + + +void OLUndoExpand::Redo() +{ + DBG_CHKTHIS(OLUndoExpand,0); + Restore( FALSE ); +} + + +void OLUndoExpand::Repeat() +{ + DBG_CHKTHIS(OLUndoExpand,0); + DBG_ERROR("Not implemented"); +} diff --git a/editeng/source/outliner/outlundo.hxx b/editeng/source/outliner/outlundo.hxx new file mode 100644 index 000000000000..163e4e62fd65 --- /dev/null +++ b/editeng/source/outliner/outlundo.hxx @@ -0,0 +1,140 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _OUTLUNDO_HXX +#define _OUTLUNDO_HXX + +#include <editeng/outliner.hxx> +#include <editeng/editdata.hxx> +#include <editeng/editund2.hxx> + +class OutlinerUndoBase : public EditUndo +{ +private: + Outliner* mpOutliner; + +public: + OutlinerUndoBase( USHORT nId, Outliner* pOutliner ); + + Outliner* GetOutliner() const { return mpOutliner; } +}; + +class OutlinerUndoChangeParaFlags : public OutlinerUndoBase +{ +private: + sal_uInt16 mnPara; + sal_uInt16 mnOldFlags; + sal_uInt16 mnNewFlags; + + void ImplChangeFlags( sal_uInt16 nFlags ); + +public: + OutlinerUndoChangeParaFlags( Outliner* pOutliner, sal_uInt16 nPara, sal_uInt16 nOldDepth, sal_uInt16 nNewDepth ); + + virtual void Undo(); + virtual void Redo(); +}; + +class OutlinerUndoChangeParaNumberingRestart : public OutlinerUndoBase +{ +private: + sal_uInt16 mnPara; + + struct ParaRestartData + { + sal_Int16 mnNumberingStartValue; + sal_Bool mbParaIsNumberingRestart; + }; + + ParaRestartData maUndoData; + ParaRestartData maRedoData; + + void ImplApplyData( const ParaRestartData& rData ); +public: + OutlinerUndoChangeParaNumberingRestart( Outliner* pOutliner, sal_uInt16 nPara, + sal_Int16 nOldNumberingStartValue, sal_Int16 mnNewNumberingStartValue, + sal_Bool nOldbParaIsNumberingRestart, sal_Bool nbNewParaIsNumberingRestart ); + + virtual void Undo(); + virtual void Redo(); +}; + +class OutlinerUndoChangeDepth : public OutlinerUndoBase +{ + using SfxUndoAction::Repeat; +private: + USHORT mnPara; + sal_Int16 mnOldDepth; + sal_Int16 mnNewDepth; + +public: + OutlinerUndoChangeDepth( Outliner* pOutliner, USHORT nPara, sal_Int16 nOldDepth, sal_Int16 nNewDepth ); + + virtual void Undo(); + virtual void Redo(); + virtual void Repeat(); +}; + +// Hilfs-Undo: Wenn es fuer eine Aktion keine OutlinerUndoAction gibst, weil +// die EditEngine das handelt, aber z.B. noch das Bullet neu berechnet werden muss. + +class OutlinerUndoCheckPara : public OutlinerUndoBase +{ + using SfxUndoAction::Repeat; +private: + USHORT mnPara; + +public: + OutlinerUndoCheckPara( Outliner* pOutliner, USHORT nPara ); + + virtual void Undo(); + virtual void Redo(); + virtual void Repeat(); +}; + + + +// ------------------------------------- + + +class OLUndoExpand : public EditUndo +{ + using SfxUndoAction::Repeat; + void Restore( BOOL bUndo ); +public: + OLUndoExpand( Outliner* pOut, USHORT nId ); + ~OLUndoExpand(); + virtual void Undo(); + virtual void Redo(); + virtual void Repeat(); + + USHORT* pParas; // 0 == nCount enthaelt Absatznummer + Outliner* pOutliner; + USHORT nCount; +}; + +#endif diff --git a/editeng/source/outliner/outlvw.cxx b/editeng/source/outliner/outlvw.cxx new file mode 100755 index 000000000000..e2a1fabea0ba --- /dev/null +++ b/editeng/source/outliner/outlvw.cxx @@ -0,0 +1,1734 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove + +#include "precompiled_editeng.hxx" + +#include <com/sun/star/i18n/WordType.hpp> + +#include <svl/intitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/editdata.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fhgtitem.hxx> + +#include <svl/style.hxx> +#include <i18npool/mslangid.hxx> + +#define _OUTLINER_CXX +#include <editeng/outliner.hxx> +#include <outleeng.hxx> +#include <paralist.hxx> +#include <outlundo.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/flditem.hxx> +#include <editeng/flditem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/numitem.hxx> +#include <vcl/window.hxx> +#include <svl/itemset.hxx> +#include <editeng/editstat.hxx> + + +// Breite der Randzonen innerhalb derer beim D&D gescrollt wird +#define OL_SCROLL_LRBORDERWIDTHPIX 10 +#define OL_SCROLL_TBBORDERWIDTHPIX 10 + +// Wert, um den Fensterinhalt beim D&D gescrollt wird +#define OL_SCROLL_HOROFFSET 20 /* in % von VisibleSize.Width */ +#define OL_SCROLL_VEROFFSET 20 /* in % von VisibleSize.Height */ + +using namespace ::com::sun::star; + +DBG_NAME(OutlinerView) + + +OutlinerView::OutlinerView( Outliner* pOut, Window* pWin ) +{ + DBG_CTOR( OutlinerView, 0 ); + + pOwner = pOut; + bDDCursorVisible = FALSE; + bInDragMode = FALSE; + nDDScrollLRBorderWidthWin = 0; + nDDScrollTBBorderWidthWin = 0; + pHorTabArrDoc = 0; + + pEditView = new EditView( pOut->pEditEngine, pWin ); + pEditView->SetSelectionMode( EE_SELMODE_TXTONLY ); +} + +OutlinerView::~OutlinerView() +{ + DBG_DTOR(OutlinerView,0); + delete pEditView; +} + +void OutlinerView::Paint( const Rectangle& rRect ) +{ + DBG_CHKTHIS(OutlinerView,0); + + // beim ersten Paint/KeyInput/Drop wird aus einem leeren Outliner ein + // Outliner mit genau einem Absatz + if( pOwner->bFirstParaIsEmpty ) + pOwner->Insert( String() ); + + pEditView->Paint( rRect ); +} + +BOOL OutlinerView::PostKeyEvent( const KeyEvent& rKEvt ) +{ + DBG_CHKTHIS( OutlinerView, 0 ); + + // beim ersten Paint/KeyInput/Drop wird aus einem leeren Outliner ein + // Outliner mit genau einem Absatz + if( pOwner->bFirstParaIsEmpty ) + pOwner->Insert( String() ); + + + BOOL bKeyProcessed = FALSE; + ESelection aSel( pEditView->GetSelection() ); + BOOL bSelection = aSel.HasRange(); + KeyCode aKeyCode = rKEvt.GetKeyCode(); + KeyFuncType eFunc = aKeyCode.GetFunction(); + USHORT nCode = aKeyCode.GetCode(); + BOOL bReadOnly = IsReadOnly(); + + if( bSelection && ( nCode != KEY_TAB ) && EditEngine::DoesKeyChangeText( rKEvt ) ) + { + if ( ImpCalcSelectedPages( FALSE ) && !pOwner->ImpCanDeleteSelectedPages( this ) ) + return TRUE; + } + + if ( eFunc != KEYFUNC_DONTKNOW ) + { + switch ( eFunc ) + { + case KEYFUNC_CUT: + { + if ( !bReadOnly ) + { + Cut(); + bKeyProcessed = TRUE; + } + } + break; + case KEYFUNC_COPY: + { + Copy(); + bKeyProcessed = TRUE; + } + break; + case KEYFUNC_PASTE: + { + if ( !bReadOnly ) + { + PasteSpecial(); + bKeyProcessed = TRUE; + } + } + break; + case KEYFUNC_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: // wird dann evtl. unten bearbeitet. + eFunc = KEYFUNC_DONTKNOW; + } + } + if ( eFunc == KEYFUNC_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->ImplHasBullet( 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 ) + { + // Sonderbehandlung: Hartes Return am Ende eines Absatzes, + // der eingeklappte Unterabsaetze besitzt + Paragraph* pPara = pOwner->pParaList->GetParagraph( aSel.nEndPara ); + + if( !aKeyCode.IsShift() ) + { + // Nochmal ImpGetCursor ??? + if( !bSelection && + aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) ) + { + ULONG nChilds = pOwner->pParaList->GetChildCount(pPara); + if( nChilds && !pOwner->pParaList->HasVisibleChilds(pPara)) + { + pOwner->UndoActionStart( OLUNDO_INSERT ); + ULONG nTemp = aSel.nEndPara; + nTemp += nChilds; + nTemp++; // einfuegen ueber naechstem Non-Child + pOwner->Insert( String(),nTemp,pPara->GetDepth()); + // Cursor positionieren + ESelection aTmpSel((USHORT)nTemp,0,(USHORT)nTemp,0); + pEditView->SetSelection( aTmpSel ); + pEditView->ShowCursor( TRUE, TRUE ); + pOwner->UndoActionEnd( OLUNDO_INSERT ); + bKeyProcessed = TRUE; + } + } + } + if( !bKeyProcessed && !bSelection && + !aKeyCode.IsShift() && aKeyCode.IsMod1() && + ( aSel.nEndPos == pOwner->pEditEngine->GetTextLen(aSel.nEndPara) ) ) + { + pOwner->UndoActionStart( OLUNDO_INSERT ); + ULONG nTemp = aSel.nEndPara; + nTemp++; + pOwner->Insert( String(), nTemp, pPara->GetDepth()+1 ); + + // Cursor positionieren + ESelection aTmpSel((USHORT)nTemp,0,(USHORT)nTemp,0); + pEditView->SetSelection( aTmpSel ); + pEditView->ShowCursor( TRUE, TRUE ); + pOwner->UndoActionEnd( OLUNDO_INSERT ); + bKeyProcessed = TRUE; + } + } + } + break; + } + } + + return bKeyProcessed ? TRUE : pEditView->PostKeyEvent( rKEvt ); +} + + +ULONG OutlinerView::ImpCheckMousePos(const Point& rPosPix, MouseTarget& reTarget) +{ + DBG_CHKTHIS(OutlinerView,0); + ULONG nPara = EE_PARA_NOT_FOUND; + + Point aMousePosWin = pEditView->GetWindow()->PixelToLogic( rPosPix ); + if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + { + reTarget = MouseOutside; + } + else + { + reTarget = MouseText; + + Point aPaperPos( aMousePosWin ); + Rectangle aOutArea = pEditView->GetOutputArea(); + Rectangle aVisArea = pEditView->GetVisArea(); + aPaperPos.X() -= aOutArea.Left(); + aPaperPos.X() += aVisArea.Left(); + aPaperPos.Y() -= aOutArea.Top(); + aPaperPos.Y() += aVisArea.Top(); + + BOOL bBullet; + if ( pOwner->IsTextPos( aPaperPos, 0, &bBullet ) ) + { + Point aDocPos = pOwner->GetDocPos( aPaperPos ); + nPara = pOwner->pEditEngine->FindParagraph( aDocPos.Y() ); + + if ( bBullet ) + { + reTarget = MouseBullet; + } + else + { + // Check for hyperlink + const SvxFieldItem* pFieldItem = pEditView->GetField( aMousePosWin ); + if ( pFieldItem && pFieldItem->GetField() && pFieldItem->GetField()->ISA( SvxURLField ) ) + reTarget = MouseHypertext; + } + } + } + return nPara; +} + +BOOL __EXPORT OutlinerView::MouseMove( const MouseEvent& rMEvt ) +{ + DBG_CHKTHIS(OutlinerView,0); + + 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; + + Pointer aPointer = GetPointer( rMEvt.GetPosPixel() ); + pEditView->GetWindow()->SetPointer( aPointer ); + return pEditView->MouseMove( rMEvt ); +} + + +BOOL __EXPORT OutlinerView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + DBG_CHKTHIS(OutlinerView,0); + 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; + + Pointer aPointer = GetPointer( rMEvt.GetPosPixel() ); + pEditView->GetWindow()->SetPointer( aPointer ); + + MouseTarget eTarget; + ULONG nPara = ImpCheckMousePos( rMEvt.GetPosPixel(), eTarget ); + if ( eTarget == MouseBullet ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + BOOL bHasChilds = (pPara && pOwner->pParaList->HasChilds(pPara)); + if( rMEvt.GetClicks() == 1 ) + { + ULONG nEndPara = nPara; + if ( bHasChilds && pOwner->pParaList->HasVisibleChilds(pPara) ) + nEndPara += pOwner->pParaList->GetChildCount( pPara ); + // umgekehrt rum selektieren, damit EditEngine nicht scrollt + ESelection aSel((USHORT)nEndPara, 0xffff,(USHORT)nPara, 0 ); + pEditView->SetSelection( aSel ); + } + else if( rMEvt.GetClicks() == 2 && bHasChilds ) + ImpToggleExpand( pPara ); + + aDDStartPosPix = rMEvt.GetPosPixel(); + aDDStartPosRef=pEditView->GetWindow()->PixelToLogic( aDDStartPosPix,pOwner->GetRefMapMode()); + 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 == MouseText) && (rMEvt.GetClicks() == 2) ) + { + ESelection aSel( pEditView->GetSelection() ); + nPara = aSel.nStartPara; + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + if( (pPara && pOwner->pParaList->HasChilds(pPara)) && pPara->HasFlag(PARAFLAG_ISPAGE) ) + { + ImpToggleExpand( pPara ); + } + } + return pEditView->MouseButtonDown( rMEvt ); +} + + +BOOL __EXPORT OutlinerView::MouseButtonUp( const MouseEvent& rMEvt ) +{ + DBG_CHKTHIS(OutlinerView,0); + 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; + + Pointer aPointer = GetPointer( rMEvt.GetPosPixel() ); + pEditView->GetWindow()->SetPointer( aPointer ); + + return pEditView->MouseButtonUp( rMEvt ); +} + +void OutlinerView::ImpHideDDCursor() +{ + DBG_CHKTHIS(OutlinerView,0); + if ( bDDCursorVisible ) + { + bDDCursorVisible = FALSE; + ImpPaintDDCursor(); + } +} + +void OutlinerView::ImpShowDDCursor() +{ + DBG_CHKTHIS(OutlinerView,0); + if ( !bDDCursorVisible ) + { + bDDCursorVisible = TRUE; + ImpPaintDDCursor(); + } +} + +void OutlinerView::ImpPaintDDCursor() +{ + DBG_CHKTHIS(OutlinerView,0); + + Window* pWindow = pEditView->GetWindow(); + RasterOp eOldOp = pWindow->GetRasterOp(); + pWindow->SetRasterOp( ROP_INVERT ); + + const Color& rOldLineColor = pWindow->GetLineColor(); + pWindow->SetLineColor( Color( COL_BLACK ) ); + + Point aStartPointWin, aEndPointWin; + Rectangle aOutputArWin = pEditView->GetOutputArea(); + Rectangle aVisAreaRef = pEditView->GetVisArea(); + + if( bDDChangingDepth ) + { + aStartPointWin.X() = pHorTabArrDoc[ nDDCurDepth ]; + aStartPointWin.X() += aOutputArWin.Left(); + aStartPointWin.Y() = aOutputArWin.Top(); + aEndPointWin.X() = aStartPointWin.X(); + aEndPointWin.Y() = aOutputArWin.Bottom(); + } + else + { + ULONG nPara = nDDCurPara; + if ( nDDCurPara == LIST_APPEND ) + { + Paragraph* pTemp = pOwner->pParaList->LastVisible(); + nPara = pOwner->pParaList->GetAbsPos( pTemp ); + } + aStartPointWin = pEditView->GetWindowPosTopLeft((USHORT) nPara ); + if ( nDDCurPara == LIST_APPEND ) + { + long nHeight = pOwner->pEditEngine->GetTextHeight((USHORT)nPara ); + aStartPointWin.Y() += nHeight; + } + aStartPointWin.X() = aOutputArWin.Left(); + aEndPointWin.Y() = aStartPointWin.Y(); + aEndPointWin.X() = aOutputArWin.Right(); + } + + pWindow->DrawLine( aStartPointWin, aEndPointWin ); + pWindow->SetLineColor( rOldLineColor ); + pWindow->SetRasterOp( eOldOp ); +} + +// Berechnet, ueber welchem Absatz eingefuegt werden muss + +ULONG OutlinerView::ImpGetInsertionPara( const Point& rPosPixel ) +{ + DBG_CHKTHIS(OutlinerView,0); + ULONG nCurPara = pEditView->GetParagraph( rPosPixel ); + ParagraphList* pParaList = pOwner->pParaList; + + if ( nCurPara == EE_PARA_NOT_FOUND ) + nCurPara = LIST_APPEND; + else + { + Point aPosWin = pEditView->GetWindow()->PixelToLogic( rPosPixel ); + Point aParaPosWin = pEditView->GetWindowPosTopLeft((USHORT)nCurPara); + long nHeightRef = pOwner->pEditEngine->GetTextHeight((USHORT)nCurPara); + long nParaYOffs = aPosWin.Y() - aParaPosWin.Y(); + + if ( nParaYOffs > nHeightRef / 2 ) + { + Paragraph* p = pParaList->GetParagraph( nCurPara ); + p = pParaList->NextVisible( p ); + nCurPara = p ? pParaList->GetAbsPos( p ) : LIST_APPEND; + } + } + return nCurPara; +} + + +void OutlinerView::ImpToggleExpand( Paragraph* pPara ) +{ + DBG_CHKTHIS(OutlinerView,0); + + USHORT nPara = (USHORT) pOwner->pParaList->GetAbsPos( pPara ); + pEditView->SetSelection( ESelection( nPara, 0, nPara, 0 ) ); + ImplExpandOrCollaps( nPara, nPara, !pOwner->pParaList->HasVisibleChilds( pPara ) ); + pEditView->ShowCursor(); +} + + +void OutlinerView::SetOutliner( Outliner* pOutliner ) +{ + DBG_CHKTHIS(OutlinerView,0); + pOwner = pOutliner; + pEditView->SetEditEngine( pOutliner->pEditEngine ); +} + + + +ULONG OutlinerView::Select( Paragraph* pParagraph, BOOL bSelect, + BOOL bWithChilds ) +{ + DBG_CHKTHIS(OutlinerView,0); + + ULONG nPara = pOwner->pParaList->GetAbsPos( pParagraph ); + USHORT nEnd = 0; + if ( bSelect ) + nEnd = 0xffff; + + ULONG nChildCount = 0; + if ( bWithChilds ) + nChildCount = pOwner->pParaList->GetChildCount( pParagraph ); + + ESelection aSel( (USHORT)nPara, 0,(USHORT)(nPara+nChildCount), nEnd ); + pEditView->SetSelection( aSel ); + return nChildCount+1; +} + + +void OutlinerView::SetAttribs( const SfxItemSet& rAttrs ) +{ + DBG_CHKTHIS(OutlinerView,0); + + 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 ); + + // Bullet-Texte aktualisieren + for( USHORT nPara= aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + pOwner->ImplCheckNumBulletItem( nPara ); + pOwner->ImplCalcBulletText( nPara, FALSE, FALSE ); + + if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) + pOwner->InsertUndo( new OutlinerUndoCheckPara( pOwner, nPara ) ); + } + + if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) + pOwner->UndoActionEnd( OLUNDO_ATTR ); + + pEditView->SetEditEngineUpdateMode( bUpdate ); +} + +ParaRange OutlinerView::ImpGetSelectedParagraphs( BOOL bIncludeHiddenChilds ) +{ + DBG_CHKTHIS( OutlinerView, 0 ); + + ESelection aSel = pEditView->GetSelection(); + ParaRange aParas( aSel.nStartPara, aSel.nEndPara ); + aParas.Adjust(); + + // unsichtbare Childs des letzten Parents in Selektion mit aufnehmen + if ( bIncludeHiddenChilds ) + { + Paragraph* pLast = pOwner->pParaList->GetParagraph( aParas.nEndPara ); + if ( pOwner->pParaList->HasHiddenChilds( pLast ) ) + aParas.nEndPara = + sal::static_int_cast< USHORT >( + aParas.nEndPara + + pOwner->pParaList->GetChildCount( pLast ) ); + } + return aParas; +} + +// MT: Name sollte mal geaendert werden! +void OutlinerView::AdjustDepth( short nDX ) +{ + Indent( nDX ); +} + +void OutlinerView::Indent( short nDiff ) +{ + DBG_CHKTHIS( OutlinerView, 0 ); + + if( !nDiff || ( ( nDiff > 0 ) && ImpCalcSelectedPages( TRUE ) && !pOwner->ImpCanIndentSelectedPages( this ) ) ) + return; + + const bool bOutlinerView = pOwner->pEditEngine->GetControlWord() & EE_CNTRL_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; // Optimierung: Nicht unnoetig viele Absatze neu berechnen + + ParaRange aSel = ImpGetSelectedParagraphs( TRUE ); + for ( USHORT 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)) ) + { + // App benachrichtigen + pOwner->nDepthChangedHdlPrevDepth = (sal_Int16)nOldDepth; + pOwner->mnDepthChangeHdlPrevFlags = pPara->nFlags; + pOwner->pHdlParagraph = pPara; + + if( bPage ) + pPara->RemoveFlag( PARAFLAG_ISPAGE ); + else + pPara->SetFlag( PARAFLAG_ISPAGE ); + + pOwner->DepthChangedHdl(); + pOwner->pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); + + if( bUndo ) + pOwner->InsertUndo( new OutlinerUndoChangeParaFlags( pOwner, nPara, pOwner->mnDepthChangeHdlPrevFlags, 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 < pOwner->nMinDepth ) + nNewDepth = pOwner->nMinDepth; + 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 )) + { + // Sonderfall: Der Vorgaenger eines eingerueckten Absatzes ist + // unsichtbar und steht jetzt auf der gleichen Ebene wie der + // sichtbare Absatz. In diesem Fall wird der naechste sichtbare + // Absatz gesucht und aufgeplustert. +#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 ) ) + { + // Vorgaenger ist eingeklappt und steht auf gleicher Ebene + // => naechsten sichtbaren Absatz suchen und expandieren + pPrev = pOwner->pParaList->GetParent( pPrev ); + while( !pPrev->IsVisible() ) + pPrev = pOwner->pParaList->GetParent( pPrev ); + + pOwner->Expand( pPrev ); + pOwner->InvalidateBullet( pPrev, pOwner->pParaList->GetAbsPos( pPrev ) ); + } + } + + pOwner->nDepthChangedHdlPrevDepth = (sal_Int16)nOldDepth; + pOwner->mnDepthChangeHdlPrevFlags = pPara->nFlags; + pOwner->pHdlParagraph = pPara; + + pOwner->ImplInitDepth( nPara, nNewDepth, TRUE, FALSE ); + pOwner->ImplCalcBulletText( nPara, FALSE, FALSE ); + + if ( pOwner->ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) + pOwner->ImplSetLevelDependendStyleSheet( nPara ); + + // App benachrichtigen + pOwner->DepthChangedHdl(); + } + else + { + // Needs at least a repaint... + pOwner->pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) ); + } + } + + // MT 19.08.99: War mal fuer Optimierung (outliner.cxx#1.193), + // hat aber zu zuviel Wartungsaufwand / doppelten Funktionen gefuehrt + // und zu wenig gebracht: + // pOwner->ImpSetBulletTextsFrom( aSel.nStartPara+1, nMinDepth ); + // Wird jetzt direkt in Schleife mit ImplCalcBulletText() erledigt. + // Jetzt fehlen nur noch die folgenden Ansaetze, die davon betroffen sind. + USHORT nParas = (USHORT)pOwner->pParaList->GetParagraphCount(); + for ( USHORT 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( OLUNDO_DEPTH ); +} + +BOOL OutlinerView::AdjustHeight( long nDY ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->MoveParagraphs( nDY ); + return TRUE; // remove return value... +} + +void OutlinerView::AdjustDepth( Paragraph* pPara, short nDX, BOOL bWithChilds) +{ + DBG_CHKTHIS(OutlinerView,0); + ULONG nStartPara = pOwner->pParaList->GetAbsPos( pPara ); + ULONG nEndPara = nStartPara; + if ( bWithChilds ) + nEndPara += pOwner->pParaList->GetChildCount( pPara ); + ESelection aSel((USHORT)nStartPara, 0,(USHORT)nEndPara, 0xffff ); + pEditView->SetSelection( aSel ); + AdjustDepth( nDX ); +} + +void OutlinerView::AdjustHeight( Paragraph* pPara, long nDY, BOOL bWithChilds ) +{ + DBG_CHKTHIS(OutlinerView,0); + ULONG nStartPara = pOwner->pParaList->GetAbsPos( pPara ); + ULONG nEndPara = nStartPara; + if ( bWithChilds ) + nEndPara += pOwner->pParaList->GetChildCount( pPara ); + ESelection aSel( (USHORT)nStartPara, 0, (USHORT)nEndPara, 0xffff ); + pEditView->SetSelection( aSel ); + AdjustHeight( nDY ); +} + + +Rectangle OutlinerView::GetVisArea() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetVisArea(); +} + + +Point OutlinerView::ImpGetDocPos( const Point& rPosPixel ) +{ + DBG_CHKTHIS(OutlinerView,0); + Rectangle aOutArWin = GetOutputArea(); + // Position in der OutputArea berechnen + Point aCurPosDoc( rPosPixel ); + aCurPosDoc = pEditView->GetWindow()->PixelToLogic( aCurPosDoc ); + aCurPosDoc -= aOutArWin.TopLeft(); + aCurPosDoc += pEditView->GetVisArea().TopLeft(); + return aCurPosDoc; +} + +// MT 05/00: Wofuer dies ImpXXXScroll, sollte das nicht die EditEngine machen??? + +void OutlinerView::ImpDragScroll( const Point& rPosPix ) +{ + DBG_CHKTHIS(OutlinerView,0); + Point aPosWin = pEditView->GetWindow()->PixelToLogic( rPosPix ); + Rectangle aOutputArWin = pEditView->GetOutputArea(); + if ( aPosWin.X() <= aOutputArWin.Left() + nDDScrollLRBorderWidthWin) + ImpScrollLeft(); + else if( aPosWin.X() >= aOutputArWin.Right()- nDDScrollLRBorderWidthWin) + ImpScrollRight(); + else if( aPosWin.Y() <= aOutputArWin.Top() + nDDScrollTBBorderWidthWin) + ImpScrollUp(); + else if(aPosWin.Y() >= aOutputArWin.Bottom() - nDDScrollTBBorderWidthWin) + ImpScrollDown(); +} + + +void OutlinerView::ImpScrollLeft() +{ + DBG_CHKTHIS(OutlinerView,0); + Rectangle aVisArea( pEditView->GetVisArea() ); + long nMaxScrollOffs = aVisArea.Left(); + if ( !nMaxScrollOffs ) + return; + long nScrollOffsRef = (aVisArea.GetWidth() * OL_SCROLL_HOROFFSET) / 100; + if ( !nScrollOffsRef ) + nScrollOffsRef = 1; + if ( nScrollOffsRef > nMaxScrollOffs ) + nScrollOffsRef = nMaxScrollOffs; + + ImpHideDDCursor(); + Scroll( -nScrollOffsRef, 0 ); + + EditStatus aScrollStat; + aScrollStat.GetStatusWord() = EE_STAT_HSCROLL; + pOwner->pEditEngine->GetStatusEventHdl().Call( &aScrollStat ); +} + + +void OutlinerView::ImpScrollRight() +{ + DBG_CHKTHIS(OutlinerView,0); + Rectangle aVisArea( pEditView->GetVisArea() ); + long nMaxScrollOffs = pOwner->pEditEngine->GetPaperSize().Width() - + aVisArea.Right(); + if ( !nMaxScrollOffs ) + return; + long nScrollOffsRef = (aVisArea.GetWidth() * OL_SCROLL_HOROFFSET) / 100; + if ( !nScrollOffsRef ) + nScrollOffsRef = 1; + if ( nScrollOffsRef > nMaxScrollOffs ) + nScrollOffsRef = nMaxScrollOffs; + + ImpHideDDCursor(); + Scroll( nScrollOffsRef, 0 ); + + EditStatus aScrollStat; + aScrollStat.GetStatusWord() = EE_STAT_HSCROLL; + pOwner->pEditEngine->GetStatusEventHdl().Call( &aScrollStat ); +} + + +void OutlinerView::ImpScrollDown() +{ + DBG_CHKTHIS(OutlinerView,0); + Rectangle aVisArea( pEditView->GetVisArea() ); + Size aDocSize( 0, (long)pOwner->pEditEngine->GetTextHeight() ); + + long nMaxScrollOffs = aDocSize.Height(); + nMaxScrollOffs -= aVisArea.Top(); + nMaxScrollOffs -= aVisArea.GetHeight(); + if ( !nMaxScrollOffs ) + return; + + long nScrollOffsRef = (aVisArea.GetHeight() * OL_SCROLL_VEROFFSET) / 100; + + if ( nScrollOffsRef > nMaxScrollOffs ) + nScrollOffsRef = nMaxScrollOffs; + if ( !nScrollOffsRef ) + nScrollOffsRef = 1; + + ImpHideDDCursor(); + Scroll( 0, -nScrollOffsRef ); + + EditStatus aScrollStat; + aScrollStat.GetStatusWord() = EE_STAT_VSCROLL; + pOwner->pEditEngine->GetStatusEventHdl().Call( &aScrollStat ); +} + + +void OutlinerView::ImpScrollUp() +{ + DBG_CHKTHIS(OutlinerView,0); + Rectangle aVisArea( pEditView->GetVisArea() ); + long nMaxScrollOffs = aVisArea.Top(); + if ( !nMaxScrollOffs ) + return; + long nScrollOffsRef = (aVisArea.GetHeight() * OL_SCROLL_VEROFFSET) / 100; + + + if ( nScrollOffsRef > nMaxScrollOffs ) + nScrollOffsRef = nMaxScrollOffs; + if ( !nScrollOffsRef ) + nScrollOffsRef = 1; + + ImpHideDDCursor(); + Scroll( 0, nScrollOffsRef ); + + EditStatus aScrollStat; + aScrollStat.GetStatusWord() = EE_STAT_VSCROLL; + pOwner->pEditEngine->GetStatusEventHdl().Call( &aScrollStat ); +} + + +void OutlinerView::Expand() +{ + DBG_CHKTHIS( OutlinerView, 0 ); + ParaRange aParas = ImpGetSelectedParagraphs( FALSE ); + ImplExpandOrCollaps( aParas.nStartPara, aParas.nEndPara, TRUE ); +} + + +void OutlinerView::Collapse() +{ + DBG_CHKTHIS( OutlinerView, 0 ); + ParaRange aParas = ImpGetSelectedParagraphs( FALSE ); + ImplExpandOrCollaps( aParas.nStartPara, aParas.nEndPara, FALSE ); +} + + +void OutlinerView::ExpandAll() +{ + DBG_CHKTHIS( OutlinerView, 0 ); + ImplExpandOrCollaps( 0, (USHORT)(pOwner->pParaList->GetParagraphCount()-1), TRUE ); +} + + +void OutlinerView::CollapseAll() +{ + DBG_CHKTHIS(OutlinerView,0); + ImplExpandOrCollaps( 0, (USHORT)(pOwner->pParaList->GetParagraphCount()-1), FALSE ); +} + +void OutlinerView::ImplExpandOrCollaps( USHORT nStartPara, USHORT nEndPara, BOOL bExpand ) +{ + DBG_CHKTHIS( OutlinerView, 0 ); + + BOOL bUpdate = pOwner->GetUpdateMode(); + pOwner->SetUpdateMode( FALSE ); + + BOOL bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled(); + if( bUndo ) + pOwner->UndoActionStart( bExpand ? OLUNDO_EXPAND : OLUNDO_COLLAPSE ); + + for ( USHORT nPara = nStartPara; nPara <= nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + BOOL bDone = bExpand ? pOwner->Expand( pPara ) : pOwner->Collapse( pPara ); + if( bDone ) + { + // Der Strich unter dem Absatz muss verschwinden... + pOwner->pEditEngine->QuickMarkToBeRepainted( nPara ); + } + } + + if( bUndo ) + pOwner->UndoActionEnd( bExpand ? OLUNDO_EXPAND : OLUNDO_COLLAPSE ); + + if ( bUpdate ) + { + pOwner->SetUpdateMode( TRUE ); + pEditView->ShowCursor(); + } +} + + +void OutlinerView::Expand( Paragraph* pPara) +{ + DBG_CHKTHIS(OutlinerView,0); + pOwner->Expand( pPara ); +} + + +void OutlinerView::Collapse( Paragraph* pPara) +{ + DBG_CHKTHIS(OutlinerView,0); + pOwner->Collapse( pPara ); +} + +void OutlinerView::InsertText( const OutlinerParaObject& rParaObj ) +{ + // MT: Wie Paste, nur EditView::Insert, statt EditView::Paste. + // Eigentlich nicht ganz richtig, das evtl. Einrueckungen + // korrigiert werden muessen, aber das kommt spaeter durch ein + // allgemeingueltiges Import. + // Dann wird im Inserted gleich ermittelt, was f�r eine Einrueckebene + // Moegliche Struktur: + // pImportInfo mit DestPara, DestPos, nFormat, pParaObj... + // Evtl. Problematisch: + // EditEngine, RTF => Absplittung des Bereichs, spaeter + // zusammenfuehrung + + DBG_CHKTHIS(OutlinerView,0); + + if ( ImpCalcSelectedPages( FALSE ) && !pOwner->ImpCanDeleteSelectedPages( this ) ) + return; + + pOwner->UndoActionStart( OLUNDO_INSERT ); + + pOwner->pEditEngine->SetUpdateMode( FALSE ); + ULONG nStart, nParaCount; + nParaCount = pOwner->pEditEngine->GetParagraphCount(); + USHORT nSize = ImpInitPaste( nStart ); + pEditView->InsertText( rParaObj.GetTextObject() ); + ImpPasted( nStart, nParaCount, nSize); + pEditView->SetEditEngineUpdateMode( TRUE ); + + pOwner->UndoActionEnd( OLUNDO_INSERT ); + + pEditView->ShowCursor( TRUE, TRUE ); +} + + + +void OutlinerView::Cut() +{ + DBG_CHKTHIS(OutlinerView,0); + if ( !ImpCalcSelectedPages( FALSE ) || pOwner->ImpCanDeleteSelectedPages( this ) ) + pEditView->Cut(); +} + +void OutlinerView::Paste() +{ + DBG_CHKTHIS(OutlinerView,0); + PasteSpecial(); // HACK(SD ruft nicht PasteSpecial auf) +} + +void OutlinerView::PasteSpecial() +{ + DBG_CHKTHIS(OutlinerView,0); + if ( !ImpCalcSelectedPages( FALSE ) || pOwner->ImpCanDeleteSelectedPages( this ) ) + { + pOwner->UndoActionStart( OLUNDO_INSERT ); + + pOwner->pEditEngine->SetUpdateMode( FALSE ); + pOwner->bPasting = TRUE; + pEditView->PasteSpecial(); + + if ( pOwner->ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) + { + const USHORT nParaCount = pOwner->pEditEngine->GetParagraphCount(); + + for( USHORT nPara = 0; nPara < nParaCount; nPara++ ) + pOwner->ImplSetLevelDependendStyleSheet( nPara ); + } + + pEditView->SetEditEngineUpdateMode( TRUE ); + pOwner->UndoActionEnd( OLUNDO_INSERT ); + pEditView->ShowCursor( TRUE, TRUE ); + } +} + +List* OutlinerView::CreateSelectionList() +{ + DBG_CHKTHIS( OutlinerView, 0 ); + + ParaRange aParas = ImpGetSelectedParagraphs( TRUE ); + List* pSelList = new List; + for ( USHORT nPara = aParas.nStartPara; nPara <= aParas.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + pSelList->Insert( pPara, LIST_APPEND ); + } + return pSelList; +} + +SfxStyleSheet* OutlinerView::GetStyleSheet() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetStyleSheet(); +} + +void OutlinerView::SetStyleSheet( SfxStyleSheet* pStyle ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetStyleSheet( pStyle ); + + ParaRange aSel = ImpGetSelectedParagraphs( TRUE ); + for( USHORT nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + pOwner->ImplCheckNumBulletItem( nPara ); + pOwner->ImplCalcBulletText( nPara, FALSE, FALSE ); + } +} + +Pointer OutlinerView::GetPointer( const Point& rPosPixel ) +{ + DBG_CHKTHIS(OutlinerView,0); + + MouseTarget eTarget; + ImpCheckMousePos( rPosPixel, eTarget ); + + PointerStyle ePointerStyle = POINTER_ARROW; + if ( eTarget == MouseText ) + { + ePointerStyle = GetOutliner()->IsVertical() ? POINTER_TEXT_VERTICAL : POINTER_TEXT; + } + else if ( eTarget == MouseHypertext ) + { + ePointerStyle = POINTER_REFHAND; + } + else if ( eTarget == MouseBullet ) + { + ePointerStyle = POINTER_MOVE; + } + + return Pointer( ePointerStyle ); +} + + +USHORT OutlinerView::ImpInitPaste( ULONG& rStart ) +{ + DBG_CHKTHIS(OutlinerView,0); + pOwner->bPasting = TRUE; + ESelection aSelection( pEditView->GetSelection() ); + aSelection.Adjust(); + rStart = aSelection.nStartPara; + USHORT nSize = aSelection.nEndPara - aSelection.nStartPara + 1; + return nSize; +} + + +void OutlinerView::ImpPasted( ULONG nStart, ULONG nPrevParaCount, USHORT nSize) +{ + DBG_CHKTHIS(OutlinerView,0); + pOwner->bPasting = FALSE; + ULONG nCurParaCount = (ULONG)pOwner->pEditEngine->GetParagraphCount(); + if( nCurParaCount < nPrevParaCount ) + nSize = sal::static_int_cast< USHORT >( + nSize - ( nPrevParaCount - nCurParaCount ) ); + else + nSize = sal::static_int_cast< USHORT >( + nSize + ( nCurParaCount - nPrevParaCount ) ); + pOwner->ImpTextPasted( nStart, nSize ); +} + + +void OutlinerView::Command( const CommandEvent& rCEvt ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->Command( rCEvt ); +} + + +void OutlinerView::SelectRange( ULONG nFirst, USHORT nCount ) +{ + DBG_CHKTHIS(OutlinerView,0); + ULONG nLast = nFirst+nCount; + nCount = (USHORT)pOwner->pParaList->GetParagraphCount(); + if( nLast <= nCount ) + nLast = nCount - 1; + ESelection aSel( (USHORT)nFirst, 0, (USHORT)nLast, 0xffff ); + pEditView->SetSelection( aSel ); +} + + +USHORT OutlinerView::ImpCalcSelectedPages( BOOL bIncludeFirstSelected ) +{ + DBG_CHKTHIS(OutlinerView,0); + + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + + USHORT nPages = 0; + USHORT nFirstPage = 0xFFFF; + USHORT nStartPara = aSel.nStartPara; + if ( !bIncludeFirstSelected ) + nStartPara++; // alle nach StartPara kommenden Absaetze werden geloescht + for ( USHORT nPara = nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + DBG_ASSERT(pPara, "ImpCalcSelectedPages: ungueltige Selection? "); + if( pPara->HasFlag(PARAFLAG_ISPAGE) ) + { + nPages++; + if( nFirstPage == 0xFFFF ) + nFirstPage = nPara; + } + } + + if( nPages ) + { + pOwner->nDepthChangedHdlPrevDepth = nPages; + pOwner->pHdlParagraph = 0; + 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 nDepth = -2; + + for ( USHORT nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + DBG_ASSERT(pPara, "OutlinerView::ToggleBullets(), illegal selection?"); + + if( pPara ) + { + if( nDepth == -2 ) + nDepth = (pOwner->GetDepth(nPara) == -1) ? 0 : -1; + + pOwner->SetDepth( pPara, nDepth ); + + if( nDepth == -1 ) + { + const SfxItemSet& rAttrs = pOwner->GetParaAttribs( nPara ); + if(rAttrs.GetItemState( EE_PARA_BULLETSTATE ) == SFX_ITEM_SET) + { + SfxItemSet aAttrs(rAttrs); + aAttrs.ClearItem( EE_PARA_BULLETSTATE ); + pOwner->SetParaAttribs( nPara, aAttrs ); + } + } + } + } + + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + USHORT nParaCount = (USHORT) (pOwner->pParaList->GetParagraphCount()); + // <-- + pOwner->ImplCheckParagraphs( aSel.nStartPara, nParaCount ); + pOwner->pEditEngine->QuickMarkInvalid( ESelection( aSel.nStartPara, 0, nParaCount, 0 ) ); + + pOwner->pEditEngine->SetUpdateMode( bUpdate ); + + pOwner->UndoActionEnd( OLUNDO_DEPTH ); +} + +void OutlinerView::EnableBullets() +{ + pOwner->UndoActionStart( OLUNDO_DEPTH ); + + ESelection aSel( pEditView->GetSelection() ); + aSel.Adjust(); + + const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); + pOwner->pEditEngine->SetUpdateMode( FALSE ); + + for ( USHORT nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + DBG_ASSERT(pPara, "OutlinerView::ToggleBullets(), illegal selection?"); + + if( pPara && (pOwner->GetDepth(nPara) == -1) ) + { + pOwner->SetDepth( pPara, 0 ); + } + } + + // --> OD 2009-03-10 #i100014# + // It is not a good idea to substract 1 from a count and cast the result + // to USHORT without check, if the count is 0. + USHORT nParaCount = (USHORT) (pOwner->pParaList->GetParagraphCount()); + // <-- + pOwner->ImplCheckParagraphs( aSel.nStartPara, nParaCount ); + pOwner->pEditEngine->QuickMarkInvalid( ESelection( aSel.nStartPara, 0, nParaCount, 0 ) ); + + pOwner->pEditEngine->SetUpdateMode( bUpdate ); + + pOwner->UndoActionEnd( OLUNDO_DEPTH ); +} + + +void OutlinerView::RemoveAttribsKeepLanguages( BOOL bRemoveParaAttribs ) +{ + RemoveAttribs( bRemoveParaAttribs, 0, TRUE /*keep language attribs*/ ); +} + +void OutlinerView::RemoveAttribs( BOOL bRemoveParaAttribs, USHORT nWhich, BOOL bKeepLanguages ) +{ + DBG_CHKTHIS(OutlinerView,0); + BOOL bUpdate = pOwner->GetUpdateMode(); + pOwner->SetUpdateMode( FALSE ); + pOwner->UndoActionStart( OLUNDO_ATTR ); + if (bKeepLanguages) + pEditView->RemoveAttribsKeepLanguages( bRemoveParaAttribs ); + else + pEditView->RemoveAttribs( bRemoveParaAttribs, nWhich ); + if ( bRemoveParaAttribs ) + { + // Ueber alle Absaetze, und Einrueckung und Level einstellen + ESelection aSel = pEditView->GetSelection(); + aSel.Adjust(); + for ( USHORT nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ ) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara ); + pOwner->ImplInitDepth( nPara, pPara->GetDepth(), FALSE, FALSE ); + } + } + pOwner->UndoActionEnd( OLUNDO_ATTR ); + pOwner->SetUpdateMode( bUpdate ); +} + + + +// ===================================================================== +// ====================== Einfache Durchreicher ======================= +// ====================================================================== + + +void OutlinerView::InsertText( const XubString& rNew, BOOL bSelect ) +{ + DBG_CHKTHIS(OutlinerView,0); + if( pOwner->bFirstParaIsEmpty ) + pOwner->Insert( String() ); + pEditView->InsertText( rNew, bSelect ); +} + +void OutlinerView::SetVisArea( const Rectangle& rRec ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetVisArea( rRec ); +} + + +void OutlinerView::SetSelection( const ESelection& rSel ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetSelection( rSel ); +} + +void OutlinerView::SetReadOnly( BOOL bReadOnly ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetReadOnly( bReadOnly ); +} + +BOOL OutlinerView::IsReadOnly() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->IsReadOnly(); +} + +BOOL OutlinerView::HasSelection() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->HasSelection(); +} + + +void OutlinerView::ShowCursor( BOOL bGotoCursor ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->ShowCursor( bGotoCursor ); +} + + +void OutlinerView::HideCursor() +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->HideCursor(); +} + + +void OutlinerView::SetWindow( Window* pWin ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetWindow( pWin ); +} + + +Window* OutlinerView::GetWindow() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetWindow(); +} + + +void OutlinerView::SetOutputArea( const Rectangle& rRect ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetOutputArea( rRect ); +} + + +Rectangle OutlinerView::GetOutputArea() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetOutputArea(); +} + + +XubString OutlinerView::GetSelected() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetSelected(); +} + + +void OutlinerView::RemoveCharAttribs( ULONG nPara, USHORT nWhich) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->RemoveCharAttribs( (USHORT)nPara, nWhich); +} + + +void OutlinerView::CompleteAutoCorrect() +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->CompleteAutoCorrect(); +} + + +EESpellState OutlinerView::StartSpeller( BOOL bMultiDoc ) +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->StartSpeller( bMultiDoc ); +} + + +EESpellState OutlinerView::StartThesaurus() +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->StartThesaurus(); +} + + +void OutlinerView::StartTextConversion( + LanguageType nSrcLang, LanguageType nDestLang, const Font *pDestFont, + INT32 nOptions, BOOL bIsInteractive, BOOL bMultipleDoc ) +{ + DBG_CHKTHIS(OutlinerView,0); + 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 + { + DBG_ERROR( "unexpected language" ); + } +} + + +USHORT OutlinerView::StartSearchAndReplace( const SvxSearchItem& rSearchItem ) +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->StartSearchAndReplace( rSearchItem ); +} + +void OutlinerView::TransliterateText( sal_Int32 nTransliterationMode ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->TransliterateText( nTransliterationMode ); +} + + + +ESelection OutlinerView::GetSelection() +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetSelection(); +} + + +void OutlinerView::Scroll( long nHorzScroll, long nVertScroll ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->Scroll( nHorzScroll, nVertScroll ); +} + + +void OutlinerView::SetControlWord( ULONG nWord ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetControlWord( nWord ); +} + + +ULONG OutlinerView::GetControlWord() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetControlWord(); +} + + +void OutlinerView::SetAnchorMode( EVAnchorMode eMode ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetAnchorMode( eMode ); +} + + +EVAnchorMode OutlinerView::GetAnchorMode() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetAnchorMode(); +} + + +void OutlinerView::Undo() +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->Undo(); +} + + +void OutlinerView::Redo() +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->Redo(); +} + + +void OutlinerView::EnablePaste( BOOL bEnable ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->EnablePaste( bEnable ); +} + + +void OutlinerView::Copy() +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->Copy(); +} + + +void OutlinerView::InsertField( const SvxFieldItem& rFld ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->InsertField( rFld ); +} + + +const SvxFieldItem* OutlinerView::GetFieldUnderMousePointer() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetFieldUnderMousePointer(); +} + + +const SvxFieldItem* OutlinerView::GetFieldUnderMousePointer( USHORT& nPara, USHORT& nPos ) const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetFieldUnderMousePointer( nPara, nPos ); +} + + +const SvxFieldItem* OutlinerView::GetFieldAtSelection() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetFieldAtSelection(); +} + +void OutlinerView::SetInvalidateMore( USHORT nPixel ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetInvalidateMore( nPixel ); +} + + +USHORT OutlinerView::GetInvalidateMore() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetInvalidateMore(); +} + + +BOOL OutlinerView::IsCursorAtWrongSpelledWord( BOOL bMarkIfWrong ) +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->IsCursorAtWrongSpelledWord( bMarkIfWrong ); +} + + +BOOL OutlinerView::IsWrongSpelledWordAtPos( const Point& rPosPixel, BOOL bMarkIfWrong ) +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->IsWrongSpelledWordAtPos( rPosPixel, bMarkIfWrong ); +} + + +void OutlinerView::SpellIgnoreWord() +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SpellIgnoreWord(); +} + + +void OutlinerView::ExecuteSpellPopup( const Point& rPosPixel, Link* pStartDlg ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->ExecuteSpellPopup( rPosPixel, pStartDlg ); +} + +ULONG OutlinerView::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, BOOL bSelect, SvKeyValueIterator* pHTTPHeaderAttrs ) +{ + DBG_CHKTHIS(OutlinerView,0); + USHORT nOldParaCount = pEditView->GetEditEngine()->GetParagraphCount(); + ESelection aOldSel = pEditView->GetSelection(); + aOldSel.Adjust(); + + ULONG nRet = pEditView->Read( rInput, rBaseURL, eFormat, bSelect, pHTTPHeaderAttrs ); + + // MT 08/00: Hier sollte eigentlich das gleiche wie in PasteSpecial passieren! + // Mal anpassen, wenn dieses ImplInitPaste und ImpPasted-Geraffel ueberarbeitet ist. + + long nParaDiff = pEditView->GetEditEngine()->GetParagraphCount() - nOldParaCount; + USHORT nChangesStart = aOldSel.nStartPara; + USHORT nChangesEnd = sal::static_int_cast< USHORT >(nChangesStart + nParaDiff + (aOldSel.nEndPara-aOldSel.nStartPara)); + + for ( USHORT n = nChangesStart; n <= nChangesEnd; n++ ) + { + if ( eFormat == EE_FORMAT_BIN ) + { + USHORT nDepth = 0; + const SfxItemSet& rAttrs = pOwner->GetParaAttribs( n ); + const SfxInt16Item& rLevel = (const SfxInt16Item&) rAttrs.Get( EE_PARA_OUTLLEVEL ); + nDepth = rLevel.GetValue(); + pOwner->ImplInitDepth( n, nDepth, FALSE ); + } + + if ( pOwner->ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) + pOwner->ImplSetLevelDependendStyleSheet( n ); + } + + if ( eFormat != EE_FORMAT_BIN ) + { + pOwner->ImpFilterIndents( nChangesStart, nChangesEnd ); + } + + return nRet; +} + +ULONG OutlinerView::Write( SvStream& rOutput, EETextFormat eFormat ) +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->Write( rOutput, eFormat ); +} + +void OutlinerView::SetBackgroundColor( const Color& rColor ) +{ + DBG_CHKTHIS(OutlinerView,0); + pEditView->SetBackgroundColor( rColor ); +} + + +Color OutlinerView::GetBackgroundColor() +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetBackgroundColor(); +} + +SfxItemSet OutlinerView::GetAttribs() +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetAttribs(); +} + +USHORT OutlinerView::GetSelectedScriptType() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetSelectedScriptType(); +} + +String OutlinerView::GetSurroundingText() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetSurroundingText(); +} + +Selection OutlinerView::GetSurroundingTextSelection() const +{ + DBG_CHKTHIS(OutlinerView,0); + return pEditView->GetSurroundingTextSelection(); +} + + +// ====================================================================== +// ===== some code for thesaurus sub menu within context menu +// ====================================================================== + +// 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 EDITENG_DLLPUBLIC GetStatusValueForThesaurusFromContext( + String &rStatusVal, + LanguageType &rLang, + const EditView &rEditView ) +{ + // get text and locale for thesaurus look up + String 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(); + LanguageType nLang = pEditEngine->GetLanguage( aTextSel.nStartPara, aTextSel.nStartPos ); + String aLangText( MsLangId::convertLanguageToIsoString( nLang ) ); + + // set word and locale to look up as status value + String aStatusVal( aText ); + aStatusVal.AppendAscii( "#" ); + aStatusVal += aLangText; + + rStatusVal = aStatusVal; + rLang = nLang; + + return aText.Len() > 0; +} + + +void EDITENG_DLLPUBLIC ReplaceTextWithSynonym( EditView &rEditView, const String &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( sal_True, sal_False ); +} + + diff --git a/editeng/source/outliner/paralist.cxx b/editeng/source/outliner/paralist.cxx new file mode 100644 index 000000000000..c46f973280dc --- /dev/null +++ b/editeng/source/outliner/paralist.cxx @@ -0,0 +1,287 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <paralist.hxx> +#include <editeng/outliner.hxx> // nur wegen Paragraph, muss geaendert werden! +#include <editeng/numdef.hxx> + +DBG_NAME(Paragraph) + +ParagraphData::ParagraphData() +: nDepth( -1 ) +, mnNumberingStartValue( -1 ) +, mbParaIsNumberingRestart( sal_False ) +{ +} + +ParagraphData::ParagraphData( const ParagraphData& r ) +: nDepth( r.nDepth ) +, mnNumberingStartValue( r.mnNumberingStartValue ) +, mbParaIsNumberingRestart( r.mbParaIsNumberingRestart ) +{ +} + +ParagraphData& ParagraphData::operator=( const ParagraphData& r) +{ + nDepth = r.nDepth; + mnNumberingStartValue = r.mnNumberingStartValue; + mbParaIsNumberingRestart = r.mbParaIsNumberingRestart; + return *this; +} + +bool ParagraphData::operator==(const ParagraphData& rCandidate) const +{ + return (nDepth == rCandidate.nDepth + && mnNumberingStartValue == rCandidate.mnNumberingStartValue + && mbParaIsNumberingRestart == rCandidate.mbParaIsNumberingRestart); +} + +Paragraph::Paragraph( sal_Int16 nDDepth ) +: aBulSize( -1, -1) +{ + DBG_CTOR( Paragraph, 0 ); + + DBG_ASSERT( ( nDDepth >= -1 ) && ( nDDepth < SVX_MAX_NUM ), "Paragraph-CTOR: nDepth invalid!" ); + + nDepth = nDDepth; + nFlags = 0; + bVisible = TRUE; +} + +Paragraph::Paragraph( const Paragraph& rPara ) +: ParagraphData( rPara ) +, aBulText( rPara.aBulText ) +, aBulSize( rPara.aBulSize ) +{ + DBG_CTOR( Paragraph, 0 ); + + nDepth = rPara.nDepth; + nFlags = rPara.nFlags; + bVisible = rPara.bVisible; +} + +Paragraph::Paragraph( const ParagraphData& rData ) +: nFlags( 0 ) +, aBulSize( -1, -1) +, bVisible( TRUE ) +{ + DBG_CTOR( Paragraph, 0 ); + + nDepth = rData.nDepth; + mnNumberingStartValue = rData.mnNumberingStartValue; + mbParaIsNumberingRestart = rData.mbParaIsNumberingRestart; +} + +Paragraph::~Paragraph() +{ + DBG_DTOR( Paragraph, 0 ); +} + +void Paragraph::SetNumberingStartValue( sal_Int16 nNumberingStartValue ) +{ + mnNumberingStartValue = nNumberingStartValue; + if( mnNumberingStartValue != -1 ) + mbParaIsNumberingRestart = true; +} + +void Paragraph::SetParaIsNumberingRestart( sal_Bool bParaIsNumberingRestart ) +{ + mbParaIsNumberingRestart = bParaIsNumberingRestart; + if( !mbParaIsNumberingRestart ) + mnNumberingStartValue = -1; +} + +void ParagraphList::Clear( BOOL bDestroyParagraphs ) +{ + if ( bDestroyParagraphs ) + { + for ( ULONG n = GetParagraphCount(); n; ) + { + Paragraph* pPara = GetParagraph( --n ); + delete pPara; + } + } + List::Clear(); +} + +void ParagraphList::MoveParagraphs( ULONG nStart, ULONG nDest, ULONG _nCount ) +{ + if ( ( nDest < nStart ) || ( nDest >= ( nStart + _nCount ) ) ) + { + ULONG n; + ParagraphList aParas; + for ( n = 0; n < _nCount; n++ ) + { + Paragraph* pPara = GetParagraph( nStart ); + aParas.Insert( pPara, LIST_APPEND ); + Remove( nStart ); + } + + if ( nDest > nStart ) + nDest -= _nCount; + + for ( n = 0; n < _nCount; n++ ) + { + Paragraph* pPara = aParas.GetParagraph( n ); + Insert( pPara, nDest++ ); + } + } + else + { + DBG_ERROR( "MoveParagraphs: Invalid Parameters" ); + } +} + +Paragraph* ParagraphList::NextVisible( Paragraph* pPara ) const +{ + ULONG n = GetAbsPos( pPara ); + + Paragraph* p = GetParagraph( ++n ); + while ( p && !p->IsVisible() ) + p = GetParagraph( ++n ); + + return p; +} + +Paragraph* ParagraphList::PrevVisible( Paragraph* pPara ) const +{ + ULONG n = GetAbsPos( pPara ); + + Paragraph* p = n ? GetParagraph( --n ) : NULL; + while ( p && !p->IsVisible() ) + p = n ? GetParagraph( --n ) : NULL; + + return p; +} + +Paragraph* ParagraphList::LastVisible() const +{ + ULONG n = GetParagraphCount(); + + Paragraph* p = n ? GetParagraph( --n ) : NULL; + while ( p && !p->IsVisible() ) + p = n ? GetParagraph( --n ) : NULL; + + return p; +} + +BOOL ParagraphList::HasChilds( Paragraph* pParagraph ) const +{ + ULONG n = GetAbsPos( pParagraph ); + Paragraph* pNext = GetParagraph( ++n ); + return ( pNext && ( pNext->GetDepth() > pParagraph->GetDepth() ) ) ? TRUE : FALSE; +} + +BOOL ParagraphList::HasHiddenChilds( Paragraph* pParagraph ) const +{ + ULONG n = GetAbsPos( pParagraph ); + Paragraph* pNext = GetParagraph( ++n ); + return ( pNext && ( pNext->GetDepth() > pParagraph->GetDepth() ) && !pNext->IsVisible() ) ? TRUE : FALSE; +} + +BOOL ParagraphList::HasVisibleChilds( Paragraph* pParagraph ) const +{ + ULONG n = GetAbsPos( pParagraph ); + Paragraph* pNext = GetParagraph( ++n ); + return ( pNext && ( pNext->GetDepth() > pParagraph->GetDepth() ) && pNext->IsVisible() ) ? TRUE : FALSE; +} + +ULONG ParagraphList::GetChildCount( Paragraph* pParent ) const +{ + ULONG nChildCount = 0; + ULONG n = GetAbsPos( pParent ); + Paragraph* pPara = GetParagraph( ++n ); + while ( pPara && ( pPara->GetDepth() > pParent->GetDepth() ) ) + { + nChildCount++; + pPara = GetParagraph( ++n ); + } + return nChildCount; +} + +Paragraph* ParagraphList::GetParent( Paragraph* pParagraph /*, USHORT& rRelPos */ ) const +{ + /* rRelPos = 0 */; + ULONG n = GetAbsPos( pParagraph ); + Paragraph* pPrev = GetParagraph( --n ); + while ( pPrev && ( pPrev->GetDepth() >= pParagraph->GetDepth() ) ) + { +// if ( pPrev->GetDepth() == pParagraph->GetDepth() ) +// rRelPos++; + pPrev = GetParagraph( --n ); + } + + return pPrev; +} + +void ParagraphList::Expand( Paragraph* pParent ) +{ + ULONG nChildCount = GetChildCount( pParent ); + ULONG nPos = GetAbsPos( pParent ); + + for ( ULONG n = 1; n <= nChildCount; n++ ) + { + Paragraph* pPara = GetParagraph( nPos+n ); + if ( !( pPara->IsVisible() ) ) + { + pPara->bVisible = TRUE; + aVisibleStateChangedHdl.Call( pPara ); + } + } +} + +void ParagraphList::Collapse( Paragraph* pParent ) +{ + ULONG nChildCount = GetChildCount( pParent ); + ULONG nPos = GetAbsPos( pParent ); + + for ( ULONG n = 1; n <= nChildCount; n++ ) + { + Paragraph* pPara = GetParagraph( nPos+n ); + if ( pPara->IsVisible() ) + { + pPara->bVisible = FALSE; + aVisibleStateChangedHdl.Call( pPara ); + } + } +} + +ULONG ParagraphList::GetVisPos( Paragraph* pPara ) +{ + ULONG nVisPos = 0; + ULONG nPos = GetAbsPos( pPara ); + for ( ULONG n = 0; n < nPos; n++ ) + { + Paragraph* _pPara = GetParagraph( n ); + if ( _pPara->IsVisible() ) + nVisPos++; + } + return nVisPos; +} diff --git a/editeng/source/outliner/paralist.hxx b/editeng/source/outliner/paralist.hxx new file mode 100644 index 000000000000..c5ecf88662c8 --- /dev/null +++ b/editeng/source/outliner/paralist.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PARALIST_HXX +#define _PARALIST_HXX + +class Paragraph; + +#include <tools/list.hxx> +#include <tools/link.hxx> + +class ParagraphList : private List +{ +private: + Link aVisibleStateChangedHdl; + +public: + void Clear( BOOL bDestroyParagraphs ); + + ULONG GetParagraphCount() const { return List::Count(); } + Paragraph* GetParagraph( ULONG nPos ) const { return (Paragraph*)List::GetObject( nPos ); } + + ULONG GetAbsPos( Paragraph* pParent ) const { return List::GetPos( pParent ); } + ULONG GetVisPos( Paragraph* pParagraph ); + + void Insert( Paragraph* pPara, ULONG nAbsPos = LIST_APPEND ) { List::Insert( pPara, nAbsPos ); } + void Remove( ULONG nPara ) { List::Remove( nPara ); } + void MoveParagraphs( ULONG nStart, ULONG nDest, ULONG nCount ); + + Paragraph* NextVisible( Paragraph* ) const; + Paragraph* PrevVisible( Paragraph* ) const; + Paragraph* LastVisible() const; + + Paragraph* GetParent( Paragraph* pParagraph /*, USHORT& rRelPos */ ) const; + BOOL HasChilds( Paragraph* pParagraph ) const; + BOOL HasHiddenChilds( Paragraph* pParagraph ) const; + BOOL HasVisibleChilds( Paragraph* pParagraph ) const; + ULONG GetChildCount( Paragraph* pParagraph ) const; + + void Expand( Paragraph* pParent ); + void Collapse( Paragraph* pParent ); + + void SetVisibleStateChangedHdl( const Link& rLink ) { aVisibleStateChangedHdl = rLink; } + Link GetVisibleStateChangedHdl() const { return aVisibleStateChangedHdl; } +}; + +#endif |