LibreOffice Module sw (master)  1
docsort.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 <hintids.hxx>
21 #include <rtl/math.hxx>
22 #include <osl/diagnose.h>
26 #include <editeng/unolingu.hxx>
27 #include <docary.hxx>
28 #include <fmtanchr.hxx>
29 #include <frmfmt.hxx>
30 #include <doc.hxx>
31 #include <IDocumentUndoRedo.hxx>
33 #include <IDocumentState.hxx>
34 #include <node.hxx>
35 #include <pam.hxx>
36 #include <ndtxt.hxx>
37 #include <swtable.hxx>
38 #include <swundo.hxx>
39 #include <sortopt.hxx>
40 #include <docsort.hxx>
41 #include <UndoSort.hxx>
42 #include <UndoRedline.hxx>
43 #include <hints.hxx>
44 #include <tblsel.hxx>
45 #include <cellatr.hxx>
46 #include <redline.hxx>
47 #include <node2lay.hxx>
48 #include <unochart.hxx>
49 
50 #include <set>
51 #include <utility>
52 
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star;
55 
57 SwDoc* SwSortElement::pDoc = nullptr;
58 const FlatFndBox* SwSortElement::pBox = nullptr;
60 lang::Locale* SwSortElement::pLocale = nullptr;
61 OUString* SwSortElement::pLastAlgorithm = nullptr;
63 
64 // List of all sorted elements
65 
66 typedef std::multiset<SwSortTextElement> SwSortTextElements;
67 typedef std::multiset<SwSortBoxElement> SwSortBoxElements;
68 
70 void SwSortElement::Init( SwDoc* pD, const SwSortOptions& rOpt,
71  FlatFndBox const * pFltBx )
72 {
73  OSL_ENSURE( !pDoc && !pOptions && !pBox, "Who forgot to call Finit?" );
74  pDoc = pD;
75  pOptions = new SwSortOptions( rOpt );
76  pBox = pFltBx;
77 
79  if ( nLang.anyOf(
82  nLang = GetAppLanguage();
83  pLocale = new lang::Locale( LanguageTag::convertToLocale( nLang ) );
84 
86 }
87 
89 {
90  delete pOptions;
91  pOptions = nullptr;
92  delete pLocale;
93  pLocale = nullptr;
94  delete pLastAlgorithm;
95  pLastAlgorithm = nullptr;
96  delete pSortCollator;
97  pSortCollator = nullptr;
98  delete pLclData;
99  pLclData = nullptr;
100  pDoc = nullptr;
101  pBox = nullptr;
102 }
103 
105 {
106 }
107 
108 double SwSortElement::StrToDouble( const OUString& rStr )
109 {
110  if( !pLclData )
112 
113  rtl_math_ConversionStatus eStatus;
114  sal_Int32 nEnd;
115  double nRet = pLclData->stringToDouble( rStr, true, &eStatus, &nEnd );
116 
117  if( rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0 )
118  nRet = 0.0;
119  return nRet;
120 }
121 
122 int SwSortElement::keycompare(const SwSortElement& rCmp, sal_uInt16 nKey) const
123 {
124  int nCmp = 0;
125  // The actual comparison
126  const SwSortElement *pOrig, *pCmp;
127 
128  const SwSortKey* pSrtKey = pOptions->aKeys[ nKey ].get();
129  if( pSrtKey->eSortOrder == SRT_ASCENDING )
130  {
131  pOrig = this;
132  pCmp = &rCmp;
133  }
134  else
135  {
136  pOrig = &rCmp;
137  pCmp = this;
138  }
139 
140  if( pSrtKey->bIsNumeric )
141  {
142  double n1 = pOrig->GetValue( nKey );
143  double n2 = pCmp->GetValue( nKey );
144 
145  nCmp = n1 < n2 ? -1 : n1 == n2 ? 0 : 1;
146  }
147  else
148  {
149  if( !pLastAlgorithm || *pLastAlgorithm != pSrtKey->sSortType )
150  {
151  if( pLastAlgorithm )
152  *pLastAlgorithm = pSrtKey->sSortType;
153  else
154  pLastAlgorithm = new OUString( pSrtKey->sSortType );
156  *pLocale,
158  }
159 
161  pOrig->GetKey( nKey ), pCmp->GetKey( nKey ));
162  }
163  return nCmp;
164 }
165 
167 {
168  // The actual comparison
169  for(size_t nKey = 0; nKey < pOptions->aKeys.size(); ++nKey)
170  {
171  int nCmp = keycompare(rCmp, nKey);
172 
173  if (nCmp == 0)
174  continue;
175 
176  return nCmp < 0;
177  }
178 
179  return false;
180 }
181 
182 double SwSortElement::GetValue( sal_uInt16 nKey ) const
183 {
184  return StrToDouble( GetKey( nKey ));
185 }
186 
189  : nOrg(rPos.GetIndex()), aPos(rPos)
190 {
191 }
192 
194 {
195 }
196 
197 OUString SwSortTextElement::GetKey(sal_uInt16 nId) const
198 {
199  SwTextNode* pTextNd = aPos.GetNode().GetTextNode();
200  if( !pTextNd )
201  return OUString();
202 
203  // for TextNodes
204  const OUString& rStr = pTextNd->GetText();
205 
206  sal_Unicode nDeli = pOptions->cDeli;
207  sal_uInt16 nDCount = pOptions->aKeys[nId]->nColumnId, i = 1;
208  sal_Int32 nStart = 0;
209 
210  // Find the delimiter
211  while( nStart != -1 && i < nDCount)
212  if( -1 != ( nStart = rStr.indexOf( nDeli, nStart ) ) )
213  {
214  nStart++;
215  i++;
216  }
217 
218  // Found next delimiter or end of String
219  // and copy
220  sal_Int32 nEnd = rStr.indexOf( nDeli, nStart+1 );
221  if (nEnd == -1)
222  return rStr.copy( nStart );
223  return rStr.copy( nStart, nEnd-nStart );
224 }
225 
228  : nRow( nRC )
229 {
230 }
231 
233 {
234 }
235 
237 OUString SwSortBoxElement::GetKey(sal_uInt16 nKey) const
238 {
239  const FndBox_* pFndBox;
240  sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
241 
242  if( SRT_ROWS == pOptions->eDirection )
243  pFndBox = pBox->GetBox(nCol, nRow); // Sort rows
244  else
245  pFndBox = pBox->GetBox(nRow, nCol); // Sort columns
246 
247  // Extract the Text
248  OUStringBuffer aRetStr;
249  if( pFndBox )
250  { // Get StartNode and skip it
251  const SwTableBox* pMyBox = pFndBox->GetBox();
252  OSL_ENSURE(pMyBox, "No atomic Box");
253 
254  if( pMyBox->GetSttNd() )
255  {
256  // Iterate over all the Box's TextNodes
257  const SwNode *pNd = nullptr, *pEndNd = pMyBox->GetSttNd()->EndOfSectionNode();
258  for( sal_uLong nIdx = pMyBox->GetSttIdx() + 1; pNd != pEndNd; ++nIdx )
259  if( ( pNd = pDoc->GetNodes()[ nIdx ])->IsTextNode() )
260  aRetStr.append(pNd->GetTextNode()->GetText());
261  }
262  }
263  return aRetStr.makeStringAndClear();
264 }
265 
266 double SwSortBoxElement::GetValue( sal_uInt16 nKey ) const
267 {
268  const FndBox_* pFndBox;
269  sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
270 
271  if( SRT_ROWS == pOptions->eDirection )
272  pFndBox = pBox->GetBox(nCol, nRow); // Sort rows
273  else
274  pFndBox = pBox->GetBox(nRow, nCol); // Sort columns
275 
276  double nVal;
277  if( pFndBox )
278  {
279  const SwFormat *pFormat = pFndBox->GetBox()->GetFrameFormat();
281  nVal = SwSortElement::GetValue( nKey );
282  else
283  nVal = pFormat->GetTableBoxValue().GetValue();
284  }
285  else
286  nVal = 0;
287 
288  return nVal;
289 }
290 
292 bool SwDoc::SortText(const SwPaM& rPaM, const SwSortOptions& rOpt)
293 {
294  // Check if Frame is in the Text
295  const SwPosition *pStart = rPaM.Start(), *pEnd = rPaM.End();
296 
297  // Set index to the Selection's start
298  for ( const auto *pFormat : *GetSpzFrameFormats() )
299  {
300  SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor();
301  SwPosition const*const pAPos = pAnchor->GetContentAnchor();
302 
303  if (pAPos && (RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) &&
304  pStart->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode )
305  return false;
306  }
307 
308  // Check if only TextNodes are within the Selection
309  {
310  sal_uLong nStart = pStart->nNode.GetIndex(),
311  nEnd = pEnd->nNode.GetIndex();
312  while( nStart <= nEnd )
313  // Iterate over a selected range
314  if( !GetNodes()[ nStart++ ]->IsTextNode() )
315  return false;
316  }
317 
318  bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
319  if( bUndo )
320  {
322  }
323 
324  SwPaM* pRedlPam = nullptr;
325  SwUndoRedlineSort* pRedlUndo = nullptr;
326  SwUndoSort* pUndoSort = nullptr;
327 
328  // To-Do - add 'SwExtraRedlineTable' also ?
329  if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
330  {
331  pRedlPam = new SwPaM( pStart->nNode, pEnd->nNode, -1, 1 );
332  SwContentNode* pCNd = pRedlPam->GetContentNode( false );
333  if( pCNd )
334  pRedlPam->GetMark()->nContent = pCNd->Len();
335 
337  {
338  if( bUndo )
339  {
340  pRedlUndo = new SwUndoRedlineSort( *pRedlPam,rOpt );
341  GetIDocumentUndoRedo().DoUndo(false);
342  }
343  // First copy the range
344  SwNodeIndex aEndIdx( pEnd->nNode, 1 );
345  SwNodeRange aRg( pStart->nNode, aEndIdx );
346  GetNodes().Copy_( aRg, aEndIdx );
347 
348  // range is new from pEnd->nNode+1 to aEndIdx
349  getIDocumentRedlineAccess().DeleteRedline( *pRedlPam, true, USHRT_MAX );
350 
351  pRedlPam->GetMark()->nNode.Assign( pEnd->nNode.GetNode(), 1 );
352  pCNd = pRedlPam->GetContentNode( false );
353  pRedlPam->GetMark()->nContent.Assign( pCNd, 0 );
354 
355  pRedlPam->GetPoint()->nNode.Assign( aEndIdx.GetNode() );
356  pCNd = pRedlPam->GetContentNode();
357  sal_Int32 nCLen = 0;
358  if( !pCNd &&
359  nullptr != (pCNd = GetNodes()[ aEndIdx.GetIndex()-1 ]->GetContentNode()))
360  {
361  nCLen = pCNd->Len();
362  pRedlPam->GetPoint()->nNode.Assign( *pCNd );
363  }
364  pRedlPam->GetPoint()->nContent.Assign( pCNd, nCLen );
365 
366  if( pRedlUndo )
367  pRedlUndo->SetValues( rPaM );
368  }
369  else
370  {
371  getIDocumentRedlineAccess().DeleteRedline( *pRedlPam, true, USHRT_MAX );
372  delete pRedlPam;
373  pRedlPam = nullptr;
374  }
375  }
376 
377  SwNodeIndex aStart(pStart->nNode);
378  SwSortElement::Init( this, rOpt );
379  SwSortTextElements aSortSet;
380  while( aStart <= pEnd->nNode )
381  {
382  // Iterate over a selected range
383  aSortSet.insert(SwSortTextElement(aStart));
384  ++aStart;
385  }
386 
387  // Now comes the tricky part: Move Nodes (and always keep Undo in mind)
388  sal_uLong nBeg = pStart->nNode.GetIndex();
389  SwNodeRange aRg( aStart, aStart );
390 
391  if( bUndo && !pRedlUndo )
392  {
393  pUndoSort = new SwUndoSort(rPaM, rOpt);
394  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndoSort));
395  }
396 
397  GetIDocumentUndoRedo().DoUndo(false);
398 
399  size_t n = 0;
400  for (const auto& rElem : aSortSet)
401  {
402  aStart = nBeg + n;
403  aRg.aStart = rElem.aPos.GetIndex();
404  aRg.aEnd = aRg.aStart.GetIndex() + 1;
405 
406  // Move Nodes
409 
410  // Insert Move in Undo
411  if(pUndoSort)
412  {
413  pUndoSort->Insert(rElem.nOrg, nBeg + n);
414  }
415  ++n;
416  }
417  // Delete all elements from the SortArray
418  aSortSet.clear();
420 
421  if( pRedlPam )
422  {
423  if( pRedlUndo )
424  {
425  pRedlUndo->SetSaveRange( *pRedlPam );
426  // UGLY: temp. enable Undo
428  GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pRedlUndo) );
429  GetIDocumentUndoRedo().DoUndo(false);
430  }
431 
432  // nBeg is start of sorted range
433  SwNodeIndex aSttIdx( GetNodes(), nBeg );
434 
435  // the copied range is deleted
436  SwRangeRedline *const pDeleteRedline(
438 
439  // pRedlPam points to nodes that may be deleted (hidden) by
440  // AppendRedline, so adjust it beforehand to prevent ASSERT
441  pRedlPam->GetPoint()->nNode = aSttIdx;
442  SwContentNode* pCNd = aSttIdx.GetNode().GetContentNode();
443  pRedlPam->GetPoint()->nContent.Assign( pCNd, 0 );
444 
445  getIDocumentRedlineAccess().AppendRedline(pDeleteRedline, true);
446 
447  // the sorted range is inserted
449 
450  if( pRedlUndo )
451  {
452  SwNodeIndex aInsEndIdx( pRedlPam->GetMark()->nNode, -1 );
453  pRedlPam->GetMark()->nNode = aInsEndIdx;
454  SwContentNode *const pPrevNode =
455  pRedlPam->GetMark()->nNode.GetNode().GetContentNode();
456  pRedlPam->GetMark()->nContent.Assign( pPrevNode, pPrevNode->Len() );
457 
458  pRedlUndo->SetValues( *pRedlPam );
459  }
460 
461  delete pRedlPam;
462  pRedlPam = nullptr;
463  }
464  GetIDocumentUndoRedo().DoUndo( bUndo );
465  if( bUndo )
466  {
468  }
469 
470  return true;
471 }
472 
474 bool SwDoc::SortTable(const SwSelBoxes& rBoxes, const SwSortOptions& rOpt)
475 {
476  // Via SwDoc for Undo!
477  OSL_ENSURE( !rBoxes.empty(), "no valid Box list" );
478  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
479  if( !pTableNd )
480  return false;
481 
482  // We begin sorting
483  // Find all Boxes/Lines
484  FndBox_ aFndBox( nullptr, nullptr );
485  {
486  FndPara aPara( rBoxes, &aFndBox );
487  ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
488  }
489 
490  if(aFndBox.GetLines().empty())
491  return false;
492 
494  getIDocumentRedlineAccess().DeleteRedline( *pTableNd, true, USHRT_MAX );
495 
496  FndLines_t::size_type nStart = 0;
497  if( pTableNd->GetTable().GetRowsToRepeat() > 0 && rOpt.eDirection == SRT_ROWS )
498  {
499  // Uppermost selected Cell
500  FndLines_t& rLines = aFndBox.GetLines();
501 
502  while( nStart < rLines.size() )
503  {
504  // Respect Split Merge nesting,
505  // extract the upper most
506  SwTableLine* pLine = rLines[nStart]->GetLine();
507  while ( pLine->GetUpper() )
508  pLine = pLine->GetUpper()->GetUpper();
509 
510  if( pTableNd->GetTable().IsHeadline( *pLine ) )
511  nStart++;
512  else
513  break;
514  }
515  // Are all selected in the HeaderLine? -> no Offset
516  if( nStart == rLines.size() )
517  nStart = 0;
518  }
519 
520  // Switch to relative Formulas
521  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
522  aMsgHint.m_eFlags = TBL_RELBOXNAME;
524 
525  // Table as a flat array structure
526  FlatFndBox aFlatBox(this, aFndBox);
527 
528  if(!aFlatBox.IsSymmetric())
529  return false;
530 
531  // Delete HTML layout
532  pTableNd->GetTable().SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
533 
534  // #i37739# A simple 'MakeFrames' after the node sorting
535  // does not work if the table is inside a frame and has no prev/next.
536  SwNode2LayoutSaveUpperFrames aNode2Layout(*pTableNd);
537 
538  // Delete the Table's Frames
539  pTableNd->DelFrames();
540  // ? TL_CHART2: ?
541 
542  SwUndoSort* pUndoSort = nullptr;
543  if (GetIDocumentUndoRedo().DoesUndo())
544  {
545  pUndoSort = new SwUndoSort( rBoxes[0]->GetSttIdx(),
546  rBoxes.back()->GetSttIdx(),
547  *pTableNd, rOpt, aFlatBox.HasItemSets() );
548  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndoSort));
549  }
550  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
551 
552  // Insert KeyElements
553  sal_uInt16 nCount = (rOpt.eDirection == SRT_ROWS) ?
554  aFlatBox.GetRows() : aFlatBox.GetCols();
555 
556  // Sort SortList by Key
557  SwSortElement::Init( this, rOpt, &aFlatBox );
558  SwSortBoxElements aSortList;
559 
560  // When sorting, do not include the first row if the HeaderLine is repeated
561  for( sal_uInt16 i = static_cast<sal_uInt16>(nStart); i < nCount; ++i)
562  {
563  aSortList.insert(SwSortBoxElement(i));
564  }
565 
566  // Move after Sorting
567  SwMovedBoxes aMovedList;
568  sal_uInt16 i = 0;
569  for (const auto& rElem : aSortList)
570  {
571  if(rOpt.eDirection == SRT_ROWS)
572  {
573  MoveRow(this, aFlatBox, rElem.nRow, i+nStart, aMovedList, pUndoSort);
574  }
575  else
576  {
577  MoveCol(this, aFlatBox, rElem.nRow, i+nStart, aMovedList, pUndoSort);
578  }
579  ++i;
580  }
581 
582  // Restore table frames:
583  // #i37739# A simple 'MakeFrames' after the node sorting
584  // does not work if the table is inside a frame and has no prev/next.
585  const sal_uLong nIdx = pTableNd->GetIndex();
586  aNode2Layout.RestoreUpperFrames( GetNodes(), nIdx, nIdx + 1 );
587 
588  // TL_CHART2: need to inform chart of probably changed cell names
589  UpdateCharts( pTableNd->GetTable().GetFrameFormat()->GetName() );
590 
591  // Delete all Elements in the SortArray
592  aSortList.clear();
594 
596  return true;
597 }
598 
600 void MoveRow(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
601  SwMovedBoxes& rMovedList, SwUndoSort* pUD)
602 {
603  for( sal_uInt16 i=0; i < rBox.GetCols(); ++i )
604  { // Get old cell position and remember it
605  const FndBox_* pSource = rBox.GetBox(i, nS);
606 
607  // new cell position
608  const FndBox_* pTarget = rBox.GetBox(i, nT);
609 
610  const SwTableBox* pT = pTarget->GetBox();
611  const SwTableBox* pS = pSource->GetBox();
612 
613  bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
614 
615  // and move it
616  MoveCell(pDoc, pS, pT, bMoved, pUD);
617 
618  rMovedList.push_back(pS);
619 
620  if( pS != pT )
621  {
622  SwFrameFormat* pTFormat = pT->GetFrameFormat();
623  const SfxItemSet* pSSet = rBox.GetItemSet( i, nS );
624 
625  if( pSSet ||
626  SfxItemState::SET == pTFormat->GetItemState( RES_BOXATR_FORMAT ) ||
627  SfxItemState::SET == pTFormat->GetItemState( RES_BOXATR_FORMULA ) ||
628  SfxItemState::SET == pTFormat->GetItemState( RES_BOXATR_VALUE ) )
629  {
630  pTFormat = const_cast<SwTableBox*>(pT)->ClaimFrameFormat();
631  pTFormat->LockModify();
633  pTFormat->ResetFormatAttr( RES_VERT_ORIENT );
634 
635  if( pSSet )
636  pTFormat->SetFormatAttr( *pSSet );
637  pTFormat->UnlockModify();
638  }
639  }
640  }
641 }
642 
644 void MoveCol(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
645  SwMovedBoxes& rMovedList, SwUndoSort* pUD)
646 {
647  for(sal_uInt16 i=0; i < rBox.GetRows(); ++i)
648  { // Get old cell position and remember it
649  const FndBox_* pSource = rBox.GetBox(nS, i);
650 
651  // new cell position
652  const FndBox_* pTarget = rBox.GetBox(nT, i);
653 
654  // and move it
655  const SwTableBox* pT = pTarget->GetBox();
656  const SwTableBox* pS = pSource->GetBox();
657 
658  // and move it
659  bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
660  MoveCell(pDoc, pS, pT, bMoved, pUD);
661 
662  rMovedList.push_back(pS);
663 
664  if( pS != pT )
665  {
666  SwFrameFormat* pTFormat = pT->GetFrameFormat();
667  const SfxItemSet* pSSet = rBox.GetItemSet( nS, i );
668 
669  if( pSSet ||
670  SfxItemState::SET == pTFormat->GetItemState( RES_BOXATR_FORMAT ) ||
671  SfxItemState::SET == pTFormat->GetItemState( RES_BOXATR_FORMULA ) ||
672  SfxItemState::SET == pTFormat->GetItemState( RES_BOXATR_VALUE ) )
673  {
674  pTFormat = const_cast<SwTableBox*>(pT)->ClaimFrameFormat();
675  pTFormat->LockModify();
677  pTFormat->ResetFormatAttr( RES_VERT_ORIENT );
678 
679  if( pSSet )
680  pTFormat->SetFormatAttr( *pSSet );
681  pTFormat->UnlockModify();
682  }
683  }
684  }
685 }
686 
688 void MoveCell(SwDoc* pDoc, const SwTableBox* pSource, const SwTableBox* pTar,
689  bool bMovedBefore, SwUndoSort* pUD)
690 {
691  OSL_ENSURE(pSource && pTar,"Source or target missing");
692 
693  if(pSource == pTar)
694  return;
695 
696  if(pUD)
697  pUD->Insert( pSource->GetName(), pTar->GetName() );
698 
699  // Set Pam source to the first ContentNode
700  SwNodeRange aRg( *pSource->GetSttNd(), 0, *pSource->GetSttNd() );
701  SwNode* pNd = pDoc->GetNodes().GoNext( &aRg.aStart );
702 
703  // If the Cell (Source) wasn't moved
704  // -> insert an empty Node and move the rest or the Mark
705  // points to the first ContentNode
706  if( pNd->StartOfSectionNode() == pSource->GetSttNd() )
707  pNd = pDoc->GetNodes().MakeTextNode( aRg.aStart,
708  pDoc->GetDfltTextFormatColl() );
709  aRg.aEnd = *pNd->EndOfSectionNode();
710 
711  // If the Target is empty (there is one empty Node)
712  // -> move and delete it
713  SwNodeIndex aTar( *pTar->GetSttNd() );
714  pNd = pDoc->GetNodes().GoNext( &aTar ); // next ContentNode
715  sal_uLong nCount = pNd->EndOfSectionIndex() - pNd->StartOfSectionIndex();
716 
717  bool bDelFirst = false;
718  if( nCount == 2 )
719  {
720  OSL_ENSURE( pNd->GetContentNode(), "No ContentNode");
721  bDelFirst = !pNd->GetContentNode()->Len() && bMovedBefore;
722  }
723 
724  if(!bDelFirst)
725  { // We already have Content -> old Content Section Down
726  SwNodeRange aRgTar( aTar.GetNode(), 0, *pNd->EndOfSectionNode() );
727  pDoc->GetNodes().SectionDown( &aRgTar );
728  }
729 
730  // Insert the Source
731  SwNodeIndex aIns( *pTar->GetSttNd()->EndOfSectionNode() );
732  pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, aIns,
734 
735  // If first Node is empty -> delete it
736  if(bDelFirst)
737  pDoc->GetNodes().Delete( aTar );
738 }
739 
741 FlatFndBox::FlatFndBox(SwDoc* pDocPtr, const FndBox_& rBoxRef) :
742  pDoc(pDocPtr),
743  nRow(0),
744  nCol(0)
745 { // If the array is symmetric
746  bSym = CheckLineSymmetry(rBoxRef);
747  if( bSym )
748  {
749  // Determine column/row count
750  nCols = GetColCount(rBoxRef);
751  nRows = GetRowCount(rBoxRef);
752 
753  // Create linear array
754  size_t nCount = static_cast<size_t>(nRows) * nCols;
755  pArr = std::make_unique<FndBox_ const *[]>(nCount);
756  memset(pArr.get(), 0, sizeof(const FndBox_*) * nCount);
757 
758  FillFlat( rBoxRef );
759  }
760 }
761 
763 {
764 }
765 
768 {
769  const FndLines_t &rLines = rBox.GetLines();
770  FndBoxes_t::size_type nBoxes {0};
771 
772  for (FndLines_t::size_type i=0; i < rLines.size(); ++i)
773  {
774  const FndLine_* pLn = rLines[i].get();
775  const FndBoxes_t& rBoxes = pLn->GetBoxes();
776 
777  // Number of Boxes of all Lines is unequal -> no symmetry
778  if( i && nBoxes != rBoxes.size())
779  return false;
780 
781  nBoxes = rBoxes.size();
782  if( !CheckBoxSymmetry( *pLn ) )
783  return false;
784  }
785  return true;
786 }
787 
790 {
791  const FndBoxes_t &rBoxes = rLn.GetBoxes();
792  FndLines_t::size_type nLines {0};
793 
794  for (FndBoxes_t::size_type i = 0; i < rBoxes.size(); ++i)
795  {
796  FndBox_ const*const pBox = rBoxes[i].get();
797  const FndLines_t& rLines = pBox->GetLines();
798 
799  // Number of Lines of all Boxes is unequal -> no symmetry
800  if( i && nLines != rLines.size() )
801  return false;
802 
803  nLines = rLines.size();
804  if( nLines && !CheckLineSymmetry( *pBox ) )
805  return false;
806  }
807  return true;
808 }
809 
811 sal_uInt16 FlatFndBox::GetColCount(const FndBox_& rBox)
812 {
813  const FndLines_t& rLines = rBox.GetLines();
814  // Iterate over Lines
815  if( rLines.empty() )
816  return 1;
817 
818  sal_uInt16 nSum = 0;
819  for (const auto & pLine : rLines)
820  {
821  // The Boxes of a Line
822  sal_uInt16 nCount = 0;
823  const FndBoxes_t& rBoxes = pLine->GetBoxes();
824  for (const auto &rpB : rBoxes)
825  { // Iterate recursively over the Lines
826  nCount += rpB->GetLines().empty() ? 1 : GetColCount(*rpB);
827  }
828 
829  if( nSum < nCount )
830  nSum = nCount;
831  }
832  return nSum;
833 }
834 
836 sal_uInt16 FlatFndBox::GetRowCount(const FndBox_& rBox)
837 {
838  const FndLines_t& rLines = rBox.GetLines();
839  if( rLines.empty() )
840  return 1;
841 
842  sal_uInt16 nLines = 0;
843  for (const auto & pLine : rLines)
844  { // The Boxes of a Line
845  const FndBoxes_t& rBoxes = pLine->GetBoxes();
846  sal_uInt16 nLn = 1;
847  for (const auto &rpB : rBoxes)
848  {
849  if (!rpB->GetLines().empty())
850  { // Iterate recursively over the Lines
851  nLn = std::max(GetRowCount(*rpB), nLn);
852  }
853  }
854 
855  nLines = nLines + nLn;
856  }
857  return nLines;
858 }
859 
861 void FlatFndBox::FillFlat(const FndBox_& rBox, bool bLastBox)
862 {
863  bool bModRow = false;
864  const FndLines_t& rLines = rBox.GetLines();
865 
866  // Iterate over Lines
867  sal_uInt16 nOldRow = nRow;
868  for (const auto & pLine : rLines)
869  {
870  // The Boxes of a Line
871  const FndBoxes_t& rBoxes = pLine->GetBoxes();
872  sal_uInt16 nOldCol = nCol;
873  for( FndBoxes_t::size_type j = 0; j < rBoxes.size(); ++j )
874  {
875  // Check the Box if it's an atomic one
876  const FndBox_ *const pBox = rBoxes[j].get();
877 
878  if( pBox->GetLines().empty() )
879  {
880  // save it
881  sal_uInt16 nOff = nRow * nCols + nCol;
882  pArr[nOff] = pBox;
883 
884  // Save the Formula/Format/Value values
885  const SwFrameFormat* pFormat = pBox->GetBox()->GetFrameFormat();
886  if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMAT ) ||
887  SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA ) ||
888  SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE ) )
889  {
890  auto pSet = std::make_unique<SfxItemSet>(
891  pDoc->GetAttrPool(),
892  svl::Items<
895  pSet->Put( pFormat->GetAttrSet() );
896  if( ppItemSets.empty() )
897  {
898  size_t nCount = static_cast<size_t>(nRows) * nCols;
899  ppItemSets.resize(nCount);
900  }
901  ppItemSets[nOff] = std::move(pSet);
902  }
903 
904  bModRow = true;
905  }
906  else
907  {
908  // Iterate recursively over the Lines of a Box
909  FillFlat( *pBox, ( j+1 == rBoxes.size() ) );
910  }
911  nCol++;
912  }
913  if(bModRow)
914  nRow++;
915  nCol = nOldCol;
916  }
917  if(!bLastBox)
918  nRow = nOldRow;
919 }
920 
922 const FndBox_* FlatFndBox::GetBox(sal_uInt16 n_Col, sal_uInt16 n_Row) const
923 {
924  sal_uInt16 nOff = n_Row * nCols + n_Col;
925  const FndBox_* pTmp = pArr[nOff];
926 
927  OSL_ENSURE(n_Col < nCols && n_Row < nRows && pTmp, "invalid array access");
928  return pTmp;
929 }
930 
931 const SfxItemSet* FlatFndBox::GetItemSet(sal_uInt16 n_Col, sal_uInt16 n_Row) const
932 {
933  OSL_ENSURE( ppItemSets.empty() || ( n_Col < nCols && n_Row < nRows), "invalid array access");
934 
935  return !ppItemSets.empty() ? ppItemSets[unsigned(n_Row * nCols) + n_Col].get() : nullptr;
936 }
937 
938 sal_uInt16 SwMovedBoxes::GetPos(const SwTableBox* pTableBox) const
939 {
940  std::vector<const SwTableBox*>::const_iterator it = std::find(mBoxes.begin(), mBoxes.end(), pTableBox);
941  return it == mBoxes.end() ? USHRT_MAX : it - mBoxes.begin();
942 }
943 
944 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwSortTextElement(const SwNodeIndex &rPos)
SortingElement for Text.
Definition: docsort.cxx:188
const SwTableBoxNumFormat & GetTableBoxNumFormat(bool=true) const
TableBox attributes - implemented in cellatr.hxx.
Definition: cellatr.hxx:105
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
const FndLines_t & GetLines() const
Definition: tblsel.hxx:173
#define LANGUAGE_NONE
virtual sal_Int32 Len() const
Definition: node.cxx:1183
std::vector< std::unique_ptr< SfxItemSet > > ppItemSets
Definition: docsort.hxx:148
static double StrToDouble(const OUString &rStr)
Definition: docsort.cxx:108
const Value & back() const
sal_uInt16 nRows
Definition: docsort.hxx:150
Marks a position in the document model.
Definition: pam.hxx:35
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
bool HasItemSets() const
Definition: docsort.hxx:158
SwSortDirection eDirection
Definition: sortopt.hxx:50
void loadCollatorAlgorithm(const OUString &rAlgorithm, const css::lang::Locale &rLocale, sal_Int32 nOption)
const OUString & GetText() const
Definition: ndtxt.hxx:211
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1880
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1399
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
SwNodeIndex nNode
Definition: pam.hxx:37
sal_Unicode cDeli
Definition: sortopt.hxx:51
SwNodeIndex aPos
Definition: docsort.hxx:103
void MoveCell(SwDoc *pDoc, const SwTableBox *pSource, const SwTableBox *pTar, bool bMovedBefore, SwUndoSort *pUD)
Move a single Cell.
Definition: docsort.cxx:688
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
static void Finit()
Definition: docsort.cxx:88
bool IsSymmetric() const
Definition: docsort.hxx:130
const SwPosition * GetMark() const
Definition: pam.hxx:209
virtual OUString GetKey(sal_uInt16 nKey) const =0
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
Definition: doc.hxx:185
std::vector< std::unique_ptr< SwSortKey > > aKeys
Definition: sortopt.hxx:49
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
SwNode & GetNode() const
Definition: ndindex.hxx:118
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:176
double GetValue() const
Definition: cellatr.hxx:95
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, sal_uInt16 nDelType)=0
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:347
void Copy_(const SwNodeRange &rRg, const SwNodeIndex &rInsPos, bool bNewFrames=true) const
Definition: ndarr.hxx:177
double stringToDouble(const OUString &rString, bool bUseGroupSep, rtl_math_ConversionStatus *pStatus, sal_Int32 *pParseEnd) const
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:738
SwDoc * pDoc
Definition: docsort.hxx:146
FlatFndBox(SwDoc *pDocPtr, const FndBox_ &rBox)
Generate two-dimensional array of FndBoxes.
Definition: docsort.cxx:741
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
Definition: tblsel.cxx:2092
static SwSortOptions * pOptions
Definition: docsort.hxx:70
static LanguageType nLang
Definition: srtdlg.cxx:58
sal_uInt16 GetRowCount(const FndBox_ &rBox)
Maximum count of Rows (Lines)
Definition: docsort.cxx:836
sal_uInt16 nCol
Definition: docsort.hxx:153
void SetValues(const SwPaM &rPam)
Definition: undobj.cxx:56
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
sal_uInt16 GetPos(const SwTableBox *pTableBox) const
Definition: docsort.cxx:938
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:389
void Delete(const SwNodeIndex &rPos, sal_uLong nNodes=1)
delete nodes
Definition: nodes.cxx:1063
sal_uInt16 sal_Unicode
SwIndex nContent
Definition: pam.hxx:38
bool empty() const
Definition: docary.hxx:369
SwNodeIndex aStart
Definition: ndindex.hxx:131
static LocaleDataWrapper * pLclData
Definition: docsort.hxx:76
virtual OUString GetKey(sal_uInt16 nKey) const override
Definition: docsort.cxx:197
const SwTextFormatColl * GetDfltTextFormatColl() const
Definition: doc.hxx:771
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
virtual void UpdateTableFields(SfxPoolItem *pHt)=0
virtual void DoUndo(bool const bDoUndo)=0
Enable/Disable Undo.
const FndBoxes_t & GetBoxes() const
Definition: tblsel.hxx:203
void UpdateCharts(const OUString &rName) const
Definition: docchart.cxx:131
void push_back(const SwTableBox *&rpTableBox)
Definition: docsort.hxx:54
const RedlineType_t REDLINE_DELETE
std::unique_ptr< FndBox_ const *[]> pArr
Definition: docsort.hxx:147
void Insert(const OUString &rOrgPos, const OUString &rNewPos)
Definition: unsort.cxx:244
virtual bool DoesUndo() const =0
Is Undo enabled?
void FillFlat(const FndBox_ &, bool bLastBox=false)
Create a linear array of atomic FndBoxes.
Definition: docsort.cxx:861
bool bIgnoreCase
Definition: sortopt.hxx:54
std::vector< const SwTableBox * > mBoxes
Definition: docsort.hxx:51
bool CheckBoxSymmetry(const FndLine_ &rLn)
Check Box for symmetry (All Boxes of a Line need to have same number of Lines)
Definition: docsort.cxx:789
Base class for various Writer styles.
Definition: format.hxx:43
const FndBox_ * GetBox(sal_uInt16 nCol, sal_uInt16 nRow) const
Access a specific Cell.
Definition: docsort.cxx:922
bool SortText(const SwPaM &, const SwSortOptions &)
Sort Text in the Document.
Definition: docsort.cxx:292
sal_uInt16 nRow
Definition: docsort.hxx:152
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
OUString GetName() const
Definition: swtable.cxx:1828
virtual void AppendUndo(std::unique_ptr< SwUndo > pUndo)=0
Add new Undo action.
Style of a layout element.
Definition: frmfmt.hxx:57
void SetSaveRange(const SwPaM &rRange)
Definition: unredln.cxx:346
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
void SectionDown(SwNodeRange *pRange, SwStartNodeType=SwNormalStartNode)
create a start/end section pair
Definition: nodes.cxx:894
static css::lang::Locale * pLocale
Definition: docsort.hxx:74
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
virtual double GetValue(sal_uInt16 nKey) const
Definition: docsort.cxx:182
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
#define RES_VERT_ORIENT
Definition: hintids.hxx:207
virtual OUString GetKey(sal_uInt16 nKey) const override
Get Key for a cell.
Definition: docsort.cxx:237
virtual double GetValue(sal_uInt16 nKey) const override
Definition: docsort.cxx:266
bool IsTextFormat(sal_uInt32 nFIndex) const
int i
static bool IsShowOriginal(const RedlineFlags eM)
SwContentNode * GetContentNode()
Definition: node.hxx:615
FlyAnchors.
Definition: fmtanchr.hxx:34
sal_uInt16 GetCols() const
Definition: docsort.hxx:132
void MoveRow(SwDoc *pDoc, const FlatFndBox &rBox, sal_uInt16 nS, sal_uInt16 nT, SwMovedBoxes &rMovedList, SwUndoSort *pUD)
Move a row.
Definition: docsort.cxx:600
void UnlockModify()
Definition: calbck.hxx:217
static void Init(SwDoc *, const SwSortOptions &rOpt, FlatFndBox const *=nullptr)
Construct a SortElement for the Sort.
Definition: docsort.cxx:70
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:426
void LockModify()
Definition: calbck.hxx:216
#define LANGUAGE_DONTKNOW
static CollatorWrapper * pSortCollator
Definition: docsort.hxx:73
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:398
Marks a node in the document model.
Definition: ndindex.hxx:31
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:425
static SwDoc * pDoc
Definition: docsort.hxx:71
std::multiset< SwSortBoxElement > SwSortBoxElements
Definition: docsort.cxx:67
#define RES_BOXATR_VALUE
Definition: hintids.hxx:263
bool empty() const
virtual bool MoveNodeRange(SwNodeRange &, SwNodeIndex &, SwMoveFlags)=0
SwSortOrder eSortOrder
Definition: sortopt.hxx:36
bool operator<(const SwSortElement &) const
Definition: docsort.cxx:166
const SwPosition * Start() const
Definition: pam.hxx:212
virtual bool IsIgnoreRedline() const =0
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:460
bool bSym
Definition: docsort.hxx:155
void RestoreUpperFrames(SwNodes &rNds, sal_uLong nStt, sal_uLong nEnd)
Definition: node2lay.cxx:439
const SwTableBoxValue & GetTableBoxValue(bool=true) const
Definition: cellatr.hxx:109
virtual ~SwSortBoxElement() override
Definition: docsort.cxx:232
const RedlineType_t REDLINE_INSERT
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
OUString sSortType
Definition: sortopt.hxx:35
sal_uInt16 const nRow
Definition: docsort.hxx:114
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:652
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:367
std::vector< std::unique_ptr< FndBox_ > > FndBoxes_t
Definition: tblsel.hxx:152
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:439
sal_uInt16 GetColCount(const FndBox_ &rBox)
Maximum count of Columns (Boxes)
Definition: docsort.cxx:811
bool CheckLineSymmetry(const FndBox_ &rBox)
All Lines of a Box need to have same number of Boxes.
Definition: docsort.cxx:767
sal_uInt16 nCols
Definition: docsort.hxx:151
std::multiset< SwSortTextElement > SwSortTextElements
Definition: docsort.cxx:66
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:259
const SwTableBox * GetBox() const
Definition: tblsel.hxx:175
const SfxItemSet * GetItemSet(sal_uInt16 nCol, sal_uInt16 nRow) const
Definition: docsort.cxx:931
LanguageType GetAppLanguage()
Definition: init.cxx:760
void MoveCol(SwDoc *pDoc, const FlatFndBox &rBox, sal_uInt16 nS, sal_uInt16 nT, SwMovedBoxes &rMovedList, SwUndoSort *pUD)
Move a column.
Definition: docsort.cxx:644
SwNodes & GetNodes()
Definition: doc.hxx:403
const SwPosition * End() const
Definition: pam.hxx:217
SwNodeIndex aEnd
Definition: ndindex.hxx:132
static const FlatFndBox * pBox
Definition: docsort.hxx:72
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
virtual ~SwSortTextElement() override
Definition: docsort.cxx:193
Reference< XComponentContext > getProcessComponentContext()
std::vector< std::unique_ptr< FndLine_ > > FndLines_t
Definition: tblsel.hxx:155
SwTableBox * GetUpper()
Definition: swtable.hxx:362
LanguageType nLanguage
Definition: sortopt.hxx:52
sal_uInt32 GetValue() const
virtual ~SwSortElement()
Definition: docsort.cxx:104
bool SortTable(const SwSelBoxes &rBoxes, const SwSortOptions &)
Sort Table in the Document.
Definition: docsort.cxx:474
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
TableFormulaUpdateFlags m_eFlags
Definition: hints.hxx:208
virtual const SwRedlineTable & GetRedlineTable() const =0
sal_uInt16 GetRows() const
Definition: docsort.hxx:131
SwTableLine * GetUpper()
Definition: swtable.hxx:421
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1273
#define SW_COLLATOR_IGNORES
Definition: swtypes.hxx:193
int keycompare(const SwSortElement &rCmp, sal_uInt16 nKey) const
Definition: docsort.cxx:122
bool bIsNumeric
Definition: sortopt.hxx:38
#define RES_BOXATR_FORMAT
Definition: hintids.hxx:261
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1307
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
bool anyOf(strong_int v) const
static OUString * pLastAlgorithm
Definition: docsort.hxx:75
SwSortBoxElement(sal_uInt16 nRC)
SortingElement for Tables.
Definition: docsort.cxx:227
SwTextNode * MakeTextNode(const SwNodeIndex &rWhere, SwTextFormatColl *pColl, bool bNewFrames=true)
Implementations of "Make...Node" are in the given .cxx-files.
Definition: ndtxt.cxx:114
#define RES_BOXATR_FORMULA
Definition: hintids.hxx:262
SwNodeIndex & Assign(SwNodes const &rNds, sal_uLong)
Definition: ndindex.hxx:271
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
Base class of the Writer document model elements.
Definition: node.hxx:79