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& rDestShell )
164 {
165  CurrShell aCurr( &rDestShell );
166 
167  // List of insert positions for smart insert of block selections
168  std::vector< std::shared_ptr<SwPosition> > aInsertList;
169 
170  // Fill list of insert positions
171  {
172  SwPosition * pPos = nullptr;
173  std::shared_ptr<SwPosition> pInsertPos;
174  sal_uInt16 nMove = 0;
175  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
176  {
177  if( !pPos )
178  {
179  if( &rDestShell == this )
180  {
181  // First cursor represents the target position!!
182  rPaM.DeleteMark();
183  pPos = rPaM.GetPoint();
184  continue;
185  }
186  else
187  pPos = rDestShell.GetCursor()->GetPoint();
188  }
189  if( IsBlockMode() )
190  { // In block mode different insert positions will be calculated
191  // by simulated cursor movements from the given first insert position
192  if( nMove )
193  {
194  SwCursor aCursor( *pPos, nullptr);
195  if (aCursor.UpDown(false, nMove, nullptr, 0, *GetLayout()))
196  {
197  pInsertPos = std::make_shared<SwPosition>( *aCursor.GetPoint() );
198  aInsertList.push_back( pInsertPos );
199  }
200  }
201  else
202  pInsertPos = std::make_shared<SwPosition>( *pPos );
203  ++nMove;
204  }
205  SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
206  // Check if a selection would be copied into itself
207  if( rDestShell.GetDoc() == GetDoc() &&
208  *rPaM.Start() <= *pTmp && *pTmp < *rPaM.End() )
209  return false;
210  }
211  }
212 
213  rDestShell.StartAllAction();
214  SwPosition *pPos = nullptr;
215  bool bRet = false;
216  bool bFirstMove = true;
217  SwNodeIndex aSttNdIdx( rDestShell.GetDoc()->GetNodes() );
218  sal_Int32 nSttCntIdx = 0;
219  // For block selection this list is filled with the insert positions
220  auto pNextInsert = aInsertList.begin();
221 
222  rDestShell.GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
223  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
224  {
225  if( !pPos )
226  {
227  if( &rDestShell == this )
228  {
229  // First cursor represents the target position!!
230  rPaM.DeleteMark();
231  pPos = rPaM.GetPoint();
232  continue;
233  }
234  else
235  pPos = rDestShell.GetCursor()->GetPoint();
236  }
237  if( !bFirstMove )
238  {
239  if( pNextInsert != aInsertList.end() )
240  {
241  pPos = pNextInsert->get();
242  ++pNextInsert;
243  }
244  else if( IsBlockMode() )
245  GetDoc()->getIDocumentContentOperations().SplitNode( *pPos, false );
246  }
247 
248  // Only for a selection (non-text nodes have selection but Point/GetMark are equal)
249  if( !rPaM.HasMark() || *rPaM.GetPoint() == *rPaM.GetMark() )
250  continue;
251 
252  if( bFirstMove )
253  {
254  // Store start position of the new area
255  aSttNdIdx = pPos->nNode.GetIndex()-1;
256  nSttCntIdx = pPos->nContent.GetIndex();
257  bFirstMove = false;
258  }
259 
260  const bool bSuccess( GetDoc()->getIDocumentContentOperations().CopyRange(rPaM, *pPos, SwCopyFlags::CheckPosInFly) );
261  if (!bSuccess)
262  continue;
263 
264  SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
265  rDestShell.GetDoc()->MakeUniqueNumRules(aInsertPaM);
266 
267  bRet = true;
268  }
269 
270  // Maybe nothing has been moved?
271  if( !bFirstMove )
272  {
273  SwPaM* pCursor = rDestShell.GetCursor();
274  pCursor->SetMark();
275  pCursor->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
276  pCursor->GetPoint()->nContent.Assign( pCursor->GetContentNode(),nSttCntIdx);
277  pCursor->Exchange();
278  }
279  else
280  {
281  // If the cursor moved during move process, move also its GetMark
282  rDestShell.GetCursor()->SetMark();
283  rDestShell.GetCursor()->DeleteMark();
284  }
285 #if OSL_DEBUG_LEVEL > 0
286  // check if the indices are registered in the correct nodes
287  {
288  for(SwPaM& rCmp : rDestShell.GetCursor()->GetRingContainer())
289  {
290  OSL_ENSURE( rCmp.GetPoint()->nContent.GetIdxReg()
291  == rCmp.GetContentNode(), "Point in wrong Node" );
292  OSL_ENSURE( rCmp.GetMark()->nContent.GetIdxReg()
293  == rCmp.GetContentNode(false), "Mark in wrong Node" );
294  }
295  }
296 #endif
297 
298  // close Undo container here
299  rDestShell.GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
300  rDestShell.EndAllAction();
301 
302  rDestShell.SaveTableBoxContent( rDestShell.GetCursor()->GetPoint() );
303 
304  return bRet;
305 }
306 
314 bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
315 {
316  CurrShell aCurr( this );
317 
318  bool bRet = false;
319  if( !HasReadonlySel() )
320  {
321  StartAllAction();
323 
324  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
325  {
326  if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
327  {
328  bRet = sw::ReplaceImpl(rPaM, rNewStr, bRegExpRplc, *GetDoc(), GetLayout())
329  || bRet;
330  SaveTableBoxContent( rPaM.GetPoint() );
331  }
332  }
333 
334  // close Undo container here
336  EndAllAction();
337  }
338  return bRet;
339 }
340 
343 {
344  bool bRet = false;
345  if( !IsTableMode() )
346  {
347  SwPaM* pCursor = GetCursor();
348  // no multi selection
349  if( !pCursor->IsMultiSelection() && !HasReadonlySel() )
350  {
351  CurrShell aCurr( this );
352  StartAllAction();
353  bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( *pCursor );
354  EndAllAction();
355  }
356  }
357  return bRet;
358 }
359 
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:962
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:690
void DeleteMark()
Definition: pam.hxx:177
sal_uLong GetIndex() const
Definition: node.hxx:290
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:342
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:144
virtual bool DeleteAndJoin(SwPaM &, const bool bForceJoinNext=false)=0
complete delete of a given PaM
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
void EndAllAction()
Definition: edws.cxx:97
bool RemoveParagraphMetadataFieldAtCursor()
Removes the paragraph metadata field at the current cursor, if any.
Definition: edfcol.cxx:2051
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
IDocumentContentOperations & getIDocumentContentOperations()
Provides access to the content operations interface.
Definition: viewsh.cxx:2614
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:281
SwPaM * GetNext()
Definition: pam.hxx:264
bool IsContentNode() const
Definition: node.hxx:636
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
bool UpDown(bool bUp, sal_uInt16 nCnt, Point const *pPt, tools::Long nUpDownX, SwRootFrame &rLayout)
Definition: swcrsr.cxx:1962
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:1049
bool HasReadonlySel() const
Definition: crsrsh.cxx:3331
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
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 &rDestShell)
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:1669
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:2073
bool Replace(const OUString &rNewStr, bool bRegExpRplc)
Replace a selected range in a TextNode by given string.
Definition: eddel.cxx:314
Base class of the Writer document model elements.
Definition: node.hxx:79
bool CursorInsideInputField() const
Definition: crstrvl.cxx:925