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