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