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 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 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 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 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 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 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 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 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 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