Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <doc.hxx>
21 : #include <node.hxx>
22 : #include <rootfrm.hxx>
23 : #include <editsh.hxx>
24 : #include <viscrs.hxx>
25 : #include <IMark.hxx>
26 : #include <bookmrk.hxx>
27 : #include <redline.hxx>
28 : #include <mvsave.hxx>
29 : #include <docary.hxx>
30 : #include <unocrsr.hxx>
31 : #include <swundo.hxx>
32 : #include <hints.hxx>
33 : #include <edimp.hxx>
34 :
35 : /*
36 : * Macros to iterate over all CrsrShells
37 : */
38 : #define PCURSH ((SwCrsrShell*)_pStartShell)
39 : #define FOREACHSHELL_START( pEShell ) \
40 : {\
41 : SwViewShell *_pStartShell = pEShell; \
42 : do { \
43 : if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
44 : {
45 :
46 : #define FOREACHSHELL_END( pEShell ) \
47 : } \
48 : } while((_pStartShell=(SwViewShell*)_pStartShell->GetNext())!= pEShell ); \
49 : }
50 :
51 : namespace
52 : {
53 : /// find the relevant section in which the SwUnoCrsr may wander.
54 : /// returns NULL if no restrictions apply
55 1291204 : static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode )
56 : {
57 1291204 : const SwStartNode* pStartNode = rNode.StartOfSectionNode();
58 6448004 : while( ( pStartNode != NULL ) &&
59 3871556 : ( pStartNode->StartOfSectionNode() != pStartNode ) &&
60 1293156 : ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
61 1287196 : pStartNode = pStartNode->StartOfSectionNode();
62 :
63 1291204 : return pStartNode;
64 : }
65 :
66 1303186 : static inline bool lcl_PosCorrAbs(SwPosition & rPos,
67 : const SwPosition& rStart,
68 : const SwPosition& rEnd,
69 : const SwPosition& rNewPos)
70 : {
71 1303186 : if ((rStart <= rPos) && (rPos <= rEnd))
72 : {
73 11656 : rPos = rNewPos;
74 11656 : return true;
75 : }
76 1291530 : return false;
77 : };
78 :
79 651593 : static inline bool lcl_PaMCorrAbs(SwPaM & rPam,
80 : const SwPosition& rStart,
81 : const SwPosition& rEnd,
82 : const SwPosition& rNewPos)
83 : {
84 651593 : bool bRet = false;
85 651593 : bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos);
86 651593 : bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
87 651593 : return bRet;
88 : };
89 :
90 9144 : static inline void lcl_PaMCorrRel1(SwPaM * pPam,
91 : SwNode const * const pOldNode,
92 : const SwPosition& rNewPos,
93 : const sal_Int32 nCntIdx)
94 : {
95 27432 : for(int nb = 0; nb < 2; ++nb)
96 18288 : if(&((pPam)->GetBound(sal_Bool(nb)).nNode.GetNode()) == pOldNode)
97 : {
98 3770 : (pPam)->GetBound(sal_Bool(nb)).nNode = rNewPos.nNode;
99 3770 : (pPam)->GetBound(sal_Bool(nb)).nContent.Assign(
100 3770 : const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()),
101 7540 : nCntIdx + (pPam)->GetBound(sal_Bool(nb)).nContent.GetIndex());
102 : }
103 9144 : }
104 : }
105 :
106 7409 : void PaMCorrAbs( const SwPaM& rRange,
107 : const SwPosition& rNewPos )
108 : {
109 7409 : SwPosition const aStart( *rRange.Start() );
110 14818 : SwPosition const aEnd( *rRange.End() );
111 14818 : SwPosition const aNewPos( rNewPos );
112 7409 : SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc();
113 7409 : SwCrsrShell *const pShell = pDoc->GetEditShell();
114 :
115 7409 : if( pShell )
116 : {
117 2420 : FOREACHSHELL_START( pShell )
118 1210 : SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
119 1210 : if( _pStkCrsr )
120 1 : do {
121 1 : lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos );
122 3 : } while ( (_pStkCrsr != 0 ) &&
123 2 : ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
124 :
125 2423 : FOREACHPAM_START( PCURSH->_GetCrsr() )
126 1213 : lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
127 1213 : FOREACHPAM_END()
128 :
129 1210 : if( PCURSH->IsTableMode() )
130 0 : lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos );
131 :
132 1210 : FOREACHSHELL_END( pShell )
133 : }
134 : {
135 7409 : SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl());
136 :
137 654660 : for( SwUnoCrsrTbl::iterator it = rTbl.begin(); it != rTbl.end(); ++it )
138 : {
139 647251 : SwUnoCrsr *const pUnoCursor = *it;
140 :
141 647251 : bool bChange = false; // has the UNO cursor been corrected?
142 :
143 : // determine whether the UNO cursor will leave it's designated
144 : // section
145 : bool const bLeaveSection =
146 1292853 : pUnoCursor->IsRemainInSection() &&
147 645602 : ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) !=
148 : lcl_FindUnoCrsrSection(
149 1292853 : pUnoCursor->GetPoint()->nNode.GetNode() ) );
150 :
151 1295470 : FOREACHPAM_START( pUnoCursor )
152 648219 : bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
153 648219 : FOREACHPAM_END()
154 :
155 : SwUnoTableCrsr *const pUnoTblCrsr =
156 647251 : dynamic_cast<SwUnoTableCrsr *>(*it);
157 647251 : if( pUnoTblCrsr )
158 : {
159 1283 : FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
160 : bChange |=
161 1216 : lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
162 1216 : FOREACHPAM_END()
163 : }
164 :
165 : // if a UNO cursor leaves its designated section, we must inform
166 : // (and invalidate) said cursor
167 647251 : if (bChange && bLeaveSection)
168 : {
169 : // the UNO cursor has left its section. We need to notify it!
170 419 : SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION );
171 419 : pUnoCursor->ModifyNotification( &aHint, NULL );
172 : }
173 : }
174 7409 : }
175 7409 : }
176 :
177 1409 : void SwDoc::CorrAbs(const SwNodeIndex& rOldNode,
178 : const SwPosition& rNewPos,
179 : const sal_Int32 nOffset,
180 : sal_Bool bMoveCrsr)
181 : {
182 1409 : SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() );
183 : SwPaM const aPam(rOldNode, 0,
184 1409 : rOldNode, (pCntntNode) ? pCntntNode->Len() : 0);
185 2818 : SwPosition aNewPos(rNewPos);
186 1409 : aNewPos.nContent += nOffset;
187 :
188 1409 : getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
189 : // fix redlines
190 : {
191 1409 : SwRedlineTbl& rTbl = *mpRedlineTbl;
192 3762 : for (sal_uInt16 n = 0; n < rTbl.size(); )
193 : {
194 : // is on position ??
195 944 : SwRangeRedline *const pRedline( rTbl[ n ] );
196 : bool const bChanged =
197 944 : lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos);
198 : // clean up empty redlines: docredln.cxx asserts these as invalid
199 944 : if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark())
200 944 : && (pRedline->GetContentIdx() == NULL))
201 : {
202 0 : rTbl.DeleteAndDestroy(n);
203 : }
204 : else
205 : {
206 944 : ++n;
207 : }
208 : }
209 :
210 : // To-Do - need to add here 'SwExtraRedlineTbl' also ?
211 : }
212 :
213 1409 : if(bMoveCrsr)
214 : {
215 1409 : ::PaMCorrAbs(aPam, aNewPos);
216 1409 : }
217 1409 : }
218 :
219 3 : void SwDoc::CorrAbs(
220 : const SwPaM& rRange,
221 : const SwPosition& rNewPos,
222 : sal_Bool bMoveCrsr )
223 : {
224 3 : SwPosition aStart(*rRange.Start());
225 6 : SwPosition aEnd(*rRange.End());
226 6 : SwPosition aNewPos(rNewPos);
227 :
228 3 : _DelBookmarks( aStart.nNode, aEnd.nNode, NULL, &aStart.nContent, &aEnd.nContent );
229 :
230 3 : if(bMoveCrsr)
231 6 : ::PaMCorrAbs(rRange, rNewPos);
232 3 : }
233 :
234 1999 : void SwDoc::CorrAbs(
235 : const SwNodeIndex& rStartNode,
236 : const SwNodeIndex& rEndNode,
237 : const SwPosition& rNewPos,
238 : sal_Bool bMoveCrsr )
239 : {
240 1999 : _DelBookmarks( rStartNode, rEndNode );
241 :
242 1999 : if(bMoveCrsr)
243 : {
244 1999 : SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
245 : SwPaM const aPam(rStartNode, 0,
246 1999 : rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
247 1999 : ::PaMCorrAbs(aPam, rNewPos);
248 : }
249 1999 : }
250 :
251 1694 : void PaMCorrRel( const SwNodeIndex &rOldNode,
252 : const SwPosition &rNewPos,
253 : const sal_Int32 nOffset )
254 : {
255 1694 : const SwNode* pOldNode = &rOldNode.GetNode();
256 1694 : SwPosition aNewPos( rNewPos );
257 1694 : const SwDoc* pDoc = pOldNode->GetDoc();
258 :
259 1694 : const sal_Int32 nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
260 :
261 1694 : SwCrsrShell* pShell = pDoc->GetEditShell();
262 1694 : if( pShell )
263 : {
264 42 : FOREACHSHELL_START( pShell )
265 21 : SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
266 21 : if( _pStkCrsr )
267 0 : do {
268 0 : lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx );
269 0 : } while ( (_pStkCrsr != 0 ) &&
270 0 : ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
271 :
272 42 : FOREACHPAM_START( PCURSH->_GetCrsr() )
273 21 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
274 21 : FOREACHPAM_END()
275 :
276 21 : if( PCURSH->IsTableMode() )
277 0 : lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
278 :
279 21 : FOREACHSHELL_END( pShell )
280 : }
281 : {
282 1694 : SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
283 9555 : for( SwUnoCrsrTbl::iterator it = rTbl.begin(); it != rTbl.end(); ++it )
284 : {
285 15722 : FOREACHPAM_START( *it )
286 7861 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
287 7861 : FOREACHPAM_END()
288 :
289 : SwUnoTableCrsr* pUnoTblCrsr =
290 7861 : dynamic_cast<SwUnoTableCrsr*>(*it);
291 7861 : if( pUnoTblCrsr )
292 : {
293 0 : FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
294 0 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
295 0 : FOREACHPAM_END()
296 : }
297 : }
298 1694 : }
299 1694 : }
300 :
301 1694 : void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
302 : const SwPosition& rNewPos,
303 : const sal_Int32 nOffset,
304 : sal_Bool bMoveCrsr)
305 : {
306 1694 : getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
307 :
308 : { // fix the Redlines
309 1694 : SwRedlineTbl& rTbl = *mpRedlineTbl;
310 1694 : SwPosition aNewPos(rNewPos);
311 2956 : for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
312 : {
313 : // lies on the position ??
314 1262 : lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
315 1694 : }
316 :
317 : // To-Do - need to add here 'SwExtraRedlineTbl' also ?
318 : }
319 :
320 1694 : if(bMoveCrsr)
321 1694 : ::PaMCorrRel(rOldNode, rNewPos, nOffset);
322 1694 : }
323 :
324 50336 : SwEditShell* SwDoc::GetEditShell( SwViewShell** ppSh ) const
325 : {
326 : // Layout and OLE shells should be available
327 50336 : if( mpCurrentView )
328 : {
329 13042 : SwViewShell *pSh = mpCurrentView, *pVSh = pSh;
330 13042 : if( ppSh )
331 5540 : *ppSh = pSh;
332 :
333 : // look for an EditShell (if it exists)
334 0 : do {
335 13042 : if( pSh->IsA( TYPE( SwEditShell ) ) )
336 13042 : return (SwEditShell*)pSh;
337 :
338 0 : } while( pVSh != ( pSh = (SwViewShell*)pSh->GetNext() ));
339 : }
340 37294 : else if( ppSh )
341 572 : *ppSh = 0;
342 :
343 37294 : return 0;
344 : }
345 :
346 1 : ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
347 : {
348 1 : return GetEditShell(0);
349 : }
350 :
351 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|