xref: /aoo42x/main/sw/source/core/doc/doccorr.cxx (revision 332f371a)
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
lcl_FindUnoCrsrSection(const SwNode & rNode)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 
lcl_PosCorrAbs(SwPosition & rPos,const SwPosition & rStart,const SwPosition & rEnd,const SwPosition & rNewPos)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 
lcl_PaMCorrAbs(SwPaM & rPam,const SwPosition & rStart,const SwPosition & rEnd,const SwPosition & rNewPos)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 
lcl_PaMCorrRel1(SwPaM * pPam,SwNode const * const pOldNode,const SwPosition & rNewPos,const xub_StrLen nCntIdx)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 
PaMCorrAbs(const SwPaM & rRange,const SwPosition & rNewPos)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 
CorrAbs(const SwNodeIndex & rOldNode,const SwPosition & rNewPos,const xub_StrLen nOffset,sal_Bool bMoveCrsr)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 
CorrAbs(const SwPaM & rRange,const SwPosition & rNewPos,sal_Bool bMoveCrsr)236 void SwDoc::CorrAbs(
237     const SwPaM& rRange,
238     const SwPosition& rNewPos,
239     sal_Bool bMoveCrsr )
240 {
241     SwPosition aStart(*rRange.Start());
242     SwPosition aEnd(*rRange.End());
243     SwPosition aNewPos(rNewPos);
244 
245     _DelBookmarks( aStart.nNode, aEnd.nNode, NULL, &aStart.nContent, &aEnd.nContent );
246 
247     if(bMoveCrsr)
248         ::PaMCorrAbs(rRange, rNewPos);
249 }
250 
CorrAbs(const SwNodeIndex & rStartNode,const SwNodeIndex & rEndNode,const SwPosition & rNewPos,sal_Bool bMoveCrsr)251 void SwDoc::CorrAbs(
252     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 
PaMCorrRel(const SwNodeIndex & rOldNode,const SwPosition & rNewPos,const xub_StrLen nOffset)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 
CorrRel(const SwNodeIndex & rOldNode,const SwPosition & rNewPos,const xub_StrLen nOffset,sal_Bool bMoveCrsr)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 
GetEditShell(ViewShell ** ppSh) const344 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 
GetIShellCursorSupplier()366 ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
367 {
368     return GetEditShell(0);
369 }
370 
371