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