summaryrefslogtreecommitdiff
path: root/sw/source/core/doc/docedt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc/docedt.cxx')
-rw-r--r--sw/source/core/doc/docedt.cxx2252
1 files changed, 2252 insertions, 0 deletions
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
new file mode 100644
index 000000000000..b763615f8a24
--- /dev/null
+++ b/sw/source/core/doc/docedt.cxx
@@ -0,0 +1,2252 @@
+/*************************************************************************
+ *
+ * $RCSfile: docedt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:08:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PRECOMPILED
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <string.h> // fuer strchr()
+
+#ifndef _HINTIDS_HXX
+#include <hintids.hxx>
+#endif
+
+#ifndef _SOUND_HXX //autogen
+#include <vcl/sound.hxx>
+#endif
+#ifndef _WORDSEL_HXX //autogen
+#include <svtools/wordsel.hxx>
+#endif
+#ifndef _SVX_CSCOITEM_HXX //autogen
+#include <svx/cscoitem.hxx>
+#endif
+#ifndef _SVX_BRKITEM_HXX //autogen
+#include <svx/brkitem.hxx>
+#endif
+#ifndef _LINGU_LNGPROPS_HHX_
+#include <lingu/lngprops.hxx>
+#endif
+#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
+#include <com/sun/star/beans/XPropertySet.hpp>
+#endif
+
+#ifndef _FMTANCHR_HXX //autogen
+#include <fmtanchr.hxx>
+#endif
+#ifndef _FMTCNTNT_HXX //autogen
+#include <fmtcntnt.hxx>
+#endif
+#ifndef _FMTPDSC_HXX //autogen
+#include <fmtpdsc.hxx>
+#endif
+#ifndef _TXTFTN_HXX //autogen
+#include <txtftn.hxx>
+#endif
+#ifndef _ACORRECT_HXX
+#include <acorrect.hxx> // Autokorrektur
+#endif
+#ifndef _BOOKMRK_HXX
+#include <bookmrk.hxx> // fuer SwBookmark
+#endif
+#ifndef _CNTFRM_HXX
+#include <cntfrm.hxx> // fuers Spell
+#endif
+#ifndef _CRSRSH_HXX
+#include <crsrsh.hxx>
+#endif
+#ifndef _CRSTATE_HXX
+#include <crstate.hxx>
+#endif
+#ifndef _DOC_HXX
+#include <doc.hxx>
+#endif
+#ifndef _DOCARY_HXX
+#include <docary.hxx>
+#endif
+#ifndef _DOCTXM_HXX
+#include <doctxm.hxx> // beim Move: Verzeichnisse korrigieren
+#endif
+#ifndef _FTNIDX_HXX
+#include <ftnidx.hxx>
+#endif
+#ifndef _FTNINFO_HXX
+#include <ftninfo.hxx>
+#endif
+#ifndef _HINTS_HXX
+#include <hints.hxx>
+#endif
+#ifndef _MDIEXP_HXX
+#include <mdiexp.hxx> // Statusanzeige
+#endif
+#ifndef _MVSAVE_HXX
+#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
+#endif
+#ifndef _NDTXT_HXX
+#include <ndtxt.hxx>
+#endif
+#ifndef _NODE_HXX
+#include <node.hxx>
+#endif
+#ifndef _PAM_HXX
+#include <pam.hxx>
+#endif
+#ifndef _REDLINE_HXX
+#include <redline.hxx>
+#endif
+#ifndef _ROOTFRM_HXX
+#include <rootfrm.hxx> // fuers UpdateFtn
+#endif
+#ifndef _SECTION_HXX
+#include <section.hxx>
+#endif
+#ifndef _SPLARGS_HXX
+#include <splargs.hxx> // fuer Spell
+#endif
+#ifndef _SWTABLE_HXX
+#include <swtable.hxx>
+#endif
+#ifndef _SWUNDO_HXX
+#include <swundo.hxx> // fuer die UndoIds
+#endif
+#ifndef _TXTFRM_HXX
+#include <txtfrm.hxx>
+#endif
+#ifndef _UNDOBJ_HXX
+#include <undobj.hxx>
+#endif
+
+
+using namespace ::com::sun::star;
+using namespace ::rtl;
+//using namespace ::utl;
+
+#define S2U(rString) OUString::createFromAscii(rString)
+
+
+struct _SaveRedline
+{
+ SwRedline* pRedl;
+ sal_uInt32 nStt, nEnd;
+ xub_StrLen nSttCnt, nEndCnt;
+
+ _SaveRedline( SwRedline* pR, const SwNodeIndex& rSttIdx )
+ : pRedl( pR )
+ {
+ const SwPosition* pStt = pR->Start(),
+ * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
+ sal_uInt32 nSttIdx = rSttIdx.GetIndex();
+ nStt = pStt->nNode.GetIndex() - nSttIdx;
+ nSttCnt = pStt->nContent.GetIndex();
+ if( pR->HasMark() )
+ {
+ nEnd = pEnd->nNode.GetIndex() - nSttIdx;
+ nEndCnt = pEnd->nContent.GetIndex();
+ }
+
+ pRedl->GetPoint()->nNode = 0;
+ pRedl->GetPoint()->nContent.Assign( 0, 0 );
+ pRedl->GetMark()->nNode = 0;
+ pRedl->GetMark()->nContent.Assign( 0, 0 );
+ }
+
+ void SetPos( sal_uInt32 nInsPos )
+ {
+ pRedl->GetPoint()->nNode = nInsPos + nStt;
+ pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
+ if( pRedl->HasMark() )
+ {
+ pRedl->GetMark()->nNode = nInsPos + nEnd;
+ pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt );
+ }
+ }
+};
+
+SV_DECL_PTRARR_DEL( _SaveRedlines, _SaveRedline*, 0, 4 )
+
+SV_IMPL_VARARR( _SaveFlyArr, _SaveFly )
+SV_IMPL_PTRARR( SaveBookmarks, SaveBookmark* )
+SV_IMPL_PTRARR( _SaveRedlines, _SaveRedline* )
+
+sal_Bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
+{
+ sal_Bool bRet = sal_True;
+ const SwTxtAttr *pHt;
+ sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
+ if( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
+ 0 != (pHt = pNode->GetTxtAttr( nPos )) )
+ switch( pHt->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ bRet = sal_False;
+ break;
+ }
+ return bRet;
+}
+
+void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
+{
+ if( !lcl_MayOverwrite( pNode, rStart ) )
+ {
+ // ueberspringe alle SonderAttribute
+ do {
+ // "Beep" bei jedem ausgelassenen
+ Sound::Beep(SOUND_ERROR);
+ rIdx++;
+ } while( (rStart = rIdx.GetIndex()) < pNode->GetTxt().Len()
+ && !lcl_MayOverwrite(pNode, rStart) );
+ }
+}
+
+// -----------------------------------------------------------------
+
+void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx )
+{
+ SwPosition aPos( rSttIdx );
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ // neuen Anker anlegen
+ _SaveFly& rSave = rArr[n];
+ SwFrmFmt* pFmt = rSave.pFrmFmt;
+ aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
+ aPos.nContent.Assign( 0, 0 );
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+ aAnchor.SetAnchor( &aPos );
+ pFmt->GetDoc()->GetSpzFrmFmts()->Insert(
+ pFmt, pFmt->GetDoc()->GetSpzFrmFmts()->Count() );
+ pFmt->SetAttr( aAnchor );
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pCNd && pCNd->GetFrm( 0, 0, sal_False ) )
+ pFmt->MakeFrms();
+ }
+}
+
+void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
+{
+ SwFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ const SwPosition* pAPos;
+ SwSpzFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ pFmt = (SwFrmFmt*)rFmts[n];
+ pAnchor = &pFmt->GetAnchor();
+ if( ( FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
+ FLY_AUTO_CNTNT == pAnchor->GetAnchorId() ) &&
+ 0 != ( pAPos = pAnchor->GetCntntAnchor() ) &&
+ rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
+ {
+ ASSERT( pAnchor->GetAnchorId() != FLY_AUTO_CNTNT, "FLY-AUTO-Baustelle!" );
+ _SaveFly aSave( pAPos->nNode.GetIndex() -
+ rRg.aStart.GetIndex(), pFmt );
+ rArr.Insert( aSave, rArr.Count());
+ pFmt->DelFrms();
+ rFmts.Remove( n--, 1 );
+ }
+ }
+}
+
+void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
+ _SaveFlyArr& rArr, sal_Bool bMoveAllFlys )
+{
+ SwSpzFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
+ SwFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+
+ const SwPosition* pPos = rPam.Start();
+ const SwNodeIndex& rSttNdIdx = pPos->nNode;
+ short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
+ pPos->nContent.GetIndex()) ? 1 : 0;
+
+ pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
+ const SwNodeIndex& rEndNdIdx = pPos->nNode;
+ short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
+ pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
+ ? 0 : 1;
+
+ const SwPosition* pAPos;
+ const SwNodeIndex* pCntntIdx;
+
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ sal_Bool bInsPos = sal_False;
+ pFmt = (SwFrmFmt*)rFmts[n];
+ pAnchor = &pFmt->GetAnchor();
+ if( ( FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
+ FLY_AUTO_CNTNT == pAnchor->GetAnchorId() ) &&
+ 0 != ( pAPos = pAnchor->GetCntntAnchor() ) &&
+ // nicht verschieben, wenn die InsPos im CntntBereich vom Fly ist
+ ( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
+ !( *pCntntIdx < rInsPos &&
+ rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
+ {
+ ASSERT( pAnchor->GetAnchorId() != FLY_AUTO_CNTNT, "FLY-AUTO-Baustelle!" );
+ if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
+ {
+ // wenn nur teil vom EndNode oder der EndNode und SttNode
+ // identisch sind, chaos::Anchor nicht anfassen
+ if( rSttNdIdx != pAPos->nNode )
+ {
+ // Anker nur an Anfang/Ende haengen
+ SwPosition aPos( rSttNdIdx );
+ SwFmtAnchor aAnchor( *pAnchor );
+ aAnchor.SetAnchor( &aPos );
+ pFmt->SetAttr( aAnchor );
+// ((SwFmtAnchor*)pAnchor)->SetAnchor( &aPos );
+ }
+ }
+ else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
+ && pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
+ 0 != ( bInsPos = rInsPos == pAPos->nNode ))
+
+ {
+ _SaveFly aSave( bInsPos ? 0 : pAPos->nNode.GetIndex() -
+ rSttNdIdx.GetIndex(), pFmt );
+ rArr.Insert( aSave, rArr.Count());
+ pFmt->DelFrms();
+ rFmts.Remove( n--, 1 );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------
+
+// loesche und verschiebe alle "Fly's am Absatz", die in der SSelection
+// liegen. Steht am SPoint ein Fly, wird dieser auf den Mark verschoben.
+
+void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
+ const SwNodeIndex& rPtNdIdx )
+{
+ const sal_Bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
+
+ SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
+ SwSpzFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
+ const SwPosition* pAPos;
+ for ( sal_uInt16 i = rTbl.Count(); i; )
+ {
+ SwFrmFmt *pFmt = rTbl[--i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if( ( rAnch.GetAnchorId() == FLY_AT_CNTNT ||
+ rAnch.GetAnchorId() == FLY_AUTO_CNTNT ) &&
+ 0 != ( pAPos = rAnch.GetCntntAnchor() ) &&
+ ( bDelFwrd
+ ? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
+ : rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
+ {
+ ASSERT( rAnch.GetAnchorId() != FLY_AUTO_CNTNT, "FLY-AUTO-Baustelle!" );
+ // nur den Anker verchieben ??
+ if( rPtNdIdx == pAPos->nNode )
+ {
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ SwPosition aPos( rMkNdIdx );
+ aAnch.SetAnchor( &aPos );
+ pFmt->SetAttr( aAnch );
+ }
+ else
+ {
+ // wird der Fly geloescht muss auch im seinem Inhalt alle
+ // Flys geloescht werden !!
+ const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() )
+ {
+ DelFlyInRange( *rCntnt.GetCntntIdx(),
+ SwNodeIndex( *rCntnt.GetCntntIdx()->
+ GetNode().EndOfSectionNode() ));
+ // Position kann sich verschoben haben !
+ if( i > rTbl.Count() )
+ i = rTbl.Count();
+ else if( pFmt != rTbl[i] )
+ i = rTbl.GetPos( pFmt );
+ }
+
+ pDoc->DelLayoutFmt( pFmt );
+// i++; // keinen auslassen
+ }
+ }
+ }
+}
+
+
+int lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
+ const SwNodeIndex& rInsPos,
+ SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
+ const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
+{
+ int bUpdateFtn = sal_False;
+ if( rFtnArr.Count() )
+ {
+ const SwNodes& rNds = rInsPos.GetNodes();
+ int bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
+ rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
+ int bSaveFtn = !bDelFtn &&
+ rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
+
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( rSttNd, &nPos );
+ SwTxtFtn* pSrch;
+ const SwNode* pFtnNd;
+
+ // loesche/sicher erstmal alle, die dahinter stehen
+ while( nPos < rFtnArr.Count() && ( pFtnNd =
+ &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
+ <= rEndNd.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( ( pEndCnt && pSttCnt )
+ ? (( &rSttNd.GetNode() == pFtnNd &&
+ pSttCnt->GetIndex() > nFtnSttIdx) ||
+ ( &rEndNd.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEndCnt->GetIndex() ))
+ : ( &rEndNd.GetNode() == pFtnNd ))
+ {
+ ++nPos; // weiter suchen
+ }
+ else
+ {
+ // dann weg damit
+ if( bDelFtn )
+ {
+ SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
+ SwIndex aIdx( &rTxtNd, nFtnSttIdx );
+ rTxtNd.Erase( aIdx, 1 );
+ }
+ else
+ {
+ pSrch->DelFrms();
+ rFtnArr.Remove( nPos );
+ if( bSaveFtn )
+ rSaveArr.Insert( pSrch );
+ }
+ bUpdateFtn = sal_True;
+ }
+ }
+
+ while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
+ GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( !pEndCnt || !pSttCnt ||
+ !( (( &rSttNd.GetNode() == pFtnNd &&
+ pSttCnt->GetIndex() > nFtnSttIdx ) ||
+ ( &rEndNd.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEndCnt->GetIndex() )) ))
+ {
+ if( bDelFtn )
+ {
+ // dann weg damit
+ SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
+ SwIndex aIdx( &rTxtNd, nFtnSttIdx );
+ rTxtNd.Erase( aIdx, 1 );
+ }
+ else
+ {
+ pSrch->DelFrms();
+ rFtnArr.Remove( nPos );
+ if( bSaveFtn )
+ rSaveArr.Insert( pSrch );
+ }
+ bUpdateFtn = sal_True;
+ }
+ }
+ }
+ return bUpdateFtn;
+}
+
+void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
+{
+ SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
+ sal_uInt16 nRedlPos;
+ SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
+ aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
+ if( pDoc->GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
+ --nRedlPos;
+ else if( nRedlPos >= pDoc->GetRedlineTbl().Count() )
+ return ;
+
+ SwRedlineMode eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );
+ SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
+
+ do {
+ SwRedline* pTmp = rRedlTbl[ nRedlPos ];
+
+ const SwPosition* pRStt = pTmp->Start(),
+ * pREnd = pTmp->GetMark() == pRStt
+ ? pTmp->GetPoint() : pTmp->GetMark();
+
+ if( pRStt->nNode < rRg.aStart )
+ {
+ if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
+ {
+ // Kopie erzeugen und Ende vom Original ans Ende des
+ // MoveBereiches setzen. Die Kopie wird mit verschoben
+ SwRedline* pNewRedl = new SwRedline( *pTmp );
+ SwPosition* pTmpPos = pNewRedl->Start();
+ pTmpPos->nNode = rRg.aStart;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+
+ _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
+// rArr.Insert( pSave, rArr.Count() );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+
+ pTmpPos = pTmp->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ else if( pREnd->nNode == rRg.aStart )
+ {
+ SwPosition* pTmpPos = pTmp->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ }
+ else if( pRStt->nNode < rRg.aEnd )
+ {
+ rRedlTbl.Remove( nRedlPos-- );
+ if( pREnd->nNode < rRg.aEnd ||
+ ( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
+ {
+ // gesamt verschieben
+ _SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
+// rArr.Insert( pSave, rArr.Count() );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+ }
+ else
+ {
+ // aufsplitten
+ SwRedline* pNewRedl = new SwRedline( *pTmp );
+ SwPosition* pTmpPos = pNewRedl->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+
+ _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
+// rArr.Insert( pSave, rArr.Count() );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+
+ pTmpPos = pTmp->Start();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ pDoc->AppendRedline( pTmp );
+ }
+ }
+ else
+ break;
+
+ } while( ++nRedlPos < pDoc->GetRedlineTbl().Count() );
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
+{
+ SwRedlineMode eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ _SaveRedline* pSave = rArr[ n ];
+ pSave->SetPos( nInsPos );
+ pDoc->AppendRedline( pSave->pRedl );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+// ------------------------------------------------------------------------
+
+_SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx )
+ : pSavArr( 0 ), pSavIdx( 0 )
+{
+ SwNode& rNd = rInsIdx.GetNode();
+ SwDoc* pDest = rNd.GetDoc();
+ if( pDest->GetRedlineTbl().Count() )
+ {
+ sal_uInt16 nFndPos;
+ const SwPosition* pEnd;
+ SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), 0 ));
+ const SwRedline* pRedl = pDest->GetRedline( aSrcPos, &nFndPos );
+ while( nFndPos-- && *( pEnd = ( pRedl =
+ pDest->GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos &&
+ *pRedl->Start() != aSrcPos )
+ {
+ if( !pSavArr )
+ {
+ pSavArr = new SvPtrarr( 2, 2 );
+ pSavIdx = new SwNodeIndex( rInsIdx, -1 );
+ }
+ void* p = (void*)pEnd;
+ pSavArr->Insert( p, pSavArr->Count() );
+ }
+ }
+}
+
+_SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
+{
+ if( pSavArr )
+ {
+ delete pSavArr;
+ delete pSavIdx;
+ }
+}
+
+void _SaveRedlEndPosForRestore::_Restore()
+{
+ (*pSavIdx)++;
+ SwPosition aPos( *pSavIdx, SwIndex( pSavIdx->GetNode().GetCntntNode(), 0 ));
+ for( sal_uInt16 n = pSavArr->Count(); n; )
+ *((SwPosition*)pSavArr->GetObject( --n )) = aPos;
+}
+
+
+// ------------------------------------------------------------------------
+
+// Loeschen einer vollstaendigen Section des NodesArray.
+// Der uebergebene Node steht irgendwo in der gewuenschten Section
+void SwDoc::DeleteSection( SwNode *pNode )
+{
+ ASSERT( pNode, "Kein Node uebergeben." );
+ SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
+ : pNode->StartOfSectionNode();
+ SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
+
+ // dann loesche mal alle Fly's, text::Bookmarks, ...
+ DelFlyInRange( aSttIdx, aEndIdx );
+ DeleteRedline( *pSttNd );
+ _DelBookmarks( aSttIdx, aEndIdx );
+
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ SwNodeIndex aMvStt( aSttIdx, 1 );
+ CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), sal_True );
+ }
+
+ GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
+}
+
+
+
+/*************************************************************************
+|* SwDoc::Insert(char)
+|* Beschreibung Zeichen einfuegen
+*************************************************************************/
+
+sal_Bool SwDoc::Insert( const SwPaM &rRg, sal_Unicode c )
+{
+ if( DoesUndo() )
+ ClearRedo();
+
+ const SwPosition & rPos = *rRg.GetPoint();
+
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ if( pACEWord->IsDeleted() )
+ pACEWord->CheckChar( rPos, c );
+ delete pACEWord, pACEWord = 0;
+ }
+ SwTxtNode *pNode = rPos.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ return sal_False;
+ sal_Bool bInsOneChar = sal_True;
+
+ SwDataChanged aTmp( rRg, 0 );
+
+ pNode->Insert( c, rPos.nContent );
+
+ if ( DoesUndo() )
+ {
+ sal_uInt16 nUndoSize = pUndos->Count();
+ SwUndo * pUndo;
+ if( DoesGroupUndo() && bInsOneChar && nUndoSize-- &&
+ UNDO_INSERT == ( pUndo = (*pUndos)[ nUndoSize ])->GetId() &&
+ ((SwUndoInsert*)pUndo)->CanGrouping( rPos, c ))
+ ; // wenn CanGrouping() sal_True returnt, ist schon alles erledigt
+ else
+ AppendUndo( new SwUndoInsert( rPos.nNode,
+ rPos.nContent.GetIndex(), 1,
+ !WordSelection::IsNormalChar( c ) ));
+ }
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex() - 1,
+ rPos.nNode, rPos.nContent.GetIndex() );
+ if( IsRedlineOn() )
+ AppendRedline( new SwRedline( REDLINE_INSERT, aPam ));
+ else
+ SplitRedline( aPam );
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+
+/*************************************************************************
+|* SwDoc::Overwrite(char)
+|* Beschreibung Zeichen ueberschreiben
+*************************************************************************/
+
+sal_Bool SwDoc::Overwrite( const SwPaM &rRg, sal_Unicode c )
+{
+ SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ pACEWord->CheckChar( rPt, c );
+ delete pACEWord, pACEWord = 0;
+ }
+
+ SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ return sal_False;
+
+ sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ SwDataChanged aTmp( rRg, 0 );
+ SwIndex& rIdx = rPt.nContent;
+ xub_StrLen nStart = rIdx.GetIndex();
+
+ // hinter das Zeichen (zum aufspannen der Attribute !!)
+ if( nStart < pNode->GetTxt().Len() )
+ lcl_SkipAttr( pNode, rIdx, nStart );
+
+ if( DoesUndo() )
+ {
+ ClearRedo();
+ sal_uInt16 nUndoSize = pUndos->Count();
+ SwUndo * pUndo;
+ if( DoesGroupUndo() && nUndoSize-- &&
+ UNDO_OVERWRITE == ( pUndo = (*pUndos)[ nUndoSize ])->GetId() &&
+ ((SwUndoOverwrite*)pUndo)->CanGrouping( this, rPt, c ))
+ ;// wenn CanGrouping() sal_True returnt, ist schon alles erledigt
+ else
+ AppendUndo( new SwUndoOverwrite( this, rPt, c ));
+ }
+ else
+ {
+ // hinter das Zeichen (zum aufspannen der Attribute !!)
+ if( nStart < pNode->GetTxt().Len() )
+ rIdx++;
+ pNode->Insert( c, rIdx );
+ if( nStart+1 < rIdx.GetIndex() )
+ {
+ rIdx = nStart;
+ pNode->Erase( rIdx, 1 );
+ rIdx++;
+ }
+ }
+
+ sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ if( nOldAttrCnt != nNewAttrCnt )
+ {
+ SwUpdateAttr aHint( 0, 0, 0 );
+ SwClientIter aIter( *pNode );
+ SwClient* pGTO = aIter.First(TYPE( SwCrsrShell ));
+ while( pGTO )
+ {
+ pGTO->Modify( 0, &aHint );
+ pGTO = aIter.Next();
+ }
+ }
+
+ if( !DoesUndo() && !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ {
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ DeleteRedline( aPam );
+ }
+ else if( IsRedlineOn() )
+ {
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ AppendRedline( new SwRedline( REDLINE_INSERT, aPam ));
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+sal_Bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
+{
+ SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ if( 1 == rStr.Len() )
+ pACEWord->CheckChar( rPt, rStr.GetChar( 0 ) );
+ delete pACEWord, pACEWord = 0;
+ }
+
+ SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ return sal_False;
+
+ if( DoesUndo() )
+ ClearRedo();
+
+ sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ SwDataChanged aTmp( rRg, 0 );
+ SwIndex& rIdx = rPt.nContent;
+ xub_StrLen nStart;
+
+ sal_uInt16 nUndoSize = pUndos->Count();
+ SwUndo * pUndo;
+ sal_Unicode c;
+ String aStr;
+
+ for( xub_StrLen nCnt = 0; nCnt < rStr.Len(); ++nCnt )
+ {
+ // hinter das Zeichen (zum aufspannen der Attribute !!)
+ if( (nStart = rIdx.GetIndex()) < pNode->GetTxt().Len() )
+ lcl_SkipAttr( pNode, rIdx, nStart );
+ c = rStr.GetChar( nCnt );
+ if( DoesUndo() )
+ {
+ if( DoesGroupUndo() && nUndoSize &&
+ UNDO_OVERWRITE == ( pUndo = (*pUndos)[ nUndoSize-1 ])->GetId() &&
+ ((SwUndoOverwrite*)pUndo)->CanGrouping( this, rPt, c ))
+ ;// wenn CanGrouping() sal_True returnt, ist schon alles erledigt
+ else
+ {
+ AppendUndo( new SwUndoOverwrite( this, rPt, c ));
+ nUndoSize = pUndos->Count();
+ }
+ }
+ else
+ {
+ // hinter das Zeichen (zum Aufspannen der Attribute !!)
+ if( nStart < pNode->GetTxt().Len() )
+ rIdx++;
+ pNode->Insert( c, rIdx );
+ if( nStart+1 < rIdx.GetIndex() )
+ {
+ rIdx = nStart;
+ pNode->Erase( rIdx, 1 );
+ rIdx++;
+ }
+ }
+ }
+
+ sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ if( nOldAttrCnt != nNewAttrCnt )
+ {
+ SwUpdateAttr aHint( 0, 0, 0 );
+ SwClientIter aIter( *pNode );
+ SwClient* pGTO = aIter.First(TYPE( SwCrsrShell ));
+ while( pGTO )
+ {
+ pGTO->Modify( 0, &aHint );
+ pGTO = aIter.Next();
+ }
+ }
+
+ if( !DoesUndo() && !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ {
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ DeleteRedline( aPam );
+ }
+ else if( IsRedlineOn() )
+ {
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ AppendRedline( new SwRedline( REDLINE_INSERT, aPam ));
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+
+sal_Bool SwDoc::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
+{
+ SwNodeIndex aIdx( rPaM.Start()->nNode );
+ sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
+ sal_Bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
+ aIdx--; // vor den Move Bereich !!
+
+ sal_Bool bRet = Move( rPaM, rPos, eMvFlags );
+ if( bRet && !bOneNode )
+ {
+ if( bJoinTxt )
+ aIdx++;
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+ SwNodeIndex aNxtIdx( aIdx );
+ if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
+ {
+ { // Block wegen SwIndex in den Node !!
+ CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex( pTxtNd,
+ pTxtNd->GetTxt().Len() ) ), 0, sal_True );
+ }
+ pTxtNd->JoinNext();
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwDoc::Move( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
+{
+ // keine Moves-Abfangen
+ const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
+ if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
+ return sal_False;
+
+ // sicher die absatzgebundenen Flys, damit sie verschoben werden koennen.
+ _SaveFlyArr aSaveFlyArr;
+ _SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, DOC_MOVEALLFLYS & eMvFlags );
+
+ int bUpdateFtn = sal_False;
+ SwFtnIdxs aTmpFntIdx;
+
+ // falls Undo eingeschaltet, erzeuge das UndoMove-Objekt
+ SwUndoMove * pUndoMove = 0;
+ if( DoesUndo() )
+ {
+ ClearRedo();
+ pUndoMove = new SwUndoMove( rPaM, rPos );
+ }
+ else
+ {
+ bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
+ GetFtnIdxs(), aTmpFntIdx,
+ &pStt->nContent, &pEnd->nContent );
+ }
+
+ sal_Bool bSplit = sal_False;
+ SwPaM * pSavePam = new SwPaM( rPos, rPos );
+
+ // stelle den SPoint an den Anfang vom Bereich (Definition)
+ if( rPaM.GetPoint() == pEnd )
+ rPaM.Exchange();
+
+ // in der EditShell wird nach dem Move ein JoinNext erzeugt, wenn
+ // vor und nach dem Move ein Text-Node steht.
+ SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
+ sal_Bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
+
+ // werden ein oder mehr TextNodes bewegt, so wird
+ // im SwNodes::Move ein SplitNode erzeugt. Dieser Updated aber nicht
+ // den Cursor. Um das zu verhindern, wird hier ein TextNode angelegt,
+ // um die Updaterei der Indizies zu erhalten. Nach dem Move wird
+ // evt. der Node geloescht.
+
+ SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
+ ( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam )) )
+ {
+ bSplit = sal_True;
+ xub_StrLen nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
+
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
+ aBkmkArr, SAVEFLY_SPLIT );
+
+ pTNd = (SwTxtNode*)pTNd->SplitNode( rPos );
+
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
+
+ // jetzt noch den Pam berichtigen !!
+ if( rPos.nNode == rPaM.GetMark()->nNode )
+ {
+ rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
+ rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
+ }
+ }
+
+ // setze den Pam um einen "Inhalt" zurueck; dadurch steht er immer
+ // ausserhalb des manipulierten Bereiches. Falls kein Inhalt mehr vor-
+ // handen, dann auf den StartNode (es ist immer einer vorhanden !!!)
+ sal_Bool bNullCntnt = !pSavePam->Move( fnMoveBackward, fnGoCntnt );
+ if( bNullCntnt )
+ pSavePam->GetPoint()->nNode--;
+
+ // kopiere alle Bookmarks, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ SaveBookmarks aSaveBkmk;
+ _DelBookmarks( pStt->nNode, pEnd->nNode, &aSaveBkmk,
+ &pStt->nContent, &pEnd->nContent );
+
+ // falls durch die vorherigen Loeschungen (z.B. der Fussnoten) kein
+ // Bereich mehr existiert, ist das immernoch ein gueltiger Move!
+ if( *rPaM.GetPoint() != *rPaM.GetMark() )
+ {
+ // jetzt kommt das eigentliche Verschieben
+ GetNodes().Move( rPaM, rPos, GetNodes() );
+
+ if( rPaM.HasMark() ) // es wurde kein Move ausgefuehrt !!
+ {
+ delete pSavePam;
+ delete pUndoMove;
+ return sal_False; // Nach einem Move() ist der GetMark geloescht
+ }
+ }
+ else
+ rPaM.DeleteMark();
+
+ ASSERT( *pSavePam->GetMark() == rPos,
+ "PaM wurde nicht verschoben, am Anfang/Ende keine ContentNodes?" );
+ *pSavePam->GetMark() = rPos;
+
+ rPaM.SetMark(); // um den neuen Bereich eine Sel. aufspannen
+ pTNd = pSavePam->GetNode()->GetTxtNode();
+ if( DoesUndo() )
+ {
+ // korrigiere erstmal den Content vom SavePam
+ if( bNullCntnt )
+ pSavePam->GetPoint()->nContent = 0;
+
+ // die Methode SwEditShell::Move() fuegt nach dem Move den Text-Node
+ // zusammen, in dem der rPaM steht. Wurde der Inhalt nach hinten
+ // geschoben und liegt der SPoint vom SavePam im naechsten Node, so
+ // muss beim Speichern vom Undo-Object das beachtet werden !!
+ SwTxtNode * pPamTxtNd;
+
+ // wird ans SwUndoMove weitergegeben, das dann beim Undo JoinNext
+ // aufruft. (falls es hier nicht moeglich ist).
+ sal_Bool bJoin = bSplit && pTNd;
+ bCorrSavePam = bCorrSavePam &&
+ 0 != ( pPamTxtNd = rPaM.GetNode()->GetTxtNode() )
+ && pPamTxtNd->CanJoinNext()
+ && *rPaM.GetPoint() <= *pSavePam->GetPoint();
+
+ // muessen am SavePam 2 Nodes zusammengefasst werden ??
+ if( bJoin && pTNd->CanJoinNext() )
+ {
+ pTNd->JoinNext();
+ // kein temp. sdbcx::Index bei &&
+ // es sollten wohl nur die Indexwerte verglichen werden.
+ if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
+ pSavePam->GetPoint()->nNode.GetIndex() )
+ pSavePam->GetPoint()->nContent += pPamTxtNd->Len();
+ bJoin = sal_False;
+ }
+// else if( !bCorrSavePam && !pSavePam->Move( fnMoveForward, fnGoCntnt ))
+ else if( !pSavePam->Move( fnMoveForward, fnGoCntnt ))
+ pSavePam->GetPoint()->nNode++;
+
+ // zwischen SPoint und GetMark steht jetzt der neu eingefuegte Bereich
+ pUndoMove->SetDestRange( *pSavePam, *rPaM.GetPoint(),
+ bJoin, bCorrSavePam );
+ AppendUndo( pUndoMove );
+ }
+ else
+ {
+ // muessen am SavePam 2 Nodes zusammengefasst werden ??
+ if( bSplit && pTNd )
+ {
+ if( pTNd->CanJoinNext())
+ pTNd->JoinNext();
+ }
+ if( bNullCntnt )
+ {
+ pSavePam->GetPoint()->nNode++;
+ pSavePam->GetPoint()->nContent.Assign( pSavePam->GetCntntNode(), 0 );
+ }
+ else
+ pSavePam->Move( fnMoveForward, fnGoCntnt );
+ }
+
+ // setze jetzt wieder die text::Bookmarks in das Dokument
+ *rPaM.GetMark() = *pSavePam->Start();
+ for( sal_uInt16 n = 0; n < aSaveBkmk.Count(); ++n )
+ aSaveBkmk[n]->SetInDoc( this, rPaM.GetMark()->nNode,
+ &rPaM.GetMark()->nContent );
+ *rPaM.GetPoint() = *pSavePam->End();
+ delete pSavePam;
+
+ // verschiebe die Flys an die neue Position
+ _RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode );
+
+ if( bUpdateFtn )
+ {
+ if( aTmpFntIdx.Count() )
+ {
+ GetFtnIdxs().Insert( &aTmpFntIdx );
+ aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
+ }
+
+ GetFtnIdxs().UpdateAllFtn();
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+sal_Bool SwDoc::Move( SwNodeRange& rRange, SwNodeIndex& rPos, SwMoveFlags eMvFlags )
+{
+ // bewegt alle Nodes an die neue Position. Dabei werden die
+ // text::Bookmarks mit verschoben !! (zur Zeit ohne Undo)
+
+ // falls durchs Move Fussnoten in den Sonderbereich kommen sollten,
+ // dann entferne sie jetzt.
+ //JP 13.07.95:
+ // ansonsten bei allen Fussnoten, die verschoben werden, die Frames
+ // loeschen und nach dem Move wieder aufbauen lassen (Fussnoten koennen
+ // die Seite wechseln). Zusaetzlich muss natuerlich die Sortierung
+ // der FtnIdx-Array wieder korrigiert werden.
+
+ int bUpdateFtn = sal_False;
+ SwFtnIdxs aTmpFntIdx;
+
+ SwUndoMove* pUndo = 0;
+ if( (DOC_CREATEUNDOOBJ & eMvFlags ) && DoesUndo() )
+ pUndo = new SwUndoMove( this, rRange, rPos );
+ else
+ bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
+ GetFtnIdxs(), aTmpFntIdx );
+
+ _SaveRedlines aSaveRedl( 0, 4 );
+ SvPtrarr aSavRedlInsPosArr( 0, 4 );
+ if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
+ {
+ lcl_SaveRedlines( rRange, aSaveRedl );
+
+ // suche alle Redlines, die an der InsPos aufhoeren. Diese muessen
+ // nach dem Move wieder an die "alte" Position verschoben werden
+ sal_uInt16 nRedlPos = GetRedlinePos( rPos.GetNode() );
+ if( USHRT_MAX != nRedlPos )
+ {
+ const SwPosition *pRStt, *pREnd;
+ do {
+ SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ pRStt = pTmp->Start();
+ pREnd = pTmp->End();
+ if( pREnd->nNode == rPos && pRStt->nNode < rPos )
+ {
+ void* p = pTmp;
+ aSavRedlInsPosArr.Insert( p, aSavRedlInsPosArr.Count() );
+ }
+ } while( pRStt->nNode < rPos && ++nRedlPos < GetRedlineTbl().Count());
+ }
+ }
+
+ // kopiere alle Bookmarks, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ SaveBookmarks aSaveBkmk;
+ _DelBookmarks( rRange.aStart, rRange.aEnd, &aSaveBkmk );
+
+ // sicher die absatzgebundenen Flys, damit verschoben werden koennen.
+ _SaveFlyArr aSaveFlyArr;
+ if( GetSpzFrmFmts()->Count() )
+ _SaveFlyInRange( rRange, aSaveFlyArr );
+
+ // vor die Position setzen, damit er nicht weitergeschoben wird
+ SwNodeIndex aIdx( rPos, -1 );
+
+ SwNodeIndex* pSaveInsPos = 0;
+ if( pUndo )
+ pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
+
+ // verschiebe die Nodes
+ if( GetNodes()._MoveNodes( rRange, GetNodes(), rPos ) )
+ {
+ aIdx++; // wieder auf alte Position
+ if( pSaveInsPos )
+ (*pSaveInsPos)++;
+ }
+ else
+ {
+ aIdx = rRange.aStart;
+ delete pUndo, pUndo = 0;
+ }
+
+ // verschiebe die Flys an die neue Position
+ if( aSaveFlyArr.Count() )
+ _RestFlyInRange( aSaveFlyArr, aIdx );
+
+ // setze jetzt wieder die text::Bookmarks in das Dokument
+ for( sal_uInt16 nCnt = 0; nCnt < aSaveBkmk.Count(); ++nCnt )
+ aSaveBkmk[nCnt]->SetInDoc( this, aIdx );
+
+ if( aSavRedlInsPosArr.Count() )
+ {
+ SwNode* pNewNd = &aIdx.GetNode();
+ for( sal_uInt16 n = 0; n < aSavRedlInsPosArr.Count(); ++n )
+ {
+ SwRedline* pTmp = (SwRedline*)aSavRedlInsPosArr[ n ];
+ if( USHRT_MAX != GetRedlineTbl().GetPos( pTmp ) )
+ {
+ SwPosition* pEnd = pTmp->End();
+ pEnd->nNode = aIdx;
+ pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
+ }
+ }
+ }
+
+ if( aSaveRedl.Count() )
+ lcl_RestoreRedlines( this, aIdx.GetIndex(), aSaveRedl );
+
+ if( pUndo )
+ {
+ ClearRedo();
+ pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
+ AppendUndo( pUndo );
+ }
+
+ if( pSaveInsPos )
+ delete pSaveInsPos;
+
+ if( bUpdateFtn )
+ {
+ if( aTmpFntIdx.Count() )
+ {
+ GetFtnIdxs().Insert( &aTmpFntIdx );
+ aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
+ }
+
+ GetFtnIdxs().UpdateAllFtn();
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev )
+{
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ rJoinTxt = 0 != pTxtNd;
+
+ if( rJoinTxt && pStt == rPam.GetPoint() &&
+ 0 != ( pTxtNd = pEnd->nNode.GetNode().GetTxtNode() ) &&
+ pTxtNd->GetTxt().Len() == pEnd->nContent.GetIndex() )
+ {
+ rPam.Exchange();
+ rJoinPrev = sal_False;
+ }
+ else
+ rJoinPrev = rJoinTxt && rPam.GetPoint() == pStt;
+ }
+ else
+ rJoinTxt = sal_False, rJoinPrev = sal_False;
+}
+
+void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev )
+{
+ SwNodeIndex aIdx( rPam.GetPoint()->nNode );
+ SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
+ SwNodeIndex aOldIdx( aIdx );
+ SwTxtNode *pOldTxtNd = pTxtNd;
+
+ if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
+ {
+ SwDoc* pDoc = rPam.GetDoc();
+ if( bJoinPrev )
+ {
+ {
+ // falls PageBreaks geloescht / gesetzt werden, darf das
+ // nicht in die Undo-History aufgenommen werden !!
+ // (das loeschen vom Node geht auch am Undo vorbei !!!)
+ sal_Bool bDoUndo = pDoc->DoesUndo();
+ pDoc->DoUndo( sal_False );
+
+ /* PageBreaks, PageDesc, ColumnBreaks */
+ // Sollte an der Logik zum Kopieren der PageBreak's ...
+ // etwas geaendert werden, muss es auch im SwUndoDelete
+ // geandert werden. Dort wird sich das AUTO-PageBreak
+ // aus dem GetMarkNode kopiert.!!!
+
+ /* Der GetMarkNode */
+ if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->GetpSwAttrSet() )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_BREAK, sal_False, &pItem ) )
+ pTxtNd->ResetAttr( RES_BREAK );
+ if( pTxtNd->GetpSwAttrSet() &&
+ SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) )
+ pTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+
+ /* Der PointNode */
+ if( pOldTxtNd->GetpSwAttrSet() )
+ {
+ const SfxPoolItem* pItem;
+ SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
+ SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ aSet.Put( *pItem );
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ aSet.Put( *pItem );
+ if( aSet.Count() )
+ pTxtNd->SwCntntNode::SetAttr( aSet );
+ }
+ pOldTxtNd->FmtToTxtAttr( pTxtNd );
+
+ SvULongs aBkmkArr( 15, 15 );
+ ::_SaveCntntIdx( pDoc, aOldIdx.GetIndex(),
+ pOldTxtNd->Len(), aBkmkArr );
+
+ SwIndex aAlphaIdx(pTxtNd);
+ pOldTxtNd->Cut( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
+ pOldTxtNd->Len() );
+ SwPosition aAlphaPos( aIdx, aAlphaIdx );
+ pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, sal_True );
+
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ ::_RestoreCntntIdx( pDoc, aBkmkArr, aIdx.GetIndex() );
+
+ pDoc->DoUndo( bDoUndo );
+
+ // falls der uebergebene PaM nicht im Crsr-Ring steht,
+ // gesondert behandeln (z.B. Aufruf aus dem Auto-Format)
+ if( pOldTxtNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
+ rPam.GetBound( sal_True ) = aAlphaPos;
+ if( pOldTxtNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
+ rPam.GetBound( sal_False ) = aAlphaPos;
+ }
+ // jetzt nur noch den Node loeschen
+ pDoc->GetNodes().Delete( aOldIdx, 1 );
+ }
+ else
+ {
+ SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
+ if( pTxtNd->Len() )
+ pDelNd->FmtToTxtAttr( pTxtNd );
+ else if( pDelNd->GetpSwAttrSet() )
+ {
+ // nur die Zeichenattribute kopieren
+ SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
+ aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
+ pTxtNd->SwCntntNode::SetAttr( aTmpSet );
+ }
+
+ pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, sal_True );
+ pTxtNd->JoinNext();
+ }
+ }
+}
+
+sal_Bool SwDoc::DeleteAndJoin( SwPaM & rPam )
+{
+ if( IsRedlineOn() )
+ {
+ sal_uInt16 nUndoSize = 0;
+ SwUndoRedlineDelete* pUndo = 0;
+ SwRedlineMode eOld = GetRedlineMode();
+ if( DoesUndo() )
+ {
+ ClearRedo();
+
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( REDLINE_ON | REDLINE_SHOW_INSERT | REDLINE_SHOW_DELETE );
+
+ nUndoSize = pUndos->Count();
+ StartUndo();
+ AppendUndo( pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE ));
+ }
+ AppendRedline( new SwRedline( REDLINE_DELETE, rPam ));
+ SetModified();
+
+ if( pUndo )
+ {
+ EndUndo();
+ SwUndo* pPrevUndo;
+ if( nUndoSize && DoesGroupUndo() &&
+ nUndoSize + 1 == pUndos->Count() &&
+ UNDO_REDLINE == ( pPrevUndo = (*pUndos)[ nUndoSize-1 ])->GetId() &&
+ UNDO_DELETE == ((SwUndoRedline*)pPrevUndo)->GetUserId() &&
+ ((SwUndoRedlineDelete*)pPrevUndo)->CanGrouping( *pUndo ))
+ {
+ DoUndo( sal_False );
+ pUndos->DeleteAndDestroy( nUndoSize, 1 );
+ --nUndoPos, --nUndoCnt;
+ DoUndo( sal_True );
+ }
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+ }
+ return sal_True;
+ }
+
+ sal_Bool bJoinTxt, bJoinPrev;
+ lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
+
+ {
+ // dann eine Kopie vom Cursor erzeugen um alle Pams aus den
+ // anderen Sichten aus dem Loeschbereich zu verschieben
+ // ABER NICHT SICH SELBST !!
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+
+ if( !Delete( aDelPam ) )
+ return sal_False;
+
+ *rPam.GetPoint() = *aDelPam.GetPoint();
+ }
+
+ if( bJoinTxt )
+ lcl_JoinText( rPam, bJoinPrev );
+
+ return sal_True;
+}
+
+sal_Bool SwDoc::Delete( SwPaM & rPam )
+{
+ SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
+
+ if( !rPam.HasMark() || *pStt >= *pEnd )
+ return sal_False;
+
+ if( pACEWord )
+ {
+ // ggfs. das gesicherte Word fuer die Ausnahme
+ if( pACEWord->IsDeleted() || pStt->nNode != pEnd->nNode ||
+ pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
+ !pACEWord->CheckDelChar( *pStt ))
+ delete pACEWord, pACEWord = 0;
+ }
+
+ {
+ // loesche alle leeren TextHints an der Mark-Position
+ SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
+ SwpHints* pHts;
+ if( pTxtNd && 0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
+ {
+ const xub_StrLen *pEndIdx;
+ xub_StrLen nMkCntPos = rPam.GetMark()->nContent.GetIndex();
+ for( sal_uInt16 n = pHts->Count(); n; )
+ {
+ const SwTxtAttr* pAttr = (*pHts)[ --n ];
+ if( nMkCntPos > *pAttr->GetStart() )
+ break;
+
+ if( nMkCntPos == *pAttr->GetStart() &&
+ 0 != (pEndIdx = pAttr->GetEnd()) &&
+ *pEndIdx == *pAttr->GetStart() )
+ pTxtNd->DestroyAttr( pHts->Cut( n ) );
+ }
+ }
+ }
+
+ {
+ // Bug 26675: DataChanged vorm loeschen verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( rPam, 0 );
+ }
+
+
+ if( DoesUndo() )
+ {
+ ClearRedo();
+ sal_uInt16 nUndoSize = pUndos->Count();
+ SwUndo * pUndo;
+ if( DoesGroupUndo() && nUndoSize-- &&
+ UNDO_DELETE == ( pUndo = (*pUndos)[ nUndoSize ])->GetId() &&
+ ((SwUndoDelete*)pUndo)->CanGrouping( this, rPam ))
+ ;// wenn CanGrouping() sal_True returnt, ist schon alles erledigt
+ else
+ AppendUndo( new SwUndoDelete( rPam ) );
+
+ SetModified();
+ return sal_True;
+ }
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( rPam );
+
+ // loesche und verschiebe erstmal alle "Fly's am Absatz", die in der
+ // SSelection liegen
+ DelFlyInRange( rPam.GetMark()->nNode, rPam.GetPoint()->nNode );
+ _DelBookmarks( pStt->nNode, pEnd->nNode, 0,
+ &pStt->nContent, &pEnd->nContent );
+
+ SwNodeIndex aSttIdx( pStt->nNode );
+ SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
+
+ do { // middle checked loop!
+ if( pCNd )
+ {
+ if( pCNd->GetTxtNode() )
+ {
+ // verschiebe jetzt noch den Inhalt in den neuen Node
+ sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
+ xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex()
+ : pCNd->Len() )
+ - pStt->nContent.GetIndex();
+
+ // falls schon leer, dann nicht noch aufrufen
+ if( nLen )
+ ((SwTxtNode*)pCNd)->Erase( pStt->nContent, nLen );
+
+ if( bOneNd ) // das wars schon
+ break;
+
+ aSttIdx++;
+ }
+ else
+ {
+ // damit beim loeschen keine Indizies mehr angemeldet sind,
+ // wird hier der SwPaM aus dem Content entfernt !!
+ pStt->nContent.Assign( 0, 0 );
+ }
+ }
+
+ sal_uInt32 nEnde = pEnd->nNode.GetIndex();
+ pCNd = pEnd->nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ if( pCNd->GetTxtNode() )
+ {
+ // falls schon leer, dann nicht noch aufrufen
+ if( pEnd->nContent.GetIndex() )
+ {
+ SwIndex aIdx( pCNd, 0 );
+ ((SwTxtNode*)pCNd)->Erase( aIdx, pEnd->nContent.GetIndex() );
+ }
+ nEnde--;
+ }
+ else
+ {
+ // damit beim Loeschen keine Indizies mehr angemeldet sind,
+ // wird hier der SwPaM aus dem Content entfernt !!
+ pEnd->nContent.Assign( 0, 0 );
+ nEnde--;
+ }
+ }
+
+ nEnde++;
+ if( aSttIdx != nEnde )
+ {
+ // loesche jetzt die Nodes in das NodesArary
+ GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
+ }
+
+ // falls der Node geloescht wurde, in dem der Cursor stand, so
+ // muss der Content im akt. Content angemeldet werden !!!
+ pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
+ pStt->nContent.GetIndex() );
+
+ // der PaM wird korrigiert, denn falls ueber Nodegrenzen geloescht
+ // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
+ // wird aufgehoben !
+ *pEnd = *pStt;
+ rPam.DeleteMark();
+
+ } while( sal_False );
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ CompressRedlines();
+ SetModified();
+ return sal_True;
+}
+
+
+uno::Reference< uno::XInterface > SwDoc::Spell( SwPaM& rPaM,
+ uno::Reference< linguistic::XSpellChecker1 > &xSpeller,
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt ) const
+{
+ SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
+ uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
+ sal_Bool bReverse = xProp.is() ?
+ *(sal_Bool*)xProp->getPropertyValue( S2U(UPN_IS_WRAP_REVERSE) ).getValue() : sal_False;
+
+ SwSpellArgs aSpellArg( xSpeller,
+ pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
+ pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
+
+ sal_uInt32 nCurrNd = pSttPos->nNode.GetIndex();
+ sal_uInt32 nEndNd = pEndPos->nNode.GetIndex();
+
+ if( nCurrNd <= nEndNd )
+ {
+ SwCntntFrm* pCntFrm;
+ sal_uInt32 nCount = nEndNd - nCurrNd;
+ if( bReverse )
+ {
+ nCurrNd = nEndNd;
+ nEndNd = nCurrNd - nCount;
+ }
+ sal_Bool bGoOn = sal_True;
+ while( bGoOn )
+ {
+ SwNode* pNd = GetNodes()[ nCurrNd ];
+ switch( pNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->GetFrm()) )
+ {
+ // geschutze Cellen/Flys ueberspringen, ausgeblendete
+ //ebenfalls
+ if( pCntFrm->IsProtected() )
+ {
+ nCurrNd = bReverse ? pNd->StartOfSectionIndex()
+ : pNd->EndOfSectionIndex();
+ }
+ else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ if( pPageCnt && *pPageCnt && pPageSt )
+ {
+ sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
+ if( !*pPageSt )
+ {
+ *pPageSt = nPageNr;
+ if( *pPageCnt < *pPageSt )
+ *pPageCnt = *pPageSt;
+ }
+ long nStat;
+ if( nPageNr >= *pPageSt )
+ nStat = bReverse ?
+ *pPageCnt - nPageNr + *pPageSt + 1 :
+ nPageNr - *pPageSt + 1;
+ else
+ nStat = bReverse ?
+ *pPageSt - nPageNr + 1 :
+ nPageNr + *pPageCnt - *pPageSt + 1;
+ ::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
+ }
+ if( ((SwTxtNode*)pNd)->Spell( &aSpellArg ) )
+ {
+ // Abbrechen und Position merken
+ pSttPos->nNode = nCurrNd;
+ pEndPos->nNode = nCurrNd;
+ nCurrNd = nEndNd;
+ }
+ }
+ }
+ break;
+ case ND_SECTIONNODE:
+ if( !bReverse &&
+ ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
+ ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
+ nCurrNd = pNd->EndOfSectionIndex();
+ break;
+ case ND_ENDNODE:
+ {
+ SwNode* pTmp;
+ if( bReverse && 0 != (pTmp = pNd->StartOfSectionNode() ) &&
+ ND_SECTIONNODE == pTmp->GetNodeType() &&
+ ( ((SwSectionNode*)pTmp)->GetSection().IsProtect() ||
+ ((SwSectionNode*)pTmp)->GetSection().IsHidden() ) )
+ nCurrNd = pNd->StartOfSectionIndex();
+ break;
+ }
+ }
+
+ if( bReverse )
+ {
+ bGoOn = nCurrNd > nEndNd;
+ if( bGoOn )
+ --nCurrNd;
+ }
+ else
+ {
+ bGoOn = nCurrNd < nEndNd;
+ ++nCurrNd;
+ }
+ }
+ }
+ return aSpellArg.xSpellAlt;
+}
+
+class SwHyphArgs : public SwInterHyphInfo
+{
+ const SwNode *pStart;
+ const SwNode *pEnd;
+ SwNode *pNode;
+ sal_uInt16 *pPageCnt;
+ sal_uInt16 *pPageSt;
+
+ sal_uInt32 nNode;
+ xub_StrLen nPamStart;
+ xub_StrLen nPamLen;
+
+public:
+ SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
+ sal_uInt16* pPageCount, sal_uInt16* pPageStart );
+ void SetPam( SwPaM *pPam ) const;
+ inline void SetNode( SwNode *pNew ) { pNode = pNew; }
+ inline const SwNode *GetNode() const { return pNode; }
+ inline void SetRange( const SwNode *pNew );
+ inline void NextNode() { ++nNode; }
+ inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
+ inline sal_uInt16 *GetPageSt() { return pPageSt; }
+};
+
+SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
+ sal_uInt16* pPageCount, sal_uInt16* pPageStart )
+ : SwInterHyphInfo( rCrsrPos ), pNode(0),
+ pPageCnt( pPageCount ), pPageSt( pPageStart )
+{
+ // Folgende Bedingungen muessen eingehalten werden:
+ // 1) es gibt mindestens eine Selektion
+ // 2) SPoint() == Start()
+ ASSERT( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
+ ASSERT( *pPam->GetPoint() <= *pPam->GetMark(),
+ "SwDoc::Hyphenate: New York, New York");
+
+ const SwNodes &rNds = pPam->GetDoc()->GetNodes();
+ const SwPosition *pPoint = pPam->GetPoint();
+ nNode = pPoint->nNode.GetIndex();
+
+ // Start einstellen
+ pStart = pPoint->nNode.GetNode().GetTxtNode();
+ nPamStart = pPoint->nContent.GetIndex();
+
+ // Ende und Laenge einstellen.
+ const SwPosition *pMark = pPam->GetMark();
+ pEnd = pMark->nNode.GetNode().GetTxtNode();
+ nPamLen = pMark->nContent.GetIndex();
+ if( pPoint->nNode == pMark->nNode )
+ nPamLen -= pPoint->nContent.GetIndex();
+}
+
+inline void SwHyphArgs::SetRange( const SwNode *pNew )
+{
+ nStart = pStart == pNew ? nPamStart : 0;
+ nLen = pEnd == pNew ? nPamLen : STRING_NOTFOUND;
+}
+
+void SwHyphArgs::SetPam( SwPaM *pPam ) const
+{
+ if( !pNode )
+ *pPam->GetPoint() = *pPam->GetMark();
+ else
+ {
+ pPam->GetPoint()->nNode = nNode;
+ pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
+ pPam->GetMark()->nNode = nNode;
+ pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
+ nWordStart + nWordLen );
+ ASSERT( nNode == pNode->GetIndex(),
+ "SwHyphArgs::SetPam: Pam desaster" );
+ }
+}
+
+// liefert sal_True zurueck, wenn es weitergehen soll.
+sal_Bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
+{
+ // Hyphenate liefert sal_True zurueck, wenn eine Trennstelle anliegt
+ // und stellt pPam ein.
+ SwTxtNode *pNode = rpNd->GetTxtNode();
+ SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
+ if( pNode )
+ {
+ SwCntntFrm* pCntFrm = pNode->GetFrm();
+ if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
+ sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
+ if( pPageCnt && *pPageCnt && pPageSt )
+ {
+ sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
+ if( !*pPageSt )
+ {
+ *pPageSt = nPageNr;
+ if( *pPageCnt < *pPageSt )
+ *pPageCnt = *pPageSt;
+ }
+ long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
+ : nPageNr + *pPageCnt - *pPageSt + 1;
+ ::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
+ }
+ pHyphArgs->SetRange( rpNd );
+ if( pNode->Hyphenate( *pHyphArgs ) )
+ {
+ pHyphArgs->SetNode( rpNd );
+ return sal_False;
+ }
+ }
+ }
+ pHyphArgs->NextNode();
+ return sal_True;
+}
+
+uno::Reference< linguistic::XHyphenatedWord > SwDoc::Hyphenate(
+ SwPaM *pPam, const Point &rCrsrPos,
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ ASSERT(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
+
+ if( *pPam->GetPoint() > *pPam->GetMark() )
+ pPam->Exchange();
+
+ SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
+ SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
+ GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
+ lcl_HyphenateNode, &aHyphArg );
+ aHyphArg.SetPam( pPam );
+ return aHyphArg.GetHyphWord(); // will be set by lcl_HyphenateNode
+}
+
+void ReplaceTabsStr( String& rStr, const String& rSrch, const String& rRepl )
+{
+ xub_StrLen nPos = 0;
+ while( STRING_NOTFOUND != ( nPos = rStr.Search( rSrch, nPos )) )
+ {
+ // wurde das escaped?
+ if( nPos && '\\' == rStr.GetChar( nPos-1 ))
+ {
+ // noch nicht am Ende ??
+ rStr.Erase( nPos-1, 1 ); // den \\ noch loeschen
+ if( nPos >= rStr.Len() )
+ break;
+ }
+ else
+ {
+ rStr.Erase( nPos, rSrch.Len() );
+ rStr.Insert( rRepl, nPos );
+ nPos += rRepl.Len();
+ }
+ }
+}
+
+sal_Bool lcl_GetTokenToParaBreak( String& rStr, String& rRet, sal_Bool bRegExpRplc )
+{
+ sal_Bool bRet = sal_False;
+ if( bRegExpRplc )
+ {
+ xub_StrLen nPos = 0;
+ String sPara( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\\n" )));
+ while( STRING_NOTFOUND != ( nPos = rStr.Search( sPara, nPos )) )
+ {
+ // wurde das escaped?
+ if( nPos && '\\' == rStr.GetChar( nPos-1 ))
+ {
+ if( ++nPos >= rStr.Len() )
+ break;
+ }
+ else
+ {
+ rRet = rStr.Copy( 0, nPos );
+ rStr.Erase( 0, nPos + sPara.Len() );
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ if( !bRet )
+ {
+ rRet = rStr;
+ rStr.Erase();
+ }
+ return bRet;
+}
+
+sal_Bool SwDoc::Replace( SwPaM& rPam, const String& rStr, sal_Bool bRegExpRplc )
+{
+ if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
+ return sal_False;
+
+ sal_Bool bJoinTxt, bJoinPrev;
+ lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
+
+ {
+ // dann eine Kopie vom Cursor erzeugen um alle Pams aus den
+ // anderen Sichten aus dem Loeschbereich zu verschieben
+ // ABER NICHT SICH SELBST !!
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+
+ SwPosition *pStt = (SwPosition*)aDelPam.Start(),
+ *pEnd = (SwPosition*)aDelPam.End();
+ ASSERT( pStt->nNode == pEnd->nNode ||
+ ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
+ !pEnd->nContent.GetIndex() ),
+ "Point & Mark zeigen auf verschiedene Nodes" );
+ sal_Bool bOneNode = pStt->nNode == pEnd->nNode;
+
+ // eigenes Undo ????
+ String sRepl( rStr );
+ SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ xub_StrLen nStt = pStt->nContent.GetIndex(),
+ nEnd = bOneNode ? pEnd->nContent.GetIndex()
+ : pTxtNd->GetTxt().Len();
+ if( bRegExpRplc ) // regulaer suchen ??
+ {
+ String sFndStr( pTxtNd->GetTxt().Copy( nStt, nEnd - nStt ));
+
+//JP 31.03.99: was ist, wenn im gefundenem anderer Inhalt als Text ist,
+// wie z.B. Rahmen, Felder, Fussnoten, ... ???
+// Die aktuelle Implementierung entfernt diese Inhalte einfach.
+// Eigentlich muss der Inhalt immer kopiert werden!
+ sFndStr.EraseAllChars( CH_TXTATR_BREAKWORD );
+ sFndStr.EraseAllChars( CH_TXTATR_INWORD );
+
+ String sTmp( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\\t" )));
+ ReplaceTabsStr( sRepl, String( '&' ), sFndStr );
+ ReplaceTabsStr( sRepl, sTmp, String( '\t' ) );
+ }
+
+ SwDataChanged aTmp( aDelPam, 0 );
+
+ if( IsRedlineOn() )
+ {
+ SwRedlineMode eOld = GetRedlineMode();
+ if( DoesUndo() )
+ {
+ StartUndo();
+
+ // Bug 68584 - if any Redline will change (split!) the node
+ String sNm; sNm = String::CreateFromInt32( (long)&aDelPam );
+ SwBookmark* pBkmk = MakeBookmark( aDelPam,
+ KeyCode(), sNm, sNm, UNO_BOOKMARK );
+
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( REDLINE_ON | REDLINE_SHOW_INSERT | REDLINE_SHOW_DELETE );
+
+ *aDelPam.GetPoint() = pBkmk->GetPos();
+ *aDelPam.GetMark() = *pBkmk->GetOtherPos();
+ DelBookmark( GetBookmarks().GetPos( pBkmk ));
+ pStt = aDelPam.Start();
+ pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ nStt = pStt->nContent.GetIndex();
+ }
+
+ if( sRepl.Len() )
+ {
+ // Attribute des 1. Zeichens ueber den ReplaceText setzen
+ SfxItemSet aSet( GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
+
+ aSet.ClearItem( RES_TXTATR_REFMARK );
+ aSet.ClearItem( RES_TXTATR_TOXMARK );
+
+ if( aDelPam.GetPoint() != aDelPam.End() )
+ aDelPam.Exchange();
+
+ // das Ende merken
+ SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
+ xub_StrLen nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
+
+ sal_Bool bFirst = sal_True;
+ String sIns;
+ while( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExpRplc ))
+ {
+ Insert( aDelPam, sIns );
+ if( bFirst )
+ {
+ SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
+ xub_StrLen nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
+
+ SplitNode( *aDelPam.GetPoint() );
+
+ aMkNd++;
+ aDelPam.GetMark()->nNode = aMkNd;
+ aDelPam.GetMark()->nContent.Assign(
+ aMkNd.GetNode().GetCntntNode(), nMkCnt );
+ bFirst = sal_False;
+ }
+ else
+ SplitNode( *aDelPam.GetPoint() );
+ }
+ if( sIns.Len() )
+ Insert( aDelPam, sIns );
+
+ SwPaM aTmpRange( *aDelPam.GetPoint() );
+ aTmpRange.SetMark();
+
+ aPtNd++;
+ aDelPam.GetPoint()->nNode = aPtNd;
+ aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
+ nPtCnt);
+ *aTmpRange.GetMark() = *aDelPam.GetPoint();
+
+ RstTxtAttr( aTmpRange );
+ Insert( aTmpRange, aSet );
+ }
+
+ if( DoesUndo() )
+ AppendUndo( new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE ));
+ AppendRedline( new SwRedline( REDLINE_DELETE, aDelPam ));
+
+ if( DoesUndo() )
+ {
+ EndUndo();
+
+ // Bug 68584 - if any Redline will change (split!) the node
+ String sNm; sNm = String::CreateFromInt32( (long)&aDelPam );
+ SwBookmark* pBkmk = MakeBookmark( aDelPam,
+ KeyCode(), sNm, sNm, UNO_BOOKMARK );
+
+ SwIndex& rIdx = aDelPam.GetPoint()->nContent;
+ rIdx.Assign( 0, 0 );
+ aDelPam.GetMark()->nContent = rIdx;
+ rPam.GetPoint()->nNode = 0;
+ rPam.GetPoint()->nContent = rIdx;
+ *rPam.GetMark() = *rPam.GetPoint();
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+
+ *rPam.GetPoint() = pBkmk->GetPos();
+ *rPam.GetMark() = *pBkmk->GetOtherPos();
+ DelBookmark( GetBookmarks().GetPos( pBkmk ));
+ }
+ bJoinTxt = sal_False;
+ }
+ else
+ {
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( aDelPam );
+
+ SwUndoReplace* pUndoRpl = 0;
+ if( DoesUndo() )
+ {
+ ClearRedo();
+ SwUndo* pU;
+
+ if( !pUndos->Count() ||
+ UNDO_REPLACE != ( pU = (*pUndos)[ pUndos->Count()-1 ])->GetId() ||
+ ( pUndoRpl = (SwUndoReplace*)pU )->IsFull() )
+ {
+ pUndoRpl = new SwUndoReplace();
+ AppendUndo( pUndoRpl );
+ }
+ pUndoRpl->AddEntry( aDelPam, sRepl, bRegExpRplc );
+ DoUndo( sal_False );
+ }
+
+ if( aDelPam.GetPoint() != pStt )
+ aDelPam.Exchange();
+
+ SwNodeIndex aPtNd( pStt->nNode, -1 );
+ xub_StrLen nPtCnt = pStt->nContent.GetIndex();
+
+ // die Werte nochmal setzen, falls schohn Rahmen oder Fussnoten
+ // auf dem Text entfernt wurden!
+ nStt = nPtCnt;
+ nEnd = bOneNode ? pEnd->nContent.GetIndex()
+ : pTxtNd->GetTxt().Len();
+
+ sal_Bool bFirst = sal_True;
+ String sIns;
+ while( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExpRplc ))
+ {
+ if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
+ Insert( aDelPam, sIns );
+ else if( nStt < nEnd || sIns.Len() )
+ pTxtNd->Replace( pStt->nContent, nEnd - nStt, sIns );
+ SplitNode( *pStt );
+ bFirst = sal_False;
+ }
+
+ if( bFirst || sIns.Len() )
+ {
+ if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
+ Insert( aDelPam, sIns );
+ else if( nStt < nEnd || sIns.Len() )
+ pTxtNd->Replace( pStt->nContent, nEnd - nStt, sIns );
+ }
+
+ *rPam.GetMark() = *aDelPam.GetMark();
+
+ aPtNd++;
+ rPam.GetMark()->nNode = aPtNd;
+ rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
+ nPtCnt );
+ if( bJoinTxt )
+ rPam.Move( fnMoveBackward );
+
+ if( pUndoRpl )
+ {
+ pUndoRpl->SetEntryEnd( rPam );
+ DoUndo( sal_True );
+ }
+ }
+ }
+
+ if( bJoinTxt )
+ lcl_JoinText( rPam, bJoinPrev );
+
+ SetModified();
+ return sal_True;
+}
+
+ // speicher die akt. Werte fuer die automatische Aufnahme von Ausnahmen
+ // in die Autokorrektur
+void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
+{
+ if( pACEWord && pNew != pACEWord )
+ delete pACEWord;
+ pACEWord = pNew;
+}
+
+sal_Bool SwDoc::DelFullPara( SwPaM& rPam )
+{
+ const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
+ const SwNode* pNd = &rStt.nNode.GetNode();
+ sal_uInt32 nSectDiff = pNd->FindStartNode()->EndOfSectionIndex() -
+ pNd->StartOfSectionIndex();
+ sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
+
+ if( nSectDiff-2 <= nNodeDiff || IsRedlineOn() )
+ return sal_False;
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
+ sal_uInt32 nNextNd = rEnd.nNode.GetIndex() + 1;
+ SwTableNode* pTblNd = GetNodes()[ nNextNd ]->GetTableNode();
+ if( pTblNd && pNd->IsCntntNode() )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+//JP 24.08.98: will man wirklich den PageDesc/Break vom
+// nachfolgen Absatz ueberbuegeln?
+// const SwAttrSet& rAttrSet = pTableFmt->GetAttrSet();
+// if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
+// SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
+ {
+ const SfxPoolItem *pItem;
+ const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ {
+ pTableFmt->SetAttr( *pItem );
+ bSavePageDesc = sal_True;
+ }
+
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ {
+ pTableFmt->SetAttr( *pItem );
+ bSavePageBreak = sal_True;
+ }
+ }
+ }
+
+ sal_Bool bDoesUndo = DoesUndo();
+ if( bDoesUndo )
+ {
+ if( !rPam.HasMark() )
+ rPam.SetMark();
+ else if( rPam.GetPoint() == &rStt )
+ rPam.Exchange();
+ rPam.GetPoint()->nNode++;
+
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ rPam.GetMark()->nContent.Assign( 0, 0 );
+
+ ClearRedo();
+ SwUndoDelete* pUndo = new SwUndoDelete( rPam, sal_True );
+ pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
+ AppendUndo( pUndo );
+ }
+ else
+ {
+ SwNodeRange aRg( rStt.nNode, rEnd.nNode );
+ if( rPam.GetPoint() != &rEnd )
+ rPam.Exchange();
+
+ // versuche hinters Ende zu verschieben
+ if( !rPam.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ rPam.Exchange();
+ if( !rPam.Move( fnMoveBackward, fnGoNode ))
+ {
+ ASSERT( sal_False, "kein Node mehr vorhanden" );
+ return sal_False;
+ }
+ }
+ // text::Bookmarks usw. verschieben
+ CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), sal_True );
+
+ // was ist mit Fly's ??
+ {
+ // stehen noch FlyFrames rum, loesche auch diese
+ const SwPosition* pAPos;
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ if( ( FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
+ FLY_AUTO_CNTNT == pAnchor->GetAnchorId() ) &&
+ 0 != ( pAPos = pAnchor->GetCntntAnchor() ) &&
+ aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+ }
+
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ rPam.GetMark()->nContent.Assign( 0, 0 );
+ GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
+ }
+ rPam.DeleteMark();
+ SetModified();
+ return sal_True;
+}
+
+
+