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 <hintids.hxx> 29 #include <doc.hxx> 30 #include <IDocumentUndoRedo.hxx> 31 #include <editsh.hxx> 32 #include <cntfrm.hxx> 33 #include <pam.hxx> 34 #include <swundo.hxx> // fuer die UndoIds 35 #include <edimp.hxx> 36 #include <IMark.hxx> 37 #include <docary.hxx> 38 #include <SwRewriter.hxx> 39 #include <globals.hrc> 40 41 #include <comcore.hrc> 42 #include <list> 43 44 /************************************************************ 45 * Loeschen 46 ************************************************************/ 47 48 void SwEditShell::DeleteSel( SwPaM& rPam, sal_Bool* pUndo ) 49 { 50 // nur bei Selektion 51 if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark()) 52 return; 53 54 // besteht eine Selection in einer Tabelle ? 55 // dann nur den Inhalt der selektierten Boxen loeschen 56 // jetzt gibt es 2 Faelle die beachtet werden muessen: 57 // 1. Point und Mark stehen in einer Box, Selection normal loeschen 58 // 2. Point und Mark stehen in unterschiedlichen Boxen, alle 59 // selektierten Boxen suchen in den Inhalt loeschen 60 if( rPam.GetNode()->FindTableNode() && 61 rPam.GetNode()->StartOfSectionNode() != 62 rPam.GetNode(sal_False)->StartOfSectionNode() ) 63 { 64 // in Tabellen das Undo gruppieren 65 if( pUndo && !*pUndo ) 66 { 67 GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); 68 *pUndo = sal_True; 69 } 70 SwPaM aDelPam( *rPam.Start() ); 71 const SwPosition* pEndSelPos = rPam.End(); 72 do { 73 aDelPam.SetMark(); 74 SwNode* pNd = aDelPam.GetNode(); 75 const SwNode& rEndNd = *pNd->EndOfSectionNode(); 76 if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() ) 77 { 78 *aDelPam.GetPoint() = *pEndSelPos; 79 pEndSelPos = 0; // Pointer als Flag missbrauchen 80 } 81 else 82 { 83 // dann ans Ende der Section 84 aDelPam.GetPoint()->nNode = rEndNd; 85 aDelPam.Move( fnMoveBackward, fnGoCntnt ); 86 } 87 // geschuetze Boxen ueberspringen ! 88 if( !pNd->IsCntntNode() || 89 !((SwCntntNode*)pNd)->getLayoutFrm( GetLayout() )->IsProtected() ) 90 { 91 // alles loeschen 92 GetDoc()->DeleteAndJoin( aDelPam ); 93 SaveTblBoxCntnt( aDelPam.GetPoint() ); 94 } 95 96 if( !pEndSelPos ) // am Ende der Selection 97 break; 98 aDelPam.DeleteMark(); 99 aDelPam.Move( fnMoveForward, fnGoCntnt ); // naechste Box 100 } while( pEndSelPos ); 101 } 102 else 103 { 104 // alles loeschen 105 GetDoc()->DeleteAndJoin( rPam ); 106 SaveTblBoxCntnt( rPam.GetPoint() ); 107 } 108 109 // Selection wird nicht mehr benoetigt. 110 rPam.DeleteMark(); 111 } 112 113 114 long SwEditShell::Delete() 115 { 116 SET_CURR_SHELL( this ); 117 long nRet = 0; 118 if( !HasReadonlySel() ) 119 { 120 StartAllAction(); 121 122 sal_Bool bUndo = GetCrsr()->GetNext() != GetCrsr(); 123 if( bUndo ) // mehr als eine Selection ? 124 { 125 SwRewriter aRewriter; 126 aRewriter.AddRule(UNDO_ARG1, String(SW_RES(STR_MULTISEL))); 127 128 GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_DELETE, &aRewriter); 129 } 130 131 FOREACHPAM_START(this) 132 DeleteSel( *PCURCRSR, &bUndo ); 133 FOREACHPAM_END() 134 135 // falls eine Undo-Klammerung, dann hier beenden 136 if( bUndo ) 137 { 138 GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, 0); 139 } 140 EndAllAction(); 141 nRet = 1; 142 } 143 return nRet; 144 } 145 146 long SwEditShell::Copy( SwEditShell* pDestShell ) 147 { 148 if( !pDestShell ) 149 pDestShell = this; 150 151 SET_CURR_SHELL( pDestShell ); 152 153 // List of insert positions for smart insert of block selections 154 std::list< boost::shared_ptr<SwPosition> > aInsertList; 155 156 // Fill list of insert positions 157 { 158 SwPosition * pPos = 0; 159 boost::shared_ptr<SwPosition> pInsertPos; 160 sal_uInt16 nMove = 0; 161 FOREACHPAM_START(this) 162 163 if( !pPos ) 164 { 165 if( pDestShell == this ) 166 { 167 // First cursor represents the target position!! 168 PCURCRSR->DeleteMark(); 169 pPos = (SwPosition*)PCURCRSR->GetPoint(); 170 continue; 171 } 172 else 173 pPos = pDestShell->GetCrsr()->GetPoint(); 174 } 175 if( IsBlockMode() ) 176 { // In block mode different insert positions will be calculated 177 // by simulated cursor movements from the given first insert position 178 if( nMove ) 179 { 180 SwCursor aCrsr( *pPos, 0, false); 181 if( aCrsr.UpDown( sal_False, nMove, 0, 0 ) ) 182 { 183 pInsertPos.reset( new SwPosition( *aCrsr.GetPoint() ) ); 184 aInsertList.push_back( pInsertPos ); 185 } 186 } 187 else 188 pInsertPos.reset( new SwPosition( *pPos ) ); 189 ++nMove; 190 } 191 SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos; 192 // Check if a selection would be copied into itself 193 if( pDestShell->GetDoc() == GetDoc() && 194 *PCURCRSR->Start() <= *pTmp && *pTmp < *PCURCRSR->End() ) 195 return sal_False; 196 FOREACHPAM_END() 197 } 198 199 pDestShell->StartAllAction(); 200 SwPosition *pPos = 0; 201 sal_Bool bRet = sal_False; 202 sal_Bool bFirstMove = sal_True; 203 SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() ); 204 xub_StrLen nSttCntIdx = 0; 205 // For block selection this list is filled with the insert positions 206 std::list< boost::shared_ptr<SwPosition> >::iterator pNextInsert = aInsertList.begin(); 207 208 pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); 209 FOREACHPAM_START(this) 210 211 if( !pPos ) 212 { 213 if( pDestShell == this ) 214 { 215 // First cursor represents the target position!! 216 PCURCRSR->DeleteMark(); 217 pPos = (SwPosition*)PCURCRSR->GetPoint(); 218 continue; 219 } 220 else 221 pPos = pDestShell->GetCrsr()->GetPoint(); 222 } 223 if( !bFirstMove ) 224 { 225 if( pNextInsert != aInsertList.end() ) 226 { 227 pPos = pNextInsert->get(); 228 ++pNextInsert; 229 } 230 else if( IsBlockMode() ) 231 GetDoc()->SplitNode( *pPos, false ); 232 } 233 234 // nur bei Selektion (nicht Textnodes haben Selection, 235 // aber Point/GetMark sind gleich 236 if( !PCURCRSR->HasMark() || *PCURCRSR->GetPoint() == *PCURCRSR->GetMark() ) 237 continue; 238 239 if( bFirstMove ) 240 { 241 // Anfangs-Position vom neuen Bereich merken 242 aSttNdIdx = pPos->nNode.GetIndex()-1; 243 nSttCntIdx = pPos->nContent.GetIndex(); 244 bFirstMove = sal_False; 245 } 246 247 const bool bSuccess( GetDoc()->CopyRange( *PCURCRSR, *pPos, false ) ); 248 if (!bSuccess) 249 continue; 250 251 SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx)); 252 pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM); 253 254 bRet = sal_True; 255 FOREACHPAM_END() 256 257 258 // Maybe nothing has been moved? 259 if( !bFirstMove ) 260 { 261 SwPaM* pCrsr = pDestShell->GetCrsr(); 262 pCrsr->SetMark(); 263 pCrsr->GetPoint()->nNode = aSttNdIdx.GetIndex()+1; 264 pCrsr->GetPoint()->nContent.Assign( pCrsr->GetCntntNode(),nSttCntIdx); 265 pCrsr->Exchange(); 266 } 267 else 268 { 269 // falls beim Move der Cursor "gewandert" ist, so setze hier auch 270 // seinen GetMark um, damit dieser nie in den Wald zeigt. 271 pDestShell->GetCrsr()->SetMark(); 272 pDestShell->GetCrsr()->DeleteMark(); 273 } 274 #if OSL_DEBUG_LEVEL > 1 275 // pruefe ob die Indizies auch in den richtigen Nodes angemeldet sind 276 { 277 SwPaM* pCmp = (SwPaM*)pDestShell->GetCrsr(); // sicher den Pointer auf Cursor 278 do { 279 ASSERT( pCmp->GetPoint()->nContent.GetIdxReg() 280 == pCmp->GetCntntNode(), "Point im falschen Node" ); 281 ASSERT( pCmp->GetMark()->nContent.GetIdxReg() 282 == pCmp->GetCntntNode(sal_False), "Mark im falschen Node" ); 283 sal_Bool bTst = *pCmp->GetPoint() == *pCmp->GetMark(); 284 (void) bTst; 285 } while( pDestShell->GetCrsr() != ( pCmp = (SwPaM*)pCmp->GetNext() ) ); 286 } 287 #endif 288 289 // Undo-Klammerung hier beenden 290 pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); 291 pDestShell->EndAllAction(); 292 293 pDestShell->SaveTblBoxCntnt( pDestShell->GetCrsr()->GetPoint() ); 294 295 return (long)bRet; 296 } 297 298 299 // Ersetz einen selektierten Bereich in einem TextNode mit dem 300 // String. Ist fuers Suchen&Ersetzen gedacht. 301 // bRegExpRplc - ersetze Tabs (\\t) und setze den gefundenen String 302 // ein ( nicht \& ) 303 // z.B.: Fnd: "zzz", Repl: "xx\t\\t..&..\&" 304 // --> "xx\t<Tab>..zzz..&" 305 sal_Bool SwEditShell::Replace( const String& rNewStr, sal_Bool bRegExpRplc ) 306 { 307 SET_CURR_SHELL( this ); 308 309 sal_Bool bRet = sal_False; 310 if( !HasReadonlySel() ) 311 { 312 StartAllAction(); 313 GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); 314 315 FOREACHPAM_START(this) 316 if( PCURCRSR->HasMark() && *PCURCRSR->GetMark() != *PCURCRSR->GetPoint() ) 317 { 318 bRet = GetDoc()->ReplaceRange( *PCURCRSR, rNewStr, bRegExpRplc ) 319 || bRet; 320 SaveTblBoxCntnt( PCURCRSR->GetPoint() ); 321 } 322 FOREACHPAM_END() 323 324 // Undo-Klammerung hier beenden 325 GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); 326 EndAllAction(); 327 } 328 return bRet; 329 } 330 331 332 // Special-Methode fuer JOE's- Wizzards 333 sal_Bool SwEditShell::DelFullPara() 334 { 335 sal_Bool bRet = sal_False; 336 if( !IsTableMode() ) 337 { 338 SwPaM* pCrsr = GetCrsr(); 339 // keine Mehrfach-Selection 340 if( pCrsr->GetNext() == pCrsr && !HasReadonlySel() ) 341 { 342 SET_CURR_SHELL( this ); 343 StartAllAction(); 344 bRet = GetDoc()->DelFullPara( *pCrsr ); 345 EndAllAction(); 346 } 347 } 348 return bRet; 349 } 350 351 352 353