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