xref: /AOO41X/main/sw/source/core/doc/doccorr.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <doc.hxx>
33 #include <node.hxx>
34 #include <rootfrm.hxx>
35 #include <editsh.hxx>
36 #include <viscrs.hxx>
37 #include <IMark.hxx>
38 #include <bookmrk.hxx>
39 #include <redline.hxx>
40 #include <mvsave.hxx>
41 #include <docary.hxx>
42 #include <unocrsr.hxx>
43 #include <swundo.hxx>
44 #include <hints.hxx>
45 
46 /*
47  * MACROS um ueber alle CrsrShells zu iterieren
48  */
49 #define PCURSH ((SwCrsrShell*)_pStartShell)
50 #define FOREACHSHELL_START( pEShell ) \
51     {\
52 		ViewShell *_pStartShell = pEShell; \
53 		do { \
54 			if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
55 			{
56 
57 #define FOREACHSHELL_END( pEShell ) \
58 			} \
59         } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
60 	}
61 
62 #define PCURCRSR (_pCurrCrsr)
63 #define FOREACHPAM_START(pSttCrsr) \
64 	{\
65 		SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
66 		do {
67 
68 #define FOREACHPAM_END() \
69 		} while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
70 	}
71 
72 namespace
73 {
74     // find the relevant section in which the SwUnoCrsr may wander.
75     // returns NULL if no restrictions apply
76     static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode )
77     {
78         const SwStartNode* pStartNode = rNode.StartOfSectionNode();
79         while( ( pStartNode != NULL ) &&
80                ( pStartNode->StartOfSectionNode() != pStartNode ) &&
81                ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
82             pStartNode = pStartNode->StartOfSectionNode();
83 
84         return pStartNode;
85     }
86 
87     static inline bool lcl_PosCorrAbs(SwPosition & rPos,
88         const SwPosition& rStart,
89         const SwPosition& rEnd,
90         const SwPosition& rNewPos)
91     {
92         if ((rStart <= rPos) && (rPos <= rEnd))
93         {
94             rPos = rNewPos;
95             return true;
96         }
97         return false;
98     };
99 
100     static inline bool lcl_PaMCorrAbs(SwPaM & rPam,
101         const SwPosition& rStart,
102         const SwPosition& rEnd,
103         const SwPosition& rNewPos)
104     {
105         bool bRet = false;
106         bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos);
107         bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
108         return bRet;
109     };
110 
111     static inline void lcl_PaMCorrRel1(SwPaM * pPam,
112         SwNode const * const pOldNode,
113         const SwPosition& rNewPos,
114         const xub_StrLen nCntIdx)
115     {
116         for(int nb = 0; nb < 2; ++nb)
117             if(&((pPam)->GetBound(sal_Bool(nb)).nNode.GetNode()) == pOldNode)
118             {
119                 (pPam)->GetBound(sal_Bool(nb)).nNode = rNewPos.nNode;
120                 (pPam)->GetBound(sal_Bool(nb)).nContent.Assign(
121                     const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()),
122                     nCntIdx + (pPam)->GetBound(sal_Bool(nb)).nContent.GetIndex());
123             }
124     }
125 }
126 
127 
128 void PaMCorrAbs( const SwPaM& rRange,
129 				const SwPosition& rNewPos )
130 {
131     SwPosition const aStart( *rRange.Start() );
132     SwPosition const aEnd( *rRange.End() );
133     SwPosition const aNewPos( rNewPos );
134     SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc();
135     SwCrsrShell *const pShell = pDoc->GetEditShell();
136 
137 	if( pShell )
138 	{
139 		FOREACHSHELL_START( pShell )
140 			SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
141 			if( _pStkCrsr )
142 			do {
143                 lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos );
144 			} while ( (_pStkCrsr != 0 ) &&
145 				((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
146 
147 			FOREACHPAM_START( PCURSH->_GetCrsr() )
148                 lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
149 			FOREACHPAM_END()
150 
151 			if( PCURSH->IsTableMode() )
152                 lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos );
153 
154 		FOREACHSHELL_END( pShell )
155 	}
156 	{
157         SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl());
158 
159 		for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
160 		{
161             SwUnoCrsr *const pUnoCursor = rTbl[ n ];
162 
163             bool bChange = false; // has the UNO cursor been corrected?
164 
165             // determine whether the UNO cursor will leave it's designated
166             // section
167             bool const bLeaveSection =
168                 pUnoCursor->IsRemainInSection() &&
169                 ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) !=
170                   lcl_FindUnoCrsrSection(
171                       pUnoCursor->GetPoint()->nNode.GetNode() ) );
172 
173 			FOREACHPAM_START( pUnoCursor )
174                 bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
175 			FOREACHPAM_END()
176 
177             SwUnoTableCrsr *const pUnoTblCrsr =
178                 dynamic_cast<SwUnoTableCrsr *>(rTbl[ n ]);
179 			if( pUnoTblCrsr )
180 			{
181 				FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
182                     bChange |=
183                         lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
184 				FOREACHPAM_END()
185 			}
186 
187             // if a UNO cursor leaves its designated section, we must inform
188             // (and invalidate) said cursor
189             if (bChange && bLeaveSection)
190             {
191                 // the UNO cursor has left its section. We need to notify it!
192                 SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION );
193                 pUnoCursor->ModifyNotification( &aHint, NULL );
194             }
195 		}
196 	}
197 }
198 
199 void SwDoc::CorrAbs(const SwNodeIndex& rOldNode,
200     const SwPosition& rNewPos,
201     const xub_StrLen nOffset,
202     sal_Bool bMoveCrsr)
203 {
204     SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() );
205     SwPaM const aPam(rOldNode, 0,
206                      rOldNode, (pCntntNode) ? pCntntNode->Len() : 0);
207     SwPosition aNewPos(rNewPos);
208     aNewPos.nContent += nOffset;
209 
210     getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
211     {   // fix redlines
212         SwRedlineTbl& rTbl = *pRedlineTbl;
213         for (sal_uInt16 n = 0; n < rTbl.Count(); )
214         {
215             // is on position ??
216             SwRedline *const pRedline( rTbl[ n ] );
217             bool const bChanged =
218                 lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos);
219             // clean up empty redlines: docredln.cxx asserts these as invalid
220             if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark())
221                          && (pRedline->GetContentIdx() == NULL))
222             {
223                 rTbl.DeleteAndDestroy(n);
224             }
225             else
226             {
227                 ++n;
228             }
229         }
230     }
231 
232     if(bMoveCrsr)
233     {
234         ::PaMCorrAbs(aPam, aNewPos);
235     }
236 }
237 
238 void SwDoc::CorrAbs(const SwPaM& rRange,
239     const SwPosition& rNewPos,
240     sal_Bool bMoveCrsr)
241 {
242     SwPosition aStart(*rRange.Start());
243     SwPosition aEnd(*rRange.End());
244     SwPosition aNewPos(rNewPos);
245 
246     _DelBookmarks(aStart.nNode, aEnd.nNode, NULL,
247         &aStart.nContent, &aEnd.nContent);
248     if(bMoveCrsr)
249         ::PaMCorrAbs(rRange, rNewPos);
250 }
251 
252 void SwDoc::CorrAbs(const SwNodeIndex& rStartNode,
253      const SwNodeIndex& rEndNode,
254      const SwPosition& rNewPos,
255      sal_Bool bMoveCrsr)
256 {
257     _DelBookmarks(rStartNode, rEndNode);
258 
259     if(bMoveCrsr)
260     {
261         SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
262         SwPaM const aPam(rStartNode, 0,
263                          rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
264         ::PaMCorrAbs(aPam, rNewPos);
265     }
266 }
267 
268 
269 
270 
271 
272 void PaMCorrRel( const SwNodeIndex &rOldNode,
273 				 const SwPosition &rNewPos,
274 				 const xub_StrLen nOffset )
275 {
276 	const SwNode* pOldNode = &rOldNode.GetNode();
277 	SwPosition aNewPos( rNewPos );
278 	const SwDoc* pDoc = pOldNode->GetDoc();
279 
280 	xub_StrLen nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
281 
282 	SwCrsrShell* pShell = pDoc->GetEditShell();
283 	if( pShell )
284 	{
285 		FOREACHSHELL_START( pShell )
286 			SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
287 			if( _pStkCrsr )
288 			do {
289 				lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx );
290 			} while ( (_pStkCrsr != 0 ) &&
291 				((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
292 
293 			FOREACHPAM_START( PCURSH->_GetCrsr() )
294 				lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
295 			FOREACHPAM_END()
296 
297 			if( PCURSH->IsTableMode() )
298 				lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
299 
300 		FOREACHSHELL_END( pShell )
301 	}
302 	{
303 		SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
304 		for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
305 		{
306 			FOREACHPAM_START( rTbl[ n ] )
307 				lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
308 			FOREACHPAM_END()
309 
310             SwUnoTableCrsr* pUnoTblCrsr =
311                 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
312 			if( pUnoTblCrsr )
313 			{
314 				FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
315 					lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
316 				FOREACHPAM_END()
317 			}
318 		}
319 	}
320 }
321 
322 void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
323     const SwPosition& rNewPos,
324     const xub_StrLen nOffset,
325     sal_Bool bMoveCrsr)
326 {
327     getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
328 
329     { // dann die Redlines korrigieren
330         SwRedlineTbl& rTbl = *pRedlineTbl;
331         SwPosition aNewPos(rNewPos);
332         for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
333         {
334             // liegt auf der Position ??
335             lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
336         }
337     }
338 
339     if(bMoveCrsr)
340         ::PaMCorrRel(rOldNode, rNewPos, nOffset);
341 }
342 
343 
344 SwEditShell* SwDoc::GetEditShell( ViewShell** ppSh ) const
345 {
346 	// Layout und OLE-Shells sollten vorhanden sein!
347 	if( pCurrentView )
348 	{
349 		ViewShell *pSh = pCurrentView, *pVSh = pSh;
350 		if( ppSh )
351 			*ppSh = pSh;
352 
353 		// wir suchen uns eine EditShell, falls diese existiert
354 		do {
355 			if( pSh->IsA( TYPE( SwEditShell ) ) )
356 				return (SwEditShell*)pSh;
357 
358 		} while( pVSh != ( pSh = (ViewShell*)pSh->GetNext() ));
359 	}
360 	else if( ppSh )
361 		*ppSh = 0;	//swmod 071029//swmod 071225
362 
363 	return 0;
364 }
365 
366 ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
367 {
368     return GetEditShell(0);
369 }
370 
371