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 
47 #include <set>
48 #include <utility>
49 
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star;
52 
54 SwDoc* SwSortElement::pDoc = nullptr;
55 const FlatFndBox* SwSortElement::pBox = nullptr;
57 lang::Locale* SwSortElement::pLocale = nullptr;
58 OUString* SwSortElement::pLastAlgorithm = nullptr;
60 
61 // List of all sorted elements
62 
63 typedef std::multiset<SwSortTextElement> SwSortTextElements;
64 typedef std::multiset<SwSortBoxElement> SwSortBoxElements;
65 
67 void SwSortElement::Init( SwDoc* pD, const SwSortOptions& rOpt,
68  FlatFndBox const * pFltBx )
69 {
70  OSL_ENSURE( !pDoc && !pOptions && !pBox, "Who forgot to call Finit?" );
71  pDoc = pD;
72  pOptions = new SwSortOptions( rOpt );
73  pBox = pFltBx;
74 
76  if ( nLang.anyOf(
79  nLang = GetAppLanguage();
80  pLocale = new lang::Locale( LanguageTag::convertToLocale( nLang ) );
81 
83 }
84 
86 {
87  delete pOptions;
88  pOptions = nullptr;
89  delete pLocale;
90  pLocale = nullptr;
91  delete pLastAlgorithm;
92  pLastAlgorithm = nullptr;
93  delete pSortCollator;
94  pSortCollator = nullptr;
95  delete pLclData;
96  pLclData = nullptr;
97  pDoc = nullptr;
98  pBox = nullptr;
99 }
100 
102 {
103 }
104 
105 double SwSortElement::StrToDouble( const OUString& rStr )
106 {
107  if( !pLclData )
109 
110  rtl_math_ConversionStatus eStatus;
111  sal_Int32 nEnd;
112  double nRet = pLclData->stringToDouble( rStr, true, &eStatus, &nEnd );
113 
114  if( rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0 )
115  nRet = 0.0;
116  return nRet;
117 }
118 
119 int SwSortElement::keycompare(const SwSortElement& rCmp, sal_uInt16 nKey) const
120 {
121  int nCmp = 0;
122  // The actual comparison
123  const SwSortElement *pOrig, *pCmp;
124 
125  const SwSortKey* pSrtKey = pOptions->aKeys[ nKey ].get();
126  if( pSrtKey->eSortOrder == SRT_ASCENDING )
127  {
128  pOrig = this;
129  pCmp = &rCmp;
130  }
131  else
132  {
133  pOrig = &rCmp;
134  pCmp = this;
135  }
136 
137  if( pSrtKey->bIsNumeric )
138  {
139  double n1 = pOrig->GetValue( nKey );
140  double n2 = pCmp->GetValue( nKey );
141 
142  nCmp = n1 < n2 ? -1 : n1 == n2 ? 0 : 1;
143  }
144  else
145  {
146  if( !pLastAlgorithm || *pLastAlgorithm != pSrtKey->sSortType )
147  {
148  if( pLastAlgorithm )
149  *pLastAlgorithm = pSrtKey->sSortType;
150  else
151  pLastAlgorithm = new OUString( pSrtKey->sSortType );
153  *pLocale,
155  }
156 
158  pOrig->GetKey( nKey ), pCmp->GetKey( nKey ));
159  }
160  return nCmp;
161 }
162 
164 {
165  // The actual comparison
166  for(size_t nKey = 0; nKey < pOptions->aKeys.size(); ++nKey)
167  {
168  int nCmp = keycompare(rCmp, nKey);
169 
170  if (nCmp == 0)
171  continue;
172 
173  return nCmp < 0;
174  }
175 
176  return false;
177 }
178 
179 double SwSortElement::GetValue( sal_uInt16 nKey ) const
180 {
181  return StrToDouble( GetKey( nKey ));
182 }
183 
186  : nOrg(rPos.GetIndex()), aPos(rPos)
187 {
188 }
189 
191 {
192 }
193 
194 OUString SwSortTextElement::GetKey(sal_uInt16 nId) const
195 {
196  SwTextNode* pTextNd = aPos.GetNode().GetTextNode();
197  if( !pTextNd )
198  return OUString();
199 
200  // for TextNodes
201  const OUString& rStr = pTextNd->GetText();
202 
203  sal_Unicode nDeli = pOptions->cDeli;
204  sal_uInt16 nDCount = pOptions->aKeys[nId]->nColumnId, i = 1;
205  sal_Int32 nStart = 0;
206 
207  // Find the delimiter
208  while( nStart != -1 && i < nDCount)
209  if( -1 != ( nStart = rStr.indexOf( nDeli, nStart ) ) )
210  {
211  nStart++;
212  i++;
213  }
214 
215  // Found next delimiter or end of String
216  // and copy
217  sal_Int32 nEnd = rStr.indexOf( nDeli, nStart+1 );
218  if (nEnd == -1)
219  return rStr.copy( nStart );
220  return rStr.copy( nStart, nEnd-nStart );
221 }
222 
225  : nRow( nRC )
226 {
227 }
228 
230 {
231 }
232 
234 OUString SwSortBoxElement::GetKey(sal_uInt16 nKey) const
235 {
236  const FndBox_* pFndBox;
237  sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
238 
239  if( SRT_ROWS == pOptions->eDirection )
240  pFndBox = pBox->GetBox(nCol, nRow); // Sort rows
241  else
242  pFndBox = pBox->GetBox(nRow, nCol); // Sort columns
243 
244  // Extract the Text
245  OUStringBuffer aRetStr;
246  if( pFndBox )
247  { // Get StartNode and skip it
248  const SwTableBox* pMyBox = pFndBox->GetBox();
249  OSL_ENSURE(pMyBox, "No atomic Box");
250 
251  if( pMyBox->GetSttNd() )
252  {
253  // Iterate over all the Box's TextNodes
254  const SwNode *pNd = nullptr, *pEndNd = pMyBox->GetSttNd()->EndOfSectionNode();
255  for( sal_uLong nIdx = pMyBox->GetSttIdx() + 1; pNd != pEndNd; ++nIdx )
256  if( ( pNd = pDoc->GetNodes()[ nIdx ])->IsTextNode() )
257  aRetStr.append(pNd->GetTextNode()->GetText());
258  }
259  }
260  return aRetStr.makeStringAndClear();
261 }
262 
263 double SwSortBoxElement::GetValue( sal_uInt16 nKey ) const
264 {
265  const FndBox_* pFndBox;
266  sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
267 
268  if( SRT_ROWS == pOptions->eDirection )
269  pFndBox = pBox->GetBox(nCol, nRow); // Sort rows
270  else
271  pFndBox = pBox->GetBox(nRow, nCol); // Sort columns
272 
273  double nVal;
274  if( pFndBox )
275  {
276  const SwFormat *pFormat = pFndBox->GetBox()->GetFrameFormat();
278  nVal = SwSortElement::GetValue( nKey );
279  else
280  nVal = pFormat->GetTableBoxValue().GetValue();
281  }
282  else
283  nVal = 0;
284 
285  return nVal;
286 }
287 
289 bool SwDoc::SortText(const SwPaM& rPaM, const SwSortOptions& rOpt)
290 {
291  // Check if Frame is in the Text
292  const SwPosition *pStart = rPaM.Start(), *pEnd = rPaM.End();
293 
294  // Set index to the Selection's start
295  for ( const auto *pFormat : *GetSpzFrameFormats() )
296  {
297  SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor();
298  SwPosition const*const pAPos = pAnchor->GetContentAnchor();
299 
300  if (pAPos && (RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) &&
301  pStart->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode )
302  return false;
303  }
304 
305  // Check if only TextNodes are within the Selection
306  {
307  sal_uLong nStart = pStart->nNode.GetIndex(),
308  nEnd = pEnd->nNode.GetIndex();
309  while( nStart <= nEnd )
310  // Iterate over a selected range
311  if( !GetNodes()[ nStart++ ]->IsTextNode() )
312  return false;
313  }
314 
315  bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
316  if( bUndo )
317  {
319  }
320 
321  SwPaM* pRedlPam = nullptr;
322  SwUndoRedlineSort* pRedlUndo = nullptr;
323  SwUndoSort* pUndoSort = nullptr;
324 
325  // To-Do - add 'SwExtraRedlineTable' also ?
326  if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
327  {
328  pRedlPam = new SwPaM( pStart->nNode, pEnd->nNode, -1, 1 );
329  SwContentNode* pCNd = pRedlPam->GetContentNode( false );
330  if( pCNd )
331  pRedlPam->GetMark()->nContent = pCNd->Len();
332 
334  {
335  if( bUndo )
336  {
337  pRedlUndo = new SwUndoRedlineSort( *pRedlPam,rOpt );
338  GetIDocumentUndoRedo().DoUndo(false);
339  }
340  // First copy the range
341  SwNodeIndex aEndIdx( pEnd->nNode, 1 );
342  SwNodeRange aRg( pStart->nNode, aEndIdx );
343  GetNodes().Copy_( aRg, aEndIdx );
344 
345  // range is new from pEnd->nNode+1 to aEndIdx
347 
348  pRedlPam->GetMark()->nNode.Assign( pEnd->nNode.GetNode(), 1 );
349  pCNd = pRedlPam->GetContentNode( false );
350  pRedlPam->GetMark()->nContent.Assign( pCNd, 0 );
351 
352  pRedlPam->GetPoint()->nNode.Assign( aEndIdx.GetNode() );
353  pCNd = pRedlPam->GetContentNode();
354  sal_Int32 nCLen = 0;
355  if( !pCNd &&
356  nullptr != (pCNd = GetNodes()[ aEndIdx.GetIndex()-1 ]->GetContentNode()))
357  {
358  nCLen = pCNd->Len();
359  pRedlPam->GetPoint()->nNode.Assign( *pCNd );
360  }
361  pRedlPam->GetPoint()->nContent.Assign( pCNd, nCLen );
362 
363  if( pRedlUndo )
364  pRedlUndo->SetValues( rPaM );
365  }
366  else
367  {
369  delete pRedlPam;
370  pRedlPam = nullptr;
371  }
372  }
373 
374  SwNodeIndex aStart(pStart->nNode);
375  SwSortElement::Init( this, rOpt );
376  SwSortTextElements 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
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 
492 
493  FndLines_t::size_type nStart = 0;
494  if( pTableNd->GetTable().GetRowsToRepeat() > 0 && rOpt.eDirection == SRT_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 == SRT_ROWS) ?
551  aFlatBox.GetRows() : aFlatBox.GetCols();
552 
553  // Sort SortList by Key
554  SwSortElement::Init( this, rOpt, &aFlatBox );
555  SwSortBoxElements 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  {
568  if(rOpt.eDirection == SRT_ROWS)
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  pDoc(pDocPtr),
740  nRow(0),
741  nCol(0)
742 { // If the array is symmetric
743  bSym = CheckLineSymmetry(rBoxRef);
744  if( bSym )
745  {
746  // Determine column/row count
747  nCols = GetColCount(rBoxRef);
748  nRows = GetRowCount(rBoxRef);
749 
750  // Create linear array
751  size_t nCount = static_cast<size_t>(nRows) * nCols;
752  pArr = std::make_unique<FndBox_ const *[]>(nCount);
753  memset(pArr.get(), 0, sizeof(const FndBox_*) * nCount);
754 
755  FillFlat( rBoxRef );
756  }
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 = 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 = 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 = nRow * nCols + nCol;
879  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  pDoc->GetAttrPool(),
889  svl::Items<
892  pSet->Put( pFormat->GetAttrSet() );
893  if( ppItemSets.empty() )
894  {
895  size_t nCount = static_cast<size_t>(nRows) * nCols;
896  ppItemSets.resize(nCount);
897  }
898  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  nCol++;
909  }
910  if(bModRow)
911  nRow++;
912  nCol = nOldCol;
913  }
914  if(!bLastBox)
915  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 * nCols + n_Col;
922  const FndBox_* pTmp = pArr[nOff];
923 
924  OSL_ENSURE(n_Col < nCols && n_Row < 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( ppItemSets.empty() || ( n_Col < nCols && n_Row < nRows), "invalid array access");
931 
932  return !ppItemSets.empty() ? ppItemSets[unsigned(n_Row * 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:185
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:1180
std::vector< std::unique_ptr< SfxItemSet > > ppItemSets
Definition: docsort.hxx:148
static double StrToDouble(const OUString &rStr)
Definition: docsort.cxx:105
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:51
void loadCollatorAlgorithm(const OUString &rAlgorithm, const css::lang::Locale &rLocale, sal_Int32 nOption)
const OUString & GetText() const
Definition: ndtxt.hxx:210
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1880
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1401
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
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:685
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
static void Finit()
Definition: docsort.cxx:85
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:50
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
SwNode & GetNode() const
Definition: ndindex.hxx:119
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:143
double GetValue() const
Definition: cellatr.hxx:95
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
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:737
SwDoc * pDoc
Definition: docsort.hxx:146
FlatFndBox(SwDoc *pDocPtr, const FndBox_ &rBox)
Generate two-dimensional array of FndBoxes.
Definition: docsort.cxx:738
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
Definition: tblsel.cxx:2092
static SwSortOptions * pOptions
Definition: docsort.hxx:70
static LanguageType nLang
Definition: srtdlg.cxx:60
sal_uInt16 GetRowCount(const FndBox_ &rBox)
Maximum count of Rows (Lines)
Definition: docsort.cxx:833
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:935
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:356
void Delete(const SwNodeIndex &rPos, sal_uLong nNodes=1)
delete nodes
Definition: nodes.cxx:1061
sal_uInt16 sal_Unicode
SwIndex nContent
Definition: pam.hxx:38
bool empty() const
Definition: docary.hxx:367
SwNodeIndex aStart
Definition: ndindex.hxx:132
static LocaleDataWrapper * pLclData
Definition: docsort.hxx:76
virtual OUString GetKey(sal_uInt16 nKey) const override
Definition: docsort.cxx:194
const SwTextFormatColl * GetDfltTextFormatColl() const
Definition: doc.hxx:772
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:123
void push_back(const SwTableBox *&rpTableBox)
Definition: docsort.hxx:54
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:858
bool bIgnoreCase
Definition: sortopt.hxx:55
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:786
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:919
bool SortText(const SwPaM &, const SwSortOptions &)
Sort Text in the Document.
Definition: docsort.cxx:289
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:892
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:179
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
#define RES_VERT_ORIENT
Definition: hintids.hxx:209
virtual OUString GetKey(sal_uInt16 nKey) const override
Get Key for a cell.
Definition: docsort.cxx:234
virtual double GetValue(sal_uInt16 nKey) const override
Definition: docsort.cxx:263
bool IsTextFormat(sal_uInt32 nFIndex) const
int i
static bool IsShowOriginal(const RedlineFlags eM)
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, RedlineType nDelType)=0
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:597
void UnlockModify()
Definition: calbck.hxx:214
static void Init(SwDoc *, const SwSortOptions &rOpt, FlatFndBox const *=nullptr)
Construct a SortElement for the Sort.
Definition: docsort.cxx:67
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:393
void LockModify()
Definition: calbck.hxx:213
#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:396
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:64
#define RES_BOXATR_VALUE
Definition: hintids.hxx:265
bool empty() const
virtual bool MoveNodeRange(SwNodeRange &, SwNodeIndex &, SwMoveFlags)=0
SwSortOrder eSortOrder
Definition: sortopt.hxx:37
bool operator<(const SwSortElement &) const
Definition: docsort.cxx:163
const SwPosition * Start() const
Definition: pam.hxx:212
virtual bool IsIgnoreRedline() const =0
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
bool bSym
Definition: docsort.hxx:155
void RestoreUpperFrames(SwNodes &rNds, sal_uLong nStt, sal_uLong nEnd)
Definition: node2lay.cxx:438
const SwTableBoxValue & GetTableBoxValue(bool=true) const
Definition: cellatr.hxx:109
virtual ~SwSortBoxElement() override
Definition: docsort.cxx:229
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:36
sal_uInt16 const nRow
Definition: docsort.hxx:114
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:650
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:334
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:808
bool CheckLineSymmetry(const FndBox_ &rBox)
All Lines of a Box need to have same number of Boxes.
Definition: docsort.cxx:764
sal_uInt16 nCols
Definition: docsort.hxx:151
std::multiset< SwSortTextElement > SwSortTextElements
Definition: docsort.cxx:63
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:261
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:729
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:402
const SwPosition * End() const
Definition: pam.hxx:217
SwNodeIndex aEnd
Definition: ndindex.hxx:133
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:190
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:53
sal_uInt32 GetValue() const
virtual ~SwSortElement()
Definition: docsort.cxx:101
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: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:1271
#define SW_COLLATOR_IGNORES
Definition: swtypes.hxx:193
int keycompare(const SwSortElement &rCmp, sal_uInt16 nKey) const
Definition: docsort.cxx:119
bool bIsNumeric
Definition: sortopt.hxx:39
#define RES_BOXATR_FORMAT
Definition: hintids.hxx:263
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1309
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:224
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:264
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