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 <doc.hxx>
22 #include <IDocumentUndoRedo.hxx>
24 #include <editsh.hxx>
25 #include <pam.hxx>
26 #include <swundo.hxx>
27 #include <undobj.hxx>
28 #include <SwRewriter.hxx>
29 #include <osl/diagnose.h>
30 
31 #include <strings.hrc>
32 #include <vector>
33 
34 void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
35 {
36  bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
37  // only for selections
38  if (!rPam.HasMark()
39  || (*rPam.GetPoint() == *rPam.GetMark()
40  && !IsFlySelectedByCursor(*GetDoc(), *rPam.Start(), *rPam.End())))
41  {
42  return;
43  }
44 
45  // Is the selection in a table? Then delete only the content of the selected boxes.
46  // Here, there are two cases:
47  // 1. Point and Mark are in one box, delete selection as usual
48  // 2. Point and Mark are in different boxes, search all selected boxes and delete content
49  // 3. Point and Mark are at the document start and end, Point is in a table: delete selection as usual
50  if( rPam.GetNode().FindTableNode() &&
51  rPam.GetNode().StartOfSectionNode() !=
52  rPam.GetNode(false).StartOfSectionNode() && !bSelectAll )
53  {
54  // group the Undo in the table
55  if( pUndo && !*pUndo )
56  {
58  *pUndo = true;
59  }
60  SwPaM aDelPam( *rPam.Start() );
61  const SwPosition* pEndSelPos = rPam.End();
62  do {
63  aDelPam.SetMark();
64  SwNode& rNd = aDelPam.GetNode();
65  const SwNode& rEndNd = *rNd.EndOfSectionNode();
66  if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() )
67  {
68  *aDelPam.GetPoint() = *pEndSelPos;
69  pEndSelPos = nullptr; // misuse a pointer as a flag
70  }
71  else
72  {
73  // then go to the end of the selection
74  aDelPam.GetPoint()->nNode = rEndNd;
75  aDelPam.Move( fnMoveBackward, GoInContent );
76  }
77  // skip protected boxes
78  if( !rNd.IsContentNode() ||
79  !rNd.IsInProtectSect() )
80  {
81  // delete everything
83  SaveTableBoxContent( aDelPam.GetPoint() );
84  }
85 
86  if( !pEndSelPos ) // at the end of a selection
87  break;
88  aDelPam.DeleteMark();
89  aDelPam.Move( fnMoveForward, GoInContent ); // next box
90  } while( pEndSelPos );
91  }
92  else
93  {
94  std::unique_ptr<SwPaM> pNewPam;
95  SwPaM * pPam = &rPam;
96  if (bSelectAll)
97  {
98  assert(dynamic_cast<SwShellCursor*>(&rPam)); // must be corrected pam
99  pNewPam.reset(new SwPaM(*rPam.GetMark(), *rPam.GetPoint()));
100  // Selection starts at the first para of the first cell, but we
101  // want to delete the table node before the first cell as well.
102  while (SwTableNode const* pTableNode =
103  pNewPam->Start()->nNode.GetNode().StartOfSectionNode()->FindTableNode())
104  {
105  pNewPam->Start()->nNode = *pTableNode;
106  }
107  // tdf#133990 ensure section is included in SwUndoDelete
108  while (SwSectionNode const* pSectionNode =
109  pNewPam->Start()->nNode.GetNode().StartOfSectionNode()->FindSectionNode())
110  {
111  pNewPam->Start()->nNode = *pSectionNode;
112  }
113  pNewPam->Start()->nContent.Assign(nullptr, 0);
114  pPam = pNewPam.get();
115  }
116  // delete everything
118  SaveTableBoxContent( pPam->GetPoint() );
119  }
120 
121  // Selection is not needed anymore
122  rPam.DeleteMark();
123 }
124 
126 {
127  CurrShell aCurr( this );
128  bool bRet = false;
130  {
131  StartAllAction();
132 
133  bool bUndo = GetCursor()->GetNext() != GetCursor();
134  if( bUndo ) // more than one selection?
135  {
136  SwRewriter aRewriter;
137  aRewriter.AddRule(UndoArg1, SwResId(STR_MULTISEL));
138 
140  }
141 
142  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
143  {
144  DeleteSel( rPaM, &bUndo );
145  }
146 
147  // If undo container then close here
148  if( bUndo )
149  {
151  }
152  EndAllAction();
153  bRet = true;
154  }
155  else
156  {
158  }
159 
160  return bRet;
161 }
162 
163 bool SwEditShell::Copy( SwEditShell* pDestShell )
164 {
165  if( !pDestShell )
166  pDestShell = this;
167 
168  CurrShell aCurr( pDestShell );
169 
170  // List of insert positions for smart insert of block selections
171  std::vector< std::shared_ptr<SwPosition> > aInsertList;
172 
173  // Fill list of insert positions
174  {
175  SwPosition * pPos = nullptr;
176  std::shared_ptr<SwPosition> pInsertPos;
177  sal_uInt16 nMove = 0;
178  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
179  {
180  if( !pPos )
181  {
182  if( pDestShell == this )
183  {
184  // First cursor represents the target position!!
185  rPaM.DeleteMark();
186  pPos = rPaM.GetPoint();
187  continue;
188  }
189  else
190  pPos = pDestShell->GetCursor()->GetPoint();
191  }
192  if( IsBlockMode() )
193  { // In block mode different insert positions will be calculated
194  // by simulated cursor movements from the given first insert position
195  if( nMove )
196  {
197  SwCursor aCursor( *pPos, nullptr);
198  if (aCursor.UpDown(false, nMove, nullptr, 0, *GetLayout()))
199  {
200  pInsertPos = std::make_shared<SwPosition>( *aCursor.GetPoint() );
201  aInsertList.push_back( pInsertPos );
202  }
203  }
204  else
205  pInsertPos = std::make_shared<SwPosition>( *pPos );
206  ++nMove;
207  }
208  SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
209  // Check if a selection would be copied into itself
210  if( pDestShell->GetDoc() == GetDoc() &&
211  *rPaM.Start() <= *pTmp && *pTmp < *rPaM.End() )
212  return false;
213  }
214  }
215 
216  pDestShell->StartAllAction();
217  SwPosition *pPos = nullptr;
218  bool bRet = false;
219  bool bFirstMove = true;
220  SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() );
221  sal_Int32 nSttCntIdx = 0;
222  // For block selection this list is filled with the insert positions
223  auto pNextInsert = aInsertList.begin();
224 
225  pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
226  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
227  {
228  if( !pPos )
229  {
230  if( pDestShell == this )
231  {
232  // First cursor represents the target position!!
233  rPaM.DeleteMark();
234  pPos = rPaM.GetPoint();
235  continue;
236  }
237  else
238  pPos = pDestShell->GetCursor()->GetPoint();
239  }
240  if( !bFirstMove )
241  {
242  if( pNextInsert != aInsertList.end() )
243  {
244  pPos = pNextInsert->get();
245  ++pNextInsert;
246  }
247  else if( IsBlockMode() )
248  GetDoc()->getIDocumentContentOperations().SplitNode( *pPos, false );
249  }
250 
251  // Only for a selection (non-text nodes have selection but Point/GetMark are equal)
252  if( !rPaM.HasMark() || *rPaM.GetPoint() == *rPaM.GetMark() )
253  continue;
254 
255  if( bFirstMove )
256  {
257  // Store start position of the new area
258  aSttNdIdx = pPos->nNode.GetIndex()-1;
259  nSttCntIdx = pPos->nContent.GetIndex();
260  bFirstMove = false;
261  }
262 
263  const bool bSuccess( GetDoc()->getIDocumentContentOperations().CopyRange(rPaM, *pPos, SwCopyFlags::CheckPosInFly) );
264  if (!bSuccess)
265  continue;
266 
267  SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
268  pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM);
269 
270  bRet = true;
271  }
272 
273  // Maybe nothing has been moved?
274  if( !bFirstMove )
275  {
276  SwPaM* pCursor = pDestShell->GetCursor();
277  pCursor->SetMark();
278  pCursor->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
279  pCursor->GetPoint()->nContent.Assign( pCursor->GetContentNode(),nSttCntIdx);
280  pCursor->Exchange();
281  }
282  else
283  {
284  // If the cursor moved during move process, move also its GetMark
285  pDestShell->GetCursor()->SetMark();
286  pDestShell->GetCursor()->DeleteMark();
287  }
288 #if OSL_DEBUG_LEVEL > 0
289  // check if the indices are registered in the correct nodes
290  {
291  for(SwPaM& rCmp : pDestShell->GetCursor()->GetRingContainer())
292  {
293  OSL_ENSURE( rCmp.GetPoint()->nContent.GetIdxReg()
294  == rCmp.GetContentNode(), "Point in wrong Node" );
295  OSL_ENSURE( rCmp.GetMark()->nContent.GetIdxReg()
296  == rCmp.GetContentNode(false), "Mark in wrong Node" );
297  }
298  }
299 #endif
300 
301  // close Undo container here
302  pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
303  pDestShell->EndAllAction();
304 
305  pDestShell->SaveTableBoxContent( pDestShell->GetCursor()->GetPoint() );
306 
307  return bRet;
308 }
309 
317 bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
318 {
319  CurrShell aCurr( this );
320 
321  bool bRet = false;
322  if( !HasReadonlySel() )
323  {
324  StartAllAction();
326 
327  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
328  {
329  if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
330  {
331  bRet = sw::ReplaceImpl(rPaM, rNewStr, bRegExpRplc, *GetDoc(), GetLayout())
332  || bRet;
333  SaveTableBoxContent( rPaM.GetPoint() );
334  }
335  }
336 
337  // close Undo container here
339  EndAllAction();
340  }
341  return bRet;
342 }
343 
346 {
347  bool bRet = false;
348  if( !IsTableMode() )
349  {
350  SwPaM* pCursor = GetCursor();
351  // no multi selection
352  if( !pCursor->IsMultiSelection() && !HasReadonlySel() )
353  {
354  CurrShell aCurr( this );
355  StartAllAction();
356  bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( *pCursor );
357  EndAllAction();
358  }
359  }
360  return bRet;
361 }
362 
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:961
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:963
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:345
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:189
void SaveTableBoxContent(const SwPosition *pPos=nullptr)
Definition: trvltbl.cxx:869
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:643
SAL_DLLPRIVATE void DeleteSel(SwPaM &rPam, bool *pUndo=nullptr)
Definition: eddel.cxx:34
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:143
virtual bool DeleteAndJoin(SwPaM &, const bool bForceJoinNext=false)=0
complete delete of a given PaM
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
void EndAllAction()
Definition: edws.cxx:97
bool RemoveParagraphMetadataFieldAtCursor()
Removes the paragraph metadata field at the current cursor, if any.
Definition: edfcol.cxx:2048
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
IDocumentContentOperations & getIDocumentContentOperations()
Provides access to the content operations interface.
Definition: viewsh.cxx:2595
SwIndex nContent
Definition: pam.hxx:38
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
check if target position is in fly anchored at source range
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
SwDoc * GetDoc() const
Definition: viewsh.hxx:282
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:605
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
void MakeUniqueNumRules(const SwPaM &rPaM)
Definition: docnum.cxx:1237
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
bool IsBlockMode() const
Definition: crsrsh.hxx:640
void Exchange()
Definition: pam.cxx:489
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
Marks a node in the document model.
Definition: ndindex.hxx:31
ring_container GetRingContainer()
OUString SwResId(const char *pId)
Definition: swmodule.cxx:165
bool ReplaceImpl(SwPaM &rCursor, OUString const &rReplacement, bool const bRegExp, SwDoc &rDoc, SwRootFrame const *const pLayout)
Definition: findtxt.cxx:1043
bool HasReadonlySel() const
Definition: crsrsh.cxx:3332
const SwPosition * Start() const
Definition: pam.hxx:212
bool IsInProtectSect() const
Is node in a protected area?
Definition: node.cxx:411
bool Delete()
Delete content of all ranges.
Definition: eddel.cxx:125
bool UpDown(bool bUp, sal_uInt16 nCnt, Point const *pPt, long nUpDownX, SwRootFrame &rLayout)
Definition: swcrsr.cxx:1947
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:91
bool StartsWithTable()
If document body starts with a table.
Definition: crsrsh.cxx:624
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:352
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:163
bool IsFlySelectedByCursor(SwDoc const &rDoc, SwPosition const &rStart, SwPosition const &rEnd)
check at-char and at-para flys in rDoc
Definition: undobj.cxx:1663
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:475
void StartAllAction()
For all views of this document.
Definition: edws.cxx:86
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2069
bool Replace(const OUString &rNewStr, bool bRegExpRplc)
Replace a selected range in a TextNode by given string.
Definition: eddel.cxx:317
Base class of the Writer document model elements.
Definition: node.hxx:79
bool CursorInsideInputField() const
Definition: crstrvl.cxx:926