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