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 <SwRewriter.hxx>
28 #include <osl/diagnose.h>
29 
30 #include <strings.hrc>
31 #include <vector>
32 
33 void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
34 {
35  bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
36  // only for selections
37  if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
38  return;
39 
40  // Is the selection in a table? Then delete only the content of the selected boxes.
41  // Here, there are two cases:
42  // 1. Point and Mark are in one box, delete selection as usual
43  // 2. Point and Mark are in different boxes, search all selected boxes and delete content
44  // 3. Point and Mark are at the document start and end, Point is in a table: delete selection as usual
45  if( rPam.GetNode().FindTableNode() &&
46  rPam.GetNode().StartOfSectionNode() !=
47  rPam.GetNode(false).StartOfSectionNode() && !bSelectAll )
48  {
49  // group the Undo in the table
50  if( pUndo && !*pUndo )
51  {
53  *pUndo = true;
54  }
55  SwPaM aDelPam( *rPam.Start() );
56  const SwPosition* pEndSelPos = rPam.End();
57  do {
58  aDelPam.SetMark();
59  SwNode& rNd = aDelPam.GetNode();
60  const SwNode& rEndNd = *rNd.EndOfSectionNode();
61  if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() )
62  {
63  *aDelPam.GetPoint() = *pEndSelPos;
64  pEndSelPos = nullptr; // misuse a pointer as a flag
65  }
66  else
67  {
68  // then go to the end of the selection
69  aDelPam.GetPoint()->nNode = rEndNd;
70  aDelPam.Move( fnMoveBackward, GoInContent );
71  }
72  // skip protected boxes
73  if( !rNd.IsContentNode() ||
74  !rNd.IsInProtectSect() )
75  {
76  // delete everything
78  SaveTableBoxContent( aDelPam.GetPoint() );
79  }
80 
81  if( !pEndSelPos ) // at the end of a selection
82  break;
83  aDelPam.DeleteMark();
84  aDelPam.Move( fnMoveForward, GoInContent ); // next box
85  } while( pEndSelPos );
86  }
87  else
88  {
89  std::unique_ptr<SwPaM> pNewPam;
90  SwPaM * pPam = &rPam;
91  if (bSelectAll)
92  {
93  assert(dynamic_cast<SwShellCursor*>(&rPam)); // must be corrected pam
94  pNewPam.reset(new SwPaM(*rPam.GetMark(), *rPam.GetPoint()));
95  // Selection starts at the first para of the first cell, but we
96  // want to delete the table node before the first cell as well.
97  pNewPam->Start()->nNode = pNewPam->Start()->nNode.GetNode().FindTableNode()->GetIndex();
98  pNewPam->Start()->nContent.Assign(nullptr, 0);
99  pPam = pNewPam.get();
100  }
101  // delete everything
103  SaveTableBoxContent( pPam->GetPoint() );
104  }
105 
106  // Selection is not needed anymore
107  rPam.DeleteMark();
108 }
109 
111 {
112  SET_CURR_SHELL( this );
113  bool bRet = false;
115  {
116  StartAllAction();
117 
118  bool bUndo = GetCursor()->GetNext() != GetCursor();
119  if( bUndo ) // more than one selection?
120  {
121  SwRewriter aRewriter;
122  aRewriter.AddRule(UndoArg1, SwResId(STR_MULTISEL));
123 
125  }
126 
127  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
128  {
129  DeleteSel( rPaM, &bUndo );
130  }
131 
132  // If undo container then close here
133  if( bUndo )
134  {
136  }
137  EndAllAction();
138  bRet = true;
139  }
140  else
141  {
143  }
144 
145  return bRet;
146 }
147 
148 bool SwEditShell::Copy( SwEditShell* pDestShell )
149 {
150  if( !pDestShell )
151  pDestShell = this;
152 
153  SET_CURR_SHELL( pDestShell );
154 
155  // List of insert positions for smart insert of block selections
156  std::vector< std::shared_ptr<SwPosition> > aInsertList;
157 
158  // Fill list of insert positions
159  {
160  SwPosition * pPos = nullptr;
161  std::shared_ptr<SwPosition> pInsertPos;
162  sal_uInt16 nMove = 0;
163  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
164  {
165  if( !pPos )
166  {
167  if( pDestShell == this )
168  {
169  // First cursor represents the target position!!
170  rPaM.DeleteMark();
171  pPos = rPaM.GetPoint();
172  continue;
173  }
174  else
175  pPos = pDestShell->GetCursor()->GetPoint();
176  }
177  if( IsBlockMode() )
178  { // In block mode different insert positions will be calculated
179  // by simulated cursor movements from the given first insert position
180  if( nMove )
181  {
182  SwCursor aCursor( *pPos, nullptr);
183  if (aCursor.UpDown(false, nMove, nullptr, 0, *GetLayout()))
184  {
185  pInsertPos = std::make_shared<SwPosition>( *aCursor.GetPoint() );
186  aInsertList.push_back( pInsertPos );
187  }
188  }
189  else
190  pInsertPos = std::make_shared<SwPosition>( *pPos );
191  ++nMove;
192  }
193  SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
194  // Check if a selection would be copied into itself
195  if( pDestShell->GetDoc() == GetDoc() &&
196  *rPaM.Start() <= *pTmp && *pTmp < *rPaM.End() )
197  return false;
198  }
199  }
200 
201  pDestShell->StartAllAction();
202  SwPosition *pPos = nullptr;
203  bool bRet = false;
204  bool bFirstMove = true;
205  SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() );
206  sal_Int32 nSttCntIdx = 0;
207  // For block selection this list is filled with the insert positions
208  auto pNextInsert = aInsertList.begin();
209 
210  pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
211  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
212  {
213  if( !pPos )
214  {
215  if( pDestShell == this )
216  {
217  // First cursor represents the target position!!
218  rPaM.DeleteMark();
219  pPos = rPaM.GetPoint();
220  continue;
221  }
222  else
223  pPos = pDestShell->GetCursor()->GetPoint();
224  }
225  if( !bFirstMove )
226  {
227  if( pNextInsert != aInsertList.end() )
228  {
229  pPos = pNextInsert->get();
230  ++pNextInsert;
231  }
232  else if( IsBlockMode() )
233  GetDoc()->getIDocumentContentOperations().SplitNode( *pPos, false );
234  }
235 
236  // Only for a selection (non-text nodes have selection but Point/GetMark are equal)
237  if( !rPaM.HasMark() || *rPaM.GetPoint() == *rPaM.GetMark() )
238  continue;
239 
240  if( bFirstMove )
241  {
242  // Store start position of the new area
243  aSttNdIdx = pPos->nNode.GetIndex()-1;
244  nSttCntIdx = pPos->nContent.GetIndex();
245  bFirstMove = false;
246  }
247 
248  const bool bSuccess( GetDoc()->getIDocumentContentOperations().CopyRange(rPaM, *pPos, SwCopyFlags::CheckPosInFly) );
249  if (!bSuccess)
250  continue;
251 
252  SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
253  pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM);
254 
255  bRet = true;
256  }
257 
258  // Maybe nothing has been moved?
259  if( !bFirstMove )
260  {
261  SwPaM* pCursor = pDestShell->GetCursor();
262  pCursor->SetMark();
263  pCursor->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
264  pCursor->GetPoint()->nContent.Assign( pCursor->GetContentNode(),nSttCntIdx);
265  pCursor->Exchange();
266  }
267  else
268  {
269  // If the cursor moved during move process, move also its GetMark
270  pDestShell->GetCursor()->SetMark();
271  pDestShell->GetCursor()->DeleteMark();
272  }
273 #if OSL_DEBUG_LEVEL > 0
274  // check if the indices are registered in the correct nodes
275  {
276  for(SwPaM& rCmp : pDestShell->GetCursor()->GetRingContainer())
277  {
278  OSL_ENSURE( rCmp.GetPoint()->nContent.GetIdxReg()
279  == rCmp.GetContentNode(), "Point in wrong Node" );
280  OSL_ENSURE( rCmp.GetMark()->nContent.GetIdxReg()
281  == rCmp.GetContentNode(false), "Mark in wrong Node" );
282  }
283  }
284 #endif
285 
286  // close Undo container here
287  pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
288  pDestShell->EndAllAction();
289 
290  pDestShell->SaveTableBoxContent( pDestShell->GetCursor()->GetPoint() );
291 
292  return bRet;
293 }
294 
302 bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
303 {
304  SET_CURR_SHELL( this );
305 
306  bool bRet = false;
307  if( !HasReadonlySel() )
308  {
309  StartAllAction();
311 
312  for(SwPaM& rPaM : GetCursor()->GetRingContainer())
313  {
314  if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
315  {
316  bRet = sw::ReplaceImpl(rPaM, rNewStr, bRegExpRplc, *GetDoc(), GetLayout())
317  || bRet;
318  SaveTableBoxContent( rPaM.GetPoint() );
319  }
320  }
321 
322  // close Undo container here
324  EndAllAction();
325  }
326  return bRet;
327 }
328 
331 {
332  bool bRet = false;
333  if( !IsTableMode() )
334  {
335  SwPaM* pCursor = GetCursor();
336  // no multi selection
337  if( !pCursor->IsMultiSelection() && !HasReadonlySel() )
338  {
339  SET_CURR_SHELL( this );
340  StartAllAction();
341  bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( *pCursor );
342  EndAllAction();
343  }
344  }
345  return bRet;
346 }
347 
348 /* 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: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:330
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:188
void SaveTableBoxContent(const SwPosition *pPos=nullptr)
Definition: trvltbl.cxx:868
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:647
SAL_DLLPRIVATE void DeleteSel(SwPaM &rPam, bool *pUndo=nullptr)
Definition: eddel.cxx:33
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:2597
SwIndex nContent
Definition: pam.hxx:38
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: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:605
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
void MakeUniqueNumRules(const SwPaM &rPaM)
Definition: docnum.cxx:1236
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:644
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
#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:178
bool ReplaceImpl(SwPaM &rCursor, OUString const &rReplacement, bool const bRegExp, SwDoc &rDoc, SwRootFrame const *const pLayout)
Definition: findtxt.cxx:1030
bool HasReadonlySel() const
Definition: crsrsh.cxx:3328
const SwPosition * Start() const
Definition: pam.hxx:212
bool IsInProtectSect() const
Is node in a protected area?
Definition: node.cxx:409
bool Delete()
Delete content of all ranges.
Definition: eddel.cxx:110
bool UpDown(bool bUp, sal_uInt16 nCnt, Point const *pPt, long nUpDownX, SwRootFrame &rLayout)
Definition: swcrsr.cxx:1938
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:623
SwNodes & GetNodes()
Definition: doc.hxx:405
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:350
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:148
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:302
Base class of the Writer document model elements.
Definition: node.hxx:79
bool CursorInsideInputField() const
Definition: crstrvl.cxx:960