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 { // fix redlines 208 SwRedlineTbl& rTbl = *pRedlineTbl; 209 for (sal_uInt16 n = 0; n < rTbl.Count(); ) 210 { 211 // is on position ?? 212 SwRedline *const pRedline( rTbl[ n ] ); 213 bool const bChanged = 214 lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos); 215 // clean up empty redlines: docredln.cxx asserts these as invalid 216 if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark()) 217 && (pRedline->GetContentIdx() == NULL)) 218 { 219 rTbl.DeleteAndDestroy(n); 220 } 221 else 222 { 223 ++n; 224 } 225 } 226 } 227 228 if(bMoveCrsr) 229 { 230 ::PaMCorrAbs(aPam, aNewPos); 231 } 232 } 233 234 void SwDoc::CorrAbs(const SwPaM& rRange, 235 const SwPosition& rNewPos, 236 sal_Bool bMoveCrsr) 237 { 238 SwPosition aStart(*rRange.Start()); 239 SwPosition aEnd(*rRange.End()); 240 SwPosition aNewPos(rNewPos); 241 242 _DelBookmarks(aStart.nNode, aEnd.nNode, NULL, 243 &aStart.nContent, &aEnd.nContent); 244 if(bMoveCrsr) 245 ::PaMCorrAbs(rRange, rNewPos); 246 } 247 248 void SwDoc::CorrAbs(const SwNodeIndex& rStartNode, 249 const SwNodeIndex& rEndNode, 250 const SwPosition& rNewPos, 251 sal_Bool bMoveCrsr) 252 { 253 _DelBookmarks(rStartNode, rEndNode); 254 255 if(bMoveCrsr) 256 { 257 SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() ); 258 SwPaM const aPam(rStartNode, 0, 259 rEndNode, (pCntntNode) ? pCntntNode->Len() : 0); 260 ::PaMCorrAbs(aPam, rNewPos); 261 } 262 } 263 264 265 266 267 268 void PaMCorrRel( const SwNodeIndex &rOldNode, 269 const SwPosition &rNewPos, 270 const xub_StrLen nOffset ) 271 { 272 const SwNode* pOldNode = &rOldNode.GetNode(); 273 SwPosition aNewPos( rNewPos ); 274 const SwDoc* pDoc = pOldNode->GetDoc(); 275 276 xub_StrLen nCntIdx = rNewPos.nContent.GetIndex() + nOffset; 277 278 SwCrsrShell* pShell = pDoc->GetEditShell(); 279 if( pShell ) 280 { 281 FOREACHSHELL_START( pShell ) 282 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr(); 283 if( _pStkCrsr ) 284 do { 285 lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx ); 286 } while ( (_pStkCrsr != 0 ) && 287 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) ); 288 289 FOREACHPAM_START( PCURSH->_GetCrsr() ) 290 lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx); 291 FOREACHPAM_END() 292 293 if( PCURSH->IsTableMode() ) 294 lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx ); 295 296 FOREACHSHELL_END( pShell ) 297 } 298 { 299 SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl(); 300 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 301 { 302 FOREACHPAM_START( rTbl[ n ] ) 303 lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx ); 304 FOREACHPAM_END() 305 306 SwUnoTableCrsr* pUnoTblCrsr = 307 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]); 308 if( pUnoTblCrsr ) 309 { 310 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() ) 311 lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx ); 312 FOREACHPAM_END() 313 } 314 } 315 } 316 } 317 318 void SwDoc::CorrRel(const SwNodeIndex& rOldNode, 319 const SwPosition& rNewPos, 320 const xub_StrLen nOffset, 321 sal_Bool bMoveCrsr) 322 { 323 getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset); 324 325 { // dann die Redlines korrigieren 326 SwRedlineTbl& rTbl = *pRedlineTbl; 327 SwPosition aNewPos(rNewPos); 328 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 329 { 330 // liegt auf der Position ?? 331 lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset ); 332 } 333 } 334 335 if(bMoveCrsr) 336 ::PaMCorrRel(rOldNode, rNewPos, nOffset); 337 } 338 339 340 SwEditShell* SwDoc::GetEditShell( ViewShell** ppSh ) const 341 { 342 // Layout und OLE-Shells sollten vorhanden sein! 343 if( pCurrentView ) 344 { 345 ViewShell *pSh = pCurrentView, *pVSh = pSh; 346 if( ppSh ) 347 *ppSh = pSh; 348 349 // wir suchen uns eine EditShell, falls diese existiert 350 do { 351 if( pSh->IsA( TYPE( SwEditShell ) ) ) 352 return (SwEditShell*)pSh; 353 354 } while( pVSh != ( pSh = (ViewShell*)pSh->GetNext() )); 355 } 356 else if( ppSh ) 357 *ppSh = 0; //swmod 071029//swmod 071225 358 359 return 0; 360 } 361 362 ::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier() 363 { 364 return GetEditShell(0); 365 } 366 367