xref: /AOO41X/main/sw/source/core/doc/docedt.cxx (revision 641de097e2e45da05c7073f6a714e738b4e22abb)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <string.h>			// fuer strchr()
28cdf0e10cSrcweir #include <hintids.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <vcl/sound.hxx>
31cdf0e10cSrcweir #include <editeng/cscoitem.hxx>
32cdf0e10cSrcweir #include <editeng/brkitem.hxx>
33cdf0e10cSrcweir #include <linguistic/lngprops.hxx>
34cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
35cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hdl>
36cdf0e10cSrcweir #include <unotools/charclass.hxx>
37cdf0e10cSrcweir #include <unotools/transliterationwrapper.hxx>
38cdf0e10cSrcweir #include <fmtanchr.hxx>
39cdf0e10cSrcweir #include <fmtcntnt.hxx>
40cdf0e10cSrcweir #include <fmtpdsc.hxx>
41cdf0e10cSrcweir #include <txtftn.hxx>
42cdf0e10cSrcweir #include <acorrect.hxx>		// Autokorrektur
43cdf0e10cSrcweir #include <IMark.hxx>		// fuer SwBookmark
44cdf0e10cSrcweir #include <cntfrm.hxx>			// fuers Spell
45cdf0e10cSrcweir #include <crsrsh.hxx>
46cdf0e10cSrcweir #include <doc.hxx>
47cdf0e10cSrcweir #include <UndoManager.hxx>
48cdf0e10cSrcweir #include <docsh.hxx>
49cdf0e10cSrcweir #include <docary.hxx>
50cdf0e10cSrcweir #include <doctxm.hxx>		// beim Move: Verzeichnisse korrigieren
51cdf0e10cSrcweir #include <ftnidx.hxx>
52cdf0e10cSrcweir #include <ftninfo.hxx>
53cdf0e10cSrcweir #include <mdiexp.hxx>		// Statusanzeige
54cdf0e10cSrcweir #include <mvsave.hxx>		// Strukturen zum Sichern beim Move/Delete
55cdf0e10cSrcweir #include <ndtxt.hxx>
56cdf0e10cSrcweir #include <pam.hxx>
57cdf0e10cSrcweir #include <redline.hxx>
58cdf0e10cSrcweir #include <rootfrm.hxx>			// fuers UpdateFtn
59cdf0e10cSrcweir #include <splargs.hxx>		// fuer Spell
60cdf0e10cSrcweir #include <swtable.hxx>
61cdf0e10cSrcweir #include <swundo.hxx>		// fuer die UndoIds
62cdf0e10cSrcweir #include <txtfrm.hxx>
63cdf0e10cSrcweir #include <hints.hxx>
64cdf0e10cSrcweir #include <UndoSplitMove.hxx>
65cdf0e10cSrcweir #include <UndoRedline.hxx>
66cdf0e10cSrcweir #include <UndoOverwrite.hxx>
67cdf0e10cSrcweir #include <UndoInsert.hxx>
68cdf0e10cSrcweir #include <UndoDelete.hxx>
69cdf0e10cSrcweir #include <breakit.hxx>
70cdf0e10cSrcweir #include <hhcwrp.hxx>
71cdf0e10cSrcweir #include <breakit.hxx>
72cdf0e10cSrcweir #include <vcl/msgbox.hxx>
73cdf0e10cSrcweir #include "comcore.hrc"
74cdf0e10cSrcweir #include "editsh.hxx"
753b32dd21SOliver-Rainer Wittmann #include <fldbas.hxx>
763b32dd21SOliver-Rainer Wittmann #include <fmtfld.hxx>
773b32dd21SOliver-Rainer Wittmann #include <docufld.hxx>
78cdf0e10cSrcweir #include <unoflatpara.hxx>
79cdf0e10cSrcweir #include <SwGrammarMarkUp.hxx>
80cdf0e10cSrcweir 
81cdf0e10cSrcweir #include <vector>
82cdf0e10cSrcweir 
83cdf0e10cSrcweir using ::rtl::OUString;
84cdf0e10cSrcweir using namespace ::com::sun::star;
85cdf0e10cSrcweir using namespace ::com::sun::star::linguistic2;
86cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir //using namespace ::utl;
89cdf0e10cSrcweir #ifndef S2U
90cdf0e10cSrcweir #define S2U(rString) OUString::createFromAscii(rString)
91cdf0e10cSrcweir #endif
92cdf0e10cSrcweir 
93cdf0e10cSrcweir struct _SaveRedline
94cdf0e10cSrcweir {
95cdf0e10cSrcweir 	SwRedline* pRedl;
96cdf0e10cSrcweir 	sal_uInt32 nStt, nEnd;
97cdf0e10cSrcweir 	xub_StrLen nSttCnt, nEndCnt;
98cdf0e10cSrcweir 
_SaveRedline_SaveRedline99cdf0e10cSrcweir 	_SaveRedline( SwRedline* pR, const SwNodeIndex& rSttIdx )
100cdf0e10cSrcweir 		: pRedl( pR )
101cdf0e10cSrcweir 	{
102cdf0e10cSrcweir 		const SwPosition* pStt = pR->Start(),
103cdf0e10cSrcweir 			* pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
104cdf0e10cSrcweir 		sal_uInt32 nSttIdx = rSttIdx.GetIndex();
105cdf0e10cSrcweir 		nStt = pStt->nNode.GetIndex() - nSttIdx;
106cdf0e10cSrcweir 		nSttCnt = pStt->nContent.GetIndex();
107cdf0e10cSrcweir 		if( pR->HasMark() )
108cdf0e10cSrcweir 		{
109cdf0e10cSrcweir 			nEnd = pEnd->nNode.GetIndex() - nSttIdx;
110cdf0e10cSrcweir 			nEndCnt = pEnd->nContent.GetIndex();
111cdf0e10cSrcweir 		}
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 		pRedl->GetPoint()->nNode = 0;
114cdf0e10cSrcweir 		pRedl->GetPoint()->nContent.Assign( 0, 0 );
115cdf0e10cSrcweir 		pRedl->GetMark()->nNode = 0;
116cdf0e10cSrcweir 		pRedl->GetMark()->nContent.Assign( 0, 0 );
117cdf0e10cSrcweir 	}
118cdf0e10cSrcweir 
_SaveRedline_SaveRedline119cdf0e10cSrcweir 	_SaveRedline( SwRedline* pR, const SwPosition& rPos )
120cdf0e10cSrcweir 		: pRedl( pR )
121cdf0e10cSrcweir 	{
122cdf0e10cSrcweir 		const SwPosition* pStt = pR->Start(),
123cdf0e10cSrcweir 			* pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
124cdf0e10cSrcweir 		sal_uInt32 nSttIdx = rPos.nNode.GetIndex();
125cdf0e10cSrcweir 		nStt = pStt->nNode.GetIndex() - nSttIdx;
126cdf0e10cSrcweir 		nSttCnt = pStt->nContent.GetIndex();
127cdf0e10cSrcweir         if( nStt == 0 )
128cdf0e10cSrcweir             nSttCnt = nSttCnt - rPos.nContent.GetIndex();
129cdf0e10cSrcweir 		if( pR->HasMark() )
130cdf0e10cSrcweir 		{
131cdf0e10cSrcweir 			nEnd = pEnd->nNode.GetIndex() - nSttIdx;
132cdf0e10cSrcweir 			nEndCnt = pEnd->nContent.GetIndex();
133cdf0e10cSrcweir             if( nEnd == 0 )
134cdf0e10cSrcweir                 nEndCnt = nEndCnt - rPos.nContent.GetIndex();
135cdf0e10cSrcweir 		}
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 		pRedl->GetPoint()->nNode = 0;
138cdf0e10cSrcweir 		pRedl->GetPoint()->nContent.Assign( 0, 0 );
139cdf0e10cSrcweir 		pRedl->GetMark()->nNode = 0;
140cdf0e10cSrcweir 		pRedl->GetMark()->nContent.Assign( 0, 0 );
141cdf0e10cSrcweir 	}
142cdf0e10cSrcweir 
SetPos_SaveRedline143cdf0e10cSrcweir 	void SetPos( sal_uInt32 nInsPos )
144cdf0e10cSrcweir 	{
145cdf0e10cSrcweir 		pRedl->GetPoint()->nNode = nInsPos + nStt;
146cdf0e10cSrcweir 		pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
147cdf0e10cSrcweir 		if( pRedl->HasMark() )
148cdf0e10cSrcweir 		{
149cdf0e10cSrcweir 			pRedl->GetMark()->nNode = nInsPos + nEnd;
150cdf0e10cSrcweir 			pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt );
151cdf0e10cSrcweir 		}
152cdf0e10cSrcweir 	}
153cdf0e10cSrcweir 
SetPos_SaveRedline154cdf0e10cSrcweir 	void SetPos( const SwPosition& aPos )
155cdf0e10cSrcweir 	{
156cdf0e10cSrcweir 		pRedl->GetPoint()->nNode = aPos.nNode.GetIndex() + nStt;
157cdf0e10cSrcweir         pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt + ( nStt == 0 ? aPos.nContent.GetIndex() : 0 ) );
158cdf0e10cSrcweir 		if( pRedl->HasMark() )
159cdf0e10cSrcweir 		{
160cdf0e10cSrcweir 			pRedl->GetMark()->nNode = aPos.nNode.GetIndex() + nEnd;
161cdf0e10cSrcweir 			pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt  + ( nEnd == 0 ? aPos.nContent.GetIndex() : 0 ) );
162cdf0e10cSrcweir 		}
163cdf0e10cSrcweir 	}
164cdf0e10cSrcweir };
165cdf0e10cSrcweir 
166cdf0e10cSrcweir SV_DECL_PTRARR_DEL( _SaveRedlines, _SaveRedline*, 0, 4 )
167cdf0e10cSrcweir 
SV_IMPL_VARARR(_SaveFlyArr,_SaveFly)168cdf0e10cSrcweir SV_IMPL_VARARR( _SaveFlyArr, _SaveFly )
169cdf0e10cSrcweir SV_IMPL_PTRARR( _SaveRedlines, _SaveRedline* )
170cdf0e10cSrcweir 
171cdf0e10cSrcweir bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
172cdf0e10cSrcweir {
173cdf0e10cSrcweir     sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
174cdf0e10cSrcweir     return !( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
175cdf0e10cSrcweir               (0 != pNode->GetTxtAttrForCharAt( nPos ) ) );
176cdf0e10cSrcweir }
177cdf0e10cSrcweir 
lcl_SkipAttr(const SwTxtNode * pNode,SwIndex & rIdx,xub_StrLen & rStart)178cdf0e10cSrcweir void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir 	if( !lcl_MayOverwrite( pNode, rStart ) )
181cdf0e10cSrcweir 	{
182cdf0e10cSrcweir 		// ueberspringe alle SonderAttribute
183cdf0e10cSrcweir 		do {
184cdf0e10cSrcweir 			// "Beep" bei jedem ausgelassenen
185cdf0e10cSrcweir 			Sound::Beep(SOUND_ERROR);
186cdf0e10cSrcweir 			rIdx++;
187cdf0e10cSrcweir 		} while( (rStart = rIdx.GetIndex()) < pNode->GetTxt().Len()
188cdf0e10cSrcweir 			   && !lcl_MayOverwrite(pNode, rStart) );
189cdf0e10cSrcweir 	}
190cdf0e10cSrcweir }
191cdf0e10cSrcweir 
192cdf0e10cSrcweir // -----------------------------------------------------------------
193cdf0e10cSrcweir 
_RestFlyInRange(_SaveFlyArr & rArr,const SwNodeIndex & rSttIdx,const SwNodeIndex * pInsertPos)194cdf0e10cSrcweir void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx,
195cdf0e10cSrcweir                       const SwNodeIndex* pInsertPos )
196cdf0e10cSrcweir {
197cdf0e10cSrcweir 	SwPosition aPos( rSttIdx );
198cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
199cdf0e10cSrcweir 	{
200cdf0e10cSrcweir 		// neuen Anker anlegen
201cdf0e10cSrcweir 		_SaveFly& rSave = rArr[n];
202cdf0e10cSrcweir 		SwFrmFmt* pFmt = rSave.pFrmFmt;
203cdf0e10cSrcweir 
204cdf0e10cSrcweir         if( rSave.bInsertPosition )
205cdf0e10cSrcweir         {
206cdf0e10cSrcweir             if( pInsertPos != NULL )
207cdf0e10cSrcweir                 aPos.nNode = *pInsertPos;
208cdf0e10cSrcweir             else
209cdf0e10cSrcweir                 aPos.nNode = rSttIdx.GetIndex();
210cdf0e10cSrcweir         }
211cdf0e10cSrcweir         else
212cdf0e10cSrcweir             aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 		aPos.nContent.Assign( 0, 0 );
215cdf0e10cSrcweir 		SwFmtAnchor aAnchor( pFmt->GetAnchor() );
216cdf0e10cSrcweir 		aAnchor.SetAnchor( &aPos );
217cdf0e10cSrcweir 		pFmt->GetDoc()->GetSpzFrmFmts()->Insert(
218cdf0e10cSrcweir 				pFmt, pFmt->GetDoc()->GetSpzFrmFmts()->Count() );
219cdf0e10cSrcweir         pFmt->SetFmtAttr( aAnchor );
220cdf0e10cSrcweir 		SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
221cdf0e10cSrcweir 		if( pCNd && pCNd->getLayoutFrm( pFmt->GetDoc()->GetCurrentLayout(), 0, 0, sal_False ) )
222cdf0e10cSrcweir 			pFmt->MakeFrms();
223cdf0e10cSrcweir 	}
224cdf0e10cSrcweir }
225cdf0e10cSrcweir 
_SaveFlyInRange(const SwNodeRange & rRg,_SaveFlyArr & rArr)226cdf0e10cSrcweir void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
227cdf0e10cSrcweir {
228cdf0e10cSrcweir 	SwSpzFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
229cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir         SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>(rFmts[n]);
232cdf0e10cSrcweir         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
233cdf0e10cSrcweir         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
234cdf0e10cSrcweir         if (pAPos &&
235cdf0e10cSrcweir             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
236cdf0e10cSrcweir              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
237cdf0e10cSrcweir 			rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
238cdf0e10cSrcweir 		{
239cdf0e10cSrcweir 			_SaveFly aSave( pAPos->nNode.GetIndex() - rRg.aStart.GetIndex(),
240cdf0e10cSrcweir                             pFmt, sal_False );
241cdf0e10cSrcweir 			rArr.Insert( aSave, rArr.Count());
242cdf0e10cSrcweir 			pFmt->DelFrms();
243cdf0e10cSrcweir 			rFmts.Remove( n--, 1 );
244cdf0e10cSrcweir 		}
245cdf0e10cSrcweir 	}
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
_SaveFlyInRange(const SwPaM & rPam,const SwNodeIndex & rInsPos,_SaveFlyArr & rArr,bool bMoveAllFlys)248cdf0e10cSrcweir void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
249cdf0e10cSrcweir 					   _SaveFlyArr& rArr, bool bMoveAllFlys )
250cdf0e10cSrcweir {
251cdf0e10cSrcweir 	SwSpzFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
252cdf0e10cSrcweir 	SwFrmFmt* pFmt;
253cdf0e10cSrcweir 	const SwFmtAnchor* pAnchor;
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 	const SwPosition* pPos = rPam.Start();
256cdf0e10cSrcweir 	const SwNodeIndex& rSttNdIdx = pPos->nNode;
257cdf0e10cSrcweir 	short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
258cdf0e10cSrcweir 					pPos->nContent.GetIndex()) ? 1 : 0;
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 	pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
261cdf0e10cSrcweir 	const SwNodeIndex& rEndNdIdx = pPos->nNode;
262cdf0e10cSrcweir 	short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
263cdf0e10cSrcweir 				pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
264cdf0e10cSrcweir 					? 0 : 1;
265cdf0e10cSrcweir 
266cdf0e10cSrcweir 	const SwNodeIndex* pCntntIdx;
267cdf0e10cSrcweir 
268cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
269cdf0e10cSrcweir 	{
270cdf0e10cSrcweir 		sal_Bool bInsPos = sal_False;
271cdf0e10cSrcweir 		pFmt = (SwFrmFmt*)rFmts[n];
272cdf0e10cSrcweir 		pAnchor = &pFmt->GetAnchor();
273cdf0e10cSrcweir         const SwPosition* pAPos = pAnchor->GetCntntAnchor();
274cdf0e10cSrcweir         if (pAPos &&
275cdf0e10cSrcweir             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
276cdf0e10cSrcweir              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
277cdf0e10cSrcweir 			// nicht verschieben, wenn die InsPos im CntntBereich vom Fly ist
278cdf0e10cSrcweir 			( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
279cdf0e10cSrcweir 			  !( *pCntntIdx < rInsPos &&
280cdf0e10cSrcweir 				rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
281cdf0e10cSrcweir 		{
282cdf0e10cSrcweir 			if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
283cdf0e10cSrcweir 			{
284cdf0e10cSrcweir 				// wenn nur teil vom EndNode oder der EndNode und SttNode
285cdf0e10cSrcweir 				// identisch sind, chaos::Anchor nicht anfassen
286cdf0e10cSrcweir 				if( rSttNdIdx != pAPos->nNode )
287cdf0e10cSrcweir 				{
288cdf0e10cSrcweir 					// Anker nur an Anfang/Ende haengen
289cdf0e10cSrcweir 					SwPosition aPos( rSttNdIdx );
290cdf0e10cSrcweir 					SwFmtAnchor aAnchor( *pAnchor );
291cdf0e10cSrcweir 					aAnchor.SetAnchor( &aPos );
292cdf0e10cSrcweir                     pFmt->SetFmtAttr( aAnchor );
293cdf0e10cSrcweir //        	        ((SwFmtAnchor*)pAnchor)->SetAnchor( &aPos );
294cdf0e10cSrcweir 				}
295cdf0e10cSrcweir 			}
296cdf0e10cSrcweir 			else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
297cdf0e10cSrcweir 					&& pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
298cdf0e10cSrcweir 						0 != ( bInsPos = rInsPos == pAPos->nNode ))
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 			{
301cdf0e10cSrcweir 				_SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
302cdf0e10cSrcweir                                 pFmt, bInsPos );
303cdf0e10cSrcweir 				rArr.Insert( aSave, rArr.Count());
304cdf0e10cSrcweir 				pFmt->DelFrms();
305cdf0e10cSrcweir 				rFmts.Remove( n--, 1 );
306cdf0e10cSrcweir 			}
307cdf0e10cSrcweir 		}
308cdf0e10cSrcweir 	}
309cdf0e10cSrcweir }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir // -----------------------------------------------------------------
312cdf0e10cSrcweir 
313cdf0e10cSrcweir // loesche und verschiebe alle "Fly's am Absatz", die in der SSelection
314cdf0e10cSrcweir // liegen. Steht am SPoint ein Fly, wird dieser auf den Mark verschoben.
315cdf0e10cSrcweir 
DelFlyInRange(const SwNodeIndex & rMkNdIdx,const SwNodeIndex & rPtNdIdx)316cdf0e10cSrcweir void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
317cdf0e10cSrcweir 					const SwNodeIndex& rPtNdIdx )
318cdf0e10cSrcweir {
319cdf0e10cSrcweir 	const sal_Bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 	SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
322cdf0e10cSrcweir 	SwSpzFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
323cdf0e10cSrcweir 	for ( sal_uInt16 i = rTbl.Count(); i; )
324cdf0e10cSrcweir 	{
325cdf0e10cSrcweir 		SwFrmFmt *pFmt = rTbl[--i];
326cdf0e10cSrcweir 		const SwFmtAnchor &rAnch = pFmt->GetAnchor();
327cdf0e10cSrcweir         SwPosition const*const pAPos = rAnch.GetCntntAnchor();
328cdf0e10cSrcweir         if (pAPos &&
329cdf0e10cSrcweir             ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
330cdf0e10cSrcweir              (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
331cdf0e10cSrcweir 			( bDelFwrd
332cdf0e10cSrcweir 				? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
333cdf0e10cSrcweir 				: rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
334cdf0e10cSrcweir 		{
335cdf0e10cSrcweir 			// nur den Anker verschieben ??
336cdf0e10cSrcweir 			if( rPtNdIdx == pAPos->nNode )
337cdf0e10cSrcweir 			{
338cdf0e10cSrcweir 				SwFmtAnchor aAnch( pFmt->GetAnchor() );
339cdf0e10cSrcweir 				SwPosition aPos( rMkNdIdx );
340cdf0e10cSrcweir 				aAnch.SetAnchor( &aPos );
341cdf0e10cSrcweir                 pFmt->SetFmtAttr( aAnch );
342cdf0e10cSrcweir 			}
343cdf0e10cSrcweir 			else
344cdf0e10cSrcweir 			{
345cdf0e10cSrcweir 				// wird der Fly geloescht muss auch im seinem Inhalt alle
346cdf0e10cSrcweir 				// Flys geloescht werden !!
347cdf0e10cSrcweir 				const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
348cdf0e10cSrcweir 				if( rCntnt.GetCntntIdx() )
349cdf0e10cSrcweir 				{
350cdf0e10cSrcweir 					DelFlyInRange( *rCntnt.GetCntntIdx(),
351cdf0e10cSrcweir 									SwNodeIndex( *rCntnt.GetCntntIdx()->
352cdf0e10cSrcweir 											GetNode().EndOfSectionNode() ));
353cdf0e10cSrcweir 					// Position kann sich verschoben haben !
354cdf0e10cSrcweir 					if( i > rTbl.Count() )
355cdf0e10cSrcweir 						i = rTbl.Count();
356cdf0e10cSrcweir 					else if( pFmt != rTbl[i] )
357cdf0e10cSrcweir 						i = rTbl.GetPos( pFmt );
358cdf0e10cSrcweir 				}
359cdf0e10cSrcweir 
360cdf0e10cSrcweir 				pDoc->DelLayoutFmt( pFmt );
361cdf0e10cSrcweir 
362cdf0e10cSrcweir                 // --> FME 2004-10-06 #117913# DelLayoutFmt can also
363cdf0e10cSrcweir                 // trigger the deletion of objects.
364cdf0e10cSrcweir     			if( i > rTbl.Count() )
365cdf0e10cSrcweir 					i = rTbl.Count();
366cdf0e10cSrcweir                 // <--
367cdf0e10cSrcweir             }
368cdf0e10cSrcweir 		}
369cdf0e10cSrcweir 	}
370cdf0e10cSrcweir }
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 
lcl_SaveFtn(const SwNodeIndex & rSttNd,const SwNodeIndex & rEndNd,const SwNodeIndex & rInsPos,SwFtnIdxs & rFtnArr,SwFtnIdxs & rSaveArr,const SwIndex * pSttCnt=0,const SwIndex * pEndCnt=0)373cdf0e10cSrcweir bool lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
374cdf0e10cSrcweir 				 const SwNodeIndex& rInsPos,
375cdf0e10cSrcweir 				 SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
376cdf0e10cSrcweir 				 const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
377cdf0e10cSrcweir {
378cdf0e10cSrcweir 	bool bUpdateFtn = sal_False;
379cdf0e10cSrcweir     const SwNodes& rNds = rInsPos.GetNodes();
380cdf0e10cSrcweir     const bool bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
381cdf0e10cSrcweir                 rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
382cdf0e10cSrcweir     const bool bSaveFtn = !bDelFtn &&
383cdf0e10cSrcweir                     rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
384cdf0e10cSrcweir 	if( rFtnArr.Count() )
385cdf0e10cSrcweir 	{
386cdf0e10cSrcweir 
387cdf0e10cSrcweir 		sal_uInt16 nPos;
388cdf0e10cSrcweir 		rFtnArr.SeekEntry( rSttNd, &nPos );
389cdf0e10cSrcweir 		SwTxtFtn* pSrch;
390cdf0e10cSrcweir 		const SwNode* pFtnNd;
391cdf0e10cSrcweir 
392cdf0e10cSrcweir 		// loesche/sicher erstmal alle, die dahinter stehen
393cdf0e10cSrcweir 		while( nPos < rFtnArr.Count() && ( pFtnNd =
394cdf0e10cSrcweir 			&( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
395cdf0e10cSrcweir 					<= rEndNd.GetIndex() )
396cdf0e10cSrcweir 		{
397cdf0e10cSrcweir 			xub_StrLen nFtnSttIdx = *pSrch->GetStart();
398cdf0e10cSrcweir 			if( ( pEndCnt && pSttCnt )
399cdf0e10cSrcweir 				? (( &rSttNd.GetNode() == pFtnNd &&
400cdf0e10cSrcweir 					 pSttCnt->GetIndex() > nFtnSttIdx) ||
401cdf0e10cSrcweir 				   ( &rEndNd.GetNode() == pFtnNd &&
402cdf0e10cSrcweir 					nFtnSttIdx >= pEndCnt->GetIndex() ))
403cdf0e10cSrcweir 				: ( &rEndNd.GetNode() == pFtnNd ))
404cdf0e10cSrcweir 			{
405cdf0e10cSrcweir 				++nPos;		// weiter suchen
406cdf0e10cSrcweir 			}
407cdf0e10cSrcweir 			else
408cdf0e10cSrcweir 			{
409cdf0e10cSrcweir 				// dann weg damit
410cdf0e10cSrcweir 				if( bDelFtn )
411cdf0e10cSrcweir 				{
412cdf0e10cSrcweir 					SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
413cdf0e10cSrcweir 					SwIndex aIdx( &rTxtNd, nFtnSttIdx );
414cdf0e10cSrcweir                     rTxtNd.EraseText( aIdx, 1 );
415cdf0e10cSrcweir                 }
416cdf0e10cSrcweir 				else
417cdf0e10cSrcweir 				{
418cdf0e10cSrcweir 					pSrch->DelFrms(0);
419cdf0e10cSrcweir 					rFtnArr.Remove( nPos );
420cdf0e10cSrcweir 					if( bSaveFtn )
421cdf0e10cSrcweir 						rSaveArr.Insert( pSrch );
422cdf0e10cSrcweir 				}
423cdf0e10cSrcweir 				bUpdateFtn = sal_True;
424cdf0e10cSrcweir 			}
425cdf0e10cSrcweir 		}
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 		while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
428cdf0e10cSrcweir 				GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
429cdf0e10cSrcweir 		{
430cdf0e10cSrcweir 			xub_StrLen nFtnSttIdx = *pSrch->GetStart();
431cdf0e10cSrcweir 			if( !pEndCnt || !pSttCnt ||
432cdf0e10cSrcweir 				!( (( &rSttNd.GetNode() == pFtnNd &&
433cdf0e10cSrcweir 					pSttCnt->GetIndex() > nFtnSttIdx ) ||
434cdf0e10cSrcweir 				   ( &rEndNd.GetNode() == pFtnNd &&
435cdf0e10cSrcweir 					nFtnSttIdx >= pEndCnt->GetIndex() )) ))
436cdf0e10cSrcweir 			{
437cdf0e10cSrcweir 				if( bDelFtn )
438cdf0e10cSrcweir 				{
439cdf0e10cSrcweir 					// dann weg damit
440cdf0e10cSrcweir 					SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
441cdf0e10cSrcweir 					SwIndex aIdx( &rTxtNd, nFtnSttIdx );
442cdf0e10cSrcweir                     rTxtNd.EraseText( aIdx, 1 );
443cdf0e10cSrcweir                 }
444cdf0e10cSrcweir 				else
445cdf0e10cSrcweir 				{
446cdf0e10cSrcweir 					pSrch->DelFrms(0);
447cdf0e10cSrcweir 					rFtnArr.Remove( nPos );
448cdf0e10cSrcweir 					if( bSaveFtn )
449cdf0e10cSrcweir 						rSaveArr.Insert( pSrch );
450cdf0e10cSrcweir 				}
451cdf0e10cSrcweir 				bUpdateFtn = sal_True;
452cdf0e10cSrcweir 			}
453cdf0e10cSrcweir 		}
454cdf0e10cSrcweir 	}
455cdf0e10cSrcweir     // When moving from redline section into document content section, e.g.
456cdf0e10cSrcweir     // after loading a document with (delete-)redlines, the footnote array
457cdf0e10cSrcweir     // has to be adjusted... (#i70572)
458cdf0e10cSrcweir     if( bSaveFtn )
459cdf0e10cSrcweir     {
460cdf0e10cSrcweir         SwNodeIndex aIdx( rSttNd );
461cdf0e10cSrcweir         while( aIdx < rEndNd ) // Check the moved section
462cdf0e10cSrcweir         {
463cdf0e10cSrcweir             SwNode* pNode = &aIdx.GetNode();
464cdf0e10cSrcweir             if( pNode->IsTxtNode() ) // Looking for text nodes...
465cdf0e10cSrcweir             {
466cdf0e10cSrcweir                 SwpHints *pHints =
467cdf0e10cSrcweir                     static_cast<SwTxtNode*>(pNode)->GetpSwpHints();
468cdf0e10cSrcweir                 if( pHints && pHints->HasFtn() ) //...with footnotes
469cdf0e10cSrcweir                 {
470cdf0e10cSrcweir                     bUpdateFtn = sal_True; // Heureka
471cdf0e10cSrcweir                     sal_uInt16 nCount = pHints->Count();
472cdf0e10cSrcweir                     for( sal_uInt16 i = 0; i < nCount; ++i )
473cdf0e10cSrcweir                     {
474cdf0e10cSrcweir                         SwTxtAttr *pAttr = pHints->GetTextHint( i );
475cdf0e10cSrcweir                         if ( pAttr->Which() == RES_TXTATR_FTN )
476cdf0e10cSrcweir                         {
477cdf0e10cSrcweir                             rSaveArr.Insert( static_cast<SwTxtFtn*>(pAttr) );
478cdf0e10cSrcweir                         }
479cdf0e10cSrcweir                     }
480cdf0e10cSrcweir                 }
481cdf0e10cSrcweir             }
482cdf0e10cSrcweir             ++aIdx;
483cdf0e10cSrcweir         }
484cdf0e10cSrcweir     }
485cdf0e10cSrcweir 	return bUpdateFtn;
486cdf0e10cSrcweir }
487cdf0e10cSrcweir 
lcl_SaveRedlines(const SwPaM & aPam,_SaveRedlines & rArr)488cdf0e10cSrcweir void lcl_SaveRedlines( const SwPaM& aPam, _SaveRedlines& rArr )
489cdf0e10cSrcweir {
490cdf0e10cSrcweir 	SwDoc* pDoc = aPam.GetNode()->GetDoc();
491cdf0e10cSrcweir 
492cdf0e10cSrcweir     const SwPosition* pStart = aPam.Start();
493cdf0e10cSrcweir     const SwPosition* pEnd = aPam.End();
494cdf0e10cSrcweir 
495cdf0e10cSrcweir     // get first relevant redline
496cdf0e10cSrcweir 	sal_uInt16 nCurrentRedline;
497cdf0e10cSrcweir     pDoc->GetRedline( *pStart, &nCurrentRedline );
498cdf0e10cSrcweir     if( nCurrentRedline > 0)
499cdf0e10cSrcweir         nCurrentRedline--;
500cdf0e10cSrcweir 
501cdf0e10cSrcweir     // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
502cdf0e10cSrcweir 	RedlineMode_t eOld = pDoc->GetRedlineMode();
503cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     // iterate over relevant redlines and decide for each whether it should
506cdf0e10cSrcweir     // be saved, or split + saved
507cdf0e10cSrcweir 	SwRedlineTbl& rRedlineTable = const_cast<SwRedlineTbl&>( pDoc->GetRedlineTbl() );
508cdf0e10cSrcweir     for( ; nCurrentRedline < rRedlineTable.Count(); nCurrentRedline++ )
509cdf0e10cSrcweir     {
510cdf0e10cSrcweir         SwRedline* pCurrent = rRedlineTable[ nCurrentRedline ];
511cdf0e10cSrcweir         SwComparePosition eCompare =
512cdf0e10cSrcweir             ComparePosition( *pCurrent->Start(), *pCurrent->End(),
513cdf0e10cSrcweir                              *pStart, *pEnd);
514cdf0e10cSrcweir 
515cdf0e10cSrcweir         // we must save this redline if it overlaps aPam
516cdf0e10cSrcweir         // (we may have to split it, too)
517cdf0e10cSrcweir         if( eCompare == POS_OVERLAP_BEHIND  ||
518cdf0e10cSrcweir             eCompare == POS_OVERLAP_BEFORE  ||
519cdf0e10cSrcweir             eCompare == POS_OUTSIDE ||
520cdf0e10cSrcweir             eCompare == POS_INSIDE ||
521cdf0e10cSrcweir             eCompare == POS_EQUAL )
522cdf0e10cSrcweir         {
523cdf0e10cSrcweir 			rRedlineTable.Remove( nCurrentRedline-- );
524cdf0e10cSrcweir 
525cdf0e10cSrcweir             // split beginning, if necessary
526cdf0e10cSrcweir             if( eCompare == POS_OVERLAP_BEFORE  ||
527cdf0e10cSrcweir                 eCompare == POS_OUTSIDE )
528cdf0e10cSrcweir             {
529cdf0e10cSrcweir 
530cdf0e10cSrcweir                 SwRedline* pNewRedline = new SwRedline( *pCurrent );
531cdf0e10cSrcweir 			    *pNewRedline->End() = *pStart;
532cdf0e10cSrcweir 			    *pCurrent->Start() = *pStart;
533cdf0e10cSrcweir                 pDoc->AppendRedline( pNewRedline, true );
534cdf0e10cSrcweir             }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir             // split end, if necessary
537cdf0e10cSrcweir             if( eCompare == POS_OVERLAP_BEHIND  ||
538cdf0e10cSrcweir                 eCompare == POS_OUTSIDE )
539cdf0e10cSrcweir             {
540cdf0e10cSrcweir                 SwRedline* pNewRedline = new SwRedline( *pCurrent );
541cdf0e10cSrcweir 	    		*pNewRedline->Start() = *pEnd;
542cdf0e10cSrcweir 		    	*pCurrent->End() = *pEnd;
543cdf0e10cSrcweir                 pDoc->AppendRedline( pNewRedline, true );
544cdf0e10cSrcweir             }
545cdf0e10cSrcweir 
546cdf0e10cSrcweir             // save the current redline
547cdf0e10cSrcweir             _SaveRedline* pSave = new _SaveRedline( pCurrent, *pStart );
548cdf0e10cSrcweir             rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
549cdf0e10cSrcweir         }
550cdf0e10cSrcweir     }
551cdf0e10cSrcweir 
552cdf0e10cSrcweir     // restore old redline mode
553cdf0e10cSrcweir     pDoc->SetRedlineMode_intern( eOld );
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
lcl_RestoreRedlines(SwDoc * pDoc,const SwPosition & rPos,_SaveRedlines & rArr)556cdf0e10cSrcweir void lcl_RestoreRedlines( SwDoc* pDoc, const SwPosition& rPos, _SaveRedlines& rArr )
557cdf0e10cSrcweir {
558cdf0e10cSrcweir 	RedlineMode_t eOld = pDoc->GetRedlineMode();
559cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
560cdf0e10cSrcweir 
561cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
562cdf0e10cSrcweir 	{
563cdf0e10cSrcweir 		_SaveRedline* pSave = rArr[ n ];
564cdf0e10cSrcweir 		pSave->SetPos( rPos );
565cdf0e10cSrcweir 		pDoc->AppendRedline( pSave->pRedl, true );
566cdf0e10cSrcweir 	}
567cdf0e10cSrcweir 
568cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( eOld );
569cdf0e10cSrcweir }
570cdf0e10cSrcweir 
571cdf0e10cSrcweir 
lcl_SaveRedlines(const SwNodeRange & rRg,_SaveRedlines & rArr)572cdf0e10cSrcweir void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
573cdf0e10cSrcweir {
574cdf0e10cSrcweir 	SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
575cdf0e10cSrcweir 	sal_uInt16 nRedlPos;
576cdf0e10cSrcweir 	SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
577cdf0e10cSrcweir 	aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
578cdf0e10cSrcweir 	if( pDoc->GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
579cdf0e10cSrcweir 		--nRedlPos;
580cdf0e10cSrcweir 	else if( nRedlPos >= pDoc->GetRedlineTbl().Count() )
581cdf0e10cSrcweir 		return ;
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 	RedlineMode_t eOld = pDoc->GetRedlineMode();
584cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
585cdf0e10cSrcweir 	SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
586cdf0e10cSrcweir 
587cdf0e10cSrcweir 	do {
588cdf0e10cSrcweir 		SwRedline* pTmp = rRedlTbl[ nRedlPos ];
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 		const SwPosition* pRStt = pTmp->Start(),
591cdf0e10cSrcweir 						* pREnd = pTmp->GetMark() == pRStt
592cdf0e10cSrcweir 							? pTmp->GetPoint() : pTmp->GetMark();
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 		if( pRStt->nNode < rRg.aStart )
595cdf0e10cSrcweir 		{
596cdf0e10cSrcweir 			if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
597cdf0e10cSrcweir 			{
598cdf0e10cSrcweir 				// Kopie erzeugen und Ende vom Original ans Ende des
599cdf0e10cSrcweir 				// MoveBereiches setzen. Die Kopie wird mit verschoben
600cdf0e10cSrcweir 				SwRedline* pNewRedl = new SwRedline( *pTmp );
601cdf0e10cSrcweir 				SwPosition* pTmpPos = pNewRedl->Start();
602cdf0e10cSrcweir 				pTmpPos->nNode = rRg.aStart;
603cdf0e10cSrcweir 				pTmpPos->nContent.Assign(
604cdf0e10cSrcweir 							pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
605cdf0e10cSrcweir 
606cdf0e10cSrcweir 				_SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
607cdf0e10cSrcweir //				rArr.Insert( pSave, rArr.Count() );
608cdf0e10cSrcweir 				rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
609cdf0e10cSrcweir 
610cdf0e10cSrcweir 				pTmpPos = pTmp->End();
611cdf0e10cSrcweir 				pTmpPos->nNode = rRg.aEnd;
612cdf0e10cSrcweir 				pTmpPos->nContent.Assign(
613cdf0e10cSrcweir 							pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
614cdf0e10cSrcweir 			}
615cdf0e10cSrcweir 			else if( pREnd->nNode == rRg.aStart )
616cdf0e10cSrcweir 			{
617cdf0e10cSrcweir 				SwPosition* pTmpPos = pTmp->End();
618cdf0e10cSrcweir 				pTmpPos->nNode = rRg.aEnd;
619cdf0e10cSrcweir 				pTmpPos->nContent.Assign(
620cdf0e10cSrcweir 							pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
621cdf0e10cSrcweir 			}
622cdf0e10cSrcweir 		}
623cdf0e10cSrcweir 		else if( pRStt->nNode < rRg.aEnd )
624cdf0e10cSrcweir 		{
625cdf0e10cSrcweir 			rRedlTbl.Remove( nRedlPos-- );
626cdf0e10cSrcweir 			if( pREnd->nNode < rRg.aEnd ||
627cdf0e10cSrcweir 				( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
628cdf0e10cSrcweir 			{
629cdf0e10cSrcweir 				// gesamt verschieben
630cdf0e10cSrcweir 				_SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
631cdf0e10cSrcweir //				rArr.Insert( pSave, rArr.Count() );
632cdf0e10cSrcweir 				rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
633cdf0e10cSrcweir 			}
634cdf0e10cSrcweir 			else
635cdf0e10cSrcweir 			{
636cdf0e10cSrcweir 				// aufsplitten
637cdf0e10cSrcweir 				SwRedline* pNewRedl = new SwRedline( *pTmp );
638cdf0e10cSrcweir 				SwPosition* pTmpPos = pNewRedl->End();
639cdf0e10cSrcweir 				pTmpPos->nNode = rRg.aEnd;
640cdf0e10cSrcweir 				pTmpPos->nContent.Assign(
641cdf0e10cSrcweir 							pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
642cdf0e10cSrcweir 
643cdf0e10cSrcweir 				_SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
644cdf0e10cSrcweir //				rArr.Insert( pSave, rArr.Count() );
645cdf0e10cSrcweir 				rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
646cdf0e10cSrcweir 
647cdf0e10cSrcweir 				pTmpPos = pTmp->Start();
648cdf0e10cSrcweir 				pTmpPos->nNode = rRg.aEnd;
649cdf0e10cSrcweir 				pTmpPos->nContent.Assign(
650cdf0e10cSrcweir 							pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
651cdf0e10cSrcweir 				pDoc->AppendRedline( pTmp, true );
652cdf0e10cSrcweir 			}
653cdf0e10cSrcweir 		}
654cdf0e10cSrcweir 		else
655cdf0e10cSrcweir 			break;
656cdf0e10cSrcweir 
657cdf0e10cSrcweir 	} while( ++nRedlPos < pDoc->GetRedlineTbl().Count() );
658cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( eOld );
659cdf0e10cSrcweir }
660cdf0e10cSrcweir 
lcl_RestoreRedlines(SwDoc * pDoc,sal_uInt32 nInsPos,_SaveRedlines & rArr)661cdf0e10cSrcweir void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
662cdf0e10cSrcweir {
663cdf0e10cSrcweir 	RedlineMode_t eOld = pDoc->GetRedlineMode();
664cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 	for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
667cdf0e10cSrcweir 	{
668cdf0e10cSrcweir 		_SaveRedline* pSave = rArr[ n ];
669cdf0e10cSrcweir 		pSave->SetPos( nInsPos );
670cdf0e10cSrcweir 		pDoc->AppendRedline( pSave->pRedl, true );
671cdf0e10cSrcweir 	}
672cdf0e10cSrcweir 
673cdf0e10cSrcweir 	pDoc->SetRedlineMode_intern( eOld );
674cdf0e10cSrcweir }
675cdf0e10cSrcweir 
676cdf0e10cSrcweir // ------------------------------------------------------------------------
677cdf0e10cSrcweir // #i59534: Redo of insertion of multiple text nodes runs into trouble
678cdf0e10cSrcweir // because of unnecessary expanded redlines
679cdf0e10cSrcweir // From now on this class saves the redline positions of all redlines which ends exact at the
680cdf0e10cSrcweir // insert position (node _and_ content index)
681cdf0e10cSrcweir 
_SaveRedlEndPosForRestore(const SwNodeIndex & rInsIdx,xub_StrLen nCnt)682cdf0e10cSrcweir _SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, xub_StrLen nCnt )
683cdf0e10cSrcweir 	: pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt )
684cdf0e10cSrcweir {
685cdf0e10cSrcweir 	SwNode& rNd = rInsIdx.GetNode();
686cdf0e10cSrcweir 	SwDoc* pDest = rNd.GetDoc();
687cdf0e10cSrcweir 	if( pDest->GetRedlineTbl().Count() )
688cdf0e10cSrcweir 	{
689cdf0e10cSrcweir 		sal_uInt16 nFndPos;
690cdf0e10cSrcweir 		const SwPosition* pEnd;
691cdf0e10cSrcweir 		SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), nCnt ));
692cdf0e10cSrcweir 		const SwRedline* pRedl = pDest->GetRedline( aSrcPos, &nFndPos );
693cdf0e10cSrcweir 		while( nFndPos-- && *( pEnd = ( pRedl =
694cdf0e10cSrcweir 			pDest->GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos && *pRedl->Start() < aSrcPos )
695cdf0e10cSrcweir 		{
696cdf0e10cSrcweir 			if( !pSavArr )
697cdf0e10cSrcweir 			{
698cdf0e10cSrcweir 				pSavArr = new SvPtrarr( 2, 2 );
699cdf0e10cSrcweir 				pSavIdx = new SwNodeIndex( rInsIdx, -1 );
700cdf0e10cSrcweir 			}
701cdf0e10cSrcweir 			void* p = (void*)pEnd;
702cdf0e10cSrcweir 			pSavArr->Insert( p, pSavArr->Count() );
703cdf0e10cSrcweir 		}
704cdf0e10cSrcweir 	}
705cdf0e10cSrcweir }
706cdf0e10cSrcweir 
~_SaveRedlEndPosForRestore()707cdf0e10cSrcweir _SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
708cdf0e10cSrcweir {
709cdf0e10cSrcweir 	if( pSavArr )
710cdf0e10cSrcweir 	{
711cdf0e10cSrcweir 		delete pSavArr;
712cdf0e10cSrcweir 		delete pSavIdx;
713cdf0e10cSrcweir 	}
714cdf0e10cSrcweir }
715cdf0e10cSrcweir 
_Restore()716cdf0e10cSrcweir void _SaveRedlEndPosForRestore::_Restore()
717cdf0e10cSrcweir {
718cdf0e10cSrcweir 	(*pSavIdx)++;
719cdf0e10cSrcweir     SwCntntNode* pNode = pSavIdx->GetNode().GetCntntNode();
720cdf0e10cSrcweir     // If there's no content node at the remembered position, we will not restore the old position
721cdf0e10cSrcweir     // This may happen if a table (or section?) will be inserted.
722cdf0e10cSrcweir     if( pNode )
723cdf0e10cSrcweir     {
724cdf0e10cSrcweir         SwPosition aPos( *pSavIdx, SwIndex( pNode, nSavCntnt ));
725cdf0e10cSrcweir         for( sal_uInt16 n = pSavArr->Count(); n; )
726cdf0e10cSrcweir             *((SwPosition*)pSavArr->GetObject( --n )) = aPos;
727cdf0e10cSrcweir     }
728cdf0e10cSrcweir }
729cdf0e10cSrcweir 
730cdf0e10cSrcweir 
731cdf0e10cSrcweir // ------------------------------------------------------------------------
732cdf0e10cSrcweir 
733cdf0e10cSrcweir // Loeschen einer vollstaendigen Section des NodesArray.
734cdf0e10cSrcweir // Der uebergebene Node steht irgendwo in der gewuenschten Section
DeleteSection(SwNode * pNode)735cdf0e10cSrcweir void SwDoc::DeleteSection( SwNode *pNode )
736cdf0e10cSrcweir {
737cdf0e10cSrcweir 	ASSERT( pNode, "Kein Node uebergeben." );
738cdf0e10cSrcweir 	SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
739cdf0e10cSrcweir 											   : pNode->StartOfSectionNode();
740cdf0e10cSrcweir 	SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
741cdf0e10cSrcweir 
742cdf0e10cSrcweir 	// dann loesche mal alle Fly's, text::Bookmarks, ...
743cdf0e10cSrcweir 	DelFlyInRange( aSttIdx, aEndIdx );
744cdf0e10cSrcweir 	DeleteRedline( *pSttNd, true, USHRT_MAX );
745cdf0e10cSrcweir 	_DelBookmarks(aSttIdx, aEndIdx);
746cdf0e10cSrcweir 
747cdf0e10cSrcweir 	{
748cdf0e10cSrcweir 		// alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
749cdf0e10cSrcweir 		SwNodeIndex aMvStt( aSttIdx, 1 );
750cdf0e10cSrcweir 		CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), sal_True );
751cdf0e10cSrcweir 	}
752cdf0e10cSrcweir 
753cdf0e10cSrcweir 	GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
754cdf0e10cSrcweir }
755cdf0e10cSrcweir 
756cdf0e10cSrcweir 
SetModified(SwPaM & rPaM)757cdf0e10cSrcweir void SwDoc::SetModified(SwPaM &rPaM)
758cdf0e10cSrcweir {
759cdf0e10cSrcweir     SwDataChanged aTmp( rPaM, 0 );
760cdf0e10cSrcweir     SetModified();
761cdf0e10cSrcweir }
762cdf0e10cSrcweir 
763cdf0e10cSrcweir /*************************************************************************
764cdf0e10cSrcweir  *				  SwDoc::Overwrite()
765cdf0e10cSrcweir  ************************************************************************/
766cdf0e10cSrcweir 
Overwrite(const SwPaM & rRg,const String & rStr)767cdf0e10cSrcweir bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
768cdf0e10cSrcweir {
769cdf0e10cSrcweir 	SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
770cdf0e10cSrcweir 	if( pACEWord )					// Aufnahme in die Autokorrektur
771cdf0e10cSrcweir 	{
772cdf0e10cSrcweir 		if( 1 == rStr.Len() )
773cdf0e10cSrcweir 			pACEWord->CheckChar( rPt, rStr.GetChar( 0 ) );
774cdf0e10cSrcweir 		delete pACEWord, pACEWord = 0;
775cdf0e10cSrcweir 	}
776cdf0e10cSrcweir 
777cdf0e10cSrcweir 	SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
778cdf0e10cSrcweir 	if(!pNode)
779cdf0e10cSrcweir 		return sal_False;
780cdf0e10cSrcweir 
781cdf0e10cSrcweir     if (GetIDocumentUndoRedo().DoesUndo())
782cdf0e10cSrcweir     {
783cdf0e10cSrcweir         GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
784cdf0e10cSrcweir     }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir 	sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
787cdf0e10cSrcweir 								? pNode->GetpSwpHints()->Count() : 0;
788cdf0e10cSrcweir 	SwDataChanged aTmp( rRg, 0 );
789cdf0e10cSrcweir 	SwIndex& rIdx = rPt.nContent;
790cdf0e10cSrcweir 	xub_StrLen nStart = 0;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 	sal_Unicode c;
793cdf0e10cSrcweir 	String aStr;
794cdf0e10cSrcweir 
795cdf0e10cSrcweir 	sal_Bool bOldExpFlg = pNode->IsIgnoreDontExpand();
796cdf0e10cSrcweir 	pNode->SetIgnoreDontExpand( sal_True );
797cdf0e10cSrcweir 
798cdf0e10cSrcweir 	for( xub_StrLen nCnt = 0; nCnt < rStr.Len(); ++nCnt )
799cdf0e10cSrcweir 	{
800cdf0e10cSrcweir 		// hinter das Zeichen (zum aufspannen der Attribute !!)
801cdf0e10cSrcweir         nStart = rIdx.GetIndex();
802cdf0e10cSrcweir         if ( nStart < pNode->GetTxt().Len() )
803cdf0e10cSrcweir         {
804cdf0e10cSrcweir             lcl_SkipAttr( pNode, rIdx, nStart );
805cdf0e10cSrcweir         }
806cdf0e10cSrcweir 		c = rStr.GetChar( nCnt );
807cdf0e10cSrcweir         if (GetIDocumentUndoRedo().DoesUndo())
808cdf0e10cSrcweir         {
809cdf0e10cSrcweir             bool bMerged(false);
810cdf0e10cSrcweir             if (GetIDocumentUndoRedo().DoesGroupUndo())
811cdf0e10cSrcweir             {
812cdf0e10cSrcweir                 SwUndo *const pUndo = GetUndoManager().GetLastUndo();
813cdf0e10cSrcweir                 SwUndoOverwrite *const pUndoOW(
814cdf0e10cSrcweir                     dynamic_cast<SwUndoOverwrite *>(pUndo) );
815cdf0e10cSrcweir                 if (pUndoOW)
816cdf0e10cSrcweir                 {
817cdf0e10cSrcweir                     // if CanGrouping() returns true it's already merged
818cdf0e10cSrcweir                     bMerged = pUndoOW->CanGrouping( this, rPt, c );
819cdf0e10cSrcweir                 }
820cdf0e10cSrcweir             }
821cdf0e10cSrcweir             if (!bMerged)
822cdf0e10cSrcweir             {
823cdf0e10cSrcweir                 SwUndo *const pUndoOW( new SwUndoOverwrite(this, rPt, c) );
824cdf0e10cSrcweir                 GetIDocumentUndoRedo().AppendUndo(pUndoOW);
825cdf0e10cSrcweir             }
826cdf0e10cSrcweir         }
827cdf0e10cSrcweir         else
828cdf0e10cSrcweir         {
829cdf0e10cSrcweir 			// hinter das Zeichen (zum Aufspannen der Attribute !!)
830cdf0e10cSrcweir 			if( nStart < pNode->GetTxt().Len() )
831cdf0e10cSrcweir 				rIdx++;
832cdf0e10cSrcweir             pNode->InsertText( c, rIdx, INS_EMPTYEXPAND );
833cdf0e10cSrcweir 			if( nStart+1 < rIdx.GetIndex() )
834cdf0e10cSrcweir 			{
835cdf0e10cSrcweir 				rIdx = nStart;
836cdf0e10cSrcweir                 pNode->EraseText( rIdx, 1 );
837cdf0e10cSrcweir 				rIdx++;
838cdf0e10cSrcweir 			}
839cdf0e10cSrcweir 		}
840cdf0e10cSrcweir 	}
841cdf0e10cSrcweir 	pNode->SetIgnoreDontExpand( bOldExpFlg );
842cdf0e10cSrcweir 
843cdf0e10cSrcweir 	sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
844cdf0e10cSrcweir 								? pNode->GetpSwpHints()->Count() : 0;
845cdf0e10cSrcweir 	if( nOldAttrCnt != nNewAttrCnt )
846cdf0e10cSrcweir 	{
847cdf0e10cSrcweir 		SwUpdateAttr aHint( 0, 0, 0 );
848cdf0e10cSrcweir         pNode->ModifyBroadcast( 0, &aHint, TYPE( SwCrsrShell ) );
849cdf0e10cSrcweir 	}
850cdf0e10cSrcweir 
851cdf0e10cSrcweir     if (!GetIDocumentUndoRedo().DoesUndo() &&
852cdf0e10cSrcweir         !IsIgnoreRedline() && GetRedlineTbl().Count())
853cdf0e10cSrcweir     {
854cdf0e10cSrcweir 		SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
855cdf0e10cSrcweir 		DeleteRedline( aPam, true, USHRT_MAX );
856cdf0e10cSrcweir 	}
857cdf0e10cSrcweir 	else if( IsRedlineOn() )
858cdf0e10cSrcweir 	{
859cdf0e10cSrcweir         // FIXME: this redline is WRONG: there is no DELETE, and the skipped
860cdf0e10cSrcweir         // characters are also included in aPam
861cdf0e10cSrcweir 		SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
862cdf0e10cSrcweir 		AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
863cdf0e10cSrcweir 	}
864cdf0e10cSrcweir 
865cdf0e10cSrcweir 	SetModified();
866cdf0e10cSrcweir 	return sal_True;
867cdf0e10cSrcweir }
868cdf0e10cSrcweir 
869cdf0e10cSrcweir 
MoveAndJoin(SwPaM & rPaM,SwPosition & rPos,SwMoveFlags eMvFlags)870cdf0e10cSrcweir bool SwDoc::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
871cdf0e10cSrcweir {
872cdf0e10cSrcweir 	SwNodeIndex aIdx( rPaM.Start()->nNode );
873cdf0e10cSrcweir 	sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
874cdf0e10cSrcweir 	sal_Bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
875cdf0e10cSrcweir 	aIdx--;				// vor den Move Bereich !!
876cdf0e10cSrcweir 
877cdf0e10cSrcweir     bool bRet = MoveRange( rPaM, rPos, eMvFlags );
878cdf0e10cSrcweir 	if( bRet && !bOneNode )
879cdf0e10cSrcweir 	{
880cdf0e10cSrcweir 		if( bJoinTxt )
881cdf0e10cSrcweir 			aIdx++;
882cdf0e10cSrcweir 		SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
883cdf0e10cSrcweir 		SwNodeIndex aNxtIdx( aIdx );
884cdf0e10cSrcweir 		if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
885cdf0e10cSrcweir 		{
886cdf0e10cSrcweir 			{   // Block wegen SwIndex in den Node !!
887cdf0e10cSrcweir 				CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex( pTxtNd,
888cdf0e10cSrcweir 							pTxtNd->GetTxt().Len() ) ), 0, sal_True );
889cdf0e10cSrcweir 			}
890cdf0e10cSrcweir 			pTxtNd->JoinNext();
891cdf0e10cSrcweir 		}
892cdf0e10cSrcweir 	}
893cdf0e10cSrcweir 	return bRet;
894cdf0e10cSrcweir }
895cdf0e10cSrcweir 
896cdf0e10cSrcweir // mst: it seems that this is mostly used by SwDoc internals; the only
897cdf0e10cSrcweir // way to call this from the outside seems to be the special case in
898cdf0e10cSrcweir // SwDoc::CopyRange (but i have not managed to actually hit that case)
MoveRange(SwPaM & rPaM,SwPosition & rPos,SwMoveFlags eMvFlags)899cdf0e10cSrcweir bool SwDoc::MoveRange( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
900cdf0e10cSrcweir {
901cdf0e10cSrcweir 	// keine Moves-Abfangen
902cdf0e10cSrcweir 	const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
903cdf0e10cSrcweir 	if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
904cdf0e10cSrcweir         return false;
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 	// sicher die absatzgebundenen Flys, damit sie verschoben werden koennen.
907cdf0e10cSrcweir 	_SaveFlyArr aSaveFlyArr;
908cdf0e10cSrcweir 	_SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, 0 != ( DOC_MOVEALLFLYS & eMvFlags ) );
909cdf0e10cSrcweir 
910cdf0e10cSrcweir     // save redlines (if DOC_MOVEREDLINES is used)
911cdf0e10cSrcweir     _SaveRedlines aSaveRedl( 0, 4 );
912cdf0e10cSrcweir 	if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
913cdf0e10cSrcweir 	{
914cdf0e10cSrcweir 		lcl_SaveRedlines( rPaM, aSaveRedl );
915cdf0e10cSrcweir 
916cdf0e10cSrcweir         // #i17764# unfortunately, code below relies on undos being
917cdf0e10cSrcweir         //          in a particular order, and presence of bookmarks
918cdf0e10cSrcweir         //          will change this order. Hence, we delete bookmarks
919cdf0e10cSrcweir         //          here without undo.
920cdf0e10cSrcweir         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
921cdf0e10cSrcweir         _DelBookmarks(
922cdf0e10cSrcweir             pStt->nNode,
923cdf0e10cSrcweir             pEnd->nNode,
924cdf0e10cSrcweir             NULL,
925cdf0e10cSrcweir             &pStt->nContent,
926cdf0e10cSrcweir             &pEnd->nContent);
927cdf0e10cSrcweir     }
928cdf0e10cSrcweir 
929cdf0e10cSrcweir 
930cdf0e10cSrcweir 	int bUpdateFtn = sal_False;
931cdf0e10cSrcweir 	SwFtnIdxs aTmpFntIdx;
932cdf0e10cSrcweir 
933cdf0e10cSrcweir 	// falls Undo eingeschaltet, erzeuge das UndoMove-Objekt
934cdf0e10cSrcweir 	SwUndoMove * pUndoMove = 0;
935cdf0e10cSrcweir     if (GetIDocumentUndoRedo().DoesUndo())
936cdf0e10cSrcweir     {
937cdf0e10cSrcweir         GetIDocumentUndoRedo().ClearRedo();
938cdf0e10cSrcweir 		pUndoMove = new SwUndoMove( rPaM, rPos );
939cdf0e10cSrcweir         pUndoMove->SetMoveRedlines( eMvFlags == DOC_MOVEREDLINES );
940cdf0e10cSrcweir 	}
941cdf0e10cSrcweir 	else
942cdf0e10cSrcweir 	{
943cdf0e10cSrcweir 		bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
944cdf0e10cSrcweir 									GetFtnIdxs(), aTmpFntIdx,
945cdf0e10cSrcweir 									&pStt->nContent, &pEnd->nContent );
946cdf0e10cSrcweir 	}
947cdf0e10cSrcweir 
948cdf0e10cSrcweir 	sal_Bool bSplit = sal_False;
949cdf0e10cSrcweir     SwPaM aSavePam( rPos, rPos );
950cdf0e10cSrcweir 
951cdf0e10cSrcweir 	// stelle den SPoint an den Anfang vom Bereich (Definition)
952cdf0e10cSrcweir 	if( rPaM.GetPoint() == pEnd )
953cdf0e10cSrcweir 		rPaM.Exchange();
954cdf0e10cSrcweir 
955cdf0e10cSrcweir 	// in der EditShell wird nach dem Move ein JoinNext erzeugt, wenn
956cdf0e10cSrcweir 	// vor und nach dem Move ein Text-Node steht.
957cdf0e10cSrcweir 	SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
958cdf0e10cSrcweir 	sal_Bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
959cdf0e10cSrcweir 
960cdf0e10cSrcweir 	// werden ein oder mehr TextNodes bewegt, so wird
961cdf0e10cSrcweir 	// im SwNodes::Move ein SplitNode erzeugt. Dieser Updated aber nicht
962cdf0e10cSrcweir 	// den Cursor. Um das zu verhindern, wird hier ein TextNode angelegt,
963cdf0e10cSrcweir 	// um die Updaterei der Indizies zu erhalten. Nach dem Move wird
964cdf0e10cSrcweir 	// evt. der Node geloescht.
965cdf0e10cSrcweir 
966cdf0e10cSrcweir 	SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
967cdf0e10cSrcweir 	if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
968cdf0e10cSrcweir 		( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam  )) )
969cdf0e10cSrcweir 	{
970cdf0e10cSrcweir 		bSplit = sal_True;
971cdf0e10cSrcweir 		xub_StrLen nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
972cdf0e10cSrcweir 
973cdf0e10cSrcweir 		SvULongs aBkmkArr( 15, 15 );
974cdf0e10cSrcweir 		_SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
975cdf0e10cSrcweir 						aBkmkArr, SAVEFLY_SPLIT );
976cdf0e10cSrcweir 
977cdf0e10cSrcweir         pTNd = static_cast<SwTxtNode*>(pTNd->SplitCntntNode( rPos ));
978cdf0e10cSrcweir 
979cdf0e10cSrcweir 		if( aBkmkArr.Count() )
980cdf0e10cSrcweir 			_RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
981cdf0e10cSrcweir 
982cdf0e10cSrcweir 		// jetzt noch den Pam berichtigen !!
983cdf0e10cSrcweir 		if( rPos.nNode == rPaM.GetMark()->nNode )
984cdf0e10cSrcweir 		{
985cdf0e10cSrcweir 			rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
986cdf0e10cSrcweir 			rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
987cdf0e10cSrcweir 		}
988cdf0e10cSrcweir 	}
989cdf0e10cSrcweir 
990cdf0e10cSrcweir 	// setze den Pam um einen "Inhalt" zurueck; dadurch steht er immer
991cdf0e10cSrcweir 	// ausserhalb des manipulierten Bereiches. Falls kein Inhalt mehr vor-
992cdf0e10cSrcweir 	// handen, dann auf den StartNode (es ist immer einer vorhanden !!!)
993cdf0e10cSrcweir     sal_Bool bNullCntnt = !aSavePam.Move( fnMoveBackward, fnGoCntnt );
994cdf0e10cSrcweir 	if( bNullCntnt )
995cdf0e10cSrcweir     {
996cdf0e10cSrcweir         aSavePam.GetPoint()->nNode--;
997cdf0e10cSrcweir     }
998cdf0e10cSrcweir 
999cdf0e10cSrcweir     // kopiere alle Bookmarks, die im Move Bereich stehen in ein
1000cdf0e10cSrcweir     // Array, das alle Angaben auf die Position als Offset speichert.
1001cdf0e10cSrcweir     // Die neue Zuordung erfolgt nach dem Moven.
1002cdf0e10cSrcweir     ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
1003cdf0e10cSrcweir     _DelBookmarks(
1004cdf0e10cSrcweir         pStt->nNode,
1005cdf0e10cSrcweir         pEnd->nNode,
1006cdf0e10cSrcweir         &aSaveBkmks,
1007cdf0e10cSrcweir         &pStt->nContent,
1008cdf0e10cSrcweir         &pEnd->nContent);
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir 	// falls durch die vorherigen Loeschungen (z.B. der Fussnoten) kein
1011cdf0e10cSrcweir 	// Bereich mehr existiert, ist das immernoch ein gueltiger Move!
1012cdf0e10cSrcweir 	if( *rPaM.GetPoint() != *rPaM.GetMark() )
1013cdf0e10cSrcweir 	{
1014cdf0e10cSrcweir         // now do the actual move
1015cdf0e10cSrcweir         GetNodes().MoveRange( rPaM, rPos, GetNodes() );
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir         // after a MoveRange() the Mark is deleted
1018cdf0e10cSrcweir         if ( rPaM.HasMark() ) // => no Move occurred!
1019cdf0e10cSrcweir         {
1020cdf0e10cSrcweir 			delete pUndoMove;
1021cdf0e10cSrcweir             return false;
1022cdf0e10cSrcweir         }
1023cdf0e10cSrcweir     }
1024cdf0e10cSrcweir 	else
1025cdf0e10cSrcweir 		rPaM.DeleteMark();
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir     ASSERT( *aSavePam.GetMark() == rPos ||
1028cdf0e10cSrcweir             ( aSavePam.GetMark()->nNode.GetNode().GetCntntNode() == NULL ),
1029cdf0e10cSrcweir 			"PaM wurde nicht verschoben, am Anfang/Ende keine ContentNodes?" );
1030cdf0e10cSrcweir     *aSavePam.GetMark() = rPos;
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir 	rPaM.SetMark();			// um den neuen Bereich eine Sel. aufspannen
1033cdf0e10cSrcweir     pTNd = aSavePam.GetNode()->GetTxtNode();
1034cdf0e10cSrcweir     if (GetIDocumentUndoRedo().DoesUndo())
1035cdf0e10cSrcweir     {
1036cdf0e10cSrcweir 		// korrigiere erstmal den Content vom SavePam
1037cdf0e10cSrcweir 		if( bNullCntnt )
1038cdf0e10cSrcweir         {
1039cdf0e10cSrcweir             aSavePam.GetPoint()->nContent = 0;
1040cdf0e10cSrcweir         }
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir 		// die Methode SwEditShell::Move() fuegt nach dem Move den Text-Node
1043cdf0e10cSrcweir 		// zusammen, in dem der rPaM steht. Wurde der Inhalt nach hinten
1044cdf0e10cSrcweir 		// geschoben und liegt der SPoint vom SavePam im naechsten Node, so
1045cdf0e10cSrcweir 		// muss beim Speichern vom Undo-Object das beachtet werden !!
1046cdf0e10cSrcweir         SwTxtNode * pPamTxtNd = 0;
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir 		// wird ans SwUndoMove weitergegeben, das dann beim Undo JoinNext
1049cdf0e10cSrcweir 		// aufruft. (falls es hier nicht moeglich ist).
1050cdf0e10cSrcweir 		sal_Bool bJoin = bSplit && pTNd;
1051cdf0e10cSrcweir 		bCorrSavePam = bCorrSavePam &&
1052cdf0e10cSrcweir 						0 != ( pPamTxtNd = rPaM.GetNode()->GetTxtNode() )
1053cdf0e10cSrcweir 						&& pPamTxtNd->CanJoinNext()
1054cdf0e10cSrcweir                         && (*rPaM.GetPoint() <= *aSavePam.GetPoint());
1055cdf0e10cSrcweir 
1056cdf0e10cSrcweir 		// muessen am SavePam 2 Nodes zusammengefasst werden ??
1057cdf0e10cSrcweir 		if( bJoin && pTNd->CanJoinNext() )
1058cdf0e10cSrcweir 		{
1059cdf0e10cSrcweir 			pTNd->JoinNext();
1060cdf0e10cSrcweir 			// kein temp. sdbcx::Index bei &&
1061cdf0e10cSrcweir 			// es sollten wohl nur die Indexwerte verglichen werden.
1062cdf0e10cSrcweir 			if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
1063cdf0e10cSrcweir                                 aSavePam.GetPoint()->nNode.GetIndex() )
1064cdf0e10cSrcweir             {
1065cdf0e10cSrcweir                 aSavePam.GetPoint()->nContent += pPamTxtNd->Len();
1066cdf0e10cSrcweir             }
1067cdf0e10cSrcweir 			bJoin = sal_False;
1068cdf0e10cSrcweir 		}
1069cdf0e10cSrcweir //		else if( !bCorrSavePam && !pSavePam->Move( fnMoveForward, fnGoCntnt ))
1070cdf0e10cSrcweir         else if ( !aSavePam.Move( fnMoveForward, fnGoCntnt ) )
1071cdf0e10cSrcweir         {
1072cdf0e10cSrcweir             aSavePam.GetPoint()->nNode++;
1073cdf0e10cSrcweir         }
1074cdf0e10cSrcweir 
1075cdf0e10cSrcweir 		// zwischen SPoint und GetMark steht jetzt der neu eingefuegte Bereich
1076cdf0e10cSrcweir         pUndoMove->SetDestRange( aSavePam, *rPaM.GetPoint(),
1077cdf0e10cSrcweir 									bJoin, bCorrSavePam );
1078cdf0e10cSrcweir         GetIDocumentUndoRedo().AppendUndo( pUndoMove );
1079cdf0e10cSrcweir     }
1080cdf0e10cSrcweir     else
1081cdf0e10cSrcweir     {
1082cdf0e10cSrcweir         bool bRemove = true;
1083cdf0e10cSrcweir 		// muessen am SavePam 2 Nodes zusammengefasst werden ??
1084cdf0e10cSrcweir 		if( bSplit && pTNd )
1085cdf0e10cSrcweir 		{
1086cdf0e10cSrcweir 			if( pTNd->CanJoinNext())
1087cdf0e10cSrcweir             {
1088cdf0e10cSrcweir                 // --> OD 2009-08-20 #i100466#
1089cdf0e10cSrcweir                 // Always join next, because <pTNd> has to stay as it is.
1090cdf0e10cSrcweir                 // A join previous from its next would more or less delete <pTNd>
1091cdf0e10cSrcweir                 pTNd->JoinNext();
1092cdf0e10cSrcweir                 // <--
1093cdf0e10cSrcweir                 bRemove = false;
1094cdf0e10cSrcweir             }
1095cdf0e10cSrcweir 		}
1096cdf0e10cSrcweir 		if( bNullCntnt )
1097cdf0e10cSrcweir         {
1098cdf0e10cSrcweir             aSavePam.GetPoint()->nNode++;
1099cdf0e10cSrcweir             aSavePam.GetPoint()->nContent.Assign( aSavePam.GetCntntNode(), 0 );
1100cdf0e10cSrcweir         }
1101cdf0e10cSrcweir 		else if( bRemove ) // No move forward after joining with next paragraph
1102cdf0e10cSrcweir         {
1103cdf0e10cSrcweir             aSavePam.Move( fnMoveForward, fnGoCntnt );
1104cdf0e10cSrcweir         }
1105cdf0e10cSrcweir 	}
1106cdf0e10cSrcweir 
1107cdf0e10cSrcweir     // setze jetzt wieder die text::Bookmarks in das Dokument
1108cdf0e10cSrcweir     *rPaM.GetMark() = *aSavePam.Start();
1109cdf0e10cSrcweir     for(
1110cdf0e10cSrcweir         ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
1111cdf0e10cSrcweir         pBkmk != aSaveBkmks.end();
1112cdf0e10cSrcweir         ++pBkmk)
1113cdf0e10cSrcweir         pBkmk->SetInDoc(
1114cdf0e10cSrcweir             this,
1115cdf0e10cSrcweir             rPaM.GetMark()->nNode,
1116cdf0e10cSrcweir             &rPaM.GetMark()->nContent);
1117cdf0e10cSrcweir     *rPaM.GetPoint() = *aSavePam.End();
1118cdf0e10cSrcweir 
1119cdf0e10cSrcweir 	// verschiebe die Flys an die neue Position
1120cdf0e10cSrcweir 	_RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode, &(rPos.nNode) );
1121cdf0e10cSrcweir 
1122cdf0e10cSrcweir     // restore redlines (if DOC_MOVEREDLINES is used)
1123cdf0e10cSrcweir 	if( aSaveRedl.Count() )
1124cdf0e10cSrcweir     {
1125cdf0e10cSrcweir         lcl_RestoreRedlines( this, *aSavePam.Start(), aSaveRedl );
1126cdf0e10cSrcweir     }
1127cdf0e10cSrcweir 
1128cdf0e10cSrcweir     if( bUpdateFtn )
1129cdf0e10cSrcweir 	{
1130cdf0e10cSrcweir 		if( aTmpFntIdx.Count() )
1131cdf0e10cSrcweir 		{
1132cdf0e10cSrcweir 			GetFtnIdxs().Insert( &aTmpFntIdx );
1133cdf0e10cSrcweir 			aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
1134cdf0e10cSrcweir 		}
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir 		GetFtnIdxs().UpdateAllFtn();
1137cdf0e10cSrcweir 	}
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir 	SetModified();
1140cdf0e10cSrcweir     return true;
1141cdf0e10cSrcweir }
1142cdf0e10cSrcweir 
MoveNodeRange(SwNodeRange & rRange,SwNodeIndex & rPos,SwMoveFlags eMvFlags)1143cdf0e10cSrcweir bool SwDoc::MoveNodeRange( SwNodeRange& rRange, SwNodeIndex& rPos,
1144cdf0e10cSrcweir         SwMoveFlags eMvFlags )
1145cdf0e10cSrcweir {
1146cdf0e10cSrcweir 	// bewegt alle Nodes an die neue Position. Dabei werden die
1147cdf0e10cSrcweir 	// text::Bookmarks mit verschoben !! (zur Zeit ohne Undo)
1148cdf0e10cSrcweir 
1149cdf0e10cSrcweir 	// falls durchs Move Fussnoten in den Sonderbereich kommen sollten,
1150cdf0e10cSrcweir 	// dann entferne sie jetzt.
1151cdf0e10cSrcweir 	//JP 13.07.95:
1152cdf0e10cSrcweir 	// ansonsten bei allen Fussnoten, die verschoben werden, die Frames
1153cdf0e10cSrcweir 	// loeschen und nach dem Move wieder aufbauen lassen (Fussnoten koennen
1154cdf0e10cSrcweir 	// die Seite wechseln). Zusaetzlich muss natuerlich die Sortierung
1155cdf0e10cSrcweir 	// der FtnIdx-Array wieder korrigiert werden.
1156cdf0e10cSrcweir 
1157cdf0e10cSrcweir 	int bUpdateFtn = sal_False;
1158cdf0e10cSrcweir 	SwFtnIdxs aTmpFntIdx;
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir 	SwUndoMove* pUndo = 0;
1161cdf0e10cSrcweir     if ((DOC_CREATEUNDOOBJ & eMvFlags ) && GetIDocumentUndoRedo().DoesUndo())
1162cdf0e10cSrcweir     {
1163cdf0e10cSrcweir 		pUndo = new SwUndoMove( this, rRange, rPos );
1164cdf0e10cSrcweir     }
1165cdf0e10cSrcweir     else
1166cdf0e10cSrcweir     {
1167cdf0e10cSrcweir 		bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
1168cdf0e10cSrcweir 									GetFtnIdxs(), aTmpFntIdx );
1169cdf0e10cSrcweir     }
1170cdf0e10cSrcweir 
1171cdf0e10cSrcweir 	_SaveRedlines aSaveRedl( 0, 4 );
1172cdf0e10cSrcweir 	SvPtrarr aSavRedlInsPosArr( 0, 4 );
1173cdf0e10cSrcweir 	if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
1174cdf0e10cSrcweir 	{
1175cdf0e10cSrcweir 		lcl_SaveRedlines( rRange, aSaveRedl );
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir 		// suche alle Redlines, die an der InsPos aufhoeren. Diese muessen
1178cdf0e10cSrcweir 		// nach dem Move wieder an die "alte" Position verschoben werden
1179cdf0e10cSrcweir 		sal_uInt16 nRedlPos = GetRedlinePos( rPos.GetNode(), USHRT_MAX );
1180cdf0e10cSrcweir 		if( USHRT_MAX != nRedlPos )
1181cdf0e10cSrcweir 		{
1182cdf0e10cSrcweir 			const SwPosition *pRStt, *pREnd;
1183cdf0e10cSrcweir 			do {
1184cdf0e10cSrcweir 				SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
1185cdf0e10cSrcweir 				pRStt = pTmp->Start();
1186cdf0e10cSrcweir 				pREnd = pTmp->End();
1187cdf0e10cSrcweir 				if( pREnd->nNode == rPos && pRStt->nNode < rPos )
1188cdf0e10cSrcweir 				{
1189cdf0e10cSrcweir 					void* p = pTmp;
1190cdf0e10cSrcweir 					aSavRedlInsPosArr.Insert( p, aSavRedlInsPosArr.Count() );
1191cdf0e10cSrcweir 				}
1192cdf0e10cSrcweir 			} while( pRStt->nNode < rPos && ++nRedlPos < GetRedlineTbl().Count());
1193cdf0e10cSrcweir 		}
1194cdf0e10cSrcweir 	}
1195cdf0e10cSrcweir 
1196cdf0e10cSrcweir     // kopiere alle Bookmarks, die im Move Bereich stehen in ein
1197cdf0e10cSrcweir     // Array, das alle Angaben auf die Position als Offset speichert.
1198cdf0e10cSrcweir     // Die neue Zuordung erfolgt nach dem Moven.
1199cdf0e10cSrcweir     ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
1200cdf0e10cSrcweir     _DelBookmarks(rRange.aStart, rRange.aEnd, &aSaveBkmks);
1201cdf0e10cSrcweir 
1202cdf0e10cSrcweir 	// sicher die absatzgebundenen Flys, damit verschoben werden koennen.
1203cdf0e10cSrcweir 	_SaveFlyArr aSaveFlyArr;
1204cdf0e10cSrcweir 	if( GetSpzFrmFmts()->Count() )
1205cdf0e10cSrcweir 		_SaveFlyInRange( rRange, aSaveFlyArr );
1206cdf0e10cSrcweir 
1207cdf0e10cSrcweir 	// vor die Position setzen, damit er nicht weitergeschoben wird
1208cdf0e10cSrcweir 	SwNodeIndex aIdx( rPos, -1 );
1209cdf0e10cSrcweir 
1210cdf0e10cSrcweir 	SwNodeIndex* pSaveInsPos = 0;
1211cdf0e10cSrcweir 	if( pUndo )
1212cdf0e10cSrcweir 		pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
1213cdf0e10cSrcweir 
1214cdf0e10cSrcweir 	// verschiebe die Nodes
1215cdf0e10cSrcweir     sal_Bool bNoDelFrms = 0 != (DOC_NO_DELFRMS & eMvFlags);
1216cdf0e10cSrcweir 	if( GetNodes()._MoveNodes( rRange, GetNodes(), rPos, !bNoDelFrms ) )
1217cdf0e10cSrcweir 	{
1218cdf0e10cSrcweir 		aIdx++;		// wieder auf alte Position
1219cdf0e10cSrcweir 		if( pSaveInsPos )
1220cdf0e10cSrcweir 			(*pSaveInsPos)++;
1221cdf0e10cSrcweir 	}
1222cdf0e10cSrcweir 	else
1223cdf0e10cSrcweir 	{
1224cdf0e10cSrcweir 		aIdx = rRange.aStart;
1225cdf0e10cSrcweir 		delete pUndo, pUndo = 0;
1226cdf0e10cSrcweir 	}
1227cdf0e10cSrcweir 
1228cdf0e10cSrcweir 	// verschiebe die Flys an die neue Position
1229cdf0e10cSrcweir 	if( aSaveFlyArr.Count() )
1230cdf0e10cSrcweir 		_RestFlyInRange( aSaveFlyArr, aIdx, NULL );
1231cdf0e10cSrcweir 
1232cdf0e10cSrcweir 	// setze jetzt wieder die text::Bookmarks in das Dokument
1233cdf0e10cSrcweir     for(
1234cdf0e10cSrcweir         ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
1235cdf0e10cSrcweir         pBkmk != aSaveBkmks.end();
1236cdf0e10cSrcweir         ++pBkmk)
1237cdf0e10cSrcweir 		pBkmk->SetInDoc(this, aIdx);
1238cdf0e10cSrcweir 
1239cdf0e10cSrcweir 	if( aSavRedlInsPosArr.Count() )
1240cdf0e10cSrcweir 	{
1241cdf0e10cSrcweir 		SwNode* pNewNd = &aIdx.GetNode();
1242cdf0e10cSrcweir 		for( sal_uInt16 n = 0; n < aSavRedlInsPosArr.Count(); ++n )
1243cdf0e10cSrcweir 		{
1244cdf0e10cSrcweir 			SwRedline* pTmp = (SwRedline*)aSavRedlInsPosArr[ n ];
1245cdf0e10cSrcweir 			if( USHRT_MAX != GetRedlineTbl().GetPos( pTmp ) )
1246cdf0e10cSrcweir 			{
1247cdf0e10cSrcweir 				SwPosition* pEnd = pTmp->End();
1248cdf0e10cSrcweir 				pEnd->nNode = aIdx;
1249cdf0e10cSrcweir 				pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
1250cdf0e10cSrcweir 			}
1251cdf0e10cSrcweir 		}
1252cdf0e10cSrcweir 	}
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir 	if( aSaveRedl.Count() )
1255cdf0e10cSrcweir 		lcl_RestoreRedlines( this, aIdx.GetIndex(), aSaveRedl );
1256cdf0e10cSrcweir 
1257cdf0e10cSrcweir 	if( pUndo )
1258cdf0e10cSrcweir     {
1259cdf0e10cSrcweir 		pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
1260cdf0e10cSrcweir         GetIDocumentUndoRedo().AppendUndo(pUndo);
1261cdf0e10cSrcweir     }
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir 	if( pSaveInsPos )
1264cdf0e10cSrcweir 		delete pSaveInsPos;
1265cdf0e10cSrcweir 
1266cdf0e10cSrcweir 	if( bUpdateFtn )
1267cdf0e10cSrcweir 	{
1268cdf0e10cSrcweir 		if( aTmpFntIdx.Count() )
1269cdf0e10cSrcweir 		{
1270cdf0e10cSrcweir 			GetFtnIdxs().Insert( &aTmpFntIdx );
1271cdf0e10cSrcweir 			aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
1272cdf0e10cSrcweir 		}
1273cdf0e10cSrcweir 
1274cdf0e10cSrcweir 		GetFtnIdxs().UpdateAllFtn();
1275cdf0e10cSrcweir 	}
1276cdf0e10cSrcweir 
1277cdf0e10cSrcweir 	SetModified();
1278cdf0e10cSrcweir 	return sal_True;
1279cdf0e10cSrcweir }
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir /* #107318# Convert list of ranges of whichIds to a corresponding list
1282cdf0e10cSrcweir     of whichIds*/
lcl_RangesToUShorts(sal_uInt16 * pRanges)1283cdf0e10cSrcweir SvUShorts * lcl_RangesToUShorts(sal_uInt16 * pRanges)
1284cdf0e10cSrcweir {
1285cdf0e10cSrcweir     SvUShorts * pResult = new SvUShorts();
1286cdf0e10cSrcweir 
1287cdf0e10cSrcweir     int i = 0;
1288cdf0e10cSrcweir     while (pRanges[i] != 0)
1289cdf0e10cSrcweir     {
1290cdf0e10cSrcweir         ASSERT(pRanges[i+1] != 0, "malformed ranges");
1291cdf0e10cSrcweir 
1292cdf0e10cSrcweir         for (sal_uInt16 j = pRanges[i]; j < pRanges[i+1]; j++)
1293cdf0e10cSrcweir             pResult->Insert(j, pResult->Count());
1294cdf0e10cSrcweir 
1295cdf0e10cSrcweir         i += 2;
1296cdf0e10cSrcweir     }
1297cdf0e10cSrcweir 
1298cdf0e10cSrcweir     return pResult;
1299cdf0e10cSrcweir }
1300cdf0e10cSrcweir 
lcl_StrLenOverFlow(const SwPaM & rPam)1301cdf0e10cSrcweir bool lcl_StrLenOverFlow( const SwPaM& rPam )
1302cdf0e10cSrcweir {
1303cdf0e10cSrcweir     // If we try to merge two paragraph we have to test if afterwards
1304cdf0e10cSrcweir     // the string doesn't exceed the allowed string length
1305cdf0e10cSrcweir     bool bRet = false;
1306cdf0e10cSrcweir 	if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
1307cdf0e10cSrcweir 	{
1308cdf0e10cSrcweir 		const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
1309cdf0e10cSrcweir 		const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
1310cdf0e10cSrcweir 		if( (0 != pEndNd) && pStt->nNode.GetNode().IsTxtNode() )
1311cdf0e10cSrcweir         {
1312cdf0e10cSrcweir             sal_uInt64 nSum = pStt->nContent.GetIndex() +
1313cdf0e10cSrcweir                 pEndNd->GetTxt().Len() - pEnd->nContent.GetIndex();
1314cdf0e10cSrcweir             if( nSum > STRING_LEN )
1315cdf0e10cSrcweir                 bRet = true;
1316cdf0e10cSrcweir         }
1317cdf0e10cSrcweir 	}
1318cdf0e10cSrcweir     return bRet;
1319cdf0e10cSrcweir }
1320cdf0e10cSrcweir 
lcl_GetJoinFlags(SwPaM & rPam,sal_Bool & rJoinTxt,sal_Bool & rJoinPrev)1321cdf0e10cSrcweir void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev )
1322cdf0e10cSrcweir {
1323cdf0e10cSrcweir     rJoinTxt = sal_False;
1324cdf0e10cSrcweir     rJoinPrev = sal_False;
1325cdf0e10cSrcweir 	if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
1326cdf0e10cSrcweir 	{
1327cdf0e10cSrcweir 		const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
1328cdf0e10cSrcweir 		SwTxtNode *pSttNd = pStt->nNode.GetNode().GetTxtNode();
1329cdf0e10cSrcweir         if( pSttNd )
1330cdf0e10cSrcweir         {
1331cdf0e10cSrcweir             SwTxtNode *pEndNd = pEnd->nNode.GetNode().GetTxtNode();
1332cdf0e10cSrcweir             rJoinTxt = 0 != pEndNd;
1333cdf0e10cSrcweir             if( rJoinTxt )
1334cdf0e10cSrcweir             {
1335cdf0e10cSrcweir                 bool bExchange = pStt == rPam.GetPoint();
1336cdf0e10cSrcweir                 if( !pStt->nContent.GetIndex() &&
1337cdf0e10cSrcweir                     pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex() )
1338cdf0e10cSrcweir                     bExchange = !bExchange;
1339cdf0e10cSrcweir                 if( bExchange )
1340cdf0e10cSrcweir                     rPam.Exchange();
1341cdf0e10cSrcweir                 rJoinPrev = rPam.GetPoint() == pStt;
1342cdf0e10cSrcweir                 ASSERT( !pStt->nContent.GetIndex() &&
1343cdf0e10cSrcweir                     pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex()
1344cdf0e10cSrcweir                     ? rPam.GetPoint()->nNode < rPam.GetMark()->nNode
1345cdf0e10cSrcweir                     : rPam.GetPoint()->nNode > rPam.GetMark()->nNode,
1346cdf0e10cSrcweir                     "lcl_GetJoinFlags");
1347cdf0e10cSrcweir             }
1348cdf0e10cSrcweir         }
1349cdf0e10cSrcweir 	}
1350cdf0e10cSrcweir }
1351cdf0e10cSrcweir 
lcl_JoinText(SwPaM & rPam,sal_Bool bJoinPrev)1352cdf0e10cSrcweir void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev )
1353cdf0e10cSrcweir {
1354cdf0e10cSrcweir 	SwNodeIndex aIdx( rPam.GetPoint()->nNode );
1355cdf0e10cSrcweir 	SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
1356cdf0e10cSrcweir 	SwNodeIndex aOldIdx( aIdx );
1357cdf0e10cSrcweir 	SwTxtNode *pOldTxtNd = pTxtNd;
1358cdf0e10cSrcweir 
1359cdf0e10cSrcweir 	if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
1360cdf0e10cSrcweir 	{
1361cdf0e10cSrcweir 		SwDoc* pDoc = rPam.GetDoc();
1362cdf0e10cSrcweir 		if( bJoinPrev )
1363cdf0e10cSrcweir 		{
1364cdf0e10cSrcweir             // N.B.: we do not need to handle xmlids in this case, because
1365cdf0e10cSrcweir             // it is only invoked if one paragraph is completely empty
1366cdf0e10cSrcweir             // (see lcl_GetJoinFlags)
1367cdf0e10cSrcweir 			{
1368cdf0e10cSrcweir 				// falls PageBreaks geloescht / gesetzt werden, darf das
1369cdf0e10cSrcweir 				// nicht in die Undo-History aufgenommen werden !!
1370cdf0e10cSrcweir 				// (das loeschen vom Node geht auch am Undo vorbei !!!)
1371cdf0e10cSrcweir                 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
1372cdf0e10cSrcweir 
1373cdf0e10cSrcweir 				/* PageBreaks, PageDesc, ColumnBreaks */
1374cdf0e10cSrcweir 				// Sollte an der Logik zum Kopieren der PageBreak's ...
1375cdf0e10cSrcweir 				// etwas geaendert werden, muss es auch im SwUndoDelete
1376cdf0e10cSrcweir 				// geandert werden. Dort wird sich das AUTO-PageBreak
1377cdf0e10cSrcweir 				// aus dem GetMarkNode kopiert.!!!
1378cdf0e10cSrcweir 
1379cdf0e10cSrcweir 				/* Der GetMarkNode */
1380cdf0e10cSrcweir                 if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->HasSwAttrSet() )
1381cdf0e10cSrcweir 				{
1382cdf0e10cSrcweir 					const SfxPoolItem* pItem;
1383cdf0e10cSrcweir 					if( SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
1384cdf0e10cSrcweir 						RES_BREAK, sal_False, &pItem ) )
1385cdf0e10cSrcweir 						pTxtNd->ResetAttr( RES_BREAK );
1386cdf0e10cSrcweir                     if( pTxtNd->HasSwAttrSet() &&
1387cdf0e10cSrcweir 						SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
1388cdf0e10cSrcweir 						RES_PAGEDESC, sal_False, &pItem ) )
1389cdf0e10cSrcweir 						pTxtNd->ResetAttr( RES_PAGEDESC );
1390cdf0e10cSrcweir 				}
1391cdf0e10cSrcweir 
1392cdf0e10cSrcweir 				/* Der PointNode */
1393cdf0e10cSrcweir                 if( pOldTxtNd->HasSwAttrSet() )
1394cdf0e10cSrcweir 				{
1395cdf0e10cSrcweir 					const SfxPoolItem* pItem;
1396cdf0e10cSrcweir 					SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
1397cdf0e10cSrcweir                     const SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
1398cdf0e10cSrcweir 					if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
1399cdf0e10cSrcweir 						sal_False, &pItem ) )
1400cdf0e10cSrcweir 						aSet.Put( *pItem );
1401cdf0e10cSrcweir 					if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
1402cdf0e10cSrcweir 						sal_False, &pItem ) )
1403cdf0e10cSrcweir 						aSet.Put( *pItem );
1404cdf0e10cSrcweir 					if( aSet.Count() )
1405cdf0e10cSrcweir                         pTxtNd->SetAttr( aSet );
1406cdf0e10cSrcweir 				}
1407cdf0e10cSrcweir 				pOldTxtNd->FmtToTxtAttr( pTxtNd );
1408cdf0e10cSrcweir 
1409cdf0e10cSrcweir 				SvULongs aBkmkArr( 15, 15 );
1410cdf0e10cSrcweir 				::_SaveCntntIdx( pDoc, aOldIdx.GetIndex(),
1411cdf0e10cSrcweir 									pOldTxtNd->Len(), aBkmkArr );
1412cdf0e10cSrcweir 
1413cdf0e10cSrcweir 				SwIndex aAlphaIdx(pTxtNd);
1414cdf0e10cSrcweir                 pOldTxtNd->CutText( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
1415cdf0e10cSrcweir 									pOldTxtNd->Len() );
1416cdf0e10cSrcweir 				SwPosition aAlphaPos( aIdx, aAlphaIdx );
1417cdf0e10cSrcweir 				pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, sal_True );
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir 				// verschiebe noch alle Bookmarks/TOXMarks
1420cdf0e10cSrcweir 				if( aBkmkArr.Count() )
1421cdf0e10cSrcweir 					::_RestoreCntntIdx( pDoc, aBkmkArr, aIdx.GetIndex() );
1422cdf0e10cSrcweir 
1423cdf0e10cSrcweir 				// falls der uebergebene PaM nicht im Crsr-Ring steht,
1424cdf0e10cSrcweir 				// gesondert behandeln (z.B. Aufruf aus dem Auto-Format)
1425cdf0e10cSrcweir 				if( pOldTxtNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
1426cdf0e10cSrcweir 					rPam.GetBound( sal_True ) = aAlphaPos;
1427cdf0e10cSrcweir 				if( pOldTxtNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
1428cdf0e10cSrcweir 					rPam.GetBound( sal_False ) = aAlphaPos;
1429cdf0e10cSrcweir 			}
1430cdf0e10cSrcweir 			// jetzt nur noch den Node loeschen
1431cdf0e10cSrcweir 			pDoc->GetNodes().Delete( aOldIdx, 1 );
1432cdf0e10cSrcweir 		}
1433cdf0e10cSrcweir 		else
1434cdf0e10cSrcweir 		{
1435cdf0e10cSrcweir 			SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
1436cdf0e10cSrcweir 			if( pTxtNd->Len() )
1437cdf0e10cSrcweir 				pDelNd->FmtToTxtAttr( pTxtNd );
1438cdf0e10cSrcweir 			else
1439cdf0e10cSrcweir             {
1440cdf0e10cSrcweir                 /* #107318# This case was missed:
1441cdf0e10cSrcweir 
1442cdf0e10cSrcweir                    <something></something>   <-- pTxtNd
1443cdf0e10cSrcweir                    <other>ccc</other>        <-- pDelNd
1444cdf0e10cSrcweir 
1445cdf0e10cSrcweir                    <something> and <other> are paragraph
1446cdf0e10cSrcweir                    attributes. The attribute <something> stayed if not
1447cdf0e10cSrcweir                    overwritten by an attribute in "ccc". Fixed by
1448cdf0e10cSrcweir                    first resetting all character attributes in first
1449cdf0e10cSrcweir                    paragraph (pTxtNd).
1450cdf0e10cSrcweir                 */
1451cdf0e10cSrcweir                 SvUShorts * pShorts =
1452cdf0e10cSrcweir                     lcl_RangesToUShorts(aCharFmtSetRange);
1453cdf0e10cSrcweir                 pTxtNd->ResetAttr(*pShorts);
1454cdf0e10cSrcweir                 delete pShorts;
1455cdf0e10cSrcweir 
1456cdf0e10cSrcweir                 if( pDelNd->HasSwAttrSet() )
1457cdf0e10cSrcweir                 {
1458cdf0e10cSrcweir                     // nur die Zeichenattribute kopieren
1459cdf0e10cSrcweir                     SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
1460cdf0e10cSrcweir                     aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
1461cdf0e10cSrcweir                     pTxtNd->SetAttr( aTmpSet );
1462cdf0e10cSrcweir                 }
1463cdf0e10cSrcweir             }
1464cdf0e10cSrcweir 
1465cdf0e10cSrcweir 			pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, sal_True );
1466cdf0e10cSrcweir             // --> OD 2009-08-20 #i100466#
1467cdf0e10cSrcweir             // adjust given <rPam>, if it does not belong to the cursors
1468cdf0e10cSrcweir             if ( pDelNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
1469cdf0e10cSrcweir             {
1470cdf0e10cSrcweir                 rPam.GetBound( sal_True ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
1471cdf0e10cSrcweir             }
1472cdf0e10cSrcweir             if( pDelNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
1473cdf0e10cSrcweir             {
1474cdf0e10cSrcweir                 rPam.GetBound( sal_False ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
1475cdf0e10cSrcweir             }
1476cdf0e10cSrcweir             // <--
1477cdf0e10cSrcweir 			pTxtNd->JoinNext();
1478cdf0e10cSrcweir 		}
1479cdf0e10cSrcweir 	}
1480cdf0e10cSrcweir }
1481cdf0e10cSrcweir 
1482cdf0e10cSrcweir static void
lcl_CalcBreaks(::std::vector<xub_StrLen> & rBreaks,SwPaM const & rPam)1483cdf0e10cSrcweir lcl_CalcBreaks( ::std::vector<xub_StrLen> & rBreaks, SwPaM const & rPam )
1484cdf0e10cSrcweir {
1485cdf0e10cSrcweir     SwTxtNode const * const pTxtNode(
1486cdf0e10cSrcweir             rPam.End()->nNode.GetNode().GetTxtNode() );
1487cdf0e10cSrcweir     if (!pTxtNode)
1488cdf0e10cSrcweir         return; // left-overlap only possible at end of selection...
1489cdf0e10cSrcweir 
1490cdf0e10cSrcweir     const xub_StrLen nStart(rPam.Start()->nContent.GetIndex());
1491cdf0e10cSrcweir     const xub_StrLen nEnd  (rPam.End  ()->nContent.GetIndex());
1492cdf0e10cSrcweir     if (nEnd == pTxtNode->Len())
1493cdf0e10cSrcweir         return; // paragraph selected until the end
1494cdf0e10cSrcweir 
1495cdf0e10cSrcweir     for (xub_StrLen i = nStart; i < nEnd; ++i)
1496cdf0e10cSrcweir     {
1497cdf0e10cSrcweir         const sal_Unicode c(pTxtNode->GetTxt().GetChar(i));
1498cdf0e10cSrcweir         if ((CH_TXTATR_INWORD == c) || (CH_TXTATR_BREAKWORD == c))
1499cdf0e10cSrcweir         {
1500cdf0e10cSrcweir             SwTxtAttr const * const pAttr( pTxtNode->GetTxtAttrForCharAt(i) );
150169a74367SOliver-Rainer Wittmann             if (pAttr && pAttr->End() && (*pAttr->End() > nEnd))
1502cdf0e10cSrcweir             {
1503cdf0e10cSrcweir                 ASSERT(pAttr->HasDummyChar(), "GetTxtAttrForCharAt broken?");
1504cdf0e10cSrcweir                 rBreaks.push_back(i);
1505cdf0e10cSrcweir             }
1506cdf0e10cSrcweir         }
1507cdf0e10cSrcweir     }
1508cdf0e10cSrcweir }
1509cdf0e10cSrcweir 
lcl_DoWithBreaks(SwDoc & rDoc,SwPaM & rPam,bool (SwDoc::* pFunc)(SwPaM &,bool),const bool bForceJoinNext=false)1510cdf0e10cSrcweir bool lcl_DoWithBreaks(SwDoc & rDoc, SwPaM & rPam,
1511cdf0e10cSrcweir         bool (SwDoc::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
1512cdf0e10cSrcweir {
1513cdf0e10cSrcweir     ::std::vector<xub_StrLen> Breaks;
1514cdf0e10cSrcweir 
1515cdf0e10cSrcweir     lcl_CalcBreaks(Breaks, rPam);
1516cdf0e10cSrcweir 
1517cdf0e10cSrcweir     if (!Breaks.size())
1518cdf0e10cSrcweir     {
1519cdf0e10cSrcweir         return (rDoc.*pFunc)(rPam, bForceJoinNext);
1520cdf0e10cSrcweir     }
1521cdf0e10cSrcweir 
1522cdf0e10cSrcweir     // N.B.: deletion must be split into several parts if the text node
1523cdf0e10cSrcweir     // contains a text attribute with end and with dummy character
1524cdf0e10cSrcweir     // and the selection does not contain the text attribute completely,
1525cdf0e10cSrcweir     // but overlaps its start (left), where the dummy character is.
1526cdf0e10cSrcweir 
1527cdf0e10cSrcweir     SwPosition const & rSelectionEnd( *rPam.End() );
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir     bool bRet( true );
1530cdf0e10cSrcweir     // iterate from end to start, to avoid invalidating the offsets!
1531cdf0e10cSrcweir     ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
1532cdf0e10cSrcweir     SwPaM aPam( rSelectionEnd, rSelectionEnd ); // end node!
1533cdf0e10cSrcweir     SwPosition & rEnd( *aPam.End() );
1534cdf0e10cSrcweir     SwPosition & rStart( *aPam.Start() );
1535cdf0e10cSrcweir 
1536cdf0e10cSrcweir     while (iter != Breaks.rend())
1537cdf0e10cSrcweir     {
1538cdf0e10cSrcweir         rStart.nContent = *iter + 1;
1539cdf0e10cSrcweir         if (rEnd.nContent > rStart.nContent) // check if part is empty
1540cdf0e10cSrcweir         {
1541cdf0e10cSrcweir             bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
1542cdf0e10cSrcweir         }
1543cdf0e10cSrcweir         rEnd.nContent = *iter;
1544cdf0e10cSrcweir         ++iter;
1545cdf0e10cSrcweir     }
1546cdf0e10cSrcweir 
1547cdf0e10cSrcweir     rStart = *rPam.Start(); // set to original start
1548cdf0e10cSrcweir     if (rEnd.nContent > rStart.nContent) // check if part is empty
1549cdf0e10cSrcweir     {
1550cdf0e10cSrcweir         bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
1551cdf0e10cSrcweir     }
1552cdf0e10cSrcweir 
1553cdf0e10cSrcweir     return bRet;
1554cdf0e10cSrcweir }
1555cdf0e10cSrcweir 
1556cdf0e10cSrcweir 
DeleteAndJoinWithRedlineImpl(SwPaM & rPam,const bool)1557cdf0e10cSrcweir bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
1558cdf0e10cSrcweir {
1559cdf0e10cSrcweir     ASSERT( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
1560cdf0e10cSrcweir 
1561cdf0e10cSrcweir     {
1562cdf0e10cSrcweir         SwUndoRedlineDelete* pUndo = 0;
1563cdf0e10cSrcweir         RedlineMode_t eOld = GetRedlineMode();
1564cdf0e10cSrcweir         checkRedlining( eOld );
1565cdf0e10cSrcweir         if (GetIDocumentUndoRedo().DoesUndo())
1566cdf0e10cSrcweir         {
1567cdf0e10cSrcweir 
1568cdf0e10cSrcweir             //JP 06.01.98: MUSS noch optimiert werden!!!
1569cdf0e10cSrcweir             SetRedlineMode(
1570cdf0e10cSrcweir                 (RedlineMode_t) ( nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ) );
1571cdf0e10cSrcweir 
1572*641de097SOliver-Rainer Wittmann             GetIDocumentUndoRedo().StartUndo( UNDO_DELETE, NULL );
1573cdf0e10cSrcweir             pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE );
1574cdf0e10cSrcweir             GetIDocumentUndoRedo().AppendUndo( pUndo );
1575cdf0e10cSrcweir         }
1576*641de097SOliver-Rainer Wittmann 
1577cdf0e10cSrcweir         if ( *rPam.GetPoint() != *rPam.GetMark() )
1578cdf0e10cSrcweir             AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true );
1579cdf0e10cSrcweir         SetModified();
1580cdf0e10cSrcweir 
1581cdf0e10cSrcweir         if ( pUndo )
1582cdf0e10cSrcweir         {
1583cdf0e10cSrcweir             GetIDocumentUndoRedo().EndUndo( UNDO_EMPTY, NULL );
1584cdf0e10cSrcweir             // ??? why the hell is the AppendUndo not below the
1585cdf0e10cSrcweir             // CanGrouping, so this hideous cleanup wouldn't be necessary?
1586cdf0e10cSrcweir             // bah, this is redlining, probably changing this would break it...
1587cdf0e10cSrcweir             if ( GetIDocumentUndoRedo().DoesGroupUndo() )
1588cdf0e10cSrcweir             {
1589cdf0e10cSrcweir                 SwUndo * const pLastUndo( GetUndoManager().GetLastUndo() );
1590*641de097SOliver-Rainer Wittmann                 SwUndoRedlineDelete * const pUndoRedlineDel( dynamic_cast< SwUndoRedlineDelete* >( pLastUndo ) );
1591cdf0e10cSrcweir                 if ( pUndoRedlineDel )
1592cdf0e10cSrcweir                 {
1593cdf0e10cSrcweir                     bool const bMerged = pUndoRedlineDel->CanGrouping( *pUndo );
1594cdf0e10cSrcweir                     if ( bMerged )
1595cdf0e10cSrcweir                     {
1596cdf0e10cSrcweir                         ::sw::UndoGuard const undoGuard( GetIDocumentUndoRedo() );
1597*641de097SOliver-Rainer Wittmann                         SwUndo const* const pDeleted = GetUndoManager().RemoveLastUndo();
1598*641de097SOliver-Rainer Wittmann                         OSL_ENSURE( pDeleted == pUndo, "DeleteAndJoinWithRedlineImpl: "
1599cdf0e10cSrcweir                             "undo removed is not undo inserted?" );
1600cdf0e10cSrcweir                         delete pDeleted;
1601cdf0e10cSrcweir                     }
1602cdf0e10cSrcweir                 }
1603cdf0e10cSrcweir             }
1604cdf0e10cSrcweir             //JP 06.01.98: MUSS noch optimiert werden!!!
1605cdf0e10cSrcweir             SetRedlineMode( eOld );
1606cdf0e10cSrcweir         }
1607cdf0e10cSrcweir         return true;
1608cdf0e10cSrcweir     }
1609cdf0e10cSrcweir }
1610cdf0e10cSrcweir 
DeleteAndJoinImpl(SwPaM & rPam,const bool bForceJoinNext)1611cdf0e10cSrcweir bool SwDoc::DeleteAndJoinImpl( SwPaM & rPam,
1612cdf0e10cSrcweir                                const bool bForceJoinNext )
1613cdf0e10cSrcweir {
1614cdf0e10cSrcweir 	sal_Bool bJoinTxt, bJoinPrev;
1615cdf0e10cSrcweir 	lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
1616cdf0e10cSrcweir     // --> OD 2009-08-20 #i100466#
1617cdf0e10cSrcweir     if ( bForceJoinNext )
1618cdf0e10cSrcweir     {
1619cdf0e10cSrcweir         bJoinPrev = sal_False;
1620cdf0e10cSrcweir     }
1621cdf0e10cSrcweir     // <--
1622cdf0e10cSrcweir 	{
1623cdf0e10cSrcweir         bool const bSuccess( DeleteRangeImpl( rPam ) );
1624cdf0e10cSrcweir         if (!bSuccess)
1625cdf0e10cSrcweir             return false;
1626cdf0e10cSrcweir 	}
1627cdf0e10cSrcweir 
1628cdf0e10cSrcweir 	if( bJoinTxt )
1629cdf0e10cSrcweir     {
1630cdf0e10cSrcweir 		lcl_JoinText( rPam, bJoinPrev );
1631cdf0e10cSrcweir     }
1632cdf0e10cSrcweir 
1633cdf0e10cSrcweir     return true;
1634cdf0e10cSrcweir }
1635cdf0e10cSrcweir 
DeleteRangeImpl(SwPaM & rPam,const bool)1636cdf0e10cSrcweir bool SwDoc::DeleteRangeImpl(SwPaM & rPam, const bool)
1637cdf0e10cSrcweir {
1638cdf0e10cSrcweir     // move all cursors out of the deleted range.
1639cdf0e10cSrcweir     // but first copy the given PaM, because it could be a cursor that
1640cdf0e10cSrcweir     // would be moved!
1641cdf0e10cSrcweir     SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
1642cdf0e10cSrcweir     ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
1643cdf0e10cSrcweir 
1644cdf0e10cSrcweir     bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
1645cdf0e10cSrcweir     if (bSuccess)
1646cdf0e10cSrcweir     {   // now copy position from temp copy to given PaM
1647cdf0e10cSrcweir         *rPam.GetPoint() = *aDelPam.GetPoint();
1648cdf0e10cSrcweir     }
1649cdf0e10cSrcweir 
1650cdf0e10cSrcweir     return bSuccess;
1651cdf0e10cSrcweir }
1652cdf0e10cSrcweir 
DeleteRangeImplImpl(SwPaM & rPam)1653cdf0e10cSrcweir bool SwDoc::DeleteRangeImplImpl(SwPaM & rPam)
1654cdf0e10cSrcweir {
1655cdf0e10cSrcweir 	SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
1656cdf0e10cSrcweir 
1657cdf0e10cSrcweir 	if( !rPam.HasMark() || *pStt >= *pEnd )
1658cdf0e10cSrcweir         return false;
1659cdf0e10cSrcweir 
1660cdf0e10cSrcweir 	if( pACEWord )
1661cdf0e10cSrcweir 	{
1662cdf0e10cSrcweir 		// ggfs. das gesicherte Word fuer die Ausnahme
1663cdf0e10cSrcweir 		if( pACEWord->IsDeleted() ||  pStt->nNode != pEnd->nNode ||
1664cdf0e10cSrcweir 			pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
1665cdf0e10cSrcweir 			!pACEWord->CheckDelChar( *pStt ))
1666cdf0e10cSrcweir 			delete pACEWord, pACEWord = 0;
1667cdf0e10cSrcweir 	}
1668cdf0e10cSrcweir 
1669cdf0e10cSrcweir 	{
1670cdf0e10cSrcweir 		// loesche alle leeren TextHints an der Mark-Position
1671cdf0e10cSrcweir 		SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
1672cdf0e10cSrcweir 		SwpHints* pHts;
1673cdf0e10cSrcweir 		if( pTxtNd &&  0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
1674cdf0e10cSrcweir 		{
1675cdf0e10cSrcweir 			const xub_StrLen *pEndIdx;
1676cdf0e10cSrcweir 			xub_StrLen nMkCntPos = rPam.GetMark()->nContent.GetIndex();
1677cdf0e10cSrcweir 			for( sal_uInt16 n = pHts->Count(); n; )
1678cdf0e10cSrcweir 			{
1679cdf0e10cSrcweir 				const SwTxtAttr* pAttr = (*pHts)[ --n ];
1680cdf0e10cSrcweir 				if( nMkCntPos > *pAttr->GetStart() )
1681cdf0e10cSrcweir 					break;
1682cdf0e10cSrcweir 
1683cdf0e10cSrcweir 				if( nMkCntPos == *pAttr->GetStart() &&
168469a74367SOliver-Rainer Wittmann 					0 != (pEndIdx = pAttr->End()) &&
1685cdf0e10cSrcweir 					*pEndIdx == *pAttr->GetStart() )
1686cdf0e10cSrcweir 					pTxtNd->DestroyAttr( pHts->Cut( n ) );
1687cdf0e10cSrcweir 			}
1688cdf0e10cSrcweir 		}
1689cdf0e10cSrcweir 	}
1690cdf0e10cSrcweir 
1691cdf0e10cSrcweir 	{
1692cdf0e10cSrcweir 		// Bug 26675:	DataChanged vorm loeschen verschicken, dann bekommt
1693cdf0e10cSrcweir 		//			man noch mit, welche Objecte sich im Bereich befinden.
1694cdf0e10cSrcweir 		//			Danach koennen sie vor/hinter der Position befinden.
1695cdf0e10cSrcweir 		SwDataChanged aTmp( rPam, 0 );
1696cdf0e10cSrcweir 	}
1697cdf0e10cSrcweir 
1698cdf0e10cSrcweir 
1699cdf0e10cSrcweir     if (GetIDocumentUndoRedo().DoesUndo())
1700cdf0e10cSrcweir     {
1701cdf0e10cSrcweir         GetIDocumentUndoRedo().ClearRedo();
1702cdf0e10cSrcweir         bool bMerged(false);
1703cdf0e10cSrcweir         if (GetIDocumentUndoRedo().DoesGroupUndo())
1704cdf0e10cSrcweir         {
1705cdf0e10cSrcweir             SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
1706cdf0e10cSrcweir             SwUndoDelete *const pUndoDelete(
1707cdf0e10cSrcweir                     dynamic_cast<SwUndoDelete *>(pLastUndo) );
1708cdf0e10cSrcweir             if (pUndoDelete)
1709cdf0e10cSrcweir             {
1710cdf0e10cSrcweir                 bMerged = pUndoDelete->CanGrouping( this, rPam );
1711cdf0e10cSrcweir                 // if CanGrouping() returns true it's already merged
1712cdf0e10cSrcweir             }
1713cdf0e10cSrcweir         }
1714cdf0e10cSrcweir         if (!bMerged)
1715cdf0e10cSrcweir         {
1716cdf0e10cSrcweir             GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam ) );
1717cdf0e10cSrcweir         }
1718cdf0e10cSrcweir 
1719cdf0e10cSrcweir 		SetModified();
1720cdf0e10cSrcweir 
1721cdf0e10cSrcweir         return true;
1722cdf0e10cSrcweir     }
1723cdf0e10cSrcweir 
1724cdf0e10cSrcweir 	if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
1725cdf0e10cSrcweir 		DeleteRedline( rPam, true, USHRT_MAX );
1726cdf0e10cSrcweir 
1727cdf0e10cSrcweir     // loesche und verschiebe erstmal alle "Fly's am Absatz", die in der
1728cdf0e10cSrcweir     // Selection liegen
1729cdf0e10cSrcweir     DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
1730cdf0e10cSrcweir     _DelBookmarks(
1731cdf0e10cSrcweir         pStt->nNode,
1732cdf0e10cSrcweir         pEnd->nNode,
1733cdf0e10cSrcweir         NULL,
1734cdf0e10cSrcweir         &pStt->nContent,
1735cdf0e10cSrcweir         &pEnd->nContent);
1736cdf0e10cSrcweir 
1737cdf0e10cSrcweir 	SwNodeIndex aSttIdx( pStt->nNode );
1738cdf0e10cSrcweir 	SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
1739cdf0e10cSrcweir 
1740cdf0e10cSrcweir 	do {		// middle checked loop!
1741cdf0e10cSrcweir 		if( pCNd )
1742cdf0e10cSrcweir 		{
1743cdf0e10cSrcweir             SwTxtNode * pStartTxtNode( pCNd->GetTxtNode() );
1744cdf0e10cSrcweir             if ( pStartTxtNode )
1745cdf0e10cSrcweir 			{
1746cdf0e10cSrcweir 				// verschiebe jetzt noch den Inhalt in den neuen Node
1747cdf0e10cSrcweir 				sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
1748cdf0e10cSrcweir 				xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex()
1749cdf0e10cSrcweir 										   : pCNd->Len() )
1750cdf0e10cSrcweir 										- pStt->nContent.GetIndex();
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir 				// falls schon leer, dann nicht noch aufrufen
1753cdf0e10cSrcweir 				if( nLen )
1754cdf0e10cSrcweir                 {
1755cdf0e10cSrcweir                     pStartTxtNode->EraseText( pStt->nContent, nLen );
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir                     if( !pStartTxtNode->Len() )
1758cdf0e10cSrcweir                     {
1759cdf0e10cSrcweir                 // METADATA: remove reference if empty (consider node deleted)
1760cdf0e10cSrcweir                         pStartTxtNode->RemoveMetadataReference();
1761cdf0e10cSrcweir                     }
1762cdf0e10cSrcweir                 }
1763cdf0e10cSrcweir 
1764cdf0e10cSrcweir 				if( bOneNd )		// das wars schon
1765cdf0e10cSrcweir 					break;
1766cdf0e10cSrcweir 
1767cdf0e10cSrcweir 				aSttIdx++;
1768cdf0e10cSrcweir 			}
1769cdf0e10cSrcweir 			else
1770cdf0e10cSrcweir 			{
1771cdf0e10cSrcweir 				// damit beim loeschen keine Indizies mehr angemeldet sind,
1772cdf0e10cSrcweir 				// wird hier der SwPaM aus dem Content entfernt !!
1773cdf0e10cSrcweir 				pStt->nContent.Assign( 0, 0 );
1774cdf0e10cSrcweir 			}
1775cdf0e10cSrcweir 		}
1776cdf0e10cSrcweir 
1777cdf0e10cSrcweir 		pCNd = pEnd->nNode.GetNode().GetCntntNode();
1778cdf0e10cSrcweir 		if( pCNd )
1779cdf0e10cSrcweir 		{
1780cdf0e10cSrcweir             SwTxtNode * pEndTxtNode( pCNd->GetTxtNode() );
1781cdf0e10cSrcweir             if( pEndTxtNode )
1782cdf0e10cSrcweir 			{
1783cdf0e10cSrcweir 				// falls schon leer, dann nicht noch aufrufen
1784cdf0e10cSrcweir 				if( pEnd->nContent.GetIndex() )
1785cdf0e10cSrcweir 				{
1786cdf0e10cSrcweir 					SwIndex aIdx( pCNd, 0 );
1787cdf0e10cSrcweir                     pEndTxtNode->EraseText( aIdx, pEnd->nContent.GetIndex() );
1788cdf0e10cSrcweir 
1789cdf0e10cSrcweir                     if( !pEndTxtNode->Len() )
1790cdf0e10cSrcweir                     {
1791cdf0e10cSrcweir                 // METADATA: remove reference if empty (consider node deleted)
1792cdf0e10cSrcweir                         pEndTxtNode->RemoveMetadataReference();
1793cdf0e10cSrcweir                     }
1794cdf0e10cSrcweir 				}
1795cdf0e10cSrcweir 			}
1796cdf0e10cSrcweir 			else
1797cdf0e10cSrcweir 			{
1798cdf0e10cSrcweir 				// damit beim Loeschen keine Indizies mehr angemeldet sind,
1799cdf0e10cSrcweir 				// wird hier der SwPaM aus dem Content entfernt !!
1800cdf0e10cSrcweir 				pEnd->nContent.Assign( 0, 0 );
1801cdf0e10cSrcweir 			}
1802cdf0e10cSrcweir 		}
1803cdf0e10cSrcweir 
1804cdf0e10cSrcweir         // if the end is not a content node, delete it as well
1805cdf0e10cSrcweir         sal_uInt32 nEnde = pEnd->nNode.GetIndex();
1806cdf0e10cSrcweir         if( pCNd == NULL )
1807cdf0e10cSrcweir             nEnde++;
1808cdf0e10cSrcweir 
1809cdf0e10cSrcweir 		if( aSttIdx != nEnde )
1810cdf0e10cSrcweir 		{
1811cdf0e10cSrcweir 			// loesche jetzt die Nodes in das NodesArary
1812cdf0e10cSrcweir 			GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
1813cdf0e10cSrcweir 		}
1814cdf0e10cSrcweir 
1815cdf0e10cSrcweir 		// falls der Node geloescht wurde, in dem der Cursor stand, so
1816cdf0e10cSrcweir 		// muss der Content im akt. Content angemeldet werden !!!
1817cdf0e10cSrcweir 		pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
1818cdf0e10cSrcweir 								pStt->nContent.GetIndex() );
1819cdf0e10cSrcweir 
1820cdf0e10cSrcweir 		// der PaM wird korrigiert, denn falls ueber Nodegrenzen geloescht
1821cdf0e10cSrcweir 		// wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
1822cdf0e10cSrcweir 		// wird aufgehoben !
1823cdf0e10cSrcweir 		*pEnd = *pStt;
1824cdf0e10cSrcweir 		rPam.DeleteMark();
1825cdf0e10cSrcweir 
1826cdf0e10cSrcweir 	} while( sal_False );
1827cdf0e10cSrcweir 
1828cdf0e10cSrcweir 	if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
1829cdf0e10cSrcweir 		CompressRedlines();
1830cdf0e10cSrcweir 	SetModified();
1831cdf0e10cSrcweir 
1832cdf0e10cSrcweir     return true;
1833cdf0e10cSrcweir }
1834cdf0e10cSrcweir 
1835cdf0e10cSrcweir // OD 2009-08-20 #i100466#
1836cdf0e10cSrcweir // Add handling of new optional parameter <bForceJoinNext>
DeleteAndJoin(SwPaM & rPam,const bool bForceJoinNext)1837cdf0e10cSrcweir bool SwDoc::DeleteAndJoin( SwPaM & rPam,
1838cdf0e10cSrcweir                            const bool bForceJoinNext )
1839cdf0e10cSrcweir {
1840cdf0e10cSrcweir     if ( lcl_StrLenOverFlow( rPam ) )
1841cdf0e10cSrcweir         return false;
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir     return lcl_DoWithBreaks( *this, rPam, (IsRedlineOn())
1844cdf0e10cSrcweir                 ? &SwDoc::DeleteAndJoinWithRedlineImpl
1845cdf0e10cSrcweir                 : &SwDoc::DeleteAndJoinImpl,
1846cdf0e10cSrcweir                 bForceJoinNext );
1847cdf0e10cSrcweir }
1848cdf0e10cSrcweir 
DeleteRange(SwPaM & rPam)1849cdf0e10cSrcweir bool SwDoc::DeleteRange( SwPaM & rPam )
1850cdf0e10cSrcweir {
1851cdf0e10cSrcweir     return lcl_DoWithBreaks( *this, rPam, &SwDoc::DeleteRangeImpl );
1852cdf0e10cSrcweir }
1853cdf0e10cSrcweir 
1854cdf0e10cSrcweir 
lcl_syncGrammarError(SwTxtNode & rTxtNode,linguistic2::ProofreadingResult & rResult,xub_StrLen,const ModelToViewHelper::ConversionMap * pConversionMap)1855cdf0e10cSrcweir void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
1856cdf0e10cSrcweir     xub_StrLen /*nBeginGrammarCheck*/, const ModelToViewHelper::ConversionMap* pConversionMap )
1857cdf0e10cSrcweir {
1858cdf0e10cSrcweir     if( rTxtNode.IsGrammarCheckDirty() )
1859cdf0e10cSrcweir         return;
1860cdf0e10cSrcweir     SwGrammarMarkUp* pWrong = rTxtNode.GetGrammarCheck();
1861cdf0e10cSrcweir 	linguistic2::SingleProofreadingError* pArray = rResult.aErrors.getArray();
1862cdf0e10cSrcweir     sal_uInt16 i, j = 0;
1863cdf0e10cSrcweir 	if( pWrong )
1864cdf0e10cSrcweir 	{
1865cdf0e10cSrcweir 		for( i = 0; i < rResult.aErrors.getLength(); ++i )
1866cdf0e10cSrcweir 		{
1867cdf0e10cSrcweir 			const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
1868cdf0e10cSrcweir 			xub_StrLen nStart = (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart ).mnPos;
1869cdf0e10cSrcweir 			xub_StrLen nEnd = (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart + rError.nErrorLength ).mnPos;
1870cdf0e10cSrcweir 			if( i != j )
1871cdf0e10cSrcweir 				pArray[j] = pArray[i];
1872cdf0e10cSrcweir 			if( pWrong->LookForEntry( nStart, nEnd ) )
1873cdf0e10cSrcweir 				++j;
1874cdf0e10cSrcweir 		}
1875cdf0e10cSrcweir 	}
1876cdf0e10cSrcweir     if( rResult.aErrors.getLength() > j )
1877cdf0e10cSrcweir         rResult.aErrors.realloc( j );
1878cdf0e10cSrcweir }
1879cdf0e10cSrcweir 
1880cdf0e10cSrcweir 
Spell(SwPaM & rPaM,uno::Reference<XSpellChecker1> & xSpeller,sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt,bool bGrammarCheck,SwConversionArgs * pConvArgs) const1881cdf0e10cSrcweir uno::Any SwDoc::Spell( SwPaM& rPaM,
1882cdf0e10cSrcweir 					uno::Reference< XSpellChecker1 >  &xSpeller,
1883cdf0e10cSrcweir                     sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
1884cdf0e10cSrcweir                     bool bGrammarCheck,
1885cdf0e10cSrcweir                     SwConversionArgs *pConvArgs  ) const
1886cdf0e10cSrcweir {
1887cdf0e10cSrcweir 	SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
1888cdf0e10cSrcweir 	uno::Reference< beans::XPropertySet >  xProp( ::GetLinguPropertySet() );
1889cdf0e10cSrcweir 
1890cdf0e10cSrcweir     SwSpellArgs      *pSpellArgs = 0;
1891cdf0e10cSrcweir     //SwConversionArgs *pConvArgs  = 0;
1892cdf0e10cSrcweir     if (pConvArgs)
1893cdf0e10cSrcweir 	{
1894cdf0e10cSrcweir         pConvArgs->SetStart(pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent);
1895cdf0e10cSrcweir 		pConvArgs->SetEnd(  pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
1896cdf0e10cSrcweir 	}
1897cdf0e10cSrcweir     else
1898cdf0e10cSrcweir         pSpellArgs = new SwSpellArgs( xSpeller,
1899cdf0e10cSrcweir                             pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
1900cdf0e10cSrcweir                             pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent,
1901cdf0e10cSrcweir                             bGrammarCheck );
1902cdf0e10cSrcweir 
1903cdf0e10cSrcweir 	sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
1904cdf0e10cSrcweir 	sal_uLong nEndNd = pEndPos->nNode.GetIndex();
1905cdf0e10cSrcweir 
1906cdf0e10cSrcweir     uno::Any aRet;
1907cdf0e10cSrcweir 	if( nCurrNd <= nEndNd )
1908cdf0e10cSrcweir 	{
1909cdf0e10cSrcweir 		SwCntntFrm* pCntFrm;
1910cdf0e10cSrcweir 		sal_Bool bGoOn = sal_True;
1911cdf0e10cSrcweir 		while( bGoOn )
1912cdf0e10cSrcweir 		{
1913cdf0e10cSrcweir 			SwNode* pNd = GetNodes()[ nCurrNd ];
1914cdf0e10cSrcweir 			switch( pNd->GetNodeType() )
1915cdf0e10cSrcweir 			{
1916cdf0e10cSrcweir 			case ND_TEXTNODE:
1917cdf0e10cSrcweir 				if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->getLayoutFrm( GetCurrentLayout() )) )
1918cdf0e10cSrcweir 				{
1919cdf0e10cSrcweir 					// geschutze Cellen/Flys ueberspringen, ausgeblendete
1920cdf0e10cSrcweir 					//ebenfalls
1921cdf0e10cSrcweir 					if( pCntFrm->IsProtected() )
1922cdf0e10cSrcweir 					{
1923cdf0e10cSrcweir                         nCurrNd = pNd->EndOfSectionIndex();
1924cdf0e10cSrcweir 					}
1925cdf0e10cSrcweir 					else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
1926cdf0e10cSrcweir 					{
1927cdf0e10cSrcweir 						if( pPageCnt && *pPageCnt && pPageSt )
1928cdf0e10cSrcweir 						{
1929cdf0e10cSrcweir 							sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
1930cdf0e10cSrcweir 							if( !*pPageSt )
1931cdf0e10cSrcweir 							{
1932cdf0e10cSrcweir 								*pPageSt = nPageNr;
1933cdf0e10cSrcweir 								if( *pPageCnt < *pPageSt )
1934cdf0e10cSrcweir 									*pPageCnt = *pPageSt;
1935cdf0e10cSrcweir 							}
1936cdf0e10cSrcweir 							long nStat;
1937cdf0e10cSrcweir 							if( nPageNr >= *pPageSt )
1938cdf0e10cSrcweir                                 nStat = nPageNr - *pPageSt + 1;
1939cdf0e10cSrcweir 							else
1940cdf0e10cSrcweir                                 nStat = nPageNr + *pPageCnt - *pPageSt + 1;
1941cdf0e10cSrcweir 							::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
1942cdf0e10cSrcweir 						}
1943cdf0e10cSrcweir                         //Spell() changes the pSpellArgs in case an error is found
1944cdf0e10cSrcweir                         xub_StrLen nBeginGrammarCheck = 0;
1945cdf0e10cSrcweir                         xub_StrLen nEndGrammarCheck = 0;
1946cdf0e10cSrcweir                         if( pSpellArgs && pSpellArgs->bIsGrammarCheck)
1947cdf0e10cSrcweir                         {
1948cdf0e10cSrcweir                             nBeginGrammarCheck = pSpellArgs->pStartNode == pNd ?  pSpellArgs->pStartIdx->GetIndex() : 0;
1949cdf0e10cSrcweir                             // if grammar checking starts inside of a sentence the start position has to be adjusted
1950cdf0e10cSrcweir                             if( nBeginGrammarCheck )
1951cdf0e10cSrcweir                             {
1952cdf0e10cSrcweir                                 SwIndex aStartIndex( dynamic_cast< SwTxtNode* >( pNd ), nBeginGrammarCheck );
1953cdf0e10cSrcweir                                 SwPosition aStart( *pNd, aStartIndex );
1954cdf0e10cSrcweir                                 SwCursor aCrsr(aStart, 0, false);
1955cdf0e10cSrcweir                                 SwPosition aOrigPos = *aCrsr.GetPoint();
1956cdf0e10cSrcweir                                 aCrsr.GoSentence( SwCursor::START_SENT );
1957cdf0e10cSrcweir                                 if( aOrigPos != *aCrsr.GetPoint() )
1958cdf0e10cSrcweir                                 {
1959cdf0e10cSrcweir                                     nBeginGrammarCheck = aCrsr.GetPoint()->nContent.GetIndex();
1960cdf0e10cSrcweir                                 }
1961cdf0e10cSrcweir                             }
1962cdf0e10cSrcweir                             nEndGrammarCheck = pSpellArgs->pEndNode == pNd ? pSpellArgs->pEndIdx->GetIndex() : ((SwTxtNode*)pNd)->GetTxt().Len();
1963cdf0e10cSrcweir                         }
1964cdf0e10cSrcweir 
1965cdf0e10cSrcweir                         xub_StrLen nSpellErrorPosition = ((SwTxtNode*)pNd)->GetTxt().Len();
1966cdf0e10cSrcweir                         if( (!pConvArgs &&
1967cdf0e10cSrcweir                                 ((SwTxtNode*)pNd)->Spell( pSpellArgs )) ||
1968cdf0e10cSrcweir                             ( pConvArgs &&
1969cdf0e10cSrcweir                                 ((SwTxtNode*)pNd)->Convert( *pConvArgs )))
1970cdf0e10cSrcweir 						{
1971cdf0e10cSrcweir 							// Abbrechen und Position merken
1972cdf0e10cSrcweir 							pSttPos->nNode = nCurrNd;
1973cdf0e10cSrcweir 							pEndPos->nNode = nCurrNd;
1974cdf0e10cSrcweir 							nCurrNd = nEndNd;
1975cdf0e10cSrcweir                             if( pSpellArgs )
1976cdf0e10cSrcweir                                 nSpellErrorPosition = pSpellArgs->pStartIdx->GetIndex() > pSpellArgs->pEndIdx->GetIndex() ?
1977cdf0e10cSrcweir                                             pSpellArgs->pEndIdx->GetIndex() :
1978cdf0e10cSrcweir                                             pSpellArgs->pStartIdx->GetIndex();
1979cdf0e10cSrcweir 						}
1980cdf0e10cSrcweir 
1981cdf0e10cSrcweir 
1982cdf0e10cSrcweir                         if( pSpellArgs && pSpellArgs->bIsGrammarCheck )
1983cdf0e10cSrcweir                         {
1984cdf0e10cSrcweir                             uno::Reference< linguistic2::XProofreadingIterator >  xGCIterator( GetGCIterator() );
1985cdf0e10cSrcweir                             if (xGCIterator.is())
1986cdf0e10cSrcweir                             {
1987cdf0e10cSrcweir                                 String aText( ((SwTxtNode*)pNd)->GetTxt().Copy( nBeginGrammarCheck, nEndGrammarCheck - nBeginGrammarCheck ) );
1988cdf0e10cSrcweir                                 uno::Reference< lang::XComponent > xDoc( ((SwDocShell*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY );
1989cdf0e10cSrcweir                                 // Expand the string:
1990cdf0e10cSrcweir                                 rtl::OUString aExpandText;
1991cdf0e10cSrcweir                                 const ModelToViewHelper::ConversionMap* pConversionMap =
1992cdf0e10cSrcweir                                         ((SwTxtNode*)pNd)->BuildConversionMap( aExpandText );
1993cdf0e10cSrcweir                                 // get XFlatParagraph to use...
1994cdf0e10cSrcweir                                 uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *((SwTxtNode*)pNd), aExpandText, pConversionMap );
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir                                 // get error position of cursor in XFlatParagraph
1997cdf0e10cSrcweir                                 sal_Int32 nGrammarErrorPosInText;
1998cdf0e10cSrcweir                                 linguistic2::ProofreadingResult aResult;
1999cdf0e10cSrcweir                                 sal_Int32 nGrammarErrors;
2000cdf0e10cSrcweir                                 do
2001cdf0e10cSrcweir                                 {
2002cdf0e10cSrcweir                                     nGrammarErrorPosInText = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nBeginGrammarCheck );
2003cdf0e10cSrcweir                                     aResult = xGCIterator->checkSentenceAtPosition(
2004cdf0e10cSrcweir                                             xDoc, xFlatPara, aExpandText, lang::Locale(), nBeginGrammarCheck, -1, -1 );
2005cdf0e10cSrcweir 
2006cdf0e10cSrcweir                                     lcl_syncGrammarError( *((SwTxtNode*)pNd), aResult, nBeginGrammarCheck, pConversionMap );
2007cdf0e10cSrcweir 
2008cdf0e10cSrcweir                                     // get suggestions to use for the specific error position
2009cdf0e10cSrcweir                                     nGrammarErrors = aResult.aErrors.getLength();
2010cdf0e10cSrcweir                                     // if grammar checking doesn't have any progress then quit
2011cdf0e10cSrcweir                                     if( aResult.nStartOfNextSentencePosition <= nBeginGrammarCheck )
2012cdf0e10cSrcweir                                         break;
2013cdf0e10cSrcweir                                     // prepare next iteration
2014cdf0e10cSrcweir                                     nBeginGrammarCheck = (xub_StrLen)aResult.nStartOfNextSentencePosition;
2015cdf0e10cSrcweir                                 }
2016cdf0e10cSrcweir                                 while( nSpellErrorPosition > aResult.nBehindEndOfSentencePosition && !nGrammarErrors && aResult.nBehindEndOfSentencePosition < nEndGrammarCheck );
2017cdf0e10cSrcweir 
2018cdf0e10cSrcweir                                 if( nGrammarErrors > 0 && nSpellErrorPosition >= aResult.nBehindEndOfSentencePosition )
2019cdf0e10cSrcweir                                 {
2020cdf0e10cSrcweir                                     aRet <<= aResult;
2021cdf0e10cSrcweir                                     //put the cursor to the current error
2022cdf0e10cSrcweir                                     const linguistic2::SingleProofreadingError &rError = aResult.aErrors[0];
2023cdf0e10cSrcweir 						            nCurrNd = pNd->GetIndex();
2024cdf0e10cSrcweir                                     pSttPos->nNode = nCurrNd;
2025cdf0e10cSrcweir 							        pEndPos->nNode = nCurrNd;
2026cdf0e10cSrcweir                                     pSpellArgs->pStartNode = ((SwTxtNode*)pNd);
2027cdf0e10cSrcweir 						            pSpellArgs->pEndNode = ((SwTxtNode*)pNd);
2028cdf0e10cSrcweir                                     pSpellArgs->pStartIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart ).mnPos );
2029cdf0e10cSrcweir                                     pSpellArgs->pEndIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart + rError.nErrorLength ).mnPos );
2030cdf0e10cSrcweir                                     nCurrNd = nEndNd;
2031cdf0e10cSrcweir                                 }
2032cdf0e10cSrcweir                             }
2033cdf0e10cSrcweir                         }
2034cdf0e10cSrcweir                     }
2035cdf0e10cSrcweir                 }
2036cdf0e10cSrcweir 				break;
2037cdf0e10cSrcweir 			case ND_SECTIONNODE:
2038cdf0e10cSrcweir                 if( ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
2039cdf0e10cSrcweir                     ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
2040cdf0e10cSrcweir 					nCurrNd = pNd->EndOfSectionIndex();
2041cdf0e10cSrcweir 				break;
2042cdf0e10cSrcweir 			case ND_ENDNODE:
2043cdf0e10cSrcweir 				{
2044cdf0e10cSrcweir 					break;
2045cdf0e10cSrcweir 				}
2046cdf0e10cSrcweir 			}
2047cdf0e10cSrcweir 
2048cdf0e10cSrcweir             bGoOn = nCurrNd < nEndNd;
2049cdf0e10cSrcweir             ++nCurrNd;
2050cdf0e10cSrcweir 		}
2051cdf0e10cSrcweir 	}
2052cdf0e10cSrcweir 
2053cdf0e10cSrcweir     if( !aRet.hasValue() )
2054cdf0e10cSrcweir     {
2055cdf0e10cSrcweir         if (pConvArgs)
2056cdf0e10cSrcweir             aRet <<= pConvArgs->aConvText;
2057cdf0e10cSrcweir         else
2058cdf0e10cSrcweir             aRet <<= pSpellArgs->xSpellAlt;
2059cdf0e10cSrcweir     }
2060cdf0e10cSrcweir     delete pSpellArgs;
2061cdf0e10cSrcweir 
2062cdf0e10cSrcweir     return aRet;
2063cdf0e10cSrcweir }
2064cdf0e10cSrcweir 
2065cdf0e10cSrcweir class SwHyphArgs : public SwInterHyphInfo
2066cdf0e10cSrcweir {
2067cdf0e10cSrcweir 	const SwNode *pStart;
2068cdf0e10cSrcweir 	const SwNode *pEnd;
2069cdf0e10cSrcweir 		  SwNode *pNode;
2070cdf0e10cSrcweir 	sal_uInt16 *pPageCnt;
2071cdf0e10cSrcweir 	sal_uInt16 *pPageSt;
2072cdf0e10cSrcweir 
2073cdf0e10cSrcweir 	sal_uInt32 nNode;
2074cdf0e10cSrcweir 	xub_StrLen nPamStart;
2075cdf0e10cSrcweir 	xub_StrLen nPamLen;
2076cdf0e10cSrcweir 
2077cdf0e10cSrcweir public:
2078cdf0e10cSrcweir 		 SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
2079cdf0e10cSrcweir 						 sal_uInt16* pPageCount, sal_uInt16* pPageStart );
2080cdf0e10cSrcweir 	void SetPam( SwPaM *pPam ) const;
SetNode(SwNode * pNew)2081cdf0e10cSrcweir 	inline void SetNode( SwNode *pNew ) { pNode = pNew; }
GetNode() const2082cdf0e10cSrcweir 	inline const SwNode *GetNode() const { return pNode; }
2083cdf0e10cSrcweir 	inline void SetRange( const SwNode *pNew );
NextNode()2084cdf0e10cSrcweir 	inline void NextNode() { ++nNode; }
GetPageCnt()2085cdf0e10cSrcweir 	inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
GetPageSt()2086cdf0e10cSrcweir 	inline sal_uInt16 *GetPageSt() { return pPageSt; }
2087cdf0e10cSrcweir };
2088cdf0e10cSrcweir 
SwHyphArgs(const SwPaM * pPam,const Point & rCrsrPos,sal_uInt16 * pPageCount,sal_uInt16 * pPageStart)2089cdf0e10cSrcweir SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
2090cdf0e10cSrcweir 						 sal_uInt16* pPageCount, sal_uInt16* pPageStart )
2091cdf0e10cSrcweir 	 : SwInterHyphInfo( rCrsrPos ), pNode(0),
2092cdf0e10cSrcweir 	 pPageCnt( pPageCount ), pPageSt( pPageStart )
2093cdf0e10cSrcweir {
2094cdf0e10cSrcweir 	// Folgende Bedingungen muessen eingehalten werden:
2095cdf0e10cSrcweir 	// 1) es gibt mindestens eine Selektion
2096cdf0e10cSrcweir 	// 2) SPoint() == Start()
2097cdf0e10cSrcweir 	ASSERT( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
2098cdf0e10cSrcweir 	ASSERT( *pPam->GetPoint() <= *pPam->GetMark(),
2099cdf0e10cSrcweir 			"SwDoc::Hyphenate: New York, New York");
2100cdf0e10cSrcweir 
2101cdf0e10cSrcweir 	const SwPosition *pPoint = pPam->GetPoint();
2102cdf0e10cSrcweir 	nNode = pPoint->nNode.GetIndex();
2103cdf0e10cSrcweir 
2104cdf0e10cSrcweir 	// Start einstellen
2105cdf0e10cSrcweir 	pStart = pPoint->nNode.GetNode().GetTxtNode();
2106cdf0e10cSrcweir 	nPamStart = pPoint->nContent.GetIndex();
2107cdf0e10cSrcweir 
2108cdf0e10cSrcweir 	// Ende und Laenge einstellen.
2109cdf0e10cSrcweir 	const SwPosition *pMark = pPam->GetMark();
2110cdf0e10cSrcweir 	pEnd = pMark->nNode.GetNode().GetTxtNode();
2111cdf0e10cSrcweir 	nPamLen = pMark->nContent.GetIndex();
2112cdf0e10cSrcweir 	if( pPoint->nNode == pMark->nNode )
2113cdf0e10cSrcweir 		nPamLen = nPamLen - pPoint->nContent.GetIndex();
2114cdf0e10cSrcweir }
2115cdf0e10cSrcweir 
SetRange(const SwNode * pNew)2116cdf0e10cSrcweir inline void SwHyphArgs::SetRange( const SwNode *pNew )
2117cdf0e10cSrcweir {
2118cdf0e10cSrcweir 	nStart = pStart == pNew ? nPamStart : 0;
2119cdf0e10cSrcweir 	nLen   = pEnd	== pNew ? nPamLen : STRING_NOTFOUND;
2120cdf0e10cSrcweir }
2121cdf0e10cSrcweir 
SetPam(SwPaM * pPam) const2122cdf0e10cSrcweir void SwHyphArgs::SetPam( SwPaM *pPam ) const
2123cdf0e10cSrcweir {
2124cdf0e10cSrcweir 	if( !pNode )
2125cdf0e10cSrcweir 		*pPam->GetPoint() = *pPam->GetMark();
2126cdf0e10cSrcweir 	else
2127cdf0e10cSrcweir 	{
2128cdf0e10cSrcweir 		pPam->GetPoint()->nNode = nNode;
2129cdf0e10cSrcweir 		pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
2130cdf0e10cSrcweir 		pPam->GetMark()->nNode = nNode;
2131cdf0e10cSrcweir 		pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
2132cdf0e10cSrcweir 										  nWordStart + nWordLen );
2133cdf0e10cSrcweir 		ASSERT( nNode == pNode->GetIndex(),
2134cdf0e10cSrcweir 				"SwHyphArgs::SetPam: Pam desaster" );
2135cdf0e10cSrcweir 	}
2136cdf0e10cSrcweir }
2137cdf0e10cSrcweir 
2138cdf0e10cSrcweir // liefert sal_True zurueck, wenn es weitergehen soll.
lcl_HyphenateNode(const SwNodePtr & rpNd,void * pArgs)2139cdf0e10cSrcweir sal_Bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
2140cdf0e10cSrcweir {
2141cdf0e10cSrcweir 	// Hyphenate liefert sal_True zurueck, wenn eine Trennstelle anliegt
2142cdf0e10cSrcweir 	// und stellt pPam ein.
2143cdf0e10cSrcweir 	SwTxtNode *pNode = rpNd->GetTxtNode();
2144cdf0e10cSrcweir 	SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
2145cdf0e10cSrcweir 	if( pNode )
2146cdf0e10cSrcweir 	{
2147cdf0e10cSrcweir 		SwCntntFrm* pCntFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout() );
2148cdf0e10cSrcweir 		if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
2149cdf0e10cSrcweir 		{
2150cdf0e10cSrcweir 			sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
2151cdf0e10cSrcweir 			sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
2152cdf0e10cSrcweir 			if( pPageCnt && *pPageCnt && pPageSt )
2153cdf0e10cSrcweir 			{
2154cdf0e10cSrcweir 				sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
2155cdf0e10cSrcweir 				if( !*pPageSt )
2156cdf0e10cSrcweir 				{
2157cdf0e10cSrcweir 					*pPageSt = nPageNr;
2158cdf0e10cSrcweir 					if( *pPageCnt < *pPageSt )
2159cdf0e10cSrcweir 						*pPageCnt = *pPageSt;
2160cdf0e10cSrcweir 				}
2161cdf0e10cSrcweir 				long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
2162cdf0e10cSrcweir 										 : nPageNr + *pPageCnt - *pPageSt + 1;
2163cdf0e10cSrcweir 				::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
2164cdf0e10cSrcweir 			}
2165cdf0e10cSrcweir 			pHyphArgs->SetRange( rpNd );
2166cdf0e10cSrcweir 			if( pNode->Hyphenate( *pHyphArgs ) )
2167cdf0e10cSrcweir 			{
2168cdf0e10cSrcweir 				pHyphArgs->SetNode( rpNd );
2169cdf0e10cSrcweir 				return sal_False;
2170cdf0e10cSrcweir 			}
2171cdf0e10cSrcweir 		}
2172cdf0e10cSrcweir 	}
2173cdf0e10cSrcweir 	pHyphArgs->NextNode();
2174cdf0e10cSrcweir 	return sal_True;
2175cdf0e10cSrcweir }
2176cdf0e10cSrcweir 
Hyphenate(SwPaM * pPam,const Point & rCrsrPos,sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt)2177cdf0e10cSrcweir uno::Reference< XHyphenatedWord >  SwDoc::Hyphenate(
2178cdf0e10cSrcweir 							SwPaM *pPam, const Point &rCrsrPos,
2179cdf0e10cSrcweir 						 	sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
2180cdf0e10cSrcweir {
2181cdf0e10cSrcweir 	ASSERT(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
2182cdf0e10cSrcweir 
2183cdf0e10cSrcweir 	if( *pPam->GetPoint() > *pPam->GetMark() )
2184cdf0e10cSrcweir 		pPam->Exchange();
2185cdf0e10cSrcweir 
2186cdf0e10cSrcweir 	SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
2187cdf0e10cSrcweir 	SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
2188cdf0e10cSrcweir 	GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
2189cdf0e10cSrcweir 					lcl_HyphenateNode, &aHyphArg );
2190cdf0e10cSrcweir 	aHyphArg.SetPam( pPam );
2191cdf0e10cSrcweir 	return aHyphArg.GetHyphWord();	// will be set by lcl_HyphenateNode
2192cdf0e10cSrcweir }
2193cdf0e10cSrcweir 
2194cdf0e10cSrcweir 
lcl_GetTokenToParaBreak(String & rStr,String & rRet,sal_Bool bRegExpRplc)2195cdf0e10cSrcweir sal_Bool lcl_GetTokenToParaBreak( String& rStr, String& rRet, sal_Bool bRegExpRplc )
2196cdf0e10cSrcweir {
2197cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
2198cdf0e10cSrcweir 	if( bRegExpRplc )
2199cdf0e10cSrcweir 	{
2200cdf0e10cSrcweir 		xub_StrLen nPos = 0;
2201cdf0e10cSrcweir 		String sPara( String::CreateFromAscii(
2202cdf0e10cSrcweir 									RTL_CONSTASCII_STRINGPARAM( "\\n" )));
2203cdf0e10cSrcweir 		while( STRING_NOTFOUND != ( nPos = rStr.Search( sPara, nPos )) )
2204cdf0e10cSrcweir 		{
2205cdf0e10cSrcweir 			// wurde das escaped?
2206cdf0e10cSrcweir 			if( nPos && '\\' == rStr.GetChar( nPos-1 ))
2207cdf0e10cSrcweir 			{
2208cdf0e10cSrcweir 				if( ++nPos >= rStr.Len() )
2209cdf0e10cSrcweir 					break;
2210cdf0e10cSrcweir 			}
2211cdf0e10cSrcweir 			else
2212cdf0e10cSrcweir 			{
2213cdf0e10cSrcweir 				rRet = rStr.Copy( 0, nPos );
2214cdf0e10cSrcweir 				rStr.Erase( 0, nPos + sPara.Len() );
2215cdf0e10cSrcweir 				bRet = sal_True;
2216cdf0e10cSrcweir 				break;
2217cdf0e10cSrcweir 			}
2218cdf0e10cSrcweir 		}
2219cdf0e10cSrcweir 	}
2220cdf0e10cSrcweir 	if( !bRet )
2221cdf0e10cSrcweir 	{
2222cdf0e10cSrcweir 		rRet = rStr;
2223cdf0e10cSrcweir 		rStr.Erase();
2224cdf0e10cSrcweir 	}
2225cdf0e10cSrcweir 	return bRet;
2226cdf0e10cSrcweir }
2227cdf0e10cSrcweir 
ReplaceRange(SwPaM & rPam,const String & rStr,const bool bRegExReplace)2228cdf0e10cSrcweir bool SwDoc::ReplaceRange( SwPaM& rPam, const String& rStr,
2229cdf0e10cSrcweir         const bool bRegExReplace )
2230cdf0e10cSrcweir {
2231cdf0e10cSrcweir     // unfortunately replace works slightly differently from delete,
2232cdf0e10cSrcweir     // so we cannot use lcl_DoWithBreaks here...
2233cdf0e10cSrcweir 
2234cdf0e10cSrcweir     ::std::vector<xub_StrLen> Breaks;
2235cdf0e10cSrcweir 
2236cdf0e10cSrcweir     SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2237cdf0e10cSrcweir     aPam.Normalize(sal_False);
2238cdf0e10cSrcweir     if (aPam.GetPoint()->nNode != aPam.GetMark()->nNode)
2239cdf0e10cSrcweir     {
2240cdf0e10cSrcweir         aPam.Move(fnMoveBackward);
2241cdf0e10cSrcweir     }
2242cdf0e10cSrcweir     ASSERT((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?");
2243cdf0e10cSrcweir 
2244cdf0e10cSrcweir     lcl_CalcBreaks(Breaks, aPam);
2245cdf0e10cSrcweir 
2246cdf0e10cSrcweir     while (!Breaks.empty() // skip over prefix of dummy chars
2247cdf0e10cSrcweir             && (aPam.GetMark()->nContent.GetIndex() == *Breaks.begin()) )
2248cdf0e10cSrcweir     {
2249cdf0e10cSrcweir         // skip!
2250cdf0e10cSrcweir         ++aPam.GetMark()->nContent; // always in bounds if Breaks valid
2251cdf0e10cSrcweir         Breaks.erase(Breaks.begin());
2252cdf0e10cSrcweir     }
2253cdf0e10cSrcweir     *rPam.Start() = *aPam.GetMark(); // update start of original pam w/ prefix
2254cdf0e10cSrcweir 
2255cdf0e10cSrcweir     if (!Breaks.size())
2256cdf0e10cSrcweir     {
2257cdf0e10cSrcweir         return ReplaceRangeImpl(rPam, rStr, bRegExReplace); // original pam!
2258cdf0e10cSrcweir     }
2259cdf0e10cSrcweir 
2260cdf0e10cSrcweir     // N.B.: deletion must be split into several parts if the text node
2261cdf0e10cSrcweir     // contains a text attribute with end and with dummy character
2262cdf0e10cSrcweir     // and the selection does not contain the text attribute completely,
2263cdf0e10cSrcweir     // but overlaps its start (left), where the dummy character is.
2264cdf0e10cSrcweir 
2265cdf0e10cSrcweir     bool bRet( true );
2266cdf0e10cSrcweir     // iterate from end to start, to avoid invalidating the offsets!
2267cdf0e10cSrcweir     ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
2268cdf0e10cSrcweir     ASSERT(aPam.GetPoint() == aPam.End(), "wrong!");
2269cdf0e10cSrcweir     SwPosition & rEnd( *aPam.End() );
2270cdf0e10cSrcweir     SwPosition & rStart( *aPam.Start() );
2271cdf0e10cSrcweir 
2272cdf0e10cSrcweir     // set end of temp pam to original end (undo Move backward above)
2273cdf0e10cSrcweir     rEnd = *rPam.End();
2274cdf0e10cSrcweir     // after first deletion, rEnd will point into the original text node again!
2275cdf0e10cSrcweir 
2276cdf0e10cSrcweir     while (iter != Breaks.rend())
2277cdf0e10cSrcweir     {
2278cdf0e10cSrcweir         rStart.nContent = *iter + 1;
2279cdf0e10cSrcweir         if (rEnd.nContent != rStart.nContent) // check if part is empty
2280cdf0e10cSrcweir         {
2281cdf0e10cSrcweir             bRet &= (IsRedlineOn())
2282cdf0e10cSrcweir                 ? DeleteAndJoinWithRedlineImpl(aPam)
2283cdf0e10cSrcweir                 : DeleteAndJoinImpl(aPam, false);
2284cdf0e10cSrcweir         }
2285cdf0e10cSrcweir         rEnd.nContent = *iter;
2286cdf0e10cSrcweir         ++iter;
2287cdf0e10cSrcweir     }
2288cdf0e10cSrcweir 
2289cdf0e10cSrcweir     rStart = *rPam.Start(); // set to original start
2290cdf0e10cSrcweir     ASSERT(rEnd.nContent > rStart.nContent, "replace part empty!");
2291cdf0e10cSrcweir     if (rEnd.nContent > rStart.nContent) // check if part is empty
2292cdf0e10cSrcweir     {
2293cdf0e10cSrcweir         bRet &= ReplaceRangeImpl(aPam, rStr, bRegExReplace);
2294cdf0e10cSrcweir     }
2295cdf0e10cSrcweir 
2296cdf0e10cSrcweir     rPam = aPam; // update original pam (is this required?)
2297cdf0e10cSrcweir 
2298cdf0e10cSrcweir     return bRet;
2299cdf0e10cSrcweir }
2300cdf0e10cSrcweir 
2301cdf0e10cSrcweir // N.B.: it is possible to call Replace with a PaM that spans 2 paragraphs:
2302cdf0e10cSrcweir // search with regex for "$", then replace _all_
ReplaceRangeImpl(SwPaM & rPam,const String & rStr,const bool bRegExReplace)2303cdf0e10cSrcweir bool SwDoc::ReplaceRangeImpl( SwPaM& rPam, const String& rStr,
2304cdf0e10cSrcweir         const bool bRegExReplace )
2305cdf0e10cSrcweir {
2306cdf0e10cSrcweir 	if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
2307cdf0e10cSrcweir         return false;
2308cdf0e10cSrcweir 
2309cdf0e10cSrcweir 	sal_Bool bJoinTxt, bJoinPrev;
2310cdf0e10cSrcweir 	lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
2311cdf0e10cSrcweir 
2312cdf0e10cSrcweir 	{
2313cdf0e10cSrcweir 		// dann eine Kopie vom Cursor erzeugen um alle Pams aus den
2314cdf0e10cSrcweir 		// anderen Sichten aus dem Loeschbereich zu verschieben
2315cdf0e10cSrcweir 		// ABER NICHT SICH SELBST !!
2316cdf0e10cSrcweir 		SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
2317cdf0e10cSrcweir 		::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
2318cdf0e10cSrcweir 
2319cdf0e10cSrcweir 		SwPosition *pStt = (SwPosition*)aDelPam.Start(),
2320cdf0e10cSrcweir 				   *pEnd = (SwPosition*)aDelPam.End();
2321cdf0e10cSrcweir 		ASSERT( pStt->nNode == pEnd->nNode ||
2322cdf0e10cSrcweir 				( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
2323cdf0e10cSrcweir 					!pEnd->nContent.GetIndex() ),
2324cdf0e10cSrcweir                 "invalid range: Point and Mark on different nodes" );
2325cdf0e10cSrcweir 		sal_Bool bOneNode = pStt->nNode == pEnd->nNode;
2326cdf0e10cSrcweir 
2327cdf0e10cSrcweir 		// eigenes Undo ????
2328cdf0e10cSrcweir 		String sRepl( rStr );
2329cdf0e10cSrcweir 		SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
2330cdf0e10cSrcweir 		xub_StrLen nStt = pStt->nContent.GetIndex(),
2331cdf0e10cSrcweir 				nEnd = bOneNode ? pEnd->nContent.GetIndex()
2332cdf0e10cSrcweir 								: pTxtNd->GetTxt().Len();
2333cdf0e10cSrcweir 
2334cdf0e10cSrcweir 		SwDataChanged aTmp( aDelPam, 0 );
2335cdf0e10cSrcweir 
2336cdf0e10cSrcweir 		if( IsRedlineOn() )
2337cdf0e10cSrcweir         {
2338cdf0e10cSrcweir 			RedlineMode_t eOld = GetRedlineMode();
2339cdf0e10cSrcweir 			checkRedlining(eOld);
2340cdf0e10cSrcweir             if (GetIDocumentUndoRedo().DoesUndo())
2341cdf0e10cSrcweir             {
2342cdf0e10cSrcweir                 GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
2343cdf0e10cSrcweir 
2344cdf0e10cSrcweir                 // Bug 68584 - if any Redline will change (split!) the node
2345cdf0e10cSrcweir                 const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
2346cdf0e10cSrcweir 
2347cdf0e10cSrcweir                 //JP 06.01.98: MUSS noch optimiert werden!!!
2348cdf0e10cSrcweir                 SetRedlineMode(
2349cdf0e10cSrcweir                     (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
2350cdf0e10cSrcweir 
2351cdf0e10cSrcweir                 *aDelPam.GetPoint() = pBkmk->GetMarkPos();
2352cdf0e10cSrcweir                 if(pBkmk->IsExpanded())
2353cdf0e10cSrcweir                     *aDelPam.GetMark() = pBkmk->GetOtherMarkPos();
2354cdf0e10cSrcweir                 getIDocumentMarkAccess()->deleteMark(pBkmk);
2355cdf0e10cSrcweir                 pStt = aDelPam.Start();
2356cdf0e10cSrcweir                 pTxtNd = pStt->nNode.GetNode().GetTxtNode();
2357cdf0e10cSrcweir                 nStt = pStt->nContent.GetIndex();
2358cdf0e10cSrcweir 			}
2359cdf0e10cSrcweir 
2360cdf0e10cSrcweir 			if( sRepl.Len() )
2361cdf0e10cSrcweir 			{
2362cdf0e10cSrcweir 				// Attribute des 1. Zeichens ueber den ReplaceText setzen
2363cdf0e10cSrcweir 				SfxItemSet aSet( GetAttrPool(),
2364cdf0e10cSrcweir 							RES_CHRATR_BEGIN,	  RES_TXTATR_WITHEND_END - 1,
2365cdf0e10cSrcweir 							RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
2366cdf0e10cSrcweir 							0 );
2367cdf0e10cSrcweir 				pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
2368cdf0e10cSrcweir 
2369cdf0e10cSrcweir 				aSet.ClearItem( RES_TXTATR_REFMARK );
2370cdf0e10cSrcweir 				aSet.ClearItem( RES_TXTATR_TOXMARK );
2371cdf0e10cSrcweir                 aSet.ClearItem( RES_TXTATR_CJK_RUBY );
2372cdf0e10cSrcweir                 aSet.ClearItem( RES_TXTATR_INETFMT );
2373cdf0e10cSrcweir                 aSet.ClearItem( RES_TXTATR_META );
2374cdf0e10cSrcweir                 aSet.ClearItem( RES_TXTATR_METAFIELD );
2375cdf0e10cSrcweir 
2376cdf0e10cSrcweir 				if( aDelPam.GetPoint() != aDelPam.End() )
2377cdf0e10cSrcweir 					aDelPam.Exchange();
2378cdf0e10cSrcweir 
2379cdf0e10cSrcweir 				// das Ende merken
2380cdf0e10cSrcweir 				SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
2381cdf0e10cSrcweir 				xub_StrLen nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
2382cdf0e10cSrcweir 
2383cdf0e10cSrcweir 				sal_Bool bFirst = sal_True;
2384cdf0e10cSrcweir 				String sIns;
2385cdf0e10cSrcweir                 while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
2386cdf0e10cSrcweir 				{
2387cdf0e10cSrcweir                     InsertString( aDelPam, sIns );
2388cdf0e10cSrcweir 					if( bFirst )
2389cdf0e10cSrcweir 					{
2390cdf0e10cSrcweir 						SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
2391cdf0e10cSrcweir 						xub_StrLen nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
2392cdf0e10cSrcweir 
2393cdf0e10cSrcweir 						SplitNode( *aDelPam.GetPoint(), false );
2394cdf0e10cSrcweir 
2395cdf0e10cSrcweir 						aMkNd++;
2396cdf0e10cSrcweir 						aDelPam.GetMark()->nNode = aMkNd;
2397cdf0e10cSrcweir 						aDelPam.GetMark()->nContent.Assign(
2398cdf0e10cSrcweir 									aMkNd.GetNode().GetCntntNode(), nMkCnt );
2399cdf0e10cSrcweir 						bFirst = sal_False;
2400cdf0e10cSrcweir 					}
2401cdf0e10cSrcweir 					else
2402cdf0e10cSrcweir 						SplitNode( *aDelPam.GetPoint(), false );
2403cdf0e10cSrcweir 				}
2404cdf0e10cSrcweir 				if( sIns.Len() )
2405cdf0e10cSrcweir                 {
2406cdf0e10cSrcweir                     InsertString( aDelPam, sIns );
2407cdf0e10cSrcweir                 }
2408cdf0e10cSrcweir 
2409cdf0e10cSrcweir 				SwPaM aTmpRange( *aDelPam.GetPoint() );
2410cdf0e10cSrcweir 				aTmpRange.SetMark();
2411cdf0e10cSrcweir 
2412cdf0e10cSrcweir 				aPtNd++;
2413cdf0e10cSrcweir 				aDelPam.GetPoint()->nNode = aPtNd;
2414cdf0e10cSrcweir 				aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
2415cdf0e10cSrcweir 													nPtCnt);
2416cdf0e10cSrcweir 				*aTmpRange.GetMark() = *aDelPam.GetPoint();
2417cdf0e10cSrcweir 
2418cdf0e10cSrcweir                 RstTxtAttrs( aTmpRange );
2419cdf0e10cSrcweir                 InsertItemSet( aTmpRange, aSet, 0 );
2420cdf0e10cSrcweir             }
2421cdf0e10cSrcweir 
2422cdf0e10cSrcweir             if (GetIDocumentUndoRedo().DoesUndo())
2423cdf0e10cSrcweir             {
2424cdf0e10cSrcweir                 SwUndo *const pUndoRD =
2425cdf0e10cSrcweir                     new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE );
2426cdf0e10cSrcweir                 GetIDocumentUndoRedo().AppendUndo(pUndoRD);
2427cdf0e10cSrcweir             }
2428cdf0e10cSrcweir 			AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDelPam ), true);
2429cdf0e10cSrcweir 
2430cdf0e10cSrcweir 			*rPam.GetMark() = *aDelPam.GetMark();
2431cdf0e10cSrcweir             if (GetIDocumentUndoRedo().DoesUndo())
2432cdf0e10cSrcweir             {
2433cdf0e10cSrcweir 				*aDelPam.GetPoint() = *rPam.GetPoint();
2434cdf0e10cSrcweir                 GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
2435cdf0e10cSrcweir 
2436cdf0e10cSrcweir 				// Bug 68584 - if any Redline will change (split!) the node
2437cdf0e10cSrcweir                 const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
2438cdf0e10cSrcweir 
2439cdf0e10cSrcweir 				SwIndex& rIdx = aDelPam.GetPoint()->nContent;
2440cdf0e10cSrcweir 				rIdx.Assign( 0, 0 );
2441cdf0e10cSrcweir 				aDelPam.GetMark()->nContent = rIdx;
2442cdf0e10cSrcweir 				rPam.GetPoint()->nNode = 0;
2443cdf0e10cSrcweir 				rPam.GetPoint()->nContent = rIdx;
2444cdf0e10cSrcweir 				*rPam.GetMark() = *rPam.GetPoint();
2445cdf0e10cSrcweir //JP 06.01.98: MUSS noch optimiert werden!!!
2446cdf0e10cSrcweir SetRedlineMode( eOld );
2447cdf0e10cSrcweir 
2448cdf0e10cSrcweir                 *rPam.GetPoint() = pBkmk->GetMarkPos();
2449cdf0e10cSrcweir                 if(pBkmk->IsExpanded())
2450cdf0e10cSrcweir                     *rPam.GetMark() = pBkmk->GetOtherMarkPos();
2451cdf0e10cSrcweir                 getIDocumentMarkAccess()->deleteMark(pBkmk);
2452cdf0e10cSrcweir 			}
2453cdf0e10cSrcweir 			bJoinTxt = sal_False;
2454cdf0e10cSrcweir 		}
2455cdf0e10cSrcweir 		else
2456cdf0e10cSrcweir 		{
2457cdf0e10cSrcweir 			if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
2458cdf0e10cSrcweir 				DeleteRedline( aDelPam, true, USHRT_MAX );
2459cdf0e10cSrcweir 
2460cdf0e10cSrcweir 			SwUndoReplace* pUndoRpl = 0;
2461cdf0e10cSrcweir             bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
2462cdf0e10cSrcweir             if (bDoesUndo)
2463cdf0e10cSrcweir             {
2464cdf0e10cSrcweir                 pUndoRpl = new SwUndoReplace(aDelPam, sRepl, bRegExReplace);
2465cdf0e10cSrcweir                 GetIDocumentUndoRedo().AppendUndo(pUndoRpl);
2466cdf0e10cSrcweir             }
2467cdf0e10cSrcweir             ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2468cdf0e10cSrcweir 
2469cdf0e10cSrcweir 			if( aDelPam.GetPoint() != pStt )
2470cdf0e10cSrcweir 				aDelPam.Exchange();
2471cdf0e10cSrcweir 
2472cdf0e10cSrcweir 			SwNodeIndex aPtNd( pStt->nNode, -1 );
2473cdf0e10cSrcweir 			xub_StrLen nPtCnt = pStt->nContent.GetIndex();
2474cdf0e10cSrcweir 
2475cdf0e10cSrcweir 			// die Werte nochmal setzen, falls schohn Rahmen oder Fussnoten
2476cdf0e10cSrcweir 			// auf dem Text entfernt wurden!
2477cdf0e10cSrcweir 			nStt = nPtCnt;
2478cdf0e10cSrcweir 			nEnd = bOneNode ? pEnd->nContent.GetIndex()
2479cdf0e10cSrcweir 							: pTxtNd->GetTxt().Len();
2480cdf0e10cSrcweir 
2481cdf0e10cSrcweir 			sal_Bool bFirst = sal_True;
2482cdf0e10cSrcweir 			String sIns;
2483cdf0e10cSrcweir             while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
2484cdf0e10cSrcweir 			{
2485cdf0e10cSrcweir 				if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
2486cdf0e10cSrcweir                 {
2487cdf0e10cSrcweir                     InsertString( aDelPam, sIns );
2488cdf0e10cSrcweir                 }
2489cdf0e10cSrcweir 				else if( nStt < nEnd || sIns.Len() )
2490cdf0e10cSrcweir                 {
2491cdf0e10cSrcweir                     pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
2492cdf0e10cSrcweir                 }
2493cdf0e10cSrcweir 				SplitNode( *pStt, false);
2494cdf0e10cSrcweir 				bFirst = sal_False;
2495cdf0e10cSrcweir 			}
2496cdf0e10cSrcweir 
2497cdf0e10cSrcweir 			if( bFirst || sIns.Len() )
2498cdf0e10cSrcweir 			{
2499cdf0e10cSrcweir 				if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
2500cdf0e10cSrcweir                 {
2501cdf0e10cSrcweir                     InsertString( aDelPam, sIns );
2502cdf0e10cSrcweir                 }
2503cdf0e10cSrcweir 				else if( nStt < nEnd || sIns.Len() )
2504cdf0e10cSrcweir                 {
2505cdf0e10cSrcweir                     pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
2506cdf0e10cSrcweir                 }
2507cdf0e10cSrcweir             }
2508cdf0e10cSrcweir 
2509cdf0e10cSrcweir 			*rPam.GetMark() = *aDelPam.GetMark();
2510cdf0e10cSrcweir 
2511cdf0e10cSrcweir 			aPtNd++;
2512cdf0e10cSrcweir 			rPam.GetMark()->nNode = aPtNd;
2513cdf0e10cSrcweir 			rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
2514cdf0e10cSrcweir 												nPtCnt );
2515cdf0e10cSrcweir 
25167879fa4dSOliver-Rainer Wittmann             if ( bJoinTxt && !bJoinPrev )
25177879fa4dSOliver-Rainer Wittmann             {
25187879fa4dSOliver-Rainer Wittmann                 rPam.Move( fnMoveBackward );
25197879fa4dSOliver-Rainer Wittmann             }
25207879fa4dSOliver-Rainer Wittmann 
2521cdf0e10cSrcweir 			if( pUndoRpl )
2522cdf0e10cSrcweir             {
2523cdf0e10cSrcweir                 pUndoRpl->SetEnd(rPam);
2524cdf0e10cSrcweir             }
2525cdf0e10cSrcweir         }
2526cdf0e10cSrcweir     }
2527cdf0e10cSrcweir 
2528cdf0e10cSrcweir 	if( bJoinTxt )
2529cdf0e10cSrcweir 		lcl_JoinText( rPam, bJoinPrev );
2530cdf0e10cSrcweir 
2531cdf0e10cSrcweir 	SetModified();
2532cdf0e10cSrcweir     return true;
2533cdf0e10cSrcweir }
2534cdf0e10cSrcweir 
2535cdf0e10cSrcweir 	// speicher die akt. Werte fuer die automatische Aufnahme von Ausnahmen
2536cdf0e10cSrcweir 	// in die Autokorrektur
SetAutoCorrExceptWord(SwAutoCorrExceptWord * pNew)2537cdf0e10cSrcweir void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
2538cdf0e10cSrcweir {
2539cdf0e10cSrcweir 	if( pACEWord && pNew != pACEWord )
2540cdf0e10cSrcweir 		delete pACEWord;
2541cdf0e10cSrcweir 	pACEWord = pNew;
2542cdf0e10cSrcweir }
2543cdf0e10cSrcweir 
DelFullPara(SwPaM & rPam)2544cdf0e10cSrcweir bool SwDoc::DelFullPara( SwPaM& rPam )
2545cdf0e10cSrcweir {
2546cdf0e10cSrcweir 	const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
2547cdf0e10cSrcweir 	const SwNode* pNd = &rStt.nNode.GetNode();
2548cdf0e10cSrcweir     sal_uInt32 nSectDiff = pNd->StartOfSectionNode()->EndOfSectionIndex() -
2549cdf0e10cSrcweir 						pNd->StartOfSectionIndex();
2550cdf0e10cSrcweir 	sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
2551cdf0e10cSrcweir 
2552cdf0e10cSrcweir 	if ( nSectDiff-2 <= nNodeDiff || IsRedlineOn() ||
2553cdf0e10cSrcweir 		 /* #i9185# Prevent getting the node after the end node (see below) */
2554cdf0e10cSrcweir         rEnd.nNode.GetIndex() + 1 == GetNodes().Count() )
2555cdf0e10cSrcweir     {
2556cdf0e10cSrcweir 		return sal_False;
2557cdf0e10cSrcweir     }
2558cdf0e10cSrcweir 
2559cdf0e10cSrcweir 	// harte SeitenUmbrueche am nachfolgenden Node verschieben
2560cdf0e10cSrcweir 	sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
2561cdf0e10cSrcweir 
2562cdf0e10cSrcweir 	/* #i9185# This whould lead to a segmentation fault if not catched
2563cdf0e10cSrcweir        above. */
2564cdf0e10cSrcweir 	sal_uLong nNextNd = rEnd.nNode.GetIndex() + 1;
2565cdf0e10cSrcweir     SwTableNode *const pTblNd = GetNodes()[ nNextNd ]->GetTableNode();
2566cdf0e10cSrcweir 
2567cdf0e10cSrcweir 	if( pTblNd && pNd->IsCntntNode() )
2568cdf0e10cSrcweir 	{
2569cdf0e10cSrcweir 		SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
2570cdf0e10cSrcweir //JP 24.08.98: will man wirklich den PageDesc/Break vom
2571cdf0e10cSrcweir //				nachfolgen Absatz ueberbuegeln?
2572cdf0e10cSrcweir //		const SwAttrSet& rAttrSet = pTableFmt->GetAttrSet();
2573cdf0e10cSrcweir //		if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
2574cdf0e10cSrcweir //			SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
2575cdf0e10cSrcweir 		{
2576cdf0e10cSrcweir 			const SfxPoolItem *pItem;
2577cdf0e10cSrcweir 			const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
2578cdf0e10cSrcweir 			if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
2579cdf0e10cSrcweir 				sal_False, &pItem ) )
2580cdf0e10cSrcweir 			{
2581cdf0e10cSrcweir                 pTableFmt->SetFmtAttr( *pItem );
2582cdf0e10cSrcweir 				bSavePageDesc = sal_True;
2583cdf0e10cSrcweir 			}
2584cdf0e10cSrcweir 
2585cdf0e10cSrcweir 			if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
2586cdf0e10cSrcweir 				sal_False, &pItem ) )
2587cdf0e10cSrcweir 			{
2588cdf0e10cSrcweir                 pTableFmt->SetFmtAttr( *pItem );
2589cdf0e10cSrcweir 				bSavePageBreak = sal_True;
2590cdf0e10cSrcweir 			}
2591cdf0e10cSrcweir 		}
2592cdf0e10cSrcweir 	}
2593cdf0e10cSrcweir 
2594cdf0e10cSrcweir     bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
2595cdf0e10cSrcweir 	if( bDoesUndo )
2596cdf0e10cSrcweir 	{
2597cdf0e10cSrcweir 		if( !rPam.HasMark() )
2598cdf0e10cSrcweir 			rPam.SetMark();
2599cdf0e10cSrcweir 		else if( rPam.GetPoint() == &rStt )
2600cdf0e10cSrcweir 			rPam.Exchange();
2601cdf0e10cSrcweir 		rPam.GetPoint()->nNode++;
2602cdf0e10cSrcweir 
2603cdf0e10cSrcweir         SwCntntNode *pTmpNode = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
2604cdf0e10cSrcweir         rPam.GetPoint()->nContent.Assign( pTmpNode, 0 );
2605cdf0e10cSrcweir         bool bGoNext = (0 == pTmpNode);
2606cdf0e10cSrcweir         pTmpNode = rPam.GetMark()->nNode.GetNode().GetCntntNode();
2607cdf0e10cSrcweir 		rPam.GetMark()->nContent.Assign( pTmpNode, 0 );
2608cdf0e10cSrcweir 
2609cdf0e10cSrcweir         GetIDocumentUndoRedo().ClearRedo();
2610cdf0e10cSrcweir 
2611cdf0e10cSrcweir 		SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
2612cdf0e10cSrcweir         {
2613cdf0e10cSrcweir             SwPosition aTmpPos( *aDelPam.GetPoint() );
2614cdf0e10cSrcweir             if( bGoNext )
2615cdf0e10cSrcweir             {
2616cdf0e10cSrcweir                 pTmpNode = GetNodes().GoNext( &aTmpPos.nNode );
2617cdf0e10cSrcweir                 aTmpPos.nContent.Assign( pTmpNode, 0 );
2618cdf0e10cSrcweir             }
2619cdf0e10cSrcweir             ::PaMCorrAbs( aDelPam, aTmpPos );
2620cdf0e10cSrcweir         }
2621cdf0e10cSrcweir 
2622cdf0e10cSrcweir 		SwUndoDelete* pUndo = new SwUndoDelete( aDelPam, sal_True );
2623cdf0e10cSrcweir 
2624cdf0e10cSrcweir 		*rPam.GetPoint() = *aDelPam.GetPoint();
2625cdf0e10cSrcweir 		pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
2626cdf0e10cSrcweir         GetIDocumentUndoRedo().AppendUndo(pUndo);
2627cdf0e10cSrcweir     }
2628cdf0e10cSrcweir     else
2629cdf0e10cSrcweir     {
2630cdf0e10cSrcweir 		SwNodeRange aRg( rStt.nNode, rEnd.nNode );
2631cdf0e10cSrcweir 		if( rPam.GetPoint() != &rEnd )
2632cdf0e10cSrcweir 			rPam.Exchange();
2633cdf0e10cSrcweir 
2634cdf0e10cSrcweir 		// versuche hinters Ende zu verschieben
2635cdf0e10cSrcweir 		if( !rPam.Move( fnMoveForward, fnGoNode ) )
2636cdf0e10cSrcweir 		{
2637cdf0e10cSrcweir 			// na gut, dann an den Anfang
2638cdf0e10cSrcweir 			rPam.Exchange();
2639cdf0e10cSrcweir 			if( !rPam.Move( fnMoveBackward, fnGoNode ))
2640cdf0e10cSrcweir 			{
2641cdf0e10cSrcweir 				ASSERT( sal_False, "kein Node mehr vorhanden" );
2642cdf0e10cSrcweir 				return sal_False;
2643cdf0e10cSrcweir 			}
2644cdf0e10cSrcweir 		}
2645cdf0e10cSrcweir         // move bookmarks, redlines etc.
2646cdf0e10cSrcweir         if (aRg.aStart == aRg.aEnd) // only first CorrAbs variant handles this
2647cdf0e10cSrcweir         {
2648cdf0e10cSrcweir             CorrAbs( aRg.aStart, *rPam.GetPoint(), 0, sal_True );
2649cdf0e10cSrcweir         }
2650cdf0e10cSrcweir         else
2651cdf0e10cSrcweir         {
2652cdf0e10cSrcweir             CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), sal_True );
2653cdf0e10cSrcweir         }
2654cdf0e10cSrcweir 
2655cdf0e10cSrcweir 			// was ist mit Fly's ??
2656cdf0e10cSrcweir 		{
2657cdf0e10cSrcweir 			// stehen noch FlyFrames rum, loesche auch diese
2658cdf0e10cSrcweir 			for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
2659cdf0e10cSrcweir 			{
2660cdf0e10cSrcweir 				SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
2661cdf0e10cSrcweir 				const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
2662cdf0e10cSrcweir                 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
2663cdf0e10cSrcweir                 if (pAPos &&
2664cdf0e10cSrcweir                     ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
2665cdf0e10cSrcweir                      (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
2666cdf0e10cSrcweir 					aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
2667cdf0e10cSrcweir 				{
2668cdf0e10cSrcweir 					DelLayoutFmt( pFly );
2669cdf0e10cSrcweir 					--n;
2670cdf0e10cSrcweir 				}
2671cdf0e10cSrcweir 			}
2672cdf0e10cSrcweir 		}
2673cdf0e10cSrcweir 
2674cdf0e10cSrcweir         SwCntntNode *pTmpNode = rPam.GetBound( sal_True ).nNode.GetNode().GetCntntNode();
2675cdf0e10cSrcweir 		rPam.GetBound( sal_True ).nContent.Assign( pTmpNode, 0 );
2676cdf0e10cSrcweir         pTmpNode = rPam.GetBound( sal_False ).nNode.GetNode().GetCntntNode();
2677cdf0e10cSrcweir 		rPam.GetBound( sal_False ).nContent.Assign( pTmpNode, 0 );
2678cdf0e10cSrcweir 		GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
2679cdf0e10cSrcweir 	}
2680cdf0e10cSrcweir 	rPam.DeleteMark();
2681cdf0e10cSrcweir 	SetModified();
2682cdf0e10cSrcweir 
2683cdf0e10cSrcweir 	return sal_True;
2684cdf0e10cSrcweir }
2685cdf0e10cSrcweir 
2686cdf0e10cSrcweir 
TransliterateText(const SwPaM & rPaM,utl::TransliterationWrapper & rTrans)2687cdf0e10cSrcweir void SwDoc::TransliterateText(
2688cdf0e10cSrcweir     const SwPaM& rPaM,
2689cdf0e10cSrcweir     utl::TransliterationWrapper& rTrans )
2690cdf0e10cSrcweir {
2691cdf0e10cSrcweir     SwUndoTransliterate *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
2692cdf0e10cSrcweir         ?   new SwUndoTransliterate( rPaM, rTrans )
2693cdf0e10cSrcweir         :   0;
2694cdf0e10cSrcweir 
2695cdf0e10cSrcweir     const SwPosition* pStt = rPaM.Start(),
2696cdf0e10cSrcweir        			    * pEnd = rPaM.End();
2697cdf0e10cSrcweir     sal_uLong nSttNd = pStt->nNode.GetIndex(),
2698cdf0e10cSrcweir           nEndNd = pEnd->nNode.GetIndex();
2699cdf0e10cSrcweir 	xub_StrLen nSttCnt = pStt->nContent.GetIndex(),
2700cdf0e10cSrcweir 			   nEndCnt = pEnd->nContent.GetIndex();
2701cdf0e10cSrcweir 
2702cdf0e10cSrcweir 	SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
2703cdf0e10cSrcweir 	if( pStt == pEnd && pTNd )  // no selection?
2704cdf0e10cSrcweir 	{
2705cdf0e10cSrcweir         // set current word as 'area of effect'
2706cdf0e10cSrcweir 
2707cdf0e10cSrcweir 		Boundary aBndry;
2708cdf0e10cSrcweir 		if( pBreakIt->GetBreakIter().is() )
2709cdf0e10cSrcweir 			aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
2710cdf0e10cSrcweir 						pTNd->GetTxt(), nSttCnt,
2711cdf0e10cSrcweir 						pBreakIt->GetLocale( pTNd->GetLang( nSttCnt ) ),
2712cdf0e10cSrcweir 						WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
2713cdf0e10cSrcweir 						sal_True );
2714cdf0e10cSrcweir 
2715cdf0e10cSrcweir 		if( aBndry.startPos < nSttCnt && nSttCnt < aBndry.endPos )
2716cdf0e10cSrcweir 		{
2717cdf0e10cSrcweir 			nSttCnt = (xub_StrLen)aBndry.startPos;
2718cdf0e10cSrcweir 			nEndCnt = (xub_StrLen)aBndry.endPos;
2719cdf0e10cSrcweir 		}
2720cdf0e10cSrcweir 	}
2721cdf0e10cSrcweir 
2722cdf0e10cSrcweir 	if( nSttNd != nEndNd )  // is more than one text node involved?
2723cdf0e10cSrcweir 	{
2724cdf0e10cSrcweir         // iterate over all effected text nodes, the first and the last one
2725cdf0e10cSrcweir         // may be incomplete because the selection starts and/or ends there
2726cdf0e10cSrcweir 
2727cdf0e10cSrcweir 		SwNodeIndex aIdx( pStt->nNode );
2728cdf0e10cSrcweir 		if( nSttCnt )
2729cdf0e10cSrcweir 		{
2730cdf0e10cSrcweir 			aIdx++;
2731cdf0e10cSrcweir 			if( pTNd )
2732cdf0e10cSrcweir 				pTNd->TransliterateText( rTrans, nSttCnt, pTNd->GetTxt().Len(), pUndo );
2733cdf0e10cSrcweir 		}
2734cdf0e10cSrcweir 
2735cdf0e10cSrcweir 		for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
2736cdf0e10cSrcweir         {
2737cdf0e10cSrcweir 			if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
2738cdf0e10cSrcweir 				pTNd->TransliterateText( rTrans, 0, pTNd->GetTxt().Len(), pUndo );
2739cdf0e10cSrcweir         }
2740cdf0e10cSrcweir 
2741cdf0e10cSrcweir 		if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
2742cdf0e10cSrcweir 			pTNd->TransliterateText( rTrans, 0, nEndCnt, pUndo );
2743cdf0e10cSrcweir 	}
2744cdf0e10cSrcweir 	else if( pTNd && nSttCnt < nEndCnt )
2745cdf0e10cSrcweir 		pTNd->TransliterateText( rTrans, nSttCnt, nEndCnt, pUndo );
2746cdf0e10cSrcweir 
2747cdf0e10cSrcweir 	if( pUndo )
2748cdf0e10cSrcweir 	{
2749cdf0e10cSrcweir 		if( pUndo->HasData() )
2750cdf0e10cSrcweir         {
2751cdf0e10cSrcweir             GetIDocumentUndoRedo().AppendUndo(pUndo);
2752cdf0e10cSrcweir         }
2753cdf0e10cSrcweir         else
2754cdf0e10cSrcweir 			delete pUndo;
2755cdf0e10cSrcweir 	}
2756cdf0e10cSrcweir     SetModified();
2757cdf0e10cSrcweir }
2758cdf0e10cSrcweir 
2759cdf0e10cSrcweir 
2760cdf0e10cSrcweir #define MAX_REDLINE_COUNT	250
2761cdf0e10cSrcweir // -----------------------------------------------------------------------------
checkRedlining(RedlineMode_t & _rReadlineMode)2762cdf0e10cSrcweir void SwDoc::checkRedlining(RedlineMode_t& _rReadlineMode)
2763cdf0e10cSrcweir {
2764cdf0e10cSrcweir 	const SwRedlineTbl& rRedlineTbl = GetRedlineTbl();
2765cdf0e10cSrcweir 	SwEditShell* pEditShell = GetEditShell();
2766cdf0e10cSrcweir 	Window* pParent = pEditShell ? pEditShell->GetWin() : NULL;
2767cdf0e10cSrcweir 	if ( pParent && !mbReadlineChecked && rRedlineTbl.Count() > MAX_REDLINE_COUNT
2768cdf0e10cSrcweir 		&& !((_rReadlineMode & nsRedlineMode_t::REDLINE_SHOW_DELETE) == nsRedlineMode_t::REDLINE_SHOW_DELETE) )
2769cdf0e10cSrcweir 	{
2770cdf0e10cSrcweir 		WarningBox aWarning( pParent,SW_RES(MSG_DISABLE_READLINE_QUESTION));
2771cdf0e10cSrcweir 		sal_uInt16 nResult = aWarning.Execute();
2772cdf0e10cSrcweir 		mbReadlineChecked = sal_True;
2773cdf0e10cSrcweir 		if ( nResult == RET_YES )
2774cdf0e10cSrcweir 		{
2775cdf0e10cSrcweir 			sal_Int32 nMode = (sal_Int32)_rReadlineMode;
2776cdf0e10cSrcweir 			nMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE;
2777cdf0e10cSrcweir 			_rReadlineMode = (RedlineMode_t)nMode;
2778cdf0e10cSrcweir 		}
2779cdf0e10cSrcweir 	}
2780cdf0e10cSrcweir }
2781cdf0e10cSrcweir // -----------------------------------------------------------------------------
2782cdf0e10cSrcweir 
CountWords(const SwPaM & rPaM,SwDocStat & rStat) const2783cdf0e10cSrcweir void SwDoc::CountWords( const SwPaM& rPaM, SwDocStat& rStat ) const
2784cdf0e10cSrcweir {
2785cdf0e10cSrcweir     // This is a modified version of SwDoc::TransliterateText
2786cdf0e10cSrcweir     const SwPosition* pStt = rPaM.Start();
2787cdf0e10cSrcweir     const SwPosition* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
2788cdf0e10cSrcweir                                                      : rPaM.GetPoint();
2789cdf0e10cSrcweir 
2790cdf0e10cSrcweir     const sal_uLong nSttNd = pStt->nNode.GetIndex();
2791cdf0e10cSrcweir     const sal_uLong nEndNd = pEnd->nNode.GetIndex();
2792cdf0e10cSrcweir 
2793cdf0e10cSrcweir     const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
2794cdf0e10cSrcweir     const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
2795cdf0e10cSrcweir 
2796cdf0e10cSrcweir     const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
2797cdf0e10cSrcweir     if( pStt == pEnd && pTNd )                  // no region ?
2798cdf0e10cSrcweir     {
2799cdf0e10cSrcweir         // do nothing
2800cdf0e10cSrcweir         return;
2801cdf0e10cSrcweir     }
2802cdf0e10cSrcweir 
2803cdf0e10cSrcweir     if( nSttNd != nEndNd )
2804cdf0e10cSrcweir     {
2805cdf0e10cSrcweir         SwNodeIndex aIdx( pStt->nNode );
2806cdf0e10cSrcweir         if( nSttCnt )
2807cdf0e10cSrcweir         {
2808cdf0e10cSrcweir             aIdx++;
2809cdf0e10cSrcweir             if( pTNd )
2810cdf0e10cSrcweir                 pTNd->CountWords( rStat, nSttCnt, pTNd->GetTxt().Len() );
2811cdf0e10cSrcweir         }
2812cdf0e10cSrcweir 
2813cdf0e10cSrcweir         for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
2814cdf0e10cSrcweir             if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
2815cdf0e10cSrcweir                 pTNd->CountWords( rStat, 0, pTNd->GetTxt().Len() );
2816cdf0e10cSrcweir 
2817cdf0e10cSrcweir         if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
2818cdf0e10cSrcweir             pTNd->CountWords( rStat, 0, nEndCnt );
2819cdf0e10cSrcweir     }
2820cdf0e10cSrcweir     else if( pTNd && nSttCnt < nEndCnt )
2821cdf0e10cSrcweir         pTNd->CountWords( rStat, nSttCnt, nEndCnt );
2822cdf0e10cSrcweir }
2823cdf0e10cSrcweir 
RemoveLeadingWhiteSpace(const SwPosition & rPos)2824cdf0e10cSrcweir void SwDoc::RemoveLeadingWhiteSpace(const SwPosition & rPos )
2825cdf0e10cSrcweir {
2826cdf0e10cSrcweir     const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
2827cdf0e10cSrcweir     if ( pTNd )
2828cdf0e10cSrcweir     {
2829cdf0e10cSrcweir         const String& rTxt = pTNd->GetTxt();
2830cdf0e10cSrcweir         xub_StrLen nIdx = 0;
2831cdf0e10cSrcweir         sal_Unicode cCh;
2832cdf0e10cSrcweir         while( nIdx < rTxt.Len() &&
2833cdf0e10cSrcweir                 ( '\t' == ( cCh = rTxt.GetChar( nIdx ) ) ||
2834cdf0e10cSrcweir                 (  ' ' == cCh ) ) )
2835cdf0e10cSrcweir             ++nIdx;
2836cdf0e10cSrcweir 
2837cdf0e10cSrcweir         if ( nIdx > 0 )
2838cdf0e10cSrcweir         {
2839cdf0e10cSrcweir             SwPaM aPam(rPos);
2840cdf0e10cSrcweir             aPam.GetPoint()->nContent = 0;
2841cdf0e10cSrcweir             aPam.SetMark();
2842cdf0e10cSrcweir             aPam.GetMark()->nContent = nIdx;
2843cdf0e10cSrcweir             DeleteRange( aPam );
2844cdf0e10cSrcweir         }
2845cdf0e10cSrcweir     }
2846cdf0e10cSrcweir }
2847