LibreOffice Module sw (master)  1
eddel.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <hintids.hxx>
22 #include <doc.hxx>
23 #include <IDocumentUndoRedo.hxx>
26 #include <editsh.hxx>
27 #include <cntfrm.hxx>
28 #include <pam.hxx>
29 #include <unocrsr.hxx>
30 #include <swundo.hxx>
31 #include <edimp.hxx>
32 #include <IMark.hxx>
33 #include <docary.hxx>
34 #include <SwRewriter.hxx>
35 #include <globals.hrc>
36 
37 #include <strings.hrc>
38 #include <vector>
39 
40 void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
41 {
42  bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
43  // only for selections
44  if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
45  return;
46 
47  // Is the selection in a table? Then delete only the content of the selected boxes.
48  // Here, there are two cases:
49  // 1. Point and Mark are in one box, delete selection as usual
50  // 2. Point and Mark are in different boxes, search all selected boxes and delete content
51  // 3. Point and Mark are at the document start and end, Point is in a table: delete selection as usual
52  if( rPam.GetNode().FindTableNode() &&
53  rPam.GetNode().StartOfSectionNode() !=
54  rPam.GetNode(false).StartOfSectionNode() && !bSelectAll )
55  {
56  // group the Undo in the table
57  if( pUndo && !*pUndo )
58  {
60  *pUndo = true;
61  }
62  SwPaM aDelPam( *rPam.Start() );
63  const SwPosition* pEndSelPos = rPam.End();
64  do {
65  aDelPam.SetMark();
66  SwNode& rNd = aDelPam.GetNode();
67  const SwNode& rEndNd = *rNd.EndOfSectionNode();
68  if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() )
69  {
70  *aDelPam.GetPoint() = *pEndSelPos;
71  pEndSelPos = nullptr; // misuse a pointer as a flag
72  }
73  else
74  {
75  // then go to the end of the selection
76  aDelPam.GetPoint()->nNode = rEndNd;
77  aDelPam.Move( fnMoveBackward, GoInContent );
78  }
79  // skip protected boxes
80  if( !rNd.IsContentNode() ||
81  !rNd.IsInProtectSect() )
82  {
83  // delete everything
85  SaveTableBoxContent( aDelPam.GetPoint() );
86  }
87 
88  if( !pEndSelPos ) // at the end of a selection
89  break;
90  aDelPam.DeleteMark();
91  aDelPam.Move( fnMoveForward, GoInContent ); // next box
92  } while( pEndSelPos );
93  }
94  else
95  {
96  std::unique_ptr<SwPaM> pNewPam;
97  SwPaM * pPam = &rPam;
98  if (bSelectAll)
99  {
100  assert(dynamic_cast<SwShellCursor*>(&rPam)); // must be corrected pam
101  pNewPam.reset(new SwPaM(*rPam.GetMark(), *rPam.GetPoint()));
102  // Selection starts at the first para of the first cell, but we
103  // want to delete the table node before the first cell as well.
104  pNewPam->Start()->nNode = pNewPam->Start()->nNode.GetNode().FindTableNode()->GetIndex();
105  pNewPam->Start()->nContent.Assign(nullptr, 0);
106  pPam = pNewPam.get();
107  }
108  // delete everything
110  SaveTableBoxContent( pPam->GetPoint() );
111  }
112 
113  // Selection is not needed anymore
114  rPam.DeleteMark();
115 }
116 
118 {
119  SET_CURR_SHELL( this );
120  bool bRet = false;
122  {
123  StartAllAction();
124 
125  bool bUndo = GetCursor()->GetNext() != GetCursor();
126  if( bUndo ) // more than one selection?
127  {
128  SwRewriter aRewriter;
129  aRewriter.AddRule(UndoArg1, SwResId(STR_MULTISEL));
130 
132  }
133 
134  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
135  {
136  DeleteSel( rPaM, &bUndo );
137  }
138 
139  // If undo container then close here
140  if( bUndo )
141  {
143  }
144  EndAllAction();
145  bRet = true;
146  }
147  else
148  {
150  }
151 
152  return bRet;
153 }
154 
155 bool SwEditShell::Copy( SwEditShell* pDestShell )
156 {
157  if( !pDestShell )
158  pDestShell = this;
159 
160  SET_CURR_SHELL( pDestShell );
161 
162  // List of insert positions for smart insert of block selections
163  std::vector< std::shared_ptr<SwPosition> > aInsertList;
164 
165  // Fill list of insert positions
166  {
167  SwPosition * pPos = nullptr;
168  std::shared_ptr<SwPosition> pInsertPos;
169  sal_uInt16 nMove = 0;
170  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
171  {
172  if( !pPos )
173  {
174  if( pDestShell == this )
175  {
176  // First cursor represents the target position!!
177  rPaM.DeleteMark();
178  pPos = rPaM.GetPoint();
179  continue;
180  }
181  else
182  pPos = pDestShell->GetCursor()->GetPoint();
183  }
184  if( IsBlockMode() )
185  { // In block mode different insert positions will be calculated
186  // by simulated cursor movements from the given first insert position
187  if( nMove )
188  {
189  SwCursor aCursor( *pPos, nullptr);
190  if (aCursor.UpDown(false, nMove, nullptr, 0, *GetLayout()))
191  {
192  pInsertPos.reset( new SwPosition( *aCursor.GetPoint() ) );
193  aInsertList.push_back( pInsertPos );
194  }
195  }
196  else
197  pInsertPos.reset( new SwPosition( *pPos ) );
198  ++nMove;
199  }
200  SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
201  // Check if a selection would be copied into itself
202  if( pDestShell->GetDoc() == GetDoc() &&
203  *rPaM.Start() <= *pTmp && *pTmp < *rPaM.End() )
204  return false;
205  }
206  }
207 
208  pDestShell->StartAllAction();
209  SwPosition *pPos = nullptr;
210  bool bRet = false;
211  bool bFirstMove = true;
212  SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() );
213  sal_Int32 nSttCntIdx = 0;
214  // For block selection this list is filled with the insert positions
215  auto pNextInsert = aInsertList.begin();
216 
217  pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
218  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
219  {
220  if( !pPos )
221  {
222  if( pDestShell == this )
223  {
224  // First cursor represents the target position!!
225  rPaM.DeleteMark();
226  pPos = rPaM.GetPoint();
227  continue;
228  }
229  else
230  pPos = pDestShell->GetCursor()->GetPoint();
231  }
232  if( !bFirstMove )
233  {
234  if( pNextInsert != aInsertList.end() )
235  {
236  pPos = pNextInsert->get();
237  ++pNextInsert;
238  }
239  else if( IsBlockMode() )
240  GetDoc()->getIDocumentContentOperations().SplitNode( *pPos, false );
241  }
242 
243  // Only for a selection (non-text nodes have selection but Point/GetMark are equal)
244  if( !rPaM.HasMark() || *rPaM.GetPoint() == *rPaM.GetMark() )
245  continue;
246 
247  if( bFirstMove )
248  {
249  // Store start position of the new area
250  aSttNdIdx = pPos->nNode.GetIndex()-1;
251  nSttCntIdx = pPos->nContent.GetIndex();
252  bFirstMove = false;
253  }
254 
255  const bool bSuccess( GetDoc()->getIDocumentContentOperations().CopyRange( rPaM, *pPos, /*bCopyAll=*/false, /*bCheckPos=*/true ) );
256  if (!bSuccess)
257  continue;
258 
259  SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
260  pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM);
261 
262  bRet = true;
263  }
264 
265  // Maybe nothing has been moved?
266  if( !bFirstMove )
267  {
268  SwPaM* pCursor = pDestShell->GetCursor();
269  pCursor->SetMark();
270  pCursor->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
271  pCursor->GetPoint()->nContent.Assign( pCursor->GetContentNode(),nSttCntIdx);
272  pCursor->Exchange();
273  }
274  else
275  {
276  // If the cursor moved during move process, move also its GetMark
277  pDestShell->GetCursor()->SetMark();
278  pDestShell->GetCursor()->DeleteMark();
279  }
280 #if OSL_DEBUG_LEVEL > 0
281  // check if the indices are registered in the correct nodes
282  {
283  for(SwPaM& rCmp : pDestShell->GetCursor()->GetRingContainer())
284  {
285  OSL_ENSURE( rCmp.GetPoint()->nContent.GetIdxReg()
286  == rCmp.GetContentNode(), "Point in wrong Node" );
287  OSL_ENSURE( rCmp.GetMark()->nContent.GetIdxReg()
288  == rCmp.GetContentNode(false), "Mark in wrong Node" );
289  }
290  }
291 #endif
292 
293  // close Undo container here
294  pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
295  pDestShell->EndAllAction();
296 
297  pDestShell->SaveTableBoxContent( pDestShell->GetCursor()->GetPoint() );
298 
299  return bRet;
300 }
301 
309 bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
310 {
311  SET_CURR_SHELL( this );
312 
313  bool bRet = false;
314  if( !HasReadonlySel() )
315  {
316  StartAllAction();
318 
319  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
320  {
321  if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
322  {
323  bRet = sw::ReplaceImpl(rPaM, rNewStr, bRegExpRplc, *GetDoc(), GetLayout())
324  || bRet;
325  SaveTableBoxContent( rPaM.GetPoint() );
326  }
327  }
328 
329  // close Undo container here
331  EndAllAction();
332  }
333  return bRet;
334 }
335 
338 {
339  bool bRet = false;
340  if( !IsTableMode() )
341  {
342  SwPaM* pCursor = GetCursor();
343  // no multi selection
344  if( !pCursor->IsMultiSelection() && !HasReadonlySel() )
345  {
346  SET_CURR_SHELL( this );
347  StartAllAction();
348  bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( *pCursor );
349  EndAllAction();
350  }
351  }
352  return bRet;
353 }
354 
355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
void DeleteMark()
Definition: pam.hxx:177
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:903
Marks a position in the document model.
Definition: pam.hxx:35
bool IsMultiSelection() const
Definition: pam.hxx:272
bool DelFullPara()
Remove a complete paragraph.
Definition: eddel.cxx:337
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:185
void SaveTableBoxContent(const SwPosition *pPos=nullptr)
Definition: trvltbl.cxx:873
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:645
SAL_DLLPRIVATE void DeleteSel(SwPaM &rPam, bool *pUndo=nullptr)
Definition: eddel.cxx:40
const SwPosition * GetMark() const
Definition: pam.hxx:209
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:176
virtual bool DeleteAndJoin(SwPaM &, const bool bForceJoinNext=false)=0
complete delete of a given PaM
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:347
void EndAllAction()
Definition: edws.cxx:96
bool RemoveParagraphMetadataFieldAtCursor()
Removes the paragraph metadata field at the current cursor, if any.
Definition: edfcol.cxx:2056
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
IDocumentContentOperations & getIDocumentContentOperations()
Provides access to the content operations interface.
Definition: viewsh.cxx:2600
SwIndex nContent
Definition: pam.hxx:38
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
SwDoc * GetDoc() const
Definition: viewsh.hxx:284
SwPaM * GetNext()
Definition: pam.hxx:264
bool IsContentNode() const
Definition: node.hxx:628
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
bool ExtendedSelectedAll()
If ExtendedSelectAll() was called and selection didn't change since then.
Definition: crsrsh.cxx:596
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
void MakeUniqueNumRules(const SwPaM &rPaM)
Definition: docnum.cxx:1244
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
bool IsBlockMode() const
Definition: crsrsh.hxx:642
void Exchange()
Definition: pam.cxx:471
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:29
#define SET_CURR_SHELL(shell)
Definition: swtypes.hxx:101
Marks a node in the document model.
Definition: ndindex.hxx:31
ring_container GetRingContainer()
OUString SwResId(const char *pId)
Definition: swmodule.cxx:191
bool ReplaceImpl(SwPaM &rCursor, OUString const &rReplacement, bool const bRegExp, SwDoc &rDoc, SwRootFrame const *const pLayout)
Definition: findtxt.cxx:1023
bool HasReadonlySel() const
Definition: crsrsh.cxx:3229
const SwPosition * Start() const
Definition: pam.hxx:212
bool IsInProtectSect() const
Is node in an protected area?
Definition: node.cxx:410
bool Delete()
Delete content of all ranges.
Definition: eddel.cxx:117
bool UpDown(bool bUp, sal_uInt16 nCnt, Point const *pPt, long nUpDownX, SwRootFrame &rLayout)
Definition: swcrsr.cxx:1923
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
virtual bool DelFullPara(SwPaM &)=0
Delete full paragraphs.
sal_Int32 GetIndex() const
Definition: index.hxx:95
bool StartsWithTable()
If document body starts with a table.
Definition: crsrsh.cxx:614
SwNodes & GetNodes()
Definition: doc.hxx:403
const SwPosition * End() const
Definition: pam.hxx:217
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:351
virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart)=0
Split a node at rPos (implemented only for TextNode).
bool Copy(SwEditShell *pDestShell)
Copy content of all ranges at current position of cursor to given Shell.
Definition: eddel.cxx:155
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:457
void StartAllAction()
For all views of this document.
Definition: edws.cxx:85
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2072
bool Replace(const OUString &rNewStr, bool bRegExpRplc)
Replace a selected range in a TextNode by given string.
Definition: eddel.cxx:309
Base class of the Writer document model elements.
Definition: node.hxx:79
bool CursorInsideInputField() const
Definition: crstrvl.cxx:948