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