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