1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 32 #include <doc.hxx> 33 #include <node.hxx> 34 #include <rootfrm.hxx> 35 #include <editsh.hxx> 36 #include <viscrs.hxx> 37 #include <IMark.hxx> 38 #include <bookmrk.hxx> 39 #include <redline.hxx> 40 #include <mvsave.hxx> 41 #include <docary.hxx> 42 #include <unocrsr.hxx> 43 #include <swundo.hxx> 44 #include <hints.hxx> 45 46 /* 47 * MACROS um ueber alle CrsrShells zu iterieren 48 */ 49 #define PCURSH ((SwCrsrShell*)_pStartShell) 50 #define FOREACHSHELL_START( pEShell ) \ 51 {\ 52 ViewShell *_pStartShell = pEShell; \ 53 do { \ 54 if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \ 55 { 56 57 #define FOREACHSHELL_END( pEShell ) \ 58 } \ 59 } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \ 60 } 61 62 #define PCURCRSR (_pCurrCrsr) 63 #define FOREACHPAM_START(pSttCrsr) \ 64 {\ 65 SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \ 66 do { 67 68 #define FOREACHPAM_END() \ 69 } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \ 70 } 71 72 namespace 73 { 74 // find the relevant section in which the SwUnoCrsr may wander. 75 // returns NULL if no restrictions apply 76 static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode ) 77 { 78 const SwStartNode* pStartNode = rNode.StartOfSectionNode(); 79 while( ( pStartNode != NULL ) && 80 ( pStartNode->StartOfSectionNode() != pStartNode ) && 81 ( pStartNode->GetStartNodeType() == SwNormalStartNode ) ) 82 pStartNode = pStartNode->StartOfSectionNode(); 83 84 return pStartNode; 85 } 86 87 static inline bool lcl_PosCorrAbs(SwPosition & rPos, 88 const SwPosition& rStart, 89 const SwPosition& rEnd, 90 const SwPosition& rNewPos) 91 { 92 if ((rStart <= rPos) && (rPos <= rEnd)) 93 { 94 rPos = rNewPos; 95 return true; 96 } 97 return false; 98 }; 99 100 static inline bool lcl_PaMCorrAbs(SwPaM & rPam, 101 const SwPosition& rStart, 102 const SwPosition& rEnd, 103 const SwPosition& rNewPos) 104 { 105 bool bRet = false; 106 bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos); 107 bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos); 108 return bRet; 109 }; 110 111 static inline void lcl_PaMCorrRel1(SwPaM * pPam, 112 SwNode const * const pOldNode, 113 const SwPosition& rNewPos, 114 const xub_StrLen nCntIdx) 115 { 116 for(int nb = 0; nb < 2; ++nb) 117 if(&((pPam)->GetBound(sal_Bool(nb)).nNode.GetNode()) == pOldNode) 118 { 119 (pPam)->GetBound(sal_Bool(nb)).nNode = rNewPos.nNode; 120 (pPam)->GetBound(sal_Bool(nb)).nContent.Assign( 121 const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()), 122 nCntIdx + (pPam)->GetBound(sal_Bool(nb)).nContent.GetIndex()); 123 } 124 } 125 } 126 127 128 void PaMCorrAbs( const SwPaM& rRange, 129 const SwPosition& rNewPos ) 130 { 131 SwPosition const aStart( *rRange.Start() ); 132 SwPosition const aEnd( *rRange.End() ); 133 SwPosition const aNewPos( rNewPos ); 134 SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc(); 135 SwCrsrShell *const pShell = pDoc->GetEditShell(); 136 137 if( pShell ) 138 { 139 FOREACHSHELL_START( pShell ) 140 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr(); 141 if( _pStkCrsr ) 142 do { 143 lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos ); 144 } while ( (_pStkCrsr != 0 ) && 145 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) ); 146 147 FOREACHPAM_START( PCURSH->_GetCrsr() ) 148 lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos ); 149 FOREACHPAM_END() 150 151 if( PCURSH->IsTableMode() ) 152 lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos ); 153 154 FOREACHSHELL_END( pShell ) 155 } 156 { 157 SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl()); 158 159 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 160 { 161 SwUnoCrsr *const pUnoCursor = rTbl[ n ]; 162 163 bool bChange = false; // has the UNO cursor been corrected? 164 165 // determine whether the UNO cursor will leave it's designated 166 // section 167 bool const bLeaveSection = 168 pUnoCursor->IsRemainInSection() && 169 ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) != 170 lcl_FindUnoCrsrSection( 171 pUnoCursor->GetPoint()->nNode.GetNode() ) ); 172 173 FOREACHPAM_START( pUnoCursor ) 174 bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos ); 175 FOREACHPAM_END() 176 177 SwUnoTableCrsr *const pUnoTblCrsr = 178 dynamic_cast<SwUnoTableCrsr *>(rTbl[ n ]); 179 if( pUnoTblCrsr ) 180 { 181 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() ) 182 bChange |= 183 lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos ); 184 FOREACHPAM_END() 185 } 186 187 // if a UNO cursor leaves its designated section, we must inform 188 // (and invalidate) said cursor 189 if (bChange && bLeaveSection) 190 { 191 // the UNO cursor has left its section. We need to notify it! 192 SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION ); 193 pUnoCursor->ModifyNotification( &aHint, NULL ); 194 } 195 } 196 } 197 } 198 199 void SwDoc::CorrAbs(const SwNodeIndex& rOldNode, 200 const SwPosition& rNewPos, 201 const xub_StrLen nOffset, 202 sal_Bool bMoveCrsr) 203 { 204 SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() ); 205 SwPaM const aPam(rOldNode, 0, 206 rOldNode, (pCntntNode) ? pCntntNode->Len() : 0); 207 SwPosition aNewPos(rNewPos); 208 aNewPos.nContent += nOffset; 209 210 getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset); 211 { // fix redlines 212 SwRedlineTbl& rTbl = *pRedlineTbl; 213 for (sal_uInt16 n = 0; n < rTbl.Count(); ) 214 { 215 // is on position ?? 216 SwRedline *const pRedline( rTbl[ n ] ); 217 bool const bChanged = 218 lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos); 219 // clean up empty redlines: docredln.cxx asserts these as invalid 220 if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark()) 221 && (pRedline->GetContentIdx() == NULL)) 222 { 223 rTbl.DeleteAndDestroy(n); 224 } 225 else 226 { 227 ++n; 228 } 229 } 230 } 231 232 if(bMoveCrsr) 233 { 234 ::PaMCorrAbs(aPam, aNewPos); 235 } 236 } 237 238 void SwDoc::CorrAbs(const SwPaM& rRange, 239 const SwPosition& rNewPos, 240 sal_Bool bMoveCrsr) 241 { 242 SwPosition aStart(*rRange.Start()); 243 SwPosition aEnd(*rRange.End()); 244 SwPosition aNewPos(rNewPos); 245 246 _DelBookmarks(aStart.nNode, aEnd.nNode, NULL, 247 &aStart.nContent, &aEnd.nContent); 248 if(bMoveCrsr) 249 ::PaMCorrAbs(rRange, rNewPos); 250 } 251 252 void SwDoc::CorrAbs(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 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 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 344 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 366 ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier() 367 { 368 return GetEditShell(0); 369 } 370 371