xref: /AOO41X/main/sw/source/core/doc/doccorr.cxx (revision badb2b8d8694a3bcf4c6ea686d316f111abf7014)
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 
208     // fix redlines
209     {
210         SwRedlineTbl& rTbl = *pRedlineTbl;
211         for (sal_uInt16 n = 0; n < rTbl.Count(); )
212         {
213             // is on position ??
214             SwRedline *const pRedline( rTbl[ n ] );
215             bool const bChanged =
216                 lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos);
217             // clean up empty redlines: docredln.cxx asserts these as invalid
218             if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark())
219                          && (pRedline->GetContentIdx() == NULL))
220             {
221                 rTbl.DeleteAndDestroy(n);
222             }
223             else
224             {
225                 ++n;
226             }
227         }
228     }
229 
230     if(bMoveCrsr)
231     {
232         ::PaMCorrAbs(aPam, aNewPos);
233     }
234 }
235 
236 void SwDoc::CorrAbs(const SwPaM& rRange,
237     const SwPosition& rNewPos,
238     sal_Bool bMoveCrsr)
239 {
240     SwPosition aStart(*rRange.Start());
241     SwPosition aEnd(*rRange.End());
242     SwPosition aNewPos(rNewPos);
243 
244     _DelBookmarks(aStart.nNode, aEnd.nNode, NULL,
245         &aStart.nContent, &aEnd.nContent);
246     if(bMoveCrsr)
247         ::PaMCorrAbs(rRange, rNewPos);
248 }
249 
250 void SwDoc::CorrAbs(const SwNodeIndex& rStartNode,
251      const SwNodeIndex& rEndNode,
252      const SwPosition& rNewPos,
253      sal_Bool bMoveCrsr)
254 {
255     _DelBookmarks(rStartNode, rEndNode);
256 
257     if(bMoveCrsr)
258     {
259         SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
260         SwPaM const aPam(rStartNode, 0,
261                          rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
262         ::PaMCorrAbs(aPam, rNewPos);
263     }
264 }
265 
266 
267 
268 
269 
270 void PaMCorrRel( const SwNodeIndex &rOldNode,
271 				 const SwPosition &rNewPos,
272 				 const xub_StrLen nOffset )
273 {
274 	const SwNode* pOldNode = &rOldNode.GetNode();
275 	SwPosition aNewPos( rNewPos );
276 	const SwDoc* pDoc = pOldNode->GetDoc();
277 
278 	xub_StrLen nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
279 
280 	SwCrsrShell* pShell = pDoc->GetEditShell();
281 	if( pShell )
282 	{
283 		FOREACHSHELL_START( pShell )
284 			SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
285 			if( _pStkCrsr )
286 			do {
287 				lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx );
288 			} while ( (_pStkCrsr != 0 ) &&
289 				((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
290 
291 			FOREACHPAM_START( PCURSH->_GetCrsr() )
292 				lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
293 			FOREACHPAM_END()
294 
295 			if( PCURSH->IsTableMode() )
296 				lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
297 
298 		FOREACHSHELL_END( pShell )
299 	}
300 	{
301 		SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
302 		for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
303 		{
304 			FOREACHPAM_START( rTbl[ n ] )
305 				lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
306 			FOREACHPAM_END()
307 
308             SwUnoTableCrsr* pUnoTblCrsr =
309                 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
310 			if( pUnoTblCrsr )
311 			{
312 				FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
313 					lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
314 				FOREACHPAM_END()
315 			}
316 		}
317 	}
318 }
319 
320 void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
321     const SwPosition& rNewPos,
322     const xub_StrLen nOffset,
323     sal_Bool bMoveCrsr)
324 {
325     getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
326 
327     { // dann die Redlines korrigieren
328         SwRedlineTbl& rTbl = *pRedlineTbl;
329         SwPosition aNewPos(rNewPos);
330         for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
331         {
332             // liegt auf der Position ??
333             lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
334         }
335     }
336 
337     if(bMoveCrsr)
338         ::PaMCorrRel(rOldNode, rNewPos, nOffset);
339 }
340 
341 
342 SwEditShell* SwDoc::GetEditShell( ViewShell** ppSh ) const
343 {
344 	// Layout und OLE-Shells sollten vorhanden sein!
345 	if( pCurrentView )
346 	{
347 		ViewShell *pSh = pCurrentView, *pVSh = pSh;
348 		if( ppSh )
349 			*ppSh = pSh;
350 
351 		// wir suchen uns eine EditShell, falls diese existiert
352 		do {
353 			if( pSh->IsA( TYPE( SwEditShell ) ) )
354 				return (SwEditShell*)pSh;
355 
356 		} while( pVSh != ( pSh = (ViewShell*)pSh->GetNext() ));
357 	}
358 	else if( ppSh )
359 		*ppSh = 0;	//swmod 071029//swmod 071225
360 
361 	return 0;
362 }
363 
364 ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
365 {
366     return GetEditShell(0);
367 }
368 
369