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 <IDocumentLayoutAccess.hxx>
22 : #include <node.hxx>
23 : #include <rootfrm.hxx>
24 : #include <editsh.hxx>
25 : #include <viscrs.hxx>
26 : #include <IMark.hxx>
27 : #include <bookmrk.hxx>
28 : #include <redline.hxx>
29 : #include <mvsave.hxx>
30 : #include <docary.hxx>
31 : #include <unocrsr.hxx>
32 : #include <swundo.hxx>
33 : #include <hints.hxx>
34 : #include <edimp.hxx>
35 :
36 : /*
37 : * Macros to iterate over all CrsrShells
38 : */
39 : #define PCURSH ((SwCrsrShell*)_pStartShell)
40 : #define FOREACHSHELL_START( pEShell ) \
41 : {\
42 : SwViewShell const *_pStartShell = pEShell; \
43 : do { \
44 : if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
45 : {
46 :
47 : #define FOREACHSHELL_END( pEShell ) \
48 : } \
49 : } while((_pStartShell=(SwViewShell const*)_pStartShell->GetNext())!= pEShell ); \
50 : }
51 :
52 : namespace
53 : {
54 : /// find the relevant section in which the SwUnoCrsr may wander.
55 : /// returns NULL if no restrictions apply
56 2726608 : static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode )
57 : {
58 2726608 : const SwStartNode* pStartNode = rNode.StartOfSectionNode();
59 13602016 : while( ( pStartNode != NULL ) &&
60 8168404 : ( pStartNode->StartOfSectionNode() != pStartNode ) &&
61 2730700 : ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
62 2711096 : pStartNode = pStartNode->StartOfSectionNode();
63 :
64 2726608 : return pStartNode;
65 : }
66 :
67 2753900 : static inline bool lcl_PosCorrAbs(SwPosition & rPos,
68 : const SwPosition& rStart,
69 : const SwPosition& rEnd,
70 : const SwPosition& rNewPos)
71 : {
72 2753900 : if ((rStart <= rPos) && (rPos <= rEnd))
73 : {
74 34317 : rPos = rNewPos;
75 34317 : return true;
76 : }
77 2719583 : return false;
78 : };
79 :
80 1376950 : static inline bool lcl_PaMCorrAbs(SwPaM & rPam,
81 : const SwPosition& rStart,
82 : const SwPosition& rEnd,
83 : const SwPosition& rNewPos)
84 : {
85 1376950 : bool bRet = false;
86 1376950 : bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos);
87 1376950 : bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
88 1376950 : return bRet;
89 : };
90 :
91 21760 : static inline void lcl_PaMCorrRel1(SwPaM * pPam,
92 : SwNode const * const pOldNode,
93 : const SwPosition& rNewPos,
94 : const sal_Int32 nCntIdx)
95 : {
96 65280 : for(int nb = 0; nb < 2; ++nb)
97 43520 : if(&((pPam)->GetBound(bool(nb)).nNode.GetNode()) == pOldNode)
98 : {
99 8995 : (pPam)->GetBound(bool(nb)).nNode = rNewPos.nNode;
100 8995 : (pPam)->GetBound(bool(nb)).nContent.Assign(
101 8995 : const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()),
102 17990 : nCntIdx + (pPam)->GetBound(bool(nb)).nContent.GetIndex());
103 : }
104 21760 : }
105 : }
106 :
107 23346 : void PaMCorrAbs( const SwPaM& rRange,
108 : const SwPosition& rNewPos )
109 : {
110 23346 : SwPosition const aStart( *rRange.Start() );
111 46692 : SwPosition const aEnd( *rRange.End() );
112 46692 : SwPosition const aNewPos( rNewPos );
113 23346 : SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc();
114 23346 : SwCrsrShell *const pShell = pDoc->GetEditShell();
115 :
116 23346 : if( pShell )
117 : {
118 5432 : FOREACHSHELL_START( pShell )
119 2716 : SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
120 2716 : if( _pStkCrsr )
121 6 : do {
122 6 : lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos );
123 18 : } while ( (_pStkCrsr != 0 ) &&
124 12 : ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
125 :
126 5442 : FOREACHPAM_START( PCURSH->_GetCrsr() )
127 2726 : lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
128 2726 : FOREACHPAM_END()
129 :
130 2716 : if( PCURSH->IsTableMode() )
131 0 : lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos );
132 :
133 2716 : FOREACHSHELL_END( pShell )
134 : }
135 : {
136 23346 : SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl());
137 :
138 1391416 : for( SwUnoCrsrTbl::iterator it = rTbl.begin(); it != rTbl.end(); ++it )
139 : {
140 1368070 : SwUnoCrsr *const pUnoCursor = *it;
141 :
142 1368070 : bool bChange = false; // has the UNO cursor been corrected?
143 :
144 : // determine whether the UNO cursor will leave it's designated
145 : // section
146 : bool const bLeaveSection =
147 2731374 : pUnoCursor->IsRemainInSection() &&
148 1363304 : ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) !=
149 : lcl_FindUnoCrsrSection(
150 2731374 : pUnoCursor->GetPoint()->nNode.GetNode() ) );
151 :
152 2738076 : FOREACHPAM_START( pUnoCursor )
153 1370006 : bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
154 1370006 : FOREACHPAM_END()
155 :
156 : SwUnoTableCrsr *const pUnoTblCrsr =
157 1368070 : dynamic_cast<SwUnoTableCrsr *>(*it);
158 1368070 : if( pUnoTblCrsr )
159 : {
160 2566 : FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
161 : bChange |=
162 2432 : lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
163 2432 : FOREACHPAM_END()
164 : }
165 :
166 : // if a UNO cursor leaves its designated section, we must inform
167 : // (and invalidate) said cursor
168 1368070 : if (bChange && bLeaveSection)
169 : {
170 : // the UNO cursor has left its section. We need to notify it!
171 2048 : SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION );
172 2048 : pUnoCursor->ModifyNotification( &aHint, NULL );
173 : }
174 : }
175 23346 : }
176 23346 : }
177 :
178 4626 : void SwDoc::CorrAbs(const SwNodeIndex& rOldNode,
179 : const SwPosition& rNewPos,
180 : const sal_Int32 nOffset,
181 : bool bMoveCrsr)
182 : {
183 4626 : SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() );
184 : SwPaM const aPam(rOldNode, 0,
185 4626 : rOldNode, (pCntntNode) ? pCntntNode->Len() : 0);
186 9252 : SwPosition aNewPos(rNewPos);
187 4626 : aNewPos.nContent += nOffset;
188 :
189 4626 : getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
190 : // fix redlines
191 : {
192 4626 : SwRedlineTbl& rTbl = getIDocumentRedlineAccess().GetRedlineTbl();
193 11032 : for (sal_uInt16 n = 0; n < rTbl.size(); )
194 : {
195 : // is on position ??
196 1780 : SwRangeRedline *const pRedline( rTbl[ n ] );
197 : bool const bChanged =
198 1780 : lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos);
199 : // clean up empty redlines: docredln.cxx asserts these as invalid
200 1780 : if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark())
201 1780 : && (pRedline->GetContentIdx() == NULL))
202 : {
203 0 : rTbl.DeleteAndDestroy(n);
204 : }
205 : else
206 : {
207 1780 : ++n;
208 : }
209 : }
210 :
211 : // To-Do - need to add here 'SwExtraRedlineTbl' also ?
212 : }
213 :
214 4626 : if(bMoveCrsr)
215 : {
216 4626 : ::PaMCorrAbs(aPam, aNewPos);
217 4626 : }
218 4626 : }
219 :
220 6 : void SwDoc::CorrAbs(
221 : const SwPaM& rRange,
222 : const SwPosition& rNewPos,
223 : bool bMoveCrsr )
224 : {
225 6 : SwPosition aStart(*rRange.Start());
226 12 : SwPosition aEnd(*rRange.End());
227 12 : SwPosition aNewPos(rNewPos);
228 :
229 6 : _DelBookmarks( aStart.nNode, aEnd.nNode, NULL, &aStart.nContent, &aEnd.nContent );
230 :
231 6 : if(bMoveCrsr)
232 12 : ::PaMCorrAbs(rRange, rNewPos);
233 6 : }
234 :
235 7066 : void SwDoc::CorrAbs(
236 : const SwNodeIndex& rStartNode,
237 : const SwNodeIndex& rEndNode,
238 : const SwPosition& rNewPos,
239 : bool bMoveCrsr )
240 : {
241 7066 : _DelBookmarks( rStartNode, rEndNode );
242 :
243 7066 : if(bMoveCrsr)
244 : {
245 7066 : SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
246 : SwPaM const aPam(rStartNode, 0,
247 7066 : rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
248 7066 : ::PaMCorrAbs(aPam, rNewPos);
249 : }
250 7066 : }
251 :
252 5018 : void PaMCorrRel( const SwNodeIndex &rOldNode,
253 : const SwPosition &rNewPos,
254 : const sal_Int32 nOffset )
255 : {
256 5018 : const SwNode* pOldNode = &rOldNode.GetNode();
257 5018 : SwPosition aNewPos( rNewPos );
258 5018 : const SwDoc* pDoc = pOldNode->GetDoc();
259 :
260 5018 : const sal_Int32 nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
261 :
262 5018 : SwCrsrShell const* pShell = pDoc->GetEditShell();
263 5018 : if( pShell )
264 : {
265 88 : FOREACHSHELL_START( pShell )
266 44 : SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
267 44 : if( _pStkCrsr )
268 0 : do {
269 0 : lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx );
270 0 : } while ( (_pStkCrsr != 0 ) &&
271 0 : ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
272 :
273 88 : FOREACHPAM_START( PCURSH->_GetCrsr() )
274 44 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
275 44 : FOREACHPAM_END()
276 :
277 44 : if( PCURSH->IsTableMode() )
278 0 : lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
279 :
280 44 : FOREACHSHELL_END( pShell )
281 : }
282 : {
283 5018 : SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
284 24418 : for( SwUnoCrsrTbl::iterator it = rTbl.begin(); it != rTbl.end(); ++it )
285 : {
286 38800 : FOREACHPAM_START( *it )
287 19400 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
288 19400 : FOREACHPAM_END()
289 :
290 : SwUnoTableCrsr* pUnoTblCrsr =
291 19400 : dynamic_cast<SwUnoTableCrsr*>(*it);
292 19400 : if( pUnoTblCrsr )
293 : {
294 0 : FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
295 0 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
296 0 : FOREACHPAM_END()
297 : }
298 : }
299 5018 : }
300 5018 : }
301 :
302 5018 : void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
303 : const SwPosition& rNewPos,
304 : const sal_Int32 nOffset,
305 : bool bMoveCrsr)
306 : {
307 5018 : getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
308 :
309 : { // fix the Redlines
310 5018 : SwRedlineTbl& rTbl = getIDocumentRedlineAccess().GetRedlineTbl();
311 5018 : SwPosition aNewPos(rNewPos);
312 7334 : for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
313 : {
314 : // lies on the position ??
315 2316 : lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
316 5018 : }
317 :
318 : // To-Do - need to add here 'SwExtraRedlineTbl' also ?
319 : }
320 :
321 5018 : if(bMoveCrsr)
322 5018 : ::PaMCorrRel(rOldNode, rNewPos, nOffset);
323 5018 : }
324 :
325 133583 : SwEditShell const * SwDoc::GetEditShell() const
326 : {
327 133583 : SwViewShell const *pCurrentView = getIDocumentLayoutAccess().GetCurrentViewShell();
328 : // Layout and OLE shells should be available
329 133583 : if( pCurrentView )
330 : {
331 16672 : SwViewShell const *pFirstVSh = pCurrentView;
332 16672 : SwViewShell const *pCurrentVSh = pFirstVSh;
333 : // look for an EditShell (if it exists)
334 0 : do {
335 16672 : if( pCurrentVSh->IsA( TYPE( SwEditShell ) ) )
336 : {
337 16672 : return (SwEditShell*)pCurrentVSh;
338 : }
339 0 : } while( pFirstVSh != ( pCurrentVSh = (SwViewShell*)pCurrentVSh->GetNext() ));
340 : }
341 116911 : return 0;
342 : }
343 :
344 128565 : SwEditShell* SwDoc::GetEditShell()
345 : {
346 128565 : return const_cast<SwEditShell*>( const_cast<SwDoc const *>( this )->GetEditShell() );
347 : }
348 :
349 2 : ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
350 : {
351 2 : return GetEditShell();
352 270 : }
353 :
354 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|