summaryrefslogtreecommitdiff
path: root/sw/source/core/crsr
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/crsr')
-rw-r--r--sw/source/core/crsr/BlockCursor.cxx106
-rw-r--r--sw/source/core/crsr/BlockCursor.hxx36
-rw-r--r--sw/source/core/crsr/IBlockCursor.hxx95
-rw-r--r--sw/source/core/crsr/bookmrk.cxx346
-rw-r--r--sw/source/core/crsr/callnk.cxx221
-rw-r--r--sw/source/core/crsr/callnk.hxx56
-rw-r--r--sw/source/core/crsr/crbm.cxx260
-rw-r--r--sw/source/core/crsr/crossrefbookmark.cxx102
-rw-r--r--sw/source/core/crsr/crsrsh.cxx3495
-rw-r--r--sw/source/core/crsr/crstrvl.cxx2216
-rw-r--r--sw/source/core/crsr/crstrvl1.cxx105
-rw-r--r--sw/source/core/crsr/findattr.cxx1309
-rw-r--r--sw/source/core/crsr/findcoll.cxx119
-rw-r--r--sw/source/core/crsr/findfmt.cxx84
-rw-r--r--sw/source/core/crsr/findtxt.cxx707
-rw-r--r--sw/source/core/crsr/makefile.mk83
-rw-r--r--sw/source/core/crsr/pam.cxx1246
-rw-r--r--sw/source/core/crsr/paminit.cxx131
-rw-r--r--sw/source/core/crsr/swcrsr.cxx2360
-rw-r--r--sw/source/core/crsr/trvlcol.cxx133
-rw-r--r--sw/source/core/crsr/trvlfnfl.cxx359
-rw-r--r--sw/source/core/crsr/trvlreg.cxx291
-rw-r--r--sw/source/core/crsr/trvltbl.cxx931
-rw-r--r--sw/source/core/crsr/unocrsr.cxx280
-rw-r--r--sw/source/core/crsr/viscrs.cxx1006
25 files changed, 16077 insertions, 0 deletions
diff --git a/sw/source/core/crsr/BlockCursor.cxx b/sw/source/core/crsr/BlockCursor.cxx
new file mode 100644
index 000000000000..589549c0ade8
--- /dev/null
+++ b/sw/source/core/crsr/BlockCursor.cxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+#include <IBlockCursor.hxx>
+#include <viscrs.hxx>
+#include "BlockCursor.hxx"
+
+/** The implementation of the block cursor interface
+
+ It's simply an aggregation of a SwShellCrsr and a rectangle defined by
+ a start and an end point.
+*/
+class SwBlockCursor : public IBlockCursor
+{
+ SwShellCrsr aCursor;
+ Point *pStartPt;
+ Point *pEndPt;
+public:
+ SwBlockCursor( const SwCrsrShell& rCrsrSh, const SwPosition &rPos ) :
+ aCursor( rCrsrSh, rPos ), pStartPt(0), pEndPt(0) {}
+ virtual SwShellCrsr& getShellCrsr();
+ virtual void setStartPoint( const Point &rPt );
+ virtual void setEndPoint( const Point &rPt );
+ virtual const Point* getStartPoint() const;
+ virtual const Point* getEndPoint() const;
+ virtual void clearPoints();
+ virtual ~SwBlockCursor();
+};
+
+SwBlockCursor::~SwBlockCursor()
+{
+ delete pStartPt;
+ delete pEndPt;
+}
+
+SwShellCrsr& SwBlockCursor::getShellCrsr()
+{
+ return aCursor;
+}
+
+void SwBlockCursor::setStartPoint( const Point &rPt )
+{
+ if( pStartPt )
+ *pStartPt = rPt;
+ else
+ pStartPt = new Point( rPt );
+}
+
+void SwBlockCursor::setEndPoint( const Point &rPt )
+{
+ if( pEndPt )
+ *pEndPt = rPt;
+ else
+ pEndPt = new Point( rPt );
+}
+
+const Point* SwBlockCursor::getStartPoint() const
+{
+ return pStartPt;
+}
+
+const Point* SwBlockCursor::getEndPoint() const
+{
+ return pEndPt;
+}
+
+void SwBlockCursor::clearPoints()
+{
+ delete pStartPt;
+ delete pEndPt;
+ pStartPt = 0;
+ pEndPt = 0;
+}
+
+IBlockCursor *createBlockCursor( const SwCrsrShell& rCrsrSh, const SwPosition &rPos )
+{
+ return new SwBlockCursor( rCrsrSh, rPos );
+}
+
diff --git a/sw/source/core/crsr/BlockCursor.hxx b/sw/source/core/crsr/BlockCursor.hxx
new file mode 100644
index 000000000000..a3acb0bac187
--- /dev/null
+++ b/sw/source/core/crsr/BlockCursor.hxx
@@ -0,0 +1,36 @@
+/*************************************************************************
+ *
+ * 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 _BLOCKCURSOR_HXX
+#define _BLOCKCURSOR_HXX
+
+class IBlockCursor;
+class SwCrsrShell;
+struct SwPosition;
+
+IBlockCursor *createBlockCursor(const SwCrsrShell& rCrsrSh, const SwPosition &rPos);
+
+#endif //_BLOCKURSOR_HXX
diff --git a/sw/source/core/crsr/IBlockCursor.hxx b/sw/source/core/crsr/IBlockCursor.hxx
new file mode 100644
index 000000000000..99b5cf3b734a
--- /dev/null
+++ b/sw/source/core/crsr/IBlockCursor.hxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+ *
+ * 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 IBLOCKCURSOR_HXX_INCLUDED
+#define IBLOCKCURSOR_HXX_INCLUDED
+
+class SwShellCrsr;
+class Point;
+
+ /** Access to the block cursor
+
+ A block cursor contains a SwShellCrsr and additional information about
+ the rectangle which has been created by pressing the mouse button and
+ moving the mouse.
+ This interface provides access to the SwShellCrsr and to start and end
+ point of the mouse movement.
+ */
+ class IBlockCursor
+ {
+ public:
+/** Access to the shell cursor
+
+ @return SwShellCrsr& which represents the start and end position of the
+ current block selection
+*/
+ virtual SwShellCrsr& getShellCrsr() = 0;
+
+/** Defines the starting vertex of the block selection
+
+ @param rPt
+ rPt should contain the document coordinates of the mouse cursor when
+ the block selection starts (MouseButtonDown)
+*/
+ virtual void setStartPoint( const Point &rPt ) = 0;
+
+/** Defines the ending vertex of the block selection
+
+ @param rPt
+ rPt should contain the document coordinates of the mouse cursor when
+ the block selection has started and the mouse has been moved (MouseMove)
+*/
+ virtual void setEndPoint( const Point &rPt ) = 0;
+
+/** The document coordinates where the block selection has been started
+
+ @return 0, if no start point has been set
+*/
+ virtual const Point* getStartPoint() const = 0;
+
+
+/** The document coordinates where the block selection ends (at the moment)
+
+ @return 0, if no end point has been set
+*/
+ virtual const Point* getEndPoint() const = 0;
+
+/** Deletion of the mouse created rectangle
+
+ When start and end points exist, the block cursor depends on this. If the
+ cursor is moved by cursor keys (e.g. up/down, home/end) the mouse rectangle
+ is obsolet and has to be deleted.
+*/
+ virtual void clearPoints() = 0;
+
+/** Destructor of the block curosr interface
+*/
+ virtual ~IBlockCursor() {};
+ };
+
+#endif // IBLOCKCURSOR_HXX_INCLUDED
+
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
new file mode 100644
index 000000000000..11060352b6c3
--- /dev/null
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -0,0 +1,346 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <bookmrk.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <doc.hxx>
+#include <errhdl.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <swserv.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <swtypes.hxx>
+#include <undobj.hxx>
+#include <unobookmark.hxx>
+#include <rtl/random.h>
+#include <xmloff/odffields.hxx>
+
+
+SV_IMPL_REF( SwServerObject )
+
+using namespace ::sw::mark;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+ static void lcl_FixPosition(SwPosition& rPos)
+ {
+ // make sure the position has 1) the proper node, and 2) a proper index
+ SwTxtNode* pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ if(pTxtNode == NULL && rPos.nContent.GetIndex() > 0)
+ {
+ OSL_TRACE(
+ "bookmrk.cxx::lcl_FixPosition"
+ " - illegal position: %d without proper TxtNode", rPos.nContent.GetIndex());
+ rPos.nContent.Assign(NULL, 0);
+ }
+ else if(pTxtNode != NULL && rPos.nContent.GetIndex() > pTxtNode->Len())
+ {
+ OSL_TRACE(
+ "bookmrk.cxx::lcl_FixPosition"
+ " - illegal position: %d is beyond %d", rPos.nContent.GetIndex(), pTxtNode->Len());
+ rPos.nContent.Assign(pTxtNode, pTxtNode->Len());
+ }
+ };
+
+ static void lcl_AssureFieldMarksSet(Fieldmark* const pField,
+ SwDoc* const io_pDoc,
+ const sal_Unicode aStartMark,
+ const sal_Unicode aEndMark)
+ {
+ SwPosition& rStart = pField->GetMarkStart();
+ SwPosition& rEnd = pField->GetMarkEnd();
+ SwTxtNode const * const pStartTxtNode = io_pDoc->GetNodes()[rStart.nNode]->GetTxtNode();
+ SwTxtNode const * const pEndTxtNode = io_pDoc->GetNodes()[rEnd.nNode]->GetTxtNode();
+ const sal_Unicode ch_start=pStartTxtNode->GetTxt().GetChar(rStart.nContent.GetIndex());
+ const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar(rEnd.nContent.GetIndex()-1);
+ SwPaM aStartPaM(rStart);
+ SwPaM aEndPaM(rEnd);
+ io_pDoc->StartUndo(UNDO_UI_REPLACE, NULL);
+ if(ch_start != aStartMark)
+ {
+ io_pDoc->InsertString(aStartPaM, aStartMark);
+ }
+ if ( aEndMark && ( ch_end != aEndMark ) && ( rStart != rEnd ) )
+ {
+ io_pDoc->InsertString(aEndPaM, aEndMark);
+ }
+ io_pDoc->EndUndo(UNDO_UI_REPLACE, NULL);
+ };
+}
+
+namespace sw { namespace mark
+{
+ MarkBase::MarkBase(const SwPaM& aPaM,
+ const ::rtl::OUString& rName)
+ : SwModify(0)
+ , m_pPos1(new SwPosition(*(aPaM.GetPoint())))
+ , m_aName(rName)
+ {
+ lcl_FixPosition(*m_pPos1);
+ if(aPaM.HasMark())
+ {
+ MarkBase::SetOtherMarkPos(*(aPaM.GetMark()));
+ lcl_FixPosition(*m_pPos2);
+ }
+ }
+
+ bool MarkBase::IsCoveringPosition(const SwPosition& rPos) const
+ {
+ return GetMarkStart() <= rPos && rPos <= GetMarkEnd();
+ }
+
+ void MarkBase::SetMarkPos(const SwPosition& rNewPos)
+ {
+ ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos1);
+ //lcl_FixPosition(*m_pPos1);
+ }
+
+ void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos)
+ {
+ ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos2);
+ //lcl_FixPosition(*m_pPos2);
+ }
+
+ rtl::OUString MarkBase::ToString( ) const
+ {
+ rtl::OUStringBuffer buf;
+ buf.appendAscii( "Mark: ( Name, [ Node1, Index1 ] ): ( " );
+ buf.append( m_aName ).appendAscii( ", [ " );
+ buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetMarkPos().nContent.GetIndex( ) ) ).appendAscii( " ] )" );
+
+ return buf.makeStringAndClear( );
+ }
+
+ MarkBase::~MarkBase()
+ { }
+
+ ::rtl::OUString MarkBase::GenerateNewName(const ::rtl::OUString& rPrefix)
+ {
+ static rtlRandomPool aPool = rtl_random_createPool();
+ static ::rtl::OUString sUniquePostfix;
+ static sal_Int32 nCount = SAL_MAX_INT32;
+ ::rtl::OUStringBuffer aResult(rPrefix);
+ if(nCount == SAL_MAX_INT32)
+ {
+ sal_Int32 nRandom;
+ ::rtl::OUStringBuffer sUniquePostfixBuffer;
+ rtl_random_getBytes(aPool, &nRandom, sizeof(nRandom));
+ sUniquePostfix = ::rtl::OUStringBuffer(13).appendAscii("_").append(static_cast<sal_Int32>(abs(nRandom))).makeStringAndClear();
+ nCount = 0;
+ }
+ // putting the counter in front of the random parts will speed up string comparisons
+ return aResult.append(nCount++).append(sUniquePostfix).makeStringAndClear();
+ }
+
+
+ void MarkBase::Modify(SfxPoolItem *pOld, SfxPoolItem *pNew)
+ {
+ SwModify::Modify(pOld, pNew);
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXBookmark(uno::Reference<text::XTextContent>(0));
+ }
+ }
+
+
+ NavigatorReminder::NavigatorReminder(const SwPaM& rPaM)
+ : MarkBase(rPaM, our_sNamePrefix)
+ { }
+
+ const ::rtl::OUString NavigatorReminder::our_sNamePrefix = ::rtl::OUString::createFromAscii("__NavigatorReminder__");
+
+ UnoMark::UnoMark(const SwPaM& aPaM)
+ : MarkBase(aPaM, MarkBase::GenerateNewName(our_sNamePrefix))
+ { }
+
+ const ::rtl::OUString UnoMark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__UnoMark__");
+
+ DdeBookmark::DdeBookmark(const SwPaM& aPaM)
+ : MarkBase(aPaM, MarkBase::GenerateNewName(our_sNamePrefix))
+ , m_aRefObj(NULL)
+ { }
+
+ void DdeBookmark::SetRefObject(SwServerObject* pObj)
+ {
+ m_aRefObj = pObj;
+ }
+
+ const ::rtl::OUString DdeBookmark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__DdeLink__");
+
+ void DdeBookmark::DeregisterFromDoc(SwDoc* const pDoc)
+ {
+ if(m_aRefObj.Is())
+ pDoc->GetLinkManager().RemoveServer(m_aRefObj);
+ }
+
+ DdeBookmark::~DdeBookmark()
+ {
+ if( m_aRefObj.Is() )
+ {
+ if(m_aRefObj->HasDataLinks())
+ {
+ ::sfx2::SvLinkSource* p = &m_aRefObj;
+ p->SendDataChanged();
+ }
+ m_aRefObj->SetNoServer();
+ }
+ }
+
+ Bookmark::Bookmark(const SwPaM& aPaM,
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName)
+ : DdeBookmark(aPaM)
+ , ::sfx2::Metadatable()
+ , m_aCode(rCode)
+ , m_sShortName(rShortName)
+ {
+ m_aName = rName;
+ }
+
+ void Bookmark::InitDoc(SwDoc* const io_pDoc)
+ {
+ if(io_pDoc->DoesUndo())
+ {
+ io_pDoc->ClearRedo();
+ io_pDoc->AppendUndo(new SwUndoInsBookmark(*this));
+ }
+ io_pDoc->SetModified();
+ }
+
+ // ::sfx2::Metadatable
+ ::sfx2::IXmlIdRegistry& Bookmark::GetRegistry()
+ {
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
+ return pDoc->GetXmlIdRegistry();
+ }
+
+ bool Bookmark::IsInClipboard() const
+ {
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::IsInClipboard: no doc?");
+ return pDoc->IsClipBoard();
+ }
+
+ bool Bookmark::IsInUndo() const
+ {
+ return false;
+ }
+
+ bool Bookmark::IsInContent() const
+ {
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::IsInContent: no doc?");
+ return !pDoc->IsInHeaderFooter( SwNodeIndex(GetMarkPos().nNode) );
+ }
+
+ uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject()
+ {
+ // create new SwXBookmark
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
+ const uno::Reference< rdf::XMetadatable> xMeta(
+ SwXBookmark::CreateXBookmark(*pDoc, *this), uno::UNO_QUERY);
+ return xMeta;
+ }
+
+
+ Fieldmark::Fieldmark(const SwPaM& rPaM)
+ : MarkBase(rPaM, MarkBase::GenerateNewName(our_sNamePrefix))
+ {
+ if(!IsExpanded())
+ SetOtherMarkPos(GetMarkPos());
+ }
+
+ rtl::OUString Fieldmark::ToString( ) const
+ {
+ rtl::OUStringBuffer buf;
+ buf.appendAscii( "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " );
+ buf.append( m_aName ).appendAscii( ", " );
+ buf.append( m_aFieldname ).appendAscii( ", [ " );
+ buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ], [" );
+ buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ] ) " );
+
+ return buf.makeStringAndClear( );
+ }
+
+ void Fieldmark::Invalidate( )
+ {
+ // @TODO: Does exist a better solution to trigger a format of the
+ // fieldmark portion? If yes, please use it.
+ SwPaM aPaM( this->GetMarkPos(), this->GetOtherMarkPos() );
+ aPaM.InvalidatePaM();
+ }
+
+ const ::rtl::OUString Fieldmark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__Fieldmark__");
+
+ TextFieldmark::TextFieldmark(const SwPaM& rPaM)
+ : Fieldmark(rPaM)
+ { }
+
+ void TextFieldmark::InitDoc(SwDoc* const io_pDoc)
+ {
+ lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
+ }
+
+ CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM)
+ : Fieldmark(rPaM)
+ { }
+
+ void CheckboxFieldmark::InitDoc(SwDoc* const io_pDoc)
+ {
+ lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FORMELEMENT, CH_TXT_ATR_FIELDEND);
+
+ // For some reason the end mark is moved from 1 by the Insert: we don't
+ // want this for checkboxes
+ this->GetMarkEnd( ).nContent--;
+ }
+ void CheckboxFieldmark::SetChecked(bool checked)
+ {
+ (*GetParameters())[::rtl::OUString::createFromAscii(ODF_FORMCHECKBOX_RESULT)] = makeAny(checked);
+ }
+
+ bool CheckboxFieldmark::IsChecked() const
+ {
+ bool bResult = false;
+ parameter_map_t::const_iterator pResult = GetParameters()->find(::rtl::OUString::createFromAscii(ODF_FORMCHECKBOX_RESULT));
+ if(pResult != GetParameters()->end())
+ pResult->second >>= bResult;
+ return bResult;
+ }
+
+}}
diff --git a/sw/source/core/crsr/callnk.cxx b/sw/source/core/crsr/callnk.cxx
new file mode 100644
index 000000000000..bf06a19d83b0
--- /dev/null
+++ b/sw/source/core/crsr/callnk.cxx
@@ -0,0 +1,221 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
+#include <com/sun/star/i18n/ScriptType.hdl>
+#endif
+#include <fmtcntnt.hxx>
+#include <txatbase.hxx>
+#include <frmatr.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <breakit.hxx>
+
+
+SwCallLink::SwCallLink( SwCrsrShell & rSh, ULONG nAktNode, xub_StrLen nAktCntnt,
+ BYTE nAktNdTyp, long nLRPos, bool bAktSelection )
+ : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
+ nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
+ bHasSelection( bAktSelection )
+{
+}
+
+
+SwCallLink::SwCallLink( SwCrsrShell & rSh )
+ : rShell( rSh )
+{
+ // SPoint-Werte vom aktuellen Cursor merken
+ SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
+ SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
+ nNode = rNd.GetIndex();
+ nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
+ nNdTyp = rNd.GetNodeType();
+ bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
+
+ if( ND_TEXTNODE & nNdTyp )
+ nLeftFrmPos = SwCallLink::GetFrm( (SwTxtNode&)rNd, nCntnt,
+ !rShell.ActionPend() );
+ else
+ {
+ nLeftFrmPos = 0;
+
+ // eine Sonderbehandlung fuer die SwFeShell: diese setzt beim Loeschen
+ // der Kopf-/Fusszeile, Fussnoten den Cursor auf NULL (Node + Content)
+ // steht der Cursor auf keinem CntntNode, wird sich das im NdType
+ // gespeichert.
+ if( ND_CONTENTNODE & nNdTyp )
+ nNdTyp = 0;
+ }
+}
+
+
+SwCallLink::~SwCallLink()
+{
+ if( !nNdTyp || !rShell.bCallChgLnk ) // siehe ctor
+ return ;
+
+ // wird ueber Nodes getravellt, Formate ueberpruefen und im neuen
+ // Node wieder anmelden
+ SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
+ SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
+ if( !pCNd )
+ return;
+
+ xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
+ USHORT nNdWhich = pCNd->GetNodeType();
+ ULONG nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
+
+ // melde die Shell beim akt. Node als abhaengig an, dadurch koennen
+ // alle Attribut-Aenderungen ueber den Link weiter gemeldet werden.
+ pCNd->Add( &rShell );
+
+ if( nNdTyp != nNdWhich || nNode != nAktNode )
+ {
+ /* immer, wenn zwischen Nodes gesprungen wird, kann es
+ * vorkommen, das neue Attribute gelten; die Text-Attribute.
+ * Es muesste also festgestellt werden, welche Attribute
+ * jetzt gelten; das kann auch gleich der Handler machen
+ */
+ rShell.CallChgLnk();
+ }
+ else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
+ {
+ // always call change link when selection changes
+ rShell.CallChgLnk();
+ }
+ else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
+ nCntnt != nAktCntnt )
+ {
+ // nur wenn mit Left/right getravellt, dann Text-Hints pruefen
+ // und sich nicht der Frame geaendert hat (Spalten!)
+ if( nLeftFrmPos == SwCallLink::GetFrm( (SwTxtNode&)*pCNd, nAktCntnt,
+ !rShell.ActionPend() ) &&
+ (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
+ nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
+ {
+ if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & Sele
+ ++nCmp;
+ if ( ((SwTxtNode*)pCNd)->HasHints() )
+ {
+
+ const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
+ USHORT n;
+ xub_StrLen nStart;
+ const xub_StrLen *pEnd;
+
+ for( n = 0; n < rHts.Count(); n++ )
+ {
+ const SwTxtAttr* pHt = rHts[ n ];
+ pEnd = pHt->GetEnd();
+ nStart = *pHt->GetStart();
+
+ // nur Start oder Start und Ende gleich, dann immer
+ // beim Ueberlaufen von Start callen
+ if( ( !pEnd || ( nStart == *pEnd ) ) &&
+ ( nStart == nCntnt || nStart == nAktCntnt) )
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+
+ // hat das Attribut einen Bereich und dieser nicht leer
+ else if( pEnd && nStart < *pEnd &&
+ // dann teste, ob ueber Start/Ende getravellt wurde
+ ( nStart == nCmp ||
+ ( pHt->DontExpand() ? nCmp == *pEnd-1
+ : nCmp == *pEnd ) ))
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+ nStart = 0;
+ }
+ }
+
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
+ if( !nCmp ||
+ pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
+ != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+ }
+ }
+ else
+ /* wenn mit Home/End/.. mehr als 1 Zeichen getravellt, dann
+ * immer den ChgLnk rufen, denn es kann hier nicht
+ * festgestellt werden, was sich geaendert; etwas kann
+ * veraendert sein.
+ */
+ rShell.CallChgLnk();
+ }
+
+ const SwFrm* pFrm;
+ const SwFlyFrm *pFlyFrm;
+ if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->GetFrm(0,0,FALSE) ) &&
+ 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
+ {
+ const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
+ ASSERT( pIndex, "Fly ohne Cntnt" );
+ const SwNode& rStNd = pIndex->GetNode();
+
+ if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
+ nNode > rStNd.EndOfSectionIndex() )
+ rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
+ }
+}
+
+long SwCallLink::GetFrm( SwTxtNode& rNd, xub_StrLen nCntPos, BOOL bCalcFrm )
+{
+ SwTxtFrm* pFrm = (SwTxtFrm*)rNd.GetFrm(0,0,bCalcFrm), *pNext = pFrm;
+ if ( pFrm && !pFrm->IsHiddenNow() )
+ {
+ if( pFrm->HasFollow() )
+ while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
+ nCntPos >= pNext->GetOfst() )
+ pFrm = pNext;
+
+ return pFrm->Frm().Left();
+ }
+ return 0;
+}
+
diff --git a/sw/source/core/crsr/callnk.hxx b/sw/source/core/crsr/callnk.hxx
new file mode 100644
index 000000000000..f85e0c5db123
--- /dev/null
+++ b/sw/source/core/crsr/callnk.hxx
@@ -0,0 +1,56 @@
+/*************************************************************************
+ *
+ * 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 _CALLNK_HXX
+#define _CALLNK_HXX
+
+#include <tools/solar.h>
+
+class SwCrsrShell;
+class SwTxtNode;
+
+class SwCallLink
+{
+public:
+ SwCrsrShell & rShell;
+ ULONG nNode;
+ xub_StrLen nCntnt;
+ BYTE nNdTyp;
+ long nLeftFrmPos;
+ bool bHasSelection;
+
+ SwCallLink( SwCrsrShell & rSh );
+ SwCallLink( SwCrsrShell & rSh, ULONG nAktNode, xub_StrLen nAktCntnt,
+ BYTE nAktNdTyp, long nLRPos,
+ bool bAktSelection );
+ ~SwCallLink();
+
+ static long GetFrm( SwTxtNode& rNd, xub_StrLen nCntPos, BOOL bCalcFrm );
+};
+
+
+
+#endif // _CALLNK_HXX
diff --git a/sw/source/core/crsr/crbm.cxx b/sw/source/core/crsr/crbm.cxx
new file mode 100644
index 000000000000..0ef82902ff08
--- /dev/null
+++ b/sw/source/core/crsr/crbm.cxx
@@ -0,0 +1,260 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include "crsrsh.hxx"
+#include "ndtxt.hxx"
+#include <docary.hxx>
+#include <boost/bind.hpp>
+
+#include "IMark.hxx"
+#include "callnk.hxx"
+#include "swcrsr.hxx"
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+
+using namespace std;
+
+namespace
+{
+ struct CrsrStateHelper
+ {
+ CrsrStateHelper(SwCrsrShell& rShell)
+ : m_aLink(rShell)
+ , m_pCrsr(rShell.GetSwCrsr())
+ , m_aSaveState(*m_pCrsr)
+ { }
+
+ void SetCrsrToMark(::sw::mark::IMark const * const pMark)
+ {
+ *(m_pCrsr->GetPoint()) = pMark->GetMarkStart();
+ if(pMark->IsExpanded())
+ {
+ m_pCrsr->SetMark();
+ *(m_pCrsr->GetMark()) = pMark->GetMarkEnd();
+ }
+ }
+
+ // returns true if the Cursor had been rolled back
+ bool RollbackIfIllegal()
+ {
+ if(m_pCrsr->IsSelOvr(nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION
+ | nsSwCursorSelOverFlags::SELOVER_TOGGLE))
+ {
+ m_pCrsr->DeleteMark();
+ m_pCrsr->RestoreSavePos();
+ return true;
+ }
+ return false;
+ }
+
+ SwCallLink m_aLink;
+ SwCursor* m_pCrsr;
+ SwCrsrSaveState m_aSaveState;
+ };
+
+
+ static bool lcl_ReverseMarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
+ const IDocumentMarkAccess::pMark_t& rpSecond)
+ {
+ return rpFirst->GetMarkEnd() > rpSecond->GetMarkEnd();
+ }
+
+ static bool lcl_IsInvisibleBookmark(IDocumentMarkAccess::pMark_t pMark)
+ {
+ return IDocumentMarkAccess::GetType(*pMark) != IDocumentMarkAccess::BOOKMARK;
+ }
+}
+
+// at CurCrsr.SPoint
+::sw::mark::IMark* SwCrsrShell::SetBookmark(
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName,
+ IDocumentMarkAccess::MarkType eMark)
+{
+ StartAction();
+ ::sw::mark::IMark* pMark = getIDocumentMarkAccess()->makeMark(
+ *GetCrsr(),
+ rName,
+ eMark);
+ ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
+ if(pBookmark)
+ {
+ pBookmark->SetKeyCode(rCode);
+ pBookmark->SetShortName(rShortName);
+ }
+ EndAction();
+ return pMark;
+}
+// setzt CurCrsr.SPoint
+
+bool SwCrsrShell::GotoMark(const ::sw::mark::IMark* const pMark, bool bAtStart)
+{
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ if ( bAtStart )
+ *(aCrsrSt.m_pCrsr)->GetPoint() = pMark->GetMarkStart();
+ else
+ *(aCrsrSt.m_pCrsr)->GetPoint() = pMark->GetMarkEnd();
+ if(aCrsrSt.RollbackIfIllegal()) return false;
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::GotoMark(const ::sw::mark::IMark* const pMark)
+{
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ aCrsrSt.SetCrsrToMark(pMark);
+
+ if(aCrsrSt.RollbackIfIllegal()) return false;
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::GoNextBookmark()
+{
+ IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
+ IDocumentMarkAccess::container_t vCandidates;
+ remove_copy_if(
+ upper_bound(
+ pMarkAccess->getBookmarksBegin(),
+ pMarkAccess->getBookmarksEnd(),
+ *GetCrsr()->GetPoint(),
+ bind(&::sw::mark::IMark::StartsAfter, _2, _1)), // finds the first that is starting after
+ pMarkAccess->getBookmarksEnd(),
+ back_inserter(vCandidates),
+ &lcl_IsInvisibleBookmark);
+
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ IDocumentMarkAccess::const_iterator_t ppMark = vCandidates.begin();
+ for(; ppMark!=vCandidates.end(); ++ppMark)
+ {
+ aCrsrSt.SetCrsrToMark(ppMark->get());
+ if(!aCrsrSt.RollbackIfIllegal())
+ break; // found legal move
+ }
+ if(ppMark==vCandidates.end())
+ {
+ SttEndDoc(false);
+ return false;
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::GoPrevBookmark()
+{
+ IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
+ // candidates from which to choose the mark before
+ // no need to consider marks starting after rPos
+ IDocumentMarkAccess::container_t vCandidates;
+ remove_copy_if(
+ pMarkAccess->getBookmarksBegin(),
+ upper_bound(
+ pMarkAccess->getBookmarksBegin(),
+ pMarkAccess->getBookmarksEnd(),
+ *GetCrsr()->GetPoint(),
+ bind(&::sw::mark::IMark::StartsAfter, _2, _1)),
+ back_inserter(vCandidates),
+ &lcl_IsInvisibleBookmark);
+ sort(
+ vCandidates.begin(),
+ vCandidates.end(),
+ &lcl_ReverseMarkOrderingByEnd);
+
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ IDocumentMarkAccess::const_iterator_t ppMark = vCandidates.begin();
+ for(; ppMark!=vCandidates.end(); ++ppMark)
+ {
+ // ignoring those not ending before the Crsr
+ // (we were only able to eliminate those starting
+ // behind the Crsr by the upper_bound(..)
+ // above)
+ if(!(**ppMark).EndsBefore(*GetCrsr()->GetPoint()))
+ continue;
+ aCrsrSt.SetCrsrToMark(ppMark->get());
+ if(!aCrsrSt.RollbackIfIllegal())
+ break; // found legal move
+ }
+ if(ppMark==vCandidates.end())
+ {
+ SttEndDoc(true);
+ return false;
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::IsFormProtected()
+{
+ return getIDocumentSettingAccess()->get(IDocumentSettingAccess::PROTECT_FORM);
+}
+
+::sw::mark::IFieldmark* SwCrsrShell::GetCurrentFieldmark()
+{
+ // TODO: Refactor
+ SwPosition pos(*GetCrsr()->GetPoint());
+ return getIDocumentMarkAccess()->getFieldmarkFor(pos);
+}
+
+::sw::mark::IFieldmark* SwCrsrShell::GetFieldmarkAfter()
+{
+ SwPosition pos(*GetCrsr()->GetPoint());
+ return getIDocumentMarkAccess()->getFieldmarkAfter(pos);
+}
+
+::sw::mark::IFieldmark* SwCrsrShell::GetFieldmarkBefore()
+{
+ SwPosition pos(*GetCrsr()->GetPoint());
+ return getIDocumentMarkAccess()->getFieldmarkBefore(pos);
+}
+
+bool SwCrsrShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark)
+{
+ if(pMark==NULL) return false;
+
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ aCrsrSt.SetCrsrToMark(pMark);
+ //aCrsrSt.m_pCrsr->GetPoint()->nContent--;
+ //aCrsrSt.m_pCrsr->GetMark()->nContent++;
+ if(aCrsrSt.RollbackIfIllegal()) return false;
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
diff --git a/sw/source/core/crsr/crossrefbookmark.cxx b/sw/source/core/crsr/crossrefbookmark.cxx
new file mode 100644
index 000000000000..dc083801ee8e
--- /dev/null
+++ b/sw/source/core/crsr/crossrefbookmark.cxx
@@ -0,0 +1,102 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+#include <crossrefbookmark.hxx>
+#include <ndtxt.hxx>
+
+using namespace rtl;
+
+namespace sw { namespace mark
+{
+ CrossRefBookmark::CrossRefBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const OUString& rName,
+ const OUString& rShortName,
+ const OUString& rPrefix)
+ : Bookmark(rPaM, rCode, rName, rShortName)
+ {
+ if(rPaM.HasMark())
+ OSL_ENSURE((rPaM.GetMark()->nNode == rPaM.GetPoint()->nNode &&
+ rPaM.Start()->nContent.GetIndex() == 0 &&
+ rPaM.End()->nContent.GetIndex() == rPaM.GetPoint()->nNode.GetNode().GetTxtNode()->Len()),
+ "<CrossRefBookmark::CrossRefBookmark(..)>"
+ "- creation of cross-reference bookmark with an expanded PaM that does not expand over exactly one whole paragraph.");
+ SetMarkPos(*rPaM.Start());
+ if(!rName.getLength())
+ m_aName = MarkBase::GenerateNewName(rPrefix);
+ }
+
+ void CrossRefBookmark::SetMarkPos(const SwPosition& rNewPos)
+ {
+ OSL_PRECOND(rNewPos.nNode.GetNode().GetTxtNode(),
+ "<SwCrossRefBookmark::SetMarkPos(..)>"
+ " - new bookmark position for cross-reference bookmark doesn't mark text node");
+ OSL_PRECOND(rNewPos.nContent.GetIndex() == 0,
+ "<SwCrossRefBookmark::SetMarkPos(..)>"
+ " - new bookmark position for cross-reference bookmark doesn't mark start of text node");
+ MarkBase::SetMarkPos(rNewPos);
+ }
+
+ SwPosition& CrossRefBookmark::GetOtherMarkPos() const
+ {
+ OSL_PRECOND(false,
+ "<SwCrossRefBookmark::GetOtherMarkPos(..)>"
+ " - this should never be called!");
+ return *static_cast<SwPosition*>(NULL);
+ }
+
+ CrossRefHeadingBookmark::CrossRefHeadingBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const OUString& rName,
+ const OUString& rShortName)
+ : CrossRefBookmark(rPaM, rCode, rName, rShortName, our_sNamePrefix)
+ { }
+
+ const ::rtl::OUString CrossRefHeadingBookmark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__RefHeading__");
+
+ bool CrossRefHeadingBookmark::IsLegalName(const ::rtl::OUString& rName)
+ {
+ return rName.match(our_sNamePrefix);
+ }
+
+ CrossRefNumItemBookmark::CrossRefNumItemBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const OUString& rName,
+ const OUString& rShortName)
+ : CrossRefBookmark(rPaM, rCode, rName, rShortName, our_sNamePrefix)
+ { }
+
+ const ::rtl::OUString CrossRefNumItemBookmark::our_sNamePrefix = ::rtl::OUString::createFromAscii("__RefNumPara__");
+
+ bool CrossRefNumItemBookmark::IsLegalName(const ::rtl::OUString& rName)
+ {
+ return rName.match(our_sNamePrefix);
+ }
+}}
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
new file mode 100644
index 000000000000..9cf698a3a709
--- /dev/null
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -0,0 +1,3495 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <hintids.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/frmdiritem.hxx>
+
+#include <SwSmartTagMgr.hxx>
+#include <doc.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewimp.hxx>
+#include <pam.hxx>
+#include <swselectionlist.hxx>
+#include <IBlockCursor.hxx>
+#include "BlockCursor.hxx"
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <dview.hxx>
+#include <viewopt.hxx>
+#include <frmtool.hxx>
+#include <crsrsh.hxx>
+#include <tabfrm.hxx>
+#include <txtfrm.hxx>
+#include <sectfrm.hxx>
+#include <swtable.hxx>
+#include <callnk.hxx>
+#include <viscrs.hxx>
+#include <section.hxx>
+#include <docsh.hxx>
+#include <scriptinfo.hxx>
+#include <globdoc.hxx>
+#include <pamtyp.hxx>
+#include <mdiexp.hxx> // ...Percent()
+#include <fmteiro.hxx>
+#include <wrong.hxx> // SMARTTAGS
+#include <unotextrange.hxx> // SMARTTAGS
+#include <vcl/svapp.hxx>
+#include <numrule.hxx>
+#include <IGrammarContact.hxx>
+
+#include <globals.hrc>
+
+#include <comcore.hrc>
+
+using namespace com::sun::star;
+using namespace util;
+
+TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
+
+
+// Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
+void CheckRange( SwCursor* );
+
+//-----------------------------------------------------------------------
+
+/*
+ * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
+ * Wenn ja, dann hebe den alten Bereich auf.
+ */
+
+
+void CheckRange( SwCursor* pCurCrsr )
+{
+ const SwPosition *pStt = pCurCrsr->Start(),
+ *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
+
+ SwPaM *pTmpDel = 0,
+ *pTmp = (SwPaM*)pCurCrsr->GetNext();
+
+ // durchsuche den gesamten Ring
+ while( pTmp != pCurCrsr )
+ {
+ const SwPosition *pTmpStt = pTmp->Start(),
+ *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
+ pTmp->GetMark() : pTmp->GetPoint();
+ if( *pStt <= *pTmpStt )
+ {
+ if( *pEnd > *pTmpStt ||
+ ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
+ pTmpDel = pTmp;
+ }
+ else
+ if( *pStt < *pTmpEnd )
+ pTmpDel = pTmp;
+ /*
+ * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
+ * muss der alte Bereich aufgehoben werden.
+ * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
+ * Bereich gehoert !
+ */
+ pTmp = (SwPaM*)pTmp->GetNext();
+ if( pTmpDel )
+ {
+ delete pTmpDel; // hebe alten Bereich auf
+ pTmpDel = 0;
+ }
+ }
+}
+
+// -------------- Methoden von der SwCrsrShell -------------
+
+SwPaM * SwCrsrShell::CreateCrsr()
+{
+ // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
+ ASSERT( !IsTableMode(), "in Tabellen SSelection" );
+
+ // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
+ // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+
+ // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
+ // vom kopierten Pam aufgehoben wird !!
+
+ // #i75172# to be able to make a complete content swap, i moved this to a method
+ // pNew->Insert( pCurCrsr, 0 );
+ // pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pNew->swapContent(*pCurCrsr);
+
+ pCurCrsr->DeleteMark();
+
+ UpdateCrsr( SwCrsrShell::SCROLLWIN );
+// return pCurCrsr;
+ return pNew;
+}
+
+// loesche den aktuellen Cursor und der folgende wird zum Aktuellen
+
+
+BOOL SwCrsrShell::DestroyCrsr()
+{
+ // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
+ ASSERT( !IsTableMode(), "in Tabellen SSelection" );
+
+ // ist ueberhaupt ein naechtser vorhanden ?
+ if(pCurCrsr->GetNext() == pCurCrsr)
+ return FALSE;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
+ delete pCurCrsr;
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
+ UpdateCrsr();
+ return TRUE;
+}
+
+
+// gebe den aktuellen zurueck
+
+SwPaM* SwCrsrShell::GetCrsr( BOOL bMakeTblCrsr ) const
+{
+ if( pTblCrsr )
+ {
+ if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
+ {
+ // geparkte Cursor werden nicht wieder erzeugt
+ const SwCntntNode* pCNd;
+ if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
+ pTblCrsr->GetMark()->nNode.GetIndex() &&
+ 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->GetFrm() &&
+ 0 != ( pCNd = pTblCrsr->GetCntntNode(FALSE) ) && pCNd->GetFrm())
+ {
+ SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
+ GetLayout()->MakeTblCrsrs( *pTC );
+ }
+ }
+
+ if( pTblCrsr->IsChgd() )
+ {
+ const_cast<SwCrsrShell*>(this)->pCurCrsr =
+ dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
+ }
+ }
+ return pCurCrsr;
+}
+
+
+void SwCrsrShell::StartAction()
+{
+ if( !ActionPend() )
+ {
+ // fuer das Update des Ribbon-Bars merken
+ const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
+ nAktNode = rNd.GetIndex();
+ nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
+ nAktNdTyp = rNd.GetNodeType();
+ bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
+ if( ND_TEXTNODE & nAktNdTyp )
+ nLeftFrmPos = SwCallLink::GetFrm( (SwTxtNode&)rNd, nAktCntnt, TRUE );
+ else
+ nLeftFrmPos = 0;
+ }
+ ViewShell::StartAction(); // zur ViewShell
+}
+
+
+void SwCrsrShell::EndAction( const BOOL bIdleEnd )
+{
+/*
+//OS: Wird z.B. eine Basic-Action im Hintergrund ausgefuehrt, geht es so nicht
+ if( !bHasFocus )
+ {
+ // hat die Shell nicht den Focus, dann nur das EndAction an
+ // die ViewShell weitergeben.
+ ViewShell::EndAction( bIdleEnd );
+ return;
+ }
+*/
+
+ BOOL bVis = bSVCrsrVis;
+
+ // Idle-Formatierung ?
+ if( bIdleEnd && Imp()->GetRegion() )
+ {
+ pCurCrsr->Hide();
+
+#ifdef SHOW_IDLE_REGION
+if( GetWin() )
+{
+ GetWin()->Push();
+ GetWin()->ChangePen( Pen( Color( COL_YELLOW )));
+ for( USHORT n = 0; n < aPntReg.Count(); ++n )
+ {
+ SwRect aIRect( aPntReg[n] );
+ GetWin()->DrawRect( aIRect.SVRect() );
+ }
+ GetWin()->Pop();
+}
+#endif
+
+ }
+
+ // vor der letzten Action alle invaliden Numerierungen updaten
+ if( 1 == nStartAction )
+ GetDoc()->UpdateNumRule();
+
+ // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
+ // Only the UpdateCrsr shows the cursor.
+ BOOL bSavSVCrsrVis = bSVCrsrVis;
+ bSVCrsrVis = FALSE;
+
+ ViewShell::EndAction( bIdleEnd ); //der ViewShell den Vortritt lassen
+
+ bSVCrsrVis = bSavSVCrsrVis;
+
+ if( ActionPend() )
+ {
+ if( bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+
+ // falls noch ein ChgCall vorhanden ist und nur noch die Basic
+ // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
+ // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
+ if( !BasicActionPend() )
+ {
+ //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction
+ // der Cursor geupdatet werden; um z.B. den
+ // TabellenCursor zu erzeugen. Im UpdateCrsr wird
+ // das jetzt beruecksichtigt!
+ UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
+
+ {
+ // Crsr-Moves ueberwachen, evt. Link callen
+ // der DTOR ist das interressante!!
+ SwCallLink aLk( *this, nAktNode, nAktCntnt, (BYTE)nAktNdTyp,
+ nLeftFrmPos, bAktSelection );
+
+ }
+ if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
+ {
+ aChgLnk.Call( this );
+ bChgCallFlag = FALSE; // Flag zuruecksetzen
+ }
+ }
+ return;
+ }
+
+ USHORT nParm = SwCrsrShell::CHKRANGE;
+ if ( !bIdleEnd )
+ nParm |= SwCrsrShell::SCROLLWIN;
+ UpdateCrsr( nParm, bIdleEnd ); // Cursor-Aenderungen anzeigen
+
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ aLk.nNode = nAktNode; // evt. Link callen
+ aLk.nNdTyp = (BYTE)nAktNdTyp;
+ aLk.nCntnt = nAktCntnt;
+ aLk.nLeftFrmPos = nLeftFrmPos;
+
+ if( !nCrsrMove ||
+ ( 1 == nCrsrMove && bInCMvVisportChgd ) )
+ ShowCrsrs( bSVCrsrVis ? TRUE : FALSE ); // Cursor & Selektionen wieder anzeigen
+ }
+ // falls noch ein ChgCall vorhanden ist, dann rufe ihn
+ if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
+ {
+ aChgLnk.Call( this );
+ bChgCallFlag = FALSE; // Flag zuruecksetzen
+ }
+}
+
+
+#if defined(DBG_UTIL)
+
+void SwCrsrShell::SttCrsrMove()
+{
+ ASSERT( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
+ ++nCrsrMove;
+ StartAction();
+}
+
+void SwCrsrShell::EndCrsrMove( const BOOL bIdleEnd )
+{
+ ASSERT( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
+ EndAction( bIdleEnd );
+ if( !--nCrsrMove )
+ bInCMvVisportChgd = FALSE;
+}
+
+#endif
+
+
+BOOL SwCrsrShell::LeftRight( BOOL bLeft, USHORT nCnt, USHORT nMode,
+ BOOL bVisualAllowed )
+{
+ if( IsTableMode() )
+ return bLeft ? GoPrevCell() : GoNextCell();
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ BOOL bRet = FALSE;
+
+ // #i27615# Handle cursor in front of label.
+ const SwTxtNode* pTxtNd = 0;
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ //
+ // 1. CASE: Cursor is in front of label. A move to the right
+ // will simply reset the bInFrontOfLabel flag:
+ //
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
+ {
+ SetInFrontOfLabel( FALSE );
+ bRet = TRUE;
+ }
+ //
+ // 2. CASE: Cursor is at beginning of numbered paragraph. A move
+ // to the left will simply set the bInFrontOfLabel flag:
+ //
+ else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
+ !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
+ 0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
+ pTxtNd->HasVisibleNumberingOrBullet() )
+ {
+ SetInFrontOfLabel( TRUE );
+ bRet = TRUE;
+ }
+ //
+ // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
+ //
+ else
+ {
+ const BOOL bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
+ // --> OD 2009-12-30 #i107447#
+ // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
+ // reflected in the return value <bRet>.
+ const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( FALSE );
+ bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
+ bSkipHidden, !IsOverwriteCrsr() );
+ if ( !bRet && bLeft && bResetOfInFrontOfLabel )
+ {
+ // undo reset of <bInFrontOfLabel> flag
+ SetInFrontOfLabel( TRUE );
+ }
+ // <--
+ }
+
+ if( bRet )
+ {
+ UpdateCrsr();
+ }
+ return bRet;
+}
+
+// --> OD 2008-04-02 #refactorlists#
+void SwCrsrShell::MarkListLevel( const String& sListId,
+ const int nListLevel )
+{
+ if ( sListId != sMarkedListId ||
+ nListLevel != nMarkedListLevel)
+ {
+ if ( sMarkedListId.Len() > 0 )
+ pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, FALSE );
+
+ if ( sListId.Len() > 0 )
+ {
+ pDoc->MarkListLevel( sListId, nListLevel, TRUE );
+ }
+
+ sMarkedListId = sListId;
+ nMarkedListLevel = nListLevel;
+ }
+}
+
+void SwCrsrShell::UpdateMarkedListLevel()
+{
+ SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
+
+ if ( pTxtNd )
+ {
+ if ( !pTxtNd->IsNumbered() )
+ {
+ pCurCrsr->_SetInFrontOfLabel( FALSE );
+ MarkListLevel( String(), 0 );
+ }
+ else if ( pCurCrsr->IsInFrontOfLabel() )
+ {
+ if ( pTxtNd->IsInList() )
+ {
+ ASSERT( pTxtNd->GetActualListLevel() >= 0 &&
+ pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?")
+ MarkListLevel( pTxtNd->GetListId(),
+ pTxtNd->GetActualListLevel() );
+ }
+ }
+ else
+ {
+ MarkListLevel( String(), 0 );
+ }
+ }
+}
+// <--
+
+BOOL SwCrsrShell::UpDown( BOOL bUp, USHORT nCnt )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ BOOL bTableMode = IsTableMode();
+ SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+
+ BOOL bRet = pTmpCrsr->UpDown( bUp, nCnt );
+ // --> FME 2005-01-10 #i40019# UpDown should always reset the
+ // bInFrontOfLabel flag:
+ bRet = SetInFrontOfLabel(FALSE) || bRet;
+ // <--
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ if( bRet )
+ {
+ eMvState = MV_UPDOWN; // Status fuers Crsr-Travelling - GetCrsrOfst
+ if( !ActionPend() )
+ {
+ CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
+ if( !bTableMode )
+ eUpdtMode = (CrsrFlag) (eUpdtMode
+ | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
+ UpdateCrsr( static_cast<USHORT>(eUpdtMode) );
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::LRMargin( BOOL bLeft, BOOL bAPI)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SET_CURR_SHELL( this );
+ eMvState = MV_LEFTMARGIN; // Status fuers Crsr-Travelling - GetCrsrOfst
+
+ const BOOL bTableMode = IsTableMode();
+ SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ const BOOL bWasAtLM =
+ ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
+
+ BOOL bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
+
+ if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
+ {
+ const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
+ if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
+ SetInFrontOfLabel( TRUE );
+ }
+ else if ( !bLeft )
+ {
+ bRet = SetInFrontOfLabel( FALSE ) || bRet;
+ }
+
+ if( bRet )
+ {
+ UpdateCrsr();
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::IsAtLRMargin( BOOL bLeft, BOOL bAPI ) const
+{
+ const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+ return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
+}
+
+
+BOOL SwCrsrShell::SttEndDoc( BOOL bStt )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
+ BOOL bRet = pTmpCrsr->SttEndDoc( bStt );
+ if( bRet )
+ {
+ if( bStt )
+ pTmpCrsr->GetPtPos().Y() = 0; // expl. 0 setzen (TabellenHeader)
+ if( pBlockCrsr )
+ {
+ pBlockCrsr->clearPoints();
+ RefreshBlockCursor();
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+void SwCrsrShell::ExtendedSelectAll()
+{
+ SwNodes& rNodes = GetDoc()->GetNodes();
+ SwPosition* pPos = pCurCrsr->GetPoint();
+ pPos->nNode = rNodes.GetEndOfPostIts();
+ pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
+ pPos = pCurCrsr->GetMark();
+ pPos->nNode = rNodes.GetEndOfContent();
+ SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
+ pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
+}
+
+BOOL SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
+{
+ BOOL bRet = FALSE;
+
+ // Springe beim Selektieren nie ueber Section-Grenzen !!
+ if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SET_CURR_SHELL( this );
+
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ Point& rPt = pCurCrsr->GetPtPos();
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
+ GetFrm( &rPt, pCurCrsr->GetPoint() );
+ if( pFrm && TRUE == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
+ fnPosPage, pCurCrsr ) ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
+ UpdateCrsr();
+ else
+ bRet = FALSE;
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCursor* pTmpCrsr = getShellCrsr( true );
+ BOOL bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
+ SwPosSection fnPosSect)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCursor* pTmpCrsr = getShellCrsr( true );
+ BOOL bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+
+}
+
+
+// Positionieren des Cursors
+
+
+SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
+{
+ SwFrm* pFrm = 0;
+ SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ pFrm = pCNd->GetFrm( &rPt, 0, FALSE )->GetUpper();
+ while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
+ pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
+ : pFrm->GetUpper();
+ }
+ return pFrm;
+}
+
+BOOL SwCrsrShell::IsInHeaderFooter( BOOL* pbInHeader ) const
+{
+ Point aPt;
+ SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
+ if( pFrm && pbInHeader )
+ *pbInHeader = pFrm->IsHeaderFrm();
+ return 0 != pFrm;
+}
+
+int SwCrsrShell::SetCrsr( const Point &rLPt, BOOL bOnlyText, bool bBlock )
+{
+ SET_CURR_SHELL( this );
+
+ SwShellCrsr* pCrsr = getShellCrsr( bBlock );
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( rLPt );
+ Point & rAktCrsrPt = pCrsr->GetPtPos();
+ SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
+ bOnlyText ? MV_SETONLYTEXT : MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
+
+ if ( pTxtNd && !IsTableMode() &&
+ // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
+ !pCrsr->HasMark() &&
+ // <--
+ pTxtNd->HasVisibleNumberingOrBullet() )
+ {
+ aTmpState.bInFrontOfLabel = TRUE; // #i27615#
+ }
+ else
+ {
+ aTmpState.bInFrontOfLabel = FALSE;
+ }
+
+ int bRet = CRSR_POSOLD |
+ ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
+ ? 0 : CRSR_POSCHG );
+
+ const bool bOldInFrontOfLabel = IsInFrontOfLabel();
+ const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
+
+ pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
+
+ if( MV_RIGHTMARGIN == aTmpState.eState )
+ eMvState = MV_RIGHTMARGIN;
+ // steht neu Pos im Header/Footer ?
+ SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
+ if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
+ pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
+ // gleiche Tabellenzelle und nicht im Header/Footer
+ // -> zurueck
+ return bRet;
+
+ if( pBlockCrsr && bBlock )
+ {
+ pBlockCrsr->setEndPoint( rLPt );
+ if( !pCrsr->HasMark() )
+ pBlockCrsr->setStartPoint( rLPt );
+ else if( !pBlockCrsr->getStartPoint() )
+ pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
+ }
+ if( !pCrsr->HasMark() )
+ {
+ // steht an der gleichen Position und wenn im Header/Footer,
+ // dann im gleichen
+ if( aPos == *pCrsr->GetPoint() &&
+ bOldInFrontOfLabel == bNewInFrontOfLabel )
+ {
+ if( pFrm )
+ {
+ if( pFrm->Frm().IsInside( rAktCrsrPt ))
+ return bRet;
+ }
+ else if( aPos.nNode.GetNode().IsCntntNode() )
+ {
+ // im gleichen Frame gelandet?
+ SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).GetFrm(
+ &aCharRect.Pos(), 0, FALSE );
+ SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).GetFrm(
+ &aPt, 0, FALSE );
+ if( pNew == pOld )
+ return bRet;
+ }
+ }
+ }
+ else
+ {
+ // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
+ // dann in verschiedene
+ if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, TRUE )
+ || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
+ return bRet;
+
+ // steht an der gleichen Position und nicht im Header/Footer
+ if( aPos == *pCrsr->GetPoint() )
+ return bRet;
+ }
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ *pCrsr->GetPoint() = aPos;
+ rAktCrsrPt = aPt;
+
+ // --> FME 2005-01-31 #i41424# Only update the marked number levels if necessary
+ // Force update of marked number levels if necessary.
+ if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
+ pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
+ SetInFrontOfLabel( bNewInFrontOfLabel );
+ // <--
+
+ if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ {
+ USHORT nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
+ UpdateCrsr( nFlag );
+ bRet &= ~CRSR_POSOLD;
+ }
+ else if( bOnlyText && !pCurCrsr->HasMark() )
+ {
+ if( FindValidCntntNode( bOnlyText ) )
+ {
+ // Cursor in einen gueltigen Content stellen
+ if( aPos == *pCrsr->GetPoint() )
+ bRet = CRSR_POSOLD;
+ else
+ {
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
+ bRet &= ~CRSR_POSOLD;
+ }
+ }
+ else
+ {
+ // es gibt keinen gueltigen Inhalt -> Cursor verstecken
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = TRUE;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( TRUE );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ }
+ }
+
+ return bRet;
+}
+
+
+void SwCrsrShell::TblCrsrToCursor()
+{
+ ASSERT( pTblCrsr, "TblCrsrToCursor: Why?" );
+ delete pTblCrsr, pTblCrsr = 0;
+}
+
+void SwCrsrShell::BlockCrsrToCrsr()
+{
+ ASSERT( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
+ if( pBlockCrsr && !HasSelection() )
+ {
+ SwPaM& rPam = pBlockCrsr->getShellCrsr();
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetPoint() = *rPam.GetPoint();
+ if( rPam.HasMark() )
+ *pCurCrsr->GetMark() = *rPam.GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ }
+ delete pBlockCrsr, pBlockCrsr = 0;
+}
+
+void SwCrsrShell::CrsrToBlockCrsr()
+{
+ if( !pBlockCrsr )
+ {
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ pBlockCrsr = createBlockCursor( *this, aPos );
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ rBlock.GetPtPos() = pCurCrsr->GetPtPos();
+ if( pCurCrsr->HasMark() )
+ {
+ rBlock.SetMark();
+ *rBlock.GetMark() = *pCurCrsr->GetMark();
+ rBlock.GetMkPos() = pCurCrsr->GetMkPos();
+ }
+ }
+ pBlockCrsr->clearPoints();
+ RefreshBlockCursor();
+}
+
+void SwCrsrShell::ClearMark()
+{
+ // ist ueberhaupt ein GetMark gesetzt ?
+ if( pTblCrsr )
+ {
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pTblCrsr->DeleteMark();
+
+ if( pCurCrsr->HasMark() )
+ {
+ // falls doch nicht alle Indizies richtig verschoben werden
+ // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
+ // Mark aufs Nodes-Array setzen
+ SwPosition& rPos = *pCurCrsr->GetMark();
+ rPos.nNode.Assign( pDoc->GetNodes(), 0 );
+ rPos.nContent.Assign( 0, 0 );
+ pCurCrsr->DeleteMark();
+ }
+
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr, pTblCrsr = 0;
+ pCurCrsr->SwSelPaintRects::Show();
+ }
+ else
+ {
+ if( !pCurCrsr->HasMark() )
+ return;
+ // falls doch nicht alle Indizies richtig verschoben werden
+ // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
+ // Mark aufs Nodes-Array setzen
+ SwPosition& rPos = *pCurCrsr->GetMark();
+ rPos.nNode.Assign( pDoc->GetNodes(), 0 );
+ rPos.nContent.Assign( 0, 0 );
+ pCurCrsr->DeleteMark();
+ if( !nCrsrMove )
+ pCurCrsr->SwSelPaintRects::Show();
+ }
+}
+
+
+void SwCrsrShell::NormalizePam(BOOL bPointFirst)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->Normalize(bPointFirst);
+}
+
+void SwCrsrShell::SwapPam()
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->Exchange();
+}
+
+
+// suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
+// den angebenen SPoint umschliesst
+// Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
+// SSelection besteht; des akt. Cursr wird nicht umgesetzt!
+// Ansonsten wird er auf die gewaehlte SSelection gesetzt.
+
+
+BOOL SwCrsrShell::ChgCurrPam( const Point & rPt,
+ BOOL bTstOnly, BOOL bTstHit )
+{
+ SET_CURR_SHELL( this );
+
+ // Pruefe ob der SPoint in einer Tabellen-Selektion liegt
+ if( bTstOnly && pTblCrsr )
+ return pTblCrsr->IsInside( rPt );
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ // Suche die Position rPt im Dokument
+ SwPosition aPtPos( *pCurCrsr->GetPoint() );
+ Point aPt( rPt );
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
+ return FALSE;
+
+ // suche in allen Selektionen nach dieser Position
+ SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr; // sicher den Pointer auf Cursor
+ do {
+ if( pCmp->HasMark() &&
+ *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
+ {
+ if( bTstOnly || pCurCrsr == pCmp ) // ist der aktuelle.
+ return TRUE; // return ohne Update
+
+ pCurCrsr = pCmp;
+ UpdateCrsr(); // Cursor steht schon richtig
+ return TRUE;
+ }
+ } while( pCurCrsr !=
+ ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
+ return FALSE;
+}
+
+
+void SwCrsrShell::KillPams()
+{
+ // keiner zum loeschen vorhanden?
+ if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
+ return;
+
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pCurCrsr->SetColumnSelection( false );
+
+ if( pTblCrsr )
+ {
+ // Cursor Ring loeschen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr;
+ pTblCrsr = 0;
+ }
+ else if( pBlockCrsr )
+ {
+ // delete the ring of cursors
+ pCurCrsr->DeleteMark();
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ *pCurCrsr->GetPoint() = *rBlock.GetPoint();
+ pCurCrsr->GetPtPos() = rBlock.GetPtPos();
+ rBlock.DeleteMark();
+ pBlockCrsr->clearPoints();
+ }
+ UpdateCrsr( SwCrsrShell::SCROLLWIN );
+}
+
+
+int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
+{
+ int nRet = 0;
+ const SwPosition *pFirst = 0, *pSecond = 0;
+ const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
+ if( CurrPtCurrMk != eType && pStk )
+ {
+ switch ( eType)
+ {
+ case StackPtStackMk:
+ pFirst = pStk->GetPoint();
+ pSecond = pStk->GetMark();
+ break;
+ case StackPtCurrPt:
+ pFirst = pStk->GetPoint();
+ pSecond = pCur->GetPoint();
+ break;
+ case StackPtCurrMk:
+ pFirst = pStk->GetPoint();
+ pSecond = pCur->GetMark();
+ break;
+ case StackMkCurrPt:
+ pFirst = pStk->GetMark();
+ pSecond = pCur->GetPoint();
+ break;
+ case StackMkCurrMk:
+ pFirst = pStk->GetMark();
+ pSecond = pStk->GetMark();
+ break;
+ case CurrPtCurrMk:
+ pFirst = pCur->GetPoint();
+ pSecond = pCur->GetMark();
+ break;
+ }
+ }
+ if( !pFirst || !pSecond )
+ nRet = INT_MAX;
+ else if( *pFirst < *pSecond )
+ nRet = -1;
+ else if( *pFirst == *pSecond )
+ nRet = 0;
+ else
+ nRet = 1;
+ return nRet;
+}
+
+
+BOOL SwCrsrShell::IsSttPara() const
+{ return( pCurCrsr->GetPoint()->nContent == 0 ? TRUE : FALSE ); }
+
+
+BOOL SwCrsrShell::IsEndPara() const
+{ return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? TRUE : FALSE ); }
+
+
+BOOL SwCrsrShell::IsInFrontOfLabel() const
+{
+ return pCurCrsr->IsInFrontOfLabel();
+}
+
+bool SwCrsrShell::SetInFrontOfLabel( BOOL bNew )
+{
+ if ( bNew != IsInFrontOfLabel() )
+ {
+ pCurCrsr->_SetInFrontOfLabel( bNew );
+ UpdateMarkedListLevel();
+ return true;
+ }
+ return false;
+}
+
+BOOL SwCrsrShell::GotoPage( USHORT nPage )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ BOOL bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+void SwCrsrShell::GetPageNum( USHORT &rnPhyNum, USHORT &rnVirtNum,
+ BOOL bAtCrsrPos, const BOOL bCalcFrm )
+{
+ SET_CURR_SHELL( this );
+ // Seitennummer: die erste sichtbare Seite oder die am Cursor
+ const SwCntntFrm* pCFrm;
+ const SwPageFrm *pPg = 0;
+
+ if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
+ 0 == (pPg = pCFrm->FindPageFrm()) )
+ {
+ pPg = Imp()->GetFirstVisPage();
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
+ // standard.vor sein.
+ rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
+ rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
+}
+
+
+USHORT SwCrsrShell::GetNextPrevPageNum( BOOL bNext )
+{
+ SET_CURR_SHELL( this );
+
+ // Seitennummer: die erste sichtbare Seite oder die am Cursor
+ const SwPageFrm *pPg = Imp()->GetFirstVisPage();
+ if( pPg )
+ {
+ const SwTwips nPageTop = pPg->Frm().Top();
+
+ if( bNext )
+ {
+ // go to next view layout row:
+ do
+ {
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ while( pPg && pPg->Frm().Top() == nPageTop );
+
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ else
+ {
+ // go to previous view layout row:
+ do
+ {
+ pPg = (const SwPageFrm *)pPg->GetPrev();
+ }
+ while( pPg && pPg->Frm().Top() == nPageTop );
+
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetPrev();
+ }
+ }
+ // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
+ // standard.vor sein.
+ return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
+}
+
+
+USHORT SwCrsrShell::GetPageCnt()
+{
+ SET_CURR_SHELL( this );
+ // gebe die Anzahl der Seiten zurueck
+ return GetLayout()->GetPageNum();
+}
+
+// Gehe zur naechsten SSelection
+
+
+BOOL SwCrsrShell::GoNextCrsr()
+{
+ // besteht ueberhaupt ein Ring ?
+ if( pCurCrsr->GetNext() == pCurCrsr )
+ return FALSE;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
+
+ // Bug 24086: auch alle anderen anzeigen
+ if( !ActionPend() )
+ {
+ UpdateCrsr();
+ pCurCrsr->Show();
+ }
+ return TRUE;
+}
+
+// gehe zur vorherigen SSelection
+
+
+BOOL SwCrsrShell::GoPrevCrsr()
+{
+ // besteht ueberhaupt ein Ring ?
+ if( pCurCrsr->GetNext() == pCurCrsr )
+ return FALSE;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
+
+ // Bug 24086: auch alle anderen anzeigen
+ if( !ActionPend() )
+ {
+ UpdateCrsr();
+ pCurCrsr->Show();
+ }
+
+ return TRUE;
+}
+
+
+void SwCrsrShell::Paint( const Rectangle &rRect)
+{
+ SET_CURR_SHELL( this );
+
+ // beim Painten immer alle Cursor ausschalten
+ SwRect aRect( rRect );
+
+ BOOL bVis = FALSE;
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ???
+ {
+ bVis = TRUE;
+ pVisCrsr->Hide();
+ }
+
+ // Bereich neu painten
+ ViewShell::Paint( rRect );
+
+ if( bHasFocus && !bBasicHideCrsr )
+ {
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+// pAktCrsr->Invalidate( aRect );
+ if( !ActionPend() )
+ {
+ // damit nicht rechts/unten die Raender abgeschnitten werden
+ pAktCrsr->Invalidate( VisArea() );
+ pAktCrsr->Show();
+ }
+ else
+ pAktCrsr->Invalidate( aRect );
+
+ }
+ if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+}
+
+
+
+void SwCrsrShell::VisPortChgd( const SwRect & rRect )
+{
+ SET_CURR_SHELL( this );
+ BOOL bVis; // beim Scrollen immer alle Cursor ausschalten
+
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( TRUE == ( bVis = pVisCrsr->IsVisible() ))
+ pVisCrsr->Hide();
+
+ bVisPortChgd = TRUE;
+ aOldRBPos.X() = VisArea().Right();
+ aOldRBPos.Y() = VisArea().Bottom();
+
+ //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
+ //ViewShell::VisPo.. ein Update() auf das Window gerufen.
+ //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
+ //angezeigt werden, deshalb wird der Aufruf hier geklammert.
+ ViewShell::VisPortChgd( rRect ); // Bereich verschieben
+
+/*
+ SwRect aRect( rRect );
+ if( VisArea().IsOver( aRect ) )
+ pCurCrsr->Invalidate( aRect );
+*/
+
+ if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+
+ if( nCrsrMove )
+ bInCMvVisportChgd = TRUE;
+
+ bVisPortChgd = FALSE;
+}
+
+// aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
+// Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
+// Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
+// ergibt sich aus seiner aktuellen Position im Layout !!
+
+
+void SwCrsrShell::UpdateCrsrPos()
+{
+ SET_CURR_SHELL( this );
+ ++nStartAction;
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ Size aOldSz( GetDocSize() );
+ SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
+ SwCntntFrm *pFrm = pCNode ?
+ pCNode->GetFrm( &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint() ) :0;
+ if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
+ &aTmpState );
+ if( pShellCrsr->HasMark())
+ pShellCrsr->DeleteMark();
+ }
+ IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
+ if( pGrammarContact )
+ pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
+ --nStartAction;
+ if( aOldSz != GetDocSize() )
+ SizeChgNotify();
+}
+
+// JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
+// stehen, so mussen diese daraus verschoben werden
+static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
+{
+ const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
+ if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
+ {
+ SwNodeIndex aTmp( *pSectNd );
+#if OSL_DEBUG_LEVEL > 1
+ const SwNode* pFrmNd =
+#endif
+ rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
+
+#if OSL_DEBUG_LEVEL > 1
+ (void) pFrmNd;
+ ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
+#endif
+ rIdx = aTmp;
+ }
+}
+
+// Try to set the cursor to the next visible content node.
+static void lcl_CheckHiddenPara( SwPosition& rPos )
+{
+ SwNodeIndex aTmp( rPos.nNode );
+ SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
+ while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
+ {
+ SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
+ if ( pCntnt && pCntnt->IsTxtNode() )
+ pTxtNd = (SwTxtNode*)pCntnt;
+ else
+ pTxtNd = 0;
+ }
+
+ if ( pTxtNd )
+ rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
+}
+
+// --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
+// about invalid text selections in its destructor
+class SwNotifyAccAboutInvalidTextSelections
+{
+ private:
+ SwCrsrShell& mrCrsrSh;
+
+ public:
+ SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
+ : mrCrsrSh( _rCrsrSh )
+ {}
+
+ ~SwNotifyAccAboutInvalidTextSelections()
+ {
+ mrCrsrSh.InvalidateAccessibleParaTextSelection();
+ }
+};
+// <--
+void SwCrsrShell::UpdateCrsr( USHORT eFlags, BOOL bIdleEnd )
+{
+ SET_CURR_SHELL( this );
+
+ ClearUpCrsrs();
+
+ // erfrage den Count fuer die Start-/End-Actions und ob die Shell
+ // ueberhaupt den Focus hat
+// if( ActionPend() /*|| !bHasFocus*/ )
+ //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
+ // Cursor geupdatet werden; um z.B. den TabellenCursor zu
+ // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
+ if( ActionPend() && BasicActionPend() )
+ {
+ if ( eFlags & SwCrsrShell::READONLY )
+ bIgnoreReadonly = TRUE;
+ return; // wenn nicht, dann kein Update !!
+ }
+
+ // --> OD 2005-12-14 #i27301#
+ SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
+ // <--
+
+ if ( bIgnoreReadonly )
+ {
+ bIgnoreReadonly = FALSE;
+ eFlags |= SwCrsrShell::READONLY;
+ }
+
+ if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf
+ CheckRange( pCurCrsr ); // ueberlappende Bereiche testen
+
+ if( !bIdleEnd )
+ CheckTblBoxCntnt();
+
+ // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
+ // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
+ SwPaM* pTstCrsr = getShellCrsr( true );
+ if( pTstCrsr->HasMark() && !pBlockCrsr &&
+ pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
+ ( pTblCrsr ||
+ pTstCrsr->GetNode( TRUE )->StartOfSectionNode() !=
+ pTstCrsr->GetNode( FALSE )->StartOfSectionNode() ) )
+ {
+ SwShellCrsr* pITmpCrsr = getShellCrsr( true );
+ Point aTmpPt( pITmpCrsr->GetPtPos() );
+ Point aTmpMk( pITmpCrsr->GetMkPos() );
+ SwPosition* pPos = pITmpCrsr->GetPoint();
+
+ // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
+ // stehen, so mussen diese daraus verschoben werden
+ lcl_CheckHiddenSection( pPos->nNode );
+ lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
+
+ // Move cursor out of hidden paragraphs
+ if ( !GetViewOptions()->IsShowHiddenChar() )
+ {
+ lcl_CheckHiddenPara( *pPos );
+ lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
+ }
+
+ SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
+ GetFrm( &aTmpPt, pPos );
+
+ ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
+
+ // --> FME 2005-12-02 #126107# Make code robust. The table
+ // cursor may point to a table in a currently inactive header.
+ SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
+ // <--
+
+ if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
+ {
+ // First check if point is in repeated headline:
+ bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
+
+ // Second check if mark is in repeated headline:
+ if ( !bInRepeatedHeadline )
+ {
+ SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( FALSE )->GetFrm( &aTmpMk, pITmpCrsr->GetMark() );
+ ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
+
+ if ( pMarkTblFrm )
+ {
+ SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
+ ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
+
+ // --> FME 2005-11-28 #120360# Make code robust:
+ if ( pMarkTab )
+ {
+ bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
+ }
+ // <--
+ }
+ }
+
+ // No table cursor in repeaded headlines:
+ if ( bInRepeatedHeadline )
+ {
+ pTblFrm = 0;
+
+ SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
+ ? fnSectionStart
+ : fnSectionEnd;
+
+ // dann nur innerhalb der Box selektieren
+ if( pTblCrsr )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
+ pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
+ pTblCrsr->DeleteMark();
+ pTblCrsr->SwSelPaintRects::Hide();
+ }
+
+ *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
+ (*fnSectionCurr)( *pCurCrsr, fnPosSect );
+ }
+ }
+
+ // wir wollen wirklich eine Tabellen-Selektion
+ if( pTab && pTblFrm )
+ {
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this,
+ *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
+ *pPos, aTmpPt );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+
+ CheckTblBoxCntnt();
+ }
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bRealHeight = TRUE;
+ if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
+ {
+ Point aCentrPt( aCharRect.Center() );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
+#ifndef DBG_UTIL
+ pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
+#else
+ if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
+ ASSERT( !this, "GetCharRect failed." );
+#endif
+ }
+// ALIGNRECT( aCharRect );
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ // Curosr in den sichtbaren Bereich scrollen
+ if( (eFlags & SwCrsrShell::SCROLLWIN) &&
+ (HasSelection() || eFlags & SwCrsrShell::READONLY ||
+ !IsCrsrReadonly()) )
+ {
+ SwFrm* pBoxFrm = pTblFrm;
+ while( pBoxFrm && !pBoxFrm->IsCellFrm() )
+ pBoxFrm = pBoxFrm->GetUpper();
+ if( pBoxFrm && pBoxFrm->Frm().HasArea() )
+ MakeVisible( pBoxFrm->Frm() );
+ else
+ MakeVisible( aCharRect );
+ }
+
+ // lasse vom Layout die Crsr in den Boxen erzeugen
+ if( pTblCrsr->IsCrsrMovedUpdt() )
+ GetLayout()->MakeTblCrsrs( *pTblCrsr );
+ if( bHasFocus && !bBasicHideCrsr )
+ pTblCrsr->Show();
+
+ // Cursor-Points auf die neuen Positionen setzen
+ pTblCrsr->GetPtPos().X() = aCharRect.Left();
+ pTblCrsr->GetPtPos().Y() = aCharRect.Top();
+
+ if( bSVCrsrVis )
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
+ -aCharRect.Width() : aCharRect.Height();
+ pVisCrsr->Show(); // wieder anzeigen
+ }
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
+ if( pTblFrm && Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
+ return;
+ }
+ }
+
+ if( pTblCrsr )
+ {
+ // Cursor Ring loeschen
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr, pTblCrsr = 0;
+ }
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+
+ // sind wir vielleicht in einer geschuetzten/versteckten Section ?
+ {
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ BOOL bChgState = TRUE;
+ const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
+ if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() &&
+ ( !pDoc->GetDocShell() ||
+ !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
+ {
+ if( !FindValidCntntNode( !HasDrawView() ||
+ 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
+ {
+ // alles ist geschuetzt / versteckt -> besonderer Mode
+ if( bAllProtect && !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() )
+ bChgState = FALSE;
+ else
+ {
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = TRUE;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( TRUE );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ return;
+ }
+ }
+ }
+ if( bChgState )
+ {
+ BOOL bWasAllProtect = bAllProtect;
+ bAllProtect = FALSE;
+ if( bWasAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( FALSE );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ }
+ }
+
+ UpdateCrsrPos();
+
+ // #100722# The cursor must always point into content; there's some code
+ // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
+ // loops _behind_ the last node in the selection, which always works if you
+ // are in content.) To achieve this, we'll force cursor(s) to point into
+ // content, if UpdateCrsrPos() hasn't already done so.
+ SwPaM* pCmp = pCurCrsr;
+ do
+ {
+ // start will move forwards, end will move backwards
+ bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
+
+ // move point; forward if it's the start, backwards if it's the end
+ if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
+ pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
+ fnGoCntnt );
+
+ // move mark (if exists); forward if it's the start, else backwards
+ if( pCmp->HasMark() )
+ {
+ if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
+ {
+ pCmp->Exchange();
+ pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
+ fnGoCntnt );
+ pCmp->Exchange();
+ }
+ }
+
+ // iterate to next PaM in ring
+ pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
+ }
+ while( pCmp != pCurCrsr );
+
+
+ SwRect aOld( aCharRect );
+ BOOL bFirst = TRUE;
+ SwCntntFrm *pFrm;
+ int nLoopCnt = 100;
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+
+ do {
+ BOOL bAgainst;
+ do {
+ bAgainst = FALSE;
+ pFrm = pShellCrsr->GetCntntNode()->GetFrm(
+ &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint() );
+ // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
+ // erzeugt werden, weil ja mal hier einer vorhanden war !!
+ if ( !pFrm )
+ {
+ do
+ {
+ CalcLayout();
+ pFrm = pShellCrsr->GetCntntNode()->GetFrm(
+ &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint() );
+ } while( !pFrm );
+ }
+ else if ( Imp()->IsIdleAction() )
+ //Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
+ pFrm->PrepareCrsr();
+
+ // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
+ if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
+ ( !Imp()->GetDrawView() ||
+ !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
+ (!pDoc->GetDocShell() ||
+ !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
+ {
+ // dann suche eine gueltige Position
+ BOOL bChgState = TRUE;
+ if( !FindValidCntntNode(!HasDrawView() ||
+ 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
+ {
+ // alles ist geschuetzt / versteckt -> besonderer Mode
+ if( bAllProtect )
+ bChgState = FALSE;
+ else
+ {
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = TRUE;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( TRUE );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ return;
+ }
+ }
+
+ if( bChgState )
+ {
+ BOOL bWasAllProtect = bAllProtect;
+ bAllProtect = FALSE;
+ if( bWasAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( FALSE );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ bAllProtect = FALSE;
+ bAgainst = TRUE; // nochmal den richigen Frm suchen
+ }
+ }
+ } while( bAgainst );
+
+ if( !( eFlags & SwCrsrShell::NOCALRECT ))
+ {
+ SwCrsrMoveState aTmpState( eMvState );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.bRealHeight = TRUE;
+ aTmpState.bRealWidth = IsOverwriteCrsr();
+ aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
+
+ // #i27615#,#i30453#
+ SwSpecialPos aSpecialPos;
+ aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
+ if (pShellCrsr->IsInFrontOfLabel())
+ {
+ aTmpState.pSpecialPos = &aSpecialPos;
+ }
+
+ if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
+ {
+ Point& rPt = pShellCrsr->GetPtPos();
+ rPt = aCharRect.Center();
+ pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
+ }
+// ALIGNRECT( aCharRect );
+
+ if( !pShellCrsr->HasMark() )
+ aCrsrHeight = aTmpState.aRealHeight;
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
+ -aCharRect.Width() : aCharRect.Height();
+ }
+ }
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aCharRect.Height();
+ }
+
+ if( !bFirst && aOld == aCharRect )
+ break;
+
+ // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
+ // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
+ // siehe Bug: 29658
+ if( !--nLoopCnt )
+ {
+ ASSERT( !this, "Endlosschleife? CharRect != OldCharRect ");
+ break;
+ }
+ aOld = aCharRect;
+ bFirst = FALSE;
+
+ // Cursor-Points auf die neuen Positionen setzen
+ pShellCrsr->GetPtPos().X() = aCharRect.Left();
+ pShellCrsr->GetPtPos().Y() = aCharRect.Top();
+
+ if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen
+ {
+ pFrm->Calc();
+ nUpDownX = pFrm->IsVertical() ?
+ aCharRect.Top() - pFrm->Frm().Top() :
+ aCharRect.Left() - pFrm->Frm().Left();
+ }
+
+ // Curosr in den sichtbaren Bereich scrollen
+ if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
+ (HasSelection() || eFlags & SwCrsrShell::READONLY ||
+ !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
+ {
+ //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den
+ // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
+ // gesichert und zurueckgesetzt.
+ BOOL bSav = bSVCrsrVis; bSVCrsrVis = FALSE;
+ MakeSelVisible();
+ bSVCrsrVis = bSav;
+ }
+
+ } while( eFlags & SwCrsrShell::SCROLLWIN );
+
+ if( pBlockCrsr )
+ RefreshBlockCursor();
+
+ if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
+ {
+ if( pTblCrsr )
+ pTblCrsr->SwSelPaintRects::Show();
+ else
+ {
+ pCurCrsr->SwSelPaintRects::Show();
+ if( pBlockCrsr )
+ {
+ SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
+ while( pNxt && pNxt != pCurCrsr )
+ {
+ pNxt->SwSelPaintRects::Show();
+ pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
+ }
+ }
+ }
+ }
+
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
+
+ if( pFrm && Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleCursorPosition( pFrm );
+
+ // switch from blinking cursor to read-only-text-selection cursor
+ static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
+ const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
+ GetCursorBlinkTime();
+
+ if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
+ ( nBlinkTime != nNoBlinkTime ) )
+ {
+ // non blinking cursor in read only - text selection mode
+ AllSettings aSettings = GetOut()->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
+ Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
+ nNoBlinkTime;
+ aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
+ aSettings.SetStyleSettings( aStyleSettings );
+ GetOut()->SetSettings( aSettings );
+ }
+
+ if( bSVCrsrVis )
+ pVisCrsr->Show(); // wieder anzeigen
+}
+
+void SwCrsrShell::RefreshBlockCursor()
+{
+ ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ Point aPt = rBlock.GetPtPos();
+ SwCntntFrm* pFrm = rBlock.GetCntntNode()->GetFrm( &aPt, rBlock.GetPoint() );
+ Point aMk;
+ if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
+ {
+ aPt = *pBlockCrsr->getStartPoint();
+ aMk = *pBlockCrsr->getEndPoint();
+ }
+ else
+ {
+ aPt = rBlock.GetPtPos();
+ if( pFrm )
+ {
+ if( pFrm->IsVertical() )
+ aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
+ else
+ aPt.X() = pFrm->Frm().Left() + GetUpDownX();
+ }
+ aMk = rBlock.GetMkPos();
+ }
+ SwRect aRect( aMk, aPt );
+ aRect.Justify();
+ SwSelectionList aSelList( pFrm );
+
+ if( GetLayout()->FillSelection( aSelList, aRect ) )
+ {
+ SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
+ while( pNxt != pCurCrsr )
+ {
+ delete pNxt;
+ pNxt = (SwCursor*)pCurCrsr->GetNext();
+ }
+
+ std::list<SwPaM*>::iterator pStart = aSelList.getStart();
+ std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
+ ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
+ pCurCrsr->SetMark();
+ --pPam;
+ // If there is only one text portion inside the rectangle, a simple
+ // selection is created
+ if( pPam == pStart )
+ {
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
+ if( (*pPam)->HasMark() )
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ delete *pPam;
+ pCurCrsr->SetColumnSelection( false );
+ }
+ else
+ {
+ // The order of the SwSelectionList has to be preserved but
+ // the order inside the ring created by CreateCrsr() is not like
+ // exspected => First create the selections before the last one
+ // downto the first selection.
+ // At least create the cursor for the last selection
+ --pPam;
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
+ if( (*pPam)->HasMark() )
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ delete *pPam;
+ pCurCrsr->SetColumnSelection( true );
+ while( pPam != pStart )
+ {
+ --pPam;
+
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+ pNew->Insert( pCurCrsr, 0 );
+ pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pCurCrsr->DeleteMark();
+
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
+ if( (*pPam)->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ }
+ else
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetColumnSelection( true );
+ delete *pPam;
+ }
+ {
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+ pNew->Insert( pCurCrsr, 0 );
+ pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pCurCrsr->DeleteMark();
+ }
+ pPam = aSelList.getEnd();
+ --pPam;
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
+ if( (*pPam)->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ }
+ else
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetColumnSelection( true );
+ delete *pPam;
+ }
+ }
+}
+
+// erzeuge eine Kopie vom Cursor und speicher diese im Stack
+
+
+void SwCrsrShell::Push()
+{
+ pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
+ pCurCrsr->GetPtPos(), pCrsrStk );
+
+ if( pCurCrsr->HasMark() )
+ {
+ pCrsrStk->SetMark();
+ *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
+ }
+}
+
+/*
+ * Loescht einen Cursor (gesteuert durch bOldCrsr)
+ * - vom Stack oder ( bOldCrsr = TRUE )
+ * - den aktuellen und der auf dem Stack stehende wird zum aktuellen
+ *
+ * Return: es war auf dem Stack noch einer vorhanden
+ */
+
+
+BOOL SwCrsrShell::Pop( BOOL bOldCrsr )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ // noch weitere vorhanden ?
+ if( 0 == pCrsrStk )
+ return FALSE;
+
+ SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
+
+ // der Nachfolger wird der Aktuelle
+ if( pCrsrStk->GetNext() != pCrsrStk )
+ {
+ pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
+ }
+
+ if( bOldCrsr ) // loesche vom Stack
+ delete pCrsrStk; //
+
+ pCrsrStk = pTmp; // neu zuweisen
+
+ if( !bOldCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // wurde die sichtbare SSelection nicht veraendert
+ if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
+ pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
+ {
+ // "Selektions-Rechtecke" verschieben
+ pCurCrsr->Insert( pOldStk, 0 );
+ pOldStk->Remove( 0, pOldStk->Count() );
+ }
+
+ if( pOldStk->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pOldStk->GetMark();
+ pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
+ }
+ else
+ // keine Selection also alte aufheben und auf die alte Pos setzen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
+ pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
+ delete pOldStk;
+
+ if( !pCurCrsr->IsInProtectTable( TRUE ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ UpdateCrsr(); // akt. Cursor Updaten
+ }
+ return TRUE;
+}
+
+/*
+ * Verbinde zwei Cursor miteinander.
+ * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
+ */
+
+
+void SwCrsrShell::Combine()
+{
+ // noch weitere vorhanden ?
+ if( 0 == pCrsrStk )
+ return;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde
+ {
+#ifndef DBG_UTIL
+ CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, TRUE );
+#else
+ if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, TRUE ))
+ ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
+#endif
+ // kopiere das GetMark
+ if( !pCurCrsr->HasMark() )
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
+ pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
+ }
+
+ SwShellCrsr * pTmp = 0;
+ if( pCrsrStk->GetNext() != pCrsrStk )
+ {
+ pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
+ }
+ delete pCrsrStk;
+ pCrsrStk = pTmp;
+ if( !pCurCrsr->IsInProtectTable( TRUE ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ UpdateCrsr(); // akt. Cursor Updaten
+}
+
+
+void SwCrsrShell::HideCrsrs()
+{
+ if( !bHasFocus || bBasicHideCrsr )
+ return;
+
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( pVisCrsr->IsVisible() )
+ {
+ SET_CURR_SHELL( this );
+ pVisCrsr->Hide();
+ }
+ // hebe die Invertierung der SSelection auf
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ pAktCrsr->Hide();
+}
+
+
+
+void SwCrsrShell::ShowCrsrs( BOOL bCrsrVis )
+{
+ if( !bHasFocus || bAllProtect || bBasicHideCrsr )
+ return;
+
+ SET_CURR_SHELL( this );
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ pAktCrsr->Show();
+
+ if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+}
+
+// Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
+
+
+void SwCrsrShell::ShowCrsr()
+{
+ if( !bBasicHideCrsr )
+ {
+ bSVCrsrVis = TRUE;
+ UpdateCrsr();
+ }
+}
+
+
+void SwCrsrShell::HideCrsr()
+{
+ if( !bBasicHideCrsr )
+ {
+ bSVCrsrVis = FALSE;
+ // evt. die sel. Bereiche aufheben !!
+ SET_CURR_SHELL( this );
+ pVisCrsr->Hide();
+ }
+}
+
+
+void SwCrsrShell::ShLooseFcs()
+{
+ if( !bBasicHideCrsr )
+ HideCrsrs();
+ bHasFocus = FALSE;
+}
+
+
+void SwCrsrShell::ShGetFcs( BOOL bUpdate )
+{
+ bHasFocus = TRUE;
+ if( !bBasicHideCrsr && VisArea().Width() )
+ {
+ UpdateCrsr( static_cast<USHORT>( bUpdate ?
+ SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
+ : SwCrsrShell::CHKRANGE ) );
+ ShowCrsrs( bSVCrsrVis ? TRUE : FALSE );
+ }
+}
+
+// gebe den aktuellen Frame, in dem der Cursor steht, zurueck
+
+SwCntntFrm *SwCrsrShell::GetCurrFrm( const BOOL bCalcFrm ) const
+{
+ SET_CURR_SHELL( (ViewShell*)this );
+ SwCntntFrm *pRet = 0;
+ SwCntntNode *pNd = pCurCrsr->GetCntntNode();
+ if ( pNd )
+ {
+ if ( bCalcFrm )
+ {
+ const USHORT* pST = &nStartAction;
+ ++(*((USHORT*)pST));
+ const Size aOldSz( GetDocSize() );
+ pRet = pNd->GetFrm( &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
+ --(*((USHORT*)pST));
+ if( aOldSz != GetDocSize() )
+ ((SwCrsrShell*)this)->SizeChgNotify();
+ }
+ else
+ pRet = pNd->GetFrm( &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), FALSE);
+ }
+ return pRet;
+}
+
+
+// alle Attribut/Format-Aenderungen am akt. Node werden an den
+// Link weitergeleitet.
+
+
+void SwCrsrShell::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ const USHORT nWhich = pOld ?
+ pOld->Which() :
+ pNew ?
+ pNew->Which() :
+ sal::static_int_cast<USHORT>(RES_MSG_BEGIN);
+
+ if( bCallChgLnk &&
+ ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
+ nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
+ nWhich == RES_ATTRSET_CHG ))
+ // die Messages werden nicht weitergemeldet
+ //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
+ //SwTxtNode::Insert(SwTxtHint*, USHORT) abgesetzt; hier wird reagiert und
+ //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
+ CallChgLnk();
+
+ if( aGrfArrivedLnk.IsSet() &&
+ ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
+ aGrfArrivedLnk.Call( this );
+}
+
+
+// Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
+// also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
+
+
+BOOL SwCrsrShell::HasSelection() const
+{
+ const SwPaM* pCrsr = getShellCrsr( true );
+ return( IsTableMode() || ( pCrsr->HasMark() &&
+ *pCrsr->GetPoint() != *pCrsr->GetMark())
+ ? TRUE : FALSE );
+}
+
+
+void SwCrsrShell::CallChgLnk()
+{
+ // innerhalb von Start-/End-Action kein Call, sondern nur merken,
+ // das sich etwas geaendert hat. Wird bei EndAction beachtet.
+ if( BasicActionPend() )
+ bChgCallFlag = TRUE; // das Change merken
+ else if( aChgLnk.IsSet() )
+ {
+ if( bCallChgLnk )
+ aChgLnk.Call( this );
+ bChgCallFlag = FALSE; // Flag zuruecksetzen
+ }
+}
+
+// returne den am akt.Cursor selektierten Text eines Nodes.
+
+
+String SwCrsrShell::GetSelTxt() const
+{
+ String aTxt;
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() )
+ {
+ SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ {
+ xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
+ aTxt = pTxtNd->GetExpandTxt( nStt,
+ pCurCrsr->End()->nContent.GetIndex() - nStt );
+ }
+ }
+ return aTxt;
+}
+
+// gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
+
+
+String SwCrsrShell::GetText() const
+{
+ String aTxt;
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() )
+ {
+ SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ aTxt = pTxtNd->GetTxt().Copy(
+ pCurCrsr->GetPoint()->nContent.GetIndex() );
+ }
+ return aTxt;
+}
+
+// hole vom Start/Ende der akt. SSelection das nte Zeichen
+sal_Unicode SwCrsrShell::GetChar( BOOL bEnd, long nOffset )
+{
+ if( IsTableMode() ) // im TabelleMode nicht moeglich
+ return 0;
+
+ const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
+ : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return 0;
+
+ xub_StrLen nPos = pPos->nContent.GetIndex();
+ const String& rStr = pTxtNd->GetTxt();
+ sal_Unicode cCh = 0;
+
+ if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
+ cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
+
+ return cCh;
+}
+
+// erweiter die akt. SSelection am Anfang/Ende um n Zeichen
+
+
+BOOL SwCrsrShell::ExtendSelection( BOOL bEnd, xub_StrLen nCount )
+{
+ if( !pCurCrsr->HasMark() || IsTableMode() )
+ return FALSE; // keine Selektion
+
+ SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
+
+ xub_StrLen nPos = pPos->nContent.GetIndex();
+ if( bEnd )
+ {
+ if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
+ nPos = nPos + nCount;
+ else
+ return FALSE; // nicht mehr moeglich
+ }
+ else if( nPos >= nCount )
+ nPos = nPos - nCount;
+ else
+ return FALSE; // nicht mehr moeglich
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+
+ pPos->nContent = nPos;
+ UpdateCrsr();
+
+ return TRUE;
+}
+
+// setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
+// returnt FALSE: wenn der SPoint vom Layout korrigiert wurde.
+
+BOOL SwCrsrShell::SetVisCrsr( const Point &rPt )
+{
+ SET_CURR_SHELL( this );
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.bRealHeight = TRUE;
+
+ BOOL bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
+
+ SetInFrontOfLabel( FALSE ); // #i27615#
+
+ // nur in TextNodes anzeigen !!
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return FALSE;
+
+ const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
+ if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag())) )
+ return FALSE;
+
+ SwCntntFrm *pFrm = pTxtNd->GetFrm( &aPt, &aPos );
+ if ( Imp()->IsIdleAction() )
+ pFrm->PrepareCrsr();
+ SwRect aTmp( aCharRect );
+
+ pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
+// ALIGNRECT( aCharRect );
+
+ if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der
+ pVisCrsr->IsVisible() ) // Position nicht hidden & showen
+ return TRUE;
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ if( IsScrollMDI( this, aCharRect ))
+ {
+ MakeVisible( aCharRect );
+ pCurCrsr->Show();
+ }
+
+ // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
+ // D&D-Cursor will man trotzdem haben
+// if( bSVCrsrVis )
+ {
+ if( aTmpState.bRealHeight )
+ aCrsrHeight = aTmpState.aRealHeight;
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aCharRect.Height();
+ }
+
+ pVisCrsr->SetDragCrsr( TRUE );
+ pVisCrsr->Show(); // wieder anzeigen
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
+{
+ Point aPt( rPt );
+ SwPaM aPam( *pCurCrsr->GetPoint() );
+ GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
+ // --> FME 2004-06-29 #114856# Formular view
+ return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
+ // <--
+}
+
+
+ // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
+ // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
+USHORT SwCrsrShell::GetCrsrCnt( BOOL bAll ) const
+{
+ Ring* pTmp = GetCrsr()->GetNext();
+ USHORT n = (bAll || ( pCurCrsr->HasMark() &&
+ *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
+ while( pTmp != pCurCrsr )
+ {
+ if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
+ *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
+ ++n;
+ pTmp = pTmp->GetNext();
+ }
+ return n;
+}
+
+
+BOOL SwCrsrShell::IsStartOfDoc() const
+{
+ if( pCurCrsr->GetPoint()->nContent.GetIndex() )
+ return FALSE;
+
+ // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
+ SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
+ if( !aIdx.GetNode().IsCntntNode() )
+ GetDoc()->GetNodes().GoNext( &aIdx );
+ return aIdx == pCurCrsr->GetPoint()->nNode;
+}
+
+
+BOOL SwCrsrShell::IsEndOfDoc() const
+{
+ SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
+
+ return aIdx == pCurCrsr->GetPoint()->nNode &&
+ pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
+}
+
+
+// loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
+// Cursor auf seinen TextNode (oder StartNode?).
+// Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
+// Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
+BOOL SwCrsrShell::ParkTblCrsr()
+{
+ if( !pTblCrsr )
+ return FALSE;
+
+ pTblCrsr->ParkCrsr();
+
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+
+ // vom Cursor !immer! SPoint und Mark umsetzen
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->DeleteMark();
+
+ return TRUE;
+}
+
+/***********************************************************************
+#* Class : SwCrsrShell
+#* Methode : ParkCrsr
+#* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der
+#* verbleibende Crsr der Shell wird geparkt.
+#* Datum : MA 05. Nov. 92
+#* Update : JP 19.09.97
+#***********************************************************************/
+
+void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
+{
+ const SwPosition *pStt = pDelRg->Start(),
+ *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
+
+ SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
+
+ // durchsuche den gesamten Ring
+ BOOL bGoNext;
+ do {
+ const SwPosition *pTmpStt = pTmp->Start(),
+ *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
+ pTmp->GetMark() : pTmp->GetPoint();
+ /*
+ * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
+ * muss der alte Bereich aufgehoben werden.
+ * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
+ * Bereich gehoert !
+ */
+ if( *pStt <= *pTmpStt )
+ {
+ if( *pEnd > *pTmpStt ||
+ ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
+ pTmpDel = pTmp;
+ }
+ else
+ if( *pStt < *pTmpEnd )
+ pTmpDel = pTmp;
+
+ bGoNext = TRUE;
+ if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn
+ {
+ BOOL bDelete = TRUE;
+ if( *ppDelRing == pTmpDel )
+ {
+ if( *ppDelRing == pCurCrsr )
+ {
+ if( TRUE == ( bDelete = GoNextCrsr() ))
+ {
+ bGoNext = FALSE;
+ pTmp = (SwPaM*)pTmp->GetNext();
+ }
+ }
+ else
+ bDelete = FALSE; // StackCrsr nie loeschen !!
+ }
+
+ if( bDelete )
+ delete pTmpDel; // hebe alten Bereich auf
+ else
+ {
+ pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
+ pTmpDel->GetPoint()->nNode = 0;
+ pTmpDel->SetMark();
+ pTmpDel->DeleteMark();
+ }
+ pTmpDel = 0;
+ }
+ else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das
+ { // nicht benutzte Indizies beachtet werden!
+ pTmp->SetMark(); // SPoint liegt nicht im Bereich,
+ pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen
+ }
+ if( bGoNext )
+ pTmp = (SwPaM*)pTmp->GetNext();
+ } while( !bGoNext || *ppDelRing != pTmp );
+}
+
+void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
+{
+ SwNode *pNode = &rIdx.GetNode();
+
+ // erzeuge einen neuen Pam
+ SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
+ if( pNode->GetStartNode() )
+ {
+ if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
+ {
+ // der angegebene Node steht in einer Tabelle, also Parke
+ // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
+ pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ }
+ else // also auf dem StartNode selbst.
+ // Dann immer ueber seinen EndNode den StartNode erfragen !!!
+ // (StartOfSection vom StartNode ist der Parent !)
+ pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
+ }
+ else
+ pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ pNew->SetMark();
+ pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
+
+ //Alle Shells wollen etwas davon haben.
+ ViewShell *pTmp = this;
+ do {
+ if( pTmp->IsA( TYPE( SwCrsrShell )))
+ {
+ SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
+ if( pSh->pCrsrStk )
+ pSh->_ParkPams( pNew, &pSh->pCrsrStk );
+
+ pSh->_ParkPams( pNew, &pSh->pCurCrsr );
+ if( pSh->pTblCrsr )
+ {
+ // setze den Tabellen Cursor immer auf 0, den aktuellen
+ // immer auf den Anfang der Tabelle
+ SwPaM* pTCrsr = pSh->GetTblCrs();
+ SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
+ if ( pTblNd )
+ {
+ pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
+ pTCrsr->GetPoint()->nNode = 0;
+ pTCrsr->SetMark();
+ pTCrsr->DeleteMark();
+ pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
+ }
+ }
+ }
+ } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
+ delete pNew;
+}
+
+//=========================================================================
+
+/*
+ * der Copy-Constructor
+ * Cursor-Position kopieren, in den Ring eingetragen.
+ * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
+ */
+
+SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
+ : ViewShell( rShell, pInitWin ),
+ SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
+ pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
+ eMvState( MV_NONE ),
+ // --> OD 2008-04-02 #refactorlists#
+ sMarkedListId(),
+ nMarkedListLevel( 0 )
+ // <--
+{
+ SET_CURR_SHELL( this );
+ // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
+ pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
+ pCurCrsr->GetCntntNode()->Add( this );
+
+ bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
+ bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
+ bOverwriteCrsr = FALSE;
+ bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = TRUE;
+ bSetCrsrInReadOnly = TRUE;
+ pVisCrsr = new SwVisCrsr( this );
+// UpdateCrsr( 0 );
+ // OD 11.02.2003 #100556#
+ mbMacroExecAllowed = rShell.IsMacroExecAllowed();
+}
+
+
+/*
+ * der normale Constructor
+ */
+
+SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
+ const SwViewOption *pInitOpt )
+ : ViewShell( rDoc, pInitWin, pInitOpt ),
+ SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
+ pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
+ eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
+ // --> OD 2008-04-02 #refactorlists#
+ sMarkedListId(),
+ nMarkedListLevel( 0 )
+ // <--
+{
+ SET_CURR_SHELL( this );
+ /*
+ * Erzeugen des initialen Cursors, wird auf die erste
+ * Inhaltsposition gesetzt
+ */
+ SwNodes& rNds = rDoc.GetNodes();
+
+ SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
+ SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
+
+ pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
+
+ // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
+ // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
+ pCNd->Add( this );
+
+ bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
+ bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
+ bOverwriteCrsr = FALSE;
+ bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = TRUE;
+ bSetCrsrInReadOnly = TRUE;
+
+ pVisCrsr = new SwVisCrsr( this );
+// UpdateCrsr( 0 );
+ // OD 11.02.2003 #100556#
+ mbMacroExecAllowed = true;
+}
+
+
+
+SwCrsrShell::~SwCrsrShell()
+{
+ // wenn es nicht die letzte View so sollte zu mindest das
+ // Feld noch geupdatet werden.
+ if( GetNext() != this )
+ CheckTblBoxCntnt( pCurCrsr->GetPoint() );
+ else
+ ClearTblBoxCntnt();
+
+ delete pVisCrsr;
+ delete pBlockCrsr;
+ delete pTblCrsr;
+
+ /*
+ * Freigabe der Cursor
+ */
+ while(pCurCrsr->GetNext() != pCurCrsr)
+ delete pCurCrsr->GetNext();
+ delete pCurCrsr;
+
+ // Stack freigeben
+ if( pCrsrStk )
+ {
+ while( pCrsrStk->GetNext() != pCrsrStk )
+ delete pCrsrStk->GetNext();
+ delete pCrsrStk;
+ }
+
+ // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
+ // der CursorShell haengt keine Chance geben, sich an den
+ // TextNode zu haengen.
+ if( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+}
+
+SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
+{
+ if( pTblCrsr )
+ return pTblCrsr;
+ if( pBlockCrsr && bBlock )
+ return &pBlockCrsr->getShellCrsr();
+ return pCurCrsr;
+}
+
+//Sollte fuer das Clipboard der WaitPtr geschaltet werden?
+//Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
+
+BOOL SwCrsrShell::ShouldWait() const
+{
+ if ( IsTableMode() || GetCrsrCnt() > 1 )
+ return TRUE;
+
+ if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ return TRUE;
+
+ SwPaM* pPam = GetCrsr();
+ return pPam->Start()->nNode.GetIndex() + 10 <
+ pPam->End()->nNode.GetIndex();
+}
+
+
+USHORT SwCrsrShell::UpdateTblSelBoxes()
+{
+ if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
+ GetLayout()->MakeTblCrsrs( *pTblCrsr );
+ return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
+}
+
+// zeige das akt. selektierte "Object" an
+void SwCrsrShell::MakeSelVisible()
+{
+ ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
+ if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
+ {
+ SwRect aTmp( aCharRect );
+ long nDiff = aCharRect.Height() - VisArea().Height();
+ if( nDiff < aCrsrHeight.X() )
+ aTmp.Top( nDiff + aCharRect.Top() );
+ else
+ {
+ aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
+ aTmp.Height( aCrsrHeight.Y() );
+ }
+ if( !aTmp.HasArea() )
+ {
+ aTmp.SSize().Height() += 1;
+ aTmp.SSize().Width() += 1;
+ }
+ MakeVisible( aTmp );
+ }
+ else
+ {
+ if( aCharRect.HasArea() )
+ MakeVisible( aCharRect );
+ else
+ {
+ SwRect aTmp( aCharRect );
+ aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
+ MakeVisible( aTmp );
+ }
+ }
+}
+
+
+// suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
+BOOL SwCrsrShell::FindValidCntntNode( BOOL bOnlyText )
+{
+ if( pTblCrsr ) // was soll ich jetzt machen ??
+ {
+ ASSERT( !this, "TabellenSelection nicht aufgehoben!" );
+ return FALSE;
+ }
+
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ if( !bAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ return TRUE;
+
+ // dann raus da!
+ if( pCurCrsr->HasMark() )
+ ClearMark();
+
+ // als erstes mal auf Rahmen abpruefen
+ SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
+ ULONG nNdIdx = rNdIdx.GetIndex(); // sichern
+ SwNodes& rNds = pDoc->GetNodes();
+ SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
+ const SwCntntFrm * pFrm;
+
+ if( pCNd && 0 != (pFrm = pCNd->GetFrm(0,pCurCrsr->GetPoint(),FALSE)) &&
+ !IsReadOnlyAvailable() && pFrm->IsProtected() &&
+ nNdIdx < rNds.GetEndOfExtras().GetIndex() )
+ {
+ // geschuetzter Rahmen ueberspringen
+ SwPaM aPam( *pCurCrsr->GetPoint() );
+ aPam.SetMark();
+ aPam.GetMark()->nNode = rNds.GetEndOfContent();
+ aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
+
+ BOOL bFirst = FALSE;
+ if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, FALSE )))
+ {
+ aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
+ pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, FALSE );
+ }
+
+ if( !pCNd ) // sollte nie passieren !!!
+ {
+ rNdIdx = nNdIdx; // alten Node zurueck
+ return FALSE;
+ }
+ *pCurCrsr->GetPoint() = *aPam.GetPoint();
+ }
+ else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
+ {
+ // dann auf den Anfang vom Doc stellen
+ rNdIdx = pDoc->GetNodes().GetEndOfExtras();
+ pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
+ &rNdIdx ), 0 );
+ nNdIdx = rNdIdx.GetIndex();
+ }
+
+ BOOL bOk = TRUE;
+
+ // #i9059# cursor may not stand in protected cells
+ // (unless cursor in protected areas is OK.)
+ const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
+ if( !IsReadOnlyAvailable() &&
+ pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
+ {
+ // we're in a table, and we're in a protected area, so we're
+ // probably in a protected cell.
+
+ // move forward into non-protected area.
+ SwPaM aPam( rNdIdx.GetNode(), 0 );
+ while( aPam.GetNode()->IsProtect() &&
+ aPam.Move( fnMoveForward, fnGoCntnt ) )
+ ; // nothing to do in the loop; the aPam.Move does the moving!
+
+ // didn't work? then go backwards!
+ if( aPam.GetNode()->IsProtect() )
+ {
+ SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
+ aPam = aTmpPaM;
+ while( aPam.GetNode()->IsProtect() &&
+ aPam.Move( fnMoveBackward, fnGoCntnt ) )
+ ; // nothing to do in the loop; the aPam.Move does the moving!
+ }
+
+ // if we're successful, set the new position
+ if( ! aPam.GetNode()->IsProtect() )
+ {
+ *pCurCrsr->GetPoint() = *aPam.GetPoint();
+ }
+ }
+
+ // in einem geschuetzten Bereich
+ const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
+ if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() )) )
+ {
+ typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
+ FNGoSection funcGoSection = &SwNodes::GoNextSection;
+
+ bOk = FALSE;
+
+ for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
+ {
+ BOOL bWeiter;
+ do {
+ bWeiter = FALSE;
+ while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
+ TRUE, !IsReadOnlyAvailable() )) )
+ {
+ // in eine Tabelle verschoben -> pruefe ob die
+ // vielleicht geschuetzt ist
+ if( pCNd->FindTableNode() )
+ {
+ SwCallLink aTmp( *this );
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ aTmp.nNdTyp = 0; // im DTOR nichts machen!
+ if( !pCurCrsr->IsInProtectTable( TRUE, TRUE ) )
+ {
+ const SwSectionNode* pSNd = pCNd->FindSectionNode();
+ if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
+ || (!IsReadOnlyAvailable() &&
+ pSNd->GetSection().IsProtectFlag() ))
+ {
+ bOk = TRUE;
+ break; // eine nicht geschuetzte Zelle gef.
+ }
+ continue; // dann weiter suchen
+ }
+ }
+ else
+ {
+ bOk = TRUE;
+ break; // eine nicht geschuetzte Zelle gef.
+ }
+ }
+
+ if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
+ {
+ // Teste mal auf Fly - kann auch noch geschuetzt sein!!
+ if( 0 == (pFrm = pCNd->GetFrm(0,0,FALSE)) ||
+ ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
+ ( bOnlyText && pCNd->IsNoTxtNode() ) )
+ {
+ // dann weiter suchen!
+ bOk = FALSE;
+ bWeiter = TRUE;
+ }
+ }
+ } while( bWeiter );
+
+ if( !bOk )
+ {
+ if( !nLoopCnt )
+ funcGoSection = &SwNodes::GoPrevSection;
+ rNdIdx = nNdIdx;
+ }
+ }
+ }
+ if( bOk )
+ {
+ pCNd = rNdIdx.GetNode().GetCntntNode();
+// USHORT nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
+ xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
+ }
+ else
+ {
+ pCNd = rNdIdx.GetNode().GetCntntNode();
+
+ // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
+ // verschieben!!
+ if( !pCNd || !pCNd->GetFrm(0,0,FALSE) )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
+ &aTmpState );
+ }
+ }
+ return bOk;
+}
+
+
+void SwCrsrShell::NewCoreSelection()
+{
+}
+
+
+BOOL SwCrsrShell::IsCrsrReadonly() const
+{
+ if ( GetViewOptions()->IsReadonly() ||
+ // --> FME 2004-06-29 #114856# Formular view
+ GetViewOptions()->IsFormView() )
+ // <--
+ {
+ SwFrm *pFrm = GetCurrFrm( FALSE );
+ const SwFlyFrm* pFly;
+ const SwSection* pSection;
+
+ if( pFrm && pFrm->IsInFly() &&
+ (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
+ pFly->Lower() &&
+ !pFly->Lower()->IsNoTxtFrm() &&
+ !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ {
+ return FALSE;
+ }
+ // --> FME 2004-06-22 #114856# edit in readonly sections
+ else if ( pFrm && pFrm->IsInSct() &&
+ 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
+ pSection->IsEditInReadonlyFlag() )
+ {
+ return FALSE;
+ }
+ // <--
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// darf der Cursor in ReadOnlyBereiche?
+void SwCrsrShell::SetReadOnlyAvailable( BOOL bFlag )
+{
+ // im GlobalDoc darf NIE umgeschaltet werden
+ if( (!GetDoc()->GetDocShell() ||
+ !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
+ bFlag != bSetCrsrInReadOnly )
+ {
+ // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
+ // Selektionen aufgehoben werden. Denn sonst wird sich darauf
+ // verlassen, das nichts geschuetztes selektiert ist!
+ if( !bFlag )
+ {
+ ClearMark();
+ }
+ bSetCrsrInReadOnly = bFlag;
+ UpdateCrsr();
+ }
+}
+
+BOOL SwCrsrShell::HasReadonlySel() const
+{
+ BOOL bRet = FALSE;
+ if( IsReadOnlyAvailable() ||
+ // --> FME 2004-06-29 #114856# Formular view
+ GetViewOptions()->IsFormView() )
+ // <--
+ {
+ if( pTblCrsr )
+ bRet = pTblCrsr->HasReadOnlyBoxSel() ||
+ pTblCrsr->HasReadonlySel(
+ // --> FME 2004-06-29 #114856# Formular view
+ GetViewOptions()->IsFormView() );
+ // <--
+ else
+ {
+ const SwPaM* pCrsr = pCurCrsr;
+
+ do {
+ if( pCrsr->HasReadonlySel(
+ // --> FME 2004-06-29 #114856# Formular view
+ GetViewOptions()->IsFormView() ) )
+ // <--
+ bRet = TRUE;
+ } while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::IsSelFullPara() const
+{
+ BOOL bRet = FALSE;
+
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
+ {
+ xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
+ nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
+ if( nStt > nEnd )
+ {
+ xub_StrLen nTmp = nStt;
+ nStt = nEnd;
+ nEnd = nTmp;
+ }
+ const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
+ bRet = pCNd && !nStt && nEnd == pCNd->Len();
+ }
+ return bRet;
+}
+
+short SwCrsrShell::GetTextDirection( const Point* pPt ) const
+{
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
+ if( pPt )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
+ }
+
+ return pDoc->GetTextDirection( aPos, &aPt );
+}
+
+BOOL SwCrsrShell::IsInVerticalText( const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( pPt );
+ return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
+}
+
+BOOL SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( pPt );
+ // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
+ // vertical environment
+ return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
+}
+
+//
+// If the current cursor position is inside a hidden range, the hidden range
+// is selected:
+//
+bool SwCrsrShell::SelectHiddenRange()
+{
+ bool bRet = false;
+ if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
+ {
+ SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
+ const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
+ if ( pNode )
+ {
+ const xub_StrLen nPos = rPt.nContent.GetIndex();
+
+ // check if nPos is in hidden range
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
+ if ( STRING_LEN != nHiddenStart )
+ {
+ // make selection:
+ pCurCrsr->SetMark();
+ pCurCrsr->GetMark()->nContent = nHiddenEnd;
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/* */
+
+ // die Suchfunktionen
+ULONG SwCrsrShell::Find( const SearchOptions& rSearchOpt, BOOL bSearchInNotes,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ BOOL& bCancel,
+ FindRanges eRng, int bReplace )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ ULONG nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
+ if( nRet || bCancel )
+ UpdateCrsr();
+ return nRet;
+}
+
+ULONG SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ BOOL& bCancel,
+ FindRanges eRng, const SwTxtFmtColl* pReplFmt )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ ULONG nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
+ if( nRet )
+ UpdateCrsr();
+ return nRet;
+}
+
+ULONG SwCrsrShell::Find( const SfxItemSet& rSet, BOOL bNoCollections,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ BOOL& bCancel,
+ FindRanges eRng, const SearchOptions* pSearchOpt,
+ const SfxItemSet* rReplSet )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ ULONG nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
+ eRng, pSearchOpt, rReplSet );
+ if( nRet )
+ UpdateCrsr();
+ return nRet;
+}
+
+void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
+{
+ StartAction();
+ SwPaM* pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = *rCrsr.GetPoint();
+ if(rCrsr.HasMark())
+ {
+ pCrsr->SetMark();
+ *pCrsr->GetMark() = *rCrsr.GetMark();
+ }
+ if((SwPaM*)rCrsr.GetNext() != &rCrsr)
+ {
+ const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
+ do
+ {
+ SwPaM* pCurrentCrsr = CreateCrsr();
+ *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
+ if(_pStartCrsr->HasMark())
+ {
+ pCurrentCrsr->SetMark();
+ *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
+ }
+ } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
+ }
+ EndAction();
+}
+
+void lcl_RemoveMark( SwPaM* pPam )
+{
+ ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
+ pPam->GetMark()->nContent.Assign( 0, 0 );
+ pPam->GetMark()->nNode = 0;
+ pPam->DeleteMark();
+}
+
+const SwStartNode* lcl_NodeContext( const SwNode& rNode )
+{
+ const SwStartNode *pRet = rNode.StartOfSectionNode();
+ while( pRet->IsSectionNode() || pRet->IsTableNode() ||
+ pRet->GetStartNodeType() == SwTableBoxStartNode )
+ {
+ pRet = pRet->StartOfSectionNode();
+ }
+ return pRet;
+}
+
+/**
+ Checks if a position is valid. To be valid the position's node must
+ be a content node and the content must not be unregistered.
+
+ @param aPos the position to check.
+*/
+bool lcl_PosOk(const SwPosition & aPos)
+{
+ return NULL != aPos.nNode.GetNode().GetCntntNode() &&
+ SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
+}
+
+/**
+ Checks if a PaM is valid. For a PaM to be valid its point must be
+ valid. Additionaly if the PaM has a mark this has to be valid, too.
+
+ @param aPam the PaM to check
+*/
+static bool lcl_CrsrOk(SwPaM & aPam)
+{
+ return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
+ || lcl_PosOk(*aPam.GetMark()));
+}
+
+void SwCrsrShell::ClearUpCrsrs()
+{
+ // start of the ring
+ SwPaM * pStartCrsr = GetCrsr();
+ // start loop with second entry of the ring
+ SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
+ SwPaM * pTmpCrsr;
+ bool bChanged = false;
+
+ /*
+ For all entries in the ring except the start entry delete the
+ entry if it is invalid.
+ */
+ while (pCrsr != pStartCrsr)
+ {
+ pTmpCrsr = (SwPaM *) pCrsr->GetNext();
+
+ if ( ! lcl_CrsrOk(*pCrsr))
+ {
+ delete pCrsr;
+
+ bChanged = true;
+ }
+
+ pCrsr = pTmpCrsr;
+ }
+
+ if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
+ {
+ lcl_RemoveMark( pStartCrsr );
+ bChanged = true;
+ }
+ if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
+ {
+ SwNodes & aNodes = GetDoc()->GetNodes();
+ const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
+ SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
+ SwNode * pNode = aNodes.GoPrevious(&aIdx);
+ if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
+ aNodes.GoNext( &aIdx );
+ if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
+ {
+ /*
+ If the start entry of the ring is invalid replace it with a
+ cursor pointing to the beginning of the first content node in
+ the document.
+ */
+ aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
+ pNode = aNodes.GoNext( &aIdx );
+ }
+ bool bFound = (pNode != NULL);
+
+ ASSERT(bFound, "no content node found");
+
+ if (bFound)
+ {
+ SwPaM aTmpPam(*pNode);
+ *pStartCrsr = aTmpPam;
+ }
+
+ bChanged = true;
+ }
+
+ /*
+ If at least one of the cursors in the ring have been deleted or
+ replaced, remove the table cursor.
+ */
+ if (pTblCrsr != NULL && bChanged)
+ TblCrsrToCursor();
+}
+
+// #111827#
+String SwCrsrShell::GetCrsrDescr() const
+{
+ String aResult;
+
+ if (IsMultiSelection())
+ aResult += String(SW_RES(STR_MULTISEL));
+ else
+ aResult = GetDoc()->GetPaMDescr(*GetCrsr());
+
+ return aResult;
+}
+
+// SMARTTAGS
+
+void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
+{
+ // Insert smart tag information
+ std::vector< rtl::OUString > aSmartTagTypes;
+ std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
+
+ for ( USHORT i = 0; i < rSmartTagList.Count(); ++i )
+ {
+ const xub_StrLen nSTPos = rSmartTagList.Pos( i );
+ const xub_StrLen nSTLen = rSmartTagList.Len( i );
+
+ if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
+ {
+ const SwWrongArea* pArea = rSmartTagList.GetElement( i );
+ if ( pArea )
+ {
+ aSmartTagTypes.push_back( pArea->maType );
+ aStringKeyMaps.push_back( pArea->mxPropertyBag );
+ }
+ }
+ }
+
+ if ( aSmartTagTypes.size() )
+ {
+ rSmartTagTypes.realloc( aSmartTagTypes.size() );
+ rStringKeyMaps.realloc( aSmartTagTypes.size() );
+
+ std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
+ USHORT i = 0;
+ for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
+ rSmartTagTypes[i++] = *aTypesIter;
+
+ std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
+ i = 0;
+ for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
+ rStringKeyMaps[i++] = *aMapsIter;
+ }
+}
+
+void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
+ SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
+{
+ // create SwPosition for nStartIndex
+ SwIndex aIndex( &rNode, nBegin );
+ SwPosition aStartPos( rNode, aIndex );
+
+ // create SwPosition for nEndIndex
+ SwPosition aEndPos( aStartPos );
+ aEndPos.nContent = nBegin + nLen;
+
+ const uno::Reference<text::XTextRange> xRange =
+ SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
+
+ rRange = xRange;
+}
+
+void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ uno::Reference< text::XTextRange>& rRange ) const
+{
+ if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
+ if ( pNode && !pNode->IsInProtectSect() )
+ {
+ const SwWrongList *pSmartTagList = pNode->GetSmartTags();
+ if ( pSmartTagList )
+ {
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
+ {
+ const USHORT nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ pSmartTagList = pSubList;
+ nCurrent = 0;
+ }
+
+ lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
+ lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
+ }
+ }
+ }
+}
+
+// see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
+void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
+ uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ uno::Reference<text::XTextRange>& rRange )
+{
+ if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( rPt );
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ SwSpecialPos aSpecialPos;
+ eTmpState.pSpecialPos = &aSpecialPos;
+ SwTxtNode *pNode;
+ const SwWrongList *pSmartTagList;
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
+ 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
+ 0 != (pSmartTagList = pNode->GetSmartTags()) &&
+ !pNode->IsInProtectSect() )
+ {
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
+ {
+ const USHORT nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ pSmartTagList = pSubList;
+ nCurrent = eTmpState.pSpecialPos->nCharOfst;
+ }
+
+ lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
+ lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
+
+ // get smarttag word
+ String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
+
+ //save the start and end positons of the line and the starting point
+ Push();
+ LeftMargin();
+ xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
+ RightMargin();
+ xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
+ Pop(FALSE);
+
+ // make sure the selection build later from the
+ // data below does not include footnotes and other
+ // "in word" character to the left and right in order
+ // to preserve those. Therefore count those "in words"
+ // in order to modify the selection accordingly.
+ const sal_Unicode* pChar = aText.GetBuffer();
+ xub_StrLen nLeft = 0;
+ while (pChar && *pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
+ xub_StrLen nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ aPos.nContent = nBegin + nLeft;
+ pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = aPos;
+ pCrsr->SetMark();
+ ExtendSelection( sal_True, nLen - nLeft - nRight );
+ //no determine the rectangle in the current line
+ xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
+ //take one less than the line end - otherwise the next line would be calculated
+ xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
+ Push();
+ pCrsr->DeleteMark();
+ SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
+ rContent = nWordStart;
+ SwRect aStartRect;
+ SwCrsrMoveState aState;
+ aState.bRealWidth = TRUE;
+ SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
+ SwCntntFrm *pCntntFrame = pCntntNode->GetFrm( &rPt, pCrsr->GetPoint(), FALSE);
+
+ pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
+ rContent = nWordEnd;
+ SwRect aEndRect;
+ pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
+ rSelectRect = aStartRect.Union( aEndRect );
+ Pop(FALSE);
+ }
+ }
+}
+
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
new file mode 100644
index 000000000000..c11092c5fd9d
--- /dev/null
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -0,0 +1,2216 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <svx/svdobj.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <swtable.hxx> // SwTxtFld
+#include <docary.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <txtftn.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <txttxmrk.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <doctxm.hxx>
+#include <docfld.hxx>
+#include <expfld.hxx>
+#include <reffld.hxx>
+#include <flddat.hxx> // SwTxtFld
+#include <cellatr.hxx>
+#include <swundo.hxx>
+#include <redline.hxx>
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+#include <pagedesc.hxx>
+#include <fesh.hxx>
+#include <charfmt.hxx>
+#include <fmturl.hxx>
+#include "txtfrm.hxx"
+#include <wrong.hxx>
+
+#include <vcl/window.hxx>
+#include <docufld.hxx> // OD 2008-06-19 #i90516#
+
+using namespace ::com::sun::star;
+
+
+// zum naechsten/vorhergehenden Punkt auf gleicher Ebene
+BOOL SwCrsrShell::GotoNextNum()
+{
+ BOOL bRet = GetDoc()->GotoNextNum( *pCurCrsr->GetPoint() );
+ if( bRet )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( !ActionPend() )
+ {
+ SET_CURR_SHELL( this );
+ // dann versuche den Cursor auf die Position zu setzen,
+ // auf halber Heohe vom Char-SRectangle
+ Point aPt( pCurCrsr->GetPtPos() );
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->GetFrm( &aPt,
+ pCurCrsr->GetPoint() );
+ pFrm->GetCharRect( aCharRect, *pCurCrsr->GetPoint() );
+ pFrm->Calc();
+ if( pFrm->IsVertical() )
+ {
+ aPt.X() = aCharRect.Center().X();
+ aPt.Y() = pFrm->Frm().Top() + nUpDownX;
+ }
+ else
+ {
+ aPt.Y() = aCharRect.Center().Y();
+ aPt.X() = pFrm->Frm().Left() + nUpDownX;
+ }
+ pFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+ bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::UPDOWN |
+ SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::GotoPrevNum()
+{
+ BOOL bRet = GetDoc()->GotoPrevNum( *pCurCrsr->GetPoint() );
+ if( bRet )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( !ActionPend() )
+ {
+ SET_CURR_SHELL( this );
+ // dann versuche den Cursor auf die Position zu setzen,
+ // auf halber Heohe vom Char-SRectangle
+ Point aPt( pCurCrsr->GetPtPos() );
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->GetFrm( &aPt,
+ pCurCrsr->GetPoint() );
+ pFrm->GetCharRect( aCharRect, *pCurCrsr->GetPoint() );
+ pFrm->Calc();
+ if( pFrm->IsVertical() )
+ {
+ aPt.X() = aCharRect.Center().X();
+ aPt.Y() = pFrm->Frm().Top() + nUpDownX;
+ }
+ else
+ {
+ aPt.Y() = aCharRect.Center().Y();
+ aPt.X() = pFrm->Frm().Left() + nUpDownX;
+ }
+ pFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+ bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::UPDOWN |
+ SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ }
+ return bRet;
+}
+
+// springe aus dem Content zum Header
+
+BOOL SwCrsrShell::GotoHeaderTxt()
+{
+ const SwFrm* pFrm = GetCurrFrm()->FindPageFrm();
+ while( pFrm && !pFrm->IsHeaderFrm() )
+ pFrm = pFrm->GetLower();
+ // Header gefunden, dann suche den 1.Cntnt-Frame
+ while( pFrm && !pFrm->IsCntntFrm() )
+ pFrm = pFrm->GetLower();
+ if( pFrm )
+ {
+ SET_CURR_SHELL( this );
+ // hole den Header-Frame
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor *pTmpCrsr = getShellCrsr( true );
+ SwCrsrSaveState aSaveState( *pTmpCrsr );
+ pFrm->Calc();
+ Point aPt( pFrm->Frm().Pos() + pFrm->Prt().Pos() );
+ pFrm->GetCrsrOfst( pTmpCrsr->GetPoint(), aPt );
+ if( !pTmpCrsr->IsSelOvr() )
+ UpdateCrsr();
+ else
+ pFrm = 0;
+ }
+ return 0 != pFrm;
+}
+
+
+// springe aus dem Content zum Footer
+
+BOOL SwCrsrShell::GotoFooterTxt()
+{
+ const SwPageFrm* pFrm = GetCurrFrm()->FindPageFrm();
+ if( pFrm )
+ {
+ const SwFrm* pLower = pFrm->GetLastLower();
+
+ while( pLower && !pLower->IsFooterFrm() )
+ pLower = pLower->GetLower();
+ // Header gefunden, dann suche den 1.Cntnt-Frame
+ while( pLower && !pLower->IsCntntFrm() )
+ pLower = pLower->GetLower();
+
+ if( pLower )
+ {
+ SwCursor *pTmpCrsr = getShellCrsr( true );
+ SET_CURR_SHELL( this );
+ // hole eine Position im Footer
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pTmpCrsr );
+ pLower->Calc();
+ Point aPt( pLower->Frm().Pos() + pLower->Prt().Pos() );
+ pLower->GetCrsrOfst( pTmpCrsr->GetPoint(), aPt );
+ if( !pTmpCrsr->IsSelOvr() )
+ UpdateCrsr();
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+ return 0 != pFrm;
+}
+
+BOOL SwCrsrShell::SetCrsrInHdFt( USHORT nDescNo, BOOL bInHeader )
+{
+ BOOL bRet = FALSE;
+ SwDoc *pMyDoc = GetDoc();
+
+ SET_CURR_SHELL( this );
+
+ if( USHRT_MAX == nDescNo )
+ {
+ // dann den akt. nehmen
+ const SwPageFrm* pPage = GetCurrFrm()->FindPageFrm();
+ if( pPage )
+ for( USHORT i = 0; i < pMyDoc->GetPageDescCnt(); ++i )
+ if( pPage->GetPageDesc() ==
+ &const_cast<const SwDoc *>(pMyDoc)->GetPageDesc( i ) )
+ {
+ nDescNo = i;
+ break;
+ }
+ }
+
+ if( USHRT_MAX != nDescNo && nDescNo < pMyDoc->GetPageDescCnt() )
+ {
+ //dann teste mal, ob ueberhaupt das Attribut vorhanden ist.
+ const SwPageDesc& rDesc = const_cast<const SwDoc *>(pMyDoc)
+ ->GetPageDesc( nDescNo );
+ const SwFmtCntnt* pCnt = 0;
+ if( bInHeader )
+ {
+ // gespiegelte Seiten??? erstmal nicht beachten
+ const SwFmtHeader& rHd = rDesc.GetMaster().GetHeader();
+ if( rHd.GetHeaderFmt() )
+ pCnt = &rHd.GetHeaderFmt()->GetCntnt();
+ }
+ else
+ {
+ const SwFmtFooter& rFt = rDesc.GetMaster().GetFooter();
+ if( rFt.GetFooterFmt() )
+ pCnt = &rFt.GetFooterFmt()->GetCntnt();
+ }
+
+ if( pCnt && pCnt->GetCntntIdx() )
+ {
+ SwNodeIndex aIdx( *pCnt->GetCntntIdx(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pMyDoc->GetNodes().GoNext( &aIdx );
+
+ const SwFrm* pFrm;
+ Point aPt( pCurCrsr->GetPtPos() );
+
+ if( pCNd && 0 != ( pFrm = pCNd->GetFrm( &aPt, 0, FALSE ) ))
+ {
+ // dann kann der Cursor ja auch hinein gesetzt werden
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ ClearMark();
+
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+ rPos.nNode = *pCNd;
+ rPos.nContent.Assign( pCNd, 0 );
+
+ bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ }
+ }
+ return bRet;
+}
+
+// springe zum naechsten Verzeichnis
+
+BOOL SwCrsrShell::GotoNextTOXBase( const String* pName )
+{
+ BOOL bRet = FALSE;
+
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ SwCntntNode* pFnd = 0;
+ for( USHORT n = rFmts.Count(); n; )
+ {
+ const SwSection* pSect = rFmts[ --n ]->GetSection();
+ const SwSectionNode* pSectNd;
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ) &&
+ pCurCrsr->GetPoint()->nNode < pSectNd->GetIndex() &&
+ ( !pFnd || pFnd->GetIndex() > pSectNd->GetIndex() ) &&
+// JP 10.12.96: solange wir nur 3 Typen kennen und UI-seitig keine anderen
+// einstellbar sind, muss ueber den Titel gesucht werden!
+// ( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTypeName() ) &&
+ ( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTOXName() )
+ )
+ {
+ SwNodeIndex aIdx( *pSectNd, 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ const SwCntntFrm* pCFrm;
+ if( pCNd &&
+ pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex() &&
+ 0 != ( pCFrm = pCNd->GetFrm() ) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ pFnd = pCNd;
+ }
+ }
+ }
+ if( pFnd )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *pFnd;
+ pCurCrsr->GetPoint()->nContent.Assign( pFnd, 0 );
+ bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+// springe zum vorherigen Verzeichnis
+
+
+BOOL SwCrsrShell::GotoPrevTOXBase( const String* pName )
+{
+ BOOL bRet = FALSE;
+
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ SwCntntNode* pFnd = 0;
+ for( USHORT n = rFmts.Count(); n; )
+ {
+ const SwSection* pSect = rFmts[ --n ]->GetSection();
+ const SwSectionNode* pSectNd;
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ) &&
+ pCurCrsr->GetPoint()->nNode > pSectNd->EndOfSectionIndex() &&
+ ( !pFnd || pFnd->GetIndex() < pSectNd->GetIndex() ) &&
+// JP 10.12.96: solange wir nur 3 Typen kennen und UI-seitig keine anderen
+// einstellbar sind, muss ueber den Titel gesucht werden!
+// ( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTypeName() ) &&
+ ( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTOXName() )
+ )
+ {
+ SwNodeIndex aIdx( *pSectNd, 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ const SwCntntFrm* pCFrm;
+ if( pCNd &&
+ pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex() &&
+ 0 != ( pCFrm = pCNd->GetFrm() ) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ pFnd = pCNd;
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *pFnd;
+ pCurCrsr->GetPoint()->nContent.Assign( pFnd, 0 );
+ bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+// springe zum Verzeichnis vom TOXMark
+
+BOOL SwCrsrShell::GotoTOXMarkBase()
+{
+ BOOL bRet = FALSE;
+
+ SwTOXMarks aMarks;
+ USHORT nCnt = GetDoc()->GetCurTOXMark( *pCurCrsr->GetPoint(), aMarks );
+ if( nCnt )
+ {
+ // dann nehme den 1. und hole den Verzeichnis-Typ.
+ // Suche in seiner Abhaengigkeitsliste nach dem eigentlichem
+ // Verzeichnis
+ SwModify* pType = (SwModify*)aMarks[0]->GetRegisteredIn();
+ SwClientIter aIter( *pType );
+ const SwSectionNode* pSectNd;
+ const SwSectionFmt* pSectFmt;
+
+ for( SwTOXBase* pTOX =
+ (SwTOXBase*)aIter.First( TYPE( SwTOXBase ));
+ pTOX; pTOX = (SwTOXBase*)aIter.Next() )
+ if( pTOX->ISA( SwTOXBaseSection ) &&
+ 0 != ( pSectFmt = ((SwTOXBaseSection*)pTOX)->GetFmt() ) &&
+ 0 != ( pSectNd = pSectFmt->GetSectionNode() ))
+ {
+ SwNodeIndex aIdx( *pSectNd, 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ const SwCntntFrm* pCFrm;
+ if( pCNd &&
+ pCNd->EndOfSectionIndex() < pSectNd->EndOfSectionIndex() &&
+ 0 != ( pCFrm = pCNd->GetFrm() ) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *pCNd;
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+ bRet = !pCurCrsr->IsInProtectTable() &&
+ !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+ // springe zur naechsten (vorherigen) Tabellenformel
+ // optional auch nur zu kaputten Formeln springen
+BOOL SwCrsrShell::GotoNxtPrvTblFormula( BOOL bNext, BOOL bOnlyErrors )
+{
+ if( IsTableMode() )
+ return FALSE;
+
+ BOOL bFnd = FALSE;
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+
+ Point aPt;
+ SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
+ if( !bNext )
+ aFndPos.nNode = 0;
+ _SetGetExpFld aFndGEF( aFndPos ), aCurGEF( rPos );
+
+ {
+ const SwNode* pSttNd = rPos.nNode.GetNode().FindTableBoxStartNode();
+ if( pSttNd )
+ {
+ const SwTableBox* pTBox = pSttNd->FindTableNode()->GetTable().
+ GetTblBox( pSttNd->GetIndex() );
+ if( pTBox )
+ aCurGEF = _SetGetExpFld( *pTBox );
+ }
+ }
+
+ if( rPos.nNode < GetDoc()->GetNodes().GetEndOfExtras() )
+ // auch beim Einsammeln wird nur der erste Frame benutzt!
+ aCurGEF.SetBodyPos( *rPos.nNode.GetNode().GetCntntNode()->GetFrm(
+ &aPt, &rPos, FALSE ) );
+
+ {
+ const SfxPoolItem* pItem;
+ const SwTableBox* pTBox;
+ USHORT n, nMaxItems = GetDoc()->GetAttrPool().GetItemCount( RES_BOXATR_FORMULA );
+
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetDoc()->GetAttrPool().GetItem(
+ RES_BOXATR_FORMULA, n ) ) &&
+ 0 != (pTBox = ((SwTblBoxFormula*)pItem)->GetTableBox() ) &&
+ pTBox->GetSttNd() &&
+ pTBox->GetSttNd()->GetNodes().IsDocNodes() &&
+ ( !bOnlyErrors ||
+ !((SwTblBoxFormula*)pItem)->HasValidBoxes() ) )
+ {
+ const SwCntntFrm* pCFrm;
+ SwNodeIndex aIdx( *pTBox->GetSttNd() );
+ const SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ if( pCNd && 0 != ( pCFrm = pCNd->GetFrm( &aPt, 0, FALSE ) ) &&
+ (IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ _SetGetExpFld aCmp( *pTBox );
+ aCmp.SetBodyPos( *pCFrm );
+
+ if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
+ : ( aCmp < aCurGEF && aFndGEF < aCmp ))
+ {
+ aFndGEF = aCmp;
+ bFnd = TRUE;
+ }
+ }
+ }
+ }
+
+ if( bFnd )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ aFndGEF.GetPosOfContent( rPos );
+ pCurCrsr->DeleteMark();
+
+ bFnd = !pCurCrsr->IsSelOvr();
+ if( bFnd )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ return bFnd;
+}
+
+// springe zum naechsten (vorherigen) Verzeichniseintrag
+BOOL SwCrsrShell::GotoNxtPrvTOXMark( BOOL bNext )
+{
+ if( IsTableMode() )
+ return FALSE;
+
+ BOOL bFnd = FALSE;
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+
+ Point aPt;
+ SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
+ if( !bNext )
+ aFndPos.nNode = 0;
+ _SetGetExpFld aFndGEF( aFndPos ), aCurGEF( rPos );
+
+ if( rPos.nNode.GetIndex() < GetDoc()->GetNodes().GetEndOfExtras().GetIndex() )
+ // auch beim Einsammeln wird nur der erste Frame benutzt!
+ aCurGEF.SetBodyPos( *rPos.nNode.GetNode().
+ GetCntntNode()->GetFrm( &aPt, &rPos, FALSE ) );
+
+ {
+ const SfxPoolItem* pItem;
+ const SwCntntFrm* pCFrm;
+ const SwTxtNode* pTxtNd;
+ const SwTxtTOXMark* pTxtTOX;
+ USHORT n, nMaxItems = GetDoc()->GetAttrPool().GetItemCount( RES_TXTATR_TOXMARK );
+
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetDoc()->GetAttrPool().GetItem(
+ RES_TXTATR_TOXMARK, n ) ) &&
+ 0 != (pTxtTOX = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
+ ( pTxtNd = &pTxtTOX->GetTxtNode())->GetNodes().IsDocNodes() &&
+ 0 != ( pCFrm = pTxtNd->GetFrm( &aPt, 0, FALSE )) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ SwNodeIndex aNdIndex( *pTxtNd ); // UNIX benoetigt dieses Obj.
+ _SetGetExpFld aCmp( aNdIndex, *pTxtTOX, 0 );
+ aCmp.SetBodyPos( *pCFrm );
+
+ if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
+ : ( aCmp < aCurGEF && aFndGEF < aCmp ))
+ {
+ aFndGEF = aCmp;
+ bFnd = TRUE;
+ }
+ }
+ }
+
+ if( bFnd )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ aFndGEF.GetPosOfContent( rPos );
+
+ bFnd = !pCurCrsr->IsSelOvr();
+ if( bFnd )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ return bFnd;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Traveling zwischen Markierungen
+ --------------------------------------------------------------------*/
+
+const SwTOXMark& SwCrsrShell::GotoTOXMark( const SwTOXMark& rStart,
+ SwTOXSearch eDir )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ const SwTOXMark& rNewMark = GetDoc()->GotoTOXMark( rStart, eDir,
+ IsReadOnlyAvailable() );
+ // Position setzen
+ SwPosition& rPos = *GetCrsr()->GetPoint();
+ rPos.nNode = rNewMark.GetTxtTOXMark()->GetTxtNode();
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
+ *rNewMark.GetTxtTOXMark()->GetStart() );
+
+ if( !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+
+ return rNewMark;
+}
+
+// springe zum naechsten / vorherigen FeldTypen
+
+void lcl_MakeFldLst( _SetGetExpFlds& rLst, const SwFieldType& rFldType,
+ USHORT nSubType, BOOL bInReadOnly,
+ BOOL bChkInpFlag = FALSE )
+{
+ // es muss immer der 1. Frame gesucht werden
+ Point aPt;
+ SwTxtFld* pTxtFld;
+ SwClientIter aIter( (SwFieldType&)rFldType );
+ BOOL bSubType = nSubType != USHRT_MAX;
+ for( SwClient* pLast = aIter.First( TYPE( SwFmtFld )); pLast; pLast = aIter.Next() )
+ if( 0 != ( pTxtFld = ((SwFmtFld*)pLast)->GetTxtFld() ) &&
+ ( !bChkInpFlag || ((SwSetExpField*)pTxtFld->GetFld().GetFld())
+ ->GetInputFlag() ) &&
+ (!bSubType || (((SwFmtFld*)pLast)->GetFld()->GetSubType()
+ & 0xff ) == nSubType ))
+ {
+ SwCntntFrm* pCFrm;
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ if( 0 != ( pCFrm = rTxtNode.GetFrm( &aPt, 0, FALSE )) &&
+ ( bInReadOnly || !pCFrm->IsProtected() ))
+ {
+ _SetGetExpFld* pNew = new _SetGetExpFld(
+ SwNodeIndex( rTxtNode ), pTxtFld );
+ pNew->SetBodyPos( *pCFrm );
+ rLst.Insert( pNew );
+ }
+ }
+}
+
+
+BOOL SwCrsrShell::MoveFldType( const SwFieldType* pFldType, BOOL bNext,
+ USHORT nSubType, USHORT nResType )
+{
+ // sortierte Liste aller Felder
+ _SetGetExpFlds aSrtLst( 64 );
+
+ if (pFldType)
+ {
+ if( RES_INPUTFLD != pFldType->Which() && !pFldType->GetDepends() )
+ return FALSE;
+
+ // Modify-Object gefunden, trage alle Felder ins Array ein
+ ::lcl_MakeFldLst( aSrtLst, *pFldType, nSubType, IsReadOnlyAvailable() );
+
+ if( RES_INPUTFLD == pFldType->Which() )
+ {
+ // es gibt noch versteckte InputFelder in den SetExp. Feldern
+ const SwFldTypes& rFldTypes = *pDoc->GetFldTypes();
+ const USHORT nSize = rFldTypes.Count();
+
+ // Alle Typen abklappern
+ for( USHORT i=0; i < nSize; ++i )
+ if( RES_SETEXPFLD == ( pFldType = rFldTypes[ i ] )->Which() )
+ ::lcl_MakeFldLst( aSrtLst, *pFldType, nSubType,
+ IsReadOnlyAvailable(), TRUE );
+ }
+ }
+ else
+ {
+ const SwFldTypes& rFldTypes = *pDoc->GetFldTypes();
+ const USHORT nSize = rFldTypes.Count();
+
+ // Alle Typen abklappern
+ for( USHORT i=0; i < nSize; ++i )
+ if( nResType == ( pFldType = rFldTypes[ i ] )->Which() )
+ ::lcl_MakeFldLst( aSrtLst, *pFldType, nSubType,
+ IsReadOnlyAvailable() );
+ }
+
+ // keine Felder gefunden?
+ if( !aSrtLst.Count() )
+ return FALSE;
+
+ USHORT nPos;
+ SwCursor* pCrsr = getShellCrsr( true );
+ {
+ // JP 19.08.98: es muss immer ueber das Feld gesucht werden, damit
+ // auch immer das richtige gefunden wird, wenn welche in
+ // Rahmen stehen, die in einem Absatz verankert sind,
+ // in dem ein Feld steht - siehe auch Bug 55247
+ const SwPosition& rPos = *pCrsr->GetPoint();
+
+ SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+ ASSERT( pTNd, "Wo ist mein CntntNode?" );
+
+ SwTxtFld * pTxtFld = static_cast<SwTxtFld *>(
+ pTNd->GetTxtAttrForCharAt(rPos.nContent.GetIndex(),
+ RES_TXTATR_FIELD));
+ BOOL bDelFld = 0 == pTxtFld;
+ if( bDelFld )
+ {
+ SwFmtFld* pFmtFld = new SwFmtFld( SwDateTimeField(
+ (SwDateTimeFieldType*)pDoc->GetSysFldType( RES_DATETIMEFLD ) ) );
+
+ pTxtFld = new SwTxtFld( *pFmtFld, rPos.nContent.GetIndex(),
+ pDoc->IsClipBoard() );
+ pTxtFld->ChgTxtNode( pTNd );
+ }
+
+ _SetGetExpFld aSrch( rPos.nNode, pTxtFld, &rPos.nContent );
+ if( rPos.nNode.GetIndex() < pDoc->GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // auch beim Einsammeln wird nur der erste Frame benutzt!
+ Point aPt;
+ aSrch.SetBodyPos( *pTNd->GetFrm( &aPt, &rPos, FALSE ) );
+ }
+
+ BOOL bFound = aSrtLst.Seek_Entry( &aSrch, &nPos );
+ if( bDelFld )
+ {
+ delete (SwFmtFld*)&pTxtFld->GetAttr();
+ delete pTxtFld;
+ }
+
+ if( bFound ) // stehe auf einem ?
+ {
+ if( bNext )
+ {
+ if( ++nPos >= aSrtLst.Count() )
+ return FALSE; // schon am Ende
+ }
+ else if( !nPos-- )
+ return FALSE; // weiter nach vorne geht nicht
+ }
+ else if( bNext ? nPos >= aSrtLst.Count() : !nPos--)
+ return FALSE;
+ }
+ const _SetGetExpFld& rFnd = **( aSrtLst.GetData() + nPos );
+
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ rFnd.GetPosOfContent( *pCrsr->GetPoint() );
+ BOOL bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::GotoFld( const SwFmtFld& rFld )
+{
+ BOOL bRet = FALSE;
+ if( rFld.GetTxtFld() )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwCursor* pCrsr = getShellCrsr( true );
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ SwTxtNode* pTNd = (SwTxtNode*)rFld.GetTxtFld()->GetpTxtNode();
+ pCrsr->GetPoint()->nNode = *pTNd;
+ pCrsr->GetPoint()->nContent.Assign( pTNd, *rFld.GetTxtFld()->GetStart() );
+
+ bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+
+void SwCrsrShell::GotoOutline( USHORT nIdx )
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ SwTxtNode* pTxtNd = (SwTxtNode*)rNds.GetOutLineNds()[ nIdx ]->GetTxtNode();
+ pCrsr->GetPoint()->nNode = *pTxtNd;
+ pCrsr->GetPoint()->nContent.Assign( pTxtNd, 0 );
+
+ if( !pCrsr->IsSelOvr() )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+}
+
+
+BOOL SwCrsrShell::GotoOutline( const String& rName )
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ BOOL bRet = FALSE;
+ if( pDoc->GotoOutline( *pCrsr->GetPoint(), rName ) && !pCrsr->IsSelOvr() )
+ {
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ bRet = TRUE;
+ }
+ return bRet;
+}
+
+
+
+BOOL SwCrsrShell::GotoNextOutline() // naechster Node mit Outline-Num.
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = pCrsr->GetNode();
+ USHORT nPos;
+ if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
+ ++nPos;
+
+ if( nPos == rNds.GetOutLineNds().Count() )
+ return FALSE;
+
+ pNd = rNds.GetOutLineNds()[ nPos ];
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+ pCrsr->GetPoint()->nNode = *pNd;
+ pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)pNd, 0 );
+
+ BOOL bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::GotoPrevOutline() // vorheriger Node mit Outline-Num.
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = pCrsr->GetNode();
+ USHORT nPos;
+ rNds.GetOutLineNds().Seek_Entry( pNd, &nPos );
+
+ BOOL bRet = FALSE;
+ if( nPos )
+ {
+ --nPos; // davor
+
+ pNd = rNds.GetOutLineNds()[ nPos ];
+ if( pNd->GetIndex() > pCrsr->GetPoint()->nNode.GetIndex() )
+ return FALSE;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+ pCrsr->GetPoint()->nNode = *pNd;
+ pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)pNd, 0 );
+
+ bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+
+ // suche die "Outline-Position" vom vorherigen Outline-Node mit dem
+ // Level.
+USHORT SwCrsrShell::GetOutlinePos( BYTE nLevel )
+{
+ SwPaM* pCrsr = getShellCrsr( true );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = pCrsr->GetNode();
+ USHORT nPos;
+ if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
+ nPos++; // steht auf der Position, fuers while zum Naechsten
+
+ while( nPos-- ) // immer den davor testen !
+ {
+ pNd = rNds.GetOutLineNds()[ nPos ];
+
+ //if( ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() <= nLevel )//#outline level,zhaojianwei
+ if( ((SwTxtNode*)pNd)->GetAttrOutlineLevel()-1 <= nLevel )//<-end,zhaojianwei
+ return nPos;
+
+ }
+ return USHRT_MAX; // davor keiner mehr also Ende
+}
+
+
+BOOL SwCrsrShell::MakeOutlineSel( USHORT nSttPos, USHORT nEndPos,
+ BOOL bWithChilds )
+{
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ if( !rOutlNds.Count() ) // wie jetzt ???
+ return FALSE;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ if( nSttPos > nEndPos ) // sollte jemand das vertauscht haben?
+ {
+ ASSERT( !this, "Start- > Ende-Position im Array" );
+ USHORT nTmp = nSttPos;
+ nSttPos = nEndPos;
+ nEndPos = nTmp;
+ }
+
+ SwNode* pSttNd = rOutlNds[ nSttPos ];
+ SwNode* pEndNd = rOutlNds[ nEndPos ];
+
+ if( bWithChilds )
+ {
+ //BYTE nLevel = pEndNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ const int nLevel = pEndNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end.zhaojianwei
+ for( ++nEndPos; nEndPos < rOutlNds.Count(); ++nEndPos )
+ {
+ pEndNd = rOutlNds[ nEndPos ];
+ //BYTE nNxtLevel = pEndNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ const int nNxtLevel = pEndNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+ if( nNxtLevel <= nLevel )
+ break; // EndPos steht jetzt auf dem naechsten
+ }
+ }
+ // ohne Childs, dann aber zumindest auf den naechsten
+ else if( ++nEndPos < rOutlNds.Count() )
+ pEndNd = rOutlNds[ nEndPos ];
+
+ if( nEndPos == rOutlNds.Count() ) // kein Ende gefunden
+ pEndNd = &rNds.GetEndOfContent();
+
+ KillPams();
+
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // Jetzt das Ende ans Ende vom voherigen ContentNode setzen
+ pCurCrsr->GetPoint()->nNode = *pSttNd;
+ pCurCrsr->GetPoint()->nContent.Assign( pSttNd->GetCntntNode(), 0 );
+ pCurCrsr->SetMark();
+ pCurCrsr->GetPoint()->nNode = *pEndNd;
+ pCurCrsr->Move( fnMoveBackward, fnGoNode ); // ans Ende vom Vorgaenger
+
+ // und schon ist alles selektiert
+ BOOL bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+// springe zu dieser Refmark
+BOOL SwCrsrShell::GotoRefMark( const String& rRefMark, USHORT nSubType,
+ USHORT nSeqNo )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ USHORT nPos;
+ SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( GetDoc(), rRefMark,
+ nSubType, nSeqNo, &nPos );
+ if( pTxtNd && pTxtNd->GetNodes().IsDocNodes() )
+ {
+ pCurCrsr->GetPoint()->nNode = *pTxtNd;
+ pCurCrsr->GetPoint()->nContent.Assign( pTxtNd, nPos );
+
+ if( !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL SwCrsrShell::IsPageAtPos( const Point &rPt ) const
+{
+ if( GetLayout() )
+ return 0 != GetLayout()->GetPageAtPos( rPt );
+ return FALSE;
+}
+
+BOOL SwCrsrShell::GetContentAtPos( const Point& rPt,
+ SwContentAtPos& rCntntAtPos,
+ BOOL bSetCrsr,
+ SwRect* pFldRect )
+{
+ SET_CURR_SHELL( this );
+ BOOL bRet = FALSE;
+
+ if( !IsTableMode() )
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+
+ SwTxtNode* pTxtNd;
+ SwCntntFrm *pFrm(0);
+ SwTxtAttr* pTxtAttr;
+ SwCrsrMoveState aTmpState;
+ aTmpState.bFieldInfo = TRUE;
+ aTmpState.bExactOnly = !( SwContentAtPos::SW_OUTLINE & rCntntAtPos.eCntntAtPos );
+ aTmpState.bCntntCheck = (SwContentAtPos::SW_CONTENT_CHECK & rCntntAtPos.eCntntAtPos) ? TRUE : FALSE;
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ SwSpecialPos aSpecialPos;
+ aTmpState.pSpecialPos = ( SwContentAtPos::SW_SMARTTAG & rCntntAtPos.eCntntAtPos ) ?
+ &aSpecialPos : 0;
+
+ const BOOL bCrsrFoundExact = GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
+ pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ if( pTxtNd && SwContentAtPos::SW_OUTLINE & rCntntAtPos.eCntntAtPos
+ && rNds.GetOutLineNds().Count() )
+ {
+ const SwTxtNode* pONd = pTxtNd->FindOutlineNodeOfLevel( MAXLEVEL-1);
+ if( pONd )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_OUTLINE;
+ rCntntAtPos.sStr = pONd->GetExpandTxt( 0, STRING_LEN, true );
+ bRet = TRUE;
+ }
+ }
+ // --> FME 2005-05-13 #i43742# New function: SW_CONTENT_CHECK
+ else if ( SwContentAtPos::SW_CONTENT_CHECK & rCntntAtPos.eCntntAtPos &&
+ bCrsrFoundExact )
+ {
+ bRet = TRUE;
+ }
+ // <--
+ // #i23726#
+ else if( pTxtNd &&
+ SwContentAtPos::SW_NUMLABEL & rCntntAtPos.eCntntAtPos)
+ {
+ bRet = aTmpState.bInNumPortion;
+ rCntntAtPos.aFnd.pNode = pTxtNd;
+
+ Size aSizeLogic(aTmpState.nInNumPostionOffset, 0);
+ Size aSizePixel = GetWin()->LogicToPixel(aSizeLogic);
+ rCntntAtPos.nDist = aSizePixel.Width();
+ }
+ else if( bCrsrFoundExact && pTxtNd )
+ {
+ if( !aTmpState.bPosCorr )
+ {
+ if( !bRet && SwContentAtPos::SW_SMARTTAG & rCntntAtPos.eCntntAtPos
+ && !aTmpState.bFtnNoInfo )
+ {
+ const SwWrongList* pSmartTagList = pTxtNd->GetSmartTags();
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if ( pSmartTagList && pSmartTagList->InWrongWord( nCurrent, nLen ) && !pTxtNd->IsSymbol(nBegin) )
+ {
+ const USHORT nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ nCurrent = aTmpState.pSpecialPos->nCharOfst;
+
+ if ( pSubList->InWrongWord( nCurrent, nLen ) )
+ bRet = TRUE;
+ }
+ else
+ bRet = TRUE;
+
+ if( bRet && bSetCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
+ bRet = FALSE;
+ else
+ UpdateCrsr();
+ }
+ if( bRet )
+ {
+// rCntntAtPos.sStr = pTxtNd->GetExpandTxt(
+// *pTxtAttr->GetStart(),
+// *pTxtAttr->GetEnd() - *pTxtAttr->GetStart(),
+// FALSE );
+
+// rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_SMARTTAG;
+// rCntntAtPos.pFndTxtAttr = pTxtAttr;
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->GetFrm( &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && ( SwContentAtPos::SW_FIELD | SwContentAtPos::SW_CLICKFIELD )
+ & rCntntAtPos.eCntntAtPos && !aTmpState.bFtnNoInfo )
+ {
+ pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_FIELD );
+ const SwField* pFld = pTxtAttr
+ ? pTxtAttr->GetFld().GetFld()
+ : 0;
+ if( SwContentAtPos::SW_CLICKFIELD & rCntntAtPos.eCntntAtPos &&
+ pFld && !pFld->HasClickHdl() )
+ pFld = 0;
+
+ if( pFld )
+ {
+ if( pFldRect && 0 != ( pFrm = pTxtNd->GetFrm( &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr() )
+ {
+ // Click-Felder in geschuetzten Bereichen zulassen
+ // Nur Platzhalter geht nicht!
+ if( SwContentAtPos::SW_FIELD & rCntntAtPos.eCntntAtPos
+ || RES_JUMPEDITFLD == pFld->Which() )
+ pFld = 0;
+ }
+ else
+ UpdateCrsr();
+ }
+ else if( RES_TABLEFLD == pFld->Which() &&
+ ((SwTblField*)pFld)->IsIntrnlName() )
+ {
+ // erzeuge aus der internen (fuer CORE)
+ // die externe (fuer UI) Formel
+ const SwTableNode* pTblNd = pTxtNd->FindTableNode();
+ if( pTblNd ) // steht in einer Tabelle
+ ((SwTblField*)pFld)->PtrToBoxNm( &pTblNd->GetTable() );
+ }
+ }
+
+ if( pFld )
+ {
+ rCntntAtPos.aFnd.pFld = pFld;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FIELD;
+ bRet = TRUE;
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_FORMCTRL & rCntntAtPos.eCntntAtPos )
+ {
+ IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
+ sw::mark::IFieldmark* pFldBookmark = pMarksAccess->getFieldmarkFor( aPos );
+ if( bCrsrFoundExact && pTxtNd && pFldBookmark) {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FORMCTRL;
+ rCntntAtPos.aFnd.pFldmark = pFldBookmark;
+ bRet=TRUE;
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_FTN & rCntntAtPos.eCntntAtPos )
+ {
+ if( aTmpState.bFtnNoInfo )
+ {
+ // stehe ueber dem Zeichen der Fussnote (??)
+ bRet = TRUE;
+ if( bSetCrsr )
+ {
+ *pCurCrsr->GetPoint() = aPos;
+ if( !GotoFtnAnchor() )
+ bRet = FALSE;
+ }
+ if( bRet )
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FTN;
+ }
+ else if ( 0 != ( pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_FTN )) )
+ {
+ bRet = TRUE;
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *((SwTxtFtn*)pTxtAttr)->GetStartNode();
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
+ &pCurCrsr->GetPoint()->nNode,
+ TRUE, !IsReadOnlyAvailable() );
+
+ if( pCNd )
+ {
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE ))
+ bRet = FALSE;
+ else
+ UpdateCrsr();
+ }
+ else
+ bRet = FALSE;
+ }
+
+ if( bRet )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FTN;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+ rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->GetFrm( &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && ( SwContentAtPos::SW_TOXMARK |
+ SwContentAtPos::SW_REFMARK ) &
+ rCntntAtPos.eCntntAtPos && !aTmpState.bFtnNoInfo )
+ {
+ pTxtAttr = 0;
+ if( SwContentAtPos::SW_TOXMARK & rCntntAtPos.eCntntAtPos )
+ {
+ ::std::vector<SwTxtAttr *> const marks(
+ pTxtNd->GetTxtAttrsAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_TOXMARK));
+ if (marks.size())
+ { // hmm... can only return 1 here
+ pTxtAttr = *marks.begin();
+ }
+ }
+
+ if( !pTxtAttr &&
+ SwContentAtPos::SW_REFMARK & rCntntAtPos.eCntntAtPos )
+ {
+ ::std::vector<SwTxtAttr *> const marks(
+ pTxtNd->GetTxtAttrsAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_REFMARK));
+ if (marks.size())
+ { // hmm... can only return 1 here
+ pTxtAttr = *marks.begin();
+ }
+ }
+
+ if( pTxtAttr )
+ {
+ bRet = TRUE;
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
+ bRet = FALSE;
+ else
+ UpdateCrsr();
+ }
+
+ if( bRet )
+ {
+ const xub_StrLen* pEnd = pTxtAttr->GetEnd();
+ if( pEnd )
+ rCntntAtPos.sStr = pTxtNd->GetExpandTxt(
+ *pTxtAttr->GetStart(),
+ *pEnd - *pTxtAttr->GetStart() );
+ else if( RES_TXTATR_TOXMARK == pTxtAttr->Which())
+ rCntntAtPos.sStr = pTxtAttr->GetTOXMark().
+ GetAlternativeText();
+
+ rCntntAtPos.eCntntAtPos =
+ RES_TXTATR_TOXMARK == pTxtAttr->Which()
+ ? SwContentAtPos::SW_TOXMARK
+ : SwContentAtPos::SW_REFMARK;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+ rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->GetFrm( &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_INETATTR & rCntntAtPos.eCntntAtPos
+ && !aTmpState.bFtnNoInfo )
+ {
+ pTxtAttr = pTxtNd->GetTxtAttrAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_INETFMT);
+ // nur INetAttrs mit URLs "erkennen"
+ if( pTxtAttr && pTxtAttr->GetINetFmt().GetValue().Len() )
+ {
+ bRet = TRUE;
+ if( bSetCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
+ bRet = FALSE;
+ else
+ UpdateCrsr();
+ }
+ if( bRet )
+ {
+ rCntntAtPos.sStr = pTxtNd->GetExpandTxt(
+ *pTxtAttr->GetStart(),
+ *pTxtAttr->GetEnd() - *pTxtAttr->GetStart() );
+
+ rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_INETATTR;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->GetFrm( &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_REDLINE & rCntntAtPos.eCntntAtPos )
+ {
+ const SwRedline* pRedl = GetDoc()->GetRedline(aPos, NULL);
+ if( pRedl )
+ {
+ rCntntAtPos.aFnd.pRedl = pRedl;
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_REDLINE;
+ rCntntAtPos.pFndTxtAttr = 0;
+ bRet = TRUE;
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->GetFrm( &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && (
+ SwContentAtPos::SW_TABLEBOXFML & rCntntAtPos.eCntntAtPos
+#ifdef DBG_UTIL
+ || SwContentAtPos::SW_TABLEBOXVALUE & rCntntAtPos.eCntntAtPos
+#endif
+ ))
+ {
+ const SwTableNode* pTblNd;
+ const SwTableBox* pBox;
+ const SwStartNode* pSttNd = pTxtNd->FindTableBoxStartNode();
+ const SfxPoolItem* pItem;
+ if( pSttNd && 0 != ( pTblNd = pTxtNd->FindTableNode()) &&
+ 0 != ( pBox = pTblNd->GetTable().GetTblBox(
+ pSttNd->GetIndex() )) &&
+#ifdef DBG_UTIL
+ ( SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_FORMULA, FALSE, &pItem ) ||
+ SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_VALUE, FALSE, &pItem ))
+#else
+ SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_FORMULA, FALSE, &pItem )
+#endif
+ )
+ {
+ SwFrm* pF = pTxtNd->GetFrm( &aPt );
+ if( pF )
+ {
+ // dann aber den CellFrame
+ pFrm = (SwCntntFrm*)pF;
+ while( pF && !pF->IsCellFrm() )
+ pF = pF->GetUpper();
+ }
+
+ // es wurde ein
+ if( aTmpState.bPosCorr )
+ {
+ if( pF && !pF->Frm().IsInside( aPt ))
+ pF = 0;
+ }
+ else if( !pF )
+ pF = pFrm;
+
+ if( pF ) // nur dann ist es gueltig!!
+ {
+ // erzeuge aus der internen (fuer CORE)
+ // die externe (fuer UI) Formel
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_TABLEBOXFML;
+#ifdef DBG_UTIL
+ if( RES_BOXATR_VALUE == pItem->Which() )
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_TABLEBOXVALUE;
+ else
+#endif
+ ((SwTblBoxFormula*)pItem)->PtrToBoxNm( &pTblNd->GetTable() );
+
+ bRet = TRUE;
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
+ bRet = FALSE;
+ else
+ UpdateCrsr();
+ }
+
+ if( bRet )
+ {
+ if( pFldRect )
+ {
+ *pFldRect = pF->Prt();
+ *pFldRect += pF->Frm().Pos();
+ }
+ rCntntAtPos.pFndTxtAttr = 0;
+ rCntntAtPos.aFnd.pAttr = pItem;
+ }
+ }
+ }
+ }
+
+#ifdef DBG_UTIL
+ if( !bRet && SwContentAtPos::SW_CURR_ATTRS & rCntntAtPos.eCntntAtPos )
+ {
+ xub_StrLen n = aPos.nContent.GetIndex();
+ SfxItemSet aSet( GetDoc()->GetAttrPool(), POOLATTR_BEGIN,
+ POOLATTR_END - 1 );
+ if( pTxtNd->GetpSwpHints() )
+ {
+ for( USHORT i = 0; i < pTxtNd->GetSwpHints().Count(); ++i )
+ {
+ const SwTxtAttr* pHt = pTxtNd->GetSwpHints()[i];
+ xub_StrLen nAttrStart = *pHt->GetStart();
+ if( nAttrStart > n ) // ueber den Bereich hinaus
+ break;
+
+ if( 0 != pHt->GetEnd() && (
+ ( nAttrStart < n &&
+ ( pHt->DontExpand() ? n < *pHt->GetEnd()
+ : n <= *pHt->GetEnd() )) ||
+ ( n == nAttrStart &&
+ ( nAttrStart == *pHt->GetEnd() || !n ))) )
+ {
+ aSet.Put( pHt->GetAttr() );
+ }
+ }
+ if( pTxtNd->HasSwAttrSet() &&
+ pTxtNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemSet aFmtSet( pTxtNd->GetSwAttrSet() );
+ // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
+ aFmtSet.Differentiate( aSet );
+ // jetzt alle zusammen "mergen"
+ aSet.Put( aFmtSet );
+ }
+ }
+ else
+ pTxtNd->SwCntntNode::GetAttr( aSet );
+
+ rCntntAtPos.sStr.AssignAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Pos: (" ));
+ rCntntAtPos.sStr += String::CreateFromInt32( aPos.nNode.GetIndex());
+ rCntntAtPos.sStr += ':';
+ rCntntAtPos.sStr += String::CreateFromInt32( aPos.nContent.GetIndex());
+ rCntntAtPos.sStr += ')';
+ rCntntAtPos.sStr.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\nAbs.Vorl.: " ));
+ rCntntAtPos.sStr += pTxtNd->GetFmtColl()->GetName();
+ if( pTxtNd->GetCondFmtColl() )
+ rCntntAtPos.sStr.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\nBed.Vorl.: " ))
+ += pTxtNd->GetCondFmtColl()->GetName();
+
+ if( aSet.Count() )
+ {
+ String sAttrs;
+ SfxItemIter aIter( aSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while( TRUE )
+ {
+ if( !IsInvalidItem( pItem ))
+ {
+ String aStr;
+ GetDoc()->GetAttrPool().GetPresentation( *pItem,
+ SFX_ITEM_PRESENTATION_COMPLETE,
+ SFX_MAPUNIT_CM, aStr );
+ if( sAttrs.Len() )
+ sAttrs.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( ", " ));
+ sAttrs += aStr;
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ if( sAttrs.Len() )
+ {
+ if( rCntntAtPos.sStr.Len() )
+ rCntntAtPos.sStr += '\n';
+ rCntntAtPos.sStr.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Attr: " ) )
+ += sAttrs;
+ }
+ }
+ bRet = TRUE;
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_CURR_ATTRS;
+ }
+#endif
+ }
+ }
+
+ if( !bRet )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_NOTHING;
+ rCntntAtPos.aFnd.pFld = 0;
+ }
+ return bRet;
+}
+
+// --> OD 2008-06-19 #i90516#
+const SwPostItField* SwCrsrShell::GetPostItFieldAtCursor() const
+{
+ const SwPostItField* pPostItFld = 0;
+
+ if ( !IsTableMode() )
+ {
+ const SwPosition* pCursorPos = _GetCrsr()->GetPoint();
+ const SwTxtNode* pTxtNd = pCursorPos->nNode.GetNode().GetTxtNode();
+ if ( pTxtNd )
+ {
+ SwTxtAttr* pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
+ pCursorPos->nContent.GetIndex(), RES_TXTATR_FIELD );
+ const SwField* pFld = pTxtAttr ? pTxtAttr->GetFld().GetFld() : 0;
+ if ( pFld && pFld->Which()== RES_POSTITFLD )
+ {
+ pPostItFld = static_cast<const SwPostItField*>(pFld);
+ }
+ }
+ }
+
+ return pPostItFld;
+}
+// <--
+
+// befindet sich der Node in einem geschuetzten Bereich?
+BOOL SwContentAtPos::IsInProtectSect() const
+{
+ const SwTxtNode* pNd = 0;
+ if( pFndTxtAttr )
+ {
+ switch( eCntntAtPos )
+ {
+ case SW_FIELD:
+ case SW_CLICKFIELD:
+ pNd = ((SwTxtFld*)pFndTxtAttr)->GetpTxtNode();
+ break;
+
+ case SW_FTN:
+ pNd = &((SwTxtFtn*)pFndTxtAttr)->GetTxtNode();
+ break;
+
+ case SW_INETATTR:
+ pNd = ((SwTxtINetFmt*)pFndTxtAttr)->GetpTxtNode();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ const SwCntntFrm* pFrm;
+ return pNd && ( pNd->IsInProtectSect() ||
+ ( 0 != ( pFrm = pNd->GetFrm(0,0,FALSE)) &&
+ pFrm->IsProtected() ));
+}
+bool SwContentAtPos::IsInRTLText()const
+{
+ bool bRet = false;
+ const SwTxtNode* pNd = 0;
+ if (pFndTxtAttr && (eCntntAtPos == SW_FTN))
+ {
+ const SwTxtFtn* pTxtFtn = static_cast<const SwTxtFtn*>(pFndTxtAttr);
+ if(pTxtFtn->GetStartNode())
+ {
+ SwStartNode* pSttNd = pTxtFtn->GetStartNode()->GetNode().GetStartNode();
+ SwPaM aTemp( *pSttNd );
+ aTemp.Move(fnMoveForward, fnGoNode);
+ SwCntntNode* pCntntNode = aTemp.GetCntntNode();
+ if(pCntntNode && pCntntNode->IsTxtNode())
+ pNd = static_cast<SwTxtNode*>(pCntntNode);
+ }
+ }
+ if(pNd)
+ {
+ SwClientIter aClientIter( * const_cast<SwTxtNode*>(pNd) );
+ SwClient* pLast = aClientIter.GoStart();
+ while( pLast )
+ {
+ if ( pLast->ISA( SwTxtFrm ) )
+ {
+ SwTxtFrm* pTmpFrm = static_cast<SwTxtFrm*>( pLast );
+ if ( !pTmpFrm->IsFollow())
+ {
+ bRet = pTmpFrm->IsRightToLeft();
+ break;
+ }
+ }
+ pLast = ++aClientIter;
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::SelectTxtAttr( USHORT nWhich, BOOL bExpand,
+ const SwTxtAttr* pTxtAttr )
+{
+ SET_CURR_SHELL( this );
+ BOOL bRet = FALSE;
+
+ if( !IsTableMode() )
+ {
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+ if( !pTxtAttr )
+ {
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ pTxtAttr = (pTxtNd)
+ ? pTxtNd->GetTxtAttrAt(rPos.nContent.GetIndex(),
+ static_cast<RES_TXTATR>(nWhich),
+ (bExpand) ? SwTxtNode::EXPAND : SwTxtNode::DEFAULT)
+ : 0;
+ }
+
+ if( pTxtAttr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pCurCrsr->DeleteMark();
+ rPos.nContent = *pTxtAttr->GetStart();
+ pCurCrsr->SetMark();
+ const xub_StrLen* pEnd = pTxtAttr->GetEnd();
+ rPos.nContent = pEnd ? *pEnd : *pTxtAttr->GetStart() + 1;
+
+ if( !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr();
+ bRet = TRUE;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::GotoINetAttr( const SwTxtINetFmt& rAttr )
+{
+ BOOL bRet = FALSE;
+ if( rAttr.GetpTxtNode() )
+ {
+ SwCursor* pCrsr = getShellCrsr( true );
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ pCrsr->GetPoint()->nNode = *rAttr.GetpTxtNode();
+ pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)rAttr.GetpTxtNode(),
+ *rAttr.GetStart() );
+ bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+
+const SwFmtINetFmt* SwCrsrShell::FindINetAttr( const String& rName ) const
+{
+ return pDoc->FindINetAttr( rName );
+}
+
+BOOL SwCrsrShell::GetShadowCrsrPos( const Point& rPt, SwFillMode eFillMode,
+ SwRect& rRect, sal_Int16& rOrient )
+{
+
+ SET_CURR_SHELL( this );
+ BOOL bRet = FALSE;
+
+ if( !IsTableMode() && !HasSelection() && GetDoc()->DoesUndo() )
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+
+ SwFillCrsrPos aFPos( eFillMode );
+ SwCrsrMoveState aTmpState( &aFPos );
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) &&
+ !aPos.nNode.GetNode().IsProtect())
+ {
+ // Start-Position im geschuetzten Bereich?
+ rRect = aFPos.aCrsr;
+ rOrient = aFPos.eOrient;
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::SetShadowCrsrPos( const Point& rPt, SwFillMode eFillMode )
+{
+ SET_CURR_SHELL( this );
+ BOOL bRet = FALSE;
+
+ if( !IsTableMode() && !HasSelection() && GetDoc()->DoesUndo() )
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+
+ SwFillCrsrPos aFPos( eFillMode );
+ SwCrsrMoveState aTmpState( &aFPos );
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen
+ StartAction();
+
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ SwUndoId nUndoId = UNDO_INS_FROM_SHADOWCRSR;
+ // Werden nur die Absatzattribute Adjust oder LRSpace gesetzt,
+ // dann sollte der naechste Aufruf die NICHT wieder entfernen.
+ if( 0 == aFPos.nParaCnt + aFPos.nColumnCnt &&
+ ( FILL_INDENT == aFPos.eMode ||
+ ( text::HoriOrientation::NONE != aFPos.eOrient &&
+ 0 == aFPos.nTabCnt + aFPos.nSpaceCnt )) &&
+ pCNd && pCNd->Len() )
+ nUndoId = UNDO_EMPTY;
+
+ GetDoc()->StartUndo( nUndoId, NULL );
+
+ SwTxtFmtColl* pNextFmt = 0;
+ SwTxtNode* pTNd = pCNd->GetTxtNode();
+ if( pTNd )
+ pNextFmt = &pTNd->GetTxtColl()->GetNextTxtFmtColl();
+
+ const SwSectionNode* pSectNd = pCNd->FindSectionNode();
+ if( pSectNd && aFPos.nParaCnt )
+ {
+ SwNodeIndex aEnd( aPos.nNode, 1 );
+ while( aEnd.GetNode().IsEndNode() &&
+ (const SwNode*)&aEnd.GetNode() !=
+ pSectNd->EndOfSectionNode() )
+ aEnd++;
+
+ if( aEnd.GetNode().IsEndNode() &&
+ pCNd->Len() == aPos.nContent.GetIndex() )
+ aPos.nNode = *pSectNd->EndOfSectionNode();
+ }
+
+ for( USHORT n = 0; n < aFPos.nParaCnt + aFPos.nColumnCnt; ++n )
+ {
+ GetDoc()->AppendTxtNode( aPos );
+ if( !n && pNextFmt )
+ {
+ *pCurCrsr->GetPoint() = aPos;
+ GetDoc()->SetTxtFmtColl( *pCurCrsr, pNextFmt, false );
+ //JP 04.11.97: erstmal keine Folgevorlage der
+ // Folgevorlage beachten
+ // pNextFmt = pNextFmt->GetNextTxtFmtColl();
+ }
+ if( n < aFPos.nColumnCnt )
+ {
+ *pCurCrsr->GetPoint() = aPos;
+ GetDoc()->InsertPoolItem( *pCurCrsr,
+ SvxFmtBreakItem( SVX_BREAK_COLUMN_BEFORE, RES_BREAK ), 0);
+ }
+ }
+
+ *pCurCrsr->GetPoint() = aPos;
+ switch( aFPos.eMode )
+ {
+ case FILL_INDENT:
+ if( 0 != (pCNd = aPos.nNode.GetNode().GetCntntNode() ))
+ {
+ SfxItemSet aSet( GetDoc()->GetAttrPool(),
+ RES_LR_SPACE, RES_LR_SPACE,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ 0 );
+ SvxLRSpaceItem aLR( (SvxLRSpaceItem&)
+ pCNd->GetAttr( RES_LR_SPACE ) );
+ aLR.SetTxtLeft( aFPos.nTabCnt );
+ aLR.SetTxtFirstLineOfst( 0 );
+ aSet.Put( aLR );
+
+ const SvxAdjustItem& rAdj = (SvxAdjustItem&)pCNd->
+ GetAttr( RES_PARATR_ADJUST );
+ if( SVX_ADJUST_LEFT != rAdj.GetAdjust() )
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );
+
+ GetDoc()->InsertItemSet( *pCurCrsr, aSet, 0 );
+ }
+ else {
+ ASSERT( !this, "wo ist mein CntntNode?" );
+ }
+ break;
+
+ case FILL_TAB:
+ case FILL_SPACE:
+ {
+ String sInsert;
+ if( aFPos.nTabCnt )
+ sInsert.Fill( aFPos.nTabCnt, '\t' );
+ if( aFPos.nSpaceCnt )
+ {
+ String sSpace;
+ sSpace.Fill( aFPos.nSpaceCnt );
+ sInsert += sSpace;
+ }
+ if( sInsert.Len() )
+ {
+ GetDoc()->InsertString( *pCurCrsr, sInsert );
+ }
+ }
+ // kein break - Ausrichtung muss noch gesetzt werden
+ case FILL_MARGIN:
+ if( text::HoriOrientation::NONE != aFPos.eOrient )
+ {
+ SvxAdjustItem aAdj( SVX_ADJUST_LEFT, RES_PARATR_ADJUST );
+ switch( aFPos.eOrient )
+ {
+ case text::HoriOrientation::CENTER:
+ aAdj.SetAdjust( SVX_ADJUST_CENTER );
+ break;
+ case text::HoriOrientation::RIGHT:
+ aAdj.SetAdjust( SVX_ADJUST_RIGHT );
+ break;
+ default:
+ break;
+ }
+ GetDoc()->InsertPoolItem( *pCurCrsr, aAdj, 0 );
+ }
+ break;
+ }
+
+ GetDoc()->EndUndo( nUndoId, NULL );
+ EndAction();
+
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+const SwRedline* SwCrsrShell::SelNextRedline()
+{
+ const SwRedline* pFnd = 0;
+ if( !IsTableMode() )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pFnd = GetDoc()->SelNextRedline( *pCurCrsr );
+ if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ else
+ pFnd = 0;
+ }
+ return pFnd;
+}
+
+const SwRedline* SwCrsrShell::SelPrevRedline()
+{
+ const SwRedline* pFnd = 0;
+ if( !IsTableMode() )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pFnd = GetDoc()->SelPrevRedline( *pCurCrsr );
+ if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ else
+ pFnd = 0;
+ }
+ return pFnd;
+}
+
+const SwRedline* SwCrsrShell::_GotoRedline( USHORT nArrPos, BOOL bSelect )
+{
+ const SwRedline* pFnd = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pFnd = GetDoc()->GetRedlineTbl()[ nArrPos ];
+ if( pFnd )
+ {
+ *pCurCrsr->GetPoint() = *pFnd->Start();
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &pCurCrsr->GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetDoc()->GetNodes().GoNextSection( pIdx,
+ TRUE, IsReadOnlyAvailable() )) )
+ {
+ if( *pIdx <= pFnd->End()->nNode )
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd && bSelect )
+ {
+ pCurCrsr->SetMark();
+ if( nsRedlineType_t::REDLINE_FMTCOLL == pFnd->GetType() )
+ {
+ pCNd = pIdx->GetNode().GetCntntNode();
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ pCurCrsr->GetMark()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ *pCurCrsr->GetPoint() = *pFnd->End();
+
+ pIdx = &pCurCrsr->GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetDoc()->GetNodes().GoPrevSection( pIdx,
+ TRUE, IsReadOnlyAvailable() )) )
+ {
+ if( *pIdx >= pCurCrsr->GetMark()->nNode )
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd )
+ {
+ pCurCrsr->DeleteMark();
+ pCurCrsr->RestoreSavePos();
+ }
+ else if( bSelect && *pCurCrsr->GetMark() == *pCurCrsr->GetPoint() )
+ pCurCrsr->DeleteMark();
+
+ if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE
+ | SwCrsrShell::READONLY );
+ else
+ {
+ pFnd = 0;
+ if( bSelect )
+ pCurCrsr->DeleteMark();
+ }
+ }
+ return pFnd;
+}
+
+const SwRedline* SwCrsrShell::GotoRedline( USHORT nArrPos, BOOL bSelect )
+{
+ const SwRedline* pFnd = 0;
+ if( !IsTableMode() )
+ {
+ SET_CURR_SHELL( this );
+
+ const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
+ const SwRedline* pTmp = rTbl[ nArrPos ];
+ USHORT nSeqNo = pTmp->GetSeqNo();
+ if( nSeqNo && bSelect )
+ {
+ BOOL bCheck = FALSE;
+ int nLoopCnt = 2;
+ USHORT nArrSavPos = nArrPos;
+
+ do {
+ pTmp = _GotoRedline( nArrPos, TRUE );
+
+ if( !pFnd )
+ pFnd = pTmp;
+
+ if( pTmp && bCheck )
+ {
+ // checke auf Ueberlappungen. Das kann durch
+ // FmtColl-Redlines kommen, die auf den gesamten Absatz
+ // aus gedehnt werden.
+
+ SwPaM* pCur = pCurCrsr;
+ SwPaM* pNextPam = (SwPaM*)pCur->GetNext();
+ SwPosition* pCStt = pCur->Start(), *pCEnd = pCur->End();
+ while( pCur != pNextPam )
+ {
+ const SwPosition *pNStt = pNextPam->Start(),
+ *pNEnd = pNextPam->End();
+
+ BOOL bDel = TRUE;
+ switch( ::ComparePosition( *pCStt, *pCEnd,
+ *pNStt, *pNEnd ))
+ {
+ case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
+ if( !pCur->HasMark() )
+ {
+ pCur->SetMark();
+ *pCur->GetMark() = *pNStt;
+ }
+ else
+ *pCStt = *pNStt;
+ *pCEnd = *pNEnd;
+ break;
+
+ case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
+ case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
+ break;
+
+ case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
+ if( !pCur->HasMark() )
+ pCur->SetMark();
+ *pCEnd = *pNEnd;
+ break;
+ case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
+ if( !pCur->HasMark() )
+ {
+ pCur->SetMark();
+ *pCur->GetMark() = *pNStt;
+ }
+ else
+ *pCStt = *pNStt;
+ break;
+
+ default:
+ bDel = FALSE;
+ }
+
+ if( bDel )
+ {
+ // den brauchen wir nicht mehr
+ SwPaM* pPrevPam = (SwPaM*)pNextPam->GetPrev();
+ delete pNextPam;
+ pNextPam = pPrevPam;
+ }
+ pNextPam = (SwPaM*)pNextPam->GetNext();
+ }
+ }
+
+ USHORT nFndPos = 2 == nLoopCnt
+ ? rTbl.FindNextOfSeqNo( nArrPos )
+ : rTbl.FindPrevOfSeqNo( nArrPos );
+ if( USHRT_MAX != nFndPos ||
+ ( 0 != ( --nLoopCnt ) && USHRT_MAX != (
+ nFndPos = rTbl.FindPrevOfSeqNo( nArrSavPos ))) )
+ {
+ if( pTmp )
+ {
+ // neuen Cursor erzeugen
+ CreateCrsr();
+ bCheck = TRUE;
+ }
+ nArrPos = nFndPos;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+ }
+ else
+ pFnd = _GotoRedline( nArrPos, bSelect );
+ }
+ return pFnd;
+}
+
+
+BOOL SwCrsrShell::SelectNxtPrvHyperlink( BOOL bNext )
+{
+ SwNodes& rNds = GetDoc()->GetNodes();
+ const SwNode* pBodyEndNd = &rNds.GetEndOfContent();
+ const SwNode* pBodySttNd = pBodyEndNd->StartOfSectionNode();
+ ULONG nBodySttNdIdx = pBodySttNd->GetIndex();
+ Point aPt;
+
+ _SetGetExpFld aCmpPos( SwPosition( bNext ? *pBodyEndNd : *pBodySttNd ) );
+ _SetGetExpFld aCurPos( bNext ? *pCurCrsr->End() : *pCurCrsr->Start() );
+ if( aCurPos.GetNode() < nBodySttNdIdx )
+ {
+ const SwCntntNode* pCNd = aCurPos.GetNodeFromCntnt()->GetCntntNode();
+ SwCntntFrm* pFrm;
+ if( pCNd && 0 != ( pFrm = pCNd->GetFrm( &aPt )) )
+ aCurPos.SetBodyPos( *pFrm );
+ }
+
+ // check first all the hyperlink fields
+ {
+ const SwTxtNode* pTxtNd;
+ const SwCharFmts* pFmts = GetDoc()->GetCharFmts();
+ for( USHORT n = pFmts->Count(); 1 < n; )
+ {
+ SwClientIter aIter( *(*pFmts)[ --n ] );
+
+ for( SwClient* pFnd = aIter.First(TYPE( SwTxtINetFmt ));
+ pFnd; pFnd = aIter.Next() )
+ if( 0 != ( pTxtNd = ((SwTxtINetFmt*)pFnd)->GetpTxtNode()) &&
+ pTxtNd->GetNodes().IsDocNodes() )
+ {
+ SwTxtINetFmt& rAttr = *(SwTxtINetFmt*)pFnd;
+ SwPosition aTmpPos( *pTxtNd );
+ _SetGetExpFld aPos( aTmpPos.nNode, rAttr );
+ SwCntntFrm* pFrm;
+ if( pTxtNd->GetIndex() < nBodySttNdIdx &&
+ 0 != ( pFrm = pTxtNd->GetFrm( &aPt )) )
+ aPos.SetBodyPos( *pFrm );
+
+ if( bNext
+ ? ( aPos < aCmpPos && aCurPos < aPos )
+ : ( aCmpPos < aPos && aPos < aCurPos ))
+ {
+ String sTxt( pTxtNd->GetExpandTxt( *rAttr.GetStart(),
+ *rAttr.GetEnd() - *rAttr.GetStart() ) );
+
+ sTxt.EraseAllChars( 0x0a );
+ sTxt.EraseLeadingChars().EraseTrailingChars();
+
+ if( sTxt.Len() )
+ aCmpPos = aPos;
+ }
+ }
+ }
+ }
+ // then check all the Flys with a URL or imapge map
+ {
+ const SwSpzFrmFmts* pFmts = GetDoc()->GetSpzFrmFmts();
+ for( USHORT n = 0, nEnd = pFmts->Count(); n < nEnd; ++n )
+ {
+ SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)(*pFmts)[ n ];
+ const SwFmtURL& rURLItem = pFmt->GetURL();
+ if( rURLItem.GetMap() || rURLItem.GetURL().Len() )
+ {
+ SwFlyFrm* pFly = pFmt->GetFrm( &aPt, FALSE );
+ SwPosition aTmpPos( *pBodySttNd );
+ if( pFly &&
+ GetBodyTxtNode( *GetDoc(), aTmpPos, *pFly->GetLower() ) )
+ {
+ _SetGetExpFld aPos( *pFmt, &aTmpPos );
+
+ if( bNext
+ ? ( aPos < aCmpPos && aCurPos < aPos )
+ : ( aCmpPos < aPos && aPos < aCurPos ))
+ aCmpPos = aPos;
+ }
+ }
+ }
+ }
+
+ // found any URL ?
+ BOOL bRet = FALSE;
+ const SwTxtINetFmt* pFndAttr = aCmpPos.GetINetFmt();
+ const SwFlyFrmFmt* pFndFmt = aCmpPos.GetFlyFmt();
+ if( pFndAttr || pFndFmt )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this );
+
+ // find a text attribute ?
+ if( pFndAttr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ aCmpPos.GetPosOfContent( *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetMark();
+ pCurCrsr->GetPoint()->nContent = *pFndAttr->SwTxtAttr::GetEnd();
+
+ if( !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|
+ SwCrsrShell::READONLY );
+ bRet = TRUE;
+ }
+ }
+ // find a draw object ?
+ else if( RES_DRAWFRMFMT == pFndFmt->Which() )
+ {
+ const SdrObject* pSObj = pFndFmt->FindSdrObject();
+ ((SwFEShell*)this)->SelectObj( pSObj->GetCurrentBoundRect().Center() );
+ MakeSelVisible();
+ bRet = TRUE;
+ }
+ else // then is it a fly
+ {
+ SwFlyFrm* pFly = pFndFmt->GetFrm(&aPt, FALSE );
+ if( pFly )
+ {
+ ((SwFEShell*)this)->SelectFlyFrm( *pFly, TRUE );
+ MakeSelVisible();
+ bRet = TRUE;
+ }
+ }
+ }
+ return bRet;
+}
+
diff --git a/sw/source/core/crsr/crstrvl1.cxx b/sw/source/core/crsr/crstrvl1.cxx
new file mode 100644
index 000000000000..53790c2ac28f
--- /dev/null
+++ b/sw/source/core/crsr/crstrvl1.cxx
@@ -0,0 +1,105 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <crsrsh.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+
+BOOL SwCrsrShell::IsStartWord( sal_Int16 nWordType ) const
+{
+ return pCurCrsr->IsStartWord( nWordType );
+}
+
+BOOL SwCrsrShell::IsEndWord( sal_Int16 nWordType ) const
+{
+ return pCurCrsr->IsEndWord( nWordType );
+}
+
+BOOL SwCrsrShell::IsInWord( sal_Int16 nWordType ) const
+{
+ return pCurCrsr->IsInWord( nWordType );
+}
+
+BOOL SwCrsrShell::IsStartSentence() const
+{
+ return pCurCrsr->IsStartEndSentence( false );
+}
+
+BOOL SwCrsrShell::IsEndSentence() const
+{
+ return pCurCrsr->IsStartEndSentence( true );
+}
+
+
+BOOL SwCrsrShell::GoStartWord()
+{
+ return CallCrsrFN( &SwCursor::GoStartWord );
+}
+BOOL SwCrsrShell::GoEndWord()
+{
+ return CallCrsrFN( &SwCursor::GoEndWord );
+}
+BOOL SwCrsrShell::GoNextWord()
+{
+ return CallCrsrFN( &SwCursor::GoNextWord );
+}
+BOOL SwCrsrShell::GoPrevWord()
+{
+ return CallCrsrFN( &SwCursor::GoPrevWord );
+}
+BOOL SwCrsrShell::GoNextSentence()
+{
+ return CallCrsrFN( &SwCursor::GoNextSentence );
+}
+BOOL SwCrsrShell::GoEndSentence()
+{
+ return CallCrsrFN( &SwCursor::GoEndSentence );
+}
+
+BOOL SwCrsrShell::GoPrevSentence()
+{
+ return CallCrsrFN( &SwCursor::GoPrevSentence );
+}
+BOOL SwCrsrShell::GoStartSentence()
+{
+ return CallCrsrFN( &SwCursor::GoStartSentence );
+}
+
+BOOL SwCrsrShell::SelectWord( const Point* pPt )
+{
+ return pCurCrsr->SelectWord( pPt );
+}
+
+BOOL SwCrsrShell::ExpandToSentenceBorders()
+{
+ return pCurCrsr->ExpandToSentenceBorders();
+}
+
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
new file mode 100644
index 000000000000..be581b17735d
--- /dev/null
+++ b/sw/source/core/crsr/findattr.cxx
@@ -0,0 +1,1309 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <i18npool/mslangid.hxx>
+#include <hintids.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/whiter.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <fmtpdsc.hxx>
+#include <txatbase.hxx>
+#include <fchrfmt.hxx>
+#include <charfmt.hxx>
+#include <doc.hxx>
+#include <swcrsr.hxx>
+#include <editsh.hxx>
+#include <ndtxt.hxx>
+#include <pamtyp.hxx>
+#include <swundo.hxx>
+#include <crsskip.hxx>
+#include <undobj.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+SV_DECL_PTRARR_SORT( SwpFmts, SwFmt*, 0, 4 )
+SV_IMPL_PTRARR_SORT( SwpFmts, SwFmt* )
+
+ // Sonderbehandlung fuer SvxFontItem, nur den Namen vergleichen:
+int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
+{
+ switch( rItem1.Which() )
+ {
+ case RES_CHRATR_FONT:
+ return ((SvxFontItem&)rItem1).GetFamilyName() ==
+ ((SvxFontItem&)rItem2).GetFamilyName();
+
+ case RES_CHRATR_COLOR:
+ return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
+ ((SvxColorItem&)rItem2).GetValue() );
+ case RES_PAGEDESC:
+ return ((SwFmtPageDesc&)rItem1).GetNumOffset() ==
+ ((SwFmtPageDesc&)rItem2).GetNumOffset() &&
+ ((SwFmtPageDesc&)rItem1).GetPageDesc() ==
+ ((SwFmtPageDesc&)rItem2).GetPageDesc();
+ }
+ return rItem1 == rItem2;
+}
+
+
+const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, USHORT& rPos,
+ xub_StrLen nCntntPos )
+{
+ while( rPos < rHtsArr.Count() )
+ {
+ const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
+ // der Start vom Attribut muss innerhalb des Bereiches liegen !!
+ if( *pTxtHt->GetStart() >= nCntntPos )
+ return pTxtHt; // gueltiges TextAttribut
+ }
+ return 0; // kein gueltiges TextAttribut
+}
+
+
+const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, USHORT& rPos,
+ xub_StrLen nCntntPos )
+{
+ while( rPos > 0 )
+ {
+ //Hack mit cast fuer das Update
+ const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
+ // der Start vom Attribut muss innerhalb des Bereiches liegen !!
+ if( *pTxtHt->GetStart() < nCntntPos )
+ return pTxtHt; // gueltiges TextAttribut
+ }
+ return 0; // kein gueltiges TextAttribut
+}
+
+
+void lcl_SetAttrPam( SwPaM & rPam, xub_StrLen nStart, const xub_StrLen* pEnde,
+ const BOOL bSaveMark )
+{
+ xub_StrLen nCntntPos;
+ if( bSaveMark )
+ nCntntPos = rPam.GetMark()->nContent.GetIndex();
+ else
+ nCntntPos = rPam.GetPoint()->nContent.GetIndex();
+ BOOL bTstEnde = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
+
+ SwCntntNode* pCNd = rPam.GetCntntNode();
+ rPam.GetPoint()->nContent.Assign( pCNd, nStart );
+ rPam.SetMark(); // Point == GetMark
+
+ // Point zeigt auf das Ende vom SuchBereich oder Ende vom Attribut
+ if( pEnde )
+ {
+ if( bTstEnde && *pEnde > nCntntPos )
+ rPam.GetPoint()->nContent = nCntntPos;
+ else
+ rPam.GetPoint()->nContent = *pEnde;
+ }
+}
+
+//------------------ Suche nach einem Text Attribut -----------------------
+
+// diese Funktion sucht in einem TextNode nach dem vorgegebenen Attribut.
+// Wird es gefunden, dann hat der SwPaM den Bereich der das Attribut
+// umspannt, unter Beachtung des Suchbereiches
+
+
+BOOL lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
+ const SfxPoolItem& rCmpItem,
+ SwMoveFn fnMove, BOOL bValue )
+{
+ if ( !rTxtNd.HasHints() )
+ return FALSE;
+ const SwTxtAttr *pTxtHt = 0;
+ BOOL bForward = fnMove == fnMoveForward;
+ USHORT nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
+ xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex();
+
+ while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
+ if( pTxtHt->Which() == rCmpItem.Which() &&
+ ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
+ {
+ lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->GetEnd(), bForward );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+//------------------ Suche nach mehren Text Attributen -------------------
+
+struct _SwSrchChrAttr
+{
+ USHORT nWhich;
+ xub_StrLen nStt, nEnd;
+
+ _SwSrchChrAttr( const SfxPoolItem& rItem,
+ xub_StrLen nStart, xub_StrLen nAnyEnd )
+ : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
+ {}
+};
+
+class SwAttrCheckArr
+{
+ _SwSrchChrAttr *pFndArr, *pStackArr;
+ xub_StrLen nNdStt, nNdEnd;
+ USHORT nArrStart, nArrLen;
+ USHORT nFound, nStackCnt;
+ SfxItemSet aCmpSet;
+ BOOL bNoColls;
+ BOOL bForward;
+
+public:
+ SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections );
+ ~SwAttrCheckArr();
+
+ void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
+
+ // wieviele Attribute ueberhaupt ??
+ USHORT Count() const { return aCmpSet.Count(); }
+ int Found() const { return nFound == aCmpSet.Count(); }
+ int CheckStack();
+
+ xub_StrLen Start() const;
+ xub_StrLen End() const;
+
+ xub_StrLen GetNdStt() const { return nNdStt; }
+ xub_StrLen GetNdEnd() const { return nNdEnd; }
+
+ int SetAttrFwd( const SwTxtAttr& rAttr );
+ int SetAttrBwd( const SwTxtAttr& rAttr );
+};
+
+
+
+SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd,
+ int bNoCollections )
+ : aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
+{
+ aCmpSet.Put( rSet, FALSE );
+ bNoColls = 0 != bNoCollections;
+
+ bForward = 0 != bFwd;
+
+ // Bestimmen den Bereich des Fnd/Stack-Arrays (Min/Max)
+ SfxItemIter aIter( aCmpSet );
+ nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
+ nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
+
+ char* pFndChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
+ char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
+
+ pFndArr = (_SwSrchChrAttr*)pFndChar;
+ pStackArr = (_SwSrchChrAttr*)pStackChar;
+}
+
+SwAttrCheckArr::~SwAttrCheckArr()
+{
+ delete[] (char*)pFndArr;
+ delete[] (char*)pStackArr;
+}
+
+void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
+{
+ memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
+ memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
+ nFound = 0;
+ nStackCnt = 0;
+
+ if( bForward )
+ {
+ nNdStt = rPam.GetPoint()->nContent.GetIndex();
+ nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
+ ? rPam.GetMark()->nContent.GetIndex()
+ : rTxtNd.GetTxt().Len();
+ }
+ else
+ {
+ nNdEnd = rPam.GetPoint()->nContent.GetIndex();
+ nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
+ ? rPam.GetMark()->nContent.GetIndex()
+ : 0;
+ }
+
+ if( bNoColls && !rTxtNd.HasSwAttrSet() )
+ return ;
+
+ const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
+// if( !rSet.Count() )
+// return;
+
+ SfxItemIter aIter( aCmpSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ const SfxPoolItem* pFndItem;
+ USHORT nWhich;
+
+ while( TRUE )
+ {
+ // nur testen, ob vorhanden ist ?
+ if( IsInvalidItem( pItem ) )
+ {
+ nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
+ if( RES_TXTATR_END <= nWhich )
+ break; // Ende der TextAttribute
+
+ if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
+ && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
+ {
+ pFndArr[ nWhich - nArrStart ] =
+ _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
+ nFound++;
+ }
+ }
+ else
+ {
+ if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
+ break; // Ende der TextAttribute
+
+//JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
+// runter
+// if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
+// && *pFndItem == *pItem )
+ if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
+ {
+ pFndArr[ nWhich - nArrStart ] =
+ _SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
+ nFound++;
+ }
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+}
+int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
+{
+ _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
+ // alle die nicht im Bereich sind -> ignorieren
+ if( aTmp.nEnd <= nNdStt || aTmp.nStt >= nNdEnd )
+ return Found();
+
+ const SfxPoolItem* pItem;
+
+// --------------------------------------------------------------
+// Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
+// --------------------------------------------------------------
+ USHORT nWhch = rAttr.Which();
+ SfxWhichIter* pIter = NULL;
+ const SfxPoolItem* pTmpItem = NULL;
+ const SfxItemSet* pSet = NULL;
+ if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
+ {
+ if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
+ return Found();
+ pTmpItem = NULL;
+ pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( pSet )
+ {
+ pIter = new SfxWhichIter( *pSet );
+ nWhch = pIter->FirstWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, TRUE, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ pTmpItem = NULL;
+ }
+ }
+ else
+ pTmpItem = &rAttr.GetAttr();
+ while( pTmpItem )
+ {
+ SfxItemState eState = aCmpSet.GetItemState( nWhch, FALSE, &pItem );
+ if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
+ {
+ USHORT n;
+ _SwSrchChrAttr* pCmp;
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind:
+
+ _SwSrchChrAttr* pArrPtr;
+ if( nFound )
+ for( pArrPtr = pFndArr, n = 0; n < nArrLen;
+ ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ nFound--;
+ }
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
+ // die Start Position ragen, vom Stack in den FndSet
+
+ if( nStackCnt )
+ for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
+ {
+ if( !pArrPtr->nWhich )
+ continue;
+
+ if( pArrPtr->nEnd <= aTmp.nStt )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ if( !--nStackCnt )
+ break;
+ }
+ else if( pArrPtr->nStt <= aTmp.nStt )
+ {
+ if( ( pCmp = &pFndArr[ n ])->nWhich )
+ {
+ if( pCmp->nEnd < pArrPtr->nEnd ) // erweitern
+ pCmp->nEnd = pArrPtr->nEnd;
+ }
+ else
+ {
+ *pCmp = *pArrPtr;
+ nFound++;
+ }
+ pArrPtr->nWhich = 0;
+ if( !--nStackCnt )
+ break;
+ }
+ }
+
+ BOOL bContinue = FALSE;
+
+ if( SFX_ITEM_DONTCARE == eState )
+ {
+ // wird Attribut gueltig ?
+ if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
+ *pTmpItem ))
+ {
+ // suche das Attribut und erweiter es gegebenenfalls
+ if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ *pCmp = aTmp; // nicht gefunden, eintragen
+ nFound++;
+ }
+ else if( pCmp->nEnd < aTmp.nEnd ) // erweitern ?
+ pCmp->nEnd = aTmp.nEnd;
+
+ bContinue = TRUE;
+ }
+ }
+ // wird Attribut gueltig ?
+ else if( CmpAttr( *pItem, *pTmpItem ) )
+ {
+ pFndArr[ nWhch - nArrStart ] = aTmp;
+ ++nFound;
+ bContinue = TRUE;
+ }
+
+ // tja, dann muss es auf den Stack
+ if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
+ if( pCmp->nEnd > aTmp.nEnd )
+ {
+ ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
+ "Stack-Platz ist noch belegt" );
+
+ // ---------
+ // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
+ // pCmp->nStt = aTmp.nEnd;
+ if( aTmp.nStt <= pCmp->nStt )
+ pCmp->nStt = aTmp.nEnd;
+ else
+ pCmp->nEnd = aTmp.nStt;
+ // ---------
+
+ pStackArr[ nWhch - nArrStart ] = *pCmp;
+ nStackCnt++;
+ }
+ pCmp->nWhich = 0;
+ nFound--;
+ }
+ }
+ if( pIter )
+ {
+ nWhch = pIter->NextWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, TRUE, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ break;
+ }
+ else
+ break;
+ }
+ return Found();
+}
+
+
+int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
+{
+ _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
+ // alle die nicht im Bereich sind -> ignorieren
+ if( aTmp.nEnd < nNdStt || aTmp.nStt >= nNdEnd )
+ return Found();
+
+ const SfxPoolItem* pItem;
+// --------------------------------------------------------------
+// Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
+// --------------------------------------------------------------
+ USHORT nWhch = rAttr.Which();
+ SfxWhichIter* pIter = NULL;
+ const SfxPoolItem* pTmpItem = NULL;
+ const SfxItemSet* pSet = NULL;
+ if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
+ {
+ if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
+ return Found();
+
+ pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( pSet )
+ {
+ pIter = new SfxWhichIter( *pSet );
+ nWhch = pIter->FirstWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, TRUE, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ pTmpItem = NULL;
+ }
+ }
+ else
+ pTmpItem = &rAttr.GetAttr();
+ while( pTmpItem )
+ {
+ SfxItemState eState = aCmpSet.GetItemState( nWhch, FALSE, &pItem );
+ if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
+ {
+ USHORT n;
+ _SwSrchChrAttr* pCmp;
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind:
+
+ _SwSrchChrAttr* pArrPtr;
+ if( nFound )
+ for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ nFound--;
+ }
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
+ // die Start Position ragen, vom Stack in den FndSet
+
+ if( nStackCnt )
+ for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
+ {
+ if( !pArrPtr->nWhich )
+ continue;
+
+ if( pArrPtr->nStt >= aTmp.nEnd )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ if( !--nStackCnt )
+ break;
+ }
+ else if( pArrPtr->nEnd >= aTmp.nEnd )
+ {
+ if( ( pCmp = &pFndArr[ n ])->nWhich )
+ {
+ if( pCmp->nStt > pArrPtr->nStt ) // erweitern
+ pCmp->nStt = pArrPtr->nStt;
+ }
+ else
+ {
+ *pCmp = *pArrPtr;
+ nFound++;
+ }
+ pArrPtr->nWhich = 0;
+ if( !--nStackCnt )
+ break;
+ }
+ }
+
+ BOOL bContinue = FALSE;
+ if( SFX_ITEM_DONTCARE == eState )
+ {
+ // wird Attribut gueltig ?
+ if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
+ *pTmpItem ) )
+ {
+ // suche das Attribut und erweiter es gegebenenfalls
+ if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ *pCmp = aTmp; // nicht gefunden, eintragen
+ nFound++;
+ }
+ else if( pCmp->nStt > aTmp.nStt ) // erweitern ?
+ pCmp->nStt = aTmp.nStt;
+
+ bContinue = TRUE;
+ }
+ }
+ // wird Attribut gueltig ?
+ else if( CmpAttr( *pItem, *pTmpItem ))
+ {
+ pFndArr[ nWhch - nArrStart ] = aTmp;
+ ++nFound;
+ bContinue = TRUE;
+ }
+
+ // tja, dann muss es auf den Stack
+ if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
+ if( pCmp->nStt < aTmp.nStt )
+ {
+ ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
+ "Stack-Platz ist noch belegt" );
+
+// ---------
+// JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
+// pCmp->nEnd = aTmp.nStt;
+ if( aTmp.nEnd <= pCmp->nEnd )
+ pCmp->nEnd = aTmp.nStt;
+ else
+ pCmp->nStt = aTmp.nEnd;
+// ---------
+
+ pStackArr[ nWhch - nArrStart ] = *pCmp;
+ nStackCnt++;
+ }
+ pCmp->nWhich = 0;
+ nFound--;
+ }
+ }
+ if( pIter )
+ {
+ nWhch = pIter->NextWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, TRUE, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ break;
+ }
+ else
+ break;
+ }
+ return Found();
+}
+
+
+xub_StrLen SwAttrCheckArr::Start() const
+{
+ xub_StrLen nStart = nNdStt;
+ _SwSrchChrAttr* pArrPtr = pFndArr;
+ for( USHORT n = 0; n < nArrLen; ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
+ nStart = pArrPtr->nStt;
+
+ return nStart;
+}
+
+
+xub_StrLen SwAttrCheckArr::End() const
+{
+ _SwSrchChrAttr* pArrPtr = pFndArr;
+ xub_StrLen nEnd = nNdEnd;
+ for( USHORT n = 0; n < nArrLen; ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
+ nEnd = pArrPtr->nEnd;
+
+ return nEnd;
+}
+
+
+int SwAttrCheckArr::CheckStack()
+{
+ if( !nStackCnt )
+ return FALSE;
+
+ USHORT n;
+ xub_StrLen nSttPos = Start(), nEndPos = End();
+ _SwSrchChrAttr* pArrPtr;
+ for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
+ {
+ if( !pArrPtr->nWhich )
+ continue;
+
+ if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ if( !--nStackCnt )
+ return nFound == aCmpSet.Count();
+ }
+ else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
+ {
+ // alle die "offen" sind, heisst ueber die Start Position ragen,
+ // im FndSet setzen
+ ASSERT( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" );
+ pFndArr[ n ] = *pArrPtr;
+ pArrPtr->nWhich = 0;
+ nFound++;
+ if( !--nStackCnt )
+ return nFound == aCmpSet.Count();
+ }
+ }
+ return nFound == aCmpSet.Count();
+}
+
+
+
+int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
+ SwPaM& rPam )
+{
+ xub_StrLen nEndPos, nSttPos;
+ rCmpArr.SetNewSet( rTxtNd, rPam );
+ if( !rTxtNd.HasHints() )
+ {
+ if( !rCmpArr.Found() )
+ return FALSE;
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, TRUE );
+ return TRUE;
+ }
+
+ // dann gehe mal durch das nach "Start" sortierte Array
+ const SwpHints& rHtArr = rTxtNd.GetSwpHints();
+ const SwTxtAttr* pAttr;
+ USHORT nPos = 0;
+
+ // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
+ // das wieder beendet wird.
+ if( rCmpArr.Found() )
+ {
+ for( ; nPos < rHtArr.Count(); ++nPos )
+ if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
+ {
+ if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
+ {
+ // dann haben wir unser Ende:
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
+ pAttr->GetStart(), TRUE );
+ return TRUE;
+ }
+ // ansonsten muessen wir weiter suchen
+ break;
+ }
+
+ if( nPos == rHtArr.Count() && rCmpArr.Found() )
+ {
+ // dann haben wir unseren Bereich
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, TRUE );
+ return TRUE;
+ }
+ }
+
+ for( ; nPos < rHtArr.Count(); ++nPos )
+ if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
+ {
+ // sollten noch mehr auf der gleichen Position anfangen ??
+ // auch die noch mit testen !!
+ nSttPos = *pAttr->GetStart();
+ while( ++nPos < rHtArr.Count() && nSttPos ==
+ *( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
+ rCmpArr.SetAttrFwd( *pAttr ) )
+ ;
+ if( !rCmpArr.Found() )
+ continue;
+
+ // dann haben wir den Bereich zusammen
+ if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return FALSE;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, TRUE );
+ return TRUE;
+ }
+
+ if( !rCmpArr.CheckStack() ||
+ (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return FALSE;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, TRUE );
+ return TRUE;
+}
+
+
+int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
+ SwPaM& rPam )
+{
+ xub_StrLen nEndPos, nSttPos;
+ rCmpArr.SetNewSet( rTxtNd, rPam );
+ if( !rTxtNd.HasHints() )
+ {
+ if( !rCmpArr.Found() )
+ return FALSE;
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, FALSE );
+ return TRUE;
+ }
+
+ // dann gehe mal durch das nach "Start" sortierte Array
+ const SwpHints& rHtArr = rTxtNd.GetSwpHints();
+ const SwTxtAttr* pAttr;
+ USHORT nPos = rHtArr.Count();
+
+ // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
+ // das wieder beendet wird.
+ if( rCmpArr.Found() )
+ {
+ while( nPos )
+ if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
+ {
+ nSttPos = *pAttr->GetAnyEnd();
+ if( nSttPos < rCmpArr.GetNdEnd() )
+ {
+ // dann haben wir unser Ende:
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, FALSE );
+ return TRUE;
+ }
+
+ // ansonsten muessen wir weiter suchen
+ break;
+ }
+
+ if( !nPos && rCmpArr.Found() )
+ {
+ // dann haben wir unseren Bereich
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, FALSE );
+ return TRUE;
+ }
+ }
+
+ while( nPos )
+ if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
+ {
+ // sollten noch mehr auf der gleichen Position anfangen ??
+ // auch die noch mit testen !!
+ if( nPos )
+ {
+ nEndPos = *pAttr->GetAnyEnd();
+ while( --nPos && nEndPos ==
+ *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
+ rCmpArr.SetAttrBwd( *pAttr ) )
+ ;
+ }
+ if( !rCmpArr.Found() )
+ continue;
+
+
+ // dann haben wir den Bereich zusammen
+ if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return FALSE;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, FALSE );
+ return TRUE;
+ }
+
+ if( !rCmpArr.CheckStack() ||
+ (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return FALSE;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, FALSE );
+ return TRUE;
+}
+
+
+int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, BOOL bNoColls )
+{
+ // nur die harte Attributierung suchen ?
+ if( bNoColls && !rCNd.HasSwAttrSet() )
+ return FALSE;
+
+ const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
+ SfxItemIter aIter( rCmpSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ const SfxPoolItem* pNdItem;
+ USHORT nWhich;
+
+ while( TRUE )
+ {
+ // nur testen, ob vorhanden ist ?
+ if( IsInvalidItem( pItem ))
+ {
+ nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
+ if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
+ || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
+ return FALSE;
+ }
+ else
+ {
+ nWhich = pItem->Which();
+//JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
+// runter
+// if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
+// || *pNdItem != *pItem )
+ if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
+ return FALSE;
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ return TRUE; // wurde gefunden
+}
+
+
+BOOL SwPaM::Find( const SfxPoolItem& rAttr, BOOL bValue, SwMoveFn fnMove,
+ const SwPaM *pRegion, BOOL bInReadOnly )
+{
+ // stelle fest welches Attribut gesucht wird:
+ USHORT nWhich = rAttr.Which();
+ int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
+
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+
+ BOOL bFound = FALSE;
+ BOOL bFirst = TRUE;
+ BOOL bSrchForward = fnMove == fnMoveForward;
+ SwCntntNode * pNode;
+ const SfxPoolItem* pItem;
+ SwpFmts aFmtArr;
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ if( bSrchForward
+ ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
+ : !pPam->GetPoint()->nContent.GetIndex() )
+ {
+ if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, FALSE ))
+ {
+ delete pPam;
+ return FALSE;
+ }
+ SwCntntNode *pNd = pPam->GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
+ }
+
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
+ {
+ if( bCharAttr )
+ {
+ if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
+ continue;
+
+ if( ((SwTxtNode*)pNode)->HasHints() &&
+ lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove, bValue ))
+ {
+ // setze auf die Werte vom Attribut
+ SetMark();
+ *GetPoint() = *pPam->GetPoint();
+ *GetMark() = *pPam->GetMark();
+ bFound = TRUE;
+ break;
+ }
+ else if (isTXTATR(nWhich))
+ continue; // --> also weiter
+ }
+
+ // keine harte Attributierung, dann pruefe, ob die Vorlage schon
+ // mal nach dem Attribut befragt wurde
+ if( !pNode->HasSwAttrSet() )
+ {
+ const SwFmt* pTmpFmt = pNode->GetFmtColl();
+ if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
+ continue; // die Collection wurde schon mal befragt
+ aFmtArr.Insert( pTmpFmt );
+ }
+
+ if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
+ TRUE, &pItem ) && ( !bValue || *pItem == rAttr ) )
+ {
+ // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
+ // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
+ // und immer nach der Logik: inkl. Start, exkl. End !!!
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+ pNode->MakeEndIndex( &GetPoint()->nContent );
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ // beim rueckwaerts Suchen noch Point und Mark vertauschen
+ if( bFound && !bSrchForward )
+ Exchange();
+
+ delete pPam;
+ return bFound;
+}
+
+
+typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
+
+BOOL SwPaM::Find( const SfxItemSet& rSet, BOOL bNoColls, SwMoveFn fnMove,
+ const SwPaM *pRegion, BOOL bInReadOnly, BOOL bMoveFirst )
+{
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+
+ BOOL bFound = FALSE;
+ BOOL bFirst = TRUE;
+ BOOL bSrchForward = fnMove == fnMoveForward;
+ SwCntntNode * pNode;
+ SwpFmts aFmtArr;
+
+ // teste doch mal welche Text/Char-Attribute gesucht werden
+ SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
+ SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
+ RES_PARATR_BEGIN, RES_GRFATR_END-1 );
+ aOtherSet.Put( rSet, FALSE ); // alle Invalid-Items erhalten!
+
+ FnSearchAttr fnSearch = bSrchForward
+ ? (&::lcl_SearchForward)
+ : (&::lcl_SearchBackward);
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ // Wenn am Anfang/Ende, aus dem Node moven
+ if( bMoveFirst &&
+ ( bSrchForward
+ ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
+ : !pPam->GetPoint()->nContent.GetIndex() ) )
+ {
+ if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, FALSE ))
+ {
+ delete pPam;
+ return FALSE;
+ }
+ SwCntntNode *pNd = pPam->GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
+ }
+
+
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
+ {
+ if( aCmpArr.Count() )
+ {
+ if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
+ continue;
+
+ if( (!aOtherSet.Count() ||
+ lcl_Search( *pNode, aOtherSet, bNoColls )) &&
+ (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
+ {
+ // setze auf die Werte vom Attribut
+ SetMark();
+ *GetPoint() = *pPam->GetPoint();
+ *GetMark() = *pPam->GetMark();
+ bFound = TRUE;
+ break;
+ }
+ continue; // TextAttribute
+ }
+
+ if( !aOtherSet.Count() )
+ continue;
+
+ // keine harte Attributierung, dann pruefe, ob die Vorlage schon
+ // mal nach dem Attribut befragt wurde
+ if( !pNode->HasSwAttrSet() )
+ {
+ const SwFmt* pTmpFmt = pNode->GetFmtColl();
+ if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
+ continue; // die Collection wurde schon mal befragt
+ aFmtArr.Insert( pTmpFmt );
+ }
+
+ if( lcl_Search( *pNode, aOtherSet, bNoColls ))
+ {
+ // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
+ // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
+ // und immer nach der Logik: inkl. Start, exkl. End !!!
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+ pNode->MakeEndIndex( &GetPoint()->nContent );
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ // beim rueckwaerts Suchen noch Point und Mark vertauschen
+ if( bFound && !bSrchForward )
+ Exchange();
+
+ delete pPam;
+ return bFound;
+}
+
+//------------------ Methoden vom SwCursor ---------------------------
+
+// Parameter fuer das Suchen vom Attributen
+struct SwFindParaAttr : public SwFindParas
+{
+ BOOL bValue;
+ const SfxItemSet *pSet, *pReplSet;
+ const SearchOptions *pSearchOpt;
+ SwCursor& rCursor;
+ utl::TextSearch* pSTxt;
+
+ SwFindParaAttr( const SfxItemSet& rSet, BOOL bNoCollection,
+ const SearchOptions* pOpt, const SfxItemSet* pRSet,
+ SwCursor& rCrsr )
+ : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
+ pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
+
+ virtual ~SwFindParaAttr() { delete pSTxt; }
+
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, BOOL bInReadOnly );
+ virtual int IsReplaceMode() const;
+};
+
+
+int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
+ BOOL bInReadOnly )
+{
+ // String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert
+ // gesucht wird)
+ BOOL bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
+ !pSet->Count() );
+ BOOL bReplaceAttr = pReplSet && pReplSet->Count();
+ BOOL bMoveFirst = !bReplaceAttr;
+ if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
+ bInReadOnly = FALSE;
+
+ // wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ?
+ {
+ SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
+ SwPaM* pTextRegion = &aRegion;
+ SwPaM aSrchPam( *pCrsr->GetPoint() );
+
+ while( TRUE )
+ {
+ if( pSet->Count() ) // gibts ueberhaupt Attributierung?
+ {
+ // zuerst die Attributierung
+ if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
+//JP 17.11.95: was ist mit Attributen in leeren Absaetzen !!
+// || *pCrsr->GetMark() == *pCrsr->GetPoint() ) // kein Bereich ??
+ return FIND_NOT_FOUND;
+ bMoveFirst = TRUE;
+
+ if( !pSearchOpt )
+ break; // ok, nur Attribute, also gefunden
+
+ pTextRegion = &aSrchPam;
+ }
+ else if( !pSearchOpt )
+ return FIND_NOT_FOUND;
+
+ // dann darin den Text
+ if( !pSTxt )
+ {
+ SearchOptions aTmp( *pSearchOpt );
+
+ // search in selection
+ aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
+ SearchFlags::REG_NOT_ENDOFLINE);
+
+ MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
+
+ pSTxt = new utl::TextSearch( aTmp );
+ }
+
+ // todo/mba: searching for attributes in Outliner text?!
+ BOOL bSearchInNotes = FALSE;
+
+ // Bug 24665: suche im richtigen Bereich weiter (pTextRegion!)
+ if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
+ *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) // gefunden ?
+ break; // also raus
+ else if( !pSet->Count() )
+ return FIND_NOT_FOUND; // nur Text und nicht gefunden
+
+/* // --> FME 2007-4-12 #i74765 # Why should we move the position?
+ Moving the position results in bugs when there are two adjacent
+ portions which both have the requested attributes set. I suspect this
+ should be only be an optimization. Therefore I boldly remove it now!
+
+ // JP: und wieder neu aufsetzen, aber eine Position weiter
+ //JP 04.11.97: Bug 44897 - aber den Mark wieder aufheben, damit
+ // weiterbewegt werden kann!
+ {
+ BOOL bCheckRegion = TRUE;
+ SwPosition* pPos = aSrchPam.GetPoint();
+ if( !(*fnMove->fnNd)( &pPos->nNode.GetNode(),
+ &pPos->nContent, CRSR_SKIP_CHARS ))
+ {
+ if( (*fnMove->fnNds)( &pPos->nNode, FALSE ))
+ {
+ SwCntntNode *pNd = pPos->nNode.GetNode().GetCntntNode();
+ xub_StrLen nCPos;
+ if( fnMove == fnMoveForward )
+ nCPos = 0;
+ else
+ nCPos = pNd->Len();
+ pPos->nContent.Assign( pNd, nCPos );
+ }
+ else
+ bCheckRegion = FALSE;
+ }
+ if( !bCheckRegion || *aRegion.GetPoint() <= *pPos )
+ return FIND_NOT_FOUND; // nicht gefunden
+ }*/
+ *aRegion.GetMark() = *aSrchPam.GetPoint();
+ }
+
+ *pCrsr->GetPoint() = *aSrchPam.GetPoint();
+ pCrsr->SetMark();
+ *pCrsr->GetMark() = *aSrchPam.GetMark();
+ }
+
+ if( bReplaceTxt )
+ {
+ const bool bRegExp(
+ SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
+ SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
+ xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
+
+ // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
+ // mit aufnehmen !!
+ Ring *pPrevRing = 0;
+ if( bRegExp )
+ {
+ pPrevRing = pRegion->GetPrev();
+ ((Ring*)pRegion)->MoveRingTo( &rCursor );
+ }
+
+ ::std::auto_ptr<String> pRepl( (bRegExp) ?
+ ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
+ rCursor.GetDoc()->ReplaceRange( *pCrsr,
+ (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
+ bRegExp );
+ rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
+
+ if( bRegExp )
+ {
+ // und die Region wieder herausnehmen:
+ Ring *p, *pNext = (Ring*)pRegion;
+ do {
+ p = pNext;
+ pNext = p->GetNext();
+ p->MoveTo( (Ring*)pRegion );
+ } while( p != pPrevRing );
+ }
+ rSttCntIdx = nSttCnt;
+ }
+
+ if( bReplaceAttr )
+ {
+ // --- Ist die Selection noch da ??????
+
+ // und noch die Attribute setzen
+#ifdef OLD
+ pCrsr->GetDoc()->Insert( *pCrsr, *pReplSet, 0 );
+#else
+ //JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im
+ // ReplaceSet angegeben, auf Default zurueck gesetzt
+
+ if( !pSet->Count() )
+ {
+ pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
+ }
+ else
+ {
+ SfxItemPool* pPool = pReplSet->GetPool();
+ SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
+
+ SfxItemIter aIter( *pSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( TRUE )
+ {
+ // alle die nicht gesetzt sind mit Pool-Defaults aufuellen
+ if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
+ pReplSet->GetItemState( pItem->Which(), FALSE ))
+ aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ aSet.Put( *pReplSet );
+ pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
+ }
+#endif
+ return FIND_NO_RING;
+ }
+
+ else
+ return FIND_FOUND;
+}
+
+
+int SwFindParaAttr::IsReplaceMode() const
+{
+ return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) ||
+ ( pReplSet && pReplSet->Count() );
+}
+
+// Suchen nach Attributen
+
+
+ULONG SwCursor::Find( const SfxItemSet& rSet, BOOL bNoCollections,
+ SwDocPositions nStart, SwDocPositions nEnde, BOOL& bCancel,
+ FindRanges eFndRngs,
+ const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ BOOL bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
+ !rSet.Count() ) ) ||
+ (pReplSet && pReplSet->Count());
+ BOOL bSttUndo = pDoc->DoesUndo() && bReplace;
+ if( bSttUndo )
+ pDoc->StartUndo( UNDO_REPLACE, NULL );
+
+ SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
+ pReplSet, *this );
+
+ ULONG nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+ if( nRet && bReplace )
+ pDoc->SetModified();
+
+ if( bSttUndo )
+ pDoc->EndUndo( UNDO_REPLACE, NULL );
+
+ return nRet;
+}
+
+
+
diff --git a/sw/source/core/crsr/findcoll.cxx b/sw/source/core/crsr/findcoll.cxx
new file mode 100644
index 000000000000..4bb594ceb4ca
--- /dev/null
+++ b/sw/source/core/crsr/findcoll.cxx
@@ -0,0 +1,119 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <swcrsr.hxx>
+#include <doc.hxx>
+#include <pamtyp.hxx>
+#include <swundo.hxx>
+#include <undobj.hxx>
+#ifndef _COMCORE_HRC
+#include <comcore.hrc>
+#endif
+#include <tools/resid.hxx>
+
+//------------------ Methoden der CrsrShell ---------------------------
+
+// Parameter fuer das Suchen vom FormatCollections
+struct SwFindParaFmtColl : public SwFindParas
+{
+ const SwTxtFmtColl *pFmtColl, *pReplColl;
+ SwCursor& rCursor;
+ SwFindParaFmtColl( const SwTxtFmtColl& rFmtColl,
+ const SwTxtFmtColl* pRpColl, SwCursor& rCrsr )
+ : pFmtColl( &rFmtColl ), pReplColl( pRpColl ), rCursor( rCrsr )
+ {}
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, BOOL bInReadOnly );
+ virtual int IsReplaceMode() const;
+};
+
+
+int SwFindParaFmtColl::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
+ BOOL bInReadOnly )
+{
+ int nRet = FIND_FOUND;
+ if( bInReadOnly && pReplColl )
+ bInReadOnly = FALSE;
+
+ if( !pCrsr->Find( *pFmtColl, fnMove, pRegion, bInReadOnly ) )
+ nRet = FIND_NOT_FOUND;
+ else if( pReplColl )
+ {
+ pCrsr->GetDoc()->SetTxtFmtColl( *pCrsr, (SwTxtFmtColl*)pReplColl );
+ nRet = FIND_NO_RING;
+ }
+ return nRet;
+}
+
+
+int SwFindParaFmtColl::IsReplaceMode() const
+{
+ return 0 != pReplColl;
+}
+
+
+// Suchen nach Format-Collections
+
+
+ULONG SwCursor::Find( const SwTxtFmtColl& rFmtColl,
+ SwDocPositions nStart, SwDocPositions nEnde, BOOL& bCancel,
+ FindRanges eFndRngs, const SwTxtFmtColl* pReplFmtColl )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ BOOL bSttUndo = pDoc->DoesUndo() && pReplFmtColl;
+ if( bSttUndo )
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, rFmtColl.GetName());
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, pReplFmtColl->GetName());
+
+ pDoc->StartUndo( UNDO_UI_REPLACE_STYLE, &aRewriter );
+ }
+
+ SwFindParaFmtColl aSwFindParaFmtColl( rFmtColl, pReplFmtColl, *this );
+
+ ULONG nRet = FindAll( aSwFindParaFmtColl, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+
+ if( nRet && pReplFmtColl )
+ pDoc->SetModified();
+
+ if( bSttUndo )
+ pDoc->EndUndo( UNDO_UI_REPLACE_STYLE, NULL );
+ return nRet;
+}
+
+
+
diff --git a/sw/source/core/crsr/findfmt.cxx b/sw/source/core/crsr/findfmt.cxx
new file mode 100644
index 000000000000..bf3492ae0a65
--- /dev/null
+++ b/sw/source/core/crsr/findfmt.cxx
@@ -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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <doc.hxx>
+#include <pamtyp.hxx>
+
+
+BOOL SwPaM::Find( const SwFmt& rFmt, SwMoveFn fnMove,
+ const SwPaM *pRegion, BOOL bInReadOnly )
+{
+ BOOL bFound = FALSE;
+ BOOL bSrchForward = fnMove == fnMoveForward;
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ if( bSrchForward
+ ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
+ : !pPam->GetPoint()->nContent.GetIndex() )
+ {
+ if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, FALSE ))
+ {
+ delete pPam;
+ return FALSE;
+ }
+ SwCntntNode *pNd = pPam->GetPoint()->nNode.GetNode().GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
+ }
+
+ BOOL bFirst = TRUE;
+ SwCntntNode* pNode;
+ while( !bFound &&
+ 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly )))
+ {
+ if( 0 != ( bFound = pNode->GetFmtColl() == &rFmt ))
+ {
+ // wurde die FormatCollection gefunden, dann handelt es sich auf
+ // jedenfall um einen SwCntntNode !!
+
+ // FORWARD: SPoint an das Ende, GetMark zum Anfanf vom Node
+ // BACKWARD: SPoint zum Anfang, GetMark an das Ende vom Node
+ // und immer nach der Logik: inkl. Start, exkl. End !!!
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+ pNode->MakeEndIndex( &GetPoint()->nContent );
+ GetMark()->nContent = 0;
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // SPoint und GetMark tauschen
+ break;
+ }
+ }
+ delete pPam;
+ return bFound;
+}
+
+
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
new file mode 100644
index 000000000000..4a0697692975
--- /dev/null
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -0,0 +1,707 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+
+
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#include <vcl/svapp.hxx>
+#include <txatritr.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <txtatr.hxx>
+#include <txtfld.hxx>
+#include <swcrsr.hxx>
+#include <doc.hxx>
+#include <pamtyp.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx>
+#include <breakit.hxx>
+
+#include <docsh.hxx>
+#include <PostItMgr.hxx>
+#include <viewsh.hxx>
+#include <vcl/window.hxx>
+
+using namespace ::com::sun::star;
+using namespace util;
+
+String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam );
+
+String& lcl_CleanStr( const SwTxtNode& rNd, xub_StrLen nStart,
+ xub_StrLen& rEnde, SvULongs& rArr, String& rRet,
+ bool bRemoveSoftHyphen )
+{
+ rRet = rNd.GetTxt();
+ if( rArr.Count() )
+ rArr.Remove( 0, rArr.Count() );
+
+ const SwpHints *pHts = rNd.GetpSwpHints();
+
+ USHORT n = 0;
+ xub_StrLen nSoftHyphen = nStart;
+ xub_StrLen nHintStart = STRING_LEN;
+ bool bNewHint = true;
+ bool bNewSoftHyphen = true;
+ const xub_StrLen nEnd = rEnde;
+ SvUShorts aReplaced;
+
+ do
+ {
+ if ( bNewHint )
+ nHintStart = pHts && n < pHts->Count() ?
+ *(*pHts)[n]->GetStart() :
+ STRING_LEN;
+
+ if ( bNewSoftHyphen )
+ nSoftHyphen = bRemoveSoftHyphen ?
+ rNd.GetTxt().Search( CHAR_SOFTHYPHEN, nSoftHyphen ) :
+ STRING_LEN;
+
+ bNewHint = false;
+ bNewSoftHyphen = false;
+
+ xub_StrLen nStt = 0;
+
+ // Check if next stop is a hint.
+ if ( STRING_LEN != nHintStart && nHintStart < nSoftHyphen && nHintStart < nEnd )
+ {
+ nStt = nHintStart;
+ bNewHint = true;
+ }
+ // Check if next stop is a soft hyphen.
+ else if ( STRING_LEN != nSoftHyphen && nSoftHyphen < nHintStart && nSoftHyphen < nEnd )
+ {
+ nStt = nSoftHyphen;
+ bNewSoftHyphen = true;
+ }
+ // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
+ else if ( STRING_LEN != nSoftHyphen && nSoftHyphen == nHintStart )
+ {
+ nStt = nSoftHyphen;
+ bNewHint = true;
+ bNewSoftHyphen = true;
+ }
+ else
+ break;
+
+ const xub_StrLen nAkt = nStt - rArr.Count();
+
+ if ( bNewHint )
+ {
+ const SwTxtAttr* pHt = (*pHts)[n];
+ if ( pHt->HasDummyChar() && (nStt >= nStart) )
+ {
+ //JP 17.05.00: Task 75806 ask for ">=" and not for ">"
+ switch( pHt->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ {
+ // JP 06.05.98: mit Bug 50100 werden sie als Trenner erwuenscht und nicht
+ // mehr zum Wort dazu gehoerend.
+ // MA 23.06.98: mit Bug 51215 sollen sie konsequenterweise auch am
+ // Satzanfang und -ende ignoriert werden wenn sie Leer sind.
+ // Dazu werden sie schlicht entfernt. Fuer den Anfang entfernen
+ // wir sie einfach.
+ // Fuer das Ende merken wir uns die Ersetzungen und entferenen
+ // hinterher alle am Stringende (koenten ja 'normale' 0x7f drinstehen
+ BOOL bEmpty = RES_TXTATR_FIELD != pHt->Which() ||
+ !(static_cast<SwTxtFld const*>(pHt)
+ ->GetFld().GetFld()->ExpandField(
+ rNd.GetDoc()->IsClipBoard()).Len());
+ if ( bEmpty && nStart == nAkt )
+ {
+ rArr.Insert( nAkt, rArr.Count() );
+ --rEnde;
+ rRet.Erase( nAkt, 1 );
+ }
+ else
+ {
+ if ( bEmpty )
+ aReplaced.Insert( nAkt, aReplaced.Count() );
+ rRet.SetChar( nAkt, '\x7f' );
+ }
+ }
+ break;
+ default:
+ ASSERT( false, "unknown case in lcl_CleanStr" )
+ break;
+ }
+ }
+ ++n;
+ }
+
+ if ( bNewSoftHyphen )
+ {
+ rArr.Insert( nAkt, rArr.Count() );
+ --rEnde;
+ rRet.Erase( nAkt, 1 );
+ ++nSoftHyphen;
+ }
+ }
+ while ( true );
+
+ for( USHORT i = aReplaced.Count(); i; )
+ {
+ const xub_StrLen nTmp = aReplaced[ --i ];
+ if( nTmp == rRet.Len() - 1 )
+ {
+ rRet.Erase( nTmp );
+ rArr.Insert( nTmp, rArr.Count() );
+ --rEnde;
+ }
+ }
+
+ return rRet;
+}
+
+// skip all non SwPostIts inside the array
+xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts)
+{
+ xub_StrLen aIndex = 0;
+ while (aCount)
+ {
+ for (xub_StrLen i = 0; i <pHts->Count();i++)
+ {
+ aIndex++;
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ {
+ aCount--;
+ if (!aCount)
+ break;
+ }
+ }
+ }
+ // throw away all following non postits
+ for (xub_StrLen i = aIndex; i <pHts->Count();i++)
+ {
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ break;
+ else
+ aIndex++;
+ }
+ return aIndex;
+}
+
+BYTE SwPaM::Find( const SearchOptions& rSearchOpt, BOOL bSearchInNotes , utl::TextSearch& rSTxt,
+ SwMoveFn fnMove, const SwPaM * pRegion,
+ BOOL bInReadOnly )
+{
+ if( !rSearchOpt.searchString.getLength() )
+ return FALSE;
+
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+ BOOL bSrchForward = fnMove == fnMoveForward;
+ SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
+ SwIndex& rCntntIdx = pPam->GetPoint()->nContent;
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ // beim leeren Node nicht weiter
+ if( bSrchForward
+ ? ( rCntntIdx.GetIndex() == pPam->GetCntntNode()->Len() &&
+ rCntntIdx.GetIndex() )
+ : !rCntntIdx.GetIndex() && pPam->GetCntntNode()->Len() )
+ {
+ if( !(*fnMove->fnNds)( &rNdIdx, FALSE ))
+ {
+ delete pPam;
+ return FALSE;
+ }
+ SwCntntNode *pNd = rNdIdx.GetNode().GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ rCntntIdx.Assign( pNd, nTmpPos );
+ }
+
+ /*
+ * Ist bFound == TRUE, dann wurde der String gefunden und in
+ * nStart und nEnde steht der gefundenen String
+ */
+ BOOL bFound = FALSE;
+ /*
+ * StartPostion im Text oder Anfangsposition
+ */
+ BOOL bFirst = TRUE;
+ SwCntntNode * pNode;
+ //testarea
+ //String sCleanStr;
+ //SvULongs aFltArr;
+ //const SwNode* pSttNd = &rNdIdx.GetNode();
+
+ xub_StrLen nStart, nEnde, nTxtLen;
+
+ BOOL bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType;
+ BOOL bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
+ ( !rSearchOpt.searchString.compareToAscii( "^$" ) ||
+ !rSearchOpt.searchString.compareToAscii( "$^" ) );
+ BOOL bChkParaEnd = bRegSearch && 1 == rSearchOpt.searchString.getLength() &&
+ !rSearchOpt.searchString.compareToAscii( "$" );
+
+// LanguageType eLastLang = 0;
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
+ {
+ if( pNode->IsTxtNode() )
+ {
+ nTxtLen = ((SwTxtNode*)pNode)->GetTxt().Len();
+ if( rNdIdx == pPam->GetMark()->nNode )
+ nEnde = pPam->GetMark()->nContent.GetIndex();
+ else
+ nEnde = bSrchForward ? nTxtLen : 0;
+ nStart = rCntntIdx.GetIndex();
+
+ /* #i80135# */
+ // if there are SwPostItFields inside our current node text, we split the text into seperate pieces
+ // and search for text inside the pieces as well as inside the fields
+ const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints();
+
+ // count postitfields by looping over all fields
+ xub_StrLen aNumberPostits = 0;
+ xub_StrLen aIgnore = 0;
+ if (pHts && bSearchInNotes)
+ {
+ if (!bSrchForward)
+ {
+ xub_StrLen swap = nEnde;
+ nEnde = nStart;
+ nStart = swap;
+ }
+
+ for (xub_StrLen i = 0; i <pHts->Count();i++)
+ {
+ xub_StrLen aPos = *(*pHts)[i]->GetStart();
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ {
+ if ( (aPos >= nStart) && (aPos <= nEnde) )
+ aNumberPostits++;
+ else
+ {
+ if (bSrchForward)
+ aIgnore++;
+ }
+ }
+ }
+
+ if (!bSrchForward)
+ {
+ xub_StrLen swap = nEnde;
+ nEnde = nStart;
+ nStart = swap;
+ }
+
+ }
+
+ SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell();
+ ViewShell *const pWrtShell = (pDocShell) ? (ViewShell*)(pDocShell->GetWrtShell()) : 0;
+ SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0;
+
+ xub_StrLen aStart = 0;
+ // do we need to finish a note?
+ if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
+ {
+ if (bSearchInNotes)
+ {
+ if (bSrchForward)
+ aStart++;
+ else
+ {
+ if (aNumberPostits)
+ --aNumberPostits;
+ }
+ //search inside and finsih and put focus back into the doc
+ if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
+ {
+ bFound = true ;
+ break;
+ }
+ }
+ else
+ {
+ pPostItMgr->SetActiveSidebarWin(0);
+ }
+ }
+
+ if (aNumberPostits)
+ {
+ // now we have to split
+ xub_StrLen nStartInside = 0;
+ xub_StrLen nEndeInside = 0;
+ sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits;
+
+ while ( (aLoop>=0) && (aLoop<=aNumberPostits))
+ {
+ if (bSrchForward)
+ {
+ nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
+ nEndeInside = aLoop==aNumberPostits? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
+ nTxtLen = nEndeInside-nStartInside;
+ }
+ else
+ {
+ nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
+ nEndeInside = aLoop==0 ? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
+ nTxtLen = nStartInside-nEndeInside;
+ }
+ // search inside the text between a note
+ bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
+ nStartInside,nEndeInside,nTxtLen, pNode,pPam);
+ if (bFound)
+ break;
+ else
+ {
+ // we should now be right in front of a note, search inside
+ if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) ))
+ {
+ const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)];
+ if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFld(),rSearchOpt,bSrchForward) )
+ {
+ bFound = true ;
+ break;
+ }
+ }
+ }
+ aLoop = bSrchForward ? aLoop+1 : aLoop-1;
+ }
+ }
+ else
+ {
+ // if there is no SwPostItField inside or searching inside notes is disabled, we search the whole length just like before
+ bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
+ nStart,nEnde,nTxtLen, pNode,pPam);
+ }
+ if (bFound)
+ break;
+ }
+ }
+ delete pPam;
+ return bFound;
+}
+
+bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt,
+ SwMoveFn fnMove,
+ BOOL bSrchForward, BOOL bRegSearch, BOOL bChkEmptyPara, BOOL bChkParaEnd,
+ xub_StrLen &nStart, xub_StrLen &nEnde, xub_StrLen nTxtLen,SwNode* pNode, SwPaM* pPam)
+{
+ bool bFound = false;
+ SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
+ const SwNode* pSttNd = &rNdIdx.GetNode();
+ String sCleanStr;
+ SvULongs aFltArr;
+ LanguageType eLastLang = 0;
+ // if the search string contains a soft hypen, we don't strip them from the text:
+ bool bRemoveSoftHyphens = true;
+ if ( bRegSearch )
+ {
+ const rtl::OUString a00AD( rtl::OUString::createFromAscii( "\\x00AD" ) );
+ if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) )
+ bRemoveSoftHyphens = false;
+ }
+ else
+ {
+ if ( 1 == rSearchOpt.searchString.getLength() &&
+ CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
+ bRemoveSoftHyphens = false;
+ }
+
+ if( bSrchForward )
+ lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnde,
+ aFltArr, sCleanStr, bRemoveSoftHyphens );
+ else
+ lcl_CleanStr( *(SwTxtNode*)pNode, nEnde, nStart,
+ aFltArr, sCleanStr, bRemoveSoftHyphens );
+
+ SwScriptIterator* pScriptIter = 0;
+ USHORT nSearchScript = 0;
+ USHORT nCurrScript = 0;
+
+ if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType &&
+ pBreakIt->GetBreakIter().is() )
+ {
+ pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward );
+ nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
+ }
+
+ xub_StrLen nStringEnd = nEnde;
+ while ( (bSrchForward && nStart < nStringEnd) ||
+ (! bSrchForward && nStart > nStringEnd) )
+ {
+ // SearchAlgorithms_APPROXIMATE works on a per word base
+ // so we have to provide the text searcher with the correct
+ // locale, because it uses the breakiterator
+ if ( pScriptIter )
+ {
+ nEnde = pScriptIter->GetScriptChgPos();
+ nCurrScript = pScriptIter->GetCurrScript();
+ if ( nSearchScript == nCurrScript )
+ {
+ const LanguageType eCurrLang =
+ ((SwTxtNode*)pNode)->GetLang( bSrchForward ?
+ nStart :
+ nEnde );
+
+ if ( eCurrLang != eLastLang )
+ {
+ const lang::Locale aLocale(
+ pBreakIt->GetLocale( eCurrLang ) );
+ rSTxt.SetLocale( rSearchOpt, aLocale );
+ eLastLang = eCurrLang;
+ }
+ }
+ pScriptIter->Next();
+ }
+
+ if( nSearchScript == nCurrScript &&
+ (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnde, 0 ))
+ {
+ // setze den Bereich richtig
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+
+ // Start und Ende wieder korrigieren !!
+ if( aFltArr.Count() )
+ {
+ xub_StrLen n, nNew;
+ // bei Rueckwaertssuche die Positionen temp. vertauschen
+ if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
+
+ for( n = 0, nNew = nStart;
+ n < aFltArr.Count() && aFltArr[ n ] <= nStart;
+ ++n, ++nNew )
+ ;
+ nStart = nNew;
+ for( n = 0, nNew = nEnde;
+ n < aFltArr.Count() && aFltArr[ n ] < nEnde;
+ ++n, ++nNew )
+ ;
+ nEnde = nNew;
+
+ // bei Rueckwaertssuche die Positionen temp. vertauschen
+ if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
+ }
+ GetMark()->nContent = nStart; // Startposition setzen
+ GetPoint()->nContent = nEnde;
+
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // Point und Mark tauschen
+ bFound = TRUE;
+ break;
+ }
+
+ nStart = nEnde;
+ } // end of script while
+
+ delete pScriptIter;
+
+ if ( bFound )
+ return true;
+ else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd )
+ {
+ *GetPoint() = *pPam->GetPoint();
+ GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0;
+ SetMark();
+ if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) &&
+ Move( fnMoveForward, fnGoCntnt ) &&
+ (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) &&
+ 1 == Abs( (int)( GetPoint()->nNode.GetIndex() -
+ GetMark()->nNode.GetIndex()) ) )
+ {
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // Point und Mark tauschen
+ //bFound = TRUE;
+ //break;
+ return true;
+ }
+ }
+ return bFound;
+}
+
+// Parameter fuers Suchen und Ersetzen von Text
+struct SwFindParaText : public SwFindParas
+{
+ const SearchOptions& rSearchOpt;
+ SwCursor& rCursor;
+ utl::TextSearch aSTxt;
+ BOOL bReplace;
+ BOOL bSearchInNotes;
+
+ SwFindParaText( const SearchOptions& rOpt, BOOL bSearchNotes, int bRepl, SwCursor& rCrsr )
+ : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes )
+ {}
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, BOOL bInReadOnly );
+ virtual int IsReplaceMode() const;
+ virtual ~SwFindParaText();
+};
+
+SwFindParaText::~SwFindParaText()
+{
+}
+
+int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
+ const SwPaM* pRegion, BOOL bInReadOnly )
+{
+ if( bInReadOnly && bReplace )
+ bInReadOnly = FALSE;
+
+ BOOL bFnd = (BOOL)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly );
+
+ /* #i80135# if we found something in a note, Mark and Point is the same
+ if( bFnd && *pCrsr->GetMark() == *pCrsr->GetPoint() )
+ return FIND_NOT_FOUND;
+ */
+
+ if( bFnd && bReplace ) // String ersetzen ??
+ {
+ // Replace-Methode vom SwDoc benutzen
+ const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType);
+ SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
+ xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
+ // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
+ // mit aufnehmen !!
+ Ring *pPrev(0);
+ if( bRegExp )
+ {
+ pPrev = pRegion->GetPrev();
+ ((Ring*)pRegion)->MoveRingTo( &rCursor );
+ }
+
+ ::std::auto_ptr<String> pRepl( (bRegExp)
+ ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
+ rCursor.GetDoc()->ReplaceRange( *pCrsr,
+ (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString),
+ bRegExp );
+ rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
+
+ if( bRegExp )
+ {
+ // und die Region wieder herausnehmen:
+ Ring *p, *pNext = (Ring*)pRegion;
+ do {
+ p = pNext;
+ pNext = p->GetNext();
+ p->MoveTo( (Ring*)pRegion );
+ } while( p != pPrev );
+ }
+ pCrsr->Start()->nContent = nSttCnt;
+ return FIND_NO_RING;
+ }
+ return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
+}
+
+
+int SwFindParaText::IsReplaceMode() const
+{
+ return bReplace;
+}
+
+
+ULONG SwCursor::Find( const SearchOptions& rSearchOpt, BOOL bSearchInNotes,
+ SwDocPositions nStart, SwDocPositions nEnde,
+ BOOL& bCancel,
+ FindRanges eFndRngs, int bReplace )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ BOOL bSttUndo = pDoc->DoesUndo() && bReplace;
+ if( bSttUndo )
+ pDoc->StartUndo( UNDO_REPLACE, NULL );
+
+ BOOL bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
+ if( bSearchSel )
+ eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL);
+ SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this );
+ ULONG nRet = FindAll( aSwFindParaText, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+ if( nRet && bReplace )
+ pDoc->SetModified();
+
+ if( bSttUndo )
+ pDoc->EndUndo( UNDO_REPLACE, NULL );
+ return nRet;
+}
+
+String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam )
+{
+ String *pRet = 0;
+ if( pPam && pPam->HasMark() &&
+ SearchAlgorithms_REGEXP == rSearchOpt.algorithmType )
+ {
+ const SwCntntNode* pTxtNode = pPam->GetCntntNode( TRUE );
+ if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( FALSE ) )
+ {
+ utl::TextSearch aSTxt( rSearchOpt );
+ String aStr( pPam->GetTxt() );
+ String aSearchStr( rSearchOpt.searchString );
+ String aReplaceStr( rSearchOpt.replaceString );
+ aStr.EraseAllChars( CH_TXTATR_BREAKWORD );
+ aStr.EraseAllChars( CH_TXTATR_INWORD );
+ xub_StrLen nStart = 0;
+ String sX( 'x' );
+ if( pPam->Start()->nContent > 0 )
+ {
+ aStr.Insert( sX, 0 );
+ ++nStart;
+ }
+ xub_StrLen nEnd = aStr.Len();
+ bool bDeleteLastX = false;
+ if( pPam->End()->nContent < (static_cast<const SwTxtNode*>(pTxtNode))->GetTxt().Len() )
+ {
+ aStr.Insert( sX );
+ bDeleteLastX = true;
+ }
+ SearchResult aResult;
+ if( aSTxt.SearchFrwrd( aStr, &nStart, &nEnd, &aResult ) )
+ {
+ if( bDeleteLastX )
+ aStr.Erase( aStr.Len() - 1 );
+ aSTxt.ReplaceBackReferences( aReplaceStr, aStr, aResult );
+ pRet = new String( aReplaceStr );
+ }
+ }
+ }
+ return pRet;
+}
+
+
diff --git a/sw/source/core/crsr/makefile.mk b/sw/source/core/crsr/makefile.mk
new file mode 100644
index 000000000000..a2571901c068
--- /dev/null
+++ b/sw/source/core/crsr/makefile.mk
@@ -0,0 +1,83 @@
+#*************************************************************************
+#
+# 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=sw
+TARGET=crsr
+
+AUTOSEG=true
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : $(PRJ)$/inc$/swpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/inc$/sw.mk
+
+.IF "$(mydebug)" != ""
+CDEFS+=-Dmydebug
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+EXCEPTIONSFILES= \
+ $(SLO)$/crbm.obj \
+ $(SLO)$/crsrsh.obj \
+ $(SLO)$/bookmrk.obj \
+ $(SLO)$/viscrs.obj
+
+SLOFILES = \
+ $(SLO)$/BlockCursor.obj \
+ $(SLO)$/bookmrk.obj \
+ $(SLO)$/callnk.obj \
+ $(SLO)$/crbm.obj \
+ $(SLO)$/crsrsh.obj \
+ $(SLO)$/crstrvl.obj \
+ $(SLO)$/crstrvl1.obj \
+ $(SLO)$/findattr.obj \
+ $(SLO)$/findcoll.obj \
+ $(SLO)$/findfmt.obj \
+ $(SLO)$/findtxt.obj \
+ $(SLO)$/pam.obj \
+ $(SLO)$/paminit.obj \
+ $(SLO)$/swcrsr.obj \
+ $(SLO)$/trvlcol.obj \
+ $(SLO)$/trvlfnfl.obj \
+ $(SLO)$/trvlreg.obj \
+ $(SLO)$/trvltbl.obj \
+ $(SLO)$/unocrsr.obj \
+ $(SLO)$/viscrs.obj \
+ $(SLO)$/crossrefbookmark.obj
+
+.IF "$(mydebug)" != ""
+SLOFILES += \
+ $(SLO)$/pamio.obj
+.ENDIF
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx
new file mode 100644
index 000000000000..ec30b5aefbe0
--- /dev/null
+++ b/sw/source/core/crsr/pam.cxx
@@ -0,0 +1,1246 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/protitem.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <pamtyp.hxx>
+#include <txtfrm.hxx>
+#include <section.hxx>
+#include <fmtcntnt.hxx>
+#include <frmatr.hxx>
+#include <swtable.hxx>
+#include <crsskip.hxx>
+
+// --> FME 2004-06-29 #114856# Formular view
+#include <flyfrm.hxx>
+#include <fmteiro.hxx>
+#include <section.hxx>
+#include <sectfrm.hxx>
+// <--
+#include <ndtxt.hxx> // #111827#
+
+#include <IMark.hxx>
+#include <hints.hxx>
+
+// fuer den dummen ?MSC-? Compiler
+inline xub_StrLen GetSttOrEnd( BOOL bCondition, const SwCntntNode& rNd )
+{
+ return bCondition ? 0 : rNd.Len();
+}
+
+/*************************************************************************
+|*
+|* SwPosition
+|*
+|* Beschreibung PAM.DOC
+|* Ersterstellung VB 4.3.91
+|* Letzte Aenderung VB 4.3.91
+|*
+*************************************************************************/
+
+
+SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwIndex & rCntnt )
+ : nNode( rNodeIndex ), nContent( rCntnt )
+{
+}
+
+SwPosition::SwPosition( const SwNodeIndex & rNodeIndex )
+ : nNode( rNodeIndex ), nContent( nNode.GetNode().GetCntntNode() )
+{
+}
+
+SwPosition::SwPosition( const SwNode& rNode )
+ : nNode( rNode ), nContent( nNode.GetNode().GetCntntNode() )
+{
+}
+
+SwPosition::SwPosition( SwCntntNode & rNode, const xub_StrLen nOffset )
+ : nNode( rNode ), nContent( &rNode, nOffset )
+{
+}
+
+
+SwPosition::SwPosition( const SwPosition & rPos )
+ : nNode( rPos.nNode ), nContent( rPos.nContent )
+{
+}
+
+SwPosition &SwPosition::operator=(const SwPosition &rPos)
+{
+ nNode = rPos.nNode;
+ nContent = rPos.nContent;
+ return *this;
+}
+
+
+BOOL SwPosition::operator<(const SwPosition &rPos) const
+{
+ if( nNode < rPos.nNode )
+ return TRUE;
+ if( nNode == rPos.nNode )
+ return ( nContent < rPos.nContent );
+ return FALSE;
+}
+
+
+BOOL SwPosition::operator>(const SwPosition &rPos) const
+{
+ if(nNode > rPos.nNode )
+ return TRUE;
+ if( nNode == rPos.nNode )
+ return ( nContent > rPos.nContent );
+ return FALSE;
+}
+
+
+BOOL SwPosition::operator<=(const SwPosition &rPos) const
+{
+ if(nNode < rPos.nNode )
+ return TRUE;
+ if( nNode == rPos.nNode )
+ return ( nContent <= rPos.nContent );
+ return FALSE;
+}
+
+
+BOOL SwPosition::operator>=(const SwPosition &rPos) const
+{
+ if(nNode > rPos.nNode )
+ return TRUE;
+ if( nNode == rPos.nNode )
+ return ( nContent >= rPos.nContent );
+ return FALSE;
+}
+
+
+BOOL SwPosition::operator==(const SwPosition &rPos) const
+{
+ return
+ ( ( nNode == rPos.nNode ) && ( nContent == rPos.nContent ) ?
+ TRUE: FALSE);
+}
+
+
+BOOL SwPosition::operator!=(const SwPosition &rPos) const
+{
+ if( nNode != rPos.nNode )
+ return TRUE;
+ return ( nContent != rPos.nContent );
+}
+
+SwDoc * SwPosition::GetDoc() const
+{
+ return nNode.GetNode().GetDoc();
+}
+
+SwComparePosition ComparePosition(
+ const SwPosition& rStt1, const SwPosition& rEnd1,
+ const SwPosition& rStt2, const SwPosition& rEnd2 )
+{
+ SwComparePosition nRet;
+ if( rStt1 < rStt2 )
+ {
+ if( rEnd1 > rStt2 )
+ {
+ if( rEnd1 >= rEnd2 )
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEFORE;
+
+ }
+ else if( rEnd1 == rStt2 )
+ nRet = POS_COLLIDE_END;
+ else
+ nRet = POS_BEFORE;
+ }
+ else if( rEnd2 > rStt1 )
+ {
+ if( rEnd2 >= rEnd1 )
+ {
+ if( rEnd2 == rEnd1 && rStt2 == rStt1 )
+ nRet = POS_EQUAL;
+ else
+ nRet = POS_INSIDE;
+ }
+ else
+ {
+ if (rStt1 == rStt2)
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEHIND;
+ }
+ }
+ else if( rEnd2 == rStt1 )
+ nRet = POS_COLLIDE_START;
+ else
+ nRet = POS_BEHIND;
+ return nRet;
+}
+
+SwComparePosition ComparePosition(
+ const unsigned long nStt1, const unsigned long nEnd1,
+ const unsigned long nStt2, const unsigned long nEnd2 )
+{
+ SwComparePosition nRet;
+ if( nStt1 < nStt2 )
+ {
+ if( nEnd1 > nStt2 )
+ {
+ if( nEnd1 >= nEnd2 )
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEFORE;
+
+ }
+ else if( nEnd1 == nStt2 )
+ nRet = POS_COLLIDE_END;
+ else
+ nRet = POS_BEFORE;
+ }
+ else if( nEnd2 > nStt1 )
+ {
+ if( nEnd2 >= nEnd1 )
+ {
+ if( nEnd2 == nEnd1 && nStt2 == nStt1 )
+ nRet = POS_EQUAL;
+ else
+ nRet = POS_INSIDE;
+ }
+ else
+ {
+ if (nStt1 == nStt2)
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEHIND;
+ }
+ }
+ else if( nEnd2 == nStt1 )
+ nRet = POS_COLLIDE_START;
+ else
+ nRet = POS_BEHIND;
+ return nRet;
+}
+
+/* */
+
+enum CHKSECTION { Chk_Both, Chk_One, Chk_None };
+
+
+CHKSECTION lcl_TstIdx( ULONG nSttIdx, ULONG nEndIdx, const SwNode& rEndNd )
+{
+ ULONG nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex();
+ CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None;
+ if( nStt < nEndIdx && nEnd >= nEndIdx )
+ return( eSec == Chk_One ? Chk_Both : Chk_One );
+ return eSec;
+}
+
+
+BOOL lcl_ChkOneRange( CHKSECTION eSec, BOOL bChkSections,
+ const SwNode& rBaseEnd, ULONG nStt, ULONG nEnd )
+{
+ if( eSec != Chk_Both )
+ return FALSE;
+
+ if( !bChkSections )
+ return TRUE;
+
+ // suche die umspannende Section
+ const SwNodes& rNds = rBaseEnd.GetNodes();
+ const SwNode *pTmp, *pNd = rNds[ nStt ];
+ if( !pNd->IsStartNode() )
+ pNd = pNd->StartOfSectionNode();
+
+ if( pNd == rNds[ nEnd ]->StartOfSectionNode() )
+ return TRUE; // der gleiche StartNode, die selbe Section
+
+ // steht schon auf einem GrundSection Node ? Fehler !!!
+ if( !pNd->StartOfSectionIndex() )
+ return FALSE;
+
+ while( ( pTmp = pNd->StartOfSectionNode())->EndOfSectionNode() !=
+ &rBaseEnd )
+ pNd = pTmp;
+
+ ULONG nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex();
+ return nSttIdx <= nStt && nStt <= nEndIdx &&
+ nSttIdx <= nEnd && nEnd <= nEndIdx ? TRUE : FALSE;
+}
+
+
+BOOL CheckNodesRange( const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd, BOOL bChkSection )
+{
+ const SwNodes& rNds = rStt.GetNodes();
+ ULONG nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
+ CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() );
+ if( Chk_None != eSec ) return eSec == Chk_Both ? TRUE : FALSE;
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfAutotext(), nStt, nEnd );
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfPostIts(), nStt, nEnd );
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfInserts(), nStt, nEnd );
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfRedlines(), nStt, nEnd );
+
+ return FALSE; // liegt irgendwo dazwischen, FEHLER
+}
+
+
+BOOL GoNext(SwNode* pNd, SwIndex * pIdx, USHORT nMode )
+{
+ if( pNd->IsCntntNode() )
+ return ((SwCntntNode*)pNd)->GoNext( pIdx, nMode );
+ return FALSE;
+}
+
+
+BOOL GoPrevious( SwNode* pNd, SwIndex * pIdx, USHORT nMode )
+{
+ if( pNd->IsCntntNode() )
+ return ((SwCntntNode*)pNd)->GoPrevious( pIdx, nMode );
+ return FALSE;
+}
+
+
+SwCntntNode* GoNextNds( SwNodeIndex* pIdx, BOOL bChk )
+{
+ SwNodeIndex aIdx( *pIdx );
+ SwCntntNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
+ if( pNd )
+ {
+ if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() &&
+ !CheckNodesRange( *pIdx, aIdx, TRUE ) )
+ pNd = 0;
+ else
+ *pIdx = aIdx;
+ }
+ return pNd;
+}
+
+
+SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, BOOL bChk )
+{
+ SwNodeIndex aIdx( *pIdx );
+ SwCntntNode* pNd = aIdx.GetNodes().GoPrevious( &aIdx );
+ if( pNd )
+ {
+ if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() &&
+ !CheckNodesRange( *pIdx, aIdx, TRUE ) )
+ pNd = 0;
+ else
+ *pIdx = aIdx;
+ }
+ return pNd;
+}
+
+// ----------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwPointAndMark
+|*
+|* Beschreibung PAM.DOC
+|* Ersterstellung VB 4.3.91
+|* Letzte Aenderung JP 6.5.91
+|*
+*************************************************************************/
+
+SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rPos )
+ , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize
+ , m_pPoint( &m_Bound1 )
+ , m_pMark( m_pPoint )
+ , m_bIsInFrontOfLabel( false )
+{
+}
+
+SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+}
+
+SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint,
+ long nMarkOffset, long nPointOffset, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ if ( nMarkOffset )
+ {
+ m_pMark->nNode += nMarkOffset;
+ }
+ if ( nPointOffset )
+ {
+ m_pPoint->nNode += nPointOffset;
+ }
+
+ m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
+ m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
+}
+
+SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint,
+ long nMarkOffset, long nPointOffset, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ if ( nMarkOffset )
+ {
+ m_pMark->nNode += nMarkOffset;
+ }
+ if ( nPointOffset )
+ {
+ m_pPoint->nNode += nPointOffset;
+ }
+
+ m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
+ m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
+}
+
+SwPaM::SwPaM( const SwNodeIndex& rMark , xub_StrLen nMarkCntnt,
+ const SwNodeIndex& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( rPoint.GetNode().GetCntntNode(), nPointCntnt);
+ m_pMark ->nContent.Assign( rMark .GetNode().GetCntntNode(), nMarkCntnt );
+}
+
+SwPaM::SwPaM( const SwNode& rMark , xub_StrLen nMarkCntnt,
+ const SwNode& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
+ nPointCntnt);
+ m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetCntntNode(),
+ nMarkCntnt );
+}
+
+SwPaM::SwPaM( const SwNode& rNode, xub_StrLen nCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rNode )
+ , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize
+ , m_pPoint( &m_Bound1 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
+ nCntnt );
+}
+
+SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, xub_StrLen nCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rNodeIdx )
+ , m_Bound2( rNodeIdx.GetNode().GetNodes() ) // default initialize
+ , m_pPoint( &m_Bound1 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetCntntNode(), nCntnt );
+}
+
+SwPaM::~SwPaM() {}
+
+// @@@ semantic: no copy ctor.
+SwPaM::SwPaM( SwPaM &rPam )
+ : Ring( &rPam )
+ , m_Bound1( *(rPam.m_pPoint) )
+ , m_Bound2( *(rPam.m_pMark) )
+ , m_pPoint( &m_Bound1 ), m_pMark( rPam.HasMark() ? &m_Bound2 : m_pPoint )
+ , m_bIsInFrontOfLabel( false )
+{
+}
+
+// @@@ semantic: no copy assignment for super class Ring.
+SwPaM &SwPaM::operator=( const SwPaM &rPam )
+{
+ *m_pPoint = *( rPam.m_pPoint );
+ if ( rPam.HasMark() )
+ {
+ SetMark();
+ *m_pMark = *( rPam.m_pMark );
+ }
+ else
+ {
+ DeleteMark();
+ }
+ return *this;
+}
+
+void SwPaM::SetMark()
+{
+ if (m_pPoint == &m_Bound1)
+ {
+ m_pMark = &m_Bound2;
+ }
+ else
+ {
+ m_pMark = &m_Bound1;
+ }
+ (*m_pMark) = (*m_pPoint);
+}
+
+#ifdef DBG_UTIL
+
+void SwPaM::Exchange()
+{
+ if (m_pPoint != m_pMark)
+ {
+ SwPosition *pTmp = m_pPoint;
+ m_pPoint = m_pMark;
+ m_pMark = pTmp;
+ }
+}
+#endif
+
+// Bewegen des Cursors
+
+
+BOOL SwPaM::Move( SwMoveFn fnMove, SwGoInDoc fnGo )
+{
+ BOOL bRet = (*fnGo)( *this, fnMove );
+
+ m_bIsInFrontOfLabel = false;
+
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* void SwPaM::MakeRegion( SwMoveFn, SwPaM*, const SwPaM* )
+|*
+|* Beschreibung Setzt den 1. SwPaM auf den uebergebenen SwPaM
+|* oder setzt auf den Anfang oder Ende vom Document.
+|* SPoint bleibt auf der Position stehen, GetMark aendert
+|* sich entsprechend !
+|*
+|* Parameter SwDirection gibt an, ob an Anfang / Ende
+|* SwPaM * der zu setzende Bereich
+|* const SwPaM& der enventuell vorgegeben Bereich
+|* Return-Werte SwPaM* der entsprehend neu gesetzte Bereich
+|*
+|* Ersterstellung JP 26.04.91
+|* Letzte Aenderung JP 26.04.91
+|*
+*************************************************************************/
+
+
+SwPaM* SwPaM::MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg )
+{
+ SwPaM* pPam;
+ if( pOrigRg == 0 )
+ {
+ pPam = new SwPaM( *m_pPoint );
+ pPam->SetMark(); // setze Anfang fest
+ pPam->Move( fnMove, fnGoSection); // an Anfang / Ende vom Node
+
+ // stelle SPoint wieder auf alte Position, GetMark auf das "Ende"
+ pPam->Exchange();
+ }
+ else
+ {
+ pPam = new SwPaM( *(SwPaM*)pOrigRg ); // die Suchregion ist vorgegeben
+ // sorge dafuer, dass SPoint auf dem "echten" StartPunkt steht
+ // FORWARD --> SPoint immer kleiner als GetMark
+ // BACKWARD --> SPoint immer groesser als GetMark
+ if( (pPam->GetMark()->*fnMove->fnCmpOp)( *pPam->GetPoint() ) )
+ pPam->Exchange();
+ }
+ return pPam;
+}
+
+SwPaM & SwPaM::Normalize(BOOL bPointFirst)
+{
+ if (HasMark())
+ if ( ( bPointFirst && *m_pPoint > *m_pMark) ||
+ (!bPointFirst && *m_pPoint < *m_pMark) )
+ {
+ Exchange();
+ }
+
+ return *this;
+}
+
+USHORT SwPaM::GetPageNum( BOOL bAtPoint, const Point* pLayPos )
+{
+ // return die Seitennummer am Cursor
+ // (fuer Reader + Seitengebundene Rahmen)
+ const SwCntntFrm* pCFrm;
+ const SwPageFrm *pPg;
+ const SwCntntNode *pNd ;
+ const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark;
+
+ if( 0 != ( pNd = pPos->nNode.GetNode().GetCntntNode() ) &&
+ 0 != ( pCFrm = pNd->GetFrm( pLayPos, pPos, FALSE )) &&
+ 0 != ( pPg = pCFrm->FindPageFrm() ))
+ return pPg->GetPhyPageNum();
+ return 0;
+}
+
+// --> FME 2004-06-29 #114856# Formular view
+// See also SwCrsrShell::IsCrsrReadonly()
+const SwFrm* lcl_FindEditInReadonlyFrm( const SwFrm& rFrm )
+{
+ const SwFrm* pRet = 0;
+
+ const SwFlyFrm* pFly;
+ const SwSectionFrm* pSectionFrm;
+
+ if( rFrm.IsInFly() &&
+ (pFly = rFrm.FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
+ pFly->Lower() &&
+ !pFly->Lower()->IsNoTxtFrm() )
+ {
+ pRet = pFly;
+ }
+ else if ( rFrm.IsInSct() &&
+ 0 != ( pSectionFrm = rFrm.FindSctFrm() )->GetSection() &&
+ pSectionFrm->GetSection()->IsEditInReadonlyFlag() )
+ {
+ pRet = pSectionFrm;
+ }
+
+ return pRet;
+}
+// <--
+
+// steht in etwas geschuetztem oder in die Selektion umspannt
+// etwas geschuetztes.
+BOOL SwPaM::HasReadonlySel( bool bFormView ) const
+{
+ BOOL bRet = FALSE;
+ Point aTmpPt;
+ const SwCntntNode *pNd;
+ const SwCntntFrm *pFrm;
+
+ if( 0 != ( pNd = GetPoint()->nNode.GetNode().GetCntntNode() ))
+ pFrm = pNd->GetFrm( &aTmpPt, GetPoint(), FALSE );
+ else
+ pFrm = 0;
+
+ // --> FME 2004-06-29 #114856# Formular view
+ // Will be set if point/mark are inside edit-in-readonly environment
+ const SwFrm* pSttEIRFrm = 0;
+ const SwFrm* pEndEIRFrm = 0;
+
+ if( pFrm && ( pFrm->IsProtected() ||
+ // --> FME 2004-06-29 #114856# Formular view
+ ( bFormView &&
+ 0 == ( pSttEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
+ // <--
+ bRet = TRUE;
+ else if( pNd )
+ {
+ const SwSectionNode* pSNd = pNd->GetSectionNode();
+ if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
+ // --> FME 2004-06-29 #114856# Formular view
+ (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
+ // <--
+ bRet = TRUE;
+ }
+
+ if( !bRet && HasMark() && GetPoint()->nNode != GetMark()->nNode )
+ {
+ if( 0 != ( pNd = GetMark()->nNode.GetNode().GetCntntNode() ))
+ pFrm = pNd->GetFrm( &aTmpPt, GetMark(), FALSE );
+ else
+ pFrm = 0;
+
+ if( pFrm && ( pFrm->IsProtected() ||
+ // --> FME 2004-06-29 #114856# Formular view
+ ( bFormView &&
+ 0 == ( pEndEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
+ // <--
+ bRet = TRUE;
+ else if( pNd )
+ {
+ const SwSectionNode* pSNd = pNd->GetSectionNode();
+ if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
+ // --> FME 2004-06-29 #114856# Formular view
+ (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
+ // <--
+ bRet = TRUE;
+ }
+
+ // --> FME 2004-06-29 #114856# Formular view
+ if ( !bRet && bFormView )
+ {
+ // Check if start and end frame are inside the _same_
+ // edit-in-readonly-environment. Otherwise we better return 'true'
+ if ( pSttEIRFrm != pEndEIRFrm )
+ bRet = TRUE;
+ }
+ // <--
+
+ // oder sollte eine geschuetzte Section innerhalb der
+ // Selektion liegen?
+ if( !bRet )
+ {
+ ULONG nSttIdx = GetMark()->nNode.GetIndex(),
+ nEndIdx = GetPoint()->nNode.GetIndex();
+ if( nEndIdx <= nSttIdx )
+ {
+ ULONG nTmp = nSttIdx;
+ nSttIdx = nEndIdx;
+ nEndIdx = nTmp;
+ }
+
+ // wenn ein geschuetzter Bereich zwischen den Nodes stehen soll,
+ // muss die Selektion selbst schon x Nodes umfassen.
+ // (TxtNd, SectNd, TxtNd, EndNd, TxtNd )
+ if( nSttIdx + 3 < nEndIdx )
+ {
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( USHORT n = rFmts.Count(); n; )
+ {
+ const SwSectionFmt* pFmt = rFmts[ --n ];
+ if( pFmt->GetProtect().IsCntntProtected() )
+ {
+ const SwFmtCntnt& rCntnt = pFmt->GetCntnt(FALSE);
+ ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
+ ULONG nIdx = rCntnt.GetCntntIdx()->GetIndex();
+ if( nSttIdx <= nIdx && nEndIdx >= nIdx &&
+ rCntnt.GetCntntIdx()->GetNode().GetNodes().IsDocNodes() )
+ {
+/* // ist es keine gelinkte Section, dann kann sie auch
+ // nicht mitselektiert werden
+ const SwSection& rSect = *pFmt->GetSection();
+ if( CONTENT_SECTION == rSect.GetType() )
+ {
+ RestoreSavePos();
+ return TRUE;
+ }
+*/
+ bRet = TRUE;
+ break;
+ }
+ }
+ }
+
+#ifdef CHECK_CELL_READONLY
+//JP 22.01.99: bisher wurden Tabelle, die in der Text-Selektion standen
+// nicht beachtet. Wollte man das haben, dann muss dieser
+// Code freigeschaltet werden
+
+ if( !bRet )
+ {
+ // dann noch ueber alle Tabellen
+ const SwFrmFmts& rFmts = *GetDoc()->GetTblFrmFmts();
+ for( n = rFmts.Count(); n ; )
+ {
+ SwFrmFmt* pFmt = (SwFrmFmt*)rFmts[ --n ];
+ const SwTable* pTbl = SwTable::FindTable( pFmt );
+ ULONG nIdx = pTbl ? pTbl->GetTabSortBoxes()[0]->GetSttIdx()
+ : 0;
+ if( nSttIdx <= nIdx && nEndIdx >= nIdx )
+ {
+ // dann teste mal alle Boxen
+ const SwTableSortBoxes& rBoxes = pTbl->GetTabSortBoxes();
+
+ for( USHORT i = rBoxes.Count(); i; )
+ if( rBoxes[ --i ]->GetFrmFmt()->GetProtect().
+ IsCntntProtected() )
+ {
+ bRet = TRUE;
+ break;
+ }
+
+ if( bRet )
+ break;
+ }
+ }
+ }
+#endif
+ }
+ }
+ }
+ //FIXME FieldBk
+ // TODO: Form Protection when Enhanced Fields are enabled
+ if (!bRet) {
+ const SwDoc *pDoc = GetDoc();
+ sw::mark::IMark* pA = NULL;
+ sw::mark::IMark* pB = NULL;
+ if ( pDoc )
+ {
+ const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( );
+ pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
+ pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA;
+ bRet = ( pA != pB );
+ }
+ bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
+ if ( bProtectForm )
+ bRet |= ( pA == NULL || pB == NULL );
+ }
+ return bRet;
+}
+
+//-------------------- Suche nach Formaten( FormatNamen ) -----------------
+
+// die Funktion gibt in Suchrichtung den folgenden Node zurueck.
+// Ist in der Richtung keiner mehr vorhanden oder ist dieser ausserhalb
+// des Bereiches, wird ein 0 Pointer returnt.
+// Das rbFirst gibt an, ob es man zu erstenmal einen Node holt. Ist das der
+// Fall, darf die Position vom Pam nicht veraendert werden!
+
+
+SwCntntNode* GetNode( SwPaM & rPam, BOOL& rbFirst, SwMoveFn fnMove,
+ BOOL bInReadOnly )
+{
+ SwCntntNode * pNd = 0;
+ SwCntntFrm* pFrm;
+ if( ((*rPam.GetPoint()).*fnMove->fnCmpOp)( *rPam.GetMark() ) ||
+ ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
+ {
+ if( rbFirst )
+ {
+ rbFirst = FALSE;
+ pNd = rPam.GetCntntNode();
+ if( pNd )
+ {
+ if(
+ (
+ 0 == ( pFrm = pNd->GetFrm()) ||
+ ( !bInReadOnly && pFrm->IsProtected() ) ||
+ (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow())
+ ) ||
+ ( !bInReadOnly && pNd->FindSectionNode() &&
+ pNd->FindSectionNode()->GetSection().IsProtect()
+ )
+ )
+ {
+ pNd = 0;
+ }
+ }
+ }
+
+ if( !pNd ) // steht Cursor auf keinem ContentNode ?
+ {
+ SwPosition aPos( *rPam.GetPoint() );
+ BOOL bSrchForward = fnMove == fnMoveForward;
+ SwNodes& rNodes = aPos.nNode.GetNodes();
+
+ // zum naechsten / vorherigen ContentNode
+// Funktioniert noch alles, wenn die Uerbpruefung vom ueberspringen der
+// Sektions herausgenommen wird ??
+// if( (*fnMove->fnNds)( rNodes, &aPos.nNode ) )
+ while( TRUE )
+ {
+ pNd = bSrchForward
+ ? rNodes.GoNextSection( &aPos.nNode, TRUE, !bInReadOnly )
+ : rNodes.GoPrevSection( &aPos.nNode, TRUE, !bInReadOnly );
+ if( pNd )
+ {
+ aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd ));
+ // liegt Position immer noch im Bereich ?
+ if( (aPos.*fnMove->fnCmpOp)( *rPam.GetMark() ) )
+ {
+ // nur in der AutoTextSection koennen Node stehen, die
+ // nicht angezeigt werden !!
+ if( 0 == ( pFrm = pNd->GetFrm()) ||
+ ( !bInReadOnly && pFrm->IsProtected() ) ||
+ ( pFrm->IsTxtFrm() &&
+ ((SwTxtFrm*)pFrm)->IsHiddenNow() ) )
+
+// rNodes[ rNodes.EndOfAutotext ]->StartOfSection().GetIndex()
+// < aPos.nNode.GetIndex() && aPos.nNode.GetIndex()
+// < rNodes.EndOfAutotext.GetIndex() &&
+// 0 == ( pFrm = pNd->GetFrm()) &&
+// pFrm->IsProtected() )
+ {
+ pNd = 0;
+ continue; // suche weiter
+ }
+ *(SwPosition*)rPam.GetPoint() = aPos;
+ }
+ else
+ pNd = 0; // kein gueltiger Node
+ break;
+ }
+ break;
+ }
+ }
+ }
+ return pNd;
+}
+
+// ----------------------------------------------------------------------
+
+// hier folgen die Move-Methoden ( Foward, Backward; Content, Node, Doc )
+
+
+void GoStartDoc( SwPosition * pPos )
+{
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
+ // es muss immer ein ContentNode gefunden werden !!
+ SwCntntNode* pCNd = rNodes.GoNext( &pPos->nNode );
+ if( pCNd )
+ pCNd->MakeStartIndex( &pPos->nContent );
+}
+
+
+void GoEndDoc( SwPosition * pPos )
+{
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ pPos->nNode = rNodes.GetEndOfContent();
+ SwCntntNode* pCNd = GoPreviousNds( &pPos->nNode, TRUE );
+ if( pCNd )
+ pCNd->MakeEndIndex( &pPos->nContent );
+}
+
+
+void GoStartSection( SwPosition * pPos )
+{
+ // springe zum Anfang der Section
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ USHORT nLevel = rNodes.GetSectionLevel( pPos->nNode );
+ if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
+ nLevel--;
+ do { rNodes.GoStartOfSection( &pPos->nNode ); } while( nLevel-- );
+
+ // steht jetzt schon auf einem CntntNode
+ pPos->nNode.GetNode().GetCntntNode()->MakeStartIndex( &pPos->nContent );
+}
+
+// gehe an das Ende der akt. Grund-Section
+
+
+void GoEndSection( SwPosition * pPos )
+{
+ // springe zum Anfang/Ende der Section
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ USHORT nLevel = rNodes.GetSectionLevel( pPos->nNode );
+ if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
+ nLevel--;
+ do { rNodes.GoEndOfSection( &pPos->nNode ); } while( nLevel-- );
+
+ // steht jetzt auf einem EndNode, also zum vorherigen CntntNode
+ if( GoPreviousNds( &pPos->nNode, TRUE ) )
+ pPos->nNode.GetNode().GetCntntNode()->MakeEndIndex( &pPos->nContent );
+}
+
+
+
+BOOL GoInDoc( SwPaM & rPam, SwMoveFn fnMove )
+{
+ (*fnMove->fnDoc)( rPam.GetPoint() );
+ return TRUE;
+}
+
+
+BOOL GoInSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ (*fnMove->fnSections)( (SwPosition*)rPam.GetPoint() );
+ return TRUE;
+}
+
+
+BOOL GoInNode( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwCntntNode *pNd = (*fnMove->fnNds)( &rPam.GetPoint()->nNode, TRUE );
+ if( pNd )
+ rPam.GetPoint()->nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
+ return 0 != pNd;
+}
+
+
+BOOL GoInCntnt( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS ))
+ return TRUE;
+ return GoInNode( rPam, fnMove );
+}
+
+BOOL GoInCntntCells( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS ))
+ return TRUE;
+ return GoInNode( rPam, fnMove );
+}
+
+BOOL GoInCntntSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) )
+ return TRUE;
+ return GoInNode( rPam, fnMove );
+}
+
+BOOL GoInCntntCellsSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) )
+ return TRUE;
+ return GoInNode( rPam, fnMove );
+}
+
+
+
+// --------- Funktionsdefinitionen fuer die SwCrsrShell --------------
+
+
+BOOL GoPrevPara( SwPaM & rPam, SwPosPara aPosPara )
+{
+ if( rPam.Move( fnMoveBackward, fnGoNode ) )
+ {
+ // steht immer auf einem ContentNode !
+ SwPosition& rPos = *rPam.GetPoint();
+ SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL GoCurrPara( SwPaM & rPam, SwPosPara aPosPara )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
+ if( pNd )
+ {
+ xub_StrLen nOld = rPos.nContent.GetIndex(),
+ nNew = aPosPara == fnMoveForward ? 0 : pNd->Len();
+ // stand er schon auf dem Anfang/Ende dann zum naechsten/vorherigen
+ if( nOld != nNew )
+ {
+ rPos.nContent.Assign( pNd, nNew );
+ return TRUE;
+ }
+ }
+ // den Node noch etwas bewegen ( auf den naechsten/vorh. CntntNode)
+ if( ( aPosPara==fnParaStart && 0 != ( pNd =
+ GoPreviousNds( &rPos.nNode, TRUE ))) ||
+ ( aPosPara==fnParaEnd && 0 != ( pNd =
+ GoNextNds( &rPos.nNode, TRUE ))) )
+ {
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL GoNextPara( SwPaM & rPam, SwPosPara aPosPara )
+{
+ if( rPam.Move( fnMoveForward, fnGoNode ) )
+ {
+ // steht immer auf einem ContentNode !
+ SwPosition& rPos = *rPam.GetPoint();
+ SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+BOOL GoCurrSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwPosition aSavePos( rPos ); // eine Vergleichsposition
+ SwNodes& rNds = aSavePos.nNode.GetNodes();
+ (rNds.*fnMove->fnSection)( &rPos.nNode );
+ SwCntntNode *pNd;
+ if( 0 == ( pNd = rPos.nNode.GetNode().GetCntntNode()) &&
+ 0 == ( pNd = (*fnMove->fnNds)( &rPos.nNode, TRUE )) )
+ {
+ rPos = aSavePos; // Cusror nicht veraendern
+ return FALSE;
+ }
+
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
+ return aSavePos != rPos;
+}
+
+
+BOOL GoNextSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwPosition aSavePos( rPos ); // eine Vergleichsposition
+ SwNodes& rNds = aSavePos.nNode.GetNodes();
+ rNds.GoEndOfSection( &rPos.nNode );
+
+ // kein weiterer ContentNode vorhanden ?
+ if( !GoInCntnt( rPam, fnMoveForward ) )
+ {
+ rPos = aSavePos; // Cusror nicht veraendern
+ return FALSE;
+ }
+ (rNds.*fnMove->fnSection)( &rPos.nNode );
+ SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
+ return TRUE;
+}
+
+
+BOOL GoPrevSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwPosition aSavePos( rPos ); // eine Vergleichsposition
+ SwNodes& rNds = aSavePos.nNode.GetNodes();
+ rNds.GoStartOfSection( &rPos.nNode );
+
+ // kein weiterer ContentNode vorhanden ?
+ if( !GoInCntnt( rPam, fnMoveBackward ))
+ {
+ rPos = aSavePos; // Cusror nicht veraendern
+ return FALSE;
+ }
+ (rNds.*fnMove->fnSection)( &rPos.nNode );
+ SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ));
+ return TRUE;
+}
+
+// #111827#
+String SwPaM::GetTxt() const
+{
+ String aResult;
+
+ SwNodeIndex aNodeIndex = Start()->nNode;
+
+ /* The first node can be the end node. A first end node must be
+ handled, too. There fore do ... while and no incrementing of
+ aNodeIndex in the first pass.
+ */
+ bool bFirst = true;
+ do
+ {
+ if (! bFirst)
+ {
+ aNodeIndex++;
+ }
+
+ bFirst = false;
+
+ SwTxtNode * pTxtNode = aNodeIndex.GetNode().GetTxtNode();
+
+ if (pTxtNode != NULL)
+ {
+ const String & aTmpStr = pTxtNode->GetTxt();
+
+ if (aNodeIndex == Start()->nNode)
+ {
+ xub_StrLen nEnd;
+ if (End()->nNode == aNodeIndex)
+ nEnd = End()->nContent.GetIndex();
+ else
+ nEnd = aTmpStr.Len();
+
+ aResult += aTmpStr.Copy(Start()->nContent.GetIndex(),
+ nEnd - Start()->nContent.GetIndex()) ;
+ }
+ else if (aNodeIndex == End()->nNode)
+ aResult += aTmpStr.Copy(0, End()->nContent.GetIndex());
+ else
+ aResult += aTmpStr;
+ }
+ }
+ while (aNodeIndex != End()->nNode);
+
+ return aResult;
+}
+
+BOOL SwPaM::Overlap(const SwPaM & a, const SwPaM & b)
+{
+ return !(*b.End() <= *a.Start() || *a.End() <= *b.End());
+}
+
+void SwPaM::InvalidatePaM()
+{
+ const SwNode *_pNd=this->GetNode();
+ const SwTxtNode *_pTxtNd=(_pNd!=NULL?_pNd->GetTxtNode():NULL);
+ if (_pTxtNd!=NULL)
+ {
+ // pretent that the PaM marks inserted text to recalc the portion...
+ SwInsTxt aHint( Start()->nContent.GetIndex(),
+ End()->nContent.GetIndex() - Start()->nContent.GetIndex() + 1 );
+ SwModify *_pModify=(SwModify*)_pTxtNd;
+ _pModify->Modify( 0, &aHint);
+ }
+}
+
+BOOL SwPaM::LessThan(const SwPaM & a, const SwPaM & b)
+{
+ return (*a.Start() < *b.Start()) || (*a.Start() == *b.Start() && *a.End() < *b.End());
+}
diff --git a/sw/source/core/crsr/paminit.cxx b/sw/source/core/crsr/paminit.cxx
new file mode 100644
index 000000000000..56f497215f91
--- /dev/null
+++ b/sw/source/core/crsr/paminit.cxx
@@ -0,0 +1,131 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <pamtyp.hxx>
+
+
+static SwMoveFnCollection aFwrd = {
+ /* fnNd */ &GoNext,
+ /* fnNds */ &GoNextNds,
+ /* fnDoc */ &GoEndDoc,
+ /* fnSections */ &GoEndSection,
+ /* fnCmpOp */ &SwPosition::operator<,
+ /* fnGetHint */ &GetFrwrdTxtHint,
+ /* fnSearch */ &utl::TextSearch::SearchFrwrd,
+ /* fnSection */ &SwNodes::GoStartOfSection
+};
+
+static SwMoveFnCollection aBwrd = {
+ /* fnNd */ &GoPrevious,
+ /* fnNds */ &GoPreviousNds,
+ /* fnDoc */ &GoStartDoc,
+ /* fnSections */ &GoStartSection,
+ /* fnCmpOp */ &SwPosition::operator>,
+ /* fnGetHint */ &GetBkwrdTxtHint,
+ /* fnSearch */ &utl::TextSearch::SearchBkwrd,
+ /* fnSection */ &SwNodes::GoEndOfSection
+};
+
+SwGoInDoc fnGoDoc = &GoInDoc;
+SwGoInDoc fnGoSection = &GoInSection;
+SwGoInDoc fnGoNode = &GoInNode;
+SwGoInDoc fnGoCntnt = &GoInCntnt;
+SwGoInDoc fnGoCntntCells = &GoInCntntCells;
+SwGoInDoc fnGoCntntSkipHidden = &GoInCntntSkipHidden;
+SwGoInDoc fnGoCntntCellsSkipHidden = &GoInCntntCellsSkipHidden;
+
+SwWhichPara fnParaPrev = &GoPrevPara;
+SwWhichPara fnParaCurr = &GoCurrPara;
+SwWhichPara fnParaNext = &GoNextPara;
+SwPosPara fnParaStart = &aFwrd;
+SwPosPara fnParaEnd = &aBwrd;
+
+SwWhichSection fnSectionPrev = &GoPrevSection;
+SwWhichSection fnSectionCurr = &GoCurrSection;
+SwWhichSection fnSectionNext = &GoNextSection;
+SwPosSection fnSectionStart = &aFwrd;
+SwPosSection fnSectionEnd = &aBwrd;
+
+// Travelling in Tabellen
+BOOL GotoPrevTable( SwPaM&, SwPosTable, BOOL bInReadOnly );
+BOOL GotoCurrTable( SwPaM&, SwPosTable, BOOL bInReadOnly );
+BOOL GotoNextTable( SwPaM&, SwPosTable, BOOL bInReadOnly );
+
+SwWhichTable fnTablePrev = &GotoPrevTable;
+SwWhichTable fnTableCurr = &GotoCurrTable;
+SwWhichTable fnTableNext = &GotoNextTable;
+SwPosTable fnTableStart = &aFwrd;
+SwPosTable fnTableEnd = &aBwrd;
+
+// Travelling in Bereichen
+BOOL GotoPrevRegion( SwPaM&, SwPosRegion, BOOL bInReadOnly );
+BOOL GotoCurrRegion( SwPaM&, SwPosRegion, BOOL bInReadOnly );
+BOOL GotoCurrRegionAndSkip( SwPaM&, SwPosRegion, BOOL bInReadOnly );
+BOOL GotoNextRegion( SwPaM&, SwPosRegion, BOOL bInReadOnly );
+
+SwWhichRegion fnRegionPrev = &GotoPrevRegion;
+SwWhichRegion fnRegionCurr = &GotoCurrRegion;
+SwWhichRegion fnRegionCurrAndSkip = &GotoCurrRegionAndSkip;
+SwWhichRegion fnRegionNext = &GotoNextRegion;
+SwPosRegion fnRegionStart = &aFwrd;
+SwPosRegion fnRegionEnd = &aBwrd;
+
+SwMoveFn fnMoveBackward = &aBwrd;
+SwMoveFn fnMoveForward = &aFwrd;
+
+SwWhichPara GetfnParaCurr()
+{
+ return fnParaCurr;
+}
+SwPosPara GetfnParaStart()
+{
+ return fnParaStart;
+}
+SwWhichTable GetfnTablePrev()
+{
+ return fnTablePrev;
+}
+SwPosPara GetfnParaEnd()
+{
+ return fnParaEnd;
+}
+SwPosTable GetfnTableStart()
+{
+ return fnTableStart;
+}
+SwWhichTable GetfnTableCurr()
+{
+ return fnTableCurr;
+}
+SwPosTable GetfnTableEnd()
+{
+ return fnTableEnd;
+}
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
new file mode 100644
index 000000000000..7637df0a67b4
--- /dev/null
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -0,0 +1,2360 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/protitem.hxx>
+
+#include <com/sun/star/i18n/WordType.hdl>
+#include <com/sun/star/i18n/CharType.hdl>
+
+#include <unotools/charclass.hxx>
+#include <svl/ctloptions.hxx>
+#include <swmodule.hxx>
+#include <fmtcntnt.hxx>
+#include <swtblfmt.hxx>
+#include <swcrsr.hxx>
+#include <unocrsr.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <section.hxx>
+#include <swtable.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <scriptinfo.hxx>
+#include <crstate.hxx>
+#include <docsh.hxx>
+#include <frmatr.hxx>
+#include <breakit.hxx>
+#include <crsskip.hxx>
+#include <vcl/msgbox.hxx>
+#include <mdiexp.hxx> // ...Percent()
+#ifndef _STATSTR_HRC
+#include <statstr.hrc> // ResId fuer Statusleiste
+#endif
+#include <redline.hxx> // SwRedline
+
+
+using namespace ::com::sun::star::i18n;
+
+
+static const USHORT coSrchRplcThreshold = 60000;
+
+struct _PercentHdl
+{
+ SwDocShell* pDSh;
+ ULONG nActPos;
+ BOOL bBack, bNodeIdx;
+
+ _PercentHdl( ULONG nStt, ULONG nEnd, SwDocShell* pSh )
+ : pDSh( pSh )
+ {
+ nActPos = nStt;
+ if( 0 != ( bBack = (nStt > nEnd )) )
+ {
+ ULONG n = nStt; nStt = nEnd; nEnd = n;
+ }
+ ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, 0 );
+ }
+
+ _PercentHdl( const SwPaM& rPam )
+ : pDSh( (SwDocShell*)rPam.GetDoc()->GetDocShell() )
+ {
+ ULONG nStt, nEnd;
+ if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
+ {
+ bNodeIdx = FALSE;
+ nStt = rPam.GetMark()->nContent.GetIndex();
+ nEnd = rPam.GetPoint()->nContent.GetIndex();
+ }
+ else
+ {
+ bNodeIdx = TRUE;
+ nStt = rPam.GetMark()->nNode.GetIndex();
+ nEnd = rPam.GetPoint()->nNode.GetIndex();
+ }
+ nActPos = nStt;
+ if( 0 != ( bBack = (nStt > nEnd )) )
+ {
+ ULONG n = nStt; nStt = nEnd; nEnd = n;
+ }
+ ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh );
+ }
+
+ ~_PercentHdl() { ::EndProgress( pDSh ); }
+
+ void NextPos( ULONG nPos ) const
+ { ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); }
+
+ void NextPos( SwPosition& rPos ) const
+ {
+ ULONG nPos;
+ if( bNodeIdx )
+ nPos = rPos.nNode.GetIndex();
+ else
+ nPos = rPos.nContent.GetIndex();
+ ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh );
+ }
+};
+
+SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing, bool bColumnSel )
+ : SwPaM( rPos, pRing ), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ),
+ mbColumnSelection( bColumnSel )
+{
+}
+
+// @@@ semantic: no copy ctor.
+SwCursor::SwCursor( SwCursor& rCpy )
+ : SwPaM( rCpy ), pSavePos( 0 ), mnRowSpanOffset( rCpy.mnRowSpanOffset ),
+ nCursorBidiLevel( rCpy.nCursorBidiLevel ), mbColumnSelection( rCpy.mbColumnSelection )
+{
+}
+
+SwCursor::~SwCursor()
+{
+ while( pSavePos )
+ {
+ _SwCursor_SavePos* pNxt = pSavePos->pNext;
+ delete pSavePos;
+ pSavePos = pNxt;
+ }
+}
+
+SwCursor* SwCursor::Create( SwPaM* pRing ) const
+{
+ return new SwCursor( *GetPoint(), pRing, false );
+}
+
+bool SwCursor::IsReadOnlyAvailable() const
+{
+ return false;
+}
+
+BOOL SwCursor::IsSkipOverHiddenSections() const
+{
+ return TRUE;
+}
+
+BOOL SwCursor::IsSkipOverProtectSections() const
+{
+ return !IsReadOnlyAvailable();
+}
+
+
+// Sicher die aktuelle Position, damit ggfs. auf diese zurueck
+// gefallen werden kann. Die SavePos Objekte werden als Stack verwaltet,
+// damit das auch alles bei verschachtelten Aufrufen funktioniert.
+// Das CreateNewSavePos ist virtual, damit abgeleitete Klassen vom Cursor
+// gegebenenfalls eigene SaveObjecte anlegen und in den virtuellen
+// Check-Routinen verwenden koennen.
+
+void SwCursor::SaveState()
+{
+ _SwCursor_SavePos* pNew = CreateNewSavePos();
+ pNew->pNext = pSavePos;
+ pSavePos = pNew;
+}
+
+void SwCursor::RestoreState()
+{
+ if( pSavePos ) // Robust
+ {
+ _SwCursor_SavePos* pDel = pSavePos;
+ pSavePos = pSavePos->pNext;
+ delete pDel;
+ }
+}
+
+_SwCursor_SavePos* SwCursor::CreateNewSavePos() const
+{
+ return new _SwCursor_SavePos( *this );
+}
+
+// stelle fest, ob sich der Point ausserhalb des Content-Bereichs
+// vom Nodes-Array befindet
+BOOL SwCursor::IsNoCntnt() const
+{
+ return GetPoint()->nNode.GetIndex() <
+ GetDoc()->GetNodes().GetEndOfExtras().GetIndex();
+}
+
+bool SwCursor::IsSelOvrCheck(int)
+{
+ return false;
+}
+
+// extracted from IsSelOvr()
+bool SwTableCursor::IsSelOvrCheck(int eFlags)
+{
+ SwNodes& rNds = GetDoc()->GetNodes();
+ // check sections of nodes array
+ if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION & eFlags)
+ && HasMark() )
+ {
+ SwNodeIndex aOldPos( rNds, GetSavePos()->nNode );
+ if( !CheckNodesRange( aOldPos, GetPoint()->nNode, TRUE ))
+ {
+ GetPoint()->nNode = aOldPos;
+ GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
+ return true;
+ }
+ }
+ return SwCursor::IsSelOvrCheck(eFlags);
+}
+
+BOOL SwCursor::IsSelOvr( int eFlags )
+{
+ SwDoc* pDoc = GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ BOOL bSkipOverHiddenSections = IsSkipOverHiddenSections();
+ BOOL bSkipOverProtectSections = IsSkipOverProtectSections();
+
+ if ( IsSelOvrCheck( eFlags ) )
+ {
+ return TRUE;
+ }
+
+// neu: Bereiche ueberpruefen
+// Anfang
+ if( pSavePos->nNode != GetPoint()->nNode.GetIndex() &&
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ ( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() ))
+ {
+ // teste doch mal die neuen Sections:
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode();
+ if( pSectNd &&
+ ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) ||
+ (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() )))
+ {
+ if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
+ {
+ // dann wars das schon
+ RestoreSavePos();
+ return TRUE;
+ }
+
+ // dann setze den Cursor auf die neue Position:
+ SwNodeIndex aIdx( rPtIdx );
+ xub_StrLen nCntntPos = pSavePos->nCntnt;
+ int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
+ SwCntntNode* pCNd = bGoNxt
+ ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
+ : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
+ if( !pCNd && ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION & eFlags ))
+ {
+ bGoNxt = !bGoNxt;
+ pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
+ : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
+ }
+
+ int bIsValidPos = 0 != pCNd;
+ BOOL bValidNodesRange = bIsValidPos &&
+ ::CheckNodesRange( rPtIdx, aIdx, TRUE );
+ if( !bValidNodesRange )
+ {
+ rPtIdx = pSavePos->nNode;
+ if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
+ {
+ bIsValidPos = FALSE;
+ nCntntPos = 0;
+ rPtIdx = aIdx;
+ if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
+ {
+ // dann auf den Anfang vom Doc
+ rPtIdx = rNds.GetEndOfExtras();
+ pCNd = rNds.GoNext( &rPtIdx );
+ }
+ }
+ }
+
+ // ContentIndex noch anmelden:
+ xub_StrLen nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nCntntPos;
+ GetPoint()->nContent.Assign( pCNd, nTmpPos );
+ if( !bIsValidPos || !bValidNodesRange ||
+ // sollten wir in einer Tabelle gelandet sein?
+ IsInProtectTable( TRUE ) )
+ return TRUE;
+ }
+
+ // oder sollte eine geschuetzte Section innerhalb der Selektion liegen?
+ if( HasMark() && bSkipOverProtectSections)
+ {
+ ULONG nSttIdx = GetMark()->nNode.GetIndex(),
+ nEndIdx = GetPoint()->nNode.GetIndex();
+ if( nEndIdx <= nSttIdx )
+ {
+ ULONG nTmp = nSttIdx;
+ nSttIdx = nEndIdx;
+ nEndIdx = nTmp;
+ }
+
+ const SwSectionFmts& rFmts = pDoc->GetSections();
+ for( USHORT n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwSectionFmt* pFmt = rFmts[n];
+ const SvxProtectItem& rProtect = pFmt->GetProtect();
+ if( rProtect.IsCntntProtected() )
+ {
+ const SwFmtCntnt& rCntnt = pFmt->GetCntnt(FALSE);
+ ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
+ ULONG nIdx = rCntnt.GetCntntIdx()->GetIndex();
+ if( nSttIdx <= nIdx && nEndIdx >= nIdx )
+ {
+ // ist es keine gelinkte Section, dann kann sie auch
+ // nicht mitselektiert werden
+ const SwSection& rSect = *pFmt->GetSection();
+ if( CONTENT_SECTION == rSect.GetType() )
+ {
+ RestoreSavePos();
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ }
+// Ende
+// neu: Bereiche ueberpruefen
+
+ const SwNode* pNd = &GetPoint()->nNode.GetNode();
+ if( pNd->IsCntntNode() && !dynamic_cast<SwUnoCrsr*>(this) )
+ {
+ const SwCntntFrm* pFrm = ((SwCntntNode*)pNd)->GetFrm();
+ if( pFrm && pFrm->IsValid() && 0 == pFrm->Frm().Height() &&
+ 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
+ {
+ // skip to the next / prev valid paragraph with a layout
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
+ while( 0 != ( pFrm = ( bGoNxt ? pFrm->GetNextCntntFrm()
+ : pFrm->GetPrevCntntFrm() )) &&
+ 0 == pFrm->Frm().Height() )
+ ;
+
+ // --> LIJIAN/FME 2007-11-27 #i72394# skip to prev /next valid paragraph
+ // with a layout in case the first search did not succeed:
+ if( !pFrm )
+ {
+ bGoNxt = !bGoNxt;
+ pFrm = ((SwCntntNode*)pNd)->GetFrm();
+ while ( pFrm && 0 == pFrm->Frm().Height() )
+ {
+ pFrm = bGoNxt ? pFrm->GetNextCntntFrm()
+ : pFrm->GetPrevCntntFrm();
+ }
+ }
+ // <--
+
+ SwCntntNode* pCNd;
+ if( pFrm && 0 != (pCNd = (SwCntntNode*)pFrm->GetNode()) )
+ {
+ // set this cntntNode as new position
+ rPtIdx = *pCNd;
+ pNd = pCNd;
+
+ // ContentIndex noch anmelden:
+ xub_StrLen nTmpPos = bGoNxt ? 0 : pCNd->Len();
+ GetPoint()->nContent.Assign( pCNd, nTmpPos );
+
+ // sollten wir in einer Tabelle gelandet sein?
+ if( IsInProtectTable( TRUE ) )
+ pFrm = 0;
+ }
+ }
+
+ if( !pFrm )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return TRUE; // ohne Frames geht gar nichts!
+ }
+ }
+
+ // darf der Cursor in geschuetzen "Nodes" stehen?
+ if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) && !IsAtValidPos() )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return TRUE;
+ }
+
+ if( !HasMark() )
+ return FALSE;
+
+ //JP 19.08.98: teste mal auf ungueltige Selektion - sprich ueber
+ // GrundSections:
+ if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, TRUE ))
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return TRUE; // ohne Frames geht gar nichts!
+ }
+
+ const SwTableNode* pPtNd = pNd->FindTableNode();
+
+ if( (pNd = &GetMark()->nNode.GetNode())->IsCntntNode() &&
+ !((SwCntntNode*)pNd)->GetFrm() && !dynamic_cast<SwUnoCrsr*>(this) )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return TRUE; // ohne Frames geht gar nichts!
+ }
+
+ const SwTableNode* pMrkNd = pNd->FindTableNode();
+
+ // beide in keinem oder beide im gleichen TableNode
+ if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd )
+ return FALSE;
+
+ // in unterschiedlichen Tabellen oder nur Mark in der Tabelle
+ if( ( pPtNd && pMrkNd ) || pMrkNd )
+ { // dann lasse das nicht zu, alte Pos zurueck
+ RestoreSavePos();
+ // Crsr bleibt an der alten Position
+ return TRUE;
+ }
+
+ // ACHTUNG: dieses kann nicht im TableMode geschehen !!
+ if( pPtNd ) // nur Point in Tabelle, dann gehe hinter/vor diese
+ {
+ if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags )
+ {
+ BOOL bSelTop = GetPoint()->nNode.GetIndex() <
+ (( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags ) ? pSavePos->nNode
+ : GetMark()->nNode.GetIndex());
+
+ do {
+ // in Schleife fuer Tabelle hinter Tabelle
+ ULONG nSEIdx = pPtNd->EndOfSectionIndex();
+ ULONG nSttEndTbl = nSEIdx + 1; // dflt. Sel. nach unten
+
+ if( bSelTop ) // Sel. nach oben
+ nSttEndTbl = rNds[ nSEIdx ]->StartOfSectionIndex() - 1;
+
+ GetPoint()->nNode = nSttEndTbl;
+ const SwNode* pMyNd = GetNode();
+
+ if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() &&
+ pMyNd->StartOfSectionNode()->IsSectionNode() ) )
+ {
+ // die lassen wir zu:
+ pMyNd = bSelTop
+ ? rNds.GoPrevSection( &GetPoint()->nNode,TRUE,FALSE )
+ : rNds.GoNextSection( &GetPoint()->nNode,TRUE,FALSE );
+
+ /* #i12312# Handle failure of Go{Prev|Next}Section */
+ if ( 0 == pMyNd)
+ break;
+
+ if( 0 != ( pPtNd = pMyNd->FindTableNode() ))
+ continue;
+ }
+
+ if( pMyNd->IsCntntNode() && // ist es ein ContentNode ??
+ ::CheckNodesRange( GetMark()->nNode,
+ GetPoint()->nNode, TRUE ))
+ {
+ // TABLE IN TABLE
+ const SwTableNode* pOuterTableNd = pMyNd->FindTableNode();
+ if ( pOuterTableNd )
+ pMyNd = pOuterTableNd;
+ else
+ {
+ SwCntntNode* pCNd = (SwCntntNode*)pMyNd;
+ xub_StrLen nTmpPos = bSelTop ? pCNd->Len() : 0;
+ GetPoint()->nContent.Assign( pCNd, nTmpPos );
+ return FALSE;
+ }
+ }
+ if( bSelTop
+ ? ( !pMyNd->IsEndNode() || 0 == ( pPtNd = pMyNd->FindTableNode() ))
+ : 0 == ( pPtNd = pMyNd->GetTableNode() ))
+ break;
+ } while( TRUE );
+ }
+
+ // dann verbleibe auf der alten Position
+ RestoreSavePos();
+ return TRUE; // Crsr bleibt an der alten Position
+ }
+ return FALSE; // was bleibt noch ??
+}
+
+#if defined( UNX )
+#define IDX (*pCellStt)
+#else
+#define IDX aCellStt
+#endif
+
+
+BOOL SwCursor::IsInProtectTable( BOOL bMove, BOOL bChgCrsr )
+{
+ SwCntntNode* pCNd = GetCntntNode();
+ if( !pCNd )
+ return FALSE;
+
+ // No table, no protected cell:
+ const SwTableNode* pTableNode = pCNd->FindTableNode();
+ if ( !pTableNode )
+ return FALSE;
+
+ // Current position == last save position?
+ if ( pSavePos->nNode == GetPoint()->nNode.GetIndex() )
+ return FALSE;
+
+ // Check for convered cell:
+ bool bInCoveredCell = false;
+ const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
+ ASSERT( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" )
+ const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTblBox( pTmpSttNode->GetIndex() ) : 0; //Robust #151355
+ if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
+ bInCoveredCell = true;
+
+ // Positions of covered cells are not acceptable:
+ if ( !bInCoveredCell )
+ {
+ // Position not protected?
+ if ( !pCNd->IsProtect() )
+ return FALSE;
+
+ // Cursor in protected cells allowed?
+ if ( IsReadOnlyAvailable() )
+ return FALSE;
+ }
+
+ // If we reach this point, we are in a protected or covered table cell!
+
+ if( !bMove )
+ {
+ if( bChgCrsr )
+ // restore the last save position
+ RestoreSavePos();
+ return TRUE; // Crsr bleibt an der alten Position
+ }
+
+ // wir stehen in einer geschuetzten TabellenZelle
+ // von Oben nach Unten Traveln ?
+ if( pSavePos->nNode < GetPoint()->nNode.GetIndex() )
+ {
+ // suche die naechste "gueltige" Box
+
+ // folgt nach dem EndNode der Zelle ein weiterer StartNode, dann
+ // gibt es auch eine naechste Zelle
+#if defined( UNX )
+ SwNodeIndex* pCellStt = new SwNodeIndex( *GetNode()->
+ FindTableBoxStartNode()->EndOfSectionNode(), 1 );
+#else
+ SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
+#endif
+ BOOL bProt = TRUE;
+GoNextCell:
+ do {
+ if( !IDX.GetNode().IsStartNode() )
+ break;
+ IDX++;
+ if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
+ pCNd = IDX.GetNodes().GoNext( &IDX );
+ if( 0 == ( bProt = pCNd->IsProtect() ))
+ break;
+ IDX.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
+ } while( bProt );
+
+SetNextCrsr:
+ if( !bProt ) // eine freie Zelle gefunden
+ {
+ GetPoint()->nNode = IDX;
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ SwCntntNode* pTmpCNd = GetCntntNode();
+ if( pTmpCNd )
+ {
+ GetPoint()->nContent.Assign( pTmpCNd, 0 );
+ return FALSE;
+ }
+ return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ }
+ // am Ende der Tabelle, also setze hinter diese
+ IDX++; // auf den naechsten Node
+ SwNode* pNd;
+ if( ( pNd = &IDX.GetNode())->IsEndNode() || HasMark())
+ {
+ // Tabelle allein in einem FlyFrame oder SSelection,
+ // dann verbleibe auf der alten Position
+ if( bChgCrsr )
+ RestoreSavePos();
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ return TRUE; // Crsr bleibt an der alten Position
+ }
+ else if( pNd->IsTableNode() && IDX++ )
+ goto GoNextCell;
+
+ bProt = FALSE; // Index steht jetzt auf einem ContentNode
+ goto SetNextCrsr;
+ }
+
+ // suche die vorherige "gueltige" Box
+ {
+ // liegt vor dem StartNode der Zelle ein weiterer EndNode, dann
+ // gibt es auch eine vorherige Zelle
+#if defined( UNX )
+ SwNodeIndex* pCellStt = new SwNodeIndex(
+ *GetNode()->FindTableBoxStartNode(), -1 );
+#else
+ SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode(), -1 );
+#endif
+ SwNode* pNd;
+ BOOL bProt = TRUE;
+GoPrevCell:
+ do {
+ if( !( pNd = &IDX.GetNode())->IsEndNode() )
+ break;
+ IDX.Assign( *pNd->StartOfSectionNode(), +1 );
+ if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
+ pCNd = pNd->GetNodes().GoNext( &IDX );
+ if( 0 == ( bProt = pCNd->IsProtect() ))
+ break;
+ IDX.Assign( *pNd->FindTableBoxStartNode(), -1 );
+ } while( bProt );
+
+SetPrevCrsr:
+ if( !bProt ) // eine freie Zelle gefunden
+ {
+ GetPoint()->nNode = IDX;
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ SwCntntNode* pTmpCNd = GetCntntNode();
+ if( pTmpCNd )
+ {
+ GetPoint()->nContent.Assign( pTmpCNd, 0 );
+ return FALSE;
+ }
+ return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ }
+ // am Start der Tabelle, also setze vor diese
+ IDX--; // auf den naechsten Node
+ if( ( pNd = &IDX.GetNode())->IsStartNode() || HasMark() )
+ {
+ // Tabelle allein in einem FlyFrame oder Selektion,
+ // dann verbleibe auf der alten Position
+ if( bChgCrsr )
+ RestoreSavePos();
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ return TRUE; // Crsr bleibt an der alten Position
+ }
+ else if( pNd->StartOfSectionNode()->IsTableNode() && IDX-- )
+ goto GoPrevCell;
+
+ bProt = FALSE; // Index steht jetzt auf einem ContentNode
+ goto SetPrevCrsr;
+ }
+}
+
+// TRUE: an die Position kann der Cursor gesetzt werden
+BOOL SwCursor::IsAtValidPos( BOOL bPoint ) const
+{
+ const SwDoc* pDoc = GetDoc();
+ const SwPosition* pPos = bPoint ? GetPoint() : GetMark();
+ const SwNode* pNd = &pPos->nNode.GetNode();
+
+ if( pNd->IsCntntNode() && !((SwCntntNode*)pNd)->GetFrm() &&
+ !dynamic_cast<const SwUnoCrsr*>(this) )
+ {
+ return FALSE;
+ }
+
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ if( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() )
+ return TRUE;
+
+ BOOL bCrsrInReadOnly = IsReadOnlyAvailable();
+ if( !bCrsrInReadOnly && pNd->IsProtect() )
+ return FALSE;
+
+ const SwSectionNode* pSectNd = pNd->FindSectionNode();
+ if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
+ ( !bCrsrInReadOnly && pSectNd->GetSection().IsProtectFlag() )))
+ return FALSE;
+
+ return TRUE;
+}
+
+void SwCursor::SaveTblBoxCntnt( const SwPosition* ) {}
+
+// setze den SRange fuer das Suchen im Dokument
+SwMoveFnCollection* SwCursor::MakeFindRange( SwDocPositions nStart,
+ SwDocPositions nEnd, SwPaM* pRange ) const
+{
+ pRange->SetMark();
+ FillFindPos( nStart, *pRange->GetMark() );
+ FillFindPos( nEnd, *pRange->GetPoint() );
+
+ // bestimme die Richtung, in der zu suchen ist
+ // ( GetPoint > GetMark -> vorwaerts, sonst rueckwaerts )
+ return ( DOCPOS_START == nStart || DOCPOS_OTHERSTART == nStart ||
+ (DOCPOS_CURR == nStart &&
+ (DOCPOS_END == nEnd || DOCPOS_OTHEREND == nEnd ) ))
+ ? fnMoveForward : fnMoveBackward;
+}
+
+
+ULONG lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurCrsr,
+ SwMoveFn fnMove, SwCursor*& pFndRing,
+ SwPaM& aRegion, FindRanges eFndRngs,
+ BOOL bInReadOnly, BOOL& bCancel )
+{
+ SwDoc* pDoc = pCurCrsr->GetDoc();
+ BOOL bDoesUndo = pDoc->DoesUndo();
+ int nFndRet = 0;
+ ULONG nFound = 0;
+ int bSrchBkwrd = fnMove == fnMoveBackward, bEnde = FALSE;
+ SwPaM *pTmpCrsr = pCurCrsr, *pSaveCrsr = pCurCrsr;
+
+ // only create progress-bar for ShellCrsr
+ bool bIsUnoCrsr = 0 != dynamic_cast<SwUnoCrsr*>(pCurCrsr);
+ _PercentHdl* pPHdl = 0;
+ USHORT nCrsrCnt = 0;
+ if( FND_IN_SEL & eFndRngs )
+ {
+ while( pCurCrsr != ( pTmpCrsr = (SwPaM*)pTmpCrsr->GetNext() ))
+ ++nCrsrCnt;
+ if( nCrsrCnt && !bIsUnoCrsr )
+ pPHdl = new _PercentHdl( 0, nCrsrCnt, pDoc->GetDocShell() );
+ }
+ else
+ pSaveCrsr = (SwPaM*)pSaveCrsr->GetPrev();
+
+ do {
+ aRegion.SetMark();
+ // egal in welche Richtung, SPoint ist immer groesser als Mark,
+ // wenn der Suchbereich gueltig ist !!
+ SwPosition *pSttPos = aRegion.GetMark(),
+ *pEndPos = aRegion.GetPoint();
+ *pSttPos = *pTmpCrsr->Start();
+ *pEndPos = *pTmpCrsr->End();
+ if( bSrchBkwrd )
+ aRegion.Exchange();
+
+ if( !nCrsrCnt && !pPHdl && !bIsUnoCrsr )
+ pPHdl = new _PercentHdl( aRegion );
+
+ // solange gefunden und nicht auf gleicher Position haengen bleibt
+ while( *pSttPos <= *pEndPos &&
+ 0 != ( nFndRet = rParas.Find( pCurCrsr, fnMove,
+ &aRegion, bInReadOnly )) &&
+ ( !pFndRing ||
+ *pFndRing->GetPoint() != *pCurCrsr->GetPoint() ||
+ *pFndRing->GetMark() != *pCurCrsr->GetMark() ))
+ {
+ if( !( FIND_NO_RING & nFndRet ))
+ {
+ // Bug 24084: Ring richtig herum aufbauen -> gleiche Mimik
+ // wie beim CreateCrsr !!!!
+
+ SwCursor* pNew = pCurCrsr->Create( pFndRing );
+ if( !pFndRing )
+ pFndRing = pNew;
+
+ pNew->SetMark();
+ *pNew->GetMark() = *pCurCrsr->GetMark();
+ }
+
+ ++nFound;
+
+ if( !( eFndRngs & FND_IN_SELALL) )
+ {
+ bEnde = TRUE;
+ break;
+ }
+
+ if( coSrchRplcThreshold == nFound && pDoc->DoesUndo()
+ && rParas.IsReplaceMode())
+ {
+ short nRet = pCurCrsr->MaxReplaceArived();
+ if( RET_YES == nRet )
+ {
+ pDoc->DelAllUndoObj();
+ pDoc->DoUndo( FALSE );
+ }
+ else
+ {
+ bEnde = TRUE;
+ if(RET_CANCEL == nRet)
+ {
+ bCancel = TRUE;
+ //unwind() ??
+ }
+ break;
+ }
+ }
+
+ if( bSrchBkwrd )
+ // bewege pEndPos vor den gefundenen Bereich
+ *pEndPos = *pCurCrsr->Start();
+ else
+ // bewege pSttPos hinter den gefundenen Bereich
+ *pSttPos = *pCurCrsr->End();
+
+ if( *pSttPos == *pEndPos ) // im Bereich, aber am Ende
+ break; // fertig
+
+ if( !nCrsrCnt && pPHdl )
+ {
+ pPHdl->NextPos( *aRegion.GetMark() );
+ }
+ }
+
+ if( bEnde || !( eFndRngs & ( FND_IN_SELALL | FND_IN_SEL )) )
+ break;
+
+ pTmpCrsr = ((SwPaM*)pTmpCrsr->GetNext());
+ if( nCrsrCnt && pPHdl )
+ {
+ pPHdl->NextPos( ++pPHdl->nActPos );
+ }
+
+ } while( pTmpCrsr != pSaveCrsr );
+
+ if( nFound && !pFndRing ) // falls kein Ring aufgebaut werden soll
+ pFndRing = pCurCrsr->Create();
+
+ delete pPHdl;
+ pDoc->DoUndo( bDoesUndo );
+ return nFound;
+}
+
+
+int lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
+ SwPaM& rPam, int bFirst )
+{
+ if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() )
+ return FALSE;
+
+ SwNodes& rNds = rPam.GetDoc()->GetNodes();
+ rPam.DeleteMark();
+ SwCntntNode* pCNd;
+ if( !bFirst )
+ {
+ rPam.GetPoint()->nNode = rSttNd;
+ pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return FALSE;
+ pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
+ }
+ else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
+ rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() )
+ return FALSE; // steht nicht in dieser Section
+
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = rEndNd;
+ pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return FALSE;
+ pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
+
+ return *rPam.GetMark() < *rPam.GetPoint();
+}
+
+
+int lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
+ SwPaM& rPam, int bFirst )
+{
+ if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() )
+ return FALSE;
+
+ SwNodes& rNds = rPam.GetDoc()->GetNodes();
+ rPam.DeleteMark();
+ SwCntntNode* pCNd;
+ if( !bFirst )
+ {
+ rPam.GetPoint()->nNode = rSttNd;
+ pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return FALSE;
+ pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
+ }
+ else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
+ rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() )
+ return FALSE; // steht nicht in dieser Section
+
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = rEndNd;
+ pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return FALSE;
+ pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
+
+ return *rPam.GetPoint() < *rPam.GetMark();
+}
+
+
+// diese Methode "sucht" fuer alle Anwendungsfaelle, denn in SwFindParas
+// steht immer die richtigen Parameter und die entsprechende Find-Methode
+
+ULONG SwCursor::FindAll( SwFindParas& rParas,
+ SwDocPositions nStart, SwDocPositions nEnde,
+ FindRanges eFndRngs, BOOL& bCancel )
+{
+ bCancel = FALSE;
+ SwCrsrSaveState aSaveState( *this );
+
+ // Region erzeugen, ohne das diese in den Ring aufgenommen wird !
+ SwPaM aRegion( *GetPoint() );
+ SwMoveFn fnMove = MakeFindRange( nStart, nEnde, &aRegion );
+
+ ULONG nFound = 0;
+ int bMvBkwrd = fnMove == fnMoveBackward;
+ BOOL bInReadOnly = IsReadOnlyAvailable();
+
+ SwCursor* pFndRing = 0;
+ SwNodes& rNds = GetDoc()->GetNodes();
+
+ // suche in Bereichen ?
+ if( FND_IN_SEL & eFndRngs )
+ {
+ // String nicht im Bereich gefunden, dann erhalte alle Bereiche,
+ // der Cursor beleibt unveraendert
+ if( 0 == ( nFound = lcl_FindSelection( rParas, this, fnMove,
+ pFndRing, aRegion, eFndRngs,
+ bInReadOnly, bCancel ) ))
+ return nFound;
+
+ // der String wurde ein- bis mehrmals gefunden. Das steht alles
+ // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
+ while( GetNext() != this )
+ delete GetNext();
+
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ pFndRing->MoveRingTo( this );
+ delete pFndRing;
+ }
+ else if( FND_IN_OTHER & eFndRngs )
+ {
+ // Cursor als Kopie vom akt. und in den Ring aufnehmen
+ // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
+ SwCursor* pSav = Create( this ); // sicher den aktuellen Crsr
+
+ // wenn schon ausserhalb vom Bodytext, suche von der Position,
+ // ansonsten beginne mit der 1. GrundSection
+ if( bMvBkwrd
+ ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
+ *rNds.GetEndOfPostIts().StartOfSectionNode(),
+ *this, rNds.GetEndOfExtras().GetIndex() >=
+ GetPoint()->nNode.GetIndex() )
+ : lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(),
+ rNds.GetEndOfExtras(), *this,
+ rNds.GetEndOfExtras().GetIndex() >=
+ GetPoint()->nNode.GetIndex() ))
+ {
+ nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
+ aRegion, eFndRngs, bInReadOnly, bCancel );
+ }
+
+ if( !nFound )
+ {
+ // den alten wieder zurueck
+ *GetPoint() = *pSav->GetPoint();
+ if( pSav->HasMark() )
+ {
+ SetMark();
+ *GetMark() = *pSav->GetMark();
+ }
+ else
+ DeleteMark();
+ return 0;
+ }
+
+ delete pSav;
+ if( !( FND_IN_SELALL & eFndRngs ))
+ {
+ // es sollte nur einer gesucht werden, also fuege in dazu
+ // egal in welche Richtung, SPoint ist immer groesser als Mark,
+ // wenn der Suchbereich gueltig ist !!
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ }
+ else
+ {
+ // es wurde ein- bis mehrmals gefunden. Das steht alles
+ // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
+ while( GetNext() != this )
+ delete GetNext();
+
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ pFndRing->MoveRingTo( this );
+ }
+ delete pFndRing;
+ }
+ else if( FND_IN_SELALL & eFndRngs )
+ {
+ SwCursor* pSav = Create( this ); // sicher den aktuellen Crsr
+
+ const SwNode* pSttNd = ( FND_IN_BODYONLY & eFndRngs )
+ ? rNds.GetEndOfContent().StartOfSectionNode()
+ : rNds.GetEndOfPostIts().StartOfSectionNode();
+
+ if( bMvBkwrd
+ ? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd,*this, FALSE )
+ : lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, FALSE ))
+ {
+ nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
+ aRegion, eFndRngs, bInReadOnly, bCancel );
+ }
+
+ if( !nFound )
+ {
+ // den alten wieder zurueck
+ *GetPoint() = *pSav->GetPoint();
+ if( pSav->HasMark() )
+ {
+ SetMark();
+ *GetMark() = *pSav->GetMark();
+ }
+ else
+ DeleteMark();
+ return 0;
+ }
+ // es wurde ein- bis mehrmals gefunden. Das steht alles
+ // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
+ delete pSav;
+
+ while( GetNext() != this )
+ delete GetNext();
+
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ pFndRing->MoveRingTo( this );
+ delete pFndRing;
+ }
+ else
+ {
+ // ist ein GetMark gesetzt, dann wird bei gefundenem Object
+ // der GetMark beibehalten !! Dadurch kann ein Bereich mit der Suche
+ // aufgespannt werden.
+ SwPosition aMarkPos( *GetMark() );
+ int bMarkPos = HasMark() && !eFndRngs;
+
+ if( 0 != (nFound = rParas.Find( this, fnMove,
+ &aRegion, bInReadOnly ) ? 1 : 0)
+ && bMarkPos )
+ *GetMark() = aMarkPos;
+ }
+
+ if( nFound && SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
+ nFound = 0;
+ return nFound;
+}
+
+
+void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const
+{
+ BOOL bIsStart = TRUE;
+ SwCntntNode* pCNd = 0;
+ SwNodes& rNds = GetDoc()->GetNodes();
+
+ switch( ePos )
+ {
+ case DOCPOS_START:
+ rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
+ pCNd = rNds.GoNext( &rPos.nNode );
+ break;
+
+ case DOCPOS_END:
+ rPos.nNode = rNds.GetEndOfContent();
+ pCNd = rNds.GoPrevious( &rPos.nNode );
+ bIsStart = FALSE;
+ break;
+
+ case DOCPOS_OTHERSTART:
+ rPos.nNode = *rNds[ ULONG(0) ];
+ pCNd = rNds.GoNext( &rPos.nNode );
+ break;
+
+ case DOCPOS_OTHEREND:
+ rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
+ pCNd = rNds.GoPrevious( &rPos.nNode );
+ bIsStart = FALSE;
+ break;
+
+// case DOCPOS_CURR:
+ default:
+ rPos = *GetPoint();
+ }
+
+ if( pCNd )
+ {
+ xub_StrLen nCPos = 0;
+ if( !bIsStart )
+ nCPos = pCNd->Len();
+ rPos.nContent.Assign( pCNd, nCPos );
+ }
+}
+
+short SwCursor::MaxReplaceArived()
+{
+ return RET_YES;
+}
+
+
+BOOL SwCursor::IsStartWord( sal_Int16 nWordType ) const
+{
+ return IsStartWordWT( nWordType );
+}
+
+BOOL SwCursor::IsEndWord( sal_Int16 nWordType ) const
+{
+ return IsEndWordWT( nWordType );
+}
+
+BOOL SwCursor::IsInWord( sal_Int16 nWordType ) const
+{
+ return IsInWordWT( nWordType );
+}
+
+BOOL SwCursor::GoStartWord()
+{
+ return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+BOOL SwCursor::GoEndWord()
+{
+ return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+BOOL SwCursor::GoNextWord()
+{
+ return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+BOOL SwCursor::GoPrevWord()
+{
+ return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+BOOL SwCursor::SelectWord( const Point* pPt )
+{
+ return SelectWordWT( WordType::ANYWORD_IGNOREWHITESPACES, pPt );
+}
+
+BOOL SwCursor::IsStartWordWT( sal_Int16 nWordType ) const
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ bRet = pBreakIt->GetBreakIter()->isBeginWord(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos )),
+ nWordType );
+ }
+ return bRet;
+}
+
+BOOL SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ bRet = pBreakIt->GetBreakIter()->isEndWord(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType );
+
+ }
+ return bRet;
+}
+
+BOOL SwCursor::IsInWordWT( sal_Int16 nWordType ) const
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ Boundary aBoundary = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ TRUE );
+
+ bRet = aBoundary.startPos != aBoundary.endPos &&
+ aBoundary.startPos <= nPtPos &&
+ nPtPos <= aBoundary.endPos;
+ if(bRet)
+ {
+ const CharClass& rCC = GetAppCharClass();
+ bRet = rCC.isLetterNumeric( pTxtNd->GetTxt(), static_cast<xub_StrLen>(aBoundary.startPos) );
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::IsStartEndSentence( bool bEnd ) const
+{
+ BOOL bRet = bEnd ?
+ GetCntntNode() && GetPoint()->nContent == GetCntntNode()->Len() :
+ GetPoint()->nContent.GetIndex() == 0;
+
+ if( !bRet )
+ {
+ SwCursor aCrsr(*GetPoint(), 0, false);
+ SwPosition aOrigPos = *aCrsr.GetPoint();
+ aCrsr.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT );
+ bRet = aOrigPos == *aCrsr.GetPoint();
+ }
+
+ return bRet;
+}
+
+BOOL SwCursor::GoStartWordWT( sal_Int16 nWordType )
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ FALSE ).startPos;
+
+ if( nPtPos < pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::GoEndWordWT( sal_Int16 nWordType )
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ TRUE ).endPos;
+
+ if( nPtPos <= pTxtNd->GetTxt().Len() &&
+ GetPoint()->nContent.GetIndex() != nPtPos )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::GoNextWordWT( sal_Int16 nWordType )
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextWord(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
+ nWordType ).startPos;
+
+ if( nPtPos < pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::GoPrevWordWT( sal_Int16 nWordType )
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ const xub_StrLen nPtStart = nPtPos;
+
+ if( nPtPos )
+ --nPtPos;
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousWord(
+ pTxtNd->GetTxt(), nPtStart,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
+ nWordType ).startPos;
+
+ if( nPtPos < pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::SelectWordWT( sal_Int16 nWordType, const Point* pPt )
+{
+ SwCrsrSaveState aSave( *this );
+
+ BOOL bRet = FALSE;
+ BOOL bForward = TRUE;
+ DeleteMark();
+ SwRootFrm* pLayout;
+ if( pPt && 0 != (pLayout = GetDoc()->GetRootFrm()) )
+ {
+ // set the cursor to the layout position
+ Point aPt( *pPt );
+ pLayout->GetCrsrOfst( GetPoint(), aPt );
+ }
+
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ bForward ));
+
+ if( aBndry.startPos != aBndry.endPos )
+ {
+ GetPoint()->nContent = (xub_StrLen)aBndry.endPos;
+ if( !IsSelOvr() )
+ {
+ SetMark();
+ GetMark()->nContent = (xub_StrLen)aBndry.startPos;
+ if( !IsSelOvr() )
+ bRet = TRUE;
+ }
+ }
+ }
+
+ if( !bRet )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ }
+ return bRet;
+}
+
+//-----------------------------------------------------------------------------
+
+static String lcl_MaskDeletedRedlines( const SwTxtNode* pTxtNd )
+{
+ String aRes;
+ if (pTxtNd)
+ {
+ //mask deleted redlines
+ String sNodeText(pTxtNd->GetTxt());
+ const SwDoc& rDoc = *pTxtNd->GetDoc();
+ const bool nShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() );
+ if ( nShowChg )
+ {
+ USHORT nAct = rDoc.GetRedlinePos( *pTxtNd, USHRT_MAX );
+ for ( ; nAct < rDoc.GetRedlineTbl().Count(); nAct++ )
+ {
+ const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ];
+ if ( pRed->Start()->nNode > pTxtNd->GetIndex() )
+ break;
+
+ if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
+ {
+ xub_StrLen nStart, nEnd;
+ pRed->CalcStartEnd( pTxtNd->GetIndex(), nStart, nEnd );
+
+ while ( nStart < nEnd && nStart < sNodeText.Len() )
+ sNodeText.SetChar( nStart++, CH_TXTATR_INWORD );
+ }
+ }
+ }
+ aRes = sNodeText;
+ }
+ return aRes;
+}
+
+BOOL SwCursor::GoSentence( SentenceMoveType eMoveType )
+{
+ BOOL bRet = FALSE;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ String sNodeText( lcl_MaskDeletedRedlines( pTxtNd ) );
+
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ switch ( eMoveType )
+ {
+ case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ break;
+ case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ break;
+ case NEXT_SENT:
+ {
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ while (nPtPos != (USHORT) -1 && ++nPtPos < sNodeText.Len()
+ && sNodeText.GetChar(nPtPos)== ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ )
+ ;
+ break;
+ }
+ case PREV_SENT:
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ if (nPtPos == 0)
+ return FALSE; // the previous sentence is not in this paragraph
+ if (nPtPos > 0)
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sNodeText,
+ nPtPos - 1, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ break;
+ }
+
+ // it is allowed to place the PaM just behind the last
+ // character in the text thus <= ...Len
+ if( nPtPos <= pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SwCursor::ExpandToSentenceBorders()
+{
+ BOOL bRes = FALSE;
+ const SwTxtNode* pStartNd = Start()->nNode.GetNode().GetTxtNode();
+ const SwTxtNode* pEndNd = End()->nNode.GetNode().GetTxtNode();
+ if (pStartNd && pEndNd && pBreakIt->GetBreakIter().is())
+ {
+ if (!HasMark())
+ SetMark();
+
+ String sStartText( lcl_MaskDeletedRedlines( pStartNd ) );
+ String sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) );
+
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nStartPos = Start()->nContent.GetIndex();
+ xub_StrLen nEndPos = End()->nContent.GetIndex();
+
+ nStartPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sStartText, nStartPos,
+ pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
+ nEndPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
+ sEndText, nEndPos,
+ pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
+
+ // it is allowed to place the PaM just behind the last
+ // character in the text thus <= ...Len
+ bool bChanged = false;
+ if (nStartPos <= pStartNd->GetTxt().Len())
+ {
+ GetMark()->nContent = nStartPos;
+ bChanged = true;
+ }
+ if (nEndPos <= pEndNd->GetTxt().Len())
+ {
+ GetPoint()->nContent = nEndPos;
+ bChanged = true;
+ }
+ if (bChanged && !IsSelOvr())
+ bRes = TRUE;
+ }
+ return bRes;
+}
+
+
+BOOL SwTableCursor::LeftRight( BOOL bLeft, USHORT nCnt, USHORT /*nMode*/,
+ BOOL /*bVisualAllowed*/, BOOL /*bSkipHidden*/, BOOL /*bInsertCrsr*/ )
+{
+ return bLeft ? GoPrevCell( nCnt )
+ : GoNextCell( nCnt );
+}
+
+
+// calculate cursor bidi level: extracted from LeftRight()
+const SwCntntFrm*
+SwCursor::DoSetBidiLevelLeftRight(
+ BOOL & io_rbLeft, BOOL bVisualAllowed, BOOL bInsertCrsr)
+{
+ // calculate cursor bidi level
+ const SwCntntFrm* pSttFrm = NULL;
+ SwNode& rNode = GetPoint()->nNode.GetNode();
+
+ if( rNode.IsTxtNode() )
+ {
+ const SwTxtNode& rTNd = *rNode.GetTxtNode();
+ SwIndex& rIdx = GetPoint()->nContent;
+ xub_StrLen nPos = rIdx.GetIndex();
+
+ const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
+ if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() &&
+ SvtCTLOptions::MOVEMENT_VISUAL ==
+ rCTLOptions.GetCTLCursorMovement() )
+ {
+ // for visual cursor travelling (used in bidi layout)
+ // we first have to convert the logic to a visual position
+ Point aPt;
+ pSttFrm = rTNd.GetFrm( &aPt, GetPoint() );
+ if( pSttFrm )
+ {
+ BYTE nCrsrLevel = GetCrsrBidiLevel();
+ sal_Bool bForward = ! io_rbLeft;
+ ((SwTxtFrm*)pSttFrm)->PrepareVisualMove( nPos, nCrsrLevel,
+ bForward, bInsertCrsr );
+ rIdx = nPos;
+ SetCrsrBidiLevel( nCrsrLevel );
+ io_rbLeft = ! bForward;
+ }
+ }
+ else
+ {
+ const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd );
+ if ( pSI )
+ {
+ const xub_StrLen nMoveOverPos = io_rbLeft ?
+ ( nPos ? nPos - 1 : 0 ) :
+ nPos;
+ SetCrsrBidiLevel( pSI->DirType( nMoveOverPos ) );
+ }
+ }
+ }
+ return pSttFrm;
+}
+
+BOOL SwCursor::LeftRight( BOOL bLeft, USHORT nCnt, USHORT nMode,
+ BOOL bVisualAllowed,BOOL bSkipHidden, BOOL bInsertCrsr )
+{
+ // calculate cursor bidi level
+ SwNode& rNode = GetPoint()->nNode.GetNode();
+ const SwCntntFrm* pSttFrm = // may side-effect bLeft!
+ DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCrsr);
+
+ // kann der Cursor n-mal weiterverschoben werden ?
+ SwCrsrSaveState aSave( *this );
+ SwMoveFn fnMove = bLeft ? fnMoveBackward : fnMoveForward;
+
+ SwGoInDoc fnGo;
+ if ( bSkipHidden )
+ fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCellsSkipHidden : fnGoCntntSkipHidden;
+ else
+ fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCells : fnGoCntnt;
+
+ // ASSERT( not in covered cell )
+
+ while( nCnt )
+ {
+ SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
+
+ bool bSuccess = Move( fnMove, fnGo );
+ if ( !bSuccess )
+ break;
+
+ // If we were located inside a covered cell but our position has been
+ // corrected, we check if the last move has moved the cursor to a different
+ // table cell. In this case we set the cursor to the stored covered position
+ // and redo the move:
+ if ( mnRowSpanOffset )
+ {
+ const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode();
+ const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : 0;
+ const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : 0;
+
+ const bool bCellChanged = pOldTabSttNode && pNewTabSttNode &&
+ pOldTabSttNode == pNewTabSttNode &&
+ pOldTabBoxSttNode && pNewTabBoxSttNode &&
+ pOldTabBoxSttNode != pNewTabBoxSttNode;
+
+ if ( bCellChanged )
+ {
+ // Set cursor to start/end of covered cell:
+ SwTableBox* pTableBox = pOldTabBoxSttNode->GetTblBox();
+ const long nRowSpan = pTableBox->getRowSpan();
+ if ( nRowSpan > 1 )
+ {
+ pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), (USHORT)(pTableBox->getRowSpan() + mnRowSpanOffset ) );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+
+ GetDoc()->GetNodes().GoNextSection( &rPtIdx, FALSE, FALSE );
+ SwCntntNode* pCntntNode = GetCntntNode();
+ if ( pCntntNode )
+ {
+ const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
+ GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
+
+ // Redo the move:
+ bSuccess = Move( fnMove, fnGo );
+ if ( !bSuccess )
+ break;
+ }
+ }
+
+ mnRowSpanOffset = 0;
+ }
+ }
+
+ // Check if I'm inside a covered cell. Correct cursor if necessary and
+ // store covered cell:
+ const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ if ( pTableBoxStartNode )
+ {
+ const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
+ if ( pTableBox->getRowSpan() < 1 )
+ {
+ // Store the row span offset:
+ mnRowSpanOffset = pTableBox->getRowSpan();
+
+ // Move cursor to non-covered cell:
+ const SwTableNode* pTblNd = pTableBoxStartNode->FindTableNode();
+ pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+
+ GetDoc()->GetNodes().GoNextSection( &rPtIdx, FALSE, FALSE );
+ SwCntntNode* pCntntNode = GetCntntNode();
+ if ( pCntntNode )
+ {
+ const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
+ GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
+ }
+ }
+ }
+
+ --nCnt;
+ }
+
+ // here come some special rules for visual cursor travelling
+ if ( pSttFrm )
+ {
+ SwNode& rTmpNode = GetPoint()->nNode.GetNode();
+ if ( &rTmpNode != &rNode && rTmpNode.IsTxtNode() )
+ {
+ Point aPt;
+ const SwCntntFrm* pEndFrm = ((SwTxtNode&)rTmpNode).GetFrm( &aPt, GetPoint() );
+ if ( pEndFrm )
+ {
+ if ( ! pEndFrm->IsRightToLeft() != ! pSttFrm->IsRightToLeft() )
+ {
+ if ( ! bLeft )
+ pEndFrm->RightMargin( this );
+ else
+ pEndFrm->LeftMargin( this );
+ }
+ }
+ }
+ }
+
+ return 0 == nCnt && !IsInProtectTable( TRUE ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+}
+
+// calculate cursor bidi level: extracted from UpDown()
+void SwCursor::DoSetBidiLevelUpDown()
+{
+ SwNode& rNode = GetPoint()->nNode.GetNode();
+ if ( rNode.IsTxtNode() )
+ {
+ const SwScriptInfo* pSI =
+ SwScriptInfo::GetScriptInfo( (SwTxtNode&)rNode );
+ if ( pSI )
+ {
+ SwIndex& rIdx = GetPoint()->nContent;
+ xub_StrLen nPos = rIdx.GetIndex();
+
+ if( nPos && nPos < ((SwTxtNode&)rNode).GetTxt().Len() )
+ {
+ const BYTE nCurrLevel = pSI->DirType( nPos );
+ const BYTE nPrevLevel = pSI->DirType( nPos - 1 );
+
+ if ( nCurrLevel % 2 != nPrevLevel % 2 )
+ {
+ // set cursor level to the lower of the two levels
+ SetCrsrBidiLevel( Min( nCurrLevel, nPrevLevel ) );
+ }
+ else
+ SetCrsrBidiLevel( nCurrLevel );
+ }
+ }
+ }
+}
+
+BOOL SwCursor::UpDown( BOOL bUp, USHORT nCnt,
+ Point* pPt, long nUpDownX )
+{
+ SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
+ sal_Bool bAdjustTableCrsr = sal_False;
+
+ // vom Tabellen Crsr Point/Mark in der gleichen Box ??
+ // dann stelle den Point an den Anfang der Box
+ if( pTblCrsr && GetNode( TRUE )->StartOfSectionNode() ==
+ GetNode( FALSE )->StartOfSectionNode() )
+ {
+ if ( End() != GetPoint() )
+ Exchange();
+ bAdjustTableCrsr = sal_True;
+ }
+
+ BOOL bRet = FALSE;
+ Point aPt;
+ if( pPt )
+ aPt = *pPt;
+ SwCntntFrm* pFrm = GetCntntNode()->GetFrm( &aPt, GetPoint() );
+
+ if( pFrm )
+ {
+ SwCrsrSaveState aSave( *this );
+
+ if( !pPt )
+ {
+ SwRect aTmpRect;
+ pFrm->GetCharRect( aTmpRect, *GetPoint() );
+ aPt = aTmpRect.Pos();
+
+ nUpDownX = pFrm->IsVertical() ?
+ aPt.Y() - pFrm->Frm().Top() :
+ aPt.X() - pFrm->Frm().Left();
+ }
+
+ // Bei Fussnoten ist auch die Bewegung in eine andere Fussnote erlaubt.
+ // aber keine Selection!!
+ const BOOL bChkRange = pFrm->IsInFtn() && !HasMark()
+ ? FALSE : TRUE;
+ const SwPosition aOldPos( *GetPoint() );
+ BOOL bInReadOnly = IsReadOnlyAvailable();
+
+ if ( bAdjustTableCrsr && !bUp )
+ {
+ // Special case: We have a table cursor but the start box
+ // has more than one paragraph. If we want to go down, we have to
+ // set the point to the last frame in the table box. This is
+ // only necessary if we do not already have a table selection
+ const SwStartNode* pTblNd = GetNode( TRUE )->FindTableBoxStartNode();
+ ASSERT( pTblNd, "pTblCrsr without SwTableNode?" )
+
+ if ( pTblNd ) // safety first
+ {
+ const SwNode* pEndNd = pTblNd->EndOfSectionNode();
+ GetPoint()->nNode = *pEndNd;
+ pTblCrsr->Move( fnMoveBackward, fnGoNode );
+ pFrm = GetCntntNode()->GetFrm( &aPt, GetPoint() );
+ }
+ }
+
+ while( nCnt &&
+ (bUp ? pFrm->UnitUp( this, nUpDownX, bInReadOnly )
+ : pFrm->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
+ CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
+ {
+ pFrm = GetCntntNode()->GetFrm( &aPt, GetPoint() );
+ --nCnt;
+ }
+
+ if( !nCnt && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) // die gesamte Anzahl durchlaufen ?
+ {
+ if( !pTblCrsr )
+ {
+ // dann versuche den Cursor auf die Position zu setzen,
+ // auf halber Heohe vom Char-Rectangle
+ pFrm = GetCntntNode()->GetFrm( &aPt, GetPoint() );
+ SwCrsrMoveState eTmpState( MV_UPDOWN );
+ eTmpState.bSetInReadOnly = bInReadOnly;
+ SwRect aTmpRect;
+ pFrm->GetCharRect( aTmpRect, *GetPoint(), &eTmpState );
+ if ( pFrm->IsVertical() )
+ {
+ aPt.X() = aTmpRect.Center().X();
+ pFrm->Calc();
+ aPt.Y() = pFrm->Frm().Top() + nUpDownX;
+ }
+ else
+ {
+ aPt.Y() = aTmpRect.Center().Y();
+ pFrm->Calc();
+ aPt.X() = pFrm->Frm().Left() + nUpDownX;
+ }
+ pFrm->GetCrsrOfst( GetPoint(), aPt, &eTmpState );
+ }
+ bRet = TRUE;
+ }
+ else
+ *GetPoint() = aOldPos;
+
+ DoSetBidiLevelUpDown(); // calculate cursor bidi level
+ }
+
+ return bRet;
+}
+
+BOOL SwCursor::LeftRightMargin( BOOL bLeft, BOOL bAPI )
+{
+ Point aPt;
+ SwCntntFrm * pFrm = GetCntntNode()->GetFrm( &aPt, GetPoint() );
+
+ // calculate cursor bidi level
+ if ( pFrm )
+ SetCrsrBidiLevel( pFrm->IsRightToLeft() ? 1 : 0 );
+
+ return pFrm && (bLeft ? pFrm->LeftMargin( this ) :
+ pFrm->RightMargin( this, bAPI ) );
+}
+
+BOOL SwCursor::IsAtLeftRightMargin( BOOL bLeft, BOOL bAPI ) const
+{
+ BOOL bRet = FALSE;
+ Point aPt;
+ SwCntntFrm * pFrm = GetCntntNode()->GetFrm( &aPt, GetPoint() );
+ if( pFrm )
+ {
+ SwPaM aPam( *GetPoint() );
+ if( !bLeft && aPam.GetPoint()->nContent.GetIndex() )
+ aPam.GetPoint()->nContent--;
+ bRet = (bLeft ? pFrm->LeftMargin( &aPam )
+ : pFrm->RightMargin( &aPam, bAPI ))
+ && *aPam.GetPoint() == *GetPoint();
+ }
+ return bRet;
+}
+
+BOOL SwCursor::SttEndDoc( BOOL bStt )
+{
+ SwCrsrSaveState aSave( *this );
+
+ // Springe beim Selektieren nie ueber Section-Grenzen !!
+ // kann der Cursor weiterverschoben werden ?
+ SwMoveFn fnMove = bStt ? fnMoveBackward : fnMoveForward;
+ BOOL bRet = (!HasMark() || !IsNoCntnt() ) &&
+ Move( fnMove, fnGoDoc ) &&
+ !IsInProtectTable( TRUE ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS |
+ nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION );
+
+ return bRet;
+}
+
+BOOL SwCursor::GoPrevNextCell( BOOL bNext, USHORT nCnt )
+{
+ const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
+ if( !pTblNd )
+ return FALSE;
+
+ // liegt vor dem StartNode der Cell ein weiterer EndNode, dann
+ // gibt es auch eine vorherige Celle
+ SwCrsrSaveState aSave( *this );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+
+ while( nCnt-- )
+ {
+ const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
+ const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
+
+ // Check if we have to move the cursor to a covered cell before
+ // proceeding:
+ if ( mnRowSpanOffset )
+ {
+ if ( pTableBox->getRowSpan() > 1 )
+ {
+ pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), (USHORT)(pTableBox->getRowSpan() + mnRowSpanOffset) );
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+ pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
+ }
+ mnRowSpanOffset = 0;
+ }
+
+ const SwNode* pTmpNode = bNext ?
+ pTableBoxStartNode->EndOfSectionNode() :
+ pTableBoxStartNode;
+
+ SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 );
+ if( (bNext && !aCellIdx.GetNode().IsStartNode()) ||
+ (!bNext && !aCellIdx.GetNode().IsEndNode()) )
+ return FALSE;
+
+ rPtIdx = bNext ? aCellIdx : SwNodeIndex(*aCellIdx.GetNode().StartOfSectionNode());
+
+ pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
+ pTableBox = pTableBoxStartNode->GetTblBox();
+ if ( pTableBox->getRowSpan() < 1 )
+ {
+ mnRowSpanOffset = pTableBox->getRowSpan();
+ // move cursor to non-covered cell:
+ pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+ }
+ }
+
+ rPtIdx++;
+ if( !rPtIdx.GetNode().IsCntntNode() )
+ GetDoc()->GetNodes().GoNextSection( &rPtIdx, TRUE, FALSE );
+ GetPoint()->nContent.Assign( GetCntntNode(), 0 );
+
+ return !IsInProtectTable( TRUE );
+}
+
+BOOL SwTableCursor::GotoTable( const String& /*rName*/ )
+{
+ return FALSE; // invalid action
+}
+
+BOOL SwCursor::GotoTable( const String& rName )
+{
+ BOOL bRet = FALSE;
+ if ( !HasMark() )
+ {
+ SwTable* pTmpTbl = SwTable::FindTable( GetDoc()->FindTblFmtByName( rName ) );
+ if( pTmpTbl )
+ {
+ // eine Tabelle im normalen NodesArr
+ SwCrsrSaveState aSave( *this );
+ GetPoint()->nNode = *pTmpTbl->GetTabSortBoxes()[ 0 ]->
+ GetSttNd()->FindTableNode();
+ Move( fnMoveForward, fnGoCntnt );
+ bRet = !IsSelOvr();
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::GotoTblBox( const String& rName )
+{
+ BOOL bRet = FALSE;
+ const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ // erfrage die Box, mit dem Nanen
+ const SwTableBox* pTblBox = pTblNd->GetTable().GetTblBox( rName );
+ if( pTblBox && pTblBox->GetSttNd() &&
+ ( !pTblBox->GetFrmFmt()->GetProtect().IsCntntProtected() ||
+ IsReadOnlyAvailable() ) )
+ {
+ SwCrsrSaveState aSave( *this );
+ GetPoint()->nNode = *pTblBox->GetSttNd();
+ Move( fnMoveForward, fnGoCntnt );
+ bRet = !IsSelOvr();
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCursor::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
+{
+ //JP 28.8.2001: for optimization test something before
+ const SwNode* pNd = &GetPoint()->nNode.GetNode();
+ bool bShortCut = false;
+ if ( fnWhichPara == fnParaCurr )
+ {
+ // --> FME 2005-02-21 #i41048#
+ // If fnWhichPara == fnParaCurr, (*fnWhichPara)( *this, fnPosPara )
+ // can already move the cursor to a different text node. In this case
+ // we better check if IsSelOvr().
+ const SwCntntNode* pCntntNd = pNd->GetCntntNode();
+ if ( pCntntNd )
+ {
+ const xub_StrLen nSttEnd = fnPosPara == fnMoveForward ? 0 : pCntntNd->Len();
+ if ( GetPoint()->nContent.GetIndex() != nSttEnd )
+ bShortCut = true;
+ }
+ // <--
+ }
+ else
+ {
+ if ( pNd->IsTxtNode() &&
+ pNd->GetNodes()[ pNd->GetIndex() +
+ (fnWhichPara == fnParaNext ? 1 : -1 ) ]->IsTxtNode() )
+ bShortCut = true;
+ }
+
+ if ( bShortCut )
+ return (*fnWhichPara)( *this, fnPosPara );
+
+ // else we must use the SaveStructure, because the next/prev is not
+ // a same node type.
+ SwCrsrSaveState aSave( *this );
+ return (*fnWhichPara)( *this, fnPosPara ) &&
+ !IsInProtectTable( TRUE ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+}
+
+
+BOOL SwCursor::MoveSection( SwWhichSection fnWhichSect,
+ SwPosSection fnPosSect)
+{
+ SwCrsrSaveState aSave( *this );
+ return (*fnWhichSect)( *this, fnPosSect ) &&
+ !IsInProtectTable( TRUE ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+}
+
+/*
+ BOOL MoveTable( SwWhichTable, SwPosTable );
+ BOOL MoveColumn( SwWhichColumn, SwPosColumn );
+ BOOL MoveRegion( SwWhichRegion, SwPosRegion );
+*/
+
+void SwCursor::RestoreSavePos() // Point auf die SavePos setzen
+{
+ if( pSavePos )
+ {
+ GetPoint()->nNode = pSavePos->nNode;
+ GetPoint()->nContent.Assign( GetCntntNode(), pSavePos->nCntnt );
+ }
+}
+
+
+/* */
+
+SwTableCursor::SwTableCursor( const SwPosition &rPos, SwPaM* pRing )
+ : SwCursor( rPos, pRing, false )
+{
+ bParked = FALSE;
+ bChg = FALSE;
+ nTblPtNd = 0, nTblMkNd = 0;
+ nTblPtCnt = 0, nTblMkCnt = 0;
+}
+
+SwTableCursor::~SwTableCursor() {}
+
+
+BOOL lcl_SeekEntry( const SwSelBoxes& rTmp, const SwStartNode* pSrch, USHORT& rFndPos )
+{
+ ULONG nIdx = pSrch->GetIndex();
+
+ USHORT nO = rTmp.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( rTmp[ nM ]->GetSttNd() == pSrch )
+ {
+ rFndPos = nM;
+ return TRUE;
+ }
+ else if( rTmp[ nM ]->GetSttIdx() < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ return FALSE;
+ else
+ nO = nM - 1;
+ }
+ }
+ return FALSE;
+}
+
+
+SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pAktCrsr )
+{
+ if( bChg ) // ???
+ {
+ if( bParked )
+ {
+ // wieder in den Inhalt schieben
+ Exchange();
+ Move( fnMoveForward );
+ Exchange();
+ Move( fnMoveForward );
+ bParked = FALSE;
+ }
+
+ bChg = FALSE;
+
+ // temp Kopie anlegen, damit alle Boxen, fuer die schon Cursor
+ // existieren, entfernt werden koennen.
+ SwSelBoxes aTmp;
+ aTmp.Insert( &aSelBoxes );
+
+ //Jetzt die Alten und die neuen abgleichen.
+ SwNodes& rNds = pAktCrsr->GetDoc()->GetNodes();
+ USHORT nPos;
+ const SwStartNode* pSttNd;
+ SwPaM* pCur = pAktCrsr;
+ do {
+ BOOL bDel = FALSE;
+ pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ if( !pCur->HasMark() || !pSttNd ||
+ pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() )
+ bDel = TRUE;
+
+ else if( lcl_SeekEntry( aTmp, pSttNd, nPos ))
+ {
+ SwNodeIndex aIdx( *pSttNd, 1 );
+ const SwNode* pNd = &aIdx.GetNode();
+ if( !pNd->IsCntntNode() )
+ pNd = rNds.GoNextSection( &aIdx, TRUE, FALSE );
+
+ SwPosition* pPos = pCur->GetMark();
+ if( pNd != &pPos->nNode.GetNode() )
+ pPos->nNode = *pNd;
+ pPos->nContent.Assign( (SwCntntNode*)pNd, 0 );
+
+ aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 );
+ if( !( pNd = &aIdx.GetNode())->IsCntntNode() )
+ pNd = rNds.GoPrevSection( &aIdx, TRUE, FALSE );
+
+ pPos = pCur->GetPoint();
+ if( pNd != &pPos->nNode.GetNode() )
+ pPos->nNode = *pNd;
+ pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
+
+ aTmp.Remove( nPos );
+ }
+ else
+ bDel = TRUE;
+
+ pCur = (SwPaM*)pCur->GetNext();
+ if( bDel )
+ {
+ SwPaM* pDel = (SwPaM*)pCur->GetPrev();
+/*
+JP 20.07.98: der alte Code geht mit dem UNO-TableCrsr nicht
+ if( pDel == pAktCrsr )
+ {
+ if( pAktCrsr->GetNext() == pAktCrsr )
+ {
+ pAktCrsr->DeleteMark();
+ break; // es gibt nichts mehr zu loeschen!
+ }
+ pAktCrsr = (SwCursor*)pDel->GetPrev();
+ }
+ delete pDel;
+*/
+
+ if( pDel == pAktCrsr )
+ pAktCrsr->DeleteMark();
+ else
+ delete pDel;
+ }
+ } while ( pAktCrsr != pCur );
+
+ for( nPos = 0; nPos < aTmp.Count(); ++nPos )
+ {
+ pSttNd = aTmp[ nPos ]->GetSttNd();
+
+ SwNodeIndex aIdx( *pSttNd, 1 );
+ if( &aIdx.GetNodes() != &rNds )
+ break;
+ const SwNode* pNd = &aIdx.GetNode();
+ if( !pNd->IsCntntNode() )
+ pNd = rNds.GoNextSection( &aIdx, TRUE, FALSE );
+
+ SwPaM* pNew;
+ if( pAktCrsr->GetNext() == pAktCrsr && !pAktCrsr->HasMark() )
+ {
+ pNew = pAktCrsr;
+ pNew->GetPoint()->nNode = *pNd;
+ pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+ }
+ else
+ {
+ pNew = pAktCrsr->Create( pAktCrsr );
+ pNew->GetPoint()->nNode = *pNd;
+ pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+ }
+ pNew->SetMark();
+
+ SwPosition* pPos = pNew->GetPoint();
+ pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 );
+ if( !( pNd = &pPos->nNode.GetNode())->IsCntntNode() )
+ pNd = rNds.GoPrevSection( &pPos->nNode, TRUE, FALSE );
+
+ pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
+ }
+ }
+ return pAktCrsr;
+}
+
+
+void SwTableCursor::InsertBox( const SwTableBox& rTblBox )
+{
+ SwTableBox* pBox = (SwTableBox*)&rTblBox;
+ aSelBoxes.Insert( pBox );
+ bChg = TRUE;
+}
+
+bool SwTableCursor::NewTableSelection()
+{
+ bool bRet = false;
+ const SwNode *pStart = GetCntntNode()->FindTableBoxStartNode();
+ const SwNode *pEnd = GetCntntNode(FALSE)->FindTableBoxStartNode();
+ if( pStart && pEnd )
+ {
+ const SwTableNode *pTableNode = pStart->FindTableNode();
+ if( pTableNode == pEnd->FindTableNode() &&
+ pTableNode->GetTable().IsNewModel() )
+ {
+ bRet = true;
+ SwSelBoxes aNew;
+ aNew.Insert( &aSelBoxes );
+ pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew,
+ SwTable::SEARCH_NONE, false );
+ ActualizeSelection( aNew );
+ }
+ }
+ return bRet;
+}
+
+void SwTableCursor::ActualizeSelection( const SwSelBoxes &rNew )
+{
+ USHORT nOld = 0, nNew = 0;
+ while ( nOld < aSelBoxes.Count() && nNew < rNew.Count() )
+ {
+ const SwTableBox* pPOld = *( aSelBoxes.GetData() + nOld );
+ const SwTableBox* pPNew = *( rNew.GetData() + nNew );
+ if( pPOld == pPNew )
+ { // this box will stay
+ ++nOld;
+ ++nNew;
+ }
+ else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
+ DeleteBox( nOld ); // this box has to go
+ else
+ {
+ InsertBox( *pPNew ); // this is a new one
+ ++nOld;
+ ++nNew;
+ }
+ }
+
+ while( nOld < aSelBoxes.Count() )
+ DeleteBox( nOld ); // some more to delete
+
+ for( ; nNew < rNew.Count(); ++nNew ) // some more to insert
+ InsertBox( **( rNew.GetData() + nNew ) );
+}
+
+BOOL SwTableCursor::IsCrsrMovedUpdt()
+{
+ if( !IsCrsrMoved() )
+ return FALSE;
+
+ nTblMkNd = GetMark()->nNode.GetIndex();
+ nTblPtNd = GetPoint()->nNode.GetIndex();
+ nTblMkCnt = GetMark()->nContent.GetIndex();
+ nTblPtCnt = GetPoint()->nContent.GetIndex();
+ return TRUE;
+}
+
+
+// Parke den Tabellen-Cursor auf dem StartNode der Boxen.
+void SwTableCursor::ParkCrsr()
+{
+ // Index aus dem TextNode abmelden
+ SwNode* pNd = &GetPoint()->nNode.GetNode();
+ if( !pNd->IsStartNode() )
+ pNd = pNd->StartOfSectionNode();
+ GetPoint()->nNode = *pNd;
+ GetPoint()->nContent.Assign( 0, 0 );
+
+ pNd = &GetMark()->nNode.GetNode();
+ if( !pNd->IsStartNode() )
+ pNd = pNd->StartOfSectionNode();
+ GetMark()->nNode = *pNd;
+ GetMark()->nContent.Assign( 0, 0 );
+
+ bChg = TRUE;
+ bParked = TRUE;
+}
+
+
+BOOL SwTableCursor::HasReadOnlyBoxSel() const
+{
+ BOOL bRet = FALSE;
+ for( USHORT n = aSelBoxes.Count(); n; )
+ if( aSelBoxes[ --n ]->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ {
+ bRet = TRUE;
+ break;
+ }
+ return bRet;
+}
+
+
diff --git a/sw/source/core/crsr/trvlcol.cxx b/sw/source/core/crsr/trvlcol.cxx
new file mode 100644
index 000000000000..076af3be386c
--- /dev/null
+++ b/sw/source/core/crsr/trvlcol.cxx
@@ -0,0 +1,133 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <layfrm.hxx>
+#include <cntfrm.hxx>
+#include <swcrsr.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+
+
+
+SwLayoutFrm* GetCurrColumn( const SwLayoutFrm* pLayFrm )
+{
+ while( pLayFrm && !pLayFrm->IsColumnFrm() )
+ pLayFrm = pLayFrm->GetUpper();
+ return (SwLayoutFrm*)pLayFrm;
+}
+
+
+SwLayoutFrm* GetNextColumn( const SwLayoutFrm* pLayFrm )
+{
+ SwLayoutFrm* pActCol = GetCurrColumn( pLayFrm );
+ return pActCol ? (SwLayoutFrm*)pActCol->GetNext() : 0;
+}
+
+
+SwLayoutFrm* GetPrevColumn( const SwLayoutFrm* pLayFrm )
+{
+ SwLayoutFrm* pActCol = GetCurrColumn( pLayFrm );
+ return pActCol ? (SwLayoutFrm*)pActCol->GetPrev() : 0;
+}
+
+
+SwCntntFrm* GetColumnStt( const SwLayoutFrm* pColFrm )
+{
+ return pColFrm ? (SwCntntFrm*)pColFrm->ContainsCntnt() : 0;
+}
+
+
+SwCntntFrm* GetColumnEnd( const SwLayoutFrm* pColFrm )
+{
+ SwCntntFrm *pRet = GetColumnStt( pColFrm );
+ if( !pRet )
+ return 0;
+
+ SwCntntFrm *pNxt = pRet->GetNextCntntFrm();
+ while( pNxt && pColFrm->IsAnLower( pNxt ) )
+ {
+ pRet = pNxt;
+ pNxt = pNxt->GetNextCntntFrm();
+ }
+ return pRet;
+}
+
+
+SwWhichColumn fnColumnPrev = &GetPrevColumn;
+SwWhichColumn fnColumnCurr = &GetCurrColumn;
+SwWhichColumn fnColumnNext = &GetNextColumn;
+SwPosColumn fnColumnStart = &GetColumnStt;
+SwPosColumn fnColumnEnd = &GetColumnEnd;
+
+
+BOOL SwCrsrShell::MoveColumn( SwWhichColumn fnWhichCol, SwPosColumn fnPosCol )
+{
+ BOOL bRet = FALSE;
+ if( !pTblCrsr )
+ {
+ SwLayoutFrm* pLayFrm = GetCurrFrm()->GetUpper();
+ if( pLayFrm && 0 != ( pLayFrm = (*fnWhichCol)( pLayFrm )) )
+ {
+ SwCntntFrm* pCnt = (*fnPosCol)( pLayFrm );
+ if( pCnt )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pCnt->Calc(); // ???
+
+ Point aPt( pCnt->Frm().Pos() + pCnt->Prt().Pos() );
+ if( fnPosCol == GetColumnEnd )
+ {
+ aPt.X() += pCnt->Prt().Width();
+ aPt.Y() += pCnt->Prt().Height();
+ }
+
+ pCnt->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+
+ if( !pCurCrsr->IsInProtectTable( TRUE ) &&
+ !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr();
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+
+
diff --git a/sw/source/core/crsr/trvlfnfl.cxx b/sw/source/core/crsr/trvlfnfl.cxx
new file mode 100644
index 000000000000..3edf3718eabe
--- /dev/null
+++ b/sw/source/core/crsr/trvlfnfl.cxx
@@ -0,0 +1,359 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <ftnfrm.hxx>
+#include <viewimp.hxx>
+#include <swcrsr.hxx>
+#include <dflyobj.hxx>
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <txtfrm.hxx>
+#include <txtftn.hxx>
+#include <ftnidx.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+
+BOOL SwCrsrShell::CallCrsrFN( FNCrsr fnCrsr )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor* pCrsr = getShellCrsr( true );
+ BOOL bRet = (pCrsr->*fnCrsr)();
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ return bRet;
+}
+
+BOOL SwCursor::GotoFtnTxt()
+{
+ // springe aus dem Content zur Fussnote
+ BOOL bRet = FALSE;
+ SwTxtNode* pTxtNd = GetPoint()->nNode.GetNode().GetTxtNode();
+
+ SwTxtAttr *const pFtn( (pTxtNd)
+ ? pTxtNd->GetTxtAttrForCharAt(
+ GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN)
+ : 0);
+ if (pFtn)
+ {
+ SwCrsrSaveState aSaveState( *this );
+ GetPoint()->nNode = *((SwTxtFtn*)pFtn)->GetStartNode();
+
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
+ &GetPoint()->nNode,
+ TRUE, !IsReadOnlyAvailable() );
+ if( pCNd )
+ {
+ GetPoint()->nContent.Assign( pCNd, 0 );
+ bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::GotoFtnTxt()
+{
+ BOOL bRet = CallCrsrFN( &SwCursor::GotoFtnTxt );
+ if( !bRet )
+ {
+ SwTxtNode* pTxtNd = _GetCrsr() ?
+ _GetCrsr()->GetPoint()->nNode.GetNode().GetTxtNode() : NULL;
+ if( pTxtNd )
+ {
+ const SwFrm *pFrm = pTxtNd->GetFrm( &_GetCrsr()->GetSttPos(),
+ _GetCrsr()->Start() );
+ const SwFtnBossFrm* pFtnBoss;
+ sal_Bool bSkip = pFrm && pFrm->IsInFtn();
+ while( pFrm && 0 != ( pFtnBoss = pFrm->FindFtnBossFrm() ) )
+ {
+ if( 0 != ( pFrm = pFtnBoss->FindFtnCont() ) )
+ {
+ if( bSkip )
+ bSkip = sal_False;
+ else
+ {
+ const SwCntntFrm* pCnt = static_cast<const SwLayoutFrm*>
+ (pFrm)->ContainsCntnt();
+ if( pCnt )
+ {
+ const SwCntntNode* pNode = pCnt->GetNode();
+ _GetCrsr()->GetPoint()->nNode = *pNode;
+ _GetCrsr()->GetPoint()->nContent.Assign(
+ const_cast<SwCntntNode*>(pNode),
+ static_cast<const SwTxtFrm*>(pCnt)->GetOfst() );
+ UpdateCrsr( SwCrsrShell::SCROLLWIN |
+ SwCrsrShell::CHKRANGE | SwCrsrShell::READONLY );
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ if( pFtnBoss->GetNext() && !pFtnBoss->IsPageFrm() )
+ pFrm = pFtnBoss->GetNext();
+ else
+ pFrm = pFtnBoss->GetUpper();
+ }
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SwCursor::GotoFtnAnchor()
+{
+ // springe aus der Fussnote zum Anker
+ const SwNode* pSttNd = GetNode()->FindFootnoteStartNode();
+ if( pSttNd )
+ {
+ // durchsuche alle Fussnoten im Dokument nach diesem StartIndex
+ const SwTxtFtn* pTxtFtn;
+ const SwFtnIdxs& rFtnArr = pSttNd->GetDoc()->GetFtnIdxs();
+ for( USHORT n = 0; n < rFtnArr.Count(); ++n )
+ if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
+ pSttNd == &pTxtFtn->GetStartNode()->GetNode() )
+ {
+ SwCrsrSaveState aSaveState( *this );
+
+ SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
+
+ GetPoint()->nNode = rTNd;
+ GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+
+ return !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ }
+ }
+ return FALSE;
+}
+
+BOOL SwCrsrShell::GotoFtnAnchor()
+{
+ // springe aus der Fussnote zum Anker
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ BOOL bRet = pCurCrsr->GotoFtnAnchor();
+ if( bRet )
+ {
+ // BUG 5996: Tabellen-Kopfzeile sonderbehandeln
+ pCurCrsr->GetPtPos() = Point();
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ return bRet;
+}
+
+inline sal_Bool CmpLE( const SwTxtFtn& rFtn, ULONG nNd, xub_StrLen nCnt )
+{
+ ULONG nTNd = rFtn.GetTxtNode().GetIndex();
+ return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() <= nCnt );
+}
+inline sal_Bool CmpL( const SwTxtFtn& rFtn, ULONG nNd, xub_StrLen nCnt )
+{
+ ULONG nTNd = rFtn.GetTxtNode().GetIndex();
+ return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() < nCnt );
+}
+
+BOOL SwCursor::GotoNextFtnAnchor()
+{
+ const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
+ const SwTxtFtn* pTxtFtn = 0;
+ USHORT nPos;
+
+ if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ))
+ {
+ // es gibt eine Fussnote mit dem Index, suche also die
+ // naechstgelegene
+ if( nPos < rFtnArr.Count() )
+ {
+ ULONG nNdPos = GetPoint()->nNode.GetIndex();
+ xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
+
+ pTxtFtn = rFtnArr[ nPos ];
+ // suche vorewaerts zur naechsten
+ if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
+ {
+ pTxtFtn = 0;
+ for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
+ {
+ pTxtFtn = rFtnArr[ nPos ];
+ if( !CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
+ break; // gefunden
+ pTxtFtn = 0;
+ }
+ }
+ else if( nPos )
+ {
+ // suche rueckwaerts zur vorherigen
+ pTxtFtn = 0;
+ while( nPos )
+ {
+ pTxtFtn = rFtnArr[ --nPos ];
+ if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
+ {
+ pTxtFtn = rFtnArr[ ++nPos ];
+ break; // gefunden
+ }
+// pTxtFtn = 0;
+ }
+ }
+ }
+ }
+ else if( nPos < rFtnArr.Count() )
+ pTxtFtn = rFtnArr[ nPos ];
+
+ BOOL bRet = 0 != pTxtFtn;
+ if( bRet )
+ {
+ SwCrsrSaveState aSaveState( *this );
+
+ SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
+ GetPoint()->nNode = rTNd;
+ GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+ bRet = !IsSelOvr();
+ }
+ return bRet;
+}
+
+BOOL SwCursor::GotoPrevFtnAnchor()
+{
+ const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
+ const SwTxtFtn* pTxtFtn = 0;
+ USHORT nPos;
+
+ if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ) )
+ {
+ // es gibt eine Fussnote mit dem Index, suche also die
+ // naechstgelegene
+ ULONG nNdPos = GetPoint()->nNode.GetIndex();
+ xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
+
+ pTxtFtn = rFtnArr[ nPos ];
+ // suche vorwaerts zur naechsten
+ if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
+ {
+ for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
+ {
+ pTxtFtn = rFtnArr[ nPos ];
+ if( !CmpL( *pTxtFtn, nNdPos, nCntPos ) )
+ {
+ pTxtFtn = rFtnArr[ nPos-1 ];
+ break;
+ }
+ }
+ }
+ else if( nPos )
+ {
+ // suche rueckwaerts zur vorherigen
+ pTxtFtn = 0;
+ while( nPos )
+ {
+ pTxtFtn = rFtnArr[ --nPos ];
+ if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
+ break; // gefunden
+ pTxtFtn = 0;
+ }
+ }
+ else
+ pTxtFtn = 0;
+ }
+ else if( nPos )
+ pTxtFtn = rFtnArr[ nPos-1 ];
+
+ BOOL bRet = 0 != pTxtFtn;
+ if( bRet )
+ {
+ SwCrsrSaveState aSaveState( *this );
+
+ SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
+ GetPoint()->nNode = rTNd;
+ GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+ bRet = !IsSelOvr();
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::GotoNextFtnAnchor()
+{
+ return CallCrsrFN( &SwCursor::GotoNextFtnAnchor );
+}
+
+BOOL SwCrsrShell::GotoPrevFtnAnchor()
+{
+ return CallCrsrFN( &SwCursor::GotoPrevFtnAnchor );
+}
+
+// springe aus dem Rahmen zum Anker
+
+
+BOOL SwCrsrShell::GotoFlyAnchor()
+{
+ SET_CURR_SHELL( this );
+ const SwFrm* pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while( pFrm && !pFrm->IsFlyFrm() );
+
+ if( !pFrm ) // ist kein FlyFrame
+ return FALSE;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // springe in den BodyFrame, der am naechsten vom Fly liegt
+ SwRect aTmpRect( aCharRect );
+ if( !pFrm->Frm().IsInside( aTmpRect ))
+ aTmpRect = pFrm->Frm();
+ Point aPt( aTmpRect.Left(), aTmpRect.Top() +
+ ( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 );
+ aPt.X() = aPt.X() > (pFrm->Frm().Left() + (pFrm->Frm().SSize().Width() / 2 ))
+ ? pFrm->Frm().Right()
+ : pFrm->Frm().Left();
+
+ const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
+ const SwCntntFrm* pFndFrm = pPageFrm->GetCntntPos( aPt, FALSE, TRUE );
+ pFndFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+
+ BOOL bRet = !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ return bRet;
+}
+
+
+
+
diff --git a/sw/source/core/crsr/trvlreg.cxx b/sw/source/core/crsr/trvlreg.cxx
new file mode 100644
index 000000000000..bf6343e77bc0
--- /dev/null
+++ b/sw/source/core/crsr/trvlreg.cxx
@@ -0,0 +1,291 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <swcrsr.hxx>
+#include <docary.hxx>
+#include <fmtcntnt.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <pamtyp.hxx>
+#include <section.hxx>
+
+
+
+BOOL GotoPrevRegion( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ BOOL bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+ SwSectionNode* pNd = aIdx.GetNode().FindSectionNode();
+ if( pNd )
+ aIdx.Assign( *pNd, - 1 );
+
+ do {
+ while( aIdx.GetIndex() &&
+ 0 == ( pNd = aIdx.GetNode().StartOfSectionNode()->GetSectionNode()) )
+ aIdx--;
+
+ if( pNd ) // gibt einen weiteren SectionNode ?
+ {
+ if( pNd->GetSection().IsHiddenFlag() ||
+ ( !bInReadOnly &&
+ pNd->GetSection().IsProtectFlag() ))
+ {
+ // geschuetzte/versteckte ueberspringen wir
+ aIdx.Assign( *pNd, - 1 );
+ }
+ else if( fnPosRegion == fnMoveForward )
+ {
+ aIdx = *pNd;
+ SwCntntNode* pCNd = pNd->GetNodes().GoNextSection( &aIdx,
+ TRUE, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx--;
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ aIdx = *pNd->EndOfSectionNode();
+ SwCntntNode* pCNd = pNd->GetNodes().GoPrevSection( &aIdx,
+ TRUE, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx.Assign( *pNd, - 1 );
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ }
+
+ rCurCrsr.GetPoint()->nNode = aIdx;
+ return TRUE;
+ }
+ } while( pNd );
+ return FALSE;
+}
+
+
+BOOL GotoNextRegion( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ BOOL bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+ SwSectionNode* pNd = aIdx.GetNode().FindSectionNode();
+ if( pNd )
+ aIdx.Assign( *pNd->EndOfSectionNode(), - 1 );
+
+ ULONG nEndCount = aIdx.GetNode().GetNodes().Count()-1;
+ do {
+ while( aIdx.GetIndex() < nEndCount &&
+ 0 == ( pNd = aIdx.GetNode().GetSectionNode()) )
+ aIdx++;
+
+ if( pNd ) // gibt einen weiteren SectionNode ?
+ {
+ if( pNd->GetSection().IsHiddenFlag() ||
+ ( !bInReadOnly &&
+ pNd->GetSection().IsProtectFlag() ))
+ {
+ // geschuetzte/versteckte ueberspringen wir
+ aIdx.Assign( *pNd->EndOfSectionNode(), +1 );
+ }
+ else if( fnPosRegion == fnMoveForward )
+ {
+ aIdx = *pNd;
+ SwCntntNode* pCNd = pNd->GetNodes().GoNextSection( &aIdx,
+ TRUE, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx.Assign( *pNd->EndOfSectionNode(), +1 );
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ aIdx = *pNd->EndOfSectionNode();
+ SwCntntNode* pCNd = pNd->GetNodes().GoPrevSection( &aIdx,
+ TRUE, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx++;
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ }
+
+ rCurCrsr.GetPoint()->nNode = aIdx;
+ return TRUE;
+ }
+ } while( pNd );
+ return FALSE;
+}
+
+
+BOOL GotoCurrRegion( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ BOOL bInReadOnly )
+{
+ SwSectionNode* pNd = rCurCrsr.GetNode()->FindSectionNode();
+ if( !pNd )
+ return FALSE;
+
+ SwPosition* pPos = rCurCrsr.GetPoint();
+ BOOL bMoveBackward = fnPosRegion == fnMoveBackward;
+
+ SwCntntNode* pCNd;
+ if( bMoveBackward )
+ {
+ SwNodeIndex aIdx( *pNd->EndOfSectionNode() );
+ pCNd = pNd->GetNodes().GoPrevSection( &aIdx, TRUE, !bInReadOnly );
+ }
+ else
+ {
+ SwNodeIndex aIdx( *pNd );
+ pCNd = pNd->GetNodes().GoNextSection( &aIdx, TRUE, !bInReadOnly );
+ }
+
+ if( pCNd )
+ {
+ pPos->nNode = *pCNd;
+ xub_StrLen nTmpPos = bMoveBackward ? pCNd->Len() : 0;
+ pPos->nContent.Assign( pCNd, nTmpPos );
+ }
+ return 0 != pCNd;
+}
+
+
+BOOL GotoCurrRegionAndSkip( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ BOOL bInReadOnly )
+{
+ SwNode* pCurrNd = rCurCrsr.GetNode();
+ SwSectionNode* pNd = pCurrNd->FindSectionNode();
+ if( !pNd )
+ return FALSE;
+
+ SwPosition* pPos = rCurCrsr.GetPoint();
+ xub_StrLen nCurrCnt = pPos->nContent.GetIndex();
+ BOOL bMoveBackward = fnPosRegion == fnMoveBackward;
+
+ do {
+ SwCntntNode* pCNd;
+ if( bMoveBackward ) // ans Ende vom Bereich
+ {
+ SwNodeIndex aIdx( *pNd->EndOfSectionNode() );
+ pCNd = pNd->GetNodes().GoPrevSection( &aIdx, TRUE, !bInReadOnly );
+ if( !pCNd )
+ return FALSE;
+ pPos->nNode = aIdx;
+ }
+ else
+ {
+ SwNodeIndex aIdx( *pNd );
+ pCNd = pNd->GetNodes().GoNextSection( &aIdx, TRUE, !bInReadOnly );
+ if( !pCNd )
+ return FALSE;
+ pPos->nNode = aIdx;
+ }
+
+ xub_StrLen nTmpPos = bMoveBackward ? pCNd->Len() : 0;
+ pPos->nContent.Assign( pCNd, nTmpPos );
+
+ if( &pPos->nNode.GetNode() != pCurrNd ||
+ pPos->nContent.GetIndex() != nCurrCnt )
+ // es gab eine Veraenderung
+ return TRUE;
+
+ // dann versuche mal den "Parent" dieser Section
+ SwSection* pParent = pNd->GetSection().GetParent();
+ pNd = pParent ? pParent->GetFmt()->GetSectionNode() : 0;
+ } while( pNd );
+ return FALSE;
+}
+
+
+
+BOOL SwCursor::MoveRegion( SwWhichRegion fnWhichRegion, SwPosRegion fnPosRegion )
+{
+ SwCrsrSaveState aSaveState( *this );
+ return !dynamic_cast<SwTableCursor*>(this) &&
+ (*fnWhichRegion)( *this, fnPosRegion, IsReadOnlyAvailable() ) &&
+ !IsSelOvr() &&
+ ( GetPoint()->nNode.GetIndex() != pSavePos->nNode ||
+ GetPoint()->nContent.GetIndex() != pSavePos->nCntnt );
+}
+
+BOOL SwCrsrShell::MoveRegion( SwWhichRegion fnWhichRegion, SwPosRegion fnPosRegion )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ BOOL bRet = !pTblCrsr && pCurCrsr->MoveRegion( fnWhichRegion, fnPosRegion );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+}
+
+
+BOOL SwCursor::GotoRegion( const String& rName )
+{
+ BOOL bRet = FALSE;
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( USHORT n = rFmts.Count(); n; )
+ {
+ const SwSectionFmt* pFmt = rFmts[ --n ];
+ const SwNodeIndex* pIdx;
+ const SwSection* pSect;
+ if( 0 != ( pSect = pFmt->GetSection() ) &&
+ pSect->GetSectionName() == rName &&
+ 0 != ( pIdx = pFmt->GetCntnt().GetCntntIdx() ) &&
+ pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ // ein Bereich im normalen NodesArr
+ SwCrsrSaveState aSaveState( *this );
+
+ GetPoint()->nNode = *pIdx;
+ Move( fnMoveForward, fnGoCntnt );
+ bRet = !IsSelOvr();
+ }
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::GotoRegion( const String& rName )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ BOOL bRet = !pTblCrsr && pCurCrsr->GotoRegion( rName );
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY ); // und den akt. Updaten
+ return bRet;
+}
+
+
+
diff --git a/sw/source/core/crsr/trvltbl.cxx b/sw/source/core/crsr/trvltbl.cxx
new file mode 100644
index 000000000000..d9a887e61ad9
--- /dev/null
+++ b/sw/source/core/crsr/trvltbl.cxx
@@ -0,0 +1,931 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+#include <hintids.hxx>
+
+#include <vcl/svapp.hxx>
+#include <editeng/protitem.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <cntfrm.hxx>
+#include <editsh.hxx> //EndAllAction gibts nur an der EditShell
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <docary.hxx>
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <tabfrm.hxx>
+#include <ndtxt.hxx>
+#include <shellres.hxx>
+#include <cellatr.hxx>
+#include <cellfrm.hxx>
+#include <rowfrm.hxx>
+
+
+// setze Crsr in die naechsten/vorherigen Celle
+BOOL SwCrsrShell::GoNextCell( BOOL bAppendLine )
+{
+ BOOL bRet = FALSE;
+ const SwTableNode* pTblNd = 0;
+
+ if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
+ {
+ SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ bRet = TRUE;
+
+ // Check if we have to move the cursor to a covered cell before
+ // proceeding:
+ const SwNode* pTableBoxStartNode = pCrsr->GetNode()->FindTableBoxStartNode();
+ const SwTableBox* pTableBox = 0;
+
+ if ( pCrsr->GetCrsrRowSpanOffset() )
+ {
+ pTableBox = pTableBoxStartNode->GetTblBox();
+ if ( pTableBox->getRowSpan() > 1 )
+ {
+ if ( !pTblNd )
+ pTblNd = IsCrsrInTbl();
+ pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(),
+ (USHORT)(pTableBox->getRowSpan() + pCrsr->GetCrsrRowSpanOffset() ) );
+ pTableBoxStartNode = pTableBox->GetSttNd();
+ }
+ }
+
+ SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 );
+
+ // folgt nach dem EndNode der Cell ein weiterer StartNode, dann
+ // gibt es auch eine naechste Celle
+
+ if( !aCellStt.GetNode().IsStartNode() )
+ {
+ if( pCrsr->HasMark() || !bAppendLine )
+ bRet = FALSE;
+ else
+ {
+ // auf besonderen Wunsch: keine Line mehr vorhanden, dann
+ // mache doch eine neue:
+ if ( !pTableBox )
+ pTableBox = pTblNd->GetTable().GetTblBox(
+ pCrsr->GetPoint()->nNode.GetNode().
+ StartOfSectionIndex() );
+
+ ASSERT( pTableBox, "Box steht nicht in dieser Tabelle" );
+ SwSelBoxes aBoxes;
+
+ //Das Dokument veraendert sich evtl. ohne Action wuerden die Sichten
+ //nichts mitbekommen.
+ ((SwEditShell*)this)->StartAllAction();
+ bRet = pDoc->InsertRow( pTblNd->GetTable().
+ SelLineFromBox( pTableBox, aBoxes, FALSE ));
+ ((SwEditShell*)this)->EndAllAction();
+ }
+ }
+ if( bRet && 0 != ( bRet = pCrsr->GoNextCell() ))
+ UpdateCrsr(); // und den akt. Updaten
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::GoPrevCell()
+{
+ BOOL bRet = FALSE;
+ const SwTableNode* pTblNd;
+ if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
+ {
+ SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ bRet = pCrsr->GoPrevCell();
+ if( bRet )
+ UpdateCrsr(); // und den akt. Updaten
+ }
+ return bRet;
+}
+
+const SwFrm* lcl_FindMostUpperCellFrm( const SwFrm* pFrm )
+{
+ while ( pFrm &&
+ ( !pFrm->IsCellFrm() ||
+ !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
+ pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
+ {
+ pFrm = pFrm->GetUpper();
+ }
+ return pFrm;
+}
+
+BOOL SwCrsrShell::_SelTblRowOrCol( bool bRow, bool bRowSimple )
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm->IsInTab() )
+ return FALSE;
+
+ const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
+ const SwTabFrm* pMasterTabFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
+ const SwTable* pTable = pTabFrm->GetTable();
+
+ SET_CURR_SHELL( this );
+
+ const SwTableBox* pStt = 0;
+ const SwTableBox* pEnd = 0;
+
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ SwTblSearchType eType = bRow ? nsSwTblSearchType::TBLSEARCH_ROW : nsSwTblSearchType::TBLSEARCH_COL;
+ const bool bCheckProtected = !IsReadOnlyAvailable();
+
+ if( bCheckProtected )
+ eType = (SwTblSearchType)(eType | nsSwTblSearchType::TBLSEARCH_PROTECT);
+
+ if ( !bRowSimple )
+ {
+ GetTblSel( *this, aBoxes, eType );
+
+ if( !aBoxes.Count() )
+ return FALSE;
+
+ pStt = aBoxes[0];
+ pEnd = aBoxes[aBoxes.Count() - 1];
+ }
+ // --> FME 2004-07-30 #i32329# Enhanced table selection
+ else if ( pTable->IsNewModel() )
+ {
+ const SwShellCrsr *pCrsr = _GetCrsr();
+ SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL;
+ pTable->CreateSelection( *pCrsr, aBoxes, eSearchType, bCheckProtected );
+ if( !aBoxes.Count() )
+ return FALSE;
+
+ pStt = aBoxes[0];
+ pEnd = aBoxes[aBoxes.Count() - 1];
+ }
+ else
+ {
+ const SwShellCrsr *pCrsr = _GetCrsr();
+ const SwFrm* pStartFrm = pFrm;
+ const SwCntntNode *pCNd = pCrsr->GetCntntNode( FALSE );
+ const SwFrm* pEndFrm = pCNd ? pCNd->GetFrm( &pCrsr->GetMkPos() ) : 0;
+
+ if ( bRow )
+ {
+ pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm );
+ pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm );
+ }
+
+ if ( !pStartFrm || !pEndFrm )
+ return FALSE;
+
+ const bool bVert = pFrm->ImplFindTabFrm()->IsVertical();
+
+ // If we select upwards it is sufficient to set pStt and pEnd
+ // to the first resp. last box of the selection obtained from
+ // GetTblSel. However, selecting downwards requires the frames
+ // located at the corners of the selection. This does not work
+ // for column selections in vertical tables:
+ const bool bSelectUp = ( bVert && !bRow ) ||
+ *pCrsr->GetPoint() <= *pCrsr->GetMark();
+ SwCellFrms aCells;
+ GetTblSel( static_cast<const SwCellFrm*>(pStartFrm),
+ static_cast<const SwCellFrm*>(pEndFrm),
+ aBoxes, bSelectUp ? 0 : &aCells, eType );
+
+ if( !aBoxes.Count() || ( !bSelectUp && 4 != aCells.Count() ) )
+ return FALSE;
+
+ if ( bSelectUp )
+ {
+ pStt = aBoxes[0];
+ pEnd = aBoxes[aBoxes.Count() - 1];
+ }
+ else
+ {
+ pStt = aCells[ bVert ? (bRow ? 0 : 3) : (bRow ? 2 : 1) ]->GetTabBox(); // will become point of table cursor
+ pEnd = aCells[ bVert ? (bRow ? 3 : 0) : (bRow ? 1 : 2) ]->GetTabBox(); // will become mark of table cursor
+ }
+ }
+ // <--
+
+ // noch kein Tabellen-Cursor vorhanden, dann erzeuge einen
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ }
+
+ pTblCrsr->DeleteMark();
+
+ // dann setze mal Anfang und Ende der Spalte
+ pTblCrsr->GetPoint()->nNode = *pEnd->GetSttNd();
+ pTblCrsr->Move( fnMoveForward, fnGoCntnt );
+ pTblCrsr->SetMark();
+ pTblCrsr->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode();
+ pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
+
+ // set PtPos 'close' to the reference table, otherwise we might get problems with the
+ // repeated headlines check in UpdateCrsr():
+ if ( !bRow )
+ pTblCrsr->GetPtPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
+
+ UpdateCrsr(); // und den akt. Updaten
+ return TRUE;
+}
+
+BOOL SwCrsrShell::SelTbl()
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm->IsInTab() )
+ return FALSE;
+
+ const SwTabFrm *pTblFrm = pFrm->ImplFindTabFrm();
+ const SwTabFrm* pMasterTabFrm = pTblFrm->IsFollow() ? pTblFrm->FindMaster( true ) : pTblFrm;
+ const SwTableNode* pTblNd = pTblFrm->GetTable()->GetTableNode();
+
+ SET_CURR_SHELL( this );
+
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ }
+
+ pTblCrsr->DeleteMark();
+ pTblCrsr->GetPoint()->nNode = *pTblNd;
+ pTblCrsr->Move( fnMoveForward, fnGoCntnt );
+ pTblCrsr->SetMark();
+ // set MkPos 'close' to the master table, otherwise we might get problems with the
+ // repeated headlines check in UpdateCrsr():
+ pTblCrsr->GetMkPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
+ pTblCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
+ UpdateCrsr(); // und den akt. Updaten
+ return TRUE;
+}
+
+
+BOOL SwCrsrShell::SelTblBox()
+{
+ // if we're in a table, create a table cursor, and select the cell
+ // that the current cursor's point resides in
+
+ // search for start node of our table box. If not found, exit realy
+ const SwStartNode* pStartNode =
+ pCurCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+
+#ifdef DBG_UTIL
+ // the old code checks whether we're in a table by asking the
+ // frame. This should yield the same result as searching for the
+ // table box start node, right?
+ SwFrm *pFrm = GetCurrFrm();
+ DBG_ASSERT( !pFrm->IsInTab() == !(pStartNode != NULL),
+ "Schroedinger's table: We're in a box, and also we aren't." );
+#endif
+
+ if( pStartNode == NULL )
+ return FALSE;
+
+
+ SET_CURR_SHELL( this );
+
+ // create a table cursor, if there isn't one already
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ }
+
+ // select the complete box with our shiny new pTblCrsr
+ // 1. delete mark, and move point to first content node in box
+ // 2. set mark, and move point to last content node in box
+ // 3. exchange
+
+ pTblCrsr->DeleteMark();
+ *(pTblCrsr->GetPoint()) = SwPosition( *pStartNode );
+ pTblCrsr->Move( fnMoveForward, fnGoNode );
+
+ pTblCrsr->SetMark();
+ *(pTblCrsr->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) );
+ pTblCrsr->Move( fnMoveBackward, fnGoNode );
+
+ pTblCrsr->Exchange();
+
+ // with some luck, UpdateCrsr() will now update everything that
+ // needs updateing
+ UpdateCrsr();
+
+ return TRUE;
+}
+
+// return the next non-protected cell inside a table
+// rIdx - is on a table node
+// return:
+// true - Idx points to content in a suitable cell
+// false - could not find a suitable cell
+bool lcl_FindNextCell( SwNodeIndex& rIdx, BOOL bInReadOnly )
+{
+ // ueberpruefe geschuetzte Zellen
+ SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
+
+ // the resulting cell should be in that table:
+ const SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
+
+ if ( !pTblNd )
+ {
+ ASSERT( false, "lcl_FindNextCell not celled with table start node!" )
+ return false;
+ }
+
+ const SwNode* pTableEndNode = pTblNd->EndOfSectionNode();
+
+ SwNodes& rNds = aTmp.GetNode().GetNodes();
+ SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
+
+ // no content node => go to next content node
+ if( !pCNd )
+ pCNd = rNds.GoNext( &aTmp );
+
+ // robust
+ if ( !pCNd )
+ return false;
+
+ SwCntntFrm* pFrm = pCNd->GetFrm();
+
+ if ( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
+ (!bInReadOnly && pFrm->IsProtected() ) )
+ {
+ // we are not located inside a 'valid' cell. We have to continue searching...
+
+ // skip behind current section. This might be the end of the table cell
+ // or behind a inner section or or or...
+ aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
+
+ // loop to find a suitable cell...
+ for( ;; )
+ {
+ SwNode* pNd = &aTmp.GetNode();
+
+ // we break this loop if we reached the end of the table.
+ // to make this code even more robust, we also break if we are
+ // already behind the table end node:
+ if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() )
+ return false;
+
+ // ok, get the next content node:
+ pCNd = aTmp.GetNode().GetCntntNode();
+ if( 0 == pCNd )
+ pCNd = rNds.GoNext( &aTmp );
+
+ // robust:
+ if ( !pCNd )
+ return false;
+
+ // check if we have found a suitable table cell:
+ pFrm = pCNd->GetFrm();
+
+ if ( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
+ (bInReadOnly || !pFrm->IsProtected() ) )
+ {
+ // finally, we have found a suitable table cell => set index and return
+ rIdx = *pCNd;
+ return true;
+ }
+
+ // continue behind the current section:
+ aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
+ }
+ }
+
+ rIdx = *pCNd;
+ return true;
+}
+
+// comments see lcl_FindNextCell
+bool lcl_FindPrevCell( SwNodeIndex& rIdx, BOOL bInReadOnly )
+{
+ SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode
+
+ const SwNode* pTableEndNode = &rIdx.GetNode();
+ const SwTableNode* pTblNd = pTableEndNode->StartOfSectionNode()->GetTableNode();
+
+ if ( !pTblNd )
+ {
+ ASSERT( false, "lcl_FindPrevCell not celled with table start node!" )
+ return false;
+ }
+
+ SwNodes& rNds = aTmp.GetNode().GetNodes();
+ SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
+
+ if( !pCNd )
+ pCNd = rNds.GoPrevious( &aTmp );
+
+ if ( !pCNd )
+ return false;
+
+ SwCntntFrm* pFrm = pCNd->GetFrm();
+
+ if( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
+ (!bInReadOnly && pFrm->IsProtected() ))
+ {
+ // skip before current section
+ aTmp.Assign( *pCNd->StartOfSectionNode(), -1 );
+ for( ;; )
+ {
+ SwNode* pNd = &aTmp.GetNode();
+
+ if( pNd == pTblNd || pNd->GetIndex() < pTblNd->GetIndex() )
+ return false;
+
+ pCNd = aTmp.GetNode().GetCntntNode();
+ if( 0 == pCNd )
+ pCNd = rNds.GoPrevious( &aTmp );
+
+ if ( !pCNd )
+ return false;
+
+ pFrm = pCNd->GetFrm();
+
+ if( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
+ (bInReadOnly || !pFrm->IsProtected() ) )
+ {
+ rIdx = *pCNd;
+ return true; // Ok, nicht geschuetzt
+ }
+ aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 );
+ }
+ }
+
+ rIdx = *pCNd;
+ return true;
+}
+
+
+BOOL GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
+ BOOL bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+
+ SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ // #i26532#: If we are inside a table, we may not go backward
+ // to the table start node, because we would miss any tables
+ // inside this table.
+ SwTableNode* pInnerTblNd = 0;
+ SwNodeIndex aTmpIdx( aIdx );
+ while( aTmpIdx.GetIndex() &&
+ 0 == ( pInnerTblNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
+ aTmpIdx--;
+
+ if( pInnerTblNd == pTblNd )
+ aIdx.Assign( *pTblNd, - 1 );
+ }
+
+ do {
+ while( aIdx.GetIndex() &&
+ 0 == ( pTblNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
+ aIdx--;
+
+ if( pTblNd ) // gibt einen weiteren TableNode ?
+ {
+ if( fnPosTbl == fnMoveForward ) // an Anfang ?
+ {
+ aIdx = *aIdx.GetNode().StartOfSectionNode();
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd, -1 );
+ continue;
+ }
+ }
+ else
+ {
+ // ueberpruefe geschuetzte Zellen
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd, -1 );
+ continue;
+ }
+ }
+
+ SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
+ if ( pTxtNode )
+ {
+ rCurCrsr.GetPoint()->nNode = *pTxtNode;
+ rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
+ pTxtNode->Len() :
+ 0 );
+ }
+ return TRUE;
+ }
+ } while( pTblNd );
+
+ return FALSE;
+}
+
+
+BOOL GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
+ BOOL bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+ SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
+
+ if( pTblNd )
+ aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 );
+
+ ULONG nLastNd = rCurCrsr.GetDoc()->GetNodes().Count() - 1;
+ do {
+ while( aIdx.GetIndex() < nLastNd &&
+ 0 == ( pTblNd = aIdx.GetNode().GetTableNode()) )
+ aIdx++;
+ if( pTblNd ) // gibt einen weiteren TableNode ?
+ {
+ if( fnPosTbl == fnMoveForward ) // an Anfang ?
+ {
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
+ continue;
+ }
+ }
+ else
+ {
+ aIdx = *aIdx.GetNode().EndOfSectionNode();
+ // ueberpruefe geschuetzte Zellen
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
+ continue;
+ }
+ }
+
+ SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
+ if ( pTxtNode )
+ {
+ rCurCrsr.GetPoint()->nNode = *pTxtNode;
+ rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
+ pTxtNode->Len() :
+ 0 );
+ }
+ return TRUE;
+ }
+ } while( pTblNd );
+
+ return FALSE;
+}
+
+
+BOOL GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
+ BOOL bInReadOnly )
+{
+ SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode();
+ if( !pTblNd )
+ return FALSE;
+
+ SwTxtNode* pTxtNode = 0;
+ if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle
+ {
+ SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() );
+ if( !lcl_FindPrevCell( aIdx, bInReadOnly ))
+ return FALSE;
+ pTxtNode = aIdx.GetNode().GetTxtNode();
+ }
+ else
+ {
+ SwNodeIndex aIdx( *pTblNd );
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ return FALSE;
+ pTxtNode = aIdx.GetNode().GetTxtNode();
+ }
+
+ if ( pTxtNode )
+ {
+ rCurCrsr.GetPoint()->nNode = *pTxtNode;
+ rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
+ pTxtNode->Len() :
+ 0 );
+ }
+
+ return TRUE;
+}
+
+
+BOOL SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
+{
+ BOOL bRet = FALSE;
+ SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
+
+ if( pTblCrsr || !HasMark() ) // nur wenn kein Mark oder ein TblCrsr
+ {
+ SwCrsrSaveState aSaveState( *this );
+ bRet = (*fnWhichTbl)( *this, fnPosTbl, IsReadOnlyAvailable() ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ }
+ return bRet;
+}
+
+BOOL SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ BOOL bCheckPos, bRet;
+ ULONG nPtNd = 0;
+ xub_StrLen nPtCnt = 0;
+
+ if( !pTblCrsr && pCurCrsr->HasMark() ) // wenn Mark und kein TblCrsr,
+ {
+ // dann auf jedenfall in den Tabellen-Modus schalten
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ pTblCrsr->SetMark();
+ pCrsr = pTblCrsr;
+ bCheckPos = FALSE;
+ }
+ else
+ {
+ bCheckPos = TRUE;
+ nPtNd = pCrsr->GetPoint()->nNode.GetIndex();
+ nPtCnt = pCrsr->GetPoint()->nContent.GetIndex();
+ }
+
+ bRet = pCrsr->MoveTable( fnWhichTbl, fnPosTbl );
+
+ if( bRet )
+ {
+ //JP 28.10.97: Bug 45028 - die "oberste" Position setzen fuer
+ // wiederholte Kopfzeilen
+ pCrsr->GetPtPos() = Point();
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+
+ if( bCheckPos &&
+ pCrsr->GetPoint()->nNode.GetIndex() == nPtNd &&
+ pCrsr->GetPoint()->nContent.GetIndex() == nPtCnt )
+ bRet = FALSE;
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::IsTblComplex() const
+{
+ SwFrm *pFrm = GetCurrFrm( FALSE );
+ if ( pFrm && pFrm->IsInTab() )
+ return pFrm->FindTabFrm()->GetTable()->IsTblComplex();
+ return FALSE;
+}
+
+
+BOOL SwCrsrShell::IsTblComplexForChart()
+{
+ BOOL bRet = FALSE;
+
+ StartAction(); // IsTblComplexForChart() may trigger table formatting
+ // we better do that inside an action
+
+ const SwTableNode* pTNd = pCurCrsr->GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTNd )
+ {
+ // wir stehen in der Tabelle, dann teste mal, ob die Tabelle oder die
+ // Selektion ausgeglichen ist.
+ String sSel;
+ if( pTblCrsr )
+ sSel = GetBoxNms();
+ bRet = pTNd->GetTable().IsTblComplexForChart( sSel );
+ }
+
+ EndAction();
+
+ return bRet;
+}
+
+String SwCrsrShell::GetBoxNms() const
+{
+ String sNm;
+ const SwPosition* pPos;
+ SwFrm* pFrm;
+
+ if( IsTableMode() )
+ {
+ SwCntntNode *pCNd = pTblCrsr->Start()->nNode.GetNode().GetCntntNode();
+ pFrm = pCNd ? pCNd->GetFrm() : 0;
+ if( !pFrm )
+ return sNm;
+
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+
+ ASSERT( pFrm, "kein Frame zur Box" );
+ sNm = ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
+ sNm += ':';
+ pPos = pTblCrsr->End();
+ }
+ else
+ {
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+ if( !pTblNd )
+ return sNm;
+ pPos = GetCrsr()->GetPoint();
+ }
+
+ SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode();
+ pFrm = pCNd ? pCNd->GetFrm() : 0;
+
+ if( pFrm )
+ {
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+
+ if( pFrm )
+ sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
+ }
+ return sNm;
+}
+
+
+BOOL SwCrsrShell::GotoTable( const String& rName )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ BOOL bRet = !pTblCrsr && pCurCrsr->GotoTable( rName );
+ if( bRet )
+ {
+ pCurCrsr->GetPtPos() = Point();
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY ); // und den akt. Updaten
+ }
+ return bRet;
+}
+
+
+BOOL SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos )
+{
+ if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() )
+ return FALSE;
+
+ // ueberpruefe, ob der Box Inhalt mit dem angegebenen Format der Box
+ // ueber einstimmt. Wenn nicht, setze neu
+ SwTableBox* pChkBox = 0;
+ SwStartNode* pSttNd = 0;
+ if( !pPos )
+ {
+ // gesicherte Position heraus holen.
+ if( pBoxIdx && pBoxPtr &&
+ 0 != ( pSttNd = pBoxIdx->GetNode().GetStartNode() ) &&
+ SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
+ pBoxPtr == pSttNd->FindTableNode()->GetTable().
+ GetTblBox( pBoxIdx->GetIndex() ) )
+ pChkBox = pBoxPtr;
+ }
+ else if( 0 != ( pSttNd = pPos->nNode.GetNode().
+ FindSttNodeByType( SwTableBoxStartNode )) )
+ {
+ pChkBox = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
+ }
+
+
+ // Box mehr als 1 Absatz?
+ if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() )
+ pChkBox = 0;
+
+ // jetzt sollten wir mal die Pointer zerstoeren, bevor eine erneute
+ // Actionklammerung kommt.
+ if( !pPos && !pChkBox )
+ ClearTblBoxCntnt();
+
+ // liegt der Cursor nicht mehr in dem Bereich ?
+ if( pChkBox && !pPos &&
+ ( pCurCrsr->HasMark() || pCurCrsr->GetNext() != pCurCrsr ||
+ pSttNd->GetIndex() + 1 == pCurCrsr->GetPoint()->nNode.GetIndex() ))
+ pChkBox = 0;
+
+ //JP 12.01.99: hat sich der Inhalt der Box ueberhaupt veraendert?
+ // Ist wichtig, wenn z.B. Undo nicht den richtigen Inhalt wieder
+ // herstellen konnte.
+ if( pChkBox )
+ {
+ const SwTxtNode* pNd = GetDoc()->GetNodes()[
+ pSttNd->GetIndex() + 1 ]->GetTxtNode();
+ if( !pNd ||
+ ( pNd->GetTxt() == ViewShell::GetShellRes()->aCalc_Error &&
+ SFX_ITEM_SET == pChkBox->GetFrmFmt()->
+ GetItemState( RES_BOXATR_FORMULA )) )
+ pChkBox = 0;
+ }
+
+ if( pChkBox )
+ {
+ // jetzt sollten wir mal die Pointer zerstoeren, bevor ein weiterer
+ // aufruf kommt.
+ ClearTblBoxCntnt();
+ StartAction();
+ GetDoc()->ChkBoxNumFmt( *pChkBox, TRUE );
+ EndAction();
+ }
+
+ return 0 != pChkBox;
+}
+
+
+void SwCrsrShell::SaveTblBoxCntnt( const SwPosition* pPos )
+{
+ if( IsSelTblCells() || !IsAutoUpdateCells() )
+ return ;
+
+ if( !pPos )
+ pPos = pCurCrsr->GetPoint();
+
+ SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode );
+
+ BOOL bCheckBox = FALSE;
+ if( pSttNd && pBoxIdx )
+ {
+ if( pSttNd == &pBoxIdx->GetNode() )
+ pSttNd = 0; // die haben wir schon
+ else
+ bCheckBox = TRUE;
+ }
+ else
+ bCheckBox = 0 != pBoxIdx;
+
+ if( bCheckBox )
+ {
+ // pBoxIdx Checken
+ SwPosition aPos( *pBoxIdx );
+ CheckTblBoxCntnt( &aPos );
+ }
+
+ if( pSttNd )
+ {
+ pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
+
+ if( pBoxIdx )
+ *pBoxIdx = *pSttNd;
+ else
+ pBoxIdx = new SwNodeIndex( *pSttNd );
+ }
+}
+
+
+void SwCrsrShell::ClearTblBoxCntnt()
+{
+ delete pBoxIdx, pBoxIdx = 0;
+ pBoxPtr = 0;
+}
+
+BOOL SwCrsrShell::EndAllTblBoxEdit()
+{
+ BOOL bRet = FALSE;
+ ViewShell *pSh = this;
+ do {
+ if( pSh->IsA( TYPE( SwCrsrShell ) ) )
+ bRet |= ((SwCrsrShell*)pSh)->CheckTblBoxCntnt(
+ ((SwCrsrShell*)pSh)->pCurCrsr->GetPoint() );
+
+ } while( this != (pSh = (ViewShell *)pSh->GetNext()) );
+ return bRet;
+}
+
+
+
+
diff --git a/sw/source/core/crsr/unocrsr.cxx b/sw/source/core/crsr/unocrsr.cxx
new file mode 100644
index 000000000000..a4e0d6f79785
--- /dev/null
+++ b/sw/source/core/crsr/unocrsr.cxx
@@ -0,0 +1,280 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#include <unocrsr.hxx>
+#include <doc.hxx>
+#include <swtable.hxx>
+#include <docary.hxx>
+#include <rootfrm.hxx>
+
+SV_IMPL_PTRARR( SwUnoCrsrTbl, SwUnoCrsrPtr )
+
+IMPL_FIXEDMEMPOOL_NEWDEL( SwUnoCrsr, 10, 10 )
+
+SwUnoCrsr::SwUnoCrsr( const SwPosition &rPos, SwPaM* pRing )
+ : SwCursor( rPos, pRing, false ), SwModify( 0 ),
+ bRemainInSection( TRUE ),
+ bSkipOverHiddenSections( FALSE ),
+ bSkipOverProtectSections( FALSE )
+
+{}
+
+// @@@ semantic: no copy ctor.
+SwUnoCrsr::SwUnoCrsr( SwUnoCrsr& rICrsr )
+ : SwCursor( rICrsr ), SwModify( 0 ),
+ bRemainInSection( rICrsr.bRemainInSection ),
+ bSkipOverHiddenSections( rICrsr.bSkipOverHiddenSections ),
+ bSkipOverProtectSections( rICrsr.bSkipOverProtectSections )
+{}
+
+SwUnoCrsr::~SwUnoCrsr()
+{
+ SwDoc* pDoc = GetDoc();
+ if( !pDoc->IsInDtor() )
+ {
+ // dann muss der Cursor aus dem Array ausgetragen werden
+ SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
+ USHORT nDelPos = rTbl.GetPos( this );
+
+ if( USHRT_MAX != nDelPos )
+ rTbl.Remove( nDelPos );
+ else {
+ ASSERT( !this, "UNO Cursor nicht mehr im Array" );
+ }
+ }
+
+ // den gesamten Ring loeschen!
+ while( GetNext() != this )
+ {
+ Ring* pNxt = GetNext();
+ pNxt->MoveTo( 0 ); // ausketten
+ delete pNxt; // und loeschen
+ }
+}
+
+SwUnoCrsr * SwUnoCrsr::Clone() const
+{
+ SwUnoCrsr * pNewCrsr = GetDoc()->CreateUnoCrsr( *GetPoint() );
+ if (HasMark())
+ {
+ pNewCrsr->SetMark();
+ *pNewCrsr->GetMark() = *GetMark();
+ }
+ return pNewCrsr;
+}
+
+SwUnoTableCrsr * SwUnoTableCrsr::Clone() const
+{
+ SwUnoTableCrsr * pNewCrsr = dynamic_cast<SwUnoTableCrsr*>(
+ GetDoc()->CreateUnoCrsr(
+ *GetPoint(), sal_True /* create SwUnoTableCrsr */ ) );
+ OSL_ENSURE(pNewCrsr, "Clone: cannot create SwUnoTableCrsr?");
+ if (HasMark())
+ {
+ pNewCrsr->SetMark();
+ *pNewCrsr->GetMark() = *GetMark();
+ }
+ return pNewCrsr;
+}
+
+
+bool SwUnoCrsr::IsReadOnlyAvailable() const
+{
+ return true;
+}
+
+const SwCntntFrm*
+SwUnoCrsr::DoSetBidiLevelLeftRight( BOOL &, BOOL, BOOL )
+{
+ return 0; // not for uno cursor
+}
+
+void SwUnoCrsr::DoSetBidiLevelUpDown()
+{
+ return; // not for uno cursor
+}
+
+BOOL SwUnoCrsr::IsSelOvr( int eFlags )
+{
+ if( bRemainInSection )
+ {
+ SwDoc* pDoc = GetDoc();
+ SwNodeIndex aOldIdx( *pDoc->GetNodes()[ GetSavePos()->nNode ] );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ SwStartNode *pOldSttNd = aOldIdx.GetNode().StartOfSectionNode(),
+ *pNewSttNd = rPtIdx.GetNode().StartOfSectionNode();
+ if( pOldSttNd != pNewSttNd )
+ {
+ BOOL bMoveDown = GetSavePos()->nNode < rPtIdx.GetIndex();
+ BOOL bValidPos = FALSE;
+
+ // search the correct surrounded start node - which the index
+ // can't leave.
+ while( pOldSttNd->IsSectionNode() )
+ pOldSttNd = pOldSttNd->StartOfSectionNode();
+
+ // is the new index inside this surrounded section?
+ if( rPtIdx > *pOldSttNd &&
+ rPtIdx < pOldSttNd->EndOfSectionIndex() )
+ {
+ // check if it a valid move inside this section
+ // (only over SwSection's !)
+ const SwStartNode* pInvalidNode;
+ do {
+ pInvalidNode = 0;
+ pNewSttNd = rPtIdx.GetNode().StartOfSectionNode();
+
+ const SwStartNode *pSttNd = pNewSttNd, *pEndNd = pOldSttNd;
+ if( pSttNd->EndOfSectionIndex() >
+ pEndNd->EndOfSectionIndex() )
+ {
+ pEndNd = pNewSttNd;
+ pSttNd = pOldSttNd;
+ }
+
+ while( pSttNd->GetIndex() > pEndNd->GetIndex() )
+ {
+ if( !pSttNd->IsSectionNode() )
+ pInvalidNode = pSttNd;
+ pSttNd = pSttNd->StartOfSectionNode();
+ }
+ if( pInvalidNode )
+ {
+ if( bMoveDown )
+ {
+ rPtIdx.Assign( *pInvalidNode->EndOfSectionNode(), 1 );
+
+ if( !rPtIdx.GetNode().IsCntntNode() &&
+ ( !pDoc->GetNodes().GoNextSection( &rPtIdx ) ||
+ rPtIdx > pOldSttNd->EndOfSectionIndex() ) )
+ break;
+ }
+ else
+ {
+ rPtIdx.Assign( *pInvalidNode, -1 );
+
+ if( !rPtIdx.GetNode().IsCntntNode() &&
+ ( !pDoc->GetNodes().GoPrevSection( &rPtIdx ) ||
+ rPtIdx < *pOldSttNd ) )
+ break;
+ }
+ }
+ else
+ bValidPos = TRUE;
+ } while ( pInvalidNode );
+ }
+
+ if( bValidPos )
+ {
+ SwCntntNode* pCNd = GetCntntNode();
+ USHORT nCnt = 0;
+ if( pCNd && !bMoveDown )
+ nCnt = pCNd->Len();
+ GetPoint()->nContent.Assign( pCNd, nCnt );
+ }
+ else
+ {
+ rPtIdx = GetSavePos()->nNode;
+ GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
+ return TRUE;
+ }
+ }
+ }
+ return SwCursor::IsSelOvr( eFlags );
+}
+
+
+/* */
+
+SwUnoTableCrsr::SwUnoTableCrsr(const SwPosition& rPos)
+ : SwCursor(rPos,0,false), SwUnoCrsr(rPos), SwTableCursor(rPos), aTblSel(rPos,0,false)
+{
+ SetRemainInSection(FALSE);
+}
+
+SwUnoTableCrsr::~SwUnoTableCrsr()
+{
+ while( aTblSel.GetNext() != &aTblSel )
+ delete aTblSel.GetNext(); // und loeschen
+}
+
+
+/*
+SwCursor* SwUnoTableCrsr::Create( SwPaM* pRing ) const
+{
+ return SwUnoCrsr::Create( pRing );
+}
+*/
+
+BOOL SwUnoTableCrsr::IsSelOvr( int eFlags )
+{
+ BOOL bRet = SwUnoCrsr::IsSelOvr( eFlags );
+ if( !bRet )
+ {
+ const SwTableNode* pTNd = GetPoint()->nNode.GetNode().FindTableNode();
+ bRet = !(pTNd == GetDoc()->GetNodes()[ GetSavePos()->nNode ]->
+ FindTableNode() && (!HasMark() ||
+ pTNd == GetMark()->nNode.GetNode().FindTableNode() ));
+ }
+ return bRet;
+}
+
+void SwUnoTableCrsr::MakeBoxSels()
+{
+ const SwCntntNode* pCNd;
+ bool bMakeTblCrsrs = true;
+ if( GetPoint()->nNode.GetIndex() && GetMark()->nNode.GetIndex() &&
+ 0 != ( pCNd = GetCntntNode() ) && pCNd->GetFrm() &&
+ 0 != ( pCNd = GetCntntNode(FALSE) ) && pCNd->GetFrm() )
+ bMakeTblCrsrs = GetDoc()->GetRootFrm()->MakeTblCrsrs( *this );
+
+ if ( !bMakeTblCrsrs )
+ {
+ SwSelBoxes& rTmpBoxes = (SwSelBoxes&)GetBoxes();
+ USHORT nCount = 0;
+ while( nCount < rTmpBoxes.Count() )
+ DeleteBox( nCount );
+ }
+
+ if( IsChgd() )
+ {
+ SwTableCursor::MakeBoxSels( &aTblSel );
+ if( !GetBoxesCount() )
+ {
+ const SwTableBox* pBox;
+ const SwNode* pBoxNd = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwTableNode* pTblNd = pBoxNd ? pBoxNd->FindTableNode() : 0;
+ if( pTblNd && 0 != ( pBox = pTblNd->GetTable().GetTblBox( pBoxNd->GetIndex() )) )
+ InsertBox( *pBox );
+ }
+ }
+}
+
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
new file mode 100644
index 000000000000..214700c5e680
--- /dev/null
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -0,0 +1,1006 @@
+/*************************************************************************
+ *
+ * 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_sw.hxx"
+
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+
+#include <vcl/dialog.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/wrkwin.hxx>
+#include <viewopt.hxx>
+#include <frmtool.hxx>
+#include <viscrs.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <swtable.hxx>
+#include <viewimp.hxx>
+#include <dview.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <docary.hxx>
+#include <extinput.hxx>
+#include <ndtxt.hxx>
+#include <scriptinfo.hxx>
+#include <mdiexp.hxx> // GetSearchDialog
+#ifndef _COMCORE_HRC
+#include <comcore.hrc> // ResId fuer Abfrage wenn zu Search & Replaces
+#endif
+
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/sdr/overlay/overlayselection.hxx>
+
+extern void SwCalcPixStatics( OutputDevice *pOut );
+
+//Damit beim ShowCrsr nicht immer wieder die gleiche Size teuer ermittelt
+//werden muss, hier statische Member, die beim Wechsel des MapModes
+// angepasst werden
+
+long SwSelPaintRects::nPixPtX = 0;
+long SwSelPaintRects::nPixPtY = 0;
+MapMode* SwSelPaintRects::pMapMode = 0;
+
+
+#ifdef SHOW_BOOKMARKS
+// #include <IMark.hxx>
+//
+// class SwBookmarkRects : public SwSelPaintRects
+// {
+// virtual void Paint( const Rectangle& rRect );
+// virtual void FillRects();
+//
+// public:
+// SwBookmarkRects( const SwCrsrShell& rSh ) : SwSelPaintRects( rSh ) {}
+// };
+//
+// void SwBookmarkRects::Paint( const Rectangle& rRect )
+// {
+// Window* pWin = GetShell()->GetWin();
+//
+// RasterOp eOld( pWin->GetRasterOp() );
+// BOOL bLCol = pWin->IsLineColor();
+// Color aLCol( pWin->GetLineColor() );
+// BOOL bFCol = pWin->IsFillColor();
+// Color aFCol( pWin->GetFillColor() );
+//
+// pWin->SetRasterOp( ROP_XOR );
+// Color aCol( RGB_COLORDATA( 0xF0, 0xC8, 0xF0 ) ^ COL_WHITE );
+// pWin->SetFillColor( aCol );
+// pWin->SetLineColor( aCol );
+//
+// pWin->DrawRect( rRect );
+//
+// if( bLCol ) pWin->SetLineColor( aLCol ); else pWin->SetLineColor();
+// if( bFCol ) pWin->SetFillColor( aFCol ); else pWin->SetFillColor();
+// pWin->SetRasterOp( eOld );
+// }
+//
+// void SwBookmarkRects::FillRects()
+// {
+// SwRegionRects aReg( GetShell()->VisArea() );
+//
+// const SwBookmarks& rBkmkTbl = GetShell()->getIDocumentMarkAccess()->getBookmarks();
+// SwShellCrsr* pCrsr = 0;
+// for( USHORT n = 0; n < rBkmkTbl.Count(); ++n )
+// {
+// const SwBookmark& rBkmk = *rBkmkTbl[ n ];
+// if( rBkmk.IsBookMark() && rBkmk.GetOtherPos() )
+// {
+// if( !pCrsr )
+// {
+// pCrsr = new SwShellCrsr( *GetShell(), rBkmk.GetPos() );
+// pCrsr->SetMark();
+// }
+// else
+// *pCrsr->GetPoint() = rBkmk.GetPos();
+// *pCrsr->GetMark() = *rBkmk.GetOtherPos();
+// pCrsr->FillRects();
+// for( USHORT i = 0; i < pCrsr->Count(); ++i )
+// aReg -= (*pCrsr)[ i ];
+//
+// pCrsr->Remove( 0, i );
+// }
+// }
+// if( pCrsr ) delete pCrsr;
+//
+// aReg.Invert();
+// SwRects::Insert( &aReg, 0 );
+// }
+//
+// SwBookmarkRects* pBookMarkRects = 0;
+//
+// void ShowBookmarks( const SwCrsrShell* pSh, int nAction, const SwRect* pRect = 0 )
+// {
+// if( !pBookMarkRects && pSh->getIDocumentMarkAccess()->getBookmarks().Count() )
+// pBookMarkRects = new SwBookmarkRects( *pSh );
+//
+// if( pBookMarkRects )
+// {
+// switch( nAction )
+// {
+// case 1: pBookMarkRects->Show(); break;
+// case 2: pBookMarkRects->Hide(); break;
+// case 3: pBookMarkRects->Invalidate( *pRect ); break;
+// }
+//
+// if( !pBookMarkRects->Count() )
+// delete pBookMarkRects, pBookMarkRects = 0;
+// }
+// }
+//
+// #define SHOWBOOKMARKS1( nAct ) ShowBookmarks( GetShell(),nAct );
+// #define SHOWBOOKMARKS2( nAct, pRect ) ShowBookmarks( GetShell(),nAct, pRect );
+
+#else
+
+#define SHOWBOOKMARKS1( nAct )
+#define SHOWBOOKMARKS2( nAct, pRect )
+
+#endif
+
+#ifdef SHOW_REDLINES
+#include <redline.hxx>
+
+class SwRedlineRects : public SwSelPaintRects
+{
+ USHORT nMode;
+ USHORT nNm;
+
+ virtual void Paint( const Rectangle& rRect );
+ virtual void FillRects();
+
+public:
+ SwRedlineRects( const SwCrsrShell& rSh, USHORT nName, USHORT n )
+ : SwSelPaintRects( rSh ), nMode( n ), nNm( nName )
+ {}
+};
+
+void SwRedlineRects::Paint( const Rectangle& rRect )
+{
+ Window* pWin = GetShell()->GetWin();
+
+ RasterOp eOld( pWin->GetRasterOp() );
+ BOOL bLCol = pWin->IsLineColor();
+ Color aLCol( pWin->GetLineColor() );
+ BOOL bFCol = pWin->IsFillColor();
+ Color aFCol( pWin->GetFillColor() );
+
+ pWin->SetRasterOp( ROP_XOR );
+ Color aCol;
+
+ UINT8 nVal = 0xc8 - ( (nMode / 4) * 16 );
+ switch( nMode % 4 )
+ {
+ case 0: aCol = RGB_COLORDATA( nVal, nVal, 0xFF ); break;
+ case 1: aCol = RGB_COLORDATA( 0xFF, 0xc8, nVal ); break;
+ case 2: aCol = RGB_COLORDATA( nVal, 0xFF, nVal ); break;
+ case 3: aCol = RGB_COLORDATA( 0xFF, nVal, nVal ); break;
+ }
+ aCol = aCol.GetColor() ^ COL_WHITE;
+
+ pWin->SetFillColor( aCol );
+ pWin->SetLineColor( aCol );
+
+ pWin->DrawRect( rRect );
+
+ if( bLCol ) pWin->SetLineColor( aLCol ); else pWin->SetLineColor();
+ if( bFCol ) pWin->SetFillColor( aFCol ); else pWin->SetFillColor();
+ pWin->SetRasterOp( eOld );
+}
+
+void SwRedlineRects::FillRects()
+{
+ SwRegionRects aReg( GetShell()->VisArea() );
+
+ const SwRedlineTbl& rTbl = GetShell()->GetDoc()->GetRedlineTbl();
+ SwShellCrsr* pCrsr = 0;
+ for( USHORT n = 0; n < rTbl.Count(); ++n )
+ {
+ const SwRedline& rRed = *rTbl[ n ];
+ if( rRed.HasMark() && (nMode % 4 ) == rRed.GetType() &&
+ nNm == rRed.GetAuthor() )
+ {
+ if( !pCrsr )
+ {
+ pCrsr = new SwShellCrsr( *GetShell(), *rRed.GetPoint() );
+ pCrsr->SetMark();
+ }
+ else
+ *pCrsr->GetPoint() = *rRed.GetPoint();
+ *pCrsr->GetMark() = *rRed.GetMark();
+ pCrsr->FillRects();
+ for( USHORT i = 0; i < pCrsr->Count(); ++i )
+ aReg -= (*pCrsr)[ i ];
+
+ pCrsr->Remove( 0, i );
+ }
+ }
+ if( pCrsr ) delete pCrsr;
+
+ aReg.Invert();
+ SwRects::Insert( &aReg, 0 );
+}
+
+SwRedlineRects* aRedlines[ 10 * 4 ];
+static int bFirstCall = TRUE;
+
+void ShowRedlines( const SwCrsrShell* pSh, int nAction, const SwRect* pRect = 0 )
+{
+ if( bFirstCall )
+ {
+ memset( aRedlines, 0, sizeof(aRedlines));
+ bFirstCall = FALSE;
+ }
+
+ const SwRedlineTbl& rTbl = pSh->GetDoc()->GetRedlineTbl();
+ const SwRedlineAuthorTbl& rAuthorTbl = pSh->GetDoc()->GetRedlineAuthorTbl();
+
+ for( USHORT n = 0; n < rAuthorTbl.Count(); ++n )
+ {
+ for( int i = 0; i < 4; ++i )
+ {
+ SwRedlineRects** ppRedRect = &aRedlines[ n * 4 + i ];
+ if( rTbl.Count() && !*ppRedRect )
+ *ppRedRect = new SwRedlineRects( *pSh, n, n * 4 + i );
+
+ if( *ppRedRect )
+ {
+ switch( nAction )
+ {
+ case 1: (*ppRedRect)->Show(); break;
+ case 2: (*ppRedRect)->Hide(); break;
+ case 3: (*ppRedRect)->Invalidate( *pRect ); break;
+ }
+
+ if( !(*ppRedRect)->Count() )
+ delete *ppRedRect, *ppRedRect = 0;
+ }
+ }
+ }
+}
+
+#define SHOWREDLINES1( nAct ) ShowRedlines( GetShell(),nAct );
+#define SHOWREDLINES2( nAct, pRect ) ShowRedlines( GetShell(),nAct, pRect );
+
+#else
+
+#define SHOWREDLINES1( nAct )
+#define SHOWREDLINES2( nAct, pRect )
+
+#endif
+
+#ifdef JP_REDLINE
+ if( GetDoc()->GetRedlineTbl().Count() )
+ {
+ SwRedlineTbl& rRedlineTbl = (SwRedlineTbl&)GetDoc()->GetRedlineTbl();
+ for( USHORT i = 0; i < rRedlineTbl.Count(); ++i )
+ rRedlineTbl[ i ]->HideRects( *GetShell() );
+ }
+#endif
+
+// -------- Ab hier Klassen / Methoden fuer den nicht Text-Cursor ------
+
+SwVisCrsr::SwVisCrsr( const SwCrsrShell * pCShell )
+ : pCrsrShell( pCShell )
+{
+ pCShell->GetWin()->SetCursor( &aTxtCrsr );
+ bIsVisible = aTxtCrsr.IsVisible();
+ bIsDragCrsr = FALSE;
+ aTxtCrsr.SetWidth( 0 );
+
+#ifdef SW_CRSR_TIMER
+ bTimerOn = TRUE;
+ SetTimeout( 50 ); // 50msec Verzoegerung
+#endif
+}
+
+
+
+SwVisCrsr::~SwVisCrsr()
+{
+#ifdef SW_CRSR_TIMER
+ if( bTimerOn )
+ Stop(); // Timer stoppen
+#endif
+
+ if( bIsVisible && aTxtCrsr.IsVisible() )
+ aTxtCrsr.Hide();
+
+ pCrsrShell->GetWin()->SetCursor( 0 );
+}
+
+
+
+
+void SwVisCrsr::Show()
+{
+ if( !bIsVisible )
+ {
+ bIsVisible = TRUE;
+
+ // muss ueberhaupt angezeigt werden ?
+ if( pCrsrShell->VisArea().IsOver( pCrsrShell->aCharRect ) )
+#ifdef SW_CRSR_TIMER
+ {
+ if( bTimerOn )
+ Start(); // Timer aufsetzen
+ else
+ {
+ if( IsActive() )
+ Stop(); // Timer Stoppen
+
+ _SetPosAndShow();
+ }
+ }
+#else
+ _SetPosAndShow();
+#endif
+ }
+}
+
+
+
+void SwVisCrsr::Hide()
+{
+ if( bIsVisible )
+ {
+ bIsVisible = FALSE;
+
+#ifdef SW_CRSR_TIMER
+ if( IsActive() )
+ Stop(); // Timer Stoppen
+#endif
+
+ if( aTxtCrsr.IsVisible() ) // sollten die Flags nicht gueltig sein?
+ aTxtCrsr.Hide();
+ }
+}
+
+#ifdef SW_CRSR_TIMER
+
+void __EXPORT SwVisCrsr::Timeout()
+{
+ ASSERT( !bIsDragCrsr, "Timer vorher abschalten" );
+ if( bIsVisible )
+ {
+ if ( !pCrsrShell->GetWin() ) //SwFrmFmt::GetGraphic setzt das Win temp aus!
+ Start();
+ else
+ _SetPosAndShow();
+ }
+}
+
+BOOL SwCrsrShell::ChgCrsrTimerFlag( BOOL bTimerOn )
+{
+ return pVisCrsr->ChgTimerFlag( bTimerOn );
+}
+
+
+BOOL SwVisCrsr::ChgTimerFlag( BOOL bFlag )
+{
+ bOld = bTimerOn;
+ if( !bFlag && bIsVisible && IsActive() )
+ {
+ Stop(); // Timer Stoppen
+ _SetPosAndShow();
+ }
+ bTimerOn = bFlag;
+ return bOld;
+}
+
+#endif
+
+
+void SwVisCrsr::_SetPosAndShow()
+{
+ SwRect aRect;
+ long nTmpY = pCrsrShell->aCrsrHeight.Y();
+ if( 0 > nTmpY )
+ {
+ nTmpY = -nTmpY;
+ aTxtCrsr.SetOrientation( 900 );
+ aRect = SwRect( pCrsrShell->aCharRect.Pos(),
+ Size( pCrsrShell->aCharRect.Height(), nTmpY ) );
+ aRect.Pos().X() += pCrsrShell->aCrsrHeight.X();
+ if( pCrsrShell->IsOverwriteCrsr() )
+ aRect.Pos().Y() += aRect.Width();
+ }
+ else
+ {
+ aTxtCrsr.SetOrientation( 0 );
+ aRect = SwRect( pCrsrShell->aCharRect.Pos(),
+ Size( pCrsrShell->aCharRect.Width(), nTmpY ) );
+ aRect.Pos().Y() += pCrsrShell->aCrsrHeight.X();
+ }
+
+ // check if cursor should show the current cursor bidi level
+ aTxtCrsr.SetDirection( CURSOR_DIRECTION_NONE );
+ const SwCursor* pTmpCrsr = pCrsrShell->_GetCrsr();
+
+ if ( pTmpCrsr && !pCrsrShell->IsOverwriteCrsr() )
+ {
+ SwNode& rNode = pTmpCrsr->GetPoint()->nNode.GetNode();
+ if( rNode.IsTxtNode() )
+ {
+ const SwTxtNode& rTNd = *rNode.GetTxtNode();
+ const SwFrm* pFrm = rTNd.GetFrm( 0, 0, FALSE );
+ if ( pFrm )
+ {
+ const SwScriptInfo* pSI = ((SwTxtFrm*)pFrm)->GetScriptInfo();
+ // cursor level has to be shown
+ if ( pSI && pSI->CountDirChg() > 1 )
+ {
+ aTxtCrsr.SetDirection(
+ ( pTmpCrsr->GetCrsrBidiLevel() % 2 ) ?
+ CURSOR_DIRECTION_RTL :
+ CURSOR_DIRECTION_LTR );
+ }
+
+ if ( pFrm->IsRightToLeft() )
+ {
+ const OutputDevice *pOut = pCrsrShell->GetOut();
+ if ( pOut )
+ {
+ long nSize = pOut->GetSettings().GetStyleSettings().GetCursorSize();
+ Size aSize( nSize, nSize );
+ aSize = pOut->PixelToLogic( aSize );
+ aRect.Left( aRect.Left() - aSize.Width() );
+ }
+ }
+ }
+ }
+ }
+
+ if( aRect.Height() )
+ {
+ ::SwCalcPixStatics( pCrsrShell->GetOut() );
+ ::SwAlignRect( aRect, (ViewShell*)pCrsrShell );
+ }
+ if( !pCrsrShell->IsOverwriteCrsr() || bIsDragCrsr ||
+ pCrsrShell->IsSelection() )
+ aRect.Width( 0 );
+
+ aTxtCrsr.SetSize( aRect.SSize() );
+
+ aTxtCrsr.SetPos( aRect.Pos() );
+ if ( !pCrsrShell->IsCrsrReadonly() || pCrsrShell->GetViewOptions()->IsSelectionInReadonly() )
+ {
+ if ( pCrsrShell->GetDrawView() )
+ ((SwDrawView*)pCrsrShell->GetDrawView())->SetAnimationEnabled(
+ !pCrsrShell->IsSelection() );
+
+ USHORT nStyle = bIsDragCrsr ? CURSOR_SHADOW : 0;
+ if( nStyle != aTxtCrsr.GetStyle() )
+ {
+ aTxtCrsr.SetStyle( nStyle );
+ aTxtCrsr.SetWindow( bIsDragCrsr ? pCrsrShell->GetWin() : 0 );
+ }
+
+ aTxtCrsr.Show();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+SwSelPaintRects::SwSelPaintRects( const SwCrsrShell& rCSh )
+: SwRects( 0 ),
+ pCShell( &rCSh ),
+ mpCursorOverlay(0)
+{
+}
+
+SwSelPaintRects::~SwSelPaintRects()
+{
+ Hide();
+}
+
+void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap)
+{
+ SwRects aTempRects;
+ aTempRects.Insert(this, 0);
+
+ Remove(0, Count());
+ Insert(&rSwap, 0);
+
+ rSwap.Remove(0, rSwap.Count());
+ rSwap.Insert(&aTempRects, 0);
+
+ // #i75172# also swap mpCursorOverlay
+ sdr::overlay::OverlayObject* pTempOverlay = getCursorOverlay();
+ setCursorOverlay(rSwap.getCursorOverlay());
+ rSwap.setCursorOverlay(pTempOverlay);
+}
+
+void SwSelPaintRects::Hide()
+{
+ if(mpCursorOverlay)
+ {
+ delete mpCursorOverlay;
+ mpCursorOverlay = 0;
+ }
+
+ SwRects::Remove( 0, Count() );
+}
+
+void SwSelPaintRects::Show()
+{
+ SdrView* pView = (SdrView*)pCShell->GetDrawView();
+
+ if(pView && pView->PaintWindowCount())
+ {
+ // reset rects
+ SwRects::Remove( 0, SwRects::Count() );
+ FillRects();
+
+ // get new rects
+ std::vector< basegfx::B2DRange > aNewRanges;
+
+ for(sal_uInt16 a(0); a < Count(); a++)
+ {
+ const SwRect aNextRect((*this)[a]);
+ const Rectangle aPntRect(aNextRect.SVRect());
+
+ aNewRanges.push_back(basegfx::B2DRange(
+ aPntRect.Left(), aPntRect.Top(),
+ aPntRect.Right() + 1, aPntRect.Bottom() + 1));
+ }
+
+ if(mpCursorOverlay)
+ {
+ if(aNewRanges.size())
+ {
+ static_cast< sdr::overlay::OverlaySelection* >(mpCursorOverlay)->setRanges(aNewRanges);
+ }
+ else
+ {
+ delete mpCursorOverlay;
+ mpCursorOverlay = 0;
+ }
+ }
+ else if(Count())
+ {
+ SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
+ sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
+
+ if(pTargetOverlay)
+ {
+ // #i97672# get the system's hilight color and limit it to the maximum
+ // allowed luminance. This is needed to react on too bright hilight colors
+ // which would otherwise vive a bad visualisation
+ const OutputDevice *pOut = Application::GetDefaultDevice();
+ Color aHighlight(pOut->GetSettings().GetStyleSettings().GetHighlightColor());
+ const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
+ const basegfx::BColor aSelection(aHighlight.getBColor());
+ const double fLuminance(aSelection.luminance());
+ const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
+
+ if(fLuminance > fMaxLum)
+ {
+ const double fFactor(fMaxLum / fLuminance);
+ const basegfx::BColor aNewSelection(
+ aSelection.getRed() * fFactor,
+ aSelection.getGreen() * fFactor,
+ aSelection.getBlue() * fFactor);
+
+ aHighlight = Color(aNewSelection);
+ }
+
+ // create correct selection
+ mpCursorOverlay = new sdr::overlay::OverlaySelection(
+ sdr::overlay::OVERLAY_TRANSPARENT,
+ aHighlight,
+ aNewRanges,
+ true);
+
+ pTargetOverlay->add(*mpCursorOverlay);
+ }
+ }
+ }
+}
+
+void SwSelPaintRects::Invalidate( const SwRect& rRect )
+{
+ USHORT nSz = Count();
+ if( !nSz )
+ return;
+
+ SwRegionRects aReg( GetShell()->VisArea() );
+ aReg.Remove( 0, aReg.Count() );
+ aReg.Insert( this, 0 );
+ aReg -= rRect;
+ SwRects::Remove( 0, nSz );
+ SwRects::Insert( &aReg, 0 );
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // Liegt die Selection rechts oder unten ausserhalb des sichtbaren
+ // Bereiches, so ist diese nie auf eine Pixel rechts/unten aligned.
+ // Das muss hier erkannt und ggf. das Rechteckt erweitert werden.
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if( GetShell()->bVisPortChgd && 0 != ( nSz = Count()) )
+ {
+ SwSelPaintRects::Get1PixelInLogic( *GetShell() );
+ SwRect* pRect = (SwRect*)GetData();
+ for( ; nSz--; ++pRect )
+ {
+ if( pRect->Right() == GetShell()->aOldRBPos.X() )
+ pRect->Right( pRect->Right() + nPixPtX );
+ if( pRect->Bottom() == GetShell()->aOldRBPos.Y() )
+ pRect->Bottom( pRect->Bottom() + nPixPtY );
+ }
+ }
+}
+
+void SwSelPaintRects::Paint( const Rectangle& /*rRect*/ )
+{
+ // nothing to do with overlays
+}
+
+
+// check current MapMode of the shell and set possibly the static members.
+// Optional set the parameters pX, pY
+void SwSelPaintRects::Get1PixelInLogic( const ViewShell& rSh,
+ long* pX, long* pY )
+{
+ const OutputDevice* pOut = rSh.GetWin();
+ if ( ! pOut )
+ pOut = rSh.GetOut();
+
+ const MapMode& rMM = pOut->GetMapMode();
+ if( pMapMode->GetMapUnit() != rMM.GetMapUnit() ||
+ pMapMode->GetScaleX() != rMM.GetScaleX() ||
+ pMapMode->GetScaleY() != rMM.GetScaleY() )
+ {
+ *pMapMode = rMM;
+ Size aTmp( 1, 1 );
+ aTmp = pOut->PixelToLogic( aTmp );
+ nPixPtX = aTmp.Width();
+ nPixPtY = aTmp.Height();
+ }
+ if( pX )
+ *pX = nPixPtX;
+ if( pY )
+ *pY = nPixPtY;
+}
+
+
+/* */
+
+SwShellCrsr::SwShellCrsr( const SwCrsrShell& rCShell, const SwPosition &rPos )
+ : SwCursor(rPos,0,false), SwSelPaintRects(rCShell), pPt(SwPaM::GetPoint())
+{}
+
+
+SwShellCrsr::SwShellCrsr( const SwCrsrShell& rCShell, const SwPosition &rPos,
+ const Point& rPtPos, SwPaM* pRing )
+ : SwCursor(rPos, pRing, false), SwSelPaintRects(rCShell), aMkPt(rPtPos),
+ aPtPt(rPtPos), pPt(SwPaM::GetPoint())
+{}
+
+
+SwShellCrsr::SwShellCrsr( SwShellCrsr& rICrsr )
+ : SwCursor(rICrsr), SwSelPaintRects(*rICrsr.GetShell()),
+ aMkPt(rICrsr.GetMkPos()), aPtPt(rICrsr.GetPtPos()), pPt(SwPaM::GetPoint())
+{}
+
+SwShellCrsr::~SwShellCrsr() {}
+
+
+bool SwShellCrsr::IsReadOnlyAvailable() const
+{
+ return GetShell()->IsReadOnlyAvailable();
+}
+
+void SwShellCrsr::SetMark()
+{
+ if( SwPaM::GetPoint() == pPt )
+ aMkPt = aPtPt;
+ else
+ aPtPt = aMkPt;
+ SwPaM::SetMark();
+}
+
+void SwShellCrsr::FillRects()
+{
+ // die neuen Rechtecke berechnen
+ if( HasMark() &&
+ GetPoint()->nNode.GetNode().IsCntntNode() &&
+ GetPoint()->nNode.GetNode().GetCntntNode()->GetFrm() &&
+ (GetMark()->nNode == GetPoint()->nNode ||
+ (GetMark()->nNode.GetNode().IsCntntNode() &&
+ GetMark()->nNode.GetNode().GetCntntNode()->GetFrm() ) ))
+ GetDoc()->GetRootFrm()->CalcFrmRects( *this, GetShell()->IsTableMode() );
+}
+
+
+void SwShellCrsr::Show()
+{
+ SwShellCrsr * pTmp = this;
+ do {
+ pTmp->SwSelPaintRects::Show();
+ } while( this != ( pTmp = dynamic_cast<SwShellCrsr*>(pTmp->GetNext()) ) );
+
+ SHOWBOOKMARKS1( 1 )
+ SHOWREDLINES1( 1 )
+}
+
+
+ // Dieses Rechteck wird neu gepaintet, also ist die SSelection in
+ // dem Bereich ungueltig
+void SwShellCrsr::Invalidate( const SwRect& rRect )
+{
+ SwShellCrsr * pTmp = this;
+
+ do
+ {
+ pTmp->SwSelPaintRects::Invalidate( rRect );
+
+ // --> FME 2005-08-18 #125102#
+ // skip any non SwShellCrsr objects in the ring
+ // (see:SwAutoFormat::DeleteSel()
+ // <--
+ Ring* pTmpRing = pTmp;
+ pTmp = 0;
+ do
+ {
+ pTmpRing = pTmpRing->GetNext();
+ pTmp = dynamic_cast<SwShellCrsr*>(pTmpRing);
+ }
+ while ( !pTmp );
+ }
+ while( this != pTmp );
+
+ SHOWBOOKMARKS2( 3, &rRect )
+ SHOWREDLINES2( 3, &rRect )
+}
+
+
+void SwShellCrsr::Hide()
+{
+ SwShellCrsr * pTmp = this;
+ do {
+ pTmp->SwSelPaintRects::Hide();
+ } while( this != ( pTmp = dynamic_cast<SwShellCrsr*>(pTmp->GetNext()) ) );
+
+ SHOWBOOKMARKS1( 2 )
+ SHOWREDLINES1( 2 )
+}
+
+SwCursor* SwShellCrsr::Create( SwPaM* pRing ) const
+{
+ return new SwShellCrsr( *GetShell(), *GetPoint(), GetPtPos(), pRing );
+}
+
+
+short SwShellCrsr::MaxReplaceArived()
+{
+ short nRet = RET_YES;
+ Window* pDlg = LAYOUT_THIS_WINDOW (::GetSearchDialog());
+ if( pDlg )
+ {
+ // alte Actions beenden; die Tabellen-Frames werden angelegt und
+ // eine SSelection kann erzeugt werden
+ SvUShorts aArr;
+ USHORT nActCnt;
+ ViewShell *pShell = GetDoc()->GetRootFrm()->GetCurrShell(),
+ *pSh = pShell;
+ do {
+ for( nActCnt = 0; pSh->ActionPend(); ++nActCnt )
+ pSh->EndAction();
+ aArr.Insert( nActCnt, aArr.Count() );
+ } while( pShell != ( pSh = (ViewShell*)pSh->GetNext() ) );
+
+ {
+ nRet = QueryBox( pDlg, SW_RES( MSG_COMCORE_ASKSEARCH )).Execute();
+ }
+
+ for( USHORT n = 0; n < aArr.Count(); ++n )
+ {
+ for( nActCnt = aArr[n]; nActCnt--; )
+ pSh->StartAction();
+ pSh = (ViewShell*)pSh->GetNext();
+ }
+ }
+ else
+ // ansonsten aus dem Basic, und dann auf RET_YES schalten
+ nRet = RET_YES;
+
+ return nRet;
+}
+
+void SwShellCrsr::SaveTblBoxCntnt( const SwPosition* pPos )
+{
+ ((SwCrsrShell*)GetShell())->SaveTblBoxCntnt( pPos );
+}
+
+BOOL SwShellCrsr::UpDown( BOOL bUp, USHORT nCnt )
+{
+ return SwCursor::UpDown( bUp, nCnt,
+ &GetPtPos(), GetShell()->GetUpDownX() );
+}
+
+#ifdef DBG_UTIL
+
+// JP 05.03.98: zum Testen des UNO-Crsr Verhaltens hier die Implementierung
+// am sichtbaren Cursor
+
+BOOL SwShellCrsr::IsSelOvr( int eFlags )
+{
+ return SwCursor::IsSelOvr( eFlags );
+}
+
+#endif
+
+// TRUE: an die Position kann der Cursor gesetzt werden
+BOOL SwShellCrsr::IsAtValidPos( BOOL bPoint ) const
+{
+ if( GetShell() && ( GetShell()->IsAllProtect() ||
+ GetShell()->GetViewOptions()->IsReadonly() ||
+ ( GetShell()->Imp()->GetDrawView() &&
+ GetShell()->Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )))
+ return TRUE;
+
+ return SwCursor::IsAtValidPos( bPoint );
+}
+
+/* */
+
+SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
+ const SwPosition& rPos )
+ : SwCursor(rPos,0,false), SwShellCrsr(rCrsrSh, rPos), SwTableCursor(rPos)
+{
+}
+
+SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
+ const SwPosition& rMkPos, const Point& rMkPt,
+ const SwPosition& rPtPos, const Point& rPtPt )
+ : SwCursor(rPtPos,0,false), SwShellCrsr(rCrsrSh, rPtPos), SwTableCursor(rPtPos)
+{
+ SetMark();
+ *GetMark() = rMkPos;
+ GetMkPos() = rMkPt;
+ GetPtPos() = rPtPt;
+}
+
+SwShellTableCrsr::~SwShellTableCrsr() {}
+
+void SwShellTableCrsr::SetMark() { SwShellCrsr::SetMark(); }
+
+SwCursor* SwShellTableCrsr::Create( SwPaM* pRing ) const
+{
+ return SwShellCrsr::Create( pRing );
+}
+short SwShellTableCrsr::MaxReplaceArived()
+{
+ return SwShellCrsr::MaxReplaceArived();
+}
+void SwShellTableCrsr::SaveTblBoxCntnt( const SwPosition* pPos )
+{
+ SwShellCrsr::SaveTblBoxCntnt( pPos );
+}
+
+
+void SwShellTableCrsr::FillRects()
+{
+ // die neuen Rechtecke berechnen
+ // JP 16.01.98: wenn der Cursor noch "geparkt" ist nichts machen!!
+ if( !aSelBoxes.Count() || bParked ||
+ !GetPoint()->nNode.GetIndex() )
+ return;
+
+ SwRegionRects aReg( GetShell()->VisArea() );
+ SwNodes& rNds = GetDoc()->GetNodes();
+ for( USHORT n = 0; n < aSelBoxes.Count(); ++n )
+ {
+ const SwStartNode* pSttNd = (*(aSelBoxes.GetData() + n ))->GetSttNd();
+ const SwTableNode* pSelTblNd = pSttNd->FindTableNode();
+
+ SwNodeIndex aIdx( *pSttNd );
+ SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, TRUE, FALSE );
+
+ // TABLE IN TABLE
+ // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different
+ // version to do this)
+ const SwTableNode* pCurTblNd = pCNd->FindTableNode();
+ while ( pSelTblNd != pCurTblNd && pCurTblNd )
+ {
+ aIdx = pCurTblNd->EndOfSectionIndex();
+ pCNd = rNds.GoNextSection( &aIdx, TRUE, FALSE );
+ pCurTblNd = pCNd->FindTableNode();
+ }
+
+ if( !pCNd )
+ continue;
+
+ SwFrm* pFrm = pCNd->GetFrm( &GetSttPos() );
+ while( pFrm && !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+
+ ASSERT( pFrm, "Node nicht in einer Tabelle" );
+
+ while ( pFrm )
+ {
+ if( pFrm && aReg.GetOrigin().IsOver( pFrm->Frm() ) )
+ aReg -= pFrm->Frm();
+
+ pFrm = pFrm->GetNextCellLeaf( MAKEPAGE_NONE );
+ }
+ }
+ aReg.Invert();
+ Insert( &aReg, 0 );
+}
+
+
+// Pruefe, ob sich der SPoint innerhalb der Tabellen-SSelection befindet
+BOOL SwShellTableCrsr::IsInside( const Point& rPt ) const
+{
+ // die neuen Rechtecke berechnen
+ // JP 16.01.98: wenn der Cursor noch "geparkt" ist nichts machen!!
+ if( !aSelBoxes.Count() || bParked ||
+ !GetPoint()->nNode.GetIndex() )
+ return FALSE;
+
+ SwNodes& rNds = GetDoc()->GetNodes();
+ for( USHORT n = 0; n < aSelBoxes.Count(); ++n )
+ {
+ SwNodeIndex aIdx( *(*(aSelBoxes.GetData() + n ))->GetSttNd() );
+ SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, TRUE, FALSE );
+ if( !pCNd )
+ continue;
+
+ SwFrm* pFrm = pCNd->GetFrm( &GetPtPos() );
+ while( pFrm && !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+ ASSERT( pFrm, "Node nicht in einer Tabelle" );
+ if( pFrm && pFrm->Frm().IsInside( rPt ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#ifdef DBG_UTIL
+
+// JP 05.03.98: zum Testen des UNO-Crsr Verhaltens hier die Implementierung
+// am sichtbaren Cursor
+BOOL SwShellTableCrsr::IsSelOvr( int eFlags )
+{
+ return SwShellCrsr::IsSelOvr( eFlags );
+}
+
+#endif
+
+BOOL SwShellTableCrsr::IsAtValidPos( BOOL bPoint ) const
+{
+ return SwShellCrsr::IsAtValidPos( bPoint );
+}
+