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