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 0 : static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode )
56 : {
57 0 : const SwStartNode* pStartNode = rNode.StartOfSectionNode();
58 0 : while( ( pStartNode != NULL ) &&
59 0 : ( pStartNode->StartOfSectionNode() != pStartNode ) &&
60 0 : ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
61 0 : pStartNode = pStartNode->StartOfSectionNode();
62 :
63 0 : return pStartNode;
64 : }
65 :
66 0 : static inline bool lcl_PosCorrAbs(SwPosition & rPos,
67 : const SwPosition& rStart,
68 : const SwPosition& rEnd,
69 : const SwPosition& rNewPos)
70 : {
71 0 : if ((rStart <= rPos) && (rPos <= rEnd))
72 : {
73 0 : rPos = rNewPos;
74 0 : return true;
75 : }
76 0 : return false;
77 : };
78 :
79 0 : static inline bool lcl_PaMCorrAbs(SwPaM & rPam,
80 : const SwPosition& rStart,
81 : const SwPosition& rEnd,
82 : const SwPosition& rNewPos)
83 : {
84 0 : bool bRet = false;
85 0 : bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos);
86 0 : bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
87 0 : return bRet;
88 : };
89 :
90 0 : static inline void lcl_PaMCorrRel1(SwPaM * pPam,
91 : SwNode const * const pOldNode,
92 : const SwPosition& rNewPos,
93 : const sal_Int32 nCntIdx)
94 : {
95 0 : for(int nb = 0; nb < 2; ++nb)
96 0 : if(&((pPam)->GetBound(sal_Bool(nb)).nNode.GetNode()) == pOldNode)
97 : {
98 0 : (pPam)->GetBound(sal_Bool(nb)).nNode = rNewPos.nNode;
99 0 : (pPam)->GetBound(sal_Bool(nb)).nContent.Assign(
100 0 : const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()),
101 0 : nCntIdx + (pPam)->GetBound(sal_Bool(nb)).nContent.GetIndex());
102 : }
103 0 : }
104 : }
105 :
106 0 : void PaMCorrAbs( const SwPaM& rRange,
107 : const SwPosition& rNewPos )
108 : {
109 0 : SwPosition const aStart( *rRange.Start() );
110 0 : SwPosition const aEnd( *rRange.End() );
111 0 : SwPosition const aNewPos( rNewPos );
112 0 : SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc();
113 0 : SwCrsrShell *const pShell = pDoc->GetEditShell();
114 :
115 0 : if( pShell )
116 : {
117 0 : FOREACHSHELL_START( pShell )
118 0 : SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
119 0 : if( _pStkCrsr )
120 0 : do {
121 0 : lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos );
122 0 : } while ( (_pStkCrsr != 0 ) &&
123 0 : ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
124 :
125 0 : FOREACHPAM_START( PCURSH->_GetCrsr() )
126 0 : lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
127 0 : FOREACHPAM_END()
128 :
129 0 : if( PCURSH->IsTableMode() )
130 0 : lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos );
131 :
132 0 : FOREACHSHELL_END( pShell )
133 : }
134 : {
135 0 : SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl());
136 :
137 0 : for( SwUnoCrsrTbl::iterator it = rTbl.begin(); it != rTbl.end(); ++it )
138 : {
139 0 : SwUnoCrsr *const pUnoCursor = *it;
140 :
141 0 : 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 0 : pUnoCursor->IsRemainInSection() &&
147 0 : ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) !=
148 : lcl_FindUnoCrsrSection(
149 0 : pUnoCursor->GetPoint()->nNode.GetNode() ) );
150 :
151 0 : FOREACHPAM_START( pUnoCursor )
152 0 : bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
153 0 : FOREACHPAM_END()
154 :
155 : SwUnoTableCrsr *const pUnoTblCrsr =
156 0 : dynamic_cast<SwUnoTableCrsr *>(*it);
157 0 : if( pUnoTblCrsr )
158 : {
159 0 : FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
160 : bChange |=
161 0 : lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
162 0 : FOREACHPAM_END()
163 : }
164 :
165 : // if a UNO cursor leaves its designated section, we must inform
166 : // (and invalidate) said cursor
167 0 : if (bChange && bLeaveSection)
168 : {
169 : // the UNO cursor has left its section. We need to notify it!
170 0 : SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION );
171 0 : pUnoCursor->ModifyNotification( &aHint, NULL );
172 : }
173 : }
174 0 : }
175 0 : }
176 :
177 0 : void SwDoc::CorrAbs(const SwNodeIndex& rOldNode,
178 : const SwPosition& rNewPos,
179 : const sal_Int32 nOffset,
180 : sal_Bool bMoveCrsr)
181 : {
182 0 : SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() );
183 : SwPaM const aPam(rOldNode, 0,
184 0 : rOldNode, (pCntntNode) ? pCntntNode->Len() : 0);
185 0 : SwPosition aNewPos(rNewPos);
186 0 : aNewPos.nContent += nOffset;
187 :
188 0 : getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
189 : // fix redlines
190 : {
191 0 : SwRedlineTbl& rTbl = *mpRedlineTbl;
192 0 : for (sal_uInt16 n = 0; n < rTbl.size(); )
193 : {
194 : // is on position ??
195 0 : SwRangeRedline *const pRedline( rTbl[ n ] );
196 : bool const bChanged =
197 0 : lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos);
198 : // clean up empty redlines: docredln.cxx asserts these as invalid
199 0 : if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark())
200 0 : && (pRedline->GetContentIdx() == NULL))
201 : {
202 0 : rTbl.DeleteAndDestroy(n);
203 : }
204 : else
205 : {
206 0 : ++n;
207 : }
208 : }
209 :
210 : // To-Do - need to add here 'SwExtraRedlineTbl' also ?
211 : }
212 :
213 0 : if(bMoveCrsr)
214 : {
215 0 : ::PaMCorrAbs(aPam, aNewPos);
216 0 : }
217 0 : }
218 :
219 0 : void SwDoc::CorrAbs(
220 : const SwPaM& rRange,
221 : const SwPosition& rNewPos,
222 : sal_Bool bMoveCrsr )
223 : {
224 0 : SwPosition aStart(*rRange.Start());
225 0 : SwPosition aEnd(*rRange.End());
226 0 : SwPosition aNewPos(rNewPos);
227 :
228 0 : _DelBookmarks( aStart.nNode, aEnd.nNode, NULL, &aStart.nContent, &aEnd.nContent );
229 :
230 0 : if(bMoveCrsr)
231 0 : ::PaMCorrAbs(rRange, rNewPos);
232 0 : }
233 :
234 0 : void SwDoc::CorrAbs(
235 : const SwNodeIndex& rStartNode,
236 : const SwNodeIndex& rEndNode,
237 : const SwPosition& rNewPos,
238 : sal_Bool bMoveCrsr )
239 : {
240 0 : _DelBookmarks( rStartNode, rEndNode );
241 :
242 0 : if(bMoveCrsr)
243 : {
244 0 : SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
245 : SwPaM const aPam(rStartNode, 0,
246 0 : rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
247 0 : ::PaMCorrAbs(aPam, rNewPos);
248 : }
249 0 : }
250 :
251 0 : void PaMCorrRel( const SwNodeIndex &rOldNode,
252 : const SwPosition &rNewPos,
253 : const sal_Int32 nOffset )
254 : {
255 0 : const SwNode* pOldNode = &rOldNode.GetNode();
256 0 : SwPosition aNewPos( rNewPos );
257 0 : const SwDoc* pDoc = pOldNode->GetDoc();
258 :
259 0 : const sal_Int32 nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
260 :
261 0 : SwCrsrShell* pShell = pDoc->GetEditShell();
262 0 : if( pShell )
263 : {
264 0 : FOREACHSHELL_START( pShell )
265 0 : SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
266 0 : 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 0 : FOREACHPAM_START( PCURSH->_GetCrsr() )
273 0 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
274 0 : FOREACHPAM_END()
275 :
276 0 : if( PCURSH->IsTableMode() )
277 0 : lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
278 :
279 0 : FOREACHSHELL_END( pShell )
280 : }
281 : {
282 0 : SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
283 0 : for( SwUnoCrsrTbl::iterator it = rTbl.begin(); it != rTbl.end(); ++it )
284 : {
285 0 : FOREACHPAM_START( *it )
286 0 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
287 0 : FOREACHPAM_END()
288 :
289 : SwUnoTableCrsr* pUnoTblCrsr =
290 0 : dynamic_cast<SwUnoTableCrsr*>(*it);
291 0 : if( pUnoTblCrsr )
292 : {
293 0 : FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
294 0 : lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
295 0 : FOREACHPAM_END()
296 : }
297 : }
298 0 : }
299 0 : }
300 :
301 0 : void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
302 : const SwPosition& rNewPos,
303 : const sal_Int32 nOffset,
304 : sal_Bool bMoveCrsr)
305 : {
306 0 : getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
307 :
308 : { // fix the Redlines
309 0 : SwRedlineTbl& rTbl = *mpRedlineTbl;
310 0 : SwPosition aNewPos(rNewPos);
311 0 : for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
312 : {
313 : // lies on the position ??
314 0 : lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
315 0 : }
316 :
317 : // To-Do - need to add here 'SwExtraRedlineTbl' also ?
318 : }
319 :
320 0 : if(bMoveCrsr)
321 0 : ::PaMCorrRel(rOldNode, rNewPos, nOffset);
322 0 : }
323 :
324 0 : SwEditShell* SwDoc::GetEditShell( SwViewShell** ppSh ) const
325 : {
326 : // Layout and OLE shells should be available
327 0 : if( mpCurrentView )
328 : {
329 0 : SwViewShell *pSh = mpCurrentView, *pVSh = pSh;
330 0 : if( ppSh )
331 0 : *ppSh = pSh;
332 :
333 : // look for an EditShell (if it exists)
334 0 : do {
335 0 : if( pSh->IsA( TYPE( SwEditShell ) ) )
336 0 : return (SwEditShell*)pSh;
337 :
338 0 : } while( pVSh != ( pSh = (SwViewShell*)pSh->GetNext() ));
339 : }
340 0 : else if( ppSh )
341 0 : *ppSh = 0;
342 :
343 0 : return 0;
344 : }
345 :
346 0 : ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
347 : {
348 0 : return GetEditShell(0);
349 : }
350 :
351 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|